moved game values for things still needed from player to game structure
[rocksndiamonds.git] / src / game.c
index d37dee3a5f7c162ce69acdf33167a2d3b64f2233..acba22e9b2f67838bbde1ba74c84b6bedf5fb9ab 100644 (file)
 #include "anim.h"
 
 
-/* DEBUG SETTINGS */
+// DEBUG SETTINGS
 #define DEBUG_INIT_PLAYER      1
 #define DEBUG_PLAYER_ACTIONS   0
 
-/* EXPERIMENTAL STUFF */
+// EXPERIMENTAL STUFF
 #define USE_NEW_AMOEBA_CODE    FALSE
 
-/* EXPERIMENTAL STUFF */
+// EXPERIMENTAL STUFF
 #define USE_QUICKSAND_BD_ROCK_BUGFIX   0
 #define USE_QUICKSAND_IMPACT_BUGFIX    0
 #define USE_DELAYED_GFX_REDRAW         0
 #endif
 
 
-/* for DigField() */
+// for DigField()
 #define DF_NO_PUSH             0
 #define DF_DIG                 1
 #define DF_SNAP                        2
 
-/* for MovePlayer() */
+// for MovePlayer()
 #define MP_NO_ACTION           0
 #define MP_MOVING              1
 #define MP_ACTION              2
 #define MP_DONT_RUN_INTO       (MP_MOVING | MP_ACTION)
 
-/* for ScrollPlayer() */
+// for ScrollPlayer()
 #define SCROLL_INIT            0
 #define SCROLL_GO_ON           1
 
-/* for Bang()/Explode() */
+// for Bang()/Explode()
 #define EX_PHASE_START         0
 #define EX_TYPE_NONE           0
 #define EX_TYPE_NORMAL         (1 << 0)
 #define EX_TYPE_DYNA           (1 << 4)
 #define EX_TYPE_SINGLE_TILE    (EX_TYPE_CENTER | EX_TYPE_BORDER)
 
-#define PANEL_OFF()            (local_player->LevelSolved_PanelOff)
+#define PANEL_OFF()            (game.panel.active == FALSE)
 #define        PANEL_DEACTIVATED(p)    ((p)->x < 0 || (p)->y < 0 || PANEL_OFF())
 #define PANEL_XPOS(p)          (DX + ALIGNED_TEXT_XPOS(p))
 #define PANEL_YPOS(p)          (DY + ALIGNED_TEXT_YPOS(p))
 
-/* game panel display and control definitions */
+// game panel display and control definitions
 #define GAME_PANEL_LEVEL_NUMBER                        0
 #define GAME_PANEL_GEMS                                1
 #define GAME_PANEL_INVENTORY_COUNT             2
@@ -831,17 +831,17 @@ static struct GamePanelControlInfo game_panel_controls[] =
   }
 };
 
-/* values for delayed check of falling and moving elements and for collision */
+// values for delayed check of falling and moving elements and for collision
 #define CHECK_DELAY_MOVING     3
 #define CHECK_DELAY_FALLING    CHECK_DELAY_MOVING
 #define CHECK_DELAY_COLLISION  2
 #define CHECK_DELAY_IMPACT     CHECK_DELAY_COLLISION
 
-/* values for initial player move delay (initial delay counter value) */
+// values for initial player move delay (initial delay counter value)
 #define INITIAL_MOVE_DELAY_OFF -1
 #define INITIAL_MOVE_DELAY_ON  0
 
-/* values for player movement speed (which is in fact a delay value) */
+// values for player movement speed (which is in fact a delay value)
 #define MOVE_DELAY_MIN_SPEED   32
 #define MOVE_DELAY_NORMAL_SPEED        8
 #define MOVE_DELAY_HIGH_SPEED  4
@@ -853,7 +853,7 @@ static struct GamePanelControlInfo game_panel_controls[] =
 #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 scroll positions */
+// values for scroll positions
 #define SCROLL_POSITION_X(x)   ((x) < SBX_Left  + MIDPOSX ? SBX_Left : \
                                 (x) > SBX_Right + MIDPOSX ? SBX_Right :\
                                 (x) - MIDPOSX)
@@ -861,7 +861,7 @@ static struct GamePanelControlInfo game_panel_controls[] =
                                 (y) > SBY_Lower + MIDPOSY ? SBY_Lower :\
                                 (y) - MIDPOSY)
 
-/* values for other actions */
+// values for other actions
 #define MOVE_STEPSIZE_NORMAL   (TILEX / MOVE_DELAY_NORMAL_SPEED)
 #define MOVE_STEPSIZE_MIN      (1)
 #define MOVE_STEPSIZE_MAX      (TILEX)
@@ -1004,7 +1004,7 @@ static struct GamePanelControlInfo game_panel_controls[] =
 
 #define MM_HEALTH(x)           (MIN(MAX(0, MAX_HEALTH - (x)), MAX_HEALTH))
 
-/* game button identifiers */
+// game button identifiers
 #define GAME_CTRL_ID_STOP              0
 #define GAME_CTRL_ID_PAUSE             1
 #define GAME_CTRL_ID_PLAY              2
@@ -1026,7 +1026,7 @@ static struct GamePanelControlInfo game_panel_controls[] =
 #define NUM_GAME_BUTTONS               17
 
 
-/* forward declaration for internal use */
+// forward declaration for internal use
 
 static void CreateField(int, int, int);
 
@@ -1085,8 +1085,8 @@ static void PlayLevelSoundElementAction(int, int, int, int);
 static void PlayLevelSoundElementActionIfLoop(int, int, int, int);
 static void PlayLevelSoundActionIfLoop(int, int, int);
 static void StopLevelSoundActionIfLoop(int, int, int);
-static void PlayLevelMusic();
-static void FadeLevelSoundsAndMusic();
+static void PlayLevelMusic(void);
+static void FadeLevelSoundsAndMusic(void);
 
 static void HandleGameButtons(struct GadgetInfo *);
 
@@ -1096,7 +1096,7 @@ void ContinueMoving(int, int);
 void Bang(int, int);
 void InitMovDir(int, int);
 void InitAmoebaNr(int, int);
-int NewHiScore(void);
+int NewHiScore(int);
 
 void TestIfGoodThingHitsBadThing(int, int, int);
 void TestIfBadThingHitsGoodThing(int, int, int);
@@ -1112,14 +1112,15 @@ void TestIfGoodThingGetsHitByBadThing(int, int, int);
 void KillPlayer(struct PlayerInfo *);
 void BuryPlayer(struct PlayerInfo *);
 void RemovePlayer(struct PlayerInfo *);
+void ExitPlayer(struct PlayerInfo *);
 
 static int getInvisibleActiveFromInvisibleElement(int);
 static int getInvisibleFromInvisibleActiveElement(int);
 
 static struct GadgetInfo *game_gadget[NUM_GAME_BUTTONS];
 
-/* for detection of endless loops, caused by custom element programming */
-/* (using maximal playfield width x 10 is just a rough approximation) */
+// for detection of endless loops, caused by custom element programming
+// (using maximal playfield width x 10 is just a rough approximation)
 #define MAX_ELEMENT_CHANGE_RECURSION_DEPTH     (MAX_PLAYFIELD_WIDTH * 10)
 
 #define RECURSION_LOOP_DETECTION_START(e, rc)                          \
@@ -1148,12 +1149,12 @@ static boolean recursion_loop_element;
 static int map_player_action[MAX_PLAYERS];
 
 
-/* ------------------------------------------------------------------------- */
-/* definition of elements that automatically change to other elements after  */
-/* a specified time, eventually calling a function when changing             */
-/* ------------------------------------------------------------------------- */
+// ----------------------------------------------------------------------------
+// definition of elements that automatically change to other elements after
+// a specified time, eventually calling a function when changing
+// ----------------------------------------------------------------------------
 
-/* forward declaration for changer functions */
+// forward declaration for changer functions
 static void InitBuggyBase(int, int);
 static void WarnBuggyBase(int, int);
 
@@ -1547,7 +1548,7 @@ static boolean trigger_events[MAX_NUM_ELEMENTS][NUM_CHANGE_EVENTS];
 
 #define CE_PAGE(e, ce)         (element_info[e].event_page[ce])
 
-/* static variables for playfield scan mode (scanning forward or backward) */
+// static variables for playfield scan mode (scanning forward or backward)
 static int playfield_scan_start_x = 0;
 static int playfield_scan_start_y = 0;
 static int playfield_scan_delta_x = 1;
@@ -1561,7 +1562,7 @@ static int playfield_scan_delta_y = 1;
                                     (x) += playfield_scan_delta_x)
 
 #ifdef DEBUG
-void DEBUG_SetMaximumDynamite()
+void DEBUG_SetMaximumDynamite(void)
 {
   int i;
 
@@ -1572,7 +1573,7 @@ void DEBUG_SetMaximumDynamite()
 }
 #endif
 
-static void InitPlayfieldScanModeVars()
+static void InitPlayfieldScanModeVars(void)
 {
   if (game.use_reverse_scan_direction)
   {
@@ -1605,7 +1606,7 @@ static int get_move_delay_from_stepsize(int move_stepsize)
   move_stepsize =
     MIN(MAX(MOVE_STEPSIZE_MIN, move_stepsize), MOVE_STEPSIZE_MAX);
 
-  /* make sure that stepsize value is always a power of 2 */
+  // make sure that stepsize value is always a power of 2
   move_stepsize = (1 << log_2(move_stepsize));
 
   return TILEX / move_stepsize;
@@ -1618,10 +1619,10 @@ static void SetPlayerMoveSpeed(struct PlayerInfo *player, int move_stepsize,
   int move_delay = get_move_delay_from_stepsize(move_stepsize);
   boolean cannot_move = (move_stepsize == STEPSIZE_NOT_MOVING ? TRUE : FALSE);
 
-  /* do no immediately change move delay -- the player might just be moving */
+  // do no immediately change move delay -- the player might just be moving
   player->move_delay_value_next = move_delay;
 
-  /* information if player can move must be set separately */
+  // information if player can move must be set separately
   player->cannot_move = cannot_move;
 
   if (init_game)
@@ -1635,7 +1636,7 @@ static void SetPlayerMoveSpeed(struct PlayerInfo *player, int move_stepsize,
   }
 }
 
-void GetPlayerConfig()
+void GetPlayerConfig(void)
 {
   GameFrameDelay = setup.game_frame_delay;
 
@@ -1682,6 +1683,30 @@ int GetElementFromGroupElement(int element)
   return element;
 }
 
+static void IncrementSokobanFieldsNeeded(void)
+{
+  if (level.sb_fields_needed)
+    game.sokoban_fields_still_needed++;
+}
+
+static void IncrementSokobanObjectsNeeded(void)
+{
+  if (level.sb_objects_needed)
+    game.sokoban_objects_still_needed++;
+}
+
+static void DecrementSokobanFieldsNeeded(void)
+{
+  if (game.sokoban_fields_still_needed > 0)
+    game.sokoban_fields_still_needed--;
+}
+
+static void DecrementSokobanObjectsNeeded(void)
+{
+  if (game.sokoban_objects_still_needed > 0)
+    game.sokoban_objects_still_needed--;
+}
+
 static void InitPlayerField(int x, int y, int element, boolean init_game)
 {
   if (element == EL_SP_MURPHY)
@@ -1718,16 +1743,16 @@ static void InitPlayerField(int x, int y, int element, boolean init_game)
                                level.sp_block_last_field :
                                level.block_last_field);
 
-    /* ---------- initialize player's last field block delay --------------- */
+    // ---------- initialize player's last field block delay ------------------
 
-    /* always start with reliable default value (no adjustment needed) */
+    // always start with reliable default value (no adjustment needed)
     player->block_delay_adjustment = 0;
 
-    /* special case 1: in Supaplex, Murphy blocks last field one more frame */
+    // special case 1: in Supaplex, Murphy blocks last field one more frame
     if (player->block_last_field && element == EL_SP_MURPHY)
       player->block_delay_adjustment = 1;
 
-    /* special case 2: in game engines before 3.1.1, blocking was different */
+    // special case 2: in game engines before 3.1.1, blocking was different
     if (game.use_block_last_field_bug)
       player->block_delay_adjustment = (player->block_last_field ? -1 : 1);
 
@@ -1735,7 +1760,7 @@ static void InitPlayerField(int x, int y, int element, boolean init_game)
     {
       player->active = TRUE;
 
-      /* remove potentially duplicate players */
+      // remove potentially duplicate players
       if (StorePlayer[jx][jy] == Feld[x][y])
        StorePlayer[jx][jy] = 0;
 
@@ -1764,7 +1789,7 @@ static void InitPlayerField(int x, int y, int element, boolean init_game)
     struct PlayerInfo *player = &stored_player[player_nr];
 
     if (player->active && player->killed)
-      player->reanimated = TRUE; /* if player was just killed, reanimate him */
+      player->reanimated = TRUE; // if player was just killed, reanimate him
   }
 }
 
@@ -1791,7 +1816,11 @@ static void InitField(int x, int y, boolean init_game)
       break;
 
     case EL_SOKOBAN_FIELD_EMPTY:
-      local_player->sokobanfields_still_needed++;
+      IncrementSokobanFieldsNeeded();
+      break;
+
+    case EL_SOKOBAN_OBJECT:
+      IncrementSokobanObjectsNeeded();
       break;
 
     case EL_STONEBLOCK:
@@ -1876,11 +1905,11 @@ static void InitField(int x, int y, boolean init_game)
       break;
 
     case EL_LAMP:
-      local_player->lights_still_needed++;
+      game.lights_still_needed++;
       break;
 
     case EL_PENGUIN:
-      local_player->friends_still_needed++;
+      game.friends_still_needed++;
       break;
 
     case EL_PIG:
@@ -1906,12 +1935,12 @@ static void InitField(int x, int y, boolean init_game)
        int belt_dir = getBeltDirFromBeltSwitchElement(Feld[x][y]);
        int belt_dir_nr = getBeltDirNrFromBeltSwitchElement(Feld[x][y]);
 
-       if (game.belt_dir_nr[belt_nr] == 3)     /* initial value */
+       if (game.belt_dir_nr[belt_nr] == 3)     // initial value
        {
          game.belt_dir[belt_nr] = belt_dir;
          game.belt_dir_nr[belt_nr] = belt_dir_nr;
        }
-       else    /* more than one switch -- set it like the first switch */
+       else    // more than one switch -- set it like the first switch
        {
          Feld[x][y] = Feld[x][y] - belt_dir_nr + game.belt_dir_nr[belt_nr];
        }
@@ -1965,7 +1994,7 @@ static void InitField(int x, int y, boolean init_game)
     case EL_NEXT_CE_6:
     case EL_NEXT_CE_7:
     case EL_NEXT_CE_8:
-      /* reference elements should not be used on the playfield */
+      // reference elements should not be used on the playfield
       Feld[x][y] = EL_EMPTY;
       break;
 
@@ -1992,23 +2021,23 @@ static void InitField(int x, int y, boolean init_game)
     CheckTriggeredElementChange(x, y, element, CE_CREATION_OF_X);
 }
 
-inline static void InitField_WithBug1(int x, int y, boolean init_game)
+static void InitField_WithBug1(int x, int y, boolean init_game)
 {
   InitField(x, y, init_game);
 
-  /* not needed to call InitMovDir() -- already done by InitField()! */
+  // not needed to call InitMovDir() -- already done by InitField()!
   if (game.engine_version < VERSION_IDENT(3,1,0,0) &&
       CAN_MOVE(Feld[x][y]))
     InitMovDir(x, y);
 }
 
-inline static void InitField_WithBug2(int x, int y, boolean init_game)
+static void InitField_WithBug2(int x, int y, boolean init_game)
 {
   int old_element = Feld[x][y];
 
   InitField(x, y, init_game);
 
-  /* not needed to call InitMovDir() -- already done by InitField()! */
+  // not needed to call InitMovDir() -- already done by InitField()!
   if (game.engine_version < VERSION_IDENT(3,1,0,0) &&
       CAN_MOVE(old_element) &&
       (old_element < EL_MOLE_LEFT || old_element > EL_MOLE_DOWN))
@@ -2045,8 +2074,8 @@ static int get_next_dropped_element(struct PlayerInfo *player)
 
 static int get_inventory_element_from_pos(struct PlayerInfo *player, int pos)
 {
-  /* pos >= 0: get element from bottom of the stack;
-     pos <  0: get element from top of the stack */
+  // pos >= 0: get element from bottom of the stack;
+  // pos <  0: get element from top of the stack
 
   if (pos < 0)
   {
@@ -2102,7 +2131,7 @@ int getPlayerInventorySize(int player_nr)
     return stored_player[player_nr].inventory_size;
 }
 
-void InitGameControlValues()
+static void InitGameControlValues(void)
 {
   int i;
 
@@ -2120,12 +2149,12 @@ void InitGameControlValues()
       Error(ERR_EXIT, "this should not happen -- please debug");
     }
 
-    /* force update of game controls after initialization */
+    // force update of game controls after initialization
     gpc->value = gpc->last_value = -1;
     gpc->frame = gpc->last_frame = -1;
     gpc->gfx_frame = -1;
 
-    /* determine panel value width for later calculation of alignment */
+    // determine panel value width for later calculation of alignment
     if (type == TYPE_INTEGER || type == TYPE_STRING)
     {
       pos->width = pos->size * getFontWidth(pos->font);
@@ -2137,22 +2166,22 @@ void InitGameControlValues()
       pos->height = pos->size;
     }
 
-    /* fill structure for game panel draw order */
+    // fill structure for game panel draw order
     gpo->nr = gpc->nr;
     gpo->sort_priority = pos->sort_priority;
   }
 
-  /* sort game panel controls according to sort_priority and control number */
+  // sort game panel controls according to sort_priority and control number
   qsort(game_panel_order, NUM_GAME_PANEL_CONTROLS,
        sizeof(struct GamePanelOrderInfo), compareGamePanelOrderInfo);
 }
 
-void UpdatePlayfieldElementCount()
+static void UpdatePlayfieldElementCount(void)
 {
   boolean use_element_count = FALSE;
   int i, j, x, y;
 
-  /* first check if it is needed at all to calculate playfield element count */
+  // first check if it is needed at all to calculate playfield element count
   for (i = GAME_PANEL_ELEMENT_COUNT_1; i <= GAME_PANEL_ELEMENT_COUNT_8; i++)
     if (!PANEL_DEACTIVATED(game_panel_controls[i].pos))
       use_element_count = TRUE;
@@ -2175,11 +2204,11 @@ void UpdatePlayfieldElementCount()
          element_info[j].element_count;
 }
 
-void UpdateGameControlValues()
+static void UpdateGameControlValues(void)
 {
   int i, k;
-  int time = (local_player->LevelSolved ?
-             local_player->LevelSolved_CountingTime :
+  int time = (game.LevelSolved ?
+             game.LevelSolved_CountingTime :
              level.game_engine_type == GAME_ENGINE_TYPE_EM ?
              level.native_em_level->lev->time :
              level.game_engine_type == GAME_ENGINE_TYPE_SP ?
@@ -2187,8 +2216,8 @@ void UpdateGameControlValues()
              level.game_engine_type == GAME_ENGINE_TYPE_MM ?
              game_mm.energy_left :
              game.no_time_limit ? TimePlayed : TimeLeft);
-  int score = (local_player->LevelSolved ?
-              local_player->LevelSolved_CountingScore :
+  int score = (game.LevelSolved ?
+              game.LevelSolved_CountingScore :
               level.game_engine_type == GAME_ENGINE_TYPE_EM ?
               level.native_em_level->lev->score :
               level.game_engine_type == GAME_ENGINE_TYPE_SP ?
@@ -2202,7 +2231,7 @@ void UpdateGameControlValues()
              level.native_sp_level->game_sp->infotrons_still_needed :
              level.game_engine_type == GAME_ENGINE_TYPE_MM ?
              game_mm.kettles_still_needed :
-             local_player->gems_still_needed);
+             game.gems_still_needed);
   int exit_closed = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
                     level.native_em_level->lev->required > 0 :
                     level.game_engine_type == GAME_ENGINE_TYPE_SP ?
@@ -2210,20 +2239,22 @@ void UpdateGameControlValues()
                     level.game_engine_type == GAME_ENGINE_TYPE_MM ?
                     game_mm.kettles_still_needed > 0 ||
                     game_mm.lights_still_needed > 0 :
-                    local_player->gems_still_needed > 0 ||
-                    local_player->sokobanfields_still_needed > 0 ||
-                    local_player->lights_still_needed > 0);
-  int health = (local_player->LevelSolved ?
-               local_player->LevelSolved_CountingHealth :
+                    game.gems_still_needed > 0 ||
+                    game.sokoban_fields_still_needed > 0 ||
+                    game.sokoban_objects_still_needed > 0 ||
+                    game.lights_still_needed > 0);
+  int health = (game.LevelSolved ?
+               game.LevelSolved_CountingHealth :
                level.game_engine_type == GAME_ENGINE_TYPE_MM ?
                MM_HEALTH(game_mm.laser_overload_value) :
                local_player->health);
 
   UpdatePlayfieldElementCount();
 
-  /* update game panel control values */
+  // update game panel control values
 
-  game_panel_controls[GAME_PANEL_LEVEL_NUMBER].value = level_nr;
+  // used instead of "level_nr" (for network games)
+  game_panel_controls[GAME_PANEL_LEVEL_NUMBER].value = levelset.level_nr;
   game_panel_controls[GAME_PANEL_GEMS].value = gems;
 
   game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value = 0;
@@ -2236,7 +2267,7 @@ void UpdateGameControlValues()
   {
     for (i = 0; i < MAX_PLAYERS; i++)
     {
-      /* only one player in Supaplex game engine */
+      // only one player in Supaplex game engine
       if (level.game_engine_type == GAME_ENGINE_TYPE_SP && i > 0)
        break;
 
@@ -2376,12 +2407,12 @@ void UpdateGameControlValues()
     (local_player->dynabomb_xl ? EL_DYNABOMB_INCREASE_POWER : EL_EMPTY);
 
   game_panel_controls[GAME_PANEL_PENGUINS].value =
-    local_player->friends_still_needed;
+    game.friends_still_needed;
 
   game_panel_controls[GAME_PANEL_SOKOBAN_OBJECTS].value =
-    local_player->sokobanfields_still_needed;
+    game.sokoban_objects_still_needed;
   game_panel_controls[GAME_PANEL_SOKOBAN_FIELDS].value =
-    local_player->sokobanfields_still_needed;
+    game.sokoban_fields_still_needed;
 
   game_panel_controls[GAME_PANEL_ROBOT_WHEEL].value =
     (game.robot_wheel_active ? EL_ROBOT_WHEEL_ACTIVE : EL_ROBOT_WHEEL);
@@ -2431,7 +2462,7 @@ void UpdateGameControlValues()
   game_panel_controls[GAME_PANEL_LEVEL_NAME].value = 0;
   game_panel_controls[GAME_PANEL_LEVEL_AUTHOR].value = 0;
 
-  /* update game panel control frames */
+  // update game panel control frames
 
   for (i = 0; game_panel_controls[i].nr != -1; i++)
   {
@@ -2505,7 +2536,7 @@ void UpdateGameControlValues()
   }
 }
 
-void DisplayGameControlValues()
+static void DisplayGameControlValues(void)
 {
   boolean redraw_panel = FALSE;
   int i;
@@ -2527,14 +2558,14 @@ void DisplayGameControlValues()
   if (!redraw_panel)
     return;
 
-  /* copy default game door content to main double buffer */
+  // copy default game door content to main double buffer
 
-  /* !!! CHECK AGAIN !!! */
+  // !!! CHECK AGAIN !!!
   SetPanelBackground();
   // SetDoorBackgroundImage(IMG_BACKGROUND_PANEL);
   DrawBackground(DX, DY, DXSIZE, DYSIZE);
 
-  /* redraw game control buttons */
+  // redraw game control buttons
   RedrawGameButtons();
 
   SetGameStatus(GAME_MODE_PSEUDO_PANEL);
@@ -2565,7 +2596,7 @@ void DisplayGameControlValues()
       {
        boolean use_dynamic_size = (size == -1 ? TRUE : FALSE);
 
-       if (use_dynamic_size)           /* use dynamic number of digits */
+       if (use_dynamic_size)           // use dynamic number of digits
        {
          int value_change = (nr == GAME_PANEL_LEVEL_NUMBER ? 100 : 1000);
          int size1 = (nr == GAME_PANEL_LEVEL_NUMBER ? 2 : 3);
@@ -2578,11 +2609,11 @@ void DisplayGameControlValues()
        }
       }
 
-      /* correct text size if "digits" is zero or less */
+      // correct text size if "digits" is zero or less
       if (size <= 0)
        size = strlen(int2str(value, size));
 
-      /* dynamically correct text alignment */
+      // dynamically correct text alignment
       pos->width = size * getFontWidth(font);
 
       DrawTextExt(drawto, PANEL_XPOS(pos), PANEL_YPOS(pos),
@@ -2722,8 +2753,8 @@ void DisplayGameControlValues()
 
       if (nr == GAME_PANEL_GRAVITY_STATE)
       {
-       int font1 = pos->font;          /* (used for normal state) */
-       int font2 = pos->font_alt;      /* (used for active state) */
+       int font1 = pos->font;          // (used for normal state)
+       int font2 = pos->font_alt;      // (used for active state)
 
        font = (active ? font2 : font1);
       }
@@ -2734,10 +2765,10 @@ void DisplayGameControlValues()
 
        if (size <= 0)
        {
-         /* don't truncate output if "chars" is zero or less */
+         // don't truncate output if "chars" is zero or less
          size = strlen(s);
 
-         /* dynamically correct text alignment */
+         // dynamically correct text alignment
          pos->width = size * getFontWidth(font);
        }
 
@@ -2756,7 +2787,7 @@ void DisplayGameControlValues()
   SetGameStatus(GAME_MODE_PLAYING);
 }
 
-void UpdateAndDisplayGameControlValues()
+void UpdateAndDisplayGameControlValues(void)
 {
   if (tape.deactivate_display)
     return;
@@ -2765,34 +2796,34 @@ void UpdateAndDisplayGameControlValues()
   DisplayGameControlValues();
 }
 
-void UpdateGameDoorValues()
+#if 0
+static void UpdateGameDoorValues(void)
 {
   UpdateGameControlValues();
 }
+#endif
 
-void DrawGameDoorValues()
+void DrawGameDoorValues(void)
 {
   DisplayGameControlValues();
 }
 
 
-/*
-  =============================================================================
-  InitGameEngine()
-  -----------------------------------------------------------------------------
-  initialize game engine due to level / tape version number
-  =============================================================================
-*/
+// ============================================================================
+// InitGameEngine()
+// ----------------------------------------------------------------------------
+// initialize game engine due to level / tape version number
+// ============================================================================
 
-static void InitGameEngine()
+static void InitGameEngine(void)
 {
   int i, j, k, l, x, y;
 
-  /* set game engine from tape file when re-playing, else from level file */
+  // set game engine from tape file when re-playing, else from level file
   game.engine_version = (tape.playing ? tape.engine_version :
                         level.game_version);
 
-  /* set single or multi-player game mode (needed for re-playing tapes) */
+  // set single or multi-player game mode (needed for re-playing tapes)
   game.team_mode = setup.team_mode;
 
   if (tape.playing)
@@ -2803,13 +2834,13 @@ static void InitGameEngine()
       if (tape.player_participates[i])
        num_players++;
 
-    /* multi-player tapes contain input data for more than one player */
+    // multi-player tapes contain input data for more than one player
     game.team_mode = (num_players > 1);
   }
 
-  /* ---------------------------------------------------------------------- */
-  /* set flags for bugs and changes according to active game engine version */
-  /* ---------------------------------------------------------------------- */
+  // --------------------------------------------------------------------------
+  // set flags for bugs and changes according to active game engine version
+  // --------------------------------------------------------------------------
 
   /*
     Summary of bugfix/change:
@@ -2879,15 +2910,15 @@ static void InitGameEngine()
   game_em.use_snap_key_bug =
     (game.engine_version < VERSION_IDENT(4,0,1,0));
 
-  /* ---------------------------------------------------------------------- */
+  // --------------------------------------------------------------------------
 
-  /* set maximal allowed number of custom element changes per game frame */
+  // set maximal allowed number of custom element changes per game frame
   game.max_num_changes_per_frame = 1;
 
-  /* default scan direction: scan playfield from top/left to bottom/right */
+  // default scan direction: scan playfield from top/left to bottom/right
   InitPlayfieldScanMode(CA_ARG_SCAN_MODE_NORMAL);
 
-  /* dynamically adjust element properties according to game engine version */
+  // dynamically adjust element properties according to game engine version
   InitElementPropertiesEngine(game.engine_version);
 
 #if 0
@@ -2898,33 +2929,33 @@ static void InitGameEngine()
   printf("       => game.engine_version == %06d\n", game.engine_version);
 #endif
 
-  /* ---------- initialize player's initial move delay --------------------- */
+  // ---------- initialize player's initial move delay ------------------------
 
-  /* dynamically adjust player properties according to level information */
+  // dynamically adjust player properties according to level information
   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 */
+  // dynamically adjust player properties according to game engine version
   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 --------------------- */
+  // ---------- initialize player's initial push delay ------------------------
 
-  /* dynamically adjust player properties according to game engine version */
+  // dynamically adjust player properties according to game engine version
   game.initial_push_delay_value =
     (game.engine_version < VERSION_IDENT(3,0,7,1) ? 5 : -1);
 
-  /* ---------- initialize changing elements ------------------------------- */
+  // ---------- initialize changing elements ----------------------------------
 
-  /* initialize changing elements information */
+  // initialize changing elements information
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
   {
     struct ElementInfo *ei = &element_info[i];
 
-    /* this pointer might have been changed in the level editor */
+    // this pointer might have been changed in the level editor
     ei->change = &ei->change_page[0];
 
     if (!IS_CUSTOM_ELEMENT(i))
@@ -2944,7 +2975,7 @@ static void InitGameEngine()
     }
   }
 
-  /* add changing elements from pre-defined list */
+  // add changing elements from pre-defined list
   for (i = 0; change_delay_list[i].element != EL_UNDEFINED; i++)
   {
     struct ChangingElementInfo *ch_delay = &change_delay_list[i];
@@ -2966,7 +2997,7 @@ static void InitGameEngine()
     SET_PROPERTY(ch_delay->element, EP_CAN_CHANGE_OR_HAS_ACTION, TRUE);
   }
 
-  /* ---------- initialize internal run-time variables --------------------- */
+  // ---------- initialize internal run-time variables ------------------------
 
   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
   {
@@ -2980,7 +3011,7 @@ static void InitGameEngine()
     }
   }
 
-  /* add change events from custom element configuration */
+  // add change events from custom element configuration
   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
   {
     struct ElementInfo *ei = &element_info[EL_CUSTOM_START + i];
@@ -2992,7 +3023,7 @@ static void InitGameEngine()
 
       for (k = 0; k < NUM_CHANGE_EVENTS; k++)
       {
-       /* only add event page for the first page found with this event */
+       // only add event page for the first page found with this event
        if (ei->change_page[j].has_event[k] && !(ei->has_change_event[k]))
        {
          ei->has_change_event[k] = TRUE;
@@ -3004,7 +3035,7 @@ static void InitGameEngine()
     }
   }
 
-  /* ---------- initialize reference elements in change conditions --------- */
+  // ---------- initialize reference elements in change conditions ------------
 
   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
   {
@@ -3023,7 +3054,7 @@ static void InitGameEngine()
     }
   }
 
-  /* ---------- initialize run-time trigger player and element ------------- */
+  // ---------- initialize run-time trigger player and element ----------------
 
   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
   {
@@ -3040,14 +3071,14 @@ static void InitGameEngine()
     }
   }
 
