@@ -111,13 +111,13 @@ public:
*/
static int GetStartNextTime();
static char *GetConsoleList(char *p, const char *last);
static const AIInfoList *GetInfoList();
static const AIInfoList *GetUniqueInfoList();
static AIInfo *FindInfo(const char *name, int version);
static AIInfo *FindInfo(const char *name, int version, bool force_exact_match);
static bool ImportLibrary(const char *library, const char *class_name, int version, HSQUIRRELVM vm);
static void Rescan();
#if defined(ENABLE_NETWORK)
static bool HasAI(const struct ContentInfo *ci, bool md5sum);
#endif
private:
@@ -13,17 +13,17 @@
#include "../openttd.h"
#include "../settings_type.h"
#include "../core/random_func.hpp"
#include "ai.hpp"
#include "ai_config.hpp"
void AIConfig::ChangeAI(const char *name, int version, bool is_random_ai)
void AIConfig::ChangeAI(const char *name, int version, bool force_exact_match, bool is_random_ai)
{
free((void *)this->name);
this->name = (name == NULL) ? NULL : strdup(name);
this->info = (name == NULL) ? NULL : AI::FindInfo(this->name, version);
this->info = (name == NULL) ? NULL : AI::FindInfo(this->name, version, force_exact_match);
this->version = (info == NULL) ? -1 : info->GetVersion();
this->is_random_ai = is_random_ai;
if (this->config_list != NULL) delete this->config_list;
this->config_list = (info == NULL) ? NULL : new AIConfigItemList();
if (this->config_list != NULL) this->config_list->push_back(_start_date_config);
@@ -76,13 +76,13 @@ AIInfo *AIConfig::GetInfo() const
return this->info;
}
bool AIConfig::ResetInfo()
this->info = AI::FindInfo(this->name, -1);
this->info = AI::FindInfo(this->name, -1, false);
return this->info != NULL;
const AIConfigItemList *AIConfig::GetConfigList()
if (this->info != NULL) return this->info->GetConfigList();
@@ -33,15 +33,17 @@ public:
~AIConfig();
/**
* Set another AI to be loaded in this slot.
* @param name The name of the AI.
* @param version The version of the AI to load, or -1 of latest.
* @param force_exact_match If true try to find the exact same version
* as specified. If false any compatible version is ok.
* @param is_random Is the AI chosen randomly?
void ChangeAI(const char *name, int version = -1, bool is_random = false);
void ChangeAI(const char *name, int version = -1, bool force_exact_match = false, bool is_random = false);
* When ever the AI Scanner is reloaded, all infos become invalid. This
* function tells AIConfig about this.
* @return True if the reset was successfull, false if the AI was no longer
* found.
@@ -41,13 +41,13 @@
AIConfig *config = AIConfig::GetConfig(company);
AIInfo *info = config->GetInfo();
if (info == NULL || (rerandomise_ai && config->IsRandomAI())) {
info = AI::ai_scanner->SelectRandomAI();
assert(info != NULL);
/* Load default data and store the name in the settings */
config->ChangeAI(info->GetName(), -1, true);
config->ChangeAI(info->GetName(), -1, false, true);
_current_company = company;
Company *c = Company::Get(company);
c->ai_info = info;
@@ -285,15 +285,15 @@ void CcAI(const CommandCost &result, Til
/* static */ const AIInfoList *AI::GetUniqueInfoList()
return AI::ai_scanner->GetUniqueAIInfoList();
/* static */ AIInfo *AI::FindInfo(const char *name, int version)
/* static */ AIInfo *AI::FindInfo(const char *name, int version, bool force_exact_match)
return AI::ai_scanner->FindInfo(name, version);
return AI::ai_scanner->FindInfo(name, version, force_exact_match);
/* static */ bool AI::ImportLibrary(const char *library, const char *class_name, int version, HSQUIRRELVM vm)
return AI::ai_scanner->ImportLibrary(library, class_name, version, vm, Company::Get(_current_company)->ai_instance->GetController());
@@ -271,13 +271,13 @@ AIInfo *AIScanner::SelectRandomAI() cons
it++;
while (!it->second->UseAsRandomAI()) it++;
return (*it).second;
AIInfo *AIScanner::FindInfo(const char *nameParam, int versionParam)
AIInfo *AIScanner::FindInfo(const char *nameParam, int versionParam, bool force_exact_match)
if (this->info_list.size() == 0) return NULL;
if (nameParam == NULL) return NULL;
char ai_name[1024];
ttd_strlcpy(ai_name, nameParam, sizeof(ai_name));
@@ -296,27 +296,25 @@ AIInfo *AIScanner::FindInfo(const char *
*e = '\0';
e++;
versionParam = atoi(e);
/* Fall-through, like we were calling this function with a version */
/* Try to find a direct 'name.version' match */
char ai_name_tmp[1024];
snprintf(ai_name_tmp, sizeof(ai_name_tmp), "%s.%d", ai_name, versionParam);
strtolower(ai_name_tmp);
if (this->info_list.find(ai_name_tmp) != this->info_list.end()) return this->info_list[ai_name_tmp];
if (force_exact_match) {
/* See if there is a compatible AI which goes by that name, with the highest
* version which allows loading the requested version */
AIInfoList::iterator it = this->info_list.begin();
for (; it != this->info_list.end(); it++) {
char ai_name_compare[1024];
snprintf(ai_name_compare, sizeof(ai_name_compare), "%s", (*it).second->GetName());
strtolower(ai_name_compare);
if (strcasecmp(ai_name, ai_name_compare) == 0 && (*it).second->CanLoadFromVersion(versionParam) && (version == -1 || (*it).second->GetVersion() > version)) {
if (strcasecmp(ai_name, (*it).second->GetName()) == 0 && (*it).second->CanLoadFromVersion(versionParam) && (version == -1 || (*it).second->GetVersion() > version)) {
version = (*it).second->GetVersion();
info = (*it).second;
return info;
@@ -45,13 +45,13 @@ public:
class AIInfo *SelectRandomAI() const;
* Find an AI by name.
class AIInfo *FindInfo(const char *name, int version);
class AIInfo *FindInfo(const char *name, int version, bool force_exact_match);
* Get the list of available AIs for the console.
char *GetAIConsoleList(char *p, const char *last) const;
@@ -1049,13 +1049,13 @@ DEF_CONSOLE_CMD(ConStartAI)
if (c->index != n) break;
n++;
AIConfig *config = AIConfig::GetConfig((CompanyID)n);
if (argc >= 2) {
config->ChangeAI(argv[1]);
config->ChangeAI(argv[1], -1, true);
if (!config->HasAI()) {
IConsoleWarning("Failed to load the specified AI");
return true;
if (argc == 3) {
config->StringToSettings(argv[2]);
@@ -72,19 +72,19 @@ static void Load_AIPL()
continue;
AIConfig *config = AIConfig::GetConfig(index);
if (StrEmpty(_ai_saveload_name)) {
/* A random AI. */
config->ChangeAI(NULL, -1, true);
config->ChangeAI(NULL, -1, false, true);
} else {
config->ChangeAI(_ai_saveload_name, _ai_saveload_version, _ai_saveload_is_random);
config->ChangeAI(_ai_saveload_name, _ai_saveload_version, false, _ai_saveload_is_random);
/* No version of the AI available that can load the data. Try to load the
* latest version of the AI instead. */
config->ChangeAI(_ai_saveload_name, -1, _ai_saveload_is_random);
config->ChangeAI(_ai_saveload_name, -1, false, _ai_saveload_is_random);
if (strcmp(_ai_saveload_name, "%_dummy") != 0) {
DEBUG(ai, 0, "The savegame has an AI by the name '%s', version %d which is no longer available.", _ai_saveload_name, _ai_saveload_version);
DEBUG(ai, 0, "A random other AI will be loaded in its place.");
DEBUG(ai, 0, "The savegame had no AIs available at the time of saving.");
Status change: