(svn r15045) -Add [NoAI API CHANGE]: in info.nut you can now have (optional) a CanLoadFromVersion(version), which should return true/false, to indicate if you can load a savegame made with your AI of version 'version'

-Add [NoAI API CHANGE]: in main.nut the Load() function now should be Load(version, data), where 'version' is the version of your AI which made the savegame
-Codechange [NoAI]: various of function renames to make things more sane
-Add [NoAI]: push the 'version' of the AI through various of layers
-Codechange [NoAI]: various of code cleanups
-Add [NoAI]: store the version of the AI in the savegame too
replace/41b28d7194a279bdc17475d4fbe2ea6ec885a466
truebrain 16 years ago
parent e6883c5cc7
commit bcbbf2c366

@ -86,11 +86,11 @@ public:
/**
* Load data for an AI from a savegame.
*/
static void Load(CompanyID company);
static void Load(CompanyID company, int version);
static char *GetConsoleList(char *p, const char *last);
static const AIInfoList *GetInfoList();
static AIInfo *GetCompanyInfo(const char *name);
static AIInfo *FindInfo(const char *name, int version);
static bool ImportLibrary(const char *library, const char *class_name, int version, HSQUIRRELVM vm);
static void Rescan();

@ -9,11 +9,11 @@
#include "ai_config.hpp"
#include "ai_info.hpp"
void AIConfig::ChangeAI(const char *name)
void AIConfig::ChangeAI(const char *name, int version)
{
free((void *)this->name);
this->name = (name == NULL) ? NULL : strdup(name);
this->info = (name == NULL) ? NULL : AI::GetCompanyInfo(this->name);
this->info = (name == NULL) ? NULL : AI::FindInfo(this->name, version);
this->version = (info == NULL) ? -1 : info->GetVersion();
for (SettingValueList::iterator it = this->settings.begin(); it != this->settings.end(); it++) {
@ -45,7 +45,7 @@ AIInfo *AIConfig::GetInfo()
bool AIConfig::ResetInfo()
{
this->info = AI::GetCompanyInfo(this->name);
this->info = AI::FindInfo(this->name, this->version);
return this->info != NULL;
}

@ -26,8 +26,10 @@ public:
/**
* 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.
*/
void ChangeAI(const char *name);
void ChangeAI(const char *name, int version = -1);
/**
* When ever the AI Scanner is reloaded, all infos become invalid. This

@ -211,7 +211,7 @@ void CcAI(bool success, TileIndex tile, uint32 p1, uint32 p2)
}
}
/* static */ void AI::Load(CompanyID company)
/* static */ void AI::Load(CompanyID company, int version)
{
if (!_networking || _network_server) {
assert(IsValidCompanyID(company));
@ -219,7 +219,7 @@ void CcAI(bool success, TileIndex tile, uint32 p1, uint32 p2)
CompanyID old_company = _current_company;
_current_company = company;
GetCompany(company)->ai_instance->Load();
GetCompany(company)->ai_instance->Load(version);
_current_company = old_company;
} else {
/* Read, but ignore, the load data */
@ -237,9 +237,9 @@ void CcAI(bool success, TileIndex tile, uint32 p1, uint32 p2)
return AI::ai_scanner->GetAIInfoList();
}
/* static */ AIInfo *AI::GetCompanyInfo(const char *name)
/* static */ AIInfo *AI::FindInfo(const char *name, int version)
{
return AI::ai_scanner->FindAI(name);
return AI::ai_scanner->FindInfo(name, version);
}
/* static */ bool AI::ImportLibrary(const char *library, const char *class_name, int version, HSQUIRRELVM vm)

@ -70,9 +70,26 @@ const char *AIFileInfo::GetInstanceName()
return this->instance_name;
}
bool AIFileInfo::AllowStartup()
bool AIFileInfo::CanLoadFromVersion(int version)
{
return true;
if (version == -1) return true;
if (!this->engine->MethodExists(*this->SQ_instance, "CanLoadFromVersion")) return true;
HSQUIRRELVM vm = this->engine->GetVM();
int top = sq_gettop(vm);
sq_pushobject(vm, *this->SQ_instance);
sq_pushstring(vm, OTTD2FS("CanLoadFromVersion"), -1);
sq_get(vm, -2);
sq_pushobject(vm, *this->SQ_instance);
sq_pushinteger(vm, version);
sq_call(vm, 2, SQTrue, SQFalse);
HSQOBJECT ret;
sq_getstackobj(vm, -1, &ret);
sq_settop(vm, top);
return sq_objtobool(&ret);
}
const char *AIFileInfo::GetDirName()

@ -74,7 +74,7 @@ public:
/**
* Check if we can start this AI.
*/
bool AllowStartup();
bool CanLoadFromVersion(int version);
/**
* Get the name of the dir this AI is in.

@ -592,37 +592,38 @@ void AIInstance::Save()
LoadObjects(NULL);
}
bool AIInstance::Load()
void AIInstance::Load(int version)
{
HSQUIRRELVM vm = (this->engine == NULL) ? NULL : this->engine->GetVM();
if (this->engine == NULL || version == -1) {
LoadEmpty();
return;
}
HSQUIRRELVM vm = this->engine->GetVM();
SlObject(NULL, _ai_byte);
/* Check if there was anything saved at all. */
if (_ai_sl_byte == 0) return true;
if (_ai_sl_byte == 0) return;
AIObject::SetAllowDoCommand(false);
if (vm != NULL) {
/* Go to the instance-root */
sq_pushobject(vm, *this->instance);
/* Find the function-name inside the script */
sq_pushstring(vm, OTTD2FS("Load"), -1);
if (SQ_FAILED(sq_get(vm, -2))) sq_pushnull(vm);
sq_pushobject(vm, *this->instance);
}
/* Go to the instance-root */
sq_pushobject(vm, *this->instance);
/* Find the function-name inside the script */
sq_pushstring(vm, OTTD2FS("Load"), -1);
if (SQ_FAILED(sq_get(vm, -2))) sq_pushnull(vm);
sq_pushobject(vm, *this->instance);
sq_pushinteger(vm, version);
LoadObjects(vm);
if (this->engine != NULL) {
if (this->engine->MethodExists(*this->instance, "Load")) {
sq_call(vm, 2, SQFalse, SQFalse);
} else {
AILog::Warning("Loading failed: there was data for the AI to load, but the AI does not have a Load() function.");
}
if (this->engine->MethodExists(*this->instance, "Load")) {
sq_call(vm, 3, SQFalse, SQFalse);
} else {
AILog::Warning("Loading failed: there was data for the AI to load, but the AI does not have a Load() function.");
}
/* Pop 1) the object instance, 2) the function name, 3) the instance again, 4) the table. */
if (vm != NULL) sq_pop(vm, 4);
/* Pop 1) the object instance, 2) the function name, 3) the instance again, 4) the (null) result. */
sq_pop(vm, 4);
AIObject::SetAllowDoCommand(true);
return true;
return;
}

@ -87,9 +87,10 @@ public:
/**
* Load data from a savegame and call the AI Load function if it
* exists.
* @return True if the loading was successfull.
* @param version The version of the AI when saving, or -1 if this was
* not the original AI saving the game.
*/
bool Load();
void Load(int version);
/**
* Load and discard data from a savegame.

@ -344,26 +344,10 @@ AIInfo *AIScanner::SelectRandomAI()
AIInfoList::iterator it = this->info_list.begin();
for (; pos > 0; pos--) it++;
AIInfoList::iterator first_it = it;
AIInfo *i = (*it).second;
if (!i->AllowStartup()) {
/* We can't start this AI, try to find the next best */
do {
it++;
if (it == this->info_list.end()) it = this->info_list.begin();
/* Back at the beginning? We can't start an AI. */
if (first_it == it) {
DEBUG(ai, 0, "No suitable AI found, loading 'dummy' AI.");
return this->info_dummy;
}
i = (*it).second;
} while (!i->AllowStartup());
}
return i;
return (*it).second;
}
AIInfo *AIScanner::FindAI(const char *name)
AIInfo *AIScanner::FindInfo(const char *name, int version)
{
if (this->info_list.size() == 0) return NULL;
if (name == NULL) return NULL;
@ -372,7 +356,7 @@ AIInfo *AIScanner::FindAI(const char *name)
for (; it != this->info_list.end(); it++) {
AIInfo *i = (*it).second;
if (strcasecmp(name, (*it).first) == 0 && i->AllowStartup()) {
if (strcasecmp(name, (*it).first) == 0 && i->CanLoadFromVersion(version)) {
return i;
}
}
@ -386,8 +370,7 @@ char *AIScanner::GetAIConsoleList(char *p, const char *last)
AIInfoList::iterator it = this->info_list.begin();
for (; it != this->info_list.end(); it++) {
AIInfo *i = (*it).second;
if (!i->AllowStartup()) continue;
p += seprintf(p, last, "%10s: %s\n", (*it).first, i->GetDescription());
p += seprintf(p, last, "%10s (v%d): %s\n", (*it).first, i->GetVersion(), i->GetDescription());
}
p += seprintf(p, last, "\n");

@ -42,7 +42,7 @@ public:
/**
* Find an AI by name.
*/
class AIInfo *FindAI(const char *name);
class AIInfo *FindInfo(const char *name, int version);
/**
* Get the list of available AIs for the console.

@ -13,12 +13,14 @@
#include "../ai/ai.hpp"
#include "../ai/ai_config.hpp"
static char _ai_saveload_ainame[64];
static char _ai_company_convert_array[1024];
static char _ai_saveload_name[64];
static int _ai_saveload_version;
static char _ai_saveload_settings[1024];
static const SaveLoad _ai_company[] = {
SLEG_STR(_ai_saveload_ainame, SLE_STRB),
SLEG_STR(_ai_company_convert_array, SLE_STRB),
SLEG_STR(_ai_saveload_name, SLE_STRB),
SLEG_STR(_ai_saveload_settings, SLE_STRB),
SLEG_CONDVAR(_ai_saveload_version, SLE_UINT32, 108, SL_MAX_VERSION),
SLE_END()
};
@ -27,10 +29,11 @@ static void SaveReal_AIPL(int *index_ptr)
CompanyID index = (CompanyID)*index_ptr;
AIConfig *config = AIConfig::GetConfig(index);
ttd_strlcpy(_ai_saveload_ainame, config->GetName(), lengthof(_ai_saveload_ainame));
ttd_strlcpy(_ai_saveload_name, config->GetName(), lengthof(_ai_saveload_name));
_ai_saveload_version = config->GetVersion();
_ai_company_convert_array[0] = '\0';
config->SettingsToString(_ai_company_convert_array, lengthof(_ai_company_convert_array));
_ai_saveload_settings[0] = '\0';
config->SettingsToString(_ai_saveload_settings, lengthof(_ai_saveload_settings));
SlObject(NULL, _ai_company);
/* If the AI was active, store his data too */
@ -47,27 +50,30 @@ static void Load_AIPL()
CompanyID index;
while ((index = (CompanyID)SlIterateArray()) != (CompanyID)-1) {
AIConfig *config = AIConfig::GetConfig(index);
_ai_saveload_version = -1;
SlObject(NULL, _ai_company);
if (_ai_saveload_ainame[0] == '\0' || AI::GetCompanyInfo(_ai_saveload_ainame) == NULL) {
if (strcmp(_ai_saveload_ainame, "%_dummy") != 0) {
DEBUG(ai, 0, "The savegame has an AI by the name '%s' which is no longer available.", _ai_saveload_ainame);
config->ChangeAI(_ai_saveload_name, _ai_saveload_version);
if (!config->HasAI()) {
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.");
} else {
DEBUG(ai, 0, "The savegame had no AIs available at the time of saving.");
DEBUG(ai, 0, "A random available AI will be loaded now.");
}
config->ChangeAI(NULL);
} else {
config->ChangeAI(_ai_saveload_ainame);
/* Make sure the AI doesn't get the saveload data, as he was not the
* writer of the saveload data in the first place */
_ai_saveload_version = -1;
}
config->StringToSettings(_ai_company_convert_array);
config->StringToSettings(_ai_saveload_settings);
/* Start the AI directly if it was active in the savegame */
if (IsValidCompanyID(index) && !IsHumanCompany(index)) {
AI::StartNew(index);
AI::Load(index);
AI::Load(index, _ai_saveload_version);
}
}
}

@ -42,7 +42,7 @@
#include <list>
extern const uint16 SAVEGAME_VERSION = 107;
extern const uint16 SAVEGAME_VERSION = 108;
SavegameType _savegame_type; ///< type of savegame we are loading

@ -48,6 +48,7 @@ public:
friend class AIController;
friend class AIScanner;
friend class AIInstance;
friend class AIFileInfo;
Squirrel();
~Squirrel();

Loading…
Cancel
Save