fixed graphical bug with wrong draw buffer when using envelope request
[rocksndiamonds.git] / src / tools.c
index f81ff9d90f210075e712ccb9fde88baba9ae558d..099fd59de0c007460883d811c59d2997624745d1 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
 // ============================================================================
 #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 */
+// tool button identifiers
 #define TOOL_CTRL_ID_YES       0
 #define TOOL_CTRL_ID_NO                1
 #define TOOL_CTRL_ID_CONFIRM   2
 #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 */
+// constants for number of doors and door parts
 #define NUM_DOORS              2
 #define NUM_PANELS             NUM_DOORS
 // #define NUM_PANELS          0
@@ -165,7 +166,7 @@ static struct DoorPartControlInfo door_part_controls[] =
 };
 
 
-/* forward declaration for internal use */
+// forward declaration for internal use
 static void UnmapToolButtons(void);
 static void HandleToolButtons(struct GadgetInfo *);
 static int el_act_dir2crm(int, int, int);
@@ -192,34 +193,19 @@ 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 ffx = (scroll_x - SBX_Left)  * TILEX_VAR + dx_var;
+    int sbx_right = SBX_Right + (BorderElement != EL_EMPTY ? 1 : 0);
+    int ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
 
-    if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
+    if (ffx < sbx_right * TILEX_VAR + TILEX_VAR / 2)
       fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
     else
       fx += (dx_var > 0 ? TILEX_VAR : 0);
@@ -240,18 +226,19 @@ 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;
 
   if (EVEN(SCR_FIELDY))
   {
+    int sby_lower = SBY_Lower + (BorderElement != EL_EMPTY ? 1 : 0);
     int ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
 
-    if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
+    if (ffy < sby_lower * TILEY_VAR + TILEY_VAR / 2)
       fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
     else
       fy += (dy_var > 0 ? TILEY_VAR : 0);
@@ -274,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);
@@ -284,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);
@@ -294,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);
@@ -304,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);
@@ -321,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;
 }
 
@@ -408,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)
@@ -466,7 +459,7 @@ void SetDrawtoField(int mode)
 
     drawto_field = fieldbuffer;
   }
-  else /* DRAW_TO_BACKBUFFER */
+  else // DRAW_TO_BACKBUFFER
   {
     FX = SX;
     FY = SY;
@@ -479,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)
@@ -559,7 +557,7 @@ static void DrawMaskedBorderExt_DOOR_2(int draw_target)
 
 static void DrawMaskedBorderExt_DOOR_3(int draw_target)
 {
-  /* currently not available */
+  // currently not available
 }
 
 static void DrawMaskedBorderExt_ALL(int draw_target)
@@ -572,7 +570,7 @@ static void DrawMaskedBorderExt_ALL(int draw_target)
 
 static void DrawMaskedBorderExt(int redraw_mask, int draw_target)
 {
-  /* never draw masked screen borders on borderless screens */
+  // never draw masked screen borders on borderless screens
   if (global.border_status == GAME_MODE_LOADING ||
       global.border_status == GAME_MODE_TITLE)
     return;
@@ -633,68 +631,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)
@@ -719,20 +669,20 @@ static void DrawFramesPerSecond(void)
   int draw_deactivation_mask = GetDrawDeactivationMask();
   boolean draw_masked = (draw_deactivation_mask == REDRAW_NONE);
 
-  /* draw FPS with leading space (needed if field buffer deactivated) */
+  // draw FPS with leading space (needed if field buffer deactivated)
   sprintf(text, " %04.1f fps", global.frames_per_second);
 
-  /* override draw deactivation mask (required for invisible warp mode) */
+  // override draw deactivation mask (required for invisible warp mode)
   SetDrawDeactivationMask(REDRAW_NONE);
 
-  /* draw opaque FPS if field buffer deactivated, else draw masked FPS */
+  // draw opaque FPS if field buffer deactivated, else draw masked FPS
   DrawTextExt(backbuffer, SX + SXSIZE - font_width * strlen(text), SY, text,
              font_nr, (draw_masked ? BLIT_MASKED : BLIT_OPAQUE));
 
-  /* set draw deactivation mask to previous value */
+  // set draw deactivation mask to previous value
   SetDrawDeactivationMask(draw_deactivation_mask);
 
-  /* force full-screen redraw in this frame */
+  // force full-screen redraw in this frame
   redraw_mask = REDRAW_ALL;
 }
 
@@ -764,7 +714,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),
@@ -906,7 +856,7 @@ static void FadeExt(int fade_mask, int fade_mode, int fade_type)
   {
     if (fade_type_skip != FADE_TYPE_NONE)
     {
-      /* skip all fade operations until specified fade operation */
+      // skip all fade operations until specified fade operation
       if (fade_type & fade_type_skip)
        fade_type_skip = FADE_TYPE_NONE;
 
@@ -931,7 +881,7 @@ static void FadeExt(int fade_mask, int fade_mode, int fade_type)
 
   if (fade_type_skip != FADE_TYPE_NONE)
   {
-    /* skip all fade operations until specified fade operation */
+    // skip all fade operations until specified fade operation
     if (fade_type & fade_type_skip)
       fade_type_skip = FADE_TYPE_NONE;
 
@@ -951,11 +901,11 @@ static void FadeExt(int fade_mask, int fade_mode, int fade_type)
     height = FADE_SYSIZE;
 
     if (border.draw_masked_when_fading)
-      draw_border_function = DrawMaskedBorder_FIELD;   /* update when fading */
+      draw_border_function = DrawMaskedBorder_FIELD;   // update when fading
     else
-      DrawMaskedBorder_FIELD();                                /* draw once */
+      DrawMaskedBorder_FIELD();                                // draw once
   }
-  else         /* REDRAW_ALL */
+  else         // REDRAW_ALL
   {
     x = 0;
     y = 0;
@@ -963,19 +913,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);
@@ -991,8 +935,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;
@@ -1015,8 +958,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)
@@ -1042,8 +984,9 @@ void FadeIn(int fade_mask)
   FADE_SXSIZE = FULL_SXSIZE;
   FADE_SYSIZE = FULL_SYSIZE;
 
-  if (game_status == GAME_MODE_PLAYING &&
-      strEqual(setup.touch.control_type, TOUCH_CONTROL_VIRTUAL_BUTTONS))
+  // activate virtual buttons depending on upcoming game status
+  if (strEqual(setup.touch.control_type, TOUCH_CONTROL_VIRTUAL_BUTTONS) &&
+      game_status == GAME_MODE_PLAYING && !tape.playing)
     SetOverlayActive(TRUE);
 
   SetScreenStates_AfterFadingIn();
@@ -1056,7 +999,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();
@@ -1090,21 +1034,21 @@ void FadeSetEnterMenu(void)
 {
   fading = menu.enter_menu;
 
-  FadeSetLeaveNext(fading, TRUE);      /* (keep same fade mode) */
+  FadeSetLeaveNext(fading, TRUE);      // (keep same fade mode)
 }
 
 void FadeSetLeaveMenu(void)
 {
   fading = menu.leave_menu;
 
-  FadeSetLeaveNext(fading, TRUE);      /* (keep same fade mode) */
+  FadeSetLeaveNext(fading, TRUE);      // (keep same fade mode)
 }
 
 void FadeSetEnterScreen(void)
 {
   fading = menu.enter_screen[game_status];
 
-  FadeSetLeaveNext(menu.leave_screen[game_status], TRUE);      /* store */
+  FadeSetLeaveNext(menu.leave_screen[game_status], TRUE);      // store
 }
 
 void FadeSetNextScreen(void)
@@ -1112,12 +1056,12 @@ void FadeSetNextScreen(void)
   fading = menu.next_screen[game_status];
 
   // (do not overwrite fade mode set by FadeSetEnterScreen)
-  // FadeSetLeaveNext(fading, TRUE);   /* (keep same fade mode) */
+  // FadeSetLeaveNext(fading, TRUE);   // (keep same fade mode)
 }
 
 void FadeSetLeaveScreen(void)
 {
-  FadeSetLeaveNext(menu.leave_screen[game_status], FALSE);     /* recall */
+  FadeSetLeaveNext(menu.leave_screen[game_status], FALSE);     // recall
 }
 
 void FadeSetFromType(int type)
@@ -1149,10 +1093,12 @@ void FadeSkipNextFadeOut(void)
 
 static Bitmap *getBitmapFromGraphicOrDefault(int graphic, int default_graphic)
 {
+  if (graphic == IMG_UNDEFINED)
+    return NULL;
+
   boolean redefined = getImageListEntryFromImageID(graphic)->redefined;
 
-  return (graphic == IMG_UNDEFINED ? NULL :
-         graphic_info[graphic].bitmap != NULL || redefined ?
+  return (graphic_info[graphic].bitmap != NULL || redefined ?
          graphic_info[graphic].bitmap :
          graphic_info[default_graphic].bitmap);
 }
@@ -1225,7 +1171,7 @@ void SetPanelBackground(void)
 
 void DrawBackground(int x, int y, int width, int height)
 {
-  /* "drawto" might still point to playfield buffer here (hall of fame) */
+  // "drawto" might still point to playfield buffer here (hall of fame)
   ClearRectangleOnBackground(backbuffer, x, y, width, height);
 
   if (IN_GFX_FIELD_FULL(x, y))
@@ -1353,6 +1299,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)
@@ -1423,11 +1372,11 @@ void ClearField(void)
 {
   RedrawGlobalBorderIfNeeded();
 
-  /* !!! "drawto" might still point to playfield buffer here (see above) !!! */
-  /* (when entering hall of fame after playing) */
+  // !!! "drawto" might still point to playfield buffer here (see above) !!!
+  // (when entering hall of fame after playing)
   DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
 
-  /* !!! maybe this should be done before clearing the background !!! */
+  // !!! maybe this should be done before clearing the background !!!
   if (game_status == GAME_MODE_PLAYING)
   {
     ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
@@ -1450,15 +1399,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)
@@ -1477,14 +1426,14 @@ void FloodFillLevelExt(int from_x, int from_y, int fill_element,
   static int check[4][2] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };
   static int safety = 0;
 
-  /* check if starting field still has the desired content */
+  // check if starting field still has the desired content
   if (field[from_x][from_y] == fill_element)
     return;
 
   safety++;
 
   if (safety > max_fieldx * max_fieldy)
-    Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug.");
+    Fail("Something went wrong in 'FloodFill()'. Please debug.");
 
   old_element = field[from_x][from_y];
   field[from_x][from_y] = fill_element;
@@ -1518,7 +1467,7 @@ void SetRandomAnimationValue(int x, int y)
 
 int getGraphicAnimationFrame(int graphic, int sync_frame)
 {
-  /* animation synchronized with global frame counter, not move position */
+  // animation synchronized with global frame counter, not move position
   if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
     sync_frame = FrameCounter;
 
@@ -1549,7 +1498,7 @@ void getGraphicSourceXY(int graphic, int frame, int *x, int *y,
   int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
   int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
 
-  if (g->offset_y == 0)                /* frames are ordered horizontally */
+  if (g->offset_y == 0)                // frames are ordered horizontally
   {
     int max_width = g->anim_frames_per_line * g->width;
     int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
@@ -1557,7 +1506,7 @@ void getGraphicSourceXY(int graphic, int frame, int *x, int *y,
     *x = pos % max_width;
     *y = src_y % g->height + pos / max_width * g->height;
   }
-  else if (g->offset_x == 0)   /* frames are ordered vertically */
+  else if (g->offset_x == 0)   // frames are ordered vertically
   {
     int max_height = g->anim_frames_per_line * g->height;
     int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
@@ -1565,7 +1514,7 @@ void getGraphicSourceXY(int graphic, int frame, int *x, int *y,
     *x = src_x % g->width + pos / max_height * g->width;
     *y = pos % max_height;
   }
-  else                         /* frames are ordered diagonally */
+  else                         // frames are ordered diagonally
   {
     *x = src_x + frame * g->offset_x;
     *y = src_y + frame * g->offset_y;
@@ -1627,8 +1576,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
@@ -1644,8 +1594,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
@@ -1681,8 +1633,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
@@ -1698,8 +1652,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
@@ -1793,35 +1749,35 @@ static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
   int width = TILEX, height = TILEY;
   int cx = 0, cy = 0;
 
-  if (dx || dy)                        /* shifted graphic */
+  if (dx || dy)                        // shifted graphic
   {
-    if (x < BX1)               /* object enters playfield from the left */
+    if (x < BX1)               // object enters playfield from the left
     {
       x = BX1;
       width = dx;
       cx = TILEX - dx;
       dx = 0;
     }
-    else if (x > BX2)          /* object enters playfield from the right */
+    else if (x > BX2)          // object enters playfield from the right
     {
       x = BX2;
       width = -dx;
       dx = TILEX + dx;
     }
-    else if (x == BX1 && dx < 0) /* object leaves playfield to the left */
+    else if (x == BX1 && dx < 0) // object leaves playfield to the left
     {
       width += dx;
       cx = -dx;
       dx = 0;
     }
-    else if (x == BX2 && dx > 0) /* object leaves playfield to the right */
+    else if (x == BX2 && dx > 0) // object leaves playfield to the right
       width -= dx;
-    else if (dx)               /* general horizontal movement */
+    else if (dx)               // general horizontal movement
       MarkTileDirty(x + SIGN(dx), y);
 
-    if (y < BY1)               /* object enters playfield from the top */
+    if (y < BY1)               // object enters playfield from the top
     {
-      if (cut_mode == CUT_BELOW) /* object completely above top border */
+      if (cut_mode == CUT_BELOW) // object completely above top border
        return;
 
       y = BY1;
@@ -1829,13 +1785,13 @@ static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
       cy = TILEY - dy;
       dy = 0;
     }
-    else if (y > BY2)          /* object enters playfield from the bottom */
+    else if (y > BY2)          // object enters playfield from the bottom
     {
       y = BY2;
       height = -dy;
       dy = TILEY + dy;
     }
-    else if (y == BY1 && dy < 0) /* object leaves playfield to the top */
+    else if (y == BY1 && dy < 0) // object leaves playfield to the top
     {
       height += dy;
       cy = -dy;
@@ -1843,25 +1799,27 @@ static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
     }
     else if (dy > 0 && cut_mode == CUT_ABOVE)
     {
-      if (y == BY2)            /* object completely above bottom border */
+      if (y == BY2)            // object completely above bottom border
        return;
 
       height = dy;
       cy = TILEY - dy;
       dy = TILEY;
       MarkTileDirty(x, y + 1);
-    }                          /* object leaves playfield to the bottom */
+    }                          // object leaves playfield to the bottom
     else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
       height -= dy;
-    else if (dy)               /* general vertical movement */
+    else if (dy)               // general vertical movement
       MarkTileDirty(x, y + SIGN(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
@@ -1907,22 +1865,22 @@ static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
   int x2 = x + SIGN(dx);
   int y2 = y + SIGN(dy);
 
-  /* movement with two-tile animations must be sync'ed with movement position,
-     not with current GfxFrame (which can be higher when using slow movement) */
+  // movement with two-tile animations must be sync'ed with movement position,
+  // not with current GfxFrame (which can be higher when using slow movement)
   int anim_pos = (dx ? ABS(dx) : ABS(dy));
   int anim_frames = graphic_info[graphic].anim_frames;
 
-  /* (we also need anim_delay here for movement animations with less frames) */
+  // (we also need anim_delay here for movement animations with less frames)
   int anim_delay = graphic_info[graphic].anim_delay;
   int sync_frame = anim_pos * anim_frames * anim_delay / TILESIZE;
 
-  boolean draw_start_tile = (cut_mode != CUT_ABOVE);   /* only for falling! */
-  boolean draw_end_tile   = (cut_mode != CUT_BELOW);   /* only for falling! */
+  boolean draw_start_tile = (cut_mode != CUT_ABOVE);   // only for falling!
+  boolean draw_end_tile   = (cut_mode != CUT_BELOW);   // only for falling!
 
-  /* re-calculate animation frame for two-tile movement animation */
+  // re-calculate animation frame for two-tile movement animation
   frame = getGraphicAnimationFrame(graphic, sync_frame);
 
-  /* check if movement start graphic inside screen area and should be drawn */
+  // check if movement start graphic inside screen area and should be drawn
   if (draw_start_tile && IN_SCR_FIELD(x1, y1))
   {
     getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
@@ -1940,7 +1898,7 @@ static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
     MarkTileDirty(x1, y1);
   }
 
-  /* check if movement end graphic inside screen area and should be drawn */
+  // check if movement end graphic inside screen area and should be drawn
   if (draw_end_tile && IN_SCR_FIELD(x2, y2))
   {
     getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
@@ -1970,7 +1928,7 @@ static void DrawGraphicShifted(int x, int y, int dx, int dy,
     return;
   }
 
-  if (graphic_info[graphic].double_movement)   /* EM style movement images */
+  if (graphic_info[graphic].double_movement)   // EM style movement images
     DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
   else
     DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
@@ -1996,14 +1954,14 @@ void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
     graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
     frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
 
-    /* do not use double (EM style) movement graphic when not moving */
+    // 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]);
     }
   }
-  else /* border element */
+  else // border element
   {
     graphic = el2img(element);
     frame = getGraphicAnimationFrame(graphic, -1);
@@ -2013,9 +1971,9 @@ void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
   {
     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)
@@ -2067,10 +2025,10 @@ 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 !!! */
+// !!! implementation of quicksand is totally broken !!!
 #define IS_CRUMBLED_TILE(x, y, e)                                      \
        (GFX_CRUMBLED(e) && (!IN_LEV_FIELD(x, y) ||                     \
                             !IS_MOVING(x, y) ||                        \
@@ -2101,17 +2059,17 @@ static void DrawLevelFieldCrumbledInnerCorners(int x, int y, int dx, int dy,
     int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
                   BorderElement);
 
-    /* check if neighbour field is of same crumble type */
+    // check if neighbour field is of same crumble type
     boolean same = (IS_CRUMBLED_TILE(xx, yy, element) &&
                    graphic_info[graphic].class ==
                    graphic_info[el_act2crm(element, ACTION_DEFAULT)].class);
 
-    /* return if check prevents inner corner */
+    // return if check prevents inner corner
     if (same == (dxx == dx && dyy == dy))
       return;
   }
 
-  /* if we reach this point, we have an inner corner */
+  // if we reach this point, we have an inner corner
 
   getGraphicSource(graphic, 1, &src_bitmap, &src_x, &src_y);
 
@@ -2140,7 +2098,7 @@ static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
 
   getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
 
-  /* draw simple, sloppy, non-corner-accurate crumbled border */
+  // draw simple, sloppy, non-corner-accurate crumbled border
 
   width  = (dir == 1 || dir == 2 ? crumbled_border_size_var : TILESIZE_VAR);
   height = (dir == 0 || dir == 3 ? crumbled_border_size_var : TILESIZE_VAR);
@@ -2151,12 +2109,12 @@ static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
             FX + sx * TILEX_VAR + cx,
             FY + sy * TILEY_VAR + cy);
 
-  /* (remaining middle border part must be at least as big as corner part) */
+  // (remaining middle border part must be at least as big as corner part)
   if (!(graphic_info[graphic].style & STYLE_ACCURATE_BORDERS) ||
       crumbled_border_size_var >= TILESIZE_VAR / 3)
     return;
 
-  /* correct corners of crumbled border, if needed */
+  // correct corners of crumbled border, if needed
 
   for (i = -1; i <= 1; i += 2)
   {
@@ -2165,12 +2123,12 @@ static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
     int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
                   BorderElement);
 
-    /* check if neighbour field is of same crumble type */
+    // check if neighbour field is of same crumble type
     if (IS_CRUMBLED_TILE(xx, yy, element) &&
        graphic_info[graphic].class ==
        graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
     {
-      /* no crumbled corner, but continued crumbled border */
+      // no crumbled corner, but continued crumbled border
 
       int c1 = (dir == 2 || dir == 3 ? crumbled_border_pos_var : 0);
       int c2 = (i == 1 ? crumbled_border_pos_var : 0);
@@ -2221,12 +2179,12 @@ static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame)
 
   element = TILE_GFX_ELEMENT(x, y);
 
-  if (IS_CRUMBLED_TILE(x, y, element))         /* crumble field itself */
+  if (IS_CRUMBLED_TILE(x, y, element))         // crumble field itself
   {
     if (!IN_SCR_FIELD(sx, sy))
       return;
 
-    /* crumble field borders towards direct neighbour fields */
+    // crumble field borders towards direct neighbour fields
     for (i = 0; i < 4; i++)
     {
       int xx = x + xy[i][0];
@@ -2235,7 +2193,7 @@ static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame)
       element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
                 BorderElement);
 
-      /* check if neighbour field is of same crumble type */
+      // check if neighbour field is of same crumble type
       if (IS_CRUMBLED_TILE(xx, yy, element) &&
          graphic_info[graphic].class ==
          graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
@@ -2244,7 +2202,7 @@ static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame)
       DrawLevelFieldCrumbledBorders(x, y, graphic, frame, i);
     }
 
-    /* crumble inner field corners towards corner neighbour fields */
+    // crumble inner field corners towards corner neighbour fields
     if ((graphic_info[graphic].style & STYLE_INNER_CORNERS) &&
        graphic_info[graphic].anim_frames == 2)
     {
@@ -2259,9 +2217,9 @@ static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame)
 
     MarkTileDirty(sx, sy);
   }
-  else         /* center field is not crumbled -- crumble neighbour fields */
+  else         // center field is not crumbled -- crumble neighbour fields
   {
-    /* crumble field borders of direct neighbour fields */
+    // crumble field borders of direct neighbour fields
     for (i = 0; i < 4; i++)
     {
       int xx = x + xy[i][0];
@@ -2273,7 +2231,9 @@ static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame)
          !IN_SCR_FIELD(sxx, syy))
        continue;
 
-      if (Feld[xx][yy] == EL_ELEMENT_SNAPPING)
+      // do not crumble fields that are being digged or snapped
+      if (Tile[xx][yy] == EL_EMPTY ||
+         Tile[xx][yy] == EL_ELEMENT_SNAPPING)
        continue;
 
       element = TILE_GFX_ELEMENT(xx, yy);
@@ -2288,7 +2248,7 @@ static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame)
       MarkTileDirty(sxx, syy);
     }
 
-    /* crumble inner field corners of corner neighbour fields */
+    // crumble inner field corners of corner neighbour fields
     for (i = 0; i < 4; i++)
     {
       int dx = (i & 1 ? +1 : -1);
@@ -2302,7 +2262,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);
@@ -2328,7 +2288,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]))
   {
@@ -2367,7 +2327,7 @@ void DrawLevelFieldCrumbledNeighbours(int x, int y)
   };
   int i;
 
-  /* crumble direct neighbour fields (required for field borders) */
+  // crumble direct neighbour fields (required for field borders)
   for (i = 0; i < 4; i++)
   {
     int xx = x + xy[i][0];
@@ -2377,14 +2337,14 @@ 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;
 
     DrawLevelField(xx, yy);
   }
 
-  /* crumble corner neighbour fields (required for inner field corners) */
+  // crumble corner neighbour fields (required for inner field corners)
   for (i = 0; i < 4; i++)
   {
     int dx = (i & 1 ? +1 : -1);
@@ -2396,7 +2356,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;
 
@@ -2461,7 +2421,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))
@@ -2528,7 +2488,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 ||
@@ -2681,7 +2641,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);
 }
