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