OpenTTD Source  14.0-beta3
ai_core.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 <http://www.gnu.org/licenses/>.
6  */
7 
10 #include "../stdafx.h"
11 #include "../core/backup_type.hpp"
12 #include "../core/bitmath_func.hpp"
13 #include "../company_base.h"
14 #include "../company_func.h"
15 #include "../network/network.h"
16 #include "../window_func.h"
17 #include "../framerate_type.h"
18 #include "ai_scanner.hpp"
19 #include "ai_instance.hpp"
20 #include "ai_config.hpp"
21 #include "ai_info.hpp"
22 #include "ai.hpp"
23 
24 #include "../safeguards.h"
25 
26 /* static */ uint AI::frame_counter = 0;
27 /* static */ AIScannerInfo *AI::scanner_info = nullptr;
28 /* static */ AIScannerLibrary *AI::scanner_library = nullptr;
29 
30 /* static */ bool AI::CanStartNew()
31 {
32  /* Only allow new AIs on the server and only when that is allowed in multiplayer */
34 }
35 
36 /* static */ void AI::StartNew(CompanyID company, bool rerandomise_ai)
37 {
38  assert(Company::IsValidID(company));
39 
40  /* Clients shouldn't start AIs */
41  if (_networking && !_network_server) return;
42 
44  AIInfo *info = config->GetInfo();
45  if (info == nullptr || (rerandomise_ai && config->IsRandom())) {
47  assert(info != nullptr);
48  /* Load default data and store the name in the settings */
49  config->Change(info->GetName(), -1, false, true);
50  }
51  if (rerandomise_ai) config->AddRandomDeviation();
53 
54  Backup<CompanyID> cur_company(_current_company, company, FILE_LINE);
55  Company *c = Company::Get(company);
56 
57  c->ai_info = info;
58  assert(c->ai_instance == nullptr);
59  c->ai_instance = new AIInstance();
60  c->ai_instance->Initialize(info);
61  c->ai_instance->LoadOnStack(config->GetToLoadData());
62  config->SetToLoadData(nullptr);
63 
64  cur_company.Restore();
65 
67  return;
68 }
69 
70 /* static */ void AI::GameLoop()
71 {
72  /* If we are in networking, only servers run this function, and that only if it is allowed */
74 
75  /* The speed with which AIs go, is limited by the 'competitor_speed' */
78  if ((AI::frame_counter & ((1 << (4 - _settings_game.difficulty.competitor_speed)) - 1)) != 0) return;
79 
80  Backup<CompanyID> cur_company(_current_company, FILE_LINE);
81  for (const Company *c : Company::Iterate()) {
82  if (c->is_ai) {
83  PerformanceMeasurer framerate((PerformanceElement)(PFE_AI0 + c->index));
84  cur_company.Change(c->index);
85  c->ai_instance->GameLoop();
86  /* Occasionally collect garbage; every 255 ticks do one company.
87  * Effectively collecting garbage once every two months per AI. */
88  if ((AI::frame_counter & 255) == 0 && (CompanyID)GB(AI::frame_counter, 8, 4) == c->index) {
89  c->ai_instance->CollectGarbage();
90  }
91  } else {
93  }
94  }
95  cur_company.Restore();
96 }
97 
98 /* static */ uint AI::GetTick()
99 {
100  return AI::frame_counter;
101 }
102 
103 /* static */ void AI::Stop(CompanyID company)
104 {
105  if (_networking && !_network_server) return;
107 
108  Backup<CompanyID> cur_company(_current_company, company, FILE_LINE);
109  Company *c = Company::Get(company);
110 
111  delete c->ai_instance;
112  c->ai_instance = nullptr;
113  c->ai_info = nullptr;
114 
115  cur_company.Restore();
116 
119 }
120 
121 /* static */ void AI::Pause(CompanyID company)
122 {
123  /* The reason why dedicated servers are forbidden to execute this
124  * command is not because it is unsafe, but because there is no way
125  * for the server owner to unpause the script again. */
126  if (_network_dedicated) return;
127 
128  Backup<CompanyID> cur_company(_current_company, company, FILE_LINE);
129  Company::Get(company)->ai_instance->Pause();
130 
131  cur_company.Restore();
132 }
133 
134 /* static */ void AI::Unpause(CompanyID company)
135 {
136  Backup<CompanyID> cur_company(_current_company, company, FILE_LINE);
137  Company::Get(company)->ai_instance->Unpause();
138 
139  cur_company.Restore();
140 }
141 
142 /* static */ bool AI::IsPaused(CompanyID company)
143 {
144  Backup<CompanyID> cur_company(_current_company, company, FILE_LINE);
145  bool paused = Company::Get(company)->ai_instance->IsPaused();
146 
147  cur_company.Restore();
148 
149  return paused;
150 }
151 
152 /* static */ void AI::KillAll()
153 {
154  /* It might happen there are no companies .. than we have nothing to loop */
155  if (Company::GetPoolSize() == 0) return;
156 
157  for (const Company *c : Company::Iterate()) {
158  if (c->is_ai) AI::Stop(c->index);
159  }
160 }
161 
162 /* static */ void AI::Initialize()
163 {
164  if (AI::scanner_info != nullptr) AI::Uninitialize(true);
165 
166  AI::frame_counter = 0;
167  if (AI::scanner_info == nullptr) {
170  AI::scanner_info->Initialize();
172  AI::scanner_library->Initialize();
173  }
174 }
175 
176 /* static */ void AI::Uninitialize(bool keepConfig)
177 {
178  AI::KillAll();
179 
180  if (keepConfig) {
181  /* Run a rescan, which indexes all AIInfos again, and check if we can
182  * still load all the AIS, while keeping the configs in place */
183  Rescan();
184  } else {
185  delete AI::scanner_info;
186  delete AI::scanner_library;
187  AI::scanner_info = nullptr;
188  AI::scanner_library = nullptr;
189 
190  for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
191  if (_settings_game.ai_config[c] != nullptr) {
192  delete _settings_game.ai_config[c];
193  _settings_game.ai_config[c] = nullptr;
194  }
195  if (_settings_newgame.ai_config[c] != nullptr) {
196  delete _settings_newgame.ai_config[c];
197  _settings_newgame.ai_config[c] = nullptr;
198  }
199  }
200  }
201 }
202 
203 /* static */ void AI::ResetConfig()
204 {
205  /* Check for both newgame as current game if we can reload the AIInfo inside
206  * the AIConfig. If not, remove the AI from the list (which will assign
207  * a random new AI on reload). */
208  for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
209  if (_settings_game.ai_config[c] != nullptr && _settings_game.ai_config[c]->HasScript()) {
210  if (!_settings_game.ai_config[c]->ResetInfo(true)) {
211  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());
212  _settings_game.ai_config[c]->Change(std::nullopt);
213  if (Company::IsValidAiID(c)) {
214  /* The code belonging to an already running AI was deleted. We can only do
215  * one thing here to keep everything sane and that is kill the AI. After
216  * killing the offending AI we start a random other one in it's place, just
217  * like what would happen if the AI was missing during loading. */
218  AI::Stop(c);
219  AI::StartNew(c, false);
220  }
221  } else if (Company::IsValidAiID(c)) {
222  /* Update the reference in the Company struct. */
223  Company::Get(c)->ai_info = _settings_game.ai_config[c]->GetInfo();
224  }
225  }
226  if (_settings_newgame.ai_config[c] != nullptr && _settings_newgame.ai_config[c]->HasScript()) {
227  if (!_settings_newgame.ai_config[c]->ResetInfo(false)) {
228  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());
229  _settings_newgame.ai_config[c]->Change(std::nullopt);
230  }
231  }
232  }
233 }
234 
235 /* static */ void AI::NewEvent(CompanyID company, ScriptEvent *event)
236 {
237  /* AddRef() and Release() need to be called at least once, so do it here */
238  event->AddRef();
239 
240  /* Clients should ignore events */
241  if (_networking && !_network_server) {
242  event->Release();
243  return;
244  }
245 
246  /* Only AIs can have an event-queue */
247  if (!Company::IsValidAiID(company)) {
248  event->Release();
249  return;
250  }
251 
252  /* Queue the event */
253  Backup<CompanyID> cur_company(_current_company, company, FILE_LINE);
254  Company::Get(_current_company)->ai_instance->InsertEvent(event);
255  cur_company.Restore();
256 
257  event->Release();
258 }
259 
260 /* static */ void AI::BroadcastNewEvent(ScriptEvent *event, CompanyID skip_company)
261 {
262  /* AddRef() and Release() need to be called at least once, so do it here */
263  event->AddRef();
264 
265  /* Clients should ignore events */
266  if (_networking && !_network_server) {
267  event->Release();
268  return;
269  }
270 
271  /* Try to send the event to all AIs */
272  for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
273  if (c != skip_company) AI::NewEvent(c, event);
274  }
275 
276  event->Release();
277 }
278 
279 /* static */ void AI::Save(CompanyID company)
280 {
281  if (!_networking || _network_server) {
282  Company *c = Company::GetIfValid(company);
283  assert(c != nullptr && c->ai_instance != nullptr);
284 
285  Backup<CompanyID> cur_company(_current_company, company, FILE_LINE);
286  c->ai_instance->Save();
287  cur_company.Restore();
288  } else {
290  }
291 }
292 
293 /* static */ void AI::GetConsoleList(std::back_insert_iterator<std::string> &output_iterator, bool newest_only)
294 {
295  AI::scanner_info->GetConsoleList(output_iterator, newest_only);
296 }
297 
298 /* static */ void AI::GetConsoleLibraryList(std::back_insert_iterator<std::string> &output_iterator)
299 {
300  AI::scanner_library->GetConsoleList(output_iterator, true);
301 }
302 
303 /* static */ const ScriptInfoList *AI::GetInfoList()
304 {
305  return AI::scanner_info->GetInfoList();
306 }
307 
309 {
311 }
312 
313 /* static */ AIInfo *AI::FindInfo(const std::string &name, int version, bool force_exact_match)
314 {
315  return AI::scanner_info->FindInfo(name, version, force_exact_match);
316 }
317 
318 /* static */ AILibrary *AI::FindLibrary(const std::string &library, int version)
319 {
320  return AI::scanner_library->FindLibrary(library, version);
321 }
322 
323 /* static */ void AI::Rescan()
324 {
326 
329  ResetConfig();
330 
334 }
335 
342 /* static */ bool AI::HasAI(const ContentInfo *ci, bool md5sum)
343 {
344  return AI::scanner_info->HasScript(ci, md5sum);
345 }
346 
347 /* static */ bool AI::HasAILibrary(const ContentInfo *ci, bool md5sum)
348 {
349  return AI::scanner_library->HasScript(ci, md5sum);
350 }
351 
353 {
354  return AI::scanner_info;
355 }
356 
358 {
359  return AI::scanner_library;
360 }
361 
AI::Uninitialize
static void Uninitialize(bool keepConfig)
Uninitialize the AI system.
Definition: ai_core.cpp:176
Backup::Change
void Change(const U &new_value)
Change the value of the variable.
Definition: backup_type.hpp:84
InvalidateWindowData
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
Definition: window.cpp:3200
WC_SCRIPT_DEBUG
@ WC_SCRIPT_DEBUG
Script debug window; Window numbers:
Definition: window_type.h:669
AIConfig
Definition: ai_config.hpp:16
ScriptInfoList
std::map< std::string, class ScriptInfo *, CaseInsensitiveComparator > ScriptInfoList
Type for the list of scripts.
Definition: script_scanner.hpp:16
GameSettings::ai_config
class AIConfig * ai_config[MAX_COMPANIES]
settings per company
Definition: settings_type.h:623
Pool::PoolItem<&_company_pool >::Get
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:335
AI::GetScannerInfo
static AIScannerInfo * GetScannerInfo()
Gets the ScriptScanner instance that is used to find AIs.
Definition: ai_core.cpp:352
Pool::PoolItem<&_company_pool >::GetIfValid
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:346
ScriptInstance::Save
void Save()
Call the script Save function and save all data in the savegame.
Definition: script_instance.cpp:476
Backup
Class to backup a specific variable and restore it later.
Definition: backup_type.hpp:21
AIScannerLibrary::FindLibrary
class AILibrary * FindLibrary(const std::string &library, int version)
Find a library in the pool.
Definition: ai_scanner.cpp:148
TarScanner::DoScan
uint DoScan(Subdirectory sd)
Perform the scanning of a particular subdirectory.
Definition: fileio.cpp:427
_network_server
bool _network_server
network-server is active
Definition: network.cpp:60
CloseWindowById
void CloseWindowById(WindowClass cls, WindowNumber number, bool force, int data)
Close a window by its class and window number (if it is open).
Definition: window.cpp:1141
AIScannerLibrary
Definition: ai_scanner.hpp:53
GB
constexpr static debug_inline uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
Definition: bitmath_func.hpp:32
GameSettings::difficulty
DifficultySettings difficulty
settings related to the difficulty
Definition: settings_type.h:618
AIInstance::Initialize
void Initialize(class AIInfo *info)
Initialize the AI and prepare it for its first run.
Definition: ai_instance.cpp:40
PerformanceMeasurer
RAII class for measuring simple elements of performance.
Definition: framerate_type.h:92
AI::CanStartNew
static bool CanStartNew()
Is it possible to start a new AI company?
Definition: ai_core.cpp:30
ScriptScanner::GetConsoleList
void GetConsoleList(std::back_insert_iterator< std::string > &output_iterator, bool newest_only) const
Get the list of registered scripts to print on the console.
Definition: script_scanner.cpp:141
DifficultySettings::competitor_speed
byte competitor_speed
the speed at which the AI builds
Definition: settings_type.h:106
Owner
Owner
Enum for all companies/owners.
Definition: company_type.h:18
PerformanceMeasurer::SetInactive
static void SetInactive(PerformanceElement elem)
Mark a performance element as not currently in use.
Definition: framerate_gui.cpp:286
ScriptScanner::RescanDir
void RescanDir()
Rescan the script dir.
Definition: script_scanner.cpp:75
Debug
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
Definition: debug.h:37
PerformanceElement
PerformanceElement
Elements of game performance that can be measured.
Definition: framerate_type.h:47
ScriptScanner::GetUniqueInfoList
const ScriptInfoList * GetUniqueInfoList()
Get the list of the latest version of all registered scripts.
Definition: script_scanner.hpp:49
ScriptInfo::version
int version
Version of the script.
Definition: script_info.hpp:152
ai.hpp
ai_info.hpp
COMPANY_FIRST
@ COMPANY_FIRST
First company, same as owner.
Definition: company_type.h:22
AI::Unpause
static void Unpause(CompanyID company)
Resume execution of the AI.
Definition: ai_core.cpp:134
Pool::PoolItem<&_company_pool >::GetPoolSize
static size_t GetPoolSize()
Returns first unused index.
Definition: pool_type.hpp:356
AI::GetConsoleLibraryList
static void GetConsoleLibraryList(std::back_insert_iterator< std::string > &output_iterator)
Wrapper function for AIScanner::GetAIConsoleLibraryList.
Definition: ai_core.cpp:298
AI::NewEvent
static void NewEvent(CompanyID company, ScriptEvent *event)
Queue a new event for an AI.
Definition: ai_core.cpp:235
AI::scanner_library
static class AIScannerLibrary * scanner_library
ScriptScanner instance that is used to find AI Libraries.
Definition: ai.hpp:144
AI::Save
static void Save(CompanyID company)
Save data from an AI to a savegame.
Definition: ai_core.cpp:279
ScriptConfig::AddRandomDeviation
void AddRandomDeviation()
Randomize all settings the Script requested to be randomized.
Definition: script_config.cpp:128
ContentInfo
Container for all important information about a piece of content.
Definition: tcp_content_type.h:52
ScriptInstance::SaveEmpty
static void SaveEmpty()
Don't save any data in the savegame.
Definition: script_instance.cpp:470
AI::StartNew
static void StartNew(CompanyID company, bool rerandomise_ai=true)
Start a new AI company.
Definition: ai_core.cpp:36
AILibrary
All static information from an AI library like name, version, etc.
Definition: ai_info.hpp:57
ai_instance.hpp
AIConfig::GetConfig
static AIConfig * GetConfig(CompanyID company, ScriptSettingSource source=SSS_DEFAULT)
Get the config of a company.
Definition: ai_config.cpp:19
AI::Pause
static void Pause(CompanyID company)
Suspend the AI and then pause execution of the script.
Definition: ai_core.cpp:121
AI::GetScannerLibrary
static AIScannerLibrary * GetScannerLibrary()
Gets the ScriptScanner instance that is used to find AI Libraries.
Definition: ai_core.cpp:357
AI::Initialize
static void Initialize()
Initialize the AI system.
Definition: ai_core.cpp:162
ScriptConfig::IsRandom
bool IsRandom() const
Is the current Script a randomly chosen Script?
Definition: script_config.cpp:142
_settings_game
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:55
AI::scanner_info
static class AIScannerInfo * scanner_info
ScriptScanner instance that is used to find AIs.
Definition: ai.hpp:143
MAX_COMPANIES
@ MAX_COMPANIES
Maximum number of companies.
Definition: company_type.h:23
AI::HasAI
static bool HasAI(const struct ContentInfo *ci, bool md5sum)
Wrapper function for AIScanner::HasAI.
Definition: ai_core.cpp:342
AI::BroadcastNewEvent
static void BroadcastNewEvent(ScriptEvent *event, CompanyID skip_company=MAX_COMPANIES)
Broadcast a new event to all active AIs.
Definition: ai_core.cpp:260
ScriptInfo::GetName
const std::string & GetName() const
Get the Name of the script.
Definition: script_info.hpp:46
AI::GetInfoList
static const ScriptInfoList * GetInfoList()
Wrapper function for AIScanner::GetAIInfoList.
Definition: ai_core.cpp:303
Company::IsValidAiID
static bool IsValidAiID(size_t index)
Is this company a valid company, controlled by the computer (a NoAI program)?
Definition: company_base.h:138
AIScannerInfo
Definition: ai_scanner.hpp:15
_networking
bool _networking
are we in networking mode?
Definition: network.cpp:59
AI::GetTick
static uint GetTick()
Get the current AI tick.
Definition: ai_core.cpp:98
_network_dedicated
bool _network_dedicated
are we a dedicated server?
Definition: network.cpp:62
AI::GameLoop
static void GameLoop()
Called every game-tick to let AIs do something.
Definition: ai_core.cpp:70
AI::FindLibrary
static class AILibrary * FindLibrary(const std::string &library, int version)
Wrapper function for AIScanner::FindLibrary.
Definition: ai_core.cpp:318
AI::IsPaused
static bool IsPaused(CompanyID company)
Checks if the AI is paused.
Definition: ai_core.cpp:142
AI::frame_counter
static uint frame_counter
Tick counter for the AI code.
Definition: ai.hpp:142
ScriptConfig::Change
void Change(std::optional< const std::string > name, int version=-1, bool force_exact_match=false, bool is_random=false)
Set another Script to be loaded in this slot.
Definition: script_config.cpp:21
GameSettings::ai
AISettings ai
what may the AI do?
Definition: settings_type.h:621
_current_company
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:50
Pool::PoolItem<&_company_pool >::Iterate
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:384
ScriptScanner::HasScript
bool HasScript(const struct ContentInfo *ci, bool md5sum)
Check whether we have a script with the exact characteristics as ci.
Definition: script_scanner.cpp:237
ScriptConfig::AnchorUnchangeableSettings
void AnchorUnchangeableSettings()
As long as the default of a setting has not been changed, the value of the setting is not stored.
Definition: script_config.cpp:75
ScriptScanner::GetInfoList
const ScriptInfoList * GetInfoList()
Get the list of all registered scripts.
Definition: script_scanner.hpp:44
AI::KillAll
static void KillAll()
Kill any and all AIs we manage.
Definition: ai_core.cpp:152
Backup::Restore
void Restore()
Restore the variable.
Definition: backup_type.hpp:112
TarScanner::AI
@ AI
Scan for AIs and its libraries.
Definition: fileio_func.h:67
InvalidateWindowClassesData
void InvalidateWindowClassesData(WindowClass cls, int data, bool gui_scope)
Mark window data of all windows of a given class as invalid (in need of re-computing) Note that by de...
Definition: window.cpp:3217
ScriptInfo::name
std::string name
Full name of the script.
Definition: script_info.hpp:147
ScriptInstance::LoadOnStack
void LoadOnStack(ScriptData *data)
Store loaded data on the stack.
Definition: script_instance.cpp:690
ai_scanner.hpp
AIInfo
All static information from an AI like name, version, etc.
Definition: ai_info.hpp:16
AI::GetUniqueInfoList
static const ScriptInfoList * GetUniqueInfoList()
Wrapper function for AIScanner::GetUniqueAIInfoList.
Definition: ai_core.cpp:308
AIInstance
Runtime information about an AI like a pointer to the squirrel vm and the current state.
Definition: ai_instance.hpp:16
AI::GetConsoleList
static void GetConsoleList(std::back_insert_iterator< std::string > &output_iterator, bool newest_only)
Wrapper function for AIScanner::GetAIConsoleList.
Definition: ai_core.cpp:293
AI::FindInfo
static class AIInfo * FindInfo(const std::string &name, int version, bool force_exact_match)
Wrapper function for AIScanner::FindInfo.
Definition: ai_core.cpp:313
Pool::PoolItem<&_company_pool >::IsValidID
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:324
PFE_AI0
@ PFE_AI0
AI execution for player slot 1.
Definition: framerate_type.h:63
AI::Stop
static void Stop(CompanyID company)
Stop a company to be controlled by an AI.
Definition: ai_core.cpp:103
WC_SCRIPT_SETTINGS
@ WC_SCRIPT_SETTINGS
Script settings; Window numbers:
Definition: window_type.h:175
WC_SCRIPT_LIST
@ WC_SCRIPT_LIST
Scripts list; Window numbers:
Definition: window_type.h:284
AI::Rescan
static void Rescan()
Rescans all searchpaths for available AIs.
Definition: ai_core.cpp:323
Company
Definition: company_base.h:116
SetWindowClassesDirty
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition: window.cpp:3108
ScriptConfig::SSS_FORCE_GAME
@ SSS_FORCE_GAME
Get the Script config from the current game.
Definition: script_config.hpp:99
AI::ResetConfig
static void ResetConfig()
Reset all AIConfigs, and make them reload their AIInfo.
Definition: ai_core.cpp:203
ScriptConfig::HasScript
bool HasScript() const
Is this config attached to an Script? In other words, is there a Script that is assigned to this slot...
Definition: script_config.cpp:137
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:95
AISettings::ai_in_multiplayer
bool ai_in_multiplayer
so we allow AIs in multiplayer
Definition: settings_type.h:399
AIScannerInfo::SelectRandomAI
class AIInfo * SelectRandomAI() const
Select a random AI.
Definition: ai_scanner.cpp:61
_settings_newgame
GameSettings _settings_newgame
Game settings for new games (updated from the intro screen).
Definition: settings.cpp:56
AIConfig::ResetInfo
bool ResetInfo(bool force_exact_match)
When ever the AI Scanner is reloaded, all infos become invalid.
Definition: ai_config.cpp:43
ai_config.hpp
ScriptConfig::GetName
const std::string & GetName() const
Get the name of the Script.
Definition: script_config.cpp:147