@@ -2693,7 +2653,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)));
 }
@@ -2822,8 +2782,12 @@ 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
 
-  game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
+  SetOverlayEnabled(FALSE);
+  UnmapAllGadgets();
 
   PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
 
@@ -2833,10 +2797,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)
@@ -2853,6 +2820,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;
@@ -2988,7 +3002,7 @@ static void DrawEnvelopeRequest(char *text)
                                  x, y, x_steps, y_steps,
                                  tile_size, tile_size);
 
-  /* force DOOR font inside door area */
+  // force DOOR font inside door area
   SetFontStatus(GAME_MODE_PSEUDO_DOOR);
 
   DrawTextBuffer(sx + sx_offset, sy + sy_offset, text_final, font_nr,
@@ -3003,6 +3017,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);
 }
@@ -3084,6 +3100,8 @@ static void AnimateEnvelopeRequest(int anim_mode, int action)
       }
     }
 
+    PrepareEnvelopeRequestToScreen(backbuffer, dst_x, dst_y, width, height);
+
     redraw_mask |= REDRAW_FIELD;
 
     BackToFront();
@@ -3099,8 +3117,8 @@ static void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
   int graphic = IMG_BACKGROUND_REQUEST;
   int sound_opening = SND_REQUEST_OPENING;
   int sound_closing = SND_REQUEST_CLOSING;
-  int anim_mode_1 = request.anim_mode;                 /* (higher priority) */
-  int anim_mode_2 = graphic_info[graphic].anim_mode;   /* (lower priority) */
+  int anim_mode_1 = request.anim_mode;                 // (higher priority)
+  int anim_mode_2 = graphic_info[graphic].anim_mode;   // (lower priority)
   int anim_mode = (anim_mode_1 != ANIM_DEFAULT ? anim_mode_1 : anim_mode_2);
   int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
                        anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
@@ -3120,10 +3138,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)
     {
@@ -3136,7 +3157,7 @@ static void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
     DrawEnvelopeRequest(text);
   }
 
-  game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
+  game.envelope_active = TRUE; // needed for RedrawPlayfield() events
 
   if (action == ACTION_OPENING)
   {
@@ -3391,7 +3412,7 @@ static void DrawPreviewLevelExt(boolean restart)
     DrawPreviewLevelInfo(MICROLABEL_LEVEL_NAME);
     DrawPreviewLevelInfo(MICROLABEL_LEVEL_AUTHOR);
 
-    /* initialize delay counters */
+    // initialize delay counters
     DelayReached(&scroll_delay, 0);
     DelayReached(&label_delay, 0);
 
@@ -3415,7 +3436,7 @@ static void DrawPreviewLevelExt(boolean restart)
     return;
   }
 
-  /* scroll preview level, if needed */
+  // scroll preview level, if needed
   if (preview.anim_mode != ANIM_NONE &&
       (level_xsize > preview.xsize || level_ysize > preview.ysize) &&
       DelayReached(&scroll_delay, scroll_delay_value))
@@ -3471,8 +3492,8 @@ static void DrawPreviewLevelExt(boolean restart)
     DrawPreviewLevelPlayfield(from_x, from_y);
   }
 
-  /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
-  /* redraw micro level label, if needed */
+  // !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!!
+  // redraw micro level label, if needed
   if (!strEqual(level.name, NAMELESS_LEVEL_NAME) &&
       !strEqual(level.author, ANONYMOUS_NAME) &&
       !strEqual(level.author, leveldir_current->name) &&
@@ -3513,12 +3534,13 @@ static void DrawPreviewLevelExt(boolean restart)
   }
 }
 
