fixed asking all network clients to "play again" after unsolved game end
[rocksndiamonds.git] / src / game.c
index 40efde17d7321a5dcac60e754bea4c0230e16ddf..f359a2cbdfb406c6bf018873c7b14c5901397dfc 100644 (file)
@@ -81,7 +81,7 @@
 #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))
@@ -3525,7 +3525,6 @@ void InitGame(void)
 
     player->LevelSolved_GameWon = FALSE;
     player->LevelSolved_GameEnd = FALSE;
-    player->LevelSolved_PanelOff = FALSE;
     player->LevelSolved_SaveTape = FALSE;
     player->LevelSolved_SaveScore = FALSE;
 
@@ -3559,6 +3558,8 @@ void InitGame(void)
 
   AllPlayersGone = FALSE;
 
+  game.panel.active = TRUE;
+
   game.no_time_limit = (level.time == 0);
 
   game.yamyam_content_nr = 0;
@@ -4195,6 +4196,7 @@ void InitGame(void)
 
   game.restart_level = FALSE;
   game.restart_game_message = NULL;
+  game.request_active = FALSE;
 
   if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
     InitGameActions_MM();
@@ -4653,7 +4655,7 @@ void GameWon(void)
     return;
   }
 
-  local_player->LevelSolved_PanelOff = TRUE;
+  game.panel.active = FALSE;
 
   if (game_over_delay_3 > 0)
   {
@@ -4734,6 +4736,7 @@ void GameEnd(void)
     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);
@@ -11080,11 +11083,8 @@ static void SetTapeActionFromMouseAction(byte *tape_action,
   tape_action[TAPE_ACTION_BUTTON] = mouse_action->button;
 }
 
-static void CheckLevelTime(void)
+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 */
@@ -11132,6 +11132,11 @@ static void CheckLevelTime(void)
     if (game_mm.game_over)                             /* game lost */
       AllPlayersGone = TRUE;
   }
+}
+
+static void CheckLevelTime(void)
+{
+  int i;
 
   if (TimeFrames >= FRAMES_PER_SECOND)
   {
@@ -11296,54 +11301,7 @@ static void GameActionsExt(void)
   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)
     GameWon();
@@ -11388,7 +11346,8 @@ static void GameActionsExt(void)
     if (game_status != GAME_MODE_PLAYING)
       return;
 
-    if (!network_player_action_received)
+    /* 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) */
@@ -11428,7 +11387,7 @@ static void GameActionsExt(void)
       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
@@ -11542,6 +11501,7 @@ static void GameActionsExt(void)
 
   BlitScreenToBitmap(backbuffer);
 
+  CheckLevelSolved();
   CheckLevelTime();
 
   AdvanceFrameAndPlayerCounters(-1);   /* advance counters for all players */
@@ -14978,7 +14938,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);
   }
@@ -14990,6 +14953,66 @@ 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 local_player->LevelSolved_GameEnd;
+}
+
+boolean checkGameFailed(void)
+{
+  if (!AllPlayersGone)
+    return FALSE;
+
+  if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+    return (level.native_em_level->lev->home > 0);
+  else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+    return (game_sp.GameOver && !game_sp.LevelSolved);
+  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 && !local_player->LevelSolved);
+}
+
+boolean checkGameEnded(void)
+{
+  return (checkGameSolved() || checkGameFailed());
+}
+
 
 /* ------------------------------------------------------------------------- */
 /* random generator functions                                                */