-  /* ---------- initialize trigger events ---------------------------------- */
+  // ---------- initialize trigger events -------------------------------------
 
-  /* initialize trigger events information */
+  // initialize trigger events information
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
     for (j = 0; j < NUM_CHANGE_EVENTS; j++)
       trigger_events[i][j] = FALSE;
 
-  /* add trigger events from element change event properties */
+  // add trigger events from element change event properties
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
   {
     struct ElementInfo *ei = &element_info[i];
@@ -3084,14 +3115,14 @@ static void InitGameEngine()
     }
   }
 
-  /* ---------- initialize push delay -------------------------------------- */
+  // ---------- initialize push delay -----------------------------------------
 
-  /* initialize push delay values to default */
+  // initialize push delay values to default
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
   {
     if (!IS_CUSTOM_ELEMENT(i))
     {
-      /* set default push delay values (corrected since version 3.0.7-1) */
+      // 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;
@@ -3105,7 +3136,7 @@ static void InitGameEngine()
     }
   }
 
-  /* set push delay value for certain elements from pre-defined list */
+  // set push delay value for certain elements from pre-defined list
   for (i = 0; push_delay_list[i].element != EL_UNDEFINED; i++)
   {
     int e = push_delay_list[i].element;
@@ -3114,14 +3145,14 @@ static void InitGameEngine()
     element_info[e].push_delay_random = push_delay_list[i].push_delay_random;
   }
 
-  /* set push delay value for Supaplex elements for newer engine versions */
+  // set push delay value for Supaplex elements for newer engine versions
   if (game.engine_version >= VERSION_IDENT(3,1,0,0))
   {
     for (i = 0; i < MAX_NUM_ELEMENTS; i++)
     {
       if (IS_SP_ELEMENT(i))
       {
-       /* set SP push delay to just enough to push under a falling zonk */
+       // set SP push delay to just enough to push under a falling zonk
        int delay = (game.engine_version >= VERSION_IDENT(3,1,1,0) ? 8 : 6);
 
        element_info[i].push_delay_fixed  = delay;
@@ -3130,14 +3161,14 @@ static void InitGameEngine()
     }
   }
 
-  /* ---------- initialize move stepsize ----------------------------------- */
+  // ---------- initialize move stepsize --------------------------------------
 
-  /* initialize move stepsize values to default */
+  // initialize move stepsize values to default
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
     if (!IS_CUSTOM_ELEMENT(i))
       element_info[i].move_stepsize = MOVE_STEPSIZE_NORMAL;
 
-  /* set move stepsize value for certain elements from pre-defined list */
+  // set move stepsize value for certain elements from pre-defined list
   for (i = 0; move_stepsize_list[i].element != EL_UNDEFINED; i++)
   {
     int e = move_stepsize_list[i].element;
@@ -3145,38 +3176,38 @@ static void InitGameEngine()
     element_info[e].move_stepsize = move_stepsize_list[i].move_stepsize;
   }
 
-  /* ---------- initialize collect score ----------------------------------- */
+  // ---------- initialize collect score --------------------------------------
 
-  /* initialize collect score values for custom elements from initial value */
+  // initialize collect score values for custom elements from initial value
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
     if (IS_CUSTOM_ELEMENT(i))
       element_info[i].collect_score = element_info[i].collect_score_initial;
 
-  /* ---------- initialize collect count ----------------------------------- */
+  // ---------- initialize collect count --------------------------------------
 
-  /* initialize collect count values for non-custom elements */
+  // initialize collect count values for non-custom elements
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
     if (!IS_CUSTOM_ELEMENT(i))
       element_info[i].collect_count_initial = 0;
 
-  /* add collect count values for all elements from pre-defined list */
+  // add collect count values for all elements from pre-defined list
   for (i = 0; collect_count_list[i].element != EL_UNDEFINED; i++)
     element_info[collect_count_list[i].element].collect_count_initial =
       collect_count_list[i].count;
 
-  /* ---------- initialize access direction -------------------------------- */
+  // ---------- initialize access direction -----------------------------------
 
-  /* initialize access direction values to default (access from every side) */
+  // initialize access direction values to default (access from every side)
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
     if (!IS_CUSTOM_ELEMENT(i))
       element_info[i].access_direction = MV_ALL_DIRECTIONS;
 
-  /* set access direction value for certain elements from pre-defined list */
+  // set access direction value for certain elements from pre-defined list
   for (i = 0; access_direction_list[i].element != EL_UNDEFINED; i++)
     element_info[access_direction_list[i].element].access_direction =
       access_direction_list[i].direction;
 
-  /* ---------- initialize explosion content ------------------------------- */
+  // ---------- initialize explosion content ----------------------------------
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
   {
     if (IS_CUSTOM_ELEMENT(i))
@@ -3184,7 +3215,7 @@ static void InitGameEngine()
 
     for (y = 0; y < 3; y++) for (x = 0; x < 3; x++)
     {
-      /* (content for EL_YAMYAM set at run-time with game.yamyam_content_nr) */
+      // (content for EL_YAMYAM set at run-time with game.yamyam_content_nr)
 
       element_info[i].content.e[x][y] =
        (i == EL_PLAYER_1 ? EL_EMERALD_YELLOW :
@@ -3209,19 +3240,19 @@ static void InitGameEngine()
     }
   }
 
-  /* ---------- initialize recursion detection ------------------------------ */
+  // ---------- initialize recursion detection --------------------------------
   recursion_loop_depth = 0;
   recursion_loop_detected = FALSE;
   recursion_loop_element = EL_UNDEFINED;
 
-  /* ---------- initialize graphics engine ---------------------------------- */
+  // ---------- initialize graphics engine ------------------------------------
   game.scroll_delay_value =
     (game.forced_scroll_delay_value != -1 ? game.forced_scroll_delay_value :
      setup.scroll_delay                   ? setup.scroll_delay_value       : 0);
   game.scroll_delay_value =
     MIN(MAX(MIN_SCROLL_DELAY, game.scroll_delay_value), MAX_SCROLL_DELAY);
 
-  /* ---------- initialize game engine snapshots ---------------------------- */
+  // ---------- initialize game engine snapshots ------------------------------
   for (i = 0; i < MAX_PLAYERS; i++)
     game.snapshot.last_action[i] = 0;
   game.snapshot.changed_action = FALSE;
@@ -3235,13 +3266,14 @@ static void InitGameEngine()
      SNAPSHOT_MODE_EVERY_COLLECT : SNAPSHOT_MODE_OFF);
   game.snapshot.save_snapshot = FALSE;
 
-  /* ---------- initialize level time for Supaplex engine ------------------- */
-  /* Supaplex levels with time limit currently unsupported -- should be added */
+  // ---------- initialize level time for Supaplex engine ---------------------
+  // Supaplex levels with time limit currently unsupported -- should be added
   if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
     level.time = 0;
 }
 
-int get_num_special_action(int element, int action_first, int action_last)
+static int get_num_special_action(int element, int action_first,
+                                 int action_last)
 {
   int num_special_action = 0;
   int i, j;
@@ -3265,23 +3297,51 @@ int get_num_special_action(int element, int action_first, int action_last)
 }
 
 
-/*
-  =============================================================================
-  InitGame()
-  -----------------------------------------------------------------------------
-  initialize and start new game
-  =============================================================================
-*/
+// ============================================================================
+// InitGame()
+// ----------------------------------------------------------------------------
+// initialize and start new game
+// ============================================================================
+
+#if DEBUG_INIT_PLAYER
+static void DebugPrintPlayerStatus(char *message)
+{
+  int i;
+
+  if (!options.debug)
+    return;
+
+  printf("%s:\n", message);
+
+  for (i = 0; i < MAX_PLAYERS; i++)
+  {
+    struct PlayerInfo *player = &stored_player[i];
+
+    printf("- player %d: present == %d, connected == %d [%d/%d], active == %d",
+          i + 1,
+          player->present,
+          player->connected,
+          player->connected_locally,
+          player->connected_network,
+          player->active);
 
-void InitGame()
+    if (local_player == player)
+      printf(" (local player)");
+
+    printf("\n");
+  }
+}
+#endif
+
+void InitGame(void)
 {
   int full_lev_fieldx = lev_fieldx + (BorderElement != EL_EMPTY ? 2 : 0);
   int full_lev_fieldy = lev_fieldy + (BorderElement != EL_EMPTY ? 2 : 0);
   int fade_mask = REDRAW_FIELD;
 
-  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 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
   int initial_move_dir = MV_DOWN;
   int i, j, x, y;
 
@@ -3305,10 +3365,9 @@ void InitGame()
 
   ExpireSoundLoops(TRUE);
 
-  if (!level_editor_test_game)
-    FadeOut(fade_mask);
+  FadeOut(fade_mask);
 
-  /* needed if different viewport properties defined for playing */
+  // needed if different viewport properties defined for playing
   ChangeViewportPropertiesIfNeeded();
 
   ClearField();
@@ -3320,7 +3379,7 @@ void InitGame()
   InitGameEngine();
   InitGameControlValues();
 
-  /* don't play tapes over network */
+  // don't play tapes over network
   network_playing = (network.enabled && !tape.playing);
 
   for (i = 0; i < MAX_PLAYERS; i++)
@@ -3358,11 +3417,6 @@ void InitGame()
     player->health = MAX_HEALTH;
     player->health_final = MAX_HEALTH;
 
-    player->gems_still_needed = level.gems_needed;
-    player->sokobanfields_still_needed = 0;
-    player->lights_still_needed = 0;
-    player->friends_still_needed = 0;
-
     for (j = 0; j < MAX_NUM_KEYS; j++)
       player->key[j] = FALSE;
 
@@ -3387,8 +3441,8 @@ void InitGame()
        player->element_nr);
     player->use_murphy = FALSE;
 
-    player->block_last_field = FALSE;  /* initialized in InitPlayerField() */
-    player->block_delay_adjustment = 0;        /* initialized in InitPlayerField() */
+    player->block_last_field = FALSE;  // initialized in InitPlayerField()
+    player->block_delay_adjustment = 0;        // initialized in InitPlayerField()
 
     player->gravity = level.initial_player_gravity[i];
 
@@ -3445,7 +3499,7 @@ void InitGame()
 
     SetPlayerMoveSpeed(player, level.initial_player_stepsize[i], TRUE);
 
-    player->push_delay       = -1;     /* initialized when pushing starts */
+    player->push_delay       = -1;     // initialized when pushing starts
     player->push_delay_value = game.initial_push_delay_value;
 
     player->drop_delay = 0;
@@ -3485,25 +3539,14 @@ void InitGame()
     DigField(player, 0, 0, 0, 0, 0, 0, DF_NO_PUSH);
     SnapField(player, 0, 0);
 
-    player->LevelSolved = FALSE;
     player->GameOver = FALSE;
 
-    player->LevelSolved_GameWon = FALSE;
-    player->LevelSolved_GameEnd = FALSE;
-    player->LevelSolved_PanelOff = FALSE;
-    player->LevelSolved_SaveTape = FALSE;
-    player->LevelSolved_SaveScore = FALSE;
-
-    player->LevelSolved_CountingTime = 0;
-    player->LevelSolved_CountingScore = 0;
-    player->LevelSolved_CountingHealth = 0;
-
     map_player_action[i] = i;
   }
 
   network_player_action_received = FALSE;
 
-  /* initial null action */
+  // initial null action
   if (network_playing)
     SendToServer_MovePlayer(MV_NONE);
 
@@ -3520,10 +3563,23 @@ void InitGame()
   ScreenMovPos = 0;
   ScreenGfxPos = 0;
 
-  ScrollStepSize = 0;  /* will be correctly initialized by ScrollScreen() */
+  ScrollStepSize = 0;  // will be correctly initialized by ScrollScreen()
 
   AllPlayersGone = FALSE;
 
+  game.LevelSolved = FALSE;
+
+  game.LevelSolved_GameWon = FALSE;
+  game.LevelSolved_GameEnd = FALSE;
+  game.LevelSolved_SaveTape = FALSE;
+  game.LevelSolved_SaveScore = FALSE;
+
+  game.LevelSolved_CountingTime = 0;
+  game.LevelSolved_CountingScore = 0;
+  game.LevelSolved_CountingHealth = 0;
+
+  game.panel.active = TRUE;
+
   game.no_time_limit = (level.time == 0);
 
   game.yamyam_content_nr = 0;
@@ -3535,55 +3591,43 @@ void InitGame()
   game.switchgate_pos = 0;
   game.wind_direction = level.wind_direction_initial;
 
+  game.gems_still_needed = level.gems_needed;
+  game.sokoban_fields_still_needed = 0;
+  game.sokoban_objects_still_needed = 0;
+  game.lights_still_needed = 0;
+  game.players_still_needed = 0;
+  game.friends_still_needed = 0;
+
   game.lenses_time_left = 0;
   game.magnify_time_left = 0;
 
   game.ball_state = level.ball_state_initial;
   game.ball_content_nr = 0;
 
+  game.explosions_delayed = TRUE;
+
   game.envelope_active = FALSE;
 
   for (i = 0; i < NUM_BELTS; i++)
   {
     game.belt_dir[i] = MV_NONE;
-    game.belt_dir_nr[i] = 3;           /* not moving, next moving left */
+    game.belt_dir_nr[i] = 3;           // not moving, next moving left
   }
 
   for (i = 0; i < MAX_NUM_AMOEBA; i++)
     AmoebaCnt[i] = AmoebaCnt2[i] = 0;
 
 #if DEBUG_INIT_PLAYER
-  if (options.debug)
-  {
-    printf("Player status at level initialization:\n");
-
-    for (i = 0; i < MAX_PLAYERS; i++)
-    {
-      struct PlayerInfo *player = &stored_player[i];
-
-      printf("- player %d: present == %d, connected == %d [%d/%d], active == %d",
-            i + 1,
-            player->present,
-            player->connected,
-            player->connected_locally,
-            player->connected_network,
-            player->active);
-
-      if (local_player == player)
-       printf(" (local player)");
-
-      printf("\n");
-    }
-  }
+  DebugPrintPlayerStatus("Player status at level initialization");
 #endif
 
   SCAN_PLAYFIELD(x, y)
   {
-    Feld[x][y] = level.field[x][y];
+    Feld[x][y] = Last[x][y] = level.field[x][y];
     MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0;
     ChangeDelay[x][y] = 0;
     ChangePage[x][y] = -1;
-    CustomValue[x][y] = 0;             /* initialized in InitField() */
+    CustomValue[x][y] = 0;             // initialized in InitField()
     Store[x][y] = Store2[x][y] = StorePlayer[x][y] = Back[x][y] = 0;
     AmoebaNr[x][y] = 0;
     WasJustMoving[x][y] = 0;
@@ -3631,7 +3675,7 @@ void InitGame()
   {
     struct PlayerInfo *player = &stored_player[i];
 
-    /* set number of special actions for bored and sleeping animation */
+    // 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);
@@ -3644,25 +3688,25 @@ void InitGame()
                    emulate_sb ? EMU_SOKOBAN :
                    emulate_sp ? EMU_SUPAPLEX : EMU_NONE);
 
-  /* initialize type of slippery elements */
+  // initialize type of slippery elements
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
   {
     if (!IS_CUSTOM_ELEMENT(i))
     {
-      /* default: elements slip down either to the left or right randomly */
+      // default: elements slip down either to the left or right randomly
       element_info[i].slippery_type = SLIPPERY_ANY_RANDOM;
 
-      /* SP style elements prefer to slip down on the left side */
+      // SP style elements prefer to slip down on the left side
       if (game.engine_version >= VERSION_IDENT(3,1,1,0) && IS_SP_ELEMENT(i))
        element_info[i].slippery_type = SLIPPERY_ANY_LEFT_RIGHT;
 
-      /* BD style elements prefer to slip down on the left side */
+      // BD style elements prefer to slip down on the left side
       if (game.emulation == EMU_BOULDERDASH)
        element_info[i].slippery_type = SLIPPERY_ANY_LEFT_RIGHT;
     }
   }
 
-  /* initialize explosion and ignition delay */
+  // initialize explosion and ignition delay
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
   {
     if (!IS_CUSTOM_ELEMENT(i))
@@ -3682,17 +3726,17 @@ void InitGame()
     }
   }
 
-  /* correct non-moving belts to start moving left */
+  // correct non-moving belts to start moving left
   for (i = 0; i < NUM_BELTS; i++)
     if (game.belt_dir[i] == MV_NONE)
-      game.belt_dir_nr[i] = 3;         /* not moving, next moving left */
+      game.belt_dir_nr[i] = 3;         // not moving, next moving left
 
 #if USE_NEW_PLAYER_ASSIGNMENTS
   for (i = 0; i < MAX_PLAYERS; i++)
   {
     stored_player[i].connected = FALSE;
 
-    /* in network game mode, the local player might not be the first player */
+    // in network game mode, the local player might not be the first player
     if (stored_player[i].connected_locally)
       local_player = &stored_player[i];
   }
