rnd-20021023-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             DrawNewScreenField(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 #if 0
438 void DrawPlayer(struct PlayerInfo *player)
439 {
440   int jx = player->jx, jy = player->jy;
441   int last_jx = player->last_jx, last_jy = player->last_jy;
442   int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
443   int sx = SCREENX(jx), sy = SCREENY(jy);
444   int sxx = 0, syy = 0;
445   int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
446   int graphic, phase;
447   boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
448
449   if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
450     return;
451
452 #if DEBUG
453   if (!IN_LEV_FIELD(jx,jy))
454   {
455     printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
456     printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
457     printf("DrawPlayerField(): This should never happen!\n");
458     return;
459   }
460 #endif
461
462   if (element == EL_EXPLOSION)
463     return;
464
465   /* draw things in the field the player is leaving, if needed */
466
467   if (player_is_moving)
468   {
469     if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
470     {
471       DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
472       if (last_element == EL_DYNAMITE_ACTIVE)
473         DrawDynamite(last_jx, last_jy);
474       else
475         DrawLevelFieldThruMask(last_jx, last_jy);
476     }
477     else if (last_element == EL_DYNAMITE_ACTIVE)
478       DrawDynamite(last_jx, last_jy);
479     else
480       DrawLevelField(last_jx, last_jy);
481
482     if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
483     {
484       if (player->GfxPos)
485       {
486         if (Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
487           DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FIELD_EMPTY);
488         else
489           DrawLevelElement(next_jx, next_jy, EL_EMPTY);
490       }
491       else
492         DrawLevelField(next_jx, next_jy);
493     }
494   }
495
496   if (!IN_SCR_FIELD(sx, sy))
497     return;
498
499   if (setup.direct_draw)
500     SetDrawtoField(DRAW_BUFFERED);
501
502   /* draw things behind the player, if needed */
503
504   if (Store[jx][jy])
505     DrawLevelElement(jx, jy, Store[jx][jy]);
506   else if (!IS_ACTIVE_BOMB(element))
507     DrawLevelField(jx, jy);
508   else
509     DrawLevelElement(jx, jy, EL_EMPTY);
510
511   /* draw player himself */
512
513   if (game.emulation == EMU_SUPAPLEX)
514   {
515     static int last_dir = MV_LEFT;
516     int action = (player->programmed_action ? player->programmed_action :
517                   player->action);
518     boolean action_moving =
519       (player_is_moving ||
520        ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
521         !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
522
523     graphic = GFX_SP_MURPHY;
524
525     if (player->Pushing)
526     {
527       if (player->MovDir == MV_LEFT)
528         graphic = GFX_MURPHY_PUSH_LEFT;
529       else if (player->MovDir == MV_RIGHT)
530         graphic = GFX_MURPHY_PUSH_RIGHT;
531       else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
532         graphic = GFX_MURPHY_PUSH_LEFT;
533       else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
534         graphic = GFX_MURPHY_PUSH_RIGHT;
535     }
536     else if (player->snapped)
537     {
538       if (player->MovDir == MV_LEFT)
539         graphic = GFX_MURPHY_SNAP_LEFT;
540       else if (player->MovDir == MV_RIGHT)
541         graphic = GFX_MURPHY_SNAP_RIGHT;
542       else if (player->MovDir == MV_UP)
543         graphic = GFX_MURPHY_SNAP_UP;
544       else if (player->MovDir == MV_DOWN)
545         graphic = GFX_MURPHY_SNAP_DOWN;
546     }
547     else if (action_moving)
548     {
549       if (player->MovDir == MV_LEFT)
550         graphic = GFX_MURPHY_GO_LEFT;
551       else if (player->MovDir == MV_RIGHT)
552         graphic = GFX_MURPHY_GO_RIGHT;
553       else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
554         graphic = GFX_MURPHY_GO_LEFT;
555       else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
556         graphic = GFX_MURPHY_GO_RIGHT;
557       else
558         graphic = GFX_MURPHY_GO_LEFT;
559
560       graphic += getGraphicAnimationPhase(3, 2, ANIM_PINGPONG);
561     }
562
563     if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
564       last_dir = player->MovDir;
565   }
566   else
567   {
568     if (player->MovDir == MV_LEFT)
569       graphic =
570         (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
571     else if (player->MovDir == MV_RIGHT)
572       graphic =
573         (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
574     else if (player->MovDir == MV_UP)
575       graphic = GFX_SPIELER1_UP;
576     else        /* MV_DOWN || MV_NO_MOVING */
577       graphic = GFX_SPIELER1_DOWN;
578
579     graphic += player->index_nr * 3 * HEROES_PER_LINE;
580     graphic += player->Frame;
581   }
582
583   if (player->GfxPos)
584   {
585     if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
586       sxx = player->GfxPos;
587     else
588       syy = player->GfxPos;
589   }
590
591   if (!setup.soft_scrolling && ScreenMovPos)
592     sxx = syy = 0;
593
594   DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
595
596   if (SHIELD_ON(player))
597   {
598     int graphic = (player->shield_deadly_time_left ? GFX2_SHIELD_ACTIVE :
599                    GFX2_SHIELD_PASSIVE);
600
601     DrawGraphicAnimationShiftedThruMask(sx, sy, sxx, syy, graphic,
602                                         3, 8, ANIM_PINGPONG);
603   }
604
605   if (player->Pushing && player->GfxPos)
606   {
607     int px = SCREENX(next_jx), py = SCREENY(next_jy);
608
609     if (element == EL_SOKOBAN_FIELD_EMPTY ||
610         Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
611       DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
612                                  NO_CUTTING);
613     else
614     {
615       int element = Feld[next_jx][next_jy];
616       int graphic = el2gfx(element);
617
618       if ((element == EL_ROCK ||
619            element == EL_SP_ZONK ||
620            element == EL_BD_ROCK) && sxx)
621       {
622         int phase = (player->GfxPos / (TILEX / 4));
623
624         if (player->MovDir == MV_LEFT)
625           graphic += phase;
626         else
627           graphic += (phase + 4) % 4;
628       }
629
630       DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
631     }
632   }
633
634   /* draw things in front of player (active dynamite or dynabombs) */
635
636   if (IS_ACTIVE_BOMB(element))
637   {
638     graphic = el2gfx(element);
639
640     if (element == EL_DYNAMITE_ACTIVE)
641     {
642       if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
643         phase = 6;
644     }
645     else
646     {
647       if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
648         phase = 7 - phase;
649     }
650
651     if (game.emulation == EMU_SUPAPLEX)
652       DrawGraphic(sx, sy, GFX_SP_DISK_RED);
653     else
654       DrawGraphicThruMask(sx, sy, graphic + phase);
655   }
656
657   if (player_is_moving && last_element == EL_EXPLOSION)
658   {
659     int phase = Frame[last_jx][last_jy];
660     int delay = 2;
661
662     if (phase > 2)
663       DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
664                           GFX_EXPLOSION + ((phase - 1) / delay - 1));
665   }
666
667   /* draw elements that stay over the player */
668   /* handle the field the player is leaving ... */
669   if (player_is_moving && IS_OVER_PLAYER(last_element))
670     DrawLevelField(last_jx, last_jy);
671   /* ... and the field the player is entering */
672   if (IS_OVER_PLAYER(element))
673     DrawLevelField(jx, jy);
674
675   if (setup.direct_draw)
676   {
677     int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
678     int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
679     int x_size = TILEX * (1 + ABS(jx - last_jx));
680     int y_size = TILEY * (1 + ABS(jy - last_jy));
681
682     BlitBitmap(drawto_field, window,
683                dest_x, dest_y, x_size, y_size, dest_x, dest_y);
684     SetDrawtoField(DRAW_DIRECT);
685   }
686
687   MarkTileDirty(sx,sy);
688 }
689
690 #else
691
692 void DrawPlayer(struct PlayerInfo *player)
693 {
694   int jx = player->jx, jy = player->jy;
695   int last_jx = player->last_jx, last_jy = player->last_jy;
696   int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
697   int sx = SCREENX(jx), sy = SCREENY(jy);
698   int sxx = 0, syy = 0;
699   int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
700   int graphic;
701   int frame = 0;
702   boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
703
704   if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
705     return;
706
707 #if DEBUG
708   if (!IN_LEV_FIELD(jx,jy))
709   {
710     printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
711     printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
712     printf("DrawPlayerField(): This should never happen!\n");
713     return;
714   }
715 #endif
716
717   if (element == EL_EXPLOSION)
718     return;
719
720   /* draw things in the field the player is leaving, if needed */
721
722   if (player_is_moving)
723   {
724     if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
725     {
726       DrawNewLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
727
728       if (last_element == EL_DYNAMITE_ACTIVE)
729         DrawDynamite(last_jx, last_jy);
730       else
731         DrawNewLevelFieldThruMask(last_jx, last_jy);
732     }
733     else if (last_element == EL_DYNAMITE_ACTIVE)
734       DrawDynamite(last_jx, last_jy);
735     else
736       DrawNewLevelField(last_jx, last_jy);
737
738     if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
739     {
740       if (player->GfxPos)
741       {
742         if (Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
743           DrawNewLevelElement(next_jx, next_jy, EL_SOKOBAN_FIELD_EMPTY);
744         else
745           DrawNewLevelElement(next_jx, next_jy, EL_EMPTY);
746       }
747       else
748         DrawNewLevelField(next_jx, next_jy);
749     }
750   }
751
752   if (!IN_SCR_FIELD(sx, sy))
753     return;
754
755   if (setup.direct_draw)
756     SetDrawtoField(DRAW_BUFFERED);
757
758   /* draw things behind the player, if needed */
759
760   if (Store[jx][jy])
761     DrawNewLevelElement(jx, jy, Store[jx][jy]);
762   else if (!IS_ACTIVE_BOMB(element))
763     DrawNewLevelField(jx, jy);
764   else
765     DrawNewLevelElement(jx, jy, EL_EMPTY);
766
767   /* draw player himself */
768
769   if (game.emulation == EMU_SUPAPLEX)
770   {
771     static int last_dir = MV_LEFT;
772     int action = (player->programmed_action ? player->programmed_action :
773                   player->action);
774     boolean action_moving =
775       (player_is_moving ||
776        ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
777         !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
778
779     graphic = IMG_SP_MURPHY;
780
781     if (player->Pushing)
782     {
783       if (player->MovDir == MV_LEFT)
784         graphic = IMG_SP_MURPHY_LEFT_PUSHING;
785       else if (player->MovDir == MV_RIGHT)
786         graphic = IMG_SP_MURPHY_RIGHT_PUSHING;
787       else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
788         graphic = IMG_SP_MURPHY_LEFT_PUSHING;
789       else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
790         graphic = IMG_SP_MURPHY_RIGHT_PUSHING;
791     }
792     else if (player->snapped)
793     {
794       if (player->MovDir == MV_LEFT)
795         graphic = IMG_SP_MURPHY_LEFT_SNAPPING;
796       else if (player->MovDir == MV_RIGHT)
797         graphic = IMG_SP_MURPHY_RIGHT_SNAPPING;
798       else if (player->MovDir == MV_UP)
799         graphic = IMG_SP_MURPHY_UP_SNAPPING;
800       else if (player->MovDir == MV_DOWN)
801         graphic = IMG_SP_MURPHY_DOWN_SNAPPING;
802     }
803     else if (action_moving)
804     {
805       if (player->MovDir == MV_LEFT)
806         graphic = IMG_SP_MURPHY_LEFT_MOVING;
807       else if (player->MovDir == MV_RIGHT)
808         graphic = IMG_SP_MURPHY_RIGHT_MOVING;
809       else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
810         graphic = IMG_SP_MURPHY_LEFT_MOVING;
811       else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
812         graphic = IMG_SP_MURPHY_RIGHT_MOVING;
813       else
814         graphic = IMG_SP_MURPHY_LEFT_MOVING;
815
816       frame = getNewGraphicAnimationFrame(graphic, -1);
817     }
818
819     if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
820       last_dir = player->MovDir;
821   }
822   else
823   {
824     if (player->MovDir == MV_LEFT)
825       graphic = (player->Pushing ? IMG_PLAYER1_LEFT_PUSHING :
826                  IMG_PLAYER1_LEFT_MOVING);
827     else if (player->MovDir == MV_RIGHT)
828       graphic = (player->Pushing ? IMG_PLAYER1_RIGHT_PUSHING :
829                  IMG_PLAYER1_RIGHT_MOVING);
830     else if (player->MovDir == MV_UP)
831       graphic = (player->Pushing ? IMG_PLAYER1_UP_PUSHING :
832                  IMG_PLAYER1_UP_MOVING);
833     else        /* MV_DOWN || MV_NO_MOVING */
834       graphic = (player->Pushing ? IMG_PLAYER1_DOWN_PUSHING :
835                  IMG_PLAYER1_DOWN_MOVING);
836
837     graphic = PLAYER_NR_GFX(graphic, player->index_nr);
838
839     frame = player->Frame;
840   }
841
842   if (player->GfxPos)
843   {
844     if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
845       sxx = player->GfxPos;
846     else
847       syy = player->GfxPos;
848   }
849
850   if (!setup.soft_scrolling && ScreenMovPos)
851     sxx = syy = 0;
852
853   DrawNewGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
854
855   if (SHIELD_ON(player))
856   {
857     int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
858                    IMG_SHIELD_NORMAL_ACTIVE);
859     int frame = getNewGraphicAnimationFrame(graphic, -1);
860
861     DrawNewGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
862   }
863
864   if (player->Pushing && player->GfxPos)
865   {
866     int px = SCREENX(next_jx), py = SCREENY(next_jy);
867
868     if (element == EL_SOKOBAN_FIELD_EMPTY ||
869         Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
870       DrawNewGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT, 0,
871                                  NO_CUTTING);
872     else
873     {
874       int element = Feld[next_jx][next_jy];
875       int graphic = el2img(element);
876       int frame = 0;
877
878       if ((element == EL_ROCK ||
879            element == EL_SP_ZONK ||
880            element == EL_BD_ROCK) && sxx)
881       {
882         graphic = el_dir_act2img(element, player->MovDir, GFX_ACTION_PUSHING);
883         frame = getNewGraphicAnimationFrame(graphic, player->GfxPos);
884
885         /* !!! FIX !!! */
886         if (player->MovDir == MV_LEFT)
887           frame = 3 - frame;
888
889 #if 0
890         frame = (player->GfxPos / (TILEX / 4));
891
892         if (player->MovDir == MV_RIGHT)
893           frame = (frame + 4) % 4;
894 #endif
895       }
896
897       DrawNewGraphicShifted(px, py, sxx, syy, graphic, frame,
898                             NO_CUTTING, NO_MASKING);
899     }
900   }
901
902   /* draw things in front of player (active dynamite or dynabombs) */
903
904   if (IS_ACTIVE_BOMB(element))
905   {
906     graphic = el2img(element);
907
908 #if 0
909     if (element == EL_DYNAMITE_ACTIVE)
910     {
911       if ((frame = (96 - MovDelay[jx][jy]) / 12) > 6)
912         frame = 6;
913     }
914     else
915     {
916       if ((frame = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
917         frame = 7 - frame;
918     }
919 #else
920     frame = getNewGraphicAnimationFrame(graphic, 96 - MovDelay[jx][jy]);
921 #endif
922
923     if (game.emulation == EMU_SUPAPLEX)
924       DrawNewGraphic(sx, sy, GFX_SP_DISK_RED, 0);
925     else
926       DrawNewGraphicThruMask(sx, sy, graphic, frame);
927   }
928
929   if (player_is_moving && last_element == EL_EXPLOSION)
930   {
931     int frame = Frame[last_jx][last_jy];
932     int delay = 2;
933
934     if (frame > 2)
935       DrawNewGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
936                              GFX_EXPLOSION, ((frame - 1) / delay - 1));
937   }
938
939   /* draw elements that stay over the player */
940   /* handle the field the player is leaving ... */
941   if (player_is_moving && IS_OVER_PLAYER(last_element))
942     DrawNewLevelField(last_jx, last_jy);
943   /* ... and the field the player is entering */
944   if (IS_OVER_PLAYER(element))
945     DrawNewLevelField(jx, jy);
946
947   if (setup.direct_draw)
948   {
949     int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
950     int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
951     int x_size = TILEX * (1 + ABS(jx - last_jx));
952     int y_size = TILEY * (1 + ABS(jy - last_jy));
953
954     BlitBitmap(drawto_field, window,
955                dest_x, dest_y, x_size, y_size, dest_x, dest_y);
956     SetDrawtoField(DRAW_DIRECT);
957   }
958
959   MarkTileDirty(sx,sy);
960 }
961 #endif
962
963 static int getGraphicAnimationPhase(int frames, int delay, int mode)
964 {
965   int phase;
966
967   if (mode & ANIM_PINGPONG)
968   {
969     int max_anim_frames = 2 * frames - 2;
970
971     phase = (FrameCounter % (delay * max_anim_frames)) / delay;
972     phase = (phase < frames ? phase : max_anim_frames - phase);
973   }
974   else
975     phase = (FrameCounter % (delay * frames)) / delay;
976
977   if (mode & ANIM_REVERSE)
978     phase = -phase;
979
980   return phase;
981 }
982
983 int getNewGraphicAnimationFrame(int graphic, int sync_frame)
984 {
985   int num_frames = new_graphic_info[graphic].anim_frames;
986   int delay = new_graphic_info[graphic].anim_delay;
987   int mode = new_graphic_info[graphic].anim_mode;
988   int frame = 0;
989
990   /* animation synchronized with global frame counter, not move position */
991   if (new_graphic_info[graphic].anim_global_sync || sync_frame < 0)
992     sync_frame = FrameCounter;
993
994   if (mode & ANIM_LOOP)                 /* normal, looping animation */
995   {
996     frame = (sync_frame % (delay * num_frames)) / delay;
997   }
998   else if (mode & ANIM_LINEAR)          /* normal, non-looping animation */
999   {
1000     frame = sync_frame / delay;
1001
1002     if (frame > num_frames - 1)
1003       frame = num_frames - 1;
1004   }
1005   else if (mode & ANIM_PINGPONG)        /* use border frames once */
1006   {
1007     int max_anim_frames = 2 * num_frames - 2;
1008
1009     frame = (sync_frame % (delay * max_anim_frames)) / delay;
1010     frame = (frame < num_frames ? frame : max_anim_frames - frame);
1011   }
1012   else if (mode & ANIM_PINGPONG2)       /* use border frames twice */
1013   {
1014     int max_anim_frames = 2 * num_frames;
1015
1016     frame = (sync_frame % (delay * max_anim_frames)) / delay;
1017     frame = (frame < num_frames ? frame : max_anim_frames - frame - 1);
1018   }
1019
1020   if (mode & ANIM_REVERSE)              /* use reverse animation direction */
1021     frame = num_frames - frame - 1;
1022
1023   return frame;
1024 }
1025
1026 #if 0
1027 void DrawGraphicAnimationExt(int x, int y, int graphic,
1028                              int frames, int delay, int mode, int mask_mode)
1029 {
1030   int phase = getGraphicAnimationPhase(frames, delay, mode);
1031
1032   if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1033   {
1034     if (mask_mode == USE_MASKING)
1035       DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
1036     else
1037       DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
1038   }
1039 }
1040 #endif
1041
1042 void DrawNewGraphicAnimationExt(int x, int y, int graphic, int mask_mode)
1043 {
1044 #if 0
1045   int delay = new_graphic_info[graphic].anim_delay;
1046
1047   if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1048 #else
1049   if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1050 #endif
1051   {
1052     int frame = getNewGraphicAnimationFrame(graphic, -1);
1053
1054     if (mask_mode == USE_MASKING)
1055       DrawNewGraphicThruMask(SCREENX(x), SCREENY(y), graphic, frame);
1056     else
1057       DrawNewGraphic(SCREENX(x), SCREENY(y), graphic, frame);
1058   }
1059 }
1060
1061 #if 0
1062 void DrawGraphicAnimation(int x, int y, int graphic,
1063                           int frames, int delay, int mode)
1064 {
1065   DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
1066 }
1067 #endif
1068
1069 void DrawNewGraphicAnimation(int x, int y, int graphic)
1070 {
1071   DrawNewGraphicAnimationExt(x, y, graphic, NO_MASKING);
1072 }
1073
1074 #if 0
1075 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
1076                                   int frames, int delay, int mode)
1077 {
1078   DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
1079 }
1080 #endif
1081
1082 static void DrawGraphicAnimationShiftedThruMask(int sx, int sy,
1083                                                 int sxx, int syy,
1084                                                 int graphic,
1085                                                 int frames, int delay,
1086                                                 int mode)
1087 {
1088   int phase = getGraphicAnimationPhase(frames, delay, mode);
1089
1090   DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic + phase, NO_CUTTING);
1091 }
1092
1093 #if 1
1094 void getGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1095 {
1096   if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
1097   {
1098     *bitmap = graphic_info[graphic].bitmap;
1099     *x = graphic_info[graphic].src_x;
1100     *y = graphic_info[graphic].src_y;
1101   }
1102   else if (graphic >= GFX_START_ROCKSELEMENTS &&
1103            graphic <= GFX_END_ROCKSELEMENTS)
1104   {
1105     graphic -= GFX_START_ROCKSELEMENTS;
1106     *bitmap = pix[PIX_ELEMENTS];
1107     *x = (graphic % GFX_PER_LINE) * TILEX;
1108     *y = (graphic / GFX_PER_LINE) * TILEY;
1109   }
1110   else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
1111   {
1112     graphic -= GFX_START_ROCKSHEROES;
1113     *bitmap = pix[PIX_HEROES];
1114     *x = (graphic % HEROES_PER_LINE) * TILEX;
1115     *y = (graphic / HEROES_PER_LINE) * TILEY;
1116   }
1117   else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
1118   {
1119     graphic -= GFX_START_ROCKSSP;
1120     *bitmap = pix[PIX_SP];
1121     *x = (graphic % SP_PER_LINE) * TILEX;
1122     *y = (graphic / SP_PER_LINE) * TILEY;
1123   }
1124   else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
1125   {
1126     graphic -= GFX_START_ROCKSDC;
1127     *bitmap = pix[PIX_DC];
1128     *x = (graphic % DC_PER_LINE) * TILEX;
1129     *y = (graphic / DC_PER_LINE) * TILEY;
1130   }
1131   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1132   {
1133     graphic -= GFX_START_ROCKSMORE;
1134     *bitmap = pix[PIX_MORE];
1135     *x = (graphic % MORE_PER_LINE) * TILEX;
1136     *y = (graphic / MORE_PER_LINE) * TILEY;
1137   }
1138   else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
1139   {
1140     graphic -= GFX_START_ROCKSFONT;
1141     *bitmap = pix[PIX_FONT_EM];
1142     *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
1143     *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
1144   }
1145   else
1146   {
1147     *bitmap = pix[PIX_SP];
1148     *x = 0;
1149     *y = 0;
1150   }
1151 }
1152 #endif
1153
1154 #if 0
1155 void DrawGraphic(int x, int y, int graphic)
1156 {
1157 #if DEBUG
1158   if (!IN_SCR_FIELD(x, y))
1159   {
1160     printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
1161     printf("DrawGraphic(): This should never happen!\n");
1162     return;
1163   }
1164 #endif
1165
1166   DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic);
1167   MarkTileDirty(x, y);
1168 }
1169 #endif
1170
1171 void DrawNewGraphic(int x, int y, int graphic, int frame)
1172 {
1173 #if DEBUG
1174   if (!IN_SCR_FIELD(x, y))
1175   {
1176     printf("DrawNewGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
1177     printf("DrawNewGraphic(): This should never happen!\n");
1178     return;
1179   }
1180 #endif
1181
1182   DrawNewGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1183                     graphic, frame);
1184   MarkTileDirty(x, y);
1185 }
1186
1187 void DrawOldGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
1188 {
1189   Bitmap *src_bitmap;
1190   int src_x, src_y;
1191
1192   getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1193   BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1194 }
1195
1196 void DrawNewGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
1197                        int frame)
1198 {
1199   Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
1200   int src_x = new_graphic_info[graphic].src_x;
1201   int src_y = new_graphic_info[graphic].src_y;
1202   int offset_x = new_graphic_info[graphic].offset_x;
1203   int offset_y = new_graphic_info[graphic].offset_y;
1204
1205   src_x += frame * offset_x;
1206   src_y += frame * offset_y;
1207
1208   BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1209 }
1210
1211 void DrawGraphicThruMask(int x, int y, int graphic)
1212 {
1213 #if DEBUG
1214   if (!IN_SCR_FIELD(x, y))
1215   {
1216     printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1217     printf("DrawGraphicThruMask(): This should never happen!\n");
1218     return;
1219   }
1220 #endif
1221
1222   DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic);
1223   MarkTileDirty(x, y);
1224 }
1225
1226 void DrawNewGraphicThruMask(int x, int y, int graphic, int frame)
1227 {
1228 #if DEBUG
1229   if (!IN_SCR_FIELD(x, y))
1230   {
1231     printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1232     printf("DrawGraphicThruMask(): This should never happen!\n");
1233     return;
1234   }
1235 #endif
1236
1237   DrawNewGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY,
1238                             graphic, frame);
1239   MarkTileDirty(x, y);
1240 }
1241
1242 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic)
1243 {
1244   int tile = graphic;
1245   int src_x, src_y;
1246   Bitmap *src_bitmap;
1247   GC drawing_gc;
1248
1249   if (graphic == GFX_LEERRAUM)
1250     return;
1251
1252   getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1253   drawing_gc = src_bitmap->stored_clip_gc;
1254
1255   if (tile_clipmask[tile] != None)
1256   {
1257     SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
1258     SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
1259     BlitBitmapMasked(src_bitmap, d,
1260                      src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1261   }
1262   else
1263   {
1264 #if DEBUG
1265 #ifndef TARGET_SDL
1266     printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
1267 #endif
1268 #endif
1269
1270     SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1271     BlitBitmapMasked(src_bitmap, d,
1272                      src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1273   }
1274 }
1275
1276 void DrawNewGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y,
1277                                int graphic, int frame)
1278 {
1279   Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
1280   GC drawing_gc = src_bitmap->stored_clip_gc;
1281   int src_x = new_graphic_info[graphic].src_x;
1282   int src_y = new_graphic_info[graphic].src_y;
1283   int offset_x = new_graphic_info[graphic].offset_x;
1284   int offset_y = new_graphic_info[graphic].offset_y;
1285
1286   src_x += frame * offset_x;
1287   src_y += frame * offset_y;
1288
1289   SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1290   BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1291 }
1292
1293 #if 0
1294 void DrawMiniGraphic(int x, int y, int graphic)
1295 {
1296   DrawMiniGraphicExt(drawto,
1297                      SX + x * MINI_TILEX, SY + y * MINI_TILEY, graphic);
1298   MarkTileDirty(x / 2, y / 2);
1299 }
1300 #endif
1301
1302 void DrawNewMiniGraphic(int x, int y, int graphic)
1303 {
1304   DrawNewMiniGraphicExt(drawto,
1305                         SX + x * MINI_TILEX, SY + y * MINI_TILEY, graphic);
1306   MarkTileDirty(x / 2, y / 2);
1307 }
1308
1309 #if 1
1310 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1311 {
1312   if (graphic >= GFX_START_ROCKSELEMENTS && graphic <= GFX_END_ROCKSELEMENTS)
1313   {
1314     graphic -= GFX_START_ROCKSELEMENTS;
1315     *bitmap = pix[PIX_ELEMENTS];
1316     *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
1317     *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
1318   }
1319   else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
1320   {
1321     graphic -= GFX_START_ROCKSSP;
1322     *bitmap = pix[PIX_SP];
1323     *x = MINI_SP_STARTX + (graphic % MINI_SP_PER_LINE) * MINI_TILEX;
1324     *y = MINI_SP_STARTY + (graphic / MINI_SP_PER_LINE) * MINI_TILEY;
1325   }
1326   else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
1327   {
1328     graphic -= GFX_START_ROCKSDC;
1329     *bitmap = pix[PIX_DC];
1330     *x = MINI_DC_STARTX + (graphic % MINI_DC_PER_LINE) * MINI_TILEX;
1331     *y = MINI_DC_STARTY + (graphic / MINI_DC_PER_LINE) * MINI_TILEY;
1332   }
1333   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1334   {
1335     graphic -= GFX_START_ROCKSMORE;
1336     *bitmap = pix[PIX_MORE];
1337     *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
1338     *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
1339   }
1340   else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
1341   {
1342     graphic -= GFX_START_ROCKSFONT;
1343     *bitmap = pix[PIX_FONT_EM];
1344     *x = MINI_FONT_STARTX + (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
1345     *y = MINI_FONT_STARTY + (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE;
1346   }
1347   else
1348   {
1349     *bitmap = pix[PIX_SP];
1350     *x = MINI_SP_STARTX;
1351     *y = MINI_SP_STARTY;
1352   }
1353 }
1354
1355 void getNewMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1356 {
1357   Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
1358   int mini_startx = 0;
1359   int mini_starty = src_bitmap->height * 2 / 3;
1360   int src_x = mini_startx + new_graphic_info[graphic].src_x / 2;
1361   int src_y = mini_starty + new_graphic_info[graphic].src_y / 2;
1362
1363   *bitmap = src_bitmap;
1364   *x = src_x;
1365   *y = src_y;
1366 }
1367 #endif
1368
1369 #if 0
1370 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1371 {
1372   Bitmap *bitmap;
1373   int src_x, src_y;
1374
1375   getMiniGraphicSource(graphic, &bitmap, &src_x, &src_y);
1376   BlitBitmap(bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1377 }
1378 #endif
1379
1380 void DrawNewMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1381 {
1382 #if 1
1383   Bitmap *src_bitmap;
1384   int src_x, src_y;
1385
1386   getNewMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1387 #else
1388   Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
1389   int mini_startx = src_bitmap->width  * 2 / 3;
1390   int mini_starty = src_bitmap->height * 2 / 3;
1391   int src_x = mini_startx + new_graphic_info[graphic].src_x / 2;
1392   int src_y = mini_starty + new_graphic_info[graphic].src_y / 2;
1393 #endif
1394
1395   BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1396 }
1397
1398 #if 0
1399 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
1400                         int cut_mode, int mask_mode)
1401 {
1402   int width = TILEX, height = TILEY;
1403   int cx = 0, cy = 0;
1404   int src_x, src_y, dest_x, dest_y;
1405   int tile = graphic;
1406   Bitmap *src_bitmap;
1407   GC drawing_gc;
1408
1409   if (graphic < 0)
1410   {
1411     DrawGraphic(x, y, graphic);
1412     return;
1413   }
1414
1415   if (dx || dy)                 /* Verschiebung der Grafik? */
1416   {
1417     if (x < BX1)                /* Element kommt von links ins Bild */
1418     {
1419       x = BX1;
1420       width = dx;
1421       cx = TILEX - dx;
1422       dx = 0;
1423     }
1424     else if (x > BX2)           /* Element kommt von rechts ins Bild */
1425     {
1426       x = BX2;
1427       width = -dx;
1428       dx = TILEX + dx;
1429     }
1430     else if (x==BX1 && dx < 0)  /* Element verläßt links das Bild */
1431     {
1432       width += dx;
1433       cx = -dx;
1434       dx = 0;
1435     }
1436     else if (x==BX2 && dx > 0)  /* Element verläßt rechts das Bild */
1437       width -= dx;
1438     else if (dx)                /* allg. Bewegung in x-Richtung */
1439       MarkTileDirty(x + SIGN(dx), y);
1440
1441     if (y < BY1)                /* Element kommt von oben ins Bild */
1442     {
1443       if (cut_mode==CUT_BELOW)  /* Element oberhalb des Bildes */
1444         return;
1445
1446       y = BY1;
1447       height = dy;
1448       cy = TILEY - dy;
1449       dy = 0;
1450     }
1451     else if (y > BY2)           /* Element kommt von unten ins Bild */
1452     {
1453       y = BY2;
1454       height = -dy;
1455       dy = TILEY + dy;
1456     }
1457     else if (y==BY1 && dy < 0)  /* Element verläßt oben das Bild */
1458     {
1459       height += dy;
1460       cy = -dy;
1461       dy = 0;
1462     }
1463     else if (dy > 0 && cut_mode == CUT_ABOVE)
1464     {
1465       if (y == BY2)             /* Element unterhalb des Bildes */
1466         return;
1467
1468       height = dy;
1469       cy = TILEY - dy;
1470       dy = TILEY;
1471       MarkTileDirty(x, y + 1);
1472     }                           /* Element verläßt unten das Bild */
1473     else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1474       height -= dy;
1475     else if (dy)                /* allg. Bewegung in y-Richtung */
1476       MarkTileDirty(x, y + SIGN(dy));
1477   }
1478
1479   getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1480   drawing_gc = src_bitmap->stored_clip_gc;
1481
1482   src_x += cx;
1483   src_y += cy;
1484
1485   dest_x = FX + x * TILEX + dx;
1486   dest_y = FY + y * TILEY + dy;
1487
1488 #if DEBUG
1489   if (!IN_SCR_FIELD(x,y))
1490   {
1491     printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1492     printf("DrawGraphicShifted(): This should never happen!\n");
1493     return;
1494   }
1495 #endif
1496
1497   if (mask_mode == USE_MASKING)
1498   {
1499     if (tile_clipmask[tile] != None)
1500     {
1501       SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
1502       SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
1503       BlitBitmapMasked(src_bitmap, drawto_field,
1504                        src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1505     }
1506     else
1507     {
1508 #if DEBUG
1509 #ifndef TARGET_SDL
1510       printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1511 #endif
1512 #endif
1513
1514       SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1515       BlitBitmapMasked(src_bitmap, drawto_field,
1516                        src_x, src_y, width, height, dest_x, dest_y);
1517     }
1518   }
1519   else
1520     BlitBitmap(src_bitmap, drawto_field,
1521                src_x, src_y, width, height, dest_x, dest_y);
1522
1523   MarkTileDirty(x,y);
1524 }
1525 #endif
1526
1527 void DrawNewGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
1528                         int cut_mode, int mask_mode)
1529 {
1530   Bitmap *src_bitmap;
1531   GC drawing_gc;
1532   int src_x;
1533   int src_y;
1534   int offset_x;
1535   int offset_y;
1536
1537   int width = TILEX, height = TILEY;
1538   int cx = 0, cy = 0;
1539   int dest_x, dest_y;
1540
1541   if (graphic < 0)
1542   {
1543     DrawNewGraphic(x, y, graphic, frame);
1544     return;
1545   }
1546
1547   if (dx || dy)                 /* Verschiebung der Grafik? */
1548   {
1549     if (x < BX1)                /* Element kommt von links ins Bild */
1550     {
1551       x = BX1;
1552       width = dx;
1553       cx = TILEX - dx;
1554       dx = 0;
1555     }
1556     else if (x > BX2)           /* Element kommt von rechts ins Bild */
1557     {
1558       x = BX2;
1559       width = -dx;
1560       dx = TILEX + dx;
1561     }
1562     else if (x==BX1 && dx < 0)  /* Element verläßt links das Bild */
1563     {
1564       width += dx;
1565       cx = -dx;
1566       dx = 0;
1567     }
1568     else if (x==BX2 && dx > 0)  /* Element verläßt rechts das Bild */
1569       width -= dx;
1570     else if (dx)                /* allg. Bewegung in x-Richtung */
1571       MarkTileDirty(x + SIGN(dx), y);
1572
1573     if (y < BY1)                /* Element kommt von oben ins Bild */
1574     {
1575       if (cut_mode==CUT_BELOW)  /* Element oberhalb des Bildes */
1576         return;
1577
1578       y = BY1;
1579       height = dy;
1580       cy = TILEY - dy;
1581       dy = 0;
1582     }
1583     else if (y > BY2)           /* Element kommt von unten ins Bild */
1584     {
1585       y = BY2;
1586       height = -dy;
1587       dy = TILEY + dy;
1588     }
1589     else if (y==BY1 && dy < 0)  /* Element verläßt oben das Bild */
1590     {
1591       height += dy;
1592       cy = -dy;
1593       dy = 0;
1594     }
1595     else if (dy > 0 && cut_mode == CUT_ABOVE)
1596     {
1597       if (y == BY2)             /* Element unterhalb des Bildes */
1598         return;
1599
1600       height = dy;
1601       cy = TILEY - dy;
1602       dy = TILEY;
1603       MarkTileDirty(x, y + 1);
1604     }                           /* Element verläßt unten das Bild */
1605     else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1606       height -= dy;
1607     else if (dy)                /* allg. Bewegung in y-Richtung */
1608       MarkTileDirty(x, y + SIGN(dy));
1609   }
1610
1611   src_bitmap = new_graphic_info[graphic].bitmap;
1612   src_x = new_graphic_info[graphic].src_x;
1613   src_y = new_graphic_info[graphic].src_y;
1614   offset_x = new_graphic_info[graphic].offset_x;
1615   offset_y = new_graphic_info[graphic].offset_y;
1616
1617   drawing_gc = src_bitmap->stored_clip_gc;
1618
1619   src_x += frame * offset_x;
1620   src_y += frame * offset_y;
1621
1622   src_x += cx;
1623   src_y += cy;
1624
1625   dest_x = FX + x * TILEX + dx;
1626   dest_y = FY + y * TILEY + dy;
1627
1628 #if DEBUG
1629   if (!IN_SCR_FIELD(x,y))
1630   {
1631     printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1632     printf("DrawGraphicShifted(): This should never happen!\n");
1633     return;
1634   }
1635 #endif
1636
1637   if (mask_mode == USE_MASKING)
1638   {
1639     SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1640     BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1641                      dest_x, dest_y);
1642   }
1643   else
1644     BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1645                dest_x, dest_y);
1646
1647   MarkTileDirty(x,y);
1648 }
1649
1650 #if 0
1651 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1652                                 int cut_mode)
1653 {
1654   DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1655 }
1656 #endif
1657
1658 void DrawNewGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1659                                    int frame, int cut_mode)
1660 {
1661   DrawNewGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1662 }
1663
1664 #if 0
1665 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1666                           int cut_mode, int mask_mode)
1667 {
1668   int ux = LEVELX(x), uy = LEVELY(y);
1669   int graphic = el2gfx(element);
1670   int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1671   int phase4 = phase8 / 2;
1672   int phase2  = phase8 / 4;
1673   int dir = MovDir[ux][uy];
1674
1675   if (element == EL_PACMAN || element == EL_BUG || element == EL_SPACESHIP)
1676   {
1677     graphic += 1 * !phase2;
1678
1679     if (dir == MV_UP)
1680       graphic += 1 * 2;
1681     else if (dir == MV_LEFT)
1682       graphic += 2 * 2;
1683     else if (dir == MV_DOWN)
1684       graphic += 3 * 2;
1685   }
1686   else if (element == EL_SP_SNIKSNAK)
1687   {
1688     if (dir == MV_LEFT)
1689       graphic = GFX_SP_SNIKSNAK_LEFT;
1690     else if (dir == MV_RIGHT)
1691       graphic = GFX_SP_SNIKSNAK_RIGHT;
1692     else if (dir == MV_UP)
1693       graphic = GFX_SP_SNIKSNAK_UP;
1694     else
1695       graphic = GFX_SP_SNIKSNAK_DOWN;
1696
1697     graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1698   }
1699   else if (element == EL_SP_ELECTRON)
1700   {
1701     graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1702   }
1703   else if (element == EL_MOLE || element == EL_PENGUIN ||
1704            element == EL_PIG || element == EL_DRAGON)
1705   {
1706     if (dir == MV_LEFT)
1707       graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1708                  element == EL_PENGUIN ? GFX_PINGUIN_LEFT :
1709                  element == EL_PIG ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1710     else if (dir == MV_RIGHT)
1711       graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1712                  element == EL_PENGUIN ? GFX_PINGUIN_RIGHT :
1713                  element == EL_PIG ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1714     else if (dir == MV_UP)
1715       graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1716                  element == EL_PENGUIN ? GFX_PINGUIN_UP :
1717                  element == EL_PIG ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1718     else
1719       graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1720                  element == EL_PENGUIN ? GFX_PINGUIN_DOWN :
1721                  element == EL_PIG ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1722
1723     graphic += phase4;
1724   }
1725   else if (element == EL_SATELLITE)
1726   {
1727     graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1728   }
1729   else if (element == EL_ACID)
1730   {
1731     graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_LOOP);
1732   }
1733   else if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY)
1734   {
1735     graphic += !phase2;
1736   }
1737   else if (element == EL_BALLOON)
1738   {
1739     graphic += phase4;
1740   }
1741   else if ((element == EL_ROCK ||
1742             element == EL_SP_ZONK ||
1743             element == EL_BD_ROCK ||
1744             element == EL_SP_INFOTRON ||
1745             IS_GEM(element))
1746            && !cut_mode)
1747   {
1748     if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1749     {
1750       if (element == EL_ROCK ||
1751           element == EL_SP_ZONK ||
1752           element == EL_BD_ROCK)
1753       {
1754         if (dir == MV_LEFT)
1755           graphic += (4 - phase4) % 4;
1756         else if (dir == MV_RIGHT)
1757           graphic += phase4;
1758         else
1759           graphic += phase2 * 2;
1760       }
1761       else if (element != EL_SP_INFOTRON)
1762         graphic += phase2;
1763     }
1764   }
1765   else if (element == EL_MAGIC_WALL_ACTIVE ||
1766            element == EL_MAGIC_WALL_EMPTYING ||
1767            element == EL_BD_MAGIC_WALL_ACTIVE ||
1768            element == EL_BD_MAGIC_WALL_EMPTYING ||
1769            element == EL_MAGIC_WALL_FULL ||
1770            element == EL_BD_MAGIC_WALL_FULL)
1771   {
1772     graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1773   }
1774   else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1775   {
1776     graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1777     graphic += (x + 2 * y + 4) % 4;
1778   }
1779   else if (element == EL_WALL_GROWING)
1780   {
1781     boolean links_massiv = FALSE, rechts_massiv = FALSE;
1782
1783     if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1784       links_massiv = TRUE;
1785     if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1786       rechts_massiv = TRUE;
1787
1788     if (links_massiv && rechts_massiv)
1789       graphic = GFX_MAUERWERK;
1790     else if (links_massiv)
1791       graphic = GFX_MAUER_R;
1792     else if (rechts_massiv)
1793       graphic = GFX_MAUER_L;
1794   }
1795 #if 0
1796   else if ((element == EL_INVISIBLE_STEELWALL ||
1797             element == EL_INVISIBLE_WALL ||
1798             element == EL_INVISIBLE_SAND) && game.light_time_left)
1799   {
1800     graphic = (element == EL_INVISIBLE_STEELWALL ? GFX_INVISIBLE_STEEL_ON :
1801                element == EL_INVISIBLE_WALL ? GFX_UNSICHTBAR_ON :
1802                GFX_SAND_INVISIBLE_ON);
1803   }
1804 #endif
1805
1806   if (dx || dy)
1807     DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1808   else if (mask_mode == USE_MASKING)
1809     DrawGraphicThruMask(x, y, graphic);
1810   else
1811     DrawGraphic(x, y, graphic);
1812 }
1813 #endif
1814
1815 inline static int getFramePosition(int x, int y)
1816 {
1817   int element = Feld[x][y];
1818   int frame_pos = -1;
1819
1820   if (element == EL_QUICKSAND_FULL ||
1821       element == EL_MAGIC_WALL_FULL ||
1822       element == EL_BD_MAGIC_WALL_FULL)
1823     frame_pos = -1;
1824   else if (IS_MOVING(x, y) || CAN_MOVE(element) || CAN_FALL(element))
1825     frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1826
1827   return frame_pos;
1828 }
1829
1830 inline static int getGfxAction(int x, int y)
1831 {
1832   int gfx_action = GFX_ACTION_DEFAULT;
1833
1834   if (GfxAction[x][y] != GFX_ACTION_DEFAULT)
1835     gfx_action = GfxAction[x][y];
1836   else if (IS_MOVING(x, y))
1837     gfx_action = GFX_ACTION_MOVING;
1838
1839   return gfx_action;
1840 }
1841
1842 void DrawNewScreenElementExt(int x, int y, int dx, int dy, int element,
1843                              int cut_mode, int mask_mode)
1844 {
1845   int ux = LEVELX(x), uy = LEVELY(y);
1846   int move_dir = MovDir[ux][uy];
1847   int move_pos = getFramePosition(ux, uy);
1848   int gfx_action = getGfxAction(ux, uy);
1849   int graphic = el_dir_act2img(element, move_dir, gfx_action);
1850   int frame = getNewGraphicAnimationFrame(graphic, move_pos);
1851
1852   if (element == EL_WALL_GROWING)
1853   {
1854     boolean left_stopped = FALSE, right_stopped = FALSE;
1855
1856     if (!IN_LEV_FIELD(ux - 1, uy) || IS_MAUER(Feld[ux - 1][uy]))
1857       left_stopped = TRUE;
1858     if (!IN_LEV_FIELD(ux + 1, uy) || IS_MAUER(Feld[ux + 1][uy]))
1859       right_stopped = TRUE;
1860
1861     if (left_stopped && right_stopped)
1862       graphic = IMG_WALL;
1863     else if (left_stopped)
1864     {
1865       graphic = IMG_WALL_GROWING_ACTIVE_RIGHT;
1866       frame = new_graphic_info[graphic].anim_frames - 1;
1867     }
1868     else if (right_stopped)
1869     {
1870       graphic = IMG_WALL_GROWING_ACTIVE_LEFT;
1871       frame = new_graphic_info[graphic].anim_frames - 1;
1872     }
1873   }
1874 #if 0
1875   else if ((element == EL_ROCK ||
1876             element == EL_SP_ZONK ||
1877             element == EL_BD_ROCK ||
1878             element == EL_SP_INFOTRON ||
1879             IS_GEM(element))
1880            && !cut_mode)
1881   {
1882     if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1883     {
1884       if (element == EL_ROCK ||
1885           element == EL_SP_ZONK ||
1886           element == EL_BD_ROCK)
1887       {
1888         if (move_dir == MV_LEFT)
1889           graphic += (4 - phase4) % 4;
1890         else if (move_dir == MV_RIGHT)
1891           graphic += phase4;
1892         else
1893           graphic += phase2 * 2;
1894       }
1895       else if (element != EL_SP_INFOTRON)
1896         graphic += phase2;
1897     }
1898   }
1899 #endif
1900   else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1901   {
1902     graphic = (element == EL_BD_AMOEBA ? IMG_BD_AMOEBA_PART1 :
1903                element == EL_AMOEBA_WET ? IMG_AMOEBA_WET_PART1 :
1904                element == EL_AMOEBA_DRY ? IMG_AMOEBA_DRY_PART1 :
1905                element == EL_AMOEBA_FULL ? IMG_AMOEBA_FULL_PART1 :
1906                IMG_AMOEBA_DEAD_PART1);
1907
1908     graphic += (x + 2 * y + 4) % 4;
1909   }
1910
1911   if (dx || dy)
1912     DrawNewGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1913   else if (mask_mode == USE_MASKING)
1914     DrawNewGraphicThruMask(x, y, graphic, frame);
1915   else
1916     DrawNewGraphic(x, y, graphic, frame);
1917 }
1918
1919 #if 0
1920 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1921                          int cut_mode, int mask_mode)
1922 {
1923   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1924     DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1925                          cut_mode, mask_mode);
1926 }
1927 #endif
1928
1929 void DrawNewLevelElementExt(int x, int y, int dx, int dy, int element,
1930                          int cut_mode, int mask_mode)
1931 {
1932   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1933     DrawNewScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1934                          cut_mode, mask_mode);
1935 }
1936
1937 #if 0
1938 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1939                               int cut_mode)
1940 {
1941   DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1942 }
1943 #endif
1944
1945 void DrawNewScreenElementShifted(int x, int y, int dx, int dy, int element,
1946                               int cut_mode)
1947 {
1948   DrawNewScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1949 }
1950
1951 #if 0
1952 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1953                              int cut_mode)
1954 {
1955   DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1956 }
1957 #endif
1958
1959 void DrawNewLevelElementShifted(int x, int y, int dx, int dy, int element,
1960                              int cut_mode)
1961 {
1962   DrawNewLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1963 }
1964
1965 #if 0
1966 void DrawScreenElementThruMask(int x, int y, int element)
1967 {
1968   DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1969 }
1970
1971 void DrawNewScreenElementThruMask(int x, int y, int element)
1972 {
1973   DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1974 }
1975 #endif
1976
1977 #if 0
1978 void DrawLevelElementThruMask(int x, int y, int element)
1979 {
1980   DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1981 }
1982 #endif
1983
1984 void DrawNewLevelElementThruMask(int x, int y, int element)
1985 {
1986   DrawNewLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1987 }
1988
1989 #if 0
1990 void DrawLevelFieldThruMask(int x, int y)
1991 {
1992   DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1993 }
1994 #endif
1995
1996 void DrawNewLevelFieldThruMask(int x, int y)
1997 {
1998   DrawNewLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1999 }
2000
2001 #if 0
2002 void ErdreichAnbroeckeln(int x, int y)
2003 {
2004   Bitmap *src_bitmap;
2005   int src_x, src_y;
2006   int i, width, height, cx,cy;
2007   int ux = LEVELX(x), uy = LEVELY(y);
2008   int element, graphic;
2009   int snip = 4;
2010   static int xy[4][2] =
2011   {
2012     { 0, -1 },
2013     { -1, 0 },
2014     { +1, 0 },
2015     { 0, +1 }
2016   };
2017
2018   if (!IN_LEV_FIELD(ux, uy))
2019     return;
2020
2021   element = Feld[ux][uy];
2022
2023   if (element == EL_SAND ||
2024       element == EL_LANDMINE ||
2025       element == EL_TRAP ||
2026       element == EL_TRAP_ACTIVE)
2027   {
2028     if (!IN_SCR_FIELD(x, y))
2029       return;
2030
2031     graphic = GFX_ERDENRAND;
2032
2033     getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
2034
2035     for(i=0; i<4; i++)
2036     {
2037       int uxx, uyy;
2038
2039       uxx = ux + xy[i][0];
2040       uyy = uy + xy[i][1];
2041       if (!IN_LEV_FIELD(uxx, uyy))
2042         element = EL_STEELWALL;
2043       else
2044         element = Feld[uxx][uyy];
2045
2046       if (element == EL_SAND ||
2047           element == EL_LANDMINE ||
2048           element == EL_TRAP ||
2049           element == EL_TRAP_ACTIVE)
2050         continue;
2051
2052       if (i == 1 || i == 2)
2053       {
2054         width = snip;
2055         height = TILEY;
2056         cx = (i == 2 ? TILEX - snip : 0);
2057         cy = 0;
2058       }
2059       else
2060       {
2061         width = TILEX;
2062         height = snip;
2063         cx = 0;
2064         cy = (i == 3 ? TILEY - snip : 0);
2065       }
2066
2067       BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
2068                  width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
2069     }
2070
2071     MarkTileDirty(x, y);
2072   }
2073   else
2074   {
2075     graphic = GFX_ERDENRAND;
2076
2077     getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
2078
2079     for(i=0; i<4; i++)
2080     {
2081       int xx, yy, uxx, uyy;
2082
2083       xx = x + xy[i][0];
2084       yy = y + xy[i][1];
2085       uxx = ux + xy[i][0];
2086       uyy = uy + xy[i][1];
2087
2088       if (!IN_LEV_FIELD(uxx, uyy) ||
2089           (Feld[uxx][uyy] != EL_SAND &&
2090            Feld[uxx][uyy] != EL_LANDMINE &&
2091            Feld[uxx][uyy] != EL_TRAP &&
2092            Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
2093           !IN_SCR_FIELD(xx, yy))
2094         continue;
2095
2096       if (i == 1 || i == 2)
2097       {
2098         width = snip;
2099         height = TILEY;
2100         cx = (i == 1 ? TILEX - snip : 0);
2101         cy = 0;
2102       }
2103       else
2104       {
2105         width = TILEX;
2106         height = snip;
2107         cx = 0;
2108         cy = (i==0 ? TILEY-snip : 0);
2109       }
2110
2111       BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
2112                  width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
2113
2114       MarkTileDirty(xx, yy);
2115     }
2116   }
2117 }
2118 #endif
2119
2120 void DrawCrumbledSand(int x, int y)
2121 {
2122   Bitmap *src_bitmap;
2123   int src_x, src_y;
2124   int i, width, height, cx,cy;
2125   int ux = LEVELX(x), uy = LEVELY(y);
2126   int element, graphic;
2127   int snip = 4;
2128   static int xy[4][2] =
2129   {
2130     { 0, -1 },
2131     { -1, 0 },
2132     { +1, 0 },
2133     { 0, +1 }
2134   };
2135
2136   if (!IN_LEV_FIELD(ux, uy))
2137     return;
2138
2139   element = Feld[ux][uy];
2140
2141   if (element == EL_SAND ||
2142       element == EL_LANDMINE ||
2143       element == EL_TRAP ||
2144       element == EL_TRAP_ACTIVE)
2145   {
2146     if (!IN_SCR_FIELD(x, y))
2147       return;
2148
2149     graphic = IMG_SAND_CRUMBLED;
2150
2151     src_bitmap = new_graphic_info[graphic].bitmap;
2152     src_x = new_graphic_info[graphic].src_x;
2153     src_y = new_graphic_info[graphic].src_y;
2154
2155     for(i=0; i<4; i++)
2156     {
2157       int uxx, uyy;
2158
2159       uxx = ux + xy[i][0];
2160       uyy = uy + xy[i][1];
2161       if (!IN_LEV_FIELD(uxx, uyy))
2162         element = EL_STEELWALL;
2163       else
2164         element = Feld[uxx][uyy];
2165
2166       if (element == EL_SAND ||
2167           element == EL_LANDMINE ||
2168           element == EL_TRAP ||
2169           element == EL_TRAP_ACTIVE)
2170         continue;
2171
2172       if (i == 1 || i == 2)
2173       {
2174         width = snip;
2175         height = TILEY;
2176         cx = (i == 2 ? TILEX - snip : 0);
2177         cy = 0;
2178       }
2179       else
2180       {
2181         width = TILEX;
2182         height = snip;
2183         cx = 0;
2184         cy = (i == 3 ? TILEY - snip : 0);
2185       }
2186
2187       BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
2188                  width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
2189     }
2190
2191     MarkTileDirty(x, y);
2192   }
2193   else
2194   {
2195     graphic = IMG_SAND_CRUMBLED;
2196
2197     src_bitmap = new_graphic_info[graphic].bitmap;
2198     src_x = new_graphic_info[graphic].src_x;
2199     src_y = new_graphic_info[graphic].src_y;
2200
2201     for(i=0; i<4; i++)
2202     {
2203       int xx, yy, uxx, uyy;
2204
2205       xx = x + xy[i][0];
2206       yy = y + xy[i][1];
2207       uxx = ux + xy[i][0];
2208       uyy = uy + xy[i][1];
2209
2210       if (!IN_LEV_FIELD(uxx, uyy) ||
2211           (Feld[uxx][uyy] != EL_SAND &&
2212            Feld[uxx][uyy] != EL_LANDMINE &&
2213            Feld[uxx][uyy] != EL_TRAP &&
2214            Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
2215           !IN_SCR_FIELD(xx, yy))
2216         continue;
2217
2218       if (i == 1 || i == 2)
2219       {
2220         width = snip;
2221         height = TILEY;
2222         cx = (i == 1 ? TILEX - snip : 0);
2223         cy = 0;
2224       }
2225       else
2226       {
2227         width = TILEX;
2228         height = snip;
2229         cx = 0;
2230         cy = (i==0 ? TILEY-snip : 0);
2231       }
2232
2233       BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
2234                  width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
2235
2236       MarkTileDirty(xx, yy);
2237     }
2238   }
2239 }
2240
2241 #if 0
2242 void DrawScreenElement(int x, int y, int element)
2243 {
2244   DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
2245   ErdreichAnbroeckeln(x, y);
2246 }
2247 #endif
2248
2249 void DrawNewScreenElement(int x, int y, int element)
2250 {
2251   DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
2252   DrawCrumbledSand(x, y);
2253 }
2254
2255
2256 #if 0
2257 void DrawLevelElement(int x, int y, int element)
2258 {
2259   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2260     DrawScreenElement(SCREENX(x), SCREENY(y), element);
2261 }
2262 #endif
2263
2264 void DrawNewLevelElement(int x, int y, int element)
2265 {
2266   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2267     DrawNewScreenElement(SCREENX(x), SCREENY(y), element);
2268 }
2269
2270 #if 0
2271 void DrawScreenField(int x, int y)
2272 {
2273   int ux = LEVELX(x), uy = LEVELY(y);
2274   int element, content;
2275
2276   if (!IN_LEV_FIELD(ux, uy))
2277   {
2278     if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
2279       element = EL_EMPTY;
2280     else
2281       element = BorderElement;
2282
2283     DrawScreenElement(x, y, element);
2284     return;
2285   }
2286
2287   element = Feld[ux][uy];
2288   content = Store[ux][uy];
2289
2290   if (IS_MOVING(ux, uy))
2291   {
2292     int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
2293     boolean cut_mode = NO_CUTTING;
2294
2295     if (element == EL_QUICKSAND_EMPTYING ||
2296         element == EL_MAGIC_WALL_EMPTYING ||
2297         element == EL_BD_MAGIC_WALL_EMPTYING ||
2298         element == EL_AMOEBA_DRIPPING)
2299       cut_mode = CUT_ABOVE;
2300     else if (element == EL_QUICKSAND_FILLING ||
2301              element == EL_MAGIC_WALL_FILLING ||
2302              element == EL_BD_MAGIC_WALL_FILLING)
2303       cut_mode = CUT_BELOW;
2304
2305     if (cut_mode == CUT_ABOVE)
2306       DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
2307     else
2308       DrawScreenElement(x, y, EL_EMPTY);
2309
2310     if (horiz_move)
2311       DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
2312     else if (cut_mode == NO_CUTTING)
2313       DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
2314     else
2315       DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
2316
2317     if (content == EL_ACID)
2318       DrawLevelElementThruMask(ux, uy + 1, EL_ACID);
2319   }
2320   else if (IS_BLOCKED(ux, uy))
2321   {
2322     int oldx, oldy;
2323     int sx, sy;
2324     int horiz_move;
2325     boolean cut_mode = NO_CUTTING;
2326     int element_old, content_old;
2327
2328     Blocked2Moving(ux, uy, &oldx, &oldy);
2329     sx = SCREENX(oldx);
2330     sy = SCREENY(oldy);
2331     horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
2332                   MovDir[oldx][oldy] == MV_RIGHT);
2333
2334     element_old = Feld[oldx][oldy];
2335     content_old = Store[oldx][oldy];
2336
2337     if (element_old == EL_QUICKSAND_EMPTYING ||
2338         element_old == EL_MAGIC_WALL_EMPTYING ||
2339         element_old == EL_BD_MAGIC_WALL_EMPTYING ||
2340         element_old == EL_AMOEBA_DRIPPING)
2341       cut_mode = CUT_ABOVE;
2342
2343     DrawScreenElement(x, y, EL_EMPTY);
2344
2345     if (horiz_move)
2346       DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
2347                                NO_CUTTING);
2348     else if (cut_mode == NO_CUTTING)
2349       DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
2350                                cut_mode);
2351     else
2352       DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
2353                                cut_mode);
2354   }
2355   else if (IS_DRAWABLE(element))
2356     DrawScreenElement(x, y, element);
2357   else
2358     DrawScreenElement(x, y, EL_EMPTY);
2359 }
2360 #endif
2361
2362 void DrawNewScreenField(int x, int y)
2363 {
2364   int ux = LEVELX(x), uy = LEVELY(y);
2365   int element, content;
2366
2367   if (!IN_LEV_FIELD(ux, uy))
2368   {
2369     if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
2370       element = EL_EMPTY;
2371     else
2372       element = BorderElement;
2373
2374     DrawNewScreenElement(x, y, element);
2375     return;
2376   }
2377
2378   element = Feld[ux][uy];
2379   content = Store[ux][uy];
2380
2381   if (IS_MOVING(ux, uy))
2382   {
2383     int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
2384     boolean cut_mode = NO_CUTTING;
2385
2386     if (element == EL_QUICKSAND_EMPTYING ||
2387         element == EL_MAGIC_WALL_EMPTYING ||
2388         element == EL_BD_MAGIC_WALL_EMPTYING ||
2389         element == EL_AMOEBA_DRIPPING)
2390       cut_mode = CUT_ABOVE;
2391     else if (element == EL_QUICKSAND_FILLING ||
2392              element == EL_MAGIC_WALL_FILLING ||
2393              element == EL_BD_MAGIC_WALL_FILLING)
2394       cut_mode = CUT_BELOW;
2395
2396     if (cut_mode == CUT_ABOVE)
2397       DrawNewScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
2398     else
2399       DrawNewScreenElement(x, y, EL_EMPTY);
2400
2401     if (horiz_move)
2402       DrawNewScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
2403     else if (cut_mode == NO_CUTTING)
2404       DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
2405     else
2406       DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
2407
2408     if (content == EL_ACID)
2409       DrawNewLevelElementThruMask(ux, uy + 1, EL_ACID);
2410   }
2411   else if (IS_BLOCKED(ux, uy))
2412   {
2413     int oldx, oldy;
2414     int sx, sy;
2415     int horiz_move;
2416     boolean cut_mode = NO_CUTTING;
2417     int element_old, content_old;
2418
2419     Blocked2Moving(ux, uy, &oldx, &oldy);
2420     sx = SCREENX(oldx);
2421     sy = SCREENY(oldy);
2422     horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
2423                   MovDir[oldx][oldy] == MV_RIGHT);
2424
2425     element_old = Feld[oldx][oldy];
2426     content_old = Store[oldx][oldy];
2427
2428     if (element_old == EL_QUICKSAND_EMPTYING ||
2429         element_old == EL_MAGIC_WALL_EMPTYING ||
2430         element_old == EL_BD_MAGIC_WALL_EMPTYING ||
2431         element_old == EL_AMOEBA_DRIPPING)
2432       cut_mode = CUT_ABOVE;
2433
2434     DrawNewScreenElement(x, y, EL_EMPTY);
2435
2436     if (horiz_move)
2437       DrawNewScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
2438                                NO_CUTTING);
2439     else if (cut_mode == NO_CUTTING)
2440       DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
2441                                cut_mode);
2442     else
2443       DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
2444                                cut_mode);
2445   }
2446   else if (IS_DRAWABLE(element))
2447     DrawNewScreenElement(x, y, element);
2448   else
2449     DrawNewScreenElement(x, y, EL_EMPTY);
2450 }
2451
2452 #if 0
2453 void DrawLevelField(int x, int y)
2454 {
2455   if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2456     DrawScreenField(SCREENX(x), SCREENY(y));
2457   else if (IS_MOVING(x, y))
2458   {
2459     int newx,newy;
2460
2461     Moving2Blocked(x, y, &newx, &newy);
2462     if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
2463       DrawScreenField(SCREENX(newx), SCREENY(newy));
2464   }
2465   else if (IS_BLOCKED(x, y))
2466   {
2467     int oldx, oldy;
2468
2469     Blocked2Moving(x, y, &oldx, &oldy);
2470     if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
2471       DrawScreenField(SCREENX(oldx), SCREENY(oldy));
2472   }
2473 }
2474 #endif
2475
2476 void DrawNewLevelField(int x, int y)
2477 {
2478   if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2479     DrawNewScreenField(SCREENX(x), SCREENY(y));
2480   else if (IS_MOVING(x, y))
2481   {
2482     int newx,newy;
2483
2484     Moving2Blocked(x, y, &newx, &newy);
2485     if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
2486       DrawNewScreenField(SCREENX(newx), SCREENY(newy));
2487   }
2488   else if (IS_BLOCKED(x, y))
2489   {
2490     int oldx, oldy;
2491
2492     Blocked2Moving(x, y, &oldx, &oldy);
2493     if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
2494       DrawNewScreenField(SCREENX(oldx), SCREENY(oldy));
2495   }
2496 }
2497
2498 #if 0
2499 void DrawMiniElement(int x, int y, int element)
2500 {
2501   int graphic;
2502
2503   if (!element)
2504   {
2505     DrawMiniGraphic(x, y, -1);
2506     return;
2507   }
2508
2509   graphic = el2gfx(element);
2510   DrawMiniGraphic(x, y, graphic);
2511 }
2512 #endif
2513
2514 void DrawNewMiniElement(int x, int y, int element)
2515 {
2516   int graphic;
2517
2518 #if 0
2519   if (!element)
2520   {
2521     DrawNewMiniGraphic(x, y, -1);
2522     return;
2523   }
2524 #endif
2525
2526   graphic = el2img(element);
2527   DrawNewMiniGraphic(x, y, graphic);
2528 }
2529
2530 #if 0
2531 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
2532 {
2533   int x = sx + scroll_x, y = sy + scroll_y;
2534
2535   if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
2536     DrawMiniElement(sx, sy, EL_EMPTY);
2537   else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
2538     DrawMiniElement(sx, sy, Feld[x][y]);
2539   else
2540   {
2541     int steel_type, steel_position;
2542     int border[6][2] =
2543     {
2544       { GFX_VSTEEL_UPPER_LEFT,  GFX_ISTEEL_UPPER_LEFT  },
2545       { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
2546       { GFX_VSTEEL_LOWER_LEFT,  GFX_ISTEEL_LOWER_LEFT  },
2547       { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
2548       { GFX_VSTEEL_VERTICAL,    GFX_ISTEEL_VERTICAL    },
2549       { GFX_VSTEEL_HORIZONTAL,  GFX_ISTEEL_HORIZONTAL  }
2550     };
2551
2552     steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
2553     steel_position = (x == -1 && y == -1                        ? 0 :
2554                       x == lev_fieldx && y == -1                ? 1 :
2555                       x == -1 && y == lev_fieldy                ? 2 :
2556                       x == lev_fieldx && y == lev_fieldy        ? 3 :
2557                       x == -1 || x == lev_fieldx                ? 4 :
2558                       y == -1 || y == lev_fieldy                ? 5 : -1);
2559
2560     if (steel_position != -1)
2561       DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
2562   }
2563 }
2564 #endif
2565
2566 void DrawNewMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
2567 {
2568   int x = sx + scroll_x, y = sy + scroll_y;
2569
2570   if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
2571     DrawNewMiniElement(sx, sy, EL_EMPTY);
2572   else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
2573     DrawNewMiniElement(sx, sy, Feld[x][y]);
2574   else
2575   {
2576     int steel_type, steel_position;
2577     int border[6][2] =
2578     {
2579       { IMG_STEELWALL_TOPLEFT,          IMG_INVISIBLE_STEELWALL_TOPLEFT     },
2580       { IMG_STEELWALL_TOPRIGHT,         IMG_INVISIBLE_STEELWALL_TOPRIGHT    },
2581       { IMG_STEELWALL_BOTTOMLEFT,       IMG_INVISIBLE_STEELWALL_BOTTOMLEFT  },
2582       { IMG_STEELWALL_BOTTOMRIGHT,      IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT },
2583       { IMG_STEELWALL_VERTICAL,         IMG_INVISIBLE_STEELWALL_VERTICAL    },
2584       { IMG_STEELWALL_HORIZONTAL,       IMG_INVISIBLE_STEELWALL_HORIZONTAL  }
2585     };
2586
2587     steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
2588     steel_position = (x == -1 && y == -1                        ? 0 :
2589                       x == lev_fieldx && y == -1                ? 1 :
2590                       x == -1 && y == lev_fieldy                ? 2 :
2591                       x == lev_fieldx && y == lev_fieldy        ? 3 :
2592                       x == -1 || x == lev_fieldx                ? 4 :
2593                       y == -1 || y == lev_fieldy                ? 5 : -1);
2594
2595     if (steel_position != -1)
2596       DrawNewMiniGraphic(sx, sy, border[steel_position][steel_type]);
2597   }
2598 }
2599
2600 #if 0
2601 void DrawMicroElement(int xpos, int ypos, int element)
2602 {
2603   int graphic;
2604
2605   if (element == EL_EMPTY)
2606     return;
2607
2608   graphic = el2gfx(element);
2609
2610   if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
2611   {
2612     graphic -= GFX_START_ROCKSSP;
2613     BlitBitmap(pix[PIX_SP], drawto,
2614                MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
2615                MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
2616                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2617   }
2618   else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
2619   {
2620     graphic -= GFX_START_ROCKSDC;
2621     BlitBitmap(pix[PIX_DC], drawto,
2622                MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
2623                MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
2624                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2625   }
2626   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
2627   {
2628     graphic -= GFX_START_ROCKSMORE;
2629     BlitBitmap(pix[PIX_MORE], drawto,
2630                MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE)*MICRO_TILEX,
2631                MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE)*MICRO_TILEY,
2632                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2633   }
2634   else if (graphic >= GFX_CHAR_START && graphic <= GFX_CHAR_END)
2635   {
2636     graphic -= GFX_CHAR_START;
2637     BlitBitmap(pix[PIX_FONT_EM], drawto,
2638                MICRO_FONT_STARTX + (graphic % MICRO_GFX_PER_LINE)* MICRO_TILEX,
2639                MICRO_FONT_STARTY + (graphic / MICRO_GFX_PER_LINE)* MICRO_TILEY,
2640                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2641   }
2642   else
2643     BlitBitmap(pix[PIX_ELEMENTS], drawto,
2644                MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
2645                MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
2646                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2647 }
2648 #endif
2649
2650 void getNewMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
2651 {
2652   Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
2653   int mini_startx = src_bitmap->width * 3 / 4;
2654   int mini_starty = src_bitmap->height * 2 / 3;
2655   int src_x = mini_startx + new_graphic_info[graphic].src_x / 8;
2656   int src_y = mini_starty + new_graphic_info[graphic].src_y / 8;
2657
2658   *bitmap = src_bitmap;
2659   *x = src_x;
2660   *y = src_y;
2661 }
2662
2663 void DrawNewMicroElement(int xpos, int ypos, int element)
2664 {
2665   Bitmap *src_bitmap;
2666   int src_x, src_y;
2667   int graphic;
2668
2669   if (element == EL_EMPTY)
2670     return;
2671
2672   graphic = el2img(element);
2673
2674   getNewMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
2675   BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
2676              xpos, ypos);
2677 }
2678
2679 void DrawLevel()
2680 {
2681   int x,y;
2682
2683   ClearWindow();
2684
2685   for(x=BX1; x<=BX2; x++)
2686     for(y=BY1; y<=BY2; y++)
2687       DrawNewScreenField(x, y);
2688
2689   redraw_mask |= REDRAW_FIELD;
2690 }
2691
2692 #if 0
2693 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
2694 {
2695   int x,y;
2696
2697   for(x=0; x<size_x; x++)
2698     for(y=0; y<size_y; y++)
2699       DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
2700
2701   redraw_mask |= REDRAW_FIELD;
2702 }
2703 #endif
2704
2705 void DrawNewMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
2706 {
2707   int x,y;
2708
2709   for(x=0; x<size_x; x++)
2710     for(y=0; y<size_y; y++)
2711       DrawNewMiniElementOrWall(x, y, scroll_x, scroll_y);
2712
2713   redraw_mask |= REDRAW_FIELD;
2714 }
2715
2716 #if 0
2717 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
2718 {
2719   int x, y;
2720
2721   ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
2722
2723   if (lev_fieldx < STD_LEV_FIELDX)
2724     xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
2725   if (lev_fieldy < STD_LEV_FIELDY)
2726     ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
2727
2728   xpos += MICRO_TILEX;
2729   ypos += MICRO_TILEY;
2730
2731   for(x=-1; x<=STD_LEV_FIELDX; x++)
2732   {
2733     for(y=-1; y<=STD_LEV_FIELDY; y++)
2734     {
2735       int lx = from_x + x, ly = from_y + y;
2736
2737       if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
2738         DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2739                          Ur[lx][ly]);
2740       else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
2741         DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2742                          BorderElement);
2743     }
2744   }
2745
2746   redraw_mask |= REDRAW_MICROLEVEL;
2747 }
2748 #endif
2749
2750 static void DrawNewMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
2751 {
2752   int x, y;
2753
2754   ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
2755
2756   if (lev_fieldx < STD_LEV_FIELDX)
2757     xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
2758   if (lev_fieldy < STD_LEV_FIELDY)
2759     ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
2760
2761   xpos += MICRO_TILEX;
2762   ypos += MICRO_TILEY;
2763
2764   for(x=-1; x<=STD_LEV_FIELDX; x++)
2765   {
2766     for(y=-1; y<=STD_LEV_FIELDY; y++)
2767     {
2768       int lx = from_x + x, ly = from_y + y;
2769
2770       if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
2771         DrawNewMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2772                             Ur[lx][ly]);
2773       else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
2774         DrawNewMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2775                             BorderElement);
2776     }
2777   }
2778
2779   redraw_mask |= REDRAW_MICROLEVEL;
2780 }
2781
2782 #define MICROLABEL_EMPTY                0
2783 #define MICROLABEL_LEVEL_NAME           1
2784 #define MICROLABEL_CREATED_BY           2
2785 #define MICROLABEL_LEVEL_AUTHOR         3
2786 #define MICROLABEL_IMPORTED_FROM        4
2787 #define MICROLABEL_LEVEL_IMPORT_INFO    5
2788
2789 #define MAX_MICROLABEL_SIZE             (SXSIZE / FONT4_XSIZE)
2790
2791 static void DrawMicroLevelLabelExt(int mode)
2792 {
2793   char label_text[MAX_MICROLABEL_SIZE + 1];
2794
2795   ClearRectangle(drawto, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
2796
2797   strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
2798                        mode == MICROLABEL_CREATED_BY ? "created by" :
2799                        mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
2800                        mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
2801                        mode == MICROLABEL_LEVEL_IMPORT_INFO ?
2802                        leveldir_current->imported_from : ""),
2803           MAX_MICROLABEL_SIZE);
2804   label_text[MAX_MICROLABEL_SIZE] = '\0';
2805
2806   if (strlen(label_text) > 0)
2807   {
2808     int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
2809     int lypos = MICROLABEL_YPOS;
2810
2811     DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
2812   }
2813
2814   redraw_mask |= REDRAW_MICROLEVEL;
2815 }
2816
2817 void DrawMicroLevel(int xpos, int ypos, boolean restart)
2818 {
2819   static unsigned long scroll_delay = 0;
2820   static unsigned long label_delay = 0;
2821   static int from_x, from_y, scroll_direction;
2822   static int label_state, label_counter;
2823
2824   if (restart)
2825   {
2826     from_x = from_y = 0;
2827     scroll_direction = MV_RIGHT;
2828     label_state = 1;
2829     label_counter = 0;
2830
2831     DrawNewMicroLevelExt(xpos, ypos, from_x, from_y);
2832     DrawMicroLevelLabelExt(label_state);
2833
2834     /* initialize delay counters */
2835     DelayReached(&scroll_delay, 0);
2836     DelayReached(&label_delay, 0);
2837
2838     return;
2839   }
2840
2841   /* scroll micro level, if needed */
2842   if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
2843       DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
2844   {
2845     switch (scroll_direction)
2846     {
2847       case MV_LEFT:
2848         if (from_x > 0)
2849           from_x--;
2850         else
2851           scroll_direction = MV_UP;
2852         break;
2853
2854       case MV_RIGHT:
2855         if (from_x < lev_fieldx - STD_LEV_FIELDX)
2856           from_x++;
2857         else
2858           scroll_direction = MV_DOWN;
2859         break;
2860
2861       case MV_UP:
2862         if (from_y > 0)
2863           from_y--;
2864         else
2865           scroll_direction = MV_RIGHT;
2866         break;
2867
2868       case MV_DOWN:
2869         if (from_y < lev_fieldy - STD_LEV_FIELDY)
2870           from_y++;
2871         else
2872           scroll_direction = MV_LEFT;
2873         break;
2874
2875       default:
2876         break;
2877     }
2878
2879     DrawNewMicroLevelExt(xpos, ypos, from_x, from_y);
2880   }
2881
2882   /* redraw micro level label, if needed */
2883   if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
2884       strcmp(level.author, ANONYMOUS_NAME) != 0 &&
2885       strcmp(level.author, leveldir_current->name) != 0 &&
2886       DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
2887   {
2888     int max_label_counter = 23;
2889
2890     if (leveldir_current->imported_from != NULL)
2891       max_label_counter += 14;
2892
2893     label_counter = (label_counter + 1) % max_label_counter;
2894     label_state = (label_counter >= 0 && label_counter <= 7 ?
2895                    MICROLABEL_LEVEL_NAME :
2896                    label_counter >= 9 && label_counter <= 12 ?
2897                    MICROLABEL_CREATED_BY :
2898                    label_counter >= 14 && label_counter <= 21 ?
2899                    MICROLABEL_LEVEL_AUTHOR :
2900                    label_counter >= 23 && label_counter <= 26 ?
2901                    MICROLABEL_IMPORTED_FROM :
2902                    label_counter >= 28 && label_counter <= 35 ?
2903                    MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
2904     DrawMicroLevelLabelExt(label_state);
2905   }
2906 }
2907
2908 int REQ_in_range(int x, int y)
2909 {
2910   if (y > DY+249 && y < DY+278)
2911   {
2912     if (x > DX+1 && x < DX+48)
2913       return 1;
2914     else if (x > DX+51 && x < DX+98) 
2915       return 2;
2916   }
2917   return 0;
2918 }
2919
2920 #define MAX_REQUEST_LINES               13
2921 #define MAX_REQUEST_LINE_LEN            7
2922
2923 boolean Request(char *text, unsigned int req_state)
2924 {
2925   int mx, my, ty, result = -1;
2926   unsigned int old_door_state;
2927
2928 #if defined(PLATFORM_UNIX)
2929   /* pause network game while waiting for request to answer */
2930   if (options.network &&
2931       game_status == PLAYING &&
2932       req_state & REQUEST_WAIT_FOR)
2933     SendToServer_PausePlaying();
2934 #endif
2935
2936   old_door_state = GetDoorState();
2937
2938   UnmapAllGadgets();
2939
2940   CloseDoor(DOOR_CLOSE_1);
2941
2942   /* save old door content */
2943   BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2944              DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2945              DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2946
2947   /* clear door drawing field */
2948   ClearRectangle(drawto, DX, DY, DXSIZE, DYSIZE);
2949
2950   /* write text for request */
2951   for(ty=0; ty < MAX_REQUEST_LINES; ty++)
2952   {
2953     char text_line[MAX_REQUEST_LINE_LEN + 1];
2954     int tx, tl, tc;
2955
2956     if (!*text)
2957       break;
2958
2959     for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
2960     {
2961       tc = *(text + tx);
2962       if (!tc || tc == ' ')
2963         break;
2964     }
2965
2966     if (!tl)
2967     { 
2968       text++; 
2969       ty--; 
2970       continue; 
2971     }
2972
2973     strncpy(text_line, text, tl);
2974     text_line[tl] = 0;
2975
2976     DrawTextExt(drawto, DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
2977                 text_line, FS_SMALL, FC_YELLOW);
2978
2979     text += tl + (tc == ' ' ? 1 : 0);
2980   }
2981
2982   if (req_state & REQ_ASK)
2983   {
2984     MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2985     MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2986   }
2987   else if (req_state & REQ_CONFIRM)
2988   {
2989     MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2990   }
2991   else if (req_state & REQ_PLAYER)
2992   {
2993     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2994     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2995     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2996     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2997   }
2998
2999   /* copy request gadgets to door backbuffer */
3000   BlitBitmap(drawto, pix[PIX_DB_DOOR],
3001              DX, DY, DXSIZE, DYSIZE,
3002              DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
3003
3004   OpenDoor(DOOR_OPEN_1);
3005
3006 #if 0
3007   ClearEventQueue();
3008 #endif
3009
3010   if (!(req_state & REQUEST_WAIT_FOR))
3011     return(FALSE);
3012
3013   if (game_status != MAINMENU)
3014     InitAnimation();
3015
3016   button_status = MB_RELEASED;
3017
3018   request_gadget_id = -1;
3019
3020   while(result < 0)
3021   {
3022     if (PendingEvent())
3023     {
3024       Event event;
3025
3026       NextEvent(&event);
3027
3028       switch(event.type)
3029       {
3030         case EVENT_BUTTONPRESS:
3031         case EVENT_BUTTONRELEASE:
3032         case EVENT_MOTIONNOTIFY:
3033         {
3034           if (event.type == EVENT_MOTIONNOTIFY)
3035           {
3036             if (!PointerInWindow(window))
3037               continue; /* window and pointer are on different screens */
3038
3039             if (!button_status)
3040               continue;
3041
3042             motion_status = TRUE;
3043             mx = ((MotionEvent *) &event)->x;
3044             my = ((MotionEvent *) &event)->y;
3045           }
3046           else
3047           {
3048             motion_status = FALSE;
3049             mx = ((ButtonEvent *) &event)->x;
3050             my = ((ButtonEvent *) &event)->y;
3051             if (event.type == EVENT_BUTTONPRESS)
3052               button_status = ((ButtonEvent *) &event)->button;
3053             else
3054               button_status = MB_RELEASED;
3055           }
3056
3057           /* this sets 'request_gadget_id' */
3058           HandleGadgets(mx, my, button_status);
3059
3060           switch(request_gadget_id)
3061           {
3062             case TOOL_CTRL_ID_YES:
3063               result = TRUE;
3064               break;
3065             case TOOL_CTRL_ID_NO:
3066               result = FALSE;
3067               break;
3068             case TOOL_CTRL_ID_CONFIRM:
3069               result = TRUE | FALSE;
3070               break;
3071
3072             case TOOL_CTRL_ID_PLAYER_1:
3073               result = 1;
3074               break;
3075             case TOOL_CTRL_ID_PLAYER_2:
3076               result = 2;
3077               break;
3078             case TOOL_CTRL_ID_PLAYER_3:
3079               result = 3;
3080               break;
3081             case TOOL_CTRL_ID_PLAYER_4:
3082               result = 4;
3083               break;
3084
3085             default:
3086               break;
3087           }
3088
3089           break;
3090         }
3091
3092         case EVENT_KEYPRESS:
3093           switch(GetEventKey((KeyEvent *)&event, TRUE))
3094           {
3095             case KSYM_Return:
3096               result = 1;
3097               break;
3098
3099             case KSYM_Escape:
3100               result = 0;
3101               break;
3102
3103             default:
3104               break;
3105           }
3106           if (req_state & REQ_PLAYER)
3107             result = 0;
3108           break;
3109
3110         case EVENT_KEYRELEASE:
3111           ClearPlayerAction();
3112           break;
3113
3114         default:
3115           HandleOtherEvents(&event);
3116           break;
3117       }
3118     }
3119     else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
3120     {
3121       int joy = AnyJoystick();
3122
3123       if (joy & JOY_BUTTON_1)
3124         result = 1;
3125       else if (joy & JOY_BUTTON_2)
3126         result = 0;
3127     }
3128
3129     DoAnimation();
3130
3131     /* don't eat all CPU time */
3132     Delay(10);
3133   }
3134
3135   if (game_status != MAINMENU)
3136     StopAnimation();
3137
3138   UnmapToolButtons();
3139
3140   if (!(req_state & REQ_STAY_OPEN))
3141   {
3142     CloseDoor(DOOR_CLOSE_1);
3143
3144     if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
3145     {
3146       BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
3147                  DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
3148                  DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
3149       OpenDoor(DOOR_OPEN_1);
3150     }
3151   }
3152
3153   RemapAllGadgets();
3154
3155 #if defined(PLATFORM_UNIX)
3156   /* continue network game after request */
3157   if (options.network &&
3158       game_status == PLAYING &&
3159       req_state & REQUEST_WAIT_FOR)
3160     SendToServer_ContinuePlaying();
3161 #endif
3162
3163   return(result);
3164 }
3165
3166 unsigned int OpenDoor(unsigned int door_state)
3167 {
3168   unsigned int new_door_state;
3169
3170   if (door_state & DOOR_COPY_BACK)
3171   {
3172     BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
3173                DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
3174                DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
3175     door_state &= ~DOOR_COPY_BACK;
3176   }
3177
3178   new_door_state = MoveDoor(door_state);
3179
3180   return(new_door_state);
3181 }
3182
3183 unsigned int CloseDoor(unsigned int door_state)
3184 {
3185   unsigned int new_door_state;
3186
3187   BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
3188              DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
3189   BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
3190              VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
3191
3192   new_door_state = MoveDoor(door_state);
3193
3194   return(new_door_state);
3195 }
3196
3197 unsigned int GetDoorState()
3198 {
3199   return MoveDoor(DOOR_GET_STATE);
3200 }
3201
3202 unsigned int SetDoorState(unsigned int door_state)
3203 {
3204   return MoveDoor(door_state | DOOR_SET_STATE);
3205 }
3206
3207 unsigned int MoveDoor(unsigned int door_state)
3208 {
3209   static int door1 = DOOR_OPEN_1;
3210   static int door2 = DOOR_CLOSE_2;
3211   static unsigned long door_delay = 0;
3212   int x, start, stepsize = 2;
3213   unsigned long door_delay_value = stepsize * 5;
3214
3215   if (door_state == DOOR_GET_STATE)
3216     return(door1 | door2);
3217
3218   if (door_state & DOOR_SET_STATE)
3219   {
3220     if (door_state & DOOR_ACTION_1)
3221       door1 = door_state & DOOR_ACTION_1;
3222     if (door_state & DOOR_ACTION_2)
3223       door2 = door_state & DOOR_ACTION_2;
3224
3225     return(door1 | door2);
3226   }
3227
3228   if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
3229     door_state &= ~DOOR_OPEN_1;
3230   else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
3231     door_state &= ~DOOR_CLOSE_1;
3232   if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
3233     door_state &= ~DOOR_OPEN_2;
3234   else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
3235     door_state &= ~DOOR_CLOSE_2;
3236
3237   if (setup.quick_doors)
3238   {
3239     stepsize = 20;
3240     door_delay_value = 0;
3241     StopSound(SND_MENU_DOOR_OPENING);
3242     StopSound(SND_MENU_DOOR_CLOSING);
3243   }
3244
3245   if (door_state & DOOR_ACTION)
3246   {
3247     if (!(door_state & DOOR_NO_DELAY))
3248     {
3249       /* opening door sound has priority over simultaneously closing door */
3250       if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
3251         PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
3252       else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
3253         PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
3254     }
3255
3256     start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
3257
3258     for(x=start; x<=DXSIZE; x+=stepsize)
3259     {
3260       Bitmap *bitmap = pix[PIX_DOOR];
3261       GC gc = bitmap->stored_clip_gc;
3262
3263       WaitUntilDelayReached(&door_delay, door_delay_value);
3264
3265       if (door_state & DOOR_ACTION_1)
3266       {
3267         int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
3268         int j = (DXSIZE - i) / 3;
3269
3270         BlitBitmap(pix[PIX_DB_DOOR], drawto,
3271                    DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
3272                    DXSIZE,DYSIZE - i/2, DX, DY);
3273
3274         ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
3275
3276         SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
3277         BlitBitmapMasked(bitmap, drawto,
3278                          DXSIZE, DOOR_GFX_PAGEY1, i, 77,
3279                          DX + DXSIZE - i, DY + j);
3280         BlitBitmapMasked(bitmap, drawto,
3281                          DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
3282                          DX + DXSIZE - i, DY + 140 + j);
3283         SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
3284         BlitBitmapMasked(bitmap, drawto,
3285                          DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
3286                          DX, DY);
3287         BlitBitmapMasked(bitmap, drawto,
3288                          DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
3289                          DX, DY + 140 - j);
3290
3291         BlitBitmapMasked(bitmap, drawto,
3292                          DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
3293                          DX, DY + 77 - j);
3294         BlitBitmapMasked(bitmap, drawto,
3295                          DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
3296                          DX, DY + 203 - j);
3297         SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
3298         BlitBitmapMasked(bitmap, drawto,
3299                          DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
3300                          DX + DXSIZE - i, DY + 77 + j);
3301         BlitBitmapMasked(bitmap, drawto,
3302                          DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
3303                          DX + DXSIZE - i, DY + 203 + j);
3304
3305         redraw_mask |= REDRAW_DOOR_1;
3306       }
3307
3308       if (door_state & DOOR_ACTION_2)
3309       {
3310         int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
3311         int j = (VXSIZE - i) / 3;
3312
3313         BlitBitmap(pix[PIX_DB_DOOR], drawto,
3314                    DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
3315                    VXSIZE, VYSIZE - i/2, VX, VY);
3316
3317         ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
3318
3319         SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
3320         BlitBitmapMasked(bitmap, drawto,
3321                          VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
3322                          VX + VXSIZE-i, VY+j);
3323         SetClipOrigin(bitmap, gc,
3324                       VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
3325         BlitBitmapMasked(bitmap, drawto,
3326                          VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
3327                          VX, VY);
3328
3329         BlitBitmapMasked(bitmap, drawto,
3330                          VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
3331                          i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
3332         SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
3333         BlitBitmapMasked(bitmap, drawto,
3334                          VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
3335                          i, VYSIZE / 2 - j,
3336                          VX + VXSIZE - i, VY + VYSIZE / 2 + j);
3337
3338         redraw_mask |= REDRAW_DOOR_2;
3339       }
3340
3341       BackToFront();
3342
3343       if (game_status == MAINMENU)
3344         DoAnimation();
3345     }
3346   }
3347
3348   if (setup.quick_doors)
3349   {
3350     StopSound(SND_MENU_DOOR_OPENING);
3351     StopSound(SND_MENU_DOOR_CLOSING);
3352   }
3353
3354   if (door_state & DOOR_ACTION_1)
3355     door1 = door_state & DOOR_ACTION_1;
3356   if (door_state & DOOR_ACTION_2)
3357     door2 = door_state & DOOR_ACTION_2;
3358
3359   return (door1 | door2);
3360 }
3361
3362 void DrawSpecialEditorDoor()
3363 {
3364   /* draw bigger toolbox window */
3365   BlitBitmap(pix[PIX_DOOR], drawto,
3366              DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
3367
3368   redraw_mask |= REDRAW_ALL;
3369 }
3370
3371 void UndrawSpecialEditorDoor()
3372 {
3373   /* draw normal tape recorder window */
3374   BlitBitmap(pix[PIX_BACK], drawto,
3375              562, 344, 108, 56, EX - 4, EY - 12);
3376
3377   redraw_mask |= REDRAW_ALL;
3378 }
3379
3380 #ifndef TARGET_SDL
3381 int ReadPixel(DrawBuffer *bitmap, int x, int y)
3382 {
3383   XImage *pixel_image;
3384   unsigned long pixel_value;
3385
3386   pixel_image = XGetImage(display, bitmap->drawable,
3387                           x, y, 1, 1, AllPlanes, ZPixmap);
3388   pixel_value = XGetPixel(pixel_image, 0, 0);
3389
3390   XDestroyImage(pixel_image);
3391
3392   return pixel_value;
3393 }
3394 #endif
3395
3396 /* ---------- new tool button stuff ---------------------------------------- */
3397
3398 /* graphic position values for tool buttons */
3399 #define TOOL_BUTTON_YES_XPOS            2
3400 #define TOOL_BUTTON_YES_YPOS            250
3401 #define TOOL_BUTTON_YES_GFX_YPOS        0
3402 #define TOOL_BUTTON_YES_XSIZE           46
3403 #define TOOL_BUTTON_YES_YSIZE           28
3404 #define TOOL_BUTTON_NO_XPOS             52
3405 #define TOOL_BUTTON_NO_YPOS             TOOL_BUTTON_YES_YPOS
3406 #define TOOL_BUTTON_NO_GFX_YPOS         TOOL_BUTTON_YES_GFX_YPOS
3407 #define TOOL_BUTTON_NO_XSIZE            TOOL_BUTTON_YES_XSIZE
3408 #define TOOL_BUTTON_NO_YSIZE            TOOL_BUTTON_YES_YSIZE
3409 #define TOOL_BUTTON_CONFIRM_XPOS        TOOL_BUTTON_YES_XPOS
3410 #define TOOL_BUTTON_CONFIRM_YPOS        TOOL_BUTTON_YES_YPOS
3411 #define TOOL_BUTTON_CONFIRM_GFX_YPOS    30
3412 #define TOOL_BUTTON_CONFIRM_XSIZE       96
3413 #define TOOL_BUTTON_CONFIRM_YSIZE       TOOL_BUTTON_YES_YSIZE
3414 #define TOOL_BUTTON_PLAYER_XSIZE        30
3415 #define TOOL_BUTTON_PLAYER_YSIZE        30
3416 #define TOOL_BUTTON_PLAYER_GFX_XPOS     5
3417 #define TOOL_BUTTON_PLAYER_GFX_YPOS     185
3418 #define TOOL_BUTTON_PLAYER_XPOS         (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
3419 #define TOOL_BUTTON_PLAYER_YPOS         (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
3420 #define TOOL_BUTTON_PLAYER1_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
3421                                          + 0 * TOOL_BUTTON_PLAYER_XSIZE)
3422 #define TOOL_BUTTON_PLAYER2_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
3423                                          + 1 * TOOL_BUTTON_PLAYER_XSIZE)
3424 #define TOOL_BUTTON_PLAYER3_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
3425                                          + 0 * TOOL_BUTTON_PLAYER_XSIZE)
3426 #define TOOL_BUTTON_PLAYER4_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
3427                                          + 1 * TOOL_BUTTON_PLAYER_XSIZE)
3428 #define TOOL_BUTTON_PLAYER1_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
3429                                          + 0 * TOOL_BUTTON_PLAYER_YSIZE)
3430 #define TOOL_BUTTON_PLAYER2_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
3431                                          + 0 * TOOL_BUTTON_PLAYER_YSIZE)
3432 #define TOOL_BUTTON_PLAYER3_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
3433                                          + 1 * TOOL_BUTTON_PLAYER_YSIZE)
3434 #define TOOL_BUTTON_PLAYER4_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
3435                                          + 1 * TOOL_BUTTON_PLAYER_YSIZE)
3436
3437 static struct
3438 {
3439   int xpos, ypos;
3440   int x, y;
3441   int width, height;
3442   int gadget_id;
3443   char *infotext;
3444 } toolbutton_info[NUM_TOOL_BUTTONS] =
3445 {
3446   {
3447     TOOL_BUTTON_YES_XPOS,       TOOL_BUTTON_YES_GFX_YPOS,
3448     TOOL_BUTTON_YES_XPOS,       TOOL_BUTTON_YES_YPOS,
3449     TOOL_BUTTON_YES_XSIZE,      TOOL_BUTTON_YES_YSIZE,
3450     TOOL_CTRL_ID_YES,
3451     "yes"
3452   },
3453   {
3454     TOOL_BUTTON_NO_XPOS,        TOOL_BUTTON_NO_GFX_YPOS,
3455     TOOL_BUTTON_NO_XPOS,        TOOL_BUTTON_NO_YPOS,
3456     TOOL_BUTTON_NO_XSIZE,       TOOL_BUTTON_NO_YSIZE,
3457     TOOL_CTRL_ID_NO,
3458     "no"
3459   },
3460   {
3461     TOOL_BUTTON_CONFIRM_XPOS,   TOOL_BUTTON_CONFIRM_GFX_YPOS,
3462     TOOL_BUTTON_CONFIRM_XPOS,   TOOL_BUTTON_CONFIRM_YPOS,
3463     TOOL_BUTTON_CONFIRM_XSIZE,  TOOL_BUTTON_CONFIRM_YSIZE,
3464     TOOL_CTRL_ID_CONFIRM,
3465     "confirm"
3466   },
3467   {
3468     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
3469     TOOL_BUTTON_PLAYER1_XPOS,   TOOL_BUTTON_PLAYER1_YPOS,
3470     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
3471     TOOL_CTRL_ID_PLAYER_1,
3472     "player 1"
3473   },
3474   {
3475     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
3476     TOOL_BUTTON_PLAYER2_XPOS,   TOOL_BUTTON_PLAYER2_YPOS,
3477     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
3478     TOOL_CTRL_ID_PLAYER_2,
3479     "player 2"
3480   },
3481   {
3482     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
3483     TOOL_BUTTON_PLAYER3_XPOS,   TOOL_BUTTON_PLAYER3_YPOS,
3484     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
3485     TOOL_CTRL_ID_PLAYER_3,
3486     "player 3"
3487   },
3488   {
3489     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
3490     TOOL_BUTTON_PLAYER4_XPOS,   TOOL_BUTTON_PLAYER4_YPOS,
3491     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
3492     TOOL_CTRL_ID_PLAYER_4,
3493     "player 4"
3494   }
3495 };
3496
3497 void CreateToolButtons()
3498 {
3499   int i;
3500
3501   for (i=0; i<NUM_TOOL_BUTTONS; i++)
3502   {
3503     Bitmap *gd_bitmap = pix[PIX_DOOR];
3504     Bitmap *deco_bitmap = None;
3505     int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
3506     struct GadgetInfo *gi;
3507     unsigned long event_mask;
3508     int gd_xoffset, gd_yoffset;
3509     int gd_x1, gd_x2, gd_y;
3510     int id = i;
3511
3512     event_mask = GD_EVENT_RELEASED;
3513
3514     gd_xoffset = toolbutton_info[i].xpos;
3515     gd_yoffset = toolbutton_info[i].ypos;
3516     gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
3517     gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
3518     gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
3519
3520     if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
3521     {
3522       getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
3523                            &deco_bitmap, &deco_x, &deco_y);
3524       deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
3525       deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
3526     }
3527
3528     gi = CreateGadget(GDI_CUSTOM_ID, id,
3529                       GDI_INFO_TEXT, toolbutton_info[i].infotext,
3530                       GDI_X, DX + toolbutton_info[i].x,
3531                       GDI_Y, DY + toolbutton_info[i].y,
3532                       GDI_WIDTH, toolbutton_info[i].width,
3533                       GDI_HEIGHT, toolbutton_info[i].height,
3534                       GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
3535                       GDI_STATE, GD_BUTTON_UNPRESSED,
3536                       GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
3537                       GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
3538                       GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
3539                       GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
3540                       GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
3541                       GDI_DECORATION_SHIFTING, 1, 1,
3542                       GDI_EVENT_MASK, event_mask,
3543                       GDI_CALLBACK_ACTION, HandleToolButtons,
3544                       GDI_END);
3545
3546     if (gi == NULL)
3547       Error(ERR_EXIT, "cannot create gadget");
3548
3549     tool_gadget[id] = gi;
3550   }
3551 }
3552
3553 static void UnmapToolButtons()
3554 {
3555   int i;
3556
3557   for (i=0; i<NUM_TOOL_BUTTONS; i++)
3558     UnmapGadget(tool_gadget[i]);
3559 }
3560
3561 static void HandleToolButtons(struct GadgetInfo *gi)
3562 {
3563   request_gadget_id = gi->custom_id;
3564 }
3565
3566 int get_next_element(int element)
3567 {
3568   switch(element)
3569   {
3570     case EL_QUICKSAND_FILLING:          return EL_QUICKSAND_FULL;
3571     case EL_QUICKSAND_EMPTYING:         return EL_QUICKSAND_EMPTY;
3572     case EL_MAGIC_WALL_FILLING:         return EL_MAGIC_WALL_FULL;
3573     case EL_MAGIC_WALL_EMPTYING:        return EL_MAGIC_WALL_ACTIVE;
3574     case EL_BD_MAGIC_WALL_FILLING:      return EL_BD_MAGIC_WALL_FULL;
3575     case EL_BD_MAGIC_WALL_EMPTYING:     return EL_BD_MAGIC_WALL_ACTIVE;
3576     case EL_AMOEBA_DRIPPING:            return EL_AMOEBA_WET;
3577
3578     default:                            return element;
3579   }
3580 }
3581
3582 int el2gfx_OLD(int element)
3583 {
3584   switch(element)
3585   {
3586     case EL_EMPTY:                      return -1;
3587     case EL_SAND:                       return GFX_ERDREICH;
3588     case EL_WALL:                       return GFX_MAUERWERK;
3589     case EL_WALL_CRUMBLED:              return GFX_FELSBODEN;
3590     case EL_ROCK:                       return GFX_FELSBROCKEN;
3591     case EL_EMERALD:                    return GFX_EDELSTEIN;
3592     case EL_EXIT_CLOSED:                return GFX_AUSGANG_ZU;
3593     case EL_EXIT_OPENING:               return GFX_AUSGANG_ACT;
3594     case EL_EXIT_OPEN:                  return GFX_AUSGANG_AUF;
3595     case EL_SP_EXIT_OPEN:               return GFX_SP_EXIT;
3596     case EL_PLAYER1:                    return GFX_SPIELER1;
3597     case EL_PLAYER2:                    return GFX_SPIELER2;
3598     case EL_PLAYER3:                    return GFX_SPIELER3;
3599     case EL_PLAYER4:                    return GFX_SPIELER4;
3600     case EL_BUG:                        return GFX_KAEFER;
3601     case EL_BUG_RIGHT:                  return GFX_KAEFER_RIGHT;
3602     case EL_BUG_UP:                     return GFX_KAEFER_UP;
3603     case EL_BUG_LEFT:                   return GFX_KAEFER_LEFT;
3604     case EL_BUG_DOWN:                   return GFX_KAEFER_DOWN;
3605     case EL_SPACESHIP:                  return GFX_FLIEGER;
3606     case EL_SPACESHIP_RIGHT:            return GFX_FLIEGER_RIGHT;
3607     case EL_SPACESHIP_UP:               return GFX_FLIEGER_UP;
3608     case EL_SPACESHIP_LEFT:             return GFX_FLIEGER_LEFT;
3609     case EL_SPACESHIP_DOWN:             return GFX_FLIEGER_DOWN;
3610     case EL_BD_BUTTERFLY:               return GFX_BUTTERFLY;
3611     case EL_BD_BUTTERFLY_RIGHT:         return GFX_BUTTERFLY_RIGHT;
3612     case EL_BD_BUTTERFLY_UP:            return GFX_BUTTERFLY_UP;
3613     case EL_BD_BUTTERFLY_LEFT:          return GFX_BUTTERFLY_LEFT;
3614     case EL_BD_BUTTERFLY_DOWN:          return GFX_BUTTERFLY_DOWN;
3615     case EL_BD_FIREFLY:                 return GFX_FIREFLY;
3616     case EL_BD_FIREFLY_RIGHT:           return GFX_FIREFLY_RIGHT;
3617     case EL_BD_FIREFLY_UP:              return GFX_FIREFLY_UP;
3618     case EL_BD_FIREFLY_LEFT:            return GFX_FIREFLY_LEFT;
3619     case EL_BD_FIREFLY_DOWN:            return GFX_FIREFLY_DOWN;
3620     case EL_YAMYAM:                     return GFX_MAMPFER;
3621     case EL_ROBOT:                      return GFX_ROBOT;
3622     case EL_STEELWALL:                  return GFX_BETON;
3623     case EL_DIAMOND:                    return GFX_DIAMANT;
3624     case EL_QUICKSAND_EMPTY:            return GFX_MORAST_LEER;
3625     case EL_QUICKSAND_FULL:             return GFX_MORAST_VOLL;
3626     case EL_QUICKSAND_EMPTYING:         return GFX_MORAST_LEER;
3627     case EL_AMOEBA_DROP:                return GFX_TROPFEN;
3628     case EL_BOMB:                       return GFX_BOMBE;
3629     case EL_MAGIC_WALL:                 return GFX_MAGIC_WALL_OFF;
3630     case EL_MAGIC_WALL_ACTIVE:          return GFX_MAGIC_WALL_EMPTY;
3631     case EL_MAGIC_WALL_EMPTYING:        return GFX_MAGIC_WALL_EMPTY;
3632     case EL_MAGIC_WALL_FULL:            return GFX_MAGIC_WALL_FULL;
3633     case EL_MAGIC_WALL_DEAD:            return GFX_MAGIC_WALL_DEAD;
3634     case EL_ACID:                       return GFX_SALZSAEURE;
3635     case EL_AMOEBA_DEAD:                return GFX_AMOEBE_TOT;
3636     case EL_AMOEBA_WET:                 return GFX_AMOEBE_NASS;
3637     case EL_AMOEBA_DRY:                 return GFX_AMOEBE_NORM;
3638     case EL_AMOEBA_FULL:                return GFX_AMOEBE_VOLL;
3639     case EL_BD_AMOEBA:                  return GFX_AMOEBE_BD;
3640     case EL_AMOEBA_TO_DIAMOND:          return GFX_AMOEBA2DIAM;
3641     case EL_AMOEBA_DRIPPING:            return GFX_AMOEBE_NASS;
3642     case EL_NUT:                        return GFX_KOKOSNUSS;
3643     case EL_GAMEOFLIFE:                 return GFX_LIFE;
3644     case EL_BIOMAZE:                    return GFX_LIFE_ASYNC;
3645     case EL_DYNAMITE_ACTIVE:            return GFX_DYNAMIT;
3646     case EL_STONEBLOCK:                 return GFX_BADEWANNE;
3647     case EL_ACIDPOOL_TOPLEFT:           return GFX_BADEWANNE1;
3648     case EL_ACIDPOOL_TOPRIGHT:          return GFX_BADEWANNE2;
3649     case EL_ACIDPOOL_BOTTOMLEFT:        return GFX_BADEWANNE3;
3650     case EL_ACIDPOOL_BOTTOM:            return GFX_BADEWANNE4;
3651     case EL_ACIDPOOL_BOTTOMRIGHT:       return GFX_BADEWANNE5;
3652     case EL_ROBOT_WHEEL:                return GFX_ABLENK_AUS;
3653     case EL_ROBOT_WHEEL_ACTIVE:         return GFX_ABLENK_EIN;
3654     case EL_KEY1:                       return GFX_SCHLUESSEL1;
3655     case EL_KEY2:                       return GFX_SCHLUESSEL2;
3656     case EL_KEY3:                       return GFX_SCHLUESSEL3;
3657     case EL_KEY4:                       return GFX_SCHLUESSEL4;
3658     case EL_GATE1:                      return GFX_PFORTE1;
3659     case EL_GATE2:                      return GFX_PFORTE2;
3660     case EL_GATE3:                      return GFX_PFORTE3;
3661     case EL_GATE4:                      return GFX_PFORTE4;
3662     case EL_GATE1_GRAY:                 return GFX_PFORTE1X;
3663     case EL_GATE2_GRAY:                 return GFX_PFORTE2X;
3664     case EL_GATE3_GRAY:                 return GFX_PFORTE3X;
3665     case EL_GATE4_GRAY:                 return GFX_PFORTE4X;
3666     case EL_DYNAMITE:                   return GFX_DYNAMIT_AUS;
3667     case EL_PACMAN:                     return GFX_PACMAN;
3668     case EL_PACMAN_RIGHT:               return GFX_PACMAN_RIGHT;
3669     case EL_PACMAN_UP:                  return GFX_PACMAN_UP;
3670     case EL_PACMAN_LEFT:                return GFX_PACMAN_LEFT;
3671     case EL_PACMAN_DOWN:                return GFX_PACMAN_DOWN;
3672     case EL_INVISIBLE_WALL:             return GFX_UNSICHTBAR;
3673     case EL_INVISIBLE_WALL_ACTIVE:      return GFX_UNSICHTBAR_ON;
3674     case EL_WALL_EMERALD:               return GFX_ERZ_EDEL;
3675     case EL_WALL_DIAMOND:               return GFX_ERZ_DIAM;
3676     case EL_LAMP:                       return GFX_BIRNE_AUS;
3677     case EL_LAMP_ACTIVE:                return GFX_BIRNE_EIN;
3678     case EL_TIME_ORB_FULL:              return GFX_ZEIT_VOLL;
3679     case EL_TIME_ORB_EMPTY:             return GFX_ZEIT_LEER;
3680     case EL_WALL_GROWING:               return GFX_MAUER_LEBT;
3681     case EL_WALL_GROWING_X:             return GFX_MAUER_X;
3682     case EL_WALL_GROWING_Y:             return GFX_MAUER_Y;
3683     case EL_WALL_GROWING_XY:            return GFX_MAUER_XY;
3684     case EL_BD_DIAMOND:                 return GFX_EDELSTEIN_BD;
3685     case EL_EMERALD_YELLOW:             return GFX_EDELSTEIN_GELB;
3686     case EL_EMERALD_RED:                return GFX_EDELSTEIN_ROT;
3687     case EL_EMERALD_PURPLE:             return GFX_EDELSTEIN_LILA;
3688     case EL_WALL_BD_DIAMOND:            return GFX_ERZ_EDEL_BD;
3689     case EL_WALL_EMERALD_YELLOW:        return GFX_ERZ_EDEL_GELB;
3690     case EL_WALL_EMERALD_RED:           return GFX_ERZ_EDEL_ROT;
3691     case EL_WALL_EMERALD_PURPLE:        return GFX_ERZ_EDEL_LILA;
3692     case EL_DARK_YAMYAM:                return GFX_MAMPFER2;
3693     case EL_BD_MAGIC_WALL:              return GFX_MAGIC_WALL_BD_OFF;
3694     case EL_BD_MAGIC_WALL_ACTIVE:       return GFX_MAGIC_WALL_BD_EMPTY;
3695     case EL_BD_MAGIC_WALL_EMPTYING:     return GFX_MAGIC_WALL_BD_EMPTY;
3696     case EL_BD_MAGIC_WALL_FULL:         return GFX_MAGIC_WALL_BD_FULL;
3697     case EL_BD_MAGIC_WALL_DEAD:         return GFX_MAGIC_WALL_BD_DEAD;
3698     case EL_DYNABOMB_PLAYER1_ACTIVE:    return GFX_DYNABOMB;
3699     case EL_DYNABOMB_PLAYER2_ACTIVE:    return GFX_DYNABOMB;
3700     case EL_DYNABOMB_PLAYER3_ACTIVE:    return GFX_DYNABOMB;
3701     case EL_DYNABOMB_PLAYER4_ACTIVE:    return GFX_DYNABOMB;
3702     case EL_DYNABOMB_NR:                return GFX_DYNABOMB_NR;
3703     case EL_DYNABOMB_SZ:                return GFX_DYNABOMB_SZ;
3704     case EL_DYNABOMB_XL:                return GFX_DYNABOMB_XL;
3705     case EL_SOKOBAN_OBJECT:             return GFX_SOKOBAN_OBJEKT;
3706     case EL_SOKOBAN_FIELD_EMPTY:        return GFX_SOKOBAN_FELD_LEER;
3707     case EL_SOKOBAN_FIELD_FULL:         return GFX_SOKOBAN_FELD_VOLL;
3708     case EL_MOLE:                       return GFX_MOLE;
3709     case EL_PENGUIN:                    return GFX_PINGUIN;
3710     case EL_PIG:                        return GFX_SCHWEIN;
3711     case EL_DRAGON:                     return GFX_DRACHE;
3712     case EL_SATELLITE:                  return GFX_SONDE;
3713     case EL_ARROW_BLUE_LEFT:            return GFX_PFEIL_LEFT;
3714     case EL_ARROW_BLUE_RIGHT:           return GFX_PFEIL_RIGHT;
3715     case EL_ARROW_BLUE_UP:              return GFX_PFEIL_UP;
3716     case EL_ARROW_BLUE_DOWN:            return GFX_PFEIL_DOWN;
3717     case EL_SPEED_PILL:                 return GFX_SPEED_PILL;
3718     case EL_SP_TERMINAL_ACTIVE:         return GFX_SP_TERMINAL;
3719     case EL_SP_BUGGY_BASE_ACTIVE:       return GFX_SP_BUG_ACTIVE;
3720     case EL_SP_ZONK:                    return GFX_SP_ZONK;
3721       /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
3722     case EL_INVISIBLE_STEELWALL:        return GFX_INVISIBLE_STEEL;
3723     case EL_INVISIBLE_STEELWALL_ACTIVE: return GFX_INVISIBLE_STEEL_ON;
3724     case EL_BLACK_ORB:                  return GFX_BLACK_ORB;
3725     case EL_EM_GATE1:                   return GFX_EM_GATE_1;
3726     case EL_EM_GATE2:                   return GFX_EM_GATE_2;
3727     case EL_EM_GATE3:                   return GFX_EM_GATE_3;
3728     case EL_EM_GATE4:                   return GFX_EM_GATE_4;
3729     case EL_EM_GATE1_GRAY:              return GFX_EM_GATE_1X;
3730     case EL_EM_GATE2_GRAY:              return GFX_EM_GATE_2X;
3731     case EL_EM_GATE3_GRAY:              return GFX_EM_GATE_3X;
3732     case EL_EM_GATE4_GRAY:              return GFX_EM_GATE_4X;
3733     case EL_EM_KEY1_FILE:               return GFX_EM_KEY_1;
3734     case EL_EM_KEY2_FILE:               return GFX_EM_KEY_2;
3735     case EL_EM_KEY3_FILE:               return GFX_EM_KEY_3;
3736     case EL_EM_KEY4_FILE:               return GFX_EM_KEY_4;
3737     case EL_EM_KEY1:                    return GFX_EM_KEY_1;
3738     case EL_EM_KEY2:                    return GFX_EM_KEY_2;
3739     case EL_EM_KEY3:                    return GFX_EM_KEY_3;
3740     case EL_EM_KEY4:                    return GFX_EM_KEY_4;
3741     case EL_PEARL:                      return GFX_PEARL;
3742     case EL_CRYSTAL:                    return GFX_CRYSTAL;
3743     case EL_WALL_PEARL:                 return GFX_WALL_PEARL;
3744     case EL_WALL_CRYSTAL:               return GFX_WALL_CRYSTAL;
3745     case EL_DOOR_WHITE:                 return GFX_DOOR_WHITE;
3746     case EL_DOOR_WHITE_GRAY:            return GFX_DOOR_WHITE_GRAY;
3747     case EL_KEY_WHITE:                  return GFX_KEY_WHITE;
3748     case EL_SHIELD_NORMAL:              return GFX_SHIELD_PASSIVE;
3749     case EL_SHIELD_DEADLY:              return GFX_SHIELD_ACTIVE;
3750     case EL_EXTRA_TIME:                 return GFX_EXTRA_TIME;
3751     case EL_SWITCHGATE_OPEN:            return GFX_SWITCHGATE_OPEN;
3752     case EL_SWITCHGATE_CLOSED:          return GFX_SWITCHGATE_CLOSED;
3753     case EL_SWITCHGATE_SWITCH_UP:       return GFX_SWITCHGATE_SWITCH_1;
3754     case EL_SWITCHGATE_SWITCH_DOWN:     return GFX_SWITCHGATE_SWITCH_2;
3755     case EL_CONVEYOR_BELT1_LEFT:        return GFX_BELT1_LEFT;
3756     case EL_CONVEYOR_BELT1_MIDDLE:      return GFX_BELT1_MIDDLE;
3757     case EL_CONVEYOR_BELT1_RIGHT:       return GFX_BELT1_RIGHT;
3758     case EL_CONVEYOR_BELT1_LEFT_ACTIVE: return GFX_BELT1_LEFT;
3759     case EL_CONVEYOR_BELT1_MIDDLE_ACTIVE:return GFX_BELT1_MIDDLE;
3760     case EL_CONVEYOR_BELT1_RIGHT_ACTIVE:return GFX_BELT1_RIGHT;
3761     case EL_CONVEYOR_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
3762     case EL_CONVEYOR_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
3763     case EL_CONVEYOR_BELT1_SWITCH_RIGHT:return GFX_BELT1_SWITCH_RIGHT;
3764     case EL_CONVEYOR_BELT2_LEFT:        return GFX_BELT2_LEFT;
3765     case EL_CONVEYOR_BELT2_MIDDLE:      return GFX_BELT2_MIDDLE;
3766     case EL_CONVEYOR_BELT2_RIGHT:       return GFX_BELT2_RIGHT;
3767     case EL_CONVEYOR_BELT2_LEFT_ACTIVE: return GFX_BELT2_LEFT;
3768     case EL_CONVEYOR_BELT2_MIDDLE_ACTIVE:return GFX_BELT2_MIDDLE;
3769     case EL_CONVEYOR_BELT2_RIGHT_ACTIVE:return GFX_BELT2_RIGHT;
3770     case EL_CONVEYOR_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
3771     case EL_CONVEYOR_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
3772     case EL_CONVEYOR_BELT2_SWITCH_RIGHT:return GFX_BELT2_SWITCH_RIGHT;
3773     case EL_CONVEYOR_BELT3_LEFT:        return GFX_BELT3_LEFT;
3774     case EL_CONVEYOR_BELT3_MIDDLE:      return GFX_BELT3_MIDDLE;
3775     case EL_CONVEYOR_BELT3_RIGHT:       return GFX_BELT3_RIGHT;
3776     case EL_CONVEYOR_BELT3_LEFT_ACTIVE: return GFX_BELT3_LEFT;
3777     case EL_CONVEYOR_BELT3_MIDDLE_ACTIVE:return GFX_BELT3_MIDDLE;
3778     case EL_CONVEYOR_BELT3_RIGHT_ACTIVE:return GFX_BELT3_RIGHT;
3779     case EL_CONVEYOR_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
3780     case EL_CONVEYOR_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
3781     case EL_CONVEYOR_BELT3_SWITCH_RIGHT:return GFX_BELT3_SWITCH_RIGHT;
3782     case EL_CONVEYOR_BELT4_LEFT:        return GFX_BELT4_LEFT;
3783     case EL_CONVEYOR_BELT4_MIDDLE:      return GFX_BELT4_MIDDLE;
3784     case EL_CONVEYOR_BELT4_RIGHT:       return GFX_BELT4_RIGHT;
3785     case EL_CONVEYOR_BELT4_LEFT_ACTIVE: return GFX_BELT4_LEFT;
3786     case EL_CONVEYOR_BELT4_MIDDLE_ACTIVE:return GFX_BELT4_MIDDLE;
3787     case EL_CONVEYOR_BELT4_RIGHT_ACTIVE:return GFX_BELT4_RIGHT;
3788     case EL_CONVEYOR_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
3789     case EL_CONVEYOR_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
3790     case EL_CONVEYOR_BELT4_SWITCH_RIGHT:return GFX_BELT4_SWITCH_RIGHT;
3791     case EL_LANDMINE:                   return GFX_LANDMINE;
3792     case EL_ENVELOPE:                   return GFX_ENVELOPE;
3793     case EL_LIGHT_SWITCH:               return GFX_LIGHT_SWITCH_OFF;
3794     case EL_LIGHT_SWITCH_ACTIVE:        return GFX_LIGHT_SWITCH_ON;
3795     case EL_SIGN_EXCLAMATION:           return GFX_SIGN_EXCLAMATION;
3796     case EL_SIGN_RADIOACTIVITY:         return GFX_SIGN_RADIOACTIVITY;
3797     case EL_SIGN_STOP:                  return GFX_SIGN_STOP;
3798     case EL_SIGN_WHEELCHAIR:            return GFX_SIGN_WHEELCHAIR;
3799     case EL_SIGN_PARKING:               return GFX_SIGN_PARKING;
3800     case EL_SIGN_ONEWAY:                return GFX_SIGN_ONEWAY;
3801     case EL_SIGN_HEART:                 return GFX_SIGN_HEART;
3802     case EL_SIGN_TRIANGLE:              return GFX_SIGN_TRIANGLE;
3803     case EL_SIGN_ROUND:                 return GFX_SIGN_ROUND;
3804     case EL_SIGN_EXIT:                  return GFX_SIGN_EXIT;
3805     case EL_SIGN_YINYANG:               return GFX_SIGN_YINYANG;
3806     case EL_SIGN_OTHER:                 return GFX_SIGN_OTHER;
3807     case EL_MOLE_LEFT:                  return GFX_MOLE_LEFT;
3808     case EL_MOLE_RIGHT:                 return GFX_MOLE_RIGHT;
3809     case EL_MOLE_UP:                    return GFX_MOLE_UP;
3810     case EL_MOLE_DOWN:                  return GFX_MOLE_DOWN;
3811     case EL_STEELWALL_SLANTED:          return GFX_STEEL_SLANTED;
3812     case EL_INVISIBLE_SAND:             return GFX_SAND_INVISIBLE;
3813     case EL_INVISIBLE_SAND_ACTIVE:      return GFX_SAND_INVISIBLE_ON;
3814     case EL_DX_UNKNOWN_15:              return GFX_DX_UNKNOWN_15;
3815     case EL_DX_UNKNOWN_42:              return GFX_DX_UNKNOWN_42;
3816     case EL_TIMEGATE_OPEN:              return GFX_TIMEGATE_OPEN;
3817     case EL_TIMEGATE_CLOSED:            return GFX_TIMEGATE_CLOSED;
3818     case EL_TIMEGATE_SWITCH_ACTIVE:     return GFX_TIMEGATE_SWITCH;
3819     case EL_TIMEGATE_SWITCH:            return GFX_TIMEGATE_SWITCH;
3820     case EL_BALLOON:                    return GFX_BALLOON;
3821     case EL_BALLOON_SEND_LEFT:          return GFX_BALLOON_SEND_LEFT;
3822     case EL_BALLOON_SEND_RIGHT:         return GFX_BALLOON_SEND_RIGHT;
3823     case EL_BALLOON_SEND_UP:            return GFX_BALLOON_SEND_UP;
3824     case EL_BALLOON_SEND_DOWN:          return GFX_BALLOON_SEND_DOWN;
3825     case EL_BALLOON_SEND_ANY_DIRECTION: return GFX_BALLOON_SEND_ANY;
3826     case EL_EMC_STEELWALL1:             return GFX_EMC_STEEL_WALL_1;
3827     case EL_EMC_STEELWALL2:             return GFX_EMC_STEEL_WALL_2;
3828     case EL_EMC_STEELWALL3:             return GFX_EMC_STEEL_WALL_3;
3829     case EL_EMC_STEELWALL4:             return GFX_EMC_STEEL_WALL_4;
3830     case EL_EMC_WALL_PILLAR_UPPER:      return GFX_EMC_WALL_1;
3831     case EL_EMC_WALL_PILLAR_MIDDLE:     return GFX_EMC_WALL_2;
3832     case EL_EMC_WALL_PILLAR_LOWER:      return GFX_EMC_WALL_3;
3833     case EL_EMC_WALL4:                  return GFX_EMC_WALL_4;
3834     case EL_EMC_WALL5:                  return GFX_EMC_WALL_5;
3835     case EL_EMC_WALL6:                  return GFX_EMC_WALL_6;
3836     case EL_EMC_WALL7:                  return GFX_EMC_WALL_7;
3837     case EL_EMC_WALL8:                  return GFX_EMC_WALL_8;
3838     case EL_TUBE_ALL:                   return GFX_TUBE_CROSS;
3839     case EL_TUBE_VERTICAL:              return GFX_TUBE_VERTICAL;
3840     case EL_TUBE_HORIZONTAL:            return GFX_TUBE_HORIZONTAL;
3841     case EL_TUBE_VERTICAL_LEFT:         return GFX_TUBE_VERT_LEFT;
3842     case EL_TUBE_VERTICAL_RIGHT:        return GFX_TUBE_VERT_RIGHT;
3843     case EL_TUBE_HORIZONTAL_UP:         return GFX_TUBE_HORIZ_UP;
3844     case EL_TUBE_HORIZONTAL_DOWN:       return GFX_TUBE_HORIZ_DOWN;
3845     case EL_TUBE_LEFT_UP:               return GFX_TUBE_LEFT_UP;
3846     case EL_TUBE_LEFT_DOWN:             return GFX_TUBE_LEFT_DOWN;
3847     case EL_TUBE_RIGHT_UP:              return GFX_TUBE_RIGHT_UP;
3848     case EL_TUBE_RIGHT_DOWN:            return GFX_TUBE_RIGHT_DOWN;
3849     case EL_SPRING:                     return GFX_SPRING;
3850     case EL_SPRING_MOVING:              return GFX_SPRING;
3851     case EL_TRAP:                       return GFX_TRAP_INACTIVE;
3852     case EL_TRAP_ACTIVE:                return GFX_TRAP_ACTIVE;
3853     case EL_BD_WALL:                    return GFX_BD_WALL;
3854     case EL_BD_ROCK:                    return GFX_BD_ROCK;
3855     case EL_DX_SUPABOMB:                return GFX_DX_SUPABOMB;
3856     case EL_SP_MURPHY_CLONE:            return GFX_SP_MURPHY_CLONE;
3857
3858     default:
3859     {
3860       if (IS_CHAR(element))
3861         return GFX_CHAR_START + (element - EL_CHAR_START);
3862       else if (element >= EL_SP_START && element <= EL_SP_END)
3863       {
3864         int nr_element = element - EL_SP_START;
3865         int gfx_per_line = 8;
3866         int nr_graphic =
3867           (nr_element / gfx_per_line) * SP_PER_LINE +
3868           (nr_element % gfx_per_line);
3869
3870         return GFX_START_ROCKSSP + nr_graphic;
3871       }
3872       else
3873         return -1;
3874     }
3875   }
3876 }
3877
3878 int el2gfx(int element)
3879 {
3880 #if 1
3881   int graphic_OLD = el2gfx_OLD(element);
3882
3883   return graphic_OLD;
3884 #else
3885
3886   int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
3887
3888 #if DEBUG
3889   int graphic_OLD = el2gfx_OLD(element);
3890
3891   if (element >= MAX_ELEMENTS)
3892   {
3893     Error(ERR_WARN, "el2gfx: element == %d >= MAX_ELEMENTS", element);
3894   }
3895
3896   if (graphic_NEW != graphic_OLD)
3897   {
3898     Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
3899           graphic_NEW, graphic_OLD);
3900   }
3901 #endif
3902
3903   return graphic_NEW;
3904 #endif
3905 }
3906
3907 int el2img(int element)
3908 {
3909 #if 1
3910   int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
3911
3912 #if DEBUG
3913   if (graphic_NEW < 0)
3914     Error(ERR_WARN, "element %d -> graphic %d -- probably crashing now...",
3915           element, graphic_NEW);
3916 #endif
3917
3918   return graphic_NEW;
3919 #else
3920
3921   switch(element)
3922   {
3923     case EL_BD_BUTTERFLY:       return IMG_BD_BUTTERFLY;
3924     case EL_BD_FIREFLY:         return IMG_BD_FIREFLY;
3925     case EL_SP_ELECTRON:        return IMG_SP_ELECTRON;
3926
3927     default:
3928       break;
3929   }
3930
3931   return IMG_EMPTY;
3932 #endif
3933 }
3934
3935 int el_dir2img(int element, int direction)
3936 {
3937   return el_dir_act2img(element, direction, GFX_ACTION_DEFAULT);
3938 }
3939
3940 int el_dir_act2img(int element, int direction, int action)
3941 {
3942   action = graphics_action_mapping[action];
3943   direction = MV_DIR_BIT(direction);
3944
3945   return element_info[element].direction_graphic[action][direction];
3946 }