-static void DrawPreviewPlayers(void)
+void DrawPreviewPlayers(void)
 {
   if (game_status != GAME_MODE_MAIN)
     return;
 
-  if (!network.enabled && !setup.team_mode)
+  // do not draw preview players if level preview redefined, but players aren't
+  if (preview.redefined && !menu.main.preview_players.redefined)
     return;
 
   boolean player_found[MAX_PLAYERS];
@@ -3528,7 +3550,7 @@ static void DrawPreviewPlayers(void)
   for (i = 0; i < MAX_PLAYERS; i++)
     player_found[i] = FALSE;
 
-  /* check which players can be found in the level (simple approach) */
+  // check which players can be found in the level (simple approach)
   for (x = 0; x < lev_fieldx; x++)
   {
     for (y = 0; y < lev_fieldy; y++)
@@ -3565,15 +3587,18 @@ static void DrawPreviewPlayers(void)
   int xpos = SX + ALIGNED_XPOS(pos->x, all_players_width,  pos->align);
   int ypos = SY + ALIGNED_YPOS(pos->y, all_players_height, pos->valign);
 
-  /* clear area in which the players will be drawn */
+  // clear area in which the players will be drawn
   ClearRectangleOnBackground(drawto, max_xpos, max_ypos,
                             max_players_width, max_players_height);
 
-  /* only draw players if level is suited for team mode */
+  if (!network.enabled && !setup.team_mode)
+    return;
+
+  // only draw players if level is suited for team mode
   if (num_players < 2)
     return;
 
-  /* draw all players that were found in the level */
+  // draw all players that were found in the level
   for (i = 0; i < MAX_PLAYERS; i++)
   {
     if (player_found[i])
@@ -3623,6 +3648,10 @@ static void DrawNetworkPlayersExt(boolean force)
   if (!network.connected && !force)
     return;
 
+  // do not draw network players if level preview redefined, but players aren't
+  if (preview.redefined && !menu.main.network_players.redefined)
+    return;
+
   int num_players = 0;
   int i;
 
@@ -3649,7 +3678,7 @@ static void DrawNetworkPlayersExt(boolean force)
   ClearRectangleOnBackground(drawto, max_xpos, max_ypos,
                             max_players_width, max_players_height);
 
-  /* first draw local network player ... */
+  // first draw local network player ...
   for (i = 0; i < MAX_PLAYERS; i++)
   {
     if (stored_player[i].connected_network &&
@@ -3665,7 +3694,7 @@ static void DrawNetworkPlayersExt(boolean force)
     }
   }
 
-  /* ... then draw all other network players */
+  // ... then draw all other network players
   for (i = 0; i < MAX_PLAYERS; i++)
   {
     if (stored_player[i].connected_network &&
@@ -3768,7 +3797,7 @@ void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
   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
 }
@@ -3796,14 +3825,14 @@ static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
 {
   if (player->use_murphy)
   {
-    /* this works only because currently only one player can be "murphy" ... */
+    // this works only because currently only one player can be "murphy" ...
     static int last_horizontal_dir = MV_LEFT;
     int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
 
     if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
       last_horizontal_dir = move_dir;
 
-    if (graphic == IMG_SP_MURPHY)      /* undefined => use special graphic */
+    if (graphic == IMG_SP_MURPHY)      // undefined => use special graphic
     {
       int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
 
@@ -3829,87 +3858,122 @@ static boolean equalGraphics(int graphic1, int graphic2)
          g1->anim_mode   == g2->anim_mode);
 }
 
-void DrawAllPlayers(void)
+#define DRAW_PLAYER_OVER_PUSHED_ELEMENT        1
+
+enum
 {
-  int i;
+  DRAW_PLAYER_STAGE_INIT = 0,
+  DRAW_PLAYER_STAGE_LAST_FIELD,
+  DRAW_PLAYER_STAGE_FIELD_UNDER_PLAYER,
+#if DRAW_PLAYER_OVER_PUSHED_ELEMENT
+  DRAW_PLAYER_STAGE_ELEMENT_PUSHED,
+  DRAW_PLAYER_STAGE_PLAYER,
+#else
+  DRAW_PLAYER_STAGE_PLAYER,
+  DRAW_PLAYER_STAGE_ELEMENT_PUSHED,
+#endif
+  DRAW_PLAYER_STAGE_ELEMENT_OVER_PLAYER,
+  DRAW_PLAYER_STAGE_FIELD_OVER_PLAYER,
 
-  for (i = 0; i < MAX_PLAYERS; i++)
-    if (stored_player[i].active)
-      DrawPlayer(&stored_player[i]);
-}
+  NUM_DRAW_PLAYER_STAGES
+};
 
-void DrawPlayerField(int x, int y)
+static void DrawPlayerExt(struct PlayerInfo *player, int drawing_stage)
 {
-  if (!IS_PLAYER(x, y))
+  static int static_last_player_graphic[MAX_PLAYERS];
+  static int static_last_player_frame[MAX_PLAYERS];
+  static boolean static_player_is_opaque[MAX_PLAYERS];
+  static boolean draw_player[MAX_PLAYERS];
+  int pnr = player->index_nr;
+
+  if (drawing_stage == DRAW_PLAYER_STAGE_INIT)
+  {
+    static_last_player_graphic[pnr] = getPlayerGraphic(player, player->MovDir);
+    static_last_player_frame[pnr] = player->Frame;
+    static_player_is_opaque[pnr] = FALSE;
+
+    draw_player[pnr] = TRUE;
+  }
+
+  if (!draw_player[pnr])
     return;
 
-  DrawPlayer(PLAYERINFO(x, y));
-}
+#if DEBUG
+  if (!IN_LEV_FIELD(player->jx, player->jy))
+  {
+    Debug("draw:DrawPlayerExt", "x = %d, y = %d", player->jx, player->jy);
+    Debug("draw:DrawPlayerExt", "This should never happen!");
 
-#define DRAW_PLAYER_OVER_PUSHED_ELEMENT        1
+    draw_player[pnr] = FALSE;
+
+    return;
+  }
+#endif
+
+  int last_player_graphic  = static_last_player_graphic[pnr];
+  int last_player_frame    = static_last_player_frame[pnr];
+  boolean player_is_opaque = static_player_is_opaque[pnr];
 
-void DrawPlayer(struct PlayerInfo *player)
-{
   int jx = player->jx;
   int jy = player->jy;
-  int move_dir = player->MovDir;
+  int move_dir = (player->is_waiting ? player->dir_waiting : player->MovDir);
   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 last_jx = (player->is_moving ? jx - dx : jx);
   int last_jy = (player->is_moving ? jy - dy : jy);
   int next_jx = jx + dx;
   int next_jy = jy + dy;
-  boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
-  boolean player_is_opaque = FALSE;
-  int sx = SCREENX(jx), sy = SCREENY(jy);
-  int sxx = 0, syy = 0;
-  int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
-  int graphic;
-  int action = ACTION_DEFAULT;
-  int last_player_graphic = getPlayerGraphic(player, move_dir);
-  int last_player_frame = player->Frame;
-  int frame = 0;
+  boolean player_is_moving = (player->MovPos != 0 ? TRUE : FALSE);
+  int sx = SCREENX(jx);
+  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 = 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      :
+               player->is_moving     ? ACTION_MOVING          :
+               player->is_snapping   ? ACTION_SNAPPING        :
+               player->is_dropping   ? ACTION_DROPPING        :
+               player->is_waiting    ? player->action_waiting :
+               ACTION_DEFAULT);
+
+  if (drawing_stage == DRAW_PLAYER_STAGE_INIT)
+  {
+    // ------------------------------------------------------------------------
+    // initialize drawing the player
+    // ------------------------------------------------------------------------
 
-  /* GfxElement[][] is set to the element the player is digging or collecting;
-     remove also for off-screen player if the player is not moving anymore */
-  if (IN_LEV_FIELD(jx, jy) && !player_is_moving)
-    GfxElement[jx][jy] = EL_UNDEFINED;
+    draw_player[pnr] = FALSE;
 
-  if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
-    return;
+    // GfxElement[][] is set to the element the player is digging or collecting;
+    // remove also for off-screen player if the player is not moving anymore
+    if (IN_LEV_FIELD(jx, jy) && !player_is_moving)
+      GfxElement[jx][jy] = EL_UNDEFINED;
 
-#if DEBUG
-  if (!IN_LEV_FIELD(jx, jy))
-  {
-    printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
-    printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
-    printf("DrawPlayerField(): This should never happen!\n");
-    return;
-  }
-#endif
+    if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
+      return;
 
-  if (element == EL_EXPLOSION)
-    return;
+    if (element == EL_EXPLOSION)
+      return;
 
-  action = (player->is_pushing    ? ACTION_PUSHING         :
-           player->is_digging    ? ACTION_DIGGING         :
-           player->is_collecting ? ACTION_COLLECTING      :
-           player->is_moving     ? ACTION_MOVING          :
-           player->is_snapping   ? ACTION_SNAPPING        :
-           player->is_dropping   ? ACTION_DROPPING        :
-           player->is_waiting    ? player->action_waiting : ACTION_DEFAULT);
+    InitPlayerGfxAnimation(player, action, move_dir);
 
-  if (player->is_waiting)
-    move_dir = player->dir_waiting;
+    draw_player[pnr] = TRUE;
+  }
+  else if (drawing_stage == DRAW_PLAYER_STAGE_LAST_FIELD)
+  {
+    // ------------------------------------------------------------------------
+    // draw things in the field the player is leaving, if needed
+    // ------------------------------------------------------------------------
 
-  InitPlayerGfxAnimation(player, action, move_dir);
+    if (!IN_SCR_FIELD(sx, sy))
+      draw_player[pnr] = FALSE;
 
-  /* ----------------------------------------------------------------------- */
-  /* draw things in the field the player is leaving, if needed               */
-  /* ----------------------------------------------------------------------- */
+    if (!player->is_moving)
+      return;
 
-  if (player->is_moving)
-  {
     if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
     {
       DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
@@ -3925,35 +3989,32 @@ void DrawPlayer(struct PlayerInfo *player)
             last_element == EL_EM_DYNAMITE_ACTIVE ||
             last_element == EL_SP_DISK_RED_ACTIVE)
       DrawDynamite(last_jx, last_jy);
-#if 0
-    /* !!! this is not enough to prevent flickering of players which are
-       moving next to each others without a free tile between them -- this
-       can only be solved by drawing all players layer by layer (first the
-       background, then the foreground etc.) !!! => TODO */
-    else if (!IS_PLAYER(last_jx, last_jy))
-      DrawLevelField(last_jx, last_jy);
-#else
     else
       DrawLevelField(last_jx, last_jy);
-#endif
 
     if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
       DrawLevelElement(next_jx, next_jy, EL_EMPTY);
   }
+  else if (drawing_stage == DRAW_PLAYER_STAGE_FIELD_UNDER_PLAYER)
+  {
+    // ------------------------------------------------------------------------
+    // draw things behind the player, if needed
+    // ------------------------------------------------------------------------
 
-  if (!IN_SCR_FIELD(sx, sy))
-    return;
+    if (Back[jx][jy])
+    {
+      DrawLevelElement(jx, jy, Back[jx][jy]);
+
+      return;
+    }
 
-  /* ----------------------------------------------------------------------- */
-  /* draw things behind the player, if needed                                */
-  /* ----------------------------------------------------------------------- */
+    if (IS_ACTIVE_BOMB(element))
+    {
+      DrawLevelElement(jx, jy, EL_EMPTY);
+
+      return;
+    }
 
-  if (Back[jx][jy])
-    DrawLevelElement(jx, jy, Back[jx][jy]);
-  else if (IS_ACTIVE_BOMB(element))
-    DrawLevelElement(jx, jy, EL_EMPTY);
-  else
-  {
     if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
     {
       int old_element = GfxElement[jx][jy];
@@ -3966,14 +4027,14 @@ void DrawPlayer(struct PlayerInfo *player)
        DrawGraphic(sx, sy, old_graphic, frame);
 
       if (graphic_info[old_graphic].anim_mode & ANIM_OPAQUE_PLAYER)
-       player_is_opaque = TRUE;
+       static_player_is_opaque[pnr] = TRUE;
     }
     else
     {
       GfxElement[jx][jy] = EL_UNDEFINED;
 
-      /* make sure that pushed elements are drawn with correct frame rate */
-      graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
+      // make sure that pushed elements are drawn with correct frame rate
+      int graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
 
       if (player->is_pushing && player->is_moving && !IS_ANIM_MODE_CE(graphic))
        GfxFrame[jx][jy] = player->StepFrame;
@@ -3981,84 +4042,31 @@ void DrawPlayer(struct PlayerInfo *player)
       DrawLevelField(jx, jy);
     }
   }
-
-#if !DRAW_PLAYER_OVER_PUSHED_ELEMENT
-  /* ----------------------------------------------------------------------- */
-  /* draw player himself                                                     */
-  /* ----------------------------------------------------------------------- */
-
-  graphic = getPlayerGraphic(player, move_dir);
-
-  /* in the case of changed player action or direction, prevent the current
-     animation frame from being restarted for identical animations */
-  if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
-    player->Frame = last_player_frame;
-
-  frame = getGraphicAnimationFrame(graphic, player->Frame);
-
-  if (player->GfxPos)
-  {
-    if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
-      sxx = player->GfxPos;
-    else
-      syy = player->GfxPos;
-  }
-
-  if (player_is_opaque)
-    DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
-  else
-    DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
-
-  if (SHIELD_ON(player))
-  {
-    int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
-                  IMG_SHIELD_NORMAL_ACTIVE);
-    int frame = getGraphicAnimationFrame(graphic, -1);
-
-    DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
-  }
-#endif
-
-#if DRAW_PLAYER_OVER_PUSHED_ELEMENT
-  if (player->GfxPos)
+  else if (drawing_stage == DRAW_PLAYER_STAGE_ELEMENT_PUSHED)
   {
-    if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
-      sxx = player->GfxPos;
-    else
-      syy = player->GfxPos;
-  }
-#endif
+    // ------------------------------------------------------------------------
+    // draw things the player is pushing, if needed
+    // ------------------------------------------------------------------------
 
-  /* ----------------------------------------------------------------------- */
-  /* draw things the player is pushing, if needed                            */
-  /* ----------------------------------------------------------------------- */
+    if (!player->is_pushing || !player->is_moving)
+      return;
 
-  if (player->is_pushing && player->is_moving)
-  {
-    int px = SCREENX(jx), py = SCREENY(jy);
-    int pxx = (TILEX - ABS(sxx)) * dx;
-    int pyy = (TILEY - ABS(syy)) * dy;
     int gfx_frame = GfxFrame[jx][jy];
 
-    int graphic;
-    int sync_frame;
-    int frame;
-
-    if (!IS_MOVING(jx, jy))            /* push movement already finished */
+    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];
     }
 
-    graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
-
-    sync_frame = (IS_ANIM_MODE_CE(graphic) ? gfx_frame : player->StepFrame);
-    frame = getGraphicAnimationFrame(graphic, sync_frame);
+    int graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
+    int sync_frame = (IS_ANIM_MODE_CE(graphic) ? gfx_frame : player->StepFrame);
+    int frame = getGraphicAnimationFrame(graphic, sync_frame);
 
-    /* draw background element under pushed element (like the Sokoban field) */
+    // draw background element under pushed element (like the Sokoban field)
     if (game.use_masked_pushing && IS_MOVING(jx, jy))
     {
-      /* this allows transparent pushing animation over non-black background */
+      // this allows transparent pushing animation over non-black background
 
       if (Back[jx][jy])
        DrawLevelElement(jx, jy, Back[jx][jy]);
@@ -4073,127 +4081,155 @@ void DrawPlayer(struct PlayerInfo *player)
     else if (Back[next_jx][next_jy])
       DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
 
+    int px = SCREENX(jx), py = SCREENY(jy);
+    int pxx = (TILEX - ABS(sxx)) * dx;
+    int pyy = (TILEY - ABS(syy)) * dy;
+
 #if 1
-    /* do not draw (EM style) pushing animation when pushing is finished */
-    /* (two-tile animations usually do not contain start and end frame) */
+    // 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
-    /* masked drawing is needed for EMC style (double) movement graphics */
-    /* !!! (ONLY WHEN DRAWING PUSHED ELEMENT OVER THE PLAYER) !!! */
+    // masked drawing is needed for EMC style (double) movement graphics
+    // !!! (ONLY WHEN DRAWING PUSHED ELEMENT OVER THE PLAYER) !!!
     DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
 #endif
   }
+  else if (drawing_stage == DRAW_PLAYER_STAGE_PLAYER)
+  {
+    // ------------------------------------------------------------------------
+    // draw player himself
+    // ------------------------------------------------------------------------
 
-#if DRAW_PLAYER_OVER_PUSHED_ELEMENT
-  /* ----------------------------------------------------------------------- */
-  /* draw player himself                                                     */
-  /* ----------------------------------------------------------------------- */
-
-  graphic = getPlayerGraphic(player, move_dir);
+    int graphic = getPlayerGraphic(player, move_dir);
 
-  /* in the case of changed player action or direction, prevent the current
-     animation frame from being restarted for identical animations */
-  if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
-    player->Frame = last_player_frame;
+    // in the case of changed player action or direction, prevent the current
+    // animation frame from being restarted for identical animations
+    if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
+      player->Frame = last_player_frame;
 
-  frame = getGraphicAnimationFrame(graphic, player->Frame);
+    int frame = getGraphicAnimationFrame(graphic, player->Frame);
 
-  if (player->GfxPos)
-  {
-    if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
-      sxx = player->GfxPos;
+    if (player_is_opaque)
+      DrawGraphicShifted(sx,sy, sxx,syy, graphic, frame, NO_CUTTING,NO_MASKING);
     else
-      syy = player->GfxPos;
-  }
+      DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
 
-  if (player_is_opaque)
-    DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
-  else
-    DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
+    if (SHIELD_ON(player))
+    {
+      graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
+                IMG_SHIELD_NORMAL_ACTIVE);
+      frame = getGraphicAnimationFrame(graphic, -1);
 
-  if (SHIELD_ON(player))
+      DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
+    }
+  }
+  else if (drawing_stage == DRAW_PLAYER_STAGE_ELEMENT_OVER_PLAYER)
   {
-    int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
-                  IMG_SHIELD_NORMAL_ACTIVE);
-    int frame = getGraphicAnimationFrame(graphic, -1);
+    // ------------------------------------------------------------------------
+    // draw things in front of player (active dynamite or dynabombs)
+    // ------------------------------------------------------------------------
 
-    DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
-  }
-#endif
+    if (IS_ACTIVE_BOMB(element))
+    {
+      int graphic = el2img(element);
+      int frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
 
-  /* ----------------------------------------------------------------------- */
-  /* draw things in front of player (active dynamite or dynabombs)           */
-  /* ----------------------------------------------------------------------- */
+      if (game.emulation == EMU_SUPAPLEX)
+       DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
+      else
+       DrawGraphicThruMask(sx, sy, graphic, frame);
+    }
 
-  if (IS_ACTIVE_BOMB(element))
+    if (player_is_moving && last_element == EL_EXPLOSION)
+    {
+      int element = (GfxElement[last_jx][last_jy] != EL_UNDEFINED ?
+                    GfxElement[last_jx][last_jy] :  EL_EMPTY);
+      int graphic = el_act2img(element, ACTION_EXPLODING);
+      int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
+      int phase = ExplodePhase[last_jx][last_jy] - 1;
+      int frame = getGraphicAnimationFrame(graphic, phase - delay);
+
+      if (phase >= delay)
+       DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
+    }
+  }
+  else if (drawing_stage == DRAW_PLAYER_STAGE_FIELD_OVER_PLAYER)
   {
-    graphic = el2img(element);
-    frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
+    // ------------------------------------------------------------------------
+    // draw elements the player is just walking/passing through/under
+    // ------------------------------------------------------------------------
 
-    if (game.emulation == EMU_SUPAPLEX)
-      DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
-    else
-      DrawGraphicThruMask(sx, sy, graphic, frame);
-  }
+    if (player_is_moving)
+    {
+      // handle the field the player is leaving ...
+      if (IS_ACCESSIBLE_INSIDE(last_element))
+       DrawLevelField(last_jx, last_jy);
+      else if (IS_ACCESSIBLE_UNDER(last_element))
+       DrawLevelFieldThruMask(last_jx, last_jy);
+    }
 
-  if (player_is_moving && last_element == EL_EXPLOSION)
-  {
-    int element = (GfxElement[last_jx][last_jy] != EL_UNDEFINED ?
-                  GfxElement[last_jx][last_jy] :  EL_EMPTY);
-    int graphic = el_act2img(element, ACTION_EXPLODING);
-    int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
-    int phase = ExplodePhase[last_jx][last_jy] - 1;
-    int frame = getGraphicAnimationFrame(graphic, phase - delay);
+    // do not redraw accessible elements if the player is just pushing them
+    if (!player_is_moving || !player->is_pushing)
+    {
+      // ... and the field the player is entering
+      if (IS_ACCESSIBLE_INSIDE(element))
+       DrawLevelField(jx, jy);
+      else if (IS_ACCESSIBLE_UNDER(element))
+       DrawLevelFieldThruMask(jx, jy);
+    }
 
-    if (phase >= delay)
-      DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
+    MarkTileDirty(sx, sy);
   }
+}
 
-  /* ----------------------------------------------------------------------- */
-  /* draw elements the player is just walking/passing through/under          */
-  /* ----------------------------------------------------------------------- */
+void DrawPlayer(struct PlayerInfo *player)
+{
+  int i;
 
-  if (player_is_moving)
-  {
-    /* handle the field the player is leaving ... */
-    if (IS_ACCESSIBLE_INSIDE(last_element))
-      DrawLevelField(last_jx, last_jy);
-    else if (IS_ACCESSIBLE_UNDER(last_element))
-      DrawLevelFieldThruMask(last_jx, last_jy);
-  }
+  for (i = 0; i < NUM_DRAW_PLAYER_STAGES; i++)
+    DrawPlayerExt(player, i);
+}
 
-  /* do not redraw accessible elements if the player is just pushing them */
-  if (!player_is_moving || !player->is_pushing)
-  {
-    /* ... and the field the player is entering */
-    if (IS_ACCESSIBLE_INSIDE(element))
-      DrawLevelField(jx, jy);
-    else if (IS_ACCESSIBLE_UNDER(element))
-      DrawLevelFieldThruMask(jx, jy);
-  }
+void DrawAllPlayers(void)
+{
+  int i, j;
+
+  for (i = 0; i < NUM_DRAW_PLAYER_STAGES; i++)
+    for (j = 0; j < MAX_PLAYERS; j++)
+      if (stored_player[j].active)
+       DrawPlayerExt(&stored_player[j], i);
+}
 
