Update to 14.0-beta1

This commit is contained in:
dP
2024-02-04 02:18:17 +05:30
parent 79037e2c65
commit 33ef333b57
1325 changed files with 138461 additions and 70983 deletions
+4 -26
View File
@@ -11,30 +11,13 @@
#define AI_HPP
#include "../script/api/script_event_types.hpp"
#include "../core/string_compare_type.hpp"
#include "ai_scanner.hpp"
#include <map>
/** A list that maps AI names to their AIInfo object. */
typedef std::map<const char *, class ScriptInfo *, StringCompare> ScriptInfoList;
/**
* Main AI class. Contains all functions needed to start, stop, save and load AIs.
*/
class AI {
public:
/**
* The default months AIs start after each other.
*/
enum StartNext {
START_NEXT_EASY = DAYS_IN_YEAR * 2,
START_NEXT_MEDIUM = DAYS_IN_YEAR,
START_NEXT_HARD = DAYS_IN_YEAR / 2,
START_NEXT_MIN = 0,
START_NEXT_MAX = 3600,
START_NEXT_DEVIATION = 60,
};
/**
* Is it possible to start a new AI company?
* @return True if a new AI company can be started.
@@ -128,23 +111,18 @@ public:
*/
static void Save(CompanyID company);
/**
* Get the number of days before the next AI should start.
*/
static int GetStartNextTime();
/** Wrapper function for AIScanner::GetAIConsoleList */
static std::string GetConsoleList(bool newest_only = false);
static void GetConsoleList(std::back_insert_iterator<std::string> &output_iterator, bool newest_only);
/** Wrapper function for AIScanner::GetAIConsoleLibraryList */
static std::string GetConsoleLibraryList();
static void GetConsoleLibraryList(std::back_insert_iterator<std::string> &output_iterator);
/** Wrapper function for AIScanner::GetAIInfoList */
static const ScriptInfoList *GetInfoList();
/** Wrapper function for AIScanner::GetUniqueAIInfoList */
static const ScriptInfoList *GetUniqueInfoList();
/** Wrapper function for AIScanner::FindInfo */
static class AIInfo *FindInfo(const char *name, int version, bool force_exact_match);
static class AIInfo *FindInfo(const std::string &name, int version, bool force_exact_match);
/** Wrapper function for AIScanner::FindLibrary */
static class AILibrary *FindLibrary(const char *library, int version);
static class AILibrary *FindLibrary(const std::string &library, int version);
/**
* Rescans all searchpaths for available AIs. If a used AI is no longer
+3 -94
View File
@@ -16,34 +16,10 @@
#include "../safeguards.h"
/** Configuration for AI start date, every AI has this setting. */
ScriptConfigItem _start_date_config = {
"start_date",
"", // STR_AI_SETTINGS_START_DELAY
AI::START_NEXT_MIN,
AI::START_NEXT_MAX,
AI::START_NEXT_MEDIUM,
AI::START_NEXT_EASY,
AI::START_NEXT_MEDIUM,
AI::START_NEXT_HARD,
AI::START_NEXT_DEVIATION,
30,
SCRIPTCONFIG_NONE,
nullptr,
false
};
AIConfig::AIConfig(const AIConfig *config) : ScriptConfig(config)
{
/* Override start_date as per AIConfig::AddRandomDeviation().
* This is necessary because the ScriptConfig constructor will instead call
* ScriptConfig::AddRandomDeviation(). */
int start_date = config->GetSetting("start_date");
this->SetSetting("start_date", start_date != 0 ? std::max(1, this->GetSetting("start_date")) : 0);
}
/* static */ AIConfig *AIConfig::GetConfig(CompanyID company, ScriptSettingSource source)
{
assert(company < MAX_COMPANIES);
AIConfig **config;
if (source == SSS_FORCE_NEWGAME || (source == SSS_DEFAULT && _game_mode == GM_MENU)) {
config = &_settings_newgame.ai_config[company];
@@ -59,7 +35,7 @@ class AIInfo *AIConfig::GetInfo() const
return static_cast<class AIInfo *>(ScriptConfig::GetInfo());
}
ScriptInfo *AIConfig::FindInfo(const char *name, int version, bool force_exact_match)
ScriptInfo *AIConfig::FindInfo(const std::string &name, int version, bool force_exact_match)
{
return static_cast<ScriptInfo *>(AI::FindInfo(name, version, force_exact_match));
}
@@ -69,70 +45,3 @@ bool AIConfig::ResetInfo(bool force_exact_match)
this->info = (ScriptInfo *)AI::FindInfo(this->name, force_exact_match ? this->version : -1, force_exact_match);
return this->info != nullptr;
}
void AIConfig::PushExtraConfigList()
{
this->config_list->push_back(_start_date_config);
}
void AIConfig::ClearConfigList()
{
/* The special casing for start_date is here to ensure that the
* start_date setting won't change even if you chose another Script. */
int start_date = this->GetSetting("start_date");
ScriptConfig::ClearConfigList();
this->SetSetting("start_date", start_date);
}
int AIConfig::GetSetting(const char *name) const
{
if (this->info == nullptr) {
SettingValueList::const_iterator it = this->settings.find(name);
if (it == this->settings.end()) {
assert(strcmp("start_date", name) == 0);
switch (GetGameSettings().script.settings_profile) {
case SP_EASY: return AI::START_NEXT_EASY;
case SP_MEDIUM: return AI::START_NEXT_MEDIUM;
case SP_HARD: return AI::START_NEXT_HARD;
case SP_CUSTOM: return AI::START_NEXT_MEDIUM;
default: NOT_REACHED();
}
}
return (*it).second;
}
return ScriptConfig::GetSetting(name);
}
void AIConfig::SetSetting(const char *name, int value)
{
if (this->info == nullptr) {
if (strcmp("start_date", name) != 0) return;
value = Clamp(value, AI::START_NEXT_MIN, AI::START_NEXT_MAX);
SettingValueList::iterator it = this->settings.find(name);
if (it != this->settings.end()) {
(*it).second = value;
} else {
this->settings[stredup(name)] = value;
}
return;
}
ScriptConfig::SetSetting(name, value);
}
void AIConfig::AddRandomDeviation()
{
int start_date = this->GetSetting("start_date");
ScriptConfig::AddRandomDeviation();
/* start_date = 0 is a special case, where random deviation does not occur.
* If start_date was not already 0, then a minimum value of 1 must apply. */
this->SetSetting("start_date", start_date != 0 ? std::max(1, this->GetSetting("start_date")) : 0);
}
+4 -8
View File
@@ -24,14 +24,12 @@ public:
ScriptConfig()
{}
AIConfig(const AIConfig *config);
AIConfig(const AIConfig *config) :
ScriptConfig(config)
{}
class AIInfo *GetInfo() const;
int GetSetting(const char *name) const override;
void SetSetting(const char *name, int value) override;
void AddRandomDeviation() override;
/**
* When ever the AI Scanner is reloaded, all infos become invalid. This
* function tells AIConfig about this.
@@ -43,9 +41,7 @@ public:
bool ResetInfo(bool force_exact_match);
protected:
void PushExtraConfigList() override;
void ClearConfigList() override;
ScriptInfo *FindInfo(const char *name, int version, bool force_exact_match) override;
ScriptInfo *FindInfo(const std::string &name, int version, bool force_exact_match) override;
};
#endif /* AI_CONFIG_HPP */
+20 -32
View File
@@ -48,6 +48,7 @@
/* Load default data and store the name in the settings */
config->Change(info->GetName(), -1, false, true);
}
if (rerandomise_ai) config->AddRandomDeviation();
config->AnchorUnchangeableSettings();
Backup<CompanyID> cur_company(_current_company, company, FILE_LINE);
@@ -62,7 +63,7 @@
cur_company.Restore();
InvalidateWindowData(WC_AI_DEBUG, 0, -1);
InvalidateWindowClassesData(WC_SCRIPT_DEBUG, -1);
return;
}
@@ -82,18 +83,16 @@
PerformanceMeasurer framerate((PerformanceElement)(PFE_AI0 + c->index));
cur_company.Change(c->index);
c->ai_instance->GameLoop();
/* Occasionally collect garbage; every 255 ticks do one company.
* Effectively collecting garbage once every two months per AI. */
if ((AI::frame_counter & 255) == 0 && (CompanyID)GB(AI::frame_counter, 8, 4) == c->index) {
c->ai_instance->CollectGarbage();
}
} else {
PerformanceMeasurer::SetInactive((PerformanceElement)(PFE_AI0 + c->index));
}
}
cur_company.Restore();
/* Occasionally collect garbage; every 255 ticks do one company.
* Effectively collecting garbage once every two months per AI. */
if ((AI::frame_counter & 255) == 0) {
CompanyID cid = (CompanyID)GB(AI::frame_counter, 8, 4);
if (Company::IsValidAiID(cid)) Company::Get(cid)->ai_instance->CollectGarbage();
}
}
/* static */ uint AI::GetTick()
@@ -115,8 +114,8 @@
cur_company.Restore();
InvalidateWindowData(WC_AI_DEBUG, 0, -1);
CloseWindowById(WC_AI_SETTINGS, company);
InvalidateWindowClassesData(WC_SCRIPT_DEBUG, -1);
CloseWindowById(WC_SCRIPT_SETTINGS, company);
}
/* static */ void AI::Pause(CompanyID company)
@@ -210,7 +209,7 @@
if (_settings_game.ai_config[c] != nullptr && _settings_game.ai_config[c]->HasScript()) {
if (!_settings_game.ai_config[c]->ResetInfo(true)) {
Debug(script, 0, "After a reload, the AI by the name '{}' was no longer found, and removed from the list.", _settings_game.ai_config[c]->GetName());
_settings_game.ai_config[c]->Change(nullptr);
_settings_game.ai_config[c]->Change(std::nullopt);
if (Company::IsValidAiID(c)) {
/* The code belonging to an already running AI was deleted. We can only do
* one thing here to keep everything sane and that is kill the AI. After
@@ -227,7 +226,7 @@
if (_settings_newgame.ai_config[c] != nullptr && _settings_newgame.ai_config[c]->HasScript()) {
if (!_settings_newgame.ai_config[c]->ResetInfo(false)) {
Debug(script, 0, "After a reload, the AI by the name '{}' was no longer found, and removed from the list.", _settings_newgame.ai_config[c]->GetName());
_settings_newgame.ai_config[c]->Change(nullptr);
_settings_newgame.ai_config[c]->Change(std::nullopt);
}
}
}
@@ -291,25 +290,14 @@
}
}
/* static */ int AI::GetStartNextTime()
/* static */ void AI::GetConsoleList(std::back_insert_iterator<std::string> &output_iterator, bool newest_only)
{
/* Find the first company which doesn't exist yet */
for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
if (!Company::IsValidID(c)) return AIConfig::GetConfig(c, AIConfig::SSS_FORCE_GAME)->GetSetting("start_date");
}
/* Currently no AI can be started, check again in a year. */
return DAYS_IN_YEAR;
AI::scanner_info->GetConsoleList(output_iterator, newest_only);
}
/* static */ std::string AI::GetConsoleList(bool newest_only)
/* static */ void AI::GetConsoleLibraryList(std::back_insert_iterator<std::string> &output_iterator)
{
return AI::scanner_info->GetConsoleList(newest_only);
}
/* static */ std::string AI::GetConsoleLibraryList()
{
return AI::scanner_library->GetConsoleList(true);
AI::scanner_library->GetConsoleList(output_iterator, true);
}
/* static */ const ScriptInfoList *AI::GetInfoList()
@@ -322,12 +310,12 @@
return AI::scanner_info->GetUniqueInfoList();
}
/* static */ AIInfo *AI::FindInfo(const char *name, int version, bool force_exact_match)
/* static */ AIInfo *AI::FindInfo(const std::string &name, int version, bool force_exact_match)
{
return AI::scanner_info->FindInfo(name, version, force_exact_match);
}
/* static */ AILibrary *AI::FindLibrary(const char *library, int version)
/* static */ AILibrary *AI::FindLibrary(const std::string &library, int version)
{
return AI::scanner_library->FindLibrary(library, version);
}
@@ -340,9 +328,9 @@
AI::scanner_library->RescanDir();
ResetConfig();
InvalidateWindowData(WC_AI_LIST, 0, 1);
SetWindowClassesDirty(WC_AI_DEBUG);
InvalidateWindowClassesData(WC_AI_SETTINGS);
InvalidateWindowData(WC_SCRIPT_LIST, 0, 1);
SetWindowClassesDirty(WC_SCRIPT_DEBUG);
InvalidateWindowClassesData(WC_SCRIPT_SETTINGS);
}
/**
+127 -1310
View File
File diff suppressed because it is too large Load Diff
-7
View File
@@ -10,13 +10,6 @@
#ifndef AI_GUI_HPP
#define AI_GUI_HPP
#include "../company_type.h"
void ShowAIListWindow(CompanyID slot);
Window* ShowAIDebugWindow(CompanyID show_company = INVALID_COMPANY);
void ShowAIConfigWindow();
void ShowScriptTextfileWindow(TextfileType file_type, CompanyID slot);
void ShowAIDebugWindowIfAIError();
void InitializeAIGui();
#endif /* AI_GUI_HPP */
+16 -37
View File
@@ -15,7 +15,6 @@
#include "../debug.h"
#include "../string_func.h"
#include "../rev.h"
#include <set>
#include "../safeguards.h"
@@ -23,34 +22,34 @@
* Check if the API version provided by the AI is supported.
* @param api_version The API version as provided by the AI.
*/
static bool CheckAPIVersion(const char *api_version)
static bool CheckAPIVersion(const std::string &api_version)
{
static const std::set<std::string> versions = { "0.7", "1.0", "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7", "1.8", "1.9", "1.10", "1.11", "12", "13" };
static const std::set<std::string> versions = { "0.7", "1.0", "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7", "1.8", "1.9", "1.10", "1.11", "12", "13", "14" };
return versions.find(api_version) != versions.end();
}
#if defined(_WIN32)
#undef GetClassName
#endif /* _WIN32 */
template <> const char *GetClassName<AIInfo, ST_AI>() { return "AIInfo"; }
template <> const char *GetClassName<AIInfo, ScriptType::AI>() { return "AIInfo"; }
/* static */ void AIInfo::RegisterAPI(Squirrel *engine)
{
/* Create the AIInfo class, and add the RegisterAI function */
DefSQClass<AIInfo, ST_AI> SQAIInfo("AIInfo");
DefSQClass<AIInfo, ScriptType::AI> SQAIInfo("AIInfo");
SQAIInfo.PreRegister(engine);
SQAIInfo.AddConstructor<void (AIInfo::*)(), 1>(engine, "x");
SQAIInfo.DefSQAdvancedMethod(engine, &AIInfo::AddSetting, "AddSetting");
SQAIInfo.DefSQAdvancedMethod(engine, &AIInfo::AddLabels, "AddLabels");
SQAIInfo.DefSQConst(engine, SCRIPTCONFIG_NONE, "CONFIG_NONE");
SQAIInfo.DefSQConst(engine, SCRIPTCONFIG_RANDOM, "CONFIG_RANDOM");
SQAIInfo.DefSQConst(engine, SCRIPTCONFIG_NONE, "CONFIG_RANDOM"); // Deprecated, mapped to NONE.
SQAIInfo.DefSQConst(engine, SCRIPTCONFIG_BOOLEAN, "CONFIG_BOOLEAN");
SQAIInfo.DefSQConst(engine, SCRIPTCONFIG_INGAME, "CONFIG_INGAME");
SQAIInfo.DefSQConst(engine, SCRIPTCONFIG_DEVELOPER, "CONFIG_DEVELOPER");
/* Pre 1.2 had an AI prefix */
SQAIInfo.DefSQConst(engine, SCRIPTCONFIG_NONE, "AICONFIG_NONE");
SQAIInfo.DefSQConst(engine, SCRIPTCONFIG_RANDOM, "AICONFIG_RANDOM");
SQAIInfo.DefSQConst(engine, SCRIPTCONFIG_NONE, "AICONFIG_RANDOM"); // Deprecated, mapped to NONE.
SQAIInfo.DefSQConst(engine, SCRIPTCONFIG_BOOLEAN, "AICONFIG_BOOLEAN");
SQAIInfo.DefSQConst(engine, SCRIPTCONFIG_INGAME, "AICONFIG_INGAME");
@@ -69,31 +68,26 @@ template <> const char *GetClassName<AIInfo, ST_AI>() { return "AIInfo"; }
SQInteger res = ScriptInfo::Constructor(vm, info);
if (res != 0) return res;
ScriptConfigItem config = _start_date_config;
config.name = stredup(config.name);
config.description = stredup(config.description);
info->config_list.push_front(config);
if (info->engine->MethodExists(*info->SQ_instance, "MinVersionToLoad")) {
if (!info->engine->CallIntegerMethod(*info->SQ_instance, "MinVersionToLoad", &info->min_loadable_version, MAX_GET_OPS)) return SQ_ERROR;
if (info->engine->MethodExists(info->SQ_instance, "MinVersionToLoad")) {
if (!info->engine->CallIntegerMethod(info->SQ_instance, "MinVersionToLoad", &info->min_loadable_version, MAX_GET_OPS)) return SQ_ERROR;
} else {
info->min_loadable_version = info->GetVersion();
}
/* When there is an UseAsRandomAI function, call it. */
if (info->engine->MethodExists(*info->SQ_instance, "UseAsRandomAI")) {
if (!info->engine->CallBoolMethod(*info->SQ_instance, "UseAsRandomAI", &info->use_as_random, MAX_GET_OPS)) return SQ_ERROR;
if (info->engine->MethodExists(info->SQ_instance, "UseAsRandomAI")) {
if (!info->engine->CallBoolMethod(info->SQ_instance, "UseAsRandomAI", &info->use_as_random, MAX_GET_OPS)) return SQ_ERROR;
} else {
info->use_as_random = true;
}
/* Try to get the API version the AI is written for. */
if (info->engine->MethodExists(*info->SQ_instance, "GetAPIVersion")) {
if (!info->engine->CallStringMethodStrdup(*info->SQ_instance, "GetAPIVersion", &info->api_version, MAX_GET_OPS)) return SQ_ERROR;
if (info->engine->MethodExists(info->SQ_instance, "GetAPIVersion")) {
if (!info->engine->CallStringMethod(info->SQ_instance, "GetAPIVersion", &info->api_version, MAX_GET_OPS)) return SQ_ERROR;
if (!CheckAPIVersion(info->api_version)) {
Debug(script, 1, "Loading info.nut from ({}.{}): GetAPIVersion returned invalid version", info->GetName(), info->GetVersion());
return SQ_ERROR;
}
} else {
info->api_version = stredup("0.7");
info->api_version = "0.7";
}
/* Remove the link to the real instance, else it might get deleted by RegisterAI() */
@@ -109,15 +103,11 @@ template <> const char *GetClassName<AIInfo, ST_AI>() { return "AIInfo"; }
SQUserPointer instance;
sq_getinstanceup(vm, 2, &instance, nullptr);
AIInfo *info = (AIInfo *)instance;
info->api_version = nullptr;
info->api_version = fmt::format("{}.{}", GB(_openttd_newgrf_version, 28, 4), GB(_openttd_newgrf_version, 24, 4));
SQInteger res = ScriptInfo::Constructor(vm, info);
if (res != 0) return res;
char buf[8];
seprintf(buf, lastof(buf), "%d.%d", GB(_openttd_newgrf_version, 28, 4), GB(_openttd_newgrf_version, 24, 4));
info->api_version = stredup(buf);
/* Remove the link to the real instance, else it might get deleted by RegisterAI() */
sq_setinstanceup(vm, 2, nullptr);
/* Register the AI to the base system */
@@ -127,16 +117,10 @@ template <> const char *GetClassName<AIInfo, ST_AI>() { return "AIInfo"; }
AIInfo::AIInfo() :
min_loadable_version(0),
use_as_random(false),
api_version(nullptr)
use_as_random(false)
{
}
AIInfo::~AIInfo()
{
free(this->api_version);
}
bool AIInfo::CanLoadFromVersion(int version) const
{
if (version == -1) return true;
@@ -144,11 +128,6 @@ bool AIInfo::CanLoadFromVersion(int version) const
}
AILibrary::~AILibrary()
{
free(this->category);
}
/* static */ void AILibrary::RegisterAPI(Squirrel *engine)
{
/* Create the AILibrary class, and add the RegisterLibrary function */
@@ -169,7 +148,7 @@ AILibrary::~AILibrary()
}
/* Cache the category */
if (!library->CheckMethod("GetCategory") || !library->engine->CallStringMethodStrdup(*library->SQ_instance, "GetCategory", &library->category, MAX_GET_OPS)) {
if (!library->CheckMethod("GetCategory") || !library->engine->CallStringMethod(library->SQ_instance, "GetCategory", &library->category, MAX_GET_OPS)) {
delete library;
return SQ_ERROR;
}
+5 -7
View File
@@ -16,7 +16,6 @@
class AIInfo : public ScriptInfo {
public:
AIInfo();
~AIInfo();
/**
* Register the functions of this class.
@@ -46,19 +45,18 @@ public:
/**
* Get the API version this AI is written for.
*/
const char *GetAPIVersion() const { return this->api_version; }
const std::string &GetAPIVersion() const { return this->api_version; }
private:
int min_loadable_version; ///< The AI can load savegame data if the version is equal or greater than this.
bool use_as_random; ///< Should this AI be used when the user wants a "random AI"?
const char *api_version; ///< API version used by this AI.
std::string api_version; ///< API version used by this AI.
};
/** All static information from an AI library like name, version, etc. */
class AILibrary : public ScriptInfo {
public:
AILibrary() : ScriptInfo(), category(nullptr) {};
~AILibrary();
AILibrary() : ScriptInfo() {};
/**
* Register the functions of this class.
@@ -73,10 +71,10 @@ public:
/**
* Get the category this library is in.
*/
const char *GetCategory() const { return this->category; }
const std::string &GetCategory() const { return this->category; }
private:
const char *category; ///< The category this library is in.
std::string category; ///< The category this library is in.
};
#endif /* AI_INFO_HPP */
+5 -6
View File
@@ -14,11 +14,11 @@
#include "../script/squirrel_class.hpp"
#include "ai_config.hpp"
#include "ai_gui.hpp"
#include "ai.hpp"
#include "../script/script_storage.hpp"
#include "../script/script_cmd.h"
#include "../script/script_gui.h"
#include "ai_info.hpp"
#include "ai_instance.hpp"
@@ -64,13 +64,13 @@ void AIInstance::Died()
/* Intro is not supposed to use AI, but it may have 'dummy' AI which instant dies. */
if (_game_mode == GM_MENU) return;
ShowAIDebugWindow(_current_company);
ShowScriptDebugWindow(_current_company);
const AIInfo *info = AIConfig::GetConfig(_current_company, AIConfig::SSS_FORCE_GAME)->GetInfo();
if (info != nullptr) {
ShowErrorMessage(STR_ERROR_AI_PLEASE_REPORT_CRASH, INVALID_STRING_ID, WL_WARNING);
if (info->GetURL() != nullptr) {
if (!info->GetURL().empty()) {
ScriptLog::Info("Please report the error to the following URL:");
ScriptLog::Info(info->GetURL());
}
@@ -80,16 +80,15 @@ void AIInstance::Died()
void AIInstance::LoadDummyScript()
{
ScriptAllocatorScope alloc_scope(this->engine);
extern void Script_CreateDummy(HSQUIRRELVM vm, StringID string, const char *type);
Script_CreateDummy(this->engine->GetVM(), STR_ERROR_AI_NO_AI_FOUND, "AI");
}
int AIInstance::GetSetting(const char *name)
int AIInstance::GetSetting(const std::string &name)
{
return AIConfig::GetConfig(_current_company)->GetSetting(name);
}
ScriptInfo *AIInstance::FindLibrary(const char *library, int version)
ScriptInfo *AIInstance::FindLibrary(const std::string &library, int version)
{
return (ScriptInfo *)AI::FindLibrary(library, version);
}
+2 -2
View File
@@ -23,8 +23,8 @@ public:
*/
void Initialize(class AIInfo *info);
int GetSetting(const char *name) override;
ScriptInfo *FindLibrary(const char *library, int version) override;
int GetSetting(const std::string &name) override;
ScriptInfo *FindLibrary(const std::string &library, int version) override;
private:
void RegisterAPI() override;
+20 -31
View File
@@ -14,6 +14,7 @@
#include "../core/random_func.hpp"
#include "../script/squirrel_class.hpp"
#include "../script/api/script_object.hpp"
#include "ai_info.hpp"
#include "ai_scanner.hpp"
@@ -34,7 +35,6 @@ void AIScannerInfo::Initialize()
/* Create the dummy AI */
this->main_script = "%_dummy";
extern void Script_CreateDummyInfo(HSQUIRRELVM vm, const char *type, const char *dir);
Script_CreateDummyInfo(this->engine->GetVM(), "AI", "ai");
}
@@ -48,9 +48,9 @@ AIScannerInfo::~AIScannerInfo()
delete this->info_dummy;
}
void AIScannerInfo::GetScriptName(ScriptInfo *info, char *name, const char *last)
std::string AIScannerInfo::GetScriptName(ScriptInfo *info)
{
seprintf(name, last, "%s", info->GetName());
return info->GetName();
}
void AIScannerInfo::RegisterAPI(class Squirrel *engine)
@@ -77,12 +77,7 @@ AIInfo *AIScannerInfo::SelectRandomAI() const
}
/* Find a random AI */
uint pos;
if (_networking) {
pos = InteractiveRandomRange(num_random_ais);
} else {
pos = RandomRange(num_random_ais);
}
uint pos = ScriptObject::GetRandomizer(OWNER_NONE).Next(num_random_ais);
/* Find the Nth item from the array */
ScriptInfoList::const_iterator it = this->info_single_list.begin();
@@ -97,39 +92,35 @@ AIInfo *AIScannerInfo::SelectRandomAI() const
#undef GetAIInfo
}
AIInfo *AIScannerInfo::FindInfo(const char *nameParam, int versionParam, bool force_exact_match)
AIInfo *AIScannerInfo::FindInfo(const std::string &name, int version, bool force_exact_match)
{
if (this->info_list.size() == 0) return nullptr;
if (nameParam == nullptr) return nullptr;
if (this->info_list.empty()) return nullptr;
if (name.empty()) return nullptr;
char ai_name[1024];
strecpy(ai_name, nameParam, lastof(ai_name));
strtolower(ai_name);
if (versionParam == -1) {
if (version == -1) {
/* We want to load the latest version of this AI; so find it */
if (this->info_single_list.find(ai_name) != this->info_single_list.end()) return static_cast<AIInfo *>(this->info_single_list[ai_name]);
auto it = this->info_single_list.find(name);
if (it != this->info_single_list.end()) return static_cast<AIInfo *>(it->second);
return nullptr;
}
if (force_exact_match) {
/* Try to find a direct 'name.version' match */
char ai_name_tmp[1024];
seprintf(ai_name_tmp, lastof(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 static_cast<AIInfo *>(this->info_list[ai_name_tmp]);
std::string name_with_version = fmt::format("{}.{}", name, version);
auto it = this->info_list.find(name_with_version);
if (it != this->info_list.end()) return static_cast<AIInfo *>(it->second);
return nullptr;
}
AIInfo *info = nullptr;
int version = -1;
int highest_version = -1;
/* See if there is a compatible AI which goes by that name, with the highest
* version which allows loading the requested version */
for (const auto &item : this->info_list) {
AIInfo *i = static_cast<AIInfo *>(item.second);
if (strcasecmp(ai_name, i->GetName()) == 0 && i->CanLoadFromVersion(versionParam) && (version == -1 || i->GetVersion() > version)) {
version = item.second->GetVersion();
if (StrEqualsIgnoreCase(name, i->GetName()) && i->CanLoadFromVersion(version) && (highest_version == -1 || i->GetVersion() > highest_version)) {
highest_version = item.second->GetVersion();
info = i;
}
}
@@ -143,10 +134,10 @@ void AIScannerLibrary::Initialize()
ScriptScanner::Initialize("AIScanner");
}
void AIScannerLibrary::GetScriptName(ScriptInfo *info, char *name, const char *last)
std::string AIScannerLibrary::GetScriptName(ScriptInfo *info)
{
AILibrary *library = static_cast<AILibrary *>(info);
seprintf(name, last, "%s.%s", library->GetCategory(), library->GetInstanceName());
return fmt::format("{}.{}", library->GetCategory(), library->GetInstanceName());
}
void AIScannerLibrary::RegisterAPI(class Squirrel *engine)
@@ -154,12 +145,10 @@ void AIScannerLibrary::RegisterAPI(class Squirrel *engine)
AILibrary::RegisterAPI(engine);
}
AILibrary *AIScannerLibrary::FindLibrary(const char *library, int version)
AILibrary *AIScannerLibrary::FindLibrary(const std::string &library, int version)
{
/* Internally we store libraries as 'library.version' */
char library_name[1024];
seprintf(library_name, lastof(library_name), "%s.%d", library, version);
strtolower(library_name);
std::string library_name = fmt::format("{}.{}", library, version);
/* Check if the library + version exists */
ScriptInfoList::iterator it = this->info_list.find(library_name);
+6 -6
View File
@@ -27,12 +27,12 @@ public:
/**
* Check if we have an AI by name and version available in our list.
* @param nameParam The name of the AI.
* @param versionParam The version of the AI, or -1 if you want the latest.
* @param name The name of the AI.
* @param version The version of the AI, or -1 if you want the latest.
* @param force_exact_match Only match name+version, never latest.
* @return nullptr if no match found, otherwise the AI that matched.
*/
class AIInfo *FindInfo(const char *nameParam, int versionParam, bool force_exact_match);
class AIInfo *FindInfo(const std::string &name, int version, bool force_exact_match);
/**
* Set the Dummy AI.
@@ -40,7 +40,7 @@ public:
void SetDummyAI(class AIInfo *info);
protected:
void GetScriptName(ScriptInfo *info, char *name, const char *last) override;
std::string GetScriptName(ScriptInfo *info) override;
const char *GetFileName() const override { return PATHSEP "info.nut"; }
Subdirectory GetDirectory() const override { return AI_DIR; }
const char *GetScannerName() const override { return "AIs"; }
@@ -60,10 +60,10 @@ public:
* @param version The version the library should have.
* @return The library if found, nullptr otherwise.
*/
class AILibrary *FindLibrary(const char *library, int version);
class AILibrary *FindLibrary(const std::string &library, int version);
protected:
void GetScriptName(ScriptInfo *info, char *name, const char *last) override;
std::string GetScriptName(ScriptInfo *info) override;
const char *GetFileName() const override { return PATHSEP "library.nut"; }
Subdirectory GetDirectory() const override { return AI_LIBRARY_DIR; }
const char *GetScannerName() const override { return "AI Libraries"; }