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