OpenTTD Source: src/ai/ai_scanner.cpp Source File

OpenTTD Source 15.3

ai_scanner.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
10#include "../stdafx.h"
11#include <ranges>
12#include "../debug.h"
13#include "../network/network.h"
14#include "../openttd.h"
15#include "../core/random_func.hpp"
16
17#include "../script/squirrel_class.hpp"
18#include "../script/api/script_object.hpp"
19#include "ai_info.hpp"
20#include "ai_scanner.hpp"
21
22#include "../safeguards.h"
23
24
25AIScannerInfo::AIScannerInfo() = default;
26AIScannerInfo::~AIScannerInfo() = default;
27
28void AIScannerInfo::Initialize()
29{
30 ScriptScanner::Initialize("AIScanner");
31
32 ScriptAllocatorScope alloc_scope(this->engine.get());
33
34 /* Create the dummy AI */
35 this->main_script = "%_dummy";
36 Script_CreateDummyInfo(this->engine->GetVM(), "AI", "ai");
37}
38
39 void AIScannerInfo::SetDummyAI(std::unique_ptr<class AIInfo> &&info)
40{
41 this->info_dummy = std::move(info);
42}
43
44std::string AIScannerInfo::GetScriptName(ScriptInfo &info)
45{
46 return info.GetName();
47}
48
49 void AIScannerInfo::RegisterAPI(class Squirrel &engine)
50{
51 AIInfo::RegisterAPI(engine);
52}
53
54 AIInfo *AIScannerInfo::SelectRandomAI() const
55{
56 if (_game_mode == GM_MENU) {
57 Debug(script, 0, "The intro game should not use AI, loading 'dummy' AI.");
58 return this->info_dummy.get();
59 }
60
61 /* Filter for AIs suitable as Random AI. */
62 auto random_ais = info_single_list | std::views::filter([](const auto &item) { return static_cast<AIInfo *>(item.second)->UseAsRandomAI(); });
63
64 uint num_random_ais = std::ranges::distance(random_ais);
65 if (num_random_ais == 0) {
66 Debug(script, 0, "No suitable AI found, loading 'dummy' AI.");
67 return this->info_dummy.get();
68 }
69
70 /* Pick a random AI */
71 uint pos = ScriptObject::GetRandomizer(OWNER_NONE).Next(num_random_ais);
72 auto it = std::ranges::next(std::begin(random_ais), pos, std::end(random_ais));
73 assert(it != std::end(random_ais));
74
75 return static_cast<AIInfo *>(it->second);
76}
77
78 AIInfo *AIScannerInfo::FindInfo(const std::string &name, int version, bool force_exact_match)
79{
80 if (this->info_list.empty()) return nullptr;
81 if (name.empty()) return nullptr;
82
83 if (version == -1) {
84 /* We want to load the latest version of this AI; so find it */
85 auto it = this->info_single_list.find(name);
86 if (it != this->info_single_list.end()) return static_cast<AIInfo *>(it->second);
87 return nullptr;
88 }
89
90 if (force_exact_match) {
91 /* Try to find a direct 'name.version' match */
92 std::string name_with_version = fmt::format("{}.{}", name, version);
93 auto it = this->info_list.find(name_with_version);
94 if (it != this->info_list.end()) return static_cast<AIInfo *>(it->second);
95 return nullptr;
96 }
97
98 AIInfo *info = nullptr;
99 int highest_version = -1;
100
101 /* See if there is a compatible AI which goes by that name, with the highest
102 * version which allows loading the requested version */
103 for (const auto &item : this->info_list) {
104 AIInfo *i = static_cast<AIInfo *>(item.second);
105 if (StrEqualsIgnoreCase(name, i->GetName()) && i->CanLoadFromVersion(version) && (highest_version == -1 || i->GetVersion() > highest_version)) {
106 highest_version = item.second->GetVersion();
107 info = i;
108 }
109 }
110
111 return info;
112}
113
114
115void AIScannerLibrary::Initialize()
116{
117 ScriptScanner::Initialize("AIScanner");
118}
119
120std::string AIScannerLibrary::GetScriptName(ScriptInfo &info)
121{
122 AILibrary &library = static_cast<AILibrary &>(info);
123 return fmt::format("{}.{}", library.GetCategory(), library.GetInstanceName());
124}
125
126 void AIScannerLibrary::RegisterAPI(class Squirrel &engine)
127{
128 AILibrary::RegisterAPI(engine);
129}
130
131 AILibrary *AIScannerLibrary::FindLibrary(const std::string &library, int version)
132{
133 /* Internally we store libraries as 'library.version' */
134 std::string library_name = fmt::format("{}.{}", library, version);
135
136 /* Check if the library + version exists */
137 ScriptInfoList::iterator it = this->info_list.find(library_name);
138 if (it == this->info_list.end()) return nullptr;
139
140 return static_cast<AILibrary *>(it->second);
141}
ai_info.hpp
AIInfo keeps track of all information of an AI, like Author, Description, ...
ai_scanner.hpp
declarations of the class for AI scanner
AIInfo
All static information from an AI like name, version, etc.
Definition ai_info.hpp:16
AIInfo::CanLoadFromVersion
bool CanLoadFromVersion(int version) const
Check if we can start this AI.
Definition ai_info.cpp:121
AIInfo::RegisterAPI
static void RegisterAPI(Squirrel &engine)
Register the functions of this class.
Definition ai_info.cpp:32
AILibrary
All static information from an AI library like name, version, etc.
Definition ai_info.hpp:60
AILibrary::GetCategory
const std::string & GetCategory() const
Get the category this library is in.
Definition ai_info.hpp:77
AILibrary::RegisterAPI
static void RegisterAPI(Squirrel &engine)
Register the functions of this class.
Definition ai_info.cpp:128
AIScannerInfo::FindInfo
class AIInfo * FindInfo(const std::string &name, int version, bool force_exact_match)
Check if we have an AI by name and version available in our list.
Definition ai_scanner.cpp:78
AIScannerInfo::SetDummyAI
void SetDummyAI(std::unique_ptr< class AIInfo > &&info)
Set the Dummy AI.
Definition ai_scanner.cpp:39
AIScannerInfo::info_dummy
std::unique_ptr< AIInfo > info_dummy
The dummy AI.
Definition ai_scanner.hpp:50
AIScannerInfo::RegisterAPI
void RegisterAPI(class Squirrel &engine) override
Register the API for this ScriptInfo.
Definition ai_scanner.cpp:49
AIScannerInfo::SelectRandomAI
class AIInfo * SelectRandomAI() const
Select a random AI.
Definition ai_scanner.cpp:54
AIScannerInfo::GetScriptName
std::string GetScriptName(ScriptInfo &info) override
Get the script name how to store the script in memory.
Definition ai_scanner.cpp:44
AIScannerLibrary::RegisterAPI
void RegisterAPI(class Squirrel &engine) override
Register the API for this ScriptInfo.
Definition ai_scanner.cpp:126
AIScannerLibrary::GetScriptName
std::string GetScriptName(ScriptInfo &info) override
Get the script name how to store the script in memory.
Definition ai_scanner.cpp:120
AIScannerLibrary::FindLibrary
class AILibrary * FindLibrary(const std::string &library, int version)
Find a library in the pool.
Definition ai_scanner.cpp:131
ScriptAllocatorScope
Definition squirrel.hpp:299
ScriptInfo
All static information from an Script like name, version, etc.
Definition script_info.hpp:30
ScriptInfo::GetInstanceName
const std::string & GetInstanceName() const
Get the name of the instance of the script to create.
Definition script_info.hpp:65
ScriptInfo::GetName
const std::string & GetName() const
Get the Name of the script.
Definition script_info.hpp:40
ScriptInfo::GetVersion
int GetVersion() const
Get the version of the script.
Definition script_info.hpp:55
ScriptScanner::main_script
std::string main_script
The full path of the script.
Definition script_scanner.hpp:88
ScriptScanner::info_list
ScriptInfoList info_list
The list of all script.
Definition script_scanner.hpp:93
ScriptScanner::info_single_list
ScriptInfoList info_single_list
The list of all unique script. The best script (highest version) is shown.
Definition script_scanner.hpp:94
ScriptScanner::engine
std::unique_ptr< class Squirrel > engine
The engine we're scanning with.
Definition script_scanner.hpp:87
Squirrel
Definition squirrel.hpp:24
OWNER_NONE
static constexpr Owner OWNER_NONE
The tile has no ownership.
Definition company_type.h:26
Debug
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
Script_CreateDummyInfo
void Script_CreateDummyInfo(HSQUIRRELVM vm, std::string_view type, std::string_view dir)
Run the dummy info.nut.
Definition script_info_dummy.cpp:29
StrEqualsIgnoreCase
bool StrEqualsIgnoreCase(std::string_view str1, std::string_view str2)
Compares two string( view)s for equality, while ignoring the case of the characters.
Definition string.cpp:323