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