rnd-19980813
[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   /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
511
512   if (element == EL_DYNAMIT || element == EL_DYNABOMB)
513   {
514     graphic = el2gfx(element);
515
516     if (element == EL_DYNAMIT)
517     {
518       if ((phase = (48-MovDelay[x][y])/6) > 6)
519         phase = 6;
520     }
521     else
522     {
523       if ((phase = ((48-MovDelay[x][y])/3) % 8) > 3)
524         phase = 7-phase;
525     }
526
527     DrawGraphicThruMask(sx,sy, graphic + phase);
528   }
529
530   if (direct_draw_on)
531   {
532     int dest_x = SX+SCROLLX(x)*TILEX;
533     int dest_y = SY+SCROLLY(y)*TILEY;
534
535     XCopyArea(display,drawto_field,window,gc,
536               dest_x,dest_y, TILEX,TILEY, dest_x,dest_y);
537     SetDrawtoField(DRAW_DIRECT);
538   }
539 }
540
541 static int getGraphicAnimationPhase(int frames, int delay, int mode)
542 {
543   int phase;
544
545   if (mode == ANIM_OSCILLATE)
546   {
547     int max_anim_frames = frames*2 - 2;
548     phase = (FrameCounter % (delay * max_anim_frames)) / delay;
549     phase = (phase < frames ? phase : max_anim_frames - phase);
550   }
551   else
552     phase = (FrameCounter % (delay * frames)) / delay;
553
554   return(phase);
555 }
556
557 void DrawGraphicAnimation(int x, int y, int graphic,
558                           int frames, int delay, int mode)
559 {
560   int phase = getGraphicAnimationPhase(frames, delay, mode);
561
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
575   if (!(FrameCounter % delay) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
576     DrawGraphic(SCROLLX(x),SCROLLY(y), graphic + phase);
577 }
578
579 void DrawGraphic(int x, int y, int graphic)
580 {
581
582 #if DEBUG
583   if (!IN_SCR_FIELD(x,y))
584   {
585     printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
586     printf("DrawGraphic(): This should never happen!\n");
587     return;
588   }
589 #endif
590
591   DrawGraphicExt(drawto_field, gc, x, y, graphic);
592   redraw_tiles++;
593   redraw[redraw_x1 + x][redraw_y1 + y] = TRUE;
594   redraw_mask |= REDRAW_TILES;
595 }
596
597 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
598 {
599   DrawGraphicExtHiRes(d, gc, FX+x*TILEX, FY+y*TILEY, graphic);
600 }
601
602 void DrawGraphicExtHiRes(Drawable d, GC gc, int x, int y, int graphic)
603 {
604   if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
605   {
606     graphic -= GFX_START_ROCKSSCREEN;
607     XCopyArea(display,pix[PIX_BACK],d,gc,
608               SX+(graphic % GFX_PER_LINE)*TILEX,
609               SY+(graphic / GFX_PER_LINE)*TILEY,
610               TILEX,TILEY, x,y);
611   }
612   else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
613   {
614     graphic -= GFX_START_ROCKSHEROES;
615     XCopyArea(display,pix[PIX_HEROES],d,gc,
616               (graphic % HEROES_PER_LINE)*TILEX,
617               (graphic / HEROES_PER_LINE)*TILEY,
618               TILEX,TILEY, x,y);
619   }
620   else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
621   {
622     graphic -= GFX_START_ROCKSFONT;
623     XCopyArea(display,pix[PIX_BIGFONT],d,gc,
624               (graphic % FONT_CHARS_PER_LINE)*TILEX,
625               (graphic / FONT_CHARS_PER_LINE)*TILEY +
626               FC_SPECIAL1*TILEY*FONT_LINES_PER_FONT,
627               TILEX,TILEY, x,y);
628   }
629   else
630     XFillRectangle(display,d,gc, x,y, TILEX,TILEY);
631 }
632
633 void DrawGraphicThruMask(int x, int y, int graphic)
634 {
635   int src_x,src_y, dest_x,dest_y;
636
637 #if DEBUG
638   if (!IN_SCR_FIELD(x,y))
639   {
640     printf("DrawGraphicThruMask(): x = %d, y = %d\n",x,y);
641     printf("DrawGraphicThruMask(): This should never happen!\n");
642     return;
643   }
644 #endif
645
646   if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
647   {
648     graphic -= GFX_START_ROCKSSCREEN;
649     src_x  = SX+(graphic % GFX_PER_LINE)*TILEX;
650     src_y  = SY+(graphic / GFX_PER_LINE)*TILEY;
651     dest_x = FX+x*TILEX;
652     dest_y = FY+y*TILEY;
653
654     XSetClipOrigin(display,clip_gc[PIX_BACK],dest_x-src_x,dest_y-src_y);
655     XCopyArea(display,pix[PIX_BACK],drawto_field,clip_gc[PIX_BACK],
656               src_x,src_y, TILEX,TILEY, dest_x,dest_y);
657   }
658   else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
659   {
660     graphic -= GFX_START_ROCKSHEROES;
661     src_x  = (graphic % HEROES_PER_LINE)*TILEX;
662     src_y  = (graphic / HEROES_PER_LINE)*TILEY;
663     dest_x = FX+x*TILEX;
664     dest_y = FY+y*TILEY;
665
666     XSetClipOrigin(display,clip_gc[PIX_HEROES],dest_x-src_x,dest_y-src_y);
667     XCopyArea(display,pix[PIX_HEROES],drawto_field,clip_gc[PIX_HEROES],
668               src_x,src_y, TILEX,TILEY, dest_x,dest_y);
669   }
670   else
671   {
672     DrawGraphic(x,y,graphic);
673     return;
674   }
675
676   redraw_tiles++;
677   redraw[redraw_x1 + x][redraw_y1 + y]=TRUE;
678   redraw_mask|=REDRAW_TILES;
679 }
680
681 void DrawElementThruMask(int x, int y, int element)
682 {
683   DrawGraphicThruMask(x,y,el2gfx(element));
684 }
685
686 void DrawMiniGraphic(int x, int y, int graphic)
687 {
688   DrawMiniGraphicExt(drawto, gc, x, y, graphic);
689   redraw_tiles++;
690   redraw[x/2][y/2]=TRUE;
691   redraw_mask|=REDRAW_TILES;
692 }
693
694 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
695 {
696   DrawMiniGraphicExtHiRes(d,gc, SX+x*MINI_TILEX,SY+y*MINI_TILEY, graphic);
697 }
698
699 void DrawMiniGraphicExtHiRes(Drawable d, GC gc, int x, int y, int graphic)
700 {
701   if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
702   {
703     graphic -= GFX_START_ROCKSSCREEN;
704     XCopyArea(display,pix[PIX_BACK],d,gc,
705               MINI_GFX_STARTX+(graphic % MINI_GFX_PER_LINE)*MINI_TILEX,
706               MINI_GFX_STARTY+(graphic / MINI_GFX_PER_LINE)*MINI_TILEY,
707               MINI_TILEX,MINI_TILEY, x,y);
708   }
709   else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
710   {
711     graphic -= GFX_START_ROCKSFONT;
712     XCopyArea(display,pix[PIX_SMALLFONT],d,gc,
713               (graphic % FONT_CHARS_PER_LINE)*FONT4_XSIZE,
714               (graphic / FONT_CHARS_PER_LINE)*FONT4_YSIZE +
715               FC_SPECIAL2*FONT2_YSIZE*FONT_LINES_PER_FONT,
716               MINI_TILEX,MINI_TILEY, x,y);
717   }
718   else
719     XFillRectangle(display,d,gc, x,y, MINI_TILEX,MINI_TILEY);
720 }
721
722 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int cut_mode)
723 {
724   int width = TILEX, height = TILEY;
725   int cx = 0, cy = 0;
726
727   if (graphic < 0)
728   {
729     DrawGraphic(x,y,graphic);
730     return;
731   }
732
733   if (dx || dy)                 /* Verschiebung der Grafik? */
734   {
735     if (x < BX1)                /* Element kommt von links ins Bild */
736     {
737       x = BX1;
738       width = dx;
739       cx = TILEX - dx;
740       dx = 0;
741     }
742     else if (x > BX2)           /* Element kommt von rechts ins Bild */
743     {
744       x = BX2;
745       width = -dx;
746       dx = TILEX + dx;
747     }
748     else if (x==BX1 && dx<0)    /* Element verläßt links das Bild */
749     {
750       width += dx;
751       cx = -dx;
752       dx = 0;
753     }
754     else if (x==BX2 && dx>0)    /* Element verläßt rechts das Bild */
755       width -= dx;
756     else if (dx)                /* allg. Bewegung in x-Richtung */
757       redraw[redraw_x1 + x + SIGN(dx)][redraw_y1 + y] = TRUE;
758
759     if (y < BY1)                /* Element kommt von oben ins Bild */
760     {
761       if (cut_mode==CUT_BELOW)  /* Element oberhalb des Bildes */
762         return;
763
764       y = BY1;
765       height = dy;
766       cy = TILEY - dy;
767       dy = 0;
768     }
769     else if (y > BY2)           /* Element kommt von unten ins Bild */
770     {
771       y = BY2;
772       height = -dy;
773       dy = TILEY + dy;
774     }
775     else if (y==BY1 && dy<0)    /* Element verläßt oben das Bild */
776     {
777       height += dy;
778       cy = -dy;
779       dy = 0;
780     }
781     else if (dy > 0 && cut_mode==CUT_ABOVE)
782     {
783       if (y == BY2)             /* Element unterhalb des Bildes */
784         return;
785
786       height = dy;
787       cy = TILEY-dy;
788       dy = TILEY;
789       redraw[redraw_x1 + x][redraw_y1 + y + 1] = TRUE;
790     }                           /* Element verläßt unten das Bild */
791     else if (dy > 0 && (y == BY2 || cut_mode==CUT_BELOW))
792       height -= dy;
793     else if (dy)                /* allg. Bewegung in y-Richtung */
794       redraw[redraw_x1 + x][redraw_y1 + y + SIGN(dy)] = TRUE;
795   }
796
797   if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
798   {
799     graphic -= GFX_START_ROCKSSCREEN;
800     XCopyArea(display,pix[PIX_BACK],drawto_field,gc,
801               SX+(graphic % GFX_PER_LINE)*TILEX+cx,
802               SY+(graphic / GFX_PER_LINE)*TILEY+cy,
803               width,height, FX+x*TILEX+dx,FY+y*TILEY+dy);
804   }
805   else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
806   {
807     graphic -= GFX_START_ROCKSHEROES;
808     XCopyArea(display,pix[PIX_HEROES],drawto_field,gc,
809               (graphic % HEROES_PER_LINE)*TILEX+cx,
810               (graphic / HEROES_PER_LINE)*TILEY+cy,
811               width,height, FX+x*TILEX+dx,FY+y*TILEY+dy);
812   }
813
814 #if DEBUG
815   if (!IN_SCR_FIELD(x,y))
816   {
817     printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
818     printf("DrawGraphicShifted(): This should never happen!\n");
819     return;
820   }
821 #endif
822
823   redraw_tiles++;
824   redraw[redraw_x1 + x][redraw_y1 + y] = TRUE;
825   redraw_mask |= REDRAW_TILES;
826 }
827
828 void DrawElementShifted(int x, int y, int dx, int dy, int element,int cut_mode)
829 {
830   int ux = UNSCROLLX(x), uy = UNSCROLLY(y);
831   int graphic = el2gfx(element);
832   int phase4 = ABS(MovPos[ux][uy])/(TILEX/4);
833   int phase  = phase4 / 2;
834   int dir = MovDir[ux][uy];
835
836   if (element==EL_PACMAN || element==EL_KAEFER || element==EL_FLIEGER)
837   {
838     graphic += 4*!phase;
839
840     if (dir == MV_UP)
841       graphic += 1;
842     else if (dir == MV_LEFT)
843       graphic += 2;
844     else if (dir == MV_DOWN)
845       graphic += 3;
846   }
847   else if (element==EL_MAULWURF || element==EL_PINGUIN ||
848            element==EL_SCHWEIN || element==EL_DRACHE)
849   {
850     if (dir==MV_LEFT)
851       graphic = (element==EL_MAULWURF ? GFX_MAULWURF_LEFT :
852                  element==EL_PINGUIN ? GFX_PINGUIN_LEFT :
853                  element==EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
854     else if (dir==MV_RIGHT)
855       graphic = (element==EL_MAULWURF ? GFX_MAULWURF_RIGHT :
856                  element==EL_PINGUIN ? GFX_PINGUIN_RIGHT :
857                  element==EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
858     else if (dir==MV_UP)
859       graphic = (element==EL_MAULWURF ? GFX_MAULWURF_UP :
860                  element==EL_PINGUIN ? GFX_PINGUIN_UP :
861                  element==EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
862     else
863       graphic = (element==EL_MAULWURF ? GFX_MAULWURF_DOWN :
864                  element==EL_PINGUIN ? GFX_PINGUIN_DOWN :
865                  element==EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
866
867     graphic += phase4;
868   }
869   else if (element==EL_SONDE)
870   {
871     graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
872   }
873   else if (element==EL_BUTTERFLY || element==EL_FIREFLY)
874   {
875     graphic += !phase;
876   }
877   else if ((element==EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
878   {
879     graphic += phase * (element==EL_FELSBROCKEN ? 2 : 1);
880   }
881   else if ((element==EL_SIEB_LEER || element==EL_SIEB2_LEER ||
882             element==EL_SIEB_VOLL || element==EL_SIEB2_VOLL) && SiebAktiv)
883   {
884     graphic += 3-(SiebAktiv%8)/2;
885   }
886   else if (IS_AMOEBOID(element))
887   {
888     graphic = (element==EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
889     graphic += (x+2*y) % 4;
890   }
891   else if (element==EL_MAUER_LEBT)
892   {
893     BOOL links_massiv = FALSE, rechts_massiv = FALSE;
894
895     if (!IN_LEV_FIELD(ux-1,uy) || IS_MAUER(Feld[ux-1][uy]))
896       links_massiv = TRUE;
897     if (!IN_LEV_FIELD(ux+1,uy) || IS_MAUER(Feld[ux+1][uy]))
898       rechts_massiv = TRUE;
899
900     if (links_massiv && rechts_massiv)
901       graphic = GFX_MAUERWERK;
902     else if (links_massiv)
903       graphic = GFX_MAUER_R;
904     else if (rechts_massiv)
905       graphic = GFX_MAUER_L;
906   }
907
908   if (dx || dy)
909     DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode);
910   else
911     DrawGraphic(x,y, graphic);
912 }
913
914 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
915                                 int cut_mode)
916 {
917   int width = TILEX, height = TILEY;
918   int cx = 0, cy = 0;
919   int src_x,src_y, dest_x,dest_y;
920
921   if (graphic < 0)
922   {
923     DrawGraphic(x,y,graphic);
924     return;
925   }
926
927   if (dx || dy)                 /* Verschiebung der Grafik? */
928   {
929     if (x < BX1)                /* Element kommt von links ins Bild */
930     {
931       x = BX1;
932       width = dx;
933       cx = TILEX - dx;
934       dx = 0;
935     }
936     else if (x > BX2)           /* Element kommt von rechts ins Bild */
937     {
938       x = BX2;
939       width = -dx;
940       dx = TILEX + dx;
941     }
942     else if (x==BX1 && dx<0)    /* Element verläßt links das Bild */
943     {
944       width += dx;
945       cx = -dx;
946       dx = 0;
947     }
948     else if (x==BX2 && dx>0)    /* Element verläßt rechts das Bild */
949       width -= dx;
950     else if (dx)                /* allg. Bewegung in x-Richtung */
951       redraw[redraw_x1 + x + SIGN(dx)][redraw_y1 + y] = TRUE;
952
953     if (y < BY1)                /* Element kommt von oben ins Bild */
954     {
955       if (cut_mode==CUT_BELOW)  /* Element oberhalb des Bildes */
956         return;
957
958       y = BY1;
959       height = dy;
960       cy = TILEY - dy;
961       dy = 0;
962     }
963     else if (y > BY2)           /* Element kommt von unten ins Bild */
964     {
965       y = BY2;
966       height = -dy;
967       dy = TILEY + dy;
968     }
969     else if (y==BY1 && dy<0)    /* Element verläßt oben das Bild */
970     {
971       height += dy;
972       cy = -dy;
973       dy = 0;
974     }
975     else if (dy > 0 && cut_mode==CUT_ABOVE)
976     {
977       if (y == BY2)             /* Element unterhalb des Bildes */
978         return;
979
980       height = dy;
981       cy = TILEY-dy;
982       dy = TILEY;
983       redraw[redraw_x1 + x][redraw_y1 + y + 1] = TRUE;
984     }                           /* Element verläßt unten das Bild */
985     else if (dy > 0 && (y == BY2 || cut_mode==CUT_BELOW))
986       height -= dy;
987     else if (dy)                /* allg. Bewegung in y-Richtung */
988       redraw[redraw_x1 + x][redraw_y1 + y + SIGN(dy)] = TRUE;
989   }
990
991   if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
992   {
993     graphic -= GFX_START_ROCKSSCREEN;
994     src_x  = SX+(graphic % GFX_PER_LINE)*TILEX+cx;
995     src_y  = SY+(graphic / GFX_PER_LINE)*TILEY+cy;
996     dest_x = FX+x*TILEX+dx;
997     dest_y = FY+y*TILEY+dy;
998
999     XSetClipOrigin(display,clip_gc[PIX_BACK],dest_x-src_x,dest_y-src_y);
1000     XCopyArea(display,pix[PIX_BACK],drawto_field,clip_gc[PIX_BACK],
1001               src_x,src_y, width,height, dest_x,dest_y);
1002   }
1003   else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
1004   {
1005     graphic -= GFX_START_ROCKSHEROES;
1006     src_x  = (graphic % HEROES_PER_LINE)*TILEX+cx;
1007     src_y  = (graphic / HEROES_PER_LINE)*TILEY+cy;
1008     dest_x = FX+x*TILEX+dx;
1009     dest_y = FY+y*TILEY+dy;
1010
1011     XSetClipOrigin(display,clip_gc[PIX_HEROES],dest_x-src_x,dest_y-src_y);
1012     XCopyArea(display,pix[PIX_HEROES],drawto_field,clip_gc[PIX_HEROES],
1013               src_x,src_y, width,height, dest_x,dest_y);
1014   }
1015
1016 #if DEBUG
1017   if (!IN_SCR_FIELD(x,y))
1018   {
1019     printf("DrawGraphicShiftedThruMask(): x = %d, y = %d, graphic = %d\n",
1020            x,y,graphic);
1021     printf("DrawGraphicShifted(): This should never happen!\n");
1022     return;
1023   }
1024 #endif
1025
1026   redraw_tiles++;
1027   redraw[redraw_x1 + x][redraw_y1 + y] = TRUE;
1028   redraw_mask |= REDRAW_TILES;
1029 }
1030
1031 void ErdreichAnbroeckeln(int x, int y)
1032 {
1033   int i, width, height, cx,cy;
1034   int ux = UNSCROLLX(x), uy = UNSCROLLY(y);
1035   int element, graphic;
1036   int snip = 4;
1037   static int xy[4][2] =
1038   {
1039     { 0,-1 },
1040     { -1,0 },
1041     { +1,0 },
1042     { 0,+1 }
1043   };
1044
1045   if (!IN_LEV_FIELD(ux,uy))
1046     return;
1047
1048   element = Feld[ux][uy];
1049
1050   if (element==EL_ERDREICH)
1051   {
1052     if (!IN_SCR_FIELD(x,y))
1053       return;
1054
1055     graphic = GFX_ERDENRAND;
1056
1057     for(i=0;i<4;i++)
1058     {
1059       int uxx,uyy;
1060
1061       uxx = ux+xy[i][0];
1062       uyy = uy+xy[i][1];
1063       if (!IN_LEV_FIELD(uxx,uyy))
1064         element = EL_BETON;
1065       else
1066         element = Feld[uxx][uyy];
1067
1068 /*
1069       if (element==EL_ERDREICH || IS_SOLID(element))
1070         continue;
1071 */
1072       if (element==EL_ERDREICH)
1073         continue;
1074
1075       if (i==1 || i==2)
1076       {
1077         width = snip;
1078         height = TILEY;
1079         cx = (i==2 ? TILEX-snip : 0);
1080         cy = 0;
1081       }
1082       else
1083       {
1084         width = TILEX;
1085         height = snip;
1086         cx = 0;
1087         cy = (i==3 ? TILEY-snip : 0);
1088       }
1089
1090       XCopyArea(display,pix[PIX_BACK],drawto_field,gc,
1091                 SX+(graphic % GFX_PER_LINE)*TILEX+cx,
1092                 SY+(graphic / GFX_PER_LINE)*TILEY+cy,
1093                 width,height, FX+x*TILEX+cx,FY+y*TILEY+cy);
1094     }
1095
1096     redraw_tiles++;
1097     redraw[redraw_x1 + x][redraw_y1 + y] = TRUE;
1098   }
1099   else
1100   {
1101     graphic = GFX_ERDENRAND;
1102
1103     for(i=0;i<4;i++)
1104     {
1105       int xx,yy,uxx,uyy;
1106
1107       xx = x+xy[i][0];
1108       yy = y+xy[i][1];
1109       uxx = ux+xy[i][0];
1110       uyy = uy+xy[i][1];
1111 /*
1112       if (!IN_LEV_FIELD(uxx,uyy) || Feld[uxx][uyy]!=EL_ERDREICH ||
1113           !IN_SCR_FIELD(xx,yy) || IS_SOLID(element))
1114         continue;
1115 */
1116
1117       if (!IN_LEV_FIELD(uxx,uyy) || Feld[uxx][uyy]!=EL_ERDREICH ||
1118           !IN_SCR_FIELD(xx,yy))
1119         continue;
1120
1121       if (i==1 || i==2)
1122       {
1123         width = snip;
1124         height = TILEY;
1125         cx = (i==1 ? TILEX-snip : 0);
1126         cy = 0;
1127       }
1128       else
1129       {
1130         width = TILEX;
1131         height = snip;
1132         cx = 0;
1133         cy = (i==0 ? TILEY-snip : 0);
1134       }
1135
1136       XCopyArea(display,pix[PIX_BACK],drawto_field,gc,
1137                 SX+(graphic % GFX_PER_LINE)*TILEX+cx,
1138                 SY+(graphic / GFX_PER_LINE)*TILEY+cy,
1139                 width,height, FX+xx*TILEX+cx,FY+yy*TILEY+cy);
1140
1141       redraw_tiles++;
1142       redraw[redraw_x1 + xx][redraw_y1 + yy] = TRUE;
1143     }
1144   }
1145 }
1146
1147 void DrawScreenElement(int x, int y, int element)
1148 {
1149   DrawElementShifted(x,y,0,0,element,CUT_NO_CUTTING);
1150   ErdreichAnbroeckeln(x,y);
1151 }
1152
1153 void DrawLevelElement(int x, int y, int element)
1154 {
1155   if (IN_LEV_FIELD(x,y) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1156     DrawScreenElement(SCROLLX(x),SCROLLY(y),element);
1157 }
1158
1159 void DrawScreenField(int x, int y)
1160 {
1161   int ux = UNSCROLLX(x), uy = UNSCROLLY(y);
1162   int element;
1163
1164   if (!IN_LEV_FIELD(ux,uy))
1165   {
1166     DrawScreenElement(x,y,EL_BETON);
1167     return;
1168   }
1169
1170   element = Feld[ux][uy];
1171
1172   if (IS_MOVING(ux,uy))
1173   {
1174     int horiz_move = (MovDir[ux][uy]==MV_LEFT || MovDir[ux][uy]==MV_RIGHT);
1175     BOOL cut_mode = CUT_NO_CUTTING;
1176
1177     if (Store[ux][uy]==EL_MORAST_LEER ||
1178         Store[ux][uy]==EL_SIEB_LEER ||
1179         Store[ux][uy]==EL_SIEB2_LEER ||
1180         Store[ux][uy]==EL_AMOEBE_NASS)
1181       cut_mode = CUT_ABOVE;
1182     else if (Store[ux][uy]==EL_MORAST_VOLL ||
1183         Store[ux][uy]==EL_SIEB_VOLL ||
1184         Store[ux][uy]==EL_SIEB2_VOLL ||
1185         Store[ux][uy]==EL_SALZSAEURE)
1186       cut_mode = CUT_BELOW;
1187
1188     if (cut_mode==CUT_ABOVE)
1189       DrawElementShifted(x,y,0,0,Store[ux][uy],CUT_NO_CUTTING);
1190     else
1191       DrawScreenElement(x,y,EL_LEERRAUM);
1192
1193     if (horiz_move)
1194       DrawElementShifted(x,y,MovPos[ux][uy],0,element,CUT_NO_CUTTING);
1195     else
1196       DrawElementShifted(x,y,0,MovPos[ux][uy],element,cut_mode);
1197   }
1198   else if (IS_BLOCKED(ux,uy))
1199   {
1200     int oldx,oldy;
1201     int sx, sy;
1202     int horiz_move;
1203     BOOL cut_mode = CUT_NO_CUTTING;
1204
1205     Blocked2Moving(ux,uy,&oldx,&oldy);
1206     sx = SCROLLX(oldx);
1207     sy = SCROLLY(oldy);
1208     horiz_move = (MovDir[oldx][oldy]==MV_LEFT || MovDir[oldx][oldy]==MV_RIGHT);
1209
1210     if (Store[oldx][oldy]==EL_MORAST_LEER ||
1211         Store[oldx][oldy]==EL_SIEB_LEER ||
1212         Store[oldx][oldy]==EL_SIEB2_LEER ||
1213         Store[oldx][oldy]==EL_AMOEBE_NASS)
1214       cut_mode = CUT_ABOVE;
1215
1216     DrawScreenElement(x,y,EL_LEERRAUM);
1217     element = Feld[oldx][oldy];
1218
1219     if (horiz_move)
1220       DrawElementShifted(sx,sy,MovPos[oldx][oldy],0,element,CUT_NO_CUTTING);
1221     else
1222       DrawElementShifted(sx,sy,0,MovPos[oldx][oldy],element,cut_mode);
1223   }
1224   else if (IS_DRAWABLE(element))
1225     DrawScreenElement(x,y,element);
1226   else
1227     DrawScreenElement(x,y,EL_LEERRAUM);
1228 }
1229
1230 void DrawLevelField(int x, int y)
1231 {
1232   if (IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1233     DrawScreenField(SCROLLX(x),SCROLLY(y));
1234   else if (IS_MOVING(x,y))
1235   {
1236     int newx,newy;
1237
1238     Moving2Blocked(x,y,&newx,&newy);
1239     if (IN_SCR_FIELD(SCROLLX(newx),SCROLLY(newy)))
1240       DrawScreenField(SCROLLX(newx),SCROLLY(newy));
1241   }
1242   else if (IS_BLOCKED(x,y))
1243   {
1244     int oldx,oldy;
1245
1246     Blocked2Moving(x,y,&oldx,&oldy);
1247     if (IN_SCR_FIELD(SCROLLX(oldx),SCROLLY(oldy)))
1248       DrawScreenField(SCROLLX(oldx),SCROLLY(oldy));
1249   }
1250 }
1251
1252 void DrawMiniElement(int x, int y, int element)
1253 {
1254   int graphic;
1255
1256   if (!element)
1257   {
1258     DrawMiniGraphic(x,y,-1);
1259     return;
1260   }
1261
1262   graphic = el2gfx(element);
1263   DrawMiniGraphic(x,y,graphic);
1264
1265   redraw_tiles++;
1266   redraw[x/2][y/2]=TRUE;
1267   redraw_mask|=REDRAW_TILES;
1268 }
1269
1270 void DrawMiniElementOrWall(int x, int y, int scroll_x, int scroll_y)
1271 {
1272   if (x+scroll_x<-1 || x+scroll_x>lev_fieldx ||
1273       y+scroll_y<-1 || y+scroll_y>lev_fieldy)
1274     DrawMiniElement(x,y,EL_LEERRAUM);
1275   else if (x+scroll_x==-1 || x+scroll_x==lev_fieldx ||
1276            y+scroll_y==-1 || y+scroll_y==lev_fieldy)
1277     DrawMiniElement(x,y,EL_BETON);
1278   else
1279     DrawMiniElement(x,y,Feld[x+scroll_x][y+scroll_y]);
1280 }
1281
1282 void DrawMicroElement(int xpos, int ypos, int element)
1283 {
1284   int graphic;
1285
1286   if (element==EL_LEERRAUM)
1287     return;
1288
1289   graphic = el2gfx(element);
1290
1291   XCopyArea(display,pix[PIX_BACK],drawto,gc,
1292             MICRO_GFX_STARTX+(graphic % MICRO_GFX_PER_LINE)*MICRO_TILEX,
1293             MICRO_GFX_STARTY+(graphic / MICRO_GFX_PER_LINE)*MICRO_TILEY,
1294             MICRO_TILEX,MICRO_TILEY, xpos,ypos);
1295 }
1296
1297 void DrawLevel()
1298 {
1299   int x,y;
1300
1301   ClearWindow();
1302
1303   for(x=BX1; x<=BX2; x++)
1304     for(y=BY1; y<=BY2; y++)
1305       DrawScreenField(x,y);
1306
1307   if (soft_scrolling_on)
1308     XCopyArea(display,fieldbuffer,backbuffer,gc,
1309               FX,FY, SXSIZE,SYSIZE,
1310               SX,SY);
1311
1312   redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1313 }
1314
1315 void DrawMiniLevel(int scroll_x, int scroll_y)
1316 {
1317   int x,y;
1318
1319   ClearWindow();
1320
1321   for(x=0;x<2*SCR_FIELDX;x++)
1322     for(y=0;y<2*SCR_FIELDY;y++)
1323       DrawMiniElementOrWall(x,y,scroll_x,scroll_y);
1324
1325   redraw_mask |= REDRAW_FIELD;
1326 }
1327
1328 void DrawMicroLevel(int xpos, int ypos)
1329 {
1330   int x,y;
1331
1332   XFillRectangle(display,drawto,gc,
1333                  xpos-MICRO_TILEX,ypos-MICRO_TILEY,
1334                  MICRO_TILEX*(STD_LEV_FIELDX+2),
1335                  MICRO_TILEY*(STD_LEV_FIELDY+2));
1336   if (lev_fieldx < STD_LEV_FIELDX)
1337     xpos += (STD_LEV_FIELDX - lev_fieldx)/2 * MICRO_TILEX;
1338   if (lev_fieldy < STD_LEV_FIELDY)
1339     ypos += (STD_LEV_FIELDY - lev_fieldy)/2 * MICRO_TILEY;
1340
1341   for(x=-1;x<=STD_LEV_FIELDX;x++)
1342     for(y=-1;y<=STD_LEV_FIELDY;y++)
1343       if (x>=0 && x<lev_fieldx && y>=0 && y<lev_fieldy)
1344         DrawMicroElement(xpos+MICRO_TILEX*x,ypos+MICRO_TILEY*y,
1345                          Feld[x][y]=Ur[x][y]);
1346       else if (x>=-1 && x<lev_fieldx+1 && y>=-1 && y<lev_fieldy+1)
1347         DrawMicroElement(xpos+MICRO_TILEX*x,ypos+MICRO_TILEY*y,
1348                          EL_BETON);
1349
1350   XFillRectangle(display,drawto,gc, SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE);
1351
1352   if (level.name)
1353   {
1354     int len = strlen(level.name);
1355     int lxpos = SX+(SXSIZE-len*FONT4_XSIZE)/2;
1356     int lypos = MICROLABEL_YPOS;
1357
1358     DrawText(lxpos,lypos,level.name,FS_SMALL,FC_SPECIAL2);
1359   }
1360
1361   redraw_mask |= REDRAW_MICROLEV;
1362 }
1363
1364 int AYS_in_range(int x, int y)
1365 {
1366   if (y>DY+249 && y<DY+278)
1367   {
1368     if (x>DX+1 && x<DX+48)
1369       return(1);
1370     else if (x>DX+51 && x<DX+98) 
1371       return(2);
1372   }
1373   return(0);
1374 }
1375
1376 BOOL AreYouSure(char *text, unsigned int ays_state)
1377 {
1378   int mx,my, ty, result = -1;
1379   unsigned int old_door_state;
1380
1381   old_door_state = GetDoorState();
1382
1383   CloseDoor(DOOR_CLOSE_1);
1384
1385   /* Alten Türinhalt sichern */
1386   XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1387             DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1388             DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1);
1389
1390   /* Fragetext schreiben */
1391   XFillRectangle(display,pix[PIX_DB_DOOR],gc,
1392                  DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1,DXSIZE,DYSIZE);
1393
1394   for(ty=0;ty<13;ty++)
1395   {
1396     int tx,tl,tc;
1397     char txt[256];
1398
1399     if (!(*text))
1400       break;
1401     for(tl=0,tx=0;tx<7;tl++,tx++)
1402     {
1403       tc=*(text+tx);
1404       if (!tc || tc==32)
1405         break;
1406     }
1407     if (!tl)
1408     { 
1409       text++; 
1410       ty--; 
1411       continue; 
1412     }
1413     sprintf(txt,text); 
1414     txt[tl]=0;
1415     DrawTextExt(pix[PIX_DB_DOOR],gc,
1416                 DOOR_GFX_PAGEX1+51-(tl*14)/2,SY+ty*16,txt,FS_SMALL,FC_YELLOW);
1417     text+=(tl+(tc==32));
1418   }
1419
1420   if (ays_state & AYS_ASK)
1421     XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1422               DOOR_GFX_PAGEX4,OK_BUTTON_GFX_YPOS,
1423               DXSIZE,OK_BUTTON_YSIZE,
1424               DOOR_GFX_PAGEX1,OK_BUTTON_YPOS);
1425   else if (ays_state & AYS_CONFIRM)
1426     XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1427               DOOR_GFX_PAGEX4,CONFIRM_BUTTON_GFX_YPOS,
1428               DXSIZE,CONFIRM_BUTTON_YSIZE,
1429               DOOR_GFX_PAGEX1,CONFIRM_BUTTON_YPOS);
1430
1431   OpenDoor(DOOR_OPEN_1);
1432   ClearEventQueue();
1433
1434   if (!(ays_state & AYS_ASK) && !(ays_state & AYS_CONFIRM))
1435     return(FALSE);
1436
1437   if (game_status != MAINMENU)
1438     InitAnimation();
1439
1440   button_status = MB_RELEASED;
1441
1442   while(result<0)
1443   {
1444     DoAnimation();
1445     Delay(10000);
1446
1447     if (XPending(display))
1448     {
1449       XEvent event;
1450
1451       XNextEvent(display, &event);
1452       switch(event.type)
1453       {
1454         case Expose:
1455           HandleExposeEvent((XExposeEvent *) &event);
1456           break;
1457         case UnmapNotify:
1458           SleepWhileUnmapped();
1459           break;
1460         case ButtonPress:
1461         case ButtonRelease:
1462         case MotionNotify:
1463         {
1464           int choice;
1465
1466           if (event.type == MotionNotify)
1467           {
1468             motion_status = TRUE;
1469             mx = ((XMotionEvent *) &event)->x;
1470             my = ((XMotionEvent *) &event)->y;
1471           }
1472           else
1473           {
1474             motion_status = FALSE;
1475             mx = ((XButtonEvent *) &event)->x;
1476             my = ((XButtonEvent *) &event)->y;
1477             if (event.type==ButtonPress)
1478               button_status = ((XButtonEvent *) &event)->button;
1479             else
1480               button_status = MB_RELEASED;
1481           }
1482
1483           if (ays_state & AYS_ASK)
1484             choice = CheckChooseButtons(mx,my,button_status);
1485           else
1486             choice = CheckConfirmButton(mx,my,button_status);
1487
1488           switch(choice)
1489           {
1490             case BUTTON_OK:
1491               result = TRUE;
1492               break;
1493             case BUTTON_NO:
1494               result = FALSE;
1495               break;
1496             case BUTTON_CONFIRM:
1497               result = TRUE|FALSE;
1498               break;
1499             default:
1500               break;
1501           }
1502           break;
1503         }
1504         case KeyPress:
1505           switch(XLookupKeysym((XKeyEvent *)&event,
1506                                ((XKeyEvent *)&event)->state))
1507           {
1508             case XK_Return:
1509               result = 1;
1510               break;
1511             case XK_Escape:
1512               result = 0;
1513               break;
1514           }
1515           break;
1516         case FocusIn:
1517         case FocusOut:
1518           HandleFocusEvent((XFocusChangeEvent *) &event);
1519           break;
1520         default:
1521           break;
1522       }
1523     }
1524     else if (JoystickButton() == JOY_BUTTON_NEW_PRESSED)
1525     {
1526       int joy=Joystick();
1527
1528       if (joy & JOY_BUTTON_1)
1529         result = 1;
1530       else if (joy & JOY_BUTTON_2)
1531         result = 0;
1532     }
1533   }
1534
1535   if (game_status != MAINMENU)
1536     StopAnimation();
1537
1538   if (!(ays_state & AYS_STAY_OPEN))
1539   {
1540     CloseDoor(DOOR_CLOSE_1);
1541
1542     if (!(ays_state & AYS_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1543     {
1544       XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1545                 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1546                 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1547       OpenDoor(DOOR_OPEN_1);
1548     }
1549   }
1550
1551   return(result);
1552 }
1553
1554 unsigned int OpenDoor(unsigned int door_state)
1555 {
1556   unsigned int new_door_state;
1557
1558   if (door_state & DOOR_COPY_BACK)
1559   {
1560     XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1561               DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE+VYSIZE,
1562               DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1563     door_state &= ~DOOR_COPY_BACK;
1564   }
1565
1566   new_door_state = MoveDoor(door_state);
1567
1568 /*
1569   ClearEventQueue();
1570 */
1571
1572   return(new_door_state);
1573 }
1574
1575 unsigned int CloseDoor(unsigned int door_state)
1576 {
1577   unsigned int new_door_state;
1578
1579   XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,
1580             DX,DY, DXSIZE,DYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1581   XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,
1582             VX,VY, VXSIZE,VYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1583
1584   new_door_state = MoveDoor(door_state);
1585
1586 /*
1587   ClearEventQueue();
1588 */
1589
1590   return(new_door_state);
1591 }
1592
1593 unsigned int GetDoorState()
1594 {
1595   return(MoveDoor(DOOR_GET_STATE));
1596 }
1597
1598 unsigned int MoveDoor(unsigned int door_state)
1599 {
1600   static unsigned int door1 = DOOR_OPEN_1;
1601   static unsigned int door2 = DOOR_CLOSE_2;
1602   int x, start, stepsize = 4, door_anim_delay = stepsize*5000;
1603
1604   if (door_state == DOOR_GET_STATE)
1605     return(door1 | door2);
1606
1607   if (door1==DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1608     door_state &= ~DOOR_OPEN_1;
1609   else if (door1==DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1610     door_state &= ~DOOR_CLOSE_1;
1611   if (door2==DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1612     door_state &= ~DOOR_OPEN_2;
1613   else if (door2==DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1614     door_state &= ~DOOR_CLOSE_2;
1615
1616   if (quick_doors)
1617   {
1618     stepsize = 20;
1619     door_anim_delay = 0;
1620     StopSound(SND_OEFFNEN);
1621   }
1622
1623   if (door_state & DOOR_ACTION)
1624   {
1625     if (!(door_state & DOOR_NO_DELAY))
1626       PlaySoundStereo(SND_OEFFNEN,PSND_MAX_RIGHT);
1627
1628     start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1629
1630     for(x=start;x<=DXSIZE;x+=stepsize)
1631     {
1632       if (door_state & DOOR_ACTION_1)
1633       {
1634         int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1635         int j = (DXSIZE - i)/3;
1636
1637         XCopyArea(display,pix[PIX_DB_DOOR],drawto,gc,
1638                   DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1+i/2,
1639                   DXSIZE,DYSIZE-i/2, DX,DY);
1640
1641         XFillRectangle(display,drawto,gc,DX,DY+DYSIZE-i/2,DXSIZE,i/2);
1642
1643         XSetClipOrigin(display,clip_gc[PIX_DOOR],
1644                        DX-i,(DY+j)-DOOR_GFX_PAGEY1);
1645         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1646                   DXSIZE,DOOR_GFX_PAGEY1, i,77, DX+DXSIZE-i,DY+j);
1647         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1648                   DXSIZE,DOOR_GFX_PAGEY1+140, i,63, DX+DXSIZE-i,DY+140+j);
1649         XSetClipOrigin(display,clip_gc[PIX_DOOR],
1650                        DX-DXSIZE+i,DY-(DOOR_GFX_PAGEY1+j));
1651         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1652                   DXSIZE-i,DOOR_GFX_PAGEY1+j, i,77-j, DX,DY);
1653         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1654                   DXSIZE-i,DOOR_GFX_PAGEY1+140, i,63, DX,DY+140-j);
1655
1656         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1657                   DXSIZE-i,DOOR_GFX_PAGEY1+77, i,63,
1658                   DX,DY+77-j);
1659         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1660                   DXSIZE-i,DOOR_GFX_PAGEY1+203, i,77,
1661                   DX,DY+203-j);
1662         XSetClipOrigin(display,clip_gc[PIX_DOOR],
1663                        DX-i,(DY+j)-DOOR_GFX_PAGEY1);
1664         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1665                   DXSIZE,DOOR_GFX_PAGEY1+77, i,63,
1666                   DX+DXSIZE-i,DY+77+j);
1667         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1668                   DXSIZE,DOOR_GFX_PAGEY1+203, i,77-j,
1669                   DX+DXSIZE-i,DY+203+j);
1670
1671         redraw_mask |= REDRAW_DOOR_1;
1672       }
1673
1674       if (door_state & DOOR_ACTION_2)
1675       {
1676         int i = (door_state & DOOR_OPEN_2 ? VXSIZE-x : x);
1677         int j = (VXSIZE - i)/3;
1678
1679         XCopyArea(display,pix[PIX_DB_DOOR],drawto,gc,
1680                   DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2+i/2,
1681                   VXSIZE,VYSIZE-i/2, VX,VY);
1682
1683         XFillRectangle(display,drawto,gc,VX,VY+VYSIZE-i/2,VXSIZE,i/2);
1684
1685         XSetClipOrigin(display,clip_gc[PIX_DOOR],
1686                        VX-i,(VY+j)-DOOR_GFX_PAGEY2);
1687         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1688                   VXSIZE,DOOR_GFX_PAGEY2, i,VYSIZE/2, VX+VXSIZE-i,VY+j);
1689         XSetClipOrigin(display,clip_gc[PIX_DOOR],
1690                        VX-VXSIZE+i,VY-(DOOR_GFX_PAGEY2+j));
1691         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1692                   VXSIZE-i,DOOR_GFX_PAGEY2+j, i,VYSIZE/2-j, VX,VY);
1693
1694         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1695                   VXSIZE-i,DOOR_GFX_PAGEY2+VYSIZE/2, i,VYSIZE/2,
1696                   VX,VY+VYSIZE/2-j);
1697         XSetClipOrigin(display,clip_gc[PIX_DOOR],
1698                        VX-i,(VY+j)-DOOR_GFX_PAGEY2);
1699         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1700                   VXSIZE,DOOR_GFX_PAGEY2+VYSIZE/2, i,VYSIZE/2-j,
1701                   VX+VXSIZE-i,VY+VYSIZE/2+j);
1702
1703         redraw_mask |= REDRAW_DOOR_2;
1704       }
1705
1706       BackToFront();
1707       Delay(door_anim_delay);
1708
1709       if (game_status==MAINMENU)
1710         DoAnimation();
1711     }
1712   }
1713
1714   if (door_state & DOOR_ACTION_1)
1715     door1 = door_state & DOOR_ACTION_1;
1716   if (door_state & DOOR_ACTION_2)
1717     door2 = door_state & DOOR_ACTION_2;
1718
1719   return(door1 | door2);
1720 }
1721
1722 int ReadPixel(Drawable d, int x, int y)
1723 {
1724   static XImage *pixelimage;
1725
1726   pixelimage = XGetImage(display, d, x,y, 1,1, AllPlanes, ZPixmap);
1727   return(XGetPixel(pixelimage,0,0));
1728 }
1729
1730 int el2gfx(int element)
1731 {
1732   switch(element)
1733   {
1734     case EL_LEERRAUM:           return(-1);
1735     case EL_ERDREICH:           return(GFX_ERDREICH);
1736     case EL_MAUERWERK:          return(GFX_MAUERWERK);
1737     case EL_FELSBODEN:          return(GFX_FELSBODEN);
1738     case EL_FELSBROCKEN:        return(GFX_FELSBROCKEN);
1739     case EL_SCHLUESSEL:         return(GFX_SCHLUESSEL);
1740     case EL_EDELSTEIN:          return(GFX_EDELSTEIN);
1741     case EL_AUSGANG_ZU:         return(GFX_AUSGANG_ZU);
1742     case EL_AUSGANG_ACT:        return(GFX_AUSGANG_ACT);
1743     case EL_AUSGANG_AUF:        return(GFX_AUSGANG_AUF);
1744     case EL_SPIELFIGUR:         return(GFX_SPIELFIGUR);
1745     case EL_SPIELER1:           return(GFX_SPIELER1);
1746     case EL_SPIELER2:           return(GFX_SPIELER2);
1747     case EL_SPIELER3:           return(GFX_SPIELER3);
1748     case EL_SPIELER4:           return(GFX_SPIELER4);
1749     case EL_KAEFER:             return(GFX_KAEFER);
1750     case EL_KAEFER_R:           return(GFX_KAEFER_R);
1751     case EL_KAEFER_O:           return(GFX_KAEFER_O);
1752     case EL_KAEFER_L:           return(GFX_KAEFER_L);
1753     case EL_KAEFER_U:           return(GFX_KAEFER_U);
1754     case EL_FLIEGER:            return(GFX_FLIEGER);
1755     case EL_FLIEGER_R:          return(GFX_FLIEGER_R);
1756     case EL_FLIEGER_O:          return(GFX_FLIEGER_O);
1757     case EL_FLIEGER_L:          return(GFX_FLIEGER_L);
1758     case EL_FLIEGER_U:          return(GFX_FLIEGER_U);
1759     case EL_BUTTERFLY:          return(GFX_BUTTERFLY);
1760     case EL_BUTTERFLY_R:        return(GFX_BUTTERFLY_R);
1761     case EL_BUTTERFLY_O:        return(GFX_BUTTERFLY_O);
1762     case EL_BUTTERFLY_L:        return(GFX_BUTTERFLY_L);
1763     case EL_BUTTERFLY_U:        return(GFX_BUTTERFLY_U);
1764     case EL_FIREFLY:            return(GFX_FIREFLY);
1765     case EL_FIREFLY_R:          return(GFX_FIREFLY_R);
1766     case EL_FIREFLY_O:          return(GFX_FIREFLY_O);
1767     case EL_FIREFLY_L:          return(GFX_FIREFLY_L);
1768     case EL_FIREFLY_U:          return(GFX_FIREFLY_U);
1769     case EL_MAMPFER:            return(GFX_MAMPFER);
1770     case EL_ROBOT:              return(GFX_ROBOT);
1771     case EL_BETON:              return(GFX_BETON);
1772     case EL_DIAMANT:            return(GFX_DIAMANT);
1773     case EL_MORAST_LEER:        return(GFX_MORAST_LEER);
1774     case EL_MORAST_VOLL:        return(GFX_MORAST_VOLL);
1775     case EL_TROPFEN:            return(GFX_TROPFEN);
1776     case EL_BOMBE:              return(GFX_BOMBE);
1777     case EL_SIEB_LEER:          return(GFX_SIEB_LEER);
1778     case EL_SIEB_VOLL:          return(GFX_SIEB_VOLL);
1779     case EL_SIEB_TOT:           return(GFX_SIEB_TOT);
1780     case EL_SALZSAEURE:         return(GFX_SALZSAEURE);
1781     case EL_AMOEBE_TOT:         return(GFX_AMOEBE_TOT);
1782     case EL_AMOEBE_NASS:        return(GFX_AMOEBE_NASS);
1783     case EL_AMOEBE_NORM:        return(GFX_AMOEBE_NORM);
1784     case EL_AMOEBE_VOLL:        return(GFX_AMOEBE_VOLL);
1785     case EL_AMOEBE_BD:          return(GFX_AMOEBE_BD);
1786     case EL_AMOEBA2DIAM:        return(GFX_AMOEBA2DIAM);
1787     case EL_KOKOSNUSS:          return(GFX_KOKOSNUSS);
1788     case EL_LIFE:               return(GFX_LIFE);
1789     case EL_LIFE_ASYNC:         return(GFX_LIFE_ASYNC);
1790     case EL_DYNAMIT:            return(GFX_DYNAMIT);
1791     case EL_BADEWANNE:          return(GFX_BADEWANNE);
1792     case EL_BADEWANNE1:         return(GFX_BADEWANNE1);
1793     case EL_BADEWANNE2:         return(GFX_BADEWANNE2);
1794     case EL_BADEWANNE3:         return(GFX_BADEWANNE3);
1795     case EL_BADEWANNE4:         return(GFX_BADEWANNE4);
1796     case EL_BADEWANNE5:         return(GFX_BADEWANNE5);
1797     case EL_ABLENK_AUS:         return(GFX_ABLENK_AUS);
1798     case EL_ABLENK_EIN:         return(GFX_ABLENK_EIN);
1799     case EL_SCHLUESSEL1:        return(GFX_SCHLUESSEL1);
1800     case EL_SCHLUESSEL2:        return(GFX_SCHLUESSEL2);
1801     case EL_SCHLUESSEL3:        return(GFX_SCHLUESSEL3);
1802     case EL_SCHLUESSEL4:        return(GFX_SCHLUESSEL4);
1803     case EL_PFORTE1:            return(GFX_PFORTE1);
1804     case EL_PFORTE2:            return(GFX_PFORTE2);
1805     case EL_PFORTE3:            return(GFX_PFORTE3);
1806     case EL_PFORTE4:            return(GFX_PFORTE4);
1807     case EL_PFORTE1X:           return(GFX_PFORTE1X);
1808     case EL_PFORTE2X:           return(GFX_PFORTE2X);
1809     case EL_PFORTE3X:           return(GFX_PFORTE3X);
1810     case EL_PFORTE4X:           return(GFX_PFORTE4X);
1811     case EL_DYNAMIT_AUS:        return(GFX_DYNAMIT_AUS);
1812     case EL_PACMAN:             return(GFX_PACMAN);
1813     case EL_PACMAN_R:           return(GFX_PACMAN_R);
1814     case EL_PACMAN_O:           return(GFX_PACMAN_O);
1815     case EL_PACMAN_L:           return(GFX_PACMAN_L);
1816     case EL_PACMAN_U:           return(GFX_PACMAN_U);
1817     case EL_UNSICHTBAR:         return(GFX_UNSICHTBAR);
1818     case EL_ERZ_EDEL:           return(GFX_ERZ_EDEL);
1819     case EL_ERZ_DIAM:           return(GFX_ERZ_DIAM);
1820     case EL_BIRNE_AUS:          return(GFX_BIRNE_AUS);
1821     case EL_BIRNE_EIN:          return(GFX_BIRNE_EIN);
1822     case EL_ZEIT_VOLL:          return(GFX_ZEIT_VOLL);
1823     case EL_ZEIT_LEER:          return(GFX_ZEIT_LEER);
1824     case EL_MAUER_LEBT:         return(GFX_MAUER_LEBT);
1825     case EL_EDELSTEIN_BD:       return(GFX_EDELSTEIN_BD);
1826     case EL_EDELSTEIN_GELB:     return(GFX_EDELSTEIN_GELB);
1827     case EL_EDELSTEIN_ROT:      return(GFX_EDELSTEIN_ROT);
1828     case EL_EDELSTEIN_LILA:     return(GFX_EDELSTEIN_LILA);
1829     case EL_ERZ_EDEL_BD:        return(GFX_ERZ_EDEL_BD);
1830     case EL_ERZ_EDEL_GELB:      return(GFX_ERZ_EDEL_GELB);
1831     case EL_ERZ_EDEL_ROT:       return(GFX_ERZ_EDEL_ROT);
1832     case EL_ERZ_EDEL_LILA:      return(GFX_ERZ_EDEL_LILA);
1833     case EL_MAMPFER2:           return(GFX_MAMPFER2);
1834     case EL_SIEB2_LEER:         return(GFX_SIEB2_LEER);
1835     case EL_SIEB2_VOLL:         return(GFX_SIEB2_VOLL);
1836     case EL_SIEB2_TOT:          return(GFX_SIEB2_TOT);
1837     case EL_DYNABOMB:           return(GFX_DYNABOMB);
1838     case EL_DYNABOMB_NR:        return(GFX_DYNABOMB_NR);
1839     case EL_DYNABOMB_SZ:        return(GFX_DYNABOMB_SZ);
1840     case EL_DYNABOMB_XL:        return(GFX_DYNABOMB_XL);
1841     case EL_SOKOBAN_OBJEKT:     return(GFX_SOKOBAN_OBJEKT);
1842     case EL_SOKOBAN_FELD_LEER:  return(GFX_SOKOBAN_FELD_LEER);
1843     case EL_SOKOBAN_FELD_VOLL:  return(GFX_SOKOBAN_FELD_VOLL);
1844     case EL_MAULWURF:           return(GFX_MAULWURF);
1845     case EL_PINGUIN:            return(GFX_PINGUIN);
1846     case EL_SCHWEIN:            return(GFX_SCHWEIN);
1847     case EL_DRACHE:             return(GFX_DRACHE);
1848     case EL_SONDE:              return(GFX_SONDE);
1849     case EL_PFEIL_L:            return(GFX_PFEIL_L);
1850     case EL_PFEIL_R:            return(GFX_PFEIL_R);
1851     case EL_PFEIL_O:            return(GFX_PFEIL_O);
1852     case EL_PFEIL_U:            return(GFX_PFEIL_U);
1853     default:
1854     {
1855       if (IS_CHAR(element))
1856         return(GFX_CHAR_START + (element-EL_CHAR_START));
1857       else
1858         return(-1);
1859     }
1860   }
1861 }