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