added saving tape basename for each high score entry
[rocksndiamonds.git] / src / game.c
index 48f5e7f158e13c68da188ade38a79d427057f63b..2002126623cb737ffc4f103eb36e8d72435e043b 100644 (file)
@@ -2402,7 +2402,7 @@ static void UpdateGameControlValues(void)
   }
 
   game_panel_controls[GAME_PANEL_SCORE].value = score;
-  game_panel_controls[GAME_PANEL_HIGHSCORE].value = highscore[0].Score;
+  game_panel_controls[GAME_PANEL_HIGHSCORE].value = scores.entry[0].score;
 
   game_panel_controls[GAME_PANEL_TIME].value = time;
 
@@ -3809,6 +3809,9 @@ void InitGame(void)
   game.switchgate_pos = 0;
   game.wind_direction = level.wind_direction_initial;
 
+  game.time_final = 0;
+  game.score_time_final = 0;
+
   game.score = 0;
   game.score_final = 0;
 
@@ -4705,19 +4708,6 @@ static void LevelSolved(void)
 
   game.LevelSolved = TRUE;
   game.GameOver = TRUE;
-
-  game.score_final = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
-                     game_em.lev->score :
-                     level.game_engine_type == GAME_ENGINE_TYPE_MM ?
-                     game_mm.score :
-                     game.score);
-  game.health_final = (level.game_engine_type == GAME_ENGINE_TYPE_MM ?
-                      MM_HEALTH(game_mm.laser_overload_value) :
-                      game.health);
-
-  game.LevelSolved_CountingTime = (game.no_time_limit ? TimePlayed : TimeLeft);
-  game.LevelSolved_CountingScore = game.score_final;
-  game.LevelSolved_CountingHealth = game.health_final;
 }
 
 void GameWon(void)
@@ -4740,6 +4730,24 @@ void GameWon(void)
     if (local_player->active && local_player->MovPos)
       return;
 
+    game.time_final = (game.no_time_limit ? TimePlayed : TimeLeft);
+    game.score_time_final = (level.use_step_counter ? TimePlayed :
+                            TimePlayed * FRAMES_PER_SECOND + TimeFrames);
+
+    game.score_final = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
+                       game_em.lev->score :
+                       level.game_engine_type == GAME_ENGINE_TYPE_MM ?
+                       game_mm.score :
+                       game.score);
+
+    game.health_final = (level.game_engine_type == GAME_ENGINE_TYPE_MM ?
+                        MM_HEALTH(game_mm.laser_overload_value) :
+                        game.health);
+
+    game.LevelSolved_CountingTime = game.time_final;
+    game.LevelSolved_CountingScore = game.score_final;
+    game.LevelSolved_CountingHealth = game.health_final;
+
     game.LevelSolved_GameWon = TRUE;
     game.LevelSolved_SaveTape = tape.recording;
     game.LevelSolved_SaveScore = !tape.playing;
@@ -4760,23 +4768,27 @@ void GameWon(void)
     game_over_delay_2 = FRAMES_PER_SECOND / 2; // delay before counting health
     game_over_delay_3 = FRAMES_PER_SECOND;     // delay before ending the game
 
-    time = time_final = (game.no_time_limit ? TimePlayed : TimeLeft);
+    time = time_final = game.time_final;
     score = score_final = game.score_final;
     health = health_final = game.health_final;
 
     if (time_score > 0)
     {
+      int time_final_max = 999;
+      int time_frames_final_max = time_final_max * FRAMES_PER_SECOND;
       int time_frames = 0;
+      int time_frames_left = TimeLeft * FRAMES_PER_SECOND - TimeFrames;
+      int time_frames_played = TimePlayed * FRAMES_PER_SECOND + TimeFrames;
 
       if (TimeLeft > 0)
       {
        time_final = 0;
-       time_frames = TimeLeft * FRAMES_PER_SECOND - TimeFrames;
+       time_frames = time_frames_left;
       }
-      else if (game.no_time_limit && TimePlayed < 999)
+      else if (game.no_time_limit && TimePlayed < time_final_max)
       {
-       time_final = 999;
-       time_frames = (999 - TimePlayed) * FRAMES_PER_SECOND - TimeFrames;
+       time_final = time_final_max;
+       time_frames = time_frames_final_max - time_frames_played;
       }
 
       score_final += time_score * time_frames / FRAMES_PER_SECOND + 0.5;
@@ -4959,6 +4971,9 @@ void GameEnd(void)
       CloseDoor(DOOR_CLOSE_1);
 
     SaveTapeChecked_LevelSolved(tape.level_nr);                // ask to save tape
+
+    // set unique basename for score tape (also saved in high score table)
+    strcpy(tape.score_tape_basename, getScoreTapeBasename(setup.player_name));
   }
 
   // if no tape is to be saved, close both doors simultaneously