-  MarkTileDirty(sx, sy);
+void DrawPlayerField(int x, int y)
+{
+  if (!IS_PLAYER(x, y))
+    return;
+
+  DrawPlayer(PLAYERINFO(x, y));
 }
 
-/* ------------------------------------------------------------------------- */
+// ----------------------------------------------------------------------------
 
 void WaitForEventToContinue(void)
 {
+  boolean first_wait = TRUE;
   boolean still_wait = TRUE;
 
   if (program.headless)
     return;
 
-  /* simulate releasing mouse button over last gadget, if still pressed */
+  // simulate releasing mouse button over last gadget, if still pressed
   if (button_status)
     HandleGadgets(-1, -1, 0);
 
   button_status = MB_RELEASED;
 
   ClearEventQueue();
+  ClearPlayerAction();
 
   while (still_wait)
   {
@@ -4203,19 +4239,22 @@ void WaitForEventToContinue(void)
     {
       switch (event.type)
       {
-       case EVENT_BUTTONRELEASE:
-       case EVENT_KEYPRESS:
-#if defined(TARGET_SDL2)
+       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:
-#endif
         case SDL_JOYBUTTONDOWN:
          still_wait = FALSE;
          break;
 
-       case EVENT_KEYRELEASE:
-         ClearPlayerAction();
-         break;
-
        default:
          HandleOtherEvents(&event);
          break;
@@ -4226,7 +4265,8 @@ void WaitForEventToContinue(void)
       still_wait = FALSE;
     }
 
-    BackToFront();
+    if (!PendingEvent())
+      BackToFront();
   }
 }
 
@@ -4234,16 +4274,17 @@ 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;
   int result;
 
-  /* when showing request dialog after game ended, deactivate game panel */
+  // when showing request dialog after game ended, deactivate game panel
   if (game_just_ended)
     game.panel.active = FALSE;
 
@@ -4258,11 +4299,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();
 
@@ -4270,7 +4311,7 @@ static int RequestHandleEvents(unsigned int req_state)
 
       if (global.use_envelope_request)
       {
-       /* copy current state of request area to middle of playfield area */
+       // copy current state of request area to middle of playfield area
        BlitBitmap(bitmap_db_store_2, drawto, sx, sy, width, height, sx, sy);
       }
     }
@@ -4281,6 +4322,8 @@ static int RequestHandleEvents(unsigned int req_state)
 
       while (NextValidEvent(&event))
       {
+       event_handled = TRUE;
+
        switch (event.type)
        {
          case EVENT_BUTTONPRESS:
@@ -4309,18 +4352,21 @@ static int RequestHandleEvents(unsigned int req_state)
                button_status = MB_RELEASED;
            }
 
-           /* this sets 'request_gadget_id' */
+           // this sets 'request_gadget_id'
            HandleGadgets(mx, my, button_status);
 
            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;
 
@@ -4338,13 +4384,14 @@ 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;
            }
 
            break;
          }
 
-#if defined(TARGET_SDL2)
          case SDL_WINDOWEVENT:
            HandleWindowEvent((WindowEvent *) &event);
            break;
@@ -4355,7 +4402,6 @@ static int RequestHandleEvents(unsigned int req_state)
          case SDL_APP_DIDENTERFOREGROUND:
            HandlePauseResumeEvent((PauseResumeEvent *) &event);
            break;
-#endif
 
          case EVENT_KEYPRESS:
          {
@@ -4370,31 +4416,27 @@ static int RequestHandleEvents(unsigned int req_state)
 
              case KSYM_Return:
              case KSYM_y:
-#if defined(TARGET_SDL2)
              case KSYM_Y:
              case KSYM_Select:
              case KSYM_Menu:
 #if defined(KSYM_Rewind)
-             case KSYM_Rewind:         /* for Amazon Fire TV remote */
-#endif
+             case KSYM_Rewind:         // for Amazon Fire TV remote
 #endif
                result = 1;
                break;
 
              case KSYM_Escape:
              case KSYM_n:
-#if defined(TARGET_SDL2)
              case KSYM_N:
              case KSYM_Back:
 #if defined(KSYM_FastForward)
-             case KSYM_FastForward:    /* for Amazon Fire TV remote */
-#endif
+             case KSYM_FastForward:    // for Amazon Fire TV remote
 #endif
                result = 0;
                break;
 
              default:
-               HandleKeysDebug(key);
+               HandleKeysDebug(key, KEY_PRESSED);
                break;
            }
 
@@ -4439,11 +4481,11 @@ static int RequestHandleEvents(unsigned int req_state)
            break;
          }
 
+         case EVENT_FINGERRELEASE:
          case EVENT_KEYRELEASE:
            ClearPlayerAction();
            break;
 
-#if defined(TARGET_SDL2)
          case SDL_CONTROLLERBUTTONDOWN:
            switch (event.cbutton.button)
            {
@@ -4503,7 +4545,6 @@ static int RequestHandleEvents(unsigned int req_state)
            HandleJoystickEvent(&event);
            ClearPlayerAction();
            break;
-#endif
 
          default:
            HandleOtherEvents(&event);
@@ -4537,18 +4578,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;
@@ -4556,6 +4604,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;
@@ -4572,35 +4621,35 @@ static boolean RequestDoor(char *text, unsigned int req_state)
   if (game_status == GAME_MODE_PLAYING)
     BlitScreenToBitmap(backbuffer);
 
-  /* disable deactivated drawing when quick-loading level tape recording */
+  // disable deactivated drawing when quick-loading level tape recording
   if (tape.playing && tape.deactivate_display)
     TapeDeactivateDisplayOff(TRUE);
 
   SetMouseCursor(CURSOR_DEFAULT);
 
-  /* pause network game while waiting for request to answer */
+  // pause network game while waiting for request to answer
   if (network.enabled &&
       game_status == GAME_MODE_PLAYING &&
-      !AllPlayersGone &&
+      !game.all_players_gone &&
       req_state & REQUEST_WAIT_FOR_INPUT)
     SendToServer_PausePlaying();
 
   old_door_state = GetDoorState();
 
-  /* simulate releasing mouse button over last gadget, if still pressed */
+  // simulate releasing mouse button over last gadget, if still pressed
   if (button_status)
     HandleGadgets(-1, -1, 0);
 
   UnmapAllGadgets();
 
-  /* draw released gadget before proceeding */
+  // draw released gadget before proceeding
   // BackToFront();
 
   if (old_door_state & DOOR_OPEN_1)
   {
     CloseDoor(DOOR_CLOSE_1);
 
-    /* save old door content */
+    // save old door content
     BlitBitmap(bitmap_db_door_1, bitmap_db_door_1,
               0 * DXSIZE, 0, DXSIZE, DYSIZE, 1 * DXSIZE, 0);
   }
@@ -4608,13 +4657,13 @@ static boolean RequestDoor(char *text, unsigned int req_state)
   SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
   SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
 
-  /* clear door drawing field */
+  // clear door drawing field
   DrawBackground(DX, DY, DXSIZE, DYSIZE);
 
-  /* force DOOR font inside door area */
+  // force DOOR font inside door area
   SetFontStatus(GAME_MODE_PSEUDO_DOOR);
 
-  /* write text for request */
+  // write text for request
   for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
   {
     char text_line[max_request_line_len + 1];
@@ -4658,10 +4707,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)
   {
@@ -4671,7 +4723,7 @@ static boolean RequestDoor(char *text, unsigned int req_state)
     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
   }
 
-  /* copy request gadgets to door backbuffer */
+  // copy request gadgets to door backbuffer
   BlitBitmap(drawto, bitmap_db_door_1, DX, DY, DXSIZE, DYSIZE, 0, 0);
 
   OpenDoor(DOOR_OPEN_1);
@@ -4694,7 +4746,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();
 
@@ -4719,14 +4771,14 @@ static boolean RequestDoor(char *text, unsigned int req_state)
     SetDrawBackgroundMask(REDRAW_FIELD);
   }
 
-  /* continue network game after request */
+  // continue network game after request
   if (network.enabled &&
       game_status == GAME_MODE_PLAYING &&
-      !AllPlayersGone &&
+      !game.all_players_gone &&
       req_state & REQUEST_WAIT_FOR_INPUT)
     SendToServer_ContinuePlaying();
 
-  /* restore deactivated drawing when quick-loading level tape recording */
+  // restore deactivated drawing when quick-loading level tape recording
   if (tape.playing && tape.deactivate_display)
     TapeDeactivateDisplayOn();
 
@@ -4735,25 +4787,26 @@ 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)
     BlitScreenToBitmap(backbuffer);
 
-  /* disable deactivated drawing when quick-loading level tape recording */
+  // disable deactivated drawing when quick-loading level tape recording
   if (tape.playing && tape.deactivate_display)
     TapeDeactivateDisplayOff(TRUE);
 
   SetMouseCursor(CURSOR_DEFAULT);
 
-  /* pause network game while waiting for request to answer */
+  // pause network game while waiting for request to answer
   if (network.enabled &&
       game_status == GAME_MODE_PLAYING &&
-      !AllPlayersGone &&
+      !game.all_players_gone &&
       req_state & REQUEST_WAIT_FOR_INPUT)
     SendToServer_PausePlaying();
 
-  /* simulate releasing mouse button over last gadget, if still pressed */
+  // simulate releasing mouse button over last gadget, if still pressed
   if (button_status)
     HandleGadgets(-1, -1, 0);
 
@@ -4763,7 +4816,7 @@ static boolean RequestEnvelope(char *text, unsigned int req_state)
   // SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
   // SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
 
-  /* clear door drawing field */
+  // clear door drawing field
   // DrawBackground(DX, DY, DXSIZE, DYSIZE);
 
   ShowEnvelopeRequest(text, req_state, ACTION_OPENING);
@@ -4786,7 +4839,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();
 
@@ -4804,14 +4857,14 @@ static boolean RequestEnvelope(char *text, unsigned int req_state)
     SetDrawBackgroundMask(REDRAW_FIELD);
   }
 
-  /* continue network game after request */
+  // continue network game after request
   if (network.enabled &&
       game_status == GAME_MODE_PLAYING &&
-      !AllPlayersGone &&
+      !game.all_players_gone &&
       req_state & REQUEST_WAIT_FOR_INPUT)
     SendToServer_ContinuePlaying();
 
-  /* restore deactivated drawing when quick-loading level tape recording */
+  // restore deactivated drawing when quick-loading level tape recording
   if (tape.playing && tape.deactivate_display)
     TapeDeactivateDisplayOn();
 
@@ -4820,17 +4873,21 @@ static boolean RequestEnvelope(char *text, unsigned int req_state)
 
 boolean Request(char *text, unsigned int req_state)
 {
-  boolean overlay_active = GetOverlayActive();
+  boolean overlay_enabled = GetOverlayEnabled();
   boolean result;
 
-  SetOverlayActive(FALSE);
+  game.request_active_or_moving = TRUE;
+
+  SetOverlayEnabled(FALSE);
 
   if (global.use_envelope_request)
     result = RequestEnvelope(text, req_state);
   else
     result = RequestDoor(text, req_state);
 
-  SetOverlayActive(overlay_active);
+  SetOverlayEnabled(overlay_enabled);
+
+  game.request_active_or_moving = FALSE;
 
   return result;
 }
@@ -4883,7 +4940,7 @@ void InitGraphicCompatibilityInfo_Doors(void)
     struct Rect *door_rect = &door_rect_list[door_index];
     boolean door_gfx_redefined = FALSE;
 
-    /* check if any door part graphic definitions have been redefined */
+    // check if any door part graphic definitions have been redefined
 
     for (j = 0; door_part_controls[j].door_token != -1; j++)
     {
@@ -4894,7 +4951,7 @@ void InitGraphicCompatibilityInfo_Doors(void)
        door_gfx_redefined = TRUE;
     }
 
-    /* check for old-style door graphic/animation modifications */
+    // check for old-style door graphic/animation modifications
 
     if (!door_gfx_redefined)
     {
@@ -4910,7 +4967,7 @@ void InitGraphicCompatibilityInfo_Doors(void)
        struct GraphicInfo *g_part_2 = &graphic_info[part_2];
        int num_door_steps, num_panel_steps;
 
-       /* remove door part graphics other than the two default wings */
+       // remove door part graphics other than the two default wings
 
        for (j = 0; door_part_controls[j].door_token != -1; j++)
        {
@@ -4922,7 +4979,7 @@ void InitGraphicCompatibilityInfo_Doors(void)
            g->bitmap = NULL;
        }
 
-       /* set graphics and screen positions of the default wings */
+       // set graphics and screen positions of the default wings
 
        g_part_1->width  = door_rect->width;
        g_part_1->height = door_rect->height;
@@ -4954,18 +5011,18 @@ void InitGraphicCompatibilityInfo_Doors(void)
          door->part_2.y  += door_rect->height - door->height;
        }
 
-       /* set animation delays for the default wings and panels */
+       // set animation delays for the default wings and panels
 
        door->part_1.step_delay = door->step_delay;
        door->part_2.step_delay = door->step_delay;
        door->panel.step_delay  = door->step_delay;
 
-       /* set animation draw order for the default wings */
+       // set animation draw order for the default wings
 
-       door->part_1.sort_priority = 2; /* draw left wing over ... */
-       door->part_2.sort_priority = 1; /*          ... right wing */
+       door->part_1.sort_priority = 2; // draw left wing over ...
+       door->part_2.sort_priority = 1; //          ... right wing
 
-       /* set animation draw offset for the default wings */
+       // set animation draw offset for the default wings
 
        if (door->anim_mode & ANIM_HORIZONTAL)
        {
@@ -4986,7 +5043,7 @@ void InitGraphicCompatibilityInfo_Doors(void)
          num_door_steps = g_part_1->height / door->step_offset;
        }
 
-       /* set animation draw offset for the default panels */
+       // set animation draw offset for the default panels
 
        if (door->step_offset > 1)
        {
@@ -5015,7 +5072,7 @@ void InitDoors(void)
     struct DoorPartControlInfo *dpc = &door_part_controls[i];
     struct DoorPartOrderInfo *dpo = &door_part_order[i];
 
-    /* initialize "start_step_opening" and "start_step_closing", if needed */
+    // initialize "start_step_opening" and "start_step_closing", if needed
     if (dpc->pos->start_step_opening == 0 &&
        dpc->pos->start_step_closing == 0)
     {
@@ -5023,12 +5080,12 @@ void InitDoors(void)
       dpc->pos->start_step_closing = dpc->pos->start_step;
     }
 
-    /* fill structure for door part draw order (sorted below) */
+    // fill structure for door part draw order (sorted below)
     dpo->nr = i;
     dpo->sort_priority = dpc->pos->sort_priority;
   }
 
-  /* sort door part controls according to sort_priority and graphic number */
+  // sort door part controls according to sort_priority and graphic number
   qsort(door_part_order, MAX_DOOR_PARTS,
         sizeof(struct DoorPartOrderInfo), compareDoorPartOrderInfo);
 }
@@ -5220,7 +5277,7 @@ unsigned int MoveDoor(unsigned int door_state)
     }
     else
     {
-      /* opening door sound has priority over simultaneously closing door */
+      // opening door sound has priority over simultaneously closing door
       if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
       {
         PlayMenuSoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
@@ -5339,7 +5396,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
@@ -5408,7 +5465,7 @@ unsigned int MoveDoor(unsigned int door_state)
 
        current_move_delay += max_step_delay;
 
-       /* prevent OS (Windows) from complaining about program not responding */
+       // prevent OS (Windows) from complaining about program not responding
        CheckQuitEvent();
       }
 
@@ -5418,7 +5475,7 @@ unsigned int MoveDoor(unsigned int door_state)
 
     if (!(door_state & DOOR_NO_DELAY))
     {
-      /* wait for specified door action post delay */
+      // wait for specified door action post delay
       if (door_state & DOOR_ACTION_1 && door_state & DOOR_ACTION_2)
        door_delay_value = MAX(door_1.post_delay, door_2.post_delay);
       else if (door_state & DOOR_ACTION_1)
@@ -5482,7 +5539,7 @@ void DrawSpecialEditorDoor(void)
   if (!useSpecialEditorDoor())
     return;
 
-  /* draw bigger level editor toolbox window */
+  // draw bigger level editor toolbox window
   BlitBitmap(gfx1->bitmap, drawto, gfx1->src_x, gfx1->src_y,
             top_border_width, top_border_height, ex, ey - top_border_height);
   BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto, ex, vy,
@@ -5506,7 +5563,7 @@ void UndrawSpecialEditorDoor(void)
   if (!useSpecialEditorDoor())
     return;
 
-  /* draw normal tape recorder window */
+  // draw normal tape recorder window
   if (graphic_info[IMG_GLOBAL_BORDER].bitmap)
   {
     BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
@@ -5526,43 +5583,56 @@ void UndrawSpecialEditorDoor(void)
 }
 
 
-/* ---------- new tool button stuff ---------------------------------------- */
+// ---------- new tool button stuff -------------------------------------------
 
 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"
   }
 };
 
