rnd-20060819-3-src
[rocksndiamonds.git] / src / game.c
index 5d1f08f90516fbf347f65246e676f1c2fce9b631..72ae34a87ddde26fa8a438a02ec3e2db33fc6dca 100644 (file)
@@ -1,7 +1,7 @@
 /***********************************************************
 * Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-* (c) 1995-2002 Artsoft Entertainment                      *
+* (c) 1995-2006 Artsoft Entertainment                      *
 *               Holger Schemel                             *
 *               Detmolder Strasse 189                      *
 *               33604 Bielefeld                            *
 #define USE_ELEMENT_TOUCHING_BUGFIX    (USE_NEW_STUFF          * 1)
 #define USE_NEW_CONTINUOUS_SNAPPING    (USE_NEW_STUFF          * 1)
 #define USE_GFX_RESET_GFX_ANIMATION    (USE_NEW_STUFF          * 1)
+#define USE_BOTH_SWITCHGATE_SWITCHES   (USE_NEW_STUFF          * 1)
+#define USE_PLAYER_GRAVITY             (USE_NEW_STUFF          * 1)
+#define USE_FIXED_BORDER_RUNNING_GFX   (USE_NEW_STUFF          * 1)
+#define USE_QUICKSAND_BD_ROCK_BUGFIX   (USE_NEW_STUFF          * 0)
 
 #define USE_QUICKSAND_IMPACT_BUGFIX    (USE_NEW_STUFF          * 0)
 
+#define USE_CODE_THAT_BREAKS_SNAKE_BITE        (USE_NEW_STUFF          * 1)
+
+#define USE_UFAST_PLAYER_EXIT_BUGFIX   (USE_NEW_STUFF          * 1)
+#define USE_NEW_GAME_WON               (USE_NEW_STUFF          * 1)
+
+
 /* for DigField() */
 #define DF_NO_PUSH             0
 #define DF_DIG                 1
 #define EX_TYPE_DYNA           (1 << 4)
 #define EX_TYPE_SINGLE_TILE    (EX_TYPE_CENTER | EX_TYPE_BORDER)
 
+#define        PANEL_DEACTIVATED(p)    ((p).x < 0 || (p).y < 0)
+
 /* special positions in the game control window (relative to control window) */
-#define XX_LEVEL               37
-#define YY_LEVEL               20
-#define XX_EMERALDS            29
-#define YY_EMERALDS            54
-#define XX_DYNAMITE            29
-#define YY_DYNAMITE            89
-#define XX_KEYS                        18
-#define YY_KEYS                        123
-#define XX_SCORE               15
-#define YY_SCORE               159
-#define XX_TIME1               29
-#define XX_TIME2               30
-#define YY_TIME                        194
+#define XX_LEVEL1              (game.panel.level.x)
+#define XX_LEVEL2              (game.panel.level.x - 1)
+#define YY_LEVEL               (game.panel.level.y)
+#define XX_EMERALDS            (game.panel.gems.x)
+#define YY_EMERALDS            (game.panel.gems.y)
+#define XX_DYNAMITE            (game.panel.inventory.x)
+#define YY_DYNAMITE            (game.panel.inventory.y)
+#define XX_KEYS                        (game.panel.keys.x)
+#define YY_KEYS                        (game.panel.keys.y)
+#define XX_SCORE               (game.panel.score.x)
+#define YY_SCORE               (game.panel.score.y)
+#define XX_TIME1               (game.panel.time.x)
+#define XX_TIME2               (game.panel.time.x + 1)
+#define YY_TIME                        (game.panel.time.y)
 
 /* special positions in the game control window (relative to main window) */
-#define DX_LEVEL               (DX + XX_LEVEL)
+#define DX_LEVEL1              (DX + XX_LEVEL1)
+#define DX_LEVEL2              (DX + XX_LEVEL2)
 #define DY_LEVEL               (DY + YY_LEVEL)
 #define DX_EMERALDS            (DX + XX_EMERALDS)
 #define DY_EMERALDS            (DY + YY_EMERALDS)
 #define MOVE_DELAY_HIGH_SPEED  4
 #define MOVE_DELAY_MAX_SPEED   1
 
-#if 0
-#define DOUBLE_MOVE_DELAY(x)   (x = (x <= MOVE_DELAY_HIGH_SPEED ? x * 2 : x))
-#define HALVE_MOVE_DELAY(x)    (x = (x >= MOVE_DELAY_HIGH_SPEED ? x / 2 : x))
-#else
 #define DOUBLE_MOVE_DELAY(x)   (x = (x < MOVE_DELAY_MIN_SPEED ? x * 2 : x))
 #define HALVE_MOVE_DELAY(x)    (x = (x > MOVE_DELAY_MAX_SPEED ? x / 2 : x))
-#endif
-#define DOUBLE_PLAYER_SPEED(p) (HALVE_MOVE_DELAY((p)->move_delay_value))
+
+#define DOUBLE_PLAYER_SPEED(p) (HALVE_MOVE_DELAY( (p)->move_delay_value))
 #define HALVE_PLAYER_SPEED(p)  (DOUBLE_MOVE_DELAY((p)->move_delay_value))
 
 /* values for other actions */
                                 RND((c)->delay_random))
 
 
-#if 1
 #define GET_VALID_RUNTIME_ELEMENT(e)                                   \
         ((e) >= NUM_RUNTIME_ELEMENTS ? EL_UNKNOWN : (e))
-#else
-#define GET_VALID_FILE_ELEMENT(e)                                      \
-       ((e) >= NUM_FILE_ELEMENTS ? EL_UNKNOWN : (e))
-#endif
 
-#define GET_TARGET_ELEMENT(e, ch, cv, cs)                              \
+#define RESOLVED_REFERENCE_ELEMENT(be, e)                              \
+       ((be) + (e) - EL_SELF < EL_CUSTOM_START ? EL_CUSTOM_START :     \
+        (be) + (e) - EL_SELF > EL_CUSTOM_END   ? EL_CUSTOM_END :       \
+        (be) + (e) - EL_SELF)
+
+#define GET_TARGET_ELEMENT(be, e, ch, cv, cs)                          \
        ((e) == EL_TRIGGER_PLAYER   ? (ch)->actual_trigger_player    :  \
         (e) == EL_TRIGGER_ELEMENT  ? (ch)->actual_trigger_element   :  \
         (e) == EL_TRIGGER_CE_VALUE ? (ch)->actual_trigger_ce_value  :  \
         (e) == EL_TRIGGER_CE_SCORE ? (ch)->actual_trigger_ce_score  :  \
         (e) == EL_CURRENT_CE_VALUE ? (cv) :                            \
-        (e) == EL_CURRENT_CE_SCORE ? (cs) : (e))
+        (e) == EL_CURRENT_CE_SCORE ? (cs) :                            \
+        (e) >= EL_LAST_CE_8 && (e) <= EL_NEXT_CE_8 ?                   \
+        RESOLVED_REFERENCE_ELEMENT(be, e) :                            \
+        (e))
 
 #define CAN_GROW_INTO(e)                                               \
        ((e) == EL_SAND || (IS_DIGGABLE(e) && level.grow_into_diggable))
        (IN_LEV_FIELD(x, y) && (Feld[x][y] == EL_EMC_SPRING_BUMPER ||   \
                                Feld[x][y] == EL_EMC_SPRING_BUMPER_ACTIVE))
 
-#if 0
-#define GROUP_NR(e)            ((e) - EL_GROUP_START)
-#define IS_IN_GROUP(e, nr)     (element_info[e].in_group[nr] == TRUE)
-#define IS_IN_GROUP_EL(e, ge)  (IS_IN_GROUP(e, (ge) - EL_GROUP_START))
-
-#define IS_EQUAL_OR_IN_GROUP(e, ge)                                    \
-       (IS_GROUP_ELEMENT(ge) ? IS_IN_GROUP(e, GROUP_NR(ge)) : (e) == (ge))
-#endif
-
 #define MOVE_ENTER_EL(e)       (element_info[e].move_enter_element)
 
 #define CE_ENTER_FIELD_COND(e, x, y)                                   \
@@ -393,8 +397,6 @@ static void RunTimegateWheel(int, int);
 static void InitMagicBallDelay(int, int);
 static void ActivateMagicBall(int, int);
 
-static void InitDiagonalMovingElement(int, int);
-
 struct ChangingElementInfo
 {
   int element;
@@ -590,7 +592,7 @@ static struct ChangingElementInfo change_delay_list[] =
     0,
     NULL,
     NULL,
-    InitDiagonalMovingElement
+    NULL,
   },
 
   {
@@ -778,6 +780,7 @@ static int get_move_delay_from_stepsize(int move_stepsize)
 static void SetPlayerMoveSpeed(struct PlayerInfo *player, int move_stepsize,
                               boolean init_game)
 {
+  int player_nr = player->index_nr;
   int move_delay = get_move_delay_from_stepsize(move_stepsize);
   boolean cannot_move = (move_stepsize == STEPSIZE_NOT_MOVING ? TRUE : FALSE);
 
@@ -789,8 +792,8 @@ static void SetPlayerMoveSpeed(struct PlayerInfo *player, int move_stepsize,
 
   if (init_game)
   {
-    player->move_delay       = game.initial_move_delay;
-    player->move_delay_value = game.initial_move_delay_value;
+    player->move_delay       = game.initial_move_delay[player_nr];
+    player->move_delay_value = game.initial_move_delay_value[player_nr];
 
     player->move_delay_value_next = -1;
 
@@ -1119,10 +1122,12 @@ static void InitField(int x, int y, boolean init_game)
       }
       break;
 
+#if !USE_BOTH_SWITCHGATE_SWITCHES
     case EL_SWITCHGATE_SWITCH_DOWN:    /* always start with same switch pos */
       if (init_game)
        Feld[x][y] = EL_SWITCHGATE_SWITCH_UP;
       break;
+#endif
 
     case EL_LIGHT_SWITCH_ACTIVE:
       if (init_game)
@@ -1148,7 +1153,6 @@ static void InitField(int x, int y, boolean init_game)
       break;
 
     default:
-#if 1
       if (IS_CUSTOM_ELEMENT(element))
       {
        if (CAN_MOVE(element))
@@ -1159,59 +1163,18 @@ static void InitField(int x, int y, boolean init_game)
          CustomValue[x][y] = GET_NEW_CE_VALUE(Feld[x][y]);
 #endif
       }
-#else
-      if (IS_CUSTOM_ELEMENT(element) && CAN_MOVE(element))
-       InitMovDir(x, y);
-#endif
       else if (IS_GROUP_ELEMENT(element))
       {
-#if 1
        Feld[x][y] = get_element_from_group_element(element);
 
        InitField(x, y, init_game);
-#else
-       struct ElementGroupInfo *group = element_info[element].group;
-       int last_anim_random_frame = gfx.anim_random_frame;
-       int element_pos;
-
-       if (group->choice_mode == ANIM_RANDOM)
-         gfx.anim_random_frame = RND(group->num_elements_resolved);
-
-       element_pos = getAnimationFrame(group->num_elements_resolved, 1,
-                                       group->choice_mode, 0,
-                                       group->choice_pos);
-
-       if (group->choice_mode == ANIM_RANDOM)
-         gfx.anim_random_frame = last_anim_random_frame;
-
-       group->choice_pos++;
-
-       Feld[x][y] = group->element_resolved[element_pos];
-
-       InitField(x, y, init_game);
-#endif
       }
+
       break;
   }
 
-#if 1
   if (!init_game)
     CheckTriggeredElementChange(x, y, element, CE_CREATION_OF_X);
-#endif
-
-#if 0
-
-#if USE_NEW_CUSTOM_VALUE
-
-#if 1
-  CustomValue[x][y] = GET_NEW_CE_VALUE(Feld[x][y]);
-#else
-  CustomValue[x][y] = element_info[Feld[x][y]].custom_value_initial;
-#endif
-
-#endif
-
-#endif
 }
 
 static inline void InitField_WithBug1(int x, int y, boolean init_game)
@@ -1249,6 +1212,9 @@ inline void DrawGameValue_Emeralds(int value)
 {
   int xpos = (3 * 14 - 3 * getFontWidth(FONT_TEXT_2)) / 2;
 
+  if (PANEL_DEACTIVATED(game.panel.gems))
+    return;
+
   DrawText(DX_EMERALDS + xpos, DY_EMERALDS, int2str(value, 3), FONT_TEXT_2);
 }
 
@@ -1256,6 +1222,9 @@ inline void DrawGameValue_Dynamite(int value)
 {
   int xpos = (3 * 14 - 3 * getFontWidth(FONT_TEXT_2)) / 2;
 
+  if (PANEL_DEACTIVATED(game.panel.inventory))
+    return;
+
   DrawText(DX_DYNAMITE + xpos, DY_DYNAMITE, int2str(value, 3), FONT_TEXT_2);
 }
 
@@ -1264,19 +1233,23 @@ inline void DrawGameValue_Keys(int key[MAX_NUM_KEYS])
   int base_key_graphic = EL_KEY_1;
   int i;
 
+  if (PANEL_DEACTIVATED(game.panel.keys))
+    return;
+
   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
     base_key_graphic = EL_EM_KEY_1;
 
   /* currently only 4 of 8 possible keys are displayed */
   for (i = 0; i < STD_NUM_KEYS; i++)
   {
+    int x = XX_KEYS + i * MINI_TILEX;
+    int y = YY_KEYS;
+
     if (key[i])
-      DrawMiniGraphicExt(drawto, DX_KEYS + i * MINI_TILEX, DY_KEYS,
-                        el2edimg(base_key_graphic + i));
+      DrawMiniGraphicExt(drawto, DX + x,DY + y, el2edimg(base_key_graphic + i));
     else
       BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
-                DOOR_GFX_PAGEX5 + XX_KEYS + i * MINI_TILEX, YY_KEYS,
-                MINI_TILEX, MINI_TILEY, DX_KEYS + i * MINI_TILEX, DY_KEYS);
+                DOOR_GFX_PAGEX5 + x, y, MINI_TILEX, MINI_TILEY, DX + x,DY + y);
   }
 }
 
@@ -1284,6 +1257,9 @@ inline void DrawGameValue_Score(int value)
 {
   int xpos = (5 * 14 - 5 * getFontWidth(FONT_TEXT_2)) / 2;
 
+  if (PANEL_DEACTIVATED(game.panel.score))
+    return;
+
   DrawText(DX_SCORE + xpos, DY_SCORE, int2str(value, 5), FONT_TEXT_2);
 }
 
@@ -1292,9 +1268,12 @@ inline void DrawGameValue_Time(int value)
   int xpos3 = (3 * 14 - 3 * getFontWidth(FONT_TEXT_2)) / 2;
   int xpos4 = (4 * 10 - 4 * getFontWidth(FONT_LEVEL_NUMBER)) / 2;
 
+  if (PANEL_DEACTIVATED(game.panel.time))
+    return;
+
   /* clear background if value just changed its size */
   if (value == 999 || value == 1000)
-    ClearRectangle(drawto, DX_TIME1, DY_TIME, 14 * 3, 14);
+    ClearRectangleOnBackground(drawto, DX_TIME1, DY_TIME, 14 * 3, 14);
 
   if (value < 1000)
     DrawText(DX_TIME1 + xpos3, DY_TIME, int2str(value, 3), FONT_TEXT_2);
@@ -1304,26 +1283,13 @@ inline void DrawGameValue_Time(int value)
 
 inline void DrawGameValue_Level(int value)
 {
+  if (PANEL_DEACTIVATED(game.panel.level))
+    return;
+
   if (level_nr < 100)
-    DrawText(DX_LEVEL, DY_LEVEL, int2str(value, 2), FONT_TEXT_2);
+    DrawText(DX_LEVEL1, DY_LEVEL, int2str(value, 2), FONT_TEXT_2);
   else
-  {
-    /* misuse area for displaying emeralds to draw bigger level number */
-    DrawTextExt(drawto, DX_EMERALDS, DY_EMERALDS,
-               int2str(value, 3), FONT_LEVEL_NUMBER, BLIT_OPAQUE);
-
-    /* now copy it to the area for displaying level number */
-    BlitBitmap(drawto, drawto,
-              DX_EMERALDS, DY_EMERALDS + 1,
-              getFontWidth(FONT_LEVEL_NUMBER) * 3,
-              getFontHeight(FONT_LEVEL_NUMBER) - 1,
-              DX_LEVEL - 1, DY_LEVEL + 1);
-
-    /* restore the area for displaying emeralds */
-    DrawGameValue_Emeralds(local_player->gems_still_needed);
-
-    /* yes, this is all really ugly :-) */
-  }
+    DrawText(DX_LEVEL2, DY_LEVEL, int2str(value, 3), FONT_LEVEL_NUMBER);
 }
 
 void DrawAllGameValues(int emeralds, int dynamite, int score, int time,
@@ -1343,10 +1309,13 @@ void DrawAllGameValues(int emeralds, int dynamite, int score, int time,
   DrawGameValue_Time(time);
 
   DrawGameValue_Keys(key);
+
+  redraw_mask |= REDRAW_DOOR_1;
 }
 
 void DrawGameDoorValues()
 {
+  int time_value = (level.time == 0 ? TimePlayed : TimeLeft);
   int dynamite_state = 0;
   int key_bits = 0;
   int i, j;
@@ -1358,16 +1327,6 @@ void DrawGameDoorValues()
     return;
   }
 
-#if 0
-  DrawGameValue_Level(level_nr);
-
-  DrawGameValue_Emeralds(local_player->gems_still_needed);
-  DrawGameValue_Dynamite(local_player->inventory_size);
-  DrawGameValue_Score(local_player->score);
-  DrawGameValue_Time(TimeLeft);
-
-#else
-
   if (game.centered_player_nr == -1)
   {
     for (i = 0; i < MAX_PLAYERS; i++)
@@ -1378,10 +1337,6 @@ void DrawGameDoorValues()
 
       dynamite_state += stored_player[i].inventory_size;
     }
-
-#if 0
-    DrawGameValue_Keys(stored_player[i].key);
-#endif
   }
   else
   {
@@ -1395,55 +1350,9 @@ void DrawGameDoorValues()
   }
 
   DrawAllGameValues(local_player->gems_still_needed, dynamite_state,
-                   local_player->score, TimeLeft, key_bits);
-#endif
+                   local_player->score, time_value, key_bits);
 }
 
-#if 0
-static void resolve_group_element(int group_element, int recursion_depth)
-{
-  static int group_nr;
-  static struct ElementGroupInfo *group;
-  struct ElementGroupInfo *actual_group = element_info[group_element].group;
-  int i;
-
-  if (recursion_depth > NUM_GROUP_ELEMENTS)    /* recursion too deep */
-  {
-    Error(ERR_WARN, "recursion too deep when resolving group element %d",
-         group_element - EL_GROUP_START + 1);
-
-    /* replace element which caused too deep recursion by question mark */
-    group->element_resolved[group->num_elements_resolved++] = EL_UNKNOWN;
-
-    return;
-  }
-
-  if (recursion_depth == 0)                    /* initialization */
-  {
-    group = element_info[group_element].group;
-    group_nr = group_element - EL_GROUP_START;
-
-    group->num_elements_resolved = 0;
-    group->choice_pos = 0;
-  }
-
-  for (i = 0; i < actual_group->num_elements; i++)
-  {
-    int element = actual_group->element[i];
-
-    if (group->num_elements_resolved == NUM_FILE_ELEMENTS)
-      break;
-
-    if (IS_GROUP_ELEMENT(element))
-      resolve_group_element(element, recursion_depth + 1);
-    else
-    {
-      group->element_resolved[group->num_elements_resolved++] = element;
-      element_info[element].in_group[group_nr] = TRUE;
-    }
-  }
-}
-#endif
 
 /*
   =============================================================================
@@ -1575,32 +1484,18 @@ static void InitGameEngine()
   printf("       => game.engine_version == %06d\n", game.engine_version);
 #endif
 
-#if 0
-  /* ---------- recursively resolve group elements ------------------------- */
-
-  for (i = 0; i < MAX_NUM_ELEMENTS; i++)
-    for (j = 0; j < NUM_GROUP_ELEMENTS; j++)
-      element_info[i].in_group[j] = FALSE;
-
-  for (i = 0; i < NUM_GROUP_ELEMENTS; i++)
-    resolve_group_element(EL_GROUP_START + i, 0);
-#endif
-
   /* ---------- initialize player's initial move delay --------------------- */
 
-#if 1
-  /* dynamically adjust player properties according to level information */
-  game.initial_move_delay_value =
-    get_move_delay_from_stepsize(level.initial_player_stepsize);
-#else
   /* dynamically adjust player properties according to level information */
-  game.initial_move_delay_value =
-    (level.double_speed ? MOVE_DELAY_HIGH_SPEED : MOVE_DELAY_NORMAL_SPEED);
-#endif
+  for (i = 0; i < MAX_PLAYERS; i++)
+    game.initial_move_delay_value[i] =
+      get_move_delay_from_stepsize(level.initial_player_stepsize[i]);
 
   /* dynamically adjust player properties according to game engine version */
-  game.initial_move_delay = (game.engine_version <= VERSION_IDENT(2,0,1,0) ?
-                            game.initial_move_delay_value : 0);
+  for (i = 0; i < MAX_PLAYERS; i++)
+    game.initial_move_delay[i] =
+      (game.engine_version <= VERSION_IDENT(2,0,1,0) ?
+       game.initial_move_delay_value[i] : 0);
 
   /* ---------- initialize player's initial push delay --------------------- */
 
@@ -1744,6 +1639,9 @@ static void InitGameEngine()
              for (l = 0; l < group->num_elements_resolved; l++)
                trigger_events[group->element_resolved[l]][k] = TRUE;
            }
+           else if (trigger_element == EL_ANY_ELEMENT)
+             for (l = 0; l < MAX_NUM_ELEMENTS; l++)
+               trigger_events[l][k] = TRUE;
            else
              trigger_events[trigger_element][k] = TRUE;
          }
@@ -1759,8 +1657,17 @@ static void InitGameEngine()
   {
     if (!IS_CUSTOM_ELEMENT(i))
     {
-      element_info[i].push_delay_fixed  = game.default_push_delay_fixed;
-      element_info[i].push_delay_random = game.default_push_delay_random;
+      /* set default push delay values (corrected since version 3.0.7-1) */
+      if (game.engine_version < VERSION_IDENT(3,0,7,1))
+      {
+       element_info[i].push_delay_fixed = 2;
+       element_info[i].push_delay_random = 8;
+      }
+      else
+      {
+       element_info[i].push_delay_fixed = 8;
+       element_info[i].push_delay_random = 8;
+      }
     }
   }
 
@@ -1889,13 +1796,10 @@ int get_num_special_action(int element, int action_first, int action_last)
       break;
   }
 
-#if 0
-  printf("::: %d->%d: %d\n", action_first, action_last, num_special_action);
-#endif
-
   return num_special_action;
 }
 
+
 /*
   =============================================================================
   InitGame()
@@ -1909,8 +1813,11 @@ void InitGame()
   boolean emulate_bd = TRUE;   /* unless non-BOULDERDASH elements found */
   boolean emulate_sb = TRUE;   /* unless non-SOKOBAN     elements found */
   boolean emulate_sp = TRUE;   /* unless non-SUPAPLEX    elements found */
+  boolean do_fading = (game_status == GAME_MODE_MAIN);
   int i, j, x, y;
 
+  game_status = GAME_MODE_PLAYING;
+
   InitGameEngine();
 
   /* don't play tapes over network */
@@ -1961,6 +1868,8 @@ void InitGame()
     player->block_last_field = FALSE;  /* initialized in InitPlayerField() */
     player->block_delay_adjustment = 0;        /* initialized in InitPlayerField() */
 
+    player->gravity = level.initial_player_gravity[i];
+
     player->can_fall_into_acid = CAN_MOVE_INTO_ACID(player->element_nr);
 
     player->actual_frame_counter = 0;
@@ -1969,6 +1878,8 @@ void InitGame()
 
     player->last_move_dir = MV_NONE;
 
+    player->is_active = FALSE;
+
     player->is_waiting = FALSE;
     player->is_moving = FALSE;
     player->is_auto_moving = FALSE;
@@ -1995,18 +1906,6 @@ void InitGame()
     player->special_action_bored = ACTION_DEFAULT;
     player->special_action_sleeping = ACTION_DEFAULT;
 
-#if 1
-    /* cannot be set here -- could be modified in Init[Player]Field() below */
-#else
-    /* set number of special actions for bored and sleeping animation */
-    player->num_special_action_bored =
-      get_num_special_action(player->artwork_element,
-                            ACTION_BORING_1, ACTION_BORING_LAST);
-    player->num_special_action_sleeping =
-      get_num_special_action(player->artwork_element,
-                            ACTION_SLEEPING_1, ACTION_SLEEPING_LAST);
-#endif
-
     player->switch_x = -1;
     player->switch_y = -1;
 
@@ -2015,18 +1914,7 @@ void InitGame()
 
     player->show_envelope = 0;
 
-#if 1
-    SetPlayerMoveSpeed(player, level.initial_player_stepsize, TRUE);
-#else
-    player->move_delay       = game.initial_move_delay;
-    player->move_delay_value = game.initial_move_delay_value;
-
-    player->move_delay_value_next = -1;
-
-    player->move_delay_reset_counter = 0;
-
-    player->cannot_move = FALSE;
-#endif
+    SetPlayerMoveSpeed(player, level.initial_player_stepsize[i], TRUE);
 
     player->push_delay       = -1;     /* initialized when pushing starts */
     player->push_delay_value = game.initial_push_delay_value;
@@ -2048,6 +1936,10 @@ void InitGame()
 
     player->LevelSolved = FALSE;
     player->GameOver = FALSE;
+
+    player->LevelSolved_GameEnd = FALSE;
+    player->LevelSolved_SaveTape = FALSE;
+    player->LevelSolved_SaveScore = FALSE;
   }
 
   network_player_action_received = FALSE;
@@ -2082,8 +1974,11 @@ void InitGame()
   game.timegate_time_left = 0;
   game.switchgate_pos = 0;
   game.wind_direction = level.wind_direction_initial;
-  game.gravity = level.initial_gravity;
+
+#if !USE_PLAYER_GRAVITY
+  game.gravity = FALSE;
   game.explosions_delayed = TRUE;
+#endif
 
   game.lenses_time_left = 0;
   game.magnify_time_left = 0;
@@ -2105,11 +2000,6 @@ void InitGame()
     tape.set_centered_player = TRUE;
   }
 
-#if 0
-  printf("::: focus set to player %d [%d]\n",
-        game.centered_player_nr, local_player->index_nr);
-#endif
-
   for (i = 0; i < NUM_BELTS; i++)
   {
     game.belt_dir[i] = MV_NONE;
@@ -2119,11 +2009,7 @@ void InitGame()
   for (i = 0; i < MAX_NUM_AMOEBA; i++)
     AmoebaCnt[i] = AmoebaCnt2[i] = 0;
 
-#if 1
   SCAN_PLAYFIELD(x, y)
-#else
-  for (x = 0; x < lev_fieldx; x++) for (y = 0; y < lev_fieldy; y++)
-#endif
   {
     Feld[x][y] = level.field[x][y];
     MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0;
@@ -2157,11 +2043,7 @@ void InitGame()
     GfxDir[x][y] = MV_NONE;
   }
 
-#if 1
   SCAN_PLAYFIELD(x, y)
-#else
-  for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
   {
     if (emulate_bd && !IS_BD_ELEMENT(Feld[x][y]))
       emulate_bd = FALSE;
@@ -2179,7 +2061,6 @@ void InitGame()
   {
     struct PlayerInfo *player = &stored_player[i];
 
-#if 1
     /* set number of special actions for bored and sleeping animation */
     player->num_special_action_bored =
       get_num_special_action(player->artwork_element,
@@ -2187,8 +2068,6 @@ void InitGame()
     player->num_special_action_sleeping =
       get_num_special_action(player->artwork_element,
                             ACTION_SLEEPING_1, ACTION_SLEEPING_LAST);
-#endif
-
   }
 
   game.emulation = (emulate_bd ? EMU_BOULDERDASH :
@@ -2269,10 +2148,6 @@ void InitGame()
          some_player->present = FALSE;
          some_player->active = FALSE;
 
-#if 0
-         player->element_nr = some_player->element_nr;
-#endif
-
          player->artwork_element = some_player->artwork_element;
 
          player->block_last_field       = some_player->block_last_field;
@@ -2385,11 +2260,7 @@ void InitGame()
     int found_element = EL_UNDEFINED;
     int player_nr = local_player->index_nr;
 
-#if 1
     SCAN_PLAYFIELD(x, y)
-#else
-    for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
     {
       int element = Feld[x][y];
       int content;
@@ -2486,13 +2357,21 @@ void InitGame()
                local_player->jy - MIDPOSY);
   }
 
+  StopAnimation();
+
   if (!game.restart_level)
     CloseDoor(DOOR_CLOSE_1);
 
+  if (do_fading)
+    FadeOut(REDRAW_FIELD);
+
   /* !!! FIX THIS (START) !!! */
   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
   {
     InitGameEngine_EM();
+
+    /* blit playfield from scroll buffer to normal back buffer for fading in */
+    BlitScreenToBitmap_EM(backbuffer);
   }
   else
   {
@@ -2503,14 +2382,19 @@ void InitGame()
     if (game.timegate_time_left == 0)
       CloseAllOpenTimegates();
 
+    /* blit playfield from scroll buffer to normal back buffer for fading in */
     if (setup.soft_scrolling)
       BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
 
     redraw_mask |= REDRAW_FROM_BACKBUFFER;
-    FadeToFront();
   }
   /* !!! FIX THIS (END) !!! */
 
+  if (do_fading)
+    FadeIn(REDRAW_FIELD);
+
+  BackToFront();
+
   if (!game.restart_level)
   {
     /* copy default game door content to main double buffer */
@@ -2518,6 +2402,9 @@ void InitGame()
               DOOR_GFX_PAGEX5, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, DX, DY);
   }
 
+  SetPanelBackground();
+  SetDrawBackgroundMask(REDRAW_DOOR_1);
+
   DrawGameDoorValues();
 
   if (!game.restart_level)
@@ -2761,6 +2648,189 @@ void InitAmoebaNr(int x, int y)
   AmoebaCnt2[group_nr]++;
 }
 
+#if USE_NEW_GAME_WON
+
+void GameWon()
+{
+  static boolean score_done = FALSE;
+  static boolean player_done = FALSE;
+  static int game_over_delay = 0;
+  int game_over_delay_value = 50;
+
+  /* do not start end game actions before the player stops moving (to exit) */
+  if (local_player->MovPos)
+    return;
+
+  if (tape.auto_play)          /* tape might already be stopped here */
+    tape.auto_play_level_solved = TRUE;
+
+  if (!local_player->LevelSolved_GameEnd)
+  {
+    local_player->LevelSolved_GameEnd = TRUE;
+    local_player->LevelSolved_SaveTape = tape.recording;
+    local_player->LevelSolved_SaveScore = !tape.playing;
+
+    score_done = FALSE;
+    player_done = FALSE;
+    game_over_delay = 0;
+  }
+
+  PlaySoundStereo(SND_GAME_WINNING, SOUND_MIDDLE);
+
+  if (TimeLeft > 0)
+  {
+    if (!tape.playing)
+    {
+      if (setup.sound_loops)
+       PlaySoundExt(SND_GAME_LEVELTIME_BONUS, SOUND_MAX_VOLUME, SOUND_MIDDLE,
+                    SND_CTRL_PLAY_LOOP);
+      else
+       PlaySoundStereo(SND_GAME_LEVELTIME_BONUS, SOUND_MIDDLE);
+    }
+
+    if (TimeLeft > 100 && TimeLeft % 10 == 0)
+    {
+      TimeLeft -= 10;
+      RaiseScore(level.score[SC_TIME_BONUS] * 10);
+    }
+    else
+    {
+      TimeLeft--;
+      RaiseScore(level.score[SC_TIME_BONUS]);
+    }
+
+    DrawGameValue_Time(TimeLeft);
+
+    if (TimeLeft <= 0 && !tape.playing && setup.sound_loops)
+      StopSound(SND_GAME_LEVELTIME_BONUS);
+  }
+  else if (level.time == 0 && TimePlayed < 999)        /* level without time limit */
+  {
+    if (!tape.playing)
+    {
+      if (setup.sound_loops)
+       PlaySoundExt(SND_GAME_LEVELTIME_BONUS, SOUND_MAX_VOLUME, SOUND_MIDDLE,
+                    SND_CTRL_PLAY_LOOP);
+      else
+       PlaySoundStereo(SND_GAME_LEVELTIME_BONUS, SOUND_MIDDLE);
+    }
+
+    if (TimePlayed < 900 && TimePlayed % 10 == 0)
+    {
+      TimePlayed += 10;
+      RaiseScore(level.score[SC_TIME_BONUS] * 10);
+    }
+    else
+    {
+      TimePlayed++;
+      RaiseScore(level.score[SC_TIME_BONUS]);
+    }
+
+    DrawGameValue_Time(TimePlayed);
+
+    if (TimePlayed >= 999 && !tape.playing && setup.sound_loops)
+      StopSound(SND_GAME_LEVELTIME_BONUS);
+  }
+  else
+  {
+    score_done = TRUE;
+  }
+
+  /* close exit door after last player */
+  if (AllPlayersGone && ExitX >= 0 && ExitY >= 0 &&
+      (Feld[ExitX][ExitY] == EL_EXIT_OPEN ||
+       Feld[ExitX][ExitY] == EL_SP_EXIT_OPEN))
+  {
+    int element = Feld[ExitX][ExitY];
+
+    Feld[ExitX][ExitY] = (element == EL_EXIT_OPEN ? EL_EXIT_CLOSING :
+                         EL_SP_EXIT_CLOSING);
+
+    PlayLevelSoundElementAction(ExitX, ExitY, element, ACTION_CLOSING);
+  }
+
+  /* player disappears */
+  if (ExitX >= 0 && ExitY >= 0 && !player_done)
+  {
+    DrawLevelField(ExitX, ExitY);
+
+    player_done = TRUE;
+  }
+
+  game_over_delay++;
+
+  if (game_over_delay < game_over_delay_value || !score_done)
+    return;
+}
+
+void GameEnd()
+{
+  int hi_pos;
+  boolean raise_level = FALSE;
+
+  CloseDoor(DOOR_CLOSE_1);
+
+  if (local_player->LevelSolved_SaveTape)
+  {
+    TapeStop();
+
+    SaveTape(tape.level_nr);           /* Ask to save tape */
+  }
+
+  if (!local_player->LevelSolved_SaveScore)
+  {
+    FadeOut(REDRAW_FIELD);
+
+    game_status = GAME_MODE_MAIN;
+
+    DrawAndFadeInMainMenu(REDRAW_FIELD);
+
+    return;
+  }
+
+  if (level_nr == leveldir_current->handicap_level)
+  {
+    leveldir_current->handicap_level++;
+    SaveLevelSetup_SeriesInfo();
+  }
+
+  if (level_editor_test_game)
+    local_player->score = -1;  /* no highscore when playing from editor */
+  else if (level_nr < leveldir_current->last_level)
+    raise_level = TRUE;                /* advance to next level */
+
+  if ((hi_pos = NewHiScore()) >= 0) 
+  {
+    game_status = GAME_MODE_SCORES;
+
+    DrawHallOfFame(hi_pos);
+
+    if (raise_level)
+    {
+      level_nr++;
+      TapeErase();
+    }
+  }
+  else
+  {
+    FadeOut(REDRAW_FIELD);
+
+    game_status = GAME_MODE_MAIN;
+
+    if (raise_level)
+    {
+      level_nr++;
+      TapeErase();
+    }
+
+    DrawAndFadeInMainMenu(REDRAW_FIELD);
+  }
+
+  local_player->LevelSolved_SaveScore = FALSE;
+}
+
+#else
+
 void GameWon()
 {
   int hi_pos;
@@ -2862,13 +2932,6 @@ void GameWon()
 
   BackToFront();
 
-#if 0
-  if (tape.playing)
-    printf("::: TAPE PLAYING -> DO NOT SAVE SCORE\n");
-  else
-    printf("::: NO TAPE PLAYING -> SAVING SCORE\n");
-#endif
-
   if (tape.playing)
     return;
 
@@ -2915,6 +2978,8 @@ void GameWon()
   BackToFront();
 }
 
+#endif
+
 int NewHiScore()
 {
   int k, l;
@@ -2988,19 +3053,11 @@ inline static int getElementMoveStepsize(int x, int y)
   /* special values for move stepsize for spring and things on conveyor belt */
   if (horiz_move)
   {
-#if 0
-    if (element == EL_SPRING)
-      step = sign * MOVE_STEPSIZE_NORMAL * 2;
-    else if (CAN_FALL(element) && !CAN_MOVE(element) &&
-            y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1]))
-      step = sign * MOVE_STEPSIZE_NORMAL / 2;
-#else
     if (CAN_FALL(element) &&
        y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1]))
       step = sign * MOVE_STEPSIZE_NORMAL / 2;
     else if (element == EL_SPRING)
       step = sign * MOVE_STEPSIZE_NORMAL * 2;
-#endif
   }
 
   return step;
@@ -3035,6 +3092,8 @@ static void ResetGfxFrame(int x, int y, boolean redraw)
     GfxFrame[x][y] = CustomValue[x][y];
   else if (ANIM_MODE(graphic) == ANIM_CE_SCORE)
     GfxFrame[x][y] = element_info[element].collect_score;
+  else if (ANIM_MODE(graphic) == ANIM_CE_DELAY)
+    GfxFrame[x][y] = ChangeDelay[x][y];
 
   if (redraw && GfxFrame[x][y] != last_gfx_frame)
     DrawLevelGraphicAnimation(x, y, graphic);
@@ -3043,26 +3102,10 @@ static void ResetGfxFrame(int x, int y, boolean redraw)
 
 static void ResetGfxAnimation(int x, int y)
 {
-#if 0
-  int element, graphic;
-#endif
-
   GfxAction[x][y] = ACTION_DEFAULT;
   GfxDir[x][y] = MovDir[x][y];
   GfxFrame[x][y] = 0;
 
-#if 0
-  element = Feld[x][y];
-  graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
-
-  if (graphic_info[graphic].anim_global_sync)
-    GfxFrame[x][y] = FrameCounter;
-  else if (ANIM_MODE(graphic) == ANIM_CE_VALUE)
-    GfxFrame[x][y] = CustomValue[x][y];
-  else if (ANIM_MODE(graphic) == ANIM_CE_SCORE)
-    GfxFrame[x][y] = element_info[element].collect_score;
-#endif
-
 #if USE_GFX_RESET_GFX_ANIMATION
   ResetGfxFrame(x, y, FALSE);
 #endif
@@ -3076,9 +3119,6 @@ static void ResetRandomAnimationValue(int x, int y)
 void InitMovingField(int x, int y, int direction)
 {
   int element = Feld[x][y];
-#if 0
-  int graphic;
-#endif
   int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0);
   int dy = (direction == MV_UP   ? -1 : direction == MV_DOWN  ? +1 : 0);
   int newx = x + dx;
@@ -3092,17 +3132,6 @@ void InitMovingField(int x, int y, int direction)
   GfxAction[x][y] = (direction == MV_DOWN && CAN_FALL(element) ?
                     ACTION_FALLING : ACTION_MOVING);
 
-#if 0
-  graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
-
-  if (graphic_info[graphic].anim_global_sync)
-    GfxFrame[x][y] = FrameCounter;
-  else if (ANIM_MODE(graphic) == ANIM_CE_VALUE)
-    GfxFrame[x][y] = CustomValue[x][y];
-  else if (ANIM_MODE(graphic) == ANIM_CE_SCORE)
-    GfxFrame[x][y] = element_info[element].collect_score;
-#endif
-
   /* this is needed for CEs with property "can move" / "not moving" */
 
   if (getElementMoveStepsize(x, y) != 0)       /* moving or being moved */
@@ -3126,13 +3155,8 @@ void InitMovingField(int x, int y, int direction)
 void Moving2Blocked(int x, int y, int *goes_to_x, int *goes_to_y)
 {
   int direction = MovDir[x][y];
-#if 1
   int newx = x + (direction & MV_LEFT ? -1 : direction & MV_RIGHT ? +1 : 0);
   int newy = y + (direction & MV_UP   ? -1 : direction & MV_DOWN  ? +1 : 0);
-#else
-  int newx = x + (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0);
-  int newy = y + (direction == MV_UP   ? -1 : direction == MV_DOWN  ? +1 : 0);
-#endif
 
   *goes_to_x = newx;
   *goes_to_y = newy;
@@ -3319,8 +3343,6 @@ void CheckDynamite(int x, int y)
   Bang(x, y);
 }
 
-#if 1
-
 static void setMinimalPlayerBoundaries(int *sx1, int *sy1, int *sx2, int *sy2)
 {
   boolean num_checked_players = 0;
@@ -3371,33 +3393,6 @@ static void setScreenCenteredToAllPlayers(int *sx, int *sy)
   *sy = (sy1 + sy2) / 2;
 }
 
-#if 0
-static void setMaxCenterDistanceForAllPlayers(int *max_dx, int *max_dy,
-                                             int center_x, int center_y)
-{
-  int sx1 = center_x, sy1 = center_y, sx2 = center_x, sy2 = center_y;
-
-  setMinimalPlayerBoundaries(&sx1, &sy1, &sx2, &sy2);
-
-  *max_dx = MAX(ABS(sx1 - center_x), ABS(sx2 - center_x));
-  *max_dy = MAX(ABS(sy1 - center_y), ABS(sy2 - center_y));
-}
-
-static boolean checkIfAllPlayersAreVisible(int center_x, int center_y)
-{
-  int max_dx, max_dy;
-
-  setMaxCenterDistanceForAllPlayers(&max_dx, &max_dy, center_x, center_y);
-
-  return (max_dx <= SCR_FIELDX / 2 &&
-         max_dy <= SCR_FIELDY / 2);
-}
-#endif
-
-#endif
-
-#if 1
-
 void DrawRelocateScreen(int x, int y, int move_dir, boolean center_screen,
                        boolean quick_relocation)
 {
@@ -3410,11 +3405,6 @@ void DrawRelocateScreen(int x, int y, int move_dir, boolean center_screen,
   {
     int offset = (setup.scroll_delay ? 3 : 0);
 
-#if 0
-    if (center_screen)
-      offset = 0;
-#endif
-
     if (!IN_VIS_FIELD(SCREENX(x), SCREENY(y)) || center_screen)
     {
       scroll_x = (x < SBX_Left  + MIDPOSX ? SBX_Left :
@@ -3494,102 +3484,6 @@ void DrawRelocateScreen(int x, int y, int move_dir, boolean center_screen,
   }
 }
 
-#else
-
-void DrawRelocatePlayer(struct PlayerInfo *player, boolean quick_relocation)
-{
-  boolean ffwd_delay = (tape.playing && tape.fast_forward);
-  boolean no_delay = (tape.warp_forward);
-  int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
-  int wait_delay_value = (no_delay ? 0 : frame_delay_value);
-  int jx = player->jx;
-  int jy = player->jy;
-
-  if (quick_relocation)
-  {
-    int offset = (setup.scroll_delay ? 3 : 0);
-
-    if (!IN_VIS_FIELD(SCREENX(jx), SCREENY(jy)))
-    {
-      scroll_x = (player->jx < SBX_Left  + MIDPOSX ? SBX_Left :
-                 player->jx > SBX_Right + MIDPOSX ? SBX_Right :
-                 player->jx - MIDPOSX);
-
-      scroll_y = (player->jy < SBY_Upper + MIDPOSY ? SBY_Upper :
-                 player->jy > SBY_Lower + MIDPOSY ? SBY_Lower :
-                 player->jy - MIDPOSY);
-    }
-    else
-    {
-      if ((player->MovDir == MV_LEFT  && scroll_x > jx - MIDPOSX + offset) ||
-         (player->MovDir == MV_RIGHT && scroll_x < jx - MIDPOSX - offset))
-       scroll_x = jx - MIDPOSX + (scroll_x < jx-MIDPOSX ? -offset : +offset);
-
-      if ((player->MovDir == MV_UP  && scroll_y > jy - MIDPOSY + offset) ||
-         (player->MovDir == MV_DOWN && scroll_y < jy - MIDPOSY - offset))
-       scroll_y = jy - MIDPOSY + (scroll_y < jy-MIDPOSY ? -offset : +offset);
-
-      /* don't scroll over playfield boundaries */
-      if (scroll_x < SBX_Left || scroll_x > SBX_Right)
-       scroll_x = (scroll_x < SBX_Left ? SBX_Left : SBX_Right);
-
-      /* don't scroll over playfield boundaries */
-      if (scroll_y < SBY_Upper || scroll_y > SBY_Lower)
-       scroll_y = (scroll_y < SBY_Upper ? SBY_Upper : SBY_Lower);
-    }
-
-    RedrawPlayfield(TRUE, 0,0,0,0);
-  }
-  else
-  {
-    int scroll_xx = (player->jx < SBX_Left  + MIDPOSX ? SBX_Left :
-                    player->jx > SBX_Right + MIDPOSX ? SBX_Right :
-                    player->jx - MIDPOSX);
-
-    int scroll_yy = (player->jy < SBY_Upper + MIDPOSY ? SBY_Upper :
-                    player->jy > SBY_Lower + MIDPOSY ? SBY_Lower :
-                    player->jy - MIDPOSY);
-
-    ScrollScreen(NULL, SCROLL_GO_ON);  /* scroll last frame to full tile */
-
-    while (scroll_x != scroll_xx || scroll_y != scroll_yy)
-    {
-      int dx = 0, dy = 0;
-      int fx = FX, fy = FY;
-
-      dx = (scroll_xx < scroll_x ? +1 : scroll_xx > scroll_x ? -1 : 0);
-      dy = (scroll_yy < scroll_y ? +1 : scroll_yy > scroll_y ? -1 : 0);
-
-      if (dx == 0 && dy == 0)          /* no scrolling needed at all */
-       break;
-
-      scroll_x -= dx;
-      scroll_y -= dy;
-
-      fx += dx * TILEX / 2;
-      fy += dy * TILEY / 2;
-
-      ScrollLevel(dx, dy);
-      DrawAllPlayers();
-
-      /* scroll in two steps of half tile size to make things smoother */
-      BlitBitmap(drawto_field, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
-      FlushDisplay();
-      Delay(wait_delay_value);
-
-      /* scroll second step to align at full tile size */
-      BackToFront();
-      Delay(wait_delay_value);
-    }
-
-    DrawPlayer(player);
-    BackToFront();
-    Delay(wait_delay_value);
-  }
-}
-
-#endif
-
 void RelocatePlayer(int jx, int jy, int el_player_raw)
 {
   int el_player = GET_PLAYER_ELEMENT(el_player_raw);
@@ -3665,19 +3559,9 @@ void RelocatePlayer(int jx, int jy, int el_player_raw)
     InitField(jx, jy, FALSE);
   }
 
-#if 1
   /* only visually relocate centered player */
-#if 1
   DrawRelocateScreen(player->jx, player->jy, player->MovDir, FALSE,
                     level.instant_relocation);
-#else
-  if (player->index_nr == game.centered_player_nr)
-    DrawRelocatePlayer(player, level.instant_relocation);
-#endif
-#else
-  if (player == local_player)  /* only visually relocate local player */
-    DrawRelocatePlayer(player, level.instant_relocation);
-#endif
 
   TestIfPlayerTouchesBadThing(jx, jy);
   TestIfPlayerTouchesCustomElement(jx, jy);
@@ -3763,11 +3647,7 @@ void Explode(int ex, int ey, int phase, int mode)
       PlayLevelSoundElementAction(ex, ey, artwork_element, ACTION_EXPLODING);
 #endif
 
-#if 1
     last_phase = element_info[explosion_element].explosion_delay + 1;
-#else
-    last_phase = element_info[center_element].explosion_delay + 1;
-#endif
 
     for (y = ey - 1; y <= ey + 1; y++) for (x = ex - 1; x <= ex + 1; x++)
     {
@@ -3840,33 +3720,14 @@ void Explode(int ex, int ey, int phase, int mode)
 
       if (IS_PLAYER(ex, ey) && !PLAYER_EXPLOSION_PROTECTED(ex, ey))
       {
-#if 1
        int player_nr = StorePlayer[ex][ey] - EL_PLAYER_1;
 
        Store[x][y] = EL_PLAYER_IS_EXPLODING_1 + player_nr;
-#else
-       switch(StorePlayer[ex][ey])
-       {
-         case EL_PLAYER_2:
-           Store[x][y] = EL_PLAYER_IS_EXPLODING_2;
-           break;
-         case EL_PLAYER_3:
-           Store[x][y] = EL_PLAYER_IS_EXPLODING_3;
-           break;
-         case EL_PLAYER_4:
-           Store[x][y] = EL_PLAYER_IS_EXPLODING_4;
-           break;
-         case EL_PLAYER_1:
-         default:
-           Store[x][y] = EL_PLAYER_IS_EXPLODING_1;
-           break;
-       }
-#endif
 
        if (PLAYERINFO(ex, ey)->use_murphy)
          Store[x][y] = EL_EMPTY;
       }
-#if 1
+
       /* !!! check this case -- currently needed for rnd_rado_negundo_v,
         !!! levels 015 018 019 020 021 022 023 026 027 028 !!! */
       else if (ELEM_IS_PLAYER(center_element))
@@ -3887,45 +3748,6 @@ void Explode(int ex, int ey, int phase, int mode)
 #endif
       else
        Store[x][y] = EL_EMPTY;
-#else
-      else if (center_element == EL_MOLE)
-       Store[x][y] = EL_EMERALD_RED;
-      else if (center_element == EL_PENGUIN)
-       Store[x][y] = EL_EMERALD_PURPLE;
-      else if (center_element == EL_BUG)
-       Store[x][y] = ((x == ex && y == ey) ? EL_DIAMOND : EL_EMERALD);
-      else if (center_element == EL_BD_BUTTERFLY)
-       Store[x][y] = EL_BD_DIAMOND;
-      else if (center_element == EL_SP_ELECTRON)
-       Store[x][y] = EL_SP_INFOTRON;
-      else if (center_element == EL_AMOEBA_TO_DIAMOND)
-       Store[x][y] = level.amoeba_content;
-      else if (center_element == EL_YAMYAM)
-       Store[x][y] = level.yamyam_content[game.yamyam_content_nr].e[xx][yy];
-      else if (IS_CUSTOM_ELEMENT(center_element) &&
-              element_info[center_element].content.e[xx][yy] != EL_EMPTY)
-       Store[x][y] = element_info[center_element].content.e[xx][yy];
-      else if (element == EL_WALL_EMERALD)
-       Store[x][y] = EL_EMERALD;
-      else if (element == EL_WALL_DIAMOND)
-       Store[x][y] = EL_DIAMOND;
-      else if (element == EL_WALL_BD_DIAMOND)
-       Store[x][y] = EL_BD_DIAMOND;
-      else if (element == EL_WALL_EMERALD_YELLOW)
-       Store[x][y] = EL_EMERALD_YELLOW;
-      else if (element == EL_WALL_EMERALD_RED)
-       Store[x][y] = EL_EMERALD_RED;
-      else if (element == EL_WALL_EMERALD_PURPLE)
-       Store[x][y] = EL_EMERALD_PURPLE;
-      else if (element == EL_WALL_PEARL)
-       Store[x][y] = EL_PEARL;
-      else if (element == EL_WALL_CRYSTAL)
-       Store[x][y] = EL_CRYSTAL;
-      else if (IS_CUSTOM_ELEMENT(element) && !CAN_EXPLODE(element))
-       Store[x][y] = element_info[element].content.e[1][1];
-      else
-       Store[x][y] = EL_EMPTY;
-#endif
 
       if (x != ex || y != ey || mode == EX_TYPE_BORDER ||
          center_element == EL_AMOEBA_TO_DIAMOND)
@@ -3934,11 +3756,6 @@ void Explode(int ex, int ey, int phase, int mode)
       Feld[x][y] = EL_EXPLOSION;
       GfxElement[x][y] = artwork_element;
 
-#if 0
-      printf(":: setting gfx(%d,%d) to %d ['%s']\n",
-            x, y, artwork_element, EL_NAME(artwork_element));
-#endif
-
       ExplodePhase[x][y] = 1;
       ExplodeDelay[x][y] = last_phase;
 
@@ -4276,11 +4093,7 @@ static void InitBeltMovement()
     }
   }
 
-#if 1
   SCAN_PLAYFIELD(x, y)
-#else
-  for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
   {
     int element = Feld[x][y];
 
@@ -4360,11 +4173,7 @@ static void ToggleBeltSwitch(int x, int y)
       graphic_info[graphic].anim_mode |=  ANIM_REVERSE;
   }
 
-#if 1
   SCAN_PLAYFIELD(xx, yy)
-#else
-  for (yy = 0; yy < lev_fieldy; yy++) for (xx = 0; xx < lev_fieldx; xx++)
-#endif
   {
     int element = Feld[xx][yy];
 
@@ -4411,20 +4220,29 @@ static void ToggleSwitchgateSwitch(int x, int y)
 
   game.switchgate_pos = !game.switchgate_pos;
 
-#if 1
   SCAN_PLAYFIELD(xx, yy)
-#else
-  for (yy = 0; yy < lev_fieldy; yy++) for (xx = 0; xx < lev_fieldx; xx++)
-#endif
   {
     int element = Feld[xx][yy];
 
+#if !USE_BOTH_SWITCHGATE_SWITCHES
     if (element == EL_SWITCHGATE_SWITCH_UP ||
        element == EL_SWITCHGATE_SWITCH_DOWN)
     {
       Feld[xx][yy] = EL_SWITCHGATE_SWITCH_UP + game.switchgate_pos;
       DrawLevelField(xx, yy);
     }
+#else
+    if (element == EL_SWITCHGATE_SWITCH_UP)
+    {
+      Feld[xx][yy] = EL_SWITCHGATE_SWITCH_DOWN;
+      DrawLevelField(xx, yy);
+    }
+    else if (element == EL_SWITCHGATE_SWITCH_DOWN)
+    {
+      Feld[xx][yy] = EL_SWITCHGATE_SWITCH_UP;
+      DrawLevelField(xx, yy);
+    }
+#endif
     else if (element == EL_SWITCHGATE_OPEN ||
             element == EL_SWITCHGATE_OPENING)
     {
@@ -4462,11 +4280,7 @@ static void RedrawAllLightSwitchesAndInvisibleElements()
 {
   int x, y;
 
-#if 1
   SCAN_PLAYFIELD(x, y)
-#else
-  for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
   {
     int element = Feld[x][y];
 
@@ -4527,11 +4341,7 @@ static void RedrawAllInvisibleElementsForLenses()
 {
   int x, y;
 
-#if 1
   SCAN_PLAYFIELD(x, y)
-#else
-  for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
   {
     int element = Feld[x][y];
 
@@ -4580,11 +4390,7 @@ static void RedrawAllInvisibleElementsForMagnifier()
 {
   int x, y;
 
-#if 1
   SCAN_PLAYFIELD(x, y)
-#else
-  for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
   {
     int element = Feld[x][y];
 
@@ -4644,11 +4450,7 @@ static void ActivateTimegateSwitch(int x, int y)
 
   game.timegate_time_left = level.time_timegate * FRAMES_PER_SECOND;
 
-#if 1
   SCAN_PLAYFIELD(xx, yy)
-#else
-  for (yy = 0; yy < lev_fieldy; yy++) for (xx = 0; xx < lev_fieldx; xx++)
-#endif
   {
     int element = Feld[xx][yy];
 
@@ -4775,11 +4577,7 @@ void Impact(int x, int y)
         EL_BD_MAGIC_WALL_ACTIVE);
 
       /* activate magic wall / mill */
-#if 1
       SCAN_PLAYFIELD(xx, yy)
-#else
-      for (yy = 0; yy < lev_fieldy; yy++) for (xx = 0; xx < lev_fieldx; xx++)
-#endif
        if (Feld[xx][yy] == smashed)
          Feld[xx][yy] = activated_magic_wall;
 
@@ -5730,9 +5528,6 @@ inline static void TurnRoundExt(int x, int y)
 static void TurnRound(int x, int y)
 {
   int direction = MovDir[x][y];
-#if 0
-  int element, graphic;
-#endif
 
   TurnRoundExt(x, y);
 
@@ -5744,19 +5539,7 @@ static void TurnRound(int x, int y)
   if (MovDelay[x][y])
     GfxAction[x][y] = ACTION_TURNING_FROM_LEFT + MV_DIR_TO_BIT(direction);
 
-#if 1
   ResetGfxFrame(x, y, FALSE);
-#else
-  element = Feld[x][y];
-  graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
-
-  if (graphic_info[graphic].anim_global_sync)
-    GfxFrame[x][y] = FrameCounter;
-  else if (ANIM_MODE(graphic) == ANIM_CE_VALUE)
-    GfxFrame[x][y] = CustomValue[x][y];
-  else if (ANIM_MODE(graphic) == ANIM_CE_SCORE)
-    GfxFrame[x][y] = element_info[element].collect_score;
-#endif
 }
 
 static boolean JustBeingPushed(int x, int y)
@@ -5806,7 +5589,12 @@ void StartMoving(int x, int y)
        started_moving = TRUE;
 
        Feld[x][y] = EL_QUICKSAND_EMPTYING;
+#if USE_QUICKSAND_BD_ROCK_BUGFIX
+       if (Store[x][y] != EL_ROCK && Store[x][y] != EL_BD_ROCK)
+         Store[x][y] = EL_ROCK;
+#else
        Store[x][y] = EL_ROCK;
+#endif
 
        PlayLevelSoundAction(x, y, ACTION_EMPTYING);
       }
@@ -6772,29 +6560,17 @@ void ContinueMoving(int x, int y)
 
   MovDelay[newx][newy] = 0;
 
-#if 1
   if (CAN_CHANGE_OR_HAS_ACTION(element))
-#else
-  if (CAN_CHANGE(element))
-#endif
   {
     /* copy element change control values to new field */
     ChangeDelay[newx][newy] = ChangeDelay[x][y];
     ChangePage[newx][newy]  = ChangePage[x][y];
     ChangeCount[newx][newy] = ChangeCount[x][y];
     ChangeEvent[newx][newy] = ChangeEvent[x][y];
-
-#if 0
-#if USE_NEW_CUSTOM_VALUE
-    CustomValue[newx][newy] = CustomValue[x][y];
-#endif
-#endif
   }
 
-#if 1
 #if USE_NEW_CUSTOM_VALUE
     CustomValue[newx][newy] = CustomValue[x][y];
-#endif
 #endif
 
   ChangeDelay[x][y] = 0;
@@ -6960,12 +6736,10 @@ void ContinueMoving(int x, int y)
   TestIfPlayerTouchesCustomElement(newx, newy);
   TestIfElementTouchesCustomElement(newx, newy);
 
-#if 1
   if (IS_CUSTOM_ELEMENT(element) && ei->move_enter_element != EL_EMPTY &&
       IS_EQUAL_OR_IN_GROUP(stored_new, ei->move_enter_element))
     CheckElementChangeBySide(newx, newy, element, stored_new, CE_DIGGING_X,
                                      MV_DIR_OPPOSITE(direction));
-#endif
 }
 
 int AmoebeNachbarNr(int ax, int ay)
@@ -7034,11 +6808,7 @@ void AmoebenVereinigen(int ax, int ay)
       AmoebaCnt2[new_group_nr] += AmoebaCnt2[old_group_nr];
       AmoebaCnt2[old_group_nr] = 0;
 
-#if 1
       SCAN_PLAYFIELD(xx, yy)
-#else
-      for (yy = 0; yy < lev_fieldy; yy++) for (xx = 0; xx < lev_fieldx; xx++)
-#endif
       {
        if (AmoebaNr[xx][yy] == old_group_nr)
          AmoebaNr[xx][yy] = new_group_nr;
@@ -7064,11 +6834,7 @@ void AmoebeUmwandeln(int ax, int ay)
     }
 #endif
 
-#if 1
     SCAN_PLAYFIELD(x, y)
-#else
-    for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
     {
       if (Feld[x][y] == EL_AMOEBA_DEAD && AmoebaNr[x][y] == group_nr)
       {
@@ -7126,11 +6892,7 @@ void AmoebeUmwandelnBD(int ax, int ay, int new_element)
   }
 #endif
 
-#if 1
   SCAN_PLAYFIELD(x, y)
-#else
-  for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
   {
     if (AmoebaNr[x][y] == group_nr &&
        (Feld[x][y] == EL_AMOEBA_DEAD ||
@@ -7379,9 +7141,6 @@ void AmoebeAbleger(int ax, int ay)
 void Life(int ax, int ay)
 {
   int x1, y1, x2, y2;
-#if 0
-  static int life[4] = { 2, 3, 3, 3 }; /* parameters for "game of life" */
-#endif
   int life_time = 40;
   int element = Feld[ax][ay];
   int graphic = el2img(element);
@@ -7526,13 +7285,6 @@ static void ActivateMagicBall(int bx, int by)
   game.ball_content_nr = (game.ball_content_nr + 1) % level.num_ball_contents;
 }
 
-static void InitDiagonalMovingElement(int x, int y)
-{
-#if 0
-  MovDelay[x][y] = level.android_move_time;
-#endif
-}
-
 void CheckExit(int x, int y)
 {
   if (local_player->gems_still_needed > 0 ||
@@ -7581,11 +7333,7 @@ static void CloseAllOpenTimegates()
 {
   int x, y;
 
-#if 1
   SCAN_PLAYFIELD(x, y)
-#else
-  for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
   {
     int element = Feld[x][y];
 
@@ -7749,7 +7497,8 @@ void MauerAbleger(int ax, int ay)
 
   if (element == EL_EXPANDABLE_WALL_HORIZONTAL ||
       element == EL_EXPANDABLE_WALL_ANY ||
-      element == EL_EXPANDABLE_WALL)
+      element == EL_EXPANDABLE_WALL ||
+      element == EL_BD_EXPANDABLE_WALL)
   {
     if (links_frei)
     {
@@ -7975,11 +7724,11 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
      CA_ARG_MAX);
 
   int action_arg_number_reset =
-    (action_type == CA_SET_PLAYER_SPEED ? level.initial_player_stepsize :
+    (action_type == CA_SET_PLAYER_SPEED ? level.initial_player_stepsize[0] :
      action_type == CA_SET_LEVEL_GEMS ? level.gems_needed :
      action_type == CA_SET_LEVEL_TIME ? level.time :
      action_type == CA_SET_LEVEL_SCORE ? 0 :
-#if 1
+#if USE_NEW_CUSTOM_VALUE
      action_type == CA_SET_CE_VALUE ? GET_NEW_CE_VALUE(element) :
 #else
      action_type == CA_SET_CE_VALUE ? ei->custom_value_initial :
@@ -8101,6 +7850,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
       break;
     }
 
+#if !USE_PLAYER_GRAVITY
     case CA_SET_LEVEL_GRAVITY:
     {
       game.gravity = (action_arg == CA_ARG_GRAVITY_OFF    ? FALSE         :
@@ -8109,6 +7859,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
                      game.gravity);
       break;
     }
+#endif
 
     case CA_SET_LEVEL_WIND:
     {
@@ -8161,13 +7912,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
          {
            stored_player[i].key[KEY_NR(element)] = key_state;
 
-#if 1
            DrawGameDoorValues();
-#else
-           DrawGameValue_Keys(stored_player[i].key);
-#endif
-
-           redraw_mask |= REDRAW_DOOR_1;
          }
        }
       }
@@ -8195,6 +7940,10 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
            action_mode = (action_arg == CA_ARG_SPEED_SLOWER ? CA_MODE_DIVIDE :
                           CA_MODE_MULTIPLY);
          }
+         else if (action_arg == CA_ARG_NUMBER_RESET)
+         {
+           action_arg_number = level.initial_player_stepsize[i];
+         }
 
          move_stepsize =
            getModifiedActionNumber(move_stepsize,
@@ -8203,18 +7952,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
                                    action_arg_number_min,
                                    action_arg_number_max);
 
-#if 1
          SetPlayerMoveSpeed(&stored_player[i], move_stepsize, FALSE);
-#else
-         /* make sure that value is power of 2 */
-         move_stepsize = (1 << log_2(move_stepsize));
-
-         /* do no immediately change -- the player might just be moving */
-         stored_player[i].move_delay_value_next = TILEX / move_stepsize;
-
-         stored_player[i].cannot_move =
-           (action_arg == CA_ARG_SPEED_NOT_MOVING ? TRUE : FALSE);
-#endif
        }
       }
 
@@ -8247,6 +7985,25 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
       break;
     }
 
+#if USE_PLAYER_GRAVITY
+    case CA_SET_PLAYER_GRAVITY:
+    {
+      for (i = 0; i < MAX_PLAYERS; i++)
+      {
+       if (trigger_player_bits & (1 << i))
+       {
+         stored_player[i].gravity =
+           (action_arg == CA_ARG_GRAVITY_OFF    ? FALSE                     :
+            action_arg == CA_ARG_GRAVITY_ON     ? TRUE                      :
+            action_arg == CA_ARG_GRAVITY_TOGGLE ? !stored_player[i].gravity :
+            stored_player[i].gravity);
+       }
+      }
+
+      break;
+    }
+#endif
+
     case CA_SET_PLAYER_ARTWORK:
     {
       for (i = 0; i < MAX_PLAYERS; i++)
@@ -8286,22 +8043,16 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
 
       CustomValue[x][y] = action_arg_number_new;
 
-#if 0
-      printf("::: CE value == %d\n", CustomValue[x][y]);
-#endif
-
-      if (CustomValue[x][y] == 0 && last_ce_value > 0)
+      if (CustomValue[x][y] != last_ce_value)
       {
-#if 0
-       printf("::: CE_VALUE_GETS_ZERO\n");
-#endif
-
-       CheckElementChange(x, y, element, EL_UNDEFINED, CE_VALUE_GETS_ZERO);
-       CheckTriggeredElementChange(x, y, element, CE_VALUE_GETS_ZERO_OF_X);
+       CheckElementChange(x, y, element, EL_UNDEFINED, CE_VALUE_CHANGES);
+       CheckTriggeredElementChange(x, y, element, CE_VALUE_CHANGES_OF_X);
 
-#if 0
-       printf("::: RESULT: %d, %d\n", Feld[x][y], ChangePage[x][y]);
-#endif
+       if (CustomValue[x][y] == 0)
+       {
+         CheckElementChange(x, y, element, EL_UNDEFINED, CE_VALUE_GETS_ZERO);
+         CheckTriggeredElementChange(x, y, element, CE_VALUE_GETS_ZERO_OF_X);
+       }
       }
 #endif
 
@@ -8315,22 +8066,36 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
 
       ei->collect_score = action_arg_number_new;
 
-#if 0
-      printf("::: CE score == %d\n", ei->collect_score);
-#endif
-
-      if (ei->collect_score == 0 && last_ce_score > 0)
+      if (ei->collect_score != last_ce_score)
       {
-#if 0
-       printf("::: CE_SCORE_GETS_ZERO\n");
-#endif
-
-       CheckElementChange(x, y, element, EL_UNDEFINED, CE_SCORE_GETS_ZERO);
-       CheckTriggeredElementChange(x, y, element, CE_SCORE_GETS_ZERO_OF_X);
+       CheckElementChange(x, y, element, EL_UNDEFINED, CE_SCORE_CHANGES);
+       CheckTriggeredElementChange(x, y, element, CE_SCORE_CHANGES_OF_X);
 
-#if 0
-       printf("::: RESULT: %d, %d\n", Feld[x][y], ChangePage[x][y]);
-#endif
+       if (ei->collect_score == 0)
+       {
+         int xx, yy;
+
+         CheckElementChange(x, y, element, EL_UNDEFINED, CE_SCORE_GETS_ZERO);
+         CheckTriggeredElementChange(x, y, element, CE_SCORE_GETS_ZERO_OF_X);
+
+         /*
+           This is a very special case that seems to be a mixture between
+           CheckElementChange() and CheckTriggeredElementChange(): while
+           the first one only affects single elements that are triggered
+           directly, the second one affects multiple elements in the playfield
+           that are triggered indirectly by another element. This is a third
+           case: Changing the CE score always affects multiple identical CEs,
+           so every affected CE must be checked, not only the single CE for
+           which the CE score was changed in the first place (as every instance
+           of that CE shares the same CE score, and therefore also can change)!
+         */
+         SCAN_PLAYFIELD(xx, yy)
+         {
+           if (Feld[xx][yy] == element)
+             CheckElementChange(xx, yy, element, EL_UNDEFINED,
+                                CE_SCORE_GETS_ZERO);
+         }
+       }
       }
 #endif
 
@@ -8359,11 +8124,18 @@ static void CreateFieldExt(int x, int y, int element, boolean is_change)
 #if USE_NEW_CUSTOM_VALUE
   int last_ce_value = CustomValue[x][y];
 #endif
-  boolean add_player = (ELEM_IS_PLAYER(new_element) &&
-                       IS_WALKABLE(old_element));
+  boolean new_element_is_player = ELEM_IS_PLAYER(new_element);
+  boolean add_player_onto_element = (new_element_is_player &&
+#if USE_CODE_THAT_BREAKS_SNAKE_BITE
+                                    /* this breaks SnakeBite when a snake is
+                                       halfway through a door that closes */
+                                    /* NOW FIXED AT LEVEL INIT IN files.c */
+                                    new_element != EL_SOKOBAN_FIELD_PLAYER &&
+#endif
+                                    IS_WALKABLE(old_element));
 
 #if 0
-  /* check if element under player changes from accessible to unaccessible
+  /* check if element under the player changes from accessible to unaccessible
      (needed for special case of dropping element which then changes) */
   if (IS_PLAYER(x, y) && !PLAYER_EXPLOSION_PROTECTED(x, y) &&
       IS_ACCESSIBLE(old_element) && !IS_ACCESSIBLE(new_element))
@@ -8374,7 +8146,7 @@ static void CreateFieldExt(int x, int y, int element, boolean is_change)
   }
 #endif
 
-  if (!add_player)
+  if (!add_player_onto_element)
   {
     if (IS_MOVING(x, y) || IS_BLOCKED(x, y))
       RemoveMovingField(x, y);
@@ -8412,8 +8184,9 @@ static void CreateFieldExt(int x, int y, int element, boolean is_change)
   }
 
 #if 1
-  /* check if element under player changes from accessible to unaccessible
+  /* check if element under the player changes from accessible to unaccessible
      (needed for special case of dropping element which then changes) */
+  /* (must be checked after creating new element for walkable group elements) */
   if (IS_PLAYER(x, y) && !PLAYER_EXPLOSION_PROTECTED(x, y) &&
       IS_ACCESSIBLE(old_element) && !IS_ACCESSIBLE(new_element))
   {
@@ -8424,7 +8197,7 @@ static void CreateFieldExt(int x, int y, int element, boolean is_change)
 #endif
 
   /* "ChangeCount" not set yet to allow "entered by player" change one time */
-  if (ELEM_IS_PLAYER(new_element))
+  if (new_element_is_player)
     RelocatePlayer(x, y, new_element);
 
   if (is_change)
@@ -8585,7 +8358,7 @@ static boolean ChangeElement(int x, int y, int element, int page)
          ChangeEvent[ex][ey] = ChangeEvent[x][y];
 
          content_element = change->target_content.e[xx][yy];
-         target_element = GET_TARGET_ELEMENT(content_element, change,
+         target_element = GET_TARGET_ELEMENT(element, content_element, change,
                                              ce_value, ce_score);
 
          CreateElementFromChange(ex, ey, target_element);
@@ -8607,7 +8380,7 @@ static boolean ChangeElement(int x, int y, int element, int page)
   }
   else
   {
-    target_element = GET_TARGET_ELEMENT(change->target_element, change,
+    target_element = GET_TARGET_ELEMENT(element, change->target_element, change,
                                        ce_value, ce_score);
 
     if (element == EL_DIAGONAL_GROWING ||
@@ -8848,11 +8621,7 @@ static boolean CheckTriggeredElementChangeExt(int trigger_x, int trigger_y,
        {
          int x, y;
 
-#if 1
          SCAN_PLAYFIELD(x, y)
-#else
-         for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
          {
            if (Feld[x][y] == element)
            {
@@ -9057,11 +8826,7 @@ static void SetPlayerWaiting(struct PlayerInfo *player, boolean is_waiting)
        game.player_sleeping_delay_fixed +
        SimpleRND(game.player_sleeping_delay_random);
 
-#if 1
       InitPlayerGfxAnimation(player, ACTION_WAITING, move_dir);
-#else
-      InitPlayerGfxAnimation(player, ACTION_WAITING, player->MovDir);
-#endif
     }
 
     if (game.player_sleeping_delay_fixed +
@@ -9079,7 +8844,6 @@ static void SetPlayerWaiting(struct PlayerInfo *player, boolean is_waiting)
                              player->is_bored ? ACTION_BORING :
                              ACTION_WAITING);
 
-#if 1
     if (player->is_sleeping && player->use_murphy)
     {
       /* special case for sleeping Murphy when leaning against non-free tile */
@@ -9097,7 +8861,6 @@ static void SetPlayerWaiting(struct PlayerInfo *player, boolean is_waiting)
 
       player->dir_waiting = move_dir;
     }
-#endif
 
     if (player->is_sleeping)
     {
@@ -9328,11 +9091,6 @@ void AdvanceFrameAndPlayerCounters(int player_nr)
 {
   int i;
 
-#if 0
-  Error(ERR_NETWORK_CLIENT, "advancing frame counter from %d to %d",
-       FrameCounter, FrameCounter + 1);
-#endif
-
   /* advance frame counters (global frame counter and time frame counter) */
   FrameCounter++;
   TimeFrames++;
@@ -9397,10 +9155,6 @@ void StartGameActions(boolean init_network_game, boolean record_tape,
   }
 #endif
 
-  StopAnimation();
-
-  game_status = GAME_MODE_PLAYING;
-
   InitGame();
 }
 
@@ -9476,12 +9230,17 @@ void GameActions()
 
   /* at this point we know that we really continue executing the game */
 
-#if 1
   network_player_action_received = FALSE;
-#endif
 
+  /* when playing tape, read previously recorded player input from tape data */
   recorded_player_action = (tape.playing ? TapePlayAction() : NULL);
 
+#if 1
+  /* TapePlayAction() may return NULL when toggling to "pause before death" */
+  if (tape.pausing)
+    return;
+#endif
+
   if (tape.set_centered_player)
   {
     game.centered_player_nr_next = tape.centered_player_nr_next;
@@ -9572,7 +9331,6 @@ void GameActions_RND()
   }
 #endif
 
-#if 1
   if (game.set_centered_player)
   {
     boolean all_players_fit_to_screen = checkIfAllPlayersFitToScreen_RND();
@@ -9614,7 +9372,6 @@ void GameActions_RND()
     DrawRelocateScreen(sx, sy, MV_NONE, TRUE, setup.quick_switch);
     DrawGameDoorValues();
   }
-#endif
 
   for (i = 0; i < MAX_PLAYERS; i++)
   {
@@ -9635,22 +9392,11 @@ void GameActions_RND()
     if (stored_player[i].programmed_action)
       actual_player_action = stored_player[i].programmed_action;
 
-#if 1
     PlayerActions(&stored_player[i], actual_player_action);
-#else
-    tape_action[i] = PlayerActions(&stored_player[i], actual_player_action);
-
-    if (tape.recording && tape_action[i] && !tape.player_participates[i])
-      tape.player_participates[i] = TRUE;    /* player just appeared from CE */
-#endif
 
     ScrollPlayer(&stored_player[i], SCROLL_GO_ON);
   }
 
-#if 0
-  network_player_action_received = FALSE;
-#endif
-
   ScrollScreen(NULL, SCROLL_GO_ON);
 
   /* for backwards compatibility, the following code emulates a fixed bug that
@@ -9685,11 +9431,7 @@ void GameActions_RND()
     }
   }
 
-#if 1
   SCAN_PLAYFIELD(x, y)
-#else
-  for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
   {
     ChangeCount[x][y] = 0;
     ChangeEvent[x][y] = -1;
@@ -9761,50 +9503,12 @@ void GameActions_RND()
 #endif
   }
 
-#if 1
   SCAN_PLAYFIELD(x, y)
-#else
-  for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
   {
     element = Feld[x][y];
     graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
 
-#if 0
-    printf("::: %d,%d\n", x, y);
-
-    if (element == EL_ROCK)
-      printf("::: Yo man! Rocks can fall!\n");
-#endif
-
-#if 1
     ResetGfxFrame(x, y, TRUE);
-#else
-    if (graphic_info[graphic].anim_global_sync)
-      GfxFrame[x][y] = FrameCounter;
-    else if (ANIM_MODE(graphic) == ANIM_CE_VALUE)
-    {
-      int old_gfx_frame = GfxFrame[x][y];
-
-      GfxFrame[x][y] = CustomValue[x][y];
-
-#if 1
-      if (GfxFrame[x][y] != old_gfx_frame)
-#endif
-       DrawLevelGraphicAnimation(x, y, graphic);
-    }
-    else if (ANIM_MODE(graphic) == ANIM_CE_SCORE)
-    {
-      int old_gfx_frame = GfxFrame[x][y];
-
-      GfxFrame[x][y] = element_info[element].collect_score;
-
-#if 1
-      if (GfxFrame[x][y] != old_gfx_frame)
-#endif
-       DrawLevelGraphicAnimation(x, y, graphic);
-    }
-#endif
 
     if (ANIM_MODE(graphic) == ANIM_RANDOM &&
        IS_NEXT_FRAME(GfxFrame[x][y], graphic))
@@ -9827,18 +9531,6 @@ void GameActions_RND()
        (game.engine_version < VERSION_IDENT(3,0,7,1) || !Stop[x][y]))
     {
       int page = element_info[element].event_page_nr[CE_DELAY];
-#if 0
-      HandleElementChange(x, y, ChangePage[x][y] != -1 ? ChangePage[x][y] : page);
-#else
-
-#if 0
-      printf("::: ChangeDelay == %d\n", ChangeDelay[x][y]);
-#endif
-
-#if 0
-      if (element == EL_CUSTOM_255)
-       printf("::: ChangeDelay == %d\n", ChangeDelay[x][y]);
-#endif
 
 #if 1
       HandleElementChange(x, y, page);
@@ -9848,8 +9540,6 @@ void GameActions_RND()
 
       if (HAS_ACTION(element))
        ExecuteCustomElementAction(x, y, element, page);
-#endif
-
 #endif
 
       element = Feld[x][y];
@@ -9906,7 +9596,8 @@ void GameActions_RND()
     else if (element == EL_EXPANDABLE_WALL ||
             element == EL_EXPANDABLE_WALL_HORIZONTAL ||
             element == EL_EXPANDABLE_WALL_VERTICAL ||
-            element == EL_EXPANDABLE_WALL_ANY)
+            element == EL_EXPANDABLE_WALL_ANY ||
+            element == EL_BD_EXPANDABLE_WALL)
       MauerAbleger(x, y);
     else if (element == EL_FLAMES)
       CheckForDragon(x, y);
@@ -9916,21 +9607,13 @@ void GameActions_RND()
             element == EL_DIAGONAL_SHRINKING ||
             element == EL_DIAGONAL_GROWING)
     {
-#if 1
       graphic = el_act_dir2img(GfxElement[x][y], GfxAction[x][y],GfxDir[x][y]);
 
       DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
-#endif
     }
     else if (IS_ANIMATED(graphic) && !IS_CHANGING(x, y))
       DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
 
-#if 0
-    if (element == EL_CUSTOM_255 ||
-       element == EL_CUSTOM_256)
-      DrawLevelGraphicAnimation(x, y, graphic);
-#endif
-
     if (IS_BELT_ACTIVE(element))
       PlayLevelSoundAction(x, y, ACTION_ACTIVE);
 
@@ -9990,11 +9673,7 @@ void GameActions_RND()
   {
     game.explosions_delayed = FALSE;
 
-#if 1
     SCAN_PLAYFIELD(x, y)
-#else
-    for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
     {
       element = Feld[x][y];
 
@@ -10028,11 +9707,7 @@ void GameActions_RND()
       game.magic_wall_time_left--;
       if (!game.magic_wall_time_left)
       {
-#if 1
        SCAN_PLAYFIELD(x, y)
-#else
-       for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
        {
          element = Feld[x][y];
 
@@ -10251,11 +9926,15 @@ static boolean canMoveToValidFieldWithGravity(int x, int y, int move_dir)
 
 static void CheckGravityMovement(struct PlayerInfo *player)
 {
+#if USE_PLAYER_GRAVITY
+  if (player->gravity && !player->programmed_action)
+#else
   if (game.gravity && !player->programmed_action)
+#endif
   {
     int move_dir_horizontal = player->effective_action & MV_HORIZONTAL;
     int move_dir_vertical   = player->effective_action & MV_VERTICAL;
-    boolean player_is_snapping = player->effective_action & JOY_BUTTON_1;
+    boolean player_is_snapping = (player->effective_action & JOY_BUTTON_1);
     int jx = player->jx, jy = player->jy;
     boolean player_is_moving_to_valid_field =
       (!player_is_snapping &&
@@ -10273,7 +9952,11 @@ static void CheckGravityMovementWhenNotMoving(struct PlayerInfo *player)
 {
   return CheckGravityMovement(player);
 
+#if USE_PLAYER_GRAVITY
+  if (player->gravity && !player->programmed_action)
+#else
   if (game.gravity && !player->programmed_action)
+#endif
   {
     int jx = player->jx, jy = player->jy;
     boolean field_under_player_is_free =
@@ -10319,7 +10002,6 @@ boolean MovePlayerOneStep(struct PlayerInfo *player,
 
   if (!player_can_move)
   {
-#if 1
     if (player->MovPos == 0)
     {
       player->is_moving = FALSE;
@@ -10328,14 +10010,6 @@ boolean MovePlayerOneStep(struct PlayerInfo *player,
       player->is_snapping = FALSE;
       player->is_pushing = FALSE;
     }
-#else
-    DigField(player, 0, 0, 0, 0, 0, 0, DF_NO_PUSH);
-    SnapField(player, 0, 0);
-#endif
-
-#if 0
-    return MP_NO_ACTION;
-#endif
   }
 
 #if 1
@@ -10370,18 +10044,9 @@ boolean MovePlayerOneStep(struct PlayerInfo *player,
 #endif
 
   can_move = DigField(player, jx, jy, new_jx, new_jy, real_dx,real_dy, DF_DIG);
-#if 0
-#if USE_FIXED_DONT_RUN_INTO
-  if (can_move == MP_DONT_RUN_INTO)
-    return MP_MOVING;
-#endif
-#endif
   if (can_move != MP_MOVING)
     return can_move;
 
-#if USE_FIXED_DONT_RUN_INTO
-#endif
-
   /* check if DigField() has caused relocation of the player */
   if (player->jx != jx || player->jy != jy)
     return MP_NO_ACTION;       /* <-- !!! CHECK THIS [-> MP_ACTION ?] !!! */
@@ -10406,7 +10071,14 @@ boolean MovePlayerOneStep(struct PlayerInfo *player,
 
   PlayerVisit[jx][jy] = FrameCounter;
 
+#if USE_UFAST_PLAYER_EXIT_BUGFIX
+  player->is_moving = TRUE;
+#endif
+
+#if 1
+  /* should better be called in MovePlayer(), but this breaks some tapes */
   ScrollPlayer(player, SCROLL_INIT);
+#endif
 
   return MP_MOVING;
 }
@@ -10474,6 +10146,8 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
     player->move_delay_value = original_move_delay_value;
   }
 
+  player->is_active = FALSE;
+
   if (player->last_move_dir & MV_HORIZONTAL)
   {
     if (!(moved |= MovePlayerOneStep(player, 0, dy, dx, dy)))
@@ -10485,6 +10159,17 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
       moved |= MovePlayerOneStep(player, 0, dy, dx, dy);
   }
 
+#if USE_FIXED_BORDER_RUNNING_GFX
+  if (!moved && !player->is_active)
+  {
+    player->is_moving = FALSE;
+    player->is_digging = FALSE;
+    player->is_collecting = FALSE;
+    player->is_snapping = FALSE;
+    player->is_pushing = FALSE;
+  }
+#endif
+
   jx = player->jx;
   jy = player->jy;
 
@@ -10591,6 +10276,11 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
     player->is_dropping = FALSE;
     player->is_dropping_pressed = FALSE;
     player->drop_pressed_delay = 0;
+
+#if 0
+    /* should better be called here than above, but this breaks some tapes */
+    ScrollPlayer(player, SCROLL_INIT);
+#endif
   }
   else
   {
@@ -10656,8 +10346,13 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
        last_field_block_delay += player->move_delay_value;
 
        /* when blocking enabled, prevent moving up despite gravity */
+#if USE_PLAYER_GRAVITY
+       if (player->gravity && player->MovDir == MV_UP)
+         block_delay_adjustment = -1;
+#else
        if (game.gravity && player->MovDir == MV_UP)
          block_delay_adjustment = -1;
+#endif
       }
 
       /* add block delay adjustment (also possible when not blocking) */
@@ -10677,12 +10372,6 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
   else if (!FrameReached(&player->actual_frame_counter, 1))
     return;
 
-#if 0
-  printf("::: player->MovPos: %d -> %d\n",
-        player->MovPos,
-        player->MovPos + (player->MovPos > 0 ? -1 : 1) * move_stepsize);
-#endif
-
 #if USE_NEW_PLAYER_SPEED
   if (player->MovPos != 0)
   {
@@ -10704,10 +10393,6 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
 
   if (player->MovPos == 0)     /* player reached destination field */
   {
-#if 0
-    printf("::: player reached destination field\n");
-#endif
-
     if (player->move_delay_reset_counter > 0)
     {
       player->move_delay_reset_counter--;
@@ -11579,50 +11264,18 @@ int DigField(struct PlayerInfo *player,
           game.engine_version >= VERSION_IDENT(2,2,0,0))
     old_element = Back[jx][jy];
 
-#if 0
-#if USE_FIXED_DONT_RUN_INTO
-  if (player_can_move && DONT_RUN_INTO(element))
-  {
-    if (element == EL_ACID && dx == 0 && dy == 1)
-    {
-      SplashAcid(x, y);
-      Feld[jx][jy] = EL_PLAYER_1;
-      InitMovingField(jx, jy, MV_DOWN);
-      Store[jx][jy] = EL_ACID;
-      ContinueMoving(jx, jy);
-      BuryPlayer(player);
-    }
-    else
-      TestIfPlayerRunsIntoBadThing(jx, jy, player->MovDir);
-
-    return MP_DONT_RUN_INTO;
-  }
-#endif
-#endif
-
-#if 1
-#if USE_FIXED_DONT_RUN_INTO
-  if (player_can_move && DONT_RUN_INTO(element))
-  {
-    TestIfPlayerRunsIntoBadThing(jx, jy, player->MovDir);
-
-    return MP_DONT_RUN_INTO;
-  }
-#endif
-#endif
-
   if (IS_WALKABLE(old_element) && !ACCESS_FROM(old_element, move_direction))
     return MP_NO_ACTION;       /* field has no opening in this direction */
 
   if (IS_PASSABLE(old_element) && !ACCESS_FROM(old_element,opposite_direction))
     return MP_NO_ACTION;       /* field has no opening in this direction */
 
-#if 1
 #if USE_FIXED_DONT_RUN_INTO
   if (player_can_move && element == EL_ACID && move_direction == MV_DOWN)
   {
     SplashAcid(x, y);
-    Feld[jx][jy] = EL_PLAYER_1;
+
+    Feld[jx][jy] = player->artwork_element;
     InitMovingField(jx, jy, MV_DOWN);
     Store[jx][jy] = EL_ACID;
     ContinueMoving(jx, jy);
@@ -11631,28 +11284,15 @@ int DigField(struct PlayerInfo *player,
     return MP_DONT_RUN_INTO;
   }
 #endif
-#endif
 
-#if 0
 #if USE_FIXED_DONT_RUN_INTO
   if (player_can_move && DONT_RUN_INTO(element))
   {
-    if (element == EL_ACID && dx == 0 && dy == 1)
-    {
-      SplashAcid(x, y);
-      Feld[jx][jy] = EL_PLAYER_1;
-      InitMovingField(jx, jy, MV_DOWN);
-      Store[jx][jy] = EL_ACID;
-      ContinueMoving(jx, jy);
-      BuryPlayer(player);
-    }
-    else
-      TestIfPlayerRunsIntoBadThing(jx, jy, player->MovDir);
+    TestIfPlayerRunsIntoBadThing(jx, jy, player->MovDir);
 
     return MP_DONT_RUN_INTO;
   }
 #endif
-#endif
 
 #if USE_FIXED_DONT_RUN_INTO
   if (IS_MOVING(x, y) || IS_PLAYER(x, y))
@@ -11685,10 +11325,17 @@ int DigField(struct PlayerInfo *player,
     return MP_NO_ACTION;
   }
 
+#if USE_PLAYER_GRAVITY
+  if (player->gravity && is_player && !player->is_auto_moving &&
+      canFallDown(player) && move_direction != MV_DOWN &&
+      !canMoveToValidFieldWithGravity(jx, jy, move_direction))
+    return MP_NO_ACTION;       /* player cannot walk here due to gravity */
+#else
   if (game.gravity && is_player && !player->is_auto_moving &&
       canFallDown(player) && move_direction != MV_DOWN &&
       !canMoveToValidFieldWithGravity(jx, jy, move_direction))
     return MP_NO_ACTION;       /* player cannot walk here due to gravity */
+#endif
 
   if (player_can_move &&
       IS_WALKABLE(element) && ACCESS_FROM(element, opposite_direction))
@@ -11752,23 +11399,50 @@ int DigField(struct PlayerInfo *player,
       if (!player->key[EM_GATE_GRAY_ACTIVE_NR(element)])
        return MP_NO_ACTION;
     }
+    else if (IS_EMC_GATE(element))
+    {
+      if (!player->key[EMC_GATE_NR(element)])
+       return MP_NO_ACTION;
+    }
+    else if (IS_EMC_GATE_GRAY(element))
+    {
+      if (!player->key[EMC_GATE_GRAY_NR(element)])
+       return MP_NO_ACTION;
+    }
+    else if (IS_EMC_GATE_GRAY_ACTIVE(element))
+    {
+      if (!player->key[EMC_GATE_GRAY_ACTIVE_NR(element)])
+       return MP_NO_ACTION;
+    }
     else if (IS_SP_PORT(element))
     {
       if (element == EL_SP_GRAVITY_PORT_LEFT ||
          element == EL_SP_GRAVITY_PORT_RIGHT ||
          element == EL_SP_GRAVITY_PORT_UP ||
          element == EL_SP_GRAVITY_PORT_DOWN)
+#if USE_PLAYER_GRAVITY
+       player->gravity = !player->gravity;
+#else
        game.gravity = !game.gravity;
+#endif
       else if (element == EL_SP_GRAVITY_ON_PORT_LEFT ||
               element == EL_SP_GRAVITY_ON_PORT_RIGHT ||
               element == EL_SP_GRAVITY_ON_PORT_UP ||
               element == EL_SP_GRAVITY_ON_PORT_DOWN)
+#if USE_PLAYER_GRAVITY
+       player->gravity = TRUE;
+#else
        game.gravity = TRUE;
+#endif
       else if (element == EL_SP_GRAVITY_OFF_PORT_LEFT ||
               element == EL_SP_GRAVITY_OFF_PORT_RIGHT ||
               element == EL_SP_GRAVITY_OFF_PORT_UP ||
               element == EL_SP_GRAVITY_OFF_PORT_DOWN)
+#if USE_PLAYER_GRAVITY
+       player->gravity = FALSE;
+#else
        game.gravity = FALSE;
+#endif
     }
 
     /* automatically move to the next field with double speed */
@@ -11845,11 +11519,7 @@ int DigField(struct PlayerInfo *player,
       if (player->inventory_size < MAX_INVENTORY_SIZE)
        player->inventory_element[player->inventory_size++] = element;
 
-#if 1
       DrawGameDoorValues();
-#else
-      DrawGameValue_Dynamite(local_player->inventory_size);
-#endif
     }
     else if (element == EL_DYNABOMB_INCREASE_NUMBER)
     {
@@ -11868,13 +11538,7 @@ int DigField(struct PlayerInfo *player,
     {
       player->key[KEY_NR(element)] = TRUE;
 
-#if 1
       DrawGameDoorValues();
-#else
-      DrawGameValue_Keys(player->key);
-#endif
-
-      redraw_mask |= REDRAW_DOOR_1;
     }
     else if (IS_ENVELOPE(element))
     {
@@ -11904,11 +11568,7 @@ int DigField(struct PlayerInfo *player,
          if (player->inventory_size < MAX_INVENTORY_SIZE)
            player->inventory_element[player->inventory_size++] = element;
 
-#if 1
       DrawGameDoorValues();
-#else
-      DrawGameValue_Dynamite(local_player->inventory_size);
-#endif
     }
     else if (collect_count > 0)
     {
@@ -11988,6 +11648,7 @@ int DigField(struct PlayerInfo *player,
     }
 
     player->is_pushing = TRUE;
+    player->is_active = TRUE;
 
     if (!(IN_LEV_FIELD(nextx, nexty) &&
          (IS_FREE(nextx, nexty) ||
@@ -12100,11 +11761,7 @@ int DigField(struct PlayerInfo *player,
     {
       int xx, yy;
 
-#if 1
       SCAN_PLAYFIELD(xx, yy)
-#else
-      for (yy = 0; yy < lev_fieldy; yy++) for (xx = 0; xx < lev_fieldx; xx++)
-#endif
       {
        if (Feld[xx][yy] == EL_SP_DISK_YELLOW)
          Bang(xx, yy);
@@ -12172,11 +11829,7 @@ int DigField(struct PlayerInfo *player,
 
       game.ball_state = !game.ball_state;
 
-#if 1
       SCAN_PLAYFIELD(xx, yy)
-#else
-      for (yy = 0; yy < lev_fieldy; yy++) for (xx = 0; xx < lev_fieldx; xx++)
-#endif
       {
        int e = Feld[xx][yy];
 
@@ -12240,7 +11893,10 @@ int DigField(struct PlayerInfo *player,
   if (is_player)               /* function can also be called by EL_PENGUIN */
   {
     if (Feld[x][y] != element)         /* really digged/collected something */
+    {
       player->is_collecting = !player->is_digging;
+      player->is_active = TRUE;
+    }
   }
 
   return MP_MOVING;
@@ -12309,6 +11965,7 @@ boolean SnapField(struct PlayerInfo *player, int dx, int dy)
     return FALSE;
 
   player->is_snapping = TRUE;
+  player->is_active = TRUE;
 
   if (player->MovPos == 0)
   {
@@ -12393,11 +12050,7 @@ boolean DropElement(struct PlayerInfo *player)
     {
       player->inventory_size--;
 
-#if 1
       DrawGameDoorValues();
-#else
-      DrawGameValue_Dynamite(local_player->inventory_size);
-#endif
 
       if (new_element == EL_DYNAMITE)
        new_element = EL_DYNAMITE_ACTIVE;
@@ -12847,8 +12500,20 @@ void RequestQuitGame(boolean ask_if_really_quit)
     else
 #endif
     {
-      game_status = GAME_MODE_MAIN;
-      DrawMainMenu();
+      if (!ask_if_really_quit || level_editor_test_game)
+      {
+       game_status = GAME_MODE_MAIN;
+
+       DrawMainMenu();
+      }
+      else
+      {
+       FadeOut(REDRAW_FIELD);
+
+       game_status = GAME_MODE_MAIN;
+
+       DrawAndFadeInMainMenu(REDRAW_FIELD);
+      }
     }
   }
   else