OpenTTD Source  13.2.1
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  }
52 
53  Backup<CompanyID> cur_company(_current_company, company, FILE_LINE);
54  Company *c = Company::Get(company);
55 
56  c->ai_info = info;
57  assert(c->ai_instance == nullptr);
58  c->ai_instance = new AIInstance();
59  c->ai_instance->Initialize(info);
60  c->ai_instance->LoadOnStack(config->GetToLoadData());
61  config->SetToLoadData(nullptr);
62 
63  cur_company.Restore();
64 
66  return;
67 }
68 
69 /* static */ void AI::GameLoop()
70 {
71  /* If we are in networking, only servers run this function, and that only if it is allowed */
73 
74  /* The speed with which AIs go, is limited by the 'competitor_speed' */
77  if ((AI::frame_counter & ((1 << (4 - _settings_game.difficulty.competitor_speed)) - 1)) != 0) return;
78 
79  Backup<CompanyID> cur_company(_current_company, FILE_LINE);
80  for (const Company *c : Company::Iterate()) {
81  if (c->is_ai) {
82  PerformanceMeasurer framerate((PerformanceElement)(PFE_AI0 + c->index));
83  cur_company.Change(c->index);
84  c->ai_instance->GameLoop();
85  } else {
87  }
88  }
89  cur_company.Restore();
90 
91  /* Occasionally collect garbage; every 255 ticks do one company.
92  * Effectively collecting garbage once every two months per AI. */
93  if ((AI::frame_counter & 255) == 0) {
95  if (Company::IsValidAiID(cid)) Company::Get(cid)->ai_instance->CollectGarbage();
96  }
97 }
98 
99 /* static */ uint AI::GetTick()
100 {
101  return AI::frame_counter;
102 }
103 
104 /* static */ void AI::Stop(CompanyID company)
105 {
106  if (_networking && !_network_server) return;
108 
109  Backup<CompanyID> cur_company(_current_company, company, FILE_LINE);
110  Company *c = Company::Get(company);
111 
112  delete c->ai_instance;
113  c->ai_instance = nullptr;
114  c->ai_info = nullptr;
115 
116  cur_company.Restore();
117 
120 }
121 
122 /* static */ void AI::Pause(CompanyID company)
123 {
124  /* The reason why dedicated servers are forbidden to execute this
125  * command is not because it is unsafe, but because there is no way
126  * for the server owner to unpause the script again. */
127  if (_network_dedicated) return;
128 
129  Backup<CompanyID> cur_company(_current_company, company, FILE_LINE);
130  Company::Get(company)->ai_instance->Pause();
131 
132  cur_company.Restore();
133 }
134 
135 /* static */ void AI::Unpause(CompanyID company)
136 {
137  Backup<CompanyID> cur_company(_current_company, company, FILE_LINE);
138  Company::Get(company)->ai_instance->Unpause();
139 
140  cur_company.Restore();
141 }
142 
143 /* static */ bool AI::IsPaused(CompanyID company)
144 {
145  Backup<CompanyID> cur_company(_current_company, company, FILE_LINE);
146  bool paused = Company::Get(company)->ai_instance->IsPaused();
147 
148  cur_company.Restore();
149 
150  return paused;
151 }
152 
153 /* static */ void AI::KillAll()
154 {
155  /* It might happen there are no companies .. than we have nothing to loop */
156  if (Company::GetPoolSize() == 0) return;
157 
158  for (const Company *c : Company::Iterate()) {
159  if (c->is_ai) AI::Stop(c->index);
160  }
161 }
162 
163 /* static */ void AI::Initialize()
164 {
165  if (AI::scanner_info != nullptr) AI::Uninitialize(true);
166 
167  AI::frame_counter = 0;
168  if (AI::scanner_info == nullptr) {
171  AI::scanner_info->Initialize();
173  AI::scanner_library->Initialize();
174  }
175 }
176 
177 /* static */ void AI::Uninitialize(bool keepConfig)
178 {
179  AI::KillAll();
180 
181  if (keepConfig) {
182  /* Run a rescan, which indexes all AIInfos again, and check if we can
183  * still load all the AIS, while keeping the configs in place */
184  Rescan();
185  } else {
186  delete AI::scanner_info;
187  delete AI::scanner_library;
188  AI::scanner_info = nullptr;
189  AI::scanner_library = nullptr;
190 
191  for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
192  if (_settings_game.ai_config[c] != nullptr) {
193  delete _settings_game.ai_config[c];
194  _settings_game.ai_config[c] = nullptr;
195  }
196  if (_settings_newgame.ai_config[c] != nullptr) {
197  delete _settings_newgame.ai_config[c];
198  _settings_newgame.ai_config[c] = nullptr;
199  }
200  }
201  }
202 }
203 
204 /* static */ void AI::ResetConfig()
205 {
206  /* Check for both newgame as current game if we can reload the AIInfo inside
207  * the AIConfig. If not, remove the AI from the list (which will assign
208  * a random new AI on reload). */
209  for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
210  if (_settings_game.ai_config[c] != nullptr && _settings_game.ai_config[c]->HasScript()) {
211  if (!_settings_game.ai_config[c]->ResetInfo(true)) {
212  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());
213  _settings_game.ai_config[c]->Change(nullptr);
214  if (Company::IsValidAiID(c)) {
215  /* The code belonging to an already running AI was deleted. We can only do
216  * one thing here to keep everything sane and that is kill the AI. After
217  * killing the offending AI we start a random other one in it's place, just
218  * like what would happen if the AI was missing during loading. */
219  AI::Stop(c);
220  AI::StartNew(c, false);
221  }
222  } else if (Company::IsValidAiID(c)) {
223  /* Update the reference in the Company struct. */
224  Company::Get(c)->ai_info = _settings_game.ai_config[c]->GetInfo();
225  }
226  }
227  if (_settings_newgame.ai_config[c] != nullptr && _settings_newgame.ai_config[c]->HasScript()) {
228  if (!_settings_newgame.ai_config[c]->ResetInfo(false)) {
229  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());
230  _settings_newgame.ai_config[c]->Change(nullptr);
231  }
232  }
233  }
234 }
235 
236 /* static */ void AI::NewEvent(CompanyID company, ScriptEvent *event)
237 {
238  /* AddRef() and Release() need to be called at least once, so do it here */
239  event->AddRef();
240 
241  /* Clients should ignore events */
242  if (_networking && !_network_server) {
243  event->Release();
244  return;
245  }
246 
247  /* Only AIs can have an event-queue */
248  if (!Company::IsValidAiID(company)) {
249  event->Release();
250  return;
251  }
252 
253  /* Queue the event */
254  Backup<CompanyID> cur_company(_current_company, company, FILE_LINE);
255  Company::Get(_current_company)->ai_instance->InsertEvent(event);
256  cur_company.Restore();
257 
258  event->Release();
259 }
260 
261 /* static */ void AI::BroadcastNewEvent(ScriptEvent *event, CompanyID skip_company)
262 {
263  /* AddRef() and Release() need to be called at least once, so do it here */
264  event->AddRef();
265 
266  /* Clients should ignore events */
267  if (_networking && !_network_server) {
268  event->Release();
269  return;
270  }
271 
272  /* Try to send the event to all AIs */
273  for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
274  if (c != skip_company) AI::NewEvent(c, event);
275  }
276 
277  event->Release();
278 }
279 
280 /* static */ void AI::Save(CompanyID company)
281 {
282  if (!_networking || _network_server) {
283  Company *c = Company::GetIfValid(company);
284  assert(c != nullptr && c->ai_instance != nullptr);
285 
286  Backup<CompanyID> cur_company(_current_company, company, FILE_LINE);
287  c->ai_instance->Save();
288  cur_company.Restore();
289  } else {
291  }
292 }
293 
294 /* static */ int AI::GetStartNextTime()
295 {
296  /* Find the first company which doesn't exist yet */
297  for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
299  }
300 
301  /* Currently no AI can be started, check again in a year. */
302  return DAYS_IN_YEAR;
303 }
304 
305 /* static */ std::string AI::GetConsoleList(bool newest_only)
306 {
307  return AI::scanner_info->GetConsoleList(newest_only);
308 }
309 
310 /* static */ std::string AI::GetConsoleLibraryList()
311 {
312  return AI::scanner_library->GetConsoleList(true);
313 }
314 
315 /* static */ const ScriptInfoList *AI::GetInfoList()
316 {
317  return AI::scanner_info->GetInfoList();
318 }
319 
321 {
323 }
324 
325 /* static */ AIInfo *AI::FindInfo(const char *name, int version, bool force_exact_match)
326 {
327  return AI::scanner_info->FindInfo(name, version, force_exact_match);
328 }
329 
330 /* static */ AILibrary *AI::FindLibrary(const char *library, int version)
331 {
332  return AI::scanner_library->FindLibrary(library, version);
333 }
334 
335 /* static */ void AI::Rescan()
336 {
338 
341  ResetConfig();
342 
346 }
347 
354 /* static */ bool AI::HasAI(const ContentInfo *ci, bool md5sum)
355 {
356  return AI::scanner_info->HasScript(ci, md5sum);
357 }
358 
359 /* static */ bool AI::HasAILibrary(const ContentInfo *ci, bool md5sum)
360 {
361  return AI::scanner_library->HasScript(ci, md5sum);
362 }
363 
365 {
366  return AI::scanner_info;
367 }
368 
370 {
371  return AI::scanner_library;
372 }
373 
AI::Uninitialize
static void Uninitialize(bool keepConfig)
Uninitialize the AI system.
Definition: ai_core.cpp:177
AI::FindLibrary
static class AILibrary * FindLibrary(const char *library, int version)
Wrapper function for AIScanner::FindLibrary.
Definition: ai_core.cpp:330
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:3254
AIConfig
Definition: ai_config.hpp:16
GameSettings::ai_config
class AIConfig * ai_config[MAX_COMPANIES]
settings per company
Definition: settings_type.h:591
Pool::PoolItem<&_company_pool >::Get
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:337
AI::GetScannerInfo
static AIScannerInfo * GetScannerInfo()
Gets the ScriptScanner instance that is used to find AIs.
Definition: ai_core.cpp:364
GB
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
Definition: bitmath_func.hpp:32
ScriptScanner::GetConsoleList
std::string GetConsoleList(bool newest_only) const
Get the list of registered scripts to print on the console.
Definition: script_scanner.cpp:148
Pool::PoolItem<&_company_pool >::GetIfValid
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:348
ScriptInstance::Save
void Save()
Call the script Save function and save all data in the savegame.
Definition: script_instance.cpp:475
Backup
Class to backup a specific variable and restore it later.
Definition: backup_type.hpp:21
TarScanner::DoScan
uint DoScan(Subdirectory sd)
Perform the scanning of a particular subdirectory.
Definition: fileio.cpp:410
AI::FindInfo
static class AIInfo * FindInfo(const char *name, int version, bool force_exact_match)
Wrapper function for AIScanner::FindInfo.
Definition: ai_core.cpp:325
_network_server
bool _network_server
network-server is active
Definition: network.cpp:59
AIScannerLibrary
Definition: ai_scanner.hpp:53
AI::GetStartNextTime
static int GetStartNextTime()
Get the number of days before the next AI should start.
Definition: ai_core.cpp:294
GameSettings::difficulty
DifficultySettings difficulty
settings related to the difficulty
Definition: settings_type.h:586
AIInstance::Initialize
void Initialize(class AIInfo *info)
Initialize the AI and prepare it for its first run.
Definition: ai_instance.cpp:40
AIScannerInfo::FindInfo
class AIInfo * FindInfo(const char *nameParam, int versionParam, bool force_exact_match)
Check if we have an AI by name and version available in our list.
Definition: ai_scanner.cpp:100
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
DifficultySettings::competitor_speed
byte competitor_speed
the speed at which the AI builds
Definition: settings_type.h:84
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
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:50
ScriptInfo::version
int version
Version of the script.
Definition: script_info.hpp:161
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:135
Pool::PoolItem<&_company_pool >::GetPoolSize
static size_t GetPoolSize()
Returns first unused index.
Definition: pool_type.hpp:358
AIScannerLibrary::FindLibrary
class AILibrary * FindLibrary(const char *library, int version)
Find a library in the pool.
Definition: ai_scanner.cpp:157
AI::NewEvent
static void NewEvent(CompanyID company, ScriptEvent *event)
Queue a new event for an AI.
Definition: ai_core.cpp:236
AI::scanner_library
static class AIScannerLibrary * scanner_library
ScriptScanner instance that is used to find AI Libraries.
Definition: ai.hpp:166
ScriptInfoList
std::map< const char *, class ScriptInfo *, StringCompare > ScriptInfoList
A list that maps AI names to their AIInfo object.
Definition: ai.hpp:19
AI::Save
static void Save(CompanyID company)
Save data from an AI to a savegame.
Definition: ai_core.cpp:280
AI::GetConsoleLibraryList
static std::string GetConsoleLibraryList()
Wrapper function for AIScanner::GetAIConsoleLibraryList.
Definition: ai_core.cpp:310
ContentInfo
Container for all important information about a piece of content.
Definition: tcp_content_type.h:50
ScriptInstance::SaveEmpty
static void SaveEmpty()
Don't save any data in the savegame.
Definition: script_instance.cpp:469
ScriptConfig::GetName
const char * GetName() const
Get the name of the Script.
Definition: script_config.cpp:175
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:58
ai_instance.hpp
AIConfig::GetConfig
static AIConfig * GetConfig(CompanyID company, ScriptSettingSource source=SSS_DEFAULT)
Get the config of a company.
Definition: ai_config.cpp:45
AI::Pause
static void Pause(CompanyID company)
Suspend the AI and then pause execution of the script.
Definition: ai_core.cpp:122
AI::GetScannerLibrary
static AIScannerLibrary * GetScannerLibrary()
Gets the ScriptScanner instance that is used to find AI Libraries.
Definition: ai_core.cpp:369
AI::Initialize
static void Initialize()
Initialize the AI system.
Definition: ai_core.cpp:163
ScriptConfig::IsRandom
bool IsRandom() const
Is the current Script a randomly chosen Script?
Definition: script_config.cpp:170
_settings_game
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:54
AI::scanner_info
static class AIScannerInfo * scanner_info
ScriptScanner instance that is used to find AIs.
Definition: ai.hpp:165
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:354
AI::BroadcastNewEvent
static void BroadcastNewEvent(ScriptEvent *event, CompanyID skip_company=MAX_COMPANIES)
Broadcast a new event to all active AIs.
Definition: ai_core.cpp:261
AI::GetInfoList
static const ScriptInfoList * GetInfoList()
Wrapper function for AIScanner::GetAIInfoList.
Definition: ai_core.cpp:315
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:137
AIScannerInfo
Definition: ai_scanner.hpp:15
_networking
bool _networking
are we in networking mode?
Definition: network.cpp:58
AI::GetTick
static uint GetTick()
Get the current AI tick.
Definition: ai_core.cpp:99
_network_dedicated
bool _network_dedicated
are we a dedicated server?
Definition: network.cpp:61
AI::GameLoop
static void GameLoop()
Called every game-tick to let AIs do something.
Definition: ai_core.cpp:69
AI::IsPaused
static bool IsPaused(CompanyID company)
Checks if the AI is paused.
Definition: ai_core.cpp:143
AI::frame_counter
static uint frame_counter
Tick counter for the AI code.
Definition: ai.hpp:164
GameSettings::ai
AISettings ai
what may the AI do?
Definition: settings_type.h:589
_current_company
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:47
WC_AI_DEBUG
@ WC_AI_DEBUG
AI debug window; Window numbers:
Definition: window_type.h:656
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:386
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:251
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:94
ScriptScanner::GetInfoList
const ScriptInfoList * GetInfoList()
Get the list of all registered scripts.
Definition: script_scanner.hpp:45
AI::KillAll
static void KillAll()
Kill any and all AIs we manage.
Definition: ai_core.cpp:153
Backup::Restore
void Restore()
Restore the variable.
Definition: backup_type.hpp:112
WC_AI_LIST
@ WC_AI_LIST
AI list; Window numbers:
Definition: window_type.h:277
TarScanner::AI
@ AI
Scan for AIs and its libraries.
Definition: fileio_func.h:69
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:3271
WC_AI_SETTINGS
@ WC_AI_SETTINGS
AI settings; Window numbers:
Definition: window_type.h:168
DAYS_IN_YEAR
static const int DAYS_IN_YEAR
days per year
Definition: date_type.h:29
ScriptInstance::LoadOnStack
void LoadOnStack(ScriptData *data)
Store loaded data on the stack.
Definition: script_instance.cpp:690
AI::GetConsoleList
static std::string GetConsoleList(bool newest_only=false)
Wrapper function for AIScanner::GetAIConsoleList.
Definition: ai_core.cpp:305
Debug
#define Debug(name, level, format_string,...)
Ouptut a line of debugging information.
Definition: debug.h:37
ai_scanner.hpp
AIInfo
All static information from an AI like name, version, etc.
Definition: ai_info.hpp:16
CloseWindowById
void CloseWindowById(WindowClass cls, WindowNumber number, bool force)
Close a window by its class and window number (if it is open).
Definition: window.cpp:1191
AI::GetUniqueInfoList
static const ScriptInfoList * GetUniqueInfoList()
Wrapper function for AIScanner::GetUniqueAIInfoList.
Definition: ai_core.cpp:320
AIInstance
Runtime information about an AI like a pointer to the squirrel vm and the current state.
Definition: ai_instance.hpp:16
ScriptConfig::Change
void Change(const char *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:19
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:326
ScriptInfo::GetName
const char * GetName() const
Get the Name of the script.
Definition: script_info.hpp:55
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:104
ScriptInfo::name
const char * name
Full name of the script.
Definition: script_info.hpp:156
AI::Rescan
static void Rescan()
Rescans all searchpaths for available AIs.
Definition: ai_core.cpp:335
Company
Definition: company_base.h:117
SetWindowClassesDirty
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition: window.cpp:3182
ScriptConfig::SSS_FORCE_GAME
@ SSS_FORCE_GAME
Get the Script config from the current game.
Definition: script_config.hpp:110
AI::ResetConfig
static void ResetConfig()
Reset all AIConfigs, and make them reload their AIInfo.
Definition: ai_core.cpp:204
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:165
AIConfig::GetSetting
int GetSetting(const char *name) const override
Get the value of a setting for this config.
Definition: ai_config.cpp:89
AISettings::ai_in_multiplayer
bool ai_in_multiplayer
so we allow AIs in multiplayer
Definition: settings_type.h:370
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:55
AIConfig::ResetInfo
bool ResetInfo(bool force_exact_match)
When ever the AI Scanner is reloaded, all infos become invalid.
Definition: ai_config.cpp:67
ai_config.hpp