4771915a3cd1f80994ae209bab94664daa956294
[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 void UnmapToolButtons();
36 static void HandleToolButtons(struct GadgetInfo *);
37 static int el_act_dir2crm(int, int, int);
38 static int el_act2crm(int, int);
39
40 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
41 static int request_gadget_id = -1;
42
43 static char *print_if_not_empty(int element)
44 {
45   static char *s = NULL;
46   char *token_name = element_info[element].token_name;
47
48   if (s != NULL)
49     free(s);
50
51   s = checked_malloc(strlen(token_name) + 10 + 1);
52
53   if (element != EL_EMPTY)
54     sprintf(s, "%d\t['%s']", element, token_name);
55   else
56     sprintf(s, "%d", element);
57
58   return s;
59 }
60
61 void DumpTile(int x, int y)
62 {
63   int sx = SCREENX(x);
64   int sy = SCREENY(y);
65
66   printf_line("-", 79);
67   printf("Field Info: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
68   printf_line("-", 79);
69
70   if (!IN_LEV_FIELD(x, y))
71   {
72     printf("(not in level field)\n");
73     printf("\n");
74
75     return;
76   }
77
78   printf("  Feld:        %d\t['%s']\n", Feld[x][y],
79          element_info[Feld[x][y]].token_name);
80   printf("  Back:        %s\n", print_if_not_empty(Back[x][y]));
81   printf("  Store:       %s\n", print_if_not_empty(Store[x][y]));
82   printf("  Store2:      %s\n", print_if_not_empty(Store2[x][y]));
83   printf("  StorePlayer: %s\n", print_if_not_empty(StorePlayer[x][y]));
84   printf("  MovPos:      %d\n", MovPos[x][y]);
85   printf("  MovDir:      %d\n", MovDir[x][y]);
86   printf("  MovDelay:    %d\n", MovDelay[x][y]);
87   printf("  ChangeDelay: %d\n", ChangeDelay[x][y]);
88   printf("  GfxElement:  %d\n", GfxElement[x][y]);
89   printf("  GfxAction:   %d\n", GfxAction[x][y]);
90   printf("  GfxFrame:    %d\n", GfxFrame[x][y]);
91   printf("\n");
92 }
93
94 void SetDrawtoField(int mode)
95 {
96   if (mode == DRAW_BUFFERED && setup.soft_scrolling)
97   {
98     FX = TILEX;
99     FY = TILEY;
100     BX1 = -1;
101     BY1 = -1;
102     BX2 = SCR_FIELDX;
103     BY2 = SCR_FIELDY;
104     redraw_x1 = 1;
105     redraw_y1 = 1;
106
107     drawto_field = fieldbuffer;
108   }
109   else  /* DRAW_DIRECT, DRAW_BACKBUFFER */
110   {
111     FX = SX;
112     FY = SY;
113     BX1 = 0;
114     BY1 = 0;
115     BX2 = SCR_FIELDX - 1;
116     BY2 = SCR_FIELDY - 1;
117     redraw_x1 = 0;
118     redraw_y1 = 0;
119
120     drawto_field = (mode == DRAW_DIRECT ? window :  backbuffer);
121   }
122 }
123
124 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
125 {
126   if (game_status == GAME_MODE_PLAYING && !game.envelope_active)
127   {
128     if (force_redraw)
129     {
130       x = gfx.sx - TILEX;
131       y = gfx.sy - TILEY;
132       width = gfx.sxsize + 2 * TILEX;
133       height = gfx.sysize + 2 * TILEY;
134     }
135
136     if (force_redraw || setup.direct_draw)
137     {
138       int xx, yy;
139       int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
140       int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
141
142       if (setup.direct_draw)
143         SetDrawtoField(DRAW_BACKBUFFER);
144
145       for (xx = BX1; xx <= BX2; xx++)
146         for (yy = BY1; yy <= BY2; yy++)
147           if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
148             DrawScreenField(xx, yy);
149       DrawAllPlayers();
150
151       if (setup.direct_draw)
152         SetDrawtoField(DRAW_DIRECT);
153     }
154
155     if (setup.soft_scrolling)
156     {
157       int fx = FX, fy = FY;
158
159       fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
160       fy += (ScreenMovDir & (MV_UP|MV_DOWN)    ? ScreenGfxPos : 0);
161
162       BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
163     }
164   }
165
166   BlitBitmap(drawto, window, x, y, width, height, x, y);
167 }
168
169 void BackToFront()
170 {
171   int x,y;
172   DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
173
174   if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
175     redraw_mask &= ~REDRAW_MAIN;
176
177   if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
178     redraw_mask |= REDRAW_FIELD;
179
180   if (redraw_mask & REDRAW_FIELD)
181     redraw_mask &= ~REDRAW_TILES;
182
183   if (redraw_mask == REDRAW_NONE)
184     return;
185
186   if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
187   {
188     static boolean last_frame_skipped = FALSE;
189     boolean skip_even_when_not_scrolling = TRUE;
190     boolean just_scrolling = (ScreenMovDir != 0);
191     boolean verbose = FALSE;
192
193     if (global.fps_slowdown_factor > 1 &&
194         (FrameCounter % global.fps_slowdown_factor) &&
195         (just_scrolling || skip_even_when_not_scrolling))
196     {
197       redraw_mask &= ~REDRAW_MAIN;
198
199       last_frame_skipped = TRUE;
200
201       if (verbose)
202         printf("FRAME SKIPPED\n");
203     }
204     else
205     {
206       if (last_frame_skipped)
207         redraw_mask |= REDRAW_FIELD;
208
209       last_frame_skipped = FALSE;
210
211       if (verbose)
212         printf("frame not skipped\n");
213     }
214   }
215
216   /* synchronize X11 graphics at this point; if we would synchronize the
217      display immediately after the buffer switching (after the XFlush),
218      this could mean that we have to wait for the graphics to complete,
219      although we could go on doing calculations for the next frame */
220
221   SyncDisplay();
222
223   if (redraw_mask & REDRAW_ALL)
224   {
225     BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
226     redraw_mask = 0;
227   }
228
229   if (redraw_mask & REDRAW_FIELD)
230   {
231     if (game_status != GAME_MODE_PLAYING ||
232         redraw_mask & REDRAW_FROM_BACKBUFFER)
233     {
234       BlitBitmap(backbuffer, window,
235                  REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
236     }
237     else
238     {
239       int fx = FX, fy = FY;
240
241       if (setup.soft_scrolling)
242       {
243         fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
244         fy += (ScreenMovDir & (MV_UP | MV_DOWN)    ? ScreenGfxPos : 0);
245       }
246
247       if (setup.soft_scrolling ||
248           ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
249           ABS(ScreenMovPos) == ScrollStepSize ||
250           redraw_tiles > REDRAWTILES_THRESHOLD)
251       {
252         BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
253
254 #ifdef DEBUG
255 #if 0
256         printf("redrawing all (ScreenGfxPos == %d) because %s\n",
257                ScreenGfxPos,
258                (setup.soft_scrolling ?
259                 "setup.soft_scrolling" :
260                 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
261                 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
262                 ABS(ScreenGfxPos) == ScrollStepSize ?
263                 "ABS(ScreenGfxPos) == ScrollStepSize" :
264                 "redraw_tiles > REDRAWTILES_THRESHOLD"));
265 #endif
266 #endif
267       }
268     }
269
270     redraw_mask &= ~REDRAW_MAIN;
271   }
272
273   if (redraw_mask & REDRAW_DOORS)
274   {
275     if (redraw_mask & REDRAW_DOOR_1)
276       BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
277
278     if (redraw_mask & REDRAW_DOOR_2)
279     {
280 #if 0
281       if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
282 #endif
283         BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
284 #if 0
285       else
286       {
287         if (redraw_mask & REDRAW_VIDEO_1)
288           BlitBitmap(backbuffer, window,
289                      VX + VIDEO_DISPLAY1_XPOS, VY + VIDEO_DISPLAY1_YPOS,
290                      VIDEO_DISPLAY_XSIZE, VIDEO_DISPLAY_YSIZE,
291                      VX + VIDEO_DISPLAY1_XPOS, VY + VIDEO_DISPLAY1_YPOS);
292         if (redraw_mask & REDRAW_VIDEO_2)
293           BlitBitmap(backbuffer, window,
294                      VX + VIDEO_DISPLAY2_XPOS, VY + VIDEO_DISPLAY2_YPOS,
295                      VIDEO_DISPLAY_XSIZE, VIDEO_DISPLAY_YSIZE,
296                      VX + VIDEO_DISPLAY2_XPOS, VY + VIDEO_DISPLAY2_YPOS);
297         if (redraw_mask & REDRAW_VIDEO_3)
298           BlitBitmap(backbuffer, window,
299                      VX + VIDEO_CONTROL_XPOS, VY + VIDEO_CONTROL_YPOS,
300                      VIDEO_CONTROL_XSIZE, VIDEO_CONTROL_YSIZE,
301                      VX + VIDEO_CONTROL_XPOS, VY + VIDEO_CONTROL_YPOS);
302       }
303 #endif
304     }
305
306     if (redraw_mask & REDRAW_DOOR_3)
307       BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
308
309     redraw_mask &= ~REDRAW_DOORS;
310   }
311
312   if (redraw_mask & REDRAW_MICROLEVEL)
313   {
314     BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
315                SX, SY + 10 * TILEY);
316
317     redraw_mask &= ~REDRAW_MICROLEVEL;
318   }
319
320   if (redraw_mask & REDRAW_TILES)
321   {
322     for (x = 0; x < SCR_FIELDX; x++)
323       for (y = 0 ; y < SCR_FIELDY; y++)
324         if (redraw[redraw_x1 + x][redraw_y1 + y])
325           BlitBitmap(buffer, window,
326                      FX + x * TILEX, FY + y * TILEY, TILEX, TILEY,
327                      SX + x * TILEX, SY + y * TILEY);
328   }
329
330   if (redraw_mask & REDRAW_FPS)         /* display frames per second */
331   {
332     char text[100];
333     char info1[100];
334
335     sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
336     if (!global.fps_slowdown)
337       info1[0] = '\0';
338
339     sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
340     DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
341   }
342
343   FlushDisplay();
344
345   for (x = 0; x < MAX_BUF_XSIZE; x++)
346     for (y = 0; y < MAX_BUF_YSIZE; y++)
347       redraw[x][y] = 0;
348   redraw_tiles = 0;
349   redraw_mask = REDRAW_NONE;
350 }
351
352 void FadeToFront()
353 {
354 #if 0
355   long fading_delay = 300;
356
357   if (setup.fading && (redraw_mask & REDRAW_FIELD))
358   {
359 #endif
360
361 #if 0
362     int x,y;
363
364     ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
365     FlushDisplay();
366
367     for (i = 0; i < 2 * FULL_SYSIZE; i++)
368     {
369       for (y = 0; y < FULL_SYSIZE; y++)
370       {
371         BlitBitmap(backbuffer, window,
372                    REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
373       }
374       FlushDisplay();
375       Delay(10);
376     }
377 #endif
378
379 #if 0
380     for (i = 1; i < FULL_SYSIZE; i+=2)
381       BlitBitmap(backbuffer, window,
382                  REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
383     FlushDisplay();
384     Delay(fading_delay);
385 #endif
386
387 #if 0
388     SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
389     BlitBitmapMasked(backbuffer, window,
390                      REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
391                      REAL_SX,REAL_SY);
392     FlushDisplay();
393     Delay(fading_delay);
394
395     SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
396     BlitBitmapMasked(backbuffer, window,
397                      REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
398                      REAL_SX,REAL_SY);
399     FlushDisplay();
400     Delay(fading_delay);
401
402     SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
403     BlitBitmapMasked(backbuffer, window,
404                      REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
405                      REAL_SX,REAL_SY);
406     FlushDisplay();
407     Delay(fading_delay);
408
409     SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
410     BlitBitmapMasked(backbuffer, window,
411                      REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
412                      REAL_SX,REAL_SY);
413     FlushDisplay();
414     Delay(fading_delay);
415
416     redraw_mask &= ~REDRAW_MAIN;
417   }
418 #endif
419
420   BackToFront();
421 }
422
423 void SetMainBackgroundImage(int graphic)
424 {
425   SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
426                           graphic_info[graphic].bitmap ?
427                           graphic_info[graphic].bitmap :
428                           graphic_info[IMG_BACKGROUND].bitmap);
429 }
430
431 void SetDoorBackgroundImage(int graphic)
432 {
433   SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
434                           graphic_info[graphic].bitmap ?
435                           graphic_info[graphic].bitmap :
436                           graphic_info[IMG_BACKGROUND].bitmap);
437 }
438
439 void DrawBackground(int dst_x, int dst_y, int width, int height)
440 {
441   ClearRectangleOnBackground(backbuffer, dst_x, dst_y, width, height);
442
443   redraw_mask |= REDRAW_FIELD;
444 }
445
446 void ClearWindow()
447 {
448   DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
449
450   if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
451   {
452     ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
453     SetDrawtoField(DRAW_BUFFERED);
454   }
455   else
456     SetDrawtoField(DRAW_BACKBUFFER);
457
458   if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
459   {
460     ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
461     SetDrawtoField(DRAW_DIRECT);
462   }
463 }
464
465 void MarkTileDirty(int x, int y)
466 {
467   int xx = redraw_x1 + x;
468   int yy = redraw_y1 + y;
469
470   if (!redraw[xx][yy])
471     redraw_tiles++;
472
473   redraw[xx][yy] = TRUE;
474   redraw_mask |= REDRAW_TILES;
475 }
476
477 void SetBorderElement()
478 {
479   int x, y;
480
481   BorderElement = EL_EMPTY;
482
483   for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
484   {
485     for (x = 0; x < lev_fieldx; x++)
486     {
487       if (!IS_INDESTRUCTIBLE(Feld[x][y]))
488         BorderElement = EL_STEELWALL;
489
490       if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
491         x = lev_fieldx - 2;
492     }
493   }
494 }
495
496 void SetRandomAnimationValue(int x, int y)
497 {
498   gfx.anim_random_frame = GfxRandom[x][y];
499 }
500
501 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
502 {
503   /* animation synchronized with global frame counter, not move position */
504   if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
505     sync_frame = FrameCounter;
506
507   return getAnimationFrame(graphic_info[graphic].anim_frames,
508                            graphic_info[graphic].anim_delay,
509                            graphic_info[graphic].anim_mode,
510                            graphic_info[graphic].anim_start_frame,
511                            sync_frame);
512 }
513
514 inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
515                                 int *x, int *y, boolean get_backside)
516 {
517   struct GraphicInfo *g = &graphic_info[graphic];
518   int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
519   int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
520
521   *bitmap = g->bitmap;
522
523   if (g->offset_y == 0)         /* frames are ordered horizontally */
524   {
525     int max_width = g->anim_frames_per_line * g->width;
526 #if 1
527     int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
528
529     *x = pos % max_width;
530     *y = src_y % g->height + pos / max_width * g->height;
531 #else
532     *x = (src_x + frame * g->offset_x) % max_width;
533     *y = src_y + (src_x + frame * g->offset_x) / max_width * g->height;
534 #endif
535   }
536   else if (g->offset_x == 0)    /* frames are ordered vertically */
537   {
538     int max_height = g->anim_frames_per_line * g->height;
539 #if 1
540     int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
541
542     *x = src_x % g->width + pos / max_height * g->width;
543     *y = pos % max_height;
544 #else
545     *x = src_x + (src_y + frame * g->offset_y) / max_height * g->width;
546     *y = (src_y + frame * g->offset_y) % max_height;
547 #endif
548   }
549   else                          /* frames are ordered diagonally */
550   {
551     *x = src_x + frame * g->offset_x;
552     *y = src_y + frame * g->offset_y;
553   }
554 }
555
556 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
557 {
558   getGraphicSourceExt(graphic, frame, bitmap, x, y, FALSE);
559 }
560
561 void DrawGraphic(int x, int y, int graphic, int frame)
562 {
563 #if DEBUG
564   if (!IN_SCR_FIELD(x, y))
565   {
566     printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
567     printf("DrawGraphic(): This should never happen!\n");
568     return;
569   }
570 #endif
571
572   DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
573   MarkTileDirty(x, y);
574 }
575
576 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
577                     int frame)
578 {
579   Bitmap *src_bitmap;
580   int src_x, src_y;
581
582   getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
583   BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
584 }
585
586 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
587 {
588 #if DEBUG
589   if (!IN_SCR_FIELD(x, y))
590   {
591     printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
592     printf("DrawGraphicThruMask(): This should never happen!\n");
593     return;
594   }
595 #endif
596
597   DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
598                          frame);
599   MarkTileDirty(x, y);
600 }
601
602 void DrawGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y, int graphic,
603                             int frame)
604 {
605   Bitmap *src_bitmap;
606   int src_x, src_y;
607
608   getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
609
610   SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
611                 dst_x - src_x, dst_y - src_y);
612   BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
613 }
614
615 void DrawMiniGraphic(int x, int y, int graphic)
616 {
617   DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
618   MarkTileDirty(x / 2, y / 2);
619 }
620
621 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
622 {
623   struct GraphicInfo *g = &graphic_info[graphic];
624   int mini_startx = 0;
625   int mini_starty = g->bitmap->height * 2 / 3;
626
627   *bitmap = g->bitmap;
628   *x = mini_startx + g->src_x / 2;
629   *y = mini_starty + g->src_y / 2;
630 }
631
632 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
633 {
634   Bitmap *src_bitmap;
635   int src_x, src_y;
636
637   getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
638   BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
639 }
640
641 inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
642                                             int graphic, int frame,
643                                             int cut_mode, int mask_mode)
644 {
645   Bitmap *src_bitmap;
646   int src_x, src_y;
647   int dst_x, dst_y;
648   int width = TILEX, height = TILEY;
649   int cx = 0, cy = 0;
650
651   if (dx || dy)                 /* shifted graphic */
652   {
653     if (x < BX1)                /* object enters playfield from the left */
654     {
655       x = BX1;
656       width = dx;
657       cx = TILEX - dx;
658       dx = 0;
659     }
660     else if (x > BX2)           /* object enters playfield from the right */
661     {
662       x = BX2;
663       width = -dx;
664       dx = TILEX + dx;
665     }
666     else if (x==BX1 && dx < 0)  /* object leaves playfield to the left */
667     {
668       width += dx;
669       cx = -dx;
670       dx = 0;
671     }
672     else if (x==BX2 && dx > 0)  /* object leaves playfield to the right */
673       width -= dx;
674     else if (dx)                /* general horizontal movement */
675       MarkTileDirty(x + SIGN(dx), y);
676
677     if (y < BY1)                /* object enters playfield from the top */
678     {
679       if (cut_mode==CUT_BELOW)  /* object completely above top border */
680         return;
681
682       y = BY1;
683       height = dy;
684       cy = TILEY - dy;
685       dy = 0;
686     }
687     else if (y > BY2)           /* object enters playfield from the bottom */
688     {
689       y = BY2;
690       height = -dy;
691       dy = TILEY + dy;
692     }
693     else if (y==BY1 && dy < 0)  /* object leaves playfield to the top */
694     {
695       height += dy;
696       cy = -dy;
697       dy = 0;
698     }
699     else if (dy > 0 && cut_mode == CUT_ABOVE)
700     {
701       if (y == BY2)             /* object completely above bottom border */
702         return;
703
704       height = dy;
705       cy = TILEY - dy;
706       dy = TILEY;
707       MarkTileDirty(x, y + 1);
708     }                           /* object leaves playfield to the bottom */
709     else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
710       height -= dy;
711     else if (dy)                /* general vertical movement */
712       MarkTileDirty(x, y + SIGN(dy));
713   }
714
715 #if DEBUG
716   if (!IN_SCR_FIELD(x, y))
717   {
718     printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
719     printf("DrawGraphicShifted(): This should never happen!\n");
720     return;
721   }
722 #endif
723
724   if (width > 0 && height > 0)
725   {
726     getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
727
728     src_x += cx;
729     src_y += cy;
730
731     dst_x = FX + x * TILEX + dx;
732     dst_y = FY + y * TILEY + dy;
733
734     if (mask_mode == USE_MASKING)
735     {
736       SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
737                     dst_x - src_x, dst_y - src_y);
738       BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
739                        dst_x, dst_y);
740     }
741     else
742       BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
743                  dst_x, dst_y);
744
745     MarkTileDirty(x, y);
746   }
747 }
748
749 inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
750                                             int graphic, int frame,
751                                             int cut_mode, int mask_mode)
752 {
753   Bitmap *src_bitmap;
754   int src_x, src_y;
755   int dst_x, dst_y;
756   int width = TILEX, height = TILEY;
757   int x1 = x;
758   int y1 = y;
759   int x2 = x + SIGN(dx);
760   int y2 = y + SIGN(dy);
761   int anim_frames = graphic_info[graphic].anim_frames;
762   int sync_frame = (dx ? ABS(dx) : ABS(dy)) * anim_frames / TILESIZE;
763
764   /* re-calculate animation frame for two-tile movement animation */
765   frame = getGraphicAnimationFrame(graphic, sync_frame);
766
767   if (IN_SCR_FIELD(x1, y1))     /* movement start graphic inside screen area */
768   {
769     getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
770
771     dst_x = FX + x1 * TILEX;
772     dst_y = FY + y1 * TILEY;
773
774     if (mask_mode == USE_MASKING)
775     {
776       SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
777                     dst_x - src_x, dst_y - src_y);
778       BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
779                        dst_x, dst_y);
780     }
781     else
782       BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
783                  dst_x, dst_y);
784
785     MarkTileDirty(x1, y1);
786   }
787
788   if (IN_SCR_FIELD(x2, y2))     /* movement end graphic inside screen area */
789   {
790     getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
791
792     dst_x = FX + x2 * TILEX;
793     dst_y = FY + y2 * TILEY;
794
795     if (mask_mode == USE_MASKING)
796     {
797       SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
798                     dst_x - src_x, dst_y - src_y);
799       BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
800                        dst_x, dst_y);
801     }
802     else
803       BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
804                  dst_x, dst_y);
805
806     MarkTileDirty(x2, y2);
807   }
808
809 #if 0
810   printf("::: DONE DrawGraphicShiftedDouble");
811   BackToFront();
812   Delay(1000);
813 #endif
814 }
815
816 static void DrawGraphicShifted(int x, int y, int dx, int dy,
817                                int graphic, int frame,
818                                int cut_mode, int mask_mode)
819 {
820   if (graphic < 0)
821   {
822     DrawGraphic(x, y, graphic, frame);
823
824     return;
825   }
826
827   if (graphic_info[graphic].double_movement)    /* EM style movement images */
828     DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
829   else
830     DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
831 }
832
833 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
834                                 int frame, int cut_mode)
835 {
836   DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
837 }
838
839 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
840                           int cut_mode, int mask_mode)
841 {
842   int lx = LEVELX(x), ly = LEVELY(y);
843   int graphic;
844   int frame;
845
846   if (IN_LEV_FIELD(lx, ly))
847   {
848     SetRandomAnimationValue(lx, ly);
849
850     graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
851     frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
852
853     /* do not use double (EM style) movement graphic when not moving */
854     if (graphic_info[graphic].double_movement && !dx && !dy)
855     {
856       graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
857       frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
858     }
859   }
860   else  /* border element */
861   {
862     graphic = el2img(element);
863     frame = getGraphicAnimationFrame(graphic, -1);
864   }
865
866   if (element == EL_EXPANDABLE_WALL)
867   {
868     boolean left_stopped = FALSE, right_stopped = FALSE;
869
870     if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
871       left_stopped = TRUE;
872     if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
873       right_stopped = TRUE;
874
875     if (left_stopped && right_stopped)
876       graphic = IMG_WALL;
877     else if (left_stopped)
878     {
879       graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
880       frame = graphic_info[graphic].anim_frames - 1;
881     }
882     else if (right_stopped)
883     {
884       graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
885       frame = graphic_info[graphic].anim_frames - 1;
886     }
887   }
888
889   if (dx || dy)
890     DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
891   else if (mask_mode == USE_MASKING)
892     DrawGraphicThruMask(x, y, graphic, frame);
893   else
894     DrawGraphic(x, y, graphic, frame);
895 }
896
897 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
898                          int cut_mode, int mask_mode)
899 {
900   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
901     DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
902                          cut_mode, mask_mode);
903 }
904
905 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
906                               int cut_mode)
907 {
908   DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
909 }
910
911 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
912                              int cut_mode)
913 {
914   DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
915 }
916
917 void DrawLevelElementThruMask(int x, int y, int element)
918 {
919   DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
920 }
921
922 void DrawLevelFieldThruMask(int x, int y)
923 {
924   DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
925 }
926
927 #define TILE_GFX_ELEMENT(x, y)                                              \
928         (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ?   \
929          GfxElement[x][y] : Feld[x][y])
930
931 static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
932 {
933   Bitmap *src_bitmap;
934   int src_x, src_y;
935   int sx = SCREENX(x), sy = SCREENY(y);
936   int element;
937   int width, height, cx, cy, i;
938 #if 1
939   int crumbled_border_size = graphic_info[graphic].border_size;
940 #else
941   int snip = TILEX / 8; /* number of border pixels from "crumbled graphic" */
942 #endif
943   static int xy[4][2] =
944   {
945     { 0, -1 },
946     { -1, 0 },
947     { +1, 0 },
948     { 0, +1 }
949   };
950
951 #if 0
952   if (x == 0 && y == 7)
953     printf("::: %d, %d [%d]\n", GfxElement[x][y], Feld[x][y],
954            crumbled_border_size);
955 #endif
956
957   if (!IN_LEV_FIELD(x, y))
958     return;
959
960   element = TILE_GFX_ELEMENT(x, y);
961
962   /* crumble field itself */
963   if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
964   {
965     if (!IN_SCR_FIELD(sx, sy))
966       return;
967
968     getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
969
970     for (i = 0; i < 4; i++)
971     {
972       int xx = x + xy[i][0];
973       int yy = y + xy[i][1];
974
975 #if 1
976       element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
977                  BorderElement);
978 #else
979       element = (IN_LEV_FIELD(xx, yy) ? Feld[xx][yy] : BorderElement);
980 #endif
981
982       /* check if neighbour field is of same type */
983       if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
984         continue;
985
986 #if 0
987       if (Feld[x][y] == EL_CUSTOM_START + 123)
988         printf("::: crumble [%d] THE CHAOS ENGINE (%d, %d): %d, %d\n",
989                i, Feld[x][y], element,
990                GFX_CRUMBLED(element), IS_MOVING(x, y));
991 #endif
992
993       if (i == 1 || i == 2)
994       {
995         width = crumbled_border_size;
996         height = TILEY;
997         cx = (i == 2 ? TILEX - crumbled_border_size : 0);
998         cy = 0;
999       }
1000       else
1001       {
1002         width = TILEX;
1003         height = crumbled_border_size;
1004         cx = 0;
1005         cy = (i == 3 ? TILEY - crumbled_border_size : 0);
1006       }
1007
1008       BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1009                  width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1010     }
1011
1012     MarkTileDirty(sx, sy);
1013   }
1014   else          /* crumble neighbour fields */
1015   {
1016 #if 0
1017     getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1018 #endif
1019
1020     for (i = 0; i < 4; i++)
1021     {
1022       int xx = x + xy[i][0];
1023       int yy = y + xy[i][1];
1024       int sxx = sx + xy[i][0];
1025       int syy = sy + xy[i][1];
1026
1027 #if 1
1028       if (!IN_LEV_FIELD(xx, yy) ||
1029           !IN_SCR_FIELD(sxx, syy) ||
1030           IS_MOVING(xx, yy))
1031         continue;
1032
1033       element = TILE_GFX_ELEMENT(xx, yy);
1034
1035       if (!GFX_CRUMBLED(element))
1036         continue;
1037 #else
1038       if (!IN_LEV_FIELD(xx, yy) ||
1039           !IN_SCR_FIELD(sxx, syy) ||
1040           !GFX_CRUMBLED(Feld[xx][yy]) ||
1041           IS_MOVING(xx, yy))
1042         continue;
1043 #endif
1044
1045 #if 1
1046       graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
1047       crumbled_border_size = graphic_info[graphic].border_size;
1048
1049       getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1050 #endif
1051
1052       if (i == 1 || i == 2)
1053       {
1054         width = crumbled_border_size;
1055         height = TILEY;
1056         cx = (i == 1 ? TILEX - crumbled_border_size : 0);
1057         cy = 0;
1058       }
1059       else
1060       {
1061         width = TILEX;
1062         height = crumbled_border_size;
1063         cx = 0;
1064         cy = (i == 0 ? TILEY - crumbled_border_size : 0);
1065       }
1066
1067       BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1068                  width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
1069
1070       MarkTileDirty(sxx, syy);
1071     }
1072   }
1073 }
1074
1075 void DrawLevelFieldCrumbledSand(int x, int y)
1076 {
1077 #if 1
1078   int graphic;
1079
1080   if (!IN_LEV_FIELD(x, y))
1081     return;
1082
1083   graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
1084
1085   DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
1086 #else
1087   DrawLevelFieldCrumbledSandExt(x, y, IMG_SAND_CRUMBLED, 0);
1088 #endif
1089 }
1090
1091 void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
1092                                        int step_frame)
1093 {
1094 #if 1
1095   int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
1096   int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
1097 #else
1098   int graphic1 = el_act_dir2img(EL_SAND,          ACTION_DIGGING, direction);
1099   int graphic2 = el_act_dir2img(EL_SAND_CRUMBLED, ACTION_DIGGING, direction);
1100 #endif
1101   int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
1102   int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
1103   int sx = SCREENX(x), sy = SCREENY(y);
1104
1105   DrawGraphic(sx, sy, graphic1, frame1);
1106   DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
1107 }
1108
1109 void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
1110 {
1111   int sx = SCREENX(x), sy = SCREENY(y);
1112   static int xy[4][2] =
1113   {
1114     { 0, -1 },
1115     { -1, 0 },
1116     { +1, 0 },
1117     { 0, +1 }
1118   };
1119   int i;
1120
1121   for (i = 0; i < 4; i++)
1122   {
1123     int xx = x + xy[i][0];
1124     int yy = y + xy[i][1];
1125     int sxx = sx + xy[i][0];
1126     int syy = sy + xy[i][1];
1127
1128     if (!IN_LEV_FIELD(xx, yy) ||
1129         !IN_SCR_FIELD(sxx, syy) ||
1130         !GFX_CRUMBLED(Feld[xx][yy]) ||
1131         IS_MOVING(xx, yy))
1132       continue;
1133
1134     DrawLevelField(xx, yy);
1135   }
1136 }
1137
1138 static int getBorderElement(int x, int y)
1139 {
1140   int border[7][2] =
1141   {
1142     { EL_STEELWALL_TOPLEFT,             EL_INVISIBLE_STEELWALL_TOPLEFT     },
1143     { EL_STEELWALL_TOPRIGHT,            EL_INVISIBLE_STEELWALL_TOPRIGHT    },
1144     { EL_STEELWALL_BOTTOMLEFT,          EL_INVISIBLE_STEELWALL_BOTTOMLEFT  },
1145     { EL_STEELWALL_BOTTOMRIGHT,         EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1146     { EL_STEELWALL_VERTICAL,            EL_INVISIBLE_STEELWALL_VERTICAL    },
1147     { EL_STEELWALL_HORIZONTAL,          EL_INVISIBLE_STEELWALL_HORIZONTAL  },
1148     { EL_STEELWALL,                     EL_INVISIBLE_STEELWALL             }
1149   };
1150   int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1151   int steel_position = (x == -1         && y == -1              ? 0 :
1152                         x == lev_fieldx && y == -1              ? 1 :
1153                         x == -1         && y == lev_fieldy      ? 2 :
1154                         x == lev_fieldx && y == lev_fieldy      ? 3 :
1155                         x == -1         || x == lev_fieldx      ? 4 :
1156                         y == -1         || y == lev_fieldy      ? 5 : 6);
1157
1158   return border[steel_position][steel_type];
1159 }
1160
1161 void DrawScreenElement(int x, int y, int element)
1162 {
1163   DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1164   DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
1165 }
1166
1167 void DrawLevelElement(int x, int y, int element)
1168 {
1169   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1170     DrawScreenElement(SCREENX(x), SCREENY(y), element);
1171 }
1172
1173 void DrawScreenField(int x, int y)
1174 {
1175   int lx = LEVELX(x), ly = LEVELY(y);
1176   int element, content;
1177
1178   if (!IN_LEV_FIELD(lx, ly))
1179   {
1180     if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1181       element = EL_EMPTY;
1182     else
1183       element = getBorderElement(lx, ly);
1184
1185     DrawScreenElement(x, y, element);
1186     return;
1187   }
1188
1189   element = Feld[lx][ly];
1190   content = Store[lx][ly];
1191
1192   if (IS_MOVING(lx, ly))
1193   {
1194     int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1195     boolean cut_mode = NO_CUTTING;
1196
1197     if (element == EL_QUICKSAND_EMPTYING ||
1198         element == EL_MAGIC_WALL_EMPTYING ||
1199         element == EL_BD_MAGIC_WALL_EMPTYING ||
1200         element == EL_AMOEBA_DROPPING)
1201       cut_mode = CUT_ABOVE;
1202     else if (element == EL_QUICKSAND_FILLING ||
1203              element == EL_MAGIC_WALL_FILLING ||
1204              element == EL_BD_MAGIC_WALL_FILLING)
1205       cut_mode = CUT_BELOW;
1206
1207     if (cut_mode == CUT_ABOVE)
1208       DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1209     else
1210       DrawScreenElement(x, y, EL_EMPTY);
1211
1212     if (horiz_move)
1213       DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1214     else if (cut_mode == NO_CUTTING)
1215       DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1216     else
1217       DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1218
1219     if (content == EL_ACID)
1220     {
1221       int dir = MovDir[lx][ly];
1222       int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
1223       int newly = ly + (dir == MV_UP   ? -1 : dir == MV_DOWN  ? +1 : 0);
1224
1225       DrawLevelElementThruMask(newlx, newly, EL_ACID);
1226     }
1227   }
1228   else if (IS_BLOCKED(lx, ly))
1229   {
1230     int oldx, oldy;
1231     int sx, sy;
1232     int horiz_move;
1233     boolean cut_mode = NO_CUTTING;
1234     int element_old, content_old;
1235
1236     Blocked2Moving(lx, ly, &oldx, &oldy);
1237     sx = SCREENX(oldx);
1238     sy = SCREENY(oldy);
1239     horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1240                   MovDir[oldx][oldy] == MV_RIGHT);
1241
1242     element_old = Feld[oldx][oldy];
1243     content_old = Store[oldx][oldy];
1244
1245     if (element_old == EL_QUICKSAND_EMPTYING ||
1246         element_old == EL_MAGIC_WALL_EMPTYING ||
1247         element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1248         element_old == EL_AMOEBA_DROPPING)
1249       cut_mode = CUT_ABOVE;
1250
1251     DrawScreenElement(x, y, EL_EMPTY);
1252
1253     if (horiz_move)
1254       DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1255                                NO_CUTTING);
1256     else if (cut_mode == NO_CUTTING)
1257       DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1258                                cut_mode);
1259     else
1260       DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1261                                cut_mode);
1262   }
1263   else if (IS_DRAWABLE(element))
1264     DrawScreenElement(x, y, element);
1265   else
1266     DrawScreenElement(x, y, EL_EMPTY);
1267 }
1268
1269 void DrawLevelField(int x, int y)
1270 {
1271   if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1272     DrawScreenField(SCREENX(x), SCREENY(y));
1273   else if (IS_MOVING(x, y))
1274   {
1275     int newx,newy;
1276
1277     Moving2Blocked(x, y, &newx, &newy);
1278     if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1279       DrawScreenField(SCREENX(newx), SCREENY(newy));
1280   }
1281   else if (IS_BLOCKED(x, y))
1282   {
1283     int oldx, oldy;
1284
1285     Blocked2Moving(x, y, &oldx, &oldy);
1286     if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1287       DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1288   }
1289 }
1290
1291 void DrawMiniElement(int x, int y, int element)
1292 {
1293   int graphic;
1294
1295   graphic = el2edimg(element);
1296   DrawMiniGraphic(x, y, graphic);
1297 }
1298
1299 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1300 {
1301   int x = sx + scroll_x, y = sy + scroll_y;
1302
1303   if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1304     DrawMiniElement(sx, sy, EL_EMPTY);
1305   else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1306     DrawMiniElement(sx, sy, Feld[x][y]);
1307   else
1308     DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1309 }
1310
1311 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
1312                             int x, int y, int xsize, int ysize, int font_nr)
1313 {
1314   int font_width  = getFontWidth(font_nr);
1315   int font_height = getFontHeight(font_nr);
1316   int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1317   Bitmap *src_bitmap;
1318   int src_x, src_y;
1319   int dst_x = SX + startx + x * font_width;
1320   int dst_y = SY + starty + y * font_height;
1321   int width  = graphic_info[graphic].width;
1322   int height = graphic_info[graphic].height;
1323   int inner_width  = MAX(width  - 2 * font_width,  font_width);
1324   int inner_height = MAX(height - 2 * font_height, font_height);
1325   int inner_sx = (width >= 3 * font_width ? font_width : 0);
1326   int inner_sy = (height >= 3 * font_height ? font_height : 0);
1327   boolean draw_masked = graphic_info[graphic].draw_masked;
1328
1329   getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1330
1331   if (src_bitmap == NULL || width < font_width || height < font_height)
1332   {
1333     ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
1334     return;
1335   }
1336
1337   src_x += (x == 0 ? 0 : x == xsize - 1 ? width  - font_width  :
1338             inner_sx + (x - 1) * font_width  % inner_width);
1339   src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
1340             inner_sy + (y - 1) * font_height % inner_height);
1341
1342   if (draw_masked)
1343   {
1344     SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1345                   dst_x - src_x, dst_y - src_y);
1346     BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1347                      dst_x, dst_y);
1348   }
1349   else
1350     BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1351                dst_x, dst_y);
1352 }
1353
1354 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
1355 {
1356   int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1357 #if 1
1358   Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1359   int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1360 #else
1361   boolean draw_masked = graphic_info[graphic].draw_masked;
1362   int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1363 #endif
1364   boolean ffwd_delay = (tape.playing && tape.fast_forward);
1365   boolean no_delay = (tape.warp_forward);
1366   unsigned long anim_delay = 0;
1367   int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
1368   int anim_delay_value = (no_delay ? 0 : frame_delay_value);
1369   int font_nr = FONT_ENVELOPE_1 + envelope_nr;
1370   int font_width = getFontWidth(font_nr);
1371   int font_height = getFontHeight(font_nr);
1372   int max_xsize = level.envelope_xsize[envelope_nr];
1373   int max_ysize = level.envelope_ysize[envelope_nr];
1374   int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
1375   int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
1376   int xend = max_xsize;
1377   int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
1378   int xstep = (xstart < xend ? 1 : 0);
1379   int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
1380   int x, y;
1381
1382   for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
1383   {
1384     int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
1385     int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
1386     int sx = (SXSIZE - xsize * font_width)  / 2;
1387     int sy = (SYSIZE - ysize * font_height) / 2;
1388     int xx, yy;
1389
1390     SetDrawtoField(DRAW_BUFFERED);
1391
1392     BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1393
1394     SetDrawtoField(DRAW_BACKBUFFER);
1395
1396     for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
1397       DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
1398
1399     DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
1400                        level.envelope_text[envelope_nr], font_nr, max_xsize,
1401                        xsize - 2, ysize - 2, mask_mode);
1402
1403     redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1404     BackToFront();
1405
1406     WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1407   }
1408 }
1409
1410 void ShowEnvelope(int envelope_nr)
1411 {
1412   int element = EL_ENVELOPE_1 + envelope_nr;
1413   int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1414   int sound_opening = element_info[element].sound[ACTION_OPENING];
1415   int sound_closing = element_info[element].sound[ACTION_CLOSING];
1416   boolean ffwd_delay = (tape.playing && tape.fast_forward);
1417   boolean no_delay = (tape.warp_forward);
1418   int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
1419   int wait_delay_value = (no_delay ? 0 : normal_delay_value);
1420   int anim_mode = graphic_info[graphic].anim_mode;
1421   int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
1422                         anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
1423
1424   game.envelope_active = TRUE;  /* needed for RedrawPlayfield() events */
1425
1426   PlaySoundStereo(sound_opening, SOUND_MIDDLE);
1427
1428   if (anim_mode == ANIM_DEFAULT)
1429     AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
1430
1431   AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
1432
1433   if (tape.playing)
1434     Delay(wait_delay_value);
1435   else
1436     WaitForEventToContinue();
1437
1438   PlaySoundStereo(sound_closing, SOUND_MIDDLE);
1439
1440   if (anim_mode != ANIM_NONE)
1441     AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
1442
1443   if (anim_mode == ANIM_DEFAULT)
1444     AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
1445
1446   game.envelope_active = FALSE;
1447
1448   SetDrawtoField(DRAW_BUFFERED);
1449
1450   redraw_mask |= REDRAW_FIELD;
1451   BackToFront();
1452 }
1453
1454 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1455 {
1456   Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1457   int mini_startx = src_bitmap->width * 3 / 4;
1458   int mini_starty = src_bitmap->height * 2 / 3;
1459   int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1460   int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1461
1462   *bitmap = src_bitmap;
1463   *x = src_x;
1464   *y = src_y;
1465 }
1466
1467 void DrawMicroElement(int xpos, int ypos, int element)
1468 {
1469   Bitmap *src_bitmap;
1470   int src_x, src_y;
1471   int graphic = el2preimg(element);
1472
1473   getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1474   BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1475              xpos, ypos);
1476 }
1477
1478 void DrawLevel()
1479 {
1480   int x,y;
1481
1482   SetDrawBackgroundMask(REDRAW_NONE);
1483   ClearWindow();
1484
1485   for (x = BX1; x <= BX2; x++)
1486     for (y = BY1; y <= BY2; y++)
1487       DrawScreenField(x, y);
1488
1489   redraw_mask |= REDRAW_FIELD;
1490 }
1491
1492 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1493 {
1494   int x,y;
1495
1496   for (x = 0; x < size_x; x++)
1497     for (y = 0; y < size_y; y++)
1498       DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1499
1500   redraw_mask |= REDRAW_FIELD;
1501 }
1502
1503 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1504 {
1505   int x, y;
1506
1507   DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1508
1509   if (lev_fieldx < STD_LEV_FIELDX)
1510     xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1511   if (lev_fieldy < STD_LEV_FIELDY)
1512     ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1513
1514   xpos += MICRO_TILEX;
1515   ypos += MICRO_TILEY;
1516
1517   for (x = -1; x <= STD_LEV_FIELDX; x++)
1518   {
1519     for (y = -1; y <= STD_LEV_FIELDY; y++)
1520     {
1521       int lx = from_x + x, ly = from_y + y;
1522
1523       if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1524         DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1525                          level.field[lx][ly]);
1526       else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1527                && BorderElement != EL_EMPTY)
1528         DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1529                          getBorderElement(lx, ly));
1530     }
1531   }
1532
1533   redraw_mask |= REDRAW_MICROLEVEL;
1534 }
1535
1536 #define MICROLABEL_EMPTY                0
1537 #define MICROLABEL_LEVEL_NAME           1
1538 #define MICROLABEL_CREATED_BY           2
1539 #define MICROLABEL_LEVEL_AUTHOR         3
1540 #define MICROLABEL_IMPORTED_FROM        4
1541 #define MICROLABEL_LEVEL_IMPORT_INFO    5
1542
1543 static void DrawMicroLevelLabelExt(int mode)
1544 {
1545   char label_text[MAX_OUTPUT_LINESIZE + 1];
1546   int max_len_label_text;
1547   int font_nr = FONT_TEXT_2;
1548
1549   if (mode == MICROLABEL_CREATED_BY || mode == MICROLABEL_IMPORTED_FROM)
1550     font_nr = FONT_TEXT_3;
1551
1552   max_len_label_text = SXSIZE / getFontWidth(font_nr);
1553
1554   DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, getFontHeight(font_nr));
1555
1556   strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1557                        mode == MICROLABEL_CREATED_BY ? "created by" :
1558                        mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1559                        mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1560                        mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1561                        leveldir_current->imported_from : ""),
1562           max_len_label_text);
1563   label_text[max_len_label_text] = '\0';
1564
1565   if (strlen(label_text) > 0)
1566   {
1567     int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1568     int lypos = MICROLABEL_YPOS;
1569
1570     DrawText(lxpos, lypos, label_text, font_nr);
1571   }
1572
1573   redraw_mask |= REDRAW_MICROLEVEL;
1574 }
1575
1576 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1577 {
1578   static unsigned long scroll_delay = 0;
1579   static unsigned long label_delay = 0;
1580   static int from_x, from_y, scroll_direction;
1581   static int label_state, label_counter;
1582   int last_game_status = game_status;   /* save current game status */
1583
1584   /* force PREVIEW font on preview level */
1585   game_status = GAME_MODE_PSEUDO_PREVIEW;
1586
1587   if (restart)
1588   {
1589     from_x = from_y = 0;
1590     scroll_direction = MV_RIGHT;
1591     label_state = 1;
1592     label_counter = 0;
1593
1594     DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1595     DrawMicroLevelLabelExt(label_state);
1596
1597     /* initialize delay counters */
1598     DelayReached(&scroll_delay, 0);
1599     DelayReached(&label_delay, 0);
1600
1601     if (leveldir_current->name)
1602     {
1603       int text_width = getTextWidth(leveldir_current->name, FONT_TEXT_1);
1604       int lxpos = SX + (SXSIZE - text_width) / 2;
1605       int lypos = SY + 352;
1606
1607       DrawText(lxpos, lypos, leveldir_current->name, FONT_TEXT_1);
1608     }
1609
1610     game_status = last_game_status;     /* restore current game status */
1611
1612     return;
1613   }
1614
1615   /* scroll micro level, if needed */
1616   if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1617       DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1618   {
1619     switch (scroll_direction)
1620     {
1621       case MV_LEFT:
1622         if (from_x > 0)
1623           from_x--;
1624         else
1625           scroll_direction = MV_UP;
1626         break;
1627
1628       case MV_RIGHT:
1629         if (from_x < lev_fieldx - STD_LEV_FIELDX)
1630           from_x++;
1631         else
1632           scroll_direction = MV_DOWN;
1633         break;
1634
1635       case MV_UP:
1636         if (from_y > 0)
1637           from_y--;
1638         else
1639           scroll_direction = MV_RIGHT;
1640         break;
1641
1642       case MV_DOWN:
1643         if (from_y < lev_fieldy - STD_LEV_FIELDY)
1644           from_y++;
1645         else
1646           scroll_direction = MV_LEFT;
1647         break;
1648
1649       default:
1650         break;
1651     }
1652
1653     DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1654   }
1655
1656   /* redraw micro level label, if needed */
1657   if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1658       strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1659       strcmp(level.author, leveldir_current->name) != 0 &&
1660       DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1661   {
1662     int max_label_counter = 23;
1663
1664     if (leveldir_current->imported_from != NULL)
1665       max_label_counter += 14;
1666
1667     label_counter = (label_counter + 1) % max_label_counter;
1668     label_state = (label_counter >= 0 && label_counter <= 7 ?
1669                    MICROLABEL_LEVEL_NAME :
1670                    label_counter >= 9 && label_counter <= 12 ?
1671                    MICROLABEL_CREATED_BY :
1672                    label_counter >= 14 && label_counter <= 21 ?
1673                    MICROLABEL_LEVEL_AUTHOR :
1674                    label_counter >= 23 && label_counter <= 26 ?
1675                    MICROLABEL_IMPORTED_FROM :
1676                    label_counter >= 28 && label_counter <= 35 ?
1677                    MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1678     DrawMicroLevelLabelExt(label_state);
1679   }
1680
1681   game_status = last_game_status;       /* restore current game status */
1682 }
1683
1684 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
1685                                     int graphic, int sync_frame, int mask_mode)
1686 {
1687   int frame = getGraphicAnimationFrame(graphic, sync_frame);
1688
1689   if (mask_mode == USE_MASKING)
1690     DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
1691   else
1692     DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
1693 }
1694
1695 inline void DrawGraphicAnimation(int x, int y, int graphic)
1696 {
1697   int lx = LEVELX(x), ly = LEVELY(y);
1698
1699   if (!IN_SCR_FIELD(x, y))
1700     return;
1701
1702   DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1703                           graphic, GfxFrame[lx][ly], NO_MASKING);
1704   MarkTileDirty(x, y);
1705 }
1706
1707 void DrawLevelGraphicAnimation(int x, int y, int graphic)
1708 {
1709   DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1710 }
1711
1712 void DrawLevelElementAnimation(int x, int y, int element)
1713 {
1714 #if 1
1715   int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1716
1717   DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1718 #else
1719   DrawGraphicAnimation(SCREENX(x), SCREENY(y), el2img(element));
1720 #endif
1721 }
1722
1723 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
1724 {
1725   int sx = SCREENX(x), sy = SCREENY(y);
1726
1727   if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1728     return;
1729
1730   if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1731     return;
1732
1733   DrawGraphicAnimation(sx, sy, graphic);
1734
1735   if (GFX_CRUMBLED(Feld[x][y]))
1736     DrawLevelFieldCrumbledSand(x, y);
1737 }
1738
1739 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
1740 {
1741   int sx = SCREENX(x), sy = SCREENY(y);
1742   int graphic;
1743
1744   if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1745     return;
1746
1747   graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1748
1749   if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1750     return;
1751
1752   DrawGraphicAnimation(sx, sy, graphic);
1753
1754   if (GFX_CRUMBLED(element))
1755     DrawLevelFieldCrumbledSand(x, y);
1756 }
1757
1758 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
1759 {
1760   if (player->use_murphy_graphic)
1761   {
1762     /* this works only because currently only one player can be "murphy" ... */
1763     static int last_horizontal_dir = MV_LEFT;
1764     int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
1765
1766     if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1767       last_horizontal_dir = move_dir;
1768
1769     if (graphic == IMG_SP_MURPHY)       /* undefined => use special graphic */
1770     {
1771       int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
1772
1773       graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
1774     }
1775
1776     return graphic;
1777   }
1778   else
1779     return el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
1780 }
1781
1782 static boolean equalGraphics(int graphic1, int graphic2)
1783 {
1784   struct GraphicInfo *g1 = &graphic_info[graphic1];
1785   struct GraphicInfo *g2 = &graphic_info[graphic2];
1786
1787   return (g1->bitmap      == g2->bitmap &&
1788           g1->src_x       == g2->src_x &&
1789           g1->src_y       == g2->src_y &&
1790           g1->anim_frames == g2->anim_frames &&
1791           g1->anim_delay  == g2->anim_delay &&
1792           g1->anim_mode   == g2->anim_mode);
1793 }
1794
1795 void DrawAllPlayers()
1796 {
1797   int i;
1798
1799   for (i = 0; i < MAX_PLAYERS; i++)
1800     if (stored_player[i].active)
1801       DrawPlayer(&stored_player[i]);
1802 }
1803
1804 void DrawPlayerField(int x, int y)
1805 {
1806   if (!IS_PLAYER(x, y))
1807     return;
1808
1809   DrawPlayer(PLAYERINFO(x, y));
1810 }
1811
1812 void DrawPlayer(struct PlayerInfo *player)
1813 {
1814   int jx = player->jx;
1815   int jy = player->jy;
1816   int move_dir = player->MovDir;
1817 #if 0
1818   int last_jx = player->last_jx;
1819   int last_jy = player->last_jy;
1820   int next_jx = jx + (jx - last_jx);
1821   int next_jy = jy + (jy - last_jy);
1822   boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
1823 #else
1824   int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
1825   int dy = (move_dir == MV_UP   ? -1 : move_dir == MV_DOWN  ? +1 : 0);
1826   int last_jx = (player->is_moving ? jx - dx : jx);
1827   int last_jy = (player->is_moving ? jy - dy : jy);
1828   int next_jx = jx + dx;
1829   int next_jy = jy + dy;
1830   boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
1831 #endif
1832   int sx = SCREENX(jx), sy = SCREENY(jy);
1833   int sxx = 0, syy = 0;
1834   int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
1835   int graphic;
1836   int action = ACTION_DEFAULT;
1837   int last_player_graphic = getPlayerGraphic(player, move_dir);
1838   int last_player_frame = player->Frame;
1839   int frame = 0;
1840
1841   if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
1842     return;
1843
1844 #if DEBUG
1845   if (!IN_LEV_FIELD(jx, jy))
1846   {
1847     printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
1848     printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
1849     printf("DrawPlayerField(): This should never happen!\n");
1850     return;
1851   }
1852 #endif
1853
1854   if (element == EL_EXPLOSION)
1855     return;
1856
1857   action = (player->is_pushing    ? ACTION_PUSHING         :
1858             player->is_digging    ? ACTION_DIGGING         :
1859             player->is_collecting ? ACTION_COLLECTING      :
1860             player->is_moving     ? ACTION_MOVING          :
1861             player->is_snapping   ? ACTION_SNAPPING        :
1862             player->is_dropping   ? ACTION_DROPPING        :
1863             player->is_waiting    ? player->action_waiting : ACTION_DEFAULT);
1864
1865   InitPlayerGfxAnimation(player, action, move_dir);
1866
1867   /* ----------------------------------------------------------------------- */
1868   /* draw things in the field the player is leaving, if needed               */
1869   /* ----------------------------------------------------------------------- */
1870
1871 #if 1
1872   if (player->is_moving)
1873 #else
1874   if (player_is_moving)
1875 #endif
1876   {
1877     if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
1878     {
1879       DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
1880
1881       if (last_element == EL_DYNAMITE_ACTIVE ||
1882           last_element == EL_SP_DISK_RED_ACTIVE)
1883         DrawDynamite(last_jx, last_jy);
1884       else
1885         DrawLevelFieldThruMask(last_jx, last_jy);
1886     }
1887     else if (last_element == EL_DYNAMITE_ACTIVE ||
1888              last_element == EL_SP_DISK_RED_ACTIVE)
1889       DrawDynamite(last_jx, last_jy);
1890     else
1891       DrawLevelField(last_jx, last_jy);
1892
1893     if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
1894       DrawLevelElement(next_jx, next_jy, EL_EMPTY);
1895   }
1896
1897   if (!IN_SCR_FIELD(sx, sy))
1898     return;
1899
1900   if (setup.direct_draw)
1901     SetDrawtoField(DRAW_BUFFERED);
1902
1903   /* ----------------------------------------------------------------------- */
1904   /* draw things behind the player, if needed                                */
1905   /* ----------------------------------------------------------------------- */
1906
1907   if (Back[jx][jy])
1908     DrawLevelElement(jx, jy, Back[jx][jy]);
1909   else if (IS_ACTIVE_BOMB(element))
1910     DrawLevelElement(jx, jy, EL_EMPTY);
1911   else
1912   {
1913     if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
1914     {
1915       if (GFX_CRUMBLED(GfxElement[jx][jy]))
1916         DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
1917       else
1918       {
1919         int old_element = GfxElement[jx][jy];
1920         int old_graphic = el_act_dir2img(old_element, action, move_dir);
1921         int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
1922
1923         DrawGraphic(sx, sy, old_graphic, frame);
1924       }
1925     }
1926     else
1927     {
1928       GfxElement[jx][jy] = EL_UNDEFINED;
1929
1930       DrawLevelField(jx, jy);
1931     }
1932   }
1933
1934   /* ----------------------------------------------------------------------- */
1935   /* draw player himself                                                     */
1936   /* ----------------------------------------------------------------------- */
1937
1938 #if 1
1939
1940   graphic = getPlayerGraphic(player, move_dir);
1941
1942   /* in the case of changed player action or direction, prevent the current
1943      animation frame from being restarted for identical animations */
1944   if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
1945     player->Frame = last_player_frame;
1946
1947 #else
1948
1949   if (player->use_murphy_graphic)
1950   {
1951     static int last_horizontal_dir = MV_LEFT;
1952
1953     if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1954       last_horizontal_dir = move_dir;
1955
1956     graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
1957
1958     if (graphic == IMG_SP_MURPHY)       /* undefined => use special graphic */
1959     {
1960       int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
1961
1962       graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
1963     }
1964   }
1965   else
1966     graphic = el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
1967
1968 #endif
1969
1970   frame = getGraphicAnimationFrame(graphic, player->Frame);
1971
1972   if (player->GfxPos)
1973   {
1974     if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1975       sxx = player->GfxPos;
1976     else
1977       syy = player->GfxPos;
1978   }
1979
1980   if (!setup.soft_scrolling && ScreenMovPos)
1981     sxx = syy = 0;
1982
1983   DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
1984
1985   if (SHIELD_ON(player))
1986   {
1987     int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
1988                    IMG_SHIELD_NORMAL_ACTIVE);
1989     int frame = getGraphicAnimationFrame(graphic, -1);
1990
1991     DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
1992   }
1993
1994   /* ----------------------------------------------------------------------- */
1995   /* draw things the player is pushing, if needed                            */
1996   /* ----------------------------------------------------------------------- */
1997
1998 #if 0
1999   printf("::: %d, %d [%d, %d] [%d]\n",
2000          player->is_pushing, player_is_moving, player->GfxAction,
2001          player->is_moving, player_is_moving);
2002 #endif
2003
2004 #if 1
2005   if (player->is_pushing && player->is_moving)
2006 #else
2007   if (player->is_pushing && player_is_moving)
2008 #endif
2009   {
2010 #if 1
2011     int px = SCREENX(jx), py = SCREENY(jy);
2012     int pxx = (TILEX - ABS(sxx)) * dx;
2013     int pyy = (TILEY - ABS(syy)) * dy;
2014 #else
2015     int px = SCREENX(next_jx), py = SCREENY(next_jy);
2016     int pxx = sxx;
2017     int pyy = syy;
2018 #endif
2019
2020 #if 1
2021     int graphic;
2022     int frame;
2023
2024     if (!IS_MOVING(jx, jy))             /* push movement already finished */
2025       element = Feld[next_jx][next_jy];
2026
2027     graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
2028     frame = getGraphicAnimationFrame(graphic, player->StepFrame);
2029
2030     /* draw background element under pushed element (like the Sokoban field) */
2031     if (Back[next_jx][next_jy])
2032       DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
2033
2034     /* masked drawing is needed for EMC style (double) movement graphics */
2035     DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
2036
2037 #else
2038     if (Back[next_jx][next_jy])
2039       DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
2040
2041     if ((pxx || pyy) && element == EL_SOKOBAN_OBJECT)
2042       DrawGraphicShiftedThruMask(px, py, pxx, pyy, IMG_SOKOBAN_OBJECT, 0,
2043                                  NO_CUTTING);
2044     else
2045     {
2046       int element = MovingOrBlocked2Element(next_jx, next_jy);
2047       int graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
2048 #if 1
2049       int frame = getGraphicAnimationFrame(graphic, player->StepFrame);
2050 #else
2051       int frame = getGraphicAnimationFrame(graphic, player->Frame);
2052 #endif
2053
2054 #if 1
2055       /* masked drawing is needed for EMC style (double) movement graphics */
2056       DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame,
2057                                  NO_CUTTING);
2058 #else
2059       DrawGraphicShifted(px, py, pxx, pyy, graphic, frame,
2060                          NO_CUTTING, NO_MASKING);
2061 #endif
2062     }
2063 #endif
2064   }
2065
2066   /* ----------------------------------------------------------------------- */
2067   /* draw things in front of player (active dynamite or dynabombs)           */
2068   /* ----------------------------------------------------------------------- */
2069
2070   if (IS_ACTIVE_BOMB(element))
2071   {
2072     graphic = el2img(element);
2073     frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
2074
2075     if (game.emulation == EMU_SUPAPLEX)
2076       DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
2077     else
2078       DrawGraphicThruMask(sx, sy, graphic, frame);
2079   }
2080
2081   if (player_is_moving && last_element == EL_EXPLOSION)
2082   {
2083     int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
2084     int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
2085     int phase = ExplodePhase[last_jx][last_jy] - 1;
2086     int frame = getGraphicAnimationFrame(graphic, phase - delay);
2087
2088     if (phase >= delay)
2089       DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
2090   }
2091
2092   /* ----------------------------------------------------------------------- */
2093   /* draw elements the player is just walking/passing through/under          */
2094   /* ----------------------------------------------------------------------- */
2095
2096   if (player_is_moving)
2097   {
2098     /* handle the field the player is leaving ... */
2099     if (IS_ACCESSIBLE_INSIDE(last_element))
2100       DrawLevelField(last_jx, last_jy);
2101     else if (IS_ACCESSIBLE_UNDER(last_element))
2102       DrawLevelFieldThruMask(last_jx, last_jy);
2103   }
2104
2105 #if 1
2106   /* do not redraw accessible elements if the player is just pushing them */
2107   if (!player_is_moving || !player->is_pushing)
2108   {
2109     /* ... and the field the player is entering */
2110     if (IS_ACCESSIBLE_INSIDE(element))
2111       DrawLevelField(jx, jy);
2112     else if (IS_ACCESSIBLE_UNDER(element))
2113       DrawLevelFieldThruMask(jx, jy);
2114   }
2115
2116 #else
2117
2118 #if 0
2119   /* !!! I have forgotton what this should be good for !!! */
2120   /* !!! causes player being visible when pushing from within tubes !!! */
2121   if (!player->is_pushing)
2122 #endif
2123   {
2124     /* ... and the field the player is entering */
2125     if (IS_ACCESSIBLE_INSIDE(element))
2126       DrawLevelField(jx, jy);
2127     else if (IS_ACCESSIBLE_UNDER(element))
2128       DrawLevelFieldThruMask(jx, jy);
2129   }
2130 #endif
2131
2132   if (setup.direct_draw)
2133   {
2134     int dst_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
2135     int dst_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
2136     int x_size = TILEX * (1 + ABS(jx - last_jx));
2137     int y_size = TILEY * (1 + ABS(jy - last_jy));
2138
2139     BlitBitmap(drawto_field, window,
2140                dst_x, dst_y, x_size, y_size, dst_x, dst_y);
2141     SetDrawtoField(DRAW_DIRECT);
2142   }
2143
2144   MarkTileDirty(sx, sy);
2145 }
2146
2147 /* ------------------------------------------------------------------------- */
2148
2149 void WaitForEventToContinue()
2150 {
2151   boolean still_wait = TRUE;
2152
2153   /* simulate releasing mouse button over last gadget, if still pressed */
2154   if (button_status)
2155     HandleGadgets(-1, -1, 0);
2156
2157   button_status = MB_RELEASED;
2158
2159   while (still_wait)
2160   {
2161     if (PendingEvent())
2162     {
2163       Event event;
2164
2165       NextEvent(&event);
2166
2167       switch (event.type)
2168       {
2169         case EVENT_BUTTONPRESS:
2170         case EVENT_KEYPRESS:
2171           still_wait = FALSE;
2172           break;
2173
2174         case EVENT_KEYRELEASE:
2175           ClearPlayerAction();
2176           break;
2177
2178         default:
2179           HandleOtherEvents(&event);
2180           break;
2181       }
2182     }
2183     else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2184     {
2185       still_wait = FALSE;
2186     }
2187
2188     DoAnimation();
2189
2190     /* don't eat all CPU time */
2191     Delay(10);
2192   }
2193 }
2194
2195 #define MAX_REQUEST_LINES               13
2196 #define MAX_REQUEST_LINE_FONT1_LEN      7
2197 #define MAX_REQUEST_LINE_FONT2_LEN      10
2198
2199 boolean Request(char *text, unsigned int req_state)
2200 {
2201   int mx, my, ty, result = -1;
2202   unsigned int old_door_state;
2203   int last_game_status = game_status;   /* save current game status */
2204   int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
2205   int font_nr = FONT_TEXT_2;
2206   int max_word_len = 0;
2207   char *text_ptr;
2208
2209   for (text_ptr = text; *text_ptr; text_ptr++)
2210   {
2211     max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2212
2213     if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
2214     {
2215       max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
2216       font_nr = FONT_LEVEL_NUMBER;
2217
2218       break;
2219     }
2220   }
2221
2222 #if 1
2223   /* disable deactivated drawing when quick-loading level tape recording */
2224   if (tape.playing && tape.deactivate_display)
2225     TapeDeactivateDisplayOff(TRUE);
2226 #endif
2227
2228 #if 1
2229   SetMouseCursor(CURSOR_DEFAULT);
2230 #endif
2231
2232 #if defined(NETWORK_AVALIABLE)
2233   /* pause network game while waiting for request to answer */
2234   if (options.network &&
2235       game_status == GAME_MODE_PLAYING &&
2236       req_state & REQUEST_WAIT_FOR_INPUT)
2237     SendToServer_PausePlaying();
2238 #endif
2239
2240   old_door_state = GetDoorState();
2241
2242   /* simulate releasing mouse button over last gadget, if still pressed */
2243   if (button_status)
2244     HandleGadgets(-1, -1, 0);
2245
2246   UnmapAllGadgets();
2247
2248   if (old_door_state & DOOR_OPEN_1)
2249   {
2250     CloseDoor(DOOR_CLOSE_1);
2251
2252     /* save old door content */
2253     BlitBitmap(bitmap_db_door, bitmap_db_door,
2254                DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2255                DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2256   }
2257
2258   SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2259
2260   /* clear door drawing field */
2261   DrawBackground(DX, DY, DXSIZE, DYSIZE);
2262
2263   /* force DOOR font on preview level */
2264   game_status = GAME_MODE_PSEUDO_DOOR;
2265
2266   /* write text for request */
2267   for (ty = 0; ty < MAX_REQUEST_LINES; ty++)
2268   {
2269     char text_line[max_request_line_len + 1];
2270     int tx, tl, tc = 0;
2271
2272     if (!*text)
2273       break;
2274
2275     for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
2276     {
2277       tc = *(text + tx);
2278       if (!tc || tc == ' ')
2279         break;
2280     }
2281
2282     if (!tl)
2283     { 
2284       text++; 
2285       ty--; 
2286       continue; 
2287     }
2288
2289     strncpy(text_line, text, tl);
2290     text_line[tl] = 0;
2291
2292     DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
2293              DY + 8 + ty * (getFontHeight(font_nr) + 2),
2294              text_line, font_nr);
2295
2296     text += tl + (tc == ' ' ? 1 : 0);
2297   }
2298
2299   game_status = last_game_status;       /* restore current game status */
2300
2301   if (req_state & REQ_ASK)
2302   {
2303     MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2304     MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2305   }
2306   else if (req_state & REQ_CONFIRM)
2307   {
2308     MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2309   }
2310   else if (req_state & REQ_PLAYER)
2311   {
2312     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2313     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2314     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2315     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2316   }
2317
2318   /* copy request gadgets to door backbuffer */
2319   BlitBitmap(drawto, bitmap_db_door,
2320              DX, DY, DXSIZE, DYSIZE,
2321              DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2322
2323   OpenDoor(DOOR_OPEN_1);
2324
2325 #if 0
2326   ClearEventQueue();
2327 #endif
2328
2329   if (!(req_state & REQUEST_WAIT_FOR_INPUT))
2330   {
2331     SetDrawBackgroundMask(REDRAW_FIELD);
2332
2333     return FALSE;
2334   }
2335
2336   if (game_status != GAME_MODE_MAIN)
2337     InitAnimation();
2338
2339   button_status = MB_RELEASED;
2340
2341   request_gadget_id = -1;
2342
2343   SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2344
2345 #if 0
2346   SetMouseCursor(CURSOR_DEFAULT);
2347 #endif
2348
2349   while (result < 0)
2350   {
2351     if (PendingEvent())
2352     {
2353       Event event;
2354
2355       NextEvent(&event);
2356
2357       switch(event.type)
2358       {
2359         case EVENT_BUTTONPRESS:
2360         case EVENT_BUTTONRELEASE:
2361         case EVENT_MOTIONNOTIFY:
2362         {
2363           if (event.type == EVENT_MOTIONNOTIFY)
2364           {
2365             if (!PointerInWindow(window))
2366               continue; /* window and pointer are on different screens */
2367
2368             if (!button_status)
2369               continue;
2370
2371             motion_status = TRUE;
2372             mx = ((MotionEvent *) &event)->x;
2373             my = ((MotionEvent *) &event)->y;
2374           }
2375           else
2376           {
2377             motion_status = FALSE;
2378             mx = ((ButtonEvent *) &event)->x;
2379             my = ((ButtonEvent *) &event)->y;
2380             if (event.type == EVENT_BUTTONPRESS)
2381               button_status = ((ButtonEvent *) &event)->button;
2382             else
2383               button_status = MB_RELEASED;
2384           }
2385
2386           /* this sets 'request_gadget_id' */
2387           HandleGadgets(mx, my, button_status);
2388
2389           switch(request_gadget_id)
2390           {
2391             case TOOL_CTRL_ID_YES:
2392               result = TRUE;
2393               break;
2394             case TOOL_CTRL_ID_NO:
2395               result = FALSE;
2396               break;
2397             case TOOL_CTRL_ID_CONFIRM:
2398               result = TRUE | FALSE;
2399               break;
2400
2401             case TOOL_CTRL_ID_PLAYER_1:
2402               result = 1;
2403               break;
2404             case TOOL_CTRL_ID_PLAYER_2:
2405               result = 2;
2406               break;
2407             case TOOL_CTRL_ID_PLAYER_3:
2408               result = 3;
2409               break;
2410             case TOOL_CTRL_ID_PLAYER_4:
2411               result = 4;
2412               break;
2413
2414             default:
2415               break;
2416           }
2417
2418           break;
2419         }
2420
2421         case EVENT_KEYPRESS:
2422           switch(GetEventKey((KeyEvent *)&event, TRUE))
2423           {
2424             case KSYM_Return:
2425               result = 1;
2426               break;
2427
2428             case KSYM_Escape:
2429               result = 0;
2430               break;
2431
2432             default:
2433               break;
2434           }
2435           if (req_state & REQ_PLAYER)
2436             result = 0;
2437           break;
2438
2439         case EVENT_KEYRELEASE:
2440           ClearPlayerAction();
2441           break;
2442
2443         default:
2444           HandleOtherEvents(&event);
2445           break;
2446       }
2447     }
2448     else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2449     {
2450       int joy = AnyJoystick();
2451
2452       if (joy & JOY_BUTTON_1)
2453         result = 1;
2454       else if (joy & JOY_BUTTON_2)
2455         result = 0;
2456     }
2457
2458     DoAnimation();
2459
2460     /* don't eat all CPU time */
2461     Delay(10);
2462   }
2463
2464   if (game_status != GAME_MODE_MAIN)
2465     StopAnimation();
2466
2467   UnmapToolButtons();
2468
2469   if (!(req_state & REQ_STAY_OPEN))
2470   {
2471     CloseDoor(DOOR_CLOSE_1);
2472
2473     if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
2474         (req_state & REQ_REOPEN))
2475       OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2476   }
2477
2478   RemapAllGadgets();
2479
2480   SetDrawBackgroundMask(REDRAW_FIELD);
2481
2482 #if defined(NETWORK_AVALIABLE)
2483   /* continue network game after request */
2484   if (options.network &&
2485       game_status == GAME_MODE_PLAYING &&
2486       req_state & REQUEST_WAIT_FOR_INPUT)
2487     SendToServer_ContinuePlaying();
2488 #endif
2489
2490 #if 1
2491   /* restore deactivated drawing when quick-loading level tape recording */
2492   if (tape.playing && tape.deactivate_display)
2493     TapeDeactivateDisplayOn();
2494 #endif
2495
2496   return result;
2497 }
2498
2499 unsigned int OpenDoor(unsigned int door_state)
2500 {
2501   if (door_state & DOOR_COPY_BACK)
2502   {
2503     if (door_state & DOOR_OPEN_1)
2504       BlitBitmap(bitmap_db_door, bitmap_db_door,
2505                  DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2506                  DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2507
2508     if (door_state & DOOR_OPEN_2)
2509       BlitBitmap(bitmap_db_door, bitmap_db_door,
2510                  DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
2511                  DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2512
2513     door_state &= ~DOOR_COPY_BACK;
2514   }
2515
2516   return MoveDoor(door_state);
2517 }
2518
2519 unsigned int CloseDoor(unsigned int door_state)
2520 {
2521   unsigned int old_door_state = GetDoorState();
2522
2523   if (!(door_state & DOOR_NO_COPY_BACK))
2524   {
2525     if (old_door_state & DOOR_OPEN_1)
2526       BlitBitmap(backbuffer, bitmap_db_door,
2527                  DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2528
2529     if (old_door_state & DOOR_OPEN_2)
2530       BlitBitmap(backbuffer, bitmap_db_door,
2531                  VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2532
2533     door_state &= ~DOOR_NO_COPY_BACK;
2534   }
2535
2536   return MoveDoor(door_state);
2537 }
2538
2539 unsigned int GetDoorState()
2540 {
2541   return MoveDoor(DOOR_GET_STATE);
2542 }
2543
2544 unsigned int SetDoorState(unsigned int door_state)
2545 {
2546   return MoveDoor(door_state | DOOR_SET_STATE);
2547 }
2548
2549 unsigned int MoveDoor(unsigned int door_state)
2550 {
2551   static int door1 = DOOR_OPEN_1;
2552   static int door2 = DOOR_CLOSE_2;
2553   unsigned long door_delay = 0;
2554   unsigned long door_delay_value;
2555   int stepsize = 1;
2556
2557   if (door_state == DOOR_GET_STATE)
2558     return(door1 | door2);
2559
2560   if (door_state & DOOR_SET_STATE)
2561   {
2562     if (door_state & DOOR_ACTION_1)
2563       door1 = door_state & DOOR_ACTION_1;
2564     if (door_state & DOOR_ACTION_2)
2565       door2 = door_state & DOOR_ACTION_2;
2566
2567     return(door1 | door2);
2568   }
2569
2570   if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2571     door_state &= ~DOOR_OPEN_1;
2572   else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2573     door_state &= ~DOOR_CLOSE_1;
2574   if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2575     door_state &= ~DOOR_OPEN_2;
2576   else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2577     door_state &= ~DOOR_CLOSE_2;
2578
2579   door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2580                       door_2.step_delay);
2581
2582   if (setup.quick_doors)
2583   {
2584     stepsize = 20;              /* must be choosen to always draw last frame */
2585     door_delay_value = 0;
2586
2587 #if 0
2588     StopSound(SND_DOOR_OPENING);
2589     StopSound(SND_DOOR_CLOSING);
2590 #endif
2591   }
2592
2593   if (global.autoplay_leveldir)
2594   {
2595     door_state |= DOOR_NO_DELAY;
2596     door_state &= ~DOOR_CLOSE_ALL;
2597   }
2598
2599   if (door_state & DOOR_ACTION)
2600   {
2601     boolean door_1_done = !(door_state & DOOR_ACTION_1);
2602     boolean door_2_done = !(door_state & DOOR_ACTION_2);
2603     int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2604     int end = (door_state & DOOR_ACTION_1 &&
2605                door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
2606     int x;
2607
2608     if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
2609     {
2610       /* opening door sound has priority over simultaneously closing door */
2611       if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2612         PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2613       else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2614         PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2615     }
2616
2617     for (x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
2618     {
2619       Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2620       GC gc = bitmap->stored_clip_gc;
2621
2622       if (door_state & DOOR_ACTION_1)
2623       {
2624         int a = MIN(x * door_1.step_offset, end);
2625         int i = (door_state & DOOR_OPEN_1 ? end - a : a);
2626
2627         if (x <= a)
2628         {
2629           BlitBitmap(bitmap_db_door, drawto,
2630                      DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
2631                      DXSIZE, DYSIZE - i / 2, DX, DY);
2632
2633           ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
2634         }
2635
2636         if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
2637         {
2638           int src1_x = DXSIZE,          src1_y = DOOR_GFX_PAGEY1;
2639           int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2640           int src2_x = DXSIZE - i,      src2_y = DOOR_GFX_PAGEY1;
2641           int dst2_x = DX,              dst2_y = DY;
2642           int width = i, height = DYSIZE;
2643
2644           SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2645           BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2646                            dst1_x, dst1_y);
2647
2648           SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2649           BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2650                            dst2_x, dst2_y);
2651         }
2652         else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
2653         {
2654           int src1_x = DXSIZE,          src1_y = DOOR_GFX_PAGEY1;
2655           int dst1_x = DX,              dst1_y = DY + DYSIZE - i;
2656           int src2_x = 0,               src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2657           int dst2_x = DX,              dst2_y = DY;
2658           int width = DXSIZE, height = i;
2659
2660           SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2661           BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2662                            dst1_x, dst1_y);
2663
2664           SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2665           BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2666                            dst2_x, dst2_y);
2667         }
2668         else if (x <= DXSIZE)   /* ANIM_DEFAULT */
2669         {
2670           int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2671
2672           SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2673           BlitBitmapMasked(bitmap, drawto,
2674                            DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2675                            DX + DXSIZE - i, DY + j);
2676           BlitBitmapMasked(bitmap, drawto,
2677                            DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2678                            DX + DXSIZE - i, DY + 140 + j);
2679           SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2680                         DY - (DOOR_GFX_PAGEY1 + j));
2681           BlitBitmapMasked(bitmap, drawto,
2682                            DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2683                            DX, DY);
2684           BlitBitmapMasked(bitmap, drawto,
2685                            DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2686                            DX, DY + 140 - j);
2687
2688           BlitBitmapMasked(bitmap, drawto,
2689                            DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2690                            DX, DY + 77 - j);
2691           BlitBitmapMasked(bitmap, drawto,
2692                            DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2693                            DX, DY + 203 - j);
2694           SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2695           BlitBitmapMasked(bitmap, drawto,
2696                            DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2697                            DX + DXSIZE - i, DY + 77 + j);
2698           BlitBitmapMasked(bitmap, drawto,
2699                            DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2700                            DX + DXSIZE - i, DY + 203 + j);
2701         }
2702
2703         redraw_mask |= REDRAW_DOOR_1;
2704         door_1_done = (a == end);
2705       }
2706
2707       if (door_state & DOOR_ACTION_2)
2708       {
2709         int a = MIN(x * door_2.step_offset, VXSIZE);
2710         int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
2711
2712         if (x <= VYSIZE)
2713         {
2714           BlitBitmap(bitmap_db_door, drawto,
2715                      DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
2716                      VXSIZE, VYSIZE - i / 2, VX, VY);
2717
2718           ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
2719         }
2720
2721         if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
2722         {
2723           int src1_x = VXSIZE,          src1_y = DOOR_GFX_PAGEY2;
2724           int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2725           int src2_x = VXSIZE - i,      src2_y = DOOR_GFX_PAGEY2;
2726           int dst2_x = VX,              dst2_y = VY;
2727           int width = i, height = VYSIZE;
2728
2729           SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2730           BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2731                            dst1_x, dst1_y);
2732
2733           SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2734           BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2735                            dst2_x, dst2_y);
2736         }
2737         else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
2738         {
2739           int src1_x = VXSIZE,          src1_y = DOOR_GFX_PAGEY2;
2740           int dst1_x = VX,              dst1_y = VY + VYSIZE - i;
2741           int src2_x = 0,               src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2742           int dst2_x = VX,              dst2_y = VY;
2743           int width = VXSIZE, height = i;
2744
2745           SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2746           BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2747                            dst1_x, dst1_y);
2748
2749           SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2750           BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2751                            dst2_x, dst2_y);
2752         }
2753         else if (x <= VXSIZE)   /* ANIM_DEFAULT */
2754         {
2755           int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2756
2757           SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2758           BlitBitmapMasked(bitmap, drawto,
2759                            VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2760                            VX + VXSIZE - i, VY + j);
2761           SetClipOrigin(bitmap, gc,
2762                         VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2763           BlitBitmapMasked(bitmap, drawto,
2764                            VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2765                            VX, VY);
2766
2767           BlitBitmapMasked(bitmap, drawto,
2768                            VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2769                            i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2770           SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2771           BlitBitmapMasked(bitmap, drawto,
2772                            VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2773                            i, VYSIZE / 2 - j,
2774                            VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2775         }
2776
2777         redraw_mask |= REDRAW_DOOR_2;
2778         door_2_done = (a == VXSIZE);
2779       }
2780
2781       BackToFront();
2782
2783       if (game_status == GAME_MODE_MAIN)
2784         DoAnimation();
2785
2786       if (!(door_state & DOOR_NO_DELAY))
2787         WaitUntilDelayReached(&door_delay, door_delay_value);
2788     }
2789   }
2790
2791 #if 0
2792   if (setup.quick_doors)
2793   {
2794     StopSound(SND_DOOR_OPENING);
2795     StopSound(SND_DOOR_CLOSING);
2796   }
2797 #endif
2798
2799   if (door_state & DOOR_ACTION_1)
2800     door1 = door_state & DOOR_ACTION_1;
2801   if (door_state & DOOR_ACTION_2)
2802     door2 = door_state & DOOR_ACTION_2;
2803
2804   return (door1 | door2);
2805 }
2806
2807 void DrawSpecialEditorDoor()
2808 {
2809   /* draw bigger toolbox window */
2810   BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2811              DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2812              EX - 4, EY - 12);
2813   BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2814              EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2815              EX - 4, EY - 4);
2816
2817   redraw_mask |= REDRAW_ALL;
2818 }
2819
2820 void UndrawSpecialEditorDoor()
2821 {
2822   /* draw normal tape recorder window */
2823   BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2824              EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2825              EX - 4, EY - 12);
2826
2827   redraw_mask |= REDRAW_ALL;
2828 }
2829
2830
2831 /* ---------- new tool button stuff ---------------------------------------- */
2832
2833 /* graphic position values for tool buttons */
2834 #define TOOL_BUTTON_YES_XPOS            2
2835 #define TOOL_BUTTON_YES_YPOS            250
2836 #define TOOL_BUTTON_YES_GFX_YPOS        0
2837 #define TOOL_BUTTON_YES_XSIZE           46
2838 #define TOOL_BUTTON_YES_YSIZE           28
2839 #define TOOL_BUTTON_NO_XPOS             52
2840 #define TOOL_BUTTON_NO_YPOS             TOOL_BUTTON_YES_YPOS
2841 #define TOOL_BUTTON_NO_GFX_YPOS         TOOL_BUTTON_YES_GFX_YPOS
2842 #define TOOL_BUTTON_NO_XSIZE            TOOL_BUTTON_YES_XSIZE
2843 #define TOOL_BUTTON_NO_YSIZE            TOOL_BUTTON_YES_YSIZE
2844 #define TOOL_BUTTON_CONFIRM_XPOS        TOOL_BUTTON_YES_XPOS
2845 #define TOOL_BUTTON_CONFIRM_YPOS        TOOL_BUTTON_YES_YPOS
2846 #define TOOL_BUTTON_CONFIRM_GFX_YPOS    30
2847 #define TOOL_BUTTON_CONFIRM_XSIZE       96
2848 #define TOOL_BUTTON_CONFIRM_YSIZE       TOOL_BUTTON_YES_YSIZE
2849 #define TOOL_BUTTON_PLAYER_XSIZE        30
2850 #define TOOL_BUTTON_PLAYER_YSIZE        30
2851 #define TOOL_BUTTON_PLAYER_GFX_XPOS     5
2852 #define TOOL_BUTTON_PLAYER_GFX_YPOS     185
2853 #define TOOL_BUTTON_PLAYER_XPOS         (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2854 #define TOOL_BUTTON_PLAYER_YPOS         (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2855 #define TOOL_BUTTON_PLAYER1_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2856                                          + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2857 #define TOOL_BUTTON_PLAYER2_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2858                                          + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2859 #define TOOL_BUTTON_PLAYER3_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2860                                          + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2861 #define TOOL_BUTTON_PLAYER4_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2862                                          + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2863 #define TOOL_BUTTON_PLAYER1_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2864                                          + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2865 #define TOOL_BUTTON_PLAYER2_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2866                                          + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2867 #define TOOL_BUTTON_PLAYER3_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2868                                          + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2869 #define TOOL_BUTTON_PLAYER4_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2870                                          + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2871
2872 static struct
2873 {
2874   int xpos, ypos;
2875   int x, y;
2876   int width, height;
2877   int gadget_id;
2878   char *infotext;
2879 } toolbutton_info[NUM_TOOL_BUTTONS] =
2880 {
2881   {
2882     TOOL_BUTTON_YES_XPOS,       TOOL_BUTTON_YES_GFX_YPOS,
2883     TOOL_BUTTON_YES_XPOS,       TOOL_BUTTON_YES_YPOS,
2884     TOOL_BUTTON_YES_XSIZE,      TOOL_BUTTON_YES_YSIZE,
2885     TOOL_CTRL_ID_YES,
2886     "yes"
2887   },
2888   {
2889     TOOL_BUTTON_NO_XPOS,        TOOL_BUTTON_NO_GFX_YPOS,
2890     TOOL_BUTTON_NO_XPOS,        TOOL_BUTTON_NO_YPOS,
2891     TOOL_BUTTON_NO_XSIZE,       TOOL_BUTTON_NO_YSIZE,
2892     TOOL_CTRL_ID_NO,
2893     "no"
2894   },
2895   {
2896     TOOL_BUTTON_CONFIRM_XPOS,   TOOL_BUTTON_CONFIRM_GFX_YPOS,
2897     TOOL_BUTTON_CONFIRM_XPOS,   TOOL_BUTTON_CONFIRM_YPOS,
2898     TOOL_BUTTON_CONFIRM_XSIZE,  TOOL_BUTTON_CONFIRM_YSIZE,
2899     TOOL_CTRL_ID_CONFIRM,
2900     "confirm"
2901   },
2902   {
2903     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2904     TOOL_BUTTON_PLAYER1_XPOS,   TOOL_BUTTON_PLAYER1_YPOS,
2905     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2906     TOOL_CTRL_ID_PLAYER_1,
2907     "player 1"
2908   },
2909   {
2910     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2911     TOOL_BUTTON_PLAYER2_XPOS,   TOOL_BUTTON_PLAYER2_YPOS,
2912     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2913     TOOL_CTRL_ID_PLAYER_2,
2914     "player 2"
2915   },
2916   {
2917     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2918     TOOL_BUTTON_PLAYER3_XPOS,   TOOL_BUTTON_PLAYER3_YPOS,
2919     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2920     TOOL_CTRL_ID_PLAYER_3,
2921     "player 3"
2922   },
2923   {
2924     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2925     TOOL_BUTTON_PLAYER4_XPOS,   TOOL_BUTTON_PLAYER4_YPOS,
2926     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2927     TOOL_CTRL_ID_PLAYER_4,
2928     "player 4"
2929   }
2930 };
2931
2932 void CreateToolButtons()
2933 {
2934   int i;
2935
2936   for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2937   {
2938     Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2939     Bitmap *deco_bitmap = None;
2940     int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2941     struct GadgetInfo *gi;
2942     unsigned long event_mask;
2943     int gd_xoffset, gd_yoffset;
2944     int gd_x1, gd_x2, gd_y;
2945     int id = i;
2946
2947     event_mask = GD_EVENT_RELEASED;
2948
2949     gd_xoffset = toolbutton_info[i].xpos;
2950     gd_yoffset = toolbutton_info[i].ypos;
2951     gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2952     gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2953     gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2954
2955     if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2956     {
2957       int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2958
2959       getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2960                            &deco_bitmap, &deco_x, &deco_y);
2961       deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2962       deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2963     }
2964
2965     gi = CreateGadget(GDI_CUSTOM_ID, id,
2966                       GDI_INFO_TEXT, toolbutton_info[i].infotext,
2967                       GDI_X, DX + toolbutton_info[i].x,
2968                       GDI_Y, DY + toolbutton_info[i].y,
2969                       GDI_WIDTH, toolbutton_info[i].width,
2970                       GDI_HEIGHT, toolbutton_info[i].height,
2971                       GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2972                       GDI_STATE, GD_BUTTON_UNPRESSED,
2973                       GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2974                       GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2975                       GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2976                       GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2977                       GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2978                       GDI_DECORATION_SHIFTING, 1, 1,
2979                       GDI_EVENT_MASK, event_mask,
2980                       GDI_CALLBACK_ACTION, HandleToolButtons,
2981                       GDI_END);
2982
2983     if (gi == NULL)
2984       Error(ERR_EXIT, "cannot create gadget");
2985
2986     tool_gadget[id] = gi;
2987   }
2988 }
2989
2990 void FreeToolButtons()
2991 {
2992   int i;
2993
2994   for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2995     FreeGadget(tool_gadget[i]);
2996 }
2997
2998 static void UnmapToolButtons()
2999 {
3000   int i;
3001
3002   for (i = 0; i < NUM_TOOL_BUTTONS; i++)
3003     UnmapGadget(tool_gadget[i]);
3004 }
3005
3006 static void HandleToolButtons(struct GadgetInfo *gi)
3007 {
3008   request_gadget_id = gi->custom_id;
3009 }
3010
3011 #if 1
3012
3013 static struct Mapping_EM_to_RND_object
3014 {
3015   int element_em;
3016   boolean is_rnd_to_em_mapping;         /* unique mapping EM <-> RND */
3017   boolean is_backside;                  /* backside of moving element */
3018
3019   int element_rnd;
3020   int action;
3021   int direction;
3022 }
3023 em_object_mapping_list[] =
3024 {
3025   {
3026     Xblank,                             TRUE,   FALSE,
3027     EL_EMPTY,                           -1, -1
3028   },
3029   {
3030     Yacid_splash_eB,                    FALSE,  FALSE,
3031     EL_ACID_SPLASH_RIGHT,               -1, -1
3032   },
3033   {
3034     Yacid_splash_wB,                    FALSE,  FALSE,
3035     EL_ACID_SPLASH_LEFT,                -1, -1
3036   },
3037
3038 #ifdef EM_ENGINE_BAD_ROLL
3039   {
3040     Xstone_force_e,                     FALSE,  FALSE,
3041     EL_ROCK,                            -1, MV_BIT_RIGHT
3042   },
3043   {
3044     Xstone_force_w,                     FALSE,  FALSE,
3045     EL_ROCK,                            -1, MV_BIT_LEFT
3046   },
3047   {
3048     Xnut_force_e,                       FALSE,  FALSE,
3049     EL_NUT,                             -1, MV_BIT_RIGHT
3050   },
3051   {
3052     Xnut_force_w,                       FALSE,  FALSE,
3053     EL_NUT,                             -1, MV_BIT_LEFT
3054   },
3055   {
3056     Xspring_force_e,                    FALSE,  FALSE,
3057     EL_SPRING,                          -1, MV_BIT_RIGHT
3058   },
3059   {
3060     Xspring_force_w,                    FALSE,  FALSE,
3061     EL_SPRING,                          -1, MV_BIT_LEFT
3062   },
3063   {
3064     Xemerald_force_e,                   FALSE,  FALSE,
3065     EL_EMERALD,                         -1, MV_BIT_RIGHT
3066   },
3067   {
3068     Xemerald_force_w,                   FALSE,  FALSE,
3069     EL_EMERALD,                         -1, MV_BIT_LEFT
3070   },
3071   {
3072     Xdiamond_force_e,                   FALSE,  FALSE,
3073     EL_DIAMOND,                         -1, MV_BIT_RIGHT
3074   },
3075   {
3076     Xdiamond_force_w,                   FALSE,  FALSE,
3077     EL_DIAMOND,                         -1, MV_BIT_LEFT
3078   },
3079   {
3080     Xbomb_force_e,                      FALSE,  FALSE,
3081     EL_BOMB,                            -1, MV_BIT_RIGHT
3082   },
3083   {
3084     Xbomb_force_w,                      FALSE,  FALSE,
3085     EL_BOMB,                            -1, MV_BIT_LEFT
3086   },
3087 #endif  /* EM_ENGINE_BAD_ROLL */
3088
3089   {
3090     Xstone,                             TRUE,   FALSE,
3091     EL_ROCK,                            -1, -1
3092   },
3093   {
3094     Xstone_pause,                       FALSE,  FALSE,
3095     EL_ROCK,                            -1, -1
3096   },
3097   {
3098     Xstone_fall,                        FALSE,  FALSE,
3099     EL_ROCK,                            -1, -1
3100   },
3101   {
3102     Ystone_s,                           FALSE,  FALSE,
3103     EL_ROCK,                            ACTION_FALLING, -1
3104   },
3105   {
3106     Ystone_sB,                          FALSE,  TRUE,
3107     EL_ROCK,                            ACTION_FALLING, -1
3108   },
3109   {
3110     Ystone_e,                           FALSE,  FALSE,
3111     EL_ROCK,                            ACTION_MOVING, MV_BIT_RIGHT
3112   },
3113   {
3114     Ystone_eB,                          FALSE,  TRUE,
3115     EL_ROCK,                            ACTION_MOVING, MV_BIT_RIGHT
3116   },
3117   {
3118     Ystone_w,                           FALSE,  FALSE,
3119     EL_ROCK,                            ACTION_MOVING, MV_BIT_LEFT
3120   },
3121   {
3122     Ystone_wB,                          FALSE,  TRUE,
3123     EL_ROCK,                            ACTION_MOVING, MV_BIT_LEFT
3124   },
3125   {
3126     Xnut,                               TRUE,   FALSE,
3127     EL_NUT,                             -1, -1
3128   },
3129   {
3130     Xnut_pause,                         FALSE,  FALSE,
3131     EL_NUT,                             -1, -1
3132   },
3133   {
3134     Xnut_fall,                          FALSE,  FALSE,
3135     EL_NUT,                             -1, -1
3136   },
3137   {
3138     Ynut_s,                             FALSE,  FALSE,
3139     EL_NUT,                             ACTION_FALLING, -1
3140   },
3141   {
3142     Ynut_sB,                            FALSE,  TRUE,
3143     EL_NUT,                             ACTION_FALLING, -1
3144   },
3145   {
3146     Ynut_e,                             FALSE,  FALSE,
3147     EL_NUT,                             ACTION_MOVING, MV_BIT_RIGHT
3148   },
3149   {
3150     Ynut_eB,                            FALSE,  TRUE,
3151     EL_NUT,                             ACTION_MOVING, MV_BIT_RIGHT
3152   },
3153   {
3154     Ynut_w,                             FALSE,  FALSE,
3155     EL_NUT,                             ACTION_MOVING, MV_BIT_LEFT
3156   },
3157   {
3158     Ynut_wB,                            FALSE,  TRUE,
3159     EL_NUT,                             ACTION_MOVING, MV_BIT_LEFT
3160   },
3161   {
3162     Xbug_n,                             TRUE,   FALSE,
3163     EL_BUG_UP,                          -1, -1
3164   },
3165   {
3166     Xbug_e,                             TRUE,   FALSE,
3167     EL_BUG_RIGHT,                       -1, -1
3168   },
3169   {
3170     Xbug_s,                             TRUE,   FALSE,
3171     EL_BUG_DOWN,                        -1, -1
3172   },
3173   {
3174     Xbug_w,                             TRUE,   FALSE,
3175     EL_BUG_LEFT,                        -1, -1
3176   },
3177   {
3178     Xbug_gon,                           FALSE,  FALSE,
3179     EL_BUG_UP,                          -1, -1
3180   },
3181   {
3182     Xbug_goe,                           FALSE,  FALSE,
3183     EL_BUG_RIGHT,                       -1, -1
3184   },
3185   {
3186     Xbug_gos,                           FALSE,  FALSE,
3187     EL_BUG_DOWN,                        -1, -1
3188   },
3189   {
3190     Xbug_gow,                           FALSE,  FALSE,
3191     EL_BUG_LEFT,                        -1, -1
3192   },
3193   {
3194     Ybug_n,                             FALSE,  FALSE,
3195     EL_BUG,                             ACTION_MOVING, MV_BIT_UP
3196   },
3197   {
3198     Ybug_nB,                            FALSE,  TRUE,
3199     EL_BUG,                             ACTION_MOVING, MV_BIT_UP
3200   },
3201   {
3202     Ybug_e,                             FALSE,  FALSE,
3203     EL_BUG,                             ACTION_MOVING, MV_BIT_RIGHT
3204   },
3205   {
3206     Ybug_eB,                            FALSE,  TRUE,
3207     EL_BUG,                             ACTION_MOVING, MV_BIT_RIGHT
3208   },
3209   {
3210     Ybug_s,                             FALSE,  FALSE,
3211     EL_BUG,                             ACTION_MOVING, MV_BIT_DOWN
3212   },
3213   {
3214     Ybug_sB,                            FALSE,  TRUE,
3215     EL_BUG,                             ACTION_MOVING, MV_BIT_DOWN
3216   },
3217   {
3218     Ybug_w,                             FALSE,  FALSE,
3219     EL_BUG,                             ACTION_MOVING, MV_BIT_LEFT
3220   },
3221   {
3222     Ybug_wB,                            FALSE,  TRUE,
3223     EL_BUG,                             ACTION_MOVING, MV_BIT_LEFT
3224   },
3225   {
3226     Ybug_w_n,                           FALSE,  FALSE,
3227     EL_BUG,                             ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3228   },
3229   {
3230     Ybug_n_e,                           FALSE,  FALSE,
3231     EL_BUG,                             ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3232   },
3233   {
3234     Ybug_e_s,                           FALSE,  FALSE,
3235     EL_BUG,                             ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3236   },
3237   {
3238     Ybug_s_w,                           FALSE,  FALSE,
3239     EL_BUG,                             ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3240   },
3241   {
3242     Ybug_e_n,                           FALSE,  FALSE,
3243     EL_BUG,                             ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3244   },
3245   {
3246     Ybug_s_e,                           FALSE,  FALSE,
3247     EL_BUG,                             ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3248   },
3249   {
3250     Ybug_w_s,                           FALSE,  FALSE,
3251     EL_BUG,                             ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3252   },
3253   {
3254     Ybug_n_w,                           FALSE,  FALSE,
3255     EL_BUG,                             ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3256   },
3257   {
3258     Ybug_stone,                         FALSE,  FALSE,
3259     EL_BUG,                             ACTION_SMASHED_BY_ROCK, -1
3260   },
3261   {
3262     Ybug_spring,                        FALSE,  FALSE,
3263     EL_BUG,                             ACTION_SMASHED_BY_SPRING, -1
3264   },
3265   {
3266     Xtank_n,                            TRUE,   FALSE,
3267     EL_SPACESHIP_UP,                    -1, -1
3268   },
3269   {
3270     Xtank_e,                            TRUE,   FALSE,
3271     EL_SPACESHIP_RIGHT,                 -1, -1
3272   },
3273   {
3274     Xtank_s,                            TRUE,   FALSE,
3275     EL_SPACESHIP_DOWN,                  -1, -1
3276   },
3277   {
3278     Xtank_w,                            TRUE,   FALSE,
3279     EL_SPACESHIP_LEFT,                  -1, -1
3280   },
3281   {
3282     Xtank_gon,                          FALSE,  FALSE,
3283     EL_SPACESHIP_UP,                    -1, -1
3284   },
3285   {
3286     Xtank_goe,                          FALSE,  FALSE,
3287     EL_SPACESHIP_RIGHT,                 -1, -1
3288   },
3289   {
3290     Xtank_gos,                          FALSE,  FALSE,
3291     EL_SPACESHIP_DOWN,                  -1, -1
3292   },
3293   {
3294     Xtank_gow,                          FALSE,  FALSE,
3295     EL_SPACESHIP_LEFT,                  -1, -1
3296   },
3297   {
3298     Ytank_n,                            FALSE,  FALSE,
3299     EL_SPACESHIP,                       ACTION_MOVING, MV_BIT_UP
3300   },
3301   {
3302     Ytank_nB,                           FALSE,  TRUE,
3303     EL_SPACESHIP,                       ACTION_MOVING, MV_BIT_UP
3304   },
3305   {
3306     Ytank_e,                            FALSE,  FALSE,
3307     EL_SPACESHIP,                       ACTION_MOVING, MV_BIT_RIGHT
3308   },
3309   {
3310     Ytank_eB,                           FALSE,  TRUE,
3311     EL_SPACESHIP,                       ACTION_MOVING, MV_BIT_RIGHT
3312   },
3313   {
3314     Ytank_s,                            FALSE,  FALSE,
3315     EL_SPACESHIP,                       ACTION_MOVING, MV_BIT_DOWN
3316   },
3317   {
3318     Ytank_sB,                           FALSE,  TRUE,
3319     EL_SPACESHIP,                       ACTION_MOVING, MV_BIT_DOWN
3320   },
3321   {
3322     Ytank_w,                            FALSE,  FALSE,
3323     EL_SPACESHIP,                       ACTION_MOVING, MV_BIT_LEFT
3324   },
3325   {
3326     Ytank_wB,                           FALSE,  TRUE,
3327     EL_SPACESHIP,                       ACTION_MOVING, MV_BIT_LEFT
3328   },
3329   {
3330     Ytank_w_n,                          FALSE,  FALSE,
3331     EL_SPACESHIP,                       ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3332   },
3333   {
3334     Ytank_n_e,                          FALSE,  FALSE,
3335     EL_SPACESHIP,                       ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3336   },
3337   {
3338     Ytank_e_s,                          FALSE,  FALSE,
3339     EL_SPACESHIP,                       ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3340   },
3341   {
3342     Ytank_s_w,                          FALSE,  FALSE,
3343     EL_SPACESHIP,                       ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3344   },
3345   {
3346     Ytank_e_n,                          FALSE,  FALSE,
3347     EL_SPACESHIP,                       ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3348   },
3349   {
3350     Ytank_s_e,                          FALSE,  FALSE,
3351     EL_SPACESHIP,                       ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3352   },
3353   {
3354     Ytank_w_s,                          FALSE,  FALSE,
3355     EL_SPACESHIP,                       ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3356   },
3357   {
3358     Ytank_n_w,                          FALSE,  FALSE,
3359     EL_SPACESHIP,                       ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3360   },
3361   {
3362     Ytank_stone,                        FALSE,  FALSE,
3363     EL_SPACESHIP,                       ACTION_SMASHED_BY_ROCK, -1
3364   },
3365   {
3366     Ytank_spring,                       FALSE,  FALSE,
3367     EL_SPACESHIP,                       ACTION_SMASHED_BY_SPRING, -1
3368   },
3369   {
3370     Xandroid,                           TRUE,   FALSE,
3371     EL_EMC_ANDROID,                     ACTION_ACTIVE, -1
3372   },
3373   {
3374     Xandroid_1_n,                       FALSE,  FALSE,
3375     EL_EMC_ANDROID,                     ACTION_ACTIVE, MV_BIT_UP
3376   },
3377   {
3378     Xandroid_2_n,                       FALSE,  FALSE,
3379     EL_EMC_ANDROID,                     ACTION_ACTIVE, MV_BIT_UP
3380   },
3381   {
3382     Xandroid_1_e,                       FALSE,  FALSE,
3383     EL_EMC_ANDROID,                     ACTION_ACTIVE, MV_BIT_RIGHT
3384   },
3385   {
3386     Xandroid_2_e,                       FALSE,  FALSE,
3387     EL_EMC_ANDROID,                     ACTION_ACTIVE, MV_BIT_RIGHT
3388   },
3389   {
3390     Xandroid_1_w,                       FALSE,  FALSE,
3391     EL_EMC_ANDROID,                     ACTION_ACTIVE, MV_BIT_LEFT
3392   },
3393   {
3394     Xandroid_2_w,                       FALSE,  FALSE,
3395     EL_EMC_ANDROID,                     ACTION_ACTIVE, MV_BIT_LEFT
3396   },
3397   {
3398     Xandroid_1_s,                       FALSE,  FALSE,
3399     EL_EMC_ANDROID,                     ACTION_ACTIVE, MV_BIT_DOWN
3400   },
3401   {
3402     Xandroid_2_s,                       FALSE,  FALSE,
3403     EL_EMC_ANDROID,                     ACTION_ACTIVE, MV_BIT_DOWN
3404   },
3405   {
3406     Yandroid_n,                         FALSE,  FALSE,
3407     EL_EMC_ANDROID,                     ACTION_MOVING, MV_BIT_UP
3408   },
3409   {
3410     Yandroid_nB,                        FALSE,  TRUE,
3411     EL_EMC_ANDROID,                     ACTION_MOVING, MV_BIT_UP
3412   },
3413   {
3414     Yandroid_ne,                        FALSE,  FALSE,
3415     EL_EMC_ANDROID,                     ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3416   },
3417   {
3418     Yandroid_neB,                       FALSE,  TRUE,
3419     EL_EMC_ANDROID,                     ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3420   },
3421   {
3422     Yandroid_e,                         FALSE,  FALSE,
3423     EL_EMC_ANDROID,                     ACTION_MOVING, MV_BIT_RIGHT
3424   },
3425   {
3426     Yandroid_eB,                        FALSE,  TRUE,
3427     EL_EMC_ANDROID,                     ACTION_MOVING, MV_BIT_RIGHT
3428   },
3429   {
3430     Yandroid_se,                        FALSE,  FALSE,
3431     EL_EMC_ANDROID,                     ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3432   },
3433   {
3434     Yandroid_seB,                       FALSE,  TRUE,
3435     EL_EMC_ANDROID,                     ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3436   },
3437   {
3438     Yandroid_s,                         FALSE,  FALSE,
3439     EL_EMC_ANDROID,                     ACTION_MOVING, MV_BIT_DOWN
3440   },
3441   {
3442     Yandroid_sB,                        FALSE,  TRUE,
3443     EL_EMC_ANDROID,                     ACTION_MOVING, MV_BIT_DOWN
3444   },
3445   {
3446     Yandroid_sw,                        FALSE,  FALSE,
3447     EL_EMC_ANDROID,                     ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3448   },
3449   {
3450     Yandroid_swB,                       FALSE,  TRUE,
3451     EL_EMC_ANDROID,                     ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3452   },
3453   {
3454     Yandroid_w,                         FALSE,  FALSE,
3455     EL_EMC_ANDROID,                     ACTION_MOVING, MV_BIT_LEFT
3456   },
3457   {
3458     Yandroid_wB,                        FALSE,  TRUE,
3459     EL_EMC_ANDROID,                     ACTION_MOVING, MV_BIT_LEFT
3460   },
3461   {
3462     Yandroid_nw,                        FALSE,  FALSE,
3463     EL_EMC_ANDROID,                     ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3464   },
3465   {
3466     Yandroid_nwB,                       FALSE,  TRUE,
3467     EL_EMC_ANDROID,                     ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3468   },
3469   {
3470     Xspring,                            TRUE,   FALSE,
3471     EL_SPRING,                          -1, -1
3472   },
3473   {
3474     Xspring_pause,                      FALSE,  FALSE,
3475     EL_SPRING,                          -1, -1
3476   },
3477   {
3478     Xspring_e,                          FALSE,  FALSE,
3479     EL_SPRING,                          -1, -1
3480   },
3481   {
3482     Xspring_w,                          FALSE,  FALSE,
3483     EL_SPRING,                          -1, -1
3484   },
3485   {
3486     Xspring_fall,                       FALSE,  FALSE,
3487     EL_SPRING,                          -1, -1
3488   },
3489   {
3490     Yspring_s,                          FALSE,  FALSE,
3491     EL_SPRING,                          ACTION_FALLING, -1
3492   },
3493   {
3494     Yspring_sB,                         FALSE,  TRUE,
3495     EL_SPRING,                          ACTION_FALLING, -1
3496   },
3497   {
3498     Yspring_e,                          FALSE,  FALSE,
3499     EL_SPRING,                          ACTION_MOVING, MV_BIT_RIGHT
3500   },
3501   {
3502     Yspring_eB,                         FALSE,  TRUE,
3503     EL_SPRING,                          ACTION_MOVING, MV_BIT_RIGHT
3504   },
3505   {
3506     Yspring_w,                          FALSE,  FALSE,
3507     EL_SPRING,                          ACTION_MOVING, MV_BIT_LEFT
3508   },
3509   {
3510     Yspring_wB,                         FALSE,  TRUE,
3511     EL_SPRING,                          ACTION_MOVING, MV_BIT_LEFT
3512   },
3513   {
3514     Yspring_kill_e,                     FALSE,  FALSE,
3515     EL_ROBOT,                           ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3516   },
3517   {
3518     Yspring_kill_eB,                    FALSE,  TRUE,
3519     EL_ROBOT,                           ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3520   },
3521   {
3522     Yspring_kill_w,                     FALSE,  FALSE,
3523     EL_ROBOT,                           ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3524   },
3525   {
3526     Yspring_kill_wB,                    FALSE,  TRUE,
3527     EL_ROBOT,                           ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3528   },
3529   {
3530     Xeater_n,                           TRUE,   FALSE,
3531     EL_YAMYAM,                          -1, -1
3532   },
3533   {
3534     Xeater_e,                           FALSE,  FALSE,
3535     EL_YAMYAM,                          -1, -1
3536   },
3537   {
3538     Xeater_w,                           FALSE,  FALSE,
3539     EL_YAMYAM,                          -1, -1
3540   },
3541   {
3542     Xeater_s,                           FALSE,  FALSE,
3543     EL_YAMYAM,                          -1, -1
3544   },
3545   {
3546     Yeater_n,                           FALSE,  FALSE,
3547     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_UP
3548   },
3549   {
3550     Yeater_nB,                          FALSE,  TRUE,
3551     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_UP
3552   },
3553   {
3554     Yeater_e,                           FALSE,  FALSE,
3555     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_RIGHT
3556   },
3557   {
3558     Yeater_eB,                          FALSE,  TRUE,
3559     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_RIGHT
3560   },
3561   {
3562     Yeater_s,                           FALSE,  FALSE,
3563     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_DOWN
3564   },
3565   {
3566     Yeater_sB,                          FALSE,  TRUE,
3567     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_DOWN
3568   },
3569   {
3570     Yeater_w,                           FALSE,  FALSE,
3571     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_LEFT
3572   },
3573   {
3574     Yeater_wB,                          FALSE,  TRUE,
3575     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_LEFT
3576   },
3577   {
3578     Yeater_stone,                       FALSE,  FALSE,
3579     EL_YAMYAM,                          ACTION_SMASHED_BY_ROCK, -1
3580   },
3581   {
3582     Yeater_spring,                      FALSE,  FALSE,
3583     EL_YAMYAM,                          ACTION_SMASHED_BY_SPRING, -1
3584   },
3585   {
3586     Xalien,                             TRUE,   FALSE,
3587     EL_ROBOT,                           -1, -1
3588   },
3589   {
3590     Xalien_pause,                       FALSE,  FALSE,
3591     EL_ROBOT,                           -1, -1
3592   },
3593   {
3594     Yalien_n,                           FALSE,  FALSE,
3595     EL_ROBOT,                           ACTION_MOVING, MV_BIT_UP
3596   },
3597   {
3598     Yalien_nB,                          FALSE,  TRUE,
3599     EL_ROBOT,                           ACTION_MOVING, MV_BIT_UP
3600   },
3601   {
3602     Yalien_e,                           FALSE,  FALSE,
3603     EL_ROBOT,                           ACTION_MOVING, MV_BIT_RIGHT
3604   },
3605   {
3606     Yalien_eB,                          FALSE,  TRUE,
3607     EL_ROBOT,                           ACTION_MOVING, MV_BIT_RIGHT
3608   },
3609   {
3610     Yalien_s,                           FALSE,  FALSE,
3611     EL_ROBOT,                           ACTION_MOVING, MV_BIT_DOWN
3612   },
3613   {
3614     Yalien_sB,                          FALSE,  TRUE,
3615     EL_ROBOT,                           ACTION_MOVING, MV_BIT_DOWN
3616   },
3617   {
3618     Yalien_w,                           FALSE,  FALSE,
3619     EL_ROBOT,                           ACTION_MOVING, MV_BIT_LEFT
3620   },
3621   {
3622     Yalien_wB,                          FALSE,  TRUE,
3623     EL_ROBOT,                           ACTION_MOVING, MV_BIT_LEFT
3624   },
3625   {
3626     Yalien_stone,                       FALSE,  FALSE,
3627     EL_ROBOT,                           ACTION_SMASHED_BY_ROCK, -1
3628   },
3629   {
3630     Yalien_spring,                      FALSE,  FALSE,
3631     EL_ROBOT,                           ACTION_SMASHED_BY_SPRING, -1
3632   },
3633   {
3634     Xemerald,                           TRUE,   FALSE,
3635     EL_EMERALD,                         -1, -1
3636   },
3637   {
3638     Xemerald_pause,                     FALSE,  FALSE,
3639     EL_EMERALD,                         -1, -1
3640   },
3641   {
3642     Xemerald_fall,                      FALSE,  FALSE,
3643     EL_EMERALD,                         -1, -1
3644   },
3645   {
3646     Xemerald_shine,                     FALSE,  FALSE,
3647     EL_EMERALD,                         ACTION_TWINKLING, -1
3648   },
3649   {
3650     Yemerald_s,                         FALSE,  FALSE,
3651     EL_EMERALD,                         ACTION_FALLING, -1
3652   },
3653   {
3654     Yemerald_sB,                        FALSE,  TRUE,
3655     EL_EMERALD,                         ACTION_FALLING, -1
3656   },
3657   {
3658     Yemerald_e,                         FALSE,  FALSE,
3659     EL_EMERALD,                         ACTION_MOVING, MV_BIT_RIGHT
3660   },
3661   {
3662     Yemerald_eB,                        FALSE,  TRUE,
3663     EL_EMERALD,                         ACTION_MOVING, MV_BIT_RIGHT
3664   },
3665   {
3666     Yemerald_w,                         FALSE,  FALSE,
3667     EL_EMERALD,                         ACTION_MOVING, MV_BIT_LEFT
3668   },
3669   {
3670     Yemerald_wB,                        FALSE,  TRUE,
3671     EL_EMERALD,                         ACTION_MOVING, MV_BIT_LEFT
3672   },
3673   {
3674     Yemerald_eat,                       FALSE,  FALSE,
3675     EL_EMERALD,                         ACTION_COLLECTING, -1
3676   },
3677   {
3678     Yemerald_stone,                     FALSE,  FALSE,
3679     EL_NUT,                             ACTION_BREAKING, -1
3680   },
3681   {
3682     Xdiamond,                           TRUE,   FALSE,
3683     EL_DIAMOND,                         -1, -1
3684   },
3685   {
3686     Xdiamond_pause,                     FALSE,  FALSE,
3687     EL_DIAMOND,                         -1, -1
3688   },
3689   {
3690     Xdiamond_fall,                      FALSE,  FALSE,
3691     EL_DIAMOND,                         -1, -1
3692   },
3693   {
3694     Xdiamond_shine,                     FALSE,  FALSE,
3695     EL_DIAMOND,                         ACTION_TWINKLING, -1
3696   },
3697   {
3698     Ydiamond_s,                         FALSE,  FALSE,
3699     EL_DIAMOND,                         ACTION_FALLING, -1
3700   },
3701   {
3702     Ydiamond_sB,                        FALSE,  TRUE,
3703     EL_DIAMOND,                         ACTION_FALLING, -1
3704   },
3705   {
3706     Ydiamond_e,                         FALSE,  FALSE,
3707     EL_DIAMOND,                         ACTION_MOVING, MV_BIT_RIGHT
3708   },
3709   {
3710     Ydiamond_eB,                        FALSE,  TRUE,
3711     EL_DIAMOND,                         ACTION_MOVING, MV_BIT_RIGHT
3712   },
3713   {
3714     Ydiamond_w,                         FALSE,  FALSE,
3715     EL_DIAMOND,                         ACTION_MOVING, MV_BIT_LEFT
3716   },
3717   {
3718     Ydiamond_wB,                        FALSE,  TRUE,
3719     EL_DIAMOND,                         ACTION_MOVING, MV_BIT_LEFT
3720   },
3721   {
3722     Ydiamond_eat,                       FALSE,  FALSE,
3723     EL_DIAMOND,                         ACTION_COLLECTING, -1
3724   },
3725   {
3726     Ydiamond_stone,                     FALSE,  FALSE,
3727     EL_DIAMOND,                         ACTION_SMASHED_BY_ROCK, -1
3728   },
3729   {
3730     Xdrip_fall,                         TRUE,   FALSE,
3731     EL_AMOEBA_DROP,                     -1, -1
3732   },
3733   {
3734     Xdrip_stretch,                      FALSE,  FALSE,
3735     EL_AMOEBA_DROP,                     ACTION_FALLING, -1
3736   },
3737   {
3738     Xdrip_stretchB,                     FALSE,  TRUE,
3739     EL_AMOEBA_DROP,                     ACTION_FALLING, -1
3740   },
3741   {
3742     Xdrip_eat,                          FALSE,  FALSE,
3743     EL_AMOEBA_DROP,                     ACTION_GROWING, -1
3744   },
3745   {
3746     Ydrip_s1,                           FALSE,  FALSE,
3747     EL_AMOEBA_DROP,                     ACTION_FALLING, -1
3748   },
3749   {
3750     Ydrip_s1B,                          FALSE,  TRUE,
3751     EL_AMOEBA_DROP,                     ACTION_FALLING, -1
3752   },
3753   {
3754     Ydrip_s2,                           FALSE,  FALSE,
3755     EL_AMOEBA_DROP,                     ACTION_FALLING, -1
3756   },
3757   {
3758     Ydrip_s2B,                          FALSE,  TRUE,
3759     EL_AMOEBA_DROP,                     ACTION_FALLING, -1
3760   },
3761   {
3762     Xbomb,                              TRUE,   FALSE,
3763     EL_BOMB,                            -1, -1
3764   },
3765   {
3766     Xbomb_pause,                        FALSE,  FALSE,
3767     EL_BOMB,                            -1, -1
3768   },
3769   {
3770     Xbomb_fall,                         FALSE,  FALSE,
3771     EL_BOMB,                            -1, -1
3772   },
3773   {
3774     Ybomb_s,                            FALSE,  FALSE,
3775     EL_BOMB,                            ACTION_FALLING, -1
3776   },
3777   {
3778     Ybomb_sB,                           FALSE,  TRUE,
3779     EL_BOMB,                            ACTION_FALLING, -1
3780   },
3781   {
3782     Ybomb_e,                            FALSE,  FALSE,
3783     EL_BOMB,                            ACTION_MOVING, MV_BIT_RIGHT
3784   },
3785   {
3786     Ybomb_eB,                           FALSE,  TRUE,
3787     EL_BOMB,                            ACTION_MOVING, MV_BIT_RIGHT
3788   },
3789   {
3790     Ybomb_w,                            FALSE,  FALSE,
3791     EL_BOMB,                            ACTION_MOVING, MV_BIT_LEFT
3792   },
3793   {
3794     Ybomb_wB,                           FALSE,  TRUE,
3795     EL_BOMB,                            ACTION_MOVING, MV_BIT_LEFT
3796   },
3797   {
3798     Ybomb_eat,                          FALSE,  FALSE,
3799     EL_BOMB,                            ACTION_SMASHED_BY_ROCK, -1
3800   },
3801   {
3802     Xballoon,                           TRUE,   FALSE,
3803     EL_BALLOON,                         -1, -1
3804   },
3805   {
3806     Yballoon_n,                         FALSE,  FALSE,
3807     EL_BALLOON,                         ACTION_MOVING, MV_BIT_UP
3808   },
3809   {
3810     Yballoon_nB,                        FALSE,  TRUE,
3811     EL_BALLOON,                         ACTION_MOVING, MV_BIT_UP
3812   },
3813   {
3814     Yballoon_e,                         FALSE,  FALSE,
3815     EL_BALLOON,                         ACTION_MOVING, MV_BIT_RIGHT
3816   },
3817   {
3818     Yballoon_eB,                        FALSE,  TRUE,
3819     EL_BALLOON,                         ACTION_MOVING, MV_BIT_RIGHT
3820   },
3821   {
3822     Yballoon_s,                         FALSE,  FALSE,
3823     EL_BALLOON,                         ACTION_MOVING, MV_BIT_DOWN
3824   },
3825   {
3826     Yballoon_sB,                        FALSE,  TRUE,
3827     EL_BALLOON,                         ACTION_MOVING, MV_BIT_DOWN
3828   },
3829   {
3830     Yballoon_w,                         FALSE,  FALSE,
3831     EL_BALLOON,                         ACTION_MOVING, MV_BIT_LEFT
3832   },
3833   {
3834     Yballoon_wB,                        FALSE,  TRUE,
3835     EL_BALLOON,                         ACTION_MOVING, MV_BIT_LEFT
3836   },
3837   {
3838     Xgrass,                             TRUE,   FALSE,
3839     EL_EMC_GRASS,                       -1, -1
3840   },
3841   {
3842     Ygrass_nB,                          FALSE,  FALSE,
3843     EL_EMC_GRASS,                       ACTION_DIGGING, MV_BIT_UP
3844   },
3845   {
3846     Ygrass_eB,                          FALSE,  FALSE,
3847     EL_EMC_GRASS,                       ACTION_DIGGING, MV_BIT_RIGHT
3848   },
3849   {
3850     Ygrass_sB,                          FALSE,  FALSE,
3851     EL_EMC_GRASS,                       ACTION_DIGGING, MV_BIT_DOWN
3852   },
3853   {
3854     Ygrass_wB,                          FALSE,  FALSE,
3855     EL_EMC_GRASS,                       ACTION_DIGGING, MV_BIT_LEFT
3856   },
3857   {
3858     Xdirt,                              TRUE,   FALSE,
3859     EL_SAND,                            -1, -1
3860   },
3861   {
3862     Ydirt_nB,                           FALSE,  FALSE,
3863     EL_SAND,                            ACTION_DIGGING, MV_BIT_UP
3864   },
3865   {
3866     Ydirt_eB,                           FALSE,  FALSE,
3867     EL_SAND,                            ACTION_DIGGING, MV_BIT_RIGHT
3868   },
3869   {
3870     Ydirt_sB,                           FALSE,  FALSE,
3871     EL_SAND,                            ACTION_DIGGING, MV_BIT_DOWN
3872   },
3873   {
3874     Ydirt_wB,                           FALSE,  FALSE,
3875     EL_SAND,                            ACTION_DIGGING, MV_BIT_LEFT
3876   },
3877   {
3878     Xacid_ne,                           TRUE,   FALSE,
3879     EL_ACID_POOL_TOPRIGHT,              -1, -1
3880   },
3881   {
3882     Xacid_se,                           TRUE,   FALSE,
3883     EL_ACID_POOL_BOTTOMRIGHT,           -1, -1
3884   },
3885   {
3886     Xacid_s,                            TRUE,   FALSE,
3887     EL_ACID_POOL_BOTTOM,                -1, -1
3888   },
3889   {
3890     Xacid_sw,                           TRUE,   FALSE,
3891     EL_ACID_POOL_BOTTOMLEFT,            -1, -1
3892   },
3893   {
3894     Xacid_nw,                           TRUE,   FALSE,
3895     EL_ACID_POOL_TOPLEFT,               -1, -1
3896   },
3897   {
3898     Xacid_1,                            TRUE,   FALSE,
3899     EL_ACID,                            -1, -1
3900   },
3901   {
3902     Xacid_2,                            FALSE,  FALSE,
3903     EL_ACID,                            -1, -1
3904   },
3905   {
3906     Xacid_3,                            FALSE,  FALSE,
3907     EL_ACID,                            -1, -1
3908   },
3909   {
3910     Xacid_4,                            FALSE,  FALSE,
3911     EL_ACID,                            -1, -1
3912   },
3913   {
3914     Xacid_5,                            FALSE,  FALSE,
3915     EL_ACID,                            -1, -1
3916   },
3917   {
3918     Xacid_6,                            FALSE,  FALSE,
3919     EL_ACID,                            -1, -1
3920   },
3921   {
3922     Xacid_7,                            FALSE,  FALSE,
3923     EL_ACID,                            -1, -1
3924   },
3925   {
3926     Xacid_8,                            FALSE,  FALSE,
3927     EL_ACID,                            -1, -1
3928   },
3929   {
3930     Xball_1,                            TRUE,   FALSE,
3931     EL_EMC_MAGIC_BALL,                  -1, -1
3932   },
3933   {
3934     Xball_1B,                           FALSE,  FALSE,
3935     EL_EMC_MAGIC_BALL,                  ACTION_ACTIVE, -1
3936   },
3937   {
3938     Xball_2,                            FALSE,  FALSE,
3939     EL_EMC_MAGIC_BALL,                  ACTION_ACTIVE, -1
3940   },
3941   {
3942     Xball_2B,                           FALSE,  FALSE,
3943     EL_EMC_MAGIC_BALL,                  ACTION_ACTIVE, -1
3944   },
3945   {
3946     Yball_eat,                          FALSE,  FALSE,
3947     EL_EMC_MAGIC_BALL,                  ACTION_DROPPING, -1
3948   },
3949   {
3950     Ykey_1_eat,                         FALSE,  FALSE,
3951     EL_EM_KEY_1,                        ACTION_COLLECTING, -1
3952   },
3953   {
3954     Ykey_2_eat,                         FALSE,  FALSE,
3955     EL_EM_KEY_2,                        ACTION_COLLECTING, -1
3956   },
3957   {
3958     Ykey_3_eat,                         FALSE,  FALSE,
3959     EL_EM_KEY_3,                        ACTION_COLLECTING, -1
3960   },
3961   {
3962     Ykey_4_eat,                         FALSE,  FALSE,
3963     EL_EM_KEY_4,                        ACTION_COLLECTING, -1
3964   },
3965   {
3966     Ykey_5_eat,                         FALSE,  FALSE,
3967     EL_EM_KEY_5,                        ACTION_COLLECTING, -1
3968   },
3969   {
3970     Ykey_6_eat,                         FALSE,  FALSE,
3971     EL_EM_KEY_6,                        ACTION_COLLECTING, -1
3972   },
3973   {
3974     Ykey_7_eat,                         FALSE,  FALSE,
3975     EL_EM_KEY_7,                        ACTION_COLLECTING, -1
3976   },
3977   {
3978     Ykey_8_eat,                         FALSE,  FALSE,
3979     EL_EM_KEY_8,                        ACTION_COLLECTING, -1
3980   },
3981   {
3982     Ylenses_eat,                        FALSE,  FALSE,
3983     EL_EMC_LENSES,                      ACTION_COLLECTING, -1
3984   },
3985   {
3986     Ymagnify_eat,                       FALSE,  FALSE,
3987     EL_EMC_MAGNIFIER,                   ACTION_COLLECTING, -1
3988   },
3989   {
3990     Ygrass_eat,                         FALSE,  FALSE,
3991     EL_EMC_GRASS,                       ACTION_SNAPPING, -1
3992   },
3993   {
3994     Ydirt_eat,                          FALSE,  FALSE,
3995     EL_SAND,                            ACTION_SNAPPING, -1
3996   },
3997   {
3998     Xgrow_ns,                           TRUE,   FALSE,
3999     EL_EXPANDABLE_WALL_VERTICAL,        -1, -1
4000   },
4001   {
4002     Ygrow_ns_eat,                       FALSE,  FALSE,
4003     EL_EXPANDABLE_WALL_VERTICAL,        ACTION_GROWING, -1
4004   },
4005   {
4006     Xgrow_ew,                           TRUE,   FALSE,
4007     EL_EXPANDABLE_WALL_HORIZONTAL,      -1, -1
4008   },
4009   {
4010     Ygrow_ew_eat,                       FALSE,  FALSE,
4011     EL_EXPANDABLE_WALL_HORIZONTAL,      ACTION_GROWING, -1
4012   },
4013   {
4014     Xwonderwall,                        TRUE,   FALSE,
4015     EL_MAGIC_WALL,                      -1, -1
4016   },
4017   {
4018     XwonderwallB,                       FALSE,  FALSE,
4019     EL_MAGIC_WALL,                      ACTION_ACTIVE, -1
4020   },
4021   {
4022     Xamoeba_1,                          TRUE,   FALSE,
4023     EL_AMOEBA_DRY,                      ACTION_OTHER, -1
4024   },
4025   {
4026     Xamoeba_2,                          FALSE,  FALSE,
4027     EL_AMOEBA_DRY,                      ACTION_OTHER, -1
4028   },
4029   {
4030     Xamoeba_3,                          FALSE,  FALSE,
4031     EL_AMOEBA_DRY,                      ACTION_OTHER, -1
4032   },
4033   {
4034     Xamoeba_4,                          FALSE,  FALSE,
4035     EL_AMOEBA_DRY,                      ACTION_OTHER, -1
4036   },
4037   {
4038     Xamoeba_5,                          FALSE,  FALSE,
4039     EL_AMOEBA_WET,                      ACTION_OTHER, -1
4040   },
4041   {
4042     Xamoeba_6,                          FALSE,  FALSE,
4043     EL_AMOEBA_WET,                      ACTION_OTHER, -1
4044   },
4045   {
4046     Xamoeba_7,                          FALSE,  FALSE,
4047     EL_AMOEBA_WET,                      ACTION_OTHER, -1
4048   },
4049   {
4050     Xamoeba_8,                          FALSE,  FALSE,
4051     EL_AMOEBA_WET,                      ACTION_OTHER, -1
4052   },
4053   {
4054     Xdoor_1,                            TRUE,   FALSE,
4055     EL_EM_GATE_1,                       -1, -1
4056   },
4057   {
4058     Xdoor_2,                            TRUE,   FALSE,
4059     EL_EM_GATE_2,                       -1, -1
4060   },
4061   {
4062     Xdoor_3,                            TRUE,   FALSE,
4063     EL_EM_GATE_3,                       -1, -1
4064   },
4065   {
4066     Xdoor_4,                            TRUE,   FALSE,
4067     EL_EM_GATE_4,                       -1, -1
4068   },
4069   {
4070     Xdoor_5,                            TRUE,   FALSE,
4071     EL_EM_GATE_5,                       -1, -1
4072   },
4073   {
4074     Xdoor_6,                            TRUE,   FALSE,
4075     EL_EM_GATE_6,                       -1, -1
4076   },
4077   {
4078     Xdoor_7,                            TRUE,   FALSE,
4079     EL_EM_GATE_7,                       -1, -1
4080   },
4081   {
4082     Xdoor_8,                            TRUE,   FALSE,
4083     EL_EM_GATE_8,                       -1, -1
4084   },
4085   {
4086     Xkey_1,                             TRUE,   FALSE,
4087     EL_EM_KEY_1,                        -1, -1
4088   },
4089   {
4090     Xkey_2,                             TRUE,   FALSE,
4091     EL_EM_KEY_2,                        -1, -1
4092   },
4093   {
4094     Xkey_3,                             TRUE,   FALSE,
4095     EL_EM_KEY_3,                        -1, -1
4096   },
4097   {
4098     Xkey_4,                             TRUE,   FALSE,
4099     EL_EM_KEY_4,                        -1, -1
4100   },
4101   {
4102     Xkey_5,                             TRUE,   FALSE,
4103     EL_EM_KEY_5,                        -1, -1
4104   },
4105   {
4106     Xkey_6,                             TRUE,   FALSE,
4107     EL_EM_KEY_6,                        -1, -1
4108   },
4109   {
4110     Xkey_7,                             TRUE,   FALSE,
4111     EL_EM_KEY_7,                        -1, -1
4112   },
4113   {
4114     Xkey_8,                             TRUE,   FALSE,
4115     EL_EM_KEY_8,                        -1, -1
4116   },
4117   {
4118     Xwind_n,                            TRUE,   FALSE,
4119     EL_BALLOON_SWITCH_UP,               -1, -1
4120   },
4121   {
4122     Xwind_e,                            TRUE,   FALSE,
4123     EL_BALLOON_SWITCH_RIGHT,            -1, -1
4124   },
4125   {
4126     Xwind_s,                            TRUE,   FALSE,
4127     EL_BALLOON_SWITCH_DOWN,             -1, -1
4128   },
4129   {
4130     Xwind_w,                            TRUE,   FALSE,
4131     EL_BALLOON_SWITCH_LEFT,             -1, -1
4132   },
4133   {
4134     Xwind_nesw,                         TRUE,   FALSE,
4135     EL_BALLOON_SWITCH_ANY,              -1, -1
4136   },
4137   {
4138     Xwind_stop,                         TRUE,   FALSE,
4139     EL_BALLOON_SWITCH_NONE,             -1, -1
4140   },
4141   {
4142     Xexit,                              TRUE,   FALSE,
4143     EL_EXIT_CLOSED,                     -1, -1
4144   },
4145   {
4146     Xexit_1,                            TRUE,   FALSE,
4147     EL_EXIT_OPEN,                       -1, -1
4148   },
4149   {
4150     Xexit_2,                            FALSE,  FALSE,
4151     EL_EXIT_OPEN,                       -1, -1
4152   },
4153   {
4154     Xexit_3,                            FALSE,  FALSE,
4155     EL_EXIT_OPEN,                       -1, -1
4156   },
4157   {
4158     Xdynamite,                          TRUE,   FALSE,
4159     EL_DYNAMITE,                        -1, -1
4160   },
4161   {
4162     Ydynamite_eat,                      FALSE,  FALSE,
4163     EL_DYNAMITE,                        ACTION_COLLECTING, -1
4164   },
4165   {
4166     Xdynamite_1,                        TRUE,   FALSE,
4167     EL_DYNAMITE_ACTIVE,                 -1, -1
4168   },
4169   {
4170     Xdynamite_2,                        FALSE,  FALSE,
4171     EL_DYNAMITE_ACTIVE,                 -1, -1
4172   },
4173   {
4174     Xdynamite_3,                        FALSE,  FALSE,
4175     EL_DYNAMITE_ACTIVE,                 -1, -1
4176   },
4177   {
4178     Xdynamite_4,                        FALSE,  FALSE,
4179     EL_DYNAMITE_ACTIVE,                 -1, -1
4180   },
4181   {
4182     Xbumper,                            TRUE,   FALSE,
4183     EL_EMC_SPRING_BUMPER,               -1, -1
4184   },
4185   {
4186     XbumperB,                           FALSE,  FALSE,
4187     EL_EMC_SPRING_BUMPER,               ACTION_ACTIVE, -1
4188   },
4189   {
4190     Xwheel,                             TRUE,   FALSE,
4191     EL_ROBOT_WHEEL,                     -1, -1
4192   },
4193   {
4194     XwheelB,                            FALSE,  FALSE,
4195     EL_ROBOT_WHEEL,                     ACTION_ACTIVE, -1
4196   },
4197   {
4198     Xswitch,                            TRUE,   FALSE,
4199     EL_EMC_MAGIC_BALL_SWITCH,           -1, -1
4200   },
4201   {
4202     XswitchB,                           FALSE,  FALSE,
4203     EL_EMC_MAGIC_BALL_SWITCH,           ACTION_ACTIVE, -1
4204   },
4205   {
4206     Xsand,                              TRUE,   FALSE,
4207     EL_QUICKSAND_EMPTY,                 -1, -1
4208   },
4209   {
4210     Xsand_stone,                        TRUE,   FALSE,
4211     EL_QUICKSAND_FULL,                  -1, -1
4212   },
4213   {
4214     Xsand_stonein_1,                    FALSE,  FALSE,
4215     EL_ROCK,                            ACTION_FILLING, -1
4216   },
4217   {
4218     Xsand_stonein_2,                    FALSE,  FALSE,
4219     EL_ROCK,                            ACTION_FILLING, -1
4220   },
4221   {
4222     Xsand_stonein_3,                    FALSE,  FALSE,
4223     EL_ROCK,                            ACTION_FILLING, -1
4224   },
4225   {
4226     Xsand_stonein_4,                    FALSE,  FALSE,
4227     EL_ROCK,                            ACTION_FILLING, -1
4228   },
4229   {
4230     Xsand_stonesand_1,                  FALSE,  FALSE,
4231     EL_QUICKSAND_FULL,                  -1, -1
4232   },
4233   {
4234     Xsand_stonesand_2,                  FALSE,  FALSE,
4235     EL_QUICKSAND_FULL,                  -1, -1
4236   },
4237   {
4238     Xsand_stonesand_3,                  FALSE,  FALSE,
4239     EL_QUICKSAND_FULL,                  -1, -1
4240   },
4241   {
4242     Xsand_stonesand_4,                  FALSE,  FALSE,
4243     EL_QUICKSAND_FULL,                  -1, -1
4244   },
4245   {
4246     Xsand_stoneout_1,                   FALSE,  FALSE,
4247     EL_ROCK,                            ACTION_EMPTYING, -1
4248   },
4249   {
4250     Xsand_stoneout_2,                   FALSE,  FALSE,
4251     EL_ROCK,                            ACTION_EMPTYING, -1
4252   },
4253   {
4254     Xsand_sandstone_1,                  FALSE,  FALSE,
4255     EL_QUICKSAND_FULL,                  -1, -1
4256   },
4257   {
4258     Xsand_sandstone_2,                  FALSE,  FALSE,
4259     EL_QUICKSAND_FULL,                  -1, -1
4260   },
4261   {
4262     Xsand_sandstone_3,                  FALSE,  FALSE,
4263     EL_QUICKSAND_FULL,                  -1, -1
4264   },
4265   {
4266     Xsand_sandstone_4,                  FALSE,  FALSE,
4267     EL_QUICKSAND_FULL,                  -1, -1
4268   },
4269   {
4270     Xplant,                             TRUE,   FALSE,
4271     EL_EMC_PLANT,                       -1, -1
4272   },
4273   {
4274     Yplant,                             FALSE,  FALSE,
4275     EL_EMC_PLANT,                       -1, -1
4276   },
4277   {
4278     Xlenses,                            TRUE,   FALSE,
4279     EL_EMC_LENSES,                      -1, -1
4280   },
4281   {
4282     Xmagnify,                           TRUE,   FALSE,
4283     EL_EMC_MAGNIFIER,                   -1, -1
4284   },
4285   {
4286     Xdripper,                           TRUE,   FALSE,
4287     EL_EMC_DRIPPER,                     -1, -1
4288   },
4289   {
4290     XdripperB,                          FALSE,  FALSE,
4291     EL_EMC_DRIPPER,                     ACTION_ACTIVE, -1
4292   },
4293   {
4294     Xfake_blank,                        TRUE,   FALSE,
4295     EL_INVISIBLE_WALL,                  -1, -1
4296   },
4297   {
4298     Xfake_blankB,                       FALSE,  FALSE,
4299     EL_INVISIBLE_WALL,                  ACTION_ACTIVE, -1
4300   },
4301   {
4302     Xfake_grass,                        TRUE,   FALSE,
4303     EL_EMC_FAKE_GRASS,                  -1, -1
4304   },
4305   {
4306     Xfake_grassB,                       FALSE,  FALSE,
4307     EL_EMC_FAKE_GRASS,                  ACTION_ACTIVE, -1
4308   },
4309   {
4310     Xfake_door_1,                       TRUE,   FALSE,
4311     EL_EM_GATE_1_GRAY,                  -1, -1
4312   },
4313   {
4314     Xfake_door_2,                       TRUE,   FALSE,
4315     EL_EM_GATE_2_GRAY,                  -1, -1
4316   },
4317   {
4318     Xfake_door_3,                       TRUE,   FALSE,
4319     EL_EM_GATE_3_GRAY,                  -1, -1
4320   },
4321   {
4322     Xfake_door_4,                       TRUE,   FALSE,
4323     EL_EM_GATE_4_GRAY,                  -1, -1
4324   },
4325   {
4326     Xfake_door_5,                       TRUE,   FALSE,
4327     EL_EM_GATE_5_GRAY,                  -1, -1
4328   },
4329   {
4330     Xfake_door_6,                       TRUE,   FALSE,
4331     EL_EM_GATE_6_GRAY,                  -1, -1
4332   },
4333   {
4334     Xfake_door_7,                       TRUE,   FALSE,
4335     EL_EM_GATE_7_GRAY,                  -1, -1
4336   },
4337   {
4338     Xfake_door_8,                       TRUE,   FALSE,
4339     EL_EM_GATE_8_GRAY,                  -1, -1
4340   },
4341   {
4342     Xsteel_1,                           TRUE,   FALSE,
4343     EL_STEELWALL,                       -1, -1
4344   },
4345   {
4346     Xsteel_2,                           TRUE,   FALSE,
4347     EL_EMC_STEELWALL_2,                 -1, -1
4348   },
4349   {
4350     Xsteel_3,                           TRUE,   FALSE,
4351     EL_EMC_STEELWALL_3,                 -1, -1
4352   },
4353   {
4354     Xsteel_4,                           TRUE,   FALSE,
4355     EL_EMC_STEELWALL_4,                 -1, -1
4356   },
4357   {
4358     Xwall_1,                            TRUE,   FALSE,
4359     EL_WALL,                            -1, -1
4360   },
4361   {
4362     Xwall_2,                            TRUE,   FALSE,
4363     EL_EMC_WALL_14,                     -1, -1
4364   },
4365   {
4366     Xwall_3,                            TRUE,   FALSE,
4367     EL_EMC_WALL_15,                     -1, -1
4368   },
4369   {
4370     Xwall_4,                            TRUE,   FALSE,
4371     EL_EMC_WALL_16,                     -1, -1
4372   },
4373   {
4374     Xround_wall_1,                      TRUE,   FALSE,
4375     EL_WALL_SLIPPERY,                   -1, -1
4376   },
4377   {
4378     Xround_wall_2,                      TRUE,   FALSE,
4379     EL_EMC_WALL_SLIPPERY_2,             -1, -1
4380   },
4381   {
4382     Xround_wall_3,                      TRUE,   FALSE,
4383     EL_EMC_WALL_SLIPPERY_3,             -1, -1
4384   },
4385   {
4386     Xround_wall_4,                      TRUE,   FALSE,
4387     EL_EMC_WALL_SLIPPERY_4,             -1, -1
4388   },
4389   {
4390     Xdecor_1,                           TRUE,   FALSE,
4391     EL_EMC_WALL_8,                      -1, -1
4392   },
4393   {
4394     Xdecor_2,                           TRUE,   FALSE,
4395     EL_EMC_WALL_6,                      -1, -1
4396   },
4397   {
4398     Xdecor_3,                           TRUE,   FALSE,
4399     EL_EMC_WALL_4,                      -1, -1
4400   },
4401   {
4402     Xdecor_4,                           TRUE,   FALSE,
4403     EL_EMC_WALL_7,                      -1, -1
4404   },
4405   {
4406     Xdecor_5,                           TRUE,   FALSE,
4407     EL_EMC_WALL_5,                      -1, -1
4408   },
4409   {
4410     Xdecor_6,                           TRUE,   FALSE,
4411     EL_EMC_WALL_9,                      -1, -1
4412   },
4413   {
4414     Xdecor_7,                           TRUE,   FALSE,
4415     EL_EMC_WALL_10,                     -1, -1
4416   },
4417   {
4418     Xdecor_8,                           TRUE,   FALSE,
4419     EL_EMC_WALL_1,                      -1, -1
4420   },
4421   {
4422     Xdecor_9,                           TRUE,   FALSE,
4423     EL_EMC_WALL_2,                      -1, -1
4424   },
4425   {
4426     Xdecor_10,                          TRUE,   FALSE,
4427     EL_EMC_WALL_3,                      -1, -1
4428   },
4429   {
4430     Xdecor_11,                          TRUE,   FALSE,
4431     EL_EMC_WALL_11,                     -1, -1
4432   },
4433   {
4434     Xdecor_12,                          TRUE,   FALSE,
4435     EL_EMC_WALL_12,                     -1, -1
4436   },
4437   {
4438     Xalpha_0,                           TRUE,   FALSE,
4439     EL_CHAR('0'),                       -1, -1
4440   },
4441   {
4442     Xalpha_1,                           TRUE,   FALSE,
4443     EL_CHAR('1'),                       -1, -1
4444   },
4445   {
4446     Xalpha_2,                           TRUE,   FALSE,
4447     EL_CHAR('2'),                       -1, -1
4448   },
4449   {
4450     Xalpha_3,                           TRUE,   FALSE,
4451     EL_CHAR('3'),                       -1, -1
4452   },
4453   {
4454     Xalpha_4,                           TRUE,   FALSE,
4455     EL_CHAR('4'),                       -1, -1
4456   },
4457   {
4458     Xalpha_5,                           TRUE,   FALSE,
4459     EL_CHAR('5'),                       -1, -1
4460   },
4461   {
4462     Xalpha_6,                           TRUE,   FALSE,
4463     EL_CHAR('6'),                       -1, -1
4464   },
4465   {
4466     Xalpha_7,                           TRUE,   FALSE,
4467     EL_CHAR('7'),                       -1, -1
4468   },
4469   {
4470     Xalpha_8,                           TRUE,   FALSE,
4471     EL_CHAR('8'),                       -1, -1
4472   },
4473   {
4474     Xalpha_9,                           TRUE,   FALSE,
4475     EL_CHAR('9'),                       -1, -1
4476   },
4477   {
4478     Xalpha_excla,                       TRUE,   FALSE,
4479     EL_CHAR('!'),                       -1, -1
4480   },
4481   {
4482     Xalpha_quote,                       TRUE,   FALSE,
4483     EL_CHAR('"'),                       -1, -1
4484   },
4485   {
4486     Xalpha_comma,                       TRUE,   FALSE,
4487     EL_CHAR(','),                       -1, -1
4488   },
4489   {
4490     Xalpha_minus,                       TRUE,   FALSE,
4491     EL_CHAR('-'),                       -1, -1
4492   },
4493   {
4494     Xalpha_perio,                       TRUE,   FALSE,
4495     EL_CHAR('.'),                       -1, -1
4496   },
4497   {
4498     Xalpha_colon,                       TRUE,   FALSE,
4499     EL_CHAR(':'),                       -1, -1
4500   },
4501   {
4502     Xalpha_quest,                       TRUE,   FALSE,
4503     EL_CHAR('?'),                       -1, -1
4504   },
4505   {
4506     Xalpha_a,                           TRUE,   FALSE,
4507     EL_CHAR('A'),                       -1, -1
4508   },
4509   {
4510     Xalpha_b,                           TRUE,   FALSE,
4511     EL_CHAR('B'),                       -1, -1
4512   },
4513   {
4514     Xalpha_c,                           TRUE,   FALSE,
4515     EL_CHAR('C'),                       -1, -1
4516   },
4517   {
4518     Xalpha_d,                           TRUE,   FALSE,
4519     EL_CHAR('D'),                       -1, -1
4520   },
4521   {
4522     Xalpha_e,                           TRUE,   FALSE,
4523     EL_CHAR('E'),                       -1, -1
4524   },
4525   {
4526     Xalpha_f,                           TRUE,   FALSE,
4527     EL_CHAR('F'),                       -1, -1
4528   },
4529   {
4530     Xalpha_g,                           TRUE,   FALSE,
4531     EL_CHAR('G'),                       -1, -1
4532   },
4533   {
4534     Xalpha_h,                           TRUE,   FALSE,
4535     EL_CHAR('H'),                       -1, -1
4536   },
4537   {
4538     Xalpha_i,                           TRUE,   FALSE,
4539     EL_CHAR('I'),                       -1, -1
4540   },
4541   {
4542     Xalpha_j,                           TRUE,   FALSE,
4543     EL_CHAR('J'),                       -1, -1
4544   },
4545   {
4546     Xalpha_k,                           TRUE,   FALSE,
4547     EL_CHAR('K'),                       -1, -1
4548   },
4549   {
4550     Xalpha_l,                           TRUE,   FALSE,
4551     EL_CHAR('L'),                       -1, -1
4552   },
4553   {
4554     Xalpha_m,                           TRUE,   FALSE,
4555     EL_CHAR('M'),                       -1, -1
4556   },
4557   {
4558     Xalpha_n,                           TRUE,   FALSE,
4559     EL_CHAR('N'),                       -1, -1
4560   },
4561   {
4562     Xalpha_o,                           TRUE,   FALSE,
4563     EL_CHAR('O'),                       -1, -1
4564   },
4565   {
4566     Xalpha_p,                           TRUE,   FALSE,
4567     EL_CHAR('P'),                       -1, -1
4568   },
4569   {
4570     Xalpha_q,                           TRUE,   FALSE,
4571     EL_CHAR('Q'),                       -1, -1
4572   },
4573   {
4574     Xalpha_r,                           TRUE,   FALSE,
4575     EL_CHAR('R'),                       -1, -1
4576   },
4577   {
4578     Xalpha_s,                           TRUE,   FALSE,
4579     EL_CHAR('S'),                       -1, -1
4580   },
4581   {
4582     Xalpha_t,                           TRUE,   FALSE,
4583     EL_CHAR('T'),                       -1, -1
4584   },
4585   {
4586     Xalpha_u,                           TRUE,   FALSE,
4587     EL_CHAR('U'),                       -1, -1
4588   },
4589   {
4590     Xalpha_v,                           TRUE,   FALSE,
4591     EL_CHAR('V'),                       -1, -1
4592   },
4593   {
4594     Xalpha_w,                           TRUE,   FALSE,
4595     EL_CHAR('W'),                       -1, -1
4596   },
4597   {
4598     Xalpha_x,                           TRUE,   FALSE,
4599     EL_CHAR('X'),                       -1, -1
4600   },
4601   {
4602     Xalpha_y,                           TRUE,   FALSE,
4603     EL_CHAR('Y'),                       -1, -1
4604   },
4605   {
4606     Xalpha_z,                           TRUE,   FALSE,
4607     EL_CHAR('Z'),                       -1, -1
4608   },
4609   {
4610     Xalpha_arrow_e,                     TRUE,   FALSE,
4611     EL_CHAR('>'),                       -1, -1
4612   },
4613   {
4614     Xalpha_arrow_w,                     TRUE,   FALSE,
4615     EL_CHAR('<'),                       -1, -1
4616   },
4617   {
4618     Xalpha_copyr,                       TRUE,   FALSE,
4619     EL_CHAR('©'),                       -1, -1
4620   },
4621   {
4622     Xalpha_copyr,                       TRUE,   FALSE,
4623     EL_CHAR('©'),                       -1, -1
4624   },
4625
4626   {
4627     Xboom_bug,                          FALSE,  FALSE,
4628     EL_BUG,                             ACTION_EXPLODING, -1
4629   },
4630   {
4631     Xboom_bomb,                         FALSE,  FALSE,
4632     EL_BOMB,                            ACTION_EXPLODING, -1
4633   },
4634   {
4635     Xboom_android,                      FALSE,  FALSE,
4636     EL_EMC_ANDROID,                     ACTION_OTHER, -1
4637   },
4638   {
4639     Xboom_1,                            FALSE,  FALSE,
4640     EL_DEFAULT,                         ACTION_EXPLODING, -1
4641   },
4642   {
4643     Xboom_2,                            FALSE,  FALSE,
4644     EL_DEFAULT,                         ACTION_EXPLODING, -1
4645   },
4646   {
4647     Znormal,                            FALSE,  FALSE,
4648     EL_EMPTY,                           -1, -1
4649   },
4650   {
4651     Zdynamite,                          FALSE,  FALSE,
4652     EL_EMPTY,                           -1, -1
4653   },
4654   {
4655     Zplayer,                            FALSE,  FALSE,
4656     EL_EMPTY,                           -1, -1
4657   },
4658   {
4659     ZBORDER,                            FALSE,  FALSE,
4660     EL_EMPTY,                           -1, -1
4661   },
4662
4663   {
4664     -1,                                 FALSE,  FALSE,
4665     -1,                                 -1, -1
4666   }
4667 };
4668
4669 static struct Mapping_EM_to_RND_player
4670 {
4671   int action_em;
4672   int player_nr;
4673
4674   int element_rnd;
4675   int action;
4676   int direction;
4677 }
4678 em_player_mapping_list[] =
4679 {
4680   {
4681     SPR_walk + 0,                       0,
4682     EL_PLAYER_1,                        ACTION_MOVING, MV_BIT_UP,
4683   },
4684   {
4685     SPR_walk + 1,                       0,
4686     EL_PLAYER_1,                        ACTION_MOVING, MV_BIT_RIGHT,
4687   },
4688   {
4689     SPR_walk + 2,                       0,
4690     EL_PLAYER_1,                        ACTION_MOVING, MV_BIT_DOWN,
4691   },
4692   {
4693     SPR_walk + 3,                       0,
4694     EL_PLAYER_1,                        ACTION_MOVING, MV_BIT_LEFT,
4695   },
4696   {
4697     SPR_push + 0,                       0,
4698     EL_PLAYER_1,                        ACTION_PUSHING, MV_BIT_UP,
4699   },
4700   {
4701     SPR_push + 1,                       0,
4702     EL_PLAYER_1,                        ACTION_PUSHING, MV_BIT_RIGHT,
4703   },
4704   {
4705     SPR_push + 2,                       0,
4706     EL_PLAYER_1,                        ACTION_PUSHING, MV_BIT_DOWN,
4707   },
4708   {
4709     SPR_push + 3,                       0,
4710     EL_PLAYER_1,                        ACTION_PUSHING, MV_BIT_LEFT,
4711   },
4712   {
4713     SPR_spray + 0,                      0,
4714     EL_PLAYER_1,                        ACTION_SNAPPING, MV_BIT_UP,
4715   },
4716   {
4717     SPR_spray + 1,                      0,
4718     EL_PLAYER_1,                        ACTION_SNAPPING, MV_BIT_RIGHT,
4719   },
4720   {
4721     SPR_spray + 2,                      0,
4722     EL_PLAYER_1,                        ACTION_SNAPPING, MV_BIT_DOWN,
4723   },
4724   {
4725     SPR_spray + 3,                      0,
4726     EL_PLAYER_1,                        ACTION_SNAPPING, MV_BIT_LEFT,
4727   },
4728   {
4729     SPR_walk + 0,                       1,
4730     EL_PLAYER_2,                        ACTION_MOVING, MV_BIT_UP,
4731   },
4732   {
4733     SPR_walk + 1,                       1,
4734     EL_PLAYER_2,                        ACTION_MOVING, MV_BIT_RIGHT,
4735   },
4736   {
4737     SPR_walk + 2,                       1,
4738     EL_PLAYER_2,                        ACTION_MOVING, MV_BIT_DOWN,
4739   },
4740   {
4741     SPR_walk + 3,                       1,
4742     EL_PLAYER_2,                        ACTION_MOVING, MV_BIT_LEFT,
4743   },
4744   {
4745     SPR_push + 0,                       1,
4746     EL_PLAYER_2,                        ACTION_PUSHING, MV_BIT_UP,
4747   },
4748   {
4749     SPR_push + 1,                       1,
4750     EL_PLAYER_2,                        ACTION_PUSHING, MV_BIT_RIGHT,
4751   },
4752   {
4753     SPR_push + 2,                       1,
4754     EL_PLAYER_2,                        ACTION_PUSHING, MV_BIT_DOWN,
4755   },
4756   {
4757     SPR_push + 3,                       1,
4758     EL_PLAYER_2,                        ACTION_PUSHING, MV_BIT_LEFT,
4759   },
4760   {
4761     SPR_spray + 0,                      1,
4762     EL_PLAYER_2,                        ACTION_SNAPPING, MV_BIT_UP,
4763   },
4764   {
4765     SPR_spray + 1,                      1,
4766     EL_PLAYER_2,                        ACTION_SNAPPING, MV_BIT_RIGHT,
4767   },
4768   {
4769     SPR_spray + 2,                      1,
4770     EL_PLAYER_2,                        ACTION_SNAPPING, MV_BIT_DOWN,
4771   },
4772   {
4773     SPR_spray + 3,                      1,
4774     EL_PLAYER_2,                        ACTION_SNAPPING, MV_BIT_LEFT,
4775   },
4776   {
4777     SPR_still,                          0,
4778     EL_PLAYER_1,                        ACTION_DEFAULT, -1,
4779   },
4780   {
4781     SPR_still,                          1,
4782     EL_PLAYER_2,                        ACTION_DEFAULT, -1,
4783   },
4784
4785   {
4786     -1,                                 -1,
4787     -1,                                 -1, -1
4788   }
4789 };
4790
4791 int map_element_RND_to_EM(int element_rnd)
4792 {
4793   static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4794   static boolean mapping_initialized = FALSE;
4795
4796   if (!mapping_initialized)
4797   {
4798     int i;
4799
4800     /* return "Xalpha_quest" for all undefined elements in mapping array */
4801     for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4802       mapping_RND_to_EM[i] = Xalpha_quest;
4803
4804     for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4805       if (em_object_mapping_list[i].is_rnd_to_em_mapping)
4806         mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
4807           em_object_mapping_list[i].element_em;
4808
4809     mapping_initialized = TRUE;
4810   }
4811
4812   if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4813     return mapping_RND_to_EM[element_rnd];
4814
4815   Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4816
4817   return EL_UNKNOWN;
4818 }
4819
4820 int map_element_EM_to_RND(int element_em)
4821 {
4822   static unsigned short mapping_EM_to_RND[TILE_MAX];
4823   static boolean mapping_initialized = FALSE;
4824
4825   if (!mapping_initialized)
4826   {
4827     int i;
4828
4829     /* return "EL_UNKNOWN" for all undefined elements in mapping array */
4830     for (i = 0; i < TILE_MAX; i++)
4831       mapping_EM_to_RND[i] = EL_UNKNOWN;
4832
4833     for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4834       mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
4835         em_object_mapping_list[i].element_rnd;
4836
4837     mapping_initialized = TRUE;
4838   }
4839
4840   if (element_em >= 0 && element_em < TILE_MAX)
4841     return mapping_EM_to_RND[element_em];
4842
4843   Error(ERR_WARN, "invalid EM level element %d", element_em);
4844
4845   return EL_UNKNOWN;
4846 }
4847
4848 #else
4849
4850 int map_element_RND_to_EM(int element_rnd)
4851 {
4852   static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4853   static boolean mapping_initialized = FALSE;
4854
4855   struct
4856   {
4857     int element_em;
4858     int element_rnd;
4859   }
4860   mapping_RND_to_EM_list[] =
4861   {
4862     { Xblank,                   EL_EMPTY                        },
4863     { Xstone,                   EL_ROCK                         },
4864     { Xnut,                     EL_NUT                          },
4865     { Xbug_n,                   EL_BUG_UP                       },
4866     { Xbug_e,                   EL_BUG_RIGHT                    },
4867     { Xbug_s,                   EL_BUG_DOWN                     },
4868     { Xbug_w,                   EL_BUG_LEFT                     },
4869     { Xtank_n,                  EL_SPACESHIP_UP                 },
4870     { Xtank_e,                  EL_SPACESHIP_RIGHT              },
4871     { Xtank_s,                  EL_SPACESHIP_DOWN               },
4872     { Xtank_w,                  EL_SPACESHIP_LEFT               },
4873     { Xandroid,                 EL_EMC_ANDROID                  },
4874     { Xandroid_1_n,             EL_EMC_ANDROID_UP               },
4875     { Xandroid_1_e,             EL_EMC_ANDROID_RIGHT            },
4876     { Xandroid_1_w,             EL_EMC_ANDROID_LEFT             },
4877     { Xandroid_1_s,             EL_EMC_ANDROID_DOWN             },
4878     { Xspring,                  EL_SPRING                       },
4879     { Xeater_n,                 EL_YAMYAM                       },
4880     { Xalien,                   EL_ROBOT                        },
4881     { Xemerald,                 EL_EMERALD                      },
4882     { Xdiamond,                 EL_DIAMOND                      },
4883     { Xdrip_fall,               EL_AMOEBA_DROP                  },
4884     { Xbomb,                    EL_BOMB                         },
4885     { Xballoon,                 EL_BALLOON                      },
4886     { Xgrass,                   EL_EMC_GRASS                    },
4887     { Xdirt,                    EL_SAND                         },
4888     { Xacid_ne,                 EL_ACID_POOL_TOPRIGHT           },
4889     { Xacid_se,                 EL_ACID_POOL_BOTTOMRIGHT        },
4890     { Xacid_s,                  EL_ACID_POOL_BOTTOM             },
4891     { Xacid_sw,                 EL_ACID_POOL_BOTTOMLEFT         },
4892     { Xacid_nw,                 EL_ACID_POOL_TOPLEFT            },
4893     { Xacid_1,                  EL_ACID                         },
4894     { Xball_1,                  EL_EMC_MAGIC_BALL               },
4895     { Xgrow_ns,                 EL_EMC_GROW                     },
4896     { Xwonderwall,              EL_MAGIC_WALL                   },
4897     { Xamoeba_1,                EL_AMOEBA_WET                   },
4898     { Xdoor_1,                  EL_EM_GATE_1                    },
4899     { Xdoor_2,                  EL_EM_GATE_2                    },
4900     { Xdoor_3,                  EL_EM_GATE_3                    },
4901     { Xdoor_4,                  EL_EM_GATE_4                    },
4902     { Xdoor_5,                  EL_EMC_GATE_5                   },
4903     { Xdoor_6,                  EL_EMC_GATE_6                   },
4904     { Xdoor_7,                  EL_EMC_GATE_7                   },
4905     { Xdoor_8,                  EL_EMC_GATE_8                   },
4906     { Xkey_1,                   EL_EM_KEY_1                     },
4907     { Xkey_2,                   EL_EM_KEY_2                     },
4908     { Xkey_3,                   EL_EM_KEY_3                     },
4909     { Xkey_4,                   EL_EM_KEY_4                     },
4910     { Xkey_5,                   EL_EMC_KEY_5                    },
4911     { Xkey_6,                   EL_EMC_KEY_6                    },
4912     { Xkey_7,                   EL_EMC_KEY_7                    },
4913     { Xkey_8,                   EL_EMC_KEY_8                    },
4914     { Xwind_n,                  EL_BALLOON_SWITCH_UP            },
4915     { Xwind_e,                  EL_BALLOON_SWITCH_RIGHT         },
4916     { Xwind_s,                  EL_BALLOON_SWITCH_DOWN          },
4917     { Xwind_w,                  EL_BALLOON_SWITCH_LEFT          },
4918     { Xwind_nesw,               EL_BALLOON_SWITCH_ANY           },
4919     { Xwind_stop,               EL_BALLOON_SWITCH_NONE          },
4920     { Xexit,                    EL_EXIT_CLOSED                  },
4921     { Xexit_1,                  EL_EXIT_OPEN                    },
4922     { Xdynamite,                EL_DYNAMITE                     },
4923     { Xdynamite_1,              EL_DYNAMITE_ACTIVE              },
4924     { Xbumper,                  EL_EMC_BUMPER                   },
4925     { Xwheel,                   EL_ROBOT_WHEEL                  },
4926     { Xswitch,                  EL_UNKNOWN                      },
4927     { Xsand,                    EL_QUICKSAND_EMPTY              },
4928     { Xsand_stone,              EL_QUICKSAND_FULL               },
4929     { Xplant,                   EL_EMC_PLANT                    },
4930     { Xlenses,                  EL_EMC_LENSES                   },
4931     { Xmagnify,                 EL_EMC_MAGNIFIER                },
4932     { Xdripper,                 EL_UNKNOWN                      },
4933     { Xfake_blank,              EL_INVISIBLE_WALL               },
4934     { Xfake_grass,              EL_INVISIBLE_SAND               },
4935     { Xfake_door_1,             EL_EM_GATE_1_GRAY               },
4936     { Xfake_door_2,             EL_EM_GATE_2_GRAY               },
4937     { Xfake_door_3,             EL_EM_GATE_3_GRAY               },
4938     { Xfake_door_4,             EL_EM_GATE_4_GRAY               },
4939     { Xfake_door_5,             EL_EMC_GATE_5_GRAY              },
4940     { Xfake_door_6,             EL_EMC_GATE_6_GRAY              },
4941     { Xfake_door_7,             EL_EMC_GATE_7_GRAY              },
4942     { Xfake_door_8,             EL_EMC_GATE_8_GRAY              },
4943     { Xsteel_1,                 EL_STEELWALL                    },
4944     { Xsteel_2,                 EL_UNKNOWN                      },
4945     { Xsteel_3,                 EL_EMC_STEELWALL_1              },
4946     { Xsteel_4,                 EL_UNKNOWN                      },
4947     { Xwall_1,                  EL_WALL                         },
4948     { Xwall_2,                  EL_UNKNOWN                      },
4949     { Xwall_3,                  EL_UNKNOWN                      },
4950     { Xwall_4,                  EL_UNKNOWN                      },
4951     { Xround_wall_1,            EL_WALL_SLIPPERY                },
4952     { Xround_wall_2,            EL_UNKNOWN                      },
4953     { Xround_wall_3,            EL_UNKNOWN                      },
4954     { Xround_wall_4,            EL_UNKNOWN                      },
4955     { Xdecor_1,                 EL_UNKNOWN                      },
4956     { Xdecor_2,                 EL_EMC_WALL_6                   },
4957     { Xdecor_3,                 EL_EMC_WALL_4                   },
4958     { Xdecor_4,                 EL_EMC_WALL_5                   },
4959     { Xdecor_5,                 EL_EMC_WALL_7                   },
4960     { Xdecor_6,                 EL_EMC_WALL_8                   },
4961     { Xdecor_7,                 EL_UNKNOWN                      },
4962     { Xdecor_8,                 EL_EMC_WALL_1                   },
4963     { Xdecor_9,                 EL_EMC_WALL_2                   },
4964     { Xdecor_10,                EL_EMC_WALL_3                   },
4965     { Xdecor_11,                EL_UNKNOWN                      },
4966     { Xdecor_12,                EL_UNKNOWN                      },
4967     { Xalpha_0,                 EL_CHAR('0')                    },
4968     { Xalpha_1,                 EL_CHAR('1')                    },
4969     { Xalpha_2,                 EL_CHAR('2')                    },
4970     { Xalpha_3,                 EL_CHAR('3')                    },
4971     { Xalpha_4,                 EL_CHAR('4')                    },
4972     { Xalpha_5,                 EL_CHAR('5')                    },
4973     { Xalpha_6,                 EL_CHAR('6')                    },
4974     { Xalpha_7,                 EL_CHAR('7')                    },
4975     { Xalpha_8,                 EL_CHAR('8')                    },
4976     { Xalpha_9,                 EL_CHAR('9')                    },
4977     { Xalpha_excla,             EL_CHAR('!')                    },
4978     { Xalpha_quote,             EL_CHAR('"')                    },
4979     { Xalpha_comma,             EL_CHAR(',')                    },
4980     { Xalpha_minus,             EL_CHAR('-')                    },
4981     { Xalpha_perio,             EL_CHAR('.')                    },
4982     { Xalpha_colon,             EL_CHAR(':')                    },
4983     { Xalpha_quest,             EL_CHAR('?')                    },
4984     { Xalpha_a,                 EL_CHAR('A')                    },
4985     { Xalpha_b,                 EL_CHAR('B')                    },
4986     { Xalpha_c,                 EL_CHAR('C')                    },
4987     { Xalpha_d,                 EL_CHAR('D')                    },
4988     { Xalpha_e,                 EL_CHAR('E')                    },
4989     { Xalpha_f,                 EL_CHAR('F')                    },
4990     { Xalpha_g,                 EL_CHAR('G')                    },
4991     { Xalpha_h,                 EL_CHAR('H')                    },
4992     { Xalpha_i,                 EL_CHAR('I')                    },
4993     { Xalpha_j,                 EL_CHAR('J')                    },
4994     { Xalpha_k,                 EL_CHAR('K')                    },
4995     { Xalpha_l,                 EL_CHAR('L')                    },
4996     { Xalpha_m,                 EL_CHAR('M')                    },
4997     { Xalpha_n,                 EL_CHAR('N')                    },
4998     { Xalpha_o,                 EL_CHAR('O')                    },
4999     { Xalpha_p,                 EL_CHAR('P')                    },
5000     { Xalpha_q,                 EL_CHAR('Q')                    },
5001     { Xalpha_r,                 EL_CHAR('R')                    },
5002     { Xalpha_s,                 EL_CHAR('S')                    },
5003     { Xalpha_t,                 EL_CHAR('T')                    },
5004     { Xalpha_u,                 EL_CHAR('U')                    },
5005     { Xalpha_v,                 EL_CHAR('V')                    },
5006     { Xalpha_w,                 EL_CHAR('W')                    },
5007     { Xalpha_x,                 EL_CHAR('X')                    },
5008     { Xalpha_y,                 EL_CHAR('Y')                    },
5009     { Xalpha_z,                 EL_CHAR('Z')                    },
5010     { Xalpha_arrow_e,           EL_CHAR('>')                    },
5011     { Xalpha_arrow_w,           EL_CHAR('<')                    },
5012     { Xalpha_copyr,             EL_CHAR('©')                    },
5013
5014     { Zplayer,                  EL_PLAYER_1                     },
5015     { Zplayer,                  EL_PLAYER_2                     },
5016     { Zplayer,                  EL_PLAYER_3                     },
5017     { Zplayer,                  EL_PLAYER_4                     },
5018
5019     { ZBORDER,                  EL_EMC_LEVEL_BORDER             },
5020
5021     { -1,                       -1                              }
5022   };
5023
5024   if (!mapping_initialized)
5025   {
5026     int i;
5027
5028     /* return "Xalpha_quest" for all undefined elements in mapping array */
5029     for (i = 0; i < NUM_FILE_ELEMENTS; i++)
5030       mapping_RND_to_EM[i] = Xalpha_quest;
5031
5032     for (i = 0; mapping_RND_to_EM_list[i].element_rnd != -1; i++)
5033       mapping_RND_to_EM[mapping_RND_to_EM_list[i].element_rnd] =
5034         mapping_RND_to_EM_list[i].element_em;
5035
5036     mapping_initialized = TRUE;
5037   }
5038
5039   if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
5040     return mapping_RND_to_EM[element_rnd];
5041
5042   Error(ERR_WARN, "invalid RND level element %d", element_rnd);
5043
5044   return EL_UNKNOWN;
5045 }
5046
5047 int map_element_EM_to_RND(int element_em)
5048 {
5049   static unsigned short mapping_EM_to_RND[TILE_MAX];
5050   static boolean mapping_initialized = FALSE;
5051
5052   struct
5053   {
5054     int element_em;
5055     int element_rnd;
5056   }
5057   em_object_mapping_list[] =
5058   {
5059     { Xblank,                   EL_EMPTY                        },
5060     { Yacid_splash_eB,          EL_EMPTY                        },
5061     { Yacid_splash_wB,          EL_EMPTY                        },
5062
5063 #ifdef EM_ENGINE_BAD_ROLL
5064     { Xstone_force_e,           EL_ROCK                         },
5065     { Xstone_force_w,           EL_ROCK                         },
5066     { Xnut_force_e,             EL_NUT                          },
5067     { Xnut_force_w,             EL_NUT                          },
5068     { Xspring_force_e,          EL_SPRING                       },
5069     { Xspring_force_w,          EL_SPRING                       },
5070     { Xemerald_force_e,         EL_EMERALD                      },
5071     { Xemerald_force_w,         EL_EMERALD                      },
5072     { Xdiamond_force_e,         EL_DIAMOND                      },
5073     { Xdiamond_force_w,         EL_DIAMOND                      },
5074     { Xbomb_force_e,            EL_BOMB                         },
5075     { Xbomb_force_w,            EL_BOMB                         },
5076 #endif
5077
5078     { Xstone,                   EL_ROCK                         },
5079     { Xstone_pause,             EL_ROCK                         },
5080     { Xstone_fall,              EL_ROCK                         },
5081     { Ystone_s,                 EL_ROCK                         },
5082     { Ystone_sB,                EL_ROCK                         },
5083     { Ystone_e,                 EL_ROCK                         },
5084     { Ystone_eB,                EL_ROCK                         },
5085     { Ystone_w,                 EL_ROCK                         },
5086     { Ystone_wB,                EL_ROCK                         },
5087     { Xnut,                     EL_NUT                          },
5088     { Xnut_pause,               EL_NUT                          },
5089     { Xnut_fall,                EL_NUT                          },
5090     { Ynut_s,                   EL_NUT                          },
5091     { Ynut_sB,                  EL_NUT                          },
5092     { Ynut_e,                   EL_NUT                          },
5093     { Ynut_eB,                  EL_NUT                          },
5094     { Ynut_w,                   EL_NUT                          },
5095     { Ynut_wB,                  EL_NUT                          },
5096     { Xbug_n,                   EL_BUG_UP                       },
5097     { Xbug_e,                   EL_BUG_RIGHT                    },
5098     { Xbug_s,                   EL_BUG_DOWN                     },
5099     { Xbug_w,                   EL_BUG_LEFT                     },
5100     { Xbug_gon,                 EL_BUG_UP                       },
5101     { Xbug_goe,                 EL_BUG_RIGHT                    },
5102     { Xbug_gos,                 EL_BUG_DOWN                     },
5103     { Xbug_gow,                 EL_BUG_LEFT                     },
5104     { Ybug_n,                   EL_BUG_UP                       },
5105     { Ybug_nB,                  EL_BUG_UP                       },
5106     { Ybug_e,                   EL_BUG_RIGHT                    },
5107     { Ybug_eB,                  EL_BUG_RIGHT                    },
5108     { Ybug_s,                   EL_BUG_DOWN                     },
5109     { Ybug_sB,                  EL_BUG_DOWN                     },
5110     { Ybug_w,                   EL_BUG_LEFT                     },
5111     { Ybug_wB,                  EL_BUG_LEFT                     },
5112     { Ybug_w_n,                 EL_BUG_UP                       },
5113     { Ybug_n_e,                 EL_BUG_RIGHT                    },
5114     { Ybug_e_s,                 EL_BUG_DOWN                     },
5115     { Ybug_s_w,                 EL_BUG_LEFT                     },
5116     { Ybug_e_n,                 EL_BUG_UP                       },
5117     { Ybug_s_e,                 EL_BUG_RIGHT                    },
5118     { Ybug_w_s,                 EL_BUG_DOWN                     },
5119     { Ybug_n_w,                 EL_BUG_LEFT                     },
5120     { Ybug_stone,               EL_ROCK                         },
5121     { Ybug_spring,              EL_SPRING                       },
5122     { Xtank_n,                  EL_SPACESHIP_UP                 },
5123     { Xtank_e,                  EL_SPACESHIP_RIGHT              },
5124     { Xtank_s,                  EL_SPACESHIP_DOWN               },
5125     { Xtank_w,                  EL_SPACESHIP_LEFT               },
5126     { Xtank_gon,                EL_SPACESHIP_UP                 },
5127     { Xtank_goe,                EL_SPACESHIP_RIGHT              },
5128     { Xtank_gos,                EL_SPACESHIP_DOWN               },
5129     { Xtank_gow,                EL_SPACESHIP_LEFT               },
5130     { Ytank_n,                  EL_SPACESHIP_UP                 },
5131     { Ytank_nB,                 EL_SPACESHIP_UP                 },
5132     { Ytank_e,                  EL_SPACESHIP_RIGHT              },
5133     { Ytank_eB,                 EL_SPACESHIP_RIGHT              },
5134     { Ytank_s,                  EL_SPACESHIP_DOWN               },
5135     { Ytank_sB,                 EL_SPACESHIP_DOWN               },
5136     { Ytank_w,                  EL_SPACESHIP_LEFT               },
5137     { Ytank_wB,                 EL_SPACESHIP_LEFT               },
5138     { Ytank_w_n,                EL_SPACESHIP_UP                 },
5139     { Ytank_n_e,                EL_SPACESHIP_RIGHT              },
5140     { Ytank_e_s,                EL_SPACESHIP_DOWN               },
5141     { Ytank_s_w,                EL_SPACESHIP_LEFT               },
5142     { Ytank_e_n,                EL_SPACESHIP_UP                 },
5143     { Ytank_s_e,                EL_SPACESHIP_RIGHT              },
5144     { Ytank_w_s,                EL_SPACESHIP_DOWN               },
5145     { Ytank_n_w,                EL_SPACESHIP_LEFT               },
5146     { Ytank_stone,              EL_ROCK                         },
5147     { Ytank_spring,             EL_SPRING                       },
5148     { Xandroid,                 EL_EMC_ANDROID                  },
5149     { Xandroid_1_n,             EL_EMC_ANDROID_UP               },
5150     { Xandroid_2_n,             EL_EMC_ANDROID_UP               },
5151     { Xandroid_1_e,             EL_EMC_ANDROID_RIGHT            },
5152     { Xandroid_2_e,             EL_EMC_ANDROID_RIGHT            },
5153     { Xandroid_1_w,             EL_EMC_ANDROID_LEFT             },
5154     { Xandroid_2_w,             EL_EMC_ANDROID_LEFT             },
5155     { Xandroid_1_s,             EL_EMC_ANDROID_DOWN             },
5156     { Xandroid_2_s,             EL_EMC_ANDROID_DOWN             },
5157     { Yandroid_n,               EL_EMC_ANDROID_UP               },
5158     { Yandroid_nB,              EL_EMC_ANDROID_UP               },
5159     { Yandroid_ne,              EL_EMC_ANDROID_RIGHT_UP         },
5160     { Yandroid_neB,             EL_EMC_ANDROID_RIGHT_UP         },
5161     { Yandroid_e,               EL_EMC_ANDROID_RIGHT            },
5162     { Yandroid_eB,              EL_EMC_ANDROID_RIGHT            },
5163     { Yandroid_se,              EL_EMC_ANDROID_RIGHT_DOWN       },
5164     { Yandroid_seB,             EL_EMC_ANDROID_RIGHT_DOWN       },
5165     { Yandroid_s,               EL_EMC_ANDROID_DOWN             },
5166     { Yandroid_sB,              EL_EMC_ANDROID_DOWN             },
5167     { Yandroid_sw,              EL_EMC_ANDROID_LEFT_DOWN        },
5168     { Yandroid_swB,             EL_EMC_ANDROID_LEFT_DOWN        },
5169     { Yandroid_w,               EL_EMC_ANDROID_LEFT             },
5170     { Yandroid_wB,              EL_EMC_ANDROID_LEFT             },
5171     { Yandroid_nw,              EL_EMC_ANDROID_LEFT_UP          },
5172     { Yandroid_nwB,             EL_EMC_ANDROID_LEFT_UP          },
5173     { Xspring,                  EL_SPRING                       },
5174     { Xspring_pause,            EL_SPRING                       },
5175     { Xspring_e,                EL_SPRING                       },
5176     { Xspring_w,                EL_SPRING                       },
5177     { Xspring_fall,             EL_SPRING                       },
5178     { Yspring_s,                EL_SPRING                       },
5179     { Yspring_sB,               EL_SPRING                       },
5180     { Yspring_e,                EL_SPRING                       },
5181     { Yspring_eB,               EL_SPRING                       },
5182     { Yspring_w,                EL_SPRING                       },
5183     { Yspring_wB,               EL_SPRING                       },
5184     { Yspring_kill_e,           EL_SPRING                       },
5185     { Yspring_kill_eB,          EL_SPRING                       },
5186     { Yspring_kill_w,           EL_SPRING                       },
5187     { Yspring_kill_wB,          EL_SPRING                       },
5188     { Xeater_n,                 EL_YAMYAM                       },
5189     { Xeater_e,                 EL_YAMYAM                       },
5190     { Xeater_w,                 EL_YAMYAM                       },
5191     { Xeater_s,                 EL_YAMYAM                       },
5192     { Yeater_n,                 EL_YAMYAM                       },
5193     { Yeater_nB,                EL_YAMYAM                       },
5194     { Yeater_e,                 EL_YAMYAM                       },
5195     { Yeater_eB,                EL_YAMYAM                       },
5196     { Yeater_s,                 EL_YAMYAM                       },
5197     { Yeater_sB,                EL_YAMYAM                       },
5198     { Yeater_w,                 EL_YAMYAM                       },
5199     { Yeater_wB,                EL_YAMYAM                       },
5200     { Yeater_stone,             EL_ROCK                         },
5201     { Yeater_spring,            EL_SPRING                       },
5202     { Xalien,                   EL_ROBOT                        },
5203     { Xalien_pause,             EL_ROBOT                        },
5204     { Yalien_n,                 EL_ROBOT                        },
5205     { Yalien_nB,                EL_ROBOT                        },
5206     { Yalien_e,                 EL_ROBOT                        },
5207     { Yalien_eB,                EL_ROBOT                        },
5208     { Yalien_s,                 EL_ROBOT                        },
5209     { Yalien_sB,                EL_ROBOT                        },
5210     { Yalien_w,                 EL_ROBOT                        },
5211     { Yalien_wB,                EL_ROBOT                        },
5212     { Yalien_stone,             EL_ROCK                         },
5213     { Yalien_spring,            EL_SPRING                       },
5214     { Xemerald,                 EL_EMERALD                      },
5215     { Xemerald_pause,           EL_EMERALD                      },
5216     { Xemerald_fall,            EL_EMERALD                      },
5217     { Xemerald_shine,           EL_EMERALD                      },
5218     { Yemerald_s,               EL_EMERALD                      },
5219     { Yemerald_sB,              EL_EMERALD                      },
5220     { Yemerald_e,               EL_EMERALD                      },
5221     { Yemerald_eB,              EL_EMERALD                      },
5222     { Yemerald_w,               EL_EMERALD                      },
5223     { Yemerald_wB,              EL_EMERALD                      },
5224     { Yemerald_eat,             EL_EMERALD                      },
5225     { Yemerald_stone,           EL_ROCK                         },
5226     { Xdiamond,                 EL_DIAMOND                      },
5227     { Xdiamond_pause,           EL_DIAMOND                      },
5228     { Xdiamond_fall,            EL_DIAMOND                      },
5229     { Xdiamond_shine,           EL_DIAMOND                      },
5230     { Ydiamond_s,               EL_DIAMOND                      },
5231     { Ydiamond_sB,              EL_DIAMOND                      },
5232     { Ydiamond_e,               EL_DIAMOND                      },
5233     { Ydiamond_eB,              EL_DIAMOND                      },
5234     { Ydiamond_w,               EL_DIAMOND                      },
5235     { Ydiamond_wB,              EL_DIAMOND                      },
5236     { Ydiamond_eat,             EL_DIAMOND                      },
5237     { Ydiamond_stone,           EL_ROCK                         },
5238     { Xdrip_fall,               EL_AMOEBA_DROP                  },
5239     { Xdrip_stretch,            EL_AMOEBA_DROP                  },
5240     { Xdrip_stretchB,           EL_AMOEBA_DROP                  },
5241     { Xdrip_eat,                EL_AMOEBA_DROP                  },
5242     { Ydrip_s1,                 EL_AMOEBA_DROP                  },
5243     { Ydrip_s1B,                EL_AMOEBA_DROP                  },
5244     { Ydrip_s2,                 EL_AMOEBA_DROP                  },
5245     { Ydrip_s2B,                EL_AMOEBA_DROP                  },
5246     { Xbomb,                    EL_BOMB                         },
5247     { Xbomb_pause,              EL_BOMB                         },
5248     { Xbomb_fall,               EL_BOMB                         },
5249     { Ybomb_s,                  EL_BOMB                         },
5250     { Ybomb_sB,                 EL_BOMB                         },
5251     { Ybomb_e,                  EL_BOMB                         },
5252     { Ybomb_eB,                 EL_BOMB                         },
5253     { Ybomb_w,                  EL_BOMB                         },
5254     { Ybomb_wB,                 EL_BOMB                         },
5255     { Ybomb_eat,                EL_BOMB                         },
5256     { Xballoon,                 EL_BALLOON                      },
5257     { Yballoon_n,               EL_BALLOON                      },
5258     { Yballoon_nB,              EL_BALLOON                      },
5259     { Yballoon_e,               EL_BALLOON                      },
5260     { Yballoon_eB,              EL_BALLOON                      },
5261     { Yballoon_s,               EL_BALLOON                      },
5262     { Yballoon_sB,              EL_BALLOON                      },
5263     { Yballoon_w,               EL_BALLOON                      },
5264     { Yballoon_wB,              EL_BALLOON                      },
5265     { Xgrass,                   EL_SAND                         },
5266     { Ygrass_nB,                EL_SAND                         },
5267     { Ygrass_eB,                EL_SAND                         },
5268     { Ygrass_sB,                EL_SAND                         },
5269     { Ygrass_wB,                EL_SAND                         },
5270     { Xdirt,                    EL_SAND                         },
5271     { Ydirt_nB,                 EL_SAND                         },
5272     { Ydirt_eB,                 EL_SAND                         },
5273     { Ydirt_sB,                 EL_SAND                         },
5274     { Ydirt_wB,                 EL_SAND                         },
5275     { Xacid_ne,                 EL_ACID_POOL_TOPRIGHT           },
5276     { Xacid_se,                 EL_ACID_POOL_BOTTOMRIGHT        },
5277     { Xacid_s,                  EL_ACID_POOL_BOTTOM             },
5278     { Xacid_sw,                 EL_ACID_POOL_BOTTOMLEFT         },
5279     { Xacid_nw,                 EL_ACID_POOL_TOPLEFT            },
5280     { Xacid_1,                  EL_ACID                         },
5281     { Xacid_2,                  EL_ACID                         },
5282     { Xacid_3,                  EL_ACID                         },
5283     { Xacid_4,                  EL_ACID                         },
5284     { Xacid_5,                  EL_ACID                         },
5285     { Xacid_6,                  EL_ACID                         },
5286     { Xacid_7,                  EL_ACID                         },
5287     { Xacid_8,                  EL_ACID                         },
5288     { Xball_1,                  EL_EMC_MAGIC_BALL               },
5289     { Xball_1B,                 EL_EMC_MAGIC_BALL               },
5290     { Xball_2,                  EL_EMC_MAGIC_BALL               },
5291     { Xball_2B,                 EL_EMC_MAGIC_BALL               },
5292     { Yball_eat,                EL_EMC_MAGIC_BALL               },
5293     { Xgrow_ns,                 EL_EMC_GROW                     },
5294     { Ygrow_ns_eat,             EL_EMC_GROW                     },
5295     { Xgrow_ew,                 EL_EMC_GROW                     },
5296     { Ygrow_ew_eat,             EL_EMC_GROW                     },
5297     { Xwonderwall,              EL_MAGIC_WALL                   },
5298     { XwonderwallB,             EL_MAGIC_WALL                   },
5299     { Xamoeba_1,                EL_AMOEBA_WET                   },
5300     { Xamoeba_2,                EL_AMOEBA_WET                   },
5301     { Xamoeba_3,                EL_AMOEBA_WET                   },
5302     { Xamoeba_4,                EL_AMOEBA_WET                   },
5303     { Xamoeba_5,                EL_AMOEBA_WET                   },
5304     { Xamoeba_6,                EL_AMOEBA_WET                   },
5305     { Xamoeba_7,                EL_AMOEBA_WET                   },
5306     { Xamoeba_8,                EL_AMOEBA_WET                   },
5307     { Xdoor_1,                  EL_EM_GATE_1                    },
5308     { Xdoor_2,                  EL_EM_GATE_2                    },
5309     { Xdoor_3,                  EL_EM_GATE_3                    },
5310     { Xdoor_4,                  EL_EM_GATE_4                    },
5311     { Xdoor_5,                  EL_EMC_GATE_5                   },
5312     { Xdoor_6,                  EL_EMC_GATE_6                   },
5313     { Xdoor_7,                  EL_EMC_GATE_7                   },
5314     { Xdoor_8,                  EL_EMC_GATE_8                   },
5315     { Xkey_1,                   EL_EM_KEY_1                     },
5316     { Xkey_2,                   EL_EM_KEY_2                     },
5317     { Xkey_3,                   EL_EM_KEY_3                     },
5318     { Xkey_4,                   EL_EM_KEY_4                     },
5319     { Xkey_5,                   EL_EMC_KEY_5                    },
5320     { Xkey_6,                   EL_EMC_KEY_6                    },
5321     { Xkey_7,                   EL_EMC_KEY_7                    },
5322     { Xkey_8,                   EL_EMC_KEY_8                    },
5323     { Xwind_n,                  EL_BALLOON_SWITCH_UP            },
5324     { Xwind_e,                  EL_BALLOON_SWITCH_RIGHT         },
5325     { Xwind_s,                  EL_BALLOON_SWITCH_DOWN          },
5326     { Xwind_w,                  EL_BALLOON_SWITCH_LEFT          },
5327     { Xwind_nesw,               EL_BALLOON_SWITCH_ANY           },
5328     { Xwind_stop,               EL_BALLOON_SWITCH_NONE          },
5329     { Xexit,                    EL_EXIT_CLOSED                  },
5330     { Xexit_1,                  EL_EXIT_OPEN                    },
5331     { Xexit_2,                  EL_EXIT_OPEN                    },
5332     { Xexit_3,                  EL_EXIT_OPEN                    },
5333     { Xdynamite,                EL_DYNAMITE                     },
5334     { Ydynamite_eat,            EL_DYNAMITE                     },
5335     { Xdynamite_1,              EL_DYNAMITE_ACTIVE              },
5336     { Xdynamite_2,              EL_DYNAMITE_ACTIVE              },
5337     { Xdynamite_3,              EL_DYNAMITE_ACTIVE              },
5338     { Xdynamite_4,              EL_DYNAMITE_ACTIVE              },
5339     { Xbumper,                  EL_EMC_BUMPER                   },
5340     { XbumperB,                 EL_EMC_BUMPER                   },
5341     { Xwheel,                   EL_ROBOT_WHEEL                  },
5342     { XwheelB,                  EL_ROBOT_WHEEL                  },
5343     { Xswitch,                  EL_UNKNOWN                      },
5344     { XswitchB,                 EL_UNKNOWN                      },
5345     { Xsand,                    EL_QUICKSAND_EMPTY              },
5346     { Xsand_stone,              EL_QUICKSAND_FULL               },
5347     { Xsand_stonein_1,          EL_QUICKSAND_FULL               },
5348     { Xsand_stonein_2,          EL_QUICKSAND_FULL               },
5349     { Xsand_stonein_3,          EL_QUICKSAND_FULL               },
5350     { Xsand_stonein_4,          EL_QUICKSAND_FULL               },
5351     { Xsand_stonesand_1,        EL_QUICKSAND_FULL               },
5352     { Xsand_stonesand_2,        EL_QUICKSAND_FULL               },
5353     { Xsand_stonesand_3,        EL_QUICKSAND_FULL               },
5354     { Xsand_stonesand_4,        EL_QUICKSAND_FULL               },
5355     { Xsand_stoneout_1,         EL_QUICKSAND_FULL               },
5356     { Xsand_stoneout_2,         EL_QUICKSAND_FULL               },
5357     { Xsand_sandstone_1,        EL_QUICKSAND_FULL               },
5358     { Xsand_sandstone_2,        EL_QUICKSAND_FULL               },
5359     { Xsand_sandstone_3,        EL_QUICKSAND_FULL               },
5360     { Xsand_sandstone_4,        EL_QUICKSAND_FULL               },
5361     { Xplant,                   EL_EMC_PLANT                    },
5362     { Yplant,                   EL_EMC_PLANT                    },
5363     { Xlenses,                  EL_EMC_LENSES                   },
5364     { Xmagnify,                 EL_EMC_MAGNIFIER                },
5365     { Xdripper,                 EL_UNKNOWN                      },
5366     { XdripperB,                EL_UNKNOWN                      },
5367     { Xfake_blank,              EL_INVISIBLE_WALL               },
5368     { Xfake_blankB,             EL_INVISIBLE_WALL               },
5369     { Xfake_grass,              EL_INVISIBLE_SAND               },
5370     { Xfake_grassB,             EL_INVISIBLE_SAND               },
5371     { Xfake_door_1,             EL_EM_GATE_1_GRAY               },
5372     { Xfake_door_2,             EL_EM_GATE_2_GRAY               },
5373     { Xfake_door_3,             EL_EM_GATE_3_GRAY               },
5374     { Xfake_door_4,             EL_EM_GATE_4_GRAY               },
5375     { Xfake_door_5,             EL_EMC_GATE_5_GRAY              },
5376     { Xfake_door_6,             EL_EMC_GATE_6_GRAY              },
5377     { Xfake_door_7,             EL_EMC_GATE_7_GRAY              },
5378     { Xfake_door_8,             EL_EMC_GATE_8_GRAY              },
5379     { Xsteel_1,                 EL_STEELWALL                    },
5380     { Xsteel_2,                 EL_UNKNOWN                      },
5381     { Xsteel_3,                 EL_EMC_STEELWALL_1              },
5382     { Xsteel_4,                 EL_UNKNOWN                      },
5383     { Xwall_1,                  EL_WALL                         },
5384     { Xwall_2,                  EL_UNKNOWN                      },
5385     { Xwall_3,                  EL_UNKNOWN                      },
5386     { Xwall_4,                  EL_UNKNOWN                      },
5387     { Xround_wall_1,            EL_WALL_SLIPPERY                },
5388     { Xround_wall_2,            EL_UNKNOWN                      },
5389     { Xround_wall_3,            EL_UNKNOWN                      },
5390     { Xround_wall_4,            EL_UNKNOWN                      },
5391     { Xdecor_1,                 EL_UNKNOWN                      },
5392     { Xdecor_2,                 EL_EMC_WALL_6                   },
5393     { Xdecor_3,                 EL_EMC_WALL_4                   },
5394     { Xdecor_4,                 EL_EMC_WALL_5                   },
5395     { Xdecor_5,                 EL_EMC_WALL_7                   },
5396     { Xdecor_6,                 EL_EMC_WALL_8                   },
5397     { Xdecor_7,                 EL_UNKNOWN                      },
5398     { Xdecor_8,                 EL_EMC_WALL_1                   },
5399     { Xdecor_9,                 EL_EMC_WALL_2                   },
5400     { Xdecor_10,                EL_EMC_WALL_3                   },
5401     { Xdecor_11,                EL_UNKNOWN                      },
5402     { Xdecor_12,                EL_UNKNOWN                      },
5403     { Xalpha_0,                 EL_CHAR('0')                    },
5404     { Xalpha_1,                 EL_CHAR('1')                    },
5405     { Xalpha_2,                 EL_CHAR('2')                    },
5406     { Xalpha_3,                 EL_CHAR('3')                    },
5407     { Xalpha_4,                 EL_CHAR('4')                    },
5408     { Xalpha_5,                 EL_CHAR('5')                    },
5409     { Xalpha_6,                 EL_CHAR('6')                    },
5410     { Xalpha_7,                 EL_CHAR('7')                    },
5411     { Xalpha_8,                 EL_CHAR('8')                    },
5412     { Xalpha_9,                 EL_CHAR('9')                    },
5413     { Xalpha_excla,             EL_CHAR('!')                    },
5414     { Xalpha_quote,             EL_CHAR('"')                    },
5415     { Xalpha_comma,             EL_CHAR(',')                    },
5416     { Xalpha_minus,             EL_CHAR('-')                    },
5417     { Xalpha_perio,             EL_CHAR('.')                    },
5418     { Xalpha_colon,             EL_CHAR(':')                    },
5419     { Xalpha_quest,             EL_CHAR('?')                    },
5420     { Xalpha_a,                 EL_CHAR('A')                    },
5421     { Xalpha_b,                 EL_CHAR('B')                    },
5422     { Xalpha_c,                 EL_CHAR('C')                    },
5423     { Xalpha_d,                 EL_CHAR('D')                    },
5424     { Xalpha_e,                 EL_CHAR('E')                    },
5425     { Xalpha_f,                 EL_CHAR('F')                    },
5426     { Xalpha_g,                 EL_CHAR('G')                    },
5427     { Xalpha_h,                 EL_CHAR('H')                    },
5428     { Xalpha_i,                 EL_CHAR('I')                    },
5429     { Xalpha_j,                 EL_CHAR('J')                    },
5430     { Xalpha_k,                 EL_CHAR('K')                    },
5431     { Xalpha_l,                 EL_CHAR('L')                    },
5432     { Xalpha_m,                 EL_CHAR('M')                    },
5433     { Xalpha_n,                 EL_CHAR('N')                    },
5434     { Xalpha_o,                 EL_CHAR('O')                    },
5435     { Xalpha_p,                 EL_CHAR('P')                    },
5436     { Xalpha_q,                 EL_CHAR('Q')                    },
5437     { Xalpha_r,                 EL_CHAR('R')                    },
5438     { Xalpha_s,                 EL_CHAR('S')                    },
5439     { Xalpha_t,                 EL_CHAR('T')                    },
5440     { Xalpha_u,                 EL_CHAR('U')                    },
5441     { Xalpha_v,                 EL_CHAR('V')                    },
5442     { Xalpha_w,                 EL_CHAR('W')                    },
5443     { Xalpha_x,                 EL_CHAR('X')                    },
5444     { Xalpha_y,                 EL_CHAR('Y')                    },
5445     { Xalpha_z,                 EL_CHAR('Z')                    },
5446     { Xalpha_arrow_e,           EL_CHAR('>')                    },
5447     { Xalpha_arrow_w,           EL_CHAR('<')                    },
5448     { Xalpha_copyr,             EL_CHAR('©')                    },
5449
5450     { Zplayer,                  EL_PLAYER_1                     },
5451
5452     { ZBORDER,                  EL_EMC_LEVEL_BORDER             },
5453
5454     { -1,                       -1                              }
5455   };
5456
5457   if (!mapping_initialized)
5458   {
5459     int i;
5460
5461     /* return "EL_UNKNOWN" for all undefined elements in mapping array */
5462     for (i = 0; i < TILE_MAX; i++)
5463       mapping_EM_to_RND[i] = EL_UNKNOWN;
5464
5465     for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
5466       mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
5467         em_object_mapping_list[i].element_rnd;
5468
5469     mapping_initialized = TRUE;
5470   }
5471
5472   if (element_em >= 0 && element_em < TILE_MAX)
5473     return mapping_EM_to_RND[element_em];
5474
5475   Error(ERR_WARN, "invalid EM level element %d", element_em);
5476
5477   return EL_UNKNOWN;
5478 }
5479
5480 #endif
5481
5482 int get_next_element(int element)
5483 {
5484   switch(element)
5485   {
5486     case EL_QUICKSAND_FILLING:          return EL_QUICKSAND_FULL;
5487     case EL_QUICKSAND_EMPTYING:         return EL_QUICKSAND_EMPTY;
5488     case EL_MAGIC_WALL_FILLING:         return EL_MAGIC_WALL_FULL;
5489     case EL_MAGIC_WALL_EMPTYING:        return EL_MAGIC_WALL_ACTIVE;
5490     case EL_BD_MAGIC_WALL_FILLING:      return EL_BD_MAGIC_WALL_FULL;
5491     case EL_BD_MAGIC_WALL_EMPTYING:     return EL_BD_MAGIC_WALL_ACTIVE;
5492     case EL_AMOEBA_DROPPING:            return EL_AMOEBA_WET;
5493
5494     default:                            return element;
5495   }
5496 }
5497
5498 #if 0
5499 int el_act_dir2img(int element, int action, int direction)
5500 {
5501   element = GFX_ELEMENT(element);
5502
5503   if (direction == MV_NO_MOVING)
5504     return element_info[element].graphic[action];
5505
5506   direction = MV_DIR_BIT(direction);
5507
5508   return element_info[element].direction_graphic[action][direction];
5509 }
5510 #else
5511 int el_act_dir2img(int element, int action, int direction)
5512 {
5513   element = GFX_ELEMENT(element);
5514   direction = MV_DIR_BIT(direction);    /* default: MV_NO_MOVING => MV_DOWN */
5515
5516   /* direction_graphic[][] == graphic[] for undefined direction graphics */
5517   return element_info[element].direction_graphic[action][direction];
5518 }
5519 #endif
5520
5521 #if 0
5522 static int el_act_dir2crm(int element, int action, int direction)
5523 {
5524   element = GFX_ELEMENT(element);
5525
5526   if (direction == MV_NO_MOVING)
5527     return element_info[element].crumbled[action];
5528
5529   direction = MV_DIR_BIT(direction);
5530
5531   return element_info[element].direction_crumbled[action][direction];
5532 }
5533 #else
5534 static int el_act_dir2crm(int element, int action, int direction)
5535 {
5536   element = GFX_ELEMENT(element);
5537   direction = MV_DIR_BIT(direction);    /* default: MV_NO_MOVING => MV_DOWN */
5538
5539   /* direction_graphic[][] == graphic[] for undefined direction graphics */
5540   return element_info[element].direction_crumbled[action][direction];
5541 }
5542 #endif
5543
5544 int el_act2img(int element, int action)
5545 {
5546   element = GFX_ELEMENT(element);
5547
5548   return element_info[element].graphic[action];
5549 }
5550
5551 int el_act2crm(int element, int action)
5552 {
5553   element = GFX_ELEMENT(element);
5554
5555   return element_info[element].crumbled[action];
5556 }
5557
5558 int el_dir2img(int element, int direction)
5559 {
5560   element = GFX_ELEMENT(element);
5561
5562   return el_act_dir2img(element, ACTION_DEFAULT, direction);
5563 }
5564
5565 int el2baseimg(int element)
5566 {
5567   return element_info[element].graphic[ACTION_DEFAULT];
5568 }
5569
5570 int el2img(int element)
5571 {
5572   element = GFX_ELEMENT(element);
5573
5574   return element_info[element].graphic[ACTION_DEFAULT];
5575 }
5576
5577 int el2edimg(int element)
5578 {
5579   element = GFX_ELEMENT(element);
5580
5581   return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
5582 }
5583
5584 int el2preimg(int element)
5585 {
5586   element = GFX_ELEMENT(element);
5587
5588   return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
5589 }
5590
5591 int getGameFrameDelay_EM(int native_em_game_frame_delay)
5592 {
5593   return (GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
5594           GameFrameDelay);
5595 }
5596
5597 unsigned int InitRND(long seed)
5598 {
5599   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
5600     return InitEngineRND_EM(seed);
5601   else
5602     return InitEngineRND(seed);
5603 }
5604
5605 #define DEBUG_EM_GFX    0
5606
5607 void InitGraphicInfo_EM(void)
5608 {
5609   struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
5610   struct Mapping_EM_to_RND_player player_mapping[2][SPR_MAX];
5611   int i, j, p;
5612
5613 #if DEBUG_EM_GFX
5614   if (graphic_info_em_object[0][0].bitmap == NULL)
5615   {
5616     /* EM graphics not yet initialized in em_open_all() */
5617
5618     return;
5619   }
5620 #endif
5621
5622   /* always start with reliable default values */
5623   for (i = 0; i < TILE_MAX; i++)
5624   {
5625     object_mapping[i].element_rnd = EL_UNKNOWN;
5626     object_mapping[i].is_backside = FALSE;
5627     object_mapping[i].action = ACTION_DEFAULT;
5628     object_mapping[i].direction = MV_NO_MOVING;
5629   }
5630
5631   /* always start with reliable default values */
5632   for (p = 0; p < 2; p++)
5633   {
5634     for (i = 0; i < SPR_MAX; i++)
5635     {
5636       player_mapping[p][i].element_rnd = EL_UNKNOWN;
5637       player_mapping[p][i].action = ACTION_DEFAULT;
5638       player_mapping[p][i].direction = MV_NO_MOVING;
5639     }
5640   }
5641
5642   for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
5643   {
5644     int e = em_object_mapping_list[i].element_em;
5645
5646     object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
5647     object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
5648
5649     if (em_object_mapping_list[i].action != -1)
5650       object_mapping[e].action = em_object_mapping_list[i].action;
5651
5652     if (em_object_mapping_list[i].direction != -1)
5653       object_mapping[e].direction = (1 << em_object_mapping_list[i].direction);
5654   }
5655
5656   for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
5657   {
5658     int a = em_player_mapping_list[i].action_em;
5659     int p = em_player_mapping_list[i].player_nr;
5660
5661     player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
5662
5663     if (em_player_mapping_list[i].action != -1)
5664       player_mapping[p][a].action = em_player_mapping_list[i].action;
5665
5666     if (em_player_mapping_list[i].direction != -1)
5667       player_mapping[p][a].direction =
5668         (1 << em_player_mapping_list[i].direction);
5669   }
5670
5671   for (i = 0; i < TILE_MAX; i++)
5672   {
5673     int element = object_mapping[i].element_rnd;
5674     int action = object_mapping[i].action;
5675     int direction = object_mapping[i].direction;
5676     boolean is_backside = object_mapping[i].is_backside;
5677     boolean action_removing = (action == ACTION_DIGGING ||
5678                                action == ACTION_SNAPPING ||
5679                                action == ACTION_COLLECTING);
5680     boolean action_exploding = ((action == ACTION_EXPLODING ||
5681                                  action == ACTION_SMASHED_BY_ROCK ||
5682                                  action == ACTION_SMASHED_BY_SPRING) &&
5683                                 element != EL_DIAMOND);
5684     boolean action_active = (action == ACTION_ACTIVE);
5685     boolean action_other = (action == ACTION_OTHER);
5686
5687     for (j = 0; j < 8; j++)
5688     {
5689       int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
5690                                j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
5691                                j < 7 ? element :
5692                                i == Xdrip_stretch ? element :
5693                                i == Xdrip_stretchB ? element :
5694                                i == Ydrip_s1 ? element :
5695                                i == Ydrip_s1B ? element :
5696                                i == Xball_1B ? element :
5697                                i == Xball_2 ? element :
5698                                i == Xball_2B ? element :
5699                                i == Yball_eat ? element :
5700                                i == Ykey_1_eat ? element :
5701                                i == Ykey_2_eat ? element :
5702                                i == Ykey_3_eat ? element :
5703                                i == Ykey_4_eat ? element :
5704                                i == Ykey_5_eat ? element :
5705                                i == Ykey_6_eat ? element :
5706                                i == Ykey_7_eat ? element :
5707                                i == Ykey_8_eat ? element :
5708                                i == Ylenses_eat ? element :
5709                                i == Ymagnify_eat ? element :
5710                                i == Ygrass_eat ? element :
5711                                i == Ydirt_eat ? element :
5712                                i == Yspring_kill_e ? EL_SPRING :
5713                                i == Yspring_kill_w ? EL_SPRING :
5714                                i == Yemerald_stone ? EL_EMERALD :
5715                                i == Ydiamond_stone ? EL_ROCK :
5716                                i == Xsand_stonein_4 ? EL_EMPTY :
5717                                i == Xsand_stoneout_2 ? EL_ROCK :
5718                                is_backside ? EL_EMPTY :
5719                                action_removing ? EL_EMPTY :
5720                                element);
5721       int effective_action = (j < 7 ? action :
5722                               i == Xdrip_stretch ? action :
5723                               i == Xdrip_stretchB ? action :
5724                               i == Ydrip_s1 ? action :
5725                               i == Ydrip_s1B ? action :
5726                               i == Xball_1B ? action :
5727                               i == Xball_2 ? action :
5728                               i == Xball_2B ? action :
5729                               i == Yball_eat ? action :
5730                               i == Ykey_1_eat ? action :
5731                               i == Ykey_2_eat ? action :
5732                               i == Ykey_3_eat ? action :
5733                               i == Ykey_4_eat ? action :
5734                               i == Ykey_5_eat ? action :
5735                               i == Ykey_6_eat ? action :
5736                               i == Ykey_7_eat ? action :
5737                               i == Ykey_8_eat ? action :
5738                               i == Ylenses_eat ? action :
5739                               i == Ymagnify_eat ? action :
5740                               i == Ygrass_eat ? action :
5741                               i == Ydirt_eat ? action :
5742                               i == Xsand_stonein_1 ? action :
5743                               i == Xsand_stonein_2 ? action :
5744                               i == Xsand_stonein_3 ? action :
5745                               i == Xsand_stonein_4 ? action :
5746                               i == Xsand_stoneout_1 ? action :
5747                               i == Xsand_stoneout_2 ? action :
5748                               i == Xboom_android ? ACTION_EXPLODING :
5749                               action_exploding ? ACTION_EXPLODING :
5750                               action_active ? action :
5751                               action_other ? action :
5752                               ACTION_DEFAULT);
5753       int graphic = (el_act_dir2img(effective_element, effective_action,
5754                                     direction));
5755       int crumbled = (el_act_dir2crm(effective_element, effective_action,
5756                                      direction));
5757       int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
5758       int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
5759       boolean has_crumbled_graphics = (base_crumbled != base_graphic);
5760       struct GraphicInfo *g = &graphic_info[graphic];
5761       struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
5762       Bitmap *src_bitmap;
5763       int src_x, src_y;
5764       /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
5765       boolean special_animation = (action != ACTION_DEFAULT &&
5766                                    g->anim_frames == 3 &&
5767                                    g->anim_delay == 2 &&
5768                                    g->anim_mode & ANIM_LINEAR);
5769       int sync_frame = (i == Xdrip_stretch ? 7 :
5770                         i == Xdrip_stretchB ? 7 :
5771                         i == Ydrip_s2 ? j + 8 :
5772                         i == Ydrip_s2B ? j + 8 :
5773                         i == Xacid_1 ? 0 :
5774                         i == Xacid_2 ? 10 :
5775                         i == Xacid_3 ? 20 :
5776                         i == Xacid_4 ? 30 :
5777                         i == Xacid_5 ? 40 :
5778                         i == Xacid_6 ? 50 :
5779                         i == Xacid_7 ? 60 :
5780                         i == Xacid_8 ? 70 :
5781                         i == Xball_2 ? 7 :
5782                         i == Xball_2B ? j + 8 :
5783                         i == Yball_eat ? j + 1 :
5784                         i == Ykey_1_eat ? j + 1 :
5785                         i == Ykey_2_eat ? j + 1 :
5786                         i == Ykey_3_eat ? j + 1 :
5787                         i == Ykey_4_eat ? j + 1 :
5788                         i == Ykey_5_eat ? j + 1 :
5789                         i == Ykey_6_eat ? j + 1 :
5790                         i == Ykey_7_eat ? j + 1 :
5791                         i == Ykey_8_eat ? j + 1 :
5792                         i == Ylenses_eat ? j + 1 :
5793                         i == Ymagnify_eat ? j + 1 :
5794                         i == Ygrass_eat ? j + 1 :
5795                         i == Ydirt_eat ? j + 1 :
5796                         i == Xamoeba_1 ? 0 :
5797                         i == Xamoeba_2 ? 1 :
5798                         i == Xamoeba_3 ? 2 :
5799                         i == Xamoeba_4 ? 3 :
5800                         i == Xamoeba_5 ? 0 :
5801                         i == Xamoeba_6 ? 1 :
5802                         i == Xamoeba_7 ? 2 :
5803                         i == Xamoeba_8 ? 3 :
5804                         i == Xexit_2 ? j + 8 :
5805                         i == Xexit_3 ? j + 16 :
5806                         i == Xdynamite_1 ? 0 :
5807                         i == Xdynamite_2 ? 20 :
5808                         i == Xdynamite_3 ? 40 :
5809                         i == Xdynamite_4 ? 60 :
5810                         i == Xsand_stonein_1 ? j + 1 :
5811                         i == Xsand_stonein_2 ? j + 9 :
5812                         i == Xsand_stonein_3 ? j + 17 :
5813                         i == Xsand_stonein_4 ? j + 25 :
5814                         i == Xsand_stoneout_1 && j == 0 ? 0 :
5815                         i == Xsand_stoneout_1 && j == 1 ? 0 :
5816                         i == Xsand_stoneout_1 && j == 2 ? 1 :
5817                         i == Xsand_stoneout_1 && j == 3 ? 2 :
5818                         i == Xsand_stoneout_1 && j == 4 ? 2 :
5819                         i == Xsand_stoneout_1 && j == 5 ? 3 :
5820                         i == Xsand_stoneout_1 && j == 6 ? 4 :
5821                         i == Xsand_stoneout_1 && j == 7 ? 4 :
5822                         i == Xsand_stoneout_2 && j == 0 ? 5 :
5823                         i == Xsand_stoneout_2 && j == 1 ? 6 :
5824                         i == Xsand_stoneout_2 && j == 2 ? 7 :
5825                         i == Xsand_stoneout_2 && j == 3 ? 8 :
5826                         i == Xsand_stoneout_2 && j == 4 ? 9 :
5827                         i == Xsand_stoneout_2 && j == 5 ? 11 :
5828                         i == Xsand_stoneout_2 && j == 6 ? 13 :
5829                         i == Xsand_stoneout_2 && j == 7 ? 15 :
5830                         i == Xboom_bug && j == 1 ? 2 :
5831                         i == Xboom_bug && j == 2 ? 2 :
5832                         i == Xboom_bug && j == 3 ? 4 :
5833                         i == Xboom_bug && j == 4 ? 4 :
5834                         i == Xboom_bug && j == 5 ? 2 :
5835                         i == Xboom_bug && j == 6 ? 2 :
5836                         i == Xboom_bug && j == 7 ? 0 :
5837                         i == Xboom_bomb && j == 1 ? 2 :
5838                         i == Xboom_bomb && j == 2 ? 2 :
5839                         i == Xboom_bomb && j == 3 ? 4 :
5840                         i == Xboom_bomb && j == 4 ? 4 :
5841                         i == Xboom_bomb && j == 5 ? 2 :
5842                         i == Xboom_bomb && j == 6 ? 2 :
5843                         i == Xboom_bomb && j == 7 ? 0 :
5844                         i == Xboom_android && j == 7 ? 6 :
5845                         i == Xboom_1 && j == 1 ? 2 :
5846                         i == Xboom_1 && j == 2 ? 2 :
5847                         i == Xboom_1 && j == 3 ? 4 :
5848                         i == Xboom_1 && j == 4 ? 4 :
5849                         i == Xboom_1 && j == 5 ? 6 :
5850                         i == Xboom_1 && j == 6 ? 6 :
5851                         i == Xboom_1 && j == 7 ? 8 :
5852                         i == Xboom_2 && j == 0 ? 8 :
5853                         i == Xboom_2 && j == 1 ? 8 :
5854                         i == Xboom_2 && j == 2 ? 10 :
5855                         i == Xboom_2 && j == 3 ? 10 :
5856                         i == Xboom_2 && j == 4 ? 10 :
5857                         i == Xboom_2 && j == 5 ? 12 :
5858                         i == Xboom_2 && j == 6 ? 12 :
5859                         i == Xboom_2 && j == 7 ? 12 :
5860                         special_animation && j == 4 ? 3 :
5861                         effective_action != action ? 0 :
5862                         j);
5863
5864 #if DEBUG_EM_GFX
5865       Bitmap *debug_bitmap = g_em->bitmap;
5866       int debug_src_x = g_em->src_x;
5867       int debug_src_y = g_em->src_y;
5868 #endif
5869
5870       int frame = getAnimationFrame(g->anim_frames,
5871                                     g->anim_delay,
5872                                     g->anim_mode,
5873                                     g->anim_start_frame,
5874                                     sync_frame);
5875
5876       getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
5877                           g->double_movement && is_backside);
5878
5879 #if 1
5880       g_em->bitmap = src_bitmap;
5881       g_em->src_x = src_x;
5882       g_em->src_y = src_y;
5883       g_em->src_offset_x = 0;
5884       g_em->src_offset_y = 0;
5885       g_em->dst_offset_x = 0;
5886       g_em->dst_offset_y = 0;
5887       g_em->width  = TILEX;
5888       g_em->height = TILEY;
5889
5890       g_em->has_crumbled_graphics = FALSE;
5891       g_em->crumbled_bitmap = NULL;
5892       g_em->crumbled_src_x = 0;
5893       g_em->crumbled_src_y = 0;
5894       g_em->crumbled_border_size = 0;
5895 #endif
5896
5897 #if 0
5898       if (effective_element == EL_EMC_GRASS &&
5899           effective_action == ACTION_DIGGING)
5900         printf("::: %d\n", crumbled);
5901 #endif
5902
5903 #if 0
5904       if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
5905         printf("::: empty crumbled: %d [%s], %d, %d\n",
5906                effective_element, element_info[effective_element].token_name,
5907                effective_action, direction);
5908 #endif
5909
5910       /* if element can be crumbled, but certain action graphics are just empty
5911          space (like snapping sand with the original R'n'D graphics), do not
5912          treat these empty space graphics as crumbled graphics in EMC engine */
5913       if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
5914       {
5915         getGraphicSource(crumbled, frame, &src_bitmap, &src_x, &src_y);
5916
5917         g_em->has_crumbled_graphics = TRUE;
5918         g_em->crumbled_bitmap = src_bitmap;
5919         g_em->crumbled_src_x = src_x;
5920         g_em->crumbled_src_y = src_y;
5921         g_em->crumbled_border_size = graphic_info[crumbled].border_size;
5922       }
5923
5924 #if 1
5925       if (!g->double_movement && (effective_action == ACTION_FALLING ||
5926                                   effective_action == ACTION_MOVING ||
5927                                   effective_action == ACTION_PUSHING))
5928       {
5929         int move_dir =
5930           (effective_action == ACTION_FALLING ? MV_DOWN : direction);
5931         int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
5932         int dy = (move_dir == MV_UP   ? -1 : move_dir == MV_DOWN  ? 1 : 0);
5933         int cx = ABS(dx) * TILEX / 8;
5934         int cy = ABS(dy) * TILEY / 8;
5935
5936         if (is_backside)                /* tile where movement starts */
5937         {
5938           if (dx < 0 || dy < 0)
5939           {
5940             g_em->src_offset_x = cx * (j + 1);
5941             g_em->src_offset_y = cy * (j + 1);
5942           }
5943           else
5944           {
5945             g_em->dst_offset_x = cx * (j + 1);
5946             g_em->dst_offset_y = cy * (j + 1);
5947           }
5948
5949           g_em->width  = TILEX - cx * (j + 1);
5950           g_em->height = TILEY - cy * (j + 1);
5951         }
5952         else                    /* tile where movement ends */
5953         {
5954           if (dx < 0 || dy < 0)
5955           {
5956             g_em->dst_offset_x = cx * (7 - j);
5957             g_em->dst_offset_y = cy * (7 - j);
5958           }
5959           else
5960           {
5961             g_em->src_offset_x = cx * (7 - j);
5962             g_em->src_offset_y = cy * (7 - j);
5963           }
5964
5965           g_em->width  = TILEX - cx * (7 - j);
5966           g_em->height = TILEY - cy * (7 - j);
5967         }
5968       }
5969 #endif
5970
5971       /* create unique graphic identifier to decide if tile must be redrawn */
5972       /* bit 31 - 16 (16 bit): EM style element
5973          bit 15 - 12 ( 4 bit): EM style frame
5974          bit 11 -  6 ( 6 bit): graphic width
5975          bit  5 -  0 ( 6 bit): graphic height */
5976       g_em->unique_identifier =
5977         (i << 16) | (j << 12) | (g_em->width << 6) | g_em->height;
5978
5979 #if DEBUG_EM_GFX
5980       if (g_em->bitmap != debug_bitmap ||
5981           g_em->src_x != debug_src_x ||
5982           g_em->src_y != debug_src_y ||
5983           g_em->src_offset_x != 0 ||
5984           g_em->src_offset_y != 0 ||
5985           g_em->dst_offset_x != 0 ||
5986           g_em->dst_offset_y != 0 ||
5987           g_em->width != TILEX ||
5988           g_em->height != TILEY)
5989       {
5990         static int last_i = -1;
5991
5992         if (i != last_i)
5993         {
5994           printf("\n");
5995           last_i = i;
5996         }
5997
5998         printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
5999                i, element, element_info[element].token_name,
6000                element_action_info[effective_action].suffix, direction);
6001
6002         if (element != effective_element)
6003           printf(" [%d ('%s')]",
6004                  effective_element,
6005                  element_info[effective_element].token_name);
6006
6007         printf("\n");
6008
6009         if (g_em->bitmap != debug_bitmap)
6010           printf("    %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
6011                  j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
6012
6013         if (g_em->src_x != debug_src_x ||
6014             g_em->src_y != debug_src_y)
6015           printf("    frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
6016                  j, (is_backside ? 'B' : 'F'),
6017                  g_em->src_x, g_em->src_y,
6018                  g_em->src_x / 32, g_em->src_y / 32,
6019                  debug_src_x, debug_src_y,
6020                  debug_src_x / 32, debug_src_y / 32);
6021
6022         if (g_em->src_offset_x != 0 ||
6023             g_em->src_offset_y != 0 ||
6024             g_em->dst_offset_x != 0 ||
6025             g_em->dst_offset_y != 0)
6026           printf("    %d (%d): offsets %d,%d and %d,%d should be all 0\n",
6027                  j, is_backside,
6028                  g_em->src_offset_x, g_em->src_offset_y,
6029                  g_em->dst_offset_x, g_em->dst_offset_y);
6030
6031         if (g_em->width != TILEX ||
6032             g_em->height != TILEY)
6033           printf("    %d (%d): size %d,%d should be %d,%d\n",
6034                  j, is_backside,
6035                  g_em->width, g_em->height, TILEX, TILEY);
6036       }
6037 #endif
6038
6039     }
6040   }
6041
6042   for (p = 0; p < 2; p++)
6043   {
6044     for (i = 0; i < SPR_MAX; i++)
6045     {
6046       int element = player_mapping[p][i].element_rnd;
6047       int action = player_mapping[p][i].action;
6048       int direction = player_mapping[p][i].direction;
6049
6050       for (j = 0; j < 8; j++)
6051       {
6052         int effective_element = element;
6053         int effective_action = action;
6054         int graphic = (direction == MV_NO_MOVING ?
6055                        el_act2img(effective_element, effective_action) :
6056                        el_act_dir2img(effective_element, effective_action,
6057                                       direction));
6058         struct GraphicInfo *g = &graphic_info[graphic];
6059         struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
6060         Bitmap *src_bitmap;
6061         int src_x, src_y;
6062         int sync_frame = j;
6063
6064 #if DEBUG_EM_GFX
6065         Bitmap *debug_bitmap = g_em->bitmap;
6066         int debug_src_x = g_em->src_x;
6067         int debug_src_y = g_em->src_y;
6068 #endif
6069
6070         int frame = getAnimationFrame(g->anim_frames,
6071                                       g->anim_delay,
6072                                       g->anim_mode,
6073                                       g->anim_start_frame,
6074                                       sync_frame);
6075
6076         getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x,&src_y, FALSE);
6077
6078 #if 1
6079         g_em->bitmap = src_bitmap;
6080         g_em->src_x = src_x;
6081         g_em->src_y = src_y;
6082         g_em->src_offset_x = 0;
6083         g_em->src_offset_y = 0;
6084         g_em->dst_offset_x = 0;
6085         g_em->dst_offset_y = 0;
6086         g_em->width  = TILEX;
6087         g_em->height = TILEY;
6088 #endif
6089
6090 #if DEBUG_EM_GFX
6091         if (g_em->bitmap != debug_bitmap ||
6092             g_em->src_x != debug_src_x ||
6093             g_em->src_y != debug_src_y)
6094         {
6095           static int last_i = -1;
6096
6097           if (i != last_i)
6098           {
6099             printf("\n");
6100             last_i = i;
6101           }
6102
6103           printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
6104                  p, i, element, element_info[element].token_name,
6105                  element_action_info[effective_action].suffix, direction);
6106
6107           if (element != effective_element)
6108             printf(" [%d ('%s')]",
6109                    effective_element,
6110                    element_info[effective_element].token_name);
6111
6112           printf("\n");
6113
6114           if (g_em->bitmap != debug_bitmap)
6115             printf("    %d: different bitmap! (0x%08x != 0x%08x)\n",
6116                    j, (int)(g_em->bitmap), (int)(debug_bitmap));
6117
6118           if (g_em->src_x != debug_src_x ||
6119               g_em->src_y != debug_src_y)
6120             printf("    frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
6121                    j,
6122                    g_em->src_x, g_em->src_y,
6123                    g_em->src_x / 32, g_em->src_y / 32,
6124                    debug_src_x, debug_src_y,
6125                    debug_src_x / 32, debug_src_y / 32);
6126         }
6127 #endif
6128
6129       }
6130     }
6131   }
6132
6133 #if DEBUG_EM_GFX
6134   exit(0);
6135 #endif
6136 }