rnd-20020930-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 static 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;
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_PINGPONG)             /* use border frames once */
721   {
722     int max_anim_frames = 2 * num_frames - 2;
723
724     frame = (sync_frame % (delay * max_anim_frames)) / delay;
725     frame = (frame < num_frames ? frame : max_anim_frames - frame);
726   }
727   else if (mode & ANIM_PINGPONG2)       /* use border frames twice */
728   {
729     int max_anim_frames = 2 * num_frames;
730
731     frame = (sync_frame % (delay * max_anim_frames)) / delay;
732     frame = (frame < num_frames ? frame : max_anim_frames - frame - 1);
733   }
734   else  /* mode == ANIM_NORMAL || mode == ANIM_REVERSE */
735     frame = (sync_frame % (delay * num_frames)) / delay;
736
737   if (mode & ANIM_REVERSE)              /* use reverse animation direction */
738     frame = num_frames - frame - 1;
739
740   return frame;
741 }
742
743 void DrawGraphicAnimationExt(int x, int y, int graphic,
744                              int frames, int delay, int mode, int mask_mode)
745 {
746   int phase = getGraphicAnimationPhase(frames, delay, mode);
747
748   if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
749   {
750     if (mask_mode == USE_MASKING)
751       DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
752     else
753       DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
754   }
755 }
756
757 void DrawNewGraphicAnimationExt(int x, int y, int graphic, int mask_mode)
758 {
759   int delay = new_graphic_info[graphic].anim_delay;
760
761   if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
762   {
763     int frame = getNewGraphicAnimationFrame(graphic, -1);
764
765     if (mask_mode == USE_MASKING)
766       DrawNewGraphicThruMask(SCREENX(x), SCREENY(y), graphic, frame);
767     else
768       DrawNewGraphic(SCREENX(x), SCREENY(y), graphic, frame);
769   }
770 }
771
772 void DrawGraphicAnimation(int x, int y, int graphic,
773                           int frames, int delay, int mode)
774 {
775   DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
776 }
777
778 void DrawNewGraphicAnimation(int x, int y, int graphic)
779 {
780   DrawNewGraphicAnimationExt(x, y, graphic, NO_MASKING);
781 }
782
783 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
784                                   int frames, int delay, int mode)
785 {
786   DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
787 }
788
789 static void DrawGraphicAnimationShiftedThruMask(int sx, int sy,
790                                                 int sxx, int syy,
791                                                 int graphic,
792                                                 int frames, int delay,
793                                                 int mode)
794 {
795   int phase = getGraphicAnimationPhase(frames, delay, mode);
796
797   DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic + phase, NO_CUTTING);
798 }
799
800 void getGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
801 {
802   if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
803   {
804     *bitmap = graphic_info[graphic].bitmap;
805     *x = graphic_info[graphic].src_x;
806     *y = graphic_info[graphic].src_y;
807   }
808   else if (graphic >= GFX_START_ROCKSELEMENTS &&
809            graphic <= GFX_END_ROCKSELEMENTS)
810   {
811     graphic -= GFX_START_ROCKSELEMENTS;
812     *bitmap = pix[PIX_ELEMENTS];
813     *x = (graphic % GFX_PER_LINE) * TILEX;
814     *y = (graphic / GFX_PER_LINE) * TILEY;
815   }
816   else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
817   {
818     graphic -= GFX_START_ROCKSHEROES;
819     *bitmap = pix[PIX_HEROES];
820     *x = (graphic % HEROES_PER_LINE) * TILEX;
821     *y = (graphic / HEROES_PER_LINE) * TILEY;
822   }
823   else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
824   {
825     graphic -= GFX_START_ROCKSSP;
826     *bitmap = pix[PIX_SP];
827     *x = (graphic % SP_PER_LINE) * TILEX;
828     *y = (graphic / SP_PER_LINE) * TILEY;
829   }
830   else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
831   {
832     graphic -= GFX_START_ROCKSDC;
833     *bitmap = pix[PIX_DC];
834     *x = (graphic % DC_PER_LINE) * TILEX;
835     *y = (graphic / DC_PER_LINE) * TILEY;
836   }
837   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
838   {
839     graphic -= GFX_START_ROCKSMORE;
840     *bitmap = pix[PIX_MORE];
841     *x = (graphic % MORE_PER_LINE) * TILEX;
842     *y = (graphic / MORE_PER_LINE) * TILEY;
843   }
844   else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
845   {
846     graphic -= GFX_START_ROCKSFONT;
847     *bitmap = pix[PIX_FONT_EM];
848     *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
849     *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
850   }
851   else
852   {
853     *bitmap = pix[PIX_SP];
854     *x = 0;
855     *y = 0;
856   }
857 }
858
859 void DrawGraphic(int x, int y, int graphic)
860 {
861 #if DEBUG
862   if (!IN_SCR_FIELD(x, y))
863   {
864     printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
865     printf("DrawGraphic(): This should never happen!\n");
866     return;
867   }
868 #endif
869
870   DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic);
871   MarkTileDirty(x, y);
872 }
873
874 void DrawNewGraphic(int x, int y, int graphic, int frame)
875 {
876 #if DEBUG
877   if (!IN_SCR_FIELD(x, y))
878   {
879     printf("DrawNewGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
880     printf("DrawNewGraphic(): This should never happen!\n");
881     return;
882   }
883 #endif
884
885   DrawNewGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
886                     graphic, frame);
887   MarkTileDirty(x, y);
888 }
889
890 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
891 {
892   Bitmap *src_bitmap;
893   int src_x, src_y;
894
895   getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
896   BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
897 }
898
899 void DrawNewGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
900                        int frame)
901 {
902   Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
903   int src_x = new_graphic_info[graphic].src_x;
904   int src_y = new_graphic_info[graphic].src_y;
905
906   if (new_graphic_info[graphic].anim_vertical)
907     src_y += frame * TILEY;
908   else
909     src_x += frame * TILEX;
910
911   BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
912 }
913
914 void DrawGraphicThruMask(int x, int y, int graphic)
915 {
916 #if DEBUG
917   if (!IN_SCR_FIELD(x, y))
918   {
919     printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
920     printf("DrawGraphicThruMask(): This should never happen!\n");
921     return;
922   }
923 #endif
924
925   DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic);
926   MarkTileDirty(x, y);
927 }
928
929 void DrawNewGraphicThruMask(int x, int y, int graphic, int frame)
930 {
931 #if DEBUG
932   if (!IN_SCR_FIELD(x, y))
933   {
934     printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
935     printf("DrawGraphicThruMask(): This should never happen!\n");
936     return;
937   }
938 #endif
939
940   DrawNewGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY,
941                             graphic, frame);
942   MarkTileDirty(x, y);
943 }
944
945 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic)
946 {
947   int tile = graphic;
948   int src_x, src_y;
949   Bitmap *src_bitmap;
950   GC drawing_gc;
951
952   if (graphic == GFX_LEERRAUM)
953     return;
954
955   getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
956   drawing_gc = src_bitmap->stored_clip_gc;
957
958   if (tile_clipmask[tile] != None)
959   {
960     SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
961     SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
962     BlitBitmapMasked(src_bitmap, d,
963                      src_x, src_y, TILEX, TILEY, dest_x, dest_y);
964   }
965   else
966   {
967 #if DEBUG
968 #ifndef TARGET_SDL
969     printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
970 #endif
971 #endif
972
973     SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
974     BlitBitmapMasked(src_bitmap, d,
975                      src_x, src_y, TILEX, TILEY, dest_x, dest_y);
976   }
977 }
978
979 void DrawNewGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y,
980                                int graphic, int frame)
981 {
982   Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
983   GC drawing_gc = src_bitmap->stored_clip_gc;
984   int src_x = new_graphic_info[graphic].src_x;
985   int src_y = new_graphic_info[graphic].src_y;
986
987   if (new_graphic_info[graphic].anim_vertical)
988     src_y += frame * TILEY;
989   else
990     src_x += frame * TILEX;
991
992   SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
993   BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
994 }
995
996 void DrawMiniGraphic(int x, int y, int graphic)
997 {
998   DrawMiniGraphicExt(drawto, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
999   MarkTileDirty(x/2, y/2);
1000 }
1001
1002 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1003 {
1004   if (graphic >= GFX_START_ROCKSELEMENTS && graphic <= GFX_END_ROCKSELEMENTS)
1005   {
1006     graphic -= GFX_START_ROCKSELEMENTS;
1007     *bitmap = pix[PIX_ELEMENTS];
1008     *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
1009     *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
1010   }
1011   else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
1012   {
1013     graphic -= GFX_START_ROCKSSP;
1014     *bitmap = pix[PIX_SP];
1015     *x = MINI_SP_STARTX + (graphic % MINI_SP_PER_LINE) * MINI_TILEX;
1016     *y = MINI_SP_STARTY + (graphic / MINI_SP_PER_LINE) * MINI_TILEY;
1017   }
1018   else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
1019   {
1020     graphic -= GFX_START_ROCKSDC;
1021     *bitmap = pix[PIX_DC];
1022     *x = MINI_DC_STARTX + (graphic % MINI_DC_PER_LINE) * MINI_TILEX;
1023     *y = MINI_DC_STARTY + (graphic / MINI_DC_PER_LINE) * MINI_TILEY;
1024   }
1025   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1026   {
1027     graphic -= GFX_START_ROCKSMORE;
1028     *bitmap = pix[PIX_MORE];
1029     *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
1030     *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
1031   }
1032   else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
1033   {
1034     graphic -= GFX_START_ROCKSFONT;
1035     *bitmap = pix[PIX_FONT_EM];
1036     *x = MINI_FONT_STARTX + (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
1037     *y = MINI_FONT_STARTY + (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE;
1038   }
1039   else
1040   {
1041     *bitmap = pix[PIX_SP];
1042     *x = MINI_SP_STARTX;
1043     *y = MINI_SP_STARTY;
1044   }
1045 }
1046
1047 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1048 {
1049   Bitmap *bitmap;
1050   int src_x, src_y;
1051
1052   getMiniGraphicSource(graphic, &bitmap, &src_x, &src_y);
1053   BlitBitmap(bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1054 }
1055
1056 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
1057                         int cut_mode, int mask_mode)
1058 {
1059   int width = TILEX, height = TILEY;
1060   int cx = 0, cy = 0;
1061   int src_x, src_y, dest_x, dest_y;
1062   int tile = graphic;
1063   Bitmap *src_bitmap;
1064   GC drawing_gc;
1065
1066   if (graphic < 0)
1067   {
1068     DrawGraphic(x, y, graphic);
1069     return;
1070   }
1071
1072   if (dx || dy)                 /* Verschiebung der Grafik? */
1073   {
1074     if (x < BX1)                /* Element kommt von links ins Bild */
1075     {
1076       x = BX1;
1077       width = dx;
1078       cx = TILEX - dx;
1079       dx = 0;
1080     }
1081     else if (x > BX2)           /* Element kommt von rechts ins Bild */
1082     {
1083       x = BX2;
1084       width = -dx;
1085       dx = TILEX + dx;
1086     }
1087     else if (x==BX1 && dx < 0)  /* Element verläßt links das Bild */
1088     {
1089       width += dx;
1090       cx = -dx;
1091       dx = 0;
1092     }
1093     else if (x==BX2 && dx > 0)  /* Element verläßt rechts das Bild */
1094       width -= dx;
1095     else if (dx)                /* allg. Bewegung in x-Richtung */
1096       MarkTileDirty(x + SIGN(dx), y);
1097
1098     if (y < BY1)                /* Element kommt von oben ins Bild */
1099     {
1100       if (cut_mode==CUT_BELOW)  /* Element oberhalb des Bildes */
1101         return;
1102
1103       y = BY1;
1104       height = dy;
1105       cy = TILEY - dy;
1106       dy = 0;
1107     }
1108     else if (y > BY2)           /* Element kommt von unten ins Bild */
1109     {
1110       y = BY2;
1111       height = -dy;
1112       dy = TILEY + dy;
1113     }
1114     else if (y==BY1 && dy < 0)  /* Element verläßt oben das Bild */
1115     {
1116       height += dy;
1117       cy = -dy;
1118       dy = 0;
1119     }
1120     else if (dy > 0 && cut_mode == CUT_ABOVE)
1121     {
1122       if (y == BY2)             /* Element unterhalb des Bildes */
1123         return;
1124
1125       height = dy;
1126       cy = TILEY - dy;
1127       dy = TILEY;
1128       MarkTileDirty(x, y + 1);
1129     }                           /* Element verläßt unten das Bild */
1130     else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1131       height -= dy;
1132     else if (dy)                /* allg. Bewegung in y-Richtung */
1133       MarkTileDirty(x, y + SIGN(dy));
1134   }
1135
1136   getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1137   drawing_gc = src_bitmap->stored_clip_gc;
1138
1139   src_x += cx;
1140   src_y += cy;
1141
1142   dest_x = FX + x * TILEX + dx;
1143   dest_y = FY + y * TILEY + dy;
1144
1145 #if DEBUG
1146   if (!IN_SCR_FIELD(x,y))
1147   {
1148     printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1149     printf("DrawGraphicShifted(): This should never happen!\n");
1150     return;
1151   }
1152 #endif
1153
1154   if (mask_mode == USE_MASKING)
1155   {
1156     if (tile_clipmask[tile] != None)
1157     {
1158       SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
1159       SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
1160       BlitBitmapMasked(src_bitmap, drawto_field,
1161                        src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1162     }
1163     else
1164     {
1165 #if DEBUG
1166 #ifndef TARGET_SDL
1167       printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1168 #endif
1169 #endif
1170
1171       SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1172       BlitBitmapMasked(src_bitmap, drawto_field,
1173                        src_x, src_y, width, height, dest_x, dest_y);
1174     }
1175   }
1176   else
1177     BlitBitmap(src_bitmap, drawto_field,
1178                src_x, src_y, width, height, dest_x, dest_y);
1179
1180   MarkTileDirty(x,y);
1181 }
1182
1183 void DrawNewGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
1184                         int cut_mode, int mask_mode)
1185 {
1186   Bitmap *src_bitmap;
1187   GC drawing_gc;
1188   int src_x;
1189   int src_y;
1190
1191   int width = TILEX, height = TILEY;
1192   int cx = 0, cy = 0;
1193   int dest_x, dest_y;
1194
1195   if (graphic < 0)
1196   {
1197     DrawNewGraphic(x, y, graphic, frame);
1198     return;
1199   }
1200
1201   if (dx || dy)                 /* Verschiebung der Grafik? */
1202   {
1203     if (x < BX1)                /* Element kommt von links ins Bild */
1204     {
1205       x = BX1;
1206       width = dx;
1207       cx = TILEX - dx;
1208       dx = 0;
1209     }
1210     else if (x > BX2)           /* Element kommt von rechts ins Bild */
1211     {
1212       x = BX2;
1213       width = -dx;
1214       dx = TILEX + dx;
1215     }
1216     else if (x==BX1 && dx < 0)  /* Element verläßt links das Bild */
1217     {
1218       width += dx;
1219       cx = -dx;
1220       dx = 0;
1221     }
1222     else if (x==BX2 && dx > 0)  /* Element verläßt rechts das Bild */
1223       width -= dx;
1224     else if (dx)                /* allg. Bewegung in x-Richtung */
1225       MarkTileDirty(x + SIGN(dx), y);
1226
1227     if (y < BY1)                /* Element kommt von oben ins Bild */
1228     {
1229       if (cut_mode==CUT_BELOW)  /* Element oberhalb des Bildes */
1230         return;
1231
1232       y = BY1;
1233       height = dy;
1234       cy = TILEY - dy;
1235       dy = 0;
1236     }
1237     else if (y > BY2)           /* Element kommt von unten ins Bild */
1238     {
1239       y = BY2;
1240       height = -dy;
1241       dy = TILEY + dy;
1242     }
1243     else if (y==BY1 && dy < 0)  /* Element verläßt oben das Bild */
1244     {
1245       height += dy;
1246       cy = -dy;
1247       dy = 0;
1248     }
1249     else if (dy > 0 && cut_mode == CUT_ABOVE)
1250     {
1251       if (y == BY2)             /* Element unterhalb des Bildes */
1252         return;
1253
1254       height = dy;
1255       cy = TILEY - dy;
1256       dy = TILEY;
1257       MarkTileDirty(x, y + 1);
1258     }                           /* Element verläßt unten das Bild */
1259     else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1260       height -= dy;
1261     else if (dy)                /* allg. Bewegung in y-Richtung */
1262       MarkTileDirty(x, y + SIGN(dy));
1263   }
1264
1265   src_bitmap = new_graphic_info[graphic].bitmap;
1266   drawing_gc = src_bitmap->stored_clip_gc;
1267   src_x = new_graphic_info[graphic].src_x;
1268   src_y = new_graphic_info[graphic].src_y;
1269
1270   if (new_graphic_info[graphic].anim_vertical)
1271     src_y += frame * TILEY;
1272   else
1273     src_x += frame * TILEX;
1274
1275   src_x += cx;
1276   src_y += cy;
1277
1278   dest_x = FX + x * TILEX + dx;
1279   dest_y = FY + y * TILEY + dy;
1280
1281 #if DEBUG
1282   if (!IN_SCR_FIELD(x,y))
1283   {
1284     printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1285     printf("DrawGraphicShifted(): This should never happen!\n");
1286     return;
1287   }
1288 #endif
1289
1290   if (mask_mode == USE_MASKING)
1291     SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1292
1293   BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1294              dest_x, dest_y);
1295
1296   MarkTileDirty(x,y);
1297 }
1298
1299 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1300                                 int cut_mode)
1301 {
1302   DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1303 }
1304
1305 void DrawNewGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1306                                    int frame, int cut_mode)
1307 {
1308   DrawNewGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1309 }
1310
1311 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1312                           int cut_mode, int mask_mode)
1313 {
1314   int ux = LEVELX(x), uy = LEVELY(y);
1315   int graphic = el2gfx(element);
1316   int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1317   int phase4 = phase8 / 2;
1318   int phase2  = phase8 / 4;
1319   int dir = MovDir[ux][uy];
1320
1321   if (element == EL_PACMAN || element == EL_BUG || element == EL_SPACESHIP)
1322   {
1323     graphic += 1 * !phase2;
1324
1325     if (dir == MV_UP)
1326       graphic += 1 * 2;
1327     else if (dir == MV_LEFT)
1328       graphic += 2 * 2;
1329     else if (dir == MV_DOWN)
1330       graphic += 3 * 2;
1331   }
1332   else if (element == EL_SP_SNIKSNAK)
1333   {
1334     if (dir == MV_LEFT)
1335       graphic = GFX_SP_SNIKSNAK_LEFT;
1336     else if (dir == MV_RIGHT)
1337       graphic = GFX_SP_SNIKSNAK_RIGHT;
1338     else if (dir == MV_UP)
1339       graphic = GFX_SP_SNIKSNAK_UP;
1340     else
1341       graphic = GFX_SP_SNIKSNAK_DOWN;
1342
1343     graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1344   }
1345   else if (element == EL_SP_ELECTRON)
1346   {
1347     graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1348   }
1349   else if (element == EL_MOLE || element == EL_PENGUIN ||
1350            element == EL_PIG || element == EL_DRAGON)
1351   {
1352     if (dir == MV_LEFT)
1353       graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1354                  element == EL_PENGUIN ? GFX_PINGUIN_LEFT :
1355                  element == EL_PIG ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1356     else if (dir == MV_RIGHT)
1357       graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1358                  element == EL_PENGUIN ? GFX_PINGUIN_RIGHT :
1359                  element == EL_PIG ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1360     else if (dir == MV_UP)
1361       graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1362                  element == EL_PENGUIN ? GFX_PINGUIN_UP :
1363                  element == EL_PIG ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1364     else
1365       graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1366                  element == EL_PENGUIN ? GFX_PINGUIN_DOWN :
1367                  element == EL_PIG ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1368
1369     graphic += phase4;
1370   }
1371   else if (element == EL_SATELLITE)
1372   {
1373     graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1374   }
1375   else if (element == EL_ACID)
1376   {
1377     graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1378   }
1379   else if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY)
1380   {
1381     graphic += !phase2;
1382   }
1383   else if (element == EL_BALLOON)
1384   {
1385     graphic += phase4;
1386   }
1387   else if ((element == EL_ROCK ||
1388             element == EL_SP_ZONK ||
1389             element == EL_BD_ROCK ||
1390             element == EL_SP_INFOTRON ||
1391             IS_GEM(element))
1392            && !cut_mode)
1393   {
1394     if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1395     {
1396       if (element == EL_ROCK ||
1397           element == EL_SP_ZONK ||
1398           element == EL_BD_ROCK)
1399       {
1400         if (dir == MV_LEFT)
1401           graphic += (4 - phase4) % 4;
1402         else if (dir == MV_RIGHT)
1403           graphic += phase4;
1404         else
1405           graphic += phase2 * 2;
1406       }
1407       else if (element != EL_SP_INFOTRON)
1408         graphic += phase2;
1409     }
1410   }
1411   else if (element == EL_MAGIC_WALL_ACTIVE ||
1412            element == EL_MAGIC_WALL_EMPTYING ||
1413            element == EL_BD_MAGIC_WALL_ACTIVE ||
1414            element == EL_BD_MAGIC_WALL_EMPTYING ||
1415            element == EL_MAGIC_WALL_FULL ||
1416            element == EL_BD_MAGIC_WALL_FULL)
1417   {
1418     graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1419   }
1420   else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1421   {
1422     graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1423     graphic += (x + 2 * y + 4) % 4;
1424   }
1425   else if (element == EL_WALL_GROWING)
1426   {
1427     boolean links_massiv = FALSE, rechts_massiv = FALSE;
1428
1429     if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1430       links_massiv = TRUE;
1431     if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1432       rechts_massiv = TRUE;
1433
1434     if (links_massiv && rechts_massiv)
1435       graphic = GFX_MAUERWERK;
1436     else if (links_massiv)
1437       graphic = GFX_MAUER_R;
1438     else if (rechts_massiv)
1439       graphic = GFX_MAUER_L;
1440   }
1441 #if 0
1442   else if ((element == EL_INVISIBLE_STEELWALL ||
1443             element == EL_INVISIBLE_WALL ||
1444             element == EL_INVISIBLE_SAND) && game.light_time_left)
1445   {
1446     graphic = (element == EL_INVISIBLE_STEELWALL ? GFX_INVISIBLE_STEEL_ON :
1447                element == EL_INVISIBLE_WALL ? GFX_UNSICHTBAR_ON :
1448                GFX_SAND_INVISIBLE_ON);
1449   }
1450 #endif
1451
1452   if (dx || dy)
1453     DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1454   else if (mask_mode == USE_MASKING)
1455     DrawGraphicThruMask(x, y, graphic);
1456   else
1457     DrawGraphic(x, y, graphic);
1458 }
1459
1460 void DrawNewScreenElementExt(int x, int y, int dx, int dy, int element,
1461                           int cut_mode, int mask_mode)
1462 {
1463   int ux = LEVELX(x), uy = LEVELY(y);
1464   int move_dir = MovDir[ux][uy];
1465   int move_pos = ABS(MovPos[ux][uy]) / (TILEX / 8);
1466   int gfx_action = (IS_MOVING(ux,uy) ? GFX_ACTION_MOVING : GFX_ACTION_DEFAULT);
1467   int graphic = el_dir_act2img(element, move_dir, gfx_action);
1468   int frame = getNewGraphicAnimationFrame(graphic, move_pos);
1469 #if 0
1470   int phase8 = move_pos;
1471   int phase4 = phase8 / 2;
1472   int phase2  = phase8 / 4;
1473 #endif
1474
1475   if (element == EL_WALL_GROWING)
1476   {
1477     boolean left_stopped = FALSE, right_stopped = FALSE;
1478
1479     if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1480       left_stopped = TRUE;
1481     if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1482       right_stopped = TRUE;
1483
1484     if (left_stopped && right_stopped)
1485       graphic = IMG_WALL;
1486     else if (left_stopped)
1487       graphic = IMG_WALL_GROWING_ACTIVE_RIGHT;
1488     else if (right_stopped)
1489       graphic = IMG_WALL_GROWING_ACTIVE_LEFT;
1490   }
1491 #if 0
1492   else if ((element == EL_ROCK ||
1493             element == EL_SP_ZONK ||
1494             element == EL_BD_ROCK ||
1495             element == EL_SP_INFOTRON ||
1496             IS_GEM(element))
1497            && !cut_mode)
1498   {
1499     if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1500     {
1501       if (element == EL_ROCK ||
1502           element == EL_SP_ZONK ||
1503           element == EL_BD_ROCK)
1504       {
1505         if (move_dir == MV_LEFT)
1506           graphic += (4 - phase4) % 4;
1507         else if (move_dir == MV_RIGHT)
1508           graphic += phase4;
1509         else
1510           graphic += phase2 * 2;
1511       }
1512       else if (element != EL_SP_INFOTRON)
1513         graphic += phase2;
1514     }
1515   }
1516   else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1517   {
1518     graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1519     graphic += (x + 2 * y + 4) % 4;
1520   }
1521 #endif
1522
1523   if (dx || dy)
1524     DrawNewGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1525   else if (mask_mode == USE_MASKING)
1526     DrawNewGraphicThruMask(x, y, graphic, frame);
1527   else
1528     DrawNewGraphic(x, y, graphic, frame);
1529 }
1530
1531 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1532                          int cut_mode, int mask_mode)
1533 {
1534   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1535     DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1536                          cut_mode, mask_mode);
1537 }
1538
1539 void DrawNewLevelElementExt(int x, int y, int dx, int dy, int element,
1540                          int cut_mode, int mask_mode)
1541 {
1542   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1543     DrawNewScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1544                          cut_mode, mask_mode);
1545 }
1546
1547 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1548                               int cut_mode)
1549 {
1550   DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1551 }
1552
1553 void DrawNewScreenElementShifted(int x, int y, int dx, int dy, int element,
1554                               int cut_mode)
1555 {
1556   DrawNewScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1557 }
1558
1559 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1560                              int cut_mode)
1561 {
1562   DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1563 }
1564
1565 void DrawNewLevelElementShifted(int x, int y, int dx, int dy, int element,
1566                              int cut_mode)
1567 {
1568   DrawNewLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1569 }
1570
1571 void DrawScreenElementThruMask(int x, int y, int element)
1572 {
1573   DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1574 }
1575
1576 void DrawNewScreenElementThruMask(int x, int y, int element)
1577 {
1578   DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1579 }
1580
1581 void DrawLevelElementThruMask(int x, int y, int element)
1582 {
1583   DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1584 }
1585
1586 void DrawNewLevelElementThruMask(int x, int y, int element)
1587 {
1588   DrawNewLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1589 }
1590
1591 void DrawLevelFieldThruMask(int x, int y)
1592 {
1593   DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1594 }
1595
1596 void DrawNewLevelFieldThruMask(int x, int y)
1597 {
1598   DrawNewLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1599 }
1600
1601 void ErdreichAnbroeckeln(int x, int y)
1602 {
1603   Bitmap *src_bitmap;
1604   int src_x, src_y;
1605   int i, width, height, cx,cy;
1606   int ux = LEVELX(x), uy = LEVELY(y);
1607   int element, graphic;
1608   int snip = 4;
1609   static int xy[4][2] =
1610   {
1611     { 0, -1 },
1612     { -1, 0 },
1613     { +1, 0 },
1614     { 0, +1 }
1615   };
1616
1617   if (!IN_LEV_FIELD(ux, uy))
1618     return;
1619
1620   element = Feld[ux][uy];
1621
1622   if (element == EL_SAND ||
1623       element == EL_LANDMINE ||
1624       element == EL_TRAP ||
1625       element == EL_TRAP_ACTIVE)
1626   {
1627     if (!IN_SCR_FIELD(x, y))
1628       return;
1629
1630     graphic = GFX_ERDENRAND;
1631
1632     getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1633
1634     for(i=0; i<4; i++)
1635     {
1636       int uxx, uyy;
1637
1638       uxx = ux + xy[i][0];
1639       uyy = uy + xy[i][1];
1640       if (!IN_LEV_FIELD(uxx, uyy))
1641         element = EL_STEELWALL;
1642       else
1643         element = Feld[uxx][uyy];
1644
1645       if (element == EL_SAND ||
1646           element == EL_LANDMINE ||
1647           element == EL_TRAP ||
1648           element == EL_TRAP_ACTIVE)
1649         continue;
1650
1651       if (i == 1 || i == 2)
1652       {
1653         width = snip;
1654         height = TILEY;
1655         cx = (i == 2 ? TILEX - snip : 0);
1656         cy = 0;
1657       }
1658       else
1659       {
1660         width = TILEX;
1661         height = snip;
1662         cx = 0;
1663         cy = (i == 3 ? TILEY - snip : 0);
1664       }
1665
1666       BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1667                  width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1668     }
1669
1670     MarkTileDirty(x, y);
1671   }
1672   else
1673   {
1674     graphic = GFX_ERDENRAND;
1675
1676     getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1677
1678     for(i=0; i<4; i++)
1679     {
1680       int xx, yy, uxx, uyy;
1681
1682       xx = x + xy[i][0];
1683       yy = y + xy[i][1];
1684       uxx = ux + xy[i][0];
1685       uyy = uy + xy[i][1];
1686
1687       if (!IN_LEV_FIELD(uxx, uyy) ||
1688           (Feld[uxx][uyy] != EL_SAND &&
1689            Feld[uxx][uyy] != EL_LANDMINE &&
1690            Feld[uxx][uyy] != EL_TRAP &&
1691            Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1692           !IN_SCR_FIELD(xx, yy))
1693         continue;
1694
1695       if (i == 1 || i == 2)
1696       {
1697         width = snip;
1698         height = TILEY;
1699         cx = (i == 1 ? TILEX - snip : 0);
1700         cy = 0;
1701       }
1702       else
1703       {
1704         width = TILEX;
1705         height = snip;
1706         cx = 0;
1707         cy = (i==0 ? TILEY-snip : 0);
1708       }
1709
1710       BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1711                  width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1712
1713       MarkTileDirty(xx, yy);
1714     }
1715   }
1716 }
1717
1718 void DrawScreenElement(int x, int y, int element)
1719 {
1720   DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1721   ErdreichAnbroeckeln(x, y);
1722 }
1723
1724 void DrawNewScreenElement(int x, int y, int element)
1725 {
1726   DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1727   ErdreichAnbroeckeln(x, y);
1728 }
1729
1730 void DrawLevelElement(int x, int y, int element)
1731 {
1732   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1733     DrawScreenElement(SCREENX(x), SCREENY(y), element);
1734 }
1735
1736 void DrawNewLevelElement(int x, int y, int element)
1737 {
1738   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1739     DrawNewScreenElement(SCREENX(x), SCREENY(y), element);
1740 }
1741
1742 void DrawScreenField(int x, int y)
1743 {
1744   int ux = LEVELX(x), uy = LEVELY(y);
1745   int element, content;
1746
1747   if (!IN_LEV_FIELD(ux, uy))
1748   {
1749     if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1750       element = EL_EMPTY;
1751     else
1752       element = BorderElement;
1753
1754     DrawScreenElement(x, y, element);
1755     return;
1756   }
1757
1758   element = Feld[ux][uy];
1759   content = Store[ux][uy];
1760
1761   if (IS_MOVING(ux, uy))
1762   {
1763     int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1764     boolean cut_mode = NO_CUTTING;
1765
1766     if (element == EL_QUICKSAND_EMPTYING ||
1767         element == EL_MAGIC_WALL_EMPTYING ||
1768         element == EL_BD_MAGIC_WALL_EMPTYING ||
1769         element == EL_AMOEBA_DRIPPING)
1770       cut_mode = CUT_ABOVE;
1771     else if (element == EL_QUICKSAND_FILLING ||
1772              element == EL_MAGIC_WALL_FILLING ||
1773              element == EL_BD_MAGIC_WALL_FILLING)
1774       cut_mode = CUT_BELOW;
1775
1776     if (cut_mode == CUT_ABOVE)
1777       DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1778     else
1779       DrawScreenElement(x, y, EL_EMPTY);
1780
1781     if (horiz_move)
1782       DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1783     else if (cut_mode == NO_CUTTING)
1784       DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1785     else
1786       DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1787
1788     if (content == EL_ACID)
1789       DrawLevelElementThruMask(ux, uy + 1, EL_ACID);
1790   }
1791   else if (IS_BLOCKED(ux, uy))
1792   {
1793     int oldx, oldy;
1794     int sx, sy;
1795     int horiz_move;
1796     boolean cut_mode = NO_CUTTING;
1797     int element_old, content_old;
1798
1799     Blocked2Moving(ux, uy, &oldx, &oldy);
1800     sx = SCREENX(oldx);
1801     sy = SCREENY(oldy);
1802     horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1803                   MovDir[oldx][oldy] == MV_RIGHT);
1804
1805     element_old = Feld[oldx][oldy];
1806     content_old = Store[oldx][oldy];
1807
1808     if (element_old == EL_QUICKSAND_EMPTYING ||
1809         element_old == EL_MAGIC_WALL_EMPTYING ||
1810         element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1811         element_old == EL_AMOEBA_DRIPPING)
1812       cut_mode = CUT_ABOVE;
1813
1814     DrawScreenElement(x, y, EL_EMPTY);
1815
1816     if (horiz_move)
1817       DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1818                                NO_CUTTING);
1819     else if (cut_mode == NO_CUTTING)
1820       DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1821                                cut_mode);
1822     else
1823       DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1824                                cut_mode);
1825   }
1826   else if (IS_DRAWABLE(element))
1827     DrawScreenElement(x, y, element);
1828   else
1829     DrawScreenElement(x, y, EL_EMPTY);
1830 }
1831
1832 void DrawNewScreenField(int x, int y)
1833 {
1834   int ux = LEVELX(x), uy = LEVELY(y);
1835   int element, content;
1836
1837   if (!IN_LEV_FIELD(ux, uy))
1838   {
1839     if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1840       element = EL_EMPTY;
1841     else
1842       element = BorderElement;
1843
1844     DrawNewScreenElement(x, y, element);
1845     return;
1846   }
1847
1848   element = Feld[ux][uy];
1849   content = Store[ux][uy];
1850
1851   if (IS_MOVING(ux, uy))
1852   {
1853     int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1854     boolean cut_mode = NO_CUTTING;
1855
1856     if (element == EL_QUICKSAND_EMPTYING ||
1857         element == EL_MAGIC_WALL_EMPTYING ||
1858         element == EL_BD_MAGIC_WALL_EMPTYING ||
1859         element == EL_AMOEBA_DRIPPING)
1860       cut_mode = CUT_ABOVE;
1861     else if (element == EL_QUICKSAND_FILLING ||
1862              element == EL_MAGIC_WALL_FILLING ||
1863              element == EL_BD_MAGIC_WALL_FILLING)
1864       cut_mode = CUT_BELOW;
1865
1866     if (cut_mode == CUT_ABOVE)
1867       DrawNewScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1868     else
1869       DrawNewScreenElement(x, y, EL_EMPTY);
1870
1871     if (horiz_move)
1872       DrawNewScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1873     else if (cut_mode == NO_CUTTING)
1874       DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1875     else
1876       DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1877
1878     if (content == EL_ACID)
1879       DrawNewLevelElementThruMask(ux, uy + 1, EL_ACID);
1880   }
1881   else if (IS_BLOCKED(ux, uy))
1882   {
1883     int oldx, oldy;
1884     int sx, sy;
1885     int horiz_move;
1886     boolean cut_mode = NO_CUTTING;
1887     int element_old, content_old;
1888
1889     Blocked2Moving(ux, uy, &oldx, &oldy);
1890     sx = SCREENX(oldx);
1891     sy = SCREENY(oldy);
1892     horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1893                   MovDir[oldx][oldy] == MV_RIGHT);
1894
1895     element_old = Feld[oldx][oldy];
1896     content_old = Store[oldx][oldy];
1897
1898     if (element_old == EL_QUICKSAND_EMPTYING ||
1899         element_old == EL_MAGIC_WALL_EMPTYING ||
1900         element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1901         element_old == EL_AMOEBA_DRIPPING)
1902       cut_mode = CUT_ABOVE;
1903
1904     DrawNewScreenElement(x, y, EL_EMPTY);
1905
1906     if (horiz_move)
1907       DrawNewScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1908                                NO_CUTTING);
1909     else if (cut_mode == NO_CUTTING)
1910       DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1911                                cut_mode);
1912     else
1913       DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1914                                cut_mode);
1915   }
1916   else if (IS_DRAWABLE(element))
1917     DrawNewScreenElement(x, y, element);
1918   else
1919     DrawNewScreenElement(x, y, EL_EMPTY);
1920 }
1921
1922 void DrawLevelField(int x, int y)
1923 {
1924   if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1925     DrawScreenField(SCREENX(x), SCREENY(y));
1926   else if (IS_MOVING(x, y))
1927   {
1928     int newx,newy;
1929
1930     Moving2Blocked(x, y, &newx, &newy);
1931     if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1932       DrawScreenField(SCREENX(newx), SCREENY(newy));
1933   }
1934   else if (IS_BLOCKED(x, y))
1935   {
1936     int oldx, oldy;
1937
1938     Blocked2Moving(x, y, &oldx, &oldy);
1939     if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1940       DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1941   }
1942 }
1943
1944 void DrawNewLevelField(int x, int y)
1945 {
1946   if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1947     DrawNewScreenField(SCREENX(x), SCREENY(y));
1948   else if (IS_MOVING(x, y))
1949   {
1950     int newx,newy;
1951
1952     Moving2Blocked(x, y, &newx, &newy);
1953     if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1954       DrawNewScreenField(SCREENX(newx), SCREENY(newy));
1955   }
1956   else if (IS_BLOCKED(x, y))
1957   {
1958     int oldx, oldy;
1959
1960     Blocked2Moving(x, y, &oldx, &oldy);
1961     if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1962       DrawNewScreenField(SCREENX(oldx), SCREENY(oldy));
1963   }
1964 }
1965
1966 void DrawMiniElement(int x, int y, int element)
1967 {
1968   int graphic;
1969
1970   if (!element)
1971   {
1972     DrawMiniGraphic(x, y, -1);
1973     return;
1974   }
1975
1976   graphic = el2gfx(element);
1977   DrawMiniGraphic(x, y, graphic);
1978 }
1979
1980 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1981 {
1982   int x = sx + scroll_x, y = sy + scroll_y;
1983
1984   if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1985     DrawMiniElement(sx, sy, EL_EMPTY);
1986   else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1987     DrawMiniElement(sx, sy, Feld[x][y]);
1988   else
1989   {
1990     int steel_type, steel_position;
1991     int border[6][2] =
1992     {
1993       { GFX_VSTEEL_UPPER_LEFT,  GFX_ISTEEL_UPPER_LEFT  },
1994       { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
1995       { GFX_VSTEEL_LOWER_LEFT,  GFX_ISTEEL_LOWER_LEFT  },
1996       { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
1997       { GFX_VSTEEL_VERTICAL,    GFX_ISTEEL_VERTICAL    },
1998       { GFX_VSTEEL_HORIZONTAL,  GFX_ISTEEL_HORIZONTAL  }
1999     };
2000
2001     steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
2002     steel_position = (x == -1 && y == -1                        ? 0 :
2003                       x == lev_fieldx && y == -1                ? 1 :
2004                       x == -1 && y == lev_fieldy                ? 2 :
2005                       x == lev_fieldx && y == lev_fieldy        ? 3 :
2006                       x == -1 || x == lev_fieldx                ? 4 :
2007                       y == -1 || y == lev_fieldy                ? 5 : -1);
2008
2009     if (steel_position != -1)
2010       DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
2011   }
2012 }
2013
2014 void DrawMicroElement(int xpos, int ypos, int element)
2015 {
2016   int graphic;
2017
2018   if (element == EL_EMPTY)
2019     return;
2020
2021   graphic = el2gfx(element);
2022
2023   if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
2024   {
2025     graphic -= GFX_START_ROCKSSP;
2026     BlitBitmap(pix[PIX_SP], drawto,
2027                MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
2028                MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
2029                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2030   }
2031   else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
2032   {
2033     graphic -= GFX_START_ROCKSDC;
2034     BlitBitmap(pix[PIX_DC], drawto,
2035                MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
2036                MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
2037                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2038   }
2039   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
2040   {
2041     graphic -= GFX_START_ROCKSMORE;
2042     BlitBitmap(pix[PIX_MORE], drawto,
2043                MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE)*MICRO_TILEX,
2044                MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE)*MICRO_TILEY,
2045                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2046   }
2047   else if (graphic >= GFX_CHAR_START && graphic <= GFX_CHAR_END)
2048   {
2049     graphic -= GFX_CHAR_START;
2050     BlitBitmap(pix[PIX_FONT_EM], drawto,
2051                MICRO_FONT_STARTX + (graphic % MICRO_GFX_PER_LINE)* MICRO_TILEX,
2052                MICRO_FONT_STARTY + (graphic / MICRO_GFX_PER_LINE)* MICRO_TILEY,
2053                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2054   }
2055   else
2056     BlitBitmap(pix[PIX_ELEMENTS], drawto,
2057                MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
2058                MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
2059                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2060 }
2061
2062 void DrawLevel()
2063 {
2064   int x,y;
2065
2066   ClearWindow();
2067
2068   for(x=BX1; x<=BX2; x++)
2069     for(y=BY1; y<=BY2; y++)
2070       DrawScreenField(x, y);
2071
2072   redraw_mask |= REDRAW_FIELD;
2073 }
2074
2075 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
2076 {
2077   int x,y;
2078
2079   for(x=0; x<size_x; x++)
2080     for(y=0; y<size_y; y++)
2081       DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
2082
2083   redraw_mask |= REDRAW_FIELD;
2084 }
2085
2086 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
2087 {
2088   int x, y;
2089
2090   ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
2091
2092   if (lev_fieldx < STD_LEV_FIELDX)
2093     xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
2094   if (lev_fieldy < STD_LEV_FIELDY)
2095     ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
2096
2097   xpos += MICRO_TILEX;
2098   ypos += MICRO_TILEY;
2099
2100   for(x=-1; x<=STD_LEV_FIELDX; x++)
2101   {
2102     for(y=-1; y<=STD_LEV_FIELDY; y++)
2103     {
2104       int lx = from_x + x, ly = from_y + y;
2105
2106       if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
2107         DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2108                          Ur[lx][ly]);
2109       else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
2110         DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2111                          BorderElement);
2112     }
2113   }
2114
2115   redraw_mask |= REDRAW_MICROLEVEL;
2116 }
2117
2118 #define MICROLABEL_EMPTY                0
2119 #define MICROLABEL_LEVEL_NAME           1
2120 #define MICROLABEL_CREATED_BY           2
2121 #define MICROLABEL_LEVEL_AUTHOR         3
2122 #define MICROLABEL_IMPORTED_FROM        4
2123 #define MICROLABEL_LEVEL_IMPORT_INFO    5
2124
2125 #define MAX_MICROLABEL_SIZE             (SXSIZE / FONT4_XSIZE)
2126
2127 static void DrawMicroLevelLabelExt(int mode)
2128 {
2129   char label_text[MAX_MICROLABEL_SIZE + 1];
2130
2131   ClearRectangle(drawto, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
2132
2133   strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
2134                        mode == MICROLABEL_CREATED_BY ? "created by" :
2135                        mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
2136                        mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
2137                        mode == MICROLABEL_LEVEL_IMPORT_INFO ?
2138                        leveldir_current->imported_from : ""),
2139           MAX_MICROLABEL_SIZE);
2140   label_text[MAX_MICROLABEL_SIZE] = '\0';
2141
2142   if (strlen(label_text) > 0)
2143   {
2144     int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
2145     int lypos = MICROLABEL_YPOS;
2146
2147     DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
2148   }
2149
2150   redraw_mask |= REDRAW_MICROLEVEL;
2151 }
2152
2153 void DrawMicroLevel(int xpos, int ypos, boolean restart)
2154 {
2155   static unsigned long scroll_delay = 0;
2156   static unsigned long label_delay = 0;
2157   static int from_x, from_y, scroll_direction;
2158   static int label_state, label_counter;
2159
2160   if (restart)
2161   {
2162     from_x = from_y = 0;
2163     scroll_direction = MV_RIGHT;
2164     label_state = 1;
2165     label_counter = 0;
2166
2167     DrawMicroLevelExt(xpos, ypos, from_x, from_y);
2168     DrawMicroLevelLabelExt(label_state);
2169
2170     /* initialize delay counters */
2171     DelayReached(&scroll_delay, 0);
2172     DelayReached(&label_delay, 0);
2173
2174     return;
2175   }
2176
2177   /* scroll micro level, if needed */
2178   if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
2179       DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
2180   {
2181     switch (scroll_direction)
2182     {
2183       case MV_LEFT:
2184         if (from_x > 0)
2185           from_x--;
2186         else
2187           scroll_direction = MV_UP;
2188         break;
2189
2190       case MV_RIGHT:
2191         if (from_x < lev_fieldx - STD_LEV_FIELDX)
2192           from_x++;
2193         else
2194           scroll_direction = MV_DOWN;
2195         break;
2196
2197       case MV_UP:
2198         if (from_y > 0)
2199           from_y--;
2200         else
2201           scroll_direction = MV_RIGHT;
2202         break;
2203
2204       case MV_DOWN:
2205         if (from_y < lev_fieldy - STD_LEV_FIELDY)
2206           from_y++;
2207         else
2208           scroll_direction = MV_LEFT;
2209         break;
2210
2211       default:
2212         break;
2213     }
2214
2215     DrawMicroLevelExt(xpos, ypos, from_x, from_y);
2216   }
2217
2218   /* redraw micro level label, if needed */
2219   if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
2220       strcmp(level.author, ANONYMOUS_NAME) != 0 &&
2221       strcmp(level.author, leveldir_current->name) != 0 &&
2222       DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
2223   {
2224     int max_label_counter = 23;
2225
2226     if (leveldir_current->imported_from != NULL)
2227       max_label_counter += 14;
2228
2229     label_counter = (label_counter + 1) % max_label_counter;
2230     label_state = (label_counter >= 0 && label_counter <= 7 ?
2231                    MICROLABEL_LEVEL_NAME :
2232                    label_counter >= 9 && label_counter <= 12 ?
2233                    MICROLABEL_CREATED_BY :
2234                    label_counter >= 14 && label_counter <= 21 ?
2235                    MICROLABEL_LEVEL_AUTHOR :
2236                    label_counter >= 23 && label_counter <= 26 ?
2237                    MICROLABEL_IMPORTED_FROM :
2238                    label_counter >= 28 && label_counter <= 35 ?
2239                    MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
2240     DrawMicroLevelLabelExt(label_state);
2241   }
2242 }
2243
2244 int REQ_in_range(int x, int y)
2245 {
2246   if (y > DY+249 && y < DY+278)
2247   {
2248     if (x > DX+1 && x < DX+48)
2249       return 1;
2250     else if (x > DX+51 && x < DX+98) 
2251       return 2;
2252   }
2253   return 0;
2254 }
2255
2256 #define MAX_REQUEST_LINES               13
2257 #define MAX_REQUEST_LINE_LEN            7
2258
2259 boolean Request(char *text, unsigned int req_state)
2260 {
2261   int mx, my, ty, result = -1;
2262   unsigned int old_door_state;
2263
2264 #if defined(PLATFORM_UNIX)
2265   /* pause network game while waiting for request to answer */
2266   if (options.network &&
2267       game_status == PLAYING &&
2268       req_state & REQUEST_WAIT_FOR)
2269     SendToServer_PausePlaying();
2270 #endif
2271
2272   old_door_state = GetDoorState();
2273
2274   UnmapAllGadgets();
2275
2276   CloseDoor(DOOR_CLOSE_1);
2277
2278   /* save old door content */
2279   BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2280              DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2281              DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2282
2283   /* clear door drawing field */
2284   ClearRectangle(drawto, DX, DY, DXSIZE, DYSIZE);
2285
2286   /* write text for request */
2287   for(ty=0; ty < MAX_REQUEST_LINES; ty++)
2288   {
2289     char text_line[MAX_REQUEST_LINE_LEN + 1];
2290     int tx, tl, tc;
2291
2292     if (!*text)
2293       break;
2294
2295     for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
2296     {
2297       tc = *(text + tx);
2298       if (!tc || tc == ' ')
2299         break;
2300     }
2301
2302     if (!tl)
2303     { 
2304       text++; 
2305       ty--; 
2306       continue; 
2307     }
2308
2309     strncpy(text_line, text, tl);
2310     text_line[tl] = 0;
2311
2312     DrawTextExt(drawto, DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
2313                 text_line, FS_SMALL, FC_YELLOW);
2314
2315     text += tl + (tc == ' ' ? 1 : 0);
2316   }
2317
2318   if (req_state & REQ_ASK)
2319   {
2320     MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2321     MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2322   }
2323   else if (req_state & REQ_CONFIRM)
2324   {
2325     MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2326   }
2327   else if (req_state & REQ_PLAYER)
2328   {
2329     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2330     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2331     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2332     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2333   }
2334
2335   /* copy request gadgets to door backbuffer */
2336   BlitBitmap(drawto, pix[PIX_DB_DOOR],
2337              DX, DY, DXSIZE, DYSIZE,
2338              DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2339
2340   OpenDoor(DOOR_OPEN_1);
2341
2342 #if 0
2343   ClearEventQueue();
2344 #endif
2345
2346   if (!(req_state & REQUEST_WAIT_FOR))
2347     return(FALSE);
2348
2349   if (game_status != MAINMENU)
2350     InitAnimation();
2351
2352   button_status = MB_RELEASED;
2353
2354   request_gadget_id = -1;
2355
2356   while(result < 0)
2357   {
2358     if (PendingEvent())
2359     {
2360       Event event;
2361
2362       NextEvent(&event);
2363
2364       switch(event.type)
2365       {
2366         case EVENT_BUTTONPRESS:
2367         case EVENT_BUTTONRELEASE:
2368         case EVENT_MOTIONNOTIFY:
2369         {
2370           if (event.type == EVENT_MOTIONNOTIFY)
2371           {
2372             if (!PointerInWindow(window))
2373               continue; /* window and pointer are on different screens */
2374
2375             if (!button_status)
2376               continue;
2377
2378             motion_status = TRUE;
2379             mx = ((MotionEvent *) &event)->x;
2380             my = ((MotionEvent *) &event)->y;
2381           }
2382           else
2383           {
2384             motion_status = FALSE;
2385             mx = ((ButtonEvent *) &event)->x;
2386             my = ((ButtonEvent *) &event)->y;
2387             if (event.type == EVENT_BUTTONPRESS)
2388               button_status = ((ButtonEvent *) &event)->button;
2389             else
2390               button_status = MB_RELEASED;
2391           }
2392
2393           /* this sets 'request_gadget_id' */
2394           HandleGadgets(mx, my, button_status);
2395
2396           switch(request_gadget_id)
2397           {
2398             case TOOL_CTRL_ID_YES:
2399               result = TRUE;
2400               break;
2401             case TOOL_CTRL_ID_NO:
2402               result = FALSE;
2403               break;
2404             case TOOL_CTRL_ID_CONFIRM:
2405               result = TRUE | FALSE;
2406               break;
2407
2408             case TOOL_CTRL_ID_PLAYER_1:
2409               result = 1;
2410               break;
2411             case TOOL_CTRL_ID_PLAYER_2:
2412               result = 2;
2413               break;
2414             case TOOL_CTRL_ID_PLAYER_3:
2415               result = 3;
2416               break;
2417             case TOOL_CTRL_ID_PLAYER_4:
2418               result = 4;
2419               break;
2420
2421             default:
2422               break;
2423           }
2424
2425           break;
2426         }
2427
2428         case EVENT_KEYPRESS:
2429           switch(GetEventKey((KeyEvent *)&event, TRUE))
2430           {
2431             case KSYM_Return:
2432               result = 1;
2433               break;
2434
2435             case KSYM_Escape:
2436               result = 0;
2437               break;
2438
2439             default:
2440               break;
2441           }
2442           if (req_state & REQ_PLAYER)
2443             result = 0;
2444           break;
2445
2446         case EVENT_KEYRELEASE:
2447           ClearPlayerAction();
2448           break;
2449
2450         default:
2451           HandleOtherEvents(&event);
2452           break;
2453       }
2454     }
2455     else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2456     {
2457       int joy = AnyJoystick();
2458
2459       if (joy & JOY_BUTTON_1)
2460         result = 1;
2461       else if (joy & JOY_BUTTON_2)
2462         result = 0;
2463     }
2464
2465     DoAnimation();
2466
2467     /* don't eat all CPU time */
2468     Delay(10);
2469   }
2470
2471   if (game_status != MAINMENU)
2472     StopAnimation();
2473
2474   UnmapToolButtons();
2475
2476   if (!(req_state & REQ_STAY_OPEN))
2477   {
2478     CloseDoor(DOOR_CLOSE_1);
2479
2480     if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2481     {
2482       BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2483                  DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2484                  DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2485       OpenDoor(DOOR_OPEN_1);
2486     }
2487   }
2488
2489   RemapAllGadgets();
2490
2491 #if defined(PLATFORM_UNIX)
2492   /* continue network game after request */
2493   if (options.network &&
2494       game_status == PLAYING &&
2495       req_state & REQUEST_WAIT_FOR)
2496     SendToServer_ContinuePlaying();
2497 #endif
2498
2499   return(result);
2500 }
2501
2502 unsigned int OpenDoor(unsigned int door_state)
2503 {
2504   unsigned int new_door_state;
2505
2506   if (door_state & DOOR_COPY_BACK)
2507   {
2508     BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2509                DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2510                DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2511     door_state &= ~DOOR_COPY_BACK;
2512   }
2513
2514   new_door_state = MoveDoor(door_state);
2515
2516   return(new_door_state);
2517 }
2518
2519 unsigned int CloseDoor(unsigned int door_state)
2520 {
2521   unsigned int new_door_state;
2522
2523   BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2524              DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2525   BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2526              VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2527
2528   new_door_state = MoveDoor(door_state);
2529
2530   return(new_door_state);
2531 }
2532
2533 unsigned int GetDoorState()
2534 {
2535   return MoveDoor(DOOR_GET_STATE);
2536 }
2537
2538 unsigned int SetDoorState(unsigned int door_state)
2539 {
2540   return MoveDoor(door_state | DOOR_SET_STATE);
2541 }
2542
2543 unsigned int MoveDoor(unsigned int door_state)
2544 {
2545   static int door1 = DOOR_OPEN_1;
2546   static int door2 = DOOR_CLOSE_2;
2547   static unsigned long door_delay = 0;
2548   int x, start, stepsize = 2;
2549   unsigned long door_delay_value = stepsize * 5;
2550
2551   if (door_state == DOOR_GET_STATE)
2552     return(door1 | door2);
2553
2554   if (door_state & DOOR_SET_STATE)
2555   {
2556     if (door_state & DOOR_ACTION_1)
2557       door1 = door_state & DOOR_ACTION_1;
2558     if (door_state & DOOR_ACTION_2)
2559       door2 = door_state & DOOR_ACTION_2;
2560
2561     return(door1 | door2);
2562   }
2563
2564   if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2565     door_state &= ~DOOR_OPEN_1;
2566   else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2567     door_state &= ~DOOR_CLOSE_1;
2568   if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2569     door_state &= ~DOOR_OPEN_2;
2570   else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2571     door_state &= ~DOOR_CLOSE_2;
2572
2573   if (setup.quick_doors)
2574   {
2575     stepsize = 20;
2576     door_delay_value = 0;
2577     StopSound(SND_MENU_DOOR_OPENING);
2578     StopSound(SND_MENU_DOOR_CLOSING);
2579   }
2580
2581   if (door_state & DOOR_ACTION)
2582   {
2583     if (!(door_state & DOOR_NO_DELAY))
2584     {
2585       /* opening door sound has priority over simultaneously closing door */
2586       if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2587         PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2588       else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2589         PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2590     }
2591
2592     start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2593
2594     for(x=start; x<=DXSIZE; x+=stepsize)
2595     {
2596       Bitmap *bitmap = pix[PIX_DOOR];
2597       GC gc = bitmap->stored_clip_gc;
2598
2599       WaitUntilDelayReached(&door_delay, door_delay_value);
2600
2601       if (door_state & DOOR_ACTION_1)
2602       {
2603         int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2604         int j = (DXSIZE - i) / 3;
2605
2606         BlitBitmap(pix[PIX_DB_DOOR], drawto,
2607                    DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2608                    DXSIZE,DYSIZE - i/2, DX, DY);
2609
2610         ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2611
2612         SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2613         BlitBitmapMasked(bitmap, drawto,
2614                          DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2615                          DX + DXSIZE - i, DY + j);
2616         BlitBitmapMasked(bitmap, drawto,
2617                          DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2618                          DX + DXSIZE - i, DY + 140 + j);
2619         SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2620         BlitBitmapMasked(bitmap, drawto,
2621                          DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2622                          DX, DY);
2623         BlitBitmapMasked(bitmap, drawto,
2624                          DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2625                          DX, DY + 140 - j);
2626
2627         BlitBitmapMasked(bitmap, drawto,
2628                          DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2629                          DX, DY + 77 - j);
2630         BlitBitmapMasked(bitmap, drawto,
2631                          DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2632                          DX, DY + 203 - j);
2633         SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2634         BlitBitmapMasked(bitmap, drawto,
2635                          DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2636                          DX + DXSIZE - i, DY + 77 + j);
2637         BlitBitmapMasked(bitmap, drawto,
2638                          DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2639                          DX + DXSIZE - i, DY + 203 + j);
2640
2641         redraw_mask |= REDRAW_DOOR_1;
2642       }
2643
2644       if (door_state & DOOR_ACTION_2)
2645       {
2646         int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2647         int j = (VXSIZE - i) / 3;
2648
2649         BlitBitmap(pix[PIX_DB_DOOR], drawto,
2650                    DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2651                    VXSIZE, VYSIZE - i/2, VX, VY);
2652
2653         ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2654
2655         SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2656         BlitBitmapMasked(bitmap, drawto,
2657                          VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2658                          VX + VXSIZE-i, VY+j);
2659         SetClipOrigin(bitmap, gc,
2660                       VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2661         BlitBitmapMasked(bitmap, drawto,
2662                          VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2663                          VX, VY);
2664
2665         BlitBitmapMasked(bitmap, drawto,
2666                          VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2667                          i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2668         SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2669         BlitBitmapMasked(bitmap, drawto,
2670                          VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2671                          i, VYSIZE / 2 - j,
2672                          VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2673
2674         redraw_mask |= REDRAW_DOOR_2;
2675       }
2676
2677       BackToFront();
2678
2679       if (game_status == MAINMENU)
2680         DoAnimation();
2681     }
2682   }
2683
2684   if (setup.quick_doors)
2685   {
2686     StopSound(SND_MENU_DOOR_OPENING);
2687     StopSound(SND_MENU_DOOR_CLOSING);
2688   }
2689
2690   if (door_state & DOOR_ACTION_1)
2691     door1 = door_state & DOOR_ACTION_1;
2692   if (door_state & DOOR_ACTION_2)
2693     door2 = door_state & DOOR_ACTION_2;
2694
2695   return (door1 | door2);
2696 }
2697
2698 void DrawSpecialEditorDoor()
2699 {
2700   /* draw bigger toolbox window */
2701   BlitBitmap(pix[PIX_DOOR], drawto,
2702              DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2703
2704   redraw_mask |= REDRAW_ALL;
2705 }
2706
2707 void UndrawSpecialEditorDoor()
2708 {
2709   /* draw normal tape recorder window */
2710   BlitBitmap(pix[PIX_BACK], drawto,
2711              562, 344, 108, 56, EX - 4, EY - 12);
2712
2713   redraw_mask |= REDRAW_ALL;
2714 }
2715
2716 #ifndef TARGET_SDL
2717 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2718 {
2719   XImage *pixel_image;
2720   unsigned long pixel_value;
2721
2722   pixel_image = XGetImage(display, bitmap->drawable,
2723                           x, y, 1, 1, AllPlanes, ZPixmap);
2724   pixel_value = XGetPixel(pixel_image, 0, 0);
2725
2726   XDestroyImage(pixel_image);
2727
2728   return pixel_value;
2729 }
2730 #endif
2731
2732 /* ---------- new tool button stuff ---------------------------------------- */
2733
2734 /* graphic position values for tool buttons */
2735 #define TOOL_BUTTON_YES_XPOS            2
2736 #define TOOL_BUTTON_YES_YPOS            250
2737 #define TOOL_BUTTON_YES_GFX_YPOS        0
2738 #define TOOL_BUTTON_YES_XSIZE           46
2739 #define TOOL_BUTTON_YES_YSIZE           28
2740 #define TOOL_BUTTON_NO_XPOS             52
2741 #define TOOL_BUTTON_NO_YPOS             TOOL_BUTTON_YES_YPOS
2742 #define TOOL_BUTTON_NO_GFX_YPOS         TOOL_BUTTON_YES_GFX_YPOS
2743 #define TOOL_BUTTON_NO_XSIZE            TOOL_BUTTON_YES_XSIZE
2744 #define TOOL_BUTTON_NO_YSIZE            TOOL_BUTTON_YES_YSIZE
2745 #define TOOL_BUTTON_CONFIRM_XPOS        TOOL_BUTTON_YES_XPOS
2746 #define TOOL_BUTTON_CONFIRM_YPOS        TOOL_BUTTON_YES_YPOS
2747 #define TOOL_BUTTON_CONFIRM_GFX_YPOS    30
2748 #define TOOL_BUTTON_CONFIRM_XSIZE       96
2749 #define TOOL_BUTTON_CONFIRM_YSIZE       TOOL_BUTTON_YES_YSIZE
2750 #define TOOL_BUTTON_PLAYER_XSIZE        30
2751 #define TOOL_BUTTON_PLAYER_YSIZE        30
2752 #define TOOL_BUTTON_PLAYER_GFX_XPOS     5
2753 #define TOOL_BUTTON_PLAYER_GFX_YPOS     185
2754 #define TOOL_BUTTON_PLAYER_XPOS         (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2755 #define TOOL_BUTTON_PLAYER_YPOS         (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2756 #define TOOL_BUTTON_PLAYER1_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2757                                          + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2758 #define TOOL_BUTTON_PLAYER2_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2759                                          + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2760 #define TOOL_BUTTON_PLAYER3_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2761                                          + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2762 #define TOOL_BUTTON_PLAYER4_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2763                                          + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2764 #define TOOL_BUTTON_PLAYER1_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2765                                          + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2766 #define TOOL_BUTTON_PLAYER2_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2767                                          + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2768 #define TOOL_BUTTON_PLAYER3_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2769                                          + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2770 #define TOOL_BUTTON_PLAYER4_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2771                                          + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2772
2773 static struct
2774 {
2775   int xpos, ypos;
2776   int x, y;
2777   int width, height;
2778   int gadget_id;
2779   char *infotext;
2780 } toolbutton_info[NUM_TOOL_BUTTONS] =
2781 {
2782   {
2783     TOOL_BUTTON_YES_XPOS,       TOOL_BUTTON_YES_GFX_YPOS,
2784     TOOL_BUTTON_YES_XPOS,       TOOL_BUTTON_YES_YPOS,
2785     TOOL_BUTTON_YES_XSIZE,      TOOL_BUTTON_YES_YSIZE,
2786     TOOL_CTRL_ID_YES,
2787     "yes"
2788   },
2789   {
2790     TOOL_BUTTON_NO_XPOS,        TOOL_BUTTON_NO_GFX_YPOS,
2791     TOOL_BUTTON_NO_XPOS,        TOOL_BUTTON_NO_YPOS,
2792     TOOL_BUTTON_NO_XSIZE,       TOOL_BUTTON_NO_YSIZE,
2793     TOOL_CTRL_ID_NO,
2794     "no"
2795   },
2796   {
2797     TOOL_BUTTON_CONFIRM_XPOS,   TOOL_BUTTON_CONFIRM_GFX_YPOS,
2798     TOOL_BUTTON_CONFIRM_XPOS,   TOOL_BUTTON_CONFIRM_YPOS,
2799     TOOL_BUTTON_CONFIRM_XSIZE,  TOOL_BUTTON_CONFIRM_YSIZE,
2800     TOOL_CTRL_ID_CONFIRM,
2801     "confirm"
2802   },
2803   {
2804     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2805     TOOL_BUTTON_PLAYER1_XPOS,   TOOL_BUTTON_PLAYER1_YPOS,
2806     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2807     TOOL_CTRL_ID_PLAYER_1,
2808     "player 1"
2809   },
2810   {
2811     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2812     TOOL_BUTTON_PLAYER2_XPOS,   TOOL_BUTTON_PLAYER2_YPOS,
2813     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2814     TOOL_CTRL_ID_PLAYER_2,
2815     "player 2"
2816   },
2817   {
2818     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2819     TOOL_BUTTON_PLAYER3_XPOS,   TOOL_BUTTON_PLAYER3_YPOS,
2820     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2821     TOOL_CTRL_ID_PLAYER_3,
2822     "player 3"
2823   },
2824   {
2825     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2826     TOOL_BUTTON_PLAYER4_XPOS,   TOOL_BUTTON_PLAYER4_YPOS,
2827     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2828     TOOL_CTRL_ID_PLAYER_4,
2829     "player 4"
2830   }
2831 };
2832
2833 void CreateToolButtons()
2834 {
2835   int i;
2836
2837   for (i=0; i<NUM_TOOL_BUTTONS; i++)
2838   {
2839     Bitmap *gd_bitmap = pix[PIX_DOOR];
2840     Bitmap *deco_bitmap = None;
2841     int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2842     struct GadgetInfo *gi;
2843     unsigned long event_mask;
2844     int gd_xoffset, gd_yoffset;
2845     int gd_x1, gd_x2, gd_y;
2846     int id = i;
2847
2848     event_mask = GD_EVENT_RELEASED;
2849
2850     gd_xoffset = toolbutton_info[i].xpos;
2851     gd_yoffset = toolbutton_info[i].ypos;
2852     gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2853     gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2854     gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2855
2856     if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2857     {
2858       getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2859                            &deco_bitmap, &deco_x, &deco_y);
2860       deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2861       deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2862     }
2863
2864     gi = CreateGadget(GDI_CUSTOM_ID, id,
2865                       GDI_INFO_TEXT, toolbutton_info[i].infotext,
2866                       GDI_X, DX + toolbutton_info[i].x,
2867                       GDI_Y, DY + toolbutton_info[i].y,
2868                       GDI_WIDTH, toolbutton_info[i].width,
2869                       GDI_HEIGHT, toolbutton_info[i].height,
2870                       GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2871                       GDI_STATE, GD_BUTTON_UNPRESSED,
2872                       GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2873                       GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2874                       GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2875                       GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2876                       GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2877                       GDI_DECORATION_SHIFTING, 1, 1,
2878                       GDI_EVENT_MASK, event_mask,
2879                       GDI_CALLBACK_ACTION, HandleToolButtons,
2880                       GDI_END);
2881
2882     if (gi == NULL)
2883       Error(ERR_EXIT, "cannot create gadget");
2884
2885     tool_gadget[id] = gi;
2886   }
2887 }
2888
2889 static void UnmapToolButtons()
2890 {
2891   int i;
2892
2893   for (i=0; i<NUM_TOOL_BUTTONS; i++)
2894     UnmapGadget(tool_gadget[i]);
2895 }
2896
2897 static void HandleToolButtons(struct GadgetInfo *gi)
2898 {
2899   request_gadget_id = gi->custom_id;
2900 }
2901
2902 int get_next_element(int element)
2903 {
2904   switch(element)
2905   {
2906     case EL_QUICKSAND_FILLING:          return EL_QUICKSAND_FULL;
2907     case EL_QUICKSAND_EMPTYING:         return EL_QUICKSAND_EMPTY;
2908     case EL_MAGIC_WALL_FILLING:         return EL_MAGIC_WALL_FULL;
2909     case EL_MAGIC_WALL_EMPTYING:        return EL_MAGIC_WALL_ACTIVE;
2910     case EL_BD_MAGIC_WALL_FILLING:      return EL_BD_MAGIC_WALL_FULL;
2911     case EL_BD_MAGIC_WALL_EMPTYING:     return EL_BD_MAGIC_WALL_ACTIVE;
2912     case EL_AMOEBA_DRIPPING:            return EL_AMOEBA_WET;
2913
2914     default:                            return element;
2915   }
2916 }
2917
2918 int el2gfx_OLD(int element)
2919 {
2920   switch(element)
2921   {
2922     case EL_EMPTY:                      return -1;
2923     case EL_SAND:                       return GFX_ERDREICH;
2924     case EL_WALL:                       return GFX_MAUERWERK;
2925     case EL_WALL_CRUMBLED:              return GFX_FELSBODEN;
2926     case EL_ROCK:                       return GFX_FELSBROCKEN;
2927     case EL_EMERALD:                    return GFX_EDELSTEIN;
2928     case EL_EXIT_CLOSED:                return GFX_AUSGANG_ZU;
2929     case EL_EXIT_OPENING:               return GFX_AUSGANG_ACT;
2930     case EL_EXIT_OPEN:                  return GFX_AUSGANG_AUF;
2931     case EL_SP_EXIT_OPEN:               return GFX_SP_EXIT;
2932     case EL_PLAYER1:                    return GFX_SPIELER1;
2933     case EL_PLAYER2:                    return GFX_SPIELER2;
2934     case EL_PLAYER3:                    return GFX_SPIELER3;
2935     case EL_PLAYER4:                    return GFX_SPIELER4;
2936     case EL_BUG:                        return GFX_KAEFER;
2937     case EL_BUG_RIGHT:                  return GFX_KAEFER_RIGHT;
2938     case EL_BUG_UP:                     return GFX_KAEFER_UP;
2939     case EL_BUG_LEFT:                   return GFX_KAEFER_LEFT;
2940     case EL_BUG_DOWN:                   return GFX_KAEFER_DOWN;
2941     case EL_SPACESHIP:                  return GFX_FLIEGER;
2942     case EL_SPACESHIP_RIGHT:            return GFX_FLIEGER_RIGHT;
2943     case EL_SPACESHIP_UP:               return GFX_FLIEGER_UP;
2944     case EL_SPACESHIP_LEFT:             return GFX_FLIEGER_LEFT;
2945     case EL_SPACESHIP_DOWN:             return GFX_FLIEGER_DOWN;
2946     case EL_BD_BUTTERFLY:               return GFX_BUTTERFLY;
2947     case EL_BD_BUTTERFLY_RIGHT:         return GFX_BUTTERFLY_RIGHT;
2948     case EL_BD_BUTTERFLY_UP:            return GFX_BUTTERFLY_UP;
2949     case EL_BD_BUTTERFLY_LEFT:          return GFX_BUTTERFLY_LEFT;
2950     case EL_BD_BUTTERFLY_DOWN:          return GFX_BUTTERFLY_DOWN;
2951     case EL_BD_FIREFLY:                 return GFX_FIREFLY;
2952     case EL_BD_FIREFLY_RIGHT:           return GFX_FIREFLY_RIGHT;
2953     case EL_BD_FIREFLY_UP:              return GFX_FIREFLY_UP;
2954     case EL_BD_FIREFLY_LEFT:            return GFX_FIREFLY_LEFT;
2955     case EL_BD_FIREFLY_DOWN:            return GFX_FIREFLY_DOWN;
2956     case EL_YAMYAM:                     return GFX_MAMPFER;
2957     case EL_ROBOT:                      return GFX_ROBOT;
2958     case EL_STEELWALL:                  return GFX_BETON;
2959     case EL_DIAMOND:                    return GFX_DIAMANT;
2960     case EL_QUICKSAND_EMPTY:            return GFX_MORAST_LEER;
2961     case EL_QUICKSAND_FULL:             return GFX_MORAST_VOLL;
2962     case EL_QUICKSAND_EMPTYING:         return GFX_MORAST_LEER;
2963     case EL_AMOEBA_DROP:                return GFX_TROPFEN;
2964     case EL_BOMB:                       return GFX_BOMBE;
2965     case EL_MAGIC_WALL:                 return GFX_MAGIC_WALL_OFF;
2966     case EL_MAGIC_WALL_ACTIVE:          return GFX_MAGIC_WALL_EMPTY;
2967     case EL_MAGIC_WALL_EMPTYING:        return GFX_MAGIC_WALL_EMPTY;
2968     case EL_MAGIC_WALL_FULL:            return GFX_MAGIC_WALL_FULL;
2969     case EL_MAGIC_WALL_DEAD:            return GFX_MAGIC_WALL_DEAD;
2970     case EL_ACID:                       return GFX_SALZSAEURE;
2971     case EL_AMOEBA_DEAD:                return GFX_AMOEBE_TOT;
2972     case EL_AMOEBA_WET:                 return GFX_AMOEBE_NASS;
2973     case EL_AMOEBA_DRY:                 return GFX_AMOEBE_NORM;
2974     case EL_AMOEBA_FULL:                return GFX_AMOEBE_VOLL;
2975     case EL_BD_AMOEBA:                  return GFX_AMOEBE_BD;
2976     case EL_AMOEBA_TO_DIAMOND:          return GFX_AMOEBA2DIAM;
2977     case EL_AMOEBA_DRIPPING:            return GFX_AMOEBE_NASS;
2978     case EL_NUT:                        return GFX_KOKOSNUSS;
2979     case EL_GAMEOFLIFE:                 return GFX_LIFE;
2980     case EL_BIOMAZE:                    return GFX_LIFE_ASYNC;
2981     case EL_DYNAMITE_ACTIVE:            return GFX_DYNAMIT;
2982     case EL_STONEBLOCK:                 return GFX_BADEWANNE;
2983     case EL_ACIDPOOL_TOPLEFT:           return GFX_BADEWANNE1;
2984     case EL_ACIDPOOL_TOPRIGHT:          return GFX_BADEWANNE2;
2985     case EL_ACIDPOOL_BOTTOMLEFT:        return GFX_BADEWANNE3;
2986     case EL_ACIDPOOL_BOTTOM:            return GFX_BADEWANNE4;
2987     case EL_ACIDPOOL_BOTTOMRIGHT:       return GFX_BADEWANNE5;
2988     case EL_ROBOT_WHEEL:                return GFX_ABLENK_AUS;
2989     case EL_ROBOT_WHEEL_ACTIVE:         return GFX_ABLENK_EIN;
2990     case EL_KEY1:                       return GFX_SCHLUESSEL1;
2991     case EL_KEY2:                       return GFX_SCHLUESSEL2;
2992     case EL_KEY3:                       return GFX_SCHLUESSEL3;
2993     case EL_KEY4:                       return GFX_SCHLUESSEL4;
2994     case EL_GATE1:                      return GFX_PFORTE1;
2995     case EL_GATE2:                      return GFX_PFORTE2;
2996     case EL_GATE3:                      return GFX_PFORTE3;
2997     case EL_GATE4:                      return GFX_PFORTE4;
2998     case EL_GATE1_GRAY:                 return GFX_PFORTE1X;
2999     case EL_GATE2_GRAY:                 return GFX_PFORTE2X;
3000     case EL_GATE3_GRAY:                 return GFX_PFORTE3X;
3001     case EL_GATE4_GRAY:                 return GFX_PFORTE4X;
3002     case EL_DYNAMITE:                   return GFX_DYNAMIT_AUS;
3003     case EL_PACMAN:                     return GFX_PACMAN;
3004     case EL_PACMAN_RIGHT:               return GFX_PACMAN_RIGHT;
3005     case EL_PACMAN_UP:                  return GFX_PACMAN_UP;
3006     case EL_PACMAN_LEFT:                return GFX_PACMAN_LEFT;
3007     case EL_PACMAN_DOWN:                return GFX_PACMAN_DOWN;
3008     case EL_INVISIBLE_WALL:             return GFX_UNSICHTBAR;
3009     case EL_INVISIBLE_WALL_ACTIVE:      return GFX_UNSICHTBAR_ON;
3010     case EL_WALL_EMERALD:               return GFX_ERZ_EDEL;
3011     case EL_WALL_DIAMOND:               return GFX_ERZ_DIAM;
3012     case EL_LAMP:                       return GFX_BIRNE_AUS;
3013     case EL_LAMP_ACTIVE:                return GFX_BIRNE_EIN;
3014     case EL_TIME_ORB_FULL:              return GFX_ZEIT_VOLL;
3015     case EL_TIME_ORB_EMPTY:             return GFX_ZEIT_LEER;
3016     case EL_WALL_GROWING:               return GFX_MAUER_LEBT;
3017     case EL_WALL_GROWING_X:             return GFX_MAUER_X;
3018     case EL_WALL_GROWING_Y:             return GFX_MAUER_Y;
3019     case EL_WALL_GROWING_XY:            return GFX_MAUER_XY;
3020     case EL_BD_DIAMOND:                 return GFX_EDELSTEIN_BD;
3021     case EL_EMERALD_YELLOW:             return GFX_EDELSTEIN_GELB;
3022     case EL_EMERALD_RED:                return GFX_EDELSTEIN_ROT;
3023     case EL_EMERALD_PURPLE:             return GFX_EDELSTEIN_LILA;
3024     case EL_WALL_BD_DIAMOND:            return GFX_ERZ_EDEL_BD;
3025     case EL_WALL_EMERALD_YELLOW:        return GFX_ERZ_EDEL_GELB;
3026     case EL_WALL_EMERALD_RED:           return GFX_ERZ_EDEL_ROT;
3027     case EL_WALL_EMERALD_PURPLE:        return GFX_ERZ_EDEL_LILA;
3028     case EL_DARK_YAMYAM:                return GFX_MAMPFER2;
3029     case EL_BD_MAGIC_WALL:              return GFX_MAGIC_WALL_BD_OFF;
3030     case EL_BD_MAGIC_WALL_ACTIVE:       return GFX_MAGIC_WALL_BD_EMPTY;
3031     case EL_BD_MAGIC_WALL_EMPTYING:     return GFX_MAGIC_WALL_BD_EMPTY;
3032     case EL_BD_MAGIC_WALL_FULL:         return GFX_MAGIC_WALL_BD_FULL;
3033     case EL_BD_MAGIC_WALL_DEAD:         return GFX_MAGIC_WALL_BD_DEAD;
3034     case EL_DYNABOMB_PLAYER1_ACTIVE:    return GFX_DYNABOMB;
3035     case EL_DYNABOMB_PLAYER2_ACTIVE:    return GFX_DYNABOMB;
3036     case EL_DYNABOMB_PLAYER3_ACTIVE:    return GFX_DYNABOMB;
3037     case EL_DYNABOMB_PLAYER4_ACTIVE:    return GFX_DYNABOMB;
3038     case EL_DYNABOMB_NR:                return GFX_DYNABOMB_NR;
3039     case EL_DYNABOMB_SZ:                return GFX_DYNABOMB_SZ;
3040     case EL_DYNABOMB_XL:                return GFX_DYNABOMB_XL;
3041     case EL_SOKOBAN_OBJECT:             return GFX_SOKOBAN_OBJEKT;
3042     case EL_SOKOBAN_FIELD_EMPTY:        return GFX_SOKOBAN_FELD_LEER;
3043     case EL_SOKOBAN_FIELD_FULL:         return GFX_SOKOBAN_FELD_VOLL;
3044     case EL_MOLE:                       return GFX_MOLE;
3045     case EL_PENGUIN:                    return GFX_PINGUIN;
3046     case EL_PIG:                        return GFX_SCHWEIN;
3047     case EL_DRAGON:                     return GFX_DRACHE;
3048     case EL_SATELLITE:                  return GFX_SONDE;
3049     case EL_ARROW_BLUE_LEFT:            return GFX_PFEIL_LEFT;
3050     case EL_ARROW_BLUE_RIGHT:           return GFX_PFEIL_RIGHT;
3051     case EL_ARROW_BLUE_UP:              return GFX_PFEIL_UP;
3052     case EL_ARROW_BLUE_DOWN:            return GFX_PFEIL_DOWN;
3053     case EL_SPEED_PILL:                 return GFX_SPEED_PILL;
3054     case EL_SP_TERMINAL_ACTIVE:         return GFX_SP_TERMINAL;
3055     case EL_SP_BUGGY_BASE_ACTIVE:       return GFX_SP_BUG_ACTIVE;
3056     case EL_SP_ZONK:                    return GFX_SP_ZONK;
3057       /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
3058     case EL_INVISIBLE_STEELWALL:        return GFX_INVISIBLE_STEEL;
3059     case EL_INVISIBLE_STEELWALL_ACTIVE: return GFX_INVISIBLE_STEEL_ON;
3060     case EL_BLACK_ORB:                  return GFX_BLACK_ORB;
3061     case EL_EM_GATE1:                   return GFX_EM_GATE_1;
3062     case EL_EM_GATE2:                   return GFX_EM_GATE_2;
3063     case EL_EM_GATE3:                   return GFX_EM_GATE_3;
3064     case EL_EM_GATE4:                   return GFX_EM_GATE_4;
3065     case EL_EM_GATE1_GRAY:              return GFX_EM_GATE_1X;
3066     case EL_EM_GATE2_GRAY:              return GFX_EM_GATE_2X;
3067     case EL_EM_GATE3_GRAY:              return GFX_EM_GATE_3X;
3068     case EL_EM_GATE4_GRAY:              return GFX_EM_GATE_4X;
3069     case EL_EM_KEY1_FILE:               return GFX_EM_KEY_1;
3070     case EL_EM_KEY2_FILE:               return GFX_EM_KEY_2;
3071     case EL_EM_KEY3_FILE:               return GFX_EM_KEY_3;
3072     case EL_EM_KEY4_FILE:               return GFX_EM_KEY_4;
3073     case EL_EM_KEY1:                    return GFX_EM_KEY_1;
3074     case EL_EM_KEY2:                    return GFX_EM_KEY_2;
3075     case EL_EM_KEY3:                    return GFX_EM_KEY_3;
3076     case EL_EM_KEY4:                    return GFX_EM_KEY_4;
3077     case EL_PEARL:                      return GFX_PEARL;
3078     case EL_CRYSTAL:                    return GFX_CRYSTAL;
3079     case EL_WALL_PEARL:                 return GFX_WALL_PEARL;
3080     case EL_WALL_CRYSTAL:               return GFX_WALL_CRYSTAL;
3081     case EL_DOOR_WHITE:                 return GFX_DOOR_WHITE;
3082     case EL_DOOR_WHITE_GRAY:            return GFX_DOOR_WHITE_GRAY;
3083     case EL_KEY_WHITE:                  return GFX_KEY_WHITE;
3084     case EL_SHIELD_NORMAL:              return GFX_SHIELD_PASSIVE;
3085     case EL_SHIELD_DEADLY:              return GFX_SHIELD_ACTIVE;
3086     case EL_EXTRA_TIME:                 return GFX_EXTRA_TIME;
3087     case EL_SWITCHGATE_OPEN:            return GFX_SWITCHGATE_OPEN;
3088     case EL_SWITCHGATE_CLOSED:          return GFX_SWITCHGATE_CLOSED;
3089     case EL_SWITCHGATE_SWITCH_UP:       return GFX_SWITCHGATE_SWITCH_1;
3090     case EL_SWITCHGATE_SWITCH_DOWN:     return GFX_SWITCHGATE_SWITCH_2;
3091     case EL_CONVEYOR_BELT1_LEFT:        return GFX_BELT1_LEFT;
3092     case EL_CONVEYOR_BELT1_MIDDLE:      return GFX_BELT1_MIDDLE;
3093     case EL_CONVEYOR_BELT1_RIGHT:       return GFX_BELT1_RIGHT;
3094     case EL_CONVEYOR_BELT1_LEFT_ACTIVE: return GFX_BELT1_LEFT;
3095     case EL_CONVEYOR_BELT1_MIDDLE_ACTIVE:return GFX_BELT1_MIDDLE;
3096     case EL_CONVEYOR_BELT1_RIGHT_ACTIVE:return GFX_BELT1_RIGHT;
3097     case EL_CONVEYOR_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
3098     case EL_CONVEYOR_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
3099     case EL_CONVEYOR_BELT1_SWITCH_RIGHT:return GFX_BELT1_SWITCH_RIGHT;
3100     case EL_CONVEYOR_BELT2_LEFT:        return GFX_BELT2_LEFT;
3101     case EL_CONVEYOR_BELT2_MIDDLE:      return GFX_BELT2_MIDDLE;
3102     case EL_CONVEYOR_BELT2_RIGHT:       return GFX_BELT2_RIGHT;
3103     case EL_CONVEYOR_BELT2_LEFT_ACTIVE: return GFX_BELT2_LEFT;
3104     case EL_CONVEYOR_BELT2_MIDDLE_ACTIVE:return GFX_BELT2_MIDDLE;
3105     case EL_CONVEYOR_BELT2_RIGHT_ACTIVE:return GFX_BELT2_RIGHT;
3106     case EL_CONVEYOR_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
3107     case EL_CONVEYOR_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
3108     case EL_CONVEYOR_BELT2_SWITCH_RIGHT:return GFX_BELT2_SWITCH_RIGHT;
3109     case EL_CONVEYOR_BELT3_LEFT:        return GFX_BELT3_LEFT;
3110     case EL_CONVEYOR_BELT3_MIDDLE:      return GFX_BELT3_MIDDLE;
3111     case EL_CONVEYOR_BELT3_RIGHT:       return GFX_BELT3_RIGHT;
3112     case EL_CONVEYOR_BELT3_LEFT_ACTIVE: return GFX_BELT3_LEFT;
3113     case EL_CONVEYOR_BELT3_MIDDLE_ACTIVE:return GFX_BELT3_MIDDLE;
3114     case EL_CONVEYOR_BELT3_RIGHT_ACTIVE:return GFX_BELT3_RIGHT;
3115     case EL_CONVEYOR_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
3116     case EL_CONVEYOR_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
3117     case EL_CONVEYOR_BELT3_SWITCH_RIGHT:return GFX_BELT3_SWITCH_RIGHT;
3118     case EL_CONVEYOR_BELT4_LEFT:        return GFX_BELT4_LEFT;
3119     case EL_CONVEYOR_BELT4_MIDDLE:      return GFX_BELT4_MIDDLE;
3120     case EL_CONVEYOR_BELT4_RIGHT:       return GFX_BELT4_RIGHT;
3121     case EL_CONVEYOR_BELT4_LEFT_ACTIVE: return GFX_BELT4_LEFT;
3122     case EL_CONVEYOR_BELT4_MIDDLE_ACTIVE:return GFX_BELT4_MIDDLE;
3123     case EL_CONVEYOR_BELT4_RIGHT_ACTIVE:return GFX_BELT4_RIGHT;
3124     case EL_CONVEYOR_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
3125     case EL_CONVEYOR_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
3126     case EL_CONVEYOR_BELT4_SWITCH_RIGHT:return GFX_BELT4_SWITCH_RIGHT;
3127     case EL_LANDMINE:                   return GFX_LANDMINE;
3128     case EL_ENVELOPE:                   return GFX_ENVELOPE;
3129     case EL_LIGHT_SWITCH:               return GFX_LIGHT_SWITCH_OFF;
3130     case EL_LIGHT_SWITCH_ACTIVE:        return GFX_LIGHT_SWITCH_ON;
3131     case EL_SIGN_EXCLAMATION:           return GFX_SIGN_EXCLAMATION;
3132     case EL_SIGN_RADIOACTIVITY:         return GFX_SIGN_RADIOACTIVITY;
3133     case EL_SIGN_STOP:                  return GFX_SIGN_STOP;
3134     case EL_SIGN_WHEELCHAIR:            return GFX_SIGN_WHEELCHAIR;
3135     case EL_SIGN_PARKING:               return GFX_SIGN_PARKING;
3136     case EL_SIGN_ONEWAY:                return GFX_SIGN_ONEWAY;
3137     case EL_SIGN_HEART:                 return GFX_SIGN_HEART;
3138     case EL_SIGN_TRIANGLE:              return GFX_SIGN_TRIANGLE;
3139     case EL_SIGN_ROUND:                 return GFX_SIGN_ROUND;
3140     case EL_SIGN_EXIT:                  return GFX_SIGN_EXIT;
3141     case EL_SIGN_YINYANG:               return GFX_SIGN_YINYANG;
3142     case EL_SIGN_OTHER:                 return GFX_SIGN_OTHER;
3143     case EL_MOLE_LEFT:                  return GFX_MOLE_LEFT;
3144     case EL_MOLE_RIGHT:                 return GFX_MOLE_RIGHT;
3145     case EL_MOLE_UP:                    return GFX_MOLE_UP;
3146     case EL_MOLE_DOWN:                  return GFX_MOLE_DOWN;
3147     case EL_STEELWALL_SLANTED:          return GFX_STEEL_SLANTED;
3148     case EL_INVISIBLE_SAND:             return GFX_SAND_INVISIBLE;
3149     case EL_INVISIBLE_SAND_ACTIVE:      return GFX_SAND_INVISIBLE_ON;
3150     case EL_DX_UNKNOWN_15:              return GFX_DX_UNKNOWN_15;
3151     case EL_DX_UNKNOWN_42:              return GFX_DX_UNKNOWN_42;
3152     case EL_TIMEGATE_OPEN:              return GFX_TIMEGATE_OPEN;
3153     case EL_TIMEGATE_CLOSED:            return GFX_TIMEGATE_CLOSED;
3154     case EL_TIMEGATE_SWITCH_ACTIVE:     return GFX_TIMEGATE_SWITCH;
3155     case EL_TIMEGATE_SWITCH:            return GFX_TIMEGATE_SWITCH;
3156     case EL_BALLOON:                    return GFX_BALLOON;
3157     case EL_BALLOON_SEND_LEFT:          return GFX_BALLOON_SEND_LEFT;
3158     case EL_BALLOON_SEND_RIGHT:         return GFX_BALLOON_SEND_RIGHT;
3159     case EL_BALLOON_SEND_UP:            return GFX_BALLOON_SEND_UP;
3160     case EL_BALLOON_SEND_DOWN:          return GFX_BALLOON_SEND_DOWN;
3161     case EL_BALLOON_SEND_ANY_DIRECTION: return GFX_BALLOON_SEND_ANY;
3162     case EL_EMC_STEELWALL1:             return GFX_EMC_STEEL_WALL_1;
3163     case EL_EMC_STEELWALL2:             return GFX_EMC_STEEL_WALL_2;
3164     case EL_EMC_STEELWALL3:             return GFX_EMC_STEEL_WALL_3;
3165     case EL_EMC_STEELWALL4:             return GFX_EMC_STEEL_WALL_4;
3166     case EL_EMC_WALL_PILLAR_UPPER:      return GFX_EMC_WALL_1;
3167     case EL_EMC_WALL_PILLAR_MIDDLE:     return GFX_EMC_WALL_2;
3168     case EL_EMC_WALL_PILLAR_LOWER:      return GFX_EMC_WALL_3;
3169     case EL_EMC_WALL4:                  return GFX_EMC_WALL_4;
3170     case EL_EMC_WALL5:                  return GFX_EMC_WALL_5;
3171     case EL_EMC_WALL6:                  return GFX_EMC_WALL_6;
3172     case EL_EMC_WALL7:                  return GFX_EMC_WALL_7;
3173     case EL_EMC_WALL8:                  return GFX_EMC_WALL_8;
3174     case EL_TUBE_ALL:                   return GFX_TUBE_CROSS;
3175     case EL_TUBE_VERTICAL:              return GFX_TUBE_VERTICAL;
3176     case EL_TUBE_HORIZONTAL:            return GFX_TUBE_HORIZONTAL;
3177     case EL_TUBE_VERTICAL_LEFT:         return GFX_TUBE_VERT_LEFT;
3178     case EL_TUBE_VERTICAL_RIGHT:        return GFX_TUBE_VERT_RIGHT;
3179     case EL_TUBE_HORIZONTAL_UP:         return GFX_TUBE_HORIZ_UP;
3180     case EL_TUBE_HORIZONTAL_DOWN:       return GFX_TUBE_HORIZ_DOWN;
3181     case EL_TUBE_LEFT_UP:               return GFX_TUBE_LEFT_UP;
3182     case EL_TUBE_LEFT_DOWN:             return GFX_TUBE_LEFT_DOWN;
3183     case EL_TUBE_RIGHT_UP:              return GFX_TUBE_RIGHT_UP;
3184     case EL_TUBE_RIGHT_DOWN:            return GFX_TUBE_RIGHT_DOWN;
3185     case EL_SPRING:                     return GFX_SPRING;
3186     case EL_SPRING_MOVING:              return GFX_SPRING;
3187     case EL_TRAP:                       return GFX_TRAP_INACTIVE;
3188     case EL_TRAP_ACTIVE:                return GFX_TRAP_ACTIVE;
3189     case EL_BD_WALL:                    return GFX_BD_WALL;
3190     case EL_BD_ROCK:                    return GFX_BD_ROCK;
3191     case EL_DX_SUPABOMB:                return GFX_DX_SUPABOMB;
3192     case EL_SP_MURPHY_CLONE:            return GFX_SP_MURPHY_CLONE;
3193
3194     default:
3195     {
3196       if (IS_CHAR(element))
3197         return GFX_CHAR_START + (element - EL_CHAR_START);
3198       else if (element >= EL_SP_START && element <= EL_SP_END)
3199       {
3200         int nr_element = element - EL_SP_START;
3201         int gfx_per_line = 8;
3202         int nr_graphic =
3203           (nr_element / gfx_per_line) * SP_PER_LINE +
3204           (nr_element % gfx_per_line);
3205
3206         return GFX_START_ROCKSSP + nr_graphic;
3207       }
3208       else
3209         return -1;
3210     }
3211   }
3212 }
3213
3214 int el2gfx(int element)
3215 {
3216 #if 1
3217   int graphic_OLD = el2gfx_OLD(element);
3218
3219   return graphic_OLD;
3220 #else
3221
3222   int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
3223
3224 #if DEBUG
3225   int graphic_OLD = el2gfx_OLD(element);
3226
3227   if (element >= MAX_ELEMENTS)
3228   {
3229     Error(ERR_WARN, "el2gfx: element == %d >= MAX_ELEMENTS", element);
3230   }
3231
3232   if (graphic_NEW != graphic_OLD)
3233   {
3234     Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
3235           graphic_NEW, graphic_OLD);
3236   }
3237 #endif
3238
3239   return graphic_NEW;
3240 #endif
3241 }
3242
3243 int el2img(int element)
3244 {
3245 #if 1
3246   int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
3247
3248   return graphic_NEW;
3249 #else
3250
3251   switch(element)
3252   {
3253     case EL_BD_BUTTERFLY:       return IMG_BD_BUTTERFLY;
3254     case EL_BD_FIREFLY:         return IMG_BD_FIREFLY;
3255     case EL_SP_ELECTRON:        return IMG_SP_ELECTRON;
3256
3257     default:
3258       break;
3259   }
3260
3261   return IMG_EMPTY_SPACE;
3262 #endif
3263 }
3264
3265 int el_dir2img(int element, int direction)
3266 {
3267   return el_dir_act2img(element, direction, GFX_ACTION_DEFAULT);
3268 }
3269
3270 int el_dir_act2img(int element, int direction, int action)
3271 {
3272   action = graphics_action_mapping[action];
3273   direction = MV_DIR_BIT(direction);
3274
3275   return element_info[element].direction_graphic[action][direction];
3276 }