rnd-19980918
[rocksndiamonds.git] / src / tools.c
1 /***********************************************************
2 *  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
3 *----------------------------------------------------------*
4 *  ©1995 Artsoft Development                               *
5 *        Holger Schemel                                    *
6 *        33659 Bielefeld-Senne                             *
7 *        Telefon: (0521) 493245                            *
8 *        eMail: aeglos@valinor.owl.de                      *
9 *               aeglos@uni-paderborn.de                    *
10 *               q99492@pbhrzx.uni-paderborn.de             *
11 *----------------------------------------------------------*
12 *  tools.c                                                 *
13 ***********************************************************/
14
15 #ifdef __FreeBSD__
16 #include <machine/joystick.h>
17 #endif
18
19 #include "tools.h"
20 #include "game.h"
21 #include "events.h"
22 #include "sound.h"
23 #include "misc.h"
24 #include "buttons.h"
25 #include "joystick.h"
26 #include "cartoons.h"
27
28 #include <math.h>
29
30 #ifdef MSDOS
31 extern BOOL wait_for_vsync;
32 #endif
33
34 void SetDrawtoField(int mode)
35 {
36   if (mode == DRAW_BUFFERED && soft_scrolling_on)
37   {
38     FX = TILEX;
39     FY = TILEY;
40     BX1 = -1;
41     BY1 = -1;
42     BX2 = SCR_FIELDX;
43     BY2 = SCR_FIELDY;
44     redraw_x1 = 1;
45     redraw_y1 = 1;
46
47     drawto_field = fieldbuffer;
48   }
49   else  /* DRAW_DIRECT, DRAW_BACKBUFFER */
50   {
51     FX = SX;
52     FY = SY;
53     BX1 = 0;
54     BY1 = 0;
55     BX2 = SCR_FIELDX - 1;
56     BY2 = SCR_FIELDY - 1;
57     redraw_x1 = 0;
58     redraw_y1 = 0;
59
60     drawto_field = (mode == DRAW_DIRECT ? window :  backbuffer);
61   }
62 }
63
64 void BackToFront()
65 {
66   int x,y;
67   Drawable buffer = (drawto_field != window ? drawto_field : backbuffer);
68
69   if (direct_draw_on && game_status == PLAYING)
70     redraw_mask &= ~REDRAW_MAIN;
71
72   if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
73     redraw_mask |= REDRAW_FIELD;
74
75   if (redraw_mask & REDRAW_FIELD || ScreenMovPos)
76     redraw_mask &= ~REDRAW_TILES;
77
78   if (!redraw_mask)
79     return;
80
81   /* synchronize X11 graphics at this point; if we would synchronize the
82      display immediately after the buffer switching (after the XFlush),
83      this could mean that we have to wait for the graphics to complete,
84      although we could go on doing calculations for the next frame */
85
86   XSync(display,FALSE);
87
88 #ifdef MSDOS
89   wait_for_vsync = TRUE;
90 #endif
91
92   if (redraw_mask & REDRAW_ALL)
93   {
94     XCopyArea(display,backbuffer,window,gc,
95               0,0, WIN_XSIZE,WIN_YSIZE,
96               0,0);
97     redraw_mask = 0;
98   }
99
100   if (redraw_mask & REDRAW_FIELD)
101   {
102     if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
103       XCopyArea(display,backbuffer,window,gc,
104                 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
105                 REAL_SX,REAL_SY);
106     else
107     {
108       int fx = FX, fy = FY;
109
110       if (soft_scrolling_on)
111       {
112         fx += (PlayerMovDir & (MV_LEFT|MV_RIGHT) ? ScreenMovPos : 0);
113         fy += (PlayerMovDir & (MV_UP|MV_DOWN)    ? ScreenMovPos : 0);
114       }
115
116       XCopyArea(display,buffer,window,gc,
117                 fx,fy, SXSIZE,SYSIZE,
118                 SX,SY);
119     }
120     redraw_mask &= ~REDRAW_MAIN;
121   }
122
123   if (redraw_mask & REDRAW_DOORS)
124   {
125     if (redraw_mask & REDRAW_DOOR_1)
126       XCopyArea(display,backbuffer,window,gc,
127                 DX,DY, DXSIZE,DYSIZE,
128                 DX,DY);
129     if (redraw_mask & REDRAW_DOOR_2)
130     {
131       if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
132         XCopyArea(display,backbuffer,window,gc,
133                   VX,VY, VXSIZE,VYSIZE,
134                   VX,VY);
135       else
136       {
137         if (redraw_mask & REDRAW_VIDEO_1)
138           XCopyArea(display,backbuffer,window,gc,
139                     VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
140                     VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
141                     VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
142         if (redraw_mask & REDRAW_VIDEO_2)
143           XCopyArea(display,backbuffer,window,gc,
144                     VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
145                     VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
146                     VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
147         if (redraw_mask & REDRAW_VIDEO_3)
148           XCopyArea(display,backbuffer,window,gc,
149                     VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
150                     VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
151                     VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
152       }
153     }
154     redraw_mask &= ~REDRAW_DOORS;
155   }
156
157   if (redraw_mask & REDRAW_MICROLEV)
158   {
159     XCopyArea(display,backbuffer,window,gc,
160               MICROLEV_XPOS,MICROLEV_YPOS, MICROLEV_XSIZE,MICROLEV_YSIZE,
161               MICROLEV_XPOS,MICROLEV_YPOS);
162     XCopyArea(display,backbuffer,window,gc,
163               SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE,
164               SX,MICROLABEL_YPOS);
165     redraw_mask &= ~REDRAW_MICROLEV;
166   }
167
168   if (redraw_mask & REDRAW_TILES)
169   {
170     for(x=0; x<SCR_FIELDX; x++)
171       for(y=0; y<SCR_FIELDY; y++)
172         if (redraw[redraw_x1 + x][redraw_y1 + y])
173           XCopyArea(display,buffer,window,gc,
174                     FX+x*TILEX,FX+y*TILEY, TILEX,TILEY,
175                     SX+x*TILEX,SY+y*TILEY);
176   }
177
178   XFlush(display);
179
180   for(x=0; x<MAX_BUF_XSIZE; x++)
181     for(y=0; y<MAX_BUF_YSIZE; y++)
182       redraw[x][y] = 0;
183   redraw_tiles = 0;
184   redraw_mask = 0;
185 }
186
187 void FadeToFront()
188 {
189 /*
190   long fading_delay = 300;
191
192   if (fading_on && (redraw_mask & REDRAW_FIELD))
193   {
194 */
195
196 /*
197     int x,y;
198
199     XFillRectangle(display,window,gc,
200                    REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
201     XFlush(display);
202
203     for(i=0;i<2*FULL_SYSIZE;i++)
204     {
205       for(y=0;y<FULL_SYSIZE;y++)
206       {
207         XCopyArea(display,backbuffer,window,gc,
208                   REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
209       }
210       XFlush(display);
211       Delay(10);
212     }
213 */
214
215 /*
216     for(i=1;i<FULL_SYSIZE;i+=2)
217       XCopyArea(display,backbuffer,window,gc,
218                 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
219     XFlush(display);
220     Delay(fading_delay);
221 */
222
223 /*
224     XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
225     XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
226               REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
227     XFlush(display);
228     Delay(fading_delay);
229
230     XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
231     XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
232               REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
233     XFlush(display);
234     Delay(fading_delay);
235
236     XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
237     XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
238               REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
239     XFlush(display);
240     Delay(fading_delay);
241
242     XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
243     XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
244               REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
245     XFlush(display);
246     Delay(fading_delay);
247
248     redraw_mask &= ~REDRAW_MAIN;
249   }
250 */
251
252   BackToFront();
253 }
254
255 void ClearWindow()
256 {
257   XFillRectangle(display,backbuffer,gc,
258                  REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE);
259
260   if (soft_scrolling_on && game_status==PLAYING)
261   {
262     XFillRectangle(display,fieldbuffer,gc,
263                    0,0, FXSIZE,FYSIZE);
264     SetDrawtoField(DRAW_BUFFERED);
265   }
266   else
267     SetDrawtoField(DRAW_BACKBUFFER);
268
269   if (direct_draw_on && game_status==PLAYING)
270   {
271     XFillRectangle(display,window,gc,
272                    REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE);
273     SetDrawtoField(DRAW_DIRECT);
274   }
275
276   redraw_mask |= REDRAW_FIELD;
277 }
278
279 void DrawText(int x, int y, char *text, int font, int col)
280 {
281   DrawTextExt(drawto, gc, x, y, text, font, col);
282   if (x < DX)
283     redraw_mask |= REDRAW_FIELD;
284   else if (y < VY)
285     redraw_mask |= REDRAW_DOOR_1;
286 }
287
288 void DrawTextExt(Drawable d, GC gc, int x, int y,
289                  char *text, int font, int font_color)
290 {
291   int font_width, font_height, font_start;
292   int font_pixmap;
293
294   if (font!=FS_SMALL && font!=FS_BIG)
295     font = FS_SMALL;
296   if (font_color<FC_RED || font_color>FC_SPECIAL2)
297     font_color = FC_RED;
298
299   font_width =
300     (font==FS_BIG ? FONT1_XSIZE :
301      font_color<FC_SPECIAL1 ? FONT2_XSIZE :
302      font_color<FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
303   font_height =
304     (font==FS_BIG ? FONT1_XSIZE :
305      font_color<FC_SPECIAL2 ? FONT2_XSIZE: FONT4_XSIZE);
306   font_pixmap = (font==FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
307   font_start =
308     font_color*(font==FS_BIG ? FONT1_YSIZE : FONT2_YSIZE)*FONT_LINES_PER_FONT;
309
310   while(*text)
311   {
312     char c = *text++;
313
314     if (c>='a' && c<='z')
315       c = 'A' + (c - 'a');
316     else if (c=='ä' || c=='Ä')
317       c = 91;
318     else if (c=='ö' || c=='Ö')
319       c = 92;
320     else if (c=='ü' || c=='Ü')
321       c = 93;
322
323     if (c>=32 && c<=95)
324       XCopyArea(display,pix[font_pixmap],d,gc,
325                 ((c-32) % FONT_CHARS_PER_LINE)*font_width,
326                 ((c-32) / FONT_CHARS_PER_LINE)*font_height + font_start,
327                 font_width,font_height, x,y);
328
329     x += font_width;
330   }
331 }
332
333 void DrawPlayerField()
334 {
335   int x = JX, y = JY;
336   int sx = SCROLLX(x), sy = SCROLLY(y);
337
338   int sxx = 0, syy = 0;
339
340   int element = Feld[x][y];
341   int graphic, phase;
342
343   if (PlayerGone)
344     return;
345
346 #if DEBUG
347   if (!IN_LEV_FIELD(x,y) || !IN_SCR_FIELD(sx,sy))
348   {
349     printf("DrawPlayerField(): x = %d, y = %d\n",x,y);
350     printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
351     printf("DrawPlayerField(): This should never happen!\n");
352     return;
353   }
354 #endif
355
356   if (element == EL_EXPLODING)
357     return;
358
359   if (direct_draw_on)
360     SetDrawtoField(DRAW_BUFFERED);
361
362   /* draw things in the field the player is leaving, if needed */
363
364   if (lastJX != JX || lastJY != JY)
365   {
366     if (Store[lastJX][lastJY])
367     {
368       DrawLevelElement(lastJX,lastJY, Store[lastJX][lastJY]);
369       DrawLevelElementThruMask(lastJX,lastJY, Feld[lastJX][lastJY]);
370     }
371     else if (Feld[lastJX][lastJY] == EL_DYNAMIT)
372       DrawDynamite(lastJX,lastJY);
373     else
374       DrawLevelField(lastJX,lastJY);
375
376     if (PlayerPushing)
377     {
378       int nextJX = JX + (JX - lastJX);
379       int nextJY = JY + (JY - lastJY);
380
381       if (PlayerGfxPos)
382       {
383         if (Feld[nextJX][nextJY] == EL_SOKOBAN_FELD_VOLL)
384           DrawLevelElement(nextJX,nextJY, EL_SOKOBAN_FELD_LEER);
385         else
386           DrawLevelElement(nextJX,nextJY, EL_LEERRAUM);
387       }
388       else
389         DrawLevelField(nextJX,nextJY);
390     }
391   }
392
393   /* draw things behind the player, if needed */
394
395   if (Store[x][y])
396     DrawLevelElement(x,y, Store[x][y]);
397   else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
398     DrawLevelField(x,y);
399
400   /* draw player himself */
401
402   if (PlayerMovDir==MV_LEFT)
403     graphic = (PlayerPushing ? GFX_SPIELER_PUSH_LEFT : GFX_SPIELER_LEFT);
404   else if (PlayerMovDir==MV_RIGHT)
405     graphic = (PlayerPushing ? GFX_SPIELER_PUSH_RIGHT : GFX_SPIELER_RIGHT);
406   else if (PlayerMovDir==MV_UP)
407     graphic = GFX_SPIELER_UP;
408   else  /* MV_DOWN || MV_NO_MOVING */
409     graphic = GFX_SPIELER_DOWN;
410
411   graphic += PlayerFrame;
412
413   if (PlayerGfxPos)
414   {
415     if (PlayerMovDir == MV_LEFT || PlayerMovDir == MV_RIGHT)
416       sxx = PlayerGfxPos;
417     else
418       syy = PlayerGfxPos;
419   }
420
421   if (!soft_scrolling_on && ScreenMovPos)
422     sxx = syy = 0;
423
424   DrawGraphicShiftedThruMask(sx,sy, sxx,syy, graphic, NO_CUTTING);
425
426   if (PlayerPushing && PlayerGfxPos)
427   {
428     int nextJX = JX + (JX - lastJX);
429     int nextJY = JY + (JY - lastJY);
430     int px = SCROLLX(nextJX), py = SCROLLY(nextJY);
431
432     if (Feld[JX][JY] == EL_SOKOBAN_FELD_LEER ||
433         Feld[nextJX][nextJY] == EL_SOKOBAN_FELD_VOLL)
434       DrawGraphicShiftedThruMask(px,py,sxx,syy, GFX_SOKOBAN_OBJEKT,NO_CUTTING);
435     else
436     {
437       int element = Feld[nextJX][nextJY];
438       int graphic = el2gfx(element);
439
440       if (element == EL_FELSBROCKEN && sxx)
441       {
442         int phase = (PlayerGfxPos / (TILEX/4));
443
444         if (PlayerMovDir == MV_LEFT)
445           graphic += phase;
446         else
447           graphic += (phase+4)%4;
448       }
449
450       DrawGraphicShifted(px,py, sxx,syy, graphic, NO_CUTTING, NO_MASKING);
451     }
452   }
453
454   /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
455
456   if (element == EL_DYNAMIT || element == EL_DYNABOMB)
457   {
458     graphic = el2gfx(element);
459
460     if (element == EL_DYNAMIT)
461     {
462       if ((phase = (96-MovDelay[x][y])/12) > 6)
463         phase = 6;
464     }
465     else
466     {
467       if ((phase = ((96-MovDelay[x][y])/6) % 8) > 3)
468         phase = 7-phase;
469     }
470
471     DrawGraphicThruMask(sx,sy, graphic + phase);
472   }
473
474   if (direct_draw_on)
475   {
476     int dest_x = SX+SCROLLX(x)*TILEX;
477     int dest_y = SY+SCROLLY(y)*TILEY;
478     int x_size = TILEX;
479     int y_size = TILEY;
480
481     if (!ScreenMovPos)
482     {
483       dest_x = SX + SCROLLX(MIN(JX,lastJX))*TILEX;
484       dest_y = SY + SCROLLY(MIN(JY,lastJY))*TILEY;
485       x_size = TILEX * (1 + ABS(JX - lastJX));
486       y_size = TILEY * (1 + ABS(JY - lastJY));
487     }
488
489     XCopyArea(display,drawto_field,window,gc,
490               dest_x,dest_y, x_size,y_size, dest_x,dest_y);
491     SetDrawtoField(DRAW_DIRECT);
492   }
493
494   MarkTileDirty(sx,sy);
495 }
496
497 static int getGraphicAnimationPhase(int frames, int delay, int mode)
498 {
499   int phase;
500
501   if (mode == ANIM_OSCILLATE)
502   {
503     int max_anim_frames = frames*2 - 2;
504     phase = (FrameCounter % (delay * max_anim_frames)) / delay;
505     phase = (phase < frames ? phase : max_anim_frames - phase);
506   }
507   else
508     phase = (FrameCounter % (delay * frames)) / delay;
509
510   if (mode == ANIM_REVERSE)
511     phase = -phase;
512
513   return(phase);
514 }
515
516 void DrawGraphicAnimationExt(int x, int y, int graphic,
517                              int frames, int delay, int mode, int mask_mode)
518 {
519   int phase = getGraphicAnimationPhase(frames, delay, mode);
520
521   if (!(FrameCounter % delay) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
522   {
523     if (mask_mode == USE_MASKING)
524       DrawGraphicThruMask(SCROLLX(x),SCROLLY(y), graphic + phase);
525     else
526       DrawGraphic(SCROLLX(x),SCROLLY(y), graphic + phase);
527   }
528 }
529
530 void DrawGraphicAnimation(int x, int y, int graphic,
531                           int frames, int delay, int mode)
532 {
533   DrawGraphicAnimationExt(x,y, graphic, frames,delay,mode, NO_MASKING);
534 }
535
536 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
537                                   int frames, int delay, int mode)
538 {
539   DrawGraphicAnimationExt(x,y, graphic, frames,delay,mode, USE_MASKING);
540 }
541
542 void DrawGraphic(int x, int y, int graphic)
543 {
544
545 #if DEBUG
546   if (!IN_SCR_FIELD(x,y))
547   {
548     printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
549     printf("DrawGraphic(): This should never happen!\n");
550     return;
551   }
552 #endif
553
554   DrawGraphicExt(drawto_field, gc, FX+x*TILEX, FY+y*TILEY, graphic);
555   MarkTileDirty(x,y);
556 }
557
558 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
559 {
560   if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
561   {
562     graphic -= GFX_START_ROCKSSCREEN;
563     XCopyArea(display,pix[PIX_BACK],d,gc,
564               SX + (graphic % GFX_PER_LINE) * TILEX,
565               SY + (graphic / GFX_PER_LINE) * TILEY,
566               TILEX,TILEY, x,y);
567   }
568   else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
569   {
570     graphic -= GFX_START_ROCKSHEROES;
571     XCopyArea(display,pix[PIX_HEROES],d,gc,
572               (graphic % HEROES_PER_LINE) * TILEX,
573               (graphic / HEROES_PER_LINE) * TILEY,
574               TILEX,TILEY, x,y);
575   }
576   else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
577   {
578     graphic -= GFX_START_ROCKSFONT;
579     XCopyArea(display,pix[PIX_BIGFONT],d,gc,
580               (graphic % FONT_CHARS_PER_LINE) * TILEX,
581               (graphic / FONT_CHARS_PER_LINE) * TILEY +
582               FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
583               TILEX,TILEY, x,y);
584   }
585   else
586     XFillRectangle(display,d,gc, x,y, TILEX,TILEY);
587 }
588
589 void DrawGraphicThruMask(int x, int y, int graphic)
590 {
591   int src_x,src_y, dest_x,dest_y;
592   int tile = graphic;
593   Pixmap src_pixmap;
594   GC drawing_gc;
595
596 #if DEBUG
597   if (!IN_SCR_FIELD(x,y))
598   {
599     printf("DrawGraphicThruMask(): x = %d, y = %d\n",x,y);
600     printf("DrawGraphicThruMask(): This should never happen!\n");
601     return;
602   }
603 #endif
604
605   if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
606   {
607     src_pixmap = pix[PIX_BACK];
608     drawing_gc = clip_gc[PIX_BACK];
609     graphic -= GFX_START_ROCKSSCREEN;
610     src_x  = SX+(graphic % GFX_PER_LINE)*TILEX;
611     src_y  = SY+(graphic / GFX_PER_LINE)*TILEY;
612   }
613   else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
614   {
615     src_pixmap = pix[PIX_HEROES];
616     drawing_gc = clip_gc[PIX_HEROES];
617     graphic -= GFX_START_ROCKSHEROES;
618     src_x  = (graphic % HEROES_PER_LINE)*TILEX;
619     src_y  = (graphic / HEROES_PER_LINE)*TILEY;
620   }
621   else
622   {
623     DrawGraphic(x,y,graphic);
624     return;
625   }
626
627   dest_x = FX + x*TILEX;
628   dest_y = FY + y*TILEY;
629
630   if (tile_clipmask[tile] != None)
631   {
632     XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
633     XSetClipOrigin(display, tile_clip_gc, dest_x,dest_y);
634     XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
635               src_x,src_y, TILEX,TILEY, dest_x,dest_y);
636   }
637   else
638   {
639 #if DEBUG
640     printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
641 #endif
642
643     XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
644     XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
645               src_x,src_y, TILEX,TILEY, dest_x,dest_y);
646   }
647
648   MarkTileDirty(x,y);
649 }
650
651 void DrawMiniGraphic(int x, int y, int graphic)
652 {
653   DrawMiniGraphicExt(drawto,gc, SX+x*MINI_TILEX,SY+y*MINI_TILEY, graphic);
654   MarkTileDirty(x/2, y/2);
655 }
656
657 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
658 {
659   if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
660   {
661     graphic -= GFX_START_ROCKSSCREEN;
662     XCopyArea(display,pix[PIX_BACK],d,gc,
663               MINI_GFX_STARTX+(graphic % MINI_GFX_PER_LINE)*MINI_TILEX,
664               MINI_GFX_STARTY+(graphic / MINI_GFX_PER_LINE)*MINI_TILEY,
665               MINI_TILEX,MINI_TILEY, x,y);
666   }
667   else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
668   {
669     graphic -= GFX_START_ROCKSFONT;
670     XCopyArea(display,pix[PIX_SMALLFONT],d,gc,
671               (graphic % FONT_CHARS_PER_LINE)*FONT4_XSIZE,
672               (graphic / FONT_CHARS_PER_LINE)*FONT4_YSIZE +
673               FC_SPECIAL2*FONT2_YSIZE*FONT_LINES_PER_FONT,
674               MINI_TILEX,MINI_TILEY, x,y);
675   }
676   else
677     XFillRectangle(display,d,gc, x,y, MINI_TILEX,MINI_TILEY);
678 }
679
680 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
681                         int cut_mode, int mask_mode)
682 {
683   int width = TILEX, height = TILEY;
684   int cx = 0, cy = 0;
685   int src_x,src_y, dest_x,dest_y;
686   int tile = graphic;
687   Pixmap src_pixmap;
688   GC drawing_gc;
689
690   if (graphic < 0)
691   {
692     DrawGraphic(x,y,graphic);
693     return;
694   }
695
696   if (dx || dy)                 /* Verschiebung der Grafik? */
697   {
698     if (x < BX1)                /* Element kommt von links ins Bild */
699     {
700       x = BX1;
701       width = dx;
702       cx = TILEX - dx;
703       dx = 0;
704     }
705     else if (x > BX2)           /* Element kommt von rechts ins Bild */
706     {
707       x = BX2;
708       width = -dx;
709       dx = TILEX + dx;
710     }
711     else if (x==BX1 && dx<0)    /* Element verläßt links das Bild */
712     {
713       width += dx;
714       cx = -dx;
715       dx = 0;
716     }
717     else if (x==BX2 && dx>0)    /* Element verläßt rechts das Bild */
718       width -= dx;
719     else if (dx)                /* allg. Bewegung in x-Richtung */
720       MarkTileDirty(x + SIGN(dx), y);
721
722     if (y < BY1)                /* Element kommt von oben ins Bild */
723     {
724       if (cut_mode==CUT_BELOW)  /* Element oberhalb des Bildes */
725         return;
726
727       y = BY1;
728       height = dy;
729       cy = TILEY - dy;
730       dy = 0;
731     }
732     else if (y > BY2)           /* Element kommt von unten ins Bild */
733     {
734       y = BY2;
735       height = -dy;
736       dy = TILEY + dy;
737     }
738     else if (y==BY1 && dy<0)    /* Element verläßt oben das Bild */
739     {
740       height += dy;
741       cy = -dy;
742       dy = 0;
743     }
744     else if (dy > 0 && cut_mode==CUT_ABOVE)
745     {
746       if (y == BY2)             /* Element unterhalb des Bildes */
747         return;
748
749       height = dy;
750       cy = TILEY-dy;
751       dy = TILEY;
752       MarkTileDirty(x, y + 1);
753     }                           /* Element verläßt unten das Bild */
754     else if (dy > 0 && (y == BY2 || cut_mode==CUT_BELOW))
755       height -= dy;
756     else if (dy)                /* allg. Bewegung in y-Richtung */
757       MarkTileDirty(x, y + SIGN(dy));
758   }
759
760   if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
761   {
762     src_pixmap = pix[PIX_BACK];
763     drawing_gc = clip_gc[PIX_BACK];
764     graphic -= GFX_START_ROCKSSCREEN;
765     src_x  = SX+(graphic % GFX_PER_LINE)*TILEX+cx;
766     src_y  = SY+(graphic / GFX_PER_LINE)*TILEY+cy;
767   }
768   else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
769   {
770     src_pixmap = pix[PIX_HEROES];
771     drawing_gc = clip_gc[PIX_HEROES];
772     graphic -= GFX_START_ROCKSHEROES;
773     src_x  = (graphic % HEROES_PER_LINE)*TILEX+cx;
774     src_y  = (graphic / HEROES_PER_LINE)*TILEY+cy;
775   }
776
777   dest_x = FX + x*TILEX + dx;
778   dest_y = FY + y*TILEY + dy;
779
780 #if DEBUG
781   if (!IN_SCR_FIELD(x,y))
782   {
783     printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
784     printf("DrawGraphicShifted(): This should never happen!\n");
785     return;
786   }
787 #endif
788
789   if (mask_mode == USE_MASKING)
790   {
791     if (tile_clipmask[tile] != None)
792     {
793       XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
794       XSetClipOrigin(display, tile_clip_gc, dest_x,dest_y);
795       XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
796                 src_x,src_y, TILEX,TILEY, dest_x,dest_y);
797     }
798     else
799     {
800 #if DEBUG
801       printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
802 #endif
803
804       XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
805       XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
806                 src_x,src_y, width,height, dest_x,dest_y);
807     }
808   }
809   else
810     XCopyArea(display, src_pixmap, drawto_field, gc,
811               src_x,src_y, width,height, dest_x,dest_y);
812
813   MarkTileDirty(x,y);
814 }
815
816 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
817                                 int cut_mode)
818 {
819   DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
820 }
821
822 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
823                           int cut_mode, int mask_mode)
824 {
825   int ux = UNSCROLLX(x), uy = UNSCROLLY(y);
826   int graphic = el2gfx(element);
827   int phase4 = ABS(MovPos[ux][uy])/(TILEX/4);
828   int phase  = phase4 / 2;
829   int dir = MovDir[ux][uy];
830
831   if (element==EL_PACMAN || element==EL_KAEFER || element==EL_FLIEGER)
832   {
833     graphic += 4*!phase;
834
835     if (dir == MV_UP)
836       graphic += 1;
837     else if (dir == MV_LEFT)
838       graphic += 2;
839     else if (dir == MV_DOWN)
840       graphic += 3;
841   }
842   else if (element==EL_MAULWURF || element==EL_PINGUIN ||
843            element==EL_SCHWEIN || element==EL_DRACHE)
844   {
845     if (dir==MV_LEFT)
846       graphic = (element==EL_MAULWURF ? GFX_MAULWURF_LEFT :
847                  element==EL_PINGUIN ? GFX_PINGUIN_LEFT :
848                  element==EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
849     else if (dir==MV_RIGHT)
850       graphic = (element==EL_MAULWURF ? GFX_MAULWURF_RIGHT :
851                  element==EL_PINGUIN ? GFX_PINGUIN_RIGHT :
852                  element==EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
853     else if (dir==MV_UP)
854       graphic = (element==EL_MAULWURF ? GFX_MAULWURF_UP :
855                  element==EL_PINGUIN ? GFX_PINGUIN_UP :
856                  element==EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
857     else
858       graphic = (element==EL_MAULWURF ? GFX_MAULWURF_DOWN :
859                  element==EL_PINGUIN ? GFX_PINGUIN_DOWN :
860                  element==EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
861
862     graphic += phase4;
863   }
864   else if (element==EL_SONDE)
865   {
866     graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
867   }
868   else if (element==EL_SALZSAEURE)
869   {
870     graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
871   }
872   else if (element==EL_BUTTERFLY || element==EL_FIREFLY)
873   {
874     graphic += !phase;
875   }
876   else if ((element==EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
877   {
878     graphic += phase * (element==EL_FELSBROCKEN ? 2 : 1);
879   }
880   else if ((element==EL_SIEB_LEER || element==EL_SIEB2_LEER ||
881             element==EL_SIEB_VOLL || element==EL_SIEB2_VOLL) && SiebAktiv)
882   {
883     graphic += 3-(SiebAktiv%8)/2;
884   }
885   else if (IS_AMOEBOID(element))
886   {
887     graphic = (element==EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
888     graphic += (x+2*y) % 4;
889   }
890   else if (element==EL_MAUER_LEBT)
891   {
892     BOOL links_massiv = FALSE, rechts_massiv = FALSE;
893
894     if (!IN_LEV_FIELD(ux-1,uy) || IS_MAUER(Feld[ux-1][uy]))
895       links_massiv = TRUE;
896     if (!IN_LEV_FIELD(ux+1,uy) || IS_MAUER(Feld[ux+1][uy]))
897       rechts_massiv = TRUE;
898
899     if (links_massiv && rechts_massiv)
900       graphic = GFX_MAUERWERK;
901     else if (links_massiv)
902       graphic = GFX_MAUER_R;
903     else if (rechts_massiv)
904       graphic = GFX_MAUER_L;
905   }
906
907   if (dx || dy)
908     DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, mask_mode);
909   else if (mask_mode == USE_MASKING)
910     DrawGraphicThruMask(x,y, graphic);
911   else
912     DrawGraphic(x,y, graphic);
913 }
914
915 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
916                          int cut_mode, int mask_mode)
917 {
918   if (IN_LEV_FIELD(x,y) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
919     DrawScreenElementExt(SCROLLX(x),SCROLLY(y), dx,dy, element,
920                          cut_mode, mask_mode);
921 }
922
923 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
924                               int cut_mode)
925 {
926   DrawScreenElementExt(x,y, dx,dy, element, cut_mode, NO_MASKING);
927 }
928
929 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
930                              int cut_mode)
931 {
932   DrawLevelElementExt(x,y, dx,dy, element, cut_mode, NO_MASKING);
933 }
934
935 void DrawScreenElementThruMask(int x, int y, int element)
936 {
937   DrawScreenElementExt(x,y, 0,0, element, NO_CUTTING, USE_MASKING);
938 }
939
940 void DrawLevelElementThruMask(int x, int y, int element)
941 {
942   DrawLevelElementExt(x,y, 0,0, element, NO_CUTTING, USE_MASKING);
943 }
944
945 void ErdreichAnbroeckeln(int x, int y)
946 {
947   int i, width, height, cx,cy;
948   int ux = UNSCROLLX(x), uy = UNSCROLLY(y);
949   int element, graphic;
950   int snip = 4;
951   static int xy[4][2] =
952   {
953     { 0,-1 },
954     { -1,0 },
955     { +1,0 },
956     { 0,+1 }
957   };
958
959   if (!IN_LEV_FIELD(ux,uy))
960     return;
961
962   element = Feld[ux][uy];
963
964   if (element==EL_ERDREICH)
965   {
966     if (!IN_SCR_FIELD(x,y))
967       return;
968
969     graphic = GFX_ERDENRAND;
970
971     for(i=0;i<4;i++)
972     {
973       int uxx,uyy;
974
975       uxx = ux+xy[i][0];
976       uyy = uy+xy[i][1];
977       if (!IN_LEV_FIELD(uxx,uyy))
978         element = EL_BETON;
979       else
980         element = Feld[uxx][uyy];
981
982       if (element==EL_ERDREICH)
983         continue;
984
985       if (i==1 || i==2)
986       {
987         width = snip;
988         height = TILEY;
989         cx = (i==2 ? TILEX-snip : 0);
990         cy = 0;
991       }
992       else
993       {
994         width = TILEX;
995         height = snip;
996         cx = 0;
997         cy = (i==3 ? TILEY-snip : 0);
998       }
999
1000       XCopyArea(display,pix[PIX_BACK],drawto_field,gc,
1001                 SX+(graphic % GFX_PER_LINE)*TILEX+cx,
1002                 SY+(graphic / GFX_PER_LINE)*TILEY+cy,
1003                 width,height, FX+x*TILEX+cx,FY+y*TILEY+cy);
1004     }
1005
1006     MarkTileDirty(x,y);
1007   }
1008   else
1009   {
1010     graphic = GFX_ERDENRAND;
1011
1012     for(i=0;i<4;i++)
1013     {
1014       int xx,yy,uxx,uyy;
1015
1016       xx = x+xy[i][0];
1017       yy = y+xy[i][1];
1018       uxx = ux+xy[i][0];
1019       uyy = uy+xy[i][1];
1020
1021       if (!IN_LEV_FIELD(uxx,uyy) || Feld[uxx][uyy]!=EL_ERDREICH ||
1022           !IN_SCR_FIELD(xx,yy))
1023         continue;
1024
1025       if (i==1 || i==2)
1026       {
1027         width = snip;
1028         height = TILEY;
1029         cx = (i==1 ? TILEX-snip : 0);
1030         cy = 0;
1031       }
1032       else
1033       {
1034         width = TILEX;
1035         height = snip;
1036         cx = 0;
1037         cy = (i==0 ? TILEY-snip : 0);
1038       }
1039
1040       XCopyArea(display,pix[PIX_BACK],drawto_field,gc,
1041                 SX+(graphic % GFX_PER_LINE)*TILEX+cx,
1042                 SY+(graphic / GFX_PER_LINE)*TILEY+cy,
1043                 width,height, FX+xx*TILEX+cx,FY+yy*TILEY+cy);
1044
1045       MarkTileDirty(xx,yy);
1046     }
1047   }
1048 }
1049
1050 void DrawScreenElement(int x, int y, int element)
1051 {
1052   DrawScreenElementExt(x,y, 0,0, element, NO_CUTTING, NO_MASKING);
1053   ErdreichAnbroeckeln(x,y);
1054 }
1055
1056 void DrawLevelElement(int x, int y, int element)
1057 {
1058   if (IN_LEV_FIELD(x,y) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1059     DrawScreenElement(SCROLLX(x),SCROLLY(y),element);
1060 }
1061
1062 void DrawScreenField(int x, int y)
1063 {
1064   int ux = UNSCROLLX(x), uy = UNSCROLLY(y);
1065   int element;
1066
1067   if (!IN_LEV_FIELD(ux,uy))
1068   {
1069     DrawScreenElement(x,y,EL_BETON);
1070     return;
1071   }
1072
1073   element = Feld[ux][uy];
1074
1075   if (IS_MOVING(ux,uy))
1076   {
1077     int horiz_move = (MovDir[ux][uy]==MV_LEFT || MovDir[ux][uy]==MV_RIGHT);
1078     BOOL cut_mode = NO_CUTTING;
1079
1080     if (Store[ux][uy]==EL_MORAST_LEER ||
1081         Store[ux][uy]==EL_SIEB_LEER ||
1082         Store[ux][uy]==EL_SIEB2_LEER ||
1083         Store[ux][uy]==EL_AMOEBE_NASS)
1084       cut_mode = CUT_ABOVE;
1085     else if (Store[ux][uy]==EL_MORAST_VOLL ||
1086
1087 #if 0
1088         Store[ux][uy]==EL_SALZSAEURE ||
1089 #endif
1090
1091         Store[ux][uy]==EL_SIEB_VOLL ||
1092         Store[ux][uy]==EL_SIEB2_VOLL)
1093       cut_mode = CUT_BELOW;
1094
1095     if (cut_mode==CUT_ABOVE)
1096       DrawScreenElementShifted(x,y, 0,0, Store[ux][uy], NO_CUTTING);
1097     else
1098       DrawScreenElement(x,y,EL_LEERRAUM);
1099
1100     if (horiz_move)
1101       DrawScreenElementShifted(x,y, MovPos[ux][uy],0, element, NO_CUTTING);
1102     else
1103       DrawScreenElementShifted(x,y, 0,MovPos[ux][uy], element, cut_mode);
1104
1105 #if 1
1106     if (Store[ux][uy] == EL_SALZSAEURE)
1107       DrawLevelElementThruMask(ux,uy+1, EL_SALZSAEURE);
1108 #endif
1109
1110   }
1111   else if (IS_BLOCKED(ux,uy))
1112   {
1113     int oldx,oldy;
1114     int sx, sy;
1115     int horiz_move;
1116     BOOL cut_mode = NO_CUTTING;
1117
1118     Blocked2Moving(ux,uy,&oldx,&oldy);
1119     sx = SCROLLX(oldx);
1120     sy = SCROLLY(oldy);
1121     horiz_move = (MovDir[oldx][oldy]==MV_LEFT || MovDir[oldx][oldy]==MV_RIGHT);
1122
1123     if (Store[oldx][oldy]==EL_MORAST_LEER ||
1124         Store[oldx][oldy]==EL_SIEB_LEER ||
1125         Store[oldx][oldy]==EL_SIEB2_LEER ||
1126         Store[oldx][oldy]==EL_AMOEBE_NASS)
1127       cut_mode = CUT_ABOVE;
1128
1129     DrawScreenElement(x,y,EL_LEERRAUM);
1130     element = Feld[oldx][oldy];
1131
1132     if (horiz_move)
1133       DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1134     else
1135       DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1136   }
1137   else if (IS_DRAWABLE(element))
1138     DrawScreenElement(x,y,element);
1139   else
1140     DrawScreenElement(x,y,EL_LEERRAUM);
1141 }
1142
1143 void DrawLevelField(int x, int y)
1144 {
1145   if (IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1146     DrawScreenField(SCROLLX(x),SCROLLY(y));
1147   else if (IS_MOVING(x,y))
1148   {
1149     int newx,newy;
1150
1151     Moving2Blocked(x,y,&newx,&newy);
1152     if (IN_SCR_FIELD(SCROLLX(newx),SCROLLY(newy)))
1153       DrawScreenField(SCROLLX(newx),SCROLLY(newy));
1154   }
1155   else if (IS_BLOCKED(x,y))
1156   {
1157     int oldx,oldy;
1158
1159     Blocked2Moving(x,y,&oldx,&oldy);
1160     if (IN_SCR_FIELD(SCROLLX(oldx),SCROLLY(oldy)))
1161       DrawScreenField(SCROLLX(oldx),SCROLLY(oldy));
1162   }
1163 }
1164
1165 void DrawMiniElement(int x, int y, int element)
1166 {
1167   int graphic;
1168
1169   if (!element)
1170   {
1171     DrawMiniGraphic(x,y,-1);
1172     return;
1173   }
1174
1175   graphic = el2gfx(element);
1176   DrawMiniGraphic(x,y,graphic);
1177 }
1178
1179 void DrawMiniElementOrWall(int x, int y, int scroll_x, int scroll_y)
1180 {
1181   if (x+scroll_x<-1 || x+scroll_x>lev_fieldx ||
1182       y+scroll_y<-1 || y+scroll_y>lev_fieldy)
1183     DrawMiniElement(x,y,EL_LEERRAUM);
1184   else if (x+scroll_x==-1 || x+scroll_x==lev_fieldx ||
1185            y+scroll_y==-1 || y+scroll_y==lev_fieldy)
1186     DrawMiniElement(x,y,EL_BETON);
1187   else
1188     DrawMiniElement(x,y,Feld[x+scroll_x][y+scroll_y]);
1189 }
1190
1191 void DrawMicroElement(int xpos, int ypos, int element)
1192 {
1193   int graphic;
1194
1195   if (element==EL_LEERRAUM)
1196     return;
1197
1198   graphic = el2gfx(element);
1199
1200   XCopyArea(display,pix[PIX_BACK],drawto,gc,
1201             MICRO_GFX_STARTX+(graphic % MICRO_GFX_PER_LINE)*MICRO_TILEX,
1202             MICRO_GFX_STARTY+(graphic / MICRO_GFX_PER_LINE)*MICRO_TILEY,
1203             MICRO_TILEX,MICRO_TILEY, xpos,ypos);
1204 }
1205
1206 void DrawLevel()
1207 {
1208   int x,y;
1209
1210   ClearWindow();
1211
1212   for(x=BX1; x<=BX2; x++)
1213     for(y=BY1; y<=BY2; y++)
1214       DrawScreenField(x,y);
1215
1216   if (soft_scrolling_on)
1217     XCopyArea(display,fieldbuffer,backbuffer,gc,
1218               FX,FY, SXSIZE,SYSIZE,
1219               SX,SY);
1220
1221   redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1222 }
1223
1224 void DrawMiniLevel(int scroll_x, int scroll_y)
1225 {
1226   int x,y;
1227
1228   ClearWindow();
1229
1230   for(x=0;x<2*SCR_FIELDX;x++)
1231     for(y=0;y<2*SCR_FIELDY;y++)
1232       DrawMiniElementOrWall(x,y,scroll_x,scroll_y);
1233
1234   redraw_mask |= REDRAW_FIELD;
1235 }
1236
1237 void DrawMicroLevel(int xpos, int ypos)
1238 {
1239   int x,y;
1240
1241   XFillRectangle(display,drawto,gc,
1242                  xpos-MICRO_TILEX,ypos-MICRO_TILEY,
1243                  MICRO_TILEX*(STD_LEV_FIELDX+2),
1244                  MICRO_TILEY*(STD_LEV_FIELDY+2));
1245   if (lev_fieldx < STD_LEV_FIELDX)
1246     xpos += (STD_LEV_FIELDX - lev_fieldx)/2 * MICRO_TILEX;
1247   if (lev_fieldy < STD_LEV_FIELDY)
1248     ypos += (STD_LEV_FIELDY - lev_fieldy)/2 * MICRO_TILEY;
1249
1250   for(x=-1;x<=STD_LEV_FIELDX;x++)
1251     for(y=-1;y<=STD_LEV_FIELDY;y++)
1252       if (x>=0 && x<lev_fieldx && y>=0 && y<lev_fieldy)
1253         DrawMicroElement(xpos+MICRO_TILEX*x,ypos+MICRO_TILEY*y,
1254                          Feld[x][y]=Ur[x][y]);
1255       else if (x>=-1 && x<lev_fieldx+1 && y>=-1 && y<lev_fieldy+1)
1256         DrawMicroElement(xpos+MICRO_TILEX*x,ypos+MICRO_TILEY*y,
1257                          EL_BETON);
1258
1259   XFillRectangle(display,drawto,gc, SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE);
1260
1261   if (level.name)
1262   {
1263     int len = strlen(level.name);
1264     int lxpos = SX+(SXSIZE-len*FONT4_XSIZE)/2;
1265     int lypos = MICROLABEL_YPOS;
1266
1267     DrawText(lxpos,lypos,level.name,FS_SMALL,FC_SPECIAL2);
1268   }
1269
1270   redraw_mask |= REDRAW_MICROLEV;
1271 }
1272
1273 int AYS_in_range(int x, int y)
1274 {
1275   if (y>DY+249 && y<DY+278)
1276   {
1277     if (x>DX+1 && x<DX+48)
1278       return(1);
1279     else if (x>DX+51 && x<DX+98) 
1280       return(2);
1281   }
1282   return(0);
1283 }
1284
1285 BOOL AreYouSure(char *text, unsigned int ays_state)
1286 {
1287   int mx,my, ty, result = -1;
1288   unsigned int old_door_state;
1289
1290   old_door_state = GetDoorState();
1291
1292   CloseDoor(DOOR_CLOSE_1);
1293
1294   /* Alten Türinhalt sichern */
1295   XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1296             DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1297             DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1);
1298
1299   /* Fragetext schreiben */
1300   XFillRectangle(display,pix[PIX_DB_DOOR],gc,
1301                  DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1,DXSIZE,DYSIZE);
1302
1303   for(ty=0;ty<13;ty++)
1304   {
1305     int tx,tl,tc;
1306     char txt[256];
1307
1308     if (!(*text))
1309       break;
1310     for(tl=0,tx=0;tx<7;tl++,tx++)
1311     {
1312       tc=*(text+tx);
1313       if (!tc || tc==32)
1314         break;
1315     }
1316     if (!tl)
1317     { 
1318       text++; 
1319       ty--; 
1320       continue; 
1321     }
1322     sprintf(txt,text); 
1323     txt[tl]=0;
1324     DrawTextExt(pix[PIX_DB_DOOR],gc,
1325                 DOOR_GFX_PAGEX1+51-(tl*14)/2,SY+ty*16,txt,FS_SMALL,FC_YELLOW);
1326     text+=(tl+(tc==32));
1327   }
1328
1329   if (ays_state & AYS_ASK)
1330     XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1331               DOOR_GFX_PAGEX4,OK_BUTTON_GFX_YPOS,
1332               DXSIZE,OK_BUTTON_YSIZE,
1333               DOOR_GFX_PAGEX1,OK_BUTTON_YPOS);
1334   else if (ays_state & AYS_CONFIRM)
1335     XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1336               DOOR_GFX_PAGEX4,CONFIRM_BUTTON_GFX_YPOS,
1337               DXSIZE,CONFIRM_BUTTON_YSIZE,
1338               DOOR_GFX_PAGEX1,CONFIRM_BUTTON_YPOS);
1339
1340   OpenDoor(DOOR_OPEN_1);
1341   ClearEventQueue();
1342
1343   if (!(ays_state & AYS_ASK) && !(ays_state & AYS_CONFIRM))
1344     return(FALSE);
1345
1346   if (game_status != MAINMENU)
1347     InitAnimation();
1348
1349   button_status = MB_RELEASED;
1350
1351   while(result<0)
1352   {
1353     DoAnimation();
1354     Delay(10);
1355
1356     if (XPending(display))
1357     {
1358       XEvent event;
1359
1360       XNextEvent(display, &event);
1361       switch(event.type)
1362       {
1363         case Expose:
1364           HandleExposeEvent((XExposeEvent *) &event);
1365           break;
1366         case UnmapNotify:
1367           SleepWhileUnmapped();
1368           break;
1369         case ButtonPress:
1370         case ButtonRelease:
1371         case MotionNotify:
1372         {
1373           int choice;
1374
1375           if (event.type == MotionNotify)
1376           {
1377             motion_status = TRUE;
1378             mx = ((XMotionEvent *) &event)->x;
1379             my = ((XMotionEvent *) &event)->y;
1380           }
1381           else
1382           {
1383             motion_status = FALSE;
1384             mx = ((XButtonEvent *) &event)->x;
1385             my = ((XButtonEvent *) &event)->y;
1386             if (event.type==ButtonPress)
1387               button_status = ((XButtonEvent *) &event)->button;
1388             else
1389               button_status = MB_RELEASED;
1390           }
1391
1392           if (ays_state & AYS_ASK)
1393             choice = CheckChooseButtons(mx,my,button_status);
1394           else
1395             choice = CheckConfirmButton(mx,my,button_status);
1396
1397           switch(choice)
1398           {
1399             case BUTTON_OK:
1400               result = TRUE;
1401               break;
1402             case BUTTON_NO:
1403               result = FALSE;
1404               break;
1405             case BUTTON_CONFIRM:
1406               result = TRUE|FALSE;
1407               break;
1408             default:
1409               break;
1410           }
1411           break;
1412         }
1413         case KeyPress:
1414           switch(XLookupKeysym((XKeyEvent *)&event,
1415                                ((XKeyEvent *)&event)->state))
1416           {
1417             case XK_Return:
1418               result = 1;
1419               break;
1420             case XK_Escape:
1421               result = 0;
1422               break;
1423           }
1424           break;
1425         case KeyRelease:
1426           key_joystick_mapping = 0;
1427           break;
1428         case FocusIn:
1429         case FocusOut:
1430           HandleFocusEvent((XFocusChangeEvent *) &event);
1431           break;
1432         case ClientMessage:
1433           HandleClientMessageEvent((XClientMessageEvent *) &event);
1434           break;
1435         default:
1436           break;
1437       }
1438     }
1439     else if (JoystickButton() == JOY_BUTTON_NEW_PRESSED)
1440     {
1441       int joy=Joystick();
1442
1443       if (joy & JOY_BUTTON_1)
1444         result = 1;
1445       else if (joy & JOY_BUTTON_2)
1446         result = 0;
1447     }
1448   }
1449
1450   if (game_status != MAINMENU)
1451     StopAnimation();
1452
1453   if (!(ays_state & AYS_STAY_OPEN))
1454   {
1455     CloseDoor(DOOR_CLOSE_1);
1456
1457     if (!(ays_state & AYS_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1458     {
1459       XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1460                 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1461                 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1462       OpenDoor(DOOR_OPEN_1);
1463     }
1464   }
1465
1466   return(result);
1467 }
1468
1469 unsigned int OpenDoor(unsigned int door_state)
1470 {
1471   unsigned int new_door_state;
1472
1473   if (door_state & DOOR_COPY_BACK)
1474   {
1475     XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1476               DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE+VYSIZE,
1477               DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1478     door_state &= ~DOOR_COPY_BACK;
1479   }
1480
1481   new_door_state = MoveDoor(door_state);
1482
1483   return(new_door_state);
1484 }
1485
1486 unsigned int CloseDoor(unsigned int door_state)
1487 {
1488   unsigned int new_door_state;
1489
1490   XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,
1491             DX,DY, DXSIZE,DYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1492   XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,
1493             VX,VY, VXSIZE,VYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1494
1495   new_door_state = MoveDoor(door_state);
1496
1497   return(new_door_state);
1498 }
1499
1500 unsigned int GetDoorState()
1501 {
1502   return(MoveDoor(DOOR_GET_STATE));
1503 }
1504
1505 unsigned int MoveDoor(unsigned int door_state)
1506 {
1507   static unsigned int door1 = DOOR_OPEN_1;
1508   static unsigned int door2 = DOOR_CLOSE_2;
1509   static long door_delay = 0;
1510   int x, start, stepsize = 2;
1511   long door_delay_value = stepsize * 5;
1512
1513   if (door_state == DOOR_GET_STATE)
1514     return(door1 | door2);
1515
1516   if (door1==DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1517     door_state &= ~DOOR_OPEN_1;
1518   else if (door1==DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1519     door_state &= ~DOOR_CLOSE_1;
1520   if (door2==DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1521     door_state &= ~DOOR_OPEN_2;
1522   else if (door2==DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1523     door_state &= ~DOOR_CLOSE_2;
1524
1525   if (quick_doors)
1526   {
1527     stepsize = 20;
1528     door_delay_value = 0;
1529     StopSound(SND_OEFFNEN);
1530   }
1531
1532   if (door_state & DOOR_ACTION)
1533   {
1534     if (!(door_state & DOOR_NO_DELAY))
1535       PlaySoundStereo(SND_OEFFNEN,PSND_MAX_RIGHT);
1536
1537     start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1538
1539     for(x=start; x<=DXSIZE; x+=stepsize)
1540     {
1541       WaitUntilDelayReached(&door_delay, door_delay_value);
1542
1543       if (door_state & DOOR_ACTION_1)
1544       {
1545         int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1546         int j = (DXSIZE - i)/3;
1547
1548         XCopyArea(display,pix[PIX_DB_DOOR],drawto,gc,
1549                   DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1+i/2,
1550                   DXSIZE,DYSIZE-i/2, DX,DY);
1551
1552         XFillRectangle(display,drawto,gc,DX,DY+DYSIZE-i/2,DXSIZE,i/2);
1553
1554         XSetClipOrigin(display,clip_gc[PIX_DOOR],
1555                        DX-i,(DY+j)-DOOR_GFX_PAGEY1);
1556         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1557                   DXSIZE,DOOR_GFX_PAGEY1, i,77, DX+DXSIZE-i,DY+j);
1558         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1559                   DXSIZE,DOOR_GFX_PAGEY1+140, i,63, DX+DXSIZE-i,DY+140+j);
1560         XSetClipOrigin(display,clip_gc[PIX_DOOR],
1561                        DX-DXSIZE+i,DY-(DOOR_GFX_PAGEY1+j));
1562         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1563                   DXSIZE-i,DOOR_GFX_PAGEY1+j, i,77-j, DX,DY);
1564         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1565                   DXSIZE-i,DOOR_GFX_PAGEY1+140, i,63, DX,DY+140-j);
1566
1567         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1568                   DXSIZE-i,DOOR_GFX_PAGEY1+77, i,63,
1569                   DX,DY+77-j);
1570         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1571                   DXSIZE-i,DOOR_GFX_PAGEY1+203, i,77,
1572                   DX,DY+203-j);
1573         XSetClipOrigin(display,clip_gc[PIX_DOOR],
1574                        DX-i,(DY+j)-DOOR_GFX_PAGEY1);
1575         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1576                   DXSIZE,DOOR_GFX_PAGEY1+77, i,63,
1577                   DX+DXSIZE-i,DY+77+j);
1578         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1579                   DXSIZE,DOOR_GFX_PAGEY1+203, i,77-j,
1580                   DX+DXSIZE-i,DY+203+j);
1581
1582         redraw_mask |= REDRAW_DOOR_1;
1583       }
1584
1585       if (door_state & DOOR_ACTION_2)
1586       {
1587         int i = (door_state & DOOR_OPEN_2 ? VXSIZE-x : x);
1588         int j = (VXSIZE - i)/3;
1589
1590         XCopyArea(display,pix[PIX_DB_DOOR],drawto,gc,
1591                   DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2+i/2,
1592                   VXSIZE,VYSIZE-i/2, VX,VY);
1593
1594         XFillRectangle(display,drawto,gc,VX,VY+VYSIZE-i/2,VXSIZE,i/2);
1595
1596         XSetClipOrigin(display,clip_gc[PIX_DOOR],
1597                        VX-i,(VY+j)-DOOR_GFX_PAGEY2);
1598         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1599                   VXSIZE,DOOR_GFX_PAGEY2, i,VYSIZE/2, VX+VXSIZE-i,VY+j);
1600         XSetClipOrigin(display,clip_gc[PIX_DOOR],
1601                        VX-VXSIZE+i,VY-(DOOR_GFX_PAGEY2+j));
1602         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1603                   VXSIZE-i,DOOR_GFX_PAGEY2+j, i,VYSIZE/2-j, VX,VY);
1604
1605         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1606                   VXSIZE-i,DOOR_GFX_PAGEY2+VYSIZE/2, i,VYSIZE/2,
1607                   VX,VY+VYSIZE/2-j);
1608         XSetClipOrigin(display,clip_gc[PIX_DOOR],
1609                        VX-i,(VY+j)-DOOR_GFX_PAGEY2);
1610         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1611                   VXSIZE,DOOR_GFX_PAGEY2+VYSIZE/2, i,VYSIZE/2-j,
1612                   VX+VXSIZE-i,VY+VYSIZE/2+j);
1613
1614         redraw_mask |= REDRAW_DOOR_2;
1615       }
1616
1617       BackToFront();
1618
1619       if (game_status == MAINMENU)
1620         DoAnimation();
1621     }
1622   }
1623
1624   if (door_state & DOOR_ACTION_1)
1625     door1 = door_state & DOOR_ACTION_1;
1626   if (door_state & DOOR_ACTION_2)
1627     door2 = door_state & DOOR_ACTION_2;
1628
1629   return(door1 | door2);
1630 }
1631
1632 int ReadPixel(Drawable d, int x, int y)
1633 {
1634   static XImage *pixelimage;
1635
1636   pixelimage = XGetImage(display, d, x,y, 1,1, AllPlanes, ZPixmap);
1637   return(XGetPixel(pixelimage,0,0));
1638 }
1639
1640 int el2gfx(int element)
1641 {
1642   switch(element)
1643   {
1644     case EL_LEERRAUM:           return(-1);
1645     case EL_ERDREICH:           return(GFX_ERDREICH);
1646     case EL_MAUERWERK:          return(GFX_MAUERWERK);
1647     case EL_FELSBODEN:          return(GFX_FELSBODEN);
1648     case EL_FELSBROCKEN:        return(GFX_FELSBROCKEN);
1649     case EL_SCHLUESSEL:         return(GFX_SCHLUESSEL);
1650     case EL_EDELSTEIN:          return(GFX_EDELSTEIN);
1651     case EL_AUSGANG_ZU:         return(GFX_AUSGANG_ZU);
1652     case EL_AUSGANG_ACT:        return(GFX_AUSGANG_ACT);
1653     case EL_AUSGANG_AUF:        return(GFX_AUSGANG_AUF);
1654     case EL_SPIELFIGUR:         return(GFX_SPIELFIGUR);
1655     case EL_SPIELER1:           return(GFX_SPIELER1);
1656     case EL_SPIELER2:           return(GFX_SPIELER2);
1657     case EL_SPIELER3:           return(GFX_SPIELER3);
1658     case EL_SPIELER4:           return(GFX_SPIELER4);
1659     case EL_KAEFER:             return(GFX_KAEFER);
1660     case EL_KAEFER_R:           return(GFX_KAEFER_R);
1661     case EL_KAEFER_O:           return(GFX_KAEFER_O);
1662     case EL_KAEFER_L:           return(GFX_KAEFER_L);
1663     case EL_KAEFER_U:           return(GFX_KAEFER_U);
1664     case EL_FLIEGER:            return(GFX_FLIEGER);
1665     case EL_FLIEGER_R:          return(GFX_FLIEGER_R);
1666     case EL_FLIEGER_O:          return(GFX_FLIEGER_O);
1667     case EL_FLIEGER_L:          return(GFX_FLIEGER_L);
1668     case EL_FLIEGER_U:          return(GFX_FLIEGER_U);
1669     case EL_BUTTERFLY:          return(GFX_BUTTERFLY);
1670     case EL_BUTTERFLY_R:        return(GFX_BUTTERFLY_R);
1671     case EL_BUTTERFLY_O:        return(GFX_BUTTERFLY_O);
1672     case EL_BUTTERFLY_L:        return(GFX_BUTTERFLY_L);
1673     case EL_BUTTERFLY_U:        return(GFX_BUTTERFLY_U);
1674     case EL_FIREFLY:            return(GFX_FIREFLY);
1675     case EL_FIREFLY_R:          return(GFX_FIREFLY_R);
1676     case EL_FIREFLY_O:          return(GFX_FIREFLY_O);
1677     case EL_FIREFLY_L:          return(GFX_FIREFLY_L);
1678     case EL_FIREFLY_U:          return(GFX_FIREFLY_U);
1679     case EL_MAMPFER:            return(GFX_MAMPFER);
1680     case EL_ROBOT:              return(GFX_ROBOT);
1681     case EL_BETON:              return(GFX_BETON);
1682     case EL_DIAMANT:            return(GFX_DIAMANT);
1683     case EL_MORAST_LEER:        return(GFX_MORAST_LEER);
1684     case EL_MORAST_VOLL:        return(GFX_MORAST_VOLL);
1685     case EL_TROPFEN:            return(GFX_TROPFEN);
1686     case EL_BOMBE:              return(GFX_BOMBE);
1687     case EL_SIEB_LEER:          return(GFX_SIEB_LEER);
1688     case EL_SIEB_VOLL:          return(GFX_SIEB_VOLL);
1689     case EL_SIEB_TOT:           return(GFX_SIEB_TOT);
1690     case EL_SALZSAEURE:         return(GFX_SALZSAEURE);
1691     case EL_AMOEBE_TOT:         return(GFX_AMOEBE_TOT);
1692     case EL_AMOEBE_NASS:        return(GFX_AMOEBE_NASS);
1693     case EL_AMOEBE_NORM:        return(GFX_AMOEBE_NORM);
1694     case EL_AMOEBE_VOLL:        return(GFX_AMOEBE_VOLL);
1695     case EL_AMOEBE_BD:          return(GFX_AMOEBE_BD);
1696     case EL_AMOEBA2DIAM:        return(GFX_AMOEBA2DIAM);
1697     case EL_KOKOSNUSS:          return(GFX_KOKOSNUSS);
1698     case EL_LIFE:               return(GFX_LIFE);
1699     case EL_LIFE_ASYNC:         return(GFX_LIFE_ASYNC);
1700     case EL_DYNAMIT:            return(GFX_DYNAMIT);
1701     case EL_BADEWANNE:          return(GFX_BADEWANNE);
1702     case EL_BADEWANNE1:         return(GFX_BADEWANNE1);
1703     case EL_BADEWANNE2:         return(GFX_BADEWANNE2);
1704     case EL_BADEWANNE3:         return(GFX_BADEWANNE3);
1705     case EL_BADEWANNE4:         return(GFX_BADEWANNE4);
1706     case EL_BADEWANNE5:         return(GFX_BADEWANNE5);
1707     case EL_ABLENK_AUS:         return(GFX_ABLENK_AUS);
1708     case EL_ABLENK_EIN:         return(GFX_ABLENK_EIN);
1709     case EL_SCHLUESSEL1:        return(GFX_SCHLUESSEL1);
1710     case EL_SCHLUESSEL2:        return(GFX_SCHLUESSEL2);
1711     case EL_SCHLUESSEL3:        return(GFX_SCHLUESSEL3);
1712     case EL_SCHLUESSEL4:        return(GFX_SCHLUESSEL4);
1713     case EL_PFORTE1:            return(GFX_PFORTE1);
1714     case EL_PFORTE2:            return(GFX_PFORTE2);
1715     case EL_PFORTE3:            return(GFX_PFORTE3);
1716     case EL_PFORTE4:            return(GFX_PFORTE4);
1717     case EL_PFORTE1X:           return(GFX_PFORTE1X);
1718     case EL_PFORTE2X:           return(GFX_PFORTE2X);
1719     case EL_PFORTE3X:           return(GFX_PFORTE3X);
1720     case EL_PFORTE4X:           return(GFX_PFORTE4X);
1721     case EL_DYNAMIT_AUS:        return(GFX_DYNAMIT_AUS);
1722     case EL_PACMAN:             return(GFX_PACMAN);
1723     case EL_PACMAN_R:           return(GFX_PACMAN_R);
1724     case EL_PACMAN_O:           return(GFX_PACMAN_O);
1725     case EL_PACMAN_L:           return(GFX_PACMAN_L);
1726     case EL_PACMAN_U:           return(GFX_PACMAN_U);
1727     case EL_UNSICHTBAR:         return(GFX_UNSICHTBAR);
1728     case EL_ERZ_EDEL:           return(GFX_ERZ_EDEL);
1729     case EL_ERZ_DIAM:           return(GFX_ERZ_DIAM);
1730     case EL_BIRNE_AUS:          return(GFX_BIRNE_AUS);
1731     case EL_BIRNE_EIN:          return(GFX_BIRNE_EIN);
1732     case EL_ZEIT_VOLL:          return(GFX_ZEIT_VOLL);
1733     case EL_ZEIT_LEER:          return(GFX_ZEIT_LEER);
1734     case EL_MAUER_LEBT:         return(GFX_MAUER_LEBT);
1735     case EL_EDELSTEIN_BD:       return(GFX_EDELSTEIN_BD);
1736     case EL_EDELSTEIN_GELB:     return(GFX_EDELSTEIN_GELB);
1737     case EL_EDELSTEIN_ROT:      return(GFX_EDELSTEIN_ROT);
1738     case EL_EDELSTEIN_LILA:     return(GFX_EDELSTEIN_LILA);
1739     case EL_ERZ_EDEL_BD:        return(GFX_ERZ_EDEL_BD);
1740     case EL_ERZ_EDEL_GELB:      return(GFX_ERZ_EDEL_GELB);
1741     case EL_ERZ_EDEL_ROT:       return(GFX_ERZ_EDEL_ROT);
1742     case EL_ERZ_EDEL_LILA:      return(GFX_ERZ_EDEL_LILA);
1743     case EL_MAMPFER2:           return(GFX_MAMPFER2);
1744     case EL_SIEB2_LEER:         return(GFX_SIEB2_LEER);
1745     case EL_SIEB2_VOLL:         return(GFX_SIEB2_VOLL);
1746     case EL_SIEB2_TOT:          return(GFX_SIEB2_TOT);
1747     case EL_DYNABOMB:           return(GFX_DYNABOMB);
1748     case EL_DYNABOMB_NR:        return(GFX_DYNABOMB_NR);
1749     case EL_DYNABOMB_SZ:        return(GFX_DYNABOMB_SZ);
1750     case EL_DYNABOMB_XL:        return(GFX_DYNABOMB_XL);
1751     case EL_SOKOBAN_OBJEKT:     return(GFX_SOKOBAN_OBJEKT);
1752     case EL_SOKOBAN_FELD_LEER:  return(GFX_SOKOBAN_FELD_LEER);
1753     case EL_SOKOBAN_FELD_VOLL:  return(GFX_SOKOBAN_FELD_VOLL);
1754     case EL_MAULWURF:           return(GFX_MAULWURF);
1755     case EL_PINGUIN:            return(GFX_PINGUIN);
1756     case EL_SCHWEIN:            return(GFX_SCHWEIN);
1757     case EL_DRACHE:             return(GFX_DRACHE);
1758     case EL_SONDE:              return(GFX_SONDE);
1759     case EL_PFEIL_L:            return(GFX_PFEIL_L);
1760     case EL_PFEIL_R:            return(GFX_PFEIL_R);
1761     case EL_PFEIL_O:            return(GFX_PFEIL_O);
1762     case EL_PFEIL_U:            return(GFX_PFEIL_U);
1763     default:
1764     {
1765       if (IS_CHAR(element))
1766         return(GFX_CHAR_START + (element-EL_CHAR_START));
1767       else
1768         return(-1);
1769     }
1770   }
1771 }