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