ebc8cb6dd6a0a0f95b4cc4fe98d4da8953ac4f25
[rocksndiamonds.git] / src / tools.c
1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back!               *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment                      *
5 *               Holger Schemel                             *
6 *               Detmolder Strasse 189                      *
7 *               33604 Bielefeld                            *
8 *               Germany                                    *
9 *               e-mail: info@artsoft.org                   *
10 *----------------------------------------------------------*
11 * tools.c                                                  *
12 ***********************************************************/
13
14 #include "libgame/libgame.h"
15
16 #include "tools.h"
17 #include "game.h"
18 #include "events.h"
19 #include "cartoons.h"
20 #include "network.h"
21 #include "tape.h"
22
23 /* tool button identifiers */
24 #define TOOL_CTRL_ID_YES        0
25 #define TOOL_CTRL_ID_NO         1
26 #define TOOL_CTRL_ID_CONFIRM    2
27 #define TOOL_CTRL_ID_PLAYER_1   3
28 #define TOOL_CTRL_ID_PLAYER_2   4
29 #define TOOL_CTRL_ID_PLAYER_3   5
30 #define TOOL_CTRL_ID_PLAYER_4   6
31
32 #define NUM_TOOL_BUTTONS        7
33
34 /* forward declaration for internal use */
35 static int getGraphicAnimationPhase(int, int, int);
36 static void DrawGraphicAnimationShiftedThruMask(int, int, int, int, int,
37                                                 int, int, int);
38 static void UnmapToolButtons();
39 static void HandleToolButtons(struct GadgetInfo *);
40
41 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
42 static int request_gadget_id = -1;
43
44 void SetDrawtoField(int mode)
45 {
46   if (mode == DRAW_BUFFERED && setup.soft_scrolling)
47   {
48     FX = TILEX;
49     FY = TILEY;
50     BX1 = -1;
51     BY1 = -1;
52     BX2 = SCR_FIELDX;
53     BY2 = SCR_FIELDY;
54     redraw_x1 = 1;
55     redraw_y1 = 1;
56
57     drawto_field = fieldbuffer;
58   }
59   else  /* DRAW_DIRECT, DRAW_BACKBUFFER */
60   {
61     FX = SX;
62     FY = SY;
63     BX1 = 0;
64     BY1 = 0;
65     BX2 = SCR_FIELDX - 1;
66     BY2 = SCR_FIELDY - 1;
67     redraw_x1 = 0;
68     redraw_y1 = 0;
69
70     drawto_field = (mode == DRAW_DIRECT ? window :  backbuffer);
71   }
72 }
73
74 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
75 {
76   if (game_status == PLAYING)
77   {
78     if (force_redraw)
79     {
80       x = gfx.sx - TILEX;
81       y = gfx.sy - TILEY;
82       width = gfx.sxsize + 2 * TILEX;
83       height = gfx.sysize + 2 * TILEY;
84     }
85
86     if (force_redraw || setup.direct_draw)
87     {
88       int xx, yy;
89       int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
90       int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
91
92       if (setup.direct_draw)
93         SetDrawtoField(DRAW_BACKBUFFER);
94
95       for(xx=BX1; xx<=BX2; xx++)
96         for(yy=BY1; yy<=BY2; yy++)
97           if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
98             DrawScreenField(xx, yy);
99       DrawAllPlayers();
100
101       if (setup.direct_draw)
102         SetDrawtoField(DRAW_DIRECT);
103     }
104
105     if (setup.soft_scrolling)
106     {
107       int fx = FX, fy = FY;
108
109       fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
110       fy += (ScreenMovDir & (MV_UP|MV_DOWN)    ? ScreenGfxPos : 0);
111
112       BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
113     }
114   }
115
116   BlitBitmap(drawto, window, x, y, width, height, x, y);
117 }
118
119 void BackToFront()
120 {
121   int x,y;
122   DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
123
124   if (setup.direct_draw && game_status == PLAYING)
125     redraw_mask &= ~REDRAW_MAIN;
126
127   if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
128     redraw_mask |= REDRAW_FIELD;
129
130   if (redraw_mask & REDRAW_FIELD)
131     redraw_mask &= ~REDRAW_TILES;
132
133   if (redraw_mask == REDRAW_NONE)
134     return;
135
136   if (global.fps_slowdown && game_status == PLAYING)
137   {
138     static boolean last_frame_skipped = FALSE;
139     boolean skip_even_when_not_scrolling = TRUE;
140     boolean just_scrolling = (ScreenMovDir != 0);
141     boolean verbose = FALSE;
142
143     if (global.fps_slowdown_factor > 1 &&
144         (FrameCounter % global.fps_slowdown_factor) &&
145         (just_scrolling || skip_even_when_not_scrolling))
146     {
147       redraw_mask &= ~REDRAW_MAIN;
148
149       last_frame_skipped = TRUE;
150
151       if (verbose)
152         printf("FRAME SKIPPED\n");
153     }
154     else
155     {
156       if (last_frame_skipped)
157         redraw_mask |= REDRAW_FIELD;
158
159       last_frame_skipped = FALSE;
160
161       if (verbose)
162         printf("frame not skipped\n");
163     }
164   }
165
166   /* synchronize X11 graphics at this point; if we would synchronize the
167      display immediately after the buffer switching (after the XFlush),
168      this could mean that we have to wait for the graphics to complete,
169      although we could go on doing calculations for the next frame */
170
171   SyncDisplay();
172
173   if (redraw_mask & REDRAW_ALL)
174   {
175     BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
176     redraw_mask = 0;
177   }
178
179   if (redraw_mask & REDRAW_FIELD)
180   {
181     if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
182     {
183       BlitBitmap(backbuffer, window,
184                  REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
185     }
186     else
187     {
188       int fx = FX, fy = FY;
189
190       if (setup.soft_scrolling)
191       {
192         fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
193         fy += (ScreenMovDir & (MV_UP | MV_DOWN)    ? ScreenGfxPos : 0);
194       }
195
196       if (setup.soft_scrolling ||
197           ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
198           ABS(ScreenMovPos) == ScrollStepSize ||
199           redraw_tiles > REDRAWTILES_THRESHOLD)
200       {
201         BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
202
203 #ifdef DEBUG
204 #if 0
205         printf("redrawing all (ScreenGfxPos == %d) because %s\n",
206                ScreenGfxPos,
207                (setup.soft_scrolling ?
208                 "setup.soft_scrolling" :
209                 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
210                 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
211                 ABS(ScreenGfxPos) == ScrollStepSize ?
212                 "ABS(ScreenGfxPos) == ScrollStepSize" :
213                 "redraw_tiles > REDRAWTILES_THRESHOLD"));
214 #endif
215 #endif
216       }
217     }
218
219     redraw_mask &= ~REDRAW_MAIN;
220   }
221
222   if (redraw_mask & REDRAW_DOORS)
223   {
224     if (redraw_mask & REDRAW_DOOR_1)
225       BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
226     if (redraw_mask & REDRAW_DOOR_2)
227     {
228       if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
229         BlitBitmap(backbuffer, window, VX,VY, VXSIZE,VYSIZE, VX,VY);
230       else
231       {
232         if (redraw_mask & REDRAW_VIDEO_1)
233           BlitBitmap(backbuffer, window,
234                      VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
235                      VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
236                      VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
237         if (redraw_mask & REDRAW_VIDEO_2)
238           BlitBitmap(backbuffer, window,
239                      VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
240                      VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
241                      VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
242         if (redraw_mask & REDRAW_VIDEO_3)
243           BlitBitmap(backbuffer, window,
244                      VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
245                      VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
246                      VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
247       }
248     }
249     if (redraw_mask & REDRAW_DOOR_3)
250       BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
251     redraw_mask &= ~REDRAW_DOORS;
252   }
253
254   if (redraw_mask & REDRAW_MICROLEVEL)
255   {
256     BlitBitmap(backbuffer, window,
257                MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
258                MICROLEV_XPOS, MICROLEV_YPOS);
259     BlitBitmap(backbuffer, window,
260                SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
261                SX, MICROLABEL_YPOS);
262     redraw_mask &= ~REDRAW_MICROLEVEL;
263   }
264
265   if (redraw_mask & REDRAW_TILES)
266   {
267     for(x=0; x<SCR_FIELDX; x++)
268       for(y=0; y<SCR_FIELDY; y++)
269         if (redraw[redraw_x1 + x][redraw_y1 + y])
270           BlitBitmap(buffer, window,
271                      FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
272                      SX + x * TILEX, SY + y * TILEY);
273   }
274
275   if (redraw_mask & REDRAW_FPS)         /* display frames per second */
276   {
277     char text[100];
278     char info1[100];
279
280     sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
281     if (!global.fps_slowdown)
282       info1[0] = '\0';
283
284     sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
285     DrawTextExt(window, SX, SY, text, FS_SMALL, FC_YELLOW);
286   }
287
288   FlushDisplay();
289
290   for(x=0; x<MAX_BUF_XSIZE; x++)
291     for(y=0; y<MAX_BUF_YSIZE; y++)
292       redraw[x][y] = 0;
293   redraw_tiles = 0;
294   redraw_mask = REDRAW_NONE;
295 }
296
297 void FadeToFront()
298 {
299 #if 0
300   long fading_delay = 300;
301
302   if (setup.fading && (redraw_mask & REDRAW_FIELD))
303   {
304 #endif
305
306 #if 0
307     int x,y;
308
309     ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
310     FlushDisplay();
311
312     for(i=0;i<2*FULL_SYSIZE;i++)
313     {
314       for(y=0;y<FULL_SYSIZE;y++)
315       {
316         BlitBitmap(backbuffer, window,
317                    REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
318       }
319       FlushDisplay();
320       Delay(10);
321     }
322 #endif
323
324 #if 0
325     for(i=1;i<FULL_SYSIZE;i+=2)
326       BlitBitmap(backbuffer, window,
327                  REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
328     FlushDisplay();
329     Delay(fading_delay);
330 #endif
331
332 #if 0
333     SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
334     BlitBitmapMasked(backbuffer, window,
335                      REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
336                      REAL_SX,REAL_SY);
337     FlushDisplay();
338     Delay(fading_delay);
339
340     SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
341     BlitBitmapMasked(backbuffer, window,
342                      REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
343                      REAL_SX,REAL_SY);
344     FlushDisplay();
345     Delay(fading_delay);
346
347     SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
348     BlitBitmapMasked(backbuffer, window,
349                      REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
350                      REAL_SX,REAL_SY);
351     FlushDisplay();
352     Delay(fading_delay);
353
354     SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
355     BlitBitmapMasked(backbuffer, window,
356                      REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
357                      REAL_SX,REAL_SY);
358     FlushDisplay();
359     Delay(fading_delay);
360
361     redraw_mask &= ~REDRAW_MAIN;
362   }
363 #endif
364
365   BackToFront();
366 }
367
368 void ClearWindow()
369 {
370   ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
371
372   if (setup.soft_scrolling && game_status == PLAYING)
373   {
374     ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
375     SetDrawtoField(DRAW_BUFFERED);
376   }
377   else
378     SetDrawtoField(DRAW_BACKBUFFER);
379
380   if (setup.direct_draw && game_status == PLAYING)
381   {
382     ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
383     SetDrawtoField(DRAW_DIRECT);
384   }
385
386   redraw_mask |= REDRAW_FIELD;
387 }
388
389 void MarkTileDirty(int x, int y)
390 {
391   int xx = redraw_x1 + x;
392   int yy = redraw_y1 + y;
393
394   if (!redraw[xx][yy])
395     redraw_tiles++;
396
397   redraw[xx][yy] = TRUE;
398   redraw_mask |= REDRAW_TILES;
399 }
400
401 void SetBorderElement()
402 {
403   int x, y;
404
405   BorderElement = EL_EMPTY;
406
407   for(y=0; y<lev_fieldy && BorderElement == EL_EMPTY; y++)
408   {
409     for(x=0; x<lev_fieldx; x++)
410     {
411       if (!IS_MASSIVE(Feld[x][y]))
412         BorderElement = EL_STEELWALL;
413
414       if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
415         x = lev_fieldx - 2;
416     }
417   }
418 }
419
420 void DrawAllPlayers()
421 {
422   int i;
423
424   for(i=0; i<MAX_PLAYERS; i++)
425     if (stored_player[i].active)
426       DrawPlayer(&stored_player[i]);
427 }
428
429 void DrawPlayerField(int x, int y)
430 {
431   if (!IS_PLAYER(x, y))
432     return;
433
434   DrawPlayer(PLAYERINFO(x, y));
435 }
436
437 void DrawPlayer(struct PlayerInfo *player)
438 {
439   int jx = player->jx, jy = player->jy;
440   int last_jx = player->last_jx, last_jy = player->last_jy;
441   int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
442   int sx = SCREENX(jx), sy = SCREENY(jy);
443   int sxx = 0, syy = 0;
444   int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
445   int graphic, phase;
446   boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
447
448   if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
449     return;
450
451 #if DEBUG
452   if (!IN_LEV_FIELD(jx,jy))
453   {
454     printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
455     printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
456     printf("DrawPlayerField(): This should never happen!\n");
457     return;
458   }
459 #endif
460
461   if (element == EL_EXPLOSION)
462     return;
463
464   /* draw things in the field the player is leaving, if needed */
465
466   if (player_is_moving)
467   {
468     if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
469     {
470       DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
471       if (last_element == EL_DYNAMITE_ACTIVE)
472         DrawDynamite(last_jx, last_jy);
473       else
474         DrawLevelFieldThruMask(last_jx, last_jy);
475     }
476     else if (last_element == EL_DYNAMITE_ACTIVE)
477       DrawDynamite(last_jx, last_jy);
478     else
479       DrawLevelField(last_jx, last_jy);
480
481     if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
482     {
483       if (player->GfxPos)
484       {
485         if (Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
486           DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FIELD_EMPTY);
487         else
488           DrawLevelElement(next_jx, next_jy, EL_EMPTY);
489       }
490       else
491         DrawLevelField(next_jx, next_jy);
492     }
493   }
494
495   if (!IN_SCR_FIELD(sx, sy))
496     return;
497
498   if (setup.direct_draw)
499     SetDrawtoField(DRAW_BUFFERED);
500
501   /* draw things behind the player, if needed */
502
503   if (Store[jx][jy])
504     DrawLevelElement(jx, jy, Store[jx][jy]);
505   else if (!IS_ACTIVE_BOMB(element))
506     DrawLevelField(jx, jy);
507   else
508     DrawLevelElement(jx, jy, EL_EMPTY);
509
510   /* draw player himself */
511
512   if (game.emulation == EMU_SUPAPLEX)
513   {
514     static int last_dir = MV_LEFT;
515     int action = (player->programmed_action ? player->programmed_action :
516                   player->action);
517     boolean action_moving =
518       (player_is_moving ||
519        ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
520         !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
521
522     graphic = GFX_SP_MURPHY;
523
524     if (player->Pushing)
525     {
526       if (player->MovDir == MV_LEFT)
527         graphic = GFX_MURPHY_PUSH_LEFT;
528       else if (player->MovDir == MV_RIGHT)
529         graphic = GFX_MURPHY_PUSH_RIGHT;
530       else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
531         graphic = GFX_MURPHY_PUSH_LEFT;
532       else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
533         graphic = GFX_MURPHY_PUSH_RIGHT;
534     }
535     else if (player->snapped)
536     {
537       if (player->MovDir == MV_LEFT)
538         graphic = GFX_MURPHY_SNAP_LEFT;
539       else if (player->MovDir == MV_RIGHT)
540         graphic = GFX_MURPHY_SNAP_RIGHT;
541       else if (player->MovDir == MV_UP)
542         graphic = GFX_MURPHY_SNAP_UP;
543       else if (player->MovDir == MV_DOWN)
544         graphic = GFX_MURPHY_SNAP_DOWN;
545     }
546     else if (action_moving)
547     {
548       if (player->MovDir == MV_LEFT)
549         graphic = GFX_MURPHY_GO_LEFT;
550       else if (player->MovDir == MV_RIGHT)
551         graphic = GFX_MURPHY_GO_RIGHT;
552       else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
553         graphic = GFX_MURPHY_GO_LEFT;
554       else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
555         graphic = GFX_MURPHY_GO_RIGHT;
556       else
557         graphic = GFX_MURPHY_GO_LEFT;
558
559       graphic += getGraphicAnimationPhase(3, 2, ANIM_PINGPONG);
560     }
561
562     if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
563       last_dir = player->MovDir;
564   }
565   else
566   {
567     if (player->MovDir == MV_LEFT)
568       graphic =
569         (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
570     else if (player->MovDir == MV_RIGHT)
571       graphic =
572         (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
573     else if (player->MovDir == MV_UP)
574       graphic = GFX_SPIELER1_UP;
575     else        /* MV_DOWN || MV_NO_MOVING */
576       graphic = GFX_SPIELER1_DOWN;
577
578     graphic += player->index_nr * 3 * HEROES_PER_LINE;
579     graphic += player->Frame;
580   }
581
582   if (player->GfxPos)
583   {
584     if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
585       sxx = player->GfxPos;
586     else
587       syy = player->GfxPos;
588   }
589
590   if (!setup.soft_scrolling && ScreenMovPos)
591     sxx = syy = 0;
592
593   DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
594
595   if (SHIELD_ON(player))
596   {
597     int graphic = (player->shield_active_time_left ? GFX2_SHIELD_ACTIVE :
598                    GFX2_SHIELD_PASSIVE);
599
600     DrawGraphicAnimationShiftedThruMask(sx, sy, sxx, syy, graphic,
601                                         3, 8, ANIM_PINGPONG);
602   }
603
604   if (player->Pushing && player->GfxPos)
605   {
606     int px = SCREENX(next_jx), py = SCREENY(next_jy);
607
608     if (element == EL_SOKOBAN_FIELD_EMPTY ||
609         Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
610       DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
611                                  NO_CUTTING);
612     else
613     {
614       int element = Feld[next_jx][next_jy];
615       int graphic = el2gfx(element);
616
617       if ((element == EL_ROCK ||
618            element == EL_SP_ZONK ||
619            element == EL_BD_ROCK) && sxx)
620       {
621         int phase = (player->GfxPos / (TILEX / 4));
622
623         if (player->MovDir == MV_LEFT)
624           graphic += phase;
625         else
626           graphic += (phase + 4) % 4;
627       }
628
629       DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
630     }
631   }
632
633   /* draw things in front of player (active dynamite or dynabombs) */
634
635   if (IS_ACTIVE_BOMB(element))
636   {
637     graphic = el2gfx(element);
638
639     if (element == EL_DYNAMITE_ACTIVE)
640     {
641       if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
642         phase = 6;
643     }
644     else
645     {
646       if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
647         phase = 7 - phase;
648     }
649
650     if (game.emulation == EMU_SUPAPLEX)
651       DrawGraphic(sx, sy, GFX_SP_DISK_RED);
652     else
653       DrawGraphicThruMask(sx, sy, graphic + phase);
654   }
655
656   if (player_is_moving && last_element == EL_EXPLOSION)
657   {
658     int phase = Frame[last_jx][last_jy];
659     int delay = 2;
660
661     if (phase > 2)
662       DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
663                           GFX_EXPLOSION + ((phase - 1) / delay - 1));
664   }
665
666   /* draw elements that stay over the player */
667   /* handle the field the player is leaving ... */
668   if (player_is_moving && IS_OVER_PLAYER(last_element))
669     DrawLevelField(last_jx, last_jy);
670   /* ... and the field the player is entering */
671   if (IS_OVER_PLAYER(element))
672     DrawLevelField(jx, jy);
673
674   if (setup.direct_draw)
675   {
676     int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
677     int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
678     int x_size = TILEX * (1 + ABS(jx - last_jx));
679     int y_size = TILEY * (1 + ABS(jy - last_jy));
680
681     BlitBitmap(drawto_field, window,
682                dest_x, dest_y, x_size, y_size, dest_x, dest_y);
683     SetDrawtoField(DRAW_DIRECT);
684   }
685
686   MarkTileDirty(sx,sy);
687 }
688
689 static int getGraphicAnimationPhase(int frames, int delay, int mode)
690 {
691   int phase;
692
693   if (mode == ANIM_PINGPONG)
694   {
695     int max_anim_frames = 2 * frames - 2;
696
697     phase = (FrameCounter % (delay * max_anim_frames)) / delay;
698     phase = (phase < frames ? phase : max_anim_frames - phase);
699   }
700   else
701     phase = (FrameCounter % (delay * frames)) / delay;
702
703   if (mode == ANIM_REVERSE)
704     phase = -phase;
705
706   return phase;
707 }
708
709 int getNewGraphicAnimationFrame(int graphic, int sync_frame)
710 {
711   int num_frames = new_graphic_info[graphic].anim_frames;
712   int delay = new_graphic_info[graphic].anim_delay;
713   int mode = new_graphic_info[graphic].anim_mode;
714   int frame = 0;
715
716   /* animation synchronized with global frame counter, not move position */
717   if (new_graphic_info[graphic].anim_global_sync || sync_frame < 0)
718     sync_frame = FrameCounter;
719
720   if (mode & ANIM_LOOP)                 /* normal, looping animation */
721   {
722     frame = (sync_frame % (delay * num_frames)) / delay;
723   }
724   else if (mode & ANIM_LINEAR)          /* normal, non-looping animation */
725   {
726     frame = sync_frame / delay;
727
728     if (frame > num_frames - 1)
729       frame = num_frames - 1;
730   }
731   else if (mode & ANIM_PINGPONG)        /* use border frames once */
732   {
733     int max_anim_frames = 2 * num_frames - 2;
734
735     frame = (sync_frame % (delay * max_anim_frames)) / delay;
736     frame = (frame < num_frames ? frame : max_anim_frames - frame);
737   }
738   else if (mode & ANIM_PINGPONG2)       /* use border frames twice */
739   {
740     int max_anim_frames = 2 * num_frames;
741
742     frame = (sync_frame % (delay * max_anim_frames)) / delay;
743     frame = (frame < num_frames ? frame : max_anim_frames - frame - 1);
744   }
745
746   if (mode & ANIM_REVERSE)              /* use reverse animation direction */
747     frame = num_frames - frame - 1;
748
749   return frame;
750 }
751
752 void DrawGraphicAnimationExt(int x, int y, int graphic,
753                              int frames, int delay, int mode, int mask_mode)
754 {
755   int phase = getGraphicAnimationPhase(frames, delay, mode);
756
757   if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
758   {
759     if (mask_mode == USE_MASKING)
760       DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
761     else
762       DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
763   }
764 }
765
766 void DrawNewGraphicAnimationExt(int x, int y, int graphic, int mask_mode)
767 {
768   int delay = new_graphic_info[graphic].anim_delay;
769
770 #if 0
771   if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
772 #else
773   if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
774 #endif
775   {
776     int frame = getNewGraphicAnimationFrame(graphic, -1);
777
778     if (mask_mode == USE_MASKING)
779       DrawNewGraphicThruMask(SCREENX(x), SCREENY(y), graphic, frame);
780     else
781       DrawNewGraphic(SCREENX(x), SCREENY(y), graphic, frame);
782   }
783 }
784
785 void DrawGraphicAnimation(int x, int y, int graphic,
786                           int frames, int delay, int mode)
787 {
788   DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
789 }
790
791 void DrawNewGraphicAnimation(int x, int y, int graphic)
792 {
793   DrawNewGraphicAnimationExt(x, y, graphic, NO_MASKING);
794 }
795
796 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
797                                   int frames, int delay, int mode)
798 {
799   DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
800 }
801
802 static void DrawGraphicAnimationShiftedThruMask(int sx, int sy,
803                                                 int sxx, int syy,
804                                                 int graphic,
805                                                 int frames, int delay,
806                                                 int mode)
807 {
808   int phase = getGraphicAnimationPhase(frames, delay, mode);
809
810   DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic + phase, NO_CUTTING);
811 }
812
813 void getGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
814 {
815   if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
816   {
817     *bitmap = graphic_info[graphic].bitmap;
818     *x = graphic_info[graphic].src_x;
819     *y = graphic_info[graphic].src_y;
820   }
821   else if (graphic >= GFX_START_ROCKSELEMENTS &&
822            graphic <= GFX_END_ROCKSELEMENTS)
823   {
824     graphic -= GFX_START_ROCKSELEMENTS;
825     *bitmap = pix[PIX_ELEMENTS];
826     *x = (graphic % GFX_PER_LINE) * TILEX;
827     *y = (graphic / GFX_PER_LINE) * TILEY;
828   }
829   else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
830   {
831     graphic -= GFX_START_ROCKSHEROES;
832     *bitmap = pix[PIX_HEROES];
833     *x = (graphic % HEROES_PER_LINE) * TILEX;
834     *y = (graphic / HEROES_PER_LINE) * TILEY;
835   }
836   else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
837   {
838     graphic -= GFX_START_ROCKSSP;
839     *bitmap = pix[PIX_SP];
840     *x = (graphic % SP_PER_LINE) * TILEX;
841     *y = (graphic / SP_PER_LINE) * TILEY;
842   }
843   else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
844   {
845     graphic -= GFX_START_ROCKSDC;
846     *bitmap = pix[PIX_DC];
847     *x = (graphic % DC_PER_LINE) * TILEX;
848     *y = (graphic / DC_PER_LINE) * TILEY;
849   }
850   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
851   {
852     graphic -= GFX_START_ROCKSMORE;
853     *bitmap = pix[PIX_MORE];
854     *x = (graphic % MORE_PER_LINE) * TILEX;
855     *y = (graphic / MORE_PER_LINE) * TILEY;
856   }
857   else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
858   {
859     graphic -= GFX_START_ROCKSFONT;
860     *bitmap = pix[PIX_FONT_EM];
861     *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
862     *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
863   }
864   else
865   {
866     *bitmap = pix[PIX_SP];
867     *x = 0;
868     *y = 0;
869   }
870 }
871
872 void DrawGraphic(int x, int y, int graphic)
873 {
874 #if DEBUG
875   if (!IN_SCR_FIELD(x, y))
876   {
877     printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
878     printf("DrawGraphic(): This should never happen!\n");
879     return;
880   }
881 #endif
882
883   DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic);
884   MarkTileDirty(x, y);
885 }
886
887 void DrawNewGraphic(int x, int y, int graphic, int frame)
888 {
889 #if DEBUG
890   if (!IN_SCR_FIELD(x, y))
891   {
892     printf("DrawNewGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
893     printf("DrawNewGraphic(): This should never happen!\n");
894     return;
895   }
896 #endif
897
898   DrawNewGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
899                     graphic, frame);
900   MarkTileDirty(x, y);
901 }
902
903 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
904 {
905   Bitmap *src_bitmap;
906   int src_x, src_y;
907
908   getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
909   BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
910 }
911
912 void DrawNewGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
913                        int frame)
914 {
915   Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
916   int src_x = new_graphic_info[graphic].src_x;
917   int src_y = new_graphic_info[graphic].src_y;
918   int offset_x = new_graphic_info[graphic].offset_x;
919   int offset_y = new_graphic_info[graphic].offset_y;
920
921   src_x += frame * offset_x;
922   src_y += frame * offset_y;
923
924   BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
925 }
926
927 void DrawGraphicThruMask(int x, int y, int graphic)
928 {
929 #if DEBUG
930   if (!IN_SCR_FIELD(x, y))
931   {
932     printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
933     printf("DrawGraphicThruMask(): This should never happen!\n");
934     return;
935   }
936 #endif
937
938   DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic);
939   MarkTileDirty(x, y);
940 }
941
942 void DrawNewGraphicThruMask(int x, int y, int graphic, int frame)
943 {
944 #if DEBUG
945   if (!IN_SCR_FIELD(x, y))
946   {
947     printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
948     printf("DrawGraphicThruMask(): This should never happen!\n");
949     return;
950   }
951 #endif
952
953   DrawNewGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY,
954                             graphic, frame);
955   MarkTileDirty(x, y);
956 }
957
958 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic)
959 {
960   int tile = graphic;
961   int src_x, src_y;
962   Bitmap *src_bitmap;
963   GC drawing_gc;
964
965   if (graphic == GFX_LEERRAUM)
966     return;
967
968   getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
969   drawing_gc = src_bitmap->stored_clip_gc;
970
971   if (tile_clipmask[tile] != None)
972   {
973     SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
974     SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
975     BlitBitmapMasked(src_bitmap, d,
976                      src_x, src_y, TILEX, TILEY, dest_x, dest_y);
977   }
978   else
979   {
980 #if DEBUG
981 #ifndef TARGET_SDL
982     printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
983 #endif
984 #endif
985
986     SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
987     BlitBitmapMasked(src_bitmap, d,
988                      src_x, src_y, TILEX, TILEY, dest_x, dest_y);
989   }
990 }
991
992 void DrawNewGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y,
993                                int graphic, int frame)
994 {
995   Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
996   GC drawing_gc = src_bitmap->stored_clip_gc;
997   int src_x = new_graphic_info[graphic].src_x;
998   int src_y = new_graphic_info[graphic].src_y;
999   int offset_x = new_graphic_info[graphic].offset_x;
1000   int offset_y = new_graphic_info[graphic].offset_y;
1001
1002   src_x += frame * offset_x;
1003   src_y += frame * offset_y;
1004
1005   SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1006   BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1007 }
1008
1009 void DrawMiniGraphic(int x, int y, int graphic)
1010 {
1011   DrawMiniGraphicExt(drawto, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
1012   MarkTileDirty(x/2, y/2);
1013 }
1014
1015 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1016 {
1017   if (graphic >= GFX_START_ROCKSELEMENTS && graphic <= GFX_END_ROCKSELEMENTS)
1018   {
1019     graphic -= GFX_START_ROCKSELEMENTS;
1020     *bitmap = pix[PIX_ELEMENTS];
1021     *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
1022     *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
1023   }
1024   else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
1025   {
1026     graphic -= GFX_START_ROCKSSP;
1027     *bitmap = pix[PIX_SP];
1028     *x = MINI_SP_STARTX + (graphic % MINI_SP_PER_LINE) * MINI_TILEX;
1029     *y = MINI_SP_STARTY + (graphic / MINI_SP_PER_LINE) * MINI_TILEY;
1030   }
1031   else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
1032   {
1033     graphic -= GFX_START_ROCKSDC;
1034     *bitmap = pix[PIX_DC];
1035     *x = MINI_DC_STARTX + (graphic % MINI_DC_PER_LINE) * MINI_TILEX;
1036     *y = MINI_DC_STARTY + (graphic / MINI_DC_PER_LINE) * MINI_TILEY;
1037   }
1038   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1039   {
1040     graphic -= GFX_START_ROCKSMORE;
1041     *bitmap = pix[PIX_MORE];
1042     *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
1043     *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
1044   }
1045   else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
1046   {
1047     graphic -= GFX_START_ROCKSFONT;
1048     *bitmap = pix[PIX_FONT_EM];
1049     *x = MINI_FONT_STARTX + (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
1050     *y = MINI_FONT_STARTY + (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE;
1051   }
1052   else
1053   {
1054     *bitmap = pix[PIX_SP];
1055     *x = MINI_SP_STARTX;
1056     *y = MINI_SP_STARTY;
1057   }
1058 }
1059
1060 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1061 {
1062   Bitmap *bitmap;
1063   int src_x, src_y;
1064
1065   getMiniGraphicSource(graphic, &bitmap, &src_x, &src_y);
1066   BlitBitmap(bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1067 }
1068
1069 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
1070                         int cut_mode, int mask_mode)
1071 {
1072   int width = TILEX, height = TILEY;
1073   int cx = 0, cy = 0;
1074   int src_x, src_y, dest_x, dest_y;
1075   int tile = graphic;
1076   Bitmap *src_bitmap;
1077   GC drawing_gc;
1078
1079   if (graphic < 0)
1080   {
1081     DrawGraphic(x, y, graphic);
1082     return;
1083   }
1084
1085   if (dx || dy)                 /* Verschiebung der Grafik? */
1086   {
1087     if (x < BX1)                /* Element kommt von links ins Bild */
1088     {
1089       x = BX1;
1090       width = dx;
1091       cx = TILEX - dx;
1092       dx = 0;
1093     }
1094     else if (x > BX2)           /* Element kommt von rechts ins Bild */
1095     {
1096       x = BX2;
1097       width = -dx;
1098       dx = TILEX + dx;
1099     }
1100     else if (x==BX1 && dx < 0)  /* Element verläßt links das Bild */
1101     {
1102       width += dx;
1103       cx = -dx;
1104       dx = 0;
1105     }
1106     else if (x==BX2 && dx > 0)  /* Element verläßt rechts das Bild */
1107       width -= dx;
1108     else if (dx)                /* allg. Bewegung in x-Richtung */
1109       MarkTileDirty(x + SIGN(dx), y);
1110
1111     if (y < BY1)                /* Element kommt von oben ins Bild */
1112     {
1113       if (cut_mode==CUT_BELOW)  /* Element oberhalb des Bildes */
1114         return;
1115
1116       y = BY1;
1117       height = dy;
1118       cy = TILEY - dy;
1119       dy = 0;
1120     }
1121     else if (y > BY2)           /* Element kommt von unten ins Bild */
1122     {
1123       y = BY2;
1124       height = -dy;
1125       dy = TILEY + dy;
1126     }
1127     else if (y==BY1 && dy < 0)  /* Element verläßt oben das Bild */
1128     {
1129       height += dy;
1130       cy = -dy;
1131       dy = 0;
1132     }
1133     else if (dy > 0 && cut_mode == CUT_ABOVE)
1134     {
1135       if (y == BY2)             /* Element unterhalb des Bildes */
1136         return;
1137
1138       height = dy;
1139       cy = TILEY - dy;
1140       dy = TILEY;
1141       MarkTileDirty(x, y + 1);
1142     }                           /* Element verläßt unten das Bild */
1143     else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1144       height -= dy;
1145     else if (dy)                /* allg. Bewegung in y-Richtung */
1146       MarkTileDirty(x, y + SIGN(dy));
1147   }
1148
1149   getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1150   drawing_gc = src_bitmap->stored_clip_gc;
1151
1152   src_x += cx;
1153   src_y += cy;
1154
1155   dest_x = FX + x * TILEX + dx;
1156   dest_y = FY + y * TILEY + dy;
1157
1158 #if DEBUG
1159   if (!IN_SCR_FIELD(x,y))
1160   {
1161     printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1162     printf("DrawGraphicShifted(): This should never happen!\n");
1163     return;
1164   }
1165 #endif
1166
1167   if (mask_mode == USE_MASKING)
1168   {
1169     if (tile_clipmask[tile] != None)
1170     {
1171       SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
1172       SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
1173       BlitBitmapMasked(src_bitmap, drawto_field,
1174                        src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1175     }
1176     else
1177     {
1178 #if DEBUG
1179 #ifndef TARGET_SDL
1180       printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1181 #endif
1182 #endif
1183
1184       SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1185       BlitBitmapMasked(src_bitmap, drawto_field,
1186                        src_x, src_y, width, height, dest_x, dest_y);
1187     }
1188   }
1189   else
1190     BlitBitmap(src_bitmap, drawto_field,
1191                src_x, src_y, width, height, dest_x, dest_y);
1192
1193   MarkTileDirty(x,y);
1194 }
1195
1196 void DrawNewGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
1197                         int cut_mode, int mask_mode)
1198 {
1199   Bitmap *src_bitmap;
1200   GC drawing_gc;
1201   int src_x;
1202   int src_y;
1203   int offset_x;
1204   int offset_y;
1205
1206   int width = TILEX, height = TILEY;
1207   int cx = 0, cy = 0;
1208   int dest_x, dest_y;
1209
1210   if (graphic < 0)
1211   {
1212     DrawNewGraphic(x, y, graphic, frame);
1213     return;
1214   }
1215
1216   if (dx || dy)                 /* Verschiebung der Grafik? */
1217   {
1218     if (x < BX1)                /* Element kommt von links ins Bild */
1219     {
1220       x = BX1;
1221       width = dx;
1222       cx = TILEX - dx;
1223       dx = 0;
1224     }
1225     else if (x > BX2)           /* Element kommt von rechts ins Bild */
1226     {
1227       x = BX2;
1228       width = -dx;
1229       dx = TILEX + dx;
1230     }
1231     else if (x==BX1 && dx < 0)  /* Element verläßt links das Bild */
1232     {
1233       width += dx;
1234       cx = -dx;
1235       dx = 0;
1236     }
1237     else if (x==BX2 && dx > 0)  /* Element verläßt rechts das Bild */
1238       width -= dx;
1239     else if (dx)                /* allg. Bewegung in x-Richtung */
1240       MarkTileDirty(x + SIGN(dx), y);
1241
1242     if (y < BY1)                /* Element kommt von oben ins Bild */
1243     {
1244       if (cut_mode==CUT_BELOW)  /* Element oberhalb des Bildes */
1245         return;
1246
1247       y = BY1;
1248       height = dy;
1249       cy = TILEY - dy;
1250       dy = 0;
1251     }
1252     else if (y > BY2)           /* Element kommt von unten ins Bild */
1253     {
1254       y = BY2;
1255       height = -dy;
1256       dy = TILEY + dy;
1257     }
1258     else if (y==BY1 && dy < 0)  /* Element verläßt oben das Bild */
1259     {
1260       height += dy;
1261       cy = -dy;
1262       dy = 0;
1263     }
1264     else if (dy > 0 && cut_mode == CUT_ABOVE)
1265     {
1266       if (y == BY2)             /* Element unterhalb des Bildes */
1267         return;
1268
1269       height = dy;
1270       cy = TILEY - dy;
1271       dy = TILEY;
1272       MarkTileDirty(x, y + 1);
1273     }                           /* Element verläßt unten das Bild */
1274     else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1275       height -= dy;
1276     else if (dy)                /* allg. Bewegung in y-Richtung */
1277       MarkTileDirty(x, y + SIGN(dy));
1278   }
1279
1280   src_bitmap = new_graphic_info[graphic].bitmap;
1281   drawing_gc = src_bitmap->stored_clip_gc;
1282   src_x = new_graphic_info[graphic].src_x;
1283   src_y = new_graphic_info[graphic].src_y;
1284   offset_x = new_graphic_info[graphic].offset_x;
1285   offset_y = new_graphic_info[graphic].offset_y;
1286
1287   src_x += frame * offset_x;
1288   src_y += frame * offset_y;
1289
1290   src_x += cx;
1291   src_y += cy;
1292
1293   dest_x = FX + x * TILEX + dx;
1294   dest_y = FY + y * TILEY + dy;
1295
1296 #if DEBUG
1297   if (!IN_SCR_FIELD(x,y))
1298   {
1299     printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1300     printf("DrawGraphicShifted(): This should never happen!\n");
1301     return;
1302   }
1303 #endif
1304
1305   if (mask_mode == USE_MASKING)
1306     SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1307
1308   BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1309              dest_x, dest_y);
1310
1311   MarkTileDirty(x,y);
1312 }
1313
1314 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1315                                 int cut_mode)
1316 {
1317   DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1318 }
1319
1320 void DrawNewGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1321                                    int frame, int cut_mode)
1322 {
1323   DrawNewGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1324 }
1325
1326 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1327                           int cut_mode, int mask_mode)
1328 {
1329   int ux = LEVELX(x), uy = LEVELY(y);
1330   int graphic = el2gfx(element);
1331   int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1332   int phase4 = phase8 / 2;
1333   int phase2  = phase8 / 4;
1334   int dir = MovDir[ux][uy];
1335
1336   if (element == EL_PACMAN || element == EL_BUG || element == EL_SPACESHIP)
1337   {
1338     graphic += 1 * !phase2;
1339
1340     if (dir == MV_UP)
1341       graphic += 1 * 2;
1342     else if (dir == MV_LEFT)
1343       graphic += 2 * 2;
1344     else if (dir == MV_DOWN)
1345       graphic += 3 * 2;
1346   }
1347   else if (element == EL_SP_SNIKSNAK)
1348   {
1349     if (dir == MV_LEFT)
1350       graphic = GFX_SP_SNIKSNAK_LEFT;
1351     else if (dir == MV_RIGHT)
1352       graphic = GFX_SP_SNIKSNAK_RIGHT;
1353     else if (dir == MV_UP)
1354       graphic = GFX_SP_SNIKSNAK_UP;
1355     else
1356       graphic = GFX_SP_SNIKSNAK_DOWN;
1357
1358     graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1359   }
1360   else if (element == EL_SP_ELECTRON)
1361   {
1362     graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1363   }
1364   else if (element == EL_MOLE || element == EL_PENGUIN ||
1365            element == EL_PIG || element == EL_DRAGON)
1366   {
1367     if (dir == MV_LEFT)
1368       graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1369                  element == EL_PENGUIN ? GFX_PINGUIN_LEFT :
1370                  element == EL_PIG ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1371     else if (dir == MV_RIGHT)
1372       graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1373                  element == EL_PENGUIN ? GFX_PINGUIN_RIGHT :
1374                  element == EL_PIG ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1375     else if (dir == MV_UP)
1376       graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1377                  element == EL_PENGUIN ? GFX_PINGUIN_UP :
1378                  element == EL_PIG ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1379     else
1380       graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1381                  element == EL_PENGUIN ? GFX_PINGUIN_DOWN :
1382                  element == EL_PIG ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1383
1384     graphic += phase4;
1385   }
1386   else if (element == EL_SATELLITE)
1387   {
1388     graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1389   }
1390   else if (element == EL_ACID)
1391   {
1392     graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_LOOP);
1393   }
1394   else if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY)
1395   {
1396     graphic += !phase2;
1397   }
1398   else if (element == EL_BALLOON)
1399   {
1400     graphic += phase4;
1401   }
1402   else if ((element == EL_ROCK ||
1403             element == EL_SP_ZONK ||
1404             element == EL_BD_ROCK ||
1405             element == EL_SP_INFOTRON ||
1406             IS_GEM(element))
1407            && !cut_mode)
1408   {
1409     if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1410     {
1411       if (element == EL_ROCK ||
1412           element == EL_SP_ZONK ||
1413           element == EL_BD_ROCK)
1414       {
1415         if (dir == MV_LEFT)
1416           graphic += (4 - phase4) % 4;
1417         else if (dir == MV_RIGHT)
1418           graphic += phase4;
1419         else
1420           graphic += phase2 * 2;
1421       }
1422       else if (element != EL_SP_INFOTRON)
1423         graphic += phase2;
1424     }
1425   }
1426   else if (element == EL_MAGIC_WALL_ACTIVE ||
1427            element == EL_MAGIC_WALL_EMPTYING ||
1428            element == EL_BD_MAGIC_WALL_ACTIVE ||
1429            element == EL_BD_MAGIC_WALL_EMPTYING ||
1430            element == EL_MAGIC_WALL_FULL ||
1431            element == EL_BD_MAGIC_WALL_FULL)
1432   {
1433     graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1434   }
1435   else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1436   {
1437     graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1438     graphic += (x + 2 * y + 4) % 4;
1439   }
1440   else if (element == EL_WALL_GROWING)
1441   {
1442     boolean links_massiv = FALSE, rechts_massiv = FALSE;
1443
1444     if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1445       links_massiv = TRUE;
1446     if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1447       rechts_massiv = TRUE;
1448
1449     if (links_massiv && rechts_massiv)
1450       graphic = GFX_MAUERWERK;
1451     else if (links_massiv)
1452       graphic = GFX_MAUER_R;
1453     else if (rechts_massiv)
1454       graphic = GFX_MAUER_L;
1455   }
1456 #if 0
1457   else if ((element == EL_INVISIBLE_STEELWALL ||
1458             element == EL_INVISIBLE_WALL ||
1459             element == EL_INVISIBLE_SAND) && game.light_time_left)
1460   {
1461     graphic = (element == EL_INVISIBLE_STEELWALL ? GFX_INVISIBLE_STEEL_ON :
1462                element == EL_INVISIBLE_WALL ? GFX_UNSICHTBAR_ON :
1463                GFX_SAND_INVISIBLE_ON);
1464   }
1465 #endif
1466
1467   if (dx || dy)
1468     DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1469   else if (mask_mode == USE_MASKING)
1470     DrawGraphicThruMask(x, y, graphic);
1471   else
1472     DrawGraphic(x, y, graphic);
1473 }
1474
1475 inline static int getFramePosition(int x, int y)
1476 {
1477   int element = Feld[x][y];
1478   int frame_pos = -1;
1479
1480   if (element == EL_QUICKSAND_FULL ||
1481       element == EL_MAGIC_WALL_FULL ||
1482       element == EL_BD_MAGIC_WALL_FULL)
1483     frame_pos = -1;
1484   else if (IS_MOVING(x, y) || CAN_MOVE(element) || CAN_FALL(element))
1485     frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1486
1487   return frame_pos;
1488 }
1489
1490 inline static int getGfxAction(int x, int y)
1491 {
1492   int gfx_action = GFX_ACTION_DEFAULT;
1493
1494   if (GfxAction[x][y] != GFX_ACTION_DEFAULT)
1495     gfx_action = GfxAction[x][y];
1496   else if (IS_MOVING(x, y))
1497     gfx_action = GFX_ACTION_MOVING;
1498
1499   return gfx_action;
1500 }
1501
1502 void DrawNewScreenElementExt(int x, int y, int dx, int dy, int element,
1503                           int cut_mode, int mask_mode)
1504 {
1505   int ux = LEVELX(x), uy = LEVELY(y);
1506   int move_dir = MovDir[ux][uy];
1507   int move_pos = getFramePosition(ux, uy);
1508   int gfx_action = getGfxAction(ux, uy);
1509   int graphic = el_dir_act2img(element, move_dir, gfx_action);
1510   int frame = getNewGraphicAnimationFrame(graphic, move_pos);
1511
1512   if (element == EL_WALL_GROWING)
1513   {
1514     boolean left_stopped = FALSE, right_stopped = FALSE;
1515
1516     if (!IN_LEV_FIELD(ux - 1, uy) || IS_MAUER(Feld[ux - 1][uy]))
1517       left_stopped = TRUE;
1518     if (!IN_LEV_FIELD(ux + 1, uy) || IS_MAUER(Feld[ux + 1][uy]))
1519       right_stopped = TRUE;
1520
1521     if (left_stopped && right_stopped)
1522       graphic = IMG_WALL;
1523     else if (left_stopped)
1524       graphic = IMG_WALL_GROWING_ACTIVE_RIGHT;
1525     else if (right_stopped)
1526       graphic = IMG_WALL_GROWING_ACTIVE_LEFT;
1527   }
1528 #if 0
1529   else if ((element == EL_ROCK ||
1530             element == EL_SP_ZONK ||
1531             element == EL_BD_ROCK ||
1532             element == EL_SP_INFOTRON ||
1533             IS_GEM(element))
1534            && !cut_mode)
1535   {
1536     if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1537     {
1538       if (element == EL_ROCK ||
1539           element == EL_SP_ZONK ||
1540           element == EL_BD_ROCK)
1541       {
1542         if (move_dir == MV_LEFT)
1543           graphic += (4 - phase4) % 4;
1544         else if (move_dir == MV_RIGHT)
1545           graphic += phase4;
1546         else
1547           graphic += phase2 * 2;
1548       }
1549       else if (element != EL_SP_INFOTRON)
1550         graphic += phase2;
1551     }
1552   }
1553 #endif
1554   else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1555   {
1556     graphic = (element == EL_BD_AMOEBA ? IMG_BD_AMOEBA_PART1 :
1557                element == EL_AMOEBA_WET ? IMG_AMOEBA_WET_PART1 :
1558                element == EL_AMOEBA_DRY ? IMG_AMOEBA_DRY_PART1 :
1559                element == EL_AMOEBA_FULL ? IMG_AMOEBA_FULL_PART1 :
1560                IMG_AMOEBA_DEAD_PART1);
1561
1562     graphic += (x + 2 * y + 4) % 4;
1563   }
1564
1565   if (dx || dy)
1566     DrawNewGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1567   else if (mask_mode == USE_MASKING)
1568     DrawNewGraphicThruMask(x, y, graphic, frame);
1569   else
1570     DrawNewGraphic(x, y, graphic, frame);
1571 }
1572
1573 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1574                          int cut_mode, int mask_mode)
1575 {
1576   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1577     DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1578                          cut_mode, mask_mode);
1579 }
1580
1581 void DrawNewLevelElementExt(int x, int y, int dx, int dy, int element,
1582                          int cut_mode, int mask_mode)
1583 {
1584   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1585     DrawNewScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1586                          cut_mode, mask_mode);
1587 }
1588
1589 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1590                               int cut_mode)
1591 {
1592   DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1593 }
1594
1595 void DrawNewScreenElementShifted(int x, int y, int dx, int dy, int element,
1596                               int cut_mode)
1597 {
1598   DrawNewScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1599 }
1600
1601 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1602                              int cut_mode)
1603 {
1604   DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1605 }
1606
1607 void DrawNewLevelElementShifted(int x, int y, int dx, int dy, int element,
1608                              int cut_mode)
1609 {
1610   DrawNewLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1611 }
1612
1613 void DrawScreenElementThruMask(int x, int y, int element)
1614 {
1615   DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1616 }
1617
1618 void DrawNewScreenElementThruMask(int x, int y, int element)
1619 {
1620   DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1621 }
1622
1623 void DrawLevelElementThruMask(int x, int y, int element)
1624 {
1625   DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1626 }
1627
1628 void DrawNewLevelElementThruMask(int x, int y, int element)
1629 {
1630   DrawNewLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1631 }
1632
1633 void DrawLevelFieldThruMask(int x, int y)
1634 {
1635   DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1636 }
1637
1638 void DrawNewLevelFieldThruMask(int x, int y)
1639 {
1640   DrawNewLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1641 }
1642
1643 void ErdreichAnbroeckeln(int x, int y)
1644 {
1645   Bitmap *src_bitmap;
1646   int src_x, src_y;
1647   int i, width, height, cx,cy;
1648   int ux = LEVELX(x), uy = LEVELY(y);
1649   int element, graphic;
1650   int snip = 4;
1651   static int xy[4][2] =
1652   {
1653     { 0, -1 },
1654     { -1, 0 },
1655     { +1, 0 },
1656     { 0, +1 }
1657   };
1658
1659   if (!IN_LEV_FIELD(ux, uy))
1660     return;
1661
1662   element = Feld[ux][uy];
1663
1664   if (element == EL_SAND ||
1665       element == EL_LANDMINE ||
1666       element == EL_TRAP ||
1667       element == EL_TRAP_ACTIVE)
1668   {
1669     if (!IN_SCR_FIELD(x, y))
1670       return;
1671
1672     graphic = GFX_ERDENRAND;
1673
1674     getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1675
1676     for(i=0; i<4; i++)
1677     {
1678       int uxx, uyy;
1679
1680       uxx = ux + xy[i][0];
1681       uyy = uy + xy[i][1];
1682       if (!IN_LEV_FIELD(uxx, uyy))
1683         element = EL_STEELWALL;
1684       else
1685         element = Feld[uxx][uyy];
1686
1687       if (element == EL_SAND ||
1688           element == EL_LANDMINE ||
1689           element == EL_TRAP ||
1690           element == EL_TRAP_ACTIVE)
1691         continue;
1692
1693       if (i == 1 || i == 2)
1694       {
1695         width = snip;
1696         height = TILEY;
1697         cx = (i == 2 ? TILEX - snip : 0);
1698         cy = 0;
1699       }
1700       else
1701       {
1702         width = TILEX;
1703         height = snip;
1704         cx = 0;
1705         cy = (i == 3 ? TILEY - snip : 0);
1706       }
1707
1708       BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1709                  width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1710     }
1711
1712     MarkTileDirty(x, y);
1713   }
1714   else
1715   {
1716     graphic = GFX_ERDENRAND;
1717
1718     getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1719
1720     for(i=0; i<4; i++)
1721     {
1722       int xx, yy, uxx, uyy;
1723
1724       xx = x + xy[i][0];
1725       yy = y + xy[i][1];
1726       uxx = ux + xy[i][0];
1727       uyy = uy + xy[i][1];
1728
1729       if (!IN_LEV_FIELD(uxx, uyy) ||
1730           (Feld[uxx][uyy] != EL_SAND &&
1731            Feld[uxx][uyy] != EL_LANDMINE &&
1732            Feld[uxx][uyy] != EL_TRAP &&
1733            Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1734           !IN_SCR_FIELD(xx, yy))
1735         continue;
1736
1737       if (i == 1 || i == 2)
1738       {
1739         width = snip;
1740         height = TILEY;
1741         cx = (i == 1 ? TILEX - snip : 0);
1742         cy = 0;
1743       }
1744       else
1745       {
1746         width = TILEX;
1747         height = snip;
1748         cx = 0;
1749         cy = (i==0 ? TILEY-snip : 0);
1750       }
1751
1752       BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1753                  width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1754
1755       MarkTileDirty(xx, yy);
1756     }
1757   }
1758 }
1759
1760 void DrawScreenElement(int x, int y, int element)
1761 {
1762   DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1763   ErdreichAnbroeckeln(x, y);
1764 }
1765
1766 void DrawNewScreenElement(int x, int y, int element)
1767 {
1768   DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1769   ErdreichAnbroeckeln(x, y);
1770 }
1771
1772 void DrawLevelElement(int x, int y, int element)
1773 {
1774   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1775     DrawScreenElement(SCREENX(x), SCREENY(y), element);
1776 }
1777
1778 void DrawNewLevelElement(int x, int y, int element)
1779 {
1780   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1781     DrawNewScreenElement(SCREENX(x), SCREENY(y), element);
1782 }
1783
1784 void DrawScreenField(int x, int y)
1785 {
1786   int ux = LEVELX(x), uy = LEVELY(y);
1787   int element, content;
1788
1789   if (!IN_LEV_FIELD(ux, uy))
1790   {
1791     if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1792       element = EL_EMPTY;
1793     else
1794       element = BorderElement;
1795
1796     DrawScreenElement(x, y, element);
1797     return;
1798   }
1799
1800   element = Feld[ux][uy];
1801   content = Store[ux][uy];
1802
1803   if (IS_MOVING(ux, uy))
1804   {
1805     int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1806     boolean cut_mode = NO_CUTTING;
1807
1808     if (element == EL_QUICKSAND_EMPTYING ||
1809         element == EL_MAGIC_WALL_EMPTYING ||
1810         element == EL_BD_MAGIC_WALL_EMPTYING ||
1811         element == EL_AMOEBA_DRIPPING)
1812       cut_mode = CUT_ABOVE;
1813     else if (element == EL_QUICKSAND_FILLING ||
1814              element == EL_MAGIC_WALL_FILLING ||
1815              element == EL_BD_MAGIC_WALL_FILLING)
1816       cut_mode = CUT_BELOW;
1817
1818     if (cut_mode == CUT_ABOVE)
1819       DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1820     else
1821       DrawScreenElement(x, y, EL_EMPTY);
1822
1823     if (horiz_move)
1824       DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1825     else if (cut_mode == NO_CUTTING)
1826       DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1827     else
1828       DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1829
1830     if (content == EL_ACID)
1831       DrawLevelElementThruMask(ux, uy + 1, EL_ACID);
1832   }
1833   else if (IS_BLOCKED(ux, uy))
1834   {
1835     int oldx, oldy;
1836     int sx, sy;
1837     int horiz_move;
1838     boolean cut_mode = NO_CUTTING;
1839     int element_old, content_old;
1840
1841     Blocked2Moving(ux, uy, &oldx, &oldy);
1842     sx = SCREENX(oldx);
1843     sy = SCREENY(oldy);
1844     horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1845                   MovDir[oldx][oldy] == MV_RIGHT);
1846
1847     element_old = Feld[oldx][oldy];
1848     content_old = Store[oldx][oldy];
1849
1850     if (element_old == EL_QUICKSAND_EMPTYING ||
1851         element_old == EL_MAGIC_WALL_EMPTYING ||
1852         element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1853         element_old == EL_AMOEBA_DRIPPING)
1854       cut_mode = CUT_ABOVE;
1855
1856     DrawScreenElement(x, y, EL_EMPTY);
1857
1858     if (horiz_move)
1859       DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1860                                NO_CUTTING);
1861     else if (cut_mode == NO_CUTTING)
1862       DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1863                                cut_mode);
1864     else
1865       DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1866                                cut_mode);
1867   }
1868   else if (IS_DRAWABLE(element))
1869     DrawScreenElement(x, y, element);
1870   else
1871     DrawScreenElement(x, y, EL_EMPTY);
1872 }
1873
1874 void DrawNewScreenField(int x, int y)
1875 {
1876   int ux = LEVELX(x), uy = LEVELY(y);
1877   int element, content;
1878
1879   if (!IN_LEV_FIELD(ux, uy))
1880   {
1881     if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1882       element = EL_EMPTY;
1883     else
1884       element = BorderElement;
1885
1886     DrawNewScreenElement(x, y, element);
1887     return;
1888   }
1889
1890   element = Feld[ux][uy];
1891   content = Store[ux][uy];
1892
1893   if (IS_MOVING(ux, uy))
1894   {
1895     int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1896     boolean cut_mode = NO_CUTTING;
1897
1898     if (element == EL_QUICKSAND_EMPTYING ||
1899         element == EL_MAGIC_WALL_EMPTYING ||
1900         element == EL_BD_MAGIC_WALL_EMPTYING ||
1901         element == EL_AMOEBA_DRIPPING)
1902       cut_mode = CUT_ABOVE;
1903     else if (element == EL_QUICKSAND_FILLING ||
1904              element == EL_MAGIC_WALL_FILLING ||
1905              element == EL_BD_MAGIC_WALL_FILLING)
1906       cut_mode = CUT_BELOW;
1907
1908     if (cut_mode == CUT_ABOVE)
1909       DrawNewScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1910     else
1911       DrawNewScreenElement(x, y, EL_EMPTY);
1912
1913     if (horiz_move)
1914       DrawNewScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1915     else if (cut_mode == NO_CUTTING)
1916       DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1917     else
1918       DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1919
1920     if (content == EL_ACID)
1921       DrawNewLevelElementThruMask(ux, uy + 1, EL_ACID);
1922   }
1923   else if (IS_BLOCKED(ux, uy))
1924   {
1925     int oldx, oldy;
1926     int sx, sy;
1927     int horiz_move;
1928     boolean cut_mode = NO_CUTTING;
1929     int element_old, content_old;
1930
1931     Blocked2Moving(ux, uy, &oldx, &oldy);
1932     sx = SCREENX(oldx);
1933     sy = SCREENY(oldy);
1934     horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1935                   MovDir[oldx][oldy] == MV_RIGHT);
1936
1937     element_old = Feld[oldx][oldy];
1938     content_old = Store[oldx][oldy];
1939
1940     if (element_old == EL_QUICKSAND_EMPTYING ||
1941         element_old == EL_MAGIC_WALL_EMPTYING ||
1942         element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1943         element_old == EL_AMOEBA_DRIPPING)
1944       cut_mode = CUT_ABOVE;
1945
1946     DrawNewScreenElement(x, y, EL_EMPTY);
1947
1948     if (horiz_move)
1949       DrawNewScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1950                                NO_CUTTING);
1951     else if (cut_mode == NO_CUTTING)
1952       DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1953                                cut_mode);
1954     else
1955       DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1956                                cut_mode);
1957   }
1958   else if (IS_DRAWABLE(element))
1959     DrawNewScreenElement(x, y, element);
1960   else
1961     DrawNewScreenElement(x, y, EL_EMPTY);
1962 }
1963
1964 void DrawLevelField(int x, int y)
1965 {
1966   if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1967     DrawScreenField(SCREENX(x), SCREENY(y));
1968   else if (IS_MOVING(x, y))
1969   {
1970     int newx,newy;
1971
1972     Moving2Blocked(x, y, &newx, &newy);
1973     if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1974       DrawScreenField(SCREENX(newx), SCREENY(newy));
1975   }
1976   else if (IS_BLOCKED(x, y))
1977   {
1978     int oldx, oldy;
1979
1980     Blocked2Moving(x, y, &oldx, &oldy);
1981     if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1982       DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1983   }
1984 }
1985
1986 void DrawNewLevelField(int x, int y)
1987 {
1988   if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1989     DrawNewScreenField(SCREENX(x), SCREENY(y));
1990   else if (IS_MOVING(x, y))
1991   {
1992     int newx,newy;
1993
1994     Moving2Blocked(x, y, &newx, &newy);
1995     if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1996       DrawNewScreenField(SCREENX(newx), SCREENY(newy));
1997   }
1998   else if (IS_BLOCKED(x, y))
1999   {
2000     int oldx, oldy;
2001
2002     Blocked2Moving(x, y, &oldx, &oldy);
2003     if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
2004       DrawNewScreenField(SCREENX(oldx), SCREENY(oldy));
2005   }
2006 }
2007
2008 void DrawMiniElement(int x, int y, int element)
2009 {
2010   int graphic;
2011
2012   if (!element)
2013   {
2014     DrawMiniGraphic(x, y, -1);
2015     return;
2016   }
2017
2018   graphic = el2gfx(element);
2019   DrawMiniGraphic(x, y, graphic);
2020 }
2021
2022 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
2023 {
2024   int x = sx + scroll_x, y = sy + scroll_y;
2025
2026   if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
2027     DrawMiniElement(sx, sy, EL_EMPTY);
2028   else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
2029     DrawMiniElement(sx, sy, Feld[x][y]);
2030   else
2031   {
2032     int steel_type, steel_position;
2033     int border[6][2] =
2034     {
2035       { GFX_VSTEEL_UPPER_LEFT,  GFX_ISTEEL_UPPER_LEFT  },
2036       { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
2037       { GFX_VSTEEL_LOWER_LEFT,  GFX_ISTEEL_LOWER_LEFT  },
2038       { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
2039       { GFX_VSTEEL_VERTICAL,    GFX_ISTEEL_VERTICAL    },
2040       { GFX_VSTEEL_HORIZONTAL,  GFX_ISTEEL_HORIZONTAL  }
2041     };
2042
2043     steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
2044     steel_position = (x == -1 && y == -1                        ? 0 :
2045                       x == lev_fieldx && y == -1                ? 1 :
2046                       x == -1 && y == lev_fieldy                ? 2 :
2047                       x == lev_fieldx && y == lev_fieldy        ? 3 :
2048                       x == -1 || x == lev_fieldx                ? 4 :
2049                       y == -1 || y == lev_fieldy                ? 5 : -1);
2050
2051     if (steel_position != -1)
2052       DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
2053   }
2054 }
2055
2056 void DrawMicroElement(int xpos, int ypos, int element)
2057 {
2058   int graphic;
2059
2060   if (element == EL_EMPTY)
2061     return;
2062
2063   graphic = el2gfx(element);
2064
2065   if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
2066   {
2067     graphic -= GFX_START_ROCKSSP;
2068     BlitBitmap(pix[PIX_SP], drawto,
2069                MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
2070                MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
2071                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2072   }
2073   else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
2074   {
2075     graphic -= GFX_START_ROCKSDC;
2076     BlitBitmap(pix[PIX_DC], drawto,
2077                MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
2078                MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
2079                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2080   }
2081   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
2082   {
2083     graphic -= GFX_START_ROCKSMORE;
2084     BlitBitmap(pix[PIX_MORE], drawto,
2085                MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE)*MICRO_TILEX,
2086                MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE)*MICRO_TILEY,
2087                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2088   }
2089   else if (graphic >= GFX_CHAR_START && graphic <= GFX_CHAR_END)
2090   {
2091     graphic -= GFX_CHAR_START;
2092     BlitBitmap(pix[PIX_FONT_EM], drawto,
2093                MICRO_FONT_STARTX + (graphic % MICRO_GFX_PER_LINE)* MICRO_TILEX,
2094                MICRO_FONT_STARTY + (graphic / MICRO_GFX_PER_LINE)* MICRO_TILEY,
2095                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2096   }
2097   else
2098     BlitBitmap(pix[PIX_ELEMENTS], drawto,
2099                MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
2100                MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
2101                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2102 }
2103
2104 void DrawLevel()
2105 {
2106   int x,y;
2107
2108   ClearWindow();
2109
2110   for(x=BX1; x<=BX2; x++)
2111     for(y=BY1; y<=BY2; y++)
2112       DrawScreenField(x, y);
2113
2114   redraw_mask |= REDRAW_FIELD;
2115 }
2116
2117 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
2118 {
2119   int x,y;
2120
2121   for(x=0; x<size_x; x++)
2122     for(y=0; y<size_y; y++)
2123       DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
2124
2125   redraw_mask |= REDRAW_FIELD;
2126 }
2127
2128 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
2129 {
2130   int x, y;
2131
2132   ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
2133
2134   if (lev_fieldx < STD_LEV_FIELDX)
2135     xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
2136   if (lev_fieldy < STD_LEV_FIELDY)
2137     ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
2138
2139   xpos += MICRO_TILEX;
2140   ypos += MICRO_TILEY;
2141
2142   for(x=-1; x<=STD_LEV_FIELDX; x++)
2143   {
2144     for(y=-1; y<=STD_LEV_FIELDY; y++)
2145     {
2146       int lx = from_x + x, ly = from_y + y;
2147
2148       if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
2149         DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2150                          Ur[lx][ly]);
2151       else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
2152         DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2153                          BorderElement);
2154     }
2155   }
2156
2157   redraw_mask |= REDRAW_MICROLEVEL;
2158 }
2159
2160 #define MICROLABEL_EMPTY                0
2161 #define MICROLABEL_LEVEL_NAME           1
2162 #define MICROLABEL_CREATED_BY           2
2163 #define MICROLABEL_LEVEL_AUTHOR         3
2164 #define MICROLABEL_IMPORTED_FROM        4
2165 #define MICROLABEL_LEVEL_IMPORT_INFO    5
2166
2167 #define MAX_MICROLABEL_SIZE             (SXSIZE / FONT4_XSIZE)
2168
2169 static void DrawMicroLevelLabelExt(int mode)
2170 {
2171   char label_text[MAX_MICROLABEL_SIZE + 1];
2172
2173   ClearRectangle(drawto, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
2174
2175   strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
2176                        mode == MICROLABEL_CREATED_BY ? "created by" :
2177                        mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
2178                        mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
2179                        mode == MICROLABEL_LEVEL_IMPORT_INFO ?
2180                        leveldir_current->imported_from : ""),
2181           MAX_MICROLABEL_SIZE);
2182   label_text[MAX_MICROLABEL_SIZE] = '\0';
2183
2184   if (strlen(label_text) > 0)
2185   {
2186     int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
2187     int lypos = MICROLABEL_YPOS;
2188
2189     DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
2190   }
2191
2192   redraw_mask |= REDRAW_MICROLEVEL;
2193 }
2194
2195 void DrawMicroLevel(int xpos, int ypos, boolean restart)
2196 {
2197   static unsigned long scroll_delay = 0;
2198   static unsigned long label_delay = 0;
2199   static int from_x, from_y, scroll_direction;
2200   static int label_state, label_counter;
2201
2202   if (restart)
2203   {
2204     from_x = from_y = 0;
2205     scroll_direction = MV_RIGHT;
2206     label_state = 1;
2207     label_counter = 0;
2208
2209     DrawMicroLevelExt(xpos, ypos, from_x, from_y);
2210     DrawMicroLevelLabelExt(label_state);
2211
2212     /* initialize delay counters */
2213     DelayReached(&scroll_delay, 0);
2214     DelayReached(&label_delay, 0);
2215
2216     return;
2217   }
2218
2219   /* scroll micro level, if needed */
2220   if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
2221       DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
2222   {
2223     switch (scroll_direction)
2224     {
2225       case MV_LEFT:
2226         if (from_x > 0)
2227           from_x--;
2228         else
2229           scroll_direction = MV_UP;
2230         break;
2231
2232       case MV_RIGHT:
2233         if (from_x < lev_fieldx - STD_LEV_FIELDX)
2234           from_x++;
2235         else
2236           scroll_direction = MV_DOWN;
2237         break;
2238
2239       case MV_UP:
2240         if (from_y > 0)
2241           from_y--;
2242         else
2243           scroll_direction = MV_RIGHT;
2244         break;
2245
2246       case MV_DOWN:
2247         if (from_y < lev_fieldy - STD_LEV_FIELDY)
2248           from_y++;
2249         else
2250           scroll_direction = MV_LEFT;
2251         break;
2252
2253       default:
2254         break;
2255     }
2256
2257     DrawMicroLevelExt(xpos, ypos, from_x, from_y);
2258   }
2259
2260   /* redraw micro level label, if needed */
2261   if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
2262       strcmp(level.author, ANONYMOUS_NAME) != 0 &&
2263       strcmp(level.author, leveldir_current->name) != 0 &&
2264       DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
2265   {
2266     int max_label_counter = 23;
2267
2268     if (leveldir_current->imported_from != NULL)
2269       max_label_counter += 14;
2270
2271     label_counter = (label_counter + 1) % max_label_counter;
2272     label_state = (label_counter >= 0 && label_counter <= 7 ?
2273                    MICROLABEL_LEVEL_NAME :
2274                    label_counter >= 9 && label_counter <= 12 ?
2275                    MICROLABEL_CREATED_BY :
2276                    label_counter >= 14 && label_counter <= 21 ?
2277                    MICROLABEL_LEVEL_AUTHOR :
2278                    label_counter >= 23 && label_counter <= 26 ?
2279                    MICROLABEL_IMPORTED_FROM :
2280                    label_counter >= 28 && label_counter <= 35 ?
2281                    MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
2282     DrawMicroLevelLabelExt(label_state);
2283   }
2284 }
2285
2286 int REQ_in_range(int x, int y)
2287 {
2288   if (y > DY+249 && y < DY+278)
2289   {
2290     if (x > DX+1 && x < DX+48)
2291       return 1;
2292     else if (x > DX+51 && x < DX+98) 
2293       return 2;
2294   }
2295   return 0;
2296 }
2297
2298 #define MAX_REQUEST_LINES               13
2299 #define MAX_REQUEST_LINE_LEN            7
2300
2301 boolean Request(char *text, unsigned int req_state)
2302 {
2303   int mx, my, ty, result = -1;
2304   unsigned int old_door_state;
2305
2306 #if defined(PLATFORM_UNIX)
2307   /* pause network game while waiting for request to answer */
2308   if (options.network &&
2309       game_status == PLAYING &&
2310       req_state & REQUEST_WAIT_FOR)
2311     SendToServer_PausePlaying();
2312 #endif
2313
2314   old_door_state = GetDoorState();
2315
2316   UnmapAllGadgets();
2317
2318   CloseDoor(DOOR_CLOSE_1);
2319
2320   /* save old door content */
2321   BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2322              DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2323              DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2324
2325   /* clear door drawing field */
2326   ClearRectangle(drawto, DX, DY, DXSIZE, DYSIZE);
2327
2328   /* write text for request */
2329   for(ty=0; ty < MAX_REQUEST_LINES; ty++)
2330   {
2331     char text_line[MAX_REQUEST_LINE_LEN + 1];
2332     int tx, tl, tc;
2333
2334     if (!*text)
2335       break;
2336
2337     for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
2338     {
2339       tc = *(text + tx);
2340       if (!tc || tc == ' ')
2341         break;
2342     }
2343
2344     if (!tl)
2345     { 
2346       text++; 
2347       ty--; 
2348       continue; 
2349     }
2350
2351     strncpy(text_line, text, tl);
2352     text_line[tl] = 0;
2353
2354     DrawTextExt(drawto, DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
2355                 text_line, FS_SMALL, FC_YELLOW);
2356
2357     text += tl + (tc == ' ' ? 1 : 0);
2358   }
2359
2360   if (req_state & REQ_ASK)
2361   {
2362     MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2363     MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2364   }
2365   else if (req_state & REQ_CONFIRM)
2366   {
2367     MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2368   }
2369   else if (req_state & REQ_PLAYER)
2370   {
2371     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2372     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2373     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2374     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2375   }
2376
2377   /* copy request gadgets to door backbuffer */
2378   BlitBitmap(drawto, pix[PIX_DB_DOOR],
2379              DX, DY, DXSIZE, DYSIZE,
2380              DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2381
2382   OpenDoor(DOOR_OPEN_1);
2383
2384 #if 0
2385   ClearEventQueue();
2386 #endif
2387
2388   if (!(req_state & REQUEST_WAIT_FOR))
2389     return(FALSE);
2390
2391   if (game_status != MAINMENU)
2392     InitAnimation();
2393
2394   button_status = MB_RELEASED;
2395
2396   request_gadget_id = -1;
2397
2398   while(result < 0)
2399   {
2400     if (PendingEvent())
2401     {
2402       Event event;
2403
2404       NextEvent(&event);
2405
2406       switch(event.type)
2407       {
2408         case EVENT_BUTTONPRESS:
2409         case EVENT_BUTTONRELEASE:
2410         case EVENT_MOTIONNOTIFY:
2411         {
2412           if (event.type == EVENT_MOTIONNOTIFY)
2413           {
2414             if (!PointerInWindow(window))
2415               continue; /* window and pointer are on different screens */
2416
2417             if (!button_status)
2418               continue;
2419
2420             motion_status = TRUE;
2421             mx = ((MotionEvent *) &event)->x;
2422             my = ((MotionEvent *) &event)->y;
2423           }
2424           else
2425           {
2426             motion_status = FALSE;
2427             mx = ((ButtonEvent *) &event)->x;
2428             my = ((ButtonEvent *) &event)->y;
2429             if (event.type == EVENT_BUTTONPRESS)
2430               button_status = ((ButtonEvent *) &event)->button;
2431             else
2432               button_status = MB_RELEASED;
2433           }
2434
2435           /* this sets 'request_gadget_id' */
2436           HandleGadgets(mx, my, button_status);
2437
2438           switch(request_gadget_id)
2439           {
2440             case TOOL_CTRL_ID_YES:
2441               result = TRUE;
2442               break;
2443             case TOOL_CTRL_ID_NO:
2444               result = FALSE;
2445               break;
2446             case TOOL_CTRL_ID_CONFIRM:
2447               result = TRUE | FALSE;
2448               break;
2449
2450             case TOOL_CTRL_ID_PLAYER_1:
2451               result = 1;
2452               break;
2453             case TOOL_CTRL_ID_PLAYER_2:
2454               result = 2;
2455               break;
2456             case TOOL_CTRL_ID_PLAYER_3:
2457               result = 3;
2458               break;
2459             case TOOL_CTRL_ID_PLAYER_4:
2460               result = 4;
2461               break;
2462
2463             default:
2464               break;
2465           }
2466
2467           break;
2468         }
2469
2470         case EVENT_KEYPRESS:
2471           switch(GetEventKey((KeyEvent *)&event, TRUE))
2472           {
2473             case KSYM_Return:
2474               result = 1;
2475               break;
2476
2477             case KSYM_Escape:
2478               result = 0;
2479               break;
2480
2481             default:
2482               break;
2483           }
2484           if (req_state & REQ_PLAYER)
2485             result = 0;
2486           break;
2487
2488         case EVENT_KEYRELEASE:
2489           ClearPlayerAction();
2490           break;
2491
2492         default:
2493           HandleOtherEvents(&event);
2494           break;
2495       }
2496     }
2497     else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2498     {
2499       int joy = AnyJoystick();
2500
2501       if (joy & JOY_BUTTON_1)
2502         result = 1;
2503       else if (joy & JOY_BUTTON_2)
2504         result = 0;
2505     }
2506
2507     DoAnimation();
2508
2509     /* don't eat all CPU time */
2510     Delay(10);
2511   }
2512
2513   if (game_status != MAINMENU)
2514     StopAnimation();
2515
2516   UnmapToolButtons();
2517
2518   if (!(req_state & REQ_STAY_OPEN))
2519   {
2520     CloseDoor(DOOR_CLOSE_1);
2521
2522     if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2523     {
2524       BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2525                  DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2526                  DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2527       OpenDoor(DOOR_OPEN_1);
2528     }
2529   }
2530
2531   RemapAllGadgets();
2532
2533 #if defined(PLATFORM_UNIX)
2534   /* continue network game after request */
2535   if (options.network &&
2536       game_status == PLAYING &&
2537       req_state & REQUEST_WAIT_FOR)
2538     SendToServer_ContinuePlaying();
2539 #endif
2540
2541   return(result);
2542 }
2543
2544 unsigned int OpenDoor(unsigned int door_state)
2545 {
2546   unsigned int new_door_state;
2547
2548   if (door_state & DOOR_COPY_BACK)
2549   {
2550     BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2551                DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2552                DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2553     door_state &= ~DOOR_COPY_BACK;
2554   }
2555
2556   new_door_state = MoveDoor(door_state);
2557
2558   return(new_door_state);
2559 }
2560
2561 unsigned int CloseDoor(unsigned int door_state)
2562 {
2563   unsigned int new_door_state;
2564
2565   BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2566              DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2567   BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2568              VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2569
2570   new_door_state = MoveDoor(door_state);
2571
2572   return(new_door_state);
2573 }
2574
2575 unsigned int GetDoorState()
2576 {
2577   return MoveDoor(DOOR_GET_STATE);
2578 }
2579
2580 unsigned int SetDoorState(unsigned int door_state)
2581 {
2582   return MoveDoor(door_state | DOOR_SET_STATE);
2583 }
2584
2585 unsigned int MoveDoor(unsigned int door_state)
2586 {
2587   static int door1 = DOOR_OPEN_1;
2588   static int door2 = DOOR_CLOSE_2;
2589   static unsigned long door_delay = 0;
2590   int x, start, stepsize = 2;
2591   unsigned long door_delay_value = stepsize * 5;
2592
2593   if (door_state == DOOR_GET_STATE)
2594     return(door1 | door2);
2595
2596   if (door_state & DOOR_SET_STATE)
2597   {
2598     if (door_state & DOOR_ACTION_1)
2599       door1 = door_state & DOOR_ACTION_1;
2600     if (door_state & DOOR_ACTION_2)
2601       door2 = door_state & DOOR_ACTION_2;
2602
2603     return(door1 | door2);
2604   }
2605
2606   if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2607     door_state &= ~DOOR_OPEN_1;
2608   else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2609     door_state &= ~DOOR_CLOSE_1;
2610   if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2611     door_state &= ~DOOR_OPEN_2;
2612   else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2613     door_state &= ~DOOR_CLOSE_2;
2614
2615   if (setup.quick_doors)
2616   {
2617     stepsize = 20;
2618     door_delay_value = 0;
2619     StopSound(SND_MENU_DOOR_OPENING);
2620     StopSound(SND_MENU_DOOR_CLOSING);
2621   }
2622
2623   if (door_state & DOOR_ACTION)
2624   {
2625     if (!(door_state & DOOR_NO_DELAY))
2626     {
2627       /* opening door sound has priority over simultaneously closing door */
2628       if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2629         PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2630       else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2631         PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2632     }
2633
2634     start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2635
2636     for(x=start; x<=DXSIZE; x+=stepsize)
2637     {
2638       Bitmap *bitmap = pix[PIX_DOOR];
2639       GC gc = bitmap->stored_clip_gc;
2640
2641       WaitUntilDelayReached(&door_delay, door_delay_value);
2642
2643       if (door_state & DOOR_ACTION_1)
2644       {
2645         int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2646         int j = (DXSIZE - i) / 3;
2647
2648         BlitBitmap(pix[PIX_DB_DOOR], drawto,
2649                    DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2650                    DXSIZE,DYSIZE - i/2, DX, DY);
2651
2652         ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2653
2654         SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2655         BlitBitmapMasked(bitmap, drawto,
2656                          DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2657                          DX + DXSIZE - i, DY + j);
2658         BlitBitmapMasked(bitmap, drawto,
2659                          DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2660                          DX + DXSIZE - i, DY + 140 + j);
2661         SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2662         BlitBitmapMasked(bitmap, drawto,
2663                          DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2664                          DX, DY);
2665         BlitBitmapMasked(bitmap, drawto,
2666                          DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2667                          DX, DY + 140 - j);
2668
2669         BlitBitmapMasked(bitmap, drawto,
2670                          DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2671                          DX, DY + 77 - j);
2672         BlitBitmapMasked(bitmap, drawto,
2673                          DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2674                          DX, DY + 203 - j);
2675         SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2676         BlitBitmapMasked(bitmap, drawto,
2677                          DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2678                          DX + DXSIZE - i, DY + 77 + j);
2679         BlitBitmapMasked(bitmap, drawto,
2680                          DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2681                          DX + DXSIZE - i, DY + 203 + j);
2682
2683         redraw_mask |= REDRAW_DOOR_1;
2684       }
2685
2686       if (door_state & DOOR_ACTION_2)
2687       {
2688         int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2689         int j = (VXSIZE - i) / 3;
2690
2691         BlitBitmap(pix[PIX_DB_DOOR], drawto,
2692                    DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2693                    VXSIZE, VYSIZE - i/2, VX, VY);
2694
2695         ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2696
2697         SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2698         BlitBitmapMasked(bitmap, drawto,
2699                          VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2700                          VX + VXSIZE-i, VY+j);
2701         SetClipOrigin(bitmap, gc,
2702                       VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2703         BlitBitmapMasked(bitmap, drawto,
2704                          VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2705                          VX, VY);
2706
2707         BlitBitmapMasked(bitmap, drawto,
2708                          VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2709                          i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2710         SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2711         BlitBitmapMasked(bitmap, drawto,
2712                          VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2713                          i, VYSIZE / 2 - j,
2714                          VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2715
2716         redraw_mask |= REDRAW_DOOR_2;
2717       }
2718
2719       BackToFront();
2720
2721       if (game_status == MAINMENU)
2722         DoAnimation();
2723     }
2724   }
2725
2726   if (setup.quick_doors)
2727   {
2728     StopSound(SND_MENU_DOOR_OPENING);
2729     StopSound(SND_MENU_DOOR_CLOSING);
2730   }
2731
2732   if (door_state & DOOR_ACTION_1)
2733     door1 = door_state & DOOR_ACTION_1;
2734   if (door_state & DOOR_ACTION_2)
2735     door2 = door_state & DOOR_ACTION_2;
2736
2737   return (door1 | door2);
2738 }
2739
2740 void DrawSpecialEditorDoor()
2741 {
2742   /* draw bigger toolbox window */
2743   BlitBitmap(pix[PIX_DOOR], drawto,
2744              DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2745
2746   redraw_mask |= REDRAW_ALL;
2747 }
2748
2749 void UndrawSpecialEditorDoor()
2750 {
2751   /* draw normal tape recorder window */
2752   BlitBitmap(pix[PIX_BACK], drawto,
2753              562, 344, 108, 56, EX - 4, EY - 12);
2754
2755   redraw_mask |= REDRAW_ALL;
2756 }
2757
2758 #ifndef TARGET_SDL
2759 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2760 {
2761   XImage *pixel_image;
2762   unsigned long pixel_value;
2763
2764   pixel_image = XGetImage(display, bitmap->drawable,
2765                           x, y, 1, 1, AllPlanes, ZPixmap);
2766   pixel_value = XGetPixel(pixel_image, 0, 0);
2767
2768   XDestroyImage(pixel_image);
2769
2770   return pixel_value;
2771 }
2772 #endif
2773
2774 /* ---------- new tool button stuff ---------------------------------------- */
2775
2776 /* graphic position values for tool buttons */
2777 #define TOOL_BUTTON_YES_XPOS            2
2778 #define TOOL_BUTTON_YES_YPOS            250
2779 #define TOOL_BUTTON_YES_GFX_YPOS        0
2780 #define TOOL_BUTTON_YES_XSIZE           46
2781 #define TOOL_BUTTON_YES_YSIZE           28
2782 #define TOOL_BUTTON_NO_XPOS             52
2783 #define TOOL_BUTTON_NO_YPOS             TOOL_BUTTON_YES_YPOS
2784 #define TOOL_BUTTON_NO_GFX_YPOS         TOOL_BUTTON_YES_GFX_YPOS
2785 #define TOOL_BUTTON_NO_XSIZE            TOOL_BUTTON_YES_XSIZE
2786 #define TOOL_BUTTON_NO_YSIZE            TOOL_BUTTON_YES_YSIZE
2787 #define TOOL_BUTTON_CONFIRM_XPOS        TOOL_BUTTON_YES_XPOS
2788 #define TOOL_BUTTON_CONFIRM_YPOS        TOOL_BUTTON_YES_YPOS
2789 #define TOOL_BUTTON_CONFIRM_GFX_YPOS    30
2790 #define TOOL_BUTTON_CONFIRM_XSIZE       96
2791 #define TOOL_BUTTON_CONFIRM_YSIZE       TOOL_BUTTON_YES_YSIZE
2792 #define TOOL_BUTTON_PLAYER_XSIZE        30
2793 #define TOOL_BUTTON_PLAYER_YSIZE        30
2794 #define TOOL_BUTTON_PLAYER_GFX_XPOS     5
2795 #define TOOL_BUTTON_PLAYER_GFX_YPOS     185
2796 #define TOOL_BUTTON_PLAYER_XPOS         (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2797 #define TOOL_BUTTON_PLAYER_YPOS         (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2798 #define TOOL_BUTTON_PLAYER1_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2799                                          + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2800 #define TOOL_BUTTON_PLAYER2_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2801                                          + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2802 #define TOOL_BUTTON_PLAYER3_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2803                                          + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2804 #define TOOL_BUTTON_PLAYER4_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2805                                          + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2806 #define TOOL_BUTTON_PLAYER1_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2807                                          + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2808 #define TOOL_BUTTON_PLAYER2_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2809                                          + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2810 #define TOOL_BUTTON_PLAYER3_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2811                                          + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2812 #define TOOL_BUTTON_PLAYER4_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2813                                          + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2814
2815 static struct
2816 {
2817   int xpos, ypos;
2818   int x, y;
2819   int width, height;
2820   int gadget_id;
2821   char *infotext;
2822 } toolbutton_info[NUM_TOOL_BUTTONS] =
2823 {
2824   {
2825     TOOL_BUTTON_YES_XPOS,       TOOL_BUTTON_YES_GFX_YPOS,
2826     TOOL_BUTTON_YES_XPOS,       TOOL_BUTTON_YES_YPOS,
2827     TOOL_BUTTON_YES_XSIZE,      TOOL_BUTTON_YES_YSIZE,
2828     TOOL_CTRL_ID_YES,
2829     "yes"
2830   },
2831   {
2832     TOOL_BUTTON_NO_XPOS,        TOOL_BUTTON_NO_GFX_YPOS,
2833     TOOL_BUTTON_NO_XPOS,        TOOL_BUTTON_NO_YPOS,
2834     TOOL_BUTTON_NO_XSIZE,       TOOL_BUTTON_NO_YSIZE,
2835     TOOL_CTRL_ID_NO,
2836     "no"
2837   },
2838   {
2839     TOOL_BUTTON_CONFIRM_XPOS,   TOOL_BUTTON_CONFIRM_GFX_YPOS,
2840     TOOL_BUTTON_CONFIRM_XPOS,   TOOL_BUTTON_CONFIRM_YPOS,
2841     TOOL_BUTTON_CONFIRM_XSIZE,  TOOL_BUTTON_CONFIRM_YSIZE,
2842     TOOL_CTRL_ID_CONFIRM,
2843     "confirm"
2844   },
2845   {
2846     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2847     TOOL_BUTTON_PLAYER1_XPOS,   TOOL_BUTTON_PLAYER1_YPOS,
2848     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2849     TOOL_CTRL_ID_PLAYER_1,
2850     "player 1"
2851   },
2852   {
2853     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2854     TOOL_BUTTON_PLAYER2_XPOS,   TOOL_BUTTON_PLAYER2_YPOS,
2855     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2856     TOOL_CTRL_ID_PLAYER_2,
2857     "player 2"
2858   },
2859   {
2860     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2861     TOOL_BUTTON_PLAYER3_XPOS,   TOOL_BUTTON_PLAYER3_YPOS,
2862     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2863     TOOL_CTRL_ID_PLAYER_3,
2864     "player 3"
2865   },
2866   {
2867     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2868     TOOL_BUTTON_PLAYER4_XPOS,   TOOL_BUTTON_PLAYER4_YPOS,
2869     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2870     TOOL_CTRL_ID_PLAYER_4,
2871     "player 4"
2872   }
2873 };
2874
2875 void CreateToolButtons()
2876 {
2877   int i;
2878
2879   for (i=0; i<NUM_TOOL_BUTTONS; i++)
2880   {
2881     Bitmap *gd_bitmap = pix[PIX_DOOR];
2882     Bitmap *deco_bitmap = None;
2883     int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2884     struct GadgetInfo *gi;
2885     unsigned long event_mask;
2886     int gd_xoffset, gd_yoffset;
2887     int gd_x1, gd_x2, gd_y;
2888     int id = i;
2889
2890     event_mask = GD_EVENT_RELEASED;
2891
2892     gd_xoffset = toolbutton_info[i].xpos;
2893     gd_yoffset = toolbutton_info[i].ypos;
2894     gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2895     gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2896     gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2897
2898     if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2899     {
2900       getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2901                            &deco_bitmap, &deco_x, &deco_y);
2902       deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2903       deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2904     }
2905
2906     gi = CreateGadget(GDI_CUSTOM_ID, id,
2907                       GDI_INFO_TEXT, toolbutton_info[i].infotext,
2908                       GDI_X, DX + toolbutton_info[i].x,
2909                       GDI_Y, DY + toolbutton_info[i].y,
2910                       GDI_WIDTH, toolbutton_info[i].width,
2911                       GDI_HEIGHT, toolbutton_info[i].height,
2912                       GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2913                       GDI_STATE, GD_BUTTON_UNPRESSED,
2914                       GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2915                       GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2916                       GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2917                       GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2918                       GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2919                       GDI_DECORATION_SHIFTING, 1, 1,
2920                       GDI_EVENT_MASK, event_mask,
2921                       GDI_CALLBACK_ACTION, HandleToolButtons,
2922                       GDI_END);
2923
2924     if (gi == NULL)
2925       Error(ERR_EXIT, "cannot create gadget");
2926
2927     tool_gadget[id] = gi;
2928   }
2929 }
2930
2931 static void UnmapToolButtons()
2932 {
2933   int i;
2934
2935   for (i=0; i<NUM_TOOL_BUTTONS; i++)
2936     UnmapGadget(tool_gadget[i]);
2937 }
2938
2939 static void HandleToolButtons(struct GadgetInfo *gi)
2940 {
2941   request_gadget_id = gi->custom_id;
2942 }
2943
2944 int get_next_element(int element)
2945 {
2946   switch(element)
2947   {
2948     case EL_QUICKSAND_FILLING:          return EL_QUICKSAND_FULL;
2949     case EL_QUICKSAND_EMPTYING:         return EL_QUICKSAND_EMPTY;
2950     case EL_MAGIC_WALL_FILLING:         return EL_MAGIC_WALL_FULL;
2951     case EL_MAGIC_WALL_EMPTYING:        return EL_MAGIC_WALL_ACTIVE;
2952     case EL_BD_MAGIC_WALL_FILLING:      return EL_BD_MAGIC_WALL_FULL;
2953     case EL_BD_MAGIC_WALL_EMPTYING:     return EL_BD_MAGIC_WALL_ACTIVE;
2954     case EL_AMOEBA_DRIPPING:            return EL_AMOEBA_WET;
2955
2956     default:                            return element;
2957   }
2958 }
2959
2960 int el2gfx_OLD(int element)
2961 {
2962   switch(element)
2963   {
2964     case EL_EMPTY:                      return -1;
2965     case EL_SAND:                       return GFX_ERDREICH;
2966     case EL_WALL:                       return GFX_MAUERWERK;
2967     case EL_WALL_CRUMBLED:              return GFX_FELSBODEN;
2968     case EL_ROCK:                       return GFX_FELSBROCKEN;
2969     case EL_EMERALD:                    return GFX_EDELSTEIN;
2970     case EL_EXIT_CLOSED:                return GFX_AUSGANG_ZU;
2971     case EL_EXIT_OPENING:               return GFX_AUSGANG_ACT;
2972     case EL_EXIT_OPEN:                  return GFX_AUSGANG_AUF;
2973     case EL_SP_EXIT_OPEN:               return GFX_SP_EXIT;
2974     case EL_PLAYER1:                    return GFX_SPIELER1;
2975     case EL_PLAYER2:                    return GFX_SPIELER2;
2976     case EL_PLAYER3:                    return GFX_SPIELER3;
2977     case EL_PLAYER4:                    return GFX_SPIELER4;
2978     case EL_BUG:                        return GFX_KAEFER;
2979     case EL_BUG_RIGHT:                  return GFX_KAEFER_RIGHT;
2980     case EL_BUG_UP:                     return GFX_KAEFER_UP;
2981     case EL_BUG_LEFT:                   return GFX_KAEFER_LEFT;
2982     case EL_BUG_DOWN:                   return GFX_KAEFER_DOWN;
2983     case EL_SPACESHIP:                  return GFX_FLIEGER;
2984     case EL_SPACESHIP_RIGHT:            return GFX_FLIEGER_RIGHT;
2985     case EL_SPACESHIP_UP:               return GFX_FLIEGER_UP;
2986     case EL_SPACESHIP_LEFT:             return GFX_FLIEGER_LEFT;
2987     case EL_SPACESHIP_DOWN:             return GFX_FLIEGER_DOWN;
2988     case EL_BD_BUTTERFLY:               return GFX_BUTTERFLY;
2989     case EL_BD_BUTTERFLY_RIGHT:         return GFX_BUTTERFLY_RIGHT;
2990     case EL_BD_BUTTERFLY_UP:            return GFX_BUTTERFLY_UP;
2991     case EL_BD_BUTTERFLY_LEFT:          return GFX_BUTTERFLY_LEFT;
2992     case EL_BD_BUTTERFLY_DOWN:          return GFX_BUTTERFLY_DOWN;
2993     case EL_BD_FIREFLY:                 return GFX_FIREFLY;
2994     case EL_BD_FIREFLY_RIGHT:           return GFX_FIREFLY_RIGHT;
2995     case EL_BD_FIREFLY_UP:              return GFX_FIREFLY_UP;
2996     case EL_BD_FIREFLY_LEFT:            return GFX_FIREFLY_LEFT;
2997     case EL_BD_FIREFLY_DOWN:            return GFX_FIREFLY_DOWN;
2998     case EL_YAMYAM:                     return GFX_MAMPFER;
2999     case EL_ROBOT:                      return GFX_ROBOT;
3000     case EL_STEELWALL:                  return GFX_BETON;
3001     case EL_DIAMOND:                    return GFX_DIAMANT;
3002     case EL_QUICKSAND_EMPTY:            return GFX_MORAST_LEER;
3003     case EL_QUICKSAND_FULL:             return GFX_MORAST_VOLL;
3004     case EL_QUICKSAND_EMPTYING:         return GFX_MORAST_LEER;
3005     case EL_AMOEBA_DROP:                return GFX_TROPFEN;
3006     case EL_BOMB:                       return GFX_BOMBE;
3007     case EL_MAGIC_WALL:                 return GFX_MAGIC_WALL_OFF;
3008     case EL_MAGIC_WALL_ACTIVE:          return GFX_MAGIC_WALL_EMPTY;
3009     case EL_MAGIC_WALL_EMPTYING:        return GFX_MAGIC_WALL_EMPTY;
3010     case EL_MAGIC_WALL_FULL:            return GFX_MAGIC_WALL_FULL;
3011     case EL_MAGIC_WALL_DEAD:            return GFX_MAGIC_WALL_DEAD;
3012     case EL_ACID:                       return GFX_SALZSAEURE;
3013     case EL_AMOEBA_DEAD:                return GFX_AMOEBE_TOT;
3014     case EL_AMOEBA_WET:                 return GFX_AMOEBE_NASS;
3015     case EL_AMOEBA_DRY:                 return GFX_AMOEBE_NORM;
3016     case EL_AMOEBA_FULL:                return GFX_AMOEBE_VOLL;
3017     case EL_BD_AMOEBA:                  return GFX_AMOEBE_BD;
3018     case EL_AMOEBA_TO_DIAMOND:          return GFX_AMOEBA2DIAM;
3019     case EL_AMOEBA_DRIPPING:            return GFX_AMOEBE_NASS;
3020     case EL_NUT:                        return GFX_KOKOSNUSS;
3021     case EL_GAMEOFLIFE:                 return GFX_LIFE;
3022     case EL_BIOMAZE:                    return GFX_LIFE_ASYNC;
3023     case EL_DYNAMITE_ACTIVE:            return GFX_DYNAMIT;
3024     case EL_STONEBLOCK:                 return GFX_BADEWANNE;
3025     case EL_ACIDPOOL_TOPLEFT:           return GFX_BADEWANNE1;
3026     case EL_ACIDPOOL_TOPRIGHT:          return GFX_BADEWANNE2;
3027     case EL_ACIDPOOL_BOTTOMLEFT:        return GFX_BADEWANNE3;
3028     case EL_ACIDPOOL_BOTTOM:            return GFX_BADEWANNE4;
3029     case EL_ACIDPOOL_BOTTOMRIGHT:       return GFX_BADEWANNE5;
3030     case EL_ROBOT_WHEEL:                return GFX_ABLENK_AUS;
3031     case EL_ROBOT_WHEEL_ACTIVE:         return GFX_ABLENK_EIN;
3032     case EL_KEY1:                       return GFX_SCHLUESSEL1;
3033     case EL_KEY2:                       return GFX_SCHLUESSEL2;
3034     case EL_KEY3:                       return GFX_SCHLUESSEL3;
3035     case EL_KEY4:                       return GFX_SCHLUESSEL4;
3036     case EL_GATE1:                      return GFX_PFORTE1;
3037     case EL_GATE2:                      return GFX_PFORTE2;
3038     case EL_GATE3:                      return GFX_PFORTE3;
3039     case EL_GATE4:                      return GFX_PFORTE4;
3040     case EL_GATE1_GRAY:                 return GFX_PFORTE1X;
3041     case EL_GATE2_GRAY:                 return GFX_PFORTE2X;
3042     case EL_GATE3_GRAY:                 return GFX_PFORTE3X;
3043     case EL_GATE4_GRAY:                 return GFX_PFORTE4X;
3044     case EL_DYNAMITE:                   return GFX_DYNAMIT_AUS;
3045     case EL_PACMAN:                     return GFX_PACMAN;
3046     case EL_PACMAN_RIGHT:               return GFX_PACMAN_RIGHT;
3047     case EL_PACMAN_UP:                  return GFX_PACMAN_UP;
3048     case EL_PACMAN_LEFT:                return GFX_PACMAN_LEFT;
3049     case EL_PACMAN_DOWN:                return GFX_PACMAN_DOWN;
3050     case EL_INVISIBLE_WALL:             return GFX_UNSICHTBAR;
3051     case EL_INVISIBLE_WALL_ACTIVE:      return GFX_UNSICHTBAR_ON;
3052     case EL_WALL_EMERALD:               return GFX_ERZ_EDEL;
3053     case EL_WALL_DIAMOND:               return GFX_ERZ_DIAM;
3054     case EL_LAMP:                       return GFX_BIRNE_AUS;
3055     case EL_LAMP_ACTIVE:                return GFX_BIRNE_EIN;
3056     case EL_TIME_ORB_FULL:              return GFX_ZEIT_VOLL;
3057     case EL_TIME_ORB_EMPTY:             return GFX_ZEIT_LEER;
3058     case EL_WALL_GROWING:               return GFX_MAUER_LEBT;
3059     case EL_WALL_GROWING_X:             return GFX_MAUER_X;
3060     case EL_WALL_GROWING_Y:             return GFX_MAUER_Y;
3061     case EL_WALL_GROWING_XY:            return GFX_MAUER_XY;
3062     case EL_BD_DIAMOND:                 return GFX_EDELSTEIN_BD;
3063     case EL_EMERALD_YELLOW:             return GFX_EDELSTEIN_GELB;
3064     case EL_EMERALD_RED:                return GFX_EDELSTEIN_ROT;
3065     case EL_EMERALD_PURPLE:             return GFX_EDELSTEIN_LILA;
3066     case EL_WALL_BD_DIAMOND:            return GFX_ERZ_EDEL_BD;
3067     case EL_WALL_EMERALD_YELLOW:        return GFX_ERZ_EDEL_GELB;
3068     case EL_WALL_EMERALD_RED:           return GFX_ERZ_EDEL_ROT;
3069     case EL_WALL_EMERALD_PURPLE:        return GFX_ERZ_EDEL_LILA;
3070     case EL_DARK_YAMYAM:                return GFX_MAMPFER2;
3071     case EL_BD_MAGIC_WALL:              return GFX_MAGIC_WALL_BD_OFF;
3072     case EL_BD_MAGIC_WALL_ACTIVE:       return GFX_MAGIC_WALL_BD_EMPTY;
3073     case EL_BD_MAGIC_WALL_EMPTYING:     return GFX_MAGIC_WALL_BD_EMPTY;
3074     case EL_BD_MAGIC_WALL_FULL:         return GFX_MAGIC_WALL_BD_FULL;
3075     case EL_BD_MAGIC_WALL_DEAD:         return GFX_MAGIC_WALL_BD_DEAD;
3076     case EL_DYNABOMB_PLAYER1_ACTIVE:    return GFX_DYNABOMB;
3077     case EL_DYNABOMB_PLAYER2_ACTIVE:    return GFX_DYNABOMB;
3078     case EL_DYNABOMB_PLAYER3_ACTIVE:    return GFX_DYNABOMB;
3079     case EL_DYNABOMB_PLAYER4_ACTIVE:    return GFX_DYNABOMB;
3080     case EL_DYNABOMB_NR:                return GFX_DYNABOMB_NR;
3081     case EL_DYNABOMB_SZ:                return GFX_DYNABOMB_SZ;
3082     case EL_DYNABOMB_XL:                return GFX_DYNABOMB_XL;
3083     case EL_SOKOBAN_OBJECT:             return GFX_SOKOBAN_OBJEKT;
3084     case EL_SOKOBAN_FIELD_EMPTY:        return GFX_SOKOBAN_FELD_LEER;
3085     case EL_SOKOBAN_FIELD_FULL:         return GFX_SOKOBAN_FELD_VOLL;
3086     case EL_MOLE:                       return GFX_MOLE;
3087     case EL_PENGUIN:                    return GFX_PINGUIN;
3088     case EL_PIG:                        return GFX_SCHWEIN;
3089     case EL_DRAGON:                     return GFX_DRACHE;
3090     case EL_SATELLITE:                  return GFX_SONDE;
3091     case EL_ARROW_BLUE_LEFT:            return GFX_PFEIL_LEFT;
3092     case EL_ARROW_BLUE_RIGHT:           return GFX_PFEIL_RIGHT;
3093     case EL_ARROW_BLUE_UP:              return GFX_PFEIL_UP;
3094     case EL_ARROW_BLUE_DOWN:            return GFX_PFEIL_DOWN;
3095     case EL_SPEED_PILL:                 return GFX_SPEED_PILL;
3096     case EL_SP_TERMINAL_ACTIVE:         return GFX_SP_TERMINAL;
3097     case EL_SP_BUGGY_BASE_ACTIVE:       return GFX_SP_BUG_ACTIVE;
3098     case EL_SP_ZONK:                    return GFX_SP_ZONK;
3099       /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
3100     case EL_INVISIBLE_STEELWALL:        return GFX_INVISIBLE_STEEL;
3101     case EL_INVISIBLE_STEELWALL_ACTIVE: return GFX_INVISIBLE_STEEL_ON;
3102     case EL_BLACK_ORB:                  return GFX_BLACK_ORB;
3103     case EL_EM_GATE1:                   return GFX_EM_GATE_1;
3104     case EL_EM_GATE2:                   return GFX_EM_GATE_2;
3105     case EL_EM_GATE3:                   return GFX_EM_GATE_3;
3106     case EL_EM_GATE4:                   return GFX_EM_GATE_4;
3107     case EL_EM_GATE1_GRAY:              return GFX_EM_GATE_1X;
3108     case EL_EM_GATE2_GRAY:              return GFX_EM_GATE_2X;
3109     case EL_EM_GATE3_GRAY:              return GFX_EM_GATE_3X;
3110     case EL_EM_GATE4_GRAY:              return GFX_EM_GATE_4X;
3111     case EL_EM_KEY1_FILE:               return GFX_EM_KEY_1;
3112     case EL_EM_KEY2_FILE:               return GFX_EM_KEY_2;
3113     case EL_EM_KEY3_FILE:               return GFX_EM_KEY_3;
3114     case EL_EM_KEY4_FILE:               return GFX_EM_KEY_4;
3115     case EL_EM_KEY1:                    return GFX_EM_KEY_1;
3116     case EL_EM_KEY2:                    return GFX_EM_KEY_2;
3117     case EL_EM_KEY3:                    return GFX_EM_KEY_3;
3118     case EL_EM_KEY4:                    return GFX_EM_KEY_4;
3119     case EL_PEARL:                      return GFX_PEARL;
3120     case EL_CRYSTAL:                    return GFX_CRYSTAL;
3121     case EL_WALL_PEARL:                 return GFX_WALL_PEARL;
3122     case EL_WALL_CRYSTAL:               return GFX_WALL_CRYSTAL;
3123     case EL_DOOR_WHITE:                 return GFX_DOOR_WHITE;
3124     case EL_DOOR_WHITE_GRAY:            return GFX_DOOR_WHITE_GRAY;
3125     case EL_KEY_WHITE:                  return GFX_KEY_WHITE;
3126     case EL_SHIELD_NORMAL:              return GFX_SHIELD_PASSIVE;
3127     case EL_SHIELD_DEADLY:              return GFX_SHIELD_ACTIVE;
3128     case EL_EXTRA_TIME:                 return GFX_EXTRA_TIME;
3129     case EL_SWITCHGATE_OPEN:            return GFX_SWITCHGATE_OPEN;
3130     case EL_SWITCHGATE_CLOSED:          return GFX_SWITCHGATE_CLOSED;
3131     case EL_SWITCHGATE_SWITCH_UP:       return GFX_SWITCHGATE_SWITCH_1;
3132     case EL_SWITCHGATE_SWITCH_DOWN:     return GFX_SWITCHGATE_SWITCH_2;
3133     case EL_CONVEYOR_BELT1_LEFT:        return GFX_BELT1_LEFT;
3134     case EL_CONVEYOR_BELT1_MIDDLE:      return GFX_BELT1_MIDDLE;
3135     case EL_CONVEYOR_BELT1_RIGHT:       return GFX_BELT1_RIGHT;
3136     case EL_CONVEYOR_BELT1_LEFT_ACTIVE: return GFX_BELT1_LEFT;
3137     case EL_CONVEYOR_BELT1_MIDDLE_ACTIVE:return GFX_BELT1_MIDDLE;
3138     case EL_CONVEYOR_BELT1_RIGHT_ACTIVE:return GFX_BELT1_RIGHT;
3139     case EL_CONVEYOR_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
3140     case EL_CONVEYOR_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
3141     case EL_CONVEYOR_BELT1_SWITCH_RIGHT:return GFX_BELT1_SWITCH_RIGHT;
3142     case EL_CONVEYOR_BELT2_LEFT:        return GFX_BELT2_LEFT;
3143     case EL_CONVEYOR_BELT2_MIDDLE:      return GFX_BELT2_MIDDLE;
3144     case EL_CONVEYOR_BELT2_RIGHT:       return GFX_BELT2_RIGHT;
3145     case EL_CONVEYOR_BELT2_LEFT_ACTIVE: return GFX_BELT2_LEFT;
3146     case EL_CONVEYOR_BELT2_MIDDLE_ACTIVE:return GFX_BELT2_MIDDLE;
3147     case EL_CONVEYOR_BELT2_RIGHT_ACTIVE:return GFX_BELT2_RIGHT;
3148     case EL_CONVEYOR_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
3149     case EL_CONVEYOR_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
3150     case EL_CONVEYOR_BELT2_SWITCH_RIGHT:return GFX_BELT2_SWITCH_RIGHT;
3151     case EL_CONVEYOR_BELT3_LEFT:        return GFX_BELT3_LEFT;
3152     case EL_CONVEYOR_BELT3_MIDDLE:      return GFX_BELT3_MIDDLE;
3153     case EL_CONVEYOR_BELT3_RIGHT:       return GFX_BELT3_RIGHT;
3154     case EL_CONVEYOR_BELT3_LEFT_ACTIVE: return GFX_BELT3_LEFT;
3155     case EL_CONVEYOR_BELT3_MIDDLE_ACTIVE:return GFX_BELT3_MIDDLE;
3156     case EL_CONVEYOR_BELT3_RIGHT_ACTIVE:return GFX_BELT3_RIGHT;
3157     case EL_CONVEYOR_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
3158     case EL_CONVEYOR_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
3159     case EL_CONVEYOR_BELT3_SWITCH_RIGHT:return GFX_BELT3_SWITCH_RIGHT;
3160     case EL_CONVEYOR_BELT4_LEFT:        return GFX_BELT4_LEFT;
3161     case EL_CONVEYOR_BELT4_MIDDLE:      return GFX_BELT4_MIDDLE;
3162     case EL_CONVEYOR_BELT4_RIGHT:       return GFX_BELT4_RIGHT;
3163     case EL_CONVEYOR_BELT4_LEFT_ACTIVE: return GFX_BELT4_LEFT;
3164     case EL_CONVEYOR_BELT4_MIDDLE_ACTIVE:return GFX_BELT4_MIDDLE;
3165     case EL_CONVEYOR_BELT4_RIGHT_ACTIVE:return GFX_BELT4_RIGHT;
3166     case EL_CONVEYOR_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
3167     case EL_CONVEYOR_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
3168     case EL_CONVEYOR_BELT4_SWITCH_RIGHT:return GFX_BELT4_SWITCH_RIGHT;
3169     case EL_LANDMINE:                   return GFX_LANDMINE;
3170     case EL_ENVELOPE:                   return GFX_ENVELOPE;
3171     case EL_LIGHT_SWITCH:               return GFX_LIGHT_SWITCH_OFF;
3172     case EL_LIGHT_SWITCH_ACTIVE:        return GFX_LIGHT_SWITCH_ON;
3173     case EL_SIGN_EXCLAMATION:           return GFX_SIGN_EXCLAMATION;
3174     case EL_SIGN_RADIOACTIVITY:         return GFX_SIGN_RADIOACTIVITY;
3175     case EL_SIGN_STOP:                  return GFX_SIGN_STOP;
3176     case EL_SIGN_WHEELCHAIR:            return GFX_SIGN_WHEELCHAIR;
3177     case EL_SIGN_PARKING:               return GFX_SIGN_PARKING;
3178     case EL_SIGN_ONEWAY:                return GFX_SIGN_ONEWAY;
3179     case EL_SIGN_HEART:                 return GFX_SIGN_HEART;
3180     case EL_SIGN_TRIANGLE:              return GFX_SIGN_TRIANGLE;
3181     case EL_SIGN_ROUND:                 return GFX_SIGN_ROUND;
3182     case EL_SIGN_EXIT:                  return GFX_SIGN_EXIT;
3183     case EL_SIGN_YINYANG:               return GFX_SIGN_YINYANG;
3184     case EL_SIGN_OTHER:                 return GFX_SIGN_OTHER;
3185     case EL_MOLE_LEFT:                  return GFX_MOLE_LEFT;
3186     case EL_MOLE_RIGHT:                 return GFX_MOLE_RIGHT;
3187     case EL_MOLE_UP:                    return GFX_MOLE_UP;
3188     case EL_MOLE_DOWN:                  return GFX_MOLE_DOWN;
3189     case EL_STEELWALL_SLANTED:          return GFX_STEEL_SLANTED;
3190     case EL_INVISIBLE_SAND:             return GFX_SAND_INVISIBLE;
3191     case EL_INVISIBLE_SAND_ACTIVE:      return GFX_SAND_INVISIBLE_ON;
3192     case EL_DX_UNKNOWN_15:              return GFX_DX_UNKNOWN_15;
3193     case EL_DX_UNKNOWN_42:              return GFX_DX_UNKNOWN_42;
3194     case EL_TIMEGATE_OPEN:              return GFX_TIMEGATE_OPEN;
3195     case EL_TIMEGATE_CLOSED:            return GFX_TIMEGATE_CLOSED;
3196     case EL_TIMEGATE_SWITCH_ACTIVE:     return GFX_TIMEGATE_SWITCH;
3197     case EL_TIMEGATE_SWITCH:            return GFX_TIMEGATE_SWITCH;
3198     case EL_BALLOON:                    return GFX_BALLOON;
3199     case EL_BALLOON_SEND_LEFT:          return GFX_BALLOON_SEND_LEFT;
3200     case EL_BALLOON_SEND_RIGHT:         return GFX_BALLOON_SEND_RIGHT;
3201     case EL_BALLOON_SEND_UP:            return GFX_BALLOON_SEND_UP;
3202     case EL_BALLOON_SEND_DOWN:          return GFX_BALLOON_SEND_DOWN;
3203     case EL_BALLOON_SEND_ANY_DIRECTION: return GFX_BALLOON_SEND_ANY;
3204     case EL_EMC_STEELWALL1:             return GFX_EMC_STEEL_WALL_1;
3205     case EL_EMC_STEELWALL2:             return GFX_EMC_STEEL_WALL_2;
3206     case EL_EMC_STEELWALL3:             return GFX_EMC_STEEL_WALL_3;
3207     case EL_EMC_STEELWALL4:             return GFX_EMC_STEEL_WALL_4;
3208     case EL_EMC_WALL_PILLAR_UPPER:      return GFX_EMC_WALL_1;
3209     case EL_EMC_WALL_PILLAR_MIDDLE:     return GFX_EMC_WALL_2;
3210     case EL_EMC_WALL_PILLAR_LOWER:      return GFX_EMC_WALL_3;
3211     case EL_EMC_WALL4:                  return GFX_EMC_WALL_4;
3212     case EL_EMC_WALL5:                  return GFX_EMC_WALL_5;
3213     case EL_EMC_WALL6:                  return GFX_EMC_WALL_6;
3214     case EL_EMC_WALL7:                  return GFX_EMC_WALL_7;
3215     case EL_EMC_WALL8:                  return GFX_EMC_WALL_8;
3216     case EL_TUBE_ALL:                   return GFX_TUBE_CROSS;
3217     case EL_TUBE_VERTICAL:              return GFX_TUBE_VERTICAL;
3218     case EL_TUBE_HORIZONTAL:            return GFX_TUBE_HORIZONTAL;
3219     case EL_TUBE_VERTICAL_LEFT:         return GFX_TUBE_VERT_LEFT;
3220     case EL_TUBE_VERTICAL_RIGHT:        return GFX_TUBE_VERT_RIGHT;
3221     case EL_TUBE_HORIZONTAL_UP:         return GFX_TUBE_HORIZ_UP;
3222     case EL_TUBE_HORIZONTAL_DOWN:       return GFX_TUBE_HORIZ_DOWN;
3223     case EL_TUBE_LEFT_UP:               return GFX_TUBE_LEFT_UP;
3224     case EL_TUBE_LEFT_DOWN:             return GFX_TUBE_LEFT_DOWN;
3225     case EL_TUBE_RIGHT_UP:              return GFX_TUBE_RIGHT_UP;
3226     case EL_TUBE_RIGHT_DOWN:            return GFX_TUBE_RIGHT_DOWN;
3227     case EL_SPRING:                     return GFX_SPRING;
3228     case EL_SPRING_MOVING:              return GFX_SPRING;
3229     case EL_TRAP:                       return GFX_TRAP_INACTIVE;
3230     case EL_TRAP_ACTIVE:                return GFX_TRAP_ACTIVE;
3231     case EL_BD_WALL:                    return GFX_BD_WALL;
3232     case EL_BD_ROCK:                    return GFX_BD_ROCK;
3233     case EL_DX_SUPABOMB:                return GFX_DX_SUPABOMB;
3234     case EL_SP_MURPHY_CLONE:            return GFX_SP_MURPHY_CLONE;
3235
3236     default:
3237     {
3238       if (IS_CHAR(element))
3239         return GFX_CHAR_START + (element - EL_CHAR_START);
3240       else if (element >= EL_SP_START && element <= EL_SP_END)
3241       {
3242         int nr_element = element - EL_SP_START;
3243         int gfx_per_line = 8;
3244         int nr_graphic =
3245           (nr_element / gfx_per_line) * SP_PER_LINE +
3246           (nr_element % gfx_per_line);
3247
3248         return GFX_START_ROCKSSP + nr_graphic;
3249       }
3250       else
3251         return -1;
3252     }
3253   }
3254 }
3255
3256 int el2gfx(int element)
3257 {
3258 #if 1
3259   int graphic_OLD = el2gfx_OLD(element);
3260
3261   return graphic_OLD;
3262 #else
3263
3264   int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
3265
3266 #if DEBUG
3267   int graphic_OLD = el2gfx_OLD(element);
3268
3269   if (element >= MAX_ELEMENTS)
3270   {
3271     Error(ERR_WARN, "el2gfx: element == %d >= MAX_ELEMENTS", element);
3272   }
3273
3274   if (graphic_NEW != graphic_OLD)
3275   {
3276     Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
3277           graphic_NEW, graphic_OLD);
3278   }
3279 #endif
3280
3281   return graphic_NEW;
3282 #endif
3283 }
3284
3285 int el2img(int element)
3286 {
3287 #if 1
3288   int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
3289
3290   return graphic_NEW;
3291 #else
3292
3293   switch(element)
3294   {
3295     case EL_BD_BUTTERFLY:       return IMG_BD_BUTTERFLY;
3296     case EL_BD_FIREFLY:         return IMG_BD_FIREFLY;
3297     case EL_SP_ELECTRON:        return IMG_SP_ELECTRON;
3298
3299     default:
3300       break;
3301   }
3302
3303   return IMG_EMPTY;
3304 #endif
3305 }
3306
3307 int el_dir2img(int element, int direction)
3308 {
3309   return el_dir_act2img(element, direction, GFX_ACTION_DEFAULT);
3310 }
3311
3312 int el_dir_act2img(int element, int direction, int action)
3313 {
3314   action = graphics_action_mapping[action];
3315   direction = MV_DIR_BIT(direction);
3316
3317   return element_info[element].direction_graphic[action][direction];
3318 }