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