moved requesting game restart to function that checks for game over
[rocksndiamonds.git] / src / game.c
index d3d7f513034d9f75dcc5a68d8d9819ef7073dda9..c5d941dd093b0882faf8d9b2dbd16c1e7ea23f86 100644 (file)
@@ -2566,7 +2566,9 @@ static void UpdateGameControlValues(void)
        int element = gpc->value;
        int graphic = el2panelimg(element);
        int init_gfx_random = (graphic_info[graphic].anim_global_sync ?
-                              sync_random_frame : INIT_GFX_RANDOM());
+                              sync_random_frame :
+                              graphic_info[graphic].anim_global_anim_sync ?
+                              getGlobalAnimSyncFrame() : INIT_GFX_RANDOM());
 
        if (gpc->value != gpc->last_value)
        {
@@ -2601,7 +2603,9 @@ static void UpdateGameControlValues(void)
        int last_anim_random_frame = gfx.anim_random_frame;
        int graphic = gpc->graphic;
        int init_gfx_random = (graphic_info[graphic].anim_global_sync ?
-                              sync_random_frame : INIT_GFX_RANDOM());
+                              sync_random_frame :
+                              graphic_info[graphic].anim_global_anim_sync ?
+                              getGlobalAnimSyncFrame() : INIT_GFX_RANDOM());
 
        if (gpc->value != gpc->last_value)
        {
@@ -3569,7 +3573,7 @@ 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 restarting = (game_status == GAME_MODE_PLAYING);
   boolean emulate_bd = TRUE;   // unless non-BOULDERDASH elements found
   boolean emulate_sp = TRUE;   // unless non-SUPAPLEX    elements found
   int initial_move_dir = MV_DOWN;
@@ -3581,7 +3585,15 @@ void InitGame(void)
   if (!game.restart_level)
     CloseDoor(DOOR_CLOSE_1);
 
-  SetGameStatus(GAME_MODE_PLAYING);
+  if (restarting)
+  {
+    // force fading out global animations displayed during game play
+    SetGameStatus(GAME_MODE_PSEUDO_RESTARTING);
+  }
+  else
+  {
+    SetGameStatus(GAME_MODE_PLAYING);
+  }
 
   if (level_editor_test_game)
     FadeSkipNextFadeOut();
@@ -3597,6 +3609,14 @@ void InitGame(void)
 
   FadeOut(fade_mask);
 
+  if (restarting)
+  {
+    // force restarting global animations displayed during game play
+    RestartGlobalAnimsByStatus(GAME_MODE_PSEUDO_RESTARTING);
+
+    SetGameStatus(GAME_MODE_PLAYING);
+  }
+
   if (level_editor_test_game)
     FadeSkipNextFadeIn();
 
@@ -5305,6 +5325,8 @@ static void ResetGfxFrame(int x, int y)
 
   if (graphic_info[graphic].anim_global_sync)
     GfxFrame[x][y] = FrameCounter;
+  else if (graphic_info[graphic].anim_global_anim_sync)
+    GfxFrame[x][y] = getGlobalAnimSyncFrame();
   else if (ANIM_MODE(graphic) == ANIM_CE_VALUE)
     GfxFrame[x][y] = CustomValue[x][y];
   else if (ANIM_MODE(graphic) == ANIM_CE_SCORE)
@@ -9853,7 +9875,7 @@ static void CheckWallGrowing(int ax, int ay)
 
   if (((stop_top && stop_bottom) || stop_horizontal) &&
       ((stop_left && stop_right) || stop_vertical))
-    Tile[ax][ay] = EL_WALL;
+    Tile[ax][ay] = (is_steelwall ? EL_STEELWALL : EL_WALL);
 
   if (new_wall)
     PlayLevelSoundAction(ax, ay, ACTION_GROWING);
@@ -11672,6 +11694,21 @@ void AdvanceFrameAndPlayerCounters(int player_nr)
   }
 }
 