@@ -5035,12 +5050,26 @@ int NewHiScore(int level_nr)
   LoadScore(level_nr);
 
   if (strEqual(setup.player_name, EMPTY_PLAYER_NAME) ||
-      game.score_final < highscore[MAX_SCORE_ENTRIES - 1].Score)
+      game.score_final < scores.entry[MAX_SCORE_ENTRIES - 1].score)
     return -1;
 
   for (k = 0; k < MAX_SCORE_ENTRIES; k++)
   {
-    if (game.score_final > highscore[k].Score)
+    struct ScoreEntry *entry = &scores.entry[k];
+    boolean score_is_better = (game.score_final      >  entry->score);
+    boolean score_is_equal  = (game.score_final      == entry->score);
+    boolean time_is_better  = (game.score_time_final <  entry->time);
+    boolean time_is_equal   = (game.score_time_final == entry->time);
+    boolean better_by_score = (score_is_better ||
+                              (score_is_equal && time_is_better));
+    boolean better_by_time  = (time_is_better ||
+                              (time_is_equal && score_is_better));
+    boolean is_better = (level.rate_time_over_score ? better_by_time :
+                        better_by_score);
+    boolean entry_is_empty = (entry->score == 0 &&
+                             entry->time == 0);
+
+    if (is_better || entry_is_empty)
     {
       // player has made it to the hall of fame
 
@@ -5051,7 +5080,7 @@ int NewHiScore(int level_nr)
        if (one_score_entry_per_name)
        {
          for (l = k; l < MAX_SCORE_ENTRIES; l++)
-           if (strEqual(setup.player_name, highscore[l].Name))
+           if (strEqual(setup.player_name, scores.entry[l].name))
              m = l;
 
          if (m == k)   // player's new highscore overwrites his old one
@@ -5060,28 +5089,33 @@ int NewHiScore(int level_nr)
 
        for (l = m; l > k; l--)
        {
-         strcpy(highscore[l].Name, highscore[l - 1].Name);
-         highscore[l].Score = highscore[l - 1].Score;
+         strcpy(scores.entry[l].name, scores.entry[l - 1].name);
+         scores.entry[l].score = scores.entry[l - 1].score;
+         scores.entry[l].time  = scores.entry[l - 1].time;
        }
       }
 
       put_into_list:
 
-      strncpy(highscore[k].Name, setup.player_name, MAX_PLAYER_NAME_LEN);
-      highscore[k].Name[MAX_PLAYER_NAME_LEN] = '\0';
-      highscore[k].Score = game.score_final;
+      strcpy(entry->tape_basename, tape.score_tape_basename);
+      strncpy(entry->name, setup.player_name, MAX_PLAYER_NAME_LEN);
+      entry->name[MAX_PLAYER_NAME_LEN] = '\0';
+      entry->score = game.score_final;
+      entry->time = game.score_time_final;
       position = k;
 
       break;
     }
     else if (one_score_entry_per_name &&
-            !strncmp(setup.player_name, highscore[k].Name,
-                     MAX_PLAYER_NAME_LEN))
+            !strncmp(setup.player_name, entry->name, MAX_PLAYER_NAME_LEN))
       break;   // player already there with a higher score
   }
 
-  if (position >= 0) 
+  if (position >= 0)
+  {
+    SaveScoreTape(level_nr);
     SaveScore(level_nr);
+  }
 
   return position;
 }
@@ -13113,7 +13147,7 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
        RemovePlayer(player);
     }
 
-    if (!game.LevelSolved && level.use_step_counter)
+    if (level.use_step_counter)
     {
       int i;
 
@@ -13123,14 +13157,14 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
       {
        TimeLeft--;
 
-       if (TimeLeft <= 10 && setup.time_limit)
+       if (TimeLeft <= 10 && setup.time_limit && !game.LevelSolved)
          PlaySound(SND_GAME_RUNNING_OUT_OF_TIME);
 
        game_panel_controls[GAME_PANEL_TIME].value = TimeLeft;
 
        DisplayGameControlValues();
 
-       if (!TimeLeft && setup.time_limit)
+       if (!TimeLeft && setup.time_limit && !game.LevelSolved)
          for (i = 0; i < MAX_PLAYERS; i++)
            KillPlayer(&stored_player[i]);
       }
@@ -15373,12 +15407,12 @@ 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
-    if (!skip_request)
+    if (!quick_quit)
     {
       // prevent short reactivation of overlay buttons while closing door
       SetOverlayActive(FALSE);
 
+      // door may still be open due to skipped or envelope style request
       CloseDoor(DOOR_CLOSE_1);
     }
 
@@ -15406,10 +15440,13 @@ void RequestQuitGameExt(boolean skip_request, boolean quick_quit, char *message)
   }
 }
 
-void RequestQuitGame(boolean ask_if_really_quit)
+void RequestQuitGame(boolean escape_key_pressed)
 {
-  boolean quick_quit = (!ask_if_really_quit || level_editor_test_game);
-  boolean skip_request = game.all_players_gone || quick_quit;
+  boolean ask_on_escape = (setup.ask_on_escape && setup.ask_on_quit_game);
+  boolean quick_quit = ((escape_key_pressed && !ask_on_escape) ||
+                       level_editor_test_game);
+  boolean skip_request = (game.all_players_gone || !setup.ask_on_quit_game ||
+                         quick_quit);
 
   RequestQuitGameExt(skip_request, quick_quit,
                     "Do you really want to quit the game?");
@@ -16271,7 +16308,7 @@ static void HandleGameButtonsExt(int id, int button)
       if (tape.playing)
        TapeStop();
       else
-       RequestQuitGame(TRUE);
+       RequestQuitGame(FALSE);
 
       break;