@@ -3707,8 +3751,8 @@ void InitGame()
   }
   else if (network.enabled)
   {
-    /* add team mode players connected over the network (needed for correct
-       assignment of player figures from level to locally playing players) */
+    // add team mode players connected over the network (needed for correct
+    // assignment of player figures from level to locally playing players)
 
     for (i = 0; i < MAX_PLAYERS; i++)
       if (stored_player[i].connected_network)
@@ -3716,8 +3760,8 @@ void InitGame()
   }
   else if (game.team_mode)
   {
-    /* try to guess locally connected team mode players (needed for correct
-       assignment of player figures from level to locally playing players) */
+    // try to guess locally connected team mode players (needed for correct
+    // assignment of player figures from level to locally playing players)
 
     for (i = 0; i < MAX_PLAYERS; i++)
       if (setup.input[i].use_joystick ||
@@ -3726,28 +3770,7 @@ void InitGame()
   }
 
 #if DEBUG_INIT_PLAYER
-  if (options.debug)
-  {
-    printf("Player status after level initialization:\n");
-
-    for (i = 0; i < MAX_PLAYERS; i++)
-    {
-      struct PlayerInfo *player = &stored_player[i];
-
-      printf("- player %d: present == %d, connected == %d [%d/%d], active == %d",
-            i + 1,
-            player->present,
-            player->connected,
-            player->connected_locally,
-            player->connected_network,
-            player->active);
-
-      if (local_player == player)
-       printf(" (local player)");
-
-      printf("\n");
-    }
-  }
+  DebugPrintPlayerStatus("Player status after level initialization");
 #endif
 
 #if DEBUG_INIT_PLAYER
@@ -3755,7 +3778,7 @@ void InitGame()
     printf("Reassigning players ...\n");
 #endif
 
-  /* check if any connected player was not found in playfield */
+  // check if any connected player was not found in playfield
   for (i = 0; i < MAX_PLAYERS; i++)
   {
     struct PlayerInfo *player = &stored_player[i];
@@ -3769,9 +3792,9 @@ void InitGame()
        printf("- looking for field player for player %d ...\n", i + 1);
 #endif
 
-      /* assign first free player found that is present in the playfield */
+      // assign first free player found that is present in the playfield
 
-      /* first try: look for unmapped playfield player that is not connected */
+      // first try: look for unmapped playfield player that is not connected
       for (j = 0; j < MAX_PLAYERS; j++)
        if (field_player == NULL &&
            stored_player[j].present &&
@@ -3779,7 +3802,7 @@ void InitGame()
            !stored_player[j].connected)
          field_player = &stored_player[j];
 
-      /* second try: look for *any* unmapped playfield player */
+      // second try: look for *any* unmapped playfield player
       for (j = 0; j < MAX_PLAYERS; j++)
        if (field_player == NULL &&
            stored_player[j].present &&
@@ -3834,33 +3857,12 @@ void InitGame()
   }
 
 #if DEBUG_INIT_PLAYER
-  if (options.debug)
-  {
-    printf("Player status after player assignment (first stage):\n");
-
-    for (i = 0; i < MAX_PLAYERS; i++)
-    {
-      struct PlayerInfo *player = &stored_player[i];
-
-      printf("- player %d: present == %d, connected == %d [%d/%d], active == %d",
-            i + 1,
-            player->present,
-            player->connected,
-            player->connected_locally,
-            player->connected_network,
-            player->active);
-
-      if (local_player == player)
-       printf(" (local player)");
-
-      printf("\n");
-    }
-  }
+  DebugPrintPlayerStatus("Player status after player assignment (first stage)");
 #endif
 
 #else
 
-  /* check if any connected player was not found in playfield */
+  // check if any connected player was not found in playfield
   for (i = 0; i < MAX_PLAYERS; i++)
   {
     struct PlayerInfo *player = &stored_player[i];
@@ -3872,7 +3874,7 @@ void InitGame()
        struct PlayerInfo *field_player = &stored_player[j];
        int jx = field_player->jx, jy = field_player->jy;
 
-       /* assign first free player found that is present in the playfield */
+       // assign first free player found that is present in the playfield
        if (field_player->present && !field_player->connected)
        {
          player->present = TRUE;
@@ -3903,21 +3905,21 @@ void InitGame()
   printf("::: local_player->present == %d\n", local_player->present);
 #endif
 
-  /* set focus to local player for network games, else to all players */
+  // set focus to local player for network games, else to all players
   game.centered_player_nr = (network_playing ? local_player->index_nr : -1);
   game.centered_player_nr_next = game.centered_player_nr;
   game.set_centered_player = FALSE;
 
   if (network_playing && tape.recording)
   {
-    /* store client dependent player focus when recording network games */
+    // store client dependent player focus when recording network games
     tape.centered_player_nr_next = game.centered_player_nr_next;
     tape.set_centered_player = TRUE;
   }
 
   if (tape.playing)
   {
-    /* when playing a tape, eliminate all players who do not participate */
+    // when playing a tape, eliminate all players who do not participate
 
 #if USE_NEW_PLAYER_ASSIGNMENTS
 
@@ -3960,9 +3962,9 @@ void InitGame()
     }
 #endif
   }
-  else if (!network.enabled && !game.team_mode)                /* && !tape.playing */
+  else if (!network.enabled && !game.team_mode)                // && !tape.playing
   {
-    /* when in single player mode, eliminate all but the local player */
+    // when in single player mode, eliminate all but the local player
 
     for (i = 0; i < MAX_PLAYERS; i++)
     {
@@ -3981,7 +3983,14 @@ void InitGame()
     }
   }
 
-  /* when recording the game, store which players take part in the game */
+  for (i = 0; i < MAX_PLAYERS; i++)
+    if (stored_player[i].active)
+      game.players_still_needed++;
+
+  if (level.solved_by_one_player)
+    game.players_still_needed = 1;
+
+  // when recording the game, store which players take part in the game
   if (tape.recording)
   {
 #if USE_NEW_PLAYER_ASSIGNMENTS
@@ -3996,28 +4005,7 @@ void InitGame()
   }
 
 #if DEBUG_INIT_PLAYER
-  if (options.debug)
-  {
-    printf("Player status after player assignment (final stage):\n");
-
-    for (i = 0; i < MAX_PLAYERS; i++)
-    {
-      struct PlayerInfo *player = &stored_player[i];
-
-      printf("- player %d: present == %d, connected == %d [%d/%d], active == %d",
-            i + 1,
-            player->present,
-            player->connected,
-            player->connected_locally,
-            player->connected_network,
-            player->active);
-
-      if (local_player == player)
-       printf(" (local player)");
-
-      printf("\n");
-    }
-  }
+  DebugPrintPlayerStatus("Player status after player assignment (final stage)");
 #endif
 
   if (BorderElement == EL_EMPTY)
@@ -4045,8 +4033,8 @@ void InitGame()
   if (EVEN(SCR_FIELDY) && full_lev_fieldy > SCR_FIELDY)
     SBY_Upper--;
 
-  /* if local player not found, look for custom element that might create
-     the player (make some assumptions about the right custom element) */
+  // if local player not found, look for custom element that might create
+  // the player (make some assumptions about the right custom element)
   if (!local_player->present)
   {
     int start_x = 0, start_y = 0;
@@ -4079,7 +4067,7 @@ void InitGame()
       {
        for (i = 0; i < element_info[element].num_change_pages; i++)
        {
-         /* check for player created from custom element as single target */
+         // check for player created from custom element as single target
          content = element_info[element].change_page[i].target_element;
          is_player = ELEM_IS_PLAYER(content);
 
@@ -4097,7 +4085,7 @@ void InitGame()
 
       for (yy = 0; yy < 3; yy++) for (xx = 0; xx < 3; xx++)
       {
-       /* check for player created from custom element as explosion content */
+       // check for player created from custom element as explosion content
        content = element_info[element].content.e[xx][yy];
        is_player = ELEM_IS_PLAYER(content);
 
@@ -4116,7 +4104,7 @@ void InitGame()
 
        for (i = 0; i < element_info[element].num_change_pages; i++)
        {
-         /* check for player created from custom element as extended target */
+         // check for player created from custom element as extended target
          content =
            element_info[element].change_page[i].target_content.e[xx][yy];
 
@@ -4144,7 +4132,7 @@ void InitGame()
     scroll_y = SCROLL_POSITION_Y(local_player->jy);
   }
 
-  /* !!! FIX THIS (START) !!! */
+  // !!! FIX THIS (START) !!!
   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
   {
     InitGameEngine_EM();
@@ -4162,14 +4150,14 @@ void InitGame()
     DrawLevel(REDRAW_FIELD);
     DrawAllPlayers();
 
-    /* after drawing the level, correct some elements */
+    // after drawing the level, correct some elements
     if (game.timegate_time_left == 0)
       CloseAllOpenTimegates();
   }
 
-  /* blit playfield from scroll buffer to normal back buffer for fading in */
+  // blit playfield from scroll buffer to normal back buffer for fading in
   BlitScreenToBitmap(backbuffer);
-  /* !!! FIX THIS (END) !!! */
+  // !!! FIX THIS (END) !!!
 
   DrawMaskedBorder(fade_mask);
 
@@ -4185,9 +4173,9 @@ void InitGame()
 
   if (!game.restart_level)
   {
-    /* copy default game door content to main double buffer */
+    // copy default game door content to main double buffer
 
-    /* !!! CHECK AGAIN !!! */
+    // !!! CHECK AGAIN !!!
     SetPanelBackground();
     // SetDoorBackgroundImage(IMG_BACKGROUND_PANEL);
     DrawBackground(DX, DY, DXSIZE, DYSIZE);
@@ -4209,7 +4197,7 @@ void InitGame()
     MapGameButtons();
     MapTapeButtons();
 
-    /* copy actual game door content to door double buffer for OpenDoor() */
+    // copy actual game door content to door double buffer for OpenDoor()
     BlitBitmap(drawto, bitmap_db_door_1, DX, DY, DXSIZE, DYSIZE, 0, 0);
 
     OpenDoor(DOOR_OPEN_ALL);
@@ -4217,28 +4205,7 @@ void InitGame()
     KeyboardAutoRepeatOffUnlessAutoplay();
 
 #if DEBUG_INIT_PLAYER
-    if (options.debug)
-    {
-      printf("Player status (final):\n");
-
-      for (i = 0; i < MAX_PLAYERS; i++)
-      {
-       struct PlayerInfo *player = &stored_player[i];
-
-       printf("- player %d: present == %d, connected == %d [%d/%d], active == %d",
-              i + 1,
-              player->present,
-              player->connected,
-              player->connected_locally,
-              player->connected_network,
-              player->active);
-
-       if (local_player == player)
-         printf(" (local player)");
-
-       printf("\n");
-      }
-    }
+    DebugPrintPlayerStatus("Player status (final)");
 #endif
   }
 
@@ -4256,6 +4223,7 @@ void InitGame()
 
   game.restart_level = FALSE;
   game.restart_game_message = NULL;
+  game.request_active = FALSE;
 
   if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
     InitGameActions_MM();
@@ -4274,7 +4242,7 @@ void InitGame()
 void UpdateEngineValues(int actual_scroll_x, int actual_scroll_y,
                        int actual_player_x, int actual_player_y)
 {
-  /* this is used for non-R'n'D game engines to update certain engine values */
+  // this is used for non-R'n'D game engines to update certain engine values
 
   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
   {
@@ -4282,11 +4250,11 @@ void UpdateEngineValues(int actual_scroll_x, int actual_scroll_y,
     actual_player_y = correctLevelPosY_EM(actual_player_y);
   }
 
-  /* needed to determine if sounds are played within the visible screen area */
+  // needed to determine if sounds are played within the visible screen area
   scroll_x = actual_scroll_x;
   scroll_y = actual_scroll_y;
 
-  /* needed to get player position for "follow finger" playing input method */
+  // needed to get player position for "follow finger" playing input method
   local_player->jx = actual_player_x;
   local_player->jy = actual_player_y;
 }
@@ -4409,7 +4377,7 @@ void InitMovDir(int x, int y)
        else if (move_pattern == MV_ALONG_LEFT_SIDE ||
                 move_pattern == MV_ALONG_RIGHT_SIDE)
        {
-         /* use random direction as default start direction */
+         // use random direction as default start direction
          if (game.engine_version >= VERSION_IDENT(3,1,0,0))
            MovDir[x][y] = 1 << RND(4);
 
@@ -4489,27 +4457,31 @@ void InitAmoebaNr(int x, int y)
   AmoebaCnt2[group_nr]++;
 }
 
-static void PlayerWins(struct PlayerInfo *player)
+static void LevelSolved(void)
 {
-  player->LevelSolved = TRUE;
-  player->GameOver = TRUE;
+  if (level.game_engine_type == GAME_ENGINE_TYPE_RND &&
+      game.players_still_needed > 0)
+    return;
+
+  game.LevelSolved = TRUE;
+
+  local_player->GameOver = TRUE;
 
-  player->score_final = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
-                        level.native_em_level->lev->score :
-                        level.game_engine_type == GAME_ENGINE_TYPE_MM ?
-                        game_mm.score :
-                        player->score);
-  player->health_final = (level.game_engine_type == GAME_ENGINE_TYPE_MM ?
-                         MM_HEALTH(game_mm.laser_overload_value) :
-                         player->health);
+  local_player->score_final = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
+                              level.native_em_level->lev->score :
+                              level.game_engine_type == GAME_ENGINE_TYPE_MM ?
+                              game_mm.score :
+                              local_player->score);
+  local_player->health_final = (level.game_engine_type == GAME_ENGINE_TYPE_MM ?
+                               MM_HEALTH(game_mm.laser_overload_value) :
+                               local_player->health);
 
-  player->LevelSolved_CountingTime = (game.no_time_limit ? TimePlayed :
-                                     TimeLeft);
-  player->LevelSolved_CountingScore = player->score_final;
-  player->LevelSolved_CountingHealth = player->health_final;
+  game.LevelSolved_CountingTime = (game.no_time_limit ? TimePlayed : TimeLeft);
+  game.LevelSolved_CountingScore = local_player->score_final;
+  game.LevelSolved_CountingHealth = local_player->health_final;
 }
 
-void GameWon()
+void GameWon(void)
 {
   static int time_count_steps;
   static int time, time_final;
@@ -4522,17 +4494,17 @@ void GameWon()
   int game_over_delay_value_2 = 25;
   int game_over_delay_value_3 = 50;
 
-  if (!local_player->LevelSolved_GameWon)
+  if (!game.LevelSolved_GameWon)
   {
     int i;
 
-    /* do not start end game actions before the player stops moving (to exit) */
+    // do not start end game actions before the player stops moving (to exit)
     if (local_player->MovPos)
       return;
 
-    local_player->LevelSolved_GameWon = TRUE;
-    local_player->LevelSolved_SaveTape = tape.recording;
-    local_player->LevelSolved_SaveScore = !tape.playing;
+    game.LevelSolved_GameWon = TRUE;
+    game.LevelSolved_SaveTape = tape.recording;
+    game.LevelSolved_SaveScore = !tape.playing;
 
     if (!tape.playing)
     {
@@ -4541,7 +4513,7 @@ void GameWon()
       SaveLevelSetup_SeriesInfo();
     }
 
-    if (tape.auto_play)                /* tape might already be stopped here */
+    if (tape.auto_play)                // tape might already be stopped here
       tape.auto_play_level_solved = TRUE;
 
     TapeStop();
@@ -4588,8 +4560,8 @@ void GameWon()
       time = time_final;
       score = score_final;
 
-      local_player->LevelSolved_CountingTime = time;
-      local_player->LevelSolved_CountingScore = score;
+      game.LevelSolved_CountingTime = time;
+      game.LevelSolved_CountingScore = score;
 
       game_panel_controls[GAME_PANEL_TIME].value = time;
       game_panel_controls[GAME_PANEL_SCORE].value = score;
@@ -4599,9 +4571,9 @@ void GameWon()
 
     if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
     {
-      if (ExitX >= 0 && ExitY >= 0)    /* local player has left the level */
+      if (ExitX >= 0 && ExitY >= 0)    // local player has left the level
       {
-       /* close exit door after last player */
+       // close exit door after last player
        if ((AllPlayersGone &&
             (Feld[ExitX][ExitY] == EL_EXIT_OPEN ||
              Feld[ExitX][ExitY] == EL_SP_EXIT_OPEN ||
@@ -4613,15 +4585,15 @@ void GameWon()
 
          Feld[ExitX][ExitY] =
            (element == EL_EXIT_OPEN            ? EL_EXIT_CLOSING :
-            element == EL_EM_EXIT_OPEN ? EL_EM_EXIT_CLOSING :
-            element == EL_SP_EXIT_OPEN ? EL_SP_EXIT_CLOSING:
+            element == EL_EM_EXIT_OPEN         ? EL_EM_EXIT_CLOSING :
+            element == EL_SP_EXIT_OPEN         ? EL_SP_EXIT_CLOSING:
             element == EL_STEEL_EXIT_OPEN      ? EL_STEEL_EXIT_CLOSING:
             EL_EM_STEEL_EXIT_CLOSING);
 
          PlayLevelSoundElementAction(ExitX, ExitY, element, ACTION_CLOSING);
        }
 
-       /* player disappears */
+       // player disappears
        DrawLevelField(ExitX, ExitY);
       }
 
@@ -4633,7 +4605,7 @@ void GameWon()
        {
          RemovePlayer(player);
 
-         /* player disappears */
+         // player disappears
          DrawLevelField(player->jx, player->jy);
        }
       }
@@ -4660,8 +4632,8 @@ void GameWon()
     time  += time_count_steps * time_count_dir;
     score += time_count_steps * level.score[SC_TIME_BONUS];
 
-    local_player->LevelSolved_CountingTime = time;
-    local_player->LevelSolved_CountingScore = score;
+    game.LevelSolved_CountingTime = time;
+    game.LevelSolved_CountingScore = score;
 
     game_panel_controls[GAME_PANEL_TIME].value = time;
     game_panel_controls[GAME_PANEL_SCORE].value = score;
@@ -4692,8 +4664,8 @@ void GameWon()
     health += health_count_dir;
     score  += level.score[SC_TIME_BONUS];
 
-    local_player->LevelSolved_CountingHealth = health;
-    local_player->LevelSolved_CountingScore = score;
+    game.LevelSolved_CountingHealth = health;
+    game.LevelSolved_CountingScore = score;
 
     game_panel_controls[GAME_PANEL_HEALTH].value = health;
     game_panel_controls[GAME_PANEL_SCORE].value = score;
@@ -4710,7 +4682,7 @@ void GameWon()
     return;
   }
 
-  local_player->LevelSolved_PanelOff = TRUE;
+  game.panel.active = FALSE;
 
   if (game_over_delay_3 > 0)
   {
@@ -4722,23 +4694,24 @@ void GameWon()
   GameEnd();
 }
 
-void GameEnd()
+void GameEnd(void)
 {
+  // used instead of "level_nr" (needed for network games)
+  int last_level_nr = levelset.level_nr;
   int hi_pos;
-  boolean raise_level = FALSE;
 
-  local_player->LevelSolved_GameEnd = TRUE;
+  game.LevelSolved_GameEnd = TRUE;
 
-  if (local_player->LevelSolved_SaveTape)
+  if (game.LevelSolved_SaveTape)
   {
-    /* make sure that request dialog to save tape does not open door again */
+    // make sure that request dialog to save tape does not open door again
     if (!global.use_envelope_request)
       CloseDoor(DOOR_CLOSE_1);
 
-    SaveTapeChecked_LevelSolved(tape.level_nr);                /* ask to save tape */
+    SaveTapeChecked_LevelSolved(tape.level_nr);                // ask to save tape
   }
 
-  /* if no tape is to be saved, close both doors simultaneously */
+  // if no tape is to be saved, close both doors simultaneously
   CloseDoor(DOOR_CLOSE_ALL);
 
   if (level_editor_test_game)
@@ -4750,7 +4723,7 @@ void GameEnd()
     return;
   }
 
-  if (!local_player->LevelSolved_SaveScore)
+  if (!game.LevelSolved_SaveScore)
   {
     SetGameStatus(GAME_MODE_MAIN);
 
@@ -4767,36 +4740,43 @@ void GameEnd()
   }
 
   if (setup.increment_levels &&
-      level_nr < leveldir_current->last_level)
-    raise_level = TRUE;                        /* advance to next level */
-
-  if ((hi_pos = NewHiScore()) >= 0) 
+      level_nr < leveldir_current->last_level &&
+      !network_playing)
   {
-    SetGameStatus(GAME_MODE_SCORES);
+    level_nr++;                // advance to next level
+    TapeErase();       // start with empty tape
 
-    DrawHallOfFame(hi_pos);
-
-    if (raise_level)
+    if (setup.auto_play_next_level)
     {
-      level_nr++;
-      TapeErase();
+      LoadLevel(level_nr);
+
+      SaveLevelSetup_SeriesInfo();
     }
   }
+
+  hi_pos = NewHiScore(last_level_nr);
+
+  if (hi_pos >= 0 && !setup.skip_scores_after_game)
+  {
+    SetGameStatus(GAME_MODE_SCORES);
+
+    DrawHallOfFame(last_level_nr, hi_pos);
+  }
+  else if (setup.auto_play_next_level && setup.increment_levels &&
+          last_level_nr < leveldir_current->last_level &&
+          !network_playing)
+  {
+    StartGameActions(network.enabled, setup.autorecord, level.random_seed);
+  }
   else
   {
     SetGameStatus(GAME_MODE_MAIN);
 
-    if (raise_level)
-    {
-      level_nr++;
-      TapeErase();
-    }
-
     DrawMainMenu();
   }
 }
 
-int NewHiScore()
+int NewHiScore(int level_nr)
 {
   int k, l;
   int position = -1;
@@ -4812,7 +4792,7 @@ int NewHiScore()
   {
     if (local_player->score_final > highscore[k].Score)
     {
-      /* player has made it to the hall of fame */
+      // player has made it to the hall of fame
 
       if (k < MAX_SCORE_ENTRIES - 1)
       {
@@ -4824,7 +4804,7 @@ int NewHiScore()
            if (strEqual(setup.player_name, highscore[l].Name))
              m = l;
 
-         if (m == k)   /* player's new highscore overwrites his old one */
+         if (m == k)   // player's new highscore overwrites his old one
            goto put_into_list;
        }
 
@@ -4847,7 +4827,7 @@ int NewHiScore()
     else if (one_score_entry_per_name &&
             !strncmp(setup.player_name, highscore[k].Name,
                      MAX_PLAYER_NAME_LEN))
-      break;   /* player already there with a higher score */
+      break;   // player already there with a higher score
   }
 
   if (position >= 0) 
@@ -4856,7 +4836,7 @@ int NewHiScore()
   return position;
 }
 
-inline static int getElementMoveStepsizeExt(int x, int y, int direction)
+static int getElementMoveStepsizeExt(int x, int y, int direction)
 {
   int element = Feld[x][y];
   int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0);
@@ -4865,7 +4845,7 @@ inline static int getElementMoveStepsizeExt(int x, int y, int direction)
   int sign = (horiz_move ? dx : dy);
   int step = sign * element_info[element].move_stepsize;
 
-  /* special values for move stepsize for spring and things on conveyor belt */
+  // special values for move stepsize for spring and things on conveyor belt
   if (horiz_move)
   {
     if (CAN_FALL(element) &&
@@ -4878,7 +4858,7 @@ inline static int getElementMoveStepsizeExt(int x, int y, int direction)
   return step;
 }
 
-inline static int getElementMoveStepsize(int x, int y)
+static int getElementMoveStepsize(int x, int y)
 {
   return getElementMoveStepsizeExt(x, y, MovDir[x][y]);
 }
@@ -4927,7 +4907,7 @@ static void ResetRandomAnimationValue(int x, int y)
   GfxRandom[x][y] = INIT_GFX_RANDOM();
 }
 
-void InitMovingField(int x, int y, int direction)
+static void InitMovingField(int x, int y, int direction)
 {
   int element = Feld[x][y];
   int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0);
@@ -4936,13 +4916,13 @@ void InitMovingField(int x, int y, int direction)
   int newy = y + dy;
   boolean is_moving_before, is_moving_after;
 
-  /* check if element was/is moving or being moved before/after mode change */
+  // check if element was/is moving or being moved before/after mode change
   is_moving_before = (WasJustMoving[x][y] != 0);
   is_moving_after  = (getElementMoveStepsizeExt(x, y, direction)    != 0);
 
-  /* reset animation only for moving elements which change direction of moving
-     or which just started or stopped moving
-     (else CEs with property "can move" / "not moving" are reset each frame) */
+  // reset animation only for moving elements which change direction of moving
+  // or which just started or stopped moving
+  // (else CEs with property "can move" / "not moving" are reset each frame)
   if (is_moving_before != is_moving_after ||
       direction != MovDir[x][y])
     ResetGfxAnimation(x, y);
@@ -4954,7 +4934,7 @@ void InitMovingField(int x, int y, int direction)
                     direction == MV_DOWN && CAN_FALL(element) ?
                     ACTION_FALLING : ACTION_MOVING);
 
-  /* this is needed for CEs with property "can move" / "not moving" */
+  // this is needed for CEs with property "can move" / "not moving"
 
   if (is_moving_after)
   {
@@ -5000,7 +4980,7 @@ void Blocked2Moving(int x, int y, int *comes_from_x, int *comes_from_y)
   *comes_from_y = oldy;
 }
 
-int MovingOrBlocked2Element(int x, int y)
+static int MovingOrBlocked2Element(int x, int y)
 {
   int element = Feld[x][y];
 
@@ -5017,9 +4997,9 @@ int MovingOrBlocked2Element(int x, int y)
 
 static int MovingOrBlocked2ElementIfNotLeaving(int x, int y)
 {
-  /* like MovingOrBlocked2Element(), but if element is moving
-     and (x,y) is the field the moving element is just leaving,
-     return EL_BLOCKED instead of the element value */
+  // like MovingOrBlocked2Element(), but if element is moving
+  // and (x,y) is the field the moving element is just leaving,
+  // return EL_BLOCKED instead of the element value
   int element = Feld[x][y];
 
   if (IS_MOVING(x, y))
@@ -5058,7 +5038,7 @@ static void RemoveField(int x, int y)
   GfxDir[x][y] = MV_NONE;
 }
 
-void RemoveMovingField(int x, int y)
+static void RemoveMovingField(int x, int y)
 {
   int oldx = x, oldy = y, newx = x, newy = y;
   int element = Feld[x][y];
@@ -5073,9 +5053,9 @@ void RemoveMovingField(int x, int y)
 
     if (Feld[newx][newy] != EL_BLOCKED)
     {
-      /* element is moving, but target field is not free (blocked), but
-        already occupied by something different (example: acid pool);
-        in this case, only remove the moving field, but not the target */
+      // element is moving, but target field is not free (blocked), but
+      // already occupied by something different (example: acid pool);
+      // in this case, only remove the moving field, but not the target
 
       RemoveField(oldx, oldy);
 
@@ -5139,9 +5119,9 @@ void DrawDynamite(int x, int y)
     DrawGraphic(sx, sy, graphic, frame);
 }
 
-void CheckDynamite(int x, int y)
+static void CheckDynamite(int x, int y)
 {
-  if (MovDelay[x][y] != 0)     /* dynamite is still waiting to explode */
+  if (MovDelay[x][y] != 0)     // dynamite is still waiting to explode
   {
     MovDelay[x][y]--;
 
@@ -5189,7 +5169,7 @@ static void setMinimalPlayerBoundaries(int *sx1, int *sy1, int *sx2, int *sy2)
   }
 }
 
-static boolean checkIfAllPlayersFitToScreen_RND()
+static boolean checkIfAllPlayersFitToScreen_RND(void)
 {
   int sx1 = 0, sy1 = 0, sx2 = 0, sy2 = 0;
 
@@ -5209,8 +5189,8 @@ static void setScreenCenteredToAllPlayers(int *sx, int *sy)
   *sy = (sy1 + sy2) / 2;
 }
 
-void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir,
-                       boolean center_screen, boolean quick_relocation)
+static void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir,
+                              boolean center_screen, boolean quick_relocation)
 {
   unsigned int frame_delay_value_old = GetVideoFrameDelay();
   boolean ffwd_delay = (tape.playing && tape.fast_forward);
@@ -5221,7 +5201,7 @@ void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir,
 
   if (level.lazy_relocation && IN_VIS_FIELD(SCREENX(x), SCREENY(y)))
   {
-    /* case 1: quick relocation inside visible screen (without scrolling) */
+    // case 1: quick relocation inside visible screen (without scrolling)
 
     RedrawPlayfield();
 
@@ -5230,28 +5210,28 @@ void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir,
 
   if (!level.shifted_relocation || center_screen)
   {
-    /* relocation _with_ centering of screen */
+    // relocation _with_ centering of screen
 
     new_scroll_x = SCROLL_POSITION_X(x);
     new_scroll_y = SCROLL_POSITION_Y(y);
   }
   else
   {
-    /* relocation _without_ centering of screen */
+    // relocation _without_ centering of screen
 
     int center_scroll_x = SCROLL_POSITION_X(old_x);
     int center_scroll_y = SCROLL_POSITION_Y(old_y);
     int offset_x = x + (scroll_x - center_scroll_x);
     int offset_y = y + (scroll_y - center_scroll_y);
 
-    /* for new screen position, apply previous offset to center position */
+    // for new screen position, apply previous offset to center position
     new_scroll_x = SCROLL_POSITION_X(offset_x);
     new_scroll_y = SCROLL_POSITION_Y(offset_y);
   }
 
   if (quick_relocation)
   {
-    /* case 2: quick relocation (redraw without visible scrolling) */
+    // case 2: quick relocation (redraw without visible scrolling)
 
     scroll_x = new_scroll_x;
     scroll_y = new_scroll_y;
@@ -5261,9 +5241,9 @@ void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir,
     return;
   }
 
-  /* case 3: visible relocation (with scrolling to new position) */
+  // case 3: visible relocation (with scrolling to new position)
 
-  ScrollScreen(NULL, SCROLL_GO_ON);    /* scroll last frame to full tile */
+  ScrollScreen(NULL, SCROLL_GO_ON);    // scroll last frame to full tile
 
   SetVideoFrameDelay(wait_delay_value);
 
@@ -5275,7 +5255,7 @@ void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir,
     dx = (new_scroll_x < scroll_x ? +1 : new_scroll_x > scroll_x ? -1 : 0);
     dy = (new_scroll_y < scroll_y ? +1 : new_scroll_y > scroll_y ? -1 : 0);
 
-    if (dx == 0 && dy == 0)            /* no scrolling needed at all */
+    if (dx == 0 && dy == 0)            // no scrolling needed at all
       break;
 
     scroll_x -= dx;
@@ -5287,10 +5267,10 @@ void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir,
     ScrollLevel(dx, dy);
     DrawAllPlayers();
 
-    /* scroll in two steps of half tile size to make things smoother */
+    // scroll in two steps of half tile size to make things smoother
     BlitBitmap(drawto_field, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
 
-    /* scroll second step to align at full tile size */
+    // scroll second step to align at full tile size
     BlitScreenToBitmap(window);
   }
 
@@ -5300,7 +5280,7 @@ void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir,
   SetVideoFrameDelay(frame_delay_value_old);
 }
 
-void RelocatePlayer(int jx, int jy, int el_player_raw)
+static void RelocatePlayer(int jx, int jy, int el_player_raw)
 {
   int el_player = GET_PLAYER_ELEMENT(el_player_raw);
   int player_nr = GET_PLAYER_NR(el_player);
@@ -5324,15 +5304,15 @@ void RelocatePlayer(int jx, int jy, int el_player_raw)
   int enter_side = enter_side_horiz | enter_side_vert;
   int leave_side = leave_side_horiz | leave_side_vert;
 
-  if (player->GameOver)                /* do not reanimate dead player */
+  if (player->GameOver)                // do not reanimate dead player
     return;
 
-  if (!player_relocated)       /* no need to relocate the player */
+  if (!player_relocated)       // no need to relocate the player
     return;
 
-  if (IS_PLAYER(jx, jy))       /* player already placed at new position */
+  if (IS_PLAYER(jx, jy))       // player already placed at new position
   {
-    RemoveField(jx, jy);       /* temporarily remove newly placed player */
+    RemoveField(jx, jy);       // temporarily remove newly placed player
     DrawLevelField(jx, jy);
   }
 
@@ -5350,8 +5330,8 @@ void RelocatePlayer(int jx, int jy, int el_player_raw)
       BackToFront_WithFrameDelay(wait_delay_value);
     }
 
-    DrawPlayer(player);                /* needed here only to cleanup last field */
-    DrawLevelField(player->jx, player->jy);    /* remove player graphic */
+    DrawPlayer(player);                // needed here only to cleanup last field
+    DrawLevelField(player->jx, player->jy);    // remove player graphic
 
     player->is_moving = FALSE;
   }
@@ -5372,12 +5352,12 @@ void RelocatePlayer(int jx, int jy, int el_player_raw)
      possible that the relocation target field did not contain a player element,
      but a walkable element, to which the new player was relocated -- in this
      case, restore that (already initialized!) element on the player field */
-  if (!ELEM_IS_PLAYER(element))        /* player may be set on walkable element */
+  if (!ELEM_IS_PLAYER(element))        // player may be set on walkable element
   {
-    Feld[jx][jy] = element;    /* restore previously existing element */
+    Feld[jx][jy] = element;    // restore previously existing element
   }
 
-  /* only visually relocate centered player */
+  // only visually relocate centered player
   DrawRelocateScreen(old_jx, old_jy, player->jx, player->jy, player->MovDir,
                     FALSE, level.instant_relocation);
 
@@ -5405,13 +5385,13 @@ void RelocatePlayer(int jx, int jy, int el_player_raw)
   }
 }
 
-void Explode(int ex, int ey, int phase, int mode)
+static void Explode(int ex, int ey, int phase, int mode)
 {
   int x, y;
   int last_phase;
   int border_element;
 
-  /* !!! eliminate this variable !!! */
+  // !!! eliminate this variable !!!
   int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
 
   if (game.explosions_delayed)
@@ -5420,26 +5400,26 @@ void Explode(int ex, int ey, int phase, int mode)
     return;
   }
 
-  if (phase == EX_PHASE_START)         /* initialize 'Store[][]' field */
+  if (phase == EX_PHASE_START)         // initialize 'Store[][]' field
   {
     int center_element = Feld[ex][ey];
-    int artwork_element, explosion_element;    /* set these values later */
+    int artwork_element, explosion_element;    // set these values later
 
-    /* remove things displayed in background while burning dynamite */
+    // remove things displayed in background while burning dynamite
     if (Back[ex][ey] != EL_EMPTY && !IS_INDESTRUCTIBLE(Back[ex][ey]))
       Back[ex][ey] = 0;
 
     if (IS_MOVING(ex, ey) || IS_BLOCKED(ex, ey))
     {
-      /* put moving element to center field (and let it explode there) */
+      // put moving element to center field (and let it explode there)
       center_element = MovingOrBlocked2Element(ex, ey);
       RemoveMovingField(ex, ey);
       Feld[ex][ey] = center_element;
     }
 
-    /* now "center_element" is finally determined -- set related values now */
-    artwork_element = center_element;          /* for custom player artwork */
-    explosion_element = center_element;                /* for custom player artwork */
+    // now "center_element" is finally determined -- set related values now
+    artwork_element = center_element;          // for custom player artwork
+    explosion_element = center_element;                // for custom player artwork
 
     if (IS_PLAYER(ex, ey))
     {
@@ -5482,7 +5462,7 @@ void Explode(int ex, int ey, int phase, int mode)
          RemoveMovingField(x, y);
       }
 
-      /* indestructible elements can only explode in center (but not flames) */
+      // indestructible elements can only explode in center (but not flames)
       if ((IS_EXPLOSION_PROOF(element) && (x != ex || y != ey ||
                                           mode == EX_TYPE_BORDER)) ||
          element == EL_FLAMES)
@@ -5491,7 +5471,7 @@ void Explode(int ex, int ey, int phase, int mode)
       /* no idea why this was changed from 3.0.8 to 3.1.0 -- this causes buggy
         behaviour, for example when touching a yamyam that explodes to rocks
         with active deadly shield, a rock is created under the player !!! */
-      /* (case 1 (surely buggy): >= 3.1.0, case 2 (maybe buggy): <= 3.0.8) */
+      // (case 1 (surely buggy): >= 3.1.0, case 2 (maybe buggy): <= 3.0.8)
 #if 0
       if (IS_PLAYER(x, y) && SHIELD_ON(PLAYERINFO(x, y)) &&
          (game.engine_version < VERSION_IDENT(3,1,0,0) ||
@@ -5502,7 +5482,7 @@ void Explode(int ex, int ey, int phase, int mode)
       {
        if (IS_ACTIVE_BOMB(element))
        {
-         /* re-activate things under the bomb like gate or penguin */
+         // re-activate things under the bomb like gate or penguin
          Feld[x][y] = (Back[x][y] ? Back[x][y] : EL_EMPTY);
          Back[x][y] = 0;
        }
@@ -5510,12 +5490,12 @@ void Explode(int ex, int ey, int phase, int mode)
        continue;
       }
 
-      /* save walkable background elements while explosion on same tile */
+      // save walkable background elements while explosion on same tile
       if (IS_WALKABLE(element) && IS_INDESTRUCTIBLE(element) &&
          (x != ex || y != ey || mode == EX_TYPE_BORDER))
        Back[x][y] = element;
 
-      /* ignite explodable elements reached by other explosion */
+      // ignite explodable elements reached by other explosion
       if (element == EL_EXPLOSION)
        element = Store2[x][y];
 
@@ -5540,8 +5520,8 @@ void Explode(int ex, int ey, int phase, int mode)
          Store[x][y] = EL_EMPTY;
       }
 
-      /* !!! check this case -- currently needed for rnd_rado_negundo_v,
-        !!! levels 015 018 019 020 021 022 023 026 027 028 !!! */
+      // !!! 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))
        Store[x][y] = EL_EMPTY;
       else if (center_element == EL_YAMYAM)
@@ -5549,9 +5529,9 @@ void Explode(int ex, int ey, int phase, int mode)
       else if (element_info[center_element].content.e[xx][yy] != EL_EMPTY)
        Store[x][y] = element_info[center_element].content.e[xx][yy];
 #if 1
-      /* needed because EL_BD_BUTTERFLY is not defined as "CAN_EXPLODE"
-        (killing EL_BD_BUTTERFLY with dynamite would result in BD diamond
-        otherwise) -- FIX THIS !!! */
+      // needed because EL_BD_BUTTERFLY is not defined as "CAN_EXPLODE"
+      // (killing EL_BD_BUTTERFLY with dynamite would result in BD diamond
+      // otherwise) -- FIX THIS !!!
       else if (!CAN_EXPLODE(element) && element != EL_BD_BUTTERFLY)
        Store[x][y] = element_info[element].content.e[1][1];
 #else
@@ -5588,13 +5568,13 @@ void Explode(int ex, int ey, int phase, int mode)
   y = ey;
 
   if (phase == 1)
-    GfxFrame[x][y] = 0;                /* restart explosion animation */
+    GfxFrame[x][y] = 0;                // restart explosion animation
 
   last_phase = ExplodeDelay[x][y];
 
   ExplodePhase[x][y] = (phase < last_phase ? phase + 1 : 0);
 
-  /* this can happen if the player leaves an explosion just in time */
+  // this can happen if the player leaves an explosion just in time
   if (GfxElement[x][y] == EL_UNDEFINED)
     GfxElement[x][y] = EL_EMPTY;
 
@@ -5627,9 +5607,9 @@ void Explode(int ex, int ey, int phase, int mode)
       border_explosion = TRUE;
     }
 
-    /* if an element just explodes due to another explosion (chain-reaction),
-       do not immediately end the new explosion when it was the last frame of
-       the explosion (as it would be done in the following "if"-statement!) */
+    // if an element just explodes due to another explosion (chain-reaction),
+    // do not immediately end the new explosion when it was the last frame of
+    // the explosion (as it would be done in the following "if"-statement!)
     if (border_explosion && phase == last_phase)
       return;
   }
@@ -5642,7 +5622,7 @@ void Explode(int ex, int ey, int phase, int mode)
     Store[x][y] = Store2[x][y] = 0;
     GfxElement[x][y] = EL_UNDEFINED;
 
-    /* player can escape from explosions and might therefore be still alive */
+    // player can escape from explosions and might therefore be still alive
     if (element >= EL_PLAYER_IS_EXPLODING_1 &&
        element <= EL_PLAYER_IS_EXPLODING_4)
     {
@@ -5658,7 +5638,7 @@ void Explode(int ex, int ey, int phase, int mode)
                    element_info[explosion_element].content.e[xx][yy]);
     }
 
-    /* restore probably existing indestructible background element */
+    // restore probably existing indestructible background element
     if (Back[x][y] && IS_INDESTRUCTIBLE(Back[x][y]))
       element = Feld[x][y] = Back[x][y];
     Back[x][y] = 0;
@@ -5708,7 +5688,7 @@ void Explode(int ex, int ey, int phase, int mode)
   }
 }
 
-void DynaExplode(int ex, int ey)
+static void DynaExplode(int ex, int ey)
 {
   int i, j;
   int dynabomb_element = Feld[ex][ey];
@@ -5746,7 +5726,7 @@ void DynaExplode(int ex, int ey)
 
       element = Feld[x][y];
 
-      /* do not restart explosions of fields with active bombs */
+      // do not restart explosions of fields with active bombs
       if (element == EL_EXPLOSION && IS_ACTIVE_BOMB(Store2[x][y]))
        continue;
 
@@ -5813,7 +5793,7 @@ void Bang(int x, int y)
     case EL_LAMP:
     case EL_LAMP_ACTIVE:
     case EL_AMOEBA_TO_DIAMOND:
-      if (!IS_PLAYER(x, y))    /* penguin and player may be at same field */
+      if (!IS_PLAYER(x, y))    // penguin and player may be at same field
        explosion_type = EX_TYPE_CENTER;
       break;
 
@@ -5833,7 +5813,7 @@ void Bang(int x, int y)
   CheckTriggeredElementChange(x, y, element, CE_EXPLOSION_OF_X);
 }
 
-void SplashAcid(int x, int y)
+static void SplashAcid(int x, int y)
 {
   if (IN_LEV_FIELD(x - 1, y - 1) && IS_FREE(x - 1, y - 1) &&
       (!IN_LEV_FIELD(x - 1, y - 2) ||
@@ -5848,7 +5828,7 @@ void SplashAcid(int x, int y)
   PlayLevelSound(x, y, SND_ACID_SPLASHING);
 }
 
-static void InitBeltMovement()
+static void InitBeltMovement(void)
 {
   static int belt_base_element[4] =
   {
@@ -5867,7 +5847,7 @@ static void InitBeltMovement()
 
   int x, y, i, j;
 
-  /* set frame order for belt animation graphic according to belt direction */
+  // set frame order for belt animation graphic according to belt direction
   for (i = 0; i < NUM_BELTS; i++)
   {
     int belt_nr = i;
@@ -5959,7 +5939,7 @@ static void ToggleBeltSwitch(int x, int y)
   if (belt_dir_nr == 3)
     belt_dir_nr = 1;
 
-  /* set frame order for belt animation graphic according to belt direction */
+  // set frame order for belt animation graphic according to belt direction
   for (i = 0; i < NUM_BELT_PARTS; i++)
   {
     int element = belt_base_active_element[belt_nr] + i;
@@ -6082,7 +6062,7 @@ static int getInvisibleFromInvisibleActiveElement(int element)
          element);
 }
 
-static void RedrawAllLightSwitchesAndInvisibleElements()
+static void RedrawAllLightSwitchesAndInvisibleElements(void)
 {
   int x, y;
 
@@ -6123,7 +6103,7 @@ static void RedrawAllLightSwitchesAndInvisibleElements()
 
       TEST_DrawLevelField(x, y);
 
-      /* uncrumble neighbour fields, if needed */
+      // uncrumble neighbour fields, if needed
       if (element == EL_INVISIBLE_SAND)
        TEST_DrawLevelFieldCrumbledNeighbours(x, y);
     }
@@ -6136,14 +6116,14 @@ static void RedrawAllLightSwitchesAndInvisibleElements()
 
       TEST_DrawLevelField(x, y);
 
-      /* re-crumble neighbour fields, if needed */
+      // re-crumble neighbour fields, if needed
       if (element == EL_INVISIBLE_SAND)
        TEST_DrawLevelFieldCrumbledNeighbours(x, y);
     }
   }
 }
 
-static void RedrawAllInvisibleElementsForLenses()
+static void RedrawAllInvisibleElementsForLenses(void)
 {
   int x, y;
 
@@ -6172,7 +6152,7 @@ static void RedrawAllInvisibleElementsForLenses()
 
       TEST_DrawLevelField(x, y);
 
-      /* uncrumble neighbour fields, if needed */
+      // uncrumble neighbour fields, if needed
       if (element == EL_INVISIBLE_SAND)
        TEST_DrawLevelFieldCrumbledNeighbours(x, y);
     }
@@ -6185,14 +6165,14 @@ static void RedrawAllInvisibleElementsForLenses()
 
       TEST_DrawLevelField(x, y);
 
-      /* re-crumble neighbour fields, if needed */
+      // re-crumble neighbour fields, if needed
       if (element == EL_INVISIBLE_SAND)
        TEST_DrawLevelFieldCrumbledNeighbours(x, y);
     }
   }
 }
 