+void AdvanceFrameCounter(void)
+{
+  FrameCounter++;
+}
+
+void AdvanceGfxFrame(void)
+{
+  int x, y;
+
+  SCAN_PLAYFIELD(x, y)
+  {
+    GfxFrame[x][y]++;
+  }
+}
+
 void StartGameActions(boolean init_network_game, boolean record_tape,
                      int random_seed)
 {
@@ -11867,7 +11904,7 @@ static void GameActionsExt(void)
     TapeRecordAction(tape_action);
 
   // remember if game was played (especially after tape stopped playing)
-  if (!tape.playing && summarized_player_action)
+  if (!tape.playing && summarized_player_action && !checkGameFailed())
     game.GamePlayed = TRUE;
 
 #if USE_NEW_PLAYER_ASSIGNMENTS
@@ -12019,6 +12056,8 @@ void GameActions_SP_Main(void)
 
 void GameActions_MM_Main(void)
 {
+  AdvanceGfxFrame();
+
   GameActions_MM(local_player->effective_mouse_action);
 }
 
@@ -13959,7 +13998,6 @@ void BuryPlayer(struct PlayerInfo *player)
     return;
 
   PlayLevelSoundElementAction(jx, jy, player->artwork_element, ACTION_DYING);
-  PlayLevelSound(jx, jy, SND_GAME_LOSING);
 
   RemovePlayer(player);
 
@@ -14617,7 +14655,7 @@ static int DigField(struct PlayerInfo *player,
 
        LevelSolved();
 
-       PlayLevelSound(x, y, SND_GAME_SOKOBAN_SOLVING);
+       PlaySound(SND_GAME_SOKOBAN_SOLVING);
       }
     }
     else
@@ -15601,15 +15639,21 @@ void RequestRestartGame(char *message)
 
   boolean has_started_game = hasStartedNetworkGame();
   int request_mode = (has_started_game ? REQ_ASK : REQ_CONFIRM);
+  int door_state = DOOR_CLOSE_1;
 
-  if (Request(message, request_mode | REQ_STAY_CLOSED) && has_started_game)
+  if (Request(message, request_mode | REQ_STAY_OPEN) && has_started_game)
   {
+    CloseDoor(door_state);
+
     StartGameActions(network.enabled, setup.autorecord, level.random_seed);
   }
   else
   {
-    // needed in case of envelope request to close game panel
-    CloseDoor(DOOR_CLOSE_1);
+    // if game was invoked from level editor, also close tape recorder door
+    if (level_editor_test_game)
+      door_state = DOOR_CLOSE_ALL;
+
+    CloseDoor(door_state);
 
     SetGameStatus(GAME_MODE_MAIN);
 
@@ -15617,42 +15661,73 @@ void RequestRestartGame(char *message)
   }
 }
 
-void CheckGameOver(void)
+static char *getRestartGameMessage(void)
+{
+  boolean play_again = hasStartedNetworkGame();
+  static char message[MAX_OUTPUT_LINESIZE];
+  char *game_over_text = "Game over!";
+  char *play_again_text = " Play it again?";
+
+  if (level.game_engine_type == GAME_ENGINE_TYPE_MM &&
+      game_mm.game_over_message != NULL)
+    game_over_text = game_mm.game_over_message;
+
+  snprintf(message, MAX_OUTPUT_LINESIZE, "%s%s", game_over_text,
+          (play_again ? play_again_text : ""));
+
+  return message;
+}
+
+boolean CheckRestartGame(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;
-
-  // do not ask to play again if game was never actually played
-  if (!game.GamePlayed)
-    return;
-
   if (!game_over)
   {
     last_game_over = FALSE;
     game_over_delay = game_over_delay_value;
 
-    return;
+    return FALSE;
   }
 
   if (game_over_delay > 0)
   {
+    if (game_over_delay == game_over_delay_value / 2)
+      PlaySound(SND_GAME_LOSING);
+
     game_over_delay--;
 
-    return;
+    return FALSE;
   }
 
+  // do not handle game over if request dialog is already active
+  if (game.request_active)
+    return FALSE;
+
+  // do not ask to play again if game was never actually played
+  if (!game.GamePlayed)
+    return FALSE;
+
+  // do not ask to play again if this was disabled in setup menu
+  if (!setup.ask_on_game_over)
+    return FALSE;
+
   if (last_game_over != game_over)
-    game.restart_game_message = (hasStartedNetworkGame() ?
-                                "Game over! Play it again?" :
-                                "Game over!");
+    game.restart_game_message = getRestartGameMessage();
 
   last_game_over = game_over;
+
+  if (game.restart_game_message != NULL)
+  {
+    RequestRestartGame(game.restart_game_message);
+
+    return TRUE;
+  }
+
+  return FALSE;
 }
 
 boolean checkGameSolved(void)