added using setup option for displaying overlay touch buttons
[rocksndiamonds.git] / src / tools.c
index c2b1ec15c80b9e31719171cb40b7d587f4f33478..79cf0885135681310694fdc4dc562fd40dfa5cf0 100644 (file)
@@ -4,7 +4,7 @@
 // (c) 1995-2014 by Artsoft Entertainment
 //                         Holger Schemel
 //                 info@artsoft.org
-//                 http://www.artsoft.org/
+//                 https://www.artsoft.org/
 // ----------------------------------------------------------------------------
 // tools.c
 // ============================================================================
@@ -23,8 +23,6 @@
 #include "screens.h"
 
 
-// select level set with EMC X11 graphics before activating EM GFX debugging
-#define DEBUG_EM_GFX           FALSE
 #define DEBUG_FRAME_TIME       FALSE
 
 // tool button identifiers
 #define TOOL_CTRL_ID_PLAYER_2  4
 #define TOOL_CTRL_ID_PLAYER_3  5
 #define TOOL_CTRL_ID_PLAYER_4  6
+#define TOOL_CTRL_ID_TOUCH_YES 7
+#define TOOL_CTRL_ID_TOUCH_NO  8
+#define TOOL_CTRL_ID_TOUCH_CONFIRM 9
 
-#define NUM_TOOL_BUTTONS       7
+#define NUM_TOOL_BUTTONS       10
 
 // constants for number of doors and door parts
 #define NUM_DOORS              2
@@ -192,33 +193,17 @@ static char *print_if_not_empty(int element)
   return s;
 }
 
-int correctLevelPosX_EM(int lx)
-{
-  lx -= 1;
-  lx -= (BorderElement != EL_EMPTY ? 1 : 0);
-
-  return lx;
-}
-
-int correctLevelPosY_EM(int ly)
-{
-  ly -= 1;
-  ly -= (BorderElement != EL_EMPTY ? 1 : 0);
-
-  return ly;
-}
-
-static int getFieldbufferOffsetX_RND(void)
+int getFieldbufferOffsetX_RND(int dir, int pos)
 {
   int full_lev_fieldx = lev_fieldx + (BorderElement != EL_EMPTY ? 2 : 0);
-  int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
+  int dx = (dir & MV_HORIZONTAL ? pos : 0);
   int dx_var = dx * TILESIZE_VAR / TILESIZE;
   int fx = FX;
 
   if (EVEN(SCR_FIELDX))
   {
     int sbx_right = SBX_Right + (BorderElement != EL_EMPTY ? 1 : 0);
-    int ffx = (scroll_x - SBX_Left)  * TILEX_VAR + dx_var;
+    int ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
 
     if (ffx < sbx_right * TILEX_VAR + TILEX_VAR / 2)
       fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
@@ -241,10 +226,10 @@ static int getFieldbufferOffsetX_RND(void)
   return fx;
 }
 
-static int getFieldbufferOffsetY_RND(void)
+int getFieldbufferOffsetY_RND(int dir, int pos)
 {
   int full_lev_fieldy = lev_fieldy + (BorderElement != EL_EMPTY ? 2 : 0);
-  int dy = (ScreenMovDir & (MV_UP | MV_DOWN)    ? ScreenGfxPos : 0);
+  int dy = (dir & MV_VERTICAL ? pos : 0);
   int dy_var = dy * TILESIZE_VAR / TILESIZE;
   int fy = FY;
 
@@ -276,7 +261,7 @@ static int getFieldbufferOffsetY_RND(void)
 
 static int getLevelFromScreenX_RND(int sx)
 {
-  int fx = getFieldbufferOffsetX_RND();
+  int fx = getFieldbufferOffsetX_RND(ScreenMovDir, ScreenGfxPos);
   int dx = fx - FX;
   int px = sx - SX;
   int lx = LEVELX((px + dx) / TILESIZE_VAR);
@@ -286,7 +271,7 @@ static int getLevelFromScreenX_RND(int sx)
 
 static int getLevelFromScreenY_RND(int sy)
 {
-  int fy = getFieldbufferOffsetY_RND();
+  int fy = getFieldbufferOffsetY_RND(ScreenMovDir, ScreenGfxPos);
   int dy = fy - FY;
   int py = sy - SY;
   int ly = LEVELY((py + dy) / TILESIZE_VAR);
@@ -296,7 +281,7 @@ static int getLevelFromScreenY_RND(int sy)
 
 static int getLevelFromScreenX_EM(int sx)
 {
-  int level_xsize = level.native_em_level->lev->width;
+  int level_xsize = level.native_em_level->cav->width;
   int full_xsize = level_xsize * TILESIZE_VAR;
 
   sx -= (full_xsize < SXSIZE ? (SXSIZE - full_xsize) / 2 : 0);
@@ -306,14 +291,12 @@ static int getLevelFromScreenX_EM(int sx)
   int px = sx - SX;
   int lx = LEVELX((px + dx) / TILESIZE_VAR);
 
-  lx = correctLevelPosX_EM(lx);
-
   return lx;
 }
 
 static int getLevelFromScreenY_EM(int sy)
 {
-  int level_ysize = level.native_em_level->lev->height;
+  int level_ysize = level.native_em_level->cav->height;
   int full_ysize = level_ysize * TILESIZE_VAR;
 
   sy -= (full_ysize < SYSIZE ? (SYSIZE - full_ysize) / 2 : 0);
@@ -323,8 +306,6 @@ static int getLevelFromScreenY_EM(int sy)
   int py = sy - SY;
   int ly = LEVELY((py + dy) / TILESIZE_VAR);
 
-  ly = correctLevelPosY_EM(ly);
-
   return ly;
 }
 
@@ -410,41 +391,51 @@ int getLevelFromScreenY(int y)
     return getLevelFromScreenY_RND(y);
 }
 
+int getScreenFieldSizeX(void)
+{
+  return (tape.playing ? tape.scr_fieldx : SCR_FIELDX);
+}
+
+int getScreenFieldSizeY(void)
+{
+  return (tape.playing ? tape.scr_fieldy : SCR_FIELDY);
+}
+
 void DumpTile(int x, int y)
 {
   int sx = SCREENX(x);
   int sy = SCREENY(y);
   char *token_name;
 
-  printf_line("-", 79);
-  printf("Field Info: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
-  printf_line("-", 79);
+  Info("---");
+  Info("Field Info: SCREEN(%d, %d), LEVEL(%d, %d)", sx, sy, x, y);
+  Info("---");
 
   if (!IN_LEV_FIELD(x, y))
   {
-    printf("(not in level field)\n");
-    printf("\n");
+    Info("(not in level field)");
+    Info("");
 
     return;
   }
 
-  token_name = element_info[Feld[x][y]].token_name;
+  token_name = element_info[Tile[x][y]].token_name;
 
-  printf("  Feld:        %d\t['%s']\n", Feld[x][y], token_name);
-  printf("  Back:        %s\n", print_if_not_empty(Back[x][y]));
-  printf("  Store:       %s\n", print_if_not_empty(Store[x][y]));
-  printf("  Store2:      %s\n", print_if_not_empty(Store2[x][y]));
-  printf("  StorePlayer: %s\n", print_if_not_empty(StorePlayer[x][y]));
-  printf("  MovPos:      %d\n", MovPos[x][y]);
-  printf("  MovDir:      %d\n", MovDir[x][y]);
-  printf("  MovDelay:    %d\n", MovDelay[x][y]);
-  printf("  ChangeDelay: %d\n", ChangeDelay[x][y]);
-  printf("  CustomValue: %d\n", CustomValue[x][y]);
-  printf("  GfxElement:  %d\n", GfxElement[x][y]);
-  printf("  GfxAction:   %d\n", GfxAction[x][y]);
-  printf("  GfxFrame:    %d [%d]\n", GfxFrame[x][y], FrameCounter);
-  printf("  Player x/y:  %d, %d\n", local_player->jx, local_player->jy);
-  printf("\n");
+  Info("Tile:        %d\t['%s']",      Tile[x][y], token_name);
+  Info("Back:        %s",              print_if_not_empty(Back[x][y]));
+  Info("Store:       %s",              print_if_not_empty(Store[x][y]));
+  Info("Store2:      %s",              print_if_not_empty(Store2[x][y]));
+  Info("StorePlayer: %s",              print_if_not_empty(StorePlayer[x][y]));
+  Info("MovPos:      %d",              MovPos[x][y]);
+  Info("MovDir:      %d",              MovDir[x][y]);
+  Info("MovDelay:    %d",              MovDelay[x][y]);
+  Info("ChangeDelay: %d",              ChangeDelay[x][y]);
+  Info("CustomValue: %d",              CustomValue[x][y]);
+  Info("GfxElement:  %d",              GfxElement[x][y]);
+  Info("GfxAction:   %d",              GfxAction[x][y]);
+  Info("GfxFrame:    %d [%d]",         GfxFrame[x][y], FrameCounter);
+  Info("Player x/y:  %d, %d",          local_player->jx, local_player->jy);
+  Info("");
 }
 
 void DumpTileFromScreen(int sx, int sy)
@@ -481,6 +472,11 @@ void SetDrawtoField(int mode)
   }
 }
 
+int GetDrawtoField(void)
+{
+  return (drawto_field == fieldbuffer ? DRAW_TO_FIELDBUFFER : DRAW_TO_BACKBUFFER);
+}
+
 static void RedrawPlayfield_RND(void)
 {
   if (game.envelope_active)
@@ -516,6 +512,10 @@ static void DrawMaskedBorderExt_Rect(int x, int y, int width, int height,
   Bitmap *src_bitmap = getGlobalBorderBitmapFromStatus(global.border_status);
   Bitmap *dst_bitmap = gfx.masked_border_bitmap_ptr;
 
+  // may happen for "border.draw_masked.*" with undefined "global.border.*"
+  if (src_bitmap == NULL)
+    return;
+
   if (x == -1 && y == -1)
     return;
 
@@ -635,68 +635,20 @@ void DrawMaskedBorderToTarget(int draw_target)
 
 void DrawTileCursor(int draw_target)
 {
-  Bitmap *fade_bitmap;
-  Bitmap *src_bitmap;
-  int src_x, src_y;
-  int dst_x, dst_y;
-  int graphic = IMG_GLOBAL_TILE_CURSOR;
-  int frame = 0;
-  int tilesize = TILESIZE_VAR;
-  int width = tilesize;
-  int height = tilesize;
-
-  if (game_status != GAME_MODE_PLAYING)
-    return;
-
-  if (!tile_cursor.enabled ||
-      !tile_cursor.active)
-    return;
-
-  if (tile_cursor.moving)
-  {
-    int step = TILESIZE_VAR / 4;
-    int dx = tile_cursor.target_x - tile_cursor.x;
-    int dy = tile_cursor.target_y - tile_cursor.y;
-
-    if (ABS(dx) < step)
-      tile_cursor.x = tile_cursor.target_x;
-    else
-      tile_cursor.x += SIGN(dx) * step;
-
-    if (ABS(dy) < step)
-      tile_cursor.y = tile_cursor.target_y;
-    else
-      tile_cursor.y += SIGN(dy) * step;
-
-    if (tile_cursor.x == tile_cursor.target_x &&
-       tile_cursor.y == tile_cursor.target_y)
-      tile_cursor.moving = FALSE;
-  }
-
-  dst_x = tile_cursor.x;
-  dst_y = tile_cursor.y;
-
-  frame = getGraphicAnimationFrame(graphic, -1);
-
-  getSizedGraphicSource(graphic, frame, tilesize, &src_bitmap, &src_x, &src_y);
-
-  fade_bitmap =
-    (draw_target == DRAW_TO_FADE_SOURCE ? gfx.fade_bitmap_source :
-     draw_target == DRAW_TO_FADE_TARGET ? gfx.fade_bitmap_target : NULL);
+  DrawTileCursor_MM(draw_target, game_status == GAME_MODE_PLAYING);
+}
 
-  if (draw_target == DRAW_TO_SCREEN)
-    BlitToScreenMasked(src_bitmap, src_x, src_y, width, height, dst_x, dst_y);
-  else
-    BlitBitmapMasked(src_bitmap, fade_bitmap, src_x, src_y, width, height,
-                    dst_x, dst_y);
+void BlitScreenToBitmapExt_RND(Bitmap *target_bitmap, int fx, int fy)
+{
+  BlitBitmap(drawto_field, target_bitmap, fx, fy, SXSIZE, SYSIZE, SX, SY);
 }
 
 void BlitScreenToBitmap_RND(Bitmap *target_bitmap)
 {
-  int fx = getFieldbufferOffsetX_RND();
-  int fy = getFieldbufferOffsetY_RND();
+  int fx = getFieldbufferOffsetX_RND(ScreenMovDir, ScreenGfxPos);
+  int fy = getFieldbufferOffsetY_RND(ScreenMovDir, ScreenGfxPos);
 
-  BlitBitmap(drawto_field, target_bitmap, fx, fy, SXSIZE, SYSIZE, SX, SY);
+  BlitScreenToBitmapExt_RND(target_bitmap, fx, fy);
 }
 
 void BlitScreenToBitmap(Bitmap *target_bitmap)
@@ -766,7 +718,7 @@ static void PrintFrameTimeDebugging(void)
 
   diff_bar[pos++] = '\0';
 
-  Error(ERR_INFO, "%06d [%02d] [%c%02d] %s",
+  Debug("time:frame", "%06d [%02d] [%c%02d] %s",
        counter,
        diff_1,
        (diff_2 < 0 ? '-' : diff_2 > 0 ? '+' : ' '), ABS(diff_2),
@@ -965,19 +917,13 @@ static void FadeExt(int fade_mask, int fade_mode, int fade_type)
     height = WIN_YSIZE;
   }
 
-  if (!setup.fade_screens ||
-      fade_delay == 0 ||
-      fading.fade_mode == FADE_MODE_NONE)
-  {
-    if (fade_mode == FADE_MODE_FADE_OUT)
-      return;
-
-    BlitBitmap(backbuffer, window, x, y, width, height, x, y);
-
-    redraw_mask &= ~fade_mask;
+  // when switching screens without fading, set fade delay to zero
+  if (!setup.fade_screens || fading.fade_mode == FADE_MODE_NONE)
+    fade_delay = 0;
 
+  // do not display black frame when fading out without fade delay
+  if (fade_mode == FADE_MODE_FADE_OUT && fade_delay == 0)
     return;
-  }
 
   FadeRectangle(x, y, width, height, fade_mode, fade_delay, post_delay,
                draw_border_function);
@@ -993,8 +939,7 @@ static void SetScreenStates_BeforeFadingIn(void)
   global.anim_status = global.anim_status_next;
 
   // store backbuffer with all animations that will be started after fading in
-  if (fade_type_skip != FADE_MODE_SKIP_FADE_IN)
-    PrepareFadeBitmap(DRAW_TO_FADE_TARGET);
+  PrepareFadeBitmap(DRAW_TO_FADE_TARGET);
 
   // set screen mode for animations back to fading
   global.anim_status = GAME_MODE_PSEUDO_FADING;
@@ -1017,8 +962,7 @@ static void SetScreenStates_BeforeFadingOut(void)
   global.anim_status = GAME_MODE_PSEUDO_FADING;
 
   // store backbuffer with all animations that will be stopped for fading out
-  if (fade_type_skip != FADE_MODE_SKIP_FADE_OUT)
-    PrepareFadeBitmap(DRAW_TO_FADE_SOURCE);
+  PrepareFadeBitmap(DRAW_TO_FADE_SOURCE);
 }
 
 static void SetScreenStates_AfterFadingOut(void)
@@ -1059,7 +1003,8 @@ void FadeIn(int fade_mask)
 void FadeOut(int fade_mask)
 {
   // update screen if areas covered by "fade_mask" and "redraw_mask" differ
-  if (!equalRedrawMasks(fade_mask, redraw_mask))
+  if (!equalRedrawMasks(fade_mask, redraw_mask) &&
+      fade_type_skip != FADE_MODE_SKIP_FADE_OUT)
     BackToFront();
 
   SetScreenStates_BeforeFadingOut();
@@ -1150,6 +1095,13 @@ void FadeSkipNextFadeOut(void)
   FadeExt(0, FADE_MODE_SKIP_FADE_OUT, FADE_TYPE_SKIP);
 }
 
+static int getGlobalGameStatus(int status)
+{
+  return (status == GAME_MODE_PSEUDO_TYPENAME ? GAME_MODE_MAIN :
+         status == GAME_MODE_SCOREINFO       ? GAME_MODE_SCORES :
+         status);
+}
+
 static Bitmap *getBitmapFromGraphicOrDefault(int graphic, int default_graphic)
 {
   if (graphic == IMG_UNDEFINED)
@@ -1172,14 +1124,14 @@ static Bitmap *getGlobalBorderBitmap(int graphic)
   return getBitmapFromGraphicOrDefault(graphic, IMG_GLOBAL_BORDER);
 }
 
-Bitmap *getGlobalBorderBitmapFromStatus(int status)
+Bitmap *getGlobalBorderBitmapFromStatus(int status_raw)
 {
+  int status = getGlobalGameStatus(status_raw);
   int graphic =
-    (status == GAME_MODE_MAIN ||
-     status == GAME_MODE_PSEUDO_TYPENAME       ? IMG_GLOBAL_BORDER_MAIN :
-     status == GAME_MODE_SCORES                        ? IMG_GLOBAL_BORDER_SCORES :
-     status == GAME_MODE_EDITOR                        ? IMG_GLOBAL_BORDER_EDITOR :
-     status == GAME_MODE_PLAYING               ? IMG_GLOBAL_BORDER_PLAYING :
+    (status == GAME_MODE_MAIN    ? IMG_GLOBAL_BORDER_MAIN :
+     status == GAME_MODE_SCORES  ? IMG_GLOBAL_BORDER_SCORES :
+     status == GAME_MODE_EDITOR  ? IMG_GLOBAL_BORDER_EDITOR :
+     status == GAME_MODE_PLAYING ? IMG_GLOBAL_BORDER_PLAYING :
      IMG_GLOBAL_BORDER);
 
   return getGlobalBorderBitmap(graphic);
@@ -1358,6 +1310,9 @@ static void RedrawGlobalBorderIfNeeded(void)
 
 #if ONLY_REDRAW_GLOBAL_BORDER_IF_NEEDED
   if (CheckIfGlobalBorderRedrawIsNeeded())
+#else
+  // determine and store new global border bitmap for current game status
+  global_border_bitmap = getGlobalBorderBitmapFromStatus(game_status);
 #endif
   {
     // redraw global screen border (or clear, if defined to be empty)
@@ -1455,15 +1410,15 @@ void SetBorderElement(void)
 
   BorderElement = EL_EMPTY;
 
-  // the MM game engine does not use a visible border element
-  if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
+  // only the R'n'D game engine may use an additional steelwall border
+  if (level.game_engine_type != GAME_ENGINE_TYPE_RND)
     return;
 
   for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
   {
     for (x = 0; x < lev_fieldx; x++)
     {
-      if (!IS_INDESTRUCTIBLE(Feld[x][y]))
+      if (!IS_INDESTRUCTIBLE(Tile[x][y]))
        BorderElement = EL_STEELWALL;
 
       if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
@@ -1472,39 +1427,42 @@ void SetBorderElement(void)
   }
 }
 
-void FloodFillLevelExt(int from_x, int from_y, int fill_element,
+void FloodFillLevelExt(int start_x, int start_y, int fill_element,
                       int max_array_fieldx, int max_array_fieldy,
                       short field[max_array_fieldx][max_array_fieldy],
                       int max_fieldx, int max_fieldy)
 {
-  int i,x,y;
-  int old_element;
-  static int check[4][2] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };
-  static int safety = 0;
+  static struct XY stack_buffer[MAX_LEV_FIELDX * MAX_LEV_FIELDY];
+  static struct XY check[4] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };
+  int old_element = field[start_x][start_y];
+  int stack_pos = 0;
 
-  // check if starting field still has the desired content
-  if (field[from_x][from_y] == fill_element)
+  // do nothing if start field already has the desired content
+  if (old_element == fill_element)
     return;
 
-  safety++;
+  stack_buffer[stack_pos++] = (struct XY){ start_x, start_y };
 
-  if (safety > max_fieldx * max_fieldy)
-    Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug.");
+  while (stack_pos > 0)
+  {
+    struct XY current = stack_buffer[--stack_pos];
+    int i;
 
-  old_element = field[from_x][from_y];
-  field[from_x][from_y] = fill_element;
+    field[current.x][current.y] = fill_element;
 
-  for (i = 0; i < 4; i++)
-  {
-    x = from_x + check[i][0];
-    y = from_y + check[i][1];
+    for (i = 0; i < 4; i++)
+    {
+      int x = current.x + check[i].x;
+      int y = current.y + check[i].y;
 
-    if (IN_FIELD(x, y, max_fieldx, max_fieldy) && field[x][y] == old_element)
-      FloodFillLevelExt(x, y, fill_element, max_array_fieldx, max_array_fieldy,
-                       field, max_fieldx, max_fieldy);
-  }
+      // check for stack buffer overflow (should not happen)
+      if (stack_pos >= MAX_LEV_FIELDX * MAX_LEV_FIELDY)
+       Fail("Stack buffer overflow in 'FloodFillLevelExt()'. Please debug.");
 
-  safety--;
+      if (IN_FIELD(x, y, max_fieldx, max_fieldy) && field[x][y] == old_element)
+       stack_buffer[stack_pos++] = (struct XY){ x, y };
+    }
+  }
 }
 
 void FloodFillLevel(int from_x, int from_y, int fill_element,
@@ -1534,6 +1492,40 @@ int getGraphicAnimationFrame(int graphic, int sync_frame)
                           sync_frame);
 }
 
+int getGraphicAnimationFrameXY(int graphic, int lx, int ly)
+{
+  if (graphic_info[graphic].anim_mode & ANIM_TILED)
+  {
+    struct GraphicInfo *g = &graphic_info[graphic];
+    int xsize = MAX(1, g->anim_frames_per_line);
+    int ysize = MAX(1, g->anim_frames / xsize);
+    int xoffset = g->anim_start_frame % xsize;
+    int yoffset = g->anim_start_frame % ysize;
+    // may be needed if screen field is significantly larger than playfield
+    int x = (lx + xoffset + SCR_FIELDX * xsize) % xsize;
+    int y = (ly + yoffset + SCR_FIELDY * ysize) % ysize;
+    int sync_frame = y * xsize + x;
+
+    return sync_frame % g->anim_frames;
+  }
+  else if (graphic_info[graphic].anim_mode & ANIM_RANDOM_STATIC)
+  {
+    struct GraphicInfo *g = &graphic_info[graphic];
+    // may be needed if screen field is significantly larger than playfield
+    int x = (lx + SCR_FIELDX * lev_fieldx) % lev_fieldx;
+    int y = (ly + SCR_FIELDY * lev_fieldy) % lev_fieldy;
+    int sync_frame = GfxRandomStatic[x][y];
+
+    return sync_frame % g->anim_frames;
+  }
+  else
+  {
+    int sync_frame = (IN_LEV_FIELD(lx, ly) ? GfxFrame[lx][ly] : -1);
+
+    return getGraphicAnimationFrame(graphic, sync_frame);
+  }
+}
+
 void getGraphicSourceBitmap(int graphic, int tilesize, Bitmap **bitmap)
 {
   struct GraphicInfo *g = &graphic_info[graphic];
@@ -1542,7 +1534,7 @@ void getGraphicSourceBitmap(int graphic, int tilesize, Bitmap **bitmap)
   if (tilesize == gfx.standard_tile_size)
     *bitmap = g->bitmaps[IMG_BITMAP_STANDARD];
   else if (tilesize == game.tile_size)
-    *bitmap = g->bitmaps[IMG_BITMAP_GAME];
+    *bitmap = g->bitmaps[IMG_BITMAP_PTR_GAME];
   else
     *bitmap = g->bitmaps[IMG_BITMAP_1x1 - log_2(tilesize_capped)];
 }
@@ -1588,7 +1580,7 @@ void getSizedGraphicSourceExt(int graphic, int frame, int tilesize,
     *g = graphic_info[IMG_CHAR_EXCLAM];
 
   // if no in-game graphics defined, always use standard graphic size
-  if (g->bitmaps[IMG_BITMAP_GAME] == NULL)
+  if (g->bitmaps[IMG_BITMAP_PTR_GAME] == NULL)
     tilesize = TILESIZE;
 
   getGraphicSourceBitmap(graphic, tilesize, bitmap);
@@ -1615,6 +1607,24 @@ void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
   getSizedGraphicSource(graphic, 0, MINI_TILESIZE, bitmap, x, y);
 }
 
+void getGlobalAnimGraphicSource(int graphic, int frame,
+                               Bitmap **bitmap, int *x, int *y)
+{
+  struct GraphicInfo *g = &graphic_info[graphic];
+
+  // if no graphics defined at all, use fallback graphics
+  if (g->bitmaps == NULL)
+    *g = graphic_info[IMG_CHAR_EXCLAM];
+
+  // use original size graphics, if existing, else use standard size graphics
+  if (g->bitmaps[IMG_BITMAP_PTR_ORIGINAL])
+    *bitmap = g->bitmaps[IMG_BITMAP_PTR_ORIGINAL];
+  else
+    *bitmap = g->bitmaps[IMG_BITMAP_STANDARD];
+
+  getGraphicSourceXY(graphic, frame, x, y, FALSE);
+}
+
 static void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
                                int *x, int *y, boolean get_backside)
 {
@@ -1632,8 +1642,9 @@ void DrawGraphic(int x, int y, int graphic, int frame)
 #if DEBUG
   if (!IN_SCR_FIELD(x, y))
   {
-    printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
-    printf("DrawGraphic(): This should never happen!\n");
+    Debug("draw:DrawGraphic", "x = %d, y = %d, graphic = %d", x, y, graphic);
+    Debug("draw:DrawGraphic", "This should never happen!");
+
     return;
   }
 #endif
@@ -1649,8 +1660,10 @@ void DrawFixedGraphic(int x, int y, int graphic, int frame)
 #if DEBUG
   if (!IN_SCR_FIELD(x, y))
   {
-    printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
-    printf("DrawGraphic(): This should never happen!\n");
+    Debug("draw:DrawFixedGraphic", "x = %d, y = %d, graphic = %d",
+         x, y, graphic);
+    Debug("draw:DrawFixedGraphic", "This should never happen!");
+
     return;
   }
 #endif
@@ -1686,8 +1699,10 @@ void DrawGraphicThruMask(int x, int y, int graphic, int frame)
 #if DEBUG
   if (!IN_SCR_FIELD(x, y))
   {
-    printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
-    printf("DrawGraphicThruMask(): This should never happen!\n");
+    Debug("draw:DrawGraphicThruMask", "x = %d,y = %d, graphic = %d",
+         x, y, graphic);
+    Debug("draw:DrawGraphicThruMask", "This should never happen!");
+
     return;
   }
 #endif
@@ -1703,8 +1718,10 @@ void DrawFixedGraphicThruMask(int x, int y, int graphic, int frame)
 #if DEBUG
   if (!IN_SCR_FIELD(x, y))
   {
-    printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
-    printf("DrawGraphicThruMask(): This should never happen!\n");
+    Debug("draw:DrawFixedGraphicThruMask", "x = %d,y = %d, graphic = %d",
+         x, y, graphic);
+    Debug("draw:DrawFixedGraphicThruMask", "This should never happen!");
+
     return;
   }
 #endif
@@ -1865,8 +1882,10 @@ static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
 #if DEBUG
   if (!IN_SCR_FIELD(x, y))
   {
-    printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
-    printf("DrawGraphicShifted(): This should never happen!\n");
+    Debug("draw:DrawGraphicShiftedNormal", "x = %d, y = %d, graphic = %d",
+         x, y, graphic);
+    Debug("draw:DrawGraphicShiftedNormal", "This should never happen!");
+
     return;
   }
 #endif
@@ -1996,31 +2015,37 @@ void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
 
   if (IN_LEV_FIELD(lx, ly))
   {
+    if (element == EL_EMPTY)
+      element = GfxElementEmpty[lx][ly];
+
     SetRandomAnimationValue(lx, ly);
 
     graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
-    frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
+    frame = getGraphicAnimationFrameXY(graphic, lx, ly);
 
     // do not use double (EM style) movement graphic when not moving
     if (graphic_info[graphic].double_movement && !dx && !dy)
     {
       graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
-      frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
+      frame = getGraphicAnimationFrameXY(graphic, lx, ly);
     }
+
+    if (game.use_masked_elements && (dx || dy))
+      mask_mode = USE_MASKING;
   }
   else // border element
   {
     graphic = el2img(element);
-    frame = getGraphicAnimationFrame(graphic, -1);
+    frame = getGraphicAnimationFrameXY(graphic, lx, ly);
   }
 
   if (element == EL_EXPANDABLE_WALL)
   {
     boolean left_stopped = FALSE, right_stopped = FALSE;
 
-    if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
+    if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Tile[lx - 1][ly]))
       left_stopped = TRUE;
-    if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
+    if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Tile[lx + 1][ly]))
       right_stopped = TRUE;
 
     if (left_stopped && right_stopped)
@@ -2072,7 +2097,7 @@ void DrawLevelElementThruMask(int x, int y, int element)
 
 void DrawLevelFieldThruMask(int x, int y)
 {
-  DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
+  DrawLevelElementExt(x, y, 0, 0, Tile[x][y], NO_CUTTING, USE_MASKING);
 }
 
 // !!! implementation of quicksand is totally broken !!!
@@ -2125,8 +2150,27 @@ static void DrawLevelFieldCrumbledInnerCorners(int x, int y, int dx, int dy,
   cx = (dx > 0 ? TILESIZE_VAR - width  : 0);
   cy = (dy > 0 ? TILESIZE_VAR - height : 0);
 
-  BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
-            width, height, FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
+  if (game.use_masked_elements)
+  {
+    int graphic0 = el2img(EL_EMPTY);
+    int frame0 = getGraphicAnimationFrameXY(graphic0, x, y);
+    Bitmap *src_bitmap0;
+    int src_x0, src_y0;
+
+    getGraphicSource(graphic0, frame0, &src_bitmap0, &src_x0, &src_y0);
+
+    BlitBitmap(src_bitmap0, drawto_field, src_x0 + cx, src_y0 + cy,
+              width, height,
+              FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
+
+    BlitBitmapMasked(src_bitmap, drawto_field, src_x + cx, src_y + cy,
+                    width, height,
+                    FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
+  }
+  else
+    BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
+              width, height,
+              FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
 }
 
 static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
@@ -2145,6 +2189,15 @@ static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
 
   getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
 
+  // only needed when using masked elements
+  int graphic0 = el2img(EL_EMPTY);
+  int frame0 = getGraphicAnimationFrameXY(graphic0, x, y);
+  Bitmap *src_bitmap0;
+  int src_x0, src_y0;
+
+  if (game.use_masked_elements)
+    getGraphicSource(graphic0, frame0, &src_bitmap0, &src_x0, &src_y0);
+
   // draw simple, sloppy, non-corner-accurate crumbled border
 
   width  = (dir == 1 || dir == 2 ? crumbled_border_size_var : TILESIZE_VAR);
@@ -2152,9 +2205,23 @@ static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
   cx = (dir == 2 ? crumbled_border_pos_var : 0);
   cy = (dir == 3 ? crumbled_border_pos_var : 0);
 
-  BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy, width, height,
-            FX + sx * TILEX_VAR + cx,
-            FY + sy * TILEY_VAR + cy);
+  if (game.use_masked_elements)
+  {
+    BlitBitmap(src_bitmap0, drawto_field, src_x0 + cx, src_y0 + cy,
+              width, height,
+              FX + sx * TILEX_VAR + cx,
+              FY + sy * TILEY_VAR + cy);
+
+    BlitBitmapMasked(src_bitmap, drawto_field, src_x + cx, src_y + cy,
+                    width, height,
+                    FX + sx * TILEX_VAR + cx,
+                    FY + sy * TILEY_VAR + cy);
+  }
+  else
+    BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
+              width, height,
+              FX + sx * TILEX_VAR + cx,
+              FY + sy * TILEY_VAR + cy);
 
   // (remaining middle border part must be at least as big as corner part)
   if (!(graphic_info[graphic].style & STYLE_ACCURATE_BORDERS) ||
@@ -2200,10 +2267,23 @@ static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
        by = cy;
       }
 
-      BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
-                width, height,
-                FX + sx * TILEX_VAR + cx,
-                FY + sy * TILEY_VAR + cy);
+      if (game.use_masked_elements)
+      {
+       BlitBitmap(src_bitmap0, drawto_field, src_x0 + bx, src_y0 + by,
+                  width, height,
+                  FX + sx * TILEX_VAR + cx,
+                  FY + sy * TILEY_VAR + cy);
+
+       BlitBitmapMasked(src_bitmap, drawto_field, src_x + bx, src_y + by,
+                        width, height,
+                        FX + sx * TILEX_VAR + cx,
+                        FY + sy * TILEY_VAR + cy);
+      }
+      else
+       BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
+                  width, height,
+                  FX + sx * TILEX_VAR + cx,
+                  FY + sy * TILEY_VAR + cy);
     }
   }
 }
@@ -2279,8 +2359,8 @@ static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame)
        continue;
 
       // do not crumble fields that are being digged or snapped
-      if (Feld[xx][yy] == EL_EMPTY ||
-         Feld[xx][yy] == EL_ELEMENT_SNAPPING)
+      if (Tile[xx][yy] == EL_EMPTY ||
+         Tile[xx][yy] == EL_ELEMENT_SNAPPING)
        continue;
 
       element = TILE_GFX_ELEMENT(xx, yy);
@@ -2309,7 +2389,7 @@ static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame)
          !IN_SCR_FIELD(sxx, syy))
        continue;
 
-      if (Feld[xx][yy] == EL_ELEMENT_SNAPPING)
+      if (Tile[xx][yy] == EL_ELEMENT_SNAPPING)
        continue;
 
       element = TILE_GFX_ELEMENT(xx, yy);
@@ -2335,7 +2415,7 @@ void DrawLevelFieldCrumbled(int x, int y)
   if (!IN_LEV_FIELD(x, y))
     return;
 
-  if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
+  if (Tile[x][y] == EL_ELEMENT_SNAPPING &&
       GfxElement[x][y] != EL_UNDEFINED &&
       GFX_CRUMBLED(GfxElement[x][y]))
   {
@@ -2358,7 +2438,7 @@ void DrawLevelFieldCrumbledDigging(int x, int y, int direction,
   int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
   int sx = SCREENX(x), sy = SCREENY(y);
 
-  DrawGraphic(sx, sy, graphic1, frame1);
+  DrawScreenGraphic(sx, sy, graphic1, frame1);
   DrawLevelFieldCrumbledExt(x, y, graphic2, frame2);
 }
 
@@ -2384,7 +2464,7 @@ void DrawLevelFieldCrumbledNeighbours(int x, int y)
 
     if (!IN_LEV_FIELD(xx, yy) ||
        !IN_SCR_FIELD(sxx, syy) ||
-       !GFX_CRUMBLED(Feld[xx][yy]) ||
+       !GFX_CRUMBLED(Tile[xx][yy]) ||
        IS_MOVING(xx, yy))
       continue;
 
@@ -2403,7 +2483,7 @@ void DrawLevelFieldCrumbledNeighbours(int x, int y)
 
     if (!IN_LEV_FIELD(xx, yy) ||
        !IN_SCR_FIELD(sxx, syy) ||
-       !GFX_CRUMBLED(Feld[xx][yy]) ||
+       !GFX_CRUMBLED(Tile[xx][yy]) ||
        IS_MOVING(xx, yy))
       continue;
 
@@ -2439,9 +2519,43 @@ static int getBorderElement(int x, int y)
   return border[steel_position][steel_type];
 }
 
+void DrawScreenGraphic(int x, int y, int graphic, int frame)
+{
+  if (game.use_masked_elements)
+  {
+    if (graphic != el2img(EL_EMPTY))
+      DrawScreenElementExt(x, y, 0, 0, EL_EMPTY, NO_CUTTING, NO_MASKING);
+
+    DrawGraphicThruMask(x, y, graphic, frame);
+  }
+  else
+  {
+    DrawGraphic(x, y, graphic, frame);
+  }
+}
+
+void DrawLevelGraphic(int x, int y, int graphic, int frame)
+{
+  DrawScreenGraphic(SCREENX(x), SCREENY(y), graphic, frame);
+}
+
 void DrawScreenElement(int x, int y, int element)
 {
-  DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
+  int mask_mode = NO_MASKING;
+
+  if (game.use_masked_elements)
+  {
+    int lx = LEVELX(x), ly = LEVELY(y);
+
+    if (IN_LEV_FIELD(lx, ly) && element != EL_EMPTY)
+    {
+      DrawScreenElementExt(x, y, 0, 0, EL_EMPTY, NO_CUTTING, NO_MASKING);
+
+      mask_mode = USE_MASKING;
+    }
+  }
+
+  DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, mask_mode);
   DrawLevelFieldCrumbled(LEVELX(x), LEVELY(y));
 }
 
@@ -2468,7 +2582,7 @@ void DrawScreenField(int x, int y)
     return;
   }
 
-  element = Feld[lx][ly];
+  element = Tile[lx][ly];
   content = Store[lx][ly];
 
   if (IS_MOVING(lx, ly))
@@ -2495,6 +2609,16 @@ void DrawScreenField(int x, int y)
     else
       DrawScreenElement(x, y, EL_EMPTY);
 
+    if (cut_mode != CUT_BELOW && game.use_masked_elements)
+    {
+      int dir = MovDir[lx][ly];
+      int newx = x + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
+      int newy = y + (dir == MV_UP   ? -1 : dir == MV_DOWN  ? +1 : 0);
+
+      if (IN_SCR_FIELD(newx, newy))
+       DrawScreenElement(newx, newy, EL_EMPTY);
+    }
+
     if (horiz_move)
       DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
     else if (cut_mode == NO_CUTTING)
@@ -2535,7 +2659,7 @@ void DrawScreenField(int x, int y)
     horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
                  MovDir[oldx][oldy] == MV_RIGHT);
 
-    element_old = Feld[oldx][oldy];
+    element_old = Tile[oldx][oldy];
     content_old = Store[oldx][oldy];
 
     if (element_old == EL_QUICKSAND_EMPTYING ||
@@ -2688,7 +2812,7 @@ void DrawSizedElementOrWall(int sx, int sy, int scroll_x, int scroll_y,
   if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
     DrawSizedElement(sx, sy, EL_EMPTY, tilesize);
   else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
-    DrawSizedElement(sx, sy, Feld[x][y], tilesize);
+    DrawSizedElement(sx, sy, Tile[x][y], tilesize);
   else
     DrawSizedGraphic(sx, sy, el2edimg(getBorderElement(x, y)), 0, tilesize);
 }
@@ -2700,7 +2824,7 @@ void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
   if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
     DrawMiniElement(sx, sy, EL_EMPTY);
   else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
-    DrawMiniElement(sx, sy, Feld[x][y]);
+    DrawMiniElement(sx, sy, Tile[x][y]);
   else
     DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
 }
@@ -2801,11 +2925,11 @@ static void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
       for (xx = 0; xx < xsize; xx++)
        DrawEnvelopeBackground(graphic, sx, sy, xx, yy, xsize, ysize, font_nr);
 
-    DrawTextBuffer(sx + font_width, sy + font_height,
-                  level.envelope[envelope_nr].text, font_nr, max_xsize,
-                  xsize - 2, ysize - 2, 0, mask_mode,
-                  level.envelope[envelope_nr].autowrap,
-                  level.envelope[envelope_nr].centered, FALSE);
+    DrawTextArea(sx + font_width, sy + font_height,
+                level.envelope[envelope_nr].text, font_nr, max_xsize,
+                xsize - 2, ysize - 2, 0, mask_mode,
+                level.envelope[envelope_nr].autowrap,
+                level.envelope[envelope_nr].centered, FALSE);
 
     redraw_mask |= REDRAW_FIELD;
     BackToFront();
@@ -2829,9 +2953,13 @@ void ShowEnvelope(int envelope_nr)
   int anim_mode = graphic_info[graphic].anim_mode;
   int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
                        anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
+  boolean overlay_enabled = GetOverlayEnabled();
 
   game.envelope_active = TRUE; // needed for RedrawPlayfield() events
 
+  SetOverlayEnabled(FALSE);
+  UnmapAllGadgets();
+
   PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
 
   if (anim_mode == ANIM_DEFAULT)
@@ -2840,10 +2968,13 @@ void ShowEnvelope(int envelope_nr)
   AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
 
   if (tape.playing)
-    Delay(wait_delay_value);
+    Delay_WithScreenUpdates(wait_delay_value);
   else
     WaitForEventToContinue();
 
+  RemapAllGadgets();
+  SetOverlayEnabled(overlay_enabled);
+
   PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
 
   if (anim_mode != ANIM_NONE)
@@ -2860,6 +2991,53 @@ void ShowEnvelope(int envelope_nr)
   BackToFront();
 }
 
+static void PrepareEnvelopeRequestToScreen(Bitmap *bitmap, int sx, int sy,
+                                          int xsize, int ysize)
+{
+  if (!global.use_envelope_request ||
+      request.sort_priority <= 0)
+    return;
+
+  if (request.bitmap == NULL ||
+      xsize > request.xsize ||
+      ysize > request.ysize)
+  {
+    if (request.bitmap != NULL)
+      FreeBitmap(request.bitmap);
+
+    request.bitmap = CreateBitmap(xsize, ysize, DEFAULT_DEPTH);
+
+    SDL_Surface *surface = request.bitmap->surface;
+
+    if ((request.bitmap->surface_masked = SDLGetNativeSurface(surface)) == NULL)
+      Fail("SDLGetNativeSurface() failed");
+  }
+
+  BlitBitmap(bitmap, request.bitmap, sx, sy, xsize, ysize, 0, 0);
+
+  SDLFreeBitmapTextures(request.bitmap);
+  SDLCreateBitmapTextures(request.bitmap);
+
+  // set envelope request run-time values
+  request.sx = sx;
+  request.sy = sy;
+  request.xsize = xsize;
+  request.ysize = ysize;
+}
+
+void DrawEnvelopeRequestToScreen(int drawing_target, int drawing_stage)
+{
+  if (global.use_envelope_request &&
+      game.request_active_or_moving &&
+      request.sort_priority > 0 &&
+      drawing_target == DRAW_TO_SCREEN &&
+      drawing_stage == DRAW_GLOBAL_ANIM_STAGE_2)
+  {
+    BlitToScreen(request.bitmap, 0, 0, request.xsize, request.ysize,
+                request.sx, request.sy);
+  }
+}
+
 static void setRequestBasePosition(int *x, int *y)
 {
   int sx_base, sy_base;
@@ -3010,6 +3188,8 @@ static void DrawEnvelopeRequest(char *text)
   // store readily prepared envelope request for later use when animating
   BlitBitmap(backbuffer, bitmap_db_store_2, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
 
+  PrepareEnvelopeRequestToScreen(bitmap_db_store_2, sx, sy, width, height);
+
   if (text_door_style)
     free(text_door_style);
 }
@@ -3091,6 +3271,8 @@ static void AnimateEnvelopeRequest(int anim_mode, int action)
       }
     }
 
+    PrepareEnvelopeRequestToScreen(backbuffer, dst_x, dst_y, width, height);
+
     redraw_mask |= REDRAW_FIELD;
 
     BackToFront();
@@ -3127,10 +3309,13 @@ static void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
     {
       MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
       MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
+      MapGadget(tool_gadget[TOOL_CTRL_ID_TOUCH_YES]);
+      MapGadget(tool_gadget[TOOL_CTRL_ID_TOUCH_NO]);
     }
     else if (req_state & REQ_CONFIRM)
     {
       MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
+      MapGadget(tool_gadget[TOOL_CTRL_ID_TOUCH_CONFIRM]);
     }
     else if (req_state & REQ_PLAYER)
     {
@@ -3399,8 +3584,8 @@ static void DrawPreviewLevelExt(boolean restart)
     DrawPreviewLevelInfo(MICROLABEL_LEVEL_AUTHOR);
 
     // initialize delay counters
-    DelayReached(&scroll_delay, 0);
-    DelayReached(&label_delay, 0);
+    ResetDelayCounter(&scroll_delay);
+    ResetDelayCounter(&label_delay);
 
     if (leveldir_current->name)
     {
@@ -3543,7 +3728,7 @@ void DrawPreviewPlayers(void)
     {
       int element = level.field[x][y];
 
-      if (ELEM_IS_PLAYER(element))
+      if (IS_PLAYER_ELEMENT(element))
       {
        int player_nr = GET_PLAYER_NR(element);
 
@@ -3708,10 +3893,10 @@ void ClearNetworkPlayers(void)
 }
 
 static void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
-                                   int graphic, int sync_frame,
+                                   int graphic, int lx, int ly,
                                    int mask_mode)
 {
-  int frame = getGraphicAnimationFrame(graphic, sync_frame);
+  int frame = getGraphicAnimationFrameXY(graphic, lx, ly);
 
   if (mask_mode == USE_MASKING)
     DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
@@ -3733,12 +3918,23 @@ void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
 static void DrawGraphicAnimation(int x, int y, int graphic)
 {
   int lx = LEVELX(x), ly = LEVELY(y);
+  int mask_mode = NO_MASKING;
 
   if (!IN_SCR_FIELD(x, y))
     return;
 
+  if (game.use_masked_elements)
+  {
+    if (Tile[lx][ly] != EL_EMPTY)
+    {
+      DrawScreenElementExt(x, y, 0, 0, EL_EMPTY, NO_CUTTING, NO_MASKING);
+
+      mask_mode = USE_MASKING;
+    }
+  }
+
   DrawGraphicAnimationExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
-                         graphic, GfxFrame[lx][ly], NO_MASKING);
+                         graphic, lx, ly, mask_mode);
 
   MarkTileDirty(x, y);
 }
@@ -3746,12 +3942,24 @@ static void DrawGraphicAnimation(int x, int y, int graphic)
 void DrawFixedGraphicAnimation(int x, int y, int graphic)
 {
   int lx = LEVELX(x), ly = LEVELY(y);
+  int mask_mode = NO_MASKING;
 
   if (!IN_SCR_FIELD(x, y))
     return;
 
+  if (game.use_masked_elements)
+  {
+    if (Tile[lx][ly] != EL_EMPTY)
+    {
+      DrawScreenElementExt(x, y, 0, 0, EL_EMPTY, NO_CUTTING, NO_MASKING);
+
+      mask_mode = USE_MASKING;
+    }
+  }
+
   DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
-                         graphic, GfxFrame[lx][ly], NO_MASKING);
+                         graphic, lx, ly, mask_mode);
+
   MarkTileDirty(x, y);
 }
 
@@ -3774,16 +3982,22 @@ void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
   if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
     return;
 
+  if (Tile[x][y] == EL_EMPTY)
+    graphic = el2img(GfxElementEmpty[x][y]);
+
   if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
     return;
 
+  if (ANIM_MODE(graphic) & (ANIM_TILED | ANIM_RANDOM_STATIC))
+    return;
+
   DrawGraphicAnimation(sx, sy, graphic);
 
 #if 1
   if (GFX_CRUMBLED(TILE_GFX_ELEMENT(x, y)))
     DrawLevelFieldCrumbled(x, y);
 #else
-  if (GFX_CRUMBLED(Feld[x][y]))
+  if (GFX_CRUMBLED(Tile[x][y]))
     DrawLevelFieldCrumbled(x, y);
 #endif
 }
