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