added setup option to ask to play again after game is over but not solved
[rocksndiamonds.git] / src / screens.c
index 1ab2be290547204e844e7ba65e3b442e436c2006..3c12d6b5df34b14d528fd4d61f8c7a828e64bfd7 100644 (file)
@@ -251,6 +251,9 @@ static void HandleInfoScreen_Credits(int);
 static void HandleInfoScreen_Program(int);
 static void HandleInfoScreen_Version(int);
 
+static void ModifyGameSpeedIfNeeded(void);
+static void DisableVsyncIfNeeded(void);
+
 static void MapScreenMenuGadgets(int);
 static void MapScreenGadgets(int);
 static void MapScreenTreeGadgets(TreeInfo *);
@@ -280,6 +283,8 @@ static TreeInfo *scroll_delay_current = NULL;
 static TreeInfo *snapshot_modes = NULL;
 static TreeInfo *snapshot_mode_current = NULL;
 
+static TreeInfo *game_speeds_normal = NULL;
+static TreeInfo *game_speeds_extended = NULL;
 static TreeInfo *game_speeds = NULL;
 static TreeInfo *game_speed_current = NULL;
 
@@ -359,33 +364,39 @@ static struct StringValueTextInfo vsync_modes_list[] =
   {    NULL,                            NULL           },
 };
 
-static struct ValueTextInfo game_speeds_list[] =
+static struct ValueTextInfo game_speeds_list_normal[] =
 {
-#if 1
   {    30,     "Very Slow"                     },
   {    25,     "Slow"                          },
   {    20,     "Normal"                        },
   {    15,     "Fast"                          },
   {    10,     "Very Fast"                     },
-#else
-  {    1000,   "1/1s (Extremely Slow)"         },
-  {    500,    "1/2s"                          },
-  {    200,    "1/5s"                          },
-  {    100,    "1/10s"                         },
-  {    50,     "1/20s"                         },
-  {    29,     "1/35s (Original Supaplex)"     },
-  {    25,     "1/40s"                         },
-  {    20,     "1/50s (Normal Speed)"          },
-  {    14,     "1/70s (Maximum Supaplex)"      },
-  {    10,     "1/100s"                        },
-  {    5,      "1/200s"                        },
-  {    2,      "1/500s"                        },
-  {    1,      "1/1000s (Extremely Fast)"      },
-#endif
 
   {    -1,     NULL                            },
 };
 