@@ -3887,8 +4101,8 @@ static void DrawPlayerExt(struct PlayerInfo *player, int drawing_stage)
 #if DEBUG
   if (!IN_LEV_FIELD(player->jx, player->jy))
   {
-    printf("DrawPlayerField(): x = %d, y = %d\n", player->jx, player->jy);
-    printf("DrawPlayerField(): This should never happen!\n");
+    Debug("draw:DrawPlayerExt", "x = %d, y = %d", player->jx, player->jy);
+    Debug("draw:DrawPlayerExt", "This should never happen!");
 
     draw_player[pnr] = FALSE;
 
@@ -3914,8 +4128,8 @@ static void DrawPlayerExt(struct PlayerInfo *player, int drawing_stage)
   int sy = SCREENY(jy);
   int sxx = (move_dir == MV_LEFT || move_dir == MV_RIGHT ? player->GfxPos : 0);
   int syy = (move_dir == MV_UP   || move_dir == MV_DOWN  ? player->GfxPos : 0);
-  int element = Feld[jx][jy];
-  int last_element = Feld[last_jx][last_jy];
+  int element = Tile[jx][jy];
+  int last_element = Tile[last_jx][last_jy];
   int action = (player->is_pushing    ? ACTION_PUSHING         :
                player->is_digging    ? ACTION_DIGGING         :
                player->is_collecting ? ACTION_COLLECTING      :
@@ -4010,7 +4224,7 @@ static void DrawPlayerExt(struct PlayerInfo *player, int drawing_stage)
       if (GFX_CRUMBLED(old_element))
        DrawLevelFieldCrumbledDigging(jx, jy, move_dir, player->StepFrame);
       else
-       DrawGraphic(sx, sy, old_graphic, frame);
+       DrawScreenGraphic(sx, sy, old_graphic, frame);
 
       if (graphic_info[old_graphic].anim_mode & ANIM_OPAQUE_PLAYER)
        static_player_is_opaque[pnr] = TRUE;
@@ -4041,7 +4255,7 @@ static void DrawPlayerExt(struct PlayerInfo *player, int drawing_stage)
 
     if (!IS_MOVING(jx, jy))            // push movement already finished
     {
-      element = Feld[next_jx][next_jy];
+      element = Tile[next_jx][next_jy];
       gfx_frame = GfxFrame[next_jx][next_jy];
     }
 
@@ -4075,7 +4289,7 @@ static void DrawPlayerExt(struct PlayerInfo *player, int drawing_stage)
     // do not draw (EM style) pushing animation when pushing is finished
     // (two-tile animations usually do not contain start and end frame)
     if (graphic_info[graphic].double_movement && !IS_MOVING(jx, jy))
-      DrawLevelElement(next_jx, next_jy, Feld[next_jx][next_jy]);
+      DrawLevelElement(next_jx, next_jy, Tile[next_jx][next_jy]);
     else
       DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
 #else
@@ -4122,7 +4336,7 @@ static void DrawPlayerExt(struct PlayerInfo *player, int drawing_stage)
     if (IS_ACTIVE_BOMB(element))
     {
       int graphic = el2img(element);
-      int frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
+      int frame = getGraphicAnimationFrameXY(graphic, jx, jy);
 
       if (game.emulation == EMU_SUPAPLEX)
        DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
@@ -4202,6 +4416,7 @@ void DrawPlayerField(int x, int y)
 
 void WaitForEventToContinue(void)
 {
+  boolean first_wait = TRUE;
   boolean still_wait = TRUE;
 
   if (program.headless)
@@ -4214,6 +4429,7 @@ void WaitForEventToContinue(void)
   button_status = MB_RELEASED;
 
   ClearEventQueue();
+  ClearPlayerAction();
 
   while (still_wait)
   {
@@ -4223,17 +4439,22 @@ void WaitForEventToContinue(void)
     {
       switch (event.type)
       {
-       case EVENT_BUTTONRELEASE:
+       case EVENT_BUTTONPRESS:
+        case EVENT_FINGERPRESS:
+         first_wait = FALSE;
+         break;
+
+        case EVENT_BUTTONRELEASE:
+        case EVENT_FINGERRELEASE:
+         still_wait = first_wait;
+         break;
+
        case EVENT_KEYPRESS:
         case SDL_CONTROLLERBUTTONDOWN:
         case SDL_JOYBUTTONDOWN:
          still_wait = FALSE;
          break;
 
-       case EVENT_KEYRELEASE:
-         ClearPlayerAction();
-         break;
-
        default:
          HandleOtherEvents(&event);
          break;
@@ -4244,7 +4465,8 @@ void WaitForEventToContinue(void)
       still_wait = FALSE;
     }
 
-    BackToFront();
+    if (!PendingEvent())
+      BackToFront();
   }
 }
 
@@ -4252,10 +4474,11 @@ void WaitForEventToContinue(void)
 #define MAX_REQUEST_LINE_FONT1_LEN     7
 #define MAX_REQUEST_LINE_FONT2_LEN     10
 
-static int RequestHandleEvents(unsigned int req_state)
+static int RequestHandleEvents(unsigned int req_state, int draw_buffer_game)
 {
   boolean game_just_ended = (game_status == GAME_MODE_PLAYING &&
                             checkGameEnded());
+  int draw_buffer_last = GetDrawtoField();
   int width  = request.width;
   int height = request.height;
   int sx, sy;
@@ -4276,11 +4499,11 @@ static int RequestHandleEvents(unsigned int req_state)
 
   while (result < 0)
   {
+    boolean event_handled = FALSE;
+
     if (game_just_ended)
     {
-      // the MM game engine does not use a special (scrollable) field buffer
-      if (level.game_engine_type != GAME_ENGINE_TYPE_MM)
-       SetDrawtoField(DRAW_TO_FIELDBUFFER);
+      SetDrawtoField(draw_buffer_game);
 
       HandleGameActions();
 
@@ -4299,6 +4522,8 @@ static int RequestHandleEvents(unsigned int req_state)
 
       while (NextValidEvent(&event))
       {
+       event_handled = TRUE;
+
        switch (event.type)
        {
          case EVENT_BUTTONPRESS:
@@ -4333,12 +4558,15 @@ static int RequestHandleEvents(unsigned int req_state)
            switch (request_gadget_id)
            {
              case TOOL_CTRL_ID_YES:
+             case TOOL_CTRL_ID_TOUCH_YES:
                result = TRUE;
                break;
              case TOOL_CTRL_ID_NO:
+             case TOOL_CTRL_ID_TOUCH_NO:
                result = FALSE;
                break;
              case TOOL_CTRL_ID_CONFIRM:
+             case TOOL_CTRL_ID_TOUCH_CONFIRM:
                result = TRUE | FALSE;
                break;
 
@@ -4356,6 +4584,8 @@ static int RequestHandleEvents(unsigned int req_state)
                break;
 
              default:
+               // only check clickable animations if no request gadget clicked
+               HandleGlobalAnimClicks(mx, my, button_status, FALSE);
                break;
            }
 
@@ -4451,6 +4681,7 @@ static int RequestHandleEvents(unsigned int req_state)
            break;
          }
 
+         case EVENT_FINGERRELEASE:
          case EVENT_KEYRELEASE:
            ClearPlayerAction();
            break;
@@ -4547,18 +4778,25 @@ static int RequestHandleEvents(unsigned int req_state)
       }
     }
 
-    if (game_just_ended)
+    if (event_handled)
     {
-      if (global.use_envelope_request)
+      if (game_just_ended)
       {
-       // copy back current state of pressed buttons inside request area
-       BlitBitmap(drawto, bitmap_db_store_2, sx, sy, width, height, sx, sy);
+       if (global.use_envelope_request)
+       {
+         // copy back current state of pressed buttons inside request area
+         BlitBitmap(drawto, bitmap_db_store_2, sx, sy, width, height, sx, sy);
+       }
       }
+
+      PrepareEnvelopeRequestToScreen(drawto, sx, sy, width, height);
     }
 
     BackToFront();
   }
 
+  SetDrawtoField(draw_buffer_last);
+
   game.request_active = FALSE;
 
   return result;
@@ -4566,6 +4804,7 @@ static int RequestHandleEvents(unsigned int req_state)
 
 static boolean RequestDoor(char *text, unsigned int req_state)
 {
+  int draw_buffer_last = GetDrawtoField();
   unsigned int old_door_state;
   int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
   int font_nr = FONT_TEXT_2;
@@ -4668,10 +4907,13 @@ static boolean RequestDoor(char *text, unsigned int req_state)
   {
     MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
     MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
+    MapGadget(tool_gadget[TOOL_CTRL_ID_TOUCH_YES]);
+    MapGadget(tool_gadget[TOOL_CTRL_ID_TOUCH_NO]);
   }
   else if (req_state & REQ_CONFIRM)
   {
     MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
+    MapGadget(tool_gadget[TOOL_CTRL_ID_TOUCH_CONFIRM]);
   }
   else if (req_state & REQ_PLAYER)
   {
@@ -4704,7 +4946,7 @@ static boolean RequestDoor(char *text, unsigned int req_state)
   SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
 
   // ---------- handle request buttons ----------
-  result = RequestHandleEvents(req_state);
+  result = RequestHandleEvents(req_state, draw_buffer_last);
 
   UnmapToolButtons();
 
@@ -4745,6 +4987,7 @@ static boolean RequestDoor(char *text, unsigned int req_state)
 
 static boolean RequestEnvelope(char *text, unsigned int req_state)
 {
+  int draw_buffer_last = GetDrawtoField();
   int result;
 
   if (game_status == GAME_MODE_PLAYING)
@@ -4796,7 +5039,7 @@ static boolean RequestEnvelope(char *text, unsigned int req_state)
   SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
 
   // ---------- handle request buttons ----------
-  result = RequestHandleEvents(req_state);
+  result = RequestHandleEvents(req_state, draw_buffer_last);
 
   UnmapToolButtons();
 
@@ -4833,6 +5076,8 @@ boolean Request(char *text, unsigned int req_state)
   boolean overlay_enabled = GetOverlayEnabled();
   boolean result;
 
+  game.request_active_or_moving = TRUE;
+
   SetOverlayEnabled(FALSE);
 
   if (global.use_envelope_request)
@@ -4842,6 +5087,8 @@ boolean Request(char *text, unsigned int req_state)
 
   SetOverlayEnabled(overlay_enabled);
 
+  game.request_active_or_moving = FALSE;
+
   return result;
 }
 
@@ -5156,7 +5403,6 @@ unsigned int MoveDoor(unsigned int door_state)
     int num_move_steps = 0;    // number of animation steps for all doors
     int max_move_delay_doors_only = 0; // delay for doors only (no panel)
     int num_move_steps_doors_only = 0; // steps for doors only (no panel)
-    int current_move_delay = 0;
     int start = 0;
     int k;
 
@@ -5349,7 +5595,7 @@ unsigned int MoveDoor(unsigned int door_state)
          if (width > door_rect->width)
            width = door_rect->width;
 
-         // printf("::: k == %d [%d] \n", k, start_step);
+         // Debug("tools:MoveDoor", "k == %d [%d]", k, start_step);
        }
 
        if (pos->step_yoffset < 0)      // door part on bottom side
@@ -5416,8 +5662,6 @@ unsigned int MoveDoor(unsigned int door_state)
 
        SkipUntilDelayReached(&door_delay, door_delay_value, &k, last_frame);
 
-       current_move_delay += max_step_delay;
-
        // prevent OS (Windows) from complaining about program not responding
        CheckQuitEvent();
       }
@@ -5543,36 +5787,49 @@ static struct
   int graphic;
   struct TextPosInfo *pos;
   int gadget_id;
+  boolean is_touch_button;
   char *infotext;
 } toolbutton_info[NUM_TOOL_BUTTONS] =
 {
   {
     IMG_GFX_REQUEST_BUTTON_YES,                &request.button.yes,
-    TOOL_CTRL_ID_YES,                  "yes"
+    TOOL_CTRL_ID_YES, FALSE,           "yes"
   },
   {
     IMG_GFX_REQUEST_BUTTON_NO,         &request.button.no,
-    TOOL_CTRL_ID_NO,                   "no"
+    TOOL_CTRL_ID_NO, FALSE,            "no"
   },
   {
     IMG_GFX_REQUEST_BUTTON_CONFIRM,    &request.button.confirm,
-    TOOL_CTRL_ID_CONFIRM,              "confirm"
+    TOOL_CTRL_ID_CONFIRM, FALSE,       "confirm"
   },
   {
     IMG_GFX_REQUEST_BUTTON_PLAYER_1,   &request.button.player_1,
-    TOOL_CTRL_ID_PLAYER_1,             "player 1"
+    TOOL_CTRL_ID_PLAYER_1, FALSE,      "player 1"
   },
   {
     IMG_GFX_REQUEST_BUTTON_PLAYER_2,   &request.button.player_2,
-    TOOL_CTRL_ID_PLAYER_2,             "player 2"
+    TOOL_CTRL_ID_PLAYER_2, FALSE,      "player 2"
   },
   {
     IMG_GFX_REQUEST_BUTTON_PLAYER_3,   &request.button.player_3,
-    TOOL_CTRL_ID_PLAYER_3,             "player 3"
+    TOOL_CTRL_ID_PLAYER_3, FALSE,      "player 3"
   },
   {
     IMG_GFX_REQUEST_BUTTON_PLAYER_4,   &request.button.player_4,
-    TOOL_CTRL_ID_PLAYER_4,             "player 4"
+    TOOL_CTRL_ID_PLAYER_4, FALSE,      "player 4"
+  },
+  {
+    IMG_GFX_REQUEST_BUTTON_TOUCH_YES,  &request.button.touch_yes,
+    TOOL_CTRL_ID_TOUCH_YES, TRUE,      "yes"
+  },
+  {
+    IMG_GFX_REQUEST_BUTTON_TOUCH_NO,   &request.button.touch_no,
+    TOOL_CTRL_ID_TOUCH_NO, TRUE,       "no"
+  },
+  {
+    IMG_GFX_REQUEST_BUTTON_TOUCH_CONFIRM, &request.button.touch_confirm,
+    TOOL_CTRL_ID_TOUCH_CONFIRM, TRUE,  "confirm"
   }
 };
 
@@ -5589,8 +5846,9 @@ void CreateToolButtons(void)
     Bitmap *deco_bitmap = None;
     int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
     unsigned int event_mask = GD_EVENT_RELEASED;
-    int dx = DX;
-    int dy = DY;
+    boolean is_touch_button = toolbutton_info[i].is_touch_button;
+    int base_x = (is_touch_button ? 0 : DX);
+    int base_y = (is_touch_button ? 0 : DY);
     int gd_x = gfx->src_x;
     int gd_y = gfx->src_y;
     int gd_xp = gfx->src_x + gfx->pressed_xoffset;
@@ -5599,9 +5857,13 @@ void CreateToolButtons(void)
     int y = pos->y;
     int id = i;
 
-    if (global.use_envelope_request)
+    // do not use touch buttons if overlay touch buttons are disabled
+    if (is_touch_button && !setup.touch.overlay_buttons)
+      continue;
+
+    if (global.use_envelope_request && !is_touch_button)
     {
-      setRequestPosition(&dx, &dy, TRUE);
+      setRequestPosition(&base_x, &base_y, TRUE);
 
       // check if request buttons are outside of envelope and fix, if needed
       if (x < 0 || x + gfx->width  > request.width ||
@@ -5648,8 +5910,8 @@ void CreateToolButtons(void)
     gi = CreateGadget(GDI_CUSTOM_ID, id,
                      GDI_IMAGE_ID, graphic,
                      GDI_INFO_TEXT, toolbutton_info[i].infotext,
-                     GDI_X, dx + x,
-                     GDI_Y, dy + y,
+                     GDI_X, base_x + x,
+                     GDI_Y, base_y + y,
                      GDI_WIDTH, gfx->width,
                      GDI_HEIGHT, gfx->height,
                      GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
@@ -5661,12 +5923,13 @@ void CreateToolButtons(void)
                      GDI_DECORATION_SIZE, pos->size, pos->size,
                      GDI_DECORATION_SHIFTING, 1, 1,
                      GDI_DIRECT_DRAW, FALSE,
+                     GDI_OVERLAY_TOUCH_BUTTON, is_touch_button,
                      GDI_EVENT_MASK, event_mask,
                      GDI_CALLBACK_ACTION, HandleToolButtons,
                      GDI_END);
 
     if (gi == NULL)
-      Error(ERR_EXIT, "cannot create gadget");
+      Fail("cannot create gadget");
 
     tool_gadget[id] = gi;
   }
@@ -5703,616 +5966,644 @@ static struct Mapping_EM_to_RND_object
   int action;
   int direction;
 }
-em_object_mapping_list[] =
+em_object_mapping_list[GAME_TILE_MAX + 1] =
 {
   {
-    Xblank,                            TRUE,   FALSE,
+    Zborder,                           FALSE,  FALSE,
     EL_EMPTY,                          -1, -1
   },
   {
-    Yacid_splash_eB,                   FALSE,  FALSE,
-    EL_ACID_SPLASH_RIGHT,              -1, -1
-  },
-  {
-    Yacid_splash_wB,                   FALSE,  FALSE,
-    EL_ACID_SPLASH_LEFT,               -1, -1
+    Zplayer,                           FALSE,  FALSE,
+    EL_EMPTY,                          -1, -1
   },
 
-#ifdef EM_ENGINE_BAD_ROLL
   {
-    Xstone_force_e,                    FALSE,  FALSE,
-    EL_ROCK,                           -1, MV_BIT_RIGHT
+    Zbug,                              FALSE,  FALSE,
+    EL_EMPTY,                          -1, -1
   },
   {
-    Xstone_force_w,                    FALSE,  FALSE,
-    EL_ROCK,                           -1, MV_BIT_LEFT
+    Ztank,                             FALSE,  FALSE,
+    EL_EMPTY,                          -1, -1
   },
   {
-    Xnut_force_e,                      FALSE,  FALSE,
-    EL_NUT,                            -1, MV_BIT_RIGHT
+    Zeater,                            FALSE,  FALSE,
+    EL_EMPTY,                          -1, -1
   },
   {
-    Xnut_force_w,                      FALSE,  FALSE,
-    EL_NUT,                            -1, MV_BIT_LEFT
+    Zdynamite,                         FALSE,  FALSE,
+    EL_EMPTY,                          -1, -1
   },
   {
-    Xspring_force_e,                   FALSE,  FALSE,
-    EL_SPRING,                         -1, MV_BIT_RIGHT
+    Zboom,                             FALSE,  FALSE,
+    EL_EMPTY,                          -1, -1
   },
+
   {
-    Xspring_force_w,                   FALSE,  FALSE,
-    EL_SPRING,                         -1, MV_BIT_LEFT
+    Xchain,                            FALSE,  FALSE,
+    EL_DEFAULT,                                ACTION_EXPLODING, -1
   },
   {
-    Xemerald_force_e,                  FALSE,  FALSE,
-    EL_EMERALD,                                -1, MV_BIT_RIGHT
+    Xboom_bug,                         FALSE,  FALSE,
+    EL_BUG,                            ACTION_EXPLODING, -1
   },
   {
-    Xemerald_force_w,                  FALSE,  FALSE,
-    EL_EMERALD,                                -1, MV_BIT_LEFT
+    Xboom_tank,                                FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_EXPLODING, -1
   },
   {
-    Xdiamond_force_e,                  FALSE,  FALSE,
-    EL_DIAMOND,                                -1, MV_BIT_RIGHT
+    Xboom_android,                     FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_OTHER, -1
   },
   {
-    Xdiamond_force_w,                  FALSE,  FALSE,
-    EL_DIAMOND,                                -1, MV_BIT_LEFT
+    Xboom_1,                           FALSE,  FALSE,
+    EL_DEFAULT,                                ACTION_EXPLODING, -1
   },
   {
-    Xbomb_force_e,                     FALSE,  FALSE,
-    EL_BOMB,                           -1, MV_BIT_RIGHT
+    Xboom_2,                           FALSE,  FALSE,
+    EL_DEFAULT,                                ACTION_EXPLODING, -1
   },
+
   {
-    Xbomb_force_w,                     FALSE,  FALSE,
-    EL_BOMB,                           -1, MV_BIT_LEFT
+    Xblank,                            TRUE,   FALSE,
+    EL_EMPTY,                          -1, -1
   },
-#endif // EM_ENGINE_BAD_ROLL
 
   {
-    Xstone,                            TRUE,   FALSE,
-    EL_ROCK,                           -1, -1
+    Xsplash_e,                         FALSE,  FALSE,
+    EL_ACID_SPLASH_RIGHT,              -1, -1
   },
   {
-    Xstone_pause,                      FALSE,  FALSE,
-    EL_ROCK,                           -1, -1
+    Xsplash_w,                         FALSE,  FALSE,
+    EL_ACID_SPLASH_LEFT,               -1, -1
   },
+
   {
-    Xstone_fall,                       FALSE,  FALSE,
-    EL_ROCK,                           -1, -1
+    Xplant,                            TRUE,   FALSE,
+    EL_EMC_PLANT,                      -1, -1
   },
   {
-    Ystone_s,                          FALSE,  FALSE,
-    EL_ROCK,                           ACTION_FALLING, -1
+    Yplant,                            FALSE,  FALSE,
+    EL_EMC_PLANT,                      -1, -1
   },
+
   {
-    Ystone_sB,                         FALSE,  TRUE,
-    EL_ROCK,                           ACTION_FALLING, -1
+    Xacid_1,                           TRUE,   FALSE,
+    EL_ACID,                           -1, -1
   },
   {
-    Ystone_e,                          FALSE,  FALSE,
-    EL_ROCK,                           ACTION_MOVING, MV_BIT_RIGHT
+    Xacid_2,                           FALSE,  FALSE,
+    EL_ACID,                           -1, -1
   },
   {
-    Ystone_eB,                         FALSE,  TRUE,
-    EL_ROCK,                           ACTION_MOVING, MV_BIT_RIGHT
+    Xacid_3,                           FALSE,  FALSE,
+    EL_ACID,                           -1, -1
   },
   {
-    Ystone_w,                          FALSE,  FALSE,
-    EL_ROCK,                           ACTION_MOVING, MV_BIT_LEFT
+    Xacid_4,                           FALSE,  FALSE,
+    EL_ACID,                           -1, -1
   },
   {
-    Ystone_wB,                         FALSE,  TRUE,
-    EL_ROCK,                           ACTION_MOVING, MV_BIT_LEFT
+    Xacid_5,                           FALSE,  FALSE,
+    EL_ACID,                           -1, -1
   },
   {
-    Xnut,                              TRUE,   FALSE,
-    EL_NUT,                            -1, -1
+    Xacid_6,                           FALSE,  FALSE,
+    EL_ACID,                           -1, -1
   },
   {
-    Xnut_pause,                                FALSE,  FALSE,
-    EL_NUT,                            -1, -1
+    Xacid_7,                           FALSE,  FALSE,
+    EL_ACID,                           -1, -1
   },
   {
-    Xnut_fall,                         FALSE,  FALSE,
-    EL_NUT,                            -1, -1
+    Xacid_8,                           FALSE,  FALSE,
+    EL_ACID,                           -1, -1
   },
+
   {
-    Ynut_s,                            FALSE,  FALSE,
-    EL_NUT,                            ACTION_FALLING, -1
+    Xfake_acid_1,                      TRUE,   FALSE,
+    EL_EMC_FAKE_ACID,                  -1, -1
   },
   {
-    Ynut_sB,                           FALSE,  TRUE,
-    EL_NUT,                            ACTION_FALLING, -1
+    Xfake_acid_2,                      FALSE,  FALSE,
+    EL_EMC_FAKE_ACID,                  -1, -1
   },
   {
-    Ynut_e,                            FALSE,  FALSE,
-    EL_NUT,                            ACTION_MOVING, MV_BIT_RIGHT
+    Xfake_acid_3,                      FALSE,  FALSE,
+    EL_EMC_FAKE_ACID,                  -1, -1
   },
   {
-    Ynut_eB,                           FALSE,  TRUE,
-    EL_NUT,                            ACTION_MOVING, MV_BIT_RIGHT
+    Xfake_acid_4,                      FALSE,  FALSE,
+    EL_EMC_FAKE_ACID,                  -1, -1
   },
   {
-    Ynut_w,                            FALSE,  FALSE,
-    EL_NUT,                            ACTION_MOVING, MV_BIT_LEFT
+    Xfake_acid_5,                      FALSE,  FALSE,
+    EL_EMC_FAKE_ACID,                  -1, -1
   },
   {
-    Ynut_wB,                           FALSE,  TRUE,
-    EL_NUT,                            ACTION_MOVING, MV_BIT_LEFT
+    Xfake_acid_6,                      FALSE,  FALSE,
+    EL_EMC_FAKE_ACID,                  -1, -1
   },
   {
-    Xbug_n,                            TRUE,   FALSE,
-    EL_BUG_UP,                         -1, -1
+    Xfake_acid_7,                      FALSE,  FALSE,
+    EL_EMC_FAKE_ACID,                  -1, -1
   },
   {
-    Xbug_e,                            TRUE,   FALSE,
-    EL_BUG_RIGHT,                      -1, -1
+    Xfake_acid_8,                      FALSE,  FALSE,
+    EL_EMC_FAKE_ACID,                  -1, -1
   },
+
   {
-    Xbug_s,                            TRUE,   FALSE,
-    EL_BUG_DOWN,                       -1, -1
+    Xfake_acid_1_player,               FALSE,  FALSE,
+    EL_EMC_FAKE_ACID,                  -1, -1
   },
   {
-    Xbug_w,                            TRUE,   FALSE,
-    EL_BUG_LEFT,                       -1, -1
+    Xfake_acid_2_player,               FALSE,  FALSE,
+    EL_EMC_FAKE_ACID,                  -1, -1
   },
   {
-    Xbug_gon,                          FALSE,  FALSE,
-    EL_BUG_UP,                         -1, -1
+    Xfake_acid_3_player,               FALSE,  FALSE,
+    EL_EMC_FAKE_ACID,                  -1, -1
   },
   {
-    Xbug_goe,                          FALSE,  FALSE,
-    EL_BUG_RIGHT,                      -1, -1
+    Xfake_acid_4_player,               FALSE,  FALSE,
+    EL_EMC_FAKE_ACID,                  -1, -1
   },
   {
-    Xbug_gos,                          FALSE,  FALSE,
-    EL_BUG_DOWN,                       -1, -1
+    Xfake_acid_5_player,               FALSE,  FALSE,
+    EL_EMC_FAKE_ACID,                  -1, -1
   },
   {
-    Xbug_gow,                          FALSE,  FALSE,
-    EL_BUG_LEFT,                       -1, -1
+    Xfake_acid_6_player,               FALSE,  FALSE,
+    EL_EMC_FAKE_ACID,                  -1, -1
   },
   {
-    Ybug_n,                            FALSE,  FALSE,
-    EL_BUG,                            ACTION_MOVING, MV_BIT_UP
+    Xfake_acid_7_player,               FALSE,  FALSE,
+    EL_EMC_FAKE_ACID,                  -1, -1
   },
   {
-    Ybug_nB,                           FALSE,  TRUE,
-    EL_BUG,                            ACTION_MOVING, MV_BIT_UP
+    Xfake_acid_8_player,               FALSE,  FALSE,
+    EL_EMC_FAKE_ACID,                  -1, -1
   },
+
   {
-    Ybug_e,                            FALSE,  FALSE,
-    EL_BUG,                            ACTION_MOVING, MV_BIT_RIGHT
+    Xgrass,                            TRUE,   FALSE,
+    EL_EMC_GRASS,                      -1, -1
   },
   {
-    Ybug_eB,                           FALSE,  TRUE,
-    EL_BUG,                            ACTION_MOVING, MV_BIT_RIGHT
+    Ygrass_nB,                         FALSE,  FALSE,
+    EL_EMC_GRASS,                      ACTION_DIGGING, MV_BIT_UP
   },
   {
-    Ybug_s,                            FALSE,  FALSE,
-    EL_BUG,                            ACTION_MOVING, MV_BIT_DOWN
+    Ygrass_eB,                         FALSE,  FALSE,
+    EL_EMC_GRASS,                      ACTION_DIGGING, MV_BIT_RIGHT
   },
   {
-    Ybug_sB,                           FALSE,  TRUE,
-    EL_BUG,                            ACTION_MOVING, MV_BIT_DOWN
+    Ygrass_sB,                         FALSE,  FALSE,
+    EL_EMC_GRASS,                      ACTION_DIGGING, MV_BIT_DOWN
   },
   {
-    Ybug_w,                            FALSE,  FALSE,
-    EL_BUG,                            ACTION_MOVING, MV_BIT_LEFT
+    Ygrass_wB,                         FALSE,  FALSE,
+    EL_EMC_GRASS,                      ACTION_DIGGING, MV_BIT_LEFT
   },
+
   {
-    Ybug_wB,                           FALSE,  TRUE,
-    EL_BUG,                            ACTION_MOVING, MV_BIT_LEFT
+    Xdirt,                             TRUE,   FALSE,
+    EL_SAND,                           -1, -1
   },
   {
-    Ybug_w_n,                          FALSE,  FALSE,
-    EL_BUG,                            ACTION_TURNING_FROM_LEFT, MV_BIT_UP
+    Ydirt_nB,                          FALSE,  FALSE,
+    EL_SAND,                           ACTION_DIGGING, MV_BIT_UP
   },
   {
-    Ybug_n_e,                          FALSE,  FALSE,
-    EL_BUG,                            ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
+    Ydirt_eB,                          FALSE,  FALSE,
+    EL_SAND,                           ACTION_DIGGING, MV_BIT_RIGHT
   },
   {
-    Ybug_e_s,                          FALSE,  FALSE,
-    EL_BUG,                            ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
+    Ydirt_sB,                          FALSE,  FALSE,
+    EL_SAND,                           ACTION_DIGGING, MV_BIT_DOWN
   },
   {
-    Ybug_s_w,                          FALSE,  FALSE,
-    EL_BUG,                            ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
+    Ydirt_wB,                          FALSE,  FALSE,
+    EL_SAND,                           ACTION_DIGGING, MV_BIT_LEFT
   },
+
   {
-    Ybug_e_n,                          FALSE,  FALSE,
-    EL_BUG,                            ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
+    Xandroid,                          TRUE,   FALSE,
+    EL_EMC_ANDROID,                    ACTION_ACTIVE, -1
   },
   {
-    Ybug_s_e,                          FALSE,  FALSE,
-    EL_BUG,                            ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
+    Xandroid_1_n,                      FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_UP
   },
   {
-    Ybug_w_s,                          FALSE,  FALSE,
-    EL_BUG,                            ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
+    Xandroid_2_n,                      FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_UP
   },
   {
-    Ybug_n_w,                          FALSE,  FALSE,
-    EL_BUG,                            ACTION_TURNING_FROM_UP, MV_BIT_LEFT
+    Xandroid_1_e,                      FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_RIGHT
   },
   {
-    Ybug_stone,                                FALSE,  FALSE,
-    EL_BUG,                            ACTION_SMASHED_BY_ROCK, -1
+    Xandroid_2_e,                      FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_RIGHT
   },
   {
-    Ybug_spring,                       FALSE,  FALSE,
-    EL_BUG,                            ACTION_SMASHED_BY_SPRING, -1
+    Xandroid_1_w,                      FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_LEFT
   },
   {
-    Xtank_n,                           TRUE,   FALSE,
-    EL_SPACESHIP_UP,                   -1, -1
+    Xandroid_2_w,                      FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_LEFT
   },
   {
-    Xtank_e,                           TRUE,   FALSE,
-    EL_SPACESHIP_RIGHT,                        -1, -1
+    Xandroid_1_s,                      FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_DOWN
   },
   {
-    Xtank_s,                           TRUE,   FALSE,
-    EL_SPACESHIP_DOWN,                 -1, -1
+    Xandroid_2_s,                      FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_DOWN
   },
   {
-    Xtank_w,                           TRUE,   FALSE,
-    EL_SPACESHIP_LEFT,                 -1, -1
+    Yandroid_n,                                FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_UP
   },
   {
-    Xtank_gon,                         FALSE,  FALSE,
-    EL_SPACESHIP_UP,                   -1, -1
+    Yandroid_nB,                       FALSE,  TRUE,
+    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_UP
   },
   {
-    Xtank_goe,                         FALSE,  FALSE,
-    EL_SPACESHIP_RIGHT,                        -1, -1
+    Yandroid_ne,                       FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_GROWING, MV_BIT_UPRIGHT
   },
   {
-    Xtank_gos,                         FALSE,  FALSE,
-    EL_SPACESHIP_DOWN,                 -1, -1
+    Yandroid_neB,                      FALSE,  TRUE,
+    EL_EMC_ANDROID,                    ACTION_SHRINKING, MV_BIT_UPRIGHT
   },
   {
-    Xtank_gow,                         FALSE,  FALSE,
-    EL_SPACESHIP_LEFT,                 -1, -1
+    Yandroid_e,                                FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_RIGHT
   },
   {
-    Ytank_n,                           FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_UP
+    Yandroid_eB,                       FALSE,  TRUE,
+    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_RIGHT
   },
   {
-    Ytank_nB,                          FALSE,  TRUE,
-    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_UP
+    Yandroid_se,                       FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_GROWING, MV_BIT_DOWNRIGHT
   },
   {
-    Ytank_e,                           FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_RIGHT
+    Yandroid_seB,                      FALSE,  TRUE,
+    EL_EMC_ANDROID,                    ACTION_SHRINKING, MV_BIT_DOWNRIGHT
   },
   {
-    Ytank_eB,                          FALSE,  TRUE,
-    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_RIGHT
+    Yandroid_s,                                FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_DOWN
   },
   {
-    Ytank_s,                           FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_DOWN
+    Yandroid_sB,                       FALSE,  TRUE,
+    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_DOWN
   },
   {
-    Ytank_sB,                          FALSE,  TRUE,
-    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_DOWN
+    Yandroid_sw,                       FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_GROWING, MV_BIT_DOWNLEFT
   },
   {
-    Ytank_w,                           FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_LEFT
+    Yandroid_swB,                      FALSE,  TRUE,
+    EL_EMC_ANDROID,                    ACTION_SHRINKING, MV_BIT_DOWNLEFT
   },
   {
-    Ytank_wB,                          FALSE,  TRUE,
-    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_LEFT
+    Yandroid_w,                                FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Ytank_w_n,                         FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_TURNING_FROM_LEFT, MV_BIT_UP
+    Yandroid_wB,                       FALSE,  TRUE,
+    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Ytank_n_e,                         FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
+    Yandroid_nw,                       FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_GROWING, MV_BIT_UPLEFT
   },
   {
-    Ytank_e_s,                         FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
+    Yandroid_nwB,                      FALSE,  TRUE,
+    EL_EMC_ANDROID,                    ACTION_SHRINKING, MV_BIT_UPLEFT
   },
+
   {
-    Ytank_s_w,                         FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
+    Xeater_n,                          TRUE,   FALSE,
+    EL_YAMYAM_UP,                      -1, -1
   },
   {
-    Ytank_e_n,                         FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
+    Xeater_e,                          TRUE,   FALSE,
+    EL_YAMYAM_RIGHT,                   -1, -1
   },
   {
-    Ytank_s_e,                         FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
+    Xeater_w,                          TRUE,   FALSE,
+    EL_YAMYAM_LEFT,                    -1, -1
   },
   {
-    Ytank_w_s,                         FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
+    Xeater_s,                          TRUE,   FALSE,
+    EL_YAMYAM_DOWN,                    -1, -1
   },
   {
-    Ytank_n_w,                         FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_TURNING_FROM_UP, MV_BIT_LEFT
+    Yeater_n,                          FALSE,  FALSE,
+    EL_YAMYAM,                         ACTION_MOVING, MV_BIT_UP
   },
   {
-    Ytank_stone,                       FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_SMASHED_BY_ROCK, -1
+    Yeater_nB,                         FALSE,  TRUE,
+    EL_YAMYAM,                         ACTION_MOVING, MV_BIT_UP
   },
   {
-    Ytank_spring,                      FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_SMASHED_BY_SPRING, -1
+    Yeater_e,                          FALSE,  FALSE,
+    EL_YAMYAM,                         ACTION_MOVING, MV_BIT_RIGHT
   },
   {
-    Xandroid,                          TRUE,   FALSE,
-    EL_EMC_ANDROID,                    ACTION_ACTIVE, -1
+    Yeater_eB,                         FALSE,  TRUE,
+    EL_YAMYAM,                         ACTION_MOVING, MV_BIT_RIGHT
   },
   {
-    Xandroid_1_n,                      FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_UP
+    Yeater_s,                          FALSE,  FALSE,
+    EL_YAMYAM,                         ACTION_MOVING, MV_BIT_DOWN
   },
   {
-    Xandroid_2_n,                      FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_UP
+    Yeater_sB,                         FALSE,  TRUE,
+    EL_YAMYAM,                         ACTION_MOVING, MV_BIT_DOWN
   },
   {
-    Xandroid_1_e,                      FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_RIGHT
+    Yeater_w,                          FALSE,  FALSE,
+    EL_YAMYAM,                         ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Xandroid_2_e,                      FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_RIGHT
+    Yeater_wB,                         FALSE,  TRUE,
+    EL_YAMYAM,                         ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Xandroid_1_w,                      FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_LEFT
+    Yeater_stone,                      FALSE,  FALSE,
+    EL_YAMYAM,                         ACTION_SMASHED_BY_ROCK, -1
   },
   {
-    Xandroid_2_w,                      FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_LEFT
+    Yeater_spring,                     FALSE,  FALSE,
+    EL_YAMYAM,                         ACTION_SMASHED_BY_SPRING, -1
   },
+
   {
-    Xandroid_1_s,                      FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_DOWN
+    Xalien,                            TRUE,   FALSE,
+    EL_ROBOT,                          -1, -1
   },
   {
-    Xandroid_2_s,                      FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_DOWN
+    Xalien_pause,                      FALSE,  FALSE,
+    EL_ROBOT,                          -1, -1
   },
   {
-    Yandroid_n,                                FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_UP
+    Yalien_n,                          FALSE,  FALSE,
+    EL_ROBOT,                          ACTION_MOVING, MV_BIT_UP
   },
   {
-    Yandroid_nB,                       FALSE,  TRUE,
-    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_UP
+    Yalien_nB,                         FALSE,  TRUE,
+    EL_ROBOT,                          ACTION_MOVING, MV_BIT_UP
   },
   {
-    Yandroid_ne,                       FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_GROWING, MV_BIT_UPRIGHT
+    Yalien_e,                          FALSE,  FALSE,
+    EL_ROBOT,                          ACTION_MOVING, MV_BIT_RIGHT
   },
   {
-    Yandroid_neB,                      FALSE,  TRUE,
-    EL_EMC_ANDROID,                    ACTION_SHRINKING, MV_BIT_UPRIGHT
+    Yalien_eB,                         FALSE,  TRUE,
+    EL_ROBOT,                          ACTION_MOVING, MV_BIT_RIGHT
   },
   {
-    Yandroid_e,                                FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_RIGHT
+    Yalien_s,                          FALSE,  FALSE,
+    EL_ROBOT,                          ACTION_MOVING, MV_BIT_DOWN
   },
   {
-    Yandroid_eB,                       FALSE,  TRUE,
-    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_RIGHT
+    Yalien_sB,                         FALSE,  TRUE,
+    EL_ROBOT,                          ACTION_MOVING, MV_BIT_DOWN
   },
   {
-    Yandroid_se,                       FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_GROWING, MV_BIT_DOWNRIGHT
+    Yalien_w,                          FALSE,  FALSE,
+    EL_ROBOT,                          ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Yandroid_seB,                      FALSE,  TRUE,
-    EL_EMC_ANDROID,                    ACTION_SHRINKING, MV_BIT_DOWNRIGHT
+    Yalien_wB,                         FALSE,  TRUE,
+    EL_ROBOT,                          ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Yandroid_s,                                FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_DOWN
+    Yalien_stone,                      FALSE,  FALSE,
+    EL_ROBOT,                          ACTION_SMASHED_BY_ROCK, -1
   },
   {
-    Yandroid_sB,                       FALSE,  TRUE,
-    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_DOWN
+    Yalien_spring,                     FALSE,  FALSE,
+    EL_ROBOT,                          ACTION_SMASHED_BY_SPRING, -1
+  },
+
+  {
+    Xbug_1_n,                          TRUE,   FALSE,
+    EL_BUG_UP,                         -1, -1
+  },
+  {
+    Xbug_1_e,                          TRUE,   FALSE,
+    EL_BUG_RIGHT,                      -1, -1
+  },
+  {
+    Xbug_1_s,                          TRUE,   FALSE,
+    EL_BUG_DOWN,                       -1, -1
+  },
+  {
+    Xbug_1_w,                          TRUE,   FALSE,
+    EL_BUG_LEFT,                       -1, -1
+  },
+  {
+    Xbug_2_n,                          FALSE,  FALSE,
+    EL_BUG_UP,                         -1, -1
   },
   {
-    Yandroid_sw,                       FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_GROWING, MV_BIT_DOWNLEFT
+    Xbug_2_e,                          FALSE,  FALSE,
+    EL_BUG_RIGHT,                      -1, -1
   },
   {
-    Yandroid_swB,                      FALSE,  TRUE,
-    EL_EMC_ANDROID,                    ACTION_SHRINKING, MV_BIT_DOWNLEFT
+    Xbug_2_s,                          FALSE,  FALSE,
+    EL_BUG_DOWN,                       -1, -1
   },
   {
-    Yandroid_w,                                FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_LEFT
+    Xbug_2_w,                          FALSE,  FALSE,
+    EL_BUG_LEFT,                       -1, -1
   },
   {
-    Yandroid_wB,                       FALSE,  TRUE,
-    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_LEFT
+    Ybug_n,                            FALSE,  FALSE,
+    EL_BUG,                            ACTION_MOVING, MV_BIT_UP
   },
   {
-    Yandroid_nw,                       FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_GROWING, MV_BIT_UPLEFT
+    Ybug_nB,                           FALSE,  TRUE,
+    EL_BUG,                            ACTION_MOVING, MV_BIT_UP
   },
   {
-    Yandroid_nwB,                      FALSE,  TRUE,
-    EL_EMC_ANDROID,                    ACTION_SHRINKING, MV_BIT_UPLEFT
+    Ybug_e,                            FALSE,  FALSE,
+    EL_BUG,                            ACTION_MOVING, MV_BIT_RIGHT
   },
   {
-    Xspring,                           TRUE,   FALSE,
-    EL_SPRING,                         -1, -1
+    Ybug_eB,                           FALSE,  TRUE,
+    EL_BUG,                            ACTION_MOVING, MV_BIT_RIGHT
   },
   {
-    Xspring_pause,                     FALSE,  FALSE,
-    EL_SPRING,                         -1, -1
+    Ybug_s,                            FALSE,  FALSE,
+    EL_BUG,                            ACTION_MOVING, MV_BIT_DOWN
   },
   {
-    Xspring_e,                         FALSE,  FALSE,
-    EL_SPRING,                         -1, -1
+    Ybug_sB,                           FALSE,  TRUE,
+    EL_BUG,                            ACTION_MOVING, MV_BIT_DOWN
   },
   {
-    Xspring_w,                         FALSE,  FALSE,
-    EL_SPRING,                         -1, -1
+    Ybug_w,                            FALSE,  FALSE,
+    EL_BUG,                            ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Xspring_fall,                      FALSE,  FALSE,
-    EL_SPRING,                         -1, -1
+    Ybug_wB,                           FALSE,  TRUE,
+    EL_BUG,                            ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Yspring_s,                         FALSE,  FALSE,
-    EL_SPRING,                         ACTION_FALLING, -1
+    Ybug_w_n,                          FALSE,  FALSE,
+    EL_BUG,                            ACTION_TURNING_FROM_LEFT, MV_BIT_UP
   },
   {
-    Yspring_sB,                                FALSE,  TRUE,
-    EL_SPRING,                         ACTION_FALLING, -1
+    Ybug_n_e,                          FALSE,  FALSE,
+    EL_BUG,                            ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
   },
   {
-    Yspring_e,                         FALSE,  FALSE,
-    EL_SPRING,                         ACTION_MOVING, MV_BIT_RIGHT
+    Ybug_e_s,                          FALSE,  FALSE,
+    EL_BUG,                            ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
   },
   {
-    Yspring_eB,                                FALSE,  TRUE,
-    EL_SPRING,                         ACTION_MOVING, MV_BIT_RIGHT
+    Ybug_s_w,                          FALSE,  FALSE,
+    EL_BUG,                            ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
   },
   {
-    Yspring_w,                         FALSE,  FALSE,
-    EL_SPRING,                         ACTION_MOVING, MV_BIT_LEFT
+    Ybug_e_n,                          FALSE,  FALSE,
+    EL_BUG,                            ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
   },
   {
-    Yspring_wB,                                FALSE,  TRUE,
-    EL_SPRING,                         ACTION_MOVING, MV_BIT_LEFT
+    Ybug_s_e,                          FALSE,  FALSE,
+    EL_BUG,                            ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
   },
   {
-    Yspring_kill_e,                    FALSE,  FALSE,
-    EL_SPRING,                         ACTION_EATING, MV_BIT_RIGHT
+    Ybug_w_s,                          FALSE,  FALSE,
+    EL_BUG,                            ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
   },
   {
-    Yspring_kill_eB,                   FALSE,  TRUE,
-    EL_SPRING,                         ACTION_EATING, MV_BIT_RIGHT
+    Ybug_n_w,                          FALSE,  FALSE,
+    EL_BUG,                            ACTION_TURNING_FROM_UP, MV_BIT_LEFT
   },
   {
-    Yspring_kill_w,                    FALSE,  FALSE,
-    EL_SPRING,                         ACTION_EATING, MV_BIT_LEFT
+    Ybug_stone,                                FALSE,  FALSE,
+    EL_BUG,                            ACTION_SMASHED_BY_ROCK, -1
   },
   {
-    Yspring_kill_wB,                   FALSE,  TRUE,
-    EL_SPRING,                         ACTION_EATING, MV_BIT_LEFT
+    Ybug_spring,                       FALSE,  FALSE,
+    EL_BUG,                            ACTION_SMASHED_BY_SPRING, -1
   },
+
   {
-    Xeater_n,                          TRUE,   FALSE,
-    EL_YAMYAM_UP,                      -1, -1
+    Xtank_1_n,                         TRUE,   FALSE,
+    EL_SPACESHIP_UP,                   -1, -1
   },
   {
-    Xeater_e,                          TRUE,   FALSE,
-    EL_YAMYAM_RIGHT,                   -1, -1
+    Xtank_1_e,                         TRUE,   FALSE,
+    EL_SPACESHIP_RIGHT,                        -1, -1
   },
   {
-    Xeater_w,                          TRUE,   FALSE,
-    EL_YAMYAM_LEFT,                    -1, -1
+    Xtank_1_s,                         TRUE,   FALSE,
+    EL_SPACESHIP_DOWN,                 -1, -1
   },
   {
-    Xeater_s,                          TRUE,   FALSE,
-    EL_YAMYAM_DOWN,                    -1, -1
+    Xtank_1_w,                         TRUE,   FALSE,
+    EL_SPACESHIP_LEFT,                 -1, -1
   },
   {
-    Yeater_n,                          FALSE,  FALSE,
-    EL_YAMYAM,                         ACTION_MOVING, MV_BIT_UP
+    Xtank_2_n,                         FALSE,  FALSE,
+    EL_SPACESHIP_UP,                   -1, -1
   },
   {
-    Yeater_nB,                         FALSE,  TRUE,
-    EL_YAMYAM,                         ACTION_MOVING, MV_BIT_UP
+    Xtank_2_e,                         FALSE,  FALSE,
+    EL_SPACESHIP_RIGHT,                        -1, -1
   },
   {
-    Yeater_e,                          FALSE,  FALSE,
-    EL_YAMYAM,                         ACTION_MOVING, MV_BIT_RIGHT
+    Xtank_2_s,                         FALSE,  FALSE,
+    EL_SPACESHIP_DOWN,                 -1, -1
   },
   {
-    Yeater_eB,                         FALSE,  TRUE,
-    EL_YAMYAM,                         ACTION_MOVING, MV_BIT_RIGHT
+    Xtank_2_w,                         FALSE,  FALSE,
+    EL_SPACESHIP_LEFT,                 -1, -1
   },
   {
-    Yeater_s,                          FALSE,  FALSE,
-    EL_YAMYAM,                         ACTION_MOVING, MV_BIT_DOWN
+    Ytank_n,                           FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_UP
   },
   {
-    Yeater_sB,                         FALSE,  TRUE,
-    EL_YAMYAM,                         ACTION_MOVING, MV_BIT_DOWN
+    Ytank_nB,                          FALSE,  TRUE,
+    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_UP
   },
   {
-    Yeater_w,                          FALSE,  FALSE,
-    EL_YAMYAM,                         ACTION_MOVING, MV_BIT_LEFT
+    Ytank_e,                           FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_RIGHT
   },
   {
-    Yeater_wB,                         FALSE,  TRUE,
-    EL_YAMYAM,                         ACTION_MOVING, MV_BIT_LEFT
+    Ytank_eB,                          FALSE,  TRUE,
+    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_RIGHT
   },
   {
-    Yeater_stone,                      FALSE,  FALSE,
-    EL_YAMYAM,                         ACTION_SMASHED_BY_ROCK, -1
+    Ytank_s,                           FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_DOWN
   },
   {
-    Yeater_spring,                     FALSE,  FALSE,
-    EL_YAMYAM,                         ACTION_SMASHED_BY_SPRING, -1
+    Ytank_sB,                          FALSE,  TRUE,
+    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_DOWN
   },
   {
-    Xalien,                            TRUE,   FALSE,
-    EL_ROBOT,                          -1, -1
+    Ytank_w,                           FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Xalien_pause,                      FALSE,  FALSE,
-    EL_ROBOT,                          -1, -1
+    Ytank_wB,                          FALSE,  TRUE,
+    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Yalien_n,                          FALSE,  FALSE,
-    EL_ROBOT,                          ACTION_MOVING, MV_BIT_UP
+    Ytank_w_n,                         FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_TURNING_FROM_LEFT, MV_BIT_UP
   },
   {
-    Yalien_nB,                         FALSE,  TRUE,
-    EL_ROBOT,                          ACTION_MOVING, MV_BIT_UP
+    Ytank_n_e,                         FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
   },
   {
-    Yalien_e,                          FALSE,  FALSE,
-    EL_ROBOT,                          ACTION_MOVING, MV_BIT_RIGHT
+    Ytank_e_s,                         FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
   },
   {
-    Yalien_eB,                         FALSE,  TRUE,
-    EL_ROBOT,                          ACTION_MOVING, MV_BIT_RIGHT
+    Ytank_s_w,                         FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
   },
   {
-    Yalien_s,                          FALSE,  FALSE,
-    EL_ROBOT,                          ACTION_MOVING, MV_BIT_DOWN
+    Ytank_e_n,                         FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
   },
   {
-    Yalien_sB,                         FALSE,  TRUE,
-    EL_ROBOT,                          ACTION_MOVING, MV_BIT_DOWN
+    Ytank_s_e,                         FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
   },
   {
-    Yalien_w,                          FALSE,  FALSE,
-    EL_ROBOT,                          ACTION_MOVING, MV_BIT_LEFT
+    Ytank_w_s,                         FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
   },
   {
-    Yalien_wB,                         FALSE,  TRUE,
-    EL_ROBOT,                          ACTION_MOVING, MV_BIT_LEFT
+    Ytank_n_w,                         FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_TURNING_FROM_UP, MV_BIT_LEFT
   },
   {
-    Yalien_stone,                      FALSE,  FALSE,
-    EL_ROBOT,                          ACTION_SMASHED_BY_ROCK, -1
+    Ytank_stone,                       FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_SMASHED_BY_ROCK, -1
   },
   {
-    Yalien_spring,                     FALSE,  FALSE,
-    EL_ROBOT,                          ACTION_SMASHED_BY_SPRING, -1
+    Ytank_spring,                      FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_SMASHED_BY_SPRING, -1
   },
+
   {
     Xemerald,                          TRUE,   FALSE,
     EL_EMERALD,                                -1, -1
@@ -6354,13 +6645,10 @@ em_object_mapping_list[] =
     EL_EMERALD,                                ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Yemerald_eat,                      FALSE,  FALSE,
+    Yemerald_blank,                    FALSE,  FALSE,
     EL_EMERALD,                                ACTION_COLLECTING, -1
   },
-  {
-    Yemerald_stone,                    FALSE,  FALSE,
-    EL_NUT,                            ACTION_BREAKING, -1
-  },
+
   {
     Xdiamond,                          TRUE,   FALSE,
     EL_DIAMOND,                                -1, -1
@@ -6402,45 +6690,51 @@ em_object_mapping_list[] =
     EL_DIAMOND,                                ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Ydiamond_eat,                      FALSE,  FALSE,
+    Ydiamond_blank,                    FALSE,  FALSE,
     EL_DIAMOND,                                ACTION_COLLECTING, -1
   },
   {
     Ydiamond_stone,                    FALSE,  FALSE,
     EL_DIAMOND,                                ACTION_SMASHED_BY_ROCK, -1
   },
+
   {
-    Xdrip_fall,                                TRUE,   FALSE,
-    EL_AMOEBA_DROP,                    -1, -1
+    Xstone,                            TRUE,   FALSE,
+    EL_ROCK,                           -1, -1
   },
   {
-    Xdrip_stretch,                     FALSE,  FALSE,
-    EL_AMOEBA_DROP,                    ACTION_FALLING, -1
+    Xstone_pause,                      FALSE,  FALSE,
+    EL_ROCK,                           -1, -1
   },
   {
-    Xdrip_stretchB,                    FALSE,  TRUE,
-    EL_AMOEBA_DROP,                    ACTION_FALLING, -1
+    Xstone_fall,                       FALSE,  FALSE,
+    EL_ROCK,                           -1, -1
   },
   {
-    Xdrip_eat,                         FALSE,  FALSE,
-    EL_AMOEBA_DROP,                    ACTION_GROWING, -1
+    Ystone_s,                          FALSE,  FALSE,
+    EL_ROCK,                           ACTION_FALLING, -1
   },
   {
-    Ydrip_s1,                          FALSE,  FALSE,
-    EL_AMOEBA_DROP,                    ACTION_FALLING, -1
+    Ystone_sB,                         FALSE,  TRUE,
+    EL_ROCK,                           ACTION_FALLING, -1
   },
   {
-    Ydrip_s1B,                         FALSE,  TRUE,
-    EL_AMOEBA_DROP,                    ACTION_FALLING, -1
+    Ystone_e,                          FALSE,  FALSE,
+    EL_ROCK,                           ACTION_MOVING, MV_BIT_RIGHT
   },
   {
-    Ydrip_s2,                          FALSE,  FALSE,
-    EL_AMOEBA_DROP,                    ACTION_FALLING, -1
+    Ystone_eB,                         FALSE,  TRUE,
+    EL_ROCK,                           ACTION_MOVING, MV_BIT_RIGHT
   },
   {
-    Ydrip_s2B,                         FALSE,  TRUE,
-    EL_AMOEBA_DROP,                    ACTION_FALLING, -1
+    Ystone_w,                          FALSE,  FALSE,
+    EL_ROCK,                           ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Ystone_wB,                         FALSE,  TRUE,
+    EL_ROCK,                           ACTION_MOVING, MV_BIT_LEFT
   },
+
   {
     Xbomb,                             TRUE,   FALSE,
     EL_BOMB,                           -1, -1
@@ -6470,269 +6764,227 @@ em_object_mapping_list[] =
     EL_BOMB,                           ACTION_MOVING, MV_BIT_RIGHT
   },
   {
-    Ybomb_w,                           FALSE,  FALSE,
-    EL_BOMB,                           ACTION_MOVING, MV_BIT_LEFT
-  },
-  {
-    Ybomb_wB,                          FALSE,  TRUE,
-    EL_BOMB,                           ACTION_MOVING, MV_BIT_LEFT
-  },
-  {
-    Ybomb_eat,                         FALSE,  FALSE,
-    EL_BOMB,                           ACTION_ACTIVATING, -1
-  },
-  {
-    Xballoon,                          TRUE,   FALSE,
-    EL_BALLOON,                                -1, -1
-  },
-  {
-    Yballoon_n,                                FALSE,  FALSE,
-    EL_BALLOON,                                ACTION_MOVING, MV_BIT_UP
-  },
-  {
-    Yballoon_nB,                       FALSE,  TRUE,
-    EL_BALLOON,                                ACTION_MOVING, MV_BIT_UP
-  },
-  {
-    Yballoon_e,                                FALSE,  FALSE,
-    EL_BALLOON,                                ACTION_MOVING, MV_BIT_RIGHT
-  },
-  {
-    Yballoon_eB,                       FALSE,  TRUE,
-    EL_BALLOON,                                ACTION_MOVING, MV_BIT_RIGHT
-  },
-  {
-    Yballoon_s,                                FALSE,  FALSE,
-    EL_BALLOON,                                ACTION_MOVING, MV_BIT_DOWN
-  },
-  {
-    Yballoon_sB,                       FALSE,  TRUE,
-    EL_BALLOON,                                ACTION_MOVING, MV_BIT_DOWN
-  },
-  {
-    Yballoon_w,                                FALSE,  FALSE,
-    EL_BALLOON,                                ACTION_MOVING, MV_BIT_LEFT
-  },
-  {
-    Yballoon_wB,                       FALSE,  TRUE,
-    EL_BALLOON,                                ACTION_MOVING, MV_BIT_LEFT
-  },
-  {
-    Xgrass,                            TRUE,   FALSE,
-    EL_EMC_GRASS,                      -1, -1
+    Ybomb_w,                           FALSE,  FALSE,
+    EL_BOMB,                           ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Ygrass_nB,                         FALSE,  FALSE,
-    EL_EMC_GRASS,                      ACTION_DIGGING, MV_BIT_UP
+    Ybomb_wB,                          FALSE,  TRUE,
+    EL_BOMB,                           ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Ygrass_eB,                         FALSE,  FALSE,
-    EL_EMC_GRASS,                      ACTION_DIGGING, MV_BIT_RIGHT
+    Ybomb_blank,                       FALSE,  FALSE,
+    EL_BOMB,                           ACTION_ACTIVATING, -1
   },
+
   {
-    Ygrass_sB,                         FALSE,  FALSE,
-    EL_EMC_GRASS,                      ACTION_DIGGING, MV_BIT_DOWN
+    Xnut,                              TRUE,   FALSE,
+    EL_NUT,                            -1, -1
   },
   {
-    Ygrass_wB,                         FALSE,  FALSE,
-    EL_EMC_GRASS,                      ACTION_DIGGING, MV_BIT_LEFT
+    Xnut_pause,                                FALSE,  FALSE,
+    EL_NUT,                            -1, -1
   },
   {
-    Xdirt,                             TRUE,   FALSE,
-    EL_SAND,                           -1, -1
+    Xnut_fall,                         FALSE,  FALSE,
+    EL_NUT,                            -1, -1
   },
   {
-    Ydirt_nB,                          FALSE,  FALSE,
-    EL_SAND,                           ACTION_DIGGING, MV_BIT_UP
+    Ynut_s,                            FALSE,  FALSE,
+    EL_NUT,                            ACTION_FALLING, -1
   },
   {
-    Ydirt_eB,                          FALSE,  FALSE,
-    EL_SAND,                           ACTION_DIGGING, MV_BIT_RIGHT
+    Ynut_sB,                           FALSE,  TRUE,
+    EL_NUT,                            ACTION_FALLING, -1
   },
   {
-    Ydirt_sB,                          FALSE,  FALSE,
-    EL_SAND,                           ACTION_DIGGING, MV_BIT_DOWN
+    Ynut_e,                            FALSE,  FALSE,
+    EL_NUT,                            ACTION_MOVING, MV_BIT_RIGHT
   },
   {
-    Ydirt_wB,                          FALSE,  FALSE,
-    EL_SAND,                           ACTION_DIGGING, MV_BIT_LEFT
+    Ynut_eB,                           FALSE,  TRUE,
+    EL_NUT,                            ACTION_MOVING, MV_BIT_RIGHT
   },
   {
-    Xacid_ne,                          TRUE,   FALSE,
-    EL_ACID_POOL_TOPRIGHT,             -1, -1
+    Ynut_w,                            FALSE,  FALSE,
+    EL_NUT,                            ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Xacid_se,                          TRUE,   FALSE,
-    EL_ACID_POOL_BOTTOMRIGHT,          -1, -1
+    Ynut_wB,                           FALSE,  TRUE,
+    EL_NUT,                            ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Xacid_s,                           TRUE,   FALSE,
-    EL_ACID_POOL_BOTTOM,               -1, -1
+    Ynut_stone,                                FALSE,  FALSE,
+    EL_NUT,                            ACTION_BREAKING, -1
   },
+
   {
-    Xacid_sw,                          TRUE,   FALSE,
-    EL_ACID_POOL_BOTTOMLEFT,           -1, -1
+    Xspring,                           TRUE,   FALSE,
+    EL_SPRING,                         -1, -1
   },
   {
-    Xacid_nw,                          TRUE,   FALSE,
-    EL_ACID_POOL_TOPLEFT,              -1, -1
+    Xspring_pause,                     FALSE,  FALSE,
+    EL_SPRING,                         -1, -1
   },
   {
-    Xacid_1,                           TRUE,   FALSE,
-    EL_ACID,                           -1, -1
+    Xspring_e,                         TRUE,   FALSE,
+    EL_SPRING_RIGHT,                   -1, -1
   },
   {
-    Xacid_2,                           FALSE,  FALSE,
-    EL_ACID,                           -1, -1
+    Xspring_w,                         TRUE,   FALSE,
+    EL_SPRING_LEFT,                    -1, -1
   },
   {
-    Xacid_3,                           FALSE,  FALSE,
-    EL_ACID,                           -1, -1
+    Xspring_fall,                      FALSE,  FALSE,
+    EL_SPRING,                         -1, -1
   },
   {
-    Xacid_4,                           FALSE,  FALSE,
-    EL_ACID,                           -1, -1
+    Yspring_s,                         FALSE,  FALSE,
+    EL_SPRING,                         ACTION_FALLING, -1
   },
   {
-    Xacid_5,                           FALSE,  FALSE,
-    EL_ACID,                           -1, -1
+    Yspring_sB,                                FALSE,  TRUE,
+    EL_SPRING,                         ACTION_FALLING, -1
   },
   {
-    Xacid_6,                           FALSE,  FALSE,
-    EL_ACID,                           -1, -1
+    Yspring_e,                         FALSE,  FALSE,
+    EL_SPRING,                         ACTION_MOVING, MV_BIT_RIGHT
   },
   {
-    Xacid_7,                           FALSE,  FALSE,
-    EL_ACID,                           -1, -1
+    Yspring_eB,                                FALSE,  TRUE,
+    EL_SPRING,                         ACTION_MOVING, MV_BIT_RIGHT
   },
   {
-    Xacid_8,                           FALSE,  FALSE,
-    EL_ACID,                           -1, -1
+    Yspring_w,                         FALSE,  FALSE,
+    EL_SPRING,                         ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Xball_1,                           TRUE,   FALSE,
-    EL_EMC_MAGIC_BALL,                 -1, -1
+    Yspring_wB,                                FALSE,  TRUE,
+    EL_SPRING,                         ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Xball_1B,                          FALSE,  FALSE,
-    EL_EMC_MAGIC_BALL,                 ACTION_ACTIVE, -1
+    Yspring_alien_e,                   FALSE,  FALSE,
+    EL_SPRING,                         ACTION_EATING, MV_BIT_RIGHT
   },
   {
-    Xball_2,                           FALSE,  FALSE,
-    EL_EMC_MAGIC_BALL,                 ACTION_ACTIVE, -1
+    Yspring_alien_eB,                  FALSE,  TRUE,
+    EL_SPRING,                         ACTION_EATING, MV_BIT_RIGHT
   },
   {
-    Xball_2B,                          FALSE,  FALSE,
-    EL_EMC_MAGIC_BALL,                 ACTION_ACTIVE, -1
+    Yspring_alien_w,                   FALSE,  FALSE,
+    EL_SPRING,                         ACTION_EATING, MV_BIT_LEFT
   },
   {
-    Yball_eat,                         FALSE,  FALSE,
-    EL_EMC_MAGIC_BALL,                 ACTION_DROPPING, -1
+    Yspring_alien_wB,                  FALSE,  TRUE,
+    EL_SPRING,                         ACTION_EATING, MV_BIT_LEFT
   },
+
   {
-    Ykey_1_eat,                                FALSE,  FALSE,
-    EL_EM_KEY_1,                       ACTION_COLLECTING, -1
+    Xpush_emerald_e,                   FALSE,  FALSE,
+    EL_EMERALD,                                -1, MV_BIT_RIGHT
   },
   {
-    Ykey_2_eat,                                FALSE,  FALSE,
-    EL_EM_KEY_2,                       ACTION_COLLECTING, -1
+    Xpush_emerald_w,                   FALSE,  FALSE,
+    EL_EMERALD,                                -1, MV_BIT_LEFT
   },
   {
-    Ykey_3_eat,                                FALSE,  FALSE,
-    EL_EM_KEY_3,                       ACTION_COLLECTING, -1
+    Xpush_diamond_e,                   FALSE,  FALSE,
+    EL_DIAMOND,                                -1, MV_BIT_RIGHT
   },
   {
-    Ykey_4_eat,                                FALSE,  FALSE,
-    EL_EM_KEY_4,                       ACTION_COLLECTING, -1
+    Xpush_diamond_w,                   FALSE,  FALSE,
+    EL_DIAMOND,                                -1, MV_BIT_LEFT
   },
   {
-    Ykey_5_eat,                                FALSE,  FALSE,
-    EL_EMC_KEY_5,                      ACTION_COLLECTING, -1
+    Xpush_stone_e,                     FALSE,  FALSE,
+    EL_ROCK,                           -1, MV_BIT_RIGHT
   },
   {
-    Ykey_6_eat,                                FALSE,  FALSE,
-    EL_EMC_KEY_6,                      ACTION_COLLECTING, -1
+    Xpush_stone_w,                     FALSE,  FALSE,
+    EL_ROCK,                           -1, MV_BIT_LEFT
   },
   {
-    Ykey_7_eat,                                FALSE,  FALSE,
-    EL_EMC_KEY_7,                      ACTION_COLLECTING, -1
+    Xpush_bomb_e,                      FALSE,  FALSE,
+    EL_BOMB,                           -1, MV_BIT_RIGHT
   },
   {
-    Ykey_8_eat,                                FALSE,  FALSE,
-    EL_EMC_KEY_8,                      ACTION_COLLECTING, -1
+    Xpush_bomb_w,                      FALSE,  FALSE,
+    EL_BOMB,                           -1, MV_BIT_LEFT
   },
   {
-    Ylenses_eat,                       FALSE,  FALSE,
-    EL_EMC_LENSES,                     ACTION_COLLECTING, -1
+    Xpush_nut_e,                       FALSE,  FALSE,
+    EL_NUT,                            -1, MV_BIT_RIGHT
   },
   {
-    Ymagnify_eat,                      FALSE,  FALSE,
-    EL_EMC_MAGNIFIER,                  ACTION_COLLECTING, -1
+    Xpush_nut_w,                       FALSE,  FALSE,
+    EL_NUT,                            -1, MV_BIT_LEFT
   },
   {
-    Ygrass_eat,                                FALSE,  FALSE,
-    EL_EMC_GRASS,                      ACTION_SNAPPING, -1
+    Xpush_spring_e,                    FALSE,  FALSE,
+    EL_SPRING_RIGHT,                   -1, MV_BIT_RIGHT
   },
   {
-    Ydirt_eat,                         FALSE,  FALSE,
-    EL_SAND,                           ACTION_SNAPPING, -1
+    Xpush_spring_w,                    FALSE,  FALSE,
+    EL_SPRING_LEFT,                    -1, MV_BIT_LEFT
   },
+
   {
-    Xgrow_ns,                          TRUE,   FALSE,
-    EL_EXPANDABLE_WALL_VERTICAL,       -1, -1
+    Xdynamite,                         TRUE,   FALSE,
+    EL_EM_DYNAMITE,                    -1, -1
   },
   {
-    Ygrow_ns_eat,                      FALSE,  FALSE,
-    EL_EXPANDABLE_WALL_VERTICAL,       ACTION_GROWING, -1
+    Ydynamite_blank,                   FALSE,  FALSE,
+    EL_EM_DYNAMITE,                    ACTION_COLLECTING, -1
   },
   {
-    Xgrow_ew,                          TRUE,   FALSE,
-    EL_EXPANDABLE_WALL_HORIZONTAL,     -1, -1
+    Xdynamite_1,                       TRUE,   FALSE,
+    EL_EM_DYNAMITE_ACTIVE,             -1, -1
   },
   {
-    Ygrow_ew_eat,                      FALSE,  FALSE,
-    EL_EXPANDABLE_WALL_HORIZONTAL,     ACTION_GROWING, -1
+    Xdynamite_2,                       FALSE,  FALSE,
+    EL_EM_DYNAMITE_ACTIVE,             -1, -1
   },
   {
-    Xwonderwall,                       TRUE,   FALSE,
-    EL_MAGIC_WALL,                     -1, -1
+    Xdynamite_3,                       FALSE,  FALSE,
+    EL_EM_DYNAMITE_ACTIVE,             -1, -1
   },
   {
-    XwonderwallB,                      FALSE,  FALSE,
-    EL_MAGIC_WALL,                     ACTION_ACTIVE, -1
+    Xdynamite_4,                       FALSE,  FALSE,
+    EL_EM_DYNAMITE_ACTIVE,             -1, -1
   },
+
   {
-    Xamoeba_1,                         TRUE,   FALSE,
-    EL_AMOEBA_DRY,                     ACTION_OTHER, -1
+    Xkey_1,                            TRUE,   FALSE,
+    EL_EM_KEY_1,                       -1, -1
   },
   {
-    Xamoeba_2,                         FALSE,  FALSE,
-    EL_AMOEBA_DRY,                     ACTION_OTHER, -1
+    Xkey_2,                            TRUE,   FALSE,
+    EL_EM_KEY_2,                       -1, -1
   },
   {
-    Xamoeba_3,                         FALSE,  FALSE,
-    EL_AMOEBA_DRY,                     ACTION_OTHER, -1
+    Xkey_3,                            TRUE,   FALSE,
+    EL_EM_KEY_3,                       -1, -1
   },
   {
-    Xamoeba_4,                         FALSE,  FALSE,
-    EL_AMOEBA_DRY,                     ACTION_OTHER, -1
+    Xkey_4,                            TRUE,   FALSE,
+    EL_EM_KEY_4,                       -1, -1
   },
   {
-    Xamoeba_5,                         TRUE,   FALSE,
-    EL_AMOEBA_WET,                     ACTION_OTHER, -1
+    Xkey_5,                            TRUE,   FALSE,
+    EL_EMC_KEY_5,                      -1, -1
   },
   {
-    Xamoeba_6,                         FALSE,  FALSE,
-    EL_AMOEBA_WET,                     ACTION_OTHER, -1
+    Xkey_6,                            TRUE,   FALSE,
+    EL_EMC_KEY_6,                      -1, -1
   },
   {
-    Xamoeba_7,                         FALSE,  FALSE,
-    EL_AMOEBA_WET,                     ACTION_OTHER, -1
+    Xkey_7,                            TRUE,   FALSE,
+    EL_EMC_KEY_7,                      -1, -1
   },
   {
-    Xamoeba_8,                         FALSE,  FALSE,
-    EL_AMOEBA_WET,                     ACTION_OTHER, -1
+    Xkey_8,                            TRUE,   FALSE,
+    EL_EMC_KEY_8,                      -1, -1
   },
+
   {
     Xdoor_1,                           TRUE,   FALSE,
     EL_EM_GATE_1,                      -1, -1
@@ -6765,318 +7017,395 @@ em_object_mapping_list[] =
     Xdoor_8,                           TRUE,   FALSE,
     EL_EMC_GATE_8,                     -1, -1
   },
+
   {
-    Xkey_1,                            TRUE,   FALSE,
-    EL_EM_KEY_1,                       -1, -1
+    Xfake_door_1,                      TRUE,   FALSE,
+    EL_EM_GATE_1_GRAY,                 -1, -1
   },
   {
-    Xkey_2,                            TRUE,   FALSE,
-    EL_EM_KEY_2,                       -1, -1
+    Xfake_door_2,                      TRUE,   FALSE,
+    EL_EM_GATE_2_GRAY,                 -1, -1
   },
   {
-    Xkey_3,                            TRUE,   FALSE,
-    EL_EM_KEY_3,                       -1, -1
+    Xfake_door_3,                      TRUE,   FALSE,
+    EL_EM_GATE_3_GRAY,                 -1, -1
   },
   {
-    Xkey_4,                            TRUE,   FALSE,
-    EL_EM_KEY_4,                       -1, -1
+    Xfake_door_4,                      TRUE,   FALSE,
+    EL_EM_GATE_4_GRAY,                 -1, -1
   },
   {
-    Xkey_5,                            TRUE,   FALSE,
-    EL_EMC_KEY_5,                      -1, -1
+    Xfake_door_5,                      TRUE,   FALSE,
+    EL_EMC_GATE_5_GRAY,                        -1, -1
   },
   {
-    Xkey_6,                            TRUE,   FALSE,
-    EL_EMC_KEY_6,                      -1, -1
+    Xfake_door_6,                      TRUE,   FALSE,
+    EL_EMC_GATE_6_GRAY,                        -1, -1
+  },
+  {
+    Xfake_door_7,                      TRUE,   FALSE,
+    EL_EMC_GATE_7_GRAY,                        -1, -1
+  },
+  {
+    Xfake_door_8,                      TRUE,   FALSE,
+    EL_EMC_GATE_8_GRAY,                        -1, -1
+  },
+
+  {
+    Xballoon,                          TRUE,   FALSE,
+    EL_BALLOON,                                -1, -1
+  },
+  {
+    Yballoon_n,                                FALSE,  FALSE,
+    EL_BALLOON,                                ACTION_MOVING, MV_BIT_UP
+  },
+  {
+    Yballoon_nB,                       FALSE,  TRUE,
+    EL_BALLOON,                                ACTION_MOVING, MV_BIT_UP
+  },
+  {
+    Yballoon_e,                                FALSE,  FALSE,
+    EL_BALLOON,                                ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Yballoon_eB,                       FALSE,  TRUE,
+    EL_BALLOON,                                ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Yballoon_s,                                FALSE,  FALSE,
+    EL_BALLOON,                                ACTION_MOVING, MV_BIT_DOWN
+  },
+  {
+    Yballoon_sB,                       FALSE,  TRUE,
+    EL_BALLOON,                                ACTION_MOVING, MV_BIT_DOWN
+  },
+  {
+    Yballoon_w,                                FALSE,  FALSE,
+    EL_BALLOON,                                ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Yballoon_wB,                       FALSE,  TRUE,
+    EL_BALLOON,                                ACTION_MOVING, MV_BIT_LEFT
+  },
+
+  {
+    Xball_1,                           TRUE,   FALSE,
+    EL_EMC_MAGIC_BALL,                 -1, -1
+  },
+  {
+    Yball_1,                           FALSE,  FALSE,
+    EL_EMC_MAGIC_BALL,                 ACTION_ACTIVE, -1
+  },
+  {
+    Xball_2,                           FALSE,  FALSE,
+    EL_EMC_MAGIC_BALL,                 ACTION_ACTIVE, -1
   },
   {
-    Xkey_7,                            TRUE,   FALSE,
-    EL_EMC_KEY_7,                      -1, -1
+    Yball_2,                           FALSE,  FALSE,
+    EL_EMC_MAGIC_BALL,                 ACTION_ACTIVE, -1
   },
   {
-    Xkey_8,                            TRUE,   FALSE,
-    EL_EMC_KEY_8,                      -1, -1
+    Yball_blank,                       FALSE,  FALSE,
+    EL_EMC_MAGIC_BALL,                 ACTION_DROPPING, -1
   },
+
   {
-    Xwind_n,                           TRUE,   FALSE,
-    EL_BALLOON_SWITCH_UP,              -1, -1
+    Xamoeba_1,                         TRUE,   FALSE,
+    EL_AMOEBA_DRY,                     ACTION_OTHER, -1
   },
   {
-    Xwind_e,                           TRUE,   FALSE,
-    EL_BALLOON_SWITCH_RIGHT,           -1, -1
+    Xamoeba_2,                         FALSE,  FALSE,
+    EL_AMOEBA_DRY,                     ACTION_OTHER, -1
   },
   {
-    Xwind_s,                           TRUE,   FALSE,
-    EL_BALLOON_SWITCH_DOWN,            -1, -1
+    Xamoeba_3,                         FALSE,  FALSE,
+    EL_AMOEBA_DRY,                     ACTION_OTHER, -1
   },
   {
-    Xwind_w,                           TRUE,   FALSE,
-    EL_BALLOON_SWITCH_LEFT,            -1, -1
+    Xamoeba_4,                         FALSE,  FALSE,
+    EL_AMOEBA_DRY,                     ACTION_OTHER, -1
   },
   {
-    Xwind_nesw,                                TRUE,   FALSE,
-    EL_BALLOON_SWITCH_ANY,             -1, -1
+    Xamoeba_5,                         TRUE,   FALSE,
+    EL_AMOEBA_WET,                     ACTION_OTHER, -1
   },
   {
-    Xwind_stop,                                TRUE,   FALSE,
-    EL_BALLOON_SWITCH_NONE,            -1, -1
+    Xamoeba_6,                         FALSE,  FALSE,
+    EL_AMOEBA_WET,                     ACTION_OTHER, -1
   },
   {
-    Xexit,                             TRUE,   FALSE,
-    EL_EM_EXIT_CLOSED,                 -1, -1
+    Xamoeba_7,                         FALSE,  FALSE,
+    EL_AMOEBA_WET,                     ACTION_OTHER, -1
   },
   {
-    Xexit_1,                           TRUE,   FALSE,
-    EL_EM_EXIT_OPEN,                   -1, -1
+    Xamoeba_8,                         FALSE,  FALSE,
+    EL_AMOEBA_WET,                     ACTION_OTHER, -1
   },
+
   {
-    Xexit_2,                           FALSE,  FALSE,
-    EL_EM_EXIT_OPEN,                   -1, -1
+    Xdrip,                             TRUE,   FALSE,
+    EL_AMOEBA_DROP,                    ACTION_GROWING, -1
   },
   {
-    Xexit_3,                           FALSE,  FALSE,
-    EL_EM_EXIT_OPEN,                   -1, -1
+    Xdrip_fall,                                FALSE,  FALSE,
+    EL_AMOEBA_DROP,                    -1, -1
   },
   {
-    Xdynamite,                         TRUE,   FALSE,
-    EL_EM_DYNAMITE,                    -1, -1
+    Xdrip_stretch,                     FALSE,  FALSE,
+    EL_AMOEBA_DROP,                    ACTION_FALLING, -1
   },
   {
-    Ydynamite_eat,                     FALSE,  FALSE,
-    EL_EM_DYNAMITE,                    ACTION_COLLECTING, -1
+    Xdrip_stretchB,                    FALSE,  TRUE,
+    EL_AMOEBA_DROP,                    ACTION_FALLING, -1
   },
   {
-    Xdynamite_1,                       TRUE,   FALSE,
-    EL_EM_DYNAMITE_ACTIVE,             -1, -1
+    Ydrip_1_s,                         FALSE,  FALSE,
+    EL_AMOEBA_DROP,                    ACTION_FALLING, -1
   },
   {
-    Xdynamite_2,                       FALSE,  FALSE,
-    EL_EM_DYNAMITE_ACTIVE,             -1, -1
+    Ydrip_1_sB,                                FALSE,  TRUE,
+    EL_AMOEBA_DROP,                    ACTION_FALLING, -1
   },
   {
-    Xdynamite_3,                       FALSE,  FALSE,
-    EL_EM_DYNAMITE_ACTIVE,             -1, -1
+    Ydrip_2_s,                         FALSE,  FALSE,
+    EL_AMOEBA_DROP,                    ACTION_FALLING, -1
   },
   {
-    Xdynamite_4,                       FALSE,  FALSE,
-    EL_EM_DYNAMITE_ACTIVE,             -1, -1
+    Ydrip_2_sB,                                FALSE,  TRUE,
+    EL_AMOEBA_DROP,                    ACTION_FALLING, -1
   },
+
   {
-    Xbumper,                           TRUE,   FALSE,
-    EL_EMC_SPRING_BUMPER,              -1, -1
+    Xwonderwall,                       TRUE,   FALSE,
+    EL_MAGIC_WALL,                     -1, -1
   },
   {
-    XbumperB,                          FALSE,  FALSE,
-    EL_EMC_SPRING_BUMPER,              ACTION_ACTIVE, -1
+    Ywonderwall,                       FALSE,  FALSE,
+    EL_MAGIC_WALL,                     ACTION_ACTIVE, -1
   },
+
   {
     Xwheel,                            TRUE,   FALSE,
     EL_ROBOT_WHEEL,                    -1, -1
   },
   {
-    XwheelB,                           FALSE,  FALSE,
+    Ywheel,                            FALSE,  FALSE,
     EL_ROBOT_WHEEL,                    ACTION_ACTIVE, -1
   },
+
   {
     Xswitch,                           TRUE,   FALSE,
     EL_EMC_MAGIC_BALL_SWITCH,          -1, -1
   },
   {
-    XswitchB,                          FALSE,  FALSE,
+    Yswitch,                           FALSE,  FALSE,
     EL_EMC_MAGIC_BALL_SWITCH,          ACTION_ACTIVE, -1
   },
+
   {
-    Xsand,                             TRUE,   FALSE,
-    EL_QUICKSAND_EMPTY,                        -1, -1
+    Xbumper,                           TRUE,   FALSE,
+    EL_EMC_SPRING_BUMPER,              -1, -1
   },
   {
-    Xsand_stone,                       TRUE,   FALSE,
-    EL_QUICKSAND_FULL,                 -1, -1
+    Ybumper,                           FALSE,  FALSE,
+    EL_EMC_SPRING_BUMPER,              ACTION_ACTIVE, -1
   },
+
   {
-    Xsand_stonein_1,                   FALSE,  TRUE,
-    EL_ROCK,                           ACTION_FILLING, -1
+    Xacid_nw,                          TRUE,   FALSE,
+    EL_ACID_POOL_TOPLEFT,              -1, -1
   },
   {
-    Xsand_stonein_2,                   FALSE,  TRUE,
-    EL_ROCK,                           ACTION_FILLING, -1
+    Xacid_ne,                          TRUE,   FALSE,
+    EL_ACID_POOL_TOPRIGHT,             -1, -1
   },
   {
-    Xsand_stonein_3,                   FALSE,  TRUE,
-    EL_ROCK,                           ACTION_FILLING, -1
+    Xacid_sw,                          TRUE,   FALSE,
+    EL_ACID_POOL_BOTTOMLEFT,           -1, -1
   },
   {
-    Xsand_stonein_4,                   FALSE,  TRUE,
-    EL_ROCK,                           ACTION_FILLING, -1
+    Xacid_s,                           TRUE,   FALSE,
+    EL_ACID_POOL_BOTTOM,               -1, -1
   },
   {
-    Xsand_stonesand_1,                 FALSE,  FALSE,
-    EL_QUICKSAND_EMPTYING,             -1, -1
+    Xacid_se,                          TRUE,   FALSE,
+    EL_ACID_POOL_BOTTOMRIGHT,          -1, -1
   },
+
   {
-    Xsand_stonesand_2,                 FALSE,  FALSE,
-    EL_QUICKSAND_EMPTYING,             -1, -1
+    Xfake_blank,                       TRUE,   FALSE,
+    EL_INVISIBLE_WALL,                 -1, -1
   },
   {
-    Xsand_stonesand_3,                 FALSE,  FALSE,
-    EL_QUICKSAND_EMPTYING,             -1, -1
+    Yfake_blank,                       FALSE,  FALSE,
+    EL_INVISIBLE_WALL,                 ACTION_ACTIVE, -1
   },
+
   {
-    Xsand_stonesand_4,                 FALSE,  FALSE,
-    EL_QUICKSAND_EMPTYING,             -1, -1
+    Xfake_grass,                       TRUE,   FALSE,
+    EL_EMC_FAKE_GRASS,                 -1, -1
   },
   {
-    Xsand_stonesand_quickout_1,                FALSE,  FALSE,
-    EL_QUICKSAND_EMPTYING,             -1, -1
+    Yfake_grass,                       FALSE,  FALSE,
+    EL_EMC_FAKE_GRASS,                 ACTION_ACTIVE, -1
   },
+
   {
-    Xsand_stonesand_quickout_2,                FALSE,  FALSE,
-    EL_QUICKSAND_EMPTYING,             -1, -1
+    Xfake_amoeba,                      TRUE,   FALSE,
+    EL_EMC_DRIPPER,                    -1, -1
   },
   {
-    Xsand_stoneout_1,                  FALSE,  FALSE,
-    EL_ROCK,                           ACTION_EMPTYING, -1
+    Yfake_amoeba,                      FALSE,  FALSE,
+    EL_EMC_DRIPPER,                    ACTION_ACTIVE, -1
   },
+
   {
-    Xsand_stoneout_2,                  FALSE,  FALSE,
-    EL_ROCK,                           ACTION_EMPTYING, -1
+    Xlenses,                           TRUE,   FALSE,
+    EL_EMC_LENSES,                     -1, -1
   },
+
   {
-    Xsand_sandstone_1,                 FALSE,  FALSE,
-    EL_QUICKSAND_FILLING,              -1, -1
+    Xmagnify,                          TRUE,   FALSE,
+    EL_EMC_MAGNIFIER,                  -1, -1
   },
+
   {
-    Xsand_sandstone_2,                 FALSE,  FALSE,
-    EL_QUICKSAND_FILLING,              -1, -1
+    Xsand,                             TRUE,   FALSE,
+    EL_QUICKSAND_EMPTY,                        -1, -1
   },
   {
-    Xsand_sandstone_3,                 FALSE,  FALSE,
-    EL_QUICKSAND_FILLING,              -1, -1
+    Xsand_stone,                       TRUE,   FALSE,
+    EL_QUICKSAND_FULL,                 -1, -1
   },
   {
-    Xsand_sandstone_4,                 FALSE,  FALSE,
-    EL_QUICKSAND_FILLING,              -1, -1
+    Xsand_stonein_1,                   FALSE,  TRUE,
+    EL_ROCK,                           ACTION_FILLING, -1
   },
   {
-    Xplant,                            TRUE,   FALSE,
-    EL_EMC_PLANT,                      -1, -1
+    Xsand_stonein_2,                   FALSE,  TRUE,
+    EL_ROCK,                           ACTION_FILLING, -1
   },
   {
-    Yplant,                            FALSE,  FALSE,
-    EL_EMC_PLANT,                      -1, -1
+    Xsand_stonein_3,                   FALSE,  TRUE,
+    EL_ROCK,                           ACTION_FILLING, -1
   },
   {
-    Xlenses,                           TRUE,   FALSE,
-    EL_EMC_LENSES,                     -1, -1
+    Xsand_stonein_4,                   FALSE,  TRUE,
+    EL_ROCK,                           ACTION_FILLING, -1
   },
   {
-    Xmagnify,                          TRUE,   FALSE,
-    EL_EMC_MAGNIFIER,                  -1, -1
+    Xsand_sandstone_1,                 FALSE,  FALSE,
+    EL_QUICKSAND_FILLING,              -1, -1
   },
   {
-    Xdripper,                          TRUE,   FALSE,
-    EL_EMC_DRIPPER,                    -1, -1
+    Xsand_sandstone_2,                 FALSE,  FALSE,
+    EL_QUICKSAND_FILLING,              -1, -1
   },
   {
-    XdripperB,                         FALSE,  FALSE,
-    EL_EMC_DRIPPER,                    ACTION_ACTIVE, -1
+    Xsand_sandstone_3,                 FALSE,  FALSE,
+    EL_QUICKSAND_FILLING,              -1, -1
   },
   {
-    Xfake_blank,                       TRUE,   FALSE,
-    EL_INVISIBLE_WALL,                 -1, -1
+    Xsand_sandstone_4,                 FALSE,  FALSE,
+    EL_QUICKSAND_FILLING,              -1, -1
   },
   {
-    Xfake_blankB,                      FALSE,  FALSE,
-    EL_INVISIBLE_WALL,                 ACTION_ACTIVE, -1
+    Xsand_stonesand_1,                 FALSE,  FALSE,
+    EL_QUICKSAND_EMPTYING,             -1, -1
   },
   {
-    Xfake_grass,                       TRUE,   FALSE,
-    EL_EMC_FAKE_GRASS,                 -1, -1
+    Xsand_stonesand_2,                 FALSE,  FALSE,
+    EL_QUICKSAND_EMPTYING,             -1, -1
   },
   {
-    Xfake_grassB,                      FALSE,  FALSE,
-    EL_EMC_FAKE_GRASS,                 ACTION_ACTIVE, -1
+    Xsand_stonesand_3,                 FALSE,  FALSE,
+    EL_QUICKSAND_EMPTYING,             -1, -1
   },
   {
-    Xfake_door_1,                      TRUE,   FALSE,
-    EL_EM_GATE_1_GRAY,                 -1, -1
+    Xsand_stonesand_4,                 FALSE,  FALSE,
+    EL_QUICKSAND_EMPTYING,             -1, -1
   },
   {
-    Xfake_door_2,                      TRUE,   FALSE,
-    EL_EM_GATE_2_GRAY,                 -1, -1
+    Xsand_stoneout_1,                  FALSE,  FALSE,
+    EL_ROCK,                           ACTION_EMPTYING, -1
   },
   {
-    Xfake_door_3,                      TRUE,   FALSE,
-    EL_EM_GATE_3_GRAY,                 -1, -1
+    Xsand_stoneout_2,                  FALSE,  FALSE,
+    EL_ROCK,                           ACTION_EMPTYING, -1
   },
   {
-    Xfake_door_4,                      TRUE,   FALSE,
-    EL_EM_GATE_4_GRAY,                 -1, -1
+    Xsand_stonesand_quickout_1,                FALSE,  FALSE,
+    EL_QUICKSAND_EMPTYING,             -1, -1
   },
   {
-    Xfake_door_5,                      TRUE,   FALSE,
-    EL_EMC_GATE_5_GRAY,                        -1, -1
+    Xsand_stonesand_quickout_2,                FALSE,  FALSE,
+    EL_QUICKSAND_EMPTYING,             -1, -1
   },
+
   {
-    Xfake_door_6,                      TRUE,   FALSE,
-    EL_EMC_GATE_6_GRAY,                        -1, -1
+    Xslide_ns,                         TRUE,   FALSE,
+    EL_EXPANDABLE_WALL_VERTICAL,       -1, -1
   },
   {
-    Xfake_door_7,                      TRUE,   FALSE,
-    EL_EMC_GATE_7_GRAY,                        -1, -1
+    Yslide_ns_blank,                   FALSE,  FALSE,
+    EL_EXPANDABLE_WALL_VERTICAL,       ACTION_GROWING, -1
   },
   {
-    Xfake_door_8,                      TRUE,   FALSE,
-    EL_EMC_GATE_8_GRAY,                        -1, -1
+    Xslide_ew,                         TRUE,   FALSE,
+    EL_EXPANDABLE_WALL_HORIZONTAL,     -1, -1
   },
   {
-    Xfake_acid_1,                      TRUE,   FALSE,
-    EL_EMC_FAKE_ACID,                  -1, -1
+    Yslide_ew_blank,                   FALSE,  FALSE,
+    EL_EXPANDABLE_WALL_HORIZONTAL,     ACTION_GROWING, -1
   },
+
   {
-    Xfake_acid_2,                      FALSE,  FALSE,
-    EL_EMC_FAKE_ACID,                  -1, -1
+    Xwind_n,                           TRUE,   FALSE,
+    EL_BALLOON_SWITCH_UP,              -1, -1
   },
   {
-    Xfake_acid_3,                      FALSE,  FALSE,
-    EL_EMC_FAKE_ACID,                  -1, -1
+    Xwind_e,                           TRUE,   FALSE,
+    EL_BALLOON_SWITCH_RIGHT,           -1, -1
   },
   {
-    Xfake_acid_4,                      FALSE,  FALSE,
-    EL_EMC_FAKE_ACID,                  -1, -1
+    Xwind_s,                           TRUE,   FALSE,
+    EL_BALLOON_SWITCH_DOWN,            -1, -1
   },
   {
-    Xfake_acid_5,                      FALSE,  FALSE,
-    EL_EMC_FAKE_ACID,                  -1, -1
+    Xwind_w,                           TRUE,   FALSE,
+    EL_BALLOON_SWITCH_LEFT,            -1, -1
   },
   {
-    Xfake_acid_6,                      FALSE,  FALSE,
-    EL_EMC_FAKE_ACID,                  -1, -1
+    Xwind_any,                         TRUE,   FALSE,
+    EL_BALLOON_SWITCH_ANY,             -1, -1
   },
   {
-    Xfake_acid_7,                      FALSE,  FALSE,
-    EL_EMC_FAKE_ACID,                  -1, -1
+    Xwind_stop,                                TRUE,   FALSE,
+    EL_BALLOON_SWITCH_NONE,            -1, -1
   },
+
   {
-    Xfake_acid_8,                      FALSE,  FALSE,
-    EL_EMC_FAKE_ACID,                  -1, -1
+    Xexit,                             TRUE,   FALSE,
+    EL_EM_EXIT_CLOSED,                 -1, -1
   },
   {
-    Xsteel_1,                          TRUE,   FALSE,
-    EL_STEELWALL,                      -1, -1
+    Xexit_1,                           TRUE,   FALSE,
+    EL_EM_EXIT_OPEN,                   -1, -1
   },
-  {
-    Xsteel_2,                          TRUE,   FALSE,
-    EL_EMC_STEELWALL_2,                        -1, -1
+  {
+    Xexit_2,                           FALSE,  FALSE,
+    EL_EM_EXIT_OPEN,                   -1, -1
   },
   {
-    Xsteel_3,                          TRUE,   FALSE,
-    EL_EMC_STEELWALL_3,                        -1, -1
+    Xexit_3,                           FALSE,  FALSE,
+    EL_EM_EXIT_OPEN,                   -1, -1
   },
+
   {
-    Xsteel_4,                          TRUE,   FALSE,
-    EL_EMC_STEELWALL_4,                        -1, -1
+    Xpause,                            FALSE,  FALSE,
+    EL_EMPTY,                          -1, -1
   },
+
   {
     Xwall_1,                           TRUE,   FALSE,
     EL_WALL,                           -1, -1
@@ -7093,22 +7422,41 @@ em_object_mapping_list[] =
     Xwall_4,                           TRUE,   FALSE,
     EL_EMC_WALL_16,                    -1, -1
   },
+
   {
-    Xround_wall_1,                     TRUE,   FALSE,
+    Xroundwall_1,                      TRUE,   FALSE,
     EL_WALL_SLIPPERY,                  -1, -1
   },
   {
-    Xround_wall_2,                     TRUE,   FALSE,
+    Xroundwall_2,                      TRUE,   FALSE,
     EL_EMC_WALL_SLIPPERY_2,            -1, -1
   },
   {
-    Xround_wall_3,                     TRUE,   FALSE,
+    Xroundwall_3,                      TRUE,   FALSE,
     EL_EMC_WALL_SLIPPERY_3,            -1, -1
   },
   {
-    Xround_wall_4,                     TRUE,   FALSE,
+    Xroundwall_4,                      TRUE,   FALSE,
     EL_EMC_WALL_SLIPPERY_4,            -1, -1
   },
+
+  {
+    Xsteel_1,                          TRUE,   FALSE,
+    EL_STEELWALL,                      -1, -1
+  },
+  {
+    Xsteel_2,                          TRUE,   FALSE,
+    EL_EMC_STEELWALL_2,                        -1, -1
+  },
+  {
+    Xsteel_3,                          TRUE,   FALSE,
+    EL_EMC_STEELWALL_3,                        -1, -1
+  },
+  {
+    Xsteel_4,                          TRUE,   FALSE,
+    EL_EMC_STEELWALL_4,                        -1, -1
+  },
+
   {
     Xdecor_1,                          TRUE,   FALSE,
     EL_EMC_WALL_8,                     -1, -1
@@ -7157,6 +7505,7 @@ em_object_mapping_list[] =
     Xdecor_12,                         TRUE,   FALSE,
     EL_EMC_WALL_12,                    -1, -1
   },
+
   {
     Xalpha_0,                          TRUE,   FALSE,
     EL_CHAR('0'),                      -1, -1
@@ -7202,8 +7551,8 @@ em_object_mapping_list[] =
     EL_CHAR('!'),                      -1, -1
   },
   {
-    Xalpha_quote,                      TRUE,   FALSE,
-    EL_CHAR('"'),                      -1, -1
+    Xalpha_apost,                      TRUE,   FALSE,
+    EL_CHAR('\''),                     -1, -1
   },
   {
     Xalpha_comma,                      TRUE,   FALSE,
@@ -7343,40 +7692,52 @@ em_object_mapping_list[] =
   },
 
   {
-    Xboom_bug,                         FALSE,  FALSE,
-    EL_BUG,                            ACTION_EXPLODING, -1
+    Ykey_1_blank,                      FALSE,  FALSE,
+    EL_EM_KEY_1,                       ACTION_COLLECTING, -1
   },
   {
-    Xboom_bomb,                                FALSE,  FALSE,
-    EL_BOMB,                           ACTION_EXPLODING, -1
+    Ykey_2_blank,                      FALSE,  FALSE,
+    EL_EM_KEY_2,                       ACTION_COLLECTING, -1
   },
   {
-    Xboom_android,                     FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_OTHER, -1
+    Ykey_3_blank,                      FALSE,  FALSE,
+    EL_EM_KEY_3,                       ACTION_COLLECTING, -1
   },
   {
-    Xboom_1,                           FALSE,  FALSE,
-    EL_DEFAULT,                                ACTION_EXPLODING, -1
+    Ykey_4_blank,                      FALSE,  FALSE,
+    EL_EM_KEY_4,                       ACTION_COLLECTING, -1
   },
   {
-    Xboom_2,                           FALSE,  FALSE,
-    EL_DEFAULT,                                ACTION_EXPLODING, -1
+    Ykey_5_blank,                      FALSE,  FALSE,
+    EL_EMC_KEY_5,                      ACTION_COLLECTING, -1
   },
   {
-    Znormal,                           FALSE,  FALSE,
-    EL_EMPTY,                          -1, -1
+    Ykey_6_blank,                      FALSE,  FALSE,
+    EL_EMC_KEY_6,                      ACTION_COLLECTING, -1
   },
   {
-    Zdynamite,                         FALSE,  FALSE,
-    EL_EMPTY,                          -1, -1
+    Ykey_7_blank,                      FALSE,  FALSE,
+    EL_EMC_KEY_7,                      ACTION_COLLECTING, -1
   },
   {
-    Zplayer,                           FALSE,  FALSE,
-    EL_EMPTY,                          -1, -1
+    Ykey_8_blank,                      FALSE,  FALSE,
+    EL_EMC_KEY_8,                      ACTION_COLLECTING, -1
   },
   {
-    ZBORDER,                           FALSE,  FALSE,
-    EL_EMPTY,                          -1, -1
+    Ylenses_blank,                     FALSE,  FALSE,
+    EL_EMC_LENSES,                     ACTION_COLLECTING, -1
+  },
+  {
+    Ymagnify_blank,                    FALSE,  FALSE,
+    EL_EMC_MAGNIFIER,                  ACTION_COLLECTING, -1
+  },
+  {
+    Ygrass_blank,                      FALSE,  FALSE,
+    EL_EMC_GRASS,                      ACTION_SNAPPING, -1
+  },
+  {
+    Ydirt_blank,                       FALSE,  FALSE,
+    EL_SAND,                           ACTION_SNAPPING, -1
   },
 
   {
@@ -7394,214 +7755,214 @@ static struct Mapping_EM_to_RND_player
   int action;
   int direction;
 }
-em_player_mapping_list[] =
+em_player_mapping_list[MAX_PLAYERS * PLY_MAX + 1] =
 {
   {
-    SPR_walk + 0,                      0,
+    PLY_walk_n,                                0,
     EL_PLAYER_1,                       ACTION_MOVING, MV_BIT_UP,
   },
   {
-    SPR_walk + 1,                      0,
+    PLY_walk_e,                                0,
     EL_PLAYER_1,                       ACTION_MOVING, MV_BIT_RIGHT,
   },
   {
-    SPR_walk + 2,                      0,
+    PLY_walk_s,                                0,
     EL_PLAYER_1,                       ACTION_MOVING, MV_BIT_DOWN,
   },
   {
-    SPR_walk + 3,                      0,
+    PLY_walk_w,                                0,
     EL_PLAYER_1,                       ACTION_MOVING, MV_BIT_LEFT,
   },
   {
-    SPR_push + 0,                      0,
+    PLY_push_n,                                0,
     EL_PLAYER_1,                       ACTION_PUSHING, MV_BIT_UP,
   },
   {
-    SPR_push + 1,                      0,
+    PLY_push_e,                                0,
     EL_PLAYER_1,                       ACTION_PUSHING, MV_BIT_RIGHT,
   },
   {
-    SPR_push + 2,                      0,
+    PLY_push_s,                                0,
     EL_PLAYER_1,                       ACTION_PUSHING, MV_BIT_DOWN,
   },
   {
-    SPR_push + 3,                      0,
+    PLY_push_w,                                0,
     EL_PLAYER_1,                       ACTION_PUSHING, MV_BIT_LEFT,
   },
   {
-    SPR_spray + 0,                     0,
+    PLY_shoot_n,                       0,
     EL_PLAYER_1,                       ACTION_SNAPPING, MV_BIT_UP,
   },
   {
-    SPR_spray + 1,                     0,
+    PLY_shoot_e,                       0,
     EL_PLAYER_1,                       ACTION_SNAPPING, MV_BIT_RIGHT,
   },
   {
-    SPR_spray + 2,                     0,
+    PLY_shoot_s,                       0,
     EL_PLAYER_1,                       ACTION_SNAPPING, MV_BIT_DOWN,
   },
   {
-    SPR_spray + 3,                     0,
+    PLY_shoot_w,                       0,
     EL_PLAYER_1,                       ACTION_SNAPPING, MV_BIT_LEFT,
   },
   {
-    SPR_walk + 0,                      1,
+    PLY_walk_n,                                1,
     EL_PLAYER_2,                       ACTION_MOVING, MV_BIT_UP,
   },
   {
-    SPR_walk + 1,                      1,
+    PLY_walk_e,                                1,
     EL_PLAYER_2,                       ACTION_MOVING, MV_BIT_RIGHT,
   },
   {
-    SPR_walk + 2,                      1,
+    PLY_walk_s,                                1,
     EL_PLAYER_2,                       ACTION_MOVING, MV_BIT_DOWN,
   },
   {
-    SPR_walk + 3,                      1,
+    PLY_walk_w,                                1,
     EL_PLAYER_2,                       ACTION_MOVING, MV_BIT_LEFT,
   },
   {
-    SPR_push + 0,                      1,
+    PLY_push_n,                                1,
     EL_PLAYER_2,                       ACTION_PUSHING, MV_BIT_UP,
   },
   {
-    SPR_push + 1,                      1,
+    PLY_push_e,                                1,
     EL_PLAYER_2,                       ACTION_PUSHING, MV_BIT_RIGHT,
   },
   {
-    SPR_push + 2,                      1,
+    PLY_push_s,                                1,
     EL_PLAYER_2,                       ACTION_PUSHING, MV_BIT_DOWN,
   },
   {
-    SPR_push + 3,                      1,
+    PLY_push_w,                                1,
     EL_PLAYER_2,                       ACTION_PUSHING, MV_BIT_LEFT,
   },
   {
-    SPR_spray + 0,                     1,
+    PLY_shoot_n,                       1,
     EL_PLAYER_2,                       ACTION_SNAPPING, MV_BIT_UP,
   },
   {
-    SPR_spray + 1,                     1,
+    PLY_shoot_e,                       1,
     EL_PLAYER_2,                       ACTION_SNAPPING, MV_BIT_RIGHT,
   },
   {
-    SPR_spray + 2,                     1,
+    PLY_shoot_s,                       1,
     EL_PLAYER_2,                       ACTION_SNAPPING, MV_BIT_DOWN,
   },
   {
-    SPR_spray + 3,                     1,
+    PLY_shoot_w,                       1,
     EL_PLAYER_2,                       ACTION_SNAPPING, MV_BIT_LEFT,
   },
   {
-    SPR_still,                         0,
+    PLY_still,                         0,
     EL_PLAYER_1,                       ACTION_DEFAULT, -1,
   },
   {
-    SPR_still,                         1,
+    PLY_still,                         1,
     EL_PLAYER_2,                       ACTION_DEFAULT, -1,
   },
   {
-    SPR_walk + 0,                      2,
+    PLY_walk_n,                                2,
     EL_PLAYER_3,                       ACTION_MOVING, MV_BIT_UP,
   },
   {
-    SPR_walk + 1,                      2,
+    PLY_walk_e,                                2,
     EL_PLAYER_3,                       ACTION_MOVING, MV_BIT_RIGHT,
   },
   {
-    SPR_walk + 2,                      2,
+    PLY_walk_s,                                2,
     EL_PLAYER_3,                       ACTION_MOVING, MV_BIT_DOWN,
   },
   {
-    SPR_walk + 3,                      2,
+    PLY_walk_w,                                2,
     EL_PLAYER_3,                       ACTION_MOVING, MV_BIT_LEFT,
   },
   {
-    SPR_push + 0,                      2,
+    PLY_push_n,                                2,
     EL_PLAYER_3,                       ACTION_PUSHING, MV_BIT_UP,
   },
   {
-    SPR_push + 1,                      2,
+    PLY_push_e,                                2,
     EL_PLAYER_3,                       ACTION_PUSHING, MV_BIT_RIGHT,
   },
   {
-    SPR_push + 2,                      2,
+    PLY_push_s,                                2,
     EL_PLAYER_3,                       ACTION_PUSHING, MV_BIT_DOWN,
   },
   {
-    SPR_push + 3,                      2,
+    PLY_push_w,                                2,
     EL_PLAYER_3,                       ACTION_PUSHING, MV_BIT_LEFT,
   },
   {
-    SPR_spray + 0,                     2,
+    PLY_shoot_n,                       2,
     EL_PLAYER_3,                       ACTION_SNAPPING, MV_BIT_UP,
   },
   {
-    SPR_spray + 1,                     2,
+    PLY_shoot_e,                       2,
     EL_PLAYER_3,                       ACTION_SNAPPING, MV_BIT_RIGHT,
   },
   {
-    SPR_spray + 2,                     2,
+    PLY_shoot_s,                       2,
     EL_PLAYER_3,                       ACTION_SNAPPING, MV_BIT_DOWN,
   },
   {
-    SPR_spray + 3,                     2,
+    PLY_shoot_w,                       2,
     EL_PLAYER_3,                       ACTION_SNAPPING, MV_BIT_LEFT,
   },
   {
-    SPR_walk + 0,                      3,
+    PLY_walk_n,                                3,
     EL_PLAYER_4,                       ACTION_MOVING, MV_BIT_UP,
   },
   {
-    SPR_walk + 1,                      3,
+    PLY_walk_e,                                3,
     EL_PLAYER_4,                       ACTION_MOVING, MV_BIT_RIGHT,
   },
   {
-    SPR_walk + 2,                      3,
+    PLY_walk_s,                                3,
     EL_PLAYER_4,                       ACTION_MOVING, MV_BIT_DOWN,
   },
   {
-    SPR_walk + 3,                      3,
+    PLY_walk_w,                                3,
     EL_PLAYER_4,                       ACTION_MOVING, MV_BIT_LEFT,
   },
   {
-    SPR_push + 0,                      3,
+    PLY_push_n,                                3,
     EL_PLAYER_4,                       ACTION_PUSHING, MV_BIT_UP,
   },
   {
-    SPR_push + 1,                      3,
+    PLY_push_e,                                3,
     EL_PLAYER_4,                       ACTION_PUSHING, MV_BIT_RIGHT,
   },
   {
-    SPR_push + 2,                      3,
+    PLY_push_s,                                3,
     EL_PLAYER_4,                       ACTION_PUSHING, MV_BIT_DOWN,
   },
   {
-    SPR_push + 3,                      3,
+    PLY_push_w,                                3,
     EL_PLAYER_4,                       ACTION_PUSHING, MV_BIT_LEFT,
   },
   {
-    SPR_spray + 0,                     3,
+    PLY_shoot_n,                       3,
     EL_PLAYER_4,                       ACTION_SNAPPING, MV_BIT_UP,
   },
   {
-    SPR_spray + 1,                     3,
+    PLY_shoot_e,                       3,
     EL_PLAYER_4,                       ACTION_SNAPPING, MV_BIT_RIGHT,
   },
   {
-    SPR_spray + 2,                     3,
+    PLY_shoot_s,                       3,
     EL_PLAYER_4,                       ACTION_SNAPPING, MV_BIT_DOWN,
   },
   {
-    SPR_spray + 3,                     3,
+    PLY_shoot_w,                       3,
     EL_PLAYER_4,                       ACTION_SNAPPING, MV_BIT_LEFT,
   },
   {
-    SPR_still,                         2,
+    PLY_still,                         2,
     EL_PLAYER_3,                       ACTION_DEFAULT, -1,
   },
   {
-    SPR_still,                         3,
+    PLY_still,                         3,
     EL_PLAYER_4,                       ACTION_DEFAULT, -1,
   },
 
@@ -7611,7 +7972,7 @@ em_player_mapping_list[] =
   }
 };
 
-int map_element_RND_to_EM(int element_rnd)
+int map_element_RND_to_EM_cave(int element_rnd)
 {
   static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
   static boolean mapping_initialized = FALSE;
@@ -7632,17 +7993,49 @@ int map_element_RND_to_EM(int element_rnd)
     mapping_initialized = TRUE;
   }
 
-  if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
-    return mapping_RND_to_EM[element_rnd];
+  if (element_rnd < 0 || element_rnd >= NUM_FILE_ELEMENTS)
+  {
+    Warn("invalid RND level element %d", element_rnd);
+
+    return EL_UNKNOWN;
+  }
+
+  return map_em_element_X_to_C(mapping_RND_to_EM[element_rnd]);
+}
+
+int map_element_EM_to_RND_cave(int element_em_cave)
+{
+  static unsigned short mapping_EM_to_RND[GAME_TILE_MAX];
+  static boolean mapping_initialized = FALSE;
+
+  if (!mapping_initialized)
+  {
+    int i;
+
+    // return "EL_UNKNOWN" for all undefined elements in mapping array
+    for (i = 0; i < GAME_TILE_MAX; i++)
+      mapping_EM_to_RND[i] = EL_UNKNOWN;
+
+    for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
+      mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
+       em_object_mapping_list[i].element_rnd;
+
+    mapping_initialized = TRUE;
+  }
+
+  if (element_em_cave < 0 || element_em_cave >= CAVE_TILE_MAX)
+  {
+    Warn("invalid EM cave element %d", element_em_cave);
 
-  Error(ERR_WARN, "invalid RND level element %d", element_rnd);
+    return EL_UNKNOWN;
+  }
 
-  return EL_UNKNOWN;
+  return mapping_EM_to_RND[map_em_element_C_to_X(element_em_cave)];
 }
 
-int map_element_EM_to_RND(int element_em)
+int map_element_EM_to_RND_game(int element_em_game)
 {
-  static unsigned short mapping_EM_to_RND[TILE_MAX];
+  static unsigned short mapping_EM_to_RND[GAME_TILE_MAX];
   static boolean mapping_initialized = FALSE;
 
   if (!mapping_initialized)
@@ -7650,7 +8043,7 @@ int map_element_EM_to_RND(int element_em)
     int i;
 
     // return "EL_UNKNOWN" for all undefined elements in mapping array
-    for (i = 0; i < TILE_MAX; i++)
+    for (i = 0; i < GAME_TILE_MAX; i++)
       mapping_EM_to_RND[i] = EL_UNKNOWN;
 
     for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
@@ -7660,52 +8053,55 @@ int map_element_EM_to_RND(int element_em)
     mapping_initialized = TRUE;
   }
 
-  if (element_em >= 0 && element_em < TILE_MAX)
-    return mapping_EM_to_RND[element_em];
+  if (element_em_game < 0 || element_em_game >= GAME_TILE_MAX)
+  {
+    Warn("invalid EM game element %d", element_em_game);
 
-  Error(ERR_WARN, "invalid EM level element %d", element_em);
+    return EL_UNKNOWN;
+  }
 
-  return EL_UNKNOWN;
+  return mapping_EM_to_RND[element_em_game];
 }
 
 void map_android_clone_elements_RND_to_EM(struct LevelInfo *level)
 {
   struct LevelInfo_EM *level_em = level->native_em_level;
-  struct LEVEL *lev = level_em->lev;
+  struct CAVE *cav = level_em->cav;
   int i, j;
 
-  for (i = 0; i < TILE_MAX; i++)
-    lev->android_array[i] = Xblank;
+  for (i = 0; i < GAME_TILE_MAX; i++)
+    cav->android_array[i] = Cblank;
 
   for (i = 0; i < level->num_android_clone_elements; i++)
   {
     int element_rnd = level->android_clone_element[i];
-    int element_em = map_element_RND_to_EM(element_rnd);
+    int element_em_cave = map_element_RND_to_EM_cave(element_rnd);
 
     for (j = 0; em_object_mapping_list[j].element_em != -1; j++)
       if (em_object_mapping_list[j].element_rnd == element_rnd)
-       lev->android_array[em_object_mapping_list[j].element_em] = element_em;
+       cav->android_array[em_object_mapping_list[j].element_em] =
+         element_em_cave;
   }
 }
 
 void map_android_clone_elements_EM_to_RND(struct LevelInfo *level)
 {
   struct LevelInfo_EM *level_em = level->native_em_level;
-  struct LEVEL *lev = level_em->lev;
+  struct CAVE *cav = level_em->cav;
   int i, j;
 
   level->num_android_clone_elements = 0;
 
-  for (i = 0; i < TILE_MAX; i++)
+  for (i = 0; i < GAME_TILE_MAX; i++)
   {
-    int element_em = lev->android_array[i];
+    int element_em_cave = cav->android_array[i];
     int element_rnd;
     boolean element_found = FALSE;
 
-    if (element_em == Xblank)
+    if (element_em_cave == Cblank)
       continue;
 
-    element_rnd = map_element_EM_to_RND(element_em);
+    element_rnd = map_element_EM_to_RND_cave(element_em_cave);
 
     for (j = 0; j < level->num_android_clone_elements; j++)
       if (level->android_clone_element[j] == element_rnd)
@@ -8134,24 +8530,19 @@ int getBeltSwitchElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
   return getBeltSwitchElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
 }
 
+boolean swapTiles_EM(boolean is_pre_emc_cave)
+{
+  return is_pre_emc_cave && leveldir_current->use_emc_tiles;
+}
+
 boolean getTeamMode_EM(void)
 {
   return game.team_mode || network_playing;
 }
 
-int getGameFrameDelay_EM(int native_em_game_frame_delay)
+boolean isActivePlayer_EM(int player_nr)
 {
-  int game_frame_delay_value;
-
-  game_frame_delay_value =
-    (tape.playing && tape.fast_forward ? FfwdFrameDelay :
-     GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
-     GameFrameDelay);
-
-  if (tape.playing && tape.warp_forward && !tape.pausing)
-    game_frame_delay_value = 0;
-
-  return game_frame_delay_value;
+  return stored_player[player_nr].active;
 }
 
 unsigned int InitRND(int seed)
@@ -8166,8 +8557,8 @@ unsigned int InitRND(int seed)
     return InitEngineRandom_RND(seed);
 }
 
-static struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
-static struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
+static struct Mapping_EM_to_RND_object object_mapping[GAME_TILE_MAX];
+static struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][PLY_MAX];
 
 static int get_effective_element_EM(int tile, int frame_em)
 {
@@ -8182,8 +8573,8 @@ static int get_effective_element_EM(int tile, int frame_em)
   {
     switch (tile)
     {
-      case Yacid_splash_eB:
-      case Yacid_splash_wB:
+      case Xsplash_e:
+      case Xsplash_w:
        return (frame_em > 5 ? EL_EMPTY : element);
 
       default:
@@ -8194,11 +8585,11 @@ static int get_effective_element_EM(int tile, int frame_em)
   {
     switch (tile)
     {
-      case Yacid_splash_eB:
-      case Yacid_splash_wB:
+      case Xsplash_e:
+      case Xsplash_w:
        return EL_EMPTY;
 
-      case Yemerald_stone:
+      case Ynut_stone:
        return EL_EMERALD;
 
       case Ydiamond_stone:
@@ -8206,24 +8597,24 @@ static int get_effective_element_EM(int tile, int frame_em)
 
       case Xdrip_stretch:
       case Xdrip_stretchB:
-      case Ydrip_s1:
-      case Ydrip_s1B:
-      case Xball_1B:
+      case Ydrip_1_s:
+      case Ydrip_1_sB:
+      case Yball_1:
       case Xball_2:
-      case Xball_2B:
-      case Yball_eat:
-      case Ykey_1_eat:
-      case Ykey_2_eat:
-      case Ykey_3_eat:
-      case Ykey_4_eat:
-      case Ykey_5_eat:
-      case Ykey_6_eat:
-      case Ykey_7_eat:
-      case Ykey_8_eat:
-      case Ylenses_eat:
-      case Ymagnify_eat:
-      case Ygrass_eat:
-      case Ydirt_eat:
+      case Yball_2:
+      case Yball_blank:
+      case Ykey_1_blank:
+      case Ykey_2_blank:
+      case Ykey_3_blank:
+      case Ykey_4_blank:
+      case Ykey_5_blank:
+      case Ykey_6_blank:
+      case Ykey_7_blank:
+      case Ykey_8_blank:
+      case Ylenses_blank:
+      case Ymagnify_blank:
+      case Ygrass_blank:
+      case Ydirt_blank:
       case Xsand_stonein_1:
       case Xsand_stonein_2:
       case Xsand_stonein_3:
@@ -8263,9 +8654,9 @@ static boolean check_linear_animation_EM(int tile)
     case Ytank_s_e:
     case Ytank_w_s:
     case Ytank_n_w:
-    case Yacid_splash_eB:
-    case Yacid_splash_wB:
-    case Yemerald_stone:
+    case Xsplash_e:
+    case Xsplash_w:
+    case Ynut_stone:
       return TRUE;
   }
 
@@ -8511,21 +8902,8 @@ void InitGraphicInfo_EM(void)
 {
   int i, j, p;
 
-#if DEBUG_EM_GFX
-  int num_em_gfx_errors = 0;
-
-  if (graphic_info_em_object[0][0].bitmap == NULL)
-  {
-    // EM graphics not yet initialized in em_open_all()
-
-    return;
-  }
-
-  printf("::: [4 errors can be ignored (1 x 'bomb', 3 x 'em_dynamite']\n");
-#endif
-
   // always start with reliable default values
-  for (i = 0; i < TILE_MAX; i++)
+  for (i = 0; i < GAME_TILE_MAX; i++)
   {
     object_mapping[i].element_rnd = EL_UNKNOWN;
     object_mapping[i].is_backside = FALSE;
@@ -8536,7 +8914,7 @@ void InitGraphicInfo_EM(void)
   // always start with reliable default values
   for (p = 0; p < MAX_PLAYERS; p++)
   {
-    for (i = 0; i < SPR_MAX; i++)
+    for (i = 0; i < PLY_MAX; i++)
     {
       player_mapping[p][i].element_rnd = EL_UNKNOWN;
       player_mapping[p][i].action = ACTION_DEFAULT;
@@ -8574,7 +8952,7 @@ void InitGraphicInfo_EM(void)
        MV_DIR_FROM_BIT(em_player_mapping_list[i].direction);
   }
 
-  for (i = 0; i < TILE_MAX; i++)
+  for (i = 0; i < GAME_TILE_MAX; i++)
   {
     int element = object_mapping[i].element_rnd;
     int action = object_mapping[i].action;
@@ -8593,24 +8971,24 @@ void InitGraphicInfo_EM(void)
       int effective_action = (j < 7 ? action :
                              i == Xdrip_stretch ? action :
                              i == Xdrip_stretchB ? action :
-                             i == Ydrip_s1 ? action :
-                             i == Ydrip_s1B ? action :
-                             i == Xball_1B ? action :
+                             i == Ydrip_1_s ? action :
+                             i == Ydrip_1_sB ? action :
+                             i == Yball_1 ? action :
                              i == Xball_2 ? action :
-                             i == Xball_2B ? action :
-                             i == Yball_eat ? action :
-                             i == Ykey_1_eat ? action :
-                             i == Ykey_2_eat ? action :
-                             i == Ykey_3_eat ? action :
-                             i == Ykey_4_eat ? action :
-                             i == Ykey_5_eat ? action :
-                             i == Ykey_6_eat ? action :
-                             i == Ykey_7_eat ? action :
-                             i == Ykey_8_eat ? action :
-                             i == Ylenses_eat ? action :
-                             i == Ymagnify_eat ? action :
-                             i == Ygrass_eat ? action :
-                             i == Ydirt_eat ? action :
+                             i == Yball_2 ? action :
+                             i == Yball_blank ? action :
+                             i == Ykey_1_blank ? action :
+                             i == Ykey_2_blank ? action :
+                             i == Ykey_3_blank ? action :
+                             i == Ykey_4_blank ? action :
+                             i == Ykey_5_blank ? action :
+                             i == Ykey_6_blank ? action :
+                             i == Ykey_7_blank ? action :
+                             i == Ykey_8_blank ? action :
+                             i == Ylenses_blank ? action :
+                             i == Ymagnify_blank ? action :
+                             i == Ygrass_blank ? action :
+                             i == Ydirt_blank ? action :
                              i == Xsand_stonein_1 ? action :
                              i == Xsand_stonein_2 ? action :
                              i == Xsand_stonein_3 ? action :
@@ -8631,7 +9009,7 @@ void InitGraphicInfo_EM(void)
       boolean has_action_graphics = (graphic != base_graphic);
       boolean has_crumbled_graphics = (base_crumbled != base_graphic);
       struct GraphicInfo *g = &graphic_info[graphic];
-      struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
+      struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][j];
       Bitmap *src_bitmap;
       int src_x, src_y;
       // ensure to get symmetric 3-frame, 2-delay animations as used in EM
@@ -8641,8 +9019,8 @@ void InitGraphicInfo_EM(void)
                                   g->anim_mode & ANIM_LINEAR);
       int sync_frame = (i == Xdrip_stretch ? 7 :
                        i == Xdrip_stretchB ? 7 :
-                       i == Ydrip_s2 ? j + 8 :
-                       i == Ydrip_s2B ? j + 8 :
+                       i == Ydrip_2_s ? j + 8 :
+                       i == Ydrip_2_sB ? j + 8 :
                        i == Xacid_1 ? 0 :
                        i == Xacid_2 ? 10 :
                        i == Xacid_3 ? 20 :
@@ -8659,21 +9037,29 @@ void InitGraphicInfo_EM(void)
                        i == Xfake_acid_6 ? 50 :
                        i == Xfake_acid_7 ? 60 :
                        i == Xfake_acid_8 ? 70 :
+                       i == Xfake_acid_1_player ? 0 :
+                       i == Xfake_acid_2_player ? 10 :
+                       i == Xfake_acid_3_player ? 20 :
+                       i == Xfake_acid_4_player ? 30 :
+                       i == Xfake_acid_5_player ? 40 :
+                       i == Xfake_acid_6_player ? 50 :
+                       i == Xfake_acid_7_player ? 60 :
+                       i == Xfake_acid_8_player ? 70 :
                        i == Xball_2 ? 7 :
-                       i == Xball_2B ? j + 8 :
-                       i == Yball_eat ? j + 1 :
-                       i == Ykey_1_eat ? j + 1 :
-                       i == Ykey_2_eat ? j + 1 :
-                       i == Ykey_3_eat ? j + 1 :
-                       i == Ykey_4_eat ? j + 1 :
-                       i == Ykey_5_eat ? j + 1 :
-                       i == Ykey_6_eat ? j + 1 :
-                       i == Ykey_7_eat ? j + 1 :
-                       i == Ykey_8_eat ? j + 1 :
-                       i == Ylenses_eat ? j + 1 :
-                       i == Ymagnify_eat ? j + 1 :
-                       i == Ygrass_eat ? j + 1 :
-                       i == Ydirt_eat ? j + 1 :
+                       i == Yball_2 ? j + 8 :
+                       i == Yball_blank ? j + 1 :
+                       i == Ykey_1_blank ? j + 1 :
+                       i == Ykey_2_blank ? j + 1 :
+                       i == Ykey_3_blank ? j + 1 :
+                       i == Ykey_4_blank ? j + 1 :
+                       i == Ykey_5_blank ? j + 1 :
+                       i == Ykey_6_blank ? j + 1 :
+                       i == Ykey_7_blank ? j + 1 :
+                       i == Ykey_8_blank ? j + 1 :
+                       i == Ylenses_blank ? j + 1 :
+                       i == Ymagnify_blank ? j + 1 :
+                       i == Ygrass_blank ? j + 1 :
+                       i == Ydirt_blank ? j + 1 :
                        i == Xamoeba_1 ? 0 :
                        i == Xamoeba_2 ? 1 :
                        i == Xamoeba_3 ? 2 :
@@ -8715,13 +9101,13 @@ void InitGraphicInfo_EM(void)
                        i == Xboom_bug && j == 5 ? 2 :
                        i == Xboom_bug && j == 6 ? 2 :
                        i == Xboom_bug && j == 7 ? 0 :
-                       i == Xboom_bomb && j == 1 ? 2 :
-                       i == Xboom_bomb && j == 2 ? 2 :
-                       i == Xboom_bomb && j == 3 ? 4 :
-                       i == Xboom_bomb && j == 4 ? 4 :
-                       i == Xboom_bomb && j == 5 ? 2 :
-                       i == Xboom_bomb && j == 6 ? 2 :
-                       i == Xboom_bomb && j == 7 ? 0 :
+                       i == Xboom_tank && j == 1 ? 2 :
+                       i == Xboom_tank && j == 2 ? 2 :
+                       i == Xboom_tank && j == 3 ? 4 :
+                       i == Xboom_tank && j == 4 ? 4 :
+                       i == Xboom_tank && j == 5 ? 2 :
+                       i == Xboom_tank && j == 6 ? 2 :
+                       i == Xboom_tank && j == 7 ? 0 :
                        i == Xboom_android && j == 7 ? 6 :
                        i == Xboom_1 && j == 1 ? 2 :
                        i == Xboom_1 && j == 2 ? 2 :
@@ -8741,13 +9127,6 @@ void InitGraphicInfo_EM(void)
                        special_animation && j == 4 ? 3 :
                        effective_action != action ? 0 :
                        j);
-
-#if DEBUG_EM_GFX
-      Bitmap *debug_bitmap = g_em->bitmap;
-      int debug_src_x = g_em->src_x;
-      int debug_src_y = g_em->src_y;
-#endif
-
       int frame = getAnimationFrame(g->anim_frames,
                                    g->anim_delay,
                                    g->anim_mode,
@@ -8785,10 +9164,10 @@ void InitGraphicInfo_EM(void)
           effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
        int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
        int dy = (move_dir == MV_UP   ? -1 : move_dir == MV_DOWN  ? 1 : 0);
-       int num_steps = (i == Ydrip_s1  ? 16 :
-                        i == Ydrip_s1B ? 16 :
-                        i == Ydrip_s2  ? 16 :
-                        i == Ydrip_s2B ? 16 :
+       int num_steps = (i == Ydrip_1_s  ? 16 :
+                        i == Ydrip_1_sB ? 16 :
+                        i == Ydrip_2_s  ? 16 :
+                        i == Ydrip_2_sB ? 16 :
                         i == Xsand_stonein_1 ? 32 :
                         i == Xsand_stonein_2 ? 32 :
                         i == Xsand_stonein_3 ? 32 :
@@ -8797,8 +9176,8 @@ void InitGraphicInfo_EM(void)
                         i == Xsand_stoneout_2 ? 16 : 8);
        int cx = ABS(dx) * (TILEX / num_steps);
        int cy = ABS(dy) * (TILEY / num_steps);
-       int step_frame = (i == Ydrip_s2         ? j + 8 :
-                         i == Ydrip_s2B        ? j + 8 :
+       int step_frame = (i == Ydrip_2_s        ? j + 8 :
+                         i == Ydrip_2_sB       ? j + 8 :
                          i == Xsand_stonein_2  ? j + 8 :
                          i == Xsand_stonein_3  ? j + 16 :
                          i == Xsand_stonein_4  ? j + 24 :
@@ -8843,78 +9222,10 @@ void InitGraphicInfo_EM(void)
         bit  5 -  0 ( 6 bit): graphic height */
       g_em->unique_identifier =
        (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
-
-#if DEBUG_EM_GFX
-
-      // skip check for EMC elements not contained in original EMC artwork
-      if (element == EL_EMC_FAKE_ACID)
-       continue;
-
-      if (g_em->bitmap != debug_bitmap ||
-         g_em->src_x != debug_src_x ||
-         g_em->src_y != debug_src_y ||
-         g_em->src_offset_x != 0 ||
-         g_em->src_offset_y != 0 ||
-         g_em->dst_offset_x != 0 ||
-         g_em->dst_offset_y != 0 ||
-         g_em->width != TILEX ||
-         g_em->height != TILEY)
-      {
-       static int last_i = -1;
-
-       if (i != last_i)
-       {
-         printf("\n");
-         last_i = i;
-       }
-
-       printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
-              i, element, element_info[element].token_name,
-              element_action_info[effective_action].suffix, direction);
-
-       if (element != effective_element)
-         printf(" [%d ('%s')]",
-                effective_element,
-                element_info[effective_element].token_name);
-
-       printf("\n");
-
-       if (g_em->bitmap != debug_bitmap)
-         printf("    %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
-                j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
-
-       if (g_em->src_x != debug_src_x ||
-           g_em->src_y != debug_src_y)
-         printf("    frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
-                j, (is_backside ? 'B' : 'F'),
-                g_em->src_x, g_em->src_y,
-                g_em->src_x / 32, g_em->src_y / 32,
-                debug_src_x, debug_src_y,
-                debug_src_x / 32, debug_src_y / 32);
-
-       if (g_em->src_offset_x != 0 ||
-           g_em->src_offset_y != 0 ||
-           g_em->dst_offset_x != 0 ||
-           g_em->dst_offset_y != 0)
-         printf("    %d (%d): offsets %d,%d and %d,%d should be all 0\n",
-                j, is_backside,
-                g_em->src_offset_x, g_em->src_offset_y,
-                g_em->dst_offset_x, g_em->dst_offset_y);
-
-       if (g_em->width != TILEX ||
-           g_em->height != TILEY)
-         printf("    %d (%d): size %d,%d should be %d,%d\n",
-                j, is_backside,
-                g_em->width, g_em->height, TILEX, TILEY);
-
-       num_em_gfx_errors++;
-      }
-#endif
-
     }
   }
 
-  for (i = 0; i < TILE_MAX; i++)
+  for (i = 0; i < GAME_TILE_MAX; i++)
   {
     for (j = 0; j < 8; j++)
     {
@@ -8937,8 +9248,8 @@ void InitGraphicInfo_EM(void)
                 Xspring);
 
        // no separate animation for "smashed by rock" -- use rock instead
-       struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
-       struct GraphicInfo_EM *g_xx = &graphic_info_em_object[e][7 - j];
+       struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][j];
+       struct GraphicInfo_EM *g_xx = &graphic_info_em_object[e][j];
 
        g_em->bitmap            = g_xx->bitmap;
        g_em->src_x             = g_xx->src_x;
@@ -8959,7 +9270,7 @@ void InitGraphicInfo_EM(void)
 
   for (p = 0; p < MAX_PLAYERS; p++)
   {
-    for (i = 0; i < SPR_MAX; i++)
+    for (i = 0; i < PLY_MAX; i++)
     {
       int element = player_mapping[p][i].element_rnd;
       int action = player_mapping[p][i].action;
@@ -8974,17 +9285,10 @@ void InitGraphicInfo_EM(void)
                       el_act_dir2img(effective_element, effective_action,
                                      direction));
        struct GraphicInfo *g = &graphic_info[graphic];
-       struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
+       struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][j];
        Bitmap *src_bitmap;
        int src_x, src_y;
        int sync_frame = j;
-
-#if DEBUG_EM_GFX
-       Bitmap *debug_bitmap = g_em->bitmap;
-       int debug_src_x = g_em->src_x;
-       int debug_src_y = g_em->src_y;
-#endif
-
        int frame = getAnimationFrame(g->anim_frames,
                                      g->anim_delay,
                                      g->anim_mode,
@@ -9002,64 +9306,9 @@ void InitGraphicInfo_EM(void)
        g_em->dst_offset_y = 0;
        g_em->width  = TILEX;
        g_em->height = TILEY;
-
-#if DEBUG_EM_GFX
-
-       // skip check for EMC elements not contained in original EMC artwork
-       if (element == EL_PLAYER_3 ||
-           element == EL_PLAYER_4)
-         continue;
-
-       if (g_em->bitmap != debug_bitmap ||
-           g_em->src_x != debug_src_x ||
-           g_em->src_y != debug_src_y)
-       {
-         static int last_i = -1;
-
-         if (i != last_i)
-         {
-           printf("\n");
-           last_i = i;
-         }
-
-         printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
-                p, i, element, element_info[element].token_name,
-                element_action_info[effective_action].suffix, direction);
-
-         if (element != effective_element)
-           printf(" [%d ('%s')]",
-                  effective_element,
-                  element_info[effective_element].token_name);
-
-         printf("\n");
-
-         if (g_em->bitmap != debug_bitmap)
-           printf("    %d: different bitmap! (0x%08x != 0x%08x)\n",
-                  j, (int)(g_em->bitmap), (int)(debug_bitmap));
-
-         if (g_em->src_x != debug_src_x ||
-             g_em->src_y != debug_src_y)
-           printf("    frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
-                  j,
-                  g_em->src_x, g_em->src_y,
-                  g_em->src_x / 32, g_em->src_y / 32,
-                  debug_src_x, debug_src_y,
-                  debug_src_x / 32, debug_src_y / 32);
-
-         num_em_gfx_errors++;
-       }
-#endif
-
       }
     }
   }
-
-#if DEBUG_EM_GFX
-  printf("\n");
-  printf("::: [%d errors found]\n", num_em_gfx_errors);
-
-  exit(0);
-#endif
 }
 
 static void CheckSaveEngineSnapshot_EM(byte action[MAX_PLAYERS], int frame,
@@ -9067,7 +9316,7 @@ static void CheckSaveEngineSnapshot_EM(byte action[MAX_PLAYERS], int frame,
                                       boolean any_player_snapping,
                                       boolean any_player_dropping)
 {
-  if (frame == 0 && !any_player_dropping)
+  if (frame == 7 && !any_player_dropping)
   {
     if (!local_player->was_waiting)
     {
@@ -9119,17 +9368,19 @@ static void CheckSaveEngineSnapshot_MM(boolean element_clicked,
   }
 }
 
-void CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame,
-                           boolean any_player_moving,
-                           boolean any_player_snapping,
-                           boolean any_player_dropping)
+boolean CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame,
+                              boolean any_player_moving,
+                              boolean any_player_snapping,
+                              boolean any_player_dropping)
 {
   if (tape.single_step && tape.recording && !tape.pausing)
-    if (frame == 0 && !any_player_dropping)
+    if (frame == 7 && !any_player_dropping && FrameCounter > 6)
       TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
 
   CheckSaveEngineSnapshot_EM(action, frame, any_player_moving,
                             any_player_snapping, any_player_dropping);
+
+  return tape.pausing;
 }
 
 void CheckSingleStepMode_SP(boolean murphy_is_waiting,
@@ -9293,51 +9544,59 @@ void PlaySoundSelecting(void)
 #endif
 }
 
-void ToggleFullscreenOrChangeWindowScalingIfNeeded(void)
+void ToggleFullscreenIfNeeded(void)
 {
-  boolean change_fullscreen = (setup.fullscreen !=
-                              video.fullscreen_enabled);
-  boolean change_window_scaling_percent = (!video.fullscreen_enabled &&
-                                          setup.window_scaling_percent !=
-                                          video.window_scaling_percent);
-
-  if (change_window_scaling_percent && video.fullscreen_enabled)
+  // if setup and video fullscreen state are already matching, nothing do do
+  if (setup.fullscreen == video.fullscreen_enabled ||
+      !video.fullscreen_available)
     return;
 
-  if (!change_window_scaling_percent && !video.fullscreen_available)
-    return;
+  SDLSetWindowFullscreen(setup.fullscreen);
 
-  if (change_window_scaling_percent)
-  {
-    SDLSetWindowScaling(setup.window_scaling_percent);
+  // set setup value according to successfully changed fullscreen mode
+  setup.fullscreen = video.fullscreen_enabled;
+}
 
+void ChangeWindowScalingIfNeeded(void)
+{
+  // if setup and video window scaling are already matching, nothing do do
+  if (setup.window_scaling_percent == video.window_scaling_percent ||
+      video.fullscreen_enabled)
     return;
-  }
-  else if (change_fullscreen)
-  {
-    SDLSetWindowFullscreen(setup.fullscreen);
 
-    // set setup value according to successfully changed fullscreen mode
-    setup.fullscreen = video.fullscreen_enabled;
+  SDLSetWindowScaling(setup.window_scaling_percent);
+
+  // set setup value according to successfully changed window scaling
+  setup.window_scaling_percent = video.window_scaling_percent;
+}
+
+void ChangeVsyncModeIfNeeded(void)
+{
+  int setup_vsync_mode = VSYNC_MODE_STR_TO_INT(setup.vsync_mode);
+  int video_vsync_mode = video.vsync_mode;
 
+  // if setup and video vsync mode are already matching, nothing do do
+  if (setup_vsync_mode == video_vsync_mode)
     return;
-  }
 
-  if (change_fullscreen ||
-      change_window_scaling_percent)
+  // if renderer is using OpenGL, vsync mode can directly be changed
+  SDLSetScreenVsyncMode(setup.vsync_mode);
+
+  // if vsync mode unchanged, try re-creating renderer to set vsync mode
+  if (video.vsync_mode == video_vsync_mode)
   {
     Bitmap *tmp_backbuffer = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
 
-    // save backbuffer content which gets lost when toggling fullscreen mode
+    // save backbuffer content which gets lost when re-creating screen
     BlitBitmap(backbuffer, tmp_backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
 
-    if (change_window_scaling_percent)
-    {
-      // keep window mode, but change window scaling
-      video.fullscreen_enabled = TRUE;         // force new window scaling
-    }
+    // force re-creating screen and renderer to set new vsync mode
+    video.fullscreen_enabled = !setup.fullscreen;
+
+    // when creating new renderer, destroy textures linked to old renderer
+    FreeAllImageTextures();    // needs old renderer to free the textures
 
-    // toggle fullscreen
+    // re-create screen and renderer (including change of vsync mode)
     ChangeVideoModeIfNeeded(setup.fullscreen);
 
     // set setup value according to successfully changed fullscreen mode
@@ -9345,12 +9604,17 @@ void ToggleFullscreenOrChangeWindowScalingIfNeeded(void)
 
     // restore backbuffer content from temporary backbuffer backup bitmap
     BlitBitmap(tmp_backbuffer, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
-
     FreeBitmap(tmp_backbuffer);
 
     // update visible window/screen
     BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+
+    // when changing vsync mode, re-create textures for new renderer
+    InitImageTextures();
   }
+
+  // set setup value according to successfully changed vsync mode
+  setup.vsync_mode = VSYNC_MODE_INT_TO_STR(video.vsync_mode);
 }
 
 static void JoinRectangles(int *x, int *y, int *width, int *height,
@@ -9370,6 +9634,8 @@ void SetAnimStatus(int anim_status_new)
 {
   if (anim_status_new == GAME_MODE_MAIN)
     anim_status_new = GAME_MODE_PSEUDO_MAINONLY;
+  else if (anim_status_new == GAME_MODE_NAMES)
+    anim_status_new = GAME_MODE_PSEUDO_NAMESONLY;
   else if (anim_status_new == GAME_MODE_SCORES)
     anim_status_new = GAME_MODE_PSEUDO_SCORESOLD;
 
@@ -9379,7 +9645,11 @@ void SetAnimStatus(int anim_status_new)
   if ((global.anim_status      == GAME_MODE_PSEUDO_MAINONLY &&
        global.anim_status_next == GAME_MODE_PSEUDO_TYPENAME) ||
       (global.anim_status      == GAME_MODE_PSEUDO_TYPENAME &&
-       global.anim_status_next == GAME_MODE_PSEUDO_MAINONLY))
+       global.anim_status_next == GAME_MODE_PSEUDO_MAINONLY) ||
+      (global.anim_status      == GAME_MODE_PSEUDO_NAMESONLY &&
+       global.anim_status_next == GAME_MODE_PSEUDO_TYPENAMES) ||
+      (global.anim_status      == GAME_MODE_PSEUDO_TYPENAMES &&
+       global.anim_status_next == GAME_MODE_PSEUDO_NAMESONLY))
     global.anim_status = global.anim_status_next;
 }
 
@@ -9480,9 +9750,9 @@ void ChangeViewportPropertiesIfNeeded(void)
 {
   boolean use_mini_tilesize = (level.game_engine_type == GAME_ENGINE_TYPE_MM ?
                               FALSE : setup.small_game_graphics);
-  int gfx_game_mode = game_status;
-  int gfx_game_mode2 = (game_status == GAME_MODE_EDITOR ? GAME_MODE_DEFAULT :
-                       game_status);
+  int gfx_game_mode = getGlobalGameStatus(game_status);
+  int gfx_game_mode2 = (gfx_game_mode == GAME_MODE_EDITOR ? GAME_MODE_DEFAULT :
+                       gfx_game_mode);
   struct RectWithBorder *vp_window    = &viewport.window[gfx_game_mode];
   struct RectWithBorder *vp_playfield = &viewport.playfield[gfx_game_mode];
   struct RectWithBorder *vp_door_1    = &viewport.door_1[gfx_game_mode];
@@ -9536,7 +9806,7 @@ void ChangeViewportPropertiesIfNeeded(void)
     init_gfx_buffers = TRUE;
     init_gadgets_and_anims = TRUE;
 
-    // printf("::: video: init_video_buffer, init_gfx_buffers\n");
+    // Debug("tools:viewport", "video: init_video_buffer, init_gfx_buffers");
   }
 
   if (new_scr_fieldx != SCR_FIELDX ||
@@ -9547,7 +9817,7 @@ void ChangeViewportPropertiesIfNeeded(void)
     SCR_FIELDX = new_scr_fieldx;
     SCR_FIELDY = new_scr_fieldy;
 
-    // printf("::: new_scr_fieldx != SCR_FIELDX ...\n");
+    // Debug("tools:viewport", "new_scr_fieldx != SCR_FIELDX ...");
   }
 
   if (new_sx != SX ||
@@ -9617,7 +9887,7 @@ void ChangeViewportPropertiesIfNeeded(void)
 
     if (new_tilesize_var != TILESIZE_VAR)
     {
-      // printf("::: new_tilesize_var != TILESIZE_VAR\n");
+      // Debug("tools:viewport", "new_tilesize_var != TILESIZE_VAR");
 
       // changing tile size invalidates scroll values of engine snapshots
       FreeEngineSnapshotSingle();
@@ -9651,13 +9921,13 @@ void ChangeViewportPropertiesIfNeeded(void)
     init_gfx_buffers = TRUE;
     init_gadgets_and_anims = TRUE;
 
-    // printf("::: viewports: init_gfx_buffers\n");
-    // printf("::: viewports: init_gadgets_and_anims\n");
+    // Debug("tools:viewport", "viewports: init_gfx_buffers");
+    // Debug("tools:viewport", "viewports: init_gadgets_and_anims");
   }
 
   if (init_gfx_buffers)
   {
-    // printf("::: init_gfx_buffers\n");
+    // Debug("tools:viewport", "init_gfx_buffers");
 
     SCR_FIELDX = new_scr_fieldx_buffers;
     SCR_FIELDY = new_scr_fieldy_buffers;
@@ -9673,7 +9943,7 @@ void ChangeViewportPropertiesIfNeeded(void)
 
   if (init_video_buffer)
   {
-    // printf("::: init_video_buffer\n");
+    // Debug("tools:viewport", "init_video_buffer");
 
     FreeAllImageTextures();    // needs old renderer to free the textures
 
@@ -9683,7 +9953,7 @@ void ChangeViewportPropertiesIfNeeded(void)
 
   if (init_gadgets_and_anims)
   {
-    // printf("::: init_gadgets_and_anims\n");
+    // Debug("tools:viewport", "init_gadgets_and_anims");
 
     InitGadgets();
     InitGlobalAnimations();
@@ -9691,6 +9961,209 @@ void ChangeViewportPropertiesIfNeeded(void)
 
   if (init_em_graphics)
   {
-      InitGraphicInfo_EM();
+    InitGraphicInfo_EM();
+  }
+}
+
+void OpenURL(char *url)
+{
+  SDL_OpenURL(url);
+}
+
+void OpenURLFromHash(SetupFileHash *hash, int hash_key)
+{
+  OpenURL(getHashEntry(hash, int2str(hash_key, 0)));
+}
+
+
+// ============================================================================
+// tests
+// ============================================================================
+
+#if defined(PLATFORM_WINDOWS)
+/* FILETIME of Jan 1 1970 00:00:00. */
+static const unsigned __int64 epoch = ((unsigned __int64) 116444736000000000ULL);
+
+/*
+ * timezone information is stored outside the kernel so tzp isn't used anymore.
+ *
+ * Note: this function is not for Win32 high precision timing purpose. See
+ * elapsed_time().
+ */
+static int gettimeofday_windows(struct timeval * tp, struct timezone * tzp)
+{
+  FILETIME    file_time;
+  SYSTEMTIME  system_time;
+  ULARGE_INTEGER ularge;
+
+  GetSystemTime(&system_time);
+  SystemTimeToFileTime(&system_time, &file_time);
+  ularge.LowPart = file_time.dwLowDateTime;
+  ularge.HighPart = file_time.dwHighDateTime;
+
+  tp->tv_sec = (long) ((ularge.QuadPart - epoch) / 10000000L);
+  tp->tv_usec = (long) (system_time.wMilliseconds * 1000);
+
+  return 0;
+}
+#endif
+
+static char *test_init_uuid_random_function_simple(void)
+{
+  static char seed_text[100];
+  unsigned int seed = InitSimpleRandom(NEW_RANDOMIZE);
+
+  sprintf(seed_text, "%d", seed);
+
+  return seed_text;
+}
+
+static char *test_init_uuid_random_function_better(void)
+{
+  static char seed_text[100];
+  struct timeval current_time;
+
+  gettimeofday(&current_time, NULL);
+
+  prng_seed_bytes(&current_time, sizeof(current_time));
+
+  sprintf(seed_text, "%ld.%ld",
+         (long)current_time.tv_sec,
+         (long)current_time.tv_usec);
+
+  return seed_text;
+}
+
+#if defined(PLATFORM_WINDOWS)
+static char *test_init_uuid_random_function_better_windows(void)
+{
+  static char seed_text[100];
+  struct timeval current_time;
+
+  gettimeofday_windows(&current_time, NULL);
+
+  prng_seed_bytes(&current_time, sizeof(current_time));
+
+  sprintf(seed_text, "%ld.%ld",
+         (long)current_time.tv_sec,
+         (long)current_time.tv_usec);
+
+  return seed_text;
+}
+#endif
+
+static unsigned int test_uuid_random_function_simple(int max)
+{
+  return GetSimpleRandom(max);
+}
+
+static unsigned int test_uuid_random_function_better(int max)
+{
+  return (max > 0 ? prng_get_uint() % max : 0);
+}
+
+#if defined(PLATFORM_WINDOWS)
+#define NUM_UUID_TESTS                 3
+#else
+#define NUM_UUID_TESTS                 2
+#endif
+
+static void TestGeneratingUUIDs_RunTest(int nr, int always_seed, int num_uuids)
+{
+  struct hashtable *hash_seeds =
+    create_hashtable(16, 0.75, get_hash_from_key, hash_keys_are_equal);
+  struct hashtable *hash_uuids =
+    create_hashtable(16, 0.75, get_hash_from_key, hash_keys_are_equal);
+  static char message[100];
+  int i;
+
+  char *random_name = (nr == 0 ? "simple" : "better");
+  char *random_type = (always_seed ? "always" : "only once");
+  char *(*init_random_function)(void) =
+    (nr == 0 ?
+     test_init_uuid_random_function_simple :
+     test_init_uuid_random_function_better);
+  unsigned int (*random_function)(int) =
+    (nr == 0 ?
+     test_uuid_random_function_simple :
+     test_uuid_random_function_better);
+  int xpos = 40;
+
+#if defined(PLATFORM_WINDOWS)
+  if (nr == 2)
+  {
+    random_name = "windows";
+    init_random_function = test_init_uuid_random_function_better_windows;
+  }
+#endif
+
+  ClearField();
+
+  DrawTextF(xpos, 40, FC_GREEN, "Test: Generating UUIDs");
+  DrawTextF(xpos, 80, FC_YELLOW, "Test %d.%d:", nr + 1, always_seed + 1);
+
+  DrawTextF(xpos, 100, FC_YELLOW, "Random Generator Name: %s", random_name);
+  DrawTextF(xpos, 120, FC_YELLOW, "Seeding Random Generator: %s", random_type);
+  DrawTextF(xpos, 140, FC_YELLOW, "Number of UUIDs generated: %d", num_uuids);
+
+  DrawTextF(xpos, 180, FC_GREEN, "Please wait ...");
+
+  BackToFront();
+
+  // always initialize random number generator at least once
+  init_random_function();
+
+  unsigned int time_start = SDL_GetTicks();
+
+  for (i = 0; i < num_uuids; i++)
+  {
+    if (always_seed)
+    {
+      char *seed = getStringCopy(init_random_function());
+
+      hashtable_remove(hash_seeds, seed);
+      hashtable_insert(hash_seeds, seed, "1");
+    }
+
+    char *uuid = getStringCopy(getUUIDExt(random_function));
+
+    hashtable_remove(hash_uuids, uuid);
+    hashtable_insert(hash_uuids, uuid, "1");
   }
+
+  int num_unique_seeds = hashtable_count(hash_seeds);
+  int num_unique_uuids = hashtable_count(hash_uuids);
+
+  unsigned int time_needed = SDL_GetTicks() - time_start;
+
+  DrawTextF(xpos, 220, FC_YELLOW, "Time needed: %d ms", time_needed);
+
+  DrawTextF(xpos, 240, FC_YELLOW, "Number of unique UUIDs: %d", num_unique_uuids);
+
+  if (always_seed)
+    DrawTextF(xpos, 260, FC_YELLOW, "Number of unique seeds: %d", num_unique_seeds);
+
+  if (nr == NUM_UUID_TESTS - 1 && always_seed)
+    DrawTextF(xpos, 300, FC_GREEN, "All tests done!");
+  else
+    DrawTextF(xpos, 300, FC_GREEN, "Confirm dialog for next test ...");
+
+  sprintf(message, "Test %d.%d finished!", nr + 1, always_seed + 1);
+
+  Request(message, REQ_CONFIRM);
+
+  hashtable_destroy(hash_seeds, 0);
+  hashtable_destroy(hash_uuids, 0);
+}
+
+void TestGeneratingUUIDs(void)
+{
+  int num_uuids = 1000000;
+  int i, j;
+
+  for (i = 0; i < NUM_UUID_TESTS; i++)
+    for (j = 0; j < 2; j++)
+      TestGeneratingUUIDs_RunTest(i, j, num_uuids);
+
+  CloseAllAndExit(0);
 }