rnd-20021006-1-src
[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 #if 0
769   int delay = new_graphic_info[graphic].anim_delay;
770
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     {
1525       graphic = IMG_WALL_GROWING_ACTIVE_RIGHT;
1526       frame = new_graphic_info[graphic].anim_frames - 1;
1527     }
1528     else if (right_stopped)
1529     {
1530       graphic = IMG_WALL_GROWING_ACTIVE_LEFT;
1531       frame = new_graphic_info[graphic].anim_frames - 1;
1532     }
1533   }
1534 #if 0
1535   else if ((element == EL_ROCK ||
1536             element == EL_SP_ZONK ||
1537             element == EL_BD_ROCK ||
1538             element == EL_SP_INFOTRON ||
1539             IS_GEM(element))
1540            && !cut_mode)
1541   {
1542     if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1543     {
1544       if (element == EL_ROCK ||
1545           element == EL_SP_ZONK ||
1546           element == EL_BD_ROCK)
1547       {
1548         if (move_dir == MV_LEFT)
1549           graphic += (4 - phase4) % 4;
1550         else if (move_dir == MV_RIGHT)
1551           graphic += phase4;
1552         else
1553           graphic += phase2 * 2;
1554       }
1555       else if (element != EL_SP_INFOTRON)
1556         graphic += phase2;
1557     }
1558   }
1559 #endif
1560   else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1561   {
1562     graphic = (element == EL_BD_AMOEBA ? IMG_BD_AMOEBA_PART1 :
1563                element == EL_AMOEBA_WET ? IMG_AMOEBA_WET_PART1 :
1564                element == EL_AMOEBA_DRY ? IMG_AMOEBA_DRY_PART1 :
1565                element == EL_AMOEBA_FULL ? IMG_AMOEBA_FULL_PART1 :
1566                IMG_AMOEBA_DEAD_PART1);
1567
1568     graphic += (x + 2 * y + 4) % 4;
1569   }
1570
1571   if (dx || dy)
1572     DrawNewGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1573   else if (mask_mode == USE_MASKING)
1574     DrawNewGraphicThruMask(x, y, graphic, frame);
1575   else
1576     DrawNewGraphic(x, y, graphic, frame);
1577 }
1578
1579 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1580                          int cut_mode, int mask_mode)
1581 {
1582   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1583     DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1584                          cut_mode, mask_mode);
1585 }
1586
1587 void DrawNewLevelElementExt(int x, int y, int dx, int dy, int element,
1588                          int cut_mode, int mask_mode)
1589 {
1590   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1591     DrawNewScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1592                          cut_mode, mask_mode);
1593 }
1594
1595 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1596                               int cut_mode)
1597 {
1598   DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1599 }
1600
1601 void DrawNewScreenElementShifted(int x, int y, int dx, int dy, int element,
1602                               int cut_mode)
1603 {
1604   DrawNewScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1605 }
1606
1607 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1608                              int cut_mode)
1609 {
1610   DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1611 }
1612
1613 void DrawNewLevelElementShifted(int x, int y, int dx, int dy, int element,
1614                              int cut_mode)
1615 {
1616   DrawNewLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1617 }
1618
1619 void DrawScreenElementThruMask(int x, int y, int element)
1620 {
1621   DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1622 }
1623
1624 void DrawNewScreenElementThruMask(int x, int y, int element)
1625 {
1626   DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1627 }
1628
1629 void DrawLevelElementThruMask(int x, int y, int element)
1630 {
1631   DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1632 }
1633
1634 void DrawNewLevelElementThruMask(int x, int y, int element)
1635 {
1636   DrawNewLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1637 }
1638
1639 void DrawLevelFieldThruMask(int x, int y)
1640 {
1641   DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1642 }
1643
1644 void DrawNewLevelFieldThruMask(int x, int y)
1645 {
1646   DrawNewLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1647 }
1648
1649 void ErdreichAnbroeckeln(int x, int y)
1650 {
1651   Bitmap *src_bitmap;
1652   int src_x, src_y;
1653   int i, width, height, cx,cy;
1654   int ux = LEVELX(x), uy = LEVELY(y);
1655   int element, graphic;
1656   int snip = 4;
1657   static int xy[4][2] =
1658   {
1659     { 0, -1 },
1660     { -1, 0 },
1661     { +1, 0 },
1662     { 0, +1 }
1663   };
1664
1665   if (!IN_LEV_FIELD(ux, uy))
1666     return;
1667
1668   element = Feld[ux][uy];
1669
1670   if (element == EL_SAND ||
1671       element == EL_LANDMINE ||
1672       element == EL_TRAP ||
1673       element == EL_TRAP_ACTIVE)
1674   {
1675     if (!IN_SCR_FIELD(x, y))
1676       return;
1677
1678     graphic = GFX_ERDENRAND;
1679
1680     getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1681
1682     for(i=0; i<4; i++)
1683     {
1684       int uxx, uyy;
1685
1686       uxx = ux + xy[i][0];
1687       uyy = uy + xy[i][1];
1688       if (!IN_LEV_FIELD(uxx, uyy))
1689         element = EL_STEELWALL;
1690       else
1691         element = Feld[uxx][uyy];
1692
1693       if (element == EL_SAND ||
1694           element == EL_LANDMINE ||
1695           element == EL_TRAP ||
1696           element == EL_TRAP_ACTIVE)
1697         continue;
1698
1699       if (i == 1 || i == 2)
1700       {
1701         width = snip;
1702         height = TILEY;
1703         cx = (i == 2 ? TILEX - snip : 0);
1704         cy = 0;
1705       }
1706       else
1707       {
1708         width = TILEX;
1709         height = snip;
1710         cx = 0;
1711         cy = (i == 3 ? TILEY - snip : 0);
1712       }
1713
1714       BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1715                  width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1716     }
1717
1718     MarkTileDirty(x, y);
1719   }
1720   else
1721   {
1722     graphic = GFX_ERDENRAND;
1723
1724     getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1725
1726     for(i=0; i<4; i++)
1727     {
1728       int xx, yy, uxx, uyy;
1729
1730       xx = x + xy[i][0];
1731       yy = y + xy[i][1];
1732       uxx = ux + xy[i][0];
1733       uyy = uy + xy[i][1];
1734
1735       if (!IN_LEV_FIELD(uxx, uyy) ||
1736           (Feld[uxx][uyy] != EL_SAND &&
1737            Feld[uxx][uyy] != EL_LANDMINE &&
1738            Feld[uxx][uyy] != EL_TRAP &&
1739            Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1740           !IN_SCR_FIELD(xx, yy))
1741         continue;
1742
1743       if (i == 1 || i == 2)
1744       {
1745         width = snip;
1746         height = TILEY;
1747         cx = (i == 1 ? TILEX - snip : 0);
1748         cy = 0;
1749       }
1750       else
1751       {
1752         width = TILEX;
1753         height = snip;
1754         cx = 0;
1755         cy = (i==0 ? TILEY-snip : 0);
1756       }
1757
1758       BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1759                  width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1760
1761       MarkTileDirty(xx, yy);
1762     }
1763   }
1764 }
1765
1766 void DrawScreenElement(int x, int y, int element)
1767 {
1768   DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1769   ErdreichAnbroeckeln(x, y);
1770 }
1771
1772 void DrawNewScreenElement(int x, int y, int element)
1773 {
1774   DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1775   ErdreichAnbroeckeln(x, y);
1776 }
1777
1778 void DrawLevelElement(int x, int y, int element)
1779 {
1780   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1781     DrawScreenElement(SCREENX(x), SCREENY(y), element);
1782 }
1783
1784 void DrawNewLevelElement(int x, int y, int element)
1785 {
1786   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1787     DrawNewScreenElement(SCREENX(x), SCREENY(y), element);
1788 }
1789
1790 void DrawScreenField(int x, int y)
1791 {
1792   int ux = LEVELX(x), uy = LEVELY(y);
1793   int element, content;
1794
1795   if (!IN_LEV_FIELD(ux, uy))
1796   {
1797     if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1798       element = EL_EMPTY;
1799     else
1800       element = BorderElement;
1801
1802     DrawScreenElement(x, y, element);
1803     return;
1804   }
1805
1806   element = Feld[ux][uy];
1807   content = Store[ux][uy];
1808
1809   if (IS_MOVING(ux, uy))
1810   {
1811     int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1812     boolean cut_mode = NO_CUTTING;
1813
1814     if (element == EL_QUICKSAND_EMPTYING ||
1815         element == EL_MAGIC_WALL_EMPTYING ||
1816         element == EL_BD_MAGIC_WALL_EMPTYING ||
1817         element == EL_AMOEBA_DRIPPING)
1818       cut_mode = CUT_ABOVE;
1819     else if (element == EL_QUICKSAND_FILLING ||
1820              element == EL_MAGIC_WALL_FILLING ||
1821              element == EL_BD_MAGIC_WALL_FILLING)
1822       cut_mode = CUT_BELOW;
1823
1824     if (cut_mode == CUT_ABOVE)
1825       DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1826     else
1827       DrawScreenElement(x, y, EL_EMPTY);
1828
1829     if (horiz_move)
1830       DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1831     else if (cut_mode == NO_CUTTING)
1832       DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1833     else
1834       DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1835
1836     if (content == EL_ACID)
1837       DrawLevelElementThruMask(ux, uy + 1, EL_ACID);
1838   }
1839   else if (IS_BLOCKED(ux, uy))
1840   {
1841     int oldx, oldy;
1842     int sx, sy;
1843     int horiz_move;
1844     boolean cut_mode = NO_CUTTING;
1845     int element_old, content_old;
1846
1847     Blocked2Moving(ux, uy, &oldx, &oldy);
1848     sx = SCREENX(oldx);
1849     sy = SCREENY(oldy);
1850     horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1851                   MovDir[oldx][oldy] == MV_RIGHT);
1852
1853     element_old = Feld[oldx][oldy];
1854     content_old = Store[oldx][oldy];
1855
1856     if (element_old == EL_QUICKSAND_EMPTYING ||
1857         element_old == EL_MAGIC_WALL_EMPTYING ||
1858         element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1859         element_old == EL_AMOEBA_DRIPPING)
1860       cut_mode = CUT_ABOVE;
1861
1862     DrawScreenElement(x, y, EL_EMPTY);
1863
1864     if (horiz_move)
1865       DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1866                                NO_CUTTING);
1867     else if (cut_mode == NO_CUTTING)
1868       DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1869                                cut_mode);
1870     else
1871       DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1872                                cut_mode);
1873   }
1874   else if (IS_DRAWABLE(element))
1875     DrawScreenElement(x, y, element);
1876   else
1877     DrawScreenElement(x, y, EL_EMPTY);
1878 }
1879
1880 void DrawNewScreenField(int x, int y)
1881 {
1882   int ux = LEVELX(x), uy = LEVELY(y);
1883   int element, content;
1884
1885   if (!IN_LEV_FIELD(ux, uy))
1886   {
1887     if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1888       element = EL_EMPTY;
1889     else
1890       element = BorderElement;
1891
1892     DrawNewScreenElement(x, y, element);
1893     return;
1894   }
1895
1896   element = Feld[ux][uy];
1897   content = Store[ux][uy];
1898
1899   if (IS_MOVING(ux, uy))
1900   {
1901     int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1902     boolean cut_mode = NO_CUTTING;
1903
1904     if (element == EL_QUICKSAND_EMPTYING ||
1905         element == EL_MAGIC_WALL_EMPTYING ||
1906         element == EL_BD_MAGIC_WALL_EMPTYING ||
1907         element == EL_AMOEBA_DRIPPING)
1908       cut_mode = CUT_ABOVE;
1909     else if (element == EL_QUICKSAND_FILLING ||
1910              element == EL_MAGIC_WALL_FILLING ||
1911              element == EL_BD_MAGIC_WALL_FILLING)
1912       cut_mode = CUT_BELOW;
1913
1914     if (cut_mode == CUT_ABOVE)
1915       DrawNewScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1916     else
1917       DrawNewScreenElement(x, y, EL_EMPTY);
1918
1919     if (horiz_move)
1920       DrawNewScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1921     else if (cut_mode == NO_CUTTING)
1922       DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1923     else
1924       DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1925
1926     if (content == EL_ACID)
1927       DrawNewLevelElementThruMask(ux, uy + 1, EL_ACID);
1928   }
1929   else if (IS_BLOCKED(ux, uy))
1930   {
1931     int oldx, oldy;
1932     int sx, sy;
1933     int horiz_move;
1934     boolean cut_mode = NO_CUTTING;
1935     int element_old, content_old;
1936
1937     Blocked2Moving(ux, uy, &oldx, &oldy);
1938     sx = SCREENX(oldx);
1939     sy = SCREENY(oldy);
1940     horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1941                   MovDir[oldx][oldy] == MV_RIGHT);
1942
1943     element_old = Feld[oldx][oldy];
1944     content_old = Store[oldx][oldy];
1945
1946     if (element_old == EL_QUICKSAND_EMPTYING ||
1947         element_old == EL_MAGIC_WALL_EMPTYING ||
1948         element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1949         element_old == EL_AMOEBA_DRIPPING)
1950       cut_mode = CUT_ABOVE;
1951
1952     DrawNewScreenElement(x, y, EL_EMPTY);
1953
1954     if (horiz_move)
1955       DrawNewScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1956                                NO_CUTTING);
1957     else if (cut_mode == NO_CUTTING)
1958       DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1959                                cut_mode);
1960     else
1961       DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1962                                cut_mode);
1963   }
1964   else if (IS_DRAWABLE(element))
1965     DrawNewScreenElement(x, y, element);
1966   else
1967     DrawNewScreenElement(x, y, EL_EMPTY);
1968 }
1969
1970 void DrawLevelField(int x, int y)
1971 {
1972   if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1973     DrawScreenField(SCREENX(x), SCREENY(y));
1974   else if (IS_MOVING(x, y))
1975   {
1976     int newx,newy;
1977
1978     Moving2Blocked(x, y, &newx, &newy);
1979     if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1980       DrawScreenField(SCREENX(newx), SCREENY(newy));
1981   }
1982   else if (IS_BLOCKED(x, y))
1983   {
1984     int oldx, oldy;
1985
1986     Blocked2Moving(x, y, &oldx, &oldy);
1987     if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1988       DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1989   }
1990 }
1991
1992 void DrawNewLevelField(int x, int y)
1993 {
1994   if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1995     DrawNewScreenField(SCREENX(x), SCREENY(y));
1996   else if (IS_MOVING(x, y))
1997   {
1998     int newx,newy;
1999
2000     Moving2Blocked(x, y, &newx, &newy);
2001     if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
2002       DrawNewScreenField(SCREENX(newx), SCREENY(newy));
2003   }
2004   else if (IS_BLOCKED(x, y))
2005   {
2006     int oldx, oldy;
2007
2008     Blocked2Moving(x, y, &oldx, &oldy);
2009     if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
2010       DrawNewScreenField(SCREENX(oldx), SCREENY(oldy));
2011   }
2012 }
2013
2014 void DrawMiniElement(int x, int y, int element)
2015 {
2016   int graphic;
2017
2018   if (!element)
2019   {
2020     DrawMiniGraphic(x, y, -1);
2021     return;
2022   }
2023
2024   graphic = el2gfx(element);
2025   DrawMiniGraphic(x, y, graphic);
2026 }
2027
2028 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
2029 {
2030   int x = sx + scroll_x, y = sy + scroll_y;
2031
2032   if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
2033     DrawMiniElement(sx, sy, EL_EMPTY);
2034   else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
2035     DrawMiniElement(sx, sy, Feld[x][y]);
2036   else
2037   {
2038     int steel_type, steel_position;
2039     int border[6][2] =
2040     {
2041       { GFX_VSTEEL_UPPER_LEFT,  GFX_ISTEEL_UPPER_LEFT  },
2042       { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
2043       { GFX_VSTEEL_LOWER_LEFT,  GFX_ISTEEL_LOWER_LEFT  },
2044       { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
2045       { GFX_VSTEEL_VERTICAL,    GFX_ISTEEL_VERTICAL    },
2046       { GFX_VSTEEL_HORIZONTAL,  GFX_ISTEEL_HORIZONTAL  }
2047     };
2048
2049     steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
2050     steel_position = (x == -1 && y == -1                        ? 0 :
2051                       x == lev_fieldx && y == -1                ? 1 :
2052                       x == -1 && y == lev_fieldy                ? 2 :
2053                       x == lev_fieldx && y == lev_fieldy        ? 3 :
2054                       x == -1 || x == lev_fieldx                ? 4 :
2055                       y == -1 || y == lev_fieldy                ? 5 : -1);
2056
2057     if (steel_position != -1)
2058       DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
2059   }
2060 }
2061
2062 void DrawMicroElement(int xpos, int ypos, int element)
2063 {
2064   int graphic;
2065
2066   if (element == EL_EMPTY)
2067     return;
2068
2069   graphic = el2gfx(element);
2070
2071   if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
2072   {
2073     graphic -= GFX_START_ROCKSSP;
2074     BlitBitmap(pix[PIX_SP], drawto,
2075                MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
2076                MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
2077                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2078   }
2079   else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
2080   {
2081     graphic -= GFX_START_ROCKSDC;
2082     BlitBitmap(pix[PIX_DC], drawto,
2083                MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
2084                MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
2085                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2086   }
2087   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
2088   {
2089     graphic -= GFX_START_ROCKSMORE;
2090     BlitBitmap(pix[PIX_MORE], drawto,
2091                MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE)*MICRO_TILEX,
2092                MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE)*MICRO_TILEY,
2093                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2094   }
2095   else if (graphic >= GFX_CHAR_START && graphic <= GFX_CHAR_END)
2096   {
2097     graphic -= GFX_CHAR_START;
2098     BlitBitmap(pix[PIX_FONT_EM], drawto,
2099                MICRO_FONT_STARTX + (graphic % MICRO_GFX_PER_LINE)* MICRO_TILEX,
2100                MICRO_FONT_STARTY + (graphic / MICRO_GFX_PER_LINE)* MICRO_TILEY,
2101                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2102   }
2103   else
2104     BlitBitmap(pix[PIX_ELEMENTS], drawto,
2105                MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
2106                MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
2107                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2108 }
2109
2110 void DrawLevel()
2111 {
2112   int x,y;
2113
2114   ClearWindow();
2115
2116   for(x=BX1; x<=BX2; x++)
2117     for(y=BY1; y<=BY2; y++)
2118       DrawNewScreenField(x, y);
2119
2120   redraw_mask |= REDRAW_FIELD;
2121 }
2122
2123 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
2124 {
2125   int x,y;
2126
2127   for(x=0; x<size_x; x++)
2128     for(y=0; y<size_y; y++)
2129       DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
2130
2131   redraw_mask |= REDRAW_FIELD;
2132 }
2133
2134 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
2135 {
2136   int x, y;
2137
2138   ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
2139
2140   if (lev_fieldx < STD_LEV_FIELDX)
2141     xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
2142   if (lev_fieldy < STD_LEV_FIELDY)
2143     ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
2144
2145   xpos += MICRO_TILEX;
2146   ypos += MICRO_TILEY;
2147
2148   for(x=-1; x<=STD_LEV_FIELDX; x++)
2149   {
2150     for(y=-1; y<=STD_LEV_FIELDY; y++)
2151     {
2152       int lx = from_x + x, ly = from_y + y;
2153
2154       if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
2155         DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2156                          Ur[lx][ly]);
2157       else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
2158         DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2159                          BorderElement);
2160     }
2161   }
2162
2163   redraw_mask |= REDRAW_MICROLEVEL;
2164 }
2165
2166 #define MICROLABEL_EMPTY                0
2167 #define MICROLABEL_LEVEL_NAME           1
2168 #define MICROLABEL_CREATED_BY           2
2169 #define MICROLABEL_LEVEL_AUTHOR         3
2170 #define MICROLABEL_IMPORTED_FROM        4
2171 #define MICROLABEL_LEVEL_IMPORT_INFO    5
2172
2173 #define MAX_MICROLABEL_SIZE             (SXSIZE / FONT4_XSIZE)
2174
2175 static void DrawMicroLevelLabelExt(int mode)
2176 {
2177   char label_text[MAX_MICROLABEL_SIZE + 1];
2178
2179   ClearRectangle(drawto, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
2180
2181   strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
2182                        mode == MICROLABEL_CREATED_BY ? "created by" :
2183                        mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
2184                        mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
2185                        mode == MICROLABEL_LEVEL_IMPORT_INFO ?
2186                        leveldir_current->imported_from : ""),
2187           MAX_MICROLABEL_SIZE);
2188   label_text[MAX_MICROLABEL_SIZE] = '\0';
2189
2190   if (strlen(label_text) > 0)
2191   {
2192     int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
2193     int lypos = MICROLABEL_YPOS;
2194
2195     DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
2196   }
2197
2198   redraw_mask |= REDRAW_MICROLEVEL;
2199 }
2200
2201 void DrawMicroLevel(int xpos, int ypos, boolean restart)
2202 {
2203   static unsigned long scroll_delay = 0;
2204   static unsigned long label_delay = 0;
2205   static int from_x, from_y, scroll_direction;
2206   static int label_state, label_counter;
2207
2208   if (restart)
2209   {
2210     from_x = from_y = 0;
2211     scroll_direction = MV_RIGHT;
2212     label_state = 1;
2213     label_counter = 0;
2214
2215     DrawMicroLevelExt(xpos, ypos, from_x, from_y);
2216     DrawMicroLevelLabelExt(label_state);
2217
2218     /* initialize delay counters */
2219     DelayReached(&scroll_delay, 0);
2220     DelayReached(&label_delay, 0);
2221
2222     return;
2223   }
2224
2225   /* scroll micro level, if needed */
2226   if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
2227       DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
2228   {
2229     switch (scroll_direction)
2230     {
2231       case MV_LEFT:
2232         if (from_x > 0)
2233           from_x--;
2234         else
2235           scroll_direction = MV_UP;
2236         break;
2237
2238       case MV_RIGHT:
2239         if (from_x < lev_fieldx - STD_LEV_FIELDX)
2240           from_x++;
2241         else
2242           scroll_direction = MV_DOWN;
2243         break;
2244
2245       case MV_UP:
2246         if (from_y > 0)
2247           from_y--;
2248         else
2249           scroll_direction = MV_RIGHT;
2250         break;
2251
2252       case MV_DOWN:
2253         if (from_y < lev_fieldy - STD_LEV_FIELDY)
2254           from_y++;
2255         else
2256           scroll_direction = MV_LEFT;
2257         break;
2258
2259       default:
2260         break;
2261     }
2262
2263     DrawMicroLevelExt(xpos, ypos, from_x, from_y);
2264   }
2265
2266   /* redraw micro level label, if needed */
2267   if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
2268       strcmp(level.author, ANONYMOUS_NAME) != 0 &&
2269       strcmp(level.author, leveldir_current->name) != 0 &&
2270       DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
2271   {
2272     int max_label_counter = 23;
2273
2274     if (leveldir_current->imported_from != NULL)
2275       max_label_counter += 14;
2276
2277     label_counter = (label_counter + 1) % max_label_counter;
2278     label_state = (label_counter >= 0 && label_counter <= 7 ?
2279                    MICROLABEL_LEVEL_NAME :
2280                    label_counter >= 9 && label_counter <= 12 ?
2281                    MICROLABEL_CREATED_BY :
2282                    label_counter >= 14 && label_counter <= 21 ?
2283                    MICROLABEL_LEVEL_AUTHOR :
2284                    label_counter >= 23 && label_counter <= 26 ?
2285                    MICROLABEL_IMPORTED_FROM :
2286                    label_counter >= 28 && label_counter <= 35 ?
2287                    MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
2288     DrawMicroLevelLabelExt(label_state);
2289   }
2290 }
2291
2292 int REQ_in_range(int x, int y)
2293 {
2294   if (y > DY+249 && y < DY+278)
2295   {
2296     if (x > DX+1 && x < DX+48)
2297       return 1;
2298     else if (x > DX+51 && x < DX+98) 
2299       return 2;
2300   }
2301   return 0;
2302 }
2303
2304 #define MAX_REQUEST_LINES               13
2305 #define MAX_REQUEST_LINE_LEN            7
2306
2307 boolean Request(char *text, unsigned int req_state)
2308 {
2309   int mx, my, ty, result = -1;
2310   unsigned int old_door_state;
2311
2312 #if defined(PLATFORM_UNIX)
2313   /* pause network game while waiting for request to answer */
2314   if (options.network &&
2315       game_status == PLAYING &&
2316       req_state & REQUEST_WAIT_FOR)
2317     SendToServer_PausePlaying();
2318 #endif
2319
2320   old_door_state = GetDoorState();
2321
2322   UnmapAllGadgets();
2323
2324   CloseDoor(DOOR_CLOSE_1);
2325
2326   /* save old door content */
2327   BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2328              DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2329              DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2330
2331   /* clear door drawing field */
2332   ClearRectangle(drawto, DX, DY, DXSIZE, DYSIZE);
2333
2334   /* write text for request */
2335   for(ty=0; ty < MAX_REQUEST_LINES; ty++)
2336   {
2337     char text_line[MAX_REQUEST_LINE_LEN + 1];
2338     int tx, tl, tc;
2339
2340     if (!*text)
2341       break;
2342
2343     for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
2344     {
2345       tc = *(text + tx);
2346       if (!tc || tc == ' ')
2347         break;
2348     }
2349
2350     if (!tl)
2351     { 
2352       text++; 
2353       ty--; 
2354       continue; 
2355     }
2356
2357     strncpy(text_line, text, tl);
2358     text_line[tl] = 0;
2359
2360     DrawTextExt(drawto, DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
2361                 text_line, FS_SMALL, FC_YELLOW);
2362
2363     text += tl + (tc == ' ' ? 1 : 0);
2364   }
2365
2366   if (req_state & REQ_ASK)
2367   {
2368     MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2369     MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2370   }
2371   else if (req_state & REQ_CONFIRM)
2372   {
2373     MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2374   }
2375   else if (req_state & REQ_PLAYER)
2376   {
2377     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2378     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2379     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2380     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2381   }
2382
2383   /* copy request gadgets to door backbuffer */
2384   BlitBitmap(drawto, pix[PIX_DB_DOOR],
2385              DX, DY, DXSIZE, DYSIZE,
2386              DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2387
2388   OpenDoor(DOOR_OPEN_1);
2389
2390 #if 0
2391   ClearEventQueue();
2392 #endif
2393
2394   if (!(req_state & REQUEST_WAIT_FOR))
2395     return(FALSE);
2396
2397   if (game_status != MAINMENU)
2398     InitAnimation();
2399
2400   button_status = MB_RELEASED;
2401
2402   request_gadget_id = -1;
2403
2404   while(result < 0)
2405   {
2406     if (PendingEvent())
2407     {
2408       Event event;
2409
2410       NextEvent(&event);
2411
2412       switch(event.type)
2413       {
2414         case EVENT_BUTTONPRESS:
2415         case EVENT_BUTTONRELEASE:
2416         case EVENT_MOTIONNOTIFY:
2417         {
2418           if (event.type == EVENT_MOTIONNOTIFY)
2419           {
2420             if (!PointerInWindow(window))
2421               continue; /* window and pointer are on different screens */
2422
2423             if (!button_status)
2424               continue;
2425
2426             motion_status = TRUE;
2427             mx = ((MotionEvent *) &event)->x;
2428             my = ((MotionEvent *) &event)->y;
2429           }
2430           else
2431           {
2432             motion_status = FALSE;
2433             mx = ((ButtonEvent *) &event)->x;
2434             my = ((ButtonEvent *) &event)->y;
2435             if (event.type == EVENT_BUTTONPRESS)
2436               button_status = ((ButtonEvent *) &event)->button;
2437             else
2438               button_status = MB_RELEASED;
2439           }
2440
2441           /* this sets 'request_gadget_id' */
2442           HandleGadgets(mx, my, button_status);
2443
2444           switch(request_gadget_id)
2445           {
2446             case TOOL_CTRL_ID_YES:
2447               result = TRUE;
2448               break;
2449             case TOOL_CTRL_ID_NO:
2450               result = FALSE;
2451               break;
2452             case TOOL_CTRL_ID_CONFIRM:
2453               result = TRUE | FALSE;
2454               break;
2455
2456             case TOOL_CTRL_ID_PLAYER_1:
2457               result = 1;
2458               break;
2459             case TOOL_CTRL_ID_PLAYER_2:
2460               result = 2;
2461               break;
2462             case TOOL_CTRL_ID_PLAYER_3:
2463               result = 3;
2464               break;
2465             case TOOL_CTRL_ID_PLAYER_4:
2466               result = 4;
2467               break;
2468
2469             default:
2470               break;
2471           }
2472
2473           break;
2474         }
2475
2476         case EVENT_KEYPRESS:
2477           switch(GetEventKey((KeyEvent *)&event, TRUE))
2478           {
2479             case KSYM_Return:
2480               result = 1;
2481               break;
2482
2483             case KSYM_Escape:
2484               result = 0;
2485               break;
2486
2487             default:
2488               break;
2489           }
2490           if (req_state & REQ_PLAYER)
2491             result = 0;
2492           break;
2493
2494         case EVENT_KEYRELEASE:
2495           ClearPlayerAction();
2496           break;
2497
2498         default:
2499           HandleOtherEvents(&event);
2500           break;
2501       }
2502     }
2503     else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2504     {
2505       int joy = AnyJoystick();
2506
2507       if (joy & JOY_BUTTON_1)
2508         result = 1;
2509       else if (joy & JOY_BUTTON_2)
2510         result = 0;
2511     }
2512
2513     DoAnimation();
2514
2515     /* don't eat all CPU time */
2516     Delay(10);
2517   }
2518
2519   if (game_status != MAINMENU)
2520     StopAnimation();
2521
2522   UnmapToolButtons();
2523
2524   if (!(req_state & REQ_STAY_OPEN))
2525   {
2526     CloseDoor(DOOR_CLOSE_1);
2527
2528     if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2529     {
2530       BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2531                  DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2532                  DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2533       OpenDoor(DOOR_OPEN_1);
2534     }
2535   }
2536
2537   RemapAllGadgets();
2538
2539 #if defined(PLATFORM_UNIX)
2540   /* continue network game after request */
2541   if (options.network &&
2542       game_status == PLAYING &&
2543       req_state & REQUEST_WAIT_FOR)
2544     SendToServer_ContinuePlaying();
2545 #endif
2546
2547   return(result);
2548 }
2549
2550 unsigned int OpenDoor(unsigned int door_state)
2551 {
2552   unsigned int new_door_state;
2553
2554   if (door_state & DOOR_COPY_BACK)
2555   {
2556     BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2557                DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2558                DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2559     door_state &= ~DOOR_COPY_BACK;
2560   }
2561
2562   new_door_state = MoveDoor(door_state);
2563
2564   return(new_door_state);
2565 }
2566
2567 unsigned int CloseDoor(unsigned int door_state)
2568 {
2569   unsigned int new_door_state;
2570
2571   BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2572              DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2573   BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2574              VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2575
2576   new_door_state = MoveDoor(door_state);
2577
2578   return(new_door_state);
2579 }
2580
2581 unsigned int GetDoorState()
2582 {
2583   return MoveDoor(DOOR_GET_STATE);
2584 }
2585
2586 unsigned int SetDoorState(unsigned int door_state)
2587 {
2588   return MoveDoor(door_state | DOOR_SET_STATE);
2589 }
2590
2591 unsigned int MoveDoor(unsigned int door_state)
2592 {
2593   static int door1 = DOOR_OPEN_1;
2594   static int door2 = DOOR_CLOSE_2;
2595   static unsigned long door_delay = 0;
2596   int x, start, stepsize = 2;
2597   unsigned long door_delay_value = stepsize * 5;
2598
2599   if (door_state == DOOR_GET_STATE)
2600     return(door1 | door2);
2601
2602   if (door_state & DOOR_SET_STATE)
2603   {
2604     if (door_state & DOOR_ACTION_1)
2605       door1 = door_state & DOOR_ACTION_1;
2606     if (door_state & DOOR_ACTION_2)
2607       door2 = door_state & DOOR_ACTION_2;
2608
2609     return(door1 | door2);
2610   }
2611
2612   if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2613     door_state &= ~DOOR_OPEN_1;
2614   else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2615     door_state &= ~DOOR_CLOSE_1;
2616   if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2617     door_state &= ~DOOR_OPEN_2;
2618   else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2619     door_state &= ~DOOR_CLOSE_2;
2620
2621   if (setup.quick_doors)
2622   {
2623     stepsize = 20;
2624     door_delay_value = 0;
2625     StopSound(SND_MENU_DOOR_OPENING);
2626     StopSound(SND_MENU_DOOR_CLOSING);
2627   }
2628
2629   if (door_state & DOOR_ACTION)
2630   {
2631     if (!(door_state & DOOR_NO_DELAY))
2632     {
2633       /* opening door sound has priority over simultaneously closing door */
2634       if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2635         PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2636       else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2637         PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2638     }
2639
2640     start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2641
2642     for(x=start; x<=DXSIZE; x+=stepsize)
2643     {
2644       Bitmap *bitmap = pix[PIX_DOOR];
2645       GC gc = bitmap->stored_clip_gc;
2646
2647       WaitUntilDelayReached(&door_delay, door_delay_value);
2648
2649       if (door_state & DOOR_ACTION_1)
2650       {
2651         int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2652         int j = (DXSIZE - i) / 3;
2653
2654         BlitBitmap(pix[PIX_DB_DOOR], drawto,
2655                    DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2656                    DXSIZE,DYSIZE - i/2, DX, DY);
2657
2658         ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2659
2660         SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2661         BlitBitmapMasked(bitmap, drawto,
2662                          DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2663                          DX + DXSIZE - i, DY + j);
2664         BlitBitmapMasked(bitmap, drawto,
2665                          DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2666                          DX + DXSIZE - i, DY + 140 + j);
2667         SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2668         BlitBitmapMasked(bitmap, drawto,
2669                          DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2670                          DX, DY);
2671         BlitBitmapMasked(bitmap, drawto,
2672                          DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2673                          DX, DY + 140 - j);
2674
2675         BlitBitmapMasked(bitmap, drawto,
2676                          DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2677                          DX, DY + 77 - j);
2678         BlitBitmapMasked(bitmap, drawto,
2679                          DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2680                          DX, DY + 203 - j);
2681         SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2682         BlitBitmapMasked(bitmap, drawto,
2683                          DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2684                          DX + DXSIZE - i, DY + 77 + j);
2685         BlitBitmapMasked(bitmap, drawto,
2686                          DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2687                          DX + DXSIZE - i, DY + 203 + j);
2688
2689         redraw_mask |= REDRAW_DOOR_1;
2690       }
2691
2692       if (door_state & DOOR_ACTION_2)
2693       {
2694         int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2695         int j = (VXSIZE - i) / 3;
2696
2697         BlitBitmap(pix[PIX_DB_DOOR], drawto,
2698                    DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2699                    VXSIZE, VYSIZE - i/2, VX, VY);
2700
2701         ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2702
2703         SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2704         BlitBitmapMasked(bitmap, drawto,
2705                          VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2706                          VX + VXSIZE-i, VY+j);
2707         SetClipOrigin(bitmap, gc,
2708                       VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2709         BlitBitmapMasked(bitmap, drawto,
2710                          VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2711                          VX, VY);
2712
2713         BlitBitmapMasked(bitmap, drawto,
2714                          VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2715                          i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2716         SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2717         BlitBitmapMasked(bitmap, drawto,
2718                          VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2719                          i, VYSIZE / 2 - j,
2720                          VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2721
2722         redraw_mask |= REDRAW_DOOR_2;
2723       }
2724
2725       BackToFront();
2726
2727       if (game_status == MAINMENU)
2728         DoAnimation();
2729     }
2730   }
2731
2732   if (setup.quick_doors)
2733   {
2734     StopSound(SND_MENU_DOOR_OPENING);
2735     StopSound(SND_MENU_DOOR_CLOSING);
2736   }
2737
2738   if (door_state & DOOR_ACTION_1)
2739     door1 = door_state & DOOR_ACTION_1;
2740   if (door_state & DOOR_ACTION_2)
2741     door2 = door_state & DOOR_ACTION_2;
2742
2743   return (door1 | door2);
2744 }
2745
2746 void DrawSpecialEditorDoor()
2747 {
2748   /* draw bigger toolbox window */
2749   BlitBitmap(pix[PIX_DOOR], drawto,
2750              DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2751
2752   redraw_mask |= REDRAW_ALL;
2753 }
2754
2755 void UndrawSpecialEditorDoor()
2756 {
2757   /* draw normal tape recorder window */
2758   BlitBitmap(pix[PIX_BACK], drawto,
2759              562, 344, 108, 56, EX - 4, EY - 12);
2760
2761   redraw_mask |= REDRAW_ALL;
2762 }
2763
2764 #ifndef TARGET_SDL
2765 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2766 {
2767   XImage *pixel_image;
2768   unsigned long pixel_value;
2769
2770   pixel_image = XGetImage(display, bitmap->drawable,
2771                           x, y, 1, 1, AllPlanes, ZPixmap);
2772   pixel_value = XGetPixel(pixel_image, 0, 0);
2773
2774   XDestroyImage(pixel_image);
2775
2776   return pixel_value;
2777 }
2778 #endif
2779
2780 /* ---------- new tool button stuff ---------------------------------------- */
2781
2782 /* graphic position values for tool buttons */
2783 #define TOOL_BUTTON_YES_XPOS            2
2784 #define TOOL_BUTTON_YES_YPOS            250
2785 #define TOOL_BUTTON_YES_GFX_YPOS        0
2786 #define TOOL_BUTTON_YES_XSIZE           46
2787 #define TOOL_BUTTON_YES_YSIZE           28
2788 #define TOOL_BUTTON_NO_XPOS             52
2789 #define TOOL_BUTTON_NO_YPOS             TOOL_BUTTON_YES_YPOS
2790 #define TOOL_BUTTON_NO_GFX_YPOS         TOOL_BUTTON_YES_GFX_YPOS
2791 #define TOOL_BUTTON_NO_XSIZE            TOOL_BUTTON_YES_XSIZE
2792 #define TOOL_BUTTON_NO_YSIZE            TOOL_BUTTON_YES_YSIZE
2793 #define TOOL_BUTTON_CONFIRM_XPOS        TOOL_BUTTON_YES_XPOS
2794 #define TOOL_BUTTON_CONFIRM_YPOS        TOOL_BUTTON_YES_YPOS
2795 #define TOOL_BUTTON_CONFIRM_GFX_YPOS    30
2796 #define TOOL_BUTTON_CONFIRM_XSIZE       96
2797 #define TOOL_BUTTON_CONFIRM_YSIZE       TOOL_BUTTON_YES_YSIZE
2798 #define TOOL_BUTTON_PLAYER_XSIZE        30
2799 #define TOOL_BUTTON_PLAYER_YSIZE        30
2800 #define TOOL_BUTTON_PLAYER_GFX_XPOS     5
2801 #define TOOL_BUTTON_PLAYER_GFX_YPOS     185
2802 #define TOOL_BUTTON_PLAYER_XPOS         (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2803 #define TOOL_BUTTON_PLAYER_YPOS         (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2804 #define TOOL_BUTTON_PLAYER1_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2805                                          + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2806 #define TOOL_BUTTON_PLAYER2_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2807                                          + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2808 #define TOOL_BUTTON_PLAYER3_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2809                                          + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2810 #define TOOL_BUTTON_PLAYER4_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2811                                          + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2812 #define TOOL_BUTTON_PLAYER1_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2813                                          + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2814 #define TOOL_BUTTON_PLAYER2_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2815                                          + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2816 #define TOOL_BUTTON_PLAYER3_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2817                                          + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2818 #define TOOL_BUTTON_PLAYER4_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2819                                          + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2820
2821 static struct
2822 {
2823   int xpos, ypos;
2824   int x, y;
2825   int width, height;
2826   int gadget_id;
2827   char *infotext;
2828 } toolbutton_info[NUM_TOOL_BUTTONS] =
2829 {
2830   {
2831     TOOL_BUTTON_YES_XPOS,       TOOL_BUTTON_YES_GFX_YPOS,
2832     TOOL_BUTTON_YES_XPOS,       TOOL_BUTTON_YES_YPOS,
2833     TOOL_BUTTON_YES_XSIZE,      TOOL_BUTTON_YES_YSIZE,
2834     TOOL_CTRL_ID_YES,
2835     "yes"
2836   },
2837   {
2838     TOOL_BUTTON_NO_XPOS,        TOOL_BUTTON_NO_GFX_YPOS,
2839     TOOL_BUTTON_NO_XPOS,        TOOL_BUTTON_NO_YPOS,
2840     TOOL_BUTTON_NO_XSIZE,       TOOL_BUTTON_NO_YSIZE,
2841     TOOL_CTRL_ID_NO,
2842     "no"
2843   },
2844   {
2845     TOOL_BUTTON_CONFIRM_XPOS,   TOOL_BUTTON_CONFIRM_GFX_YPOS,
2846     TOOL_BUTTON_CONFIRM_XPOS,   TOOL_BUTTON_CONFIRM_YPOS,
2847     TOOL_BUTTON_CONFIRM_XSIZE,  TOOL_BUTTON_CONFIRM_YSIZE,
2848     TOOL_CTRL_ID_CONFIRM,
2849     "confirm"
2850   },
2851   {
2852     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2853     TOOL_BUTTON_PLAYER1_XPOS,   TOOL_BUTTON_PLAYER1_YPOS,
2854     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2855     TOOL_CTRL_ID_PLAYER_1,
2856     "player 1"
2857   },
2858   {
2859     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2860     TOOL_BUTTON_PLAYER2_XPOS,   TOOL_BUTTON_PLAYER2_YPOS,
2861     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2862     TOOL_CTRL_ID_PLAYER_2,
2863     "player 2"
2864   },
2865   {
2866     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2867     TOOL_BUTTON_PLAYER3_XPOS,   TOOL_BUTTON_PLAYER3_YPOS,
2868     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2869     TOOL_CTRL_ID_PLAYER_3,
2870     "player 3"
2871   },
2872   {
2873     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2874     TOOL_BUTTON_PLAYER4_XPOS,   TOOL_BUTTON_PLAYER4_YPOS,
2875     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2876     TOOL_CTRL_ID_PLAYER_4,
2877     "player 4"
2878   }
2879 };
2880
2881 void CreateToolButtons()
2882 {
2883   int i;
2884
2885   for (i=0; i<NUM_TOOL_BUTTONS; i++)
2886   {
2887     Bitmap *gd_bitmap = pix[PIX_DOOR];
2888     Bitmap *deco_bitmap = None;
2889     int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2890     struct GadgetInfo *gi;
2891     unsigned long event_mask;
2892     int gd_xoffset, gd_yoffset;
2893     int gd_x1, gd_x2, gd_y;
2894     int id = i;
2895
2896     event_mask = GD_EVENT_RELEASED;
2897
2898     gd_xoffset = toolbutton_info[i].xpos;
2899     gd_yoffset = toolbutton_info[i].ypos;
2900     gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2901     gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2902     gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2903
2904     if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2905     {
2906       getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2907                            &deco_bitmap, &deco_x, &deco_y);
2908       deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2909       deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2910     }
2911
2912     gi = CreateGadget(GDI_CUSTOM_ID, id,
2913                       GDI_INFO_TEXT, toolbutton_info[i].infotext,
2914                       GDI_X, DX + toolbutton_info[i].x,
2915                       GDI_Y, DY + toolbutton_info[i].y,
2916                       GDI_WIDTH, toolbutton_info[i].width,
2917                       GDI_HEIGHT, toolbutton_info[i].height,
2918                       GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2919                       GDI_STATE, GD_BUTTON_UNPRESSED,
2920                       GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2921                       GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2922                       GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2923                       GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2924                       GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2925                       GDI_DECORATION_SHIFTING, 1, 1,
2926                       GDI_EVENT_MASK, event_mask,
2927                       GDI_CALLBACK_ACTION, HandleToolButtons,
2928                       GDI_END);
2929
2930     if (gi == NULL)
2931       Error(ERR_EXIT, "cannot create gadget");
2932
2933     tool_gadget[id] = gi;
2934   }
2935 }
2936
2937 static void UnmapToolButtons()
2938 {
2939   int i;
2940
2941   for (i=0; i<NUM_TOOL_BUTTONS; i++)
2942     UnmapGadget(tool_gadget[i]);
2943 }
2944
2945 static void HandleToolButtons(struct GadgetInfo *gi)
2946 {
2947   request_gadget_id = gi->custom_id;
2948 }
2949
2950 int get_next_element(int element)
2951 {
2952   switch(element)
2953   {
2954     case EL_QUICKSAND_FILLING:          return EL_QUICKSAND_FULL;
2955     case EL_QUICKSAND_EMPTYING:         return EL_QUICKSAND_EMPTY;
2956     case EL_MAGIC_WALL_FILLING:         return EL_MAGIC_WALL_FULL;
2957     case EL_MAGIC_WALL_EMPTYING:        return EL_MAGIC_WALL_ACTIVE;
2958     case EL_BD_MAGIC_WALL_FILLING:      return EL_BD_MAGIC_WALL_FULL;
2959     case EL_BD_MAGIC_WALL_EMPTYING:     return EL_BD_MAGIC_WALL_ACTIVE;
2960     case EL_AMOEBA_DRIPPING:            return EL_AMOEBA_WET;
2961
2962     default:                            return element;
2963   }
2964 }
2965
2966 int el2gfx_OLD(int element)
2967 {
2968   switch(element)
2969   {
2970     case EL_EMPTY:                      return -1;
2971     case EL_SAND:                       return GFX_ERDREICH;
2972     case EL_WALL:                       return GFX_MAUERWERK;
2973     case EL_WALL_CRUMBLED:              return GFX_FELSBODEN;
2974     case EL_ROCK:                       return GFX_FELSBROCKEN;
2975     case EL_EMERALD:                    return GFX_EDELSTEIN;
2976     case EL_EXIT_CLOSED:                return GFX_AUSGANG_ZU;
2977     case EL_EXIT_OPENING:               return GFX_AUSGANG_ACT;
2978     case EL_EXIT_OPEN:                  return GFX_AUSGANG_AUF;
2979     case EL_SP_EXIT_OPEN:               return GFX_SP_EXIT;
2980     case EL_PLAYER1:                    return GFX_SPIELER1;
2981     case EL_PLAYER2:                    return GFX_SPIELER2;
2982     case EL_PLAYER3:                    return GFX_SPIELER3;
2983     case EL_PLAYER4:                    return GFX_SPIELER4;
2984     case EL_BUG:                        return GFX_KAEFER;
2985     case EL_BUG_RIGHT:                  return GFX_KAEFER_RIGHT;
2986     case EL_BUG_UP:                     return GFX_KAEFER_UP;
2987     case EL_BUG_LEFT:                   return GFX_KAEFER_LEFT;
2988     case EL_BUG_DOWN:                   return GFX_KAEFER_DOWN;
2989     case EL_SPACESHIP:                  return GFX_FLIEGER;
2990     case EL_SPACESHIP_RIGHT:            return GFX_FLIEGER_RIGHT;
2991     case EL_SPACESHIP_UP:               return GFX_FLIEGER_UP;
2992     case EL_SPACESHIP_LEFT:             return GFX_FLIEGER_LEFT;
2993     case EL_SPACESHIP_DOWN:             return GFX_FLIEGER_DOWN;
2994     case EL_BD_BUTTERFLY:               return GFX_BUTTERFLY;
2995     case EL_BD_BUTTERFLY_RIGHT:         return GFX_BUTTERFLY_RIGHT;
2996     case EL_BD_BUTTERFLY_UP:            return GFX_BUTTERFLY_UP;
2997     case EL_BD_BUTTERFLY_LEFT:          return GFX_BUTTERFLY_LEFT;
2998     case EL_BD_BUTTERFLY_DOWN:          return GFX_BUTTERFLY_DOWN;
2999     case EL_BD_FIREFLY:                 return GFX_FIREFLY;
3000     case EL_BD_FIREFLY_RIGHT:           return GFX_FIREFLY_RIGHT;
3001     case EL_BD_FIREFLY_UP:              return GFX_FIREFLY_UP;
3002     case EL_BD_FIREFLY_LEFT:            return GFX_FIREFLY_LEFT;
3003     case EL_BD_FIREFLY_DOWN:            return GFX_FIREFLY_DOWN;
3004     case EL_YAMYAM:                     return GFX_MAMPFER;
3005     case EL_ROBOT:                      return GFX_ROBOT;
3006     case EL_STEELWALL:                  return GFX_BETON;
3007     case EL_DIAMOND:                    return GFX_DIAMANT;
3008     case EL_QUICKSAND_EMPTY:            return GFX_MORAST_LEER;
3009     case EL_QUICKSAND_FULL:             return GFX_MORAST_VOLL;
3010     case EL_QUICKSAND_EMPTYING:         return GFX_MORAST_LEER;
3011     case EL_AMOEBA_DROP:                return GFX_TROPFEN;
3012     case EL_BOMB:                       return GFX_BOMBE;
3013     case EL_MAGIC_WALL:                 return GFX_MAGIC_WALL_OFF;
3014     case EL_MAGIC_WALL_ACTIVE:          return GFX_MAGIC_WALL_EMPTY;
3015     case EL_MAGIC_WALL_EMPTYING:        return GFX_MAGIC_WALL_EMPTY;
3016     case EL_MAGIC_WALL_FULL:            return GFX_MAGIC_WALL_FULL;
3017     case EL_MAGIC_WALL_DEAD:            return GFX_MAGIC_WALL_DEAD;
3018     case EL_ACID:                       return GFX_SALZSAEURE;
3019     case EL_AMOEBA_DEAD:                return GFX_AMOEBE_TOT;
3020     case EL_AMOEBA_WET:                 return GFX_AMOEBE_NASS;
3021     case EL_AMOEBA_DRY:                 return GFX_AMOEBE_NORM;
3022     case EL_AMOEBA_FULL:                return GFX_AMOEBE_VOLL;
3023     case EL_BD_AMOEBA:                  return GFX_AMOEBE_BD;
3024     case EL_AMOEBA_TO_DIAMOND:          return GFX_AMOEBA2DIAM;
3025     case EL_AMOEBA_DRIPPING:            return GFX_AMOEBE_NASS;
3026     case EL_NUT:                        return GFX_KOKOSNUSS;
3027     case EL_GAMEOFLIFE:                 return GFX_LIFE;
3028     case EL_BIOMAZE:                    return GFX_LIFE_ASYNC;
3029     case EL_DYNAMITE_ACTIVE:            return GFX_DYNAMIT;
3030     case EL_STONEBLOCK:                 return GFX_BADEWANNE;
3031     case EL_ACIDPOOL_TOPLEFT:           return GFX_BADEWANNE1;
3032     case EL_ACIDPOOL_TOPRIGHT:          return GFX_BADEWANNE2;
3033     case EL_ACIDPOOL_BOTTOMLEFT:        return GFX_BADEWANNE3;
3034     case EL_ACIDPOOL_BOTTOM:            return GFX_BADEWANNE4;
3035     case EL_ACIDPOOL_BOTTOMRIGHT:       return GFX_BADEWANNE5;
3036     case EL_ROBOT_WHEEL:                return GFX_ABLENK_AUS;
3037     case EL_ROBOT_WHEEL_ACTIVE:         return GFX_ABLENK_EIN;
3038     case EL_KEY1:                       return GFX_SCHLUESSEL1;
3039     case EL_KEY2:                       return GFX_SCHLUESSEL2;
3040     case EL_KEY3:                       return GFX_SCHLUESSEL3;
3041     case EL_KEY4:                       return GFX_SCHLUESSEL4;
3042     case EL_GATE1:                      return GFX_PFORTE1;
3043     case EL_GATE2:                      return GFX_PFORTE2;
3044     case EL_GATE3:                      return GFX_PFORTE3;
3045     case EL_GATE4:                      return GFX_PFORTE4;
3046     case EL_GATE1_GRAY:                 return GFX_PFORTE1X;
3047     case EL_GATE2_GRAY:                 return GFX_PFORTE2X;
3048     case EL_GATE3_GRAY:                 return GFX_PFORTE3X;
3049     case EL_GATE4_GRAY:                 return GFX_PFORTE4X;
3050     case EL_DYNAMITE:                   return GFX_DYNAMIT_AUS;
3051     case EL_PACMAN:                     return GFX_PACMAN;
3052     case EL_PACMAN_RIGHT:               return GFX_PACMAN_RIGHT;
3053     case EL_PACMAN_UP:                  return GFX_PACMAN_UP;
3054     case EL_PACMAN_LEFT:                return GFX_PACMAN_LEFT;
3055     case EL_PACMAN_DOWN:                return GFX_PACMAN_DOWN;
3056     case EL_INVISIBLE_WALL:             return GFX_UNSICHTBAR;
3057     case EL_INVISIBLE_WALL_ACTIVE:      return GFX_UNSICHTBAR_ON;
3058     case EL_WALL_EMERALD:               return GFX_ERZ_EDEL;
3059     case EL_WALL_DIAMOND:               return GFX_ERZ_DIAM;
3060     case EL_LAMP:                       return GFX_BIRNE_AUS;
3061     case EL_LAMP_ACTIVE:                return GFX_BIRNE_EIN;
3062     case EL_TIME_ORB_FULL:              return GFX_ZEIT_VOLL;
3063     case EL_TIME_ORB_EMPTY:             return GFX_ZEIT_LEER;
3064     case EL_WALL_GROWING:               return GFX_MAUER_LEBT;
3065     case EL_WALL_GROWING_X:             return GFX_MAUER_X;
3066     case EL_WALL_GROWING_Y:             return GFX_MAUER_Y;
3067     case EL_WALL_GROWING_XY:            return GFX_MAUER_XY;
3068     case EL_BD_DIAMOND:                 return GFX_EDELSTEIN_BD;
3069     case EL_EMERALD_YELLOW:             return GFX_EDELSTEIN_GELB;
3070     case EL_EMERALD_RED:                return GFX_EDELSTEIN_ROT;
3071     case EL_EMERALD_PURPLE:             return GFX_EDELSTEIN_LILA;
3072     case EL_WALL_BD_DIAMOND:            return GFX_ERZ_EDEL_BD;
3073     case EL_WALL_EMERALD_YELLOW:        return GFX_ERZ_EDEL_GELB;
3074     case EL_WALL_EMERALD_RED:           return GFX_ERZ_EDEL_ROT;
3075     case EL_WALL_EMERALD_PURPLE:        return GFX_ERZ_EDEL_LILA;
3076     case EL_DARK_YAMYAM:                return GFX_MAMPFER2;
3077     case EL_BD_MAGIC_WALL:              return GFX_MAGIC_WALL_BD_OFF;
3078     case EL_BD_MAGIC_WALL_ACTIVE:       return GFX_MAGIC_WALL_BD_EMPTY;
3079     case EL_BD_MAGIC_WALL_EMPTYING:     return GFX_MAGIC_WALL_BD_EMPTY;
3080     case EL_BD_MAGIC_WALL_FULL:         return GFX_MAGIC_WALL_BD_FULL;
3081     case EL_BD_MAGIC_WALL_DEAD:         return GFX_MAGIC_WALL_BD_DEAD;
3082     case EL_DYNABOMB_PLAYER1_ACTIVE:    return GFX_DYNABOMB;
3083     case EL_DYNABOMB_PLAYER2_ACTIVE:    return GFX_DYNABOMB;
3084     case EL_DYNABOMB_PLAYER3_ACTIVE:    return GFX_DYNABOMB;
3085     case EL_DYNABOMB_PLAYER4_ACTIVE:    return GFX_DYNABOMB;
3086     case EL_DYNABOMB_NR:                return GFX_DYNABOMB_NR;
3087     case EL_DYNABOMB_SZ:                return GFX_DYNABOMB_SZ;
3088     case EL_DYNABOMB_XL:                return GFX_DYNABOMB_XL;
3089     case EL_SOKOBAN_OBJECT:             return GFX_SOKOBAN_OBJEKT;
3090     case EL_SOKOBAN_FIELD_EMPTY:        return GFX_SOKOBAN_FELD_LEER;
3091     case EL_SOKOBAN_FIELD_FULL:         return GFX_SOKOBAN_FELD_VOLL;
3092     case EL_MOLE:                       return GFX_MOLE;
3093     case EL_PENGUIN:                    return GFX_PINGUIN;
3094     case EL_PIG:                        return GFX_SCHWEIN;
3095     case EL_DRAGON:                     return GFX_DRACHE;
3096     case EL_SATELLITE:                  return GFX_SONDE;
3097     case EL_ARROW_BLUE_LEFT:            return GFX_PFEIL_LEFT;
3098     case EL_ARROW_BLUE_RIGHT:           return GFX_PFEIL_RIGHT;
3099     case EL_ARROW_BLUE_UP:              return GFX_PFEIL_UP;
3100     case EL_ARROW_BLUE_DOWN:            return GFX_PFEIL_DOWN;
3101     case EL_SPEED_PILL:                 return GFX_SPEED_PILL;
3102     case EL_SP_TERMINAL_ACTIVE:         return GFX_SP_TERMINAL;
3103     case EL_SP_BUGGY_BASE_ACTIVE:       return GFX_SP_BUG_ACTIVE;
3104     case EL_SP_ZONK:                    return GFX_SP_ZONK;
3105       /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
3106     case EL_INVISIBLE_STEELWALL:        return GFX_INVISIBLE_STEEL;
3107     case EL_INVISIBLE_STEELWALL_ACTIVE: return GFX_INVISIBLE_STEEL_ON;
3108     case EL_BLACK_ORB:                  return GFX_BLACK_ORB;
3109     case EL_EM_GATE1:                   return GFX_EM_GATE_1;
3110     case EL_EM_GATE2:                   return GFX_EM_GATE_2;
3111     case EL_EM_GATE3:                   return GFX_EM_GATE_3;
3112     case EL_EM_GATE4:                   return GFX_EM_GATE_4;
3113     case EL_EM_GATE1_GRAY:              return GFX_EM_GATE_1X;
3114     case EL_EM_GATE2_GRAY:              return GFX_EM_GATE_2X;
3115     case EL_EM_GATE3_GRAY:              return GFX_EM_GATE_3X;
3116     case EL_EM_GATE4_GRAY:              return GFX_EM_GATE_4X;
3117     case EL_EM_KEY1_FILE:               return GFX_EM_KEY_1;
3118     case EL_EM_KEY2_FILE:               return GFX_EM_KEY_2;
3119     case EL_EM_KEY3_FILE:               return GFX_EM_KEY_3;
3120     case EL_EM_KEY4_FILE:               return GFX_EM_KEY_4;
3121     case EL_EM_KEY1:                    return GFX_EM_KEY_1;
3122     case EL_EM_KEY2:                    return GFX_EM_KEY_2;
3123     case EL_EM_KEY3:                    return GFX_EM_KEY_3;
3124     case EL_EM_KEY4:                    return GFX_EM_KEY_4;
3125     case EL_PEARL:                      return GFX_PEARL;
3126     case EL_CRYSTAL:                    return GFX_CRYSTAL;
3127     case EL_WALL_PEARL:                 return GFX_WALL_PEARL;
3128     case EL_WALL_CRYSTAL:               return GFX_WALL_CRYSTAL;
3129     case EL_DOOR_WHITE:                 return GFX_DOOR_WHITE;
3130     case EL_DOOR_WHITE_GRAY:            return GFX_DOOR_WHITE_GRAY;
3131     case EL_KEY_WHITE:                  return GFX_KEY_WHITE;
3132     case EL_SHIELD_NORMAL:              return GFX_SHIELD_PASSIVE;
3133     case EL_SHIELD_DEADLY:              return GFX_SHIELD_ACTIVE;
3134     case EL_EXTRA_TIME:                 return GFX_EXTRA_TIME;
3135     case EL_SWITCHGATE_OPEN:            return GFX_SWITCHGATE_OPEN;
3136     case EL_SWITCHGATE_CLOSED:          return GFX_SWITCHGATE_CLOSED;
3137     case EL_SWITCHGATE_SWITCH_UP:       return GFX_SWITCHGATE_SWITCH_1;
3138     case EL_SWITCHGATE_SWITCH_DOWN:     return GFX_SWITCHGATE_SWITCH_2;
3139     case EL_CONVEYOR_BELT1_LEFT:        return GFX_BELT1_LEFT;
3140     case EL_CONVEYOR_BELT1_MIDDLE:      return GFX_BELT1_MIDDLE;
3141     case EL_CONVEYOR_BELT1_RIGHT:       return GFX_BELT1_RIGHT;
3142     case EL_CONVEYOR_BELT1_LEFT_ACTIVE: return GFX_BELT1_LEFT;
3143     case EL_CONVEYOR_BELT1_MIDDLE_ACTIVE:return GFX_BELT1_MIDDLE;
3144     case EL_CONVEYOR_BELT1_RIGHT_ACTIVE:return GFX_BELT1_RIGHT;
3145     case EL_CONVEYOR_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
3146     case EL_CONVEYOR_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
3147     case EL_CONVEYOR_BELT1_SWITCH_RIGHT:return GFX_BELT1_SWITCH_RIGHT;
3148     case EL_CONVEYOR_BELT2_LEFT:        return GFX_BELT2_LEFT;
3149     case EL_CONVEYOR_BELT2_MIDDLE:      return GFX_BELT2_MIDDLE;
3150     case EL_CONVEYOR_BELT2_RIGHT:       return GFX_BELT2_RIGHT;
3151     case EL_CONVEYOR_BELT2_LEFT_ACTIVE: return GFX_BELT2_LEFT;
3152     case EL_CONVEYOR_BELT2_MIDDLE_ACTIVE:return GFX_BELT2_MIDDLE;
3153     case EL_CONVEYOR_BELT2_RIGHT_ACTIVE:return GFX_BELT2_RIGHT;
3154     case EL_CONVEYOR_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
3155     case EL_CONVEYOR_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
3156     case EL_CONVEYOR_BELT2_SWITCH_RIGHT:return GFX_BELT2_SWITCH_RIGHT;
3157     case EL_CONVEYOR_BELT3_LEFT:        return GFX_BELT3_LEFT;
3158     case EL_CONVEYOR_BELT3_MIDDLE:      return GFX_BELT3_MIDDLE;
3159     case EL_CONVEYOR_BELT3_RIGHT:       return GFX_BELT3_RIGHT;
3160     case EL_CONVEYOR_BELT3_LEFT_ACTIVE: return GFX_BELT3_LEFT;
3161     case EL_CONVEYOR_BELT3_MIDDLE_ACTIVE:return GFX_BELT3_MIDDLE;
3162     case EL_CONVEYOR_BELT3_RIGHT_ACTIVE:return GFX_BELT3_RIGHT;
3163     case EL_CONVEYOR_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
3164     case EL_CONVEYOR_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
3165     case EL_CONVEYOR_BELT3_SWITCH_RIGHT:return GFX_BELT3_SWITCH_RIGHT;
3166     case EL_CONVEYOR_BELT4_LEFT:        return GFX_BELT4_LEFT;
3167     case EL_CONVEYOR_BELT4_MIDDLE:      return GFX_BELT4_MIDDLE;
3168     case EL_CONVEYOR_BELT4_RIGHT:       return GFX_BELT4_RIGHT;
3169     case EL_CONVEYOR_BELT4_LEFT_ACTIVE: return GFX_BELT4_LEFT;
3170     case EL_CONVEYOR_BELT4_MIDDLE_ACTIVE:return GFX_BELT4_MIDDLE;
3171     case EL_CONVEYOR_BELT4_RIGHT_ACTIVE:return GFX_BELT4_RIGHT;
3172     case EL_CONVEYOR_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
3173     case EL_CONVEYOR_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
3174     case EL_CONVEYOR_BELT4_SWITCH_RIGHT:return GFX_BELT4_SWITCH_RIGHT;
3175     case EL_LANDMINE:                   return GFX_LANDMINE;
3176     case EL_ENVELOPE:                   return GFX_ENVELOPE;
3177     case EL_LIGHT_SWITCH:               return GFX_LIGHT_SWITCH_OFF;
3178     case EL_LIGHT_SWITCH_ACTIVE:        return GFX_LIGHT_SWITCH_ON;
3179     case EL_SIGN_EXCLAMATION:           return GFX_SIGN_EXCLAMATION;
3180     case EL_SIGN_RADIOACTIVITY:         return GFX_SIGN_RADIOACTIVITY;
3181     case EL_SIGN_STOP:                  return GFX_SIGN_STOP;
3182     case EL_SIGN_WHEELCHAIR:            return GFX_SIGN_WHEELCHAIR;
3183     case EL_SIGN_PARKING:               return GFX_SIGN_PARKING;
3184     case EL_SIGN_ONEWAY:                return GFX_SIGN_ONEWAY;
3185     case EL_SIGN_HEART:                 return GFX_SIGN_HEART;
3186     case EL_SIGN_TRIANGLE:              return GFX_SIGN_TRIANGLE;
3187     case EL_SIGN_ROUND:                 return GFX_SIGN_ROUND;
3188     case EL_SIGN_EXIT:                  return GFX_SIGN_EXIT;
3189     case EL_SIGN_YINYANG:               return GFX_SIGN_YINYANG;
3190     case EL_SIGN_OTHER:                 return GFX_SIGN_OTHER;
3191     case EL_MOLE_LEFT:                  return GFX_MOLE_LEFT;
3192     case EL_MOLE_RIGHT:                 return GFX_MOLE_RIGHT;
3193     case EL_MOLE_UP:                    return GFX_MOLE_UP;
3194     case EL_MOLE_DOWN:                  return GFX_MOLE_DOWN;
3195     case EL_STEELWALL_SLANTED:          return GFX_STEEL_SLANTED;
3196     case EL_INVISIBLE_SAND:             return GFX_SAND_INVISIBLE;
3197     case EL_INVISIBLE_SAND_ACTIVE:      return GFX_SAND_INVISIBLE_ON;
3198     case EL_DX_UNKNOWN_15:              return GFX_DX_UNKNOWN_15;
3199     case EL_DX_UNKNOWN_42:              return GFX_DX_UNKNOWN_42;
3200     case EL_TIMEGATE_OPEN:              return GFX_TIMEGATE_OPEN;
3201     case EL_TIMEGATE_CLOSED:            return GFX_TIMEGATE_CLOSED;
3202     case EL_TIMEGATE_SWITCH_ACTIVE:     return GFX_TIMEGATE_SWITCH;
3203     case EL_TIMEGATE_SWITCH:            return GFX_TIMEGATE_SWITCH;
3204     case EL_BALLOON:                    return GFX_BALLOON;
3205     case EL_BALLOON_SEND_LEFT:          return GFX_BALLOON_SEND_LEFT;
3206     case EL_BALLOON_SEND_RIGHT:         return GFX_BALLOON_SEND_RIGHT;
3207     case EL_BALLOON_SEND_UP:            return GFX_BALLOON_SEND_UP;
3208     case EL_BALLOON_SEND_DOWN:          return GFX_BALLOON_SEND_DOWN;
3209     case EL_BALLOON_SEND_ANY_DIRECTION: return GFX_BALLOON_SEND_ANY;
3210     case EL_EMC_STEELWALL1:             return GFX_EMC_STEEL_WALL_1;
3211     case EL_EMC_STEELWALL2:             return GFX_EMC_STEEL_WALL_2;
3212     case EL_EMC_STEELWALL3:             return GFX_EMC_STEEL_WALL_3;
3213     case EL_EMC_STEELWALL4:             return GFX_EMC_STEEL_WALL_4;
3214     case EL_EMC_WALL_PILLAR_UPPER:      return GFX_EMC_WALL_1;
3215     case EL_EMC_WALL_PILLAR_MIDDLE:     return GFX_EMC_WALL_2;
3216     case EL_EMC_WALL_PILLAR_LOWER:      return GFX_EMC_WALL_3;
3217     case EL_EMC_WALL4:                  return GFX_EMC_WALL_4;
3218     case EL_EMC_WALL5:                  return GFX_EMC_WALL_5;
3219     case EL_EMC_WALL6:                  return GFX_EMC_WALL_6;
3220     case EL_EMC_WALL7:                  return GFX_EMC_WALL_7;
3221     case EL_EMC_WALL8:                  return GFX_EMC_WALL_8;
3222     case EL_TUBE_ALL:                   return GFX_TUBE_CROSS;
3223     case EL_TUBE_VERTICAL:              return GFX_TUBE_VERTICAL;
3224     case EL_TUBE_HORIZONTAL:            return GFX_TUBE_HORIZONTAL;
3225     case EL_TUBE_VERTICAL_LEFT:         return GFX_TUBE_VERT_LEFT;
3226     case EL_TUBE_VERTICAL_RIGHT:        return GFX_TUBE_VERT_RIGHT;
3227     case EL_TUBE_HORIZONTAL_UP:         return GFX_TUBE_HORIZ_UP;
3228     case EL_TUBE_HORIZONTAL_DOWN:       return GFX_TUBE_HORIZ_DOWN;
3229     case EL_TUBE_LEFT_UP:               return GFX_TUBE_LEFT_UP;
3230     case EL_TUBE_LEFT_DOWN:             return GFX_TUBE_LEFT_DOWN;
3231     case EL_TUBE_RIGHT_UP:              return GFX_TUBE_RIGHT_UP;
3232     case EL_TUBE_RIGHT_DOWN:            return GFX_TUBE_RIGHT_DOWN;
3233     case EL_SPRING:                     return GFX_SPRING;
3234     case EL_SPRING_MOVING:              return GFX_SPRING;
3235     case EL_TRAP:                       return GFX_TRAP_INACTIVE;
3236     case EL_TRAP_ACTIVE:                return GFX_TRAP_ACTIVE;
3237     case EL_BD_WALL:                    return GFX_BD_WALL;
3238     case EL_BD_ROCK:                    return GFX_BD_ROCK;
3239     case EL_DX_SUPABOMB:                return GFX_DX_SUPABOMB;
3240     case EL_SP_MURPHY_CLONE:            return GFX_SP_MURPHY_CLONE;
3241
3242     default:
3243     {
3244       if (IS_CHAR(element))
3245         return GFX_CHAR_START + (element - EL_CHAR_START);
3246       else if (element >= EL_SP_START && element <= EL_SP_END)
3247       {
3248         int nr_element = element - EL_SP_START;
3249         int gfx_per_line = 8;
3250         int nr_graphic =
3251           (nr_element / gfx_per_line) * SP_PER_LINE +
3252           (nr_element % gfx_per_line);
3253
3254         return GFX_START_ROCKSSP + nr_graphic;
3255       }
3256       else
3257         return -1;
3258     }
3259   }
3260 }
3261
3262 int el2gfx(int element)
3263 {
3264 #if 1
3265   int graphic_OLD = el2gfx_OLD(element);
3266
3267   return graphic_OLD;
3268 #else
3269
3270   int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
3271
3272 #if DEBUG
3273   int graphic_OLD = el2gfx_OLD(element);
3274
3275   if (element >= MAX_ELEMENTS)
3276   {
3277     Error(ERR_WARN, "el2gfx: element == %d >= MAX_ELEMENTS", element);
3278   }
3279
3280   if (graphic_NEW != graphic_OLD)
3281   {
3282     Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
3283           graphic_NEW, graphic_OLD);
3284   }
3285 #endif
3286
3287   return graphic_NEW;
3288 #endif
3289 }
3290
3291 int el2img(int element)
3292 {
3293 #if 1
3294   int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
3295
3296   return graphic_NEW;
3297 #else
3298
3299   switch(element)
3300   {
3301     case EL_BD_BUTTERFLY:       return IMG_BD_BUTTERFLY;
3302     case EL_BD_FIREFLY:         return IMG_BD_FIREFLY;
3303     case EL_SP_ELECTRON:        return IMG_SP_ELECTRON;
3304
3305     default:
3306       break;
3307   }
3308
3309   return IMG_EMPTY;
3310 #endif
3311 }
3312
3313 int el_dir2img(int element, int direction)
3314 {
3315   return el_dir_act2img(element, direction, GFX_ACTION_DEFAULT);
3316 }
3317
3318 int el_dir_act2img(int element, int direction, int action)
3319 {
3320   action = graphics_action_mapping[action];
3321   direction = MV_DIR_BIT(direction);
3322
3323   return element_info[element].direction_graphic[action][direction];
3324 }