@@ -5579,8 +5649,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;
@@ -5589,9 +5660,9 @@ void CreateToolButtons(void)
     int y = pos->y;
     int id = i;
 
-    if (global.use_envelope_request)
+    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 ||
@@ -5638,8 +5709,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,
@@ -5651,12 +5722,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;
   }
@@ -5686,414 +5758,289 @@ static void HandleToolButtons(struct GadgetInfo *gi)
 static struct Mapping_EM_to_RND_object
 {
   int element_em;
-  boolean is_rnd_to_em_mapping;                /* unique mapping EM <-> RND */
-  boolean is_backside;                 /* backside of moving element */
+  boolean is_rnd_to_em_mapping;                // unique mapping EM <-> RND
+  boolean is_backside;                 // backside of moving element
 
   int element_rnd;
   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
-  },
-  {
-    Ytank_n,                           FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_UP
-  },
-  {
-    Ytank_nB,                          FALSE,  TRUE,
-    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_UP
-  },
-  {
-    Ytank_e,                           FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_RIGHT
-  },
-  {
-    Ytank_eB,                          FALSE,  TRUE,
-    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_RIGHT
-  },
-  {
-    Ytank_s,                           FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_DOWN
-  },
-  {
-    Ytank_sB,                          FALSE,  TRUE,
-    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_DOWN
-  },
-  {
-    Ytank_w,                           FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_LEFT
-  },
-  {
-    Ytank_wB,                          FALSE,  TRUE,
-    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_LEFT
-  },
-  {
-    Ytank_w_n,                         FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_TURNING_FROM_LEFT, MV_BIT_UP
-  },
-  {
-    Ytank_n_e,                         FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
-  },
-  {
-    Ytank_e_s,                         FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
-  },
-  {
-    Ytank_s_w,                         FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
-  },
-  {
-    Ytank_e_n,                         FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
-  },
-  {
-    Ytank_s_e,                         FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
-  },
-  {
-    Ytank_w_s,                         FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
-  },
-  {
-    Ytank_n_w,                         FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_TURNING_FROM_UP, MV_BIT_LEFT
-  },
-  {
-    Ytank_stone,                       FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_SMASHED_BY_ROCK, -1
-  },
-  {
-    Ytank_spring,                      FALSE,  FALSE,
-    EL_SPACESHIP,                      ACTION_SMASHED_BY_SPRING, -1
-  },
-  {
-    Xandroid,                          TRUE,   FALSE,
-    EL_EMC_ANDROID,                    ACTION_ACTIVE, -1
-  },
-  {
-    Xandroid_1_n,                      FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_UP
-  },
-  {
-    Xandroid_2_n,                      FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_UP
-  },
-  {
-    Xandroid_1_e,                      FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_RIGHT
-  },
-  {
-    Xandroid_2_e,                      FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_RIGHT
-  },
-  {
-    Xandroid_1_w,                      FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_LEFT
-  },
-  {
-    Xandroid_2_w,                      FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_LEFT
-  },
-  {
-    Xandroid_1_s,                      FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_DOWN
-  },
-  {
-    Xandroid_2_s,                      FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_DOWN
-  },
-  {
-    Yandroid_n,                                FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_UP
-  },
-  {
-    Yandroid_nB,                       FALSE,  TRUE,
-    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_UP
-  },
-  {
-    Yandroid_ne,                       FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_GROWING, MV_BIT_UPRIGHT
-  },
-  {
-    Yandroid_neB,                      FALSE,  TRUE,
-    EL_EMC_ANDROID,                    ACTION_SHRINKING, MV_BIT_UPRIGHT
-  },
-  {
-    Yandroid_e,                                FALSE,  FALSE,
-    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_RIGHT
+    Yandroid_e,                                FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_RIGHT
   },
   {
     Yandroid_eB,                       FALSE,  TRUE,
@@ -6139,66 +6086,7 @@ em_object_mapping_list[] =
     Yandroid_nwB,                      FALSE,  TRUE,
     EL_EMC_ANDROID,                    ACTION_SHRINKING, MV_BIT_UPLEFT
   },
-  {
-    Xspring,                           TRUE,   FALSE,
-    EL_SPRING,                         -1, -1
-  },
-  {
-    Xspring_pause,                     FALSE,  FALSE,
-    EL_SPRING,                         -1, -1
-  },
-  {
-    Xspring_e,                         FALSE,  FALSE,
-    EL_SPRING,                         -1, -1
-  },
-  {
-    Xspring_w,                         FALSE,  FALSE,
-    EL_SPRING,                         -1, -1
-  },
-  {
-    Xspring_fall,                      FALSE,  FALSE,
-    EL_SPRING,                         -1, -1
-  },
-  {
-    Yspring_s,                         FALSE,  FALSE,
-    EL_SPRING,                         ACTION_FALLING, -1
-  },
-  {
-    Yspring_sB,                                FALSE,  TRUE,
-    EL_SPRING,                         ACTION_FALLING, -1
-  },
-  {
-    Yspring_e,                         FALSE,  FALSE,
-    EL_SPRING,                         ACTION_MOVING, MV_BIT_RIGHT
-  },
-  {
-    Yspring_eB,                                FALSE,  TRUE,
-    EL_SPRING,                         ACTION_MOVING, MV_BIT_RIGHT
-  },
-  {
-    Yspring_w,                         FALSE,  FALSE,
-    EL_SPRING,                         ACTION_MOVING, MV_BIT_LEFT
-  },
-  {
-    Yspring_wB,                                FALSE,  TRUE,
-    EL_SPRING,                         ACTION_MOVING, MV_BIT_LEFT
-  },
-  {
-    Yspring_kill_e,                    FALSE,  FALSE,
-    EL_SPRING,                         ACTION_EATING, MV_BIT_RIGHT
-  },
-  {
-    Yspring_kill_eB,                   FALSE,  TRUE,
-    EL_SPRING,                         ACTION_EATING, MV_BIT_RIGHT
-  },
-  {
-    Yspring_kill_w,                    FALSE,  FALSE,
-    EL_SPRING,                         ACTION_EATING, MV_BIT_LEFT
-  },
-  {
-    Yspring_kill_wB,                   FALSE,  TRUE,
-    EL_SPRING,                         ACTION_EATING, MV_BIT_LEFT
-  },
+
   {
     Xeater_n,                          TRUE,   FALSE,
     EL_YAMYAM_UP,                      -1, -1
@@ -6255,6 +6143,7 @@ em_object_mapping_list[] =
     Yeater_spring,                     FALSE,  FALSE,
     EL_YAMYAM,                         ACTION_SMASHED_BY_SPRING, -1
   },
+
   {
     Xalien,                            TRUE,   FALSE,
     EL_ROBOT,                          -1, -1
@@ -6303,134 +6192,348 @@ em_object_mapping_list[] =
     Yalien_spring,                     FALSE,  FALSE,
     EL_ROBOT,                          ACTION_SMASHED_BY_SPRING, -1
   },
+
   {
-    Xemerald,                          TRUE,   FALSE,
-    EL_EMERALD,                                -1, -1
+    Xbug_1_n,                          TRUE,   FALSE,
+    EL_BUG_UP,                         -1, -1
   },
   {
-    Xemerald_pause,                    FALSE,  FALSE,
-    EL_EMERALD,                                -1, -1
+    Xbug_1_e,                          TRUE,   FALSE,
+    EL_BUG_RIGHT,                      -1, -1
   },
   {
-    Xemerald_fall,                     FALSE,  FALSE,
-    EL_EMERALD,                                -1, -1
+    Xbug_1_s,                          TRUE,   FALSE,
+    EL_BUG_DOWN,                       -1, -1
   },
   {
-    Xemerald_shine,                    FALSE,  FALSE,
-    EL_EMERALD,                                ACTION_TWINKLING, -1
+    Xbug_1_w,                          TRUE,   FALSE,
+    EL_BUG_LEFT,                       -1, -1
   },
   {
-    Yemerald_s,                                FALSE,  FALSE,
-    EL_EMERALD,                                ACTION_FALLING, -1
+    Xbug_2_n,                          FALSE,  FALSE,
+    EL_BUG_UP,                         -1, -1
   },
   {
-    Yemerald_sB,                       FALSE,  TRUE,
-    EL_EMERALD,                                ACTION_FALLING, -1
+    Xbug_2_e,                          FALSE,  FALSE,
+    EL_BUG_RIGHT,                      -1, -1
   },
   {
-    Yemerald_e,                                FALSE,  FALSE,
-    EL_EMERALD,                                ACTION_MOVING, MV_BIT_RIGHT
+    Xbug_2_s,                          FALSE,  FALSE,
+    EL_BUG_DOWN,                       -1, -1
   },
   {
-    Yemerald_eB,                       FALSE,  TRUE,
-    EL_EMERALD,                                ACTION_MOVING, MV_BIT_RIGHT
+    Xbug_2_w,                          FALSE,  FALSE,
+    EL_BUG_LEFT,                       -1, -1
   },
   {
-    Yemerald_w,                                FALSE,  FALSE,
-    EL_EMERALD,                                ACTION_MOVING, MV_BIT_LEFT
+    Ybug_n,                            FALSE,  FALSE,
+    EL_BUG,                            ACTION_MOVING, MV_BIT_UP
   },
   {
-    Yemerald_wB,                       FALSE,  TRUE,
-    EL_EMERALD,                                ACTION_MOVING, MV_BIT_LEFT
+    Ybug_nB,                           FALSE,  TRUE,
+    EL_BUG,                            ACTION_MOVING, MV_BIT_UP
   },
   {
-    Yemerald_eat,                      FALSE,  FALSE,
-    EL_EMERALD,                                ACTION_COLLECTING, -1
+    Ybug_e,                            FALSE,  FALSE,
+    EL_BUG,                            ACTION_MOVING, MV_BIT_RIGHT
   },
   {
-    Yemerald_stone,                    FALSE,  FALSE,
-    EL_NUT,                            ACTION_BREAKING, -1
+    Ybug_eB,                           FALSE,  TRUE,
+    EL_BUG,                            ACTION_MOVING, MV_BIT_RIGHT
   },
   {
-    Xdiamond,                          TRUE,   FALSE,
-    EL_DIAMOND,                                -1, -1
+    Ybug_s,                            FALSE,  FALSE,
+    EL_BUG,                            ACTION_MOVING, MV_BIT_DOWN
   },
   {
-    Xdiamond_pause,                    FALSE,  FALSE,
-    EL_DIAMOND,                                -1, -1
+    Ybug_sB,                           FALSE,  TRUE,
+    EL_BUG,                            ACTION_MOVING, MV_BIT_DOWN
   },
   {
-    Xdiamond_fall,                     FALSE,  FALSE,
-    EL_DIAMOND,                                -1, -1
+    Ybug_w,                            FALSE,  FALSE,
+    EL_BUG,                            ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Xdiamond_shine,                    FALSE,  FALSE,
-    EL_DIAMOND,                                ACTION_TWINKLING, -1
+    Ybug_wB,                           FALSE,  TRUE,
+    EL_BUG,                            ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Ydiamond_s,                                FALSE,  FALSE,
-    EL_DIAMOND,                                ACTION_FALLING, -1
+    Ybug_w_n,                          FALSE,  FALSE,
+    EL_BUG,                            ACTION_TURNING_FROM_LEFT, MV_BIT_UP
   },
   {
-    Ydiamond_sB,                       FALSE,  TRUE,
-    EL_DIAMOND,                                ACTION_FALLING, -1
+    Ybug_n_e,                          FALSE,  FALSE,
+    EL_BUG,                            ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
   },
   {
-    Ydiamond_e,                                FALSE,  FALSE,
-    EL_DIAMOND,                                ACTION_MOVING, MV_BIT_RIGHT
+    Ybug_e_s,                          FALSE,  FALSE,
+    EL_BUG,                            ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
   },
   {
-    Ydiamond_eB,                       FALSE,  TRUE,
-    EL_DIAMOND,                                ACTION_MOVING, MV_BIT_RIGHT
+    Ybug_s_w,                          FALSE,  FALSE,
+    EL_BUG,                            ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
   },
   {
-    Ydiamond_w,                                FALSE,  FALSE,
-    EL_DIAMOND,                                ACTION_MOVING, MV_BIT_LEFT
+    Ybug_e_n,                          FALSE,  FALSE,
+    EL_BUG,                            ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
+  },
+  {
+    Ybug_s_e,                          FALSE,  FALSE,
+    EL_BUG,                            ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
+  },
+  {
+    Ybug_w_s,                          FALSE,  FALSE,
+    EL_BUG,                            ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
+  },
+  {
+    Ybug_n_w,                          FALSE,  FALSE,
+    EL_BUG,                            ACTION_TURNING_FROM_UP, MV_BIT_LEFT
+  },
+  {
+    Ybug_stone,                                FALSE,  FALSE,
+    EL_BUG,                            ACTION_SMASHED_BY_ROCK, -1
+  },
+  {
+    Ybug_spring,                       FALSE,  FALSE,
+    EL_BUG,                            ACTION_SMASHED_BY_SPRING, -1
+  },
+
+  {
+    Xtank_1_n,                         TRUE,   FALSE,
+    EL_SPACESHIP_UP,                   -1, -1
+  },
+  {
+    Xtank_1_e,                         TRUE,   FALSE,
+    EL_SPACESHIP_RIGHT,                        -1, -1
+  },
+  {
+    Xtank_1_s,                         TRUE,   FALSE,
+    EL_SPACESHIP_DOWN,                 -1, -1
+  },
+  {
+    Xtank_1_w,                         TRUE,   FALSE,
+    EL_SPACESHIP_LEFT,                 -1, -1
+  },
+  {
+    Xtank_2_n,                         FALSE,  FALSE,
+    EL_SPACESHIP_UP,                   -1, -1
+  },
+  {
+    Xtank_2_e,                         FALSE,  FALSE,
+    EL_SPACESHIP_RIGHT,                        -1, -1
+  },
+  {
+    Xtank_2_s,                         FALSE,  FALSE,
+    EL_SPACESHIP_DOWN,                 -1, -1
+  },
+  {
+    Xtank_2_w,                         FALSE,  FALSE,
+    EL_SPACESHIP_LEFT,                 -1, -1
+  },
+  {
+    Ytank_n,                           FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_UP
+  },
+  {
+    Ytank_nB,                          FALSE,  TRUE,
+    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_UP
+  },
+  {
+    Ytank_e,                           FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Ytank_eB,                          FALSE,  TRUE,
+    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Ytank_s,                           FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_DOWN
+  },
+  {
+    Ytank_sB,                          FALSE,  TRUE,
+    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_DOWN
+  },
+  {
+    Ytank_w,                           FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Ytank_wB,                          FALSE,  TRUE,
+    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Ytank_w_n,                         FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_TURNING_FROM_LEFT, MV_BIT_UP
+  },
+  {
+    Ytank_n_e,                         FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
+  },
+  {
+    Ytank_e_s,                         FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
+  },
+  {
+    Ytank_s_w,                         FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
+  },
+  {
+    Ytank_e_n,                         FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
+  },
+  {
+    Ytank_s_e,                         FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
+  },
+  {
+    Ytank_w_s,                         FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
+  },
+  {
+    Ytank_n_w,                         FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_TURNING_FROM_UP, MV_BIT_LEFT
+  },
+  {
+    Ytank_stone,                       FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_SMASHED_BY_ROCK, -1
+  },
+  {
+    Ytank_spring,                      FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_SMASHED_BY_SPRING, -1
+  },
+
+  {
+    Xemerald,                          TRUE,   FALSE,
+    EL_EMERALD,                                -1, -1
+  },
+  {
+    Xemerald_pause,                    FALSE,  FALSE,
+    EL_EMERALD,                                -1, -1
+  },
+  {
+    Xemerald_fall,                     FALSE,  FALSE,
+    EL_EMERALD,                                -1, -1
+  },
+  {
+    Xemerald_shine,                    FALSE,  FALSE,
+    EL_EMERALD,                                ACTION_TWINKLING, -1
+  },
+  {
+    Yemerald_s,                                FALSE,  FALSE,
+    EL_EMERALD,                                ACTION_FALLING, -1
+  },
+  {
+    Yemerald_sB,                       FALSE,  TRUE,
+    EL_EMERALD,                                ACTION_FALLING, -1
+  },
+  {
+    Yemerald_e,                                FALSE,  FALSE,
+    EL_EMERALD,                                ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Yemerald_eB,                       FALSE,  TRUE,
+    EL_EMERALD,                                ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Yemerald_w,                                FALSE,  FALSE,
+    EL_EMERALD,                                ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Yemerald_wB,                       FALSE,  TRUE,
+    EL_EMERALD,                                ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Yemerald_blank,                    FALSE,  FALSE,
+    EL_EMERALD,                                ACTION_COLLECTING, -1
+  },
+
+  {
+    Xdiamond,                          TRUE,   FALSE,
+    EL_DIAMOND,                                -1, -1
+  },
+  {
+    Xdiamond_pause,                    FALSE,  FALSE,
+    EL_DIAMOND,                                -1, -1
+  },
+  {
+    Xdiamond_fall,                     FALSE,  FALSE,
+    EL_DIAMOND,                                -1, -1
+  },
+  {
+    Xdiamond_shine,                    FALSE,  FALSE,
+    EL_DIAMOND,                                ACTION_TWINKLING, -1
+  },
+  {
+    Ydiamond_s,                                FALSE,  FALSE,
+    EL_DIAMOND,                                ACTION_FALLING, -1
+  },
+  {
+    Ydiamond_sB,                       FALSE,  TRUE,
+    EL_DIAMOND,                                ACTION_FALLING, -1
+  },
+  {
+    Ydiamond_e,                                FALSE,  FALSE,
+    EL_DIAMOND,                                ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Ydiamond_eB,                       FALSE,  TRUE,
+    EL_DIAMOND,                                ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Ydiamond_w,                                FALSE,  FALSE,
+    EL_DIAMOND,                                ACTION_MOVING, MV_BIT_LEFT
   },
   {
     Ydiamond_wB,                       FALSE,  TRUE,
     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
@@ -6468,229 +6571,343 @@ em_object_mapping_list[] =
     EL_BOMB,                           ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Ybomb_eat,                         FALSE,  FALSE,
+    Ybomb_blank,                       FALSE,  FALSE,
     EL_BOMB,                           ACTION_ACTIVATING, -1
   },
