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