From 3f3e42e56e4bb6c75c58d55de27324c47d27385d Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Tue, 30 Jan 2024 23:58:06 +0000 Subject: [PATCH] Fix: Initialise random seed earlier in new game process. This prevents setting up script settings with the seed not initialised. --- src/core/random_func.hpp | 13 +++++++++++++ src/genworld.cpp | 14 +++++++++----- src/misc.cpp | 16 ++++++++++++++++ src/script/script_config.cpp | 3 --- 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/core/random_func.hpp b/src/core/random_func.hpp index ef3f4569b2..db0832e0b5 100644 --- a/src/core/random_func.hpp +++ b/src/core/random_func.hpp @@ -45,6 +45,19 @@ inline void SaveRandomSeeds(SavedRandomSeeds *storage) storage->interactive_random = _interactive_random; } +/** + * Check if random seeds have been changed. + * @param saved_seeds Saved random seeds. + * @returns true if the saved seeds match the current random seeds. + */ +inline bool CheckRandomSeeds(const SavedRandomSeeds &saved_seeds) +{ + return (saved_seeds.random.state[0] == _random.state[0]) + && (saved_seeds.random.state[1] == _random.state[1]) + && (saved_seeds.interactive_random.state[0] == _interactive_random.state[0]) + && (saved_seeds.interactive_random.state[1] == _interactive_random.state[1]); +} + /** * Restores previously saved seeds * @param storage Storage where SaveRandomSeeds() stored th seeds diff --git a/src/genworld.cpp b/src/genworld.cpp index b657273f95..e60cc87949 100644 --- a/src/genworld.cpp +++ b/src/genworld.cpp @@ -91,11 +91,9 @@ static void _GenerateWorld() try { _generating_world = true; if (_network_dedicated) Debug(net, 3, "Generating map, please wait..."); - /* Set the Random() seed to generation_seed so we produce the same map with the same seed */ - _random.SetSeed(_settings_game.game_creation.generation_seed); + SetGeneratingWorldProgress(GWP_MAP_INIT, 2); SetObjectToPlace(SPR_CURSOR_ZZZ, PAL_NONE, HT_NONE, WC_MAIN_WINDOW, 0); - ScriptObject::InitializeRandomizers(); BasePersistentStorageArray::SwitchMode(PSM_ENTER_GAMELOOP); @@ -289,6 +287,10 @@ void GenerateWorld(GenWorldMode mode, uint size_x, uint size_y, bool reset_setti SetLocalCompany(COMPANY_SPECTATOR); InitializeGame(_gw.size_x, _gw.size_y, true, reset_settings); + + SavedRandomSeeds saved_seeds; + SaveRandomSeeds(&saved_seeds); + PrepareGenerateWorldProgress(); if (_settings_game.construction.map_height_limit == 0) { @@ -307,8 +309,6 @@ void GenerateWorld(GenWorldMode mode, uint size_x, uint size_y, bool reset_setti _settings_game.construction.map_height_limit = std::max(MAP_HEIGHT_LIMIT_AUTO_MINIMUM, std::min(MAX_MAP_HEIGHT_LIMIT, estimated_height + MAP_HEIGHT_LIMIT_AUTO_CEILING_ROOM)); } - if (_settings_game.game_creation.generation_seed == GENERATE_NEW_SEED) _settings_game.game_creation.generation_seed = InteractiveRandom(); - /* Load the right landscape stuff, and the NewGRFs! */ GfxLoadSprites(); LoadStringWidthTable(); @@ -329,5 +329,9 @@ void GenerateWorld(GenWorldMode mode, uint size_x, uint size_y, bool reset_setti /* Centre the view on the map */ ScrollMainWindowToTile(TileXY(Map::SizeX() / 2, Map::SizeY() / 2), true); + /* Initialization should use Random() as that could affect the ability to recreate the same map with the + * same settings. (This is not guaranteed between different versions though.) */ + assert(CheckRandomSeeds(saved_seeds)); + _GenerateWorld(); } diff --git a/src/misc.cpp b/src/misc.cpp index dd95950dda..48c9f6c9ea 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -8,6 +8,10 @@ /** @file misc.cpp Misc functions that shouldn't be here. */ #include "stdafx.h" +#include "core/random_func.hpp" +#include "ai/ai_config.hpp" +#include "game/game_config.hpp" +#include "genworld.h" #include "landscape.h" #include "news_func.h" #include "ai/ai.hpp" @@ -173,4 +177,16 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin _gamelog.Mode(); _gamelog.GRFAddList(_grfconfig); _gamelog.StopAction(); + + /* Set the Random() seed to generation_seed so we produce the same map with the same seed. */ + if (_settings_game.game_creation.generation_seed == GENERATE_NEW_SEED) _settings_game.game_creation.generation_seed = InteractiveRandom(); + + _random.SetSeed(_settings_game.game_creation.generation_seed); + ScriptObject::InitializeRandomizers(); + + /* Set random deviation for scripts. */ + for (auto &ai_config : _settings_game.ai_config) { + if (ai_config != nullptr) ai_config->AddRandomDeviation(); + } + if (_settings_game.game_config != nullptr) _settings_game.game_config->AddRandomDeviation(); } diff --git a/src/script/script_config.cpp b/src/script/script_config.cpp index d86191b5f7..3a97e6d82f 100644 --- a/src/script/script_config.cpp +++ b/src/script/script_config.cpp @@ -57,9 +57,6 @@ ScriptConfig::ScriptConfig(const ScriptConfig *config) for (const auto &item : config->settings) { this->settings[item.first] = item.second; } - - /* Virtual functions get called statically in constructors, so make it explicit to remove any confusion. */ - this->ScriptConfig::AddRandomDeviation(); } ScriptConfig::~ScriptConfig()