+
   {
-    Xballoon,                          TRUE,   FALSE,
-    EL_BALLOON,                                -1, -1
+    Xnut,                              TRUE,   FALSE,
+    EL_NUT,                            -1, -1
   },
   {
-    Yballoon_n,                                FALSE,  FALSE,
-    EL_BALLOON,                                ACTION_MOVING, MV_BIT_UP
+    Xnut_pause,                                FALSE,  FALSE,
+    EL_NUT,                            -1, -1
   },
   {
-    Yballoon_nB,                       FALSE,  TRUE,
-    EL_BALLOON,                                ACTION_MOVING, MV_BIT_UP
+    Xnut_fall,                         FALSE,  FALSE,
+    EL_NUT,                            -1, -1
   },
   {
-    Yballoon_e,                                FALSE,  FALSE,
-    EL_BALLOON,                                ACTION_MOVING, MV_BIT_RIGHT
+    Ynut_s,                            FALSE,  FALSE,
+    EL_NUT,                            ACTION_FALLING, -1
   },
   {
-    Yballoon_eB,                       FALSE,  TRUE,
-    EL_BALLOON,                                ACTION_MOVING, MV_BIT_RIGHT
+    Ynut_sB,                           FALSE,  TRUE,
+    EL_NUT,                            ACTION_FALLING, -1
   },
   {
-    Yballoon_s,                                FALSE,  FALSE,
-    EL_BALLOON,                                ACTION_MOVING, MV_BIT_DOWN
+    Ynut_e,                            FALSE,  FALSE,
+    EL_NUT,                            ACTION_MOVING, MV_BIT_RIGHT
   },
   {
-    Yballoon_sB,                       FALSE,  TRUE,
-    EL_BALLOON,                                ACTION_MOVING, MV_BIT_DOWN
+    Ynut_eB,                           FALSE,  TRUE,
+    EL_NUT,                            ACTION_MOVING, MV_BIT_RIGHT
   },
   {
-    Yballoon_w,                                FALSE,  FALSE,
-    EL_BALLOON,                                ACTION_MOVING, MV_BIT_LEFT
+    Ynut_w,                            FALSE,  FALSE,
+    EL_NUT,                            ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Yballoon_wB,                       FALSE,  TRUE,
-    EL_BALLOON,                                ACTION_MOVING, MV_BIT_LEFT
+    Ynut_wB,                           FALSE,  TRUE,
+    EL_NUT,                            ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Xgrass,                            TRUE,   FALSE,
-    EL_EMC_GRASS,                      -1, -1
+    Ynut_stone,                                FALSE,  FALSE,
+    EL_NUT,                            ACTION_BREAKING, -1
   },
+
   {
-    Ygrass_nB,                         FALSE,  FALSE,
-    EL_EMC_GRASS,                      ACTION_DIGGING, MV_BIT_UP
+    Xspring,                           TRUE,   FALSE,
+    EL_SPRING,                         -1, -1
   },
   {
-    Ygrass_eB,                         FALSE,  FALSE,
-    EL_EMC_GRASS,                      ACTION_DIGGING, MV_BIT_RIGHT
+    Xspring_pause,                     FALSE,  FALSE,
+    EL_SPRING,                         -1, -1
   },
   {
-    Ygrass_sB,                         FALSE,  FALSE,
-    EL_EMC_GRASS,                      ACTION_DIGGING, MV_BIT_DOWN
+    Xspring_e,                         TRUE,   FALSE,
+    EL_SPRING_RIGHT,                   -1, -1
   },
   {
-    Ygrass_wB,                         FALSE,  FALSE,
-    EL_EMC_GRASS,                      ACTION_DIGGING, MV_BIT_LEFT
+    Xspring_w,                         TRUE,   FALSE,
+    EL_SPRING_LEFT,                    -1, -1
   },
   {
-    Xdirt,                             TRUE,   FALSE,
-    EL_SAND,                           -1, -1
+    Xspring_fall,                      FALSE,  FALSE,
+    EL_SPRING,                         -1, -1
   },
   {
-    Ydirt_nB,                          FALSE,  FALSE,
-    EL_SAND,                           ACTION_DIGGING, MV_BIT_UP
+    Yspring_s,                         FALSE,  FALSE,
+    EL_SPRING,                         ACTION_FALLING, -1
   },
   {
-    Ydirt_eB,                          FALSE,  FALSE,
-    EL_SAND,                           ACTION_DIGGING, MV_BIT_RIGHT
+    Yspring_sB,                                FALSE,  TRUE,
+    EL_SPRING,                         ACTION_FALLING, -1
   },
   {
-    Ydirt_sB,                          FALSE,  FALSE,
-    EL_SAND,                           ACTION_DIGGING, MV_BIT_DOWN
+    Yspring_e,                         FALSE,  FALSE,
+    EL_SPRING,                         ACTION_MOVING, MV_BIT_RIGHT
   },
   {
-    Ydirt_wB,                          FALSE,  FALSE,
-    EL_SAND,                           ACTION_DIGGING, MV_BIT_LEFT
+    Yspring_eB,                                FALSE,  TRUE,
+    EL_SPRING,                         ACTION_MOVING, MV_BIT_RIGHT
   },
   {
-    Xacid_ne,                          TRUE,   FALSE,
-    EL_ACID_POOL_TOPRIGHT,             -1, -1
+    Yspring_w,                         FALSE,  FALSE,
+    EL_SPRING,                         ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Xacid_se,                          TRUE,   FALSE,
-    EL_ACID_POOL_BOTTOMRIGHT,          -1, -1
+    Yspring_wB,                                FALSE,  TRUE,
+    EL_SPRING,                         ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Xacid_s,                           TRUE,   FALSE,
-    EL_ACID_POOL_BOTTOM,               -1, -1
+    Yspring_alien_e,                   FALSE,  FALSE,
+    EL_SPRING,                         ACTION_EATING, MV_BIT_RIGHT
   },
   {
-    Xacid_sw,                          TRUE,   FALSE,
-    EL_ACID_POOL_BOTTOMLEFT,           -1, -1
+    Yspring_alien_eB,                  FALSE,  TRUE,
+    EL_SPRING,                         ACTION_EATING, MV_BIT_RIGHT
   },
   {
-    Xacid_nw,                          TRUE,   FALSE,
-    EL_ACID_POOL_TOPLEFT,              -1, -1
+    Yspring_alien_w,                   FALSE,  FALSE,
+    EL_SPRING,                         ACTION_EATING, MV_BIT_LEFT
   },
   {
-    Xacid_1,                           TRUE,   FALSE,
-    EL_ACID,                           -1, -1
+    Yspring_alien_wB,                  FALSE,  TRUE,
+    EL_SPRING,                         ACTION_EATING, MV_BIT_LEFT
   },
+
   {
-    Xacid_2,                           FALSE,  FALSE,
-    EL_ACID,                           -1, -1
+    Xpush_emerald_e,                   FALSE,  FALSE,
+    EL_EMERALD,                                -1, MV_BIT_RIGHT
   },
   {
-    Xacid_3,                           FALSE,  FALSE,
-    EL_ACID,                           -1, -1
+    Xpush_emerald_w,                   FALSE,  FALSE,
+    EL_EMERALD,                                -1, MV_BIT_LEFT
   },
   {
-    Xacid_4,                           FALSE,  FALSE,
-    EL_ACID,                           -1, -1
+    Xpush_diamond_e,                   FALSE,  FALSE,
+    EL_DIAMOND,                                -1, MV_BIT_RIGHT
   },
   {
-    Xacid_5,                           FALSE,  FALSE,
-    EL_ACID,                           -1, -1
+    Xpush_diamond_w,                   FALSE,  FALSE,
+    EL_DIAMOND,                                -1, MV_BIT_LEFT
   },
   {
-    Xacid_6,                           FALSE,  FALSE,
-    EL_ACID,                           -1, -1
+    Xpush_stone_e,                     FALSE,  FALSE,
+    EL_ROCK,                           -1, MV_BIT_RIGHT
   },
   {
-    Xacid_7,                           FALSE,  FALSE,
-    EL_ACID,                           -1, -1
+    Xpush_stone_w,                     FALSE,  FALSE,
+    EL_ROCK,                           -1, MV_BIT_LEFT
   },
   {
-    Xacid_8,                           FALSE,  FALSE,
-    EL_ACID,                           -1, -1
+    Xpush_bomb_e,                      FALSE,  FALSE,
+    EL_BOMB,                           -1, MV_BIT_RIGHT
   },
   {
-    Xball_1,                           TRUE,   FALSE,
-    EL_EMC_MAGIC_BALL,                 -1, -1
+    Xpush_bomb_w,                      FALSE,  FALSE,
+    EL_BOMB,                           -1, MV_BIT_LEFT
   },
   {
-    Xball_1B,                          FALSE,  FALSE,
-    EL_EMC_MAGIC_BALL,                 ACTION_ACTIVE, -1
+    Xpush_nut_e,                       FALSE,  FALSE,
+    EL_NUT,                            -1, MV_BIT_RIGHT
   },
   {
-    Xball_2,                           FALSE,  FALSE,
-    EL_EMC_MAGIC_BALL,                 ACTION_ACTIVE, -1
+    Xpush_nut_w,                       FALSE,  FALSE,
+    EL_NUT,                            -1, MV_BIT_LEFT
   },
   {
-    Xball_2B,                          FALSE,  FALSE,
-    EL_EMC_MAGIC_BALL,                 ACTION_ACTIVE, -1
+    Xpush_spring_e,                    FALSE,  FALSE,
+    EL_SPRING_RIGHT,                   -1, MV_BIT_RIGHT
   },
   {
-    Yball_eat,                         FALSE,  FALSE,
-    EL_EMC_MAGIC_BALL,                 ACTION_DROPPING, -1
+    Xpush_spring_w,                    FALSE,  FALSE,
+    EL_SPRING_LEFT,                    -1, MV_BIT_LEFT
   },
+
   {
-    Ykey_1_eat,                                FALSE,  FALSE,
-    EL_EM_KEY_1,                       ACTION_COLLECTING, -1
+    Xdynamite,                         TRUE,   FALSE,
+    EL_EM_DYNAMITE,                    -1, -1
+  },
+  {
+    Ydynamite_blank,                   FALSE,  FALSE,
+    EL_EM_DYNAMITE,                    ACTION_COLLECTING, -1
+  },
+  {
+    Xdynamite_1,                       TRUE,   FALSE,
+    EL_EM_DYNAMITE_ACTIVE,             -1, -1
+  },
+  {
+    Xdynamite_2,                       FALSE,  FALSE,
+    EL_EM_DYNAMITE_ACTIVE,             -1, -1
+  },
+  {
+    Xdynamite_3,                       FALSE,  FALSE,
+    EL_EM_DYNAMITE_ACTIVE,             -1, -1
+  },
+  {
+    Xdynamite_4,                       FALSE,  FALSE,
+    EL_EM_DYNAMITE_ACTIVE,             -1, -1
+  },
+
+  {
+    Xkey_1,                            TRUE,   FALSE,
+    EL_EM_KEY_1,                       -1, -1
+  },
+  {
+    Xkey_2,                            TRUE,   FALSE,
+    EL_EM_KEY_2,                       -1, -1
+  },
+  {
+    Xkey_3,                            TRUE,   FALSE,
+    EL_EM_KEY_3,                       -1, -1
+  },
+  {
+    Xkey_4,                            TRUE,   FALSE,
+    EL_EM_KEY_4,                       -1, -1
+  },
+  {
+    Xkey_5,                            TRUE,   FALSE,
+    EL_EMC_KEY_5,                      -1, -1
+  },
+  {
+    Xkey_6,                            TRUE,   FALSE,
+    EL_EMC_KEY_6,                      -1, -1
+  },
+  {
+    Xkey_7,                            TRUE,   FALSE,
+    EL_EMC_KEY_7,                      -1, -1
+  },
+  {
+    Xkey_8,                            TRUE,   FALSE,
+    EL_EMC_KEY_8,                      -1, -1
+  },
+
+  {
+    Xdoor_1,                           TRUE,   FALSE,
+    EL_EM_GATE_1,                      -1, -1
+  },
+  {
+    Xdoor_2,                           TRUE,   FALSE,
+    EL_EM_GATE_2,                      -1, -1
+  },
+  {
+    Xdoor_3,                           TRUE,   FALSE,
+    EL_EM_GATE_3,                      -1, -1
+  },
+  {
+    Xdoor_4,                           TRUE,   FALSE,
+    EL_EM_GATE_4,                      -1, -1
+  },
+  {
+    Xdoor_5,                           TRUE,   FALSE,
+    EL_EMC_GATE_5,                     -1, -1
+  },
+  {
+    Xdoor_6,                           TRUE,   FALSE,
+    EL_EMC_GATE_6,                     -1, -1
+  },
+  {
+    Xdoor_7,                           TRUE,   FALSE,
+    EL_EMC_GATE_7,                     -1, -1
+  },
+  {
+    Xdoor_8,                           TRUE,   FALSE,
+    EL_EMC_GATE_8,                     -1, -1
+  },
+
+  {
+    Xfake_door_1,                      TRUE,   FALSE,
+    EL_EM_GATE_1_GRAY,                 -1, -1
+  },
+  {
+    Xfake_door_2,                      TRUE,   FALSE,
+    EL_EM_GATE_2_GRAY,                 -1, -1
+  },
+  {
+    Xfake_door_3,                      TRUE,   FALSE,
+    EL_EM_GATE_3_GRAY,                 -1, -1
+  },
+  {
+    Xfake_door_4,                      TRUE,   FALSE,
+    EL_EM_GATE_4_GRAY,                 -1, -1
+  },
+  {
+    Xfake_door_5,                      TRUE,   FALSE,
+    EL_EMC_GATE_5_GRAY,                        -1, -1
   },
   {
-    Ykey_2_eat,                                FALSE,  FALSE,
-    EL_EM_KEY_2,                       ACTION_COLLECTING, -1
+    Xfake_door_6,                      TRUE,   FALSE,
+    EL_EMC_GATE_6_GRAY,                        -1, -1
   },
   {
-    Ykey_3_eat,                                FALSE,  FALSE,
-    EL_EM_KEY_3,                       ACTION_COLLECTING, -1
+    Xfake_door_7,                      TRUE,   FALSE,
+    EL_EMC_GATE_7_GRAY,                        -1, -1
   },
   {
-    Ykey_4_eat,                                FALSE,  FALSE,
-    EL_EM_KEY_4,                       ACTION_COLLECTING, -1
+    Xfake_door_8,                      TRUE,   FALSE,
+    EL_EMC_GATE_8_GRAY,                        -1, -1
   },
