Changeset - r28725:1677e679c3e8
[Not reviewed]
master
0 15 0
Loïc Guilloux - 3 months ago 2024-02-09 21:55:49
glx22@users.noreply.github.com
Change: Store running AI config inside Company (#12003)
15 files changed with 98 insertions and 62 deletions:
0 comments (0 inline, 0 general)
src/ai/ai.hpp
Show inline comments
 
@@ -27,9 +27,9 @@ public:
 
	/**
 
	 * Start a new AI company.
 
	 * @param company At which slot the AI company should start.
 
	 * @param rerandomise_ai Whether to rerandomise the configured AI.
 
	 * @param deviate Whether to apply random deviation to the configured AI.
 
	 */
 
	static void StartNew(CompanyID company, bool rerandomise_ai = true);
 
	static void StartNew(CompanyID company, bool deviate = true);
 

	
 
	/**
 
	 * Called every game-tick to let AIs do something.
src/ai/ai_config.cpp
Show inline comments
 
@@ -8,6 +8,7 @@
 
/** @file ai_config.cpp Implementation of AIConfig. */
 

	
 
#include "../stdafx.h"
 
#include "../company_base.h"
 
#include "../settings_type.h"
 
#include "../string_func.h"
 
#include "ai.hpp"
 
@@ -24,6 +25,10 @@
 
	if (source == SSS_FORCE_NEWGAME || (source == SSS_DEFAULT && _game_mode == GM_MENU)) {
 
		config = &_settings_newgame.ai_config[company];
 
	} else {
 
		if (source != SSS_FORCE_GAME) {
 
			Company *c = Company::GetIfValid(company);
 
			if (c != nullptr && c->ai_config != nullptr) return c->ai_config.get();
 
		}
 
		config = &_settings_game.ai_config[company];
 
	}
 
	if (*config == nullptr) *config = new AIConfig();
src/ai/ai_core.cpp
Show inline comments
 
@@ -33,27 +33,32 @@
 
	return !_networking || (_network_server && _settings_game.ai.ai_in_multiplayer);
 
}
 

	
 
/* static */ void AI::StartNew(CompanyID company, bool rerandomise_ai)
 
/* static */ void AI::StartNew(CompanyID company, bool deviate)
 
{
 
	assert(Company::IsValidID(company));
 

	
 
	/* Clients shouldn't start AIs */
 
	if (_networking && !_network_server) return;
 

	
 
	AIConfig *config = AIConfig::GetConfig(company, AIConfig::SSS_FORCE_GAME);
 
	Backup<CompanyID> cur_company(_current_company, company, FILE_LINE);
 
	Company *c = Company::Get(company);
 

	
 
	AIConfig *config = c->ai_config.get();
 
	if (config == nullptr) {
 
		c->ai_config = std::make_unique<AIConfig>(AIConfig::GetConfig(company, AIConfig::SSS_FORCE_GAME));
 
		config = c->ai_config.get();
 
	}
 

	
 
	AIInfo *info = config->GetInfo();
 
	if (info == nullptr || (rerandomise_ai && config->IsRandom())) {
 
	if (info == nullptr) {
 
		info = AI::scanner_info->SelectRandomAI();
 
		assert(info != nullptr);
 
		/* Load default data and store the name in the settings */
 
		config->Change(info->GetName(), -1, false, true);
 
		config->Change(info->GetName(), -1, false);
 
	}
 
	if (rerandomise_ai) config->AddRandomDeviation();
 
	if (deviate) config->AddRandomDeviation();
 
	config->AnchorUnchangeableSettings();
 

	
 
	Backup<CompanyID> cur_company(_current_company, company, FILE_LINE);
 
	Company *c = Company::Get(company);
 

	
 
	c->ai_info = info;
 
	assert(c->ai_instance == nullptr);
 
	c->ai_instance = new AIInstance();
 
@@ -111,11 +116,11 @@
 
	delete c->ai_instance;
 
	c->ai_instance = nullptr;
 
	c->ai_info = nullptr;
 
	c->ai_config.reset();
 

	
 
	cur_company.Restore();
 

	
 
	InvalidateWindowClassesData(WC_SCRIPT_DEBUG, -1);
 
	CloseWindowById(WC_SCRIPT_SETTINGS, company);
 
}
 

	
 
/* static */ void AI::Pause(CompanyID company)
src/ai/ai_instance.cpp
Show inline comments
 
@@ -66,7 +66,7 @@ void AIInstance::Died()
 

	
 
	ShowScriptDebugWindow(_current_company);
 

	
 
	const AIInfo *info = AIConfig::GetConfig(_current_company, AIConfig::SSS_FORCE_GAME)->GetInfo();
 
	const AIInfo *info = AIConfig::GetConfig(_current_company)->GetInfo();
 
	if (info != nullptr) {
 
		ShowErrorMessage(STR_ERROR_AI_PLEASE_REPORT_CRASH, INVALID_STRING_ID, WL_WARNING);
 

	
src/company_base.h
Show inline comments
 
@@ -122,6 +122,7 @@ struct Company : CompanyProperties, Comp
 

	
 
	class AIInstance *ai_instance;
 
	class AIInfo *ai_info;
 
	std::unique_ptr<class AIConfig> ai_config;
 

	
 
	GroupStatistics group_all[VEH_COMPANY_END];      ///< NOSAVE: Statistics for the ALL_GROUP group.
 
	GroupStatistics group_default[VEH_COMPANY_END];  ///< NOSAVE: Statistics for the DEFAULT_GROUP group.
src/company_cmd.cpp
Show inline comments
 
@@ -20,6 +20,7 @@
 
#include "network/network_base.h"
 
#include "network/network_admin.h"
 
#include "ai/ai.hpp"
 
#include "ai/ai_config.hpp"
 
#include "company_manager_face.h"
 
#include "window_func.h"
 
#include "strings_func.h"
src/game/game.hpp
Show inline comments
 
@@ -31,9 +31,9 @@ public:
 

	
 
	/**
 
	 * Start up a new GameScript.
 
	 * @param randomise Whether to randomise the configured GameScript.
 
	 * @param deviate Whether to apply random deviation to the configured GameScript.
 
	 */
 
	static void StartNew(bool randomise = true);
 
	static void StartNew(bool deviate = true);
 

	
 
	/**
 
	 * Uninitialize the Game system.
src/game/game_core.cpp
Show inline comments
 
@@ -69,7 +69,7 @@
 
	}
 
}
 

	
 
/* static */ void Game::StartNew(bool randomise)
 
/* static */ void Game::StartNew(bool deviate)
 
{
 
	if (Game::instance != nullptr) return;
 

	
 
@@ -83,7 +83,7 @@
 
	GameInfo *info = config->GetInfo();
 
	if (info == nullptr) return;
 

	
 
	if (randomise) config->AddRandomDeviation();
 
	if (deviate) config->AddRandomDeviation();
 
	config->AnchorUnchangeableSettings();
 

	
 
	Backup<CompanyID> cur_company(_current_company, FILE_LINE);
src/saveload/ai_sl.cpp
Show inline comments
 
@@ -32,13 +32,19 @@ static const SaveLoad _ai_company_desc[]
 
	   SLEG_SSTR("name",      _ai_saveload_name,         SLE_STR),
 
	   SLEG_SSTR("settings",  _ai_saveload_settings,     SLE_STR),
 
	SLEG_CONDVAR("version",   _ai_saveload_version,   SLE_UINT32, SLV_108, SL_MAX_VERSION),
 
	SLEG_CONDVAR("is_random", _ai_saveload_is_random,   SLE_BOOL, SLV_136, SL_MAX_VERSION),
 
	SLEG_CONDVAR("is_random", _ai_saveload_is_random,   SLE_BOOL, SLV_136, SLV_AI_LOCAL_CONFIG),
 
};
 

	
 
static const SaveLoad _ai_running_desc[] = {
 
	SLEG_CONDSSTR("running_name",     _ai_saveload_name,        SLE_STR, SLV_AI_LOCAL_CONFIG, SL_MAX_VERSION),
 
	SLEG_CONDSSTR("running_settings", _ai_saveload_settings,    SLE_STR, SLV_AI_LOCAL_CONFIG, SL_MAX_VERSION),
 
	 SLEG_CONDVAR("running_version",  _ai_saveload_version,  SLE_UINT32, SLV_AI_LOCAL_CONFIG, SL_MAX_VERSION),
 
};
 

	
 
static void SaveReal_AIPL(int *index_ptr)
 
{
 
	CompanyID index = (CompanyID)*index_ptr;
 
	AIConfig *config = AIConfig::GetConfig(index);
 
	AIConfig *config = AIConfig::GetConfig(index, AIConfig::SSS_FORCE_GAME);
 

	
 
	if (config->HasScript()) {
 
		_ai_saveload_name = config->GetName();
 
@@ -49,12 +55,21 @@ static void SaveReal_AIPL(int *index_ptr
 
		_ai_saveload_version = -1;
 
	}
 

	
 
	_ai_saveload_is_random = config->IsRandom();
 
	_ai_saveload_settings = config->SettingsToString();
 

	
 
	SlObject(nullptr, _ai_company_desc);
 

	
 
	if (!Company::IsValidAiID(index)) return;
 

	
 
	/* If the AI was active, store its data too */
 
	if (Company::IsValidAiID(index)) AI::Save(index);
 
	config = AIConfig::GetConfig(index);
 
	_ai_saveload_name = config->GetName();
 
	_ai_saveload_version = config->GetVersion();
 
	_ai_saveload_settings = config->SettingsToString();
 

	
 
	SlObject(nullptr, _ai_running_desc);
 
	AI::Save(index);
 

	
 
}
 

	
 
struct AIPLChunkHandler : ChunkHandler {
 
@@ -78,42 +93,66 @@ struct AIPLChunkHandler : ChunkHandler {
 
			SlObject(nullptr, slt);
 

	
 
			if (_game_mode == GM_MENU || (_networking && !_network_server)) {
 
				if (Company::IsValidAiID(index)) AIInstance::LoadEmpty();
 
				if (Company::IsValidAiID(index)) {
 
					SlObject(nullptr, _ai_running_desc);
 
					AIInstance::LoadEmpty();
 
				}
 
				continue;
 
			}
 

	
 
			AIConfig *config = AIConfig::GetConfig(index, AIConfig::SSS_FORCE_GAME);
 
			if (_ai_saveload_name.empty()) {
 
			if (_ai_saveload_name.empty() || _ai_saveload_is_random) {
 
				/* A random AI. */
 
				config->Change(std::nullopt, -1, false, true);
 
				config->Change(std::nullopt, -1, false);
 
			} else {
 
				config->Change(_ai_saveload_name, _ai_saveload_version, false, _ai_saveload_is_random);
 
				config->Change(_ai_saveload_name, _ai_saveload_version, false);
 
				if (!config->HasScript()) {
 
					/* No version of the AI available that can load the data. Try to load the
 
					/* No version of the AI available. Try to configure the
 
					 * latest version of the AI instead. */
 
					config->Change(_ai_saveload_name, -1, false, _ai_saveload_is_random);
 
					config->Change(_ai_saveload_name, -1, false);
 
					if (!config->HasScript()) {
 
						if (_ai_saveload_name.compare("%_dummy") != 0) {
 
							Debug(script, 0, "The savegame has an AI by the name '{}', version {} which is no longer available.", _ai_saveload_name, _ai_saveload_version);
 
							Debug(script, 0, "A random other AI will be loaded in its place.");
 
						} else {
 
							Debug(script, 0, "The savegame had no AIs available at the time of saving.");
 
							Debug(script, 0, "A random available AI will be loaded now.");
 
							Debug(script, 0, "Configuration switched to Random AI.");
 
						}
 
					} else {
 
						Debug(script, 0, "The savegame has an AI by the name '{}', version {} which is no longer available.", _ai_saveload_name, _ai_saveload_version);
 
						Debug(script, 0, "The latest version of that AI has been loaded instead, but it'll not get the savegame data as it's incompatible.");
 
						Debug(script, 0, "The latest version of that AI has been configured instead");
 
					}
 
					/* Make sure the AI doesn't get the saveload data, as it was not the
 
					 *  writer of the saveload data in the first place */
 
					_ai_saveload_version = -1;
 
				}
 
			}
 

	
 
			config->StringToSettings(_ai_saveload_settings);
 

	
 
			if (!Company::IsValidAiID(index)) continue;
 

	
 
			/* Load the AI saved data */
 
			if (Company::IsValidAiID(index)) config->SetToLoadData(AIInstance::Load(_ai_saveload_version));
 
			SlObject(nullptr, _ai_running_desc);
 

	
 
			Company::Get(index)->ai_config = std::make_unique<AIConfig>();
 
			config = Company::Get(index)->ai_config.get();
 
			config->Change(_ai_saveload_name, _ai_saveload_version, false);
 
			if (!config->HasScript()) {
 
				/* No version of the AI available that can load the data. Try to load the
 
				 * latest version of the AI instead. */
 
				config->Change(_ai_saveload_name, -1, false);
 
				if (!config->HasScript()) {
 
					if (_ai_saveload_name.compare("%_dummy") != 0) {
 
						Debug(script, 0, "The savegame has an AI by the name '{}', version {} which is no longer available.", _ai_saveload_name, _ai_saveload_version);
 
						Debug(script, 0, "A random other AI will be loaded in its place.");
 
					} else {
 
						Debug(script, 0, "The savegame had no AIs available at the time of saving.");
 
						Debug(script, 0, "A random available AI will be loaded now.");
 
					}
 
				} else {
 
					Debug(script, 0, "The savegame has an AI by the name '{}', version {} which is no longer available.", _ai_saveload_name, _ai_saveload_version);
 
					Debug(script, 0, "The latest version of that AI has been loaded instead, but it'll not get the savegame data as it's incompatible.");
 
				}
 
				/* Make sure the AI doesn't get the saveload data, as it was not the
 
				 *  writer of the saveload data in the first place */
 
				_ai_saveload_version = -1;
 
			}
 
			config->StringToSettings(_ai_saveload_settings);
 
			config->SetToLoadData(AIInstance::Load(_ai_saveload_version));
 
		}
 
	}
 

	
src/saveload/compat/game_sl_compat.h
Show inline comments
 
@@ -17,7 +17,7 @@ const SaveLoadCompat _game_script_sl_com
 
	SLC_VAR("name"),
 
	SLC_VAR("settings"),
 
	SLC_VAR("version"),
 
	SLC_VAR("is_random"),
 
	SLC_NULL(1, SL_MIN_VERSION, SLV_AI_LOCAL_CONFIG),
 
};
 

	
 
/** Original field order for SlGameLanguageString. */
src/saveload/game_sl.cpp
Show inline comments
 
@@ -25,13 +25,11 @@
 
static std::string _game_saveload_name;
 
static int         _game_saveload_version;
 
static std::string _game_saveload_settings;
 
static bool        _game_saveload_is_random;
 

	
 
static const SaveLoad _game_script_desc[] = {
 
	   SLEG_SSTR("name",      _game_saveload_name,         SLE_STR),
 
	   SLEG_SSTR("settings",  _game_saveload_settings,     SLE_STR),
 
	    SLEG_VAR("version",   _game_saveload_version,   SLE_UINT32),
 
	    SLEG_VAR("is_random", _game_saveload_is_random,   SLE_BOOL),
 
};
 

	
 
static void SaveReal_GSDT(int *)
 
@@ -47,7 +45,6 @@ static void SaveReal_GSDT(int *)
 
		_game_saveload_version = -1;
 
	}
 

	
 
	_game_saveload_is_random = config->IsRandom();
 
	_game_saveload_settings = config->SettingsToString();
 

	
 
	SlObject(nullptr, _game_script_desc);
 
@@ -77,11 +74,11 @@ struct GSDTChunkHandler : ChunkHandler {
 

	
 
		GameConfig *config = GameConfig::GetConfig(GameConfig::SSS_FORCE_GAME);
 
		if (!_game_saveload_name.empty()) {
 
			config->Change(_game_saveload_name, _game_saveload_version, false, _game_saveload_is_random);
 
			config->Change(_game_saveload_name, _game_saveload_version, false);
 
			if (!config->HasScript()) {
 
				/* No version of the GameScript available that can load the data. Try to load the
 
				 * latest version of the GameScript instead. */
 
				config->Change(_game_saveload_name, -1, false, _game_saveload_is_random);
 
				config->Change(_game_saveload_name, -1, false);
 
				if (!config->HasScript()) {
 
					if (_game_saveload_name.compare("%_dummy") != 0) {
 
						Debug(script, 0, "The savegame has an GameScript by the name '{}', version {} which is no longer available.", _game_saveload_name, _game_saveload_version);
src/saveload/saveload.h
Show inline comments
 
@@ -375,6 +375,7 @@ enum SaveLoadVersion : uint16_t {
 

	
 
	SLV_MAX_LOAN_FOR_COMPANY,               ///< 330  PR#11224 Separate max loan for each company.
 
	SLV_DEPOT_UNBUNCHING,                   ///< 331  PR#11945 Allow unbunching shared order vehicles at a depot.
 
	SLV_AI_LOCAL_CONFIG,                    ///< 332  PR#12003 Config of running AI is stored inside Company.
 

	
 
	SL_MAX_VERSION,                         ///< Highest possible saveload version
 
};
src/script/script_config.cpp
Show inline comments
 
@@ -18,7 +18,7 @@
 

	
 
#include "../safeguards.h"
 

	
 
void ScriptConfig::Change(std::optional<const std::string> name, int version, bool force_exact_match, bool is_random)
 
void ScriptConfig::Change(std::optional<const std::string> name, int version, bool force_exact_match)
 
{
 
	if (name.has_value()) {
 
		this->name = std::move(name.value());
 
@@ -27,7 +27,6 @@ void ScriptConfig::Change(std::optional<
 
		this->info = nullptr;
 
	}
 
	this->version = (info == nullptr) ? -1 : info->GetVersion();
 
	this->is_random = is_random;
 
	this->config_list.reset();
 
	this->to_load_data.reset();
 

	
 
@@ -39,7 +38,6 @@ ScriptConfig::ScriptConfig(const ScriptC
 
	this->name = config->name;
 
	this->info = config->info;
 
	this->version = config->version;
 
	this->is_random = config->is_random;
 
	this->to_load_data.reset();
 

	
 
	for (const auto &item : config->settings) {
 
@@ -139,11 +137,6 @@ bool ScriptConfig::HasScript() const
 
	return this->info != nullptr;
 
}
 

	
 
bool ScriptConfig::IsRandom() const
 
{
 
	return this->is_random;
 
}
 

	
 
const std::string &ScriptConfig::GetName() const
 
{
 
	return this->name;
src/script/script_config.hpp
Show inline comments
 
@@ -56,7 +56,6 @@ public:
 
	ScriptConfig() :
 
		version(-1),
 
		info(nullptr),
 
		is_random(false),
 
		to_load_data(nullptr)
 
	{}
 

	
 
@@ -77,7 +76,7 @@ public:
 
	 *   as specified. If false any compatible version is ok.
 
	 * @param is_random Is the Script chosen randomly?
 
	 */
 
	void Change(std::optional<const std::string> name, int version = -1, bool force_exact_match = false, bool is_random = false);
 
	void Change(std::optional<const std::string> name, int version = -1, bool force_exact_match = false);
 

	
 
	/**
 
	 * Get the ScriptInfo linked to this ScriptConfig.
 
@@ -145,11 +144,6 @@ public:
 
	bool HasScript() const;
 

	
 
	/**
 
	 * Is the current Script a randomly chosen Script?
 
	 */
 
	bool IsRandom() const;
 

	
 
	/**
 
	 * Get the name of the Script.
 
	 */
 
	const std::string &GetName() const;
 
@@ -188,7 +182,6 @@ protected:
 
	class ScriptInfo *info;                                   ///< ScriptInfo object for related to this Script version
 
	SettingValueList settings;                                ///< List with all setting=>value pairs that are configure for this Script
 
	std::unique_ptr<ScriptConfigItemList> config_list;        ///< List with all settings defined by this Script
 
	bool is_random;                                           ///< True if the AI in this slot was randomly chosen.
 
	std::unique_ptr<ScriptInstance::ScriptData> to_load_data; ///< Data to load after the Script start.
 

	
 
	/**
src/script/script_gui.cpp
Show inline comments
 
@@ -307,13 +307,11 @@ struct ScriptSettingsWindow : public Win
 
		clicked_dropdown(false),
 
		closing_dropdown(false)
 
	{
 
		this->script_config = GetConfig(slot);
 

	
 
		this->CreateNestedTree();
 
		this->vscroll = this->GetScrollbar(WID_SCRS_SCROLLBAR);
 
		this->FinishInitNested(slot);  // Initializes 'this->line_height' as side effect.
 

	
 
		this->RebuildVisibleSettings();
 
		this->OnInvalidateData();
 
	}
 

	
 
	/**
 
@@ -591,6 +589,8 @@ struct ScriptSettingsWindow : public Win
 
	 */
 
	void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
 
	{
 
		this->script_config = GetConfig(this->slot);
 
		if (this->script_config->GetConfigList()->empty()) this->Close();
 
		this->RebuildVisibleSettings();
 
		this->CloseChildWindows(WC_DROPDOWN_MENU);
 
		this->CloseChildWindows(WC_QUERY_STRING);
 
@@ -1206,7 +1206,8 @@ struct ScriptDebugWindow : public Window
 
		this->SetWidgetLoweredState(WID_SCRD_BREAK_STR_ON_OFF_BTN, this->filter.break_check_enabled);
 
		this->SetWidgetLoweredState(WID_SCRD_MATCH_CASE_BTN, this->filter.case_sensitive_break_check);
 

	
 
		this->SetWidgetDisabledState(WID_SCRD_SETTINGS, this->filter.script_debug_company == INVALID_COMPANY);
 
		this->SetWidgetDisabledState(WID_SCRD_SETTINGS, this->filter.script_debug_company == INVALID_COMPANY ||
 
			GetConfig(this->filter.script_debug_company)->GetConfigList()->empty());
 
		extern CompanyID _local_company;
 
		this->SetWidgetDisabledState(WID_SCRD_RELOAD_TOGGLE,
 
				this->filter.script_debug_company == INVALID_COMPANY ||
0 comments (0 inline, 0 general)