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