Changeset - r10713:ba92067a4b49
[Not reviewed]
master
0 13 0
truebrain - 15 years ago 2009-01-13 01:46:46
truebrain@openttd.org
(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
13 files changed with 84 insertions and 73 deletions:
0 comments (0 inline, 0 general)
src/ai/ai.hpp
Show inline comments
 
@@ -83,17 +83,17 @@ public:
 
	 */
 
	static void Save(CompanyID company);
 

	
 
	/**
 
	 * 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();
 

	
 
private:
 
	static uint frame_counter;
 
	static class AIScanner *ai_scanner;
src/ai/ai_config.cpp
Show inline comments
 
@@ -6,17 +6,17 @@
 
#include "../openttd.h"
 
#include "../settings_type.h"
 
#include "ai.hpp"
 
#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++) {
 
		free((void*)(*it).first);
 
	}
 
	this->settings.clear();
 
@@ -42,13 +42,13 @@ AIInfo *AIConfig::GetInfo()
 
{
 
	return this->info;
 
}
 

	
 
bool AIConfig::ResetInfo()
 
{
 
	 this->info = AI::GetCompanyInfo(this->name);
 
	 this->info = AI::FindInfo(this->name, this->version);
 
	 return this->info != NULL;
 
}
 

	
 
AIConfig *AIConfig::GetConfig(CompanyID company, bool forceNewgameSetting)
 
{
 
	AIConfig **config;
src/ai/ai_config.hpp
Show inline comments
 
@@ -23,14 +23,16 @@ public:
 
	{}
 
	AIConfig(const AIConfig *config);
 
	~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.
 
	 */
 
	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
 
	 *  function tells AIConfig about this.
 
	 * @return True if the reset was successfull, false if the AI was no longer
 
	 *  found.
src/ai/ai_core.cpp
Show inline comments
 
@@ -208,21 +208,21 @@ void CcAI(bool success, TileIndex tile, 
 
		_current_company = old_company;
 
	} else {
 
		AIInstance::SaveEmpty();
 
	}
 
}
 

	
 
/* static */ void AI::Load(CompanyID company)
 
/* static */ void AI::Load(CompanyID company, int version)
 
{
 
	if (!_networking || _network_server) {
 
		assert(IsValidCompanyID(company));
 
		assert(GetCompany(company)->ai_instance != NULL);
 

	
 
		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 */
 
		AIInstance::LoadEmpty();
 
	}
 
}
 
@@ -234,15 +234,15 @@ void CcAI(bool success, TileIndex tile, 
 

	
 
/* static */ const AIInfoList *AI::GetInfoList()
 
{
 
	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)
 
{
 
	return AI::ai_scanner->ImportLibrary(library, class_name, version, vm, GetCompany(_current_company)->ai_instance->GetController());
 
}
src/ai/ai_info.cpp
Show inline comments
 
@@ -67,15 +67,32 @@ const char *AIFileInfo::GetDate()
 
const char *AIFileInfo::GetInstanceName()
 
{
 
	if (this->instance_name == NULL) this->instance_name = this->engine->CallStringMethodStrdup(*this->SQ_instance, "CreateInstance");
 
	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()
 
{
 
	return this->dir_name;
 
}
src/ai/ai_info.hpp
Show inline comments
 
@@ -71,13 +71,13 @@ public:
 
	 */
 
	const char *GetInstanceName();
 

	
 
	/**
 
	 * Check if we can start this AI.
 
	 */
 
	bool AllowStartup();
 
	bool CanLoadFromVersion(int version);
 

	
 
	/**
 
	 * Get the name of the dir this AI is in.
 
	 */
 
	const char *GetDirName();
 

	
src/ai/ai_instance.cpp
Show inline comments
 
@@ -589,40 +589,41 @@ void AIInstance::Save()
 
	/* Check if there was anything saved at all. */
 
	if (_ai_sl_byte == 0) return;
 

	
 
	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;
 
}
src/ai/ai_instance.hpp
Show inline comments
 
@@ -84,15 +84,16 @@ public:
 
	 */
 
	static void SaveEmpty();
 

	
 
	/**
 
	 * 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.
 
	 */
 
	static void LoadEmpty();
 

	
src/ai/ai_scanner.cpp
Show inline comments
 
@@ -341,41 +341,25 @@ AIInfo *AIScanner::SelectRandomAI()
 
	else             pos =            RandomRange((uint16)this->info_list.size());
 

	
 
	/* Find the Nth item from the array */
 
	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;
 

	
 
	AIInfoList::iterator it = this->info_list.begin();
 
	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;
 
		}
 
	}
 

	
 
	return NULL;
 
}
 
@@ -383,13 +367,12 @@ AIInfo *AIScanner::FindAI(const char *na
 
char *AIScanner::GetAIConsoleList(char *p, const char *last)
 
{
 
	p += seprintf(p, last, "List of AIs:\n");
 
	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");
 

	
 
	return p;
 
}
src/ai/ai_scanner.hpp
Show inline comments
 
@@ -39,13 +39,13 @@ public:
 
	 */
 
	class AIInfo *SelectRandomAI();
 

	
 
	/**
 
	 * 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.
 
	 */
 
	char *GetAIConsoleList(char *p, const char *last);
 

	
src/saveload/ai_sl.cpp
Show inline comments
 
@@ -10,30 +10,33 @@
 
#include "saveload.h"
 
#include "../settings_type.h"
 
#include "../string_func.h"
 
#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()
 
};
 

	
 
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 */
 
	if (IsValidCompanyID(index) && !IsHumanCompany(index)) AI::Save(index);
 
}
 

	
 
@@ -44,33 +47,36 @@ static void Load_AIPL()
 
		AIConfig::GetConfig(c)->ChangeAI(NULL);
 
	}
 

	
 
	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);
 
		}
 
	}
 
}
 

	
 
static void Save_AIPL()
 
{
src/saveload/saveload.cpp
Show inline comments
 
@@ -39,13 +39,13 @@
 

	
 
#include "saveload.h"
 
#include "saveload_internal.h"
 

	
 
#include <list>
 

	
 
extern const uint16 SAVEGAME_VERSION = 107;
 
extern const uint16 SAVEGAME_VERSION = 108;
 

	
 
SavegameType _savegame_type; ///< type of savegame we are loading
 

	
 
uint32 _ttdp_version;     ///< version of TTDP savegame (if applicable)
 
uint16 _sl_version;       ///< the major savegame version identifier
 
byte   _sl_minor_version; ///< the minor savegame version, DO NOT USE!
src/script/squirrel.hpp
Show inline comments
 
@@ -45,12 +45,13 @@ protected:
 
	static void ErrorPrintFunc(HSQUIRRELVM vm, const SQChar *s, ...);
 

	
 
public:
 
	friend class AIController;
 
	friend class AIScanner;
 
	friend class AIInstance;
 
	friend class AIFileInfo;
 

	
 
	Squirrel();
 
	~Squirrel();
 

	
 
	/**
 
	 * Load a script.
0 comments (0 inline, 0 general)