+
   {
-    Ykey_5_eat,                                FALSE,  FALSE,
-    EL_EMC_KEY_5,                      ACTION_COLLECTING, -1
+    Xballoon,                          TRUE,   FALSE,
+    EL_BALLOON,                                -1, -1
   },
   {
-    Ykey_6_eat,                                FALSE,  FALSE,
-    EL_EMC_KEY_6,                      ACTION_COLLECTING, -1
+    Yballoon_n,                                FALSE,  FALSE,
+    EL_BALLOON,                                ACTION_MOVING, MV_BIT_UP
   },
   {
-    Ykey_7_eat,                                FALSE,  FALSE,
-    EL_EMC_KEY_7,                      ACTION_COLLECTING, -1
+    Yballoon_nB,                       FALSE,  TRUE,
+    EL_BALLOON,                                ACTION_MOVING, MV_BIT_UP
   },
   {
-    Ykey_8_eat,                                FALSE,  FALSE,
-    EL_EMC_KEY_8,                      ACTION_COLLECTING, -1
+    Yballoon_e,                                FALSE,  FALSE,
+    EL_BALLOON,                                ACTION_MOVING, MV_BIT_RIGHT
   },
   {
-    Ylenses_eat,                       FALSE,  FALSE,
-    EL_EMC_LENSES,                     ACTION_COLLECTING, -1
+    Yballoon_eB,                       FALSE,  TRUE,
+    EL_BALLOON,                                ACTION_MOVING, MV_BIT_RIGHT
   },
   {
-    Ymagnify_eat,                      FALSE,  FALSE,
-    EL_EMC_MAGNIFIER,                  ACTION_COLLECTING, -1
+    Yballoon_s,                                FALSE,  FALSE,
+    EL_BALLOON,                                ACTION_MOVING, MV_BIT_DOWN
   },
   {
-    Ygrass_eat,                                FALSE,  FALSE,
-    EL_EMC_GRASS,                      ACTION_SNAPPING, -1
+    Yballoon_sB,                       FALSE,  TRUE,
+    EL_BALLOON,                                ACTION_MOVING, MV_BIT_DOWN
   },
   {
-    Ydirt_eat,                         FALSE,  FALSE,
-    EL_SAND,                           ACTION_SNAPPING, -1
+    Yballoon_w,                                FALSE,  FALSE,
+    EL_BALLOON,                                ACTION_MOVING, MV_BIT_LEFT
   },
   {
-    Xgrow_ns,                          TRUE,   FALSE,
-    EL_EXPANDABLE_WALL_VERTICAL,       -1, -1
+    Yballoon_wB,                       FALSE,  TRUE,
+    EL_BALLOON,                                ACTION_MOVING, MV_BIT_LEFT
   },
+
   {
-    Ygrow_ns_eat,                      FALSE,  FALSE,
-    EL_EXPANDABLE_WALL_VERTICAL,       ACTION_GROWING, -1
+    Xball_1,                           TRUE,   FALSE,
+    EL_EMC_MAGIC_BALL,                 -1, -1
   },
   {
-    Xgrow_ew,                          TRUE,   FALSE,
-    EL_EXPANDABLE_WALL_HORIZONTAL,     -1, -1
+    Yball_1,                           FALSE,  FALSE,
+    EL_EMC_MAGIC_BALL,                 ACTION_ACTIVE, -1
   },
   {
-    Ygrow_ew_eat,                      FALSE,  FALSE,
-    EL_EXPANDABLE_WALL_HORIZONTAL,     ACTION_GROWING, -1
+    Xball_2,                           FALSE,  FALSE,
+    EL_EMC_MAGIC_BALL,                 ACTION_ACTIVE, -1
   },
   {
-    Xwonderwall,                       TRUE,   FALSE,
-    EL_MAGIC_WALL,                     -1, -1
+    Yball_2,                           FALSE,  FALSE,
+    EL_EMC_MAGIC_BALL,                 ACTION_ACTIVE, -1
   },
   {
-    XwonderwallB,                      FALSE,  FALSE,
-    EL_MAGIC_WALL,                     ACTION_ACTIVE, -1
+    Yball_blank,                       FALSE,  FALSE,
+    EL_EMC_MAGIC_BALL,                 ACTION_DROPPING, -1
   },
+
   {
     Xamoeba_1,                         TRUE,   FALSE,
     EL_AMOEBA_DRY,                     ACTION_OTHER, -1
@@ -6723,158 +6940,134 @@ em_object_mapping_list[] =
     Xamoeba_8,                         FALSE,  FALSE,
     EL_AMOEBA_WET,                     ACTION_OTHER, -1
   },
+
   {
-    Xdoor_1,                           TRUE,   FALSE,
-    EL_EM_GATE_1,                      -1, -1
-  },
-  {
-    Xdoor_2,                           TRUE,   FALSE,
-    EL_EM_GATE_2,                      -1, -1
-  },
-  {
-    Xdoor_3,                           TRUE,   FALSE,
-    EL_EM_GATE_3,                      -1, -1
-  },
-  {
-    Xdoor_4,                           TRUE,   FALSE,
-    EL_EM_GATE_4,                      -1, -1
-  },
-  {
-    Xdoor_5,                           TRUE,   FALSE,
-    EL_EMC_GATE_5,                     -1, -1
-  },
-  {
-    Xdoor_6,                           TRUE,   FALSE,
-    EL_EMC_GATE_6,                     -1, -1
-  },
-  {
-    Xdoor_7,                           TRUE,   FALSE,
-    EL_EMC_GATE_7,                     -1, -1
-  },
-  {
-    Xdoor_8,                           TRUE,   FALSE,
-    EL_EMC_GATE_8,                     -1, -1
-  },
-  {
-    Xkey_1,                            TRUE,   FALSE,
-    EL_EM_KEY_1,                       -1, -1
-  },
-  {
-    Xkey_2,                            TRUE,   FALSE,
-    EL_EM_KEY_2,                       -1, -1
+    Xdrip,                             TRUE,   FALSE,
+    EL_AMOEBA_DROP,                    ACTION_GROWING, -1
   },
   {
-    Xkey_3,                            TRUE,   FALSE,
-    EL_EM_KEY_3,                       -1, -1
+    Xdrip_fall,                                FALSE,  FALSE,
+    EL_AMOEBA_DROP,                    -1, -1
   },
   {
-    Xkey_4,                            TRUE,   FALSE,
-    EL_EM_KEY_4,                       -1, -1
+    Xdrip_stretch,                     FALSE,  FALSE,
+    EL_AMOEBA_DROP,                    ACTION_FALLING, -1
   },
   {
-    Xkey_5,                            TRUE,   FALSE,
-    EL_EMC_KEY_5,                      -1, -1
+    Xdrip_stretchB,                    FALSE,  TRUE,
+    EL_AMOEBA_DROP,                    ACTION_FALLING, -1
   },
   {
-    Xkey_6,                            TRUE,   FALSE,
-    EL_EMC_KEY_6,                      -1, -1
+    Ydrip_1_s,                         FALSE,  FALSE,
+    EL_AMOEBA_DROP,                    ACTION_FALLING, -1
   },
   {
-    Xkey_7,                            TRUE,   FALSE,
-    EL_EMC_KEY_7,                      -1, -1
+    Ydrip_1_sB,                                FALSE,  TRUE,
+    EL_AMOEBA_DROP,                    ACTION_FALLING, -1
   },
   {
-    Xkey_8,                            TRUE,   FALSE,
-    EL_EMC_KEY_8,                      -1, -1
+    Ydrip_2_s,                         FALSE,  FALSE,
+    EL_AMOEBA_DROP,                    ACTION_FALLING, -1
   },
   {
-    Xwind_n,                           TRUE,   FALSE,
-    EL_BALLOON_SWITCH_UP,              -1, -1
+    Ydrip_2_sB,                                FALSE,  TRUE,
+    EL_AMOEBA_DROP,                    ACTION_FALLING, -1
   },
+
   {
-    Xwind_e,                           TRUE,   FALSE,
-    EL_BALLOON_SWITCH_RIGHT,           -1, -1
+    Xwonderwall,                       TRUE,   FALSE,
+    EL_MAGIC_WALL,                     -1, -1
   },
   {
-    Xwind_s,                           TRUE,   FALSE,
-    EL_BALLOON_SWITCH_DOWN,            -1, -1
+    Ywonderwall,                       FALSE,  FALSE,
+    EL_MAGIC_WALL,                     ACTION_ACTIVE, -1
   },
+
   {
-    Xwind_w,                           TRUE,   FALSE,
-    EL_BALLOON_SWITCH_LEFT,            -1, -1
+    Xwheel,                            TRUE,   FALSE,
+    EL_ROBOT_WHEEL,                    -1, -1
   },
   {
-    Xwind_nesw,                                TRUE,   FALSE,
-    EL_BALLOON_SWITCH_ANY,             -1, -1
+    Ywheel,                            FALSE,  FALSE,
+    EL_ROBOT_WHEEL,                    ACTION_ACTIVE, -1
   },
+
   {
-    Xwind_stop,                                TRUE,   FALSE,
-    EL_BALLOON_SWITCH_NONE,            -1, -1
+    Xswitch,                           TRUE,   FALSE,
+    EL_EMC_MAGIC_BALL_SWITCH,          -1, -1
   },
   {
-    Xexit,                             TRUE,   FALSE,
-    EL_EM_EXIT_CLOSED,                 -1, -1
+    Yswitch,                           FALSE,  FALSE,
+    EL_EMC_MAGIC_BALL_SWITCH,          ACTION_ACTIVE, -1
   },
+
   {
-    Xexit_1,                           TRUE,   FALSE,
-    EL_EM_EXIT_OPEN,                   -1, -1
+    Xbumper,                           TRUE,   FALSE,
+    EL_EMC_SPRING_BUMPER,              -1, -1
   },
   {
-    Xexit_2,                           FALSE,  FALSE,
-    EL_EM_EXIT_OPEN,                   -1, -1
+    Ybumper,                           FALSE,  FALSE,
+    EL_EMC_SPRING_BUMPER,              ACTION_ACTIVE, -1
   },
+
   {
-    Xexit_3,                           FALSE,  FALSE,
-    EL_EM_EXIT_OPEN,                   -1, -1
+    Xacid_nw,                          TRUE,   FALSE,
+    EL_ACID_POOL_TOPLEFT,              -1, -1
   },
   {
-    Xdynamite,                         TRUE,   FALSE,
-    EL_EM_DYNAMITE,                    -1, -1
+    Xacid_ne,                          TRUE,   FALSE,
+    EL_ACID_POOL_TOPRIGHT,             -1, -1
   },
   {
-    Ydynamite_eat,                     FALSE,  FALSE,
-    EL_EM_DYNAMITE,                    ACTION_COLLECTING, -1
+    Xacid_sw,                          TRUE,   FALSE,
+    EL_ACID_POOL_BOTTOMLEFT,           -1, -1
   },
   {
-    Xdynamite_1,                       TRUE,   FALSE,
-    EL_EM_DYNAMITE_ACTIVE,             -1, -1
+    Xacid_s,                           TRUE,   FALSE,
+    EL_ACID_POOL_BOTTOM,               -1, -1
   },
   {
-    Xdynamite_2,                       FALSE,  FALSE,
-    EL_EM_DYNAMITE_ACTIVE,             -1, -1
+    Xacid_se,                          TRUE,   FALSE,
+    EL_ACID_POOL_BOTTOMRIGHT,          -1, -1
   },
+
   {
-    Xdynamite_3,                       FALSE,  FALSE,
-    EL_EM_DYNAMITE_ACTIVE,             -1, -1
+    Xfake_blank,                       TRUE,   FALSE,
+    EL_INVISIBLE_WALL,                 -1, -1
   },
   {
-    Xdynamite_4,                       FALSE,  FALSE,
-    EL_EM_DYNAMITE_ACTIVE,             -1, -1
+    Yfake_blank,                       FALSE,  FALSE,
+    EL_INVISIBLE_WALL,                 ACTION_ACTIVE, -1
   },
+
   {
-    Xbumper,                           TRUE,   FALSE,
-    EL_EMC_SPRING_BUMPER,              -1, -1
+    Xfake_grass,                       TRUE,   FALSE,
+    EL_EMC_FAKE_GRASS,                 -1, -1
   },
   {
-    XbumperB,                          FALSE,  FALSE,
-    EL_EMC_SPRING_BUMPER,              ACTION_ACTIVE, -1
+    Yfake_grass,                       FALSE,  FALSE,
+    EL_EMC_FAKE_GRASS,                 ACTION_ACTIVE, -1
   },
+
   {
-    Xwheel,                            TRUE,   FALSE,
-    EL_ROBOT_WHEEL,                    -1, -1
+    Xfake_amoeba,                      TRUE,   FALSE,
+    EL_EMC_DRIPPER,                    -1, -1
   },
   {
-    XwheelB,                           FALSE,  FALSE,
-    EL_ROBOT_WHEEL,                    ACTION_ACTIVE, -1
+    Yfake_amoeba,                      FALSE,  FALSE,
+    EL_EMC_DRIPPER,                    ACTION_ACTIVE, -1
   },
+
   {
-    Xswitch,                           TRUE,   FALSE,
-    EL_EMC_MAGIC_BALL_SWITCH,          -1, -1
+    Xlenses,                           TRUE,   FALSE,
+    EL_EMC_LENSES,                     -1, -1
   },
+
   {
-    XswitchB,                          FALSE,  FALSE,
-    EL_EMC_MAGIC_BALL_SWITCH,          ACTION_ACTIVE, -1
+    Xmagnify,                          TRUE,   FALSE,
+    EL_EMC_MAGNIFIER,                  -1, -1
   },
+
   {
     Xsand,                             TRUE,   FALSE,
     EL_QUICKSAND_EMPTY,                        -1, -1
@@ -6899,38 +7092,6 @@ em_object_mapping_list[] =
     Xsand_stonein_4,                   FALSE,  TRUE,
     EL_ROCK,                           ACTION_FILLING, -1
   },
-  {
-    Xsand_stonesand_1,                 FALSE,  FALSE,
-    EL_QUICKSAND_EMPTYING,             -1, -1
-  },
-  {
-    Xsand_stonesand_2,                 FALSE,  FALSE,
-    EL_QUICKSAND_EMPTYING,             -1, -1
-  },
-  {
-    Xsand_stonesand_3,                 FALSE,  FALSE,
-    EL_QUICKSAND_EMPTYING,             -1, -1
-  },
-  {
-    Xsand_stonesand_4,                 FALSE,  FALSE,
-    EL_QUICKSAND_EMPTYING,             -1, -1
-  },
-  {
-    Xsand_stonesand_quickout_1,                FALSE,  FALSE,
-    EL_QUICKSAND_EMPTYING,             -1, -1
-  },
-  {
-    Xsand_stonesand_quickout_2,                FALSE,  FALSE,
-    EL_QUICKSAND_EMPTYING,             -1, -1
-  },
-  {
-    Xsand_stoneout_1,                  FALSE,  FALSE,
-    EL_ROCK,                           ACTION_EMPTYING, -1
-  },
-  {
-    Xsand_stoneout_2,                  FALSE,  FALSE,
-    EL_ROCK,                           ACTION_EMPTYING, -1
-  },
   {
     Xsand_sandstone_1,                 FALSE,  FALSE,
     EL_QUICKSAND_FILLING,              -1, -1
@@ -6945,128 +7106,105 @@ em_object_mapping_list[] =
   },
   {
     Xsand_sandstone_4,                 FALSE,  FALSE,
-    EL_QUICKSAND_FILLING,              -1, -1
-  },
-  {
-    Xplant,                            TRUE,   FALSE,
-    EL_EMC_PLANT,                      -1, -1
-  },
-  {
-    Yplant,                            FALSE,  FALSE,
-    EL_EMC_PLANT,                      -1, -1
-  },
-  {
-    Xlenses,                           TRUE,   FALSE,
-    EL_EMC_LENSES,                     -1, -1
-  },
-  {
-    Xmagnify,                          TRUE,   FALSE,
-    EL_EMC_MAGNIFIER,                  -1, -1
-  },
-  {
-    Xdripper,                          TRUE,   FALSE,
-    EL_EMC_DRIPPER,                    -1, -1
-  },
-  {
-    XdripperB,                         FALSE,  FALSE,
-    EL_EMC_DRIPPER,                    ACTION_ACTIVE, -1
-  },
-  {
-    Xfake_blank,                       TRUE,   FALSE,
-    EL_INVISIBLE_WALL,                 -1, -1
+    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
@@ -7083,22 +7221,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
@@ -7147,6 +7304,7 @@ em_object_mapping_list[] =
     Xdecor_12,                         TRUE,   FALSE,
     EL_EMC_WALL_12,                    -1, -1
   },
+
   {
     Xalpha_0,                          TRUE,   FALSE,
     EL_CHAR('0'),                      -1, -1
@@ -7192,8 +7350,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,
@@ -7333,40 +7491,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
   },
 
   {
@@ -7384,214 +7554,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,
   },
 
@@ -7601,7 +7771,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;
@@ -7610,7 +7780,7 @@ int map_element_RND_to_EM(int element_rnd)
   {
     int i;
 
-    /* return "Xalpha_quest" for all undefined elements in mapping array */
+    // return "Xalpha_quest" for all undefined elements in mapping array
     for (i = 0; i < NUM_FILE_ELEMENTS; i++)
       mapping_RND_to_EM[i] = Xalpha_quest;
 
@@ -7622,25 +7792,57 @@ 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)
   {
     int i;
 
-    /* return "EL_UNKNOWN" for all undefined elements in mapping array */
-    for (i = 0; i < TILE_MAX; 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++)
@@ -7650,52 +7852,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)
@@ -7738,7 +7943,7 @@ int map_direction_EM_to_RND(int direction)
 
 int map_element_RND_to_SP(int element_rnd)
 {
-  int element_sp = 0x20;       /* map unknown elements to yellow "hardware" */
+  int element_sp = 0x20;       // map unknown elements to yellow "hardware"
 
   if (element_rnd >= EL_SP_START &&
       element_rnd <= EL_SP_END)
@@ -7838,7 +8043,7 @@ int map_element_MM_to_RND(int element_mm)
 
 int map_action_MM_to_RND(int action_mm)
 {
-  /* all MM actions are defined to exactly match their RND counterparts */
+  // all MM actions are defined to exactly match their RND counterparts
   return action_mm;
 }
 
@@ -7929,18 +8134,18 @@ int el2img_mm(int element_mm)
 int el_act_dir2img(int element, int action, int direction)
 {
   element = GFX_ELEMENT(element);
-  direction = MV_DIR_TO_BIT(direction);        /* default: MV_NONE => MV_DOWN */
+  direction = MV_DIR_TO_BIT(direction);        // default: MV_NONE => MV_DOWN
 
-  /* direction_graphic[][] == graphic[] for undefined direction graphics */
+  // direction_graphic[][] == graphic[] for undefined direction graphics
   return element_info[element].direction_graphic[action][direction];
 }
 
 static int el_act_dir2crm(int element, int action, int direction)
 {
   element = GFX_ELEMENT(element);
-  direction = MV_DIR_TO_BIT(direction);        /* default: MV_NONE => MV_DOWN */
+  direction = MV_DIR_TO_BIT(direction);        // default: MV_NONE => MV_DOWN
 
-  /* direction_graphic[][] == graphic[] for undefined direction graphics */
+  // direction_graphic[][] == graphic[] for undefined direction graphics
   return element_info[element].direction_crumbled[action][direction];
 }
 
@@ -8124,24 +8329,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)
@@ -8156,8 +8356,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)
 {
@@ -8172,23 +8372,23 @@ 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:
        return element;
     }
   }
-  else /* frame_em == 7 */
+  else // frame_em == 7
   {
     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:
@@ -8196,24 +8396,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:
@@ -8253,9 +8453,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;
   }
 
@@ -8266,9 +8466,9 @@ static void set_crumbled_graphics_EM(struct GraphicInfo_EM *g_em,
                                     boolean has_crumbled_graphics,
                                     int crumbled, int sync_frame)
 {
-  /* if element can be crumbled, but certain action graphics are just empty
-     space (like instantly snapping sand to empty space in 1 frame), do not
-     treat these empty space graphics as crumbled graphics in EMC engine */
+  // if element can be crumbled, but certain action graphics are just empty
+  // space (like instantly snapping sand to empty space in 1 frame), do not
+  // treat these empty space graphics as crumbled graphics in EMC engine
   if (crumbled == IMG_EMPTY_SPACE)
     has_crumbled_graphics = FALSE;
 
@@ -8332,12 +8532,12 @@ void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
                             action == ACTION_FILLING ||
                             action == ACTION_EMPTYING);
 
-  /* special case: graphic uses "2nd movement tile" and has defined
-     7 frames for movement animation (or less) => use default graphic
-     for last (8th) frame which ends the movement animation */
+  // special case: graphic uses "2nd movement tile" and has defined
+  // 7 frames for movement animation (or less) => use default graphic
+  // for last (8th) frame which ends the movement animation
   if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
   {
-    action = ACTION_DEFAULT;   /* (keep action_* unchanged for now) */
+    action = ACTION_DEFAULT;   // (keep action_* unchanged for now)
     graphic = (direction == MV_NONE ?
               el_act2img(effective_element, action) :
               el_act_dir2img(effective_element, action, direction));
@@ -8361,7 +8561,7 @@ void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
       GfxFrame[x][y]++;
 
 #if 1
-      /* !!! TEST !!! NEW !!! DOES NOT WORK RIGHT YET !!! */
+      // !!! TEST !!! NEW !!! DOES NOT WORK RIGHT YET !!!
       if (g->double_movement && frame_em == 0)
        GfxFrame[x][y] = 0;
 #endif
@@ -8380,7 +8580,7 @@ void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
   {
     GfxFrame[x][y]++;
 
-    /* special case: animation for Xsand_stonesand_quickout_1/2 twice as fast */
+    // special case: animation for Xsand_stonesand_quickout_1/2 twice as fast
     if (tile == Xsand_stonesand_quickout_1 ||
        tile == Xsand_stonesand_quickout_2)
       GfxFrame[x][y]++;
@@ -8391,7 +8591,7 @@ void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
   else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
     sync_frame = GfxFrame[x][y];
   else
-    sync_frame = 0;    /* playfield border (pseudo steel) */
+    sync_frame = 0;    // playfield border (pseudo steel)
 
   SetRandomAnimationValue(x, y);
 
@@ -8427,9 +8627,9 @@ void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *g_em,
   struct GraphicInfo *g = &graphic_info[graphic];
   int sync_frame;
 
-  /* special case: graphic uses "2nd movement tile" and has defined
-     7 frames for movement animation (or less) => use default graphic
-     for last (8th) frame which ends the movement animation */
+  // special case: graphic uses "2nd movement tile" and has defined
+  // 7 frames for movement animation (or less) => use default graphic
+  // for last (8th) frame which ends the movement animation
   if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
   {
     effective_action = ACTION_DEFAULT;
@@ -8450,7 +8650,7 @@ void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *g_em,
   else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
     sync_frame = GfxFrame[x][y];
   else
-    sync_frame = 0;    /* playfield border (pseudo steel) */
+    sync_frame = 0;    // playfield border (pseudo steel)
 
   SetRandomAnimationValue(x, y);
 
@@ -8463,8 +8663,8 @@ void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *g_em,
   getGraphicSourceExt(graphic, frame, &g_em->bitmap, &g_em->src_x, &g_em->src_y,
                      g->double_movement && is_backside);
 
-  /* (updating the "crumbled" graphic definitions is probably not really needed,
-     as animations for crumbled graphics can't be longer than one EMC cycle) */
+  // (updating the "crumbled" graphic definitions is probably not really needed,
+  // as animations for crumbled graphics can't be longer than one EMC cycle)
   set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
                           sync_frame);
 }
@@ -8501,21 +8701,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++)
+  // always start with reliable default values
+  for (i = 0; i < GAME_TILE_MAX; i++)
   {
     object_mapping[i].element_rnd = EL_UNKNOWN;
     object_mapping[i].is_backside = FALSE;
@@ -8523,10 +8710,10 @@ void InitGraphicInfo_EM(void)
     object_mapping[i].direction = MV_NONE;
   }
 
-  /* always start with reliable default values */
+  // 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;
@@ -8564,7 +8751,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;
@@ -8583,24 +8770,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 :
@@ -8621,18 +8808,18 @@ 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 */
+      // ensure to get symmetric 3-frame, 2-delay animations as used in EM
       boolean special_animation = (action != ACTION_DEFAULT &&
                                   g->anim_frames == 3 &&
                                   g->anim_delay == 2 &&
                                   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 :
@@ -8649,21 +8836,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 :
@@ -8705,13 +8900,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 :
@@ -8731,13 +8926,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,
@@ -8775,10 +8963,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 :
@@ -8787,15 +8975,15 @@ 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 :
                          i == Xsand_stoneout_2 ? j + 8 : j) + 1;
        int step = (is_backside ? step_frame : num_steps - step_frame);
 
-       if (is_backside)        /* tile where movement starts */
+       if (is_backside)        // tile where movement starts
        {
          if (dx < 0 || dy < 0)
          {
@@ -8808,7 +8996,7 @@ void InitGraphicInfo_EM(void)
            g_em->dst_offset_y = cy * step;
          }
        }
-       else                    /* tile where movement ends */
+       else                    // tile where movement ends
        {
          if (dx < 0 || dy < 0)
          {
@@ -8826,85 +9014,17 @@ void InitGraphicInfo_EM(void)
        g_em->height = TILEY - cy * step;
       }
 
-      /* create unique graphic identifier to decide if tile must be redrawn */
+      // create unique graphic identifier to decide if tile must be redrawn
       /* bit 31 - 16 (16 bit): EM style graphic
         bit 15 - 12 ( 4 bit): EM style frame
         bit 11 -  6 ( 6 bit): graphic width
         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++)
     {
@@ -8926,9 +9046,9 @@ void InitGraphicInfo_EM(void)
                 direction == MV_RIGHT ? (is_backside? Yspring_eB: Yspring_e) :
                 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];
+       // no separate animation for "smashed by rock" -- use rock instead
+       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;
@@ -8949,7 +9069,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;
@@ -8964,17 +9084,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,
@@ -8992,64 +9105,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,
@@ -9057,7 +9115,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)
     {
@@ -9109,17 +9167,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,
@@ -9283,66 +9343,77 @@ 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 defined(TARGET_SDL2)
-  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;
-  }
-#endif
 
-  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;
 
-    /* toggle fullscreen */
+    // when creating new renderer, destroy textures linked to old renderer
+    FreeAllImageTextures();    // needs old renderer to free the textures
+
+    // re-create screen and renderer (including change of vsync mode)
     ChangeVideoModeIfNeeded(setup.fullscreen);
 
-    /* set setup value according to successfully changed fullscreen mode */
+    // set setup value according to successfully changed fullscreen mode
     setup.fullscreen = video.fullscreen_enabled;
 
-    /* restore backbuffer content from temporary backbuffer backup bitmap */
+    // 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 */
+    // 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,
@@ -9362,6 +9433,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;
 
@@ -9371,7 +9444,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;
 }
 
@@ -9414,29 +9491,58 @@ void SetLevelSetInfo(char *identifier, int level_nr)
   levelset.level_nr = level_nr;
 }
 
-boolean CheckIfPlayfieldViewportHasChanged(void)
+boolean CheckIfAllViewportsHaveChanged(void)
 {
-  // if game status has not changed, playfield viewport has not changed either
+  // if game status has not changed, viewports have not changed either
   if (game_status == game_status_last)
     return FALSE;
 
-  // check if playfield viewport has changed with current game status
+  // check if all viewports have changed with current game status
+
   struct RectWithBorder *vp_playfield = &viewport.playfield[game_status];
+  struct RectWithBorder *vp_door_1    = &viewport.door_1[game_status];
+  struct RectWithBorder *vp_door_2    = &viewport.door_2[game_status];
   int new_real_sx      = vp_playfield->x;
   int new_real_sy      = vp_playfield->y;
   int new_full_sxsize  = vp_playfield->width;
   int new_full_sysize  = vp_playfield->height;
+  int new_dx           = vp_door_1->x;
+  int new_dy           = vp_door_1->y;
+  int new_dxsize       = vp_door_1->width;
+  int new_dysize       = vp_door_1->height;
+  int new_vx           = vp_door_2->x;
+  int new_vy           = vp_door_2->y;
+  int new_vxsize       = vp_door_2->width;
+  int new_vysize       = vp_door_2->height;
 
-  return (new_real_sx != REAL_SX ||
-         new_real_sy != REAL_SY ||
-         new_full_sxsize != FULL_SXSIZE ||
-         new_full_sysize != FULL_SYSIZE);
+  boolean playfield_viewport_has_changed =
+    (new_real_sx != REAL_SX ||
+     new_real_sy != REAL_SY ||
+     new_full_sxsize != FULL_SXSIZE ||
+     new_full_sysize != FULL_SYSIZE);
+
+  boolean door_1_viewport_has_changed =
+    (new_dx != DX ||
+     new_dy != DY ||
+     new_dxsize != DXSIZE ||
+     new_dysize != DYSIZE);
+
+  boolean door_2_viewport_has_changed =
+    (new_vx != VX ||
+     new_vy != VY ||
+     new_vxsize != VXSIZE ||
+     new_vysize != VYSIZE ||
+     game_status_last == GAME_MODE_EDITOR);
+
+  return (playfield_viewport_has_changed &&
+         door_1_viewport_has_changed &&
+         door_2_viewport_has_changed);
 }
 
-boolean CheckIfGlobalBorderOrPlayfieldViewportHasChanged(void)
+boolean CheckFadeAll(void)
 {
   return (CheckIfGlobalBorderHasChanged() ||
-         CheckIfPlayfieldViewportHasChanged());
+         CheckIfAllViewportsHaveChanged());
 }
 
 void ChangeViewportPropertiesIfNeeded(void)
@@ -9453,11 +9559,14 @@ void ChangeViewportPropertiesIfNeeded(void)
   struct RectWithBorder *vp_door_3    = &viewport.door_2[GAME_MODE_EDITOR];
   int new_win_xsize    = vp_window->width;
   int new_win_ysize    = vp_window->height;
-  int border_size      = vp_playfield->border_size;
-  int new_sx           = vp_playfield->x + border_size;
-  int new_sy           = vp_playfield->y + border_size;
-  int new_sxsize       = vp_playfield->width  - 2 * border_size;
-  int new_sysize       = vp_playfield->height - 2 * border_size;
+  int border_left      = vp_playfield->border_left;
+  int border_right     = vp_playfield->border_right;
+  int border_top       = vp_playfield->border_top;
+  int border_bottom    = vp_playfield->border_bottom;
+  int new_sx           = vp_playfield->x      + border_left;
+  int new_sy           = vp_playfield->y      + border_top;
+  int new_sxsize       = vp_playfield->width  - border_left - border_right;
+  int new_sysize       = vp_playfield->height - border_top  - border_bottom;
   int new_real_sx      = vp_playfield->x;
   int new_real_sy      = vp_playfield->y;
   int new_full_sxsize  = vp_playfield->width;
@@ -9496,18 +9605,18 @@ 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 ||
       new_scr_fieldy != SCR_FIELDY)
   {
-    /* this always toggles between MAIN and GAME when using small tile size */
+    // this always toggles between MAIN and GAME when using small tile size
 
     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 ||
@@ -9562,8 +9671,8 @@ void ChangeViewportPropertiesIfNeeded(void)
     }
 
     // add current and new door 2 area if position or size has changed
-    if (new_dx != VX || new_dy != VY ||
-       new_dxsize != VXSIZE || new_dysize != VYSIZE)
+    if (new_vx != VX || new_vy != VY ||
+       new_vxsize != VXSIZE || new_vysize != VYSIZE)
     {
       JoinRectangles(&FADE_SX, &FADE_SY, &FADE_SXSIZE, &FADE_SYSIZE,
                     VX, VY, VXSIZE, VYSIZE);
@@ -9577,7 +9686,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();
@@ -9611,13 +9720,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;
@@ -9633,7 +9742,9 @@ 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
 
     InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
     InitImageTextures();
@@ -9641,7 +9752,7 @@ void ChangeViewportPropertiesIfNeeded(void)
 
   if (init_gadgets_and_anims)
   {
-    // printf("::: init_gadgets_and_anims\n");
+    // Debug("tools:viewport", "init_gadgets_and_anims");
 
     InitGadgets();
     InitGlobalAnimations();
@@ -9649,6 +9760,6 @@ void ChangeViewportPropertiesIfNeeded(void)
 
   if (init_em_graphics)
   {
-      InitGraphicInfo_EM();
+    InitGraphicInfo_EM();
   }
 }