+static struct ValueTextInfo game_speeds_list_extended[] =
+{
+  {    1000,   "1 fps (Extremely Slow)"        },
+  {    500,    "2 fps"                         },
+  {    200,    "5 fps"                         },
+  {    100,    "10 fps"                        },
+  {    50,     "20 fps"                        },
+  {    29,     "35 fps (Original Supaplex)"    },
+  {    25,     "40 fps"                        },
+  {    20,     "50 fps (=== Normal Speed ===)" },
+  {    16,     "60 fps (60 Hz VSync Speed)"    },
+  {    14,     "70 fps (Maximum Supaplex)"     },
+  {    10,     "100 fps"                       },
+  {    5,      "200 fps"                       },
+  {    2,      "500 fps"                       },
+  {    1,      "1000 fps (Extremely Fast)"     },
+
+  {    -1,     NULL                            },
+};
+
+static struct ValueTextInfo *game_speeds_list;
+
 static struct ValueTextInfo scroll_delays_list[] =
 {
   {    0,      "0 Tiles (No Scroll Delay)"     },
@@ -4651,6 +4662,7 @@ void HandleHallOfFame(int mx, int my, int dx, int dy, int button)
 
     if (game_status_last_screen == GAME_MODE_PLAYING &&
        setup.auto_play_next_level && setup.increment_levels &&
+       level_nr < leveldir_current->last_level &&
        !network_playing)
     {
       StartGameActions(network.enabled, setup.autorecord, level.random_seed);
@@ -4705,6 +4717,17 @@ static void execSetupMain(void)
 
 static void execSetupGame_setGameSpeeds(boolean update_value)
 {
+  if (setup.game_speed_extended)
+  {
+    game_speeds_list = game_speeds_list_extended;
+    game_speeds      = game_speeds_extended;
+  }
+  else
+  {
+    game_speeds_list = game_speeds_list_normal;
+    game_speeds      = game_speeds_normal;
+  }
+
   if (game_speeds == NULL)
   {
     int i;
@@ -4750,6 +4773,11 @@ static void execSetupGame_setGameSpeeds(boolean update_value)
     /* if that also fails, set current game speed to first available speed */
     if (game_speed_current == NULL)
       game_speed_current = game_speeds;
+
+    if (setup.game_speed_extended)
+      game_speeds_extended = game_speeds;
+    else
+      game_speeds_normal = game_speeds;
   }
 
   setup.game_frame_delay = atoi(game_speed_current->identifier);
@@ -4875,30 +4903,9 @@ static void execSetupGame_setNetworkServerText(void)
   network_server_text = network_server_hostname;
 }
 
-static void CheckGameSpeedForVsync(boolean force_vsync_game_speed)
-{
-  if (strEqual(setup.vsync_mode, STR_VSYNC_MODE_OFF) ||
-      setup.game_frame_delay <= MAX_VSYNC_FRAME_DELAY)
-    return;
-
-  if (force_vsync_game_speed)
-  {
-    /* set game speed to existing list value that is fast enough for vsync */
-    setup.game_frame_delay = 15;
-
-    execSetupGame_setGameSpeeds(TRUE);
-
-    Request("Game speed was set to \"fast\" for VSync to work!", REQ_CONFIRM);
-  }
-  else
-  {
-    Request("Warning! Game speed too low for VSync to work!", REQ_CONFIRM);
-  }
-}
-
 static void execSetupGame(void)
 {
-  boolean check_vsync_game_speed = (setup_mode == SETUP_MODE_CHOOSE_GAME_SPEED);
+  boolean check_vsync_mode = (setup_mode == SETUP_MODE_CHOOSE_GAME_SPEED);
 
   execSetupGame_setGameSpeeds(FALSE);
   execSetupGame_setScrollDelays();
@@ -4910,9 +4917,9 @@ static void execSetupGame(void)
 
   DrawSetupScreen();
 
-  // check if game speed is high enough for 60 Hz vsync to work
-  if (check_vsync_game_speed)
-    CheckGameSpeedForVsync(FALSE);
+  // check if vsync needs to be disabled for this game speed to work
+  if (check_vsync_mode)
+    DisableVsyncIfNeeded();
 }
 
 static void execSetupChooseGameSpeed(void)
@@ -5129,7 +5136,7 @@ static void execSetupGraphics_setRenderingModes(void)
   rendering_mode_text = rendering_mode_current->name;
 }
 
-static void execSetupGraphics_setVsyncModes(void)
+static void execSetupGraphics_setVsyncModes(boolean update_value)
 {
   if (vsync_modes == NULL)
   {
@@ -5159,6 +5166,11 @@ static void execSetupGraphics_setVsyncModes(void)
     /* sort vsync mode values to start with lowest vsync mode value */
     sortTreeInfo(&vsync_modes);
 
+    update_value = TRUE;
+  }
+
+  if (update_value)
+  {
     /* set current vsync mode value to configured vsync mode value */
     vsync_mode_current =
       getTreeInfoFromIdentifier(vsync_modes, setup.vsync_mode);
@@ -5181,7 +5193,7 @@ static void execSetupGraphics_setVsyncModes(void)
 
 static void execSetupGraphics(void)
 {
-  boolean check_vsync_game_speed = (setup_mode == SETUP_MODE_CHOOSE_VSYNC);
+  boolean check_game_speed = (setup_mode == SETUP_MODE_CHOOSE_VSYNC);
 
   // update "setup.window_scaling_percent" from list selection
   // (in this case, window scaling was changed on setup screen)
@@ -5194,15 +5206,15 @@ static void execSetupGraphics(void)
 
   execSetupGraphics_setScalingTypes();
   execSetupGraphics_setRenderingModes();
-  execSetupGraphics_setVsyncModes();
+  execSetupGraphics_setVsyncModes(FALSE);
 
   setup_mode = SETUP_MODE_GRAPHICS;
 
   DrawSetupScreen();
 
   // check if game speed is high enough for 60 Hz vsync to work
-  if (check_vsync_game_speed)
-    CheckGameSpeedForVsync(TRUE);
+  if (check_game_speed)
+    ModifyGameSpeedIfNeeded();
 
 #if defined(TARGET_SDL2)
   // window scaling may have changed at this point
@@ -5975,6 +5987,71 @@ static void ToggleNetworkModeIfNeeded(void)
   DrawSetupScreen();
 }
 
+static void ToggleGameSpeedsListIfNeeded(void)
+{
+  boolean using_game_speeds_extended = (game_speeds == game_speeds_extended);
+
+  if (setup.game_speed_extended == using_game_speeds_extended)
+    return;
+
+  /* try to match similar values when changing game speeds list */
+  if (setup.game_speed_extended)
+    setup.game_frame_delay = (setup.game_frame_delay == 15 ? 16 :
+                             setup.game_frame_delay == 30 ? 29 :
+                             setup.game_frame_delay);
+  else
+    setup.game_frame_delay = (setup.game_frame_delay == 14 ? 15 :
+                             setup.game_frame_delay == 16 ? 15 :
+                             setup.game_frame_delay >= 29 ? 30 :
+                             setup.game_frame_delay <= 10 ? 10 :
+                             setup.game_frame_delay);
+
+  execSetupGame_setGameSpeeds(TRUE);
+
+  DrawSetupScreen();
+}
+
+static void ModifyGameSpeedIfNeeded(void)
+{
+  if (strEqual(setup.vsync_mode, STR_VSYNC_MODE_OFF) ||
+      setup.game_frame_delay <= MAX_VSYNC_FRAME_DELAY)
+    return;
+
+  char message[100];
+  char *game_speed_text = "Fast";
+  int game_speed_value = 15;
+
+  if (setup.game_speed_extended)
+  {
+    game_speed_text = "60 fps";
+    game_speed_value = 16;
+  }
+
+  sprintf(message, "Game speed set to %s for VSync to work!", game_speed_text);
+
+  /* set game speed to existing list value that is fast enough for vsync */
+  setup.game_frame_delay = game_speed_value;
+
+  execSetupGame_setGameSpeeds(TRUE);
+
+  Request(message, REQ_CONFIRM);
+}
+
+static void DisableVsyncIfNeeded(void)
+{
+  if (strEqual(setup.vsync_mode, STR_VSYNC_MODE_OFF) ||
+      (setup.game_frame_delay >= MIN_VSYNC_FRAME_DELAY &&
+       setup.game_frame_delay <= MAX_VSYNC_FRAME_DELAY))
+    return;
+
+  /* disable vsync for the selected game speed to work */
+  setup.vsync_mode = STR_VSYNC_MODE_OFF;
+
+  execSetupGraphics_setVsyncModes(TRUE);
+
+  Request("VSync disabled for this game speed to work!", REQ_CONFIRM);
+}
+
 static struct
 {
   void *value;
@@ -6087,9 +6164,11 @@ static struct TokenInfo setup_info_game[] =
   { TYPE_SWITCH,       &setup.increment_levels,"Increment Solved Levels:" },
   { TYPE_SWITCH,       &setup.auto_play_next_level,"Auto-play Next Level:" },
   { TYPE_SWITCH,       &setup.skip_scores_after_game,"Skip Scores After Game:" },
+  { TYPE_YES_NO,       &setup.ask_on_game_over, "Ask on Game Over:"    },
   { TYPE_SWITCH,       &setup.autorecord,      "Auto-Record Tapes:"    },
   { TYPE_ENTER_LIST,   execSetupChooseGameSpeed, "Game Speed:"         },
   { TYPE_STRING,       &game_speed_text,       ""                      },
+  { TYPE_SWITCH,       &setup.game_speed_extended, "Game Speed Extended List:" },
 #if 1
   { TYPE_ENTER_LIST,   execSetupChooseScrollDelay, "Scroll Delay:"     },
   { TYPE_STRING,       &scroll_delay_text,     ""                      },
@@ -6653,6 +6732,10 @@ static void changeSetupValue(int screen_pos, int setup_info_pos_raw, int dx)
   // network mode may have changed at this point
   if (si->value == &setup.network_mode)
     ToggleNetworkModeIfNeeded();
+
+  // game speed list may have changed at this point
+  if (si->value == &setup.game_speed_extended)
+    ToggleGameSpeedsListIfNeeded();
 }
 
 static struct TokenInfo *getSetupInfoFinal(struct TokenInfo *setup_info_orig)
@@ -8129,9 +8212,16 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
 
 void HandleGameActions(void)
 {
+  if (setup.ask_on_game_over)
+    CheckGameOver();
+
   if (game.restart_game_message != NULL)
+  {
     RequestRestartGame(game.restart_game_message);
 
+    return;
+  }
+
   if (game_status != GAME_MODE_PLAYING)
     return;