-static void RedrawAllInvisibleElementsForMagnifier()
+static void RedrawAllInvisibleElementsForMagnifier(void)
 {
   int x, y;
 
@@ -6285,7 +6265,7 @@ static void ActivateTimegateSwitch(int x, int y)
                EL_DC_TIMEGATE_SWITCH_ACTIVE);
 }
 
-void Impact(int x, int y)
+static void Impact(int x, int y)
 {
   boolean last_line = (y == lev_fieldy - 1);
   boolean object_hit = FALSE;
@@ -6293,7 +6273,7 @@ void Impact(int x, int y)
   int element = Feld[x][y];
   int smashed = EL_STEELWALL;
 
-  if (!last_line)      /* check if element below was hit */
+  if (!last_line)      // check if element below was hit
   {
     if (Feld[x][y + 1] == EL_PLAYER_IS_LEAVING)
       return;
@@ -6302,7 +6282,7 @@ void Impact(int x, int y)
                                         MovDir[x][y + 1] != MV_DOWN ||
                                         MovPos[x][y + 1] <= TILEY / 2));
 
-    /* do not smash moving elements that left the smashed field in time */
+    // do not smash moving elements that left the smashed field in time
     if (game.engine_version >= VERSION_IDENT(2,2,0,7) && IS_MOVING(x, y + 1) &&
        ABS(MovPos[x][y + 1] + getElementMoveStepsize(x, y + 1)) >= TILEX)
       object_hit = FALSE;
@@ -6335,14 +6315,14 @@ void Impact(int x, int y)
     impact = (last_line || object_hit);
   }
 
-  if (!last_line && smashed == EL_ACID)        /* element falls into acid */
+  if (!last_line && smashed == EL_ACID)        // element falls into acid
   {
     SplashAcid(x, y + 1);
     return;
   }
 
-  /* !!! not sufficient for all cases -- see EL_PEARL below !!! */
-  /* only reset graphic animation if graphic really changes after impact */
+  // !!! not sufficient for all cases -- see EL_PEARL below !!!
+  // only reset graphic animation if graphic really changes after impact
   if (impact &&
       el_act_dir2img(element, GfxAction[x][y], MV_DOWN) != el2img(element))
   {
@@ -6387,7 +6367,7 @@ void Impact(int x, int y)
     return;
   }
 
-  if (object_hit)              /* check which object was hit */
+  if (object_hit)              // check which object was hit
   {
     if ((CAN_PASS_MAGIC_WALL(element) && 
         (smashed == EL_MAGIC_WALL ||
@@ -6401,7 +6381,7 @@ void Impact(int x, int y)
         smashed == EL_BD_MAGIC_WALL ? EL_BD_MAGIC_WALL_ACTIVE :
         EL_DC_MAGIC_WALL_ACTIVE);
 
-      /* activate magic wall / mill */
+      // activate magic wall / mill
       SCAN_PLAYFIELD(xx, yy)
       {
        if (Feld[xx][yy] == smashed)
@@ -6523,7 +6503,7 @@ void Impact(int x, int y)
     }
   }
 
-  /* play sound of magic wall / mill */
+  // play sound of magic wall / mill
   if (!last_line &&
       (Feld[x][y + 1] == EL_MAGIC_WALL_ACTIVE ||
        Feld[x][y + 1] == EL_BD_MAGIC_WALL_ACTIVE ||
@@ -6539,12 +6519,12 @@ void Impact(int x, int y)
     return;
   }
 
-  /* play sound of object that hits the ground */
+  // play sound of object that hits the ground
   if (last_line || object_hit)
     PlayLevelSoundElementAction(x, y, element, ACTION_IMPACT);
 }
 
-inline static void TurnRoundExt(int x, int y)
+static void TurnRoundExt(int x, int y)
 {
   static struct
   {
@@ -6605,7 +6585,7 @@ inline static void TurnRoundExt(int x, int y)
 
     if (element == EL_BUG && MovDir[x][y] != old_move_dir)
       MovDelay[x][y] = 9;
-    else if (element == EL_BD_BUTTERFLY)     /* && MovDir[x][y] == left_dir) */
+    else if (element == EL_BD_BUTTERFLY)     // && MovDir[x][y] == left_dir)
       MovDelay[x][y] = 1;
   }
   else if (element == EL_SPACESHIP || element == EL_BD_FIREFLY)
@@ -6619,7 +6599,7 @@ inline static void TurnRoundExt(int x, int y)
 
     if (element == EL_SPACESHIP        && MovDir[x][y] != old_move_dir)
       MovDelay[x][y] = 9;
-    else if (element == EL_BD_FIREFLY)     /* && MovDir[x][y] == right_dir) */
+    else if (element == EL_BD_FIREFLY)     // && MovDir[x][y] == right_dir)
       MovDelay[x][y] = 1;
   }
   else if (element == EL_SP_SNIKSNAK || element == EL_SP_ELECTRON)
@@ -6981,22 +6961,22 @@ inline static void TurnRoundExt(int x, int y)
     {
       static int check_pos[16] =
       {
-       -1,             /*  0 => (invalid)          */
-       7,              /*  1 => MV_LEFT            */
-       3,              /*  2 => MV_RIGHT           */
-       -1,             /*  3 => (invalid)          */
-       1,              /*  4 =>            MV_UP   */
-       0,              /*  5 => MV_LEFT  | MV_UP   */
-       2,              /*  6 => MV_RIGHT | MV_UP   */
-       -1,             /*  7 => (invalid)          */
-       5,              /*  8 =>            MV_DOWN */
-       6,              /*  9 => MV_LEFT  | MV_DOWN */
-       4,              /* 10 => MV_RIGHT | MV_DOWN */
-       -1,             /* 11 => (invalid)          */
-       -1,             /* 12 => (invalid)          */
-       -1,             /* 13 => (invalid)          */
-       -1,             /* 14 => (invalid)          */
-       -1,             /* 15 => (invalid)          */
+       -1,             //  0 => (invalid)
+       7,              //  1 => MV_LEFT
+       3,              //  2 => MV_RIGHT
+       -1,             //  3 => (invalid)
+       1,              //  4 =>            MV_UP
+       0,              //  5 => MV_LEFT  | MV_UP
+       2,              //  6 => MV_RIGHT | MV_UP
+       -1,             //  7 => (invalid)
+       5,              //  8 =>            MV_DOWN
+       6,              //  9 => MV_LEFT  | MV_DOWN
+       4,              // 10 => MV_RIGHT | MV_DOWN
+       -1,             // 11 => (invalid)
+       -1,             // 12 => (invalid)
+       -1,             // 13 => (invalid)
+       -1,             // 14 => (invalid)
+       -1,             // 15 => (invalid)
       };
       static struct
       {
@@ -7017,7 +6997,7 @@ inline static void TurnRoundExt(int x, int y)
       boolean can_clone = FALSE;
       int i;
 
-      /* check if there is any free field around current position */
+      // check if there is any free field around current position
       for (i = 0; i < 8; i++)
       {
        int newx = x + check_xy[i].dx;
@@ -7031,7 +7011,7 @@ inline static void TurnRoundExt(int x, int y)
        }
       }
 
-      if (can_clone)           /* randomly find an element to clone */
+      if (can_clone)           // randomly find an element to clone
       {
        can_clone = FALSE;
 
@@ -7059,7 +7039,7 @@ inline static void TurnRoundExt(int x, int y)
        }
       }
 
-      if (can_clone)           /* randomly find a direction to move */
+      if (can_clone)           // randomly find a direction to move
       {
        can_clone = FALSE;
 
@@ -7086,17 +7066,17 @@ inline static void TurnRoundExt(int x, int y)
        }
       }
 
-      if (can_clone)           /* cloning and moving successful */
+      if (can_clone)           // cloning and moving successful
        return;
 
-      /* cannot clone -- try to move towards player */
+      // cannot clone -- try to move towards player
 
       start_pos = check_pos[MovDir[x][y] & 0x0f];
       check_order = (RND(2) ? -1 : +1);
 
       for (i = 0; i < 3; i++)
       {
-       /* first check start_pos, then previous/next or (next/previous) pos */
+       // first check start_pos, then previous/next or (next/previous) pos
        int pos_raw = start_pos + (i < 2 ? i : -1) * check_order;
        int pos = (pos_raw + 8) % 8;
        int newx = x + check_xy[pos].dx;
@@ -7128,7 +7108,7 @@ inline static void TurnRoundExt(int x, int y)
     boolean can_turn_right =
       CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, right_x,right_y);
 
-    if (element_info[element].move_stepsize == 0)      /* "not moving" */
+    if (element_info[element].move_stepsize == 0)      // "not moving"
       return;
 
     if (move_pattern == MV_TURNING_LEFT)
@@ -7246,7 +7226,7 @@ inline static void TurnRoundExt(int x, int y)
       boolean first_horiz = RND(2);
       int new_move_dir = MovDir[x][y];
 
-      if (element_info[element].move_stepsize == 0)    /* "not moving" */
+      if (element_info[element].move_stepsize == 0)    // "not moving"
       {
        first_horiz = (ABS(attr_x - x) >= ABS(attr_y - y));
        MovDir[x][y] &= (first_horiz ? MV_HORIZONTAL : MV_VERTICAL);
@@ -7302,7 +7282,7 @@ inline static void TurnRoundExt(int x, int y)
       MV_RIGHT,
     };
     boolean hunter_mode = (move_pattern == MV_MAZE_HUNTER);
-    int move_preference = -1000000;    /* start with very low preference */
+    int move_preference = -1000000;    // start with very low preference
     int new_move_dir = MV_NONE;
     int start_test = RND(4);
     int i;
@@ -7332,14 +7312,14 @@ inline static void TurnRoundExt(int x, int y)
 
       if (move_dir_preference > move_preference)
       {
-       /* prefer field that has not been visited for the longest time */
+       // prefer field that has not been visited for the longest time
        move_preference = move_dir_preference;
        new_move_dir = move_dir;
       }
       else if (move_dir_preference == move_preference &&
               move_dir == old_move_dir)
       {
-       /* prefer last direction when all directions are preferred equally */
+       // prefer last direction when all directions are preferred equally
        move_preference = move_dir_preference;
        new_move_dir = move_dir;
       }
@@ -7389,9 +7369,9 @@ static boolean JustBeingPushed(int x, int y)
   return FALSE;
 }
 
-void StartMoving(int x, int y)
+static void StartMoving(int x, int y)
 {
-  boolean started_moving = FALSE;      /* some elements can fall _and_ move */
+  boolean started_moving = FALSE;      // some elements can fall _and_ move
   int element = Feld[x][y];
 
   if (Stop[x][y])
@@ -7718,7 +7698,7 @@ void StartMoving(int x, int y)
     }
     else if (IS_FREE(x, y + 1) || Feld[x][y + 1] == EL_DIAMOND_BREAKING)
     {
-      if (WasJustFalling[x][y])        /* prevent animation from being restarted */
+      if (WasJustFalling[x][y])        // prevent animation from being restarted
        MovDir[x][y] = MV_DOWN;
 
       InitMovingField(x, y, MV_DOWN);
@@ -7762,7 +7742,7 @@ void StartMoving(int x, int y)
       if (can_fall_both)
       {
        if (element == EL_BD_ROCK || element == EL_BD_DIAMOND)
-         can_fall_right = FALSE;       /* slip down on left side */
+         can_fall_right = FALSE;       // slip down on left side
        else
          can_fall_left = !(can_fall_right = RND(2));
 
@@ -7771,7 +7751,7 @@ void StartMoving(int x, int y)
 
       if (can_fall_any)
       {
-       /* if not determined otherwise, prefer left side for slipping down */
+       // if not determined otherwise, prefer left side for slipping down
        InitMovingField(x, y, can_fall_left ? MV_LEFT : MV_RIGHT);
        started_moving = TRUE;
       }
@@ -7798,12 +7778,12 @@ void StartMoving(int x, int y)
       }
       else
       {
-       MovDir[x][y] = 0;       /* if element was moving, stop it */
+       MovDir[x][y] = 0;       // if element was moving, stop it
       }
     }
   }
 
-  /* not "else if" because of elements that can fall and move (EL_SPRING) */
+  // not "else if" because of elements that can fall and move (EL_SPRING)
   if (CAN_MOVE(element) && !started_moving)
   {
     int move_pattern = element_info[element].move_pattern;
@@ -7822,14 +7802,14 @@ void StartMoving(int x, int y)
 
       TestIfElementHitsCustomElement(x, y, MovDir[x][y]);
 
-      if (Feld[x][y] != element)       /* element has changed */
+      if (Feld[x][y] != element)       // element has changed
        return;
     }
 
-    if (!MovDelay[x][y])       /* start new movement phase */
+    if (!MovDelay[x][y])       // start new movement phase
     {
-      /* all objects that can change their move direction after each step
-        (YAMYAM, DARK_YAMYAM and PACMAN go straight until they hit a wall */
+      // all objects that can change their move direction after each step
+      // (YAMYAM, DARK_YAMYAM and PACMAN go straight until they hit a wall
 
       if (element != EL_YAMYAM &&
          element != EL_DARK_YAMYAM &&
@@ -7852,7 +7832,7 @@ void StartMoving(int x, int y)
       }
     }
 
-    if (MovDelay[x][y])                /* wait some time before next movement */
+    if (MovDelay[x][y])                // wait some time before next movement
     {
       MovDelay[x][y]--;
 
@@ -7925,7 +7905,7 @@ void StartMoving(int x, int y)
        }
       }
 
-      if (MovDelay[x][y])      /* element still has to wait some time */
+      if (MovDelay[x][y])      // element still has to wait some time
       {
        PlayLevelSoundAction(x, y, ACTION_WAITING);
 
@@ -7933,9 +7913,9 @@ void StartMoving(int x, int y)
       }
     }
 
-    /* now make next step */
+    // now make next step
 
-    Moving2Blocked(x, y, &newx, &newy);        /* get next screen position */
+    Moving2Blocked(x, y, &newx, &newy);        // get next screen position
 
     if (DONT_COLLIDE_WITH(element) &&
        IN_LEV_FIELD(newx, newy) && IS_PLAYER(newx, newy) &&
@@ -7969,10 +7949,10 @@ void StartMoving(int x, int y)
        if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
          DrawGraphicThruMask(SCREENX(newx),SCREENY(newy), el2img(element), 0);
 
-       local_player->friends_still_needed--;
-       if (!local_player->friends_still_needed &&
+       game.friends_still_needed--;
+       if (!game.friends_still_needed &&
            !local_player->GameOver && AllPlayersGone)
-         PlayerWins(local_player);
+         LevelSolved();
 
        return;
       }
@@ -8026,7 +8006,7 @@ void StartMoving(int x, int y)
        boolean can_clone = FALSE;
        int xx, yy;
 
-       /* check if element to clone is still there */
+       // check if element to clone is still there
        for (yy = y - 1; yy <= y + 1; yy++) for (xx = x - 1; xx <= x + 1; xx++)
        {
          if (IN_LEV_FIELD(xx, yy) && Feld[xx][yy] == Store[x][y])
@@ -8037,7 +8017,7 @@ void StartMoving(int x, int y)
          }
        }
 
-       /* cannot clone or target field not free anymore -- do not clone */
+       // cannot clone or target field not free anymore -- do not clone
        if (!can_clone || !ANDROID_CAN_ENTER_FIELD(element, newx, newy))
          Store[x][y] = EL_EMPTY;
       }
@@ -8051,7 +8031,7 @@ void StartMoving(int x, int y)
          int change_delay = 8;
          int graphic;
 
-         /* android is moving diagonally */
+         // android is moving diagonally
 
          CreateField(x, y, EL_DIAGONAL_SHRINKING);
 
@@ -8112,7 +8092,7 @@ void StartMoving(int x, int y)
       if (move_pattern & MV_MAZE_RUNNER_STYLE)
       {
        RunnerVisit[x][y] = FrameCounter;
-       PlayerVisit[x][y] /= 8;         /* expire player visit path */
+       PlayerVisit[x][y] /= 8;         // expire player visit path
       }
     }
     else if (element == EL_DRAGON && IN_LEV_FIELD(newx, newy))
@@ -8221,11 +8201,11 @@ void StartMoving(int x, int y)
        GfxAction[x][y] = ACTION_DIGGING;
        TEST_DrawLevelField(x, y);
 
-       MovDelay[newx][newy] = 0;       /* start amoeba shrinking delay */
+       MovDelay[newx][newy] = 0;       // start amoeba shrinking delay
 
-       return;                         /* wait for shrinking amoeba */
+       return;                         // wait for shrinking amoeba
       }
-      else     /* element == EL_PACMAN */
+      else     // element == EL_PACMAN
       {
        Feld[newx][newy] = EL_EMPTY;
        TEST_DrawLevelField(newx, newy);
@@ -8236,16 +8216,16 @@ void StartMoving(int x, int y)
             (Feld[newx][newy] == EL_AMOEBA_SHRINKING ||
              (Feld[newx][newy] == EL_EMPTY && Stop[newx][newy])))
     {
-      /* wait for shrinking amoeba to completely disappear */
+      // wait for shrinking amoeba to completely disappear
       return;
     }
     else if (!IN_LEV_FIELD(newx, newy) || !IS_FREE(newx, newy))
     {
-      /* object was running against a wall */
+      // object was running against a wall
 
       TurnRound(x, y);
 
-      if (GFX_ELEMENT(element) != EL_SAND)     /* !!! FIX THIS (crumble) !!! */
+      if (GFX_ELEMENT(element) != EL_SAND)     // !!! FIX THIS (crumble) !!!
        DrawLevelElementAnimation(x, y, element);
 
       if (DONT_TOUCH(element))
@@ -8279,23 +8259,23 @@ void ContinueMoving(int x, int y)
 
   MovPos[x][y] += getElementMoveStepsize(x, y);
 
-  if (pushed_by_player)        /* special case: moving object pushed by player */
+  if (pushed_by_player)        // special case: moving object pushed by player
     MovPos[x][y] = SIGN(MovPos[x][y]) * (TILEX - ABS(PLAYERINFO(x,y)->MovPos));
 
   if (ABS(MovPos[x][y]) < TILEX)
   {
     TEST_DrawLevelField(x, y);
 
-    return;    /* element is still moving */
+    return;    // element is still moving
   }
 
-  /* element reached destination field */
+  // element reached destination field
 
   Feld[x][y] = EL_EMPTY;
   Feld[newx][newy] = element;
-  MovPos[x][y] = 0;    /* force "not moving" for "crumbled sand" */
+  MovPos[x][y] = 0;    // force "not moving" for "crumbled sand"
 
-  if (Store[x][y] == EL_ACID)  /* element is moving into acid pool */
+  if (Store[x][y] == EL_ACID)  // element is moving into acid pool
   {
     element = Feld[newx][newy] = EL_ACID;
   }
@@ -8398,7 +8378,7 @@ void ContinueMoving(int x, int y)
 
   if (CAN_CHANGE_OR_HAS_ACTION(element))
   {
-    /* copy element change control values to new field */
+    // 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];
@@ -8414,22 +8394,22 @@ void ContinueMoving(int x, int y)
 
   CustomValue[x][y] = 0;
 
-  /* copy animation control values to new field */
+  // copy animation control values to new field
   GfxFrame[newx][newy]  = GfxFrame[x][y];
-  GfxRandom[newx][newy] = GfxRandom[x][y];     /* keep same random value */
-  GfxAction[newx][newy] = GfxAction[x][y];     /* keep action one frame  */
-  GfxDir[newx][newy]    = GfxDir[x][y];                /* keep element direction */
+  GfxRandom[newx][newy] = GfxRandom[x][y];     // keep same random value
+  GfxAction[newx][newy] = GfxAction[x][y];     // keep action one frame
+  GfxDir[newx][newy]    = GfxDir[x][y];                // keep element direction
 
   Pushed[x][y] = Pushed[newx][newy] = FALSE;
 
-  /* some elements can leave other elements behind after moving */
+  // some elements can leave other elements behind after moving
   if (ei->move_leave_element != EL_EMPTY &&
       (ei->move_leave_type == LEAVE_TYPE_UNLIMITED || stored != EL_EMPTY) &&
       (!IS_PLAYER(x, y) || IS_WALKABLE(ei->move_leave_element)))
   {
     int move_leave_element = ei->move_leave_element;
 
-    /* this makes it possible to leave the removed element again */
+    // this makes it possible to leave the removed element again
     if (ei->move_leave_element == EL_TRIGGER_ELEMENT)
       move_leave_element = (stored == EL_ACID ? EL_EMPTY : stored);
 
@@ -8447,8 +8427,8 @@ void ContinueMoving(int x, int y)
       RelocatePlayer(x, y, move_leave_element);
   }
 
-  /* do this after checking for left-behind element */
-  ResetGfxAnimation(x, y);     /* reset animation values for old field */
+  // do this after checking for left-behind element
+  ResetGfxAnimation(x, y);     // reset animation values for old field
 
   if (!CAN_MOVE(element) ||
       (CAN_FALL(element) && direction == MV_DOWN &&
@@ -8460,15 +8440,15 @@ void ContinueMoving(int x, int y)
   TEST_DrawLevelField(x, y);
   TEST_DrawLevelField(newx, newy);
 
-  Stop[newx][newy] = TRUE;     /* ignore this element until the next frame */
+  Stop[newx][newy] = TRUE;     // ignore this element until the next frame
 
-  /* prevent pushed element from moving on in pushed direction */
+  // prevent pushed element from moving on in pushed direction
   if (pushed_by_player && CAN_MOVE(element) &&
       element_info[element].move_pattern & MV_ANY_DIRECTION &&
       !(element_info[element].move_pattern & direction))
     TurnRound(newx, newy);
 
-  /* prevent elements on conveyor belt from moving on in last direction */
+  // prevent elements on conveyor belt from moving on in last direction
   if (pushed_by_conveyor && CAN_FALL(element) &&
       direction & MV_HORIZONTAL)
     MovDir[newx][newy] = 0;
@@ -8490,7 +8470,7 @@ void ContinueMoving(int x, int y)
       CheckImpact[newx][newy] = CHECK_DELAY_IMPACT;
   }
 
-  if (DONT_TOUCH(element))     /* object may be nasty to player or others */
+  if (DONT_TOUCH(element))     // object may be nasty to player or others
   {
     TestIfBadThingTouchesPlayer(newx, newy);
     TestIfBadThingTouchesFriend(newx, newy);
@@ -8506,7 +8486,7 @@ void ContinueMoving(int x, int y)
     TestIfGoodThingGetsHitByBadThing(newx, newy, direction);
   }
 
-  /* give the player one last chance (one more frame) to move away */
+  // give the player one last chance (one more frame) to move away
   if (CAN_FALL(element) && direction == MV_DOWN &&
       (last_line || (!IS_FREE(x, newy + 1) &&
                     (!IS_PLAYER(x, newy + 1) ||
@@ -8524,12 +8504,12 @@ void ContinueMoving(int x, int y)
                                        player->index_bit, push_side);
   }
 
-  if (element == EL_EMC_ANDROID && pushed_by_player)   /* make another move */
+  if (element == EL_EMC_ANDROID && pushed_by_player)   // make another move
     MovDelay[newx][newy] = 1;
 
   CheckTriggeredElementChangeBySide(x, y, element, CE_MOVE_OF_X, direction);
 
-  TestIfElementTouchesCustomElement(x, y);     /* empty or new element */
+  TestIfElementTouchesCustomElement(x, y);     // empty or new element
   TestIfElementHitsCustomElement(newx, newy, direction);
   TestIfPlayerTouchesCustomElement(newx, newy);
   TestIfElementTouchesCustomElement(newx, newy);
@@ -8568,7 +8548,7 @@ int AmoebeNachbarNr(int ax, int ay)
   return group_nr;
 }
 
-void AmoebenVereinigen(int ax, int ay)
+static void AmoebenVereinigen(int ax, int ay)
 {
   int i, x, y, xx, yy;
   int new_group_nr = AmoebaNr[ax][ay];
@@ -8675,7 +8655,7 @@ void AmoebeUmwandeln(int ax, int ay)
   }
 }
 
-void AmoebeUmwandelnBD(int ax, int ay, int new_element)
+static void AmoebeUmwandelnBD(int ax, int ay, int new_element)
 {
   int x, y;
   int group_nr = AmoebaNr[ax][ay];
@@ -8711,12 +8691,12 @@ void AmoebeUmwandelnBD(int ax, int ay, int new_element)
                            SND_BD_AMOEBA_TURNING_TO_GEM));
 }
 
-void AmoebeWaechst(int x, int y)
+static void AmoebeWaechst(int x, int y)
 {
   static unsigned int sound_delay = 0;
   static unsigned int sound_delay_value = 0;
 
-  if (!MovDelay[x][y])         /* start new growing cycle */
+  if (!MovDelay[x][y])         // start new growing cycle
   {
     MovDelay[x][y] = 7;
 
@@ -8727,7 +8707,7 @@ void AmoebeWaechst(int x, int y)
     }
   }
 
-  if (MovDelay[x][y])          /* wait some time before growing bigger */
+  if (MovDelay[x][y])          // wait some time before growing bigger
   {
     MovDelay[x][y]--;
     if (MovDelay[x][y]/2 && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
@@ -8747,12 +8727,12 @@ void AmoebeWaechst(int x, int y)
   }
 }
 
-void AmoebaDisappearing(int x, int y)
+static void AmoebaDisappearing(int x, int y)
 {
   static unsigned int sound_delay = 0;
   static unsigned int sound_delay_value = 0;
 
-  if (!MovDelay[x][y])         /* start new shrinking cycle */
+  if (!MovDelay[x][y])         // start new shrinking cycle
   {
     MovDelay[x][y] = 7;
 
@@ -8760,7 +8740,7 @@ void AmoebaDisappearing(int x, int y)
       sound_delay_value = 30;
   }
 
-  if (MovDelay[x][y])          /* wait some time before shrinking */
+  if (MovDelay[x][y])          // wait some time before shrinking
   {
     MovDelay[x][y]--;
     if (MovDelay[x][y]/2 && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
@@ -8776,14 +8756,14 @@ void AmoebaDisappearing(int x, int y)
       Feld[x][y] = EL_EMPTY;
       TEST_DrawLevelField(x, y);
 
-      /* don't let mole enter this field in this cycle;
-        (give priority to objects falling to this field from above) */
+      // don't let mole enter this field in this cycle;
+      // (give priority to objects falling to this field from above)
       Stop[x][y] = TRUE;
     }
   }
 }
 
-void AmoebeAbleger(int ax, int ay)
+static void AmoebeAbleger(int ax, int ay)
 {
   int i;
   int element = Feld[ax][ay];
@@ -8808,17 +8788,17 @@ void AmoebeAbleger(int ax, int ay)
   if (IS_ANIMATED(graphic))
     DrawLevelGraphicAnimationIfNeeded(ax, ay, graphic);
 
-  if (!MovDelay[ax][ay])       /* start making new amoeba field */
+  if (!MovDelay[ax][ay])       // start making new amoeba field
     MovDelay[ax][ay] = RND(FRAMES_PER_SECOND * 25 / (1 + level.amoeba_speed));
 
-  if (MovDelay[ax][ay])                /* wait some time before making new amoeba */
+  if (MovDelay[ax][ay])                // wait some time before making new amoeba
   {
     MovDelay[ax][ay]--;
     if (MovDelay[ax][ay])
       return;
   }
 
-  if (can_drop)                        /* EL_AMOEBA_WET or EL_EMC_DRIPPER */
+  if (can_drop)                        // EL_AMOEBA_WET or EL_EMC_DRIPPER
   {
     int start = RND(4);
     int x = ax + xy[start][0];
@@ -8839,7 +8819,7 @@ void AmoebeAbleger(int ax, int ay)
     if (newax == ax && neway == ay)
       return;
   }
-  else                         /* normal or "filled" (BD style) amoeba */
+  else                         // normal or "filled" (BD style) amoeba
   {
     int start = RND(4);
     boolean waiting_for_player = FALSE;
@@ -8866,7 +8846,7 @@ void AmoebeAbleger(int ax, int ay)
        waiting_for_player = TRUE;
     }
 
-    if (newax == ax && neway == ay)            /* amoeba cannot grow */
+    if (newax == ax && neway == ay)            // amoeba cannot grow
     {
       if (i == 4 && (!waiting_for_player || element == EL_BD_AMOEBA))
       {
@@ -8874,7 +8854,7 @@ void AmoebeAbleger(int ax, int ay)
        TEST_DrawLevelField(ax, ay);
        AmoebaCnt[AmoebaNr[ax][ay]]--;
 
-       if (AmoebaCnt[AmoebaNr[ax][ay]] <= 0)   /* amoeba is completely dead */
+       if (AmoebaCnt[AmoebaNr[ax][ay]] <= 0)   // amoeba is completely dead
        {
          if (element == EL_AMOEBA_FULL)
            AmoebeUmwandeln(ax, ay);
@@ -8886,7 +8866,7 @@ void AmoebeAbleger(int ax, int ay)
     }
     else if (element == EL_AMOEBA_FULL || element == EL_BD_AMOEBA)
     {
-      /* amoeba gets larger by growing in some direction */
+      // amoeba gets larger by growing in some direction
 
       int new_group_nr = AmoebaNr[ax][ay];
 
@@ -8903,7 +8883,7 @@ void AmoebeAbleger(int ax, int ay)
       AmoebaCnt[new_group_nr]++;
       AmoebaCnt2[new_group_nr]++;
 
-      /* if amoeba touches other amoeba(s) after growing, unify them */
+      // if amoeba touches other amoeba(s) after growing, unify them
       AmoebenVereinigen(newax, neway);
 
       if (element == EL_BD_AMOEBA && AmoebaCnt2[new_group_nr] >= 200)
@@ -8917,18 +8897,18 @@ void AmoebeAbleger(int ax, int ay)
   if (!can_drop || neway < ay || !IS_FREE(newax, neway) ||
       (neway == lev_fieldy - 1 && newax != ax))
   {
-    Feld[newax][neway] = EL_AMOEBA_GROWING;    /* creation of new amoeba */
+    Feld[newax][neway] = EL_AMOEBA_GROWING;    // creation of new amoeba
     Store[newax][neway] = element;
   }
   else if (neway == ay || element == EL_EMC_DRIPPER)
   {
-    Feld[newax][neway] = EL_AMOEBA_DROP;       /* drop left/right of amoeba */
+    Feld[newax][neway] = EL_AMOEBA_DROP;       // drop left/right of amoeba
 
     PlayLevelSoundAction(newax, neway, ACTION_GROWING);
   }
   else
   {
-    InitMovingField(ax, ay, MV_DOWN);          /* drop dripping from amoeba */
+    InitMovingField(ax, ay, MV_DOWN);          // drop dripping from amoeba
     Feld[ax][ay] = EL_AMOEBA_DROPPING;
     Store[ax][ay] = EL_AMOEBA_DROP;
     ContinueMoving(ax, ay);
@@ -8938,7 +8918,7 @@ void AmoebeAbleger(int ax, int ay)
   TEST_DrawLevelField(newax, neway);
 }
 
-void Life(int ax, int ay)
+static void Life(int ax, int ay)
 {
   int x1, y1, x2, y2;
   int life_time = 40;
@@ -8954,10 +8934,10 @@ void Life(int ax, int ay)
   if (Stop[ax][ay])
     return;
 
-  if (!MovDelay[ax][ay])       /* start new "game of life" cycle */
+  if (!MovDelay[ax][ay])       // start new "game of life" cycle
     MovDelay[ax][ay] = life_time;
 
-  if (MovDelay[ax][ay])                /* wait some time before next cycle */
+  if (MovDelay[ax][ay])                // wait some time before next cycle
   {
     MovDelay[ax][ay]--;
     if (MovDelay[ax][ay])
@@ -8967,7 +8947,8 @@ void Life(int ax, int ay)
   for (y1 = -1; y1 < 2; y1++) for (x1 = -1; x1 < 2; x1++)
   {
     int xx = ax+x1, yy = ay+y1;
-    int nachbarn = 0;
+    int old_element = Feld[xx][yy];
+    int num_neighbours = 0;
 
     if (!IN_LEV_FIELD(xx, yy))
       continue;
@@ -8979,33 +8960,48 @@ void Life(int ax, int ay)
       if (!IN_LEV_FIELD(x, y) || (x == xx && y == yy))
        continue;
 
-      if (((Feld[x][y] == element ||
-           (element == EL_GAME_OF_LIFE && IS_PLAYER(x, y))) &&
-          !Stop[x][y]) ||
-         (IS_FREE(x, y) && Stop[x][y]))
-       nachbarn++;
+      boolean is_player_cell = (element == EL_GAME_OF_LIFE && IS_PLAYER(x, y));
+      boolean is_neighbour = FALSE;
+
+      if (level.use_life_bugs)
+       is_neighbour =
+         (((Feld[x][y] == element || is_player_cell) && !Stop[x][y]) ||
+          (IS_FREE(x, y)                             &&  Stop[x][y]));
+      else
+       is_neighbour =
+         (Last[x][y] == element || is_player_cell);
+
+      if (is_neighbour)
+       num_neighbours++;
     }
 
-    if (xx == ax && yy == ay)          /* field in the middle */
+    boolean is_free = FALSE;
+
+    if (level.use_life_bugs)
+      is_free = (IS_FREE(xx, yy));
+    else
+      is_free = (IS_FREE(xx, yy) && Last[xx][yy] == EL_EMPTY);
+
+    if (xx == ax && yy == ay)          // field in the middle
     {
-      if (nachbarn < life_parameter[0] ||
-         nachbarn > life_parameter[1])
+      if (num_neighbours < life_parameter[0] ||
+         num_neighbours > life_parameter[1])
       {
        Feld[xx][yy] = EL_EMPTY;
-       if (!Stop[xx][yy])
+       if (Feld[xx][yy] != old_element)
          TEST_DrawLevelField(xx, yy);
        Stop[xx][yy] = TRUE;
        changed = TRUE;
       }
     }
-    else if (IS_FREE(xx, yy) || CAN_GROW_INTO(Feld[xx][yy]))
-    {                                  /* free border field */
-      if (nachbarn >= life_parameter[2] &&
-         nachbarn <= life_parameter[3])
+    else if (is_free || CAN_GROW_INTO(Feld[xx][yy]))
+    {                                  // free border field
+      if (num_neighbours >= life_parameter[2] &&
+         num_neighbours <= life_parameter[3])
       {
        Feld[xx][yy] = element;
        MovDelay[xx][yy] = (element == EL_GAME_OF_LIFE ? 0 : life_time-1);
-       if (!Stop[xx][yy])
+       if (Feld[xx][yy] != old_element)
          TEST_DrawLevelField(xx, yy);
        Stop[xx][yy] = TRUE;
        changed = TRUE;
@@ -9059,7 +9055,7 @@ static void ActivateMagicBall(int bx, int by)
 
   if (level.ball_random)
   {
-    int pos_border = RND(8);   /* select one of the eight border elements */
+    int pos_border = RND(8);   // select one of the eight border elements
     int pos_content = (pos_border > 3 ? pos_border + 1 : pos_border);
     int xx = pos_content % 3;
     int yy = pos_content / 3;
@@ -9085,11 +9081,12 @@ static void ActivateMagicBall(int bx, int by)
   game.ball_content_nr = (game.ball_content_nr + 1) % level.num_ball_contents;
 }
 
-void CheckExit(int x, int y)
+static void CheckExit(int x, int y)
 {
-  if (local_player->gems_still_needed > 0 ||
-      local_player->sokobanfields_still_needed > 0 ||
-      local_player->lights_still_needed > 0)
+  if (game.gems_still_needed > 0 ||
+      game.sokoban_fields_still_needed > 0 ||
+      game.sokoban_objects_still_needed > 0 ||
+      game.lights_still_needed > 0)
   {
     int element = Feld[x][y];
     int graphic = el2img(element);
@@ -9100,7 +9097,7 @@ void CheckExit(int x, int y)
     return;
   }
 
-  if (AllPlayersGone)  /* do not re-open exit door closed after last player */
+  if (AllPlayersGone)  // do not re-open exit door closed after last player
     return;
 
   Feld[x][y] = EL_EXIT_OPENING;
@@ -9108,11 +9105,12 @@ void CheckExit(int x, int y)
   PlayLevelSoundNearest(x, y, SND_CLASS_EXIT_OPENING);
 }
 
-void CheckExitEM(int x, int y)
+static void CheckExitEM(int x, int y)
 {
-  if (local_player->gems_still_needed > 0 ||
-      local_player->sokobanfields_still_needed > 0 ||
-      local_player->lights_still_needed > 0)
+  if (game.gems_still_needed > 0 ||
+      game.sokoban_fields_still_needed > 0 ||
+      game.sokoban_objects_still_needed > 0 ||
+      game.lights_still_needed > 0)
   {
     int element = Feld[x][y];
     int graphic = el2img(element);
@@ -9123,7 +9121,7 @@ void CheckExitEM(int x, int y)
     return;
   }
 
-  if (AllPlayersGone)  /* do not re-open exit door closed after last player */
+  if (AllPlayersGone)  // do not re-open exit door closed after last player
     return;
 
   Feld[x][y] = EL_EM_EXIT_OPENING;
@@ -9131,11 +9129,12 @@ void CheckExitEM(int x, int y)
   PlayLevelSoundNearest(x, y, SND_CLASS_EM_EXIT_OPENING);
 }
 
-void CheckExitSteel(int x, int y)
+static void CheckExitSteel(int x, int y)
 {
-  if (local_player->gems_still_needed > 0 ||
-      local_player->sokobanfields_still_needed > 0 ||
-      local_player->lights_still_needed > 0)
+  if (game.gems_still_needed > 0 ||
+      game.sokoban_fields_still_needed > 0 ||
+      game.sokoban_objects_still_needed > 0 ||
+      game.lights_still_needed > 0)
   {
     int element = Feld[x][y];
     int graphic = el2img(element);
@@ -9146,7 +9145,7 @@ void CheckExitSteel(int x, int y)
     return;
   }
 
-  if (AllPlayersGone)  /* do not re-open exit door closed after last player */
+  if (AllPlayersGone)  // do not re-open exit door closed after last player
     return;
 
   Feld[x][y] = EL_STEEL_EXIT_OPENING;
@@ -9154,11 +9153,12 @@ void CheckExitSteel(int x, int y)
   PlayLevelSoundNearest(x, y, SND_CLASS_STEEL_EXIT_OPENING);
 }
 
-void CheckExitSteelEM(int x, int y)
+static void CheckExitSteelEM(int x, int y)
 {
-  if (local_player->gems_still_needed > 0 ||
-      local_player->sokobanfields_still_needed > 0 ||
-      local_player->lights_still_needed > 0)
+  if (game.gems_still_needed > 0 ||
+      game.sokoban_fields_still_needed > 0 ||
+      game.sokoban_objects_still_needed > 0 ||
+      game.lights_still_needed > 0)
   {
     int element = Feld[x][y];
     int graphic = el2img(element);
@@ -9169,7 +9169,7 @@ void CheckExitSteelEM(int x, int y)
     return;
   }
 
-  if (AllPlayersGone)  /* do not re-open exit door closed after last player */
+  if (AllPlayersGone)  // do not re-open exit door closed after last player
     return;
 
   Feld[x][y] = EL_EM_STEEL_EXIT_OPENING;
@@ -9177,9 +9177,9 @@ void CheckExitSteelEM(int x, int y)
   PlayLevelSoundNearest(x, y, SND_CLASS_EM_STEEL_EXIT_OPENING);
 }
 
-void CheckExitSP(int x, int y)
+static void CheckExitSP(int x, int y)
 {
-  if (local_player->gems_still_needed > 0)
+  if (game.gems_still_needed > 0)
   {
     int element = Feld[x][y];
     int graphic = el2img(element);
@@ -9190,7 +9190,7 @@ void CheckExitSP(int x, int y)
     return;
   }
 
-  if (AllPlayersGone)  /* do not re-open exit door closed after last player */
+  if (AllPlayersGone)  // do not re-open exit door closed after last player
     return;
 
   Feld[x][y] = EL_SP_EXIT_OPENING;
@@ -9198,7 +9198,7 @@ void CheckExitSP(int x, int y)
   PlayLevelSoundNearest(x, y, SND_CLASS_SP_EXIT_OPENING);
 }
 
-static void CloseAllOpenTimegates()
+static void CloseAllOpenTimegates(void)
 {
   int x, y;
 
@@ -9215,7 +9215,7 @@ static void CloseAllOpenTimegates()
   }
 }
 
-void DrawTwinkleOnField(int x, int y)
+static void DrawTwinkleOnField(int x, int y)
 {
   if (!IN_SCR_FIELD(SCREENX(x), SCREENY(y)) || IS_MOVING(x, y))
     return;
@@ -9223,10 +9223,10 @@ void DrawTwinkleOnField(int x, int y)
   if (Feld[x][y] == EL_BD_DIAMOND)
     return;
 
-  if (MovDelay[x][y] == 0)     /* next animation frame */
+  if (MovDelay[x][y] == 0)     // next animation frame
     MovDelay[x][y] = 11 * !GetSimpleRandom(500);
 
-  if (MovDelay[x][y] != 0)     /* wait some time before next frame */
+  if (MovDelay[x][y] != 0)     // wait some time before next frame
   {
     MovDelay[x][y]--;
 
@@ -9242,14 +9242,14 @@ void DrawTwinkleOnField(int x, int y)
   }
 }
 
-void MauerWaechst(int x, int y)
+static void MauerWaechst(int x, int y)
 {
   int delay = 6;
 
-  if (!MovDelay[x][y])         /* next animation frame */
+  if (!MovDelay[x][y])         // next animation frame
     MovDelay[x][y] = 3 * delay;
 
-  if (MovDelay[x][y])          /* wait some time before next frame */
+  if (MovDelay[x][y])          // wait some time before next frame
   {
     MovDelay[x][y]--;
 
@@ -9292,7 +9292,7 @@ void MauerWaechst(int x, int y)
   }
 }
 
-void MauerAbleger(int ax, int ay)
+static void MauerAbleger(int ax, int ay)
 {
   int element = Feld[ax][ay];
   int graphic = el2img(element);
@@ -9305,10 +9305,10 @@ void MauerAbleger(int ax, int ay)
   if (IS_ANIMATED(graphic))
     DrawLevelGraphicAnimationIfNeeded(ax, ay, graphic);
 
-  if (!MovDelay[ax][ay])       /* start building new wall */
+  if (!MovDelay[ax][ay])       // start building new wall
     MovDelay[ax][ay] = 6;
 
-  if (MovDelay[ax][ay])                /* wait some time before building new wall */
+  if (MovDelay[ax][ay])                // wait some time before building new wall
   {
     MovDelay[ax][ay]--;
     if (MovDelay[ax][ay])
@@ -9400,7 +9400,7 @@ void MauerAbleger(int ax, int ay)
     PlayLevelSoundAction(ax, ay, ACTION_GROWING);
 }
 
-void MauerAblegerStahl(int ax, int ay)
+static void MauerAblegerStahl(int ax, int ay)
 {
   int element = Feld[ax][ay];
   int graphic = el2img(element);
@@ -9413,10 +9413,10 @@ void MauerAblegerStahl(int ax, int ay)
   if (IS_ANIMATED(graphic))
     DrawLevelGraphicAnimationIfNeeded(ax, ay, graphic);
 
-  if (!MovDelay[ax][ay])       /* start building new wall */
+  if (!MovDelay[ax][ay])       // start building new wall
     MovDelay[ax][ay] = 6;
 
-  if (MovDelay[ax][ay])                /* wait some time before building new wall */
+  if (MovDelay[ax][ay])                // wait some time before building new wall
   {
     MovDelay[ax][ay]--;
     if (MovDelay[ax][ay])
@@ -9502,7 +9502,7 @@ void MauerAblegerStahl(int ax, int ay)
     PlayLevelSoundAction(ax, ay, ACTION_GROWING);
 }
 
-void CheckForDragon(int x, int y)
+static void CheckForDragon(int x, int y)
 {
   int i, j;
   boolean dragon_found = FALSE;
@@ -9604,7 +9604,7 @@ static void ChangeActiveTrap(int x, int y)
 {
   int graphic = IMG_TRAP_ACTIVE;
 
-  /* if new animation frame was drawn, correct crumbled sand border */
+  // if new animation frame was drawn, correct crumbled sand border
   if (IS_NEW_FRAME(GfxFrame[x][y], graphic))
     TEST_DrawLevelFieldCrumbled(x, y);
 }
@@ -9646,7 +9646,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
   if (!change->has_action)
     return;
 
-  /* ---------- determine action paramater values -------------------------- */
+  // ---------- determine action paramater values -----------------------------
 
   int level_time_value =
     (level.time > 0 ? TimeLeft :
@@ -9706,7 +9706,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
      action_arg == CA_ARG_NUMBER_CE_SCORE ? ei->collect_score :
      action_arg == CA_ARG_NUMBER_CE_DELAY ? GET_CE_DELAY_VALUE(change) :
      action_arg == CA_ARG_NUMBER_LEVEL_TIME ? level_time_value :
-     action_arg == CA_ARG_NUMBER_LEVEL_GEMS ? local_player->gems_still_needed :
+     action_arg == CA_ARG_NUMBER_LEVEL_GEMS ? game.gems_still_needed :
      action_arg == CA_ARG_NUMBER_LEVEL_SCORE ? local_player->score :
      action_arg == CA_ARG_ELEMENT_CV_TARGET ? GET_NEW_CE_VALUE(target_element):
      action_arg == CA_ARG_ELEMENT_CV_TRIGGER ? change->actual_trigger_ce_value:
@@ -9720,7 +9720,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
      -1);
 
   int action_arg_number_old =
-    (action_type == CA_SET_LEVEL_GEMS ? local_player->gems_still_needed :
+    (action_type == CA_SET_LEVEL_GEMS ? game.gems_still_needed :
      action_type == CA_SET_LEVEL_TIME ? TimeLeft :
      action_type == CA_SET_LEVEL_SCORE ? local_player->score :
      action_type == CA_SET_CE_VALUE ? CustomValue[x][y] :
@@ -9743,7 +9743,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
      action_arg == CA_ARG_PLAYER_ACTION ? 1 << GET_PLAYER_NR(action_element) :
      PLAYER_BITS_ANY);
 
-  /* ---------- execute action  -------------------------------------------- */
+  // ---------- execute action  -----------------------------------------------
 
   switch (action_type)
   {
@@ -9752,7 +9752,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
       return;
     }
 
-    /* ---------- level actions  ------------------------------------------- */
+    // ---------- level actions  ----------------------------------------------
 
     case CA_RESTART_LEVEL:
     {
@@ -9774,7 +9774,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
 
     case CA_SET_LEVEL_TIME:
     {
-      if (level.time > 0)      /* only modify limited time value */
+      if (level.time > 0)      // only modify limited time value
       {
        TimeLeft = action_arg_number_new;
 
@@ -9803,12 +9803,11 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
 
     case CA_SET_LEVEL_GEMS:
     {
-      local_player->gems_still_needed = action_arg_number_new;
+      game.gems_still_needed = action_arg_number_new;
 
       game.snapshot.collected_item = TRUE;
 
-      game_panel_controls[GAME_PANEL_GEMS].value =
-       local_player->gems_still_needed;
+      game_panel_controls[GAME_PANEL_GEMS].value = game.gems_still_needed;
 
       DisplayGameControlValues();
 
@@ -9824,17 +9823,17 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
 
     case CA_SET_LEVEL_RANDOM_SEED:
     {
-      /* ensure that setting a new random seed while playing is predictable */
+      // ensure that setting a new random seed while playing is predictable
       InitRND(action_arg_number_new ? action_arg_number_new : RND(1000000) + 1);
 
       break;
     }
 
-    /* ---------- player actions  ------------------------------------------ */
+    // ---------- player actions  ---------------------------------------------
 
     case CA_MOVE_PLAYER:
     {
-      /* automatically move to the next field in specified direction */
+      // automatically move to the next field in specified direction
       for (i = 0; i < MAX_PLAYERS; i++)
        if (trigger_player_bits & (1 << i))
          stored_player[i].programmed_action = action_arg_direction;
@@ -9846,7 +9845,10 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
     {
       for (i = 0; i < MAX_PLAYERS; i++)
        if (action_arg_player_bits & (1 << i))
-         PlayerWins(&stored_player[i]);
+         ExitPlayer(&stored_player[i]);
+
+      if (AllPlayersGone)
+       LevelSolved();
 
       break;
     }
@@ -9984,7 +9986,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
 
          SetPlayerWaiting(&stored_player[i], FALSE);
 
-         /* set number of special actions for bored and sleeping animation */
+         // set number of special actions for bored and sleeping animation
          stored_player[i].num_special_action_bored =
            get_num_special_action(artwork_element,
                                   ACTION_BORING_1, ACTION_BORING_LAST);
@@ -10095,7 +10097,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
       break;
     }
 
-    /* ---------- CE actions  ---------------------------------------------- */
+    // ---------- CE actions  -------------------------------------------------
 
     case CA_SET_CE_VALUE:
     {
@@ -10191,7 +10193,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
       break;
     }
 
-    /* ---------- engine actions  ------------------------------------------ */
+    // ---------- engine actions  ---------------------------------------------
 
     case CA_SET_ENGINE_SCAN_MODE:
     {
@@ -10234,7 +10236,7 @@ static void CreateFieldExt(int x, int y, int element, boolean is_change)
 
     InitField_WithBug1(x, y, FALSE);
 
-    new_element = Feld[x][y];  /* element may have changed */
+    new_element = Feld[x][y];  // element may have changed
 
     ResetGfxAnimation(x, y);
     ResetRandomAnimationValue(x, y);
@@ -10245,9 +10247,9 @@ static void CreateFieldExt(int x, int y, int element, boolean is_change)
       TEST_DrawLevelFieldCrumbledNeighbours(x, y);
   }
 
-  /* 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) */
+  // 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 &&
       IS_ACCESSIBLE(old_element) && !IS_ACCESSIBLE(new_element))
   {
@@ -10256,12 +10258,12 @@ static void CreateFieldExt(int x, int y, int element, boolean is_change)
     return;
   }
 
-  /* "ChangeCount" not set yet to allow "entered by player" change one time */
+  // "ChangeCount" not set yet to allow "entered by player" change one time
   if (new_element_is_player)
     RelocatePlayer(x, y, new_element);
 
   if (is_change)
-    ChangeCount[x][y]++;       /* count number of changes in the same frame */
+    ChangeCount[x][y]++;       // count number of changes in the same frame
 
   TestIfBadThingTouchesPlayer(x, y);
   TestIfPlayerTouchesCustomElement(x, y);
@@ -10281,8 +10283,8 @@ static void CreateElementFromChange(int x, int y, int element)
   {
     int old_element = Feld[x][y];
 
-    /* prevent changed element from moving in same engine frame
-       unless both old and new element can either fall or move */
+    // prevent changed element from moving in same engine frame
+    // unless both old and new element can either fall or move
     if ((!CAN_FALL(old_element) || !CAN_FALL(element)) &&
        (!CAN_MOVE(old_element) || !CAN_MOVE(element)))
       Stop[x][y] = TRUE;
@@ -10300,13 +10302,13 @@ static boolean ChangeElement(int x, int y, int element, int page)
   int target_element;
   int old_element = Feld[x][y];
 
-  /* always use default change event to prevent running into a loop */
+  // always use default change event to prevent running into a loop
   if (ChangeEvent[x][y] == -1)
     ChangeEvent[x][y] = CE_DELAY;
 
   if (ChangeEvent[x][y] == CE_DELAY)
   {
-    /* reset actual trigger element, trigger player and action element */
+    // reset actual trigger element, trigger player and action element
     change->actual_trigger_element = EL_EMPTY;
     change->actual_trigger_player = EL_EMPTY;
     change->actual_trigger_player_bits = CH_PLAYER_NONE;
@@ -10315,11 +10317,11 @@ static boolean ChangeElement(int x, int y, int element, int page)
     change->actual_trigger_ce_score = 0;
   }
 
-  /* do not change elements more than a specified maximum number of changes */
+  // do not change elements more than a specified maximum number of changes
   if (ChangeCount[x][y] >= game.max_num_changes_per_frame)
     return FALSE;
 
-  ChangeCount[x][y]++;         /* count number of changes in the same frame */
+  ChangeCount[x][y]++;         // count number of changes in the same frame
 
   if (change->explode)
   {
@@ -10349,12 +10351,12 @@ static boolean ChangeElement(int x, int y, int element, int page)
 
       can_replace[xx][yy] = TRUE;
 
-      if (ex == x && ey == y)  /* do not check changing element itself */
+      if (ex == x && ey == y)  // do not check changing element itself
        continue;
 
       if (content_element == EL_EMPTY_SPACE)
       {
-       can_replace[xx][yy] = FALSE;    /* do not replace border with space */
+       can_replace[xx][yy] = FALSE;    // do not replace border with space
 
        continue;
       }
@@ -10424,9 +10426,9 @@ static boolean ChangeElement(int x, int y, int element, int page)
 
          something_has_changed = TRUE;
 
-         /* for symmetry reasons, freeze newly created border elements */
+         // for symmetry reasons, freeze newly created border elements
          if (ex != x || ey != y)
-           Stop[ex][ey] = TRUE;        /* no more moving in this frame */
+           Stop[ex][ey] = TRUE;        // no more moving in this frame
        }
       }
 
@@ -10456,7 +10458,7 @@ static boolean ChangeElement(int x, int y, int element, int page)
     PlayLevelSoundElementAction(x, y, element, ACTION_PAGE_1 + page);
   }
 
-  /* this uses direct change before indirect change */
+  // this uses direct change before indirect change
   CheckTriggeredElementChangeByPage(x, y, old_element, CE_CHANGE_OF_X, page);
 
   return TRUE;
@@ -10481,21 +10483,21 @@ static void HandleElementChange(int x, int y, int page)
   }
 #endif
 
-  /* this can happen with classic bombs on walkable, changing elements */
+  // this can happen with classic bombs on walkable, changing elements
   if (!CAN_CHANGE_OR_HAS_ACTION(element))
   {
     return;
   }
 
-  if (ChangeDelay[x][y] == 0)          /* initialize element change */
+  if (ChangeDelay[x][y] == 0)          // initialize element change
   {
     ChangeDelay[x][y] = GET_CHANGE_DELAY(change) + 1;
 
     if (change->can_change)
     {
-      /* !!! not clear why graphic animation should be reset at all here !!! */
-      /* !!! UPDATE: but is needed for correct Snake Bite tail animation !!! */
-      /* !!! SOLUTION: do not reset if graphics engine set to 4 or above !!! */
+      // !!! not clear why graphic animation should be reset at all here !!!
+      // !!! UPDATE: but is needed for correct Snake Bite tail animation !!!
+      // !!! SOLUTION: do not reset if graphics engine set to 4 or above !!!
 
       /*
        GRAPHICAL BUG ADDRESSED BY CHECKING GRAPHICS ENGINE VERSION:
@@ -10535,8 +10537,8 @@ static void HandleElementChange(int x, int y, int page)
        This can also be seen from the debug output for this test element.)
       */
 
-      /* when a custom element is about to change (for example by change delay),
-        do not reset graphic animation when the custom element is moving */
+      // when a custom element is about to change (for example by change delay),
+      // do not reset graphic animation when the custom element is moving
       if (game.graphics_engine_version < 4 &&
          !IS_MOVING(x, y))
       {
@@ -10551,7 +10553,7 @@ static void HandleElementChange(int x, int y, int page)
 
   ChangeDelay[x][y]--;
 
-  if (ChangeDelay[x][y] != 0)          /* continue element change */
+  if (ChangeDelay[x][y] != 0)          // continue element change
   {
     if (change->can_change)
     {
@@ -10564,9 +10566,9 @@ static void HandleElementChange(int x, int y, int page)
        change->change_function(x, y);
     }
   }
-  else                                 /* finish element change */
+  else                                 // finish element change
   {
-    if (ChangePage[x][y] != -1)                /* remember page from delayed change */
+    if (ChangePage[x][y] != -1)                // remember page from delayed change
     {
       page = ChangePage[x][y];
       ChangePage[x][y] = -1;
@@ -10574,15 +10576,15 @@ static void HandleElementChange(int x, int y, int page)
       change = &ei->change_page[page];
     }
 
-    if (IS_MOVING(x, y))               /* never change a running system ;-) */
+    if (IS_MOVING(x, y))               // never change a running system ;-)
     {
-      ChangeDelay[x][y] = 1;           /* try change after next move step */
-      ChangePage[x][y] = page;         /* remember page to use for change */
+      ChangeDelay[x][y] = 1;           // try change after next move step
+      ChangePage[x][y] = page;         // remember page to use for change
 
       return;
     }
 
-    /* special case: set new level random seed before changing element */
+    // special case: set new level random seed before changing element
     if (change->has_action && change->action_type == CA_SET_LEVEL_RANDOM_SEED)
       handle_action_before_change = TRUE;
 
@@ -10657,9 +10659,9 @@ static boolean CheckTriggeredElementChangeExt(int trigger_x, int trigger_y,
            {
              if (change->can_change && !change_done)
              {
-               /* if element already changed in this frame, not only prevent
-                  another element change (checked in ChangeElement()), but
-                  also prevent additional element actions for this element */
+               // if element already changed in this frame, not only prevent
+               // another element change (checked in ChangeElement()), but
+               // also prevent additional element actions for this element
 
                if (ChangeCount[x][y] >= game.max_num_changes_per_frame &&
                    !level.use_action_after_change_bug)
@@ -10672,9 +10674,9 @@ static boolean CheckTriggeredElementChangeExt(int trigger_x, int trigger_y,
              }
              else if (change->has_action)
              {
-               /* if element already changed in this frame, not only prevent
-                  another element change (checked in ChangeElement()), but
-                  also prevent additional element actions for this element */
+               // if element already changed in this frame, not only prevent
+               // another element change (checked in ChangeElement()), but
+               // also prevent additional element actions for this element
 
                if (ChangeCount[x][y] >= game.max_num_changes_per_frame &&
                    !level.use_action_after_change_bug)
@@ -10721,7 +10723,7 @@ static boolean CheckElementChangeExt(int x, int y,
     element = Feld[x][y];
   }
 
-  /* check if element has already changed or is about to change after moving */
+  // check if element has already changed or is about to change after moving
   if ((game.engine_version < VERSION_IDENT(3,2,0,7) &&
        Feld[x][y] != element) ||
 
@@ -10744,7 +10746,7 @@ static boolean CheckElementChangeExt(int x, int y,
       (trigger_event == CE_TOUCHING_X ||
        trigger_event == CE_HITTING_X ||
        trigger_event == CE_HIT_BY_X ||
-       trigger_event == CE_DIGGING_X); /* this one was forgotten until 3.2.3 */
+       trigger_event == CE_DIGGING_X); // this one was forgotten until 3.2.3
 
     if (change->can_change_or_has_action &&
        change->has_event[trigger_event] &&
@@ -10760,7 +10762,7 @@ static boolean CheckElementChangeExt(int x, int y,
       change->actual_trigger_ce_value = CustomValue[x][y];
       change->actual_trigger_ce_score = GET_CE_SCORE(trigger_element);
 
-      /* special case: trigger element not at (x,y) position for some events */
+      // special case: trigger element not at (x,y) position for some events
       if (check_trigger_element)
       {
        static struct
@@ -10830,7 +10832,7 @@ static void PlayPlayerSound(struct PlayerInfo *player)
   }
 }
 
-static void PlayAllPlayersSound()
+static void PlayAllPlayersSound(void)
 {
   int i;
 
@@ -10849,7 +10851,7 @@ static void SetPlayerWaiting(struct PlayerInfo *player, boolean is_waiting)
 
   if (is_waiting)
   {
-    if (!last_waiting)         /* not waiting -> waiting */
+    if (!last_waiting)         // not waiting -> waiting
     {
       player->is_waiting = TRUE;
 
@@ -10882,7 +10884,7 @@ static void SetPlayerWaiting(struct PlayerInfo *player, boolean is_waiting)
 
     if (player->is_sleeping && player->use_murphy)
     {
-      /* special case for sleeping Murphy when leaning against non-free tile */
+      // special case for sleeping Murphy when leaning against non-free tile
 
       if (!IN_LEV_FIELD(player->jx - 1, player->jy) ||
          (Feld[player->jx - 1][player->jy] != EL_EMPTY &&
@@ -10968,7 +10970,7 @@ static void SetPlayerWaiting(struct PlayerInfo *player, boolean is_waiting)
       }
     }
   }
-  else if (last_waiting)       /* waiting -> not waiting */
+  else if (last_waiting)       // waiting -> not waiting
   {
     player->is_waiting = FALSE;
     player->is_bored = FALSE;
@@ -11026,7 +11028,7 @@ static void CheckSingleStepMode(struct PlayerInfo *player)
        !player->is_dropping_pressed)
     {
       TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
-      SnapField(player, 0, 0);                 /* stop snapping */
+      SnapField(player, 0, 0);                 // stop snapping
     }
   }
 
@@ -11067,7 +11069,7 @@ static byte PlayerActions(struct PlayerInfo *player, byte player_action)
   }
   else
   {
-    /* no actions for this player (no input at player's configured device) */
+    // no actions for this player (no input at player's configured device)
 
     DigField(player, 0, 0, 0, 0, 0, 0, DF_NO_PUSH);
     SnapField(player, 0, 0);
@@ -11076,7 +11078,7 @@ static byte PlayerActions(struct PlayerInfo *player, byte player_action)
     if (player->MovPos == 0)
       SetPlayerWaiting(player, TRUE);
 
-    if (player->MovPos == 0)   /* needed for tape.playing */
+    if (player->MovPos == 0)   // needed for tape.playing
       player->is_moving = FALSE;
 
     player->is_dropping = FALSE;
@@ -11111,58 +11113,58 @@ static void SetTapeActionFromMouseAction(byte *tape_action,
   tape_action[TAPE_ACTION_BUTTON] = mouse_action->button;
 }
 
-static void CheckLevelTime()
+static void CheckLevelSolved(void)
 {
-  int i;
-
-  /* !!! SAME CODE AS IN "GameActions()" -- FIX THIS !!! */
   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
   {
-    if (level.native_em_level->lev->home == 0) /* all players at home */
+    if (game_em.level_solved &&
+       !game_em.game_over)                             // game won
     {
-      PlayerWins(local_player);
+      LevelSolved();
 
-      AllPlayersGone = TRUE;
+      game_em.game_over = TRUE;
 
-      level.native_em_level->lev->home = -1;
+      AllPlayersGone = TRUE;
     }
 
-    if (level.native_em_level->ply[0]->alive == 0 &&
-       level.native_em_level->ply[1]->alive == 0 &&
-       level.native_em_level->ply[2]->alive == 0 &&
-       level.native_em_level->ply[3]->alive == 0)      /* all dead */
+    if (game_em.game_over)                             // game lost
       AllPlayersGone = TRUE;
   }
   else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
   {
-    if (game_sp.LevelSolved &&
-       !game_sp.GameOver)                              /* game won */
+    if (game_sp.level_solved &&
+       !game_sp.game_over)                             // game won
     {
-      PlayerWins(local_player);
+      LevelSolved();
 
-      game_sp.GameOver = TRUE;
+      game_sp.game_over = TRUE;
 
       AllPlayersGone = TRUE;
     }
 
-    if (game_sp.GameOver)                              /* game lost */
+    if (game_sp.game_over)                             // game lost
       AllPlayersGone = TRUE;
   }
   else if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
   {
     if (game_mm.level_solved &&
-       !game_mm.game_over)                             /* game won */
+       !game_mm.game_over)                             // game won
     {
-      PlayerWins(local_player);
+      LevelSolved();
 
       game_mm.game_over = TRUE;
 
       AllPlayersGone = TRUE;
     }
 
-    if (game_mm.game_over)                             /* game lost */
+    if (game_mm.game_over)                             // game lost
       AllPlayersGone = TRUE;
   }
+}
+
+static void CheckLevelTime(void)
+{
+  int i;
 
   if (TimeFrames >= FRAMES_PER_SECOND)
   {
@@ -11182,7 +11184,7 @@ static void CheckLevelTime()
       }
     }
 
-    if (!local_player->LevelSolved && !level.use_step_counter)
+    if (!game.LevelSolved && !level.use_step_counter)
     {
       TimePlayed++;
 
@@ -11207,7 +11209,7 @@ static void CheckLevelTime()
              KillPlayer(&stored_player[i]);
        }
       }
-      else if (game.no_time_limit && !AllPlayersGone) /* level w/o time limit */
+      else if (game.no_time_limit && !AllPlayersGone) // level w/o time limit
       {
        game_panel_controls[GAME_PANEL_TIME].value = TimePlayed;
       }
@@ -11230,21 +11232,21 @@ void AdvanceFrameAndPlayerCounters(int player_nr)
 {
   int i;
 
-  /* advance frame counters (global frame counter and time frame counter) */
+  // advance frame counters (global frame counter and time frame counter)
   FrameCounter++;
   TimeFrames++;
 
-  /* advance player counters (counters for move delay, move animation etc.) */
+  // advance player counters (counters for move delay, move animation etc.)
   for (i = 0; i < MAX_PLAYERS; i++)
   {
     boolean advance_player_counters = (player_nr == -1 || player_nr == i);
     int move_delay_value = stored_player[i].move_delay_value;
     int move_frames = MOVE_DELAY_NORMAL_SPEED / move_delay_value;
 
-    if (!advance_player_counters)      /* not all players may be affected */
+    if (!advance_player_counters)      // not all players may be affected
       continue;
 
-    if (move_frames == 0)      /* less than one move per game frame */
+    if (move_frames == 0)      // less than one move per game frame
     {
       int stepsize = TILEX / move_delay_value;
       int delay = move_delay_value / MOVE_DELAY_NORMAL_SPEED;
@@ -11263,7 +11265,7 @@ void AdvanceFrameAndPlayerCounters(int player_nr)
     if (stored_player[i].move_delay > 0)
       stored_player[i].move_delay--;
 
-    /* due to bugs in previous versions, counter must count up, not down */
+    // due to bugs in previous versions, counter must count up, not down
     if (stored_player[i].push_delay != -1)
       stored_player[i].push_delay++;
 
@@ -11285,6 +11287,7 @@ void StartGameActions(boolean init_network_game, boolean record_tape,
 
   if (init_network_game)
   {
+    SendToServer_LevelFile();
     SendToServer_StartPlaying();
 
     return;
@@ -11293,7 +11296,7 @@ void StartGameActions(boolean init_network_game, boolean record_tape,
   InitGame();
 }
 
-void GameActionsExt()
+static void GameActionsExt(void)
 {
 #if 0
   static unsigned int game_frame_delay = 0;
@@ -11304,7 +11307,7 @@ void GameActionsExt()
   byte tape_action[MAX_PLAYERS];
   int i;
 
-  /* detect endless loops, caused by custom element programming */
+  // detect endless loops, caused by custom element programming
   if (recursion_loop_detected && recursion_loop_depth == 0)
   {
     char *message = getStringCat3("Internal Error! Element ",
@@ -11316,7 +11319,7 @@ void GameActionsExt()
 
     RequestQuitGameExt(FALSE, level_editor_test_game, message);
 
-    recursion_loop_detected = FALSE;   /* if game should be continued */
+    recursion_loop_detected = FALSE;   // if game should be continued
 
     free(message);
 
@@ -11326,62 +11329,15 @@ void GameActionsExt()
   if (game.restart_level)
     StartGameActions(network.enabled, setup.autorecord, level.random_seed);
 
-  /* !!! SAME CODE AS IN "CheckLevelTime()" -- FIX THIS !!! */
-  if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
-  {
-    if (level.native_em_level->lev->home == 0) /* all players at home */
-    {
-      PlayerWins(local_player);
-
-      AllPlayersGone = TRUE;
-
-      level.native_em_level->lev->home = -1;
-    }
-
-    if (level.native_em_level->ply[0]->alive == 0 &&
-       level.native_em_level->ply[1]->alive == 0 &&
-       level.native_em_level->ply[2]->alive == 0 &&
-       level.native_em_level->ply[3]->alive == 0)      /* all dead */
-      AllPlayersGone = TRUE;
-  }
-  else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
-  {
-    if (game_sp.LevelSolved &&
-       !game_sp.GameOver)                              /* game won */
-    {
-      PlayerWins(local_player);
-
-      game_sp.GameOver = TRUE;
-
-      AllPlayersGone = TRUE;
-    }
-
-    if (game_sp.GameOver)                              /* game lost */
-      AllPlayersGone = TRUE;
-  }
-  else if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
-  {
-    if (game_mm.level_solved &&
-       !game_mm.game_over)                             /* game won */
-    {
-      PlayerWins(local_player);
-
-      game_mm.game_over = TRUE;
-
-      AllPlayersGone = TRUE;
-    }
-
-    if (game_mm.game_over)                             /* game lost */
-      AllPlayersGone = TRUE;
-  }
+  CheckLevelSolved();
 
-  if (local_player->LevelSolved && !local_player->LevelSolved_GameEnd)
+  if (game.LevelSolved && !game.LevelSolved_GameEnd)
     GameWon();
 
   if (AllPlayersGone && !TAPE_IS_STOPPED(tape))
     TapeStop();
 
-  if (game_status != GAME_MODE_PLAYING)                /* status might have changed */
+  if (game_status != GAME_MODE_PLAYING)                // status might have changed
     return;
 
   game_frame_delay_value =
@@ -11394,14 +11350,14 @@ void GameActionsExt()
 
 #if 0
 #if 0
-  /* ---------- main game synchronization point ---------- */
+  // ---------- main game synchronization point ----------
 
   int skip = WaitUntilDelayReached(&game_frame_delay, game_frame_delay_value);
 
   printf("::: skip == %d\n", skip);
 
 #else
-  /* ---------- main game synchronization point ---------- */
+  // ---------- main game synchronization point ----------
 
   WaitUntilDelayReached(&game_frame_delay, game_frame_delay_value);
 #endif
@@ -11409,29 +11365,30 @@ void GameActionsExt()
 
   if (network_playing && !network_player_action_received)
   {
-    /* try to get network player actions in time */
+    // try to get network player actions in time
 
-    /* last chance to get network player actions without main loop delay */
+    // last chance to get network player actions without main loop delay
     HandleNetworking();
 
-    /* game was quit by network peer */
+    // game was quit by network peer
     if (game_status != GAME_MODE_PLAYING)
       return;
 
-    if (!network_player_action_received)
-      return;          /* failed to get network player actions in time */
+    // check if network player actions still missing and game still running
+    if (!network_player_action_received && !checkGameEnded())
+      return;          // failed to get network player actions in time
 
-    /* do not yet reset "network_player_action_received" (for tape.pausing) */
+    // do not yet reset "network_player_action_received" (for tape.pausing)
   }
 
   if (tape.pausing)
     return;
 
-  /* at this point we know that we really continue executing the game */
+  // at this point we know that we really continue executing the game
 
   network_player_action_received = FALSE;
 
-  /* when playing tape, read previously recorded player input from tape data */
+  // when playing tape, read previously recorded player input from tape data
   recorded_player_action = (tape.playing ? TapePlayAction() : NULL);
 
   local_player->effective_mouse_action = local_player->mouse_action;
@@ -11440,7 +11397,7 @@ void GameActionsExt()
     SetMouseActionFromTapeAction(&local_player->effective_mouse_action,
                                 recorded_player_action);
 
-  /* TapePlayAction() may return NULL when toggling to "pause before death" */
+  // TapePlayAction() may return NULL when toggling to "pause before death"
   if (tape.pausing)
     return;
 
@@ -11458,7 +11415,7 @@ void GameActionsExt()
       stored_player[i].effective_action = stored_player[i].action;
   }
 
-  if (network_playing)
+  if (network_playing && !checkGameEnded())
     SendToServer_MovePlayer(summarized_player_action);
 
   // summarize all actions at local players mapped input device position
@@ -11497,7 +11454,7 @@ void GameActionsExt()
   SetTapeActionFromMouseAction(tape_action,
                               &local_player->effective_mouse_action);
 
-  /* only record actions from input devices, but not programmed actions */
+  // only record actions from input devices, but not programmed actions
   if (tape.recording)
     TapeRecordAction(tape_action);
 
@@ -11572,9 +11529,10 @@ void GameActionsExt()
 
   BlitScreenToBitmap(backbuffer);
 
+  CheckLevelSolved();
   CheckLevelTime();
 
-  AdvanceFrameAndPlayerCounters(-1);   /* advance counters for all players */
+  AdvanceFrameAndPlayerCounters(-1);   // advance counters for all players
 
   if (global.show_frames_per_second)
   {
@@ -11584,24 +11542,24 @@ void GameActionsExt()
 
     fps_frames++;
 
-    if (fps_delay_ms >= 500)   /* calculate FPS every 0.5 seconds */
+    if (fps_delay_ms >= 500)   // calculate FPS every 0.5 seconds
     {
       global.frames_per_second = 1000 * (float)fps_frames / fps_delay_ms;
 
       fps_frames = 0;
       fps_counter = Counter();
 
-      /* always draw FPS to screen after FPS value was updated */
+      // always draw FPS to screen after FPS value was updated
       redraw_mask |= REDRAW_FPS;
     }
 
-    /* only draw FPS if no screen areas are deactivated (invisible warp mode) */
+    // only draw FPS if no screen areas are deactivated (invisible warp mode)
     if (GetDrawDeactivationMask() == REDRAW_NONE)
       redraw_mask |= REDRAW_FPS;
   }
 }
 
-static void GameActions_CheckSaveEngineSnapshot()
+static void GameActions_CheckSaveEngineSnapshot(void)
 {
   if (!game.snapshot.save_snapshot)
     return;
@@ -11612,14 +11570,14 @@ static void GameActions_CheckSaveEngineSnapshot()
   SaveEngineSnapshotToList();
 }
 
-void GameActions()
+void GameActions(void)
 {
   GameActionsExt();
 
   GameActions_CheckSaveEngineSnapshot();
 }
 
-void GameActions_EM_Main()
+void GameActions_EM_Main(void)
 {
   byte effective_action[MAX_PLAYERS];
   boolean warp_mode = (tape.playing && tape.warp_forward && !tape.pausing);
@@ -11631,7 +11589,7 @@ void GameActions_EM_Main()
   GameActions_EM(effective_action, warp_mode);
 }
 
-void GameActions_SP_Main()
+void GameActions_SP_Main(void)
 {
   byte effective_action[MAX_PLAYERS];
   boolean warp_mode = (tape.playing && tape.warp_forward && !tape.pausing);
@@ -11651,19 +11609,19 @@ void GameActions_SP_Main()
   }
 }
 
-void GameActions_MM_Main()
+void GameActions_MM_Main(void)
 {
   boolean warp_mode = (tape.playing && tape.warp_forward && !tape.pausing);
 
   GameActions_MM(local_player->effective_mouse_action, warp_mode);
 }
 
-void GameActions_RND_Main()
+void GameActions_RND_Main(void)
 {
   GameActions_RND();
 }
 
-void GameActions_RND()
+void GameActions_RND(void)
 {
   int magic_wall_x = 0, magic_wall_y = 0;
   int i, x, y, element, graphic, last_gfx_frame;
@@ -11683,14 +11641,14 @@ void GameActions_RND()
   {
     boolean all_players_fit_to_screen = checkIfAllPlayersFitToScreen_RND();
 
-    /* switching to "all players" only possible if all players fit to screen */
+    // switching to "all players" only possible if all players fit to screen
     if (game.centered_player_nr_next == -1 && !all_players_fit_to_screen)
     {
       game.centered_player_nr_next = game.centered_player_nr;
       game.set_centered_player = FALSE;
     }
 
-    /* do not switch focus to non-existing (or non-active) player */
+    // do not switch focus to non-existing (or non-active) player
     if (game.centered_player_nr_next >= 0 &&
        !stored_player[game.centered_player_nr_next].active)
     {
@@ -11700,7 +11658,7 @@ void GameActions_RND()
   }
 
   if (game.set_centered_player &&
-      ScreenMovPos == 0)       /* screen currently aligned at tile position */
+      ScreenMovPos == 0)       // screen currently aligned at tile position
   {
     int sx, sy;
 
@@ -11736,7 +11694,7 @@ void GameActions_RND()
       CheckGravityMovement(&stored_player[i]);
 #endif
 
-    /* overwrite programmed action with tape action */
+    // overwrite programmed action with tape action
     if (stored_player[i].programmed_action)
       actual_player_action = stored_player[i].programmed_action;
 
@@ -11770,7 +11728,7 @@ void GameActions_RND()
       {
        ContinueMoving(x, y);
 
-       /* continue moving after pushing (this is actually a bug) */
+       // continue moving after pushing (this is actually a bug)
        if (!IS_MOVING(x, y))
          Stop[x][y] = FALSE;
       }
@@ -11779,10 +11737,12 @@ void GameActions_RND()
 
   SCAN_PLAYFIELD(x, y)
   {
+    Last[x][y] = Feld[x][y];
+
     ChangeCount[x][y] = 0;
     ChangeEvent[x][y] = -1;
 
-    /* this must be handled before main playfield loop */
+    // this must be handled before main playfield loop
     if (Feld[x][y] == EL_PLAYER_IS_LEAVING)
     {
       MovDelay[x][y]--;
@@ -11798,7 +11758,7 @@ void GameActions_RND()
        RemoveField(x, y);
        TEST_DrawLevelField(x, y);
 
-       TestIfElementTouchesCustomElement(x, y);        /* for empty space */
+       TestIfElementTouchesCustomElement(x, y);        // for empty space
       }
     }
 
@@ -11876,7 +11836,7 @@ void GameActions_RND()
       continue;
     }
 
-    /* this may take place after moving, so 'element' may have changed */
+    // this may take place after moving, so 'element' may have changed
     if (IS_CHANGING(x, y) &&
        (game.engine_version < VERSION_IDENT(3,0,7,1) || !Stop[x][y]))
     {
@@ -11962,7 +11922,7 @@ void GameActions_RND()
     else if (element == EL_FLAMES)
       CheckForDragon(x, y);
     else if (element == EL_EXPLOSION)
-      ;        /* drawing of correct explosion animation is handled separately */
+      ;        // drawing of correct explosion animation is handled separately
     else if (element == EL_ELEMENT_SNAPPING ||
             element == EL_DIAGONAL_SHRINKING ||
             element == EL_DIAGONAL_GROWING)
@@ -11981,7 +11941,7 @@ void GameActions_RND()
     {
       int jx = local_player->jx, jy = local_player->jy;
 
-      /* play the element sound at the position nearest to the player */
+      // play the element sound at the position nearest to the player
       if ((element == EL_MAGIC_WALL_FULL ||
           element == EL_MAGIC_WALL_ACTIVE ||
           element == EL_MAGIC_WALL_EMPTYING ||
@@ -12000,7 +11960,7 @@ void GameActions_RND()
   }
 
 #if USE_NEW_AMOEBA_CODE
-  /* new experimental amoeba growth stuff */
+  // new experimental amoeba growth stuff
   if (!(FrameCounter % 8))
   {
     static unsigned int random = 1684108901;
@@ -12180,7 +12140,7 @@ void GameActions_RND()
     local_player->show_envelope = 0;
   }
 
-  /* use random number generator in every frame to make it less predictable */
+  // use random number generator in every frame to make it less predictable
   if (game.engine_version >= VERSION_IDENT(3,1,1,0))
     RND(1);
 }
@@ -12206,7 +12166,7 @@ static boolean AllPlayersInSight(struct PlayerInfo *player, int x, int y)
   return (max_x - min_x < SCR_FIELDX && max_y - min_y < SCR_FIELDY);
 }
 
-static boolean AllPlayersInVisibleScreen()
+static boolean AllPlayersInVisibleScreen(void)
 {
   int i;
 
@@ -12381,9 +12341,9 @@ boolean MovePlayerOneStep(struct PlayerInfo *player,
   if (can_move != MP_MOVING)
     return can_move;
 
-  /* check if DigField() has caused relocation of the player */
+  // check if DigField() has caused relocation of the player
   if (player->jx != jx || player->jy != jy)
-    return MP_NO_ACTION;       /* <-- !!! CHECK THIS [-> MP_ACTION ?] !!! */
+    return MP_NO_ACTION;       // <-- !!! CHECK THIS [-> MP_ACTION ?] !!!
 
   StorePlayer[jx][jy] = 0;
   player->last_jx = jx;
@@ -12408,7 +12368,7 @@ boolean MovePlayerOneStep(struct PlayerInfo *player,
   player->is_moving = TRUE;
 
 #if 1
-  /* should better be called in MovePlayer(), but this breaks some tapes */
+  // should better be called in MovePlayer(), but this breaks some tapes
   ScrollPlayer(player, SCROLL_INIT);
 #endif
 
@@ -12441,18 +12401,18 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
   if (player->move_delay > 0)
     return FALSE;
 
-  player->move_delay = -1;             /* set to "uninitialized" value */
+  player->move_delay = -1;             // set to "uninitialized" value
 
-  /* store if player is automatically moved to next field */
+  // store if player is automatically moved to next field
   player->is_auto_moving = (player->programmed_action != MV_NONE);
 
-  /* remove the last programmed player action */
+  // remove the last programmed player action
   player->programmed_action = 0;
 
   if (player->MovPos)
   {
-    /* should only happen if pre-1.2 tape recordings are played */
-    /* this is only for backward compatibility */
+    // should only happen if pre-1.2 tape recordings are played
+    // this is only for backward compatibility
 
     int original_move_delay_value = player->move_delay_value;
 
@@ -12461,7 +12421,7 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
           tape.counter);
 #endif
 
-    /* scroll remaining steps with finest movement resolution */
+    // scroll remaining steps with finest movement resolution
     player->move_delay_value = MOVE_DELAY_NORMAL_SPEED;
 
     while (player->MovPos)
@@ -12512,46 +12472,46 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
 
     if (!IN_VIS_FIELD(SCREENX(jx), SCREENY(jy)))
     {
-      /* actual player has left the screen -- scroll in that direction */
-      if (jx != old_jx)                /* player has moved horizontally */
+      // actual player has left the screen -- scroll in that direction
+      if (jx != old_jx)                // player has moved horizontally
        scroll_x += (jx - old_jx);
-      else                     /* player has moved vertically */
+      else                     // player has moved vertically
        scroll_y += (jy - old_jy);
     }
     else
     {
-      if (jx != old_jx)                /* player has moved horizontally */
+      if (jx != old_jx)                // player has moved horizontally
       {
        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);
 
-       /* don't scroll over playfield boundaries */
+       // 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 more than one field at a time */
+       // don't scroll more than one field at a time
        scroll_x = old_scroll_x + SIGN(scroll_x - old_scroll_x);
 
-       /* don't scroll against the player's moving direction */
+       // don't scroll against the player's moving direction
        if ((player->MovDir == MV_LEFT  && scroll_x > old_scroll_x) ||
            (player->MovDir == MV_RIGHT && scroll_x < old_scroll_x))
          scroll_x = old_scroll_x;
       }
-      else                     /* player has moved vertically */
+      else                     // player has moved vertically
       {
        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 */
+       // 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);
 
-       /* don't scroll more than one field at a time */
+       // don't scroll more than one field at a time
        scroll_y = old_scroll_y + SIGN(scroll_y - old_scroll_y);
 
-       /* don't scroll against the player's moving direction */
+       // don't scroll against the player's moving direction
        if ((player->MovDir == MV_UP   && scroll_y > old_scroll_y) ||
            (player->MovDir == MV_DOWN && scroll_y < old_scroll_y))
          scroll_y = old_scroll_y;
@@ -12583,7 +12543,7 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
     else if (old_jx == jx && old_jy != jy)
       player->MovDir = (old_jy < jy ? MV_DOWN : MV_UP);
 
-    TEST_DrawLevelField(jx, jy);       /* for "crumbled sand" */
+    TEST_DrawLevelField(jx, jy);       // for "crumbled sand"
 
     player->last_move_dir = player->MovDir;
     player->is_moving = TRUE;
@@ -12594,7 +12554,7 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
     player->drop_pressed_delay = 0;
 
 #if 0
-    /* should better be called here than above, but this breaks some tapes */
+    // should better be called here than above, but this breaks some tapes
     ScrollPlayer(player, SCROLL_INIT);
 #endif
   }
@@ -12610,10 +12570,10 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
        the player was forced to wait again for eight frames before next try) */
 
     if (game.engine_version >= VERSION_IDENT(3,1,1,0))
-      player->move_delay = 0;  /* allow direct movement in the next frame */
+      player->move_delay = 0;  // allow direct movement in the next frame
   }
 
-  if (player->move_delay == -1)                /* not yet initialized by DigField() */
+  if (player->move_delay == -1)                // not yet initialized by DigField()
     player->move_delay = player->move_delay_value;
 
   if (game.engine_version < VERSION_IDENT(3,0,7,0))
@@ -12637,7 +12597,7 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
   if (!player->active)
     return;
 
-  if (player->MovPos == 0 && mode == SCROLL_GO_ON)     /* player not moving */
+  if (player->MovPos == 0 && mode == SCROLL_GO_ON)     // player not moving
     return;
 
   if (mode == SCROLL_INIT)
@@ -12648,27 +12608,27 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
     if ((player->block_last_field || player->block_delay_adjustment > 0) &&
        Feld[last_jx][last_jy] == EL_EMPTY)
     {
-      int last_field_block_delay = 0;  /* start with no blocking at all */
+      int last_field_block_delay = 0;  // start with no blocking at all
       int block_delay_adjustment = player->block_delay_adjustment;
 
-      /* if player blocks last field, add delay for exactly one move */
+      // if player blocks last field, add delay for exactly one move
       if (player->block_last_field)
       {
        last_field_block_delay += player->move_delay_value;
 
-       /* when blocking enabled, prevent moving up despite gravity */
+       // when blocking enabled, prevent moving up despite gravity
        if (player->gravity && player->MovDir == MV_UP)
          block_delay_adjustment = -1;
       }
 
-      /* add block delay adjustment (also possible when not blocking) */
+      // add block delay adjustment (also possible when not blocking)
       last_field_block_delay += block_delay_adjustment;
 
       Feld[last_jx][last_jy] = EL_PLAYER_IS_LEAVING;
       MovDelay[last_jx][last_jy] = last_field_block_delay + 1;
     }
 
-    if (player->MovPos != 0)   /* player has not yet reached destination */
+    if (player->MovPos != 0)   // player has not yet reached destination
       return;
   }
   else if (!FrameReached(&player->actual_frame_counter, 1))
@@ -12679,12 +12639,12 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
     player->MovPos += (player->MovPos > 0 ? -1 : 1) * move_stepsize;
     player->GfxPos = move_stepsize * (player->MovPos / move_stepsize);
 
-    /* before DrawPlayer() to draw correct player graphic for this case */
+    // before DrawPlayer() to draw correct player graphic for this case
     if (player->MovPos == 0)
       CheckGravityMovement(player);
   }
 
-  if (player->MovPos == 0)     /* player reached destination field */
+  if (player->MovPos == 0)     // player reached destination field
   {
     if (player->move_delay_reset_counter > 0)
     {
@@ -12692,10 +12652,10 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
 
       if (player->move_delay_reset_counter == 0)
       {
-       /* continue with normal speed after quickly moving through gate */
+       // continue with normal speed after quickly moving through gate
        HALVE_PLAYER_SPEED(player);
 
-       /* be able to make the next move without delay */
+       // be able to make the next move without delay
        player->move_delay = 0;
       }
     }
@@ -12710,17 +12670,17 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
        Feld[jx][jy] == EL_EM_STEEL_EXIT_OPEN ||
        Feld[jx][jy] == EL_EM_STEEL_EXIT_OPENING ||
        Feld[jx][jy] == EL_SP_EXIT_OPEN ||
-       Feld[jx][jy] == EL_SP_EXIT_OPENING)     /* <-- special case */
+       Feld[jx][jy] == EL_SP_EXIT_OPENING)     // <-- special case
     {
-      DrawPlayer(player);      /* needed here only to cleanup last field */
-      RemovePlayer(player);
+      ExitPlayer(player);
 
-      if (local_player->friends_still_needed == 0 ||
-         IS_SP_ELEMENT(Feld[jx][jy]))
-       PlayerWins(player);
+      if ((game.friends_still_needed == 0 ||
+          IS_SP_ELEMENT(Feld[jx][jy])) &&
+         AllPlayersGone)
+       LevelSolved();
     }
 
-    /* this breaks one level: "machine", level 000 */
+    // this breaks one level: "machine", level 000
     {
       int move_direction = player->MovDir;
       int enter_side = MV_DIR_OPPOSITE(move_direction);
@@ -12759,13 +12719,13 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
       /* needed because pushed element has not yet reached its destination,
         so it would trigger a change event at its previous field location */
       if (!player->is_pushing)
-       TestIfElementTouchesCustomElement(jx, jy);      /* for empty space */
+       TestIfElementTouchesCustomElement(jx, jy);      // for empty space
 
       if (!player->active)
        RemovePlayer(player);
     }
 
-    if (!local_player->LevelSolved && level.use_step_counter)
+    if (!game.LevelSolved && level.use_step_counter)
     {
       int i;
 
@@ -12786,7 +12746,7 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
          for (i = 0; i < MAX_PLAYERS; i++)
            KillPlayer(&stored_player[i]);
       }
-      else if (game.no_time_limit && !AllPlayersGone) /* level w/o time limit */
+      else if (game.no_time_limit && !AllPlayersGone) // level w/o time limit
       {
        game_panel_controls[GAME_PANEL_TIME].value = TimePlayed;
 
@@ -12809,7 +12769,7 @@ void ScrollScreen(struct PlayerInfo *player, int mode)
 
   if (mode == SCROLL_INIT)
   {
-    /* set scrolling step size according to actual player's moving speed */
+    // set scrolling step size according to actual player's moving speed
     ScrollStepSize = TILEX / player->move_delay_value;
 
     screen_frame_counter = FrameCounter;
@@ -12842,11 +12802,11 @@ void TestIfPlayerTouchesCustomElement(int x, int y)
   };
   static int trigger_sides[4][2] =
   {
-    /* center side       border side */
-    { CH_SIDE_TOP,     CH_SIDE_BOTTOM  },      /* check top    */
-    { CH_SIDE_LEFT,    CH_SIDE_RIGHT   },      /* check left   */
-    { CH_SIDE_RIGHT,   CH_SIDE_LEFT    },      /* check right  */
-    { CH_SIDE_BOTTOM,  CH_SIDE_TOP     }       /* check bottom */
+    // center side       border side
+    { CH_SIDE_TOP,     CH_SIDE_BOTTOM  },      // check top
+    { CH_SIDE_LEFT,    CH_SIDE_RIGHT   },      // check left
+    { CH_SIDE_RIGHT,   CH_SIDE_LEFT    },      // check right
+    { CH_SIDE_BOTTOM,  CH_SIDE_TOP     }       // check bottom
   };
   static int touch_dir[4] =
   {
@@ -12855,7 +12815,7 @@ void TestIfPlayerTouchesCustomElement(int x, int y)
     MV_UP   | MV_DOWN,
     MV_LEFT | MV_RIGHT
   };
-  int center_element = Feld[x][y];     /* should always be non-moving! */
+  int center_element = Feld[x][y];     // should always be non-moving!
   int i;
 
   for (i = 0; i < NUM_DIRECTIONS; i++)
@@ -12869,18 +12829,18 @@ void TestIfPlayerTouchesCustomElement(int x, int y)
     if (!IN_LEV_FIELD(xx, yy))
       continue;
 
-    if (IS_PLAYER(x, y))               /* player found at center element */
+    if (IS_PLAYER(x, y))               // player found at center element
     {
       struct PlayerInfo *player = PLAYERINFO(x, y);
 
       if (game.engine_version < VERSION_IDENT(3,0,7,0))
-       border_element = Feld[xx][yy];          /* may be moving! */
+       border_element = Feld[xx][yy];          // may be moving!
       else if (!IS_MOVING(xx, yy) && !IS_BLOCKED(xx, yy))
        border_element = Feld[xx][yy];
-      else if (MovDir[xx][yy] & touch_dir[i])  /* elements are touching */
+      else if (MovDir[xx][yy] & touch_dir[i])  // elements are touching
        border_element = MovingOrBlocked2Element(xx, yy);
       else
-       continue;               /* center and border element do not touch */
+       continue;               // center and border element do not touch
 
       CheckElementChangeByPlayer(xx, yy, border_element, CE_TOUCHED_BY_PLAYER,
                                 player->index_bit, border_side);
@@ -12899,14 +12859,14 @@ void TestIfPlayerTouchesCustomElement(int x, int y)
                                 CE_TOUCHING_X, border_side);
       }
     }
-    else if (IS_PLAYER(xx, yy))                /* player found at border element */
+    else if (IS_PLAYER(xx, yy))                // player found at border element
     {
       struct PlayerInfo *player = PLAYERINFO(xx, yy);
 
       if (game.engine_version >= VERSION_IDENT(3,0,7,0))
       {
        if (player->MovPos != 0 && !(player->MovDir & touch_dir[i]))
-         continue;             /* center and border element do not touch */
+         continue;             // center and border element do not touch
       }
 
       CheckElementChangeByPlayer(x, y, center_element, CE_TOUCHED_BY_PLAYER,
@@ -12942,11 +12902,11 @@ void TestIfElementTouchesCustomElement(int x, int y)
   };
   static int trigger_sides[4][2] =
   {
-    /* center side     border side */
-    { CH_SIDE_TOP,     CH_SIDE_BOTTOM  },      /* check top    */
-    { CH_SIDE_LEFT,    CH_SIDE_RIGHT   },      /* check left   */
-    { CH_SIDE_RIGHT,   CH_SIDE_LEFT    },      /* check right  */
-    { CH_SIDE_BOTTOM,  CH_SIDE_TOP     }       /* check bottom */
+    // center side     border side
+    { CH_SIDE_TOP,     CH_SIDE_BOTTOM  },      // check top
+    { CH_SIDE_LEFT,    CH_SIDE_RIGHT   },      // check left
+    { CH_SIDE_RIGHT,   CH_SIDE_LEFT    },      // check right
+    { CH_SIDE_BOTTOM,  CH_SIDE_TOP     }       // check bottom
   };
   static int touch_dir[4] =
   {
@@ -12956,7 +12916,7 @@ void TestIfElementTouchesCustomElement(int x, int y)
     MV_LEFT | MV_RIGHT
   };
   boolean change_center_element = FALSE;
-  int center_element = Feld[x][y];     /* should always be non-moving! */
+  int center_element = Feld[x][y];     // should always be non-moving!
   int border_element_old[NUM_DIRECTIONS];
   int i;
 
@@ -12972,13 +12932,13 @@ void TestIfElementTouchesCustomElement(int x, int y)
       continue;
 
     if (game.engine_version < VERSION_IDENT(3,0,7,0))
-      border_element = Feld[xx][yy];   /* may be moving! */
+      border_element = Feld[xx][yy];   // may be moving!
     else if (!IS_MOVING(xx, yy) && !IS_BLOCKED(xx, yy))
       border_element = Feld[xx][yy];
-    else if (MovDir[xx][yy] & touch_dir[i])    /* elements are touching */
+    else if (MovDir[xx][yy] & touch_dir[i])    // elements are touching
       border_element = MovingOrBlocked2Element(xx, yy);
     else
-      continue;                        /* center and border element do not touch */
+      continue;                        // center and border element do not touch
 
     border_element_old[i] = border_element;
   }
@@ -12993,11 +12953,11 @@ void TestIfElementTouchesCustomElement(int x, int y)
     if (border_element == -1)
       continue;
 
-    /* check for change of border element */
+    // check for change of border element
     CheckElementChangeBySide(xx, yy, border_element, center_element,
                             CE_TOUCHING_X, center_side);
 
-    /* (center element cannot be player, so we dont have to check this here) */
+    // (center element cannot be player, so we dont have to check this here)
   }
 
   for (i = 0; i < NUM_DIRECTIONS; i++)
@@ -13010,7 +12970,7 @@ void TestIfElementTouchesCustomElement(int x, int y)
     if (border_element == -1)
       continue;
 
-    /* check for change of center element (but change it only once) */
+    // check for change of center element (but change it only once)
     if (!change_center_element)
       change_center_element =
        CheckElementChangeBySide(x, y, center_element, border_element,
@@ -13080,7 +13040,7 @@ void TestIfElementHitsCustomElement(int x, int y, int direction)
     }
   }
 
-  /* "hitting something" is also true when hitting the playfield border */
+  // "hitting something" is also true when hitting the playfield border
   CheckElementChangeBySide(x, y, hitting_element, touched_element,
                           CE_HITTING_SOMETHING, direction);
 }
@@ -13177,7 +13137,7 @@ void TestIfBadThingHitsGoodThing(int bad_x, int bad_y, int bad_move_dir)
     MV_DOWN
   };
 
-  if (bad_element == EL_EXPLOSION)     /* skip just exploding bad things */
+  if (bad_element == EL_EXPLOSION)     // skip just exploding bad things
     return;
 
   for (i = 0; i < NUM_DIRECTIONS; i++)
@@ -13201,18 +13161,18 @@ void TestIfBadThingHitsGoodThing(int bad_x, int bad_y, int bad_move_dir)
     if ((DONT_RUN_INTO(bad_element) &&  bad_move_dir == test_dir[i]) ||
        (DONT_TOUCH(bad_element)    && test_move_dir != test_dir[i]))
     {
-      /* good thing is player or penguin that does not move away */
+      // good thing is player or penguin that does not move away
       if (IS_PLAYER(test_x, test_y))
       {
        struct PlayerInfo *player = PLAYERINFO(test_x, test_y);
 
        if (bad_element == EL_ROBOT && player->is_moving)
-         continue;     /* robot does not kill player if he is moving */
+         continue;     // robot does not kill player if he is moving
 
        if (game.engine_version >= VERSION_IDENT(3,0,7,0))
        {
          if (player->MovPos != 0 && !(player->MovDir & touch_dir[i]))
-           continue;           /* center and border element do not touch */
+           continue;           // center and border element do not touch
        }
 
        kill_x = test_x;
@@ -13266,7 +13226,7 @@ void TestIfGoodThingGetsHitByBadThing(int bad_x, int bad_y, int bad_move_dir)
 
   if (test_move_dir != bad_move_dir)
   {
-    /* good thing can be player or penguin that does not move away */
+    // good thing can be player or penguin that does not move away
     if (IS_PLAYER(test_x, test_y))
     {
       struct PlayerInfo *player = PLAYERINFO(test_x, test_y);
@@ -13275,7 +13235,7 @@ void TestIfGoodThingGetsHitByBadThing(int bad_x, int bad_y, int bad_move_dir)
         player as being hit when he is moving towards the bad thing, because
         the "get hit by" condition would be lost after the player stops) */
       if (player->MovPos != 0 && player->MovDir == bad_move_dir)
-       return;         /* player moves away from bad thing */
+       return;         // player moves away from bad thing
 
       kill_x = test_x;
       kill_y = test_y;
@@ -13397,10 +13357,10 @@ void KillPlayer(struct PlayerInfo *player)
 
   player->killed = TRUE;
 
-  /* remove accessible field at the player's position */
+  // remove accessible field at the player's position
   Feld[jx][jy] = EL_EMPTY;
 
-  /* deactivate shield (else Bang()/Explode() would not work right) */
+  // deactivate shield (else Bang()/Explode() would not work right)
   player->shield_normal_time_left = 0;
   player->shield_deadly_time_left = 0;
 
@@ -13416,7 +13376,7 @@ void KillPlayer(struct PlayerInfo *player)
         player->killed, player->active, player->reanimated);
 #endif
 
-  if (player->reanimated)      /* killed player may have been reanimated */
+  if (player->reanimated)      // killed player may have been reanimated
     player->killed = player->reanimated = FALSE;
   else
     BuryPlayer(player);
@@ -13473,6 +13433,19 @@ void RemovePlayer(struct PlayerInfo *player)
   ExitY = ZY = jy;
 }
 
+void ExitPlayer(struct PlayerInfo *player)
+{
+  DrawPlayer(player);  // needed here only to cleanup last field
+  RemovePlayer(player);
+
+  if (game.players_still_needed > 0)
+    game.players_still_needed--;
+
+  // also set if some players not yet gone, but not needed to solve level
+  if (game.players_still_needed == 0)
+    AllPlayersGone = TRUE;
+}
+
 static void setFieldForSnapping(int x, int y, int element, int direction)
 {
   struct ElementInfo *ei = &element_info[element];
@@ -13506,10 +13479,10 @@ static boolean checkDiagonalPushing(struct PlayerInfo *player,
 {
   int jx, jy, dx, dy, xx, yy;
 
-  if (real_dx == 0 || real_dy == 0)    /* no diagonal direction => push */
+  if (real_dx == 0 || real_dy == 0)    // no diagonal direction => push
     return TRUE;
 
-  /* diagonal direction: check alternative direction */
+  // diagonal direction: check alternative direction
   jx = player->jx;
   jy = player->jy;
   dx = x - jx;
@@ -13550,7 +13523,7 @@ static int DigField(struct PlayerInfo *player,
   int element = MovingOrBlocked2ElementIfNotLeaving(x, y);
   int collect_count;
 
-  if (is_player)               /* function can also be called by EL_PENGUIN */
+  if (is_player)               // function can also be called by EL_PENGUIN
   {
     if (player->MovPos == 0)
     {
@@ -13558,10 +13531,10 @@ static int DigField(struct PlayerInfo *player,
       player->is_collecting = FALSE;
     }
 
-    if (player->MovPos == 0)   /* last pushing move finished */
+    if (player->MovPos == 0)   // last pushing move finished
       player->is_pushing = FALSE;
 
-    if (mode == DF_NO_PUSH)    /* player just stopped pushing */
+    if (mode == DF_NO_PUSH)    // player just stopped pushing
     {
       player->is_switching = FALSE;
       player->push_delay = -1;
@@ -13573,16 +13546,16 @@ static int DigField(struct PlayerInfo *player,
   if (IS_TUBE(Back[jx][jy]) && game.engine_version >= VERSION_IDENT(2,2,0,0))
     old_element = Back[jx][jy];
 
-  /* in case of element dropped at player position, check background */
+  // in case of element dropped at player position, check background
   else if (Back[jx][jy] != EL_EMPTY &&
           game.engine_version >= VERSION_IDENT(2,2,0,0))
     old_element = Back[jx][jy];
 
   if (IS_WALKABLE(old_element) && !ACCESS_FROM(old_element, move_direction))
-    return MP_NO_ACTION;       /* field has no opening in this 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 */
+    return MP_NO_ACTION;       // field has no opening in this direction
 
   if (player_can_move && element == EL_ACID && move_direction == MV_DOWN)
   {
@@ -13609,7 +13582,7 @@ static int DigField(struct PlayerInfo *player,
 
   collect_count = element_info[element].collect_count_initial;
 
-  if (!is_player && !IS_COLLECTIBLE(element))  /* penguin cannot collect it */
+  if (!is_player && !IS_COLLECTIBLE(element))  // penguin cannot collect it
     return MP_NO_ACTION;
 
   if (game.engine_version < VERSION_IDENT(2,2,0,0))
@@ -13626,7 +13599,7 @@ static int DigField(struct PlayerInfo *player,
     if (element == EL_DC_LANDMINE)
       Bang(x, y);
 
-    if (Feld[x][y] != element)         /* field changed by snapping */
+    if (Feld[x][y] != element)         // field changed by snapping
       return MP_ACTION;
 
     return MP_NO_ACTION;
@@ -13635,7 +13608,7 @@ static int DigField(struct PlayerInfo *player,
   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 */
+    return MP_NO_ACTION;       // player cannot walk here due to gravity
 
   if (player_can_move &&
       IS_WALKABLE(element) && ACCESS_FROM(element, opposite_direction))
@@ -13667,14 +13640,14 @@ static int DigField(struct PlayerInfo *player,
             element == EL_SP_EXIT_OPEN ||
             element == EL_SP_EXIT_OPENING)
     {
-      sound_action = ACTION_PASSING;   /* player is passing exit */
+      sound_action = ACTION_PASSING;   // player is passing exit
     }
     else if (element == EL_EMPTY)
     {
-      sound_action = ACTION_MOVING;            /* nothing to walk on */
+      sound_action = ACTION_MOVING;            // nothing to walk on
     }
 
-    /* play sound from background or player, whatever is available */
+    // play sound from background or player, whatever is available
     if (element_info[sound_element].sound[sound_action] != SND_UNDEFINED)
       PlayLevelSoundElementAction(x, y, sound_element, sound_action);
     else
@@ -13684,9 +13657,9 @@ static int DigField(struct PlayerInfo *player,
           IS_PASSABLE(element) && canPassField(x, y, move_direction))
   {
     if (!ACCESS_FROM(element, opposite_direction))
-      return MP_NO_ACTION;     /* field not accessible from this direction */
+      return MP_NO_ACTION;     // field not accessible from this direction
 
-    if (CAN_MOVE(element))     /* only fixed elements can be passed! */
+    if (CAN_MOVE(element))     // only fixed elements can be passed!
       return MP_NO_ACTION;
 
     if (IS_EM_GATE(element))
@@ -13747,12 +13720,12 @@ static int DigField(struct PlayerInfo *player,
        player->gravity = FALSE;
     }
 
-    /* automatically move to the next field with double speed */
+    // automatically move to the next field with double speed
     player->programmed_action = move_direction;
 
     if (player->move_delay_reset_counter == 0)
     {
-      player->move_delay_reset_counter = 2;    /* two double speed steps */
+      player->move_delay_reset_counter = 2;    // two double speed steps
 
       DOUBLE_PLAYER_SPEED(player);
     }
@@ -13779,7 +13752,7 @@ static int DigField(struct PlayerInfo *player,
       if (level.block_snap_field)
        setFieldForSnapping(x, y, element, move_direction);
       else
-       TestIfElementTouchesCustomElement(x, y);        /* for empty space */
+       TestIfElementTouchesCustomElement(x, y);        // for empty space
 
       CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_SNAPS_X,
                                          player->index_bit, dig_side);
@@ -13845,8 +13818,8 @@ static int DigField(struct PlayerInfo *player,
     {
       player->num_white_keys++;
 
-      /* display white keys? */
-      /* DrawGameDoorValues(); */
+      // display white keys?
+      // DrawGameDoorValues();
     }
     else if (IS_ENVELOPE(element))
     {
@@ -13865,7 +13838,7 @@ static int DigField(struct PlayerInfo *player,
       RedrawAllInvisibleElementsForMagnifier();
     }
     else if (IS_DROPPABLE(element) ||
-            IS_THROWABLE(element))     /* can be collected and dropped */
+            IS_THROWABLE(element))     // can be collected and dropped
     {
       int i;
 
@@ -13880,13 +13853,13 @@ static int DigField(struct PlayerInfo *player,
     }
     else if (collect_count > 0)
     {
-      local_player->gems_still_needed -= collect_count;
-      if (local_player->gems_still_needed < 0)
-       local_player->gems_still_needed = 0;
+      game.gems_still_needed -= collect_count;
+      if (game.gems_still_needed < 0)
+       game.gems_still_needed = 0;
 
       game.snapshot.collected_item = TRUE;
 
-      game_panel_controls[GAME_PANEL_GEMS].value = local_player->gems_still_needed;
+      game_panel_controls[GAME_PANEL_GEMS].value = game.gems_still_needed;
 
       DisplayGameControlValues();
     }
@@ -13903,7 +13876,7 @@ static int DigField(struct PlayerInfo *player,
       if (level.block_snap_field)
        setFieldForSnapping(x, y, element, move_direction);
       else
-       TestIfElementTouchesCustomElement(x, y);        /* for empty space */
+       TestIfElementTouchesCustomElement(x, y);        // for empty space
 
       CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_SNAPS_X,
                                          player->index_bit, dig_side);
@@ -13934,7 +13907,7 @@ static int DigField(struct PlayerInfo *player,
            IN_LEV_FIELD(x, y + 1) && IS_FREE(x, y + 1))))))
       return MP_NO_ACTION;
 
-    /* do not push elements already moving away faster than player */
+    // do not push elements already moving away faster than player
     if (CAN_MOVE(element) && MovDir[x][y] == move_direction &&
        ABS(getElementMoveStepsize(x, y)) > MOVE_STEPSIZE_NORMAL)
       return MP_NO_ACTION;
@@ -13969,14 +13942,14 @@ static int DigField(struct PlayerInfo *player,
     if (!checkDiagonalPushing(player, x, y, real_dx, real_dy))
       return MP_NO_ACTION;
 
-    if (player->push_delay == -1)      /* new pushing; restart delay */
+    if (player->push_delay == -1)      // new pushing; restart delay
       player->push_delay = 0;
 
     if (player->push_delay < player->push_delay_value &&
        !(tape.playing && tape.file_version < FILE_VERSION_2_0) &&
        element != EL_SPRING && element != EL_BALLOON)
     {
-      /* make sure that there is no move delay before next try to push */
+      // make sure that there is no move delay before next try to push
       if (game.engine_version >= VERSION_IDENT(3,0,7,1))
        player->move_delay = 0;
 
@@ -13992,16 +13965,26 @@ static int DigField(struct PlayerInfo *player,
 
     if (IS_SB_ELEMENT(element))
     {
+      boolean sokoban_task_solved = FALSE;
+
       if (element == EL_SOKOBAN_FIELD_FULL)
       {
        Back[x][y] = EL_SOKOBAN_FIELD_EMPTY;
-       local_player->sokobanfields_still_needed++;
+
+       IncrementSokobanFieldsNeeded();
+       IncrementSokobanObjectsNeeded();
       }
 
       if (Feld[nextx][nexty] == EL_SOKOBAN_FIELD_EMPTY)
       {
        Back[nextx][nexty] = EL_SOKOBAN_FIELD_EMPTY;
-       local_player->sokobanfields_still_needed--;
+
+       DecrementSokobanFieldsNeeded();
+       DecrementSokobanObjectsNeeded();
+
+       // sokoban object was pushed from empty field to sokoban field
+       if (Back[x][y] == EL_EMPTY)
+         sokoban_task_solved = TRUE;
       }
 
       Feld[x][y] = EL_SOKOBAN_OBJECT;
@@ -14015,10 +13998,14 @@ static int DigField(struct PlayerInfo *player,
        PlayLevelSoundElementAction(nextx, nexty, EL_SOKOBAN_FIELD_EMPTY,
                                    ACTION_FILLING);
 
-      if (local_player->sokobanfields_still_needed == 0 &&
+      if (sokoban_task_solved &&
+         game.sokoban_fields_still_needed == 0 &&
+         game.sokoban_objects_still_needed == 0 &&
          (game.emulation == EMU_SOKOBAN || level.auto_exit_sokoban))
       {
-       PlayerWins(player);
+       game.players_still_needed = 0;
+
+       LevelSolved();
 
        PlayLevelSound(x, y, SND_GAME_SOKOBAN_SOLVING);
       }
@@ -14040,9 +14027,9 @@ static int DigField(struct PlayerInfo *player,
     if (game.engine_version < VERSION_IDENT(2,2,0,7))
       player->push_delay_value = GET_NEW_PUSH_DELAY(element);
     else
-      player->push_delay_value = -1;   /* get new value later */
+      player->push_delay_value = -1;   // get new value later
 
-    /* check for element change _after_ element has been pushed */
+    // check for element change _after_ element has been pushed
     if (game.use_change_when_pushing_bug)
     {
       CheckElementChangeByPlayer(x, y, element, CE_PUSHED_BY_PLAYER,
@@ -14134,7 +14121,7 @@ static int DigField(struct PlayerInfo *player,
     else if (element == EL_LAMP)
     {
       Feld[x][y] = EL_LAMP_ACTIVE;
-      local_player->lights_still_needed--;
+      game.lights_still_needed--;
 
       ResetGfxAnimation(x, y);
       TEST_DrawLevelField(x, y);
@@ -14224,9 +14211,9 @@ static int DigField(struct PlayerInfo *player,
 
   player->push_delay = -1;
 
-  if (is_player)               /* function can also be called by EL_PENGUIN */
+  if (is_player)               // function can also be called by EL_PENGUIN
   {
-    if (Feld[x][y] != element)         /* really digged/collected something */
+    if (Feld[x][y] != element)         // really digged/collected something
     {
       player->is_collecting = !player->is_digging;
       player->is_active = TRUE;
@@ -14246,7 +14233,7 @@ static boolean DigFieldByCE(int x, int y, int digging_element)
                  IS_COLLECTIBLE(element) ? ACTION_COLLECTING :
                  ACTION_BREAKING);
 
-    /* no element can dig solid indestructible elements */
+    // no element can dig solid indestructible elements
     if (IS_INDESTRUCTIBLE(element) &&
        !IS_DIGGABLE(element) &&
        !IS_COLLECTIBLE(element))
@@ -14269,7 +14256,7 @@ static boolean DigFieldByCE(int x, int y, int digging_element)
       TEST_DrawLevelField(x, y);
     }
 
-    /* if digged element was about to explode, prevent the explosion */
+    // if digged element was about to explode, prevent the explosion
     ExplodeField[x][y] = EX_TYPE_NONE;
 
     PlayLevelSoundAction(x, y, action);
@@ -14277,7 +14264,7 @@ static boolean DigFieldByCE(int x, int y, int digging_element)
 
   Store[x][y] = EL_EMPTY;
 
-  /* this makes it possible to leave the removed element again */
+  // this makes it possible to leave the removed element again
   if (IS_EQUAL_OR_IN_GROUP(element, MOVE_ENTER_EL(digging_element)))
     Store[x][y] = element;
 
@@ -14321,7 +14308,7 @@ static boolean SnapField(struct PlayerInfo *player, int dx, int dy)
     return FALSE;
   }
 
-  /* prevent snapping with already pressed snap key when not allowed */
+  // prevent snapping with already pressed snap key when not allowed
   if (player->is_snapping && !can_continue_snapping)
     return FALSE;
 
@@ -14351,7 +14338,7 @@ static boolean SnapField(struct PlayerInfo *player, int dx, int dy)
     player->is_collecting = FALSE;
   }
 
-  if (player->MovPos != 0)     /* prevent graphic bugs in versions < 2.2.0 */
+  if (player->MovPos != 0)     // prevent graphic bugs in versions < 2.2.0
     TEST_DrawLevelField(player->last_jx, player->last_jy);
 
   TEST_DrawLevelField(x, y);
@@ -14383,34 +14370,34 @@ static boolean DropElement(struct PlayerInfo *player)
       return FALSE;
   }
 
-  old_element = Feld[dropx][dropy];    /* old element at dropping position */
-  new_element = drop_element;          /* default: no change when dropping */
+  old_element = Feld[dropx][dropy];    // old element at dropping position
+  new_element = drop_element;          // default: no change when dropping
 
-  /* check if player is active, not moving and ready to drop */
+  // check if player is active, not moving and ready to drop
   if (!player->active || player->MovPos || player->drop_delay > 0)
     return FALSE;
 
-  /* check if player has anything that can be dropped */
+  // check if player has anything that can be dropped
   if (new_element == EL_UNDEFINED)
     return FALSE;
 
-  /* only set if player has anything that can be dropped */
+  // only set if player has anything that can be dropped
   player->is_dropping_pressed = TRUE;
 
-  /* check if drop key was pressed long enough for EM style dynamite */
+  // check if drop key was pressed long enough for EM style dynamite
   if (new_element == EL_EM_DYNAMITE && player->drop_pressed_delay < 40)
     return FALSE;
 
-  /* check if anything can be dropped at the current position */
+  // check if anything can be dropped at the current position
   if (IS_ACTIVE_BOMB(old_element) || old_element == EL_EXPLOSION)
     return FALSE;
 
-  /* collected custom elements can only be dropped on empty fields */
+  // collected custom elements can only be dropped on empty fields
   if (IS_CUSTOM_ELEMENT(new_element) && old_element != EL_EMPTY)
     return FALSE;
 
   if (old_element != EL_EMPTY)
-    Back[dropx][dropy] = old_element;  /* store old element on this field */
+    Back[dropx][dropy] = old_element;  // store old element on this field
 
   ResetGfxAnimation(dropx, dropy);
   ResetRandomAnimationValue(dropx, dropy);
@@ -14440,8 +14427,8 @@ static boolean DropElement(struct PlayerInfo *player)
 
     PlayLevelSoundAction(dropx, dropy, ACTION_DROPPING);
 
-    /* needed if previous element just changed to "empty" in the last frame */
-    ChangeCount[dropx][dropy] = 0;     /* allow at least one more change */
+    // needed if previous element just changed to "empty" in the last frame
+    ChangeCount[dropx][dropy] = 0;     // allow at least one more change
 
     CheckElementChangeByPlayer(dropx, dropy, new_element, CE_DROPPED_BY_PLAYER,
                               player->index_bit, drop_side);
@@ -14451,7 +14438,7 @@ static boolean DropElement(struct PlayerInfo *player)
 
     TestIfElementTouchesCustomElement(dropx, dropy);
   }
-  else         /* player is dropping a dyna bomb */
+  else         // player is dropping a dyna bomb
   {
     player->dynabombs_left--;
 
@@ -14464,10 +14451,10 @@ static boolean DropElement(struct PlayerInfo *player)
     PlayLevelSoundAction(dropx, dropy, ACTION_DROPPING);
   }
 
-  if (Feld[dropx][dropy] == new_element) /* uninitialized unless CE change */
+  if (Feld[dropx][dropy] == new_element) // uninitialized unless CE change
     InitField_WithBug1(dropx, dropy, FALSE);
 
-  new_element = Feld[dropx][dropy];    /* element might have changed */
+  new_element = Feld[dropx][dropy];    // element might have changed
 
   if (IS_CUSTOM_ELEMENT(new_element) && CAN_MOVE(new_element) &&
       element_info[new_element].move_pattern == MV_WHEN_DROPPED)
@@ -14475,9 +14462,9 @@ static boolean DropElement(struct PlayerInfo *player)
     if (element_info[new_element].move_direction_initial == MV_START_AUTOMATIC)
       MovDir[dropx][dropy] = drop_direction;
 
-    ChangeCount[dropx][dropy] = 0;     /* allow at least one more change */
+    ChangeCount[dropx][dropy] = 0;     // allow at least one more change
 
-    /* do not cause impact style collision by dropping elements that can fall */
+    // do not cause impact style collision by dropping elements that can fall
     CheckCollision[dropx][dropy] = CHECK_DELAY_COLLISION;
   }
 
@@ -14493,14 +14480,14 @@ static boolean DropElement(struct PlayerInfo *player)
   return TRUE;
 }
 
-/* ------------------------------------------------------------------------- */
-/* game sound playing functions                                              */
-/* ------------------------------------------------------------------------- */
+// ----------------------------------------------------------------------------
+// game sound playing functions
+// ----------------------------------------------------------------------------
 
 static int *loop_sound_frame = NULL;
 static int *loop_sound_volume = NULL;
 
-void InitPlayLevelSound()
+void InitPlayLevelSound(void)
 {
   int num_sounds = getSoundListSize();
 
@@ -14603,20 +14590,20 @@ static void StopLevelSoundActionIfLoop(int x, int y, int action)
     StopSound(sound_effect);
 }
 
-static int getLevelMusicNr()
+static int getLevelMusicNr(void)
 {
   if (levelset.music[level_nr] != MUS_UNDEFINED)
-    return levelset.music[level_nr];           /* from config file */
+    return levelset.music[level_nr];           // from config file
   else
-    return MAP_NOCONF_MUSIC(level_nr);         /* from music dir */
+    return MAP_NOCONF_MUSIC(level_nr);         // from music dir
 }
 
-static void FadeLevelSounds()
+static void FadeLevelSounds(void)
 {
   FadeSounds();
 }
 
-static void FadeLevelMusic()
+static void FadeLevelMusic(void)
 {
   int music_nr = getLevelMusicNr();
   char *curr_music = getCurrentlyPlayingMusicFilename();
@@ -14626,20 +14613,20 @@ static void FadeLevelMusic()
     FadeMusic();
 }
 
-void FadeLevelSoundsAndMusic()
+void FadeLevelSoundsAndMusic(void)
 {
   FadeLevelSounds();
   FadeLevelMusic();
 }
 
-static void PlayLevelMusic()
+static void PlayLevelMusic(void)
 {
   int music_nr = getLevelMusicNr();
   char *curr_music = getCurrentlyPlayingMusicFilename();
   char *next_music = getMusicInfoEntryFilename(music_nr);
 
   if (!strEqual(curr_music, next_music))
-    PlayMusic(music_nr);
+    PlayMusicLoop(music_nr);
 }
 
 void PlayLevelSound_EM(int xx, int yy, int element_em, int sample)
@@ -14716,7 +14703,7 @@ void PlayLevelSound_EM(int xx, int yy, int element_em, int sample)
       break;
 
     case SAMPLE_squash:
-      /* !!! CHECK THIS !!! */
+      // !!! CHECK THIS !!!
 #if 1
       PlayLevelSoundElementAction(x, y, element, ACTION_BREAKING);
 #else
@@ -14950,7 +14937,7 @@ void RequestQuitGameExt(boolean skip_request, boolean quick_quit, char *message)
 {
   if (skip_request || Request(message, REQ_ASK | REQ_STAY_CLOSED))
   {
-    /* closing door required in case of envelope style request dialogs */
+    // closing door required in case of envelope style request dialogs
     if (!skip_request)
       CloseDoor(DOOR_CLOSE_1);
 
@@ -14966,7 +14953,7 @@ void RequestQuitGameExt(boolean skip_request, boolean quick_quit, char *message)
       DrawMainMenu();
     }
   }
-  else         /* continue playing the game */
+  else         // continue playing the game
   {
     if (tape.playing && tape.deactivate_display)
       TapeDeactivateDisplayOff(TRUE);
@@ -14991,7 +14978,10 @@ void RequestRestartGame(char *message)
 {
   game.restart_game_message = NULL;
 
-  if (Request(message, REQ_ASK | REQ_STAY_CLOSED))
+  boolean has_started_game = hasStartedNetworkGame();
+  int request_mode = (has_started_game ? REQ_ASK : REQ_CONFIRM);
+
+  if (Request(message, request_mode | REQ_STAY_CLOSED) && has_started_game)
   {
     StartGameActions(network.enabled, setup.autorecord, level.random_seed);
   }
@@ -15003,10 +14993,70 @@ void RequestRestartGame(char *message)
   }
 }
 
+void CheckGameOver(void)
+{
+  static boolean last_game_over = FALSE;
+  static int game_over_delay = 0;
+  int game_over_delay_value = 50;
+  boolean game_over = checkGameFailed();
+
+  // do not handle game over if request dialog is already active
+  if (game.request_active)
+    return;
+
+  if (!game_over)
+  {
+    last_game_over = FALSE;
+    game_over_delay = game_over_delay_value;
+
+    return;
+  }
+
+  if (game_over_delay > 0)
+  {
+    game_over_delay--;
+
+    return;
+  }
+
+  if (last_game_over != game_over)
+    game.restart_game_message = (hasStartedNetworkGame() ?
+                                "Game over! Play it again?" :
+                                "Game over!");
+
+  last_game_over = game_over;
+}
+
+boolean checkGameSolved(void)
+{
+  // set for all game engines if level was solved
+  return game.LevelSolved_GameEnd;
+}
+
+boolean checkGameFailed(void)
+{
+  if (!AllPlayersGone)
+    return FALSE;
 
-/* ------------------------------------------------------------------------- */
-/* random generator functions                                                */
-/* ------------------------------------------------------------------------- */
+  if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+    return (game_em.game_over && !game_em.level_solved);
+  else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+    return (game_sp.game_over && !game_sp.level_solved);
+  else if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
+    return (game_mm.game_over && !game_mm.level_solved);
+  else                         // GAME_ENGINE_TYPE_RND
+    return (local_player->GameOver && !game.LevelSolved);
+}
+
+boolean checkGameEnded(void)
+{
+  return (checkGameSolved() || checkGameFailed());
+}
+
+
+// ----------------------------------------------------------------------------
+// random generator functions
+// ----------------------------------------------------------------------------
 
 unsigned int InitEngineRandom_RND(int seed)
 {
@@ -15028,19 +15078,19 @@ unsigned int RND(int max)
 }
 
 
-/* ------------------------------------------------------------------------- */
-/* game engine snapshot handling functions                                   */
-/* ------------------------------------------------------------------------- */
+// ----------------------------------------------------------------------------
+// game engine snapshot handling functions
+// ----------------------------------------------------------------------------
 
 struct EngineSnapshotInfo
 {
-  /* runtime values for custom element collect score */
+  // runtime values for custom element collect score
   int collect_score[NUM_CUSTOM_ELEMENTS];
 
-  /* runtime values for group element choice position */
+  // runtime values for group element choice position
   int choice_pos[NUM_GROUP_ELEMENTS];
 
-  /* runtime values for belt position animations */
+  // runtime values for belt position animations
   int belt_graphic[4][NUM_BELT_PARTS];
   int belt_anim_mode[4][NUM_BELT_PARTS];
 };
@@ -15049,7 +15099,7 @@ static struct EngineSnapshotInfo engine_snapshot_rnd;
 static char *snapshot_level_identifier = NULL;
 static int snapshot_level_nr = -1;
 
-static void SaveEngineSnapshotValues_RND()
+static void SaveEngineSnapshotValues_RND(void)
 {
   static int belt_base_active_element[4] =
   {
@@ -15088,7 +15138,7 @@ static void SaveEngineSnapshotValues_RND()
   }
 }
 
-static void LoadEngineSnapshotValues_RND()
+static void LoadEngineSnapshotValues_RND(void)
 {
   unsigned int num_random_calls = game.num_random_calls;
   int i, j;
@@ -15134,7 +15184,7 @@ static void LoadEngineSnapshotValues_RND()
   }
 }
 
-void FreeEngineSnapshotSingle()
+void FreeEngineSnapshotSingle(void)
 {
   FreeSnapshotSingle();
 
@@ -15142,16 +15192,16 @@ void FreeEngineSnapshotSingle()
   snapshot_level_nr = -1;
 }
 
-void FreeEngineSnapshotList()
+void FreeEngineSnapshotList(void)
 {
   FreeSnapshotList();
 }
 
-ListNode *SaveEngineSnapshotBuffers()
+static ListNode *SaveEngineSnapshotBuffers(void)
 {
   ListNode *buffers = NULL;
 
-  /* copy some special values to a structure better suited for the snapshot */
+  // copy some special values to a structure better suited for the snapshot
 
   if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
     SaveEngineSnapshotValues_RND();
@@ -15162,7 +15212,7 @@ ListNode *SaveEngineSnapshotBuffers()
   if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
     SaveEngineSnapshotValues_MM(&buffers);
 
-  /* save values stored in special snapshot structure */
+  // save values stored in special snapshot structure
 
   if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
     SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_rnd));
@@ -15173,7 +15223,7 @@ ListNode *SaveEngineSnapshotBuffers()
   if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
     SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_mm));
 
-  /* save further RND engine values */
+  // save further RND engine values
 
   SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(stored_player));
   SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(game));
@@ -15256,19 +15306,19 @@ ListNode *SaveEngineSnapshotBuffers()
   return buffers;
 }
 
-void SaveEngineSnapshotSingle()
+void SaveEngineSnapshotSingle(void)
 {
   ListNode *buffers = SaveEngineSnapshotBuffers();
 
-  /* finally save all snapshot buffers to single snapshot */
+  // finally save all snapshot buffers to single snapshot
   SaveSnapshotSingle(buffers);
 
-  /* save level identification information */
+  // save level identification information
   setString(&snapshot_level_identifier, leveldir_current->identifier);
   snapshot_level_nr = level_nr;
 }
 
-boolean CheckSaveEngineSnapshotToList()
+boolean CheckSaveEngineSnapshotToList(void)
 {
   boolean save_snapshot =
     ((game.snapshot.mode == SNAPSHOT_MODE_EVERY_STEP) ||
@@ -15284,7 +15334,7 @@ boolean CheckSaveEngineSnapshotToList()
   return save_snapshot;
 }
 
-void SaveEngineSnapshotToList()
+void SaveEngineSnapshotToList(void)
 {
   if (game.snapshot.mode == SNAPSHOT_MODE_OFF ||
       tape.quick_resume)
@@ -15292,20 +15342,20 @@ void SaveEngineSnapshotToList()
 
   ListNode *buffers = SaveEngineSnapshotBuffers();
 
-  /* finally save all snapshot buffers to snapshot list */
+  // finally save all snapshot buffers to snapshot list
   SaveSnapshotToList(buffers);
 }
 
-void SaveEngineSnapshotToListInitial()
+void SaveEngineSnapshotToListInitial(void)
 {
   FreeEngineSnapshotList();
 
   SaveEngineSnapshotToList();
 }
 
-void LoadEngineSnapshotValues()
+static void LoadEngineSnapshotValues(void)
 {
-  /* restore special values from snapshot structure */
+  // restore special values from snapshot structure
 
   if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
     LoadEngineSnapshotValues_RND();
@@ -15317,40 +15367,40 @@ void LoadEngineSnapshotValues()
     LoadEngineSnapshotValues_MM();
 }
 
-void LoadEngineSnapshotSingle()
+void LoadEngineSnapshotSingle(void)
 {
   LoadSnapshotSingle();
 
   LoadEngineSnapshotValues();
 }
 
-void LoadEngineSnapshot_Undo(int steps)
+static void LoadEngineSnapshot_Undo(int steps)
 {
   LoadSnapshotFromList_Older(steps);
 
   LoadEngineSnapshotValues();
 }
 
-void LoadEngineSnapshot_Redo(int steps)
+static void LoadEngineSnapshot_Redo(int steps)
 {
   LoadSnapshotFromList_Newer(steps);
 
   LoadEngineSnapshotValues();
 }
 
-boolean CheckEngineSnapshotSingle()
+boolean CheckEngineSnapshotSingle(void)
 {
   return (strEqual(snapshot_level_identifier, leveldir_current->identifier) &&
          snapshot_level_nr == level_nr);
 }
 
-boolean CheckEngineSnapshotList()
+boolean CheckEngineSnapshotList(void)
 {
   return CheckSnapshotList();
 }
 
 
-/* ---------- new game button stuff ---------------------------------------- */
+// ---------- new game button stuff -------------------------------------------
 
 static struct
 {
@@ -15449,7 +15499,7 @@ static struct
   }
 };
 
-void CreateGameButtons()
+void CreateGameButtons(void)
 {
   int i;
 
@@ -15535,7 +15585,7 @@ void CreateGameButtons()
   }
 }
 
-void FreeGameButtons()
+void FreeGameButtons(void)
 {
   int i;
 
@@ -15554,7 +15604,7 @@ static void UnmapGameButtonsAtSamePosition(int id)
       UnmapGadget(game_gadget[i]);
 }
 
-static void UnmapGameButtonsAtSamePosition_All()
+static void UnmapGameButtonsAtSamePosition_All(void)
 {
   if (setup.show_snapshot_buttons)
   {
@@ -15587,7 +15637,7 @@ static void MapGameButtonsAtSamePosition(int id)
   UnmapGameButtonsAtSamePosition_All();
 }
 
-void MapUndoRedoButtons()
+void MapUndoRedoButtons(void)
 {
   UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_UNDO);
   UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_REDO);
@@ -15598,7 +15648,7 @@ void MapUndoRedoButtons()
   ModifyGadget(game_gadget[GAME_CTRL_ID_PAUSE2], GDI_CHECKED, TRUE, GDI_END);
 }
 
-void UnmapUndoRedoButtons()
+void UnmapUndoRedoButtons(void)
 {
   UnmapGadget(game_gadget[GAME_CTRL_ID_UNDO]);
   UnmapGadget(game_gadget[GAME_CTRL_ID_REDO]);
@@ -15609,7 +15659,7 @@ void UnmapUndoRedoButtons()
   ModifyGadget(game_gadget[GAME_CTRL_ID_PAUSE2], GDI_CHECKED, FALSE, GDI_END);
 }
 
-void MapGameButtonsExt(boolean on_tape)
+static void MapGameButtonsExt(boolean on_tape)
 {
   int i;
 
@@ -15624,7 +15674,7 @@ void MapGameButtonsExt(boolean on_tape)
   RedrawGameButtons();
 }
 
-void UnmapGameButtonsExt(boolean on_tape)
+static void UnmapGameButtonsExt(boolean on_tape)
 {
   int i;
 
@@ -15633,7 +15683,7 @@ void UnmapGameButtonsExt(boolean on_tape)
       UnmapGadget(game_gadget[i]);
 }
 
-void RedrawGameButtonsExt(boolean on_tape)
+static void RedrawGameButtonsExt(boolean on_tape)
 {
   int i;
 
@@ -15645,7 +15695,7 @@ void RedrawGameButtonsExt(boolean on_tape)
   redraw_mask &= ~REDRAW_ALL;
 }
 
-void SetGadgetState(struct GadgetInfo *gi, boolean state)
+static void SetGadgetState(struct GadgetInfo *gi, boolean state)
 {
   if (gi == NULL)
     return;
@@ -15653,7 +15703,7 @@ void SetGadgetState(struct GadgetInfo *gi, boolean state)
   gi->checked = state;
 }
 
-void RedrawSoundButtonGadget(int id)
+static void RedrawSoundButtonGadget(int id)
 {
   int id2 = (id == SOUND_CTRL_ID_MUSIC        ? SOUND_CTRL_ID_PANEL_MUSIC :
             id == SOUND_CTRL_ID_LOOPS        ? SOUND_CTRL_ID_PANEL_LOOPS :
@@ -15667,37 +15717,37 @@ void RedrawSoundButtonGadget(int id)
   RedrawGadget(game_gadget[id2]);
 }
 
-void MapGameButtons()
+void MapGameButtons(void)
 {
   MapGameButtonsExt(FALSE);
 }
 
-void UnmapGameButtons()
+void UnmapGameButtons(void)
 {
   UnmapGameButtonsExt(FALSE);
 }
 
-void RedrawGameButtons()
+void RedrawGameButtons(void)
 {
   RedrawGameButtonsExt(FALSE);
 }
 
-void MapGameButtonsOnTape()
+void MapGameButtonsOnTape(void)
 {
   MapGameButtonsExt(TRUE);
 }
 
-void UnmapGameButtonsOnTape()
+void UnmapGameButtonsOnTape(void)
 {
   UnmapGameButtonsExt(TRUE);
 }
 
-void RedrawGameButtonsOnTape()
+void RedrawGameButtonsOnTape(void)
 {
   RedrawGameButtonsExt(TRUE);
 }
 
-void GameUndoRedoExt()
+static void GameUndoRedoExt(void)
 {
   ClearPlayerAction();
 
@@ -15714,7 +15764,7 @@ void GameUndoRedoExt()
   BackToFront();
 }
 
-void GameUndo(int steps)
+static void GameUndo(int steps)
 {
   if (!CheckEngineSnapshotList())
     return;
@@ -15724,7 +15774,7 @@ void GameUndo(int steps)
   GameUndoRedoExt();
 }
 
-void GameRedo(int steps)
+static void GameRedo(int steps)
 {
   if (!CheckEngineSnapshotList())
     return;