File: AILibraryManager.h

package info (click to toggle)
spring 106.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 55,260 kB
  • sloc: cpp: 543,946; ansic: 44,800; python: 12,575; java: 12,201; awk: 5,889; sh: 1,796; asm: 1,546; xml: 655; perl: 405; php: 211; objc: 194; makefile: 76; sed: 2
file content (200 lines) | stat: -rw-r--r-- 6,518 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */

#ifndef AI_LIBRARY_MANAGER_H
#define	AI_LIBRARY_MANAGER_H

#include "AIInterfaceLibrary.h"
#include "AIInterfaceLibraryInfo.h"
#include "SkirmishAILibraryInfo.h"

#include <memory>
#include <map>
#include <vector>
#include <set>

class AIInterfaceKey;
class SkirmishAIKey;
class CSkirmishAILibrary;

/**
 * Manages AI Interfaces and Skirmish AIs; their info and current status.
 * It loads info about AI Interfaces and Skirmish AIs from info files
 * in the data directories, from InterfaceInfo.lua and AIInfo.lua files.
 * In addition to that, it keeps track fo which Interfaces and AIs
 * are currently loaded, and unloads them when they are not needed anymore.
 */
class AILibraryManager {
public:
	typedef std::set<AIInterfaceKey> T_interfaceSpecs;
	typedef std::set<SkirmishAIKey> T_skirmishAIKeys;

	typedef std::map<const AIInterfaceKey, CAIInterfaceLibraryInfo> T_interfaceInfos;
	typedef std::map<const SkirmishAIKey, CSkirmishAILibraryInfo> T_skirmishAIInfos;

	typedef std::map<const AIInterfaceKey, std::set<std::string> > T_dupInt;
	typedef std::map<const SkirmishAIKey, std::set<std::string> > T_dupSkirm;


public:
	static AILibraryManager* GetInstance(bool init = true);

	static void Create() { GetInstance(false); }
	static void Destroy() { GetInstance(false)->Kill(); }
	static void OutputAIInterfacesInfo();
	static void OutputSkirmishAIInfo();


	void Init();
	/**
	 * Unloads all Interface and AI shared libraries that are currently loaded.
	 */
	void Kill();

	bool Initialized() const { return initialized; }

	/**
	 * Returns a resolved aikey
	 * @see SkirmishAIKey::IsUnspecified()
	 */
	SkirmishAIKey ResolveSkirmishAIKey(const SkirmishAIKey& skirmishAIKey) const;


	const T_interfaceSpecs& GetInterfaceKeys() const { return interfaceKeys; }
	const T_skirmishAIKeys& GetSkirmishAIKeys() const { return skirmishAIKeys; }

	const T_interfaceInfos& GetInterfaceInfos() const { return interfaceInfos; }
	const T_skirmishAIInfos& GetSkirmishAIInfos() const { return skirmishAIInfos; }

	/**
	 * Returns a set of files which contain duplicate Skirmish AI infos.
	 * This can be used for issueing warnings.
	 */
	const T_dupSkirm& GetDuplicateSkirmishAIInfos() const { return duplicateSkirmishAIInfos; }

	std::vector<SkirmishAIKey> FittingSkirmishAIKeys(const SkirmishAIKey& skirmishAIKey) const;

	/**
	 * A Skirmish AI (its library) is only really loaded when it is not yet
	 * loaded.
	 */
	const CSkirmishAILibrary* FetchSkirmishAILibrary(const SkirmishAIKey& skirmishAIKey);

	/**
	 * A Skirmish AI is only unloaded when ReleaseSkirmishAILibrary() is called
	 * as many times as GetSkirmishAILibrary() was.
	 * loading and unloading of the interfaces
	 * is handled internally/automatically.
	 */
	void ReleaseSkirmishAILibrary(const SkirmishAIKey& skirmishAIKey);

private:
	/** Unloads all currently loaded AIs and interfaces. */
	void ReleaseAll();

	/**
	 * Loads the interface if it is not yet loaded; increments load count.
	 */
	CAIInterfaceLibrary* FetchInterface(const AIInterfaceKey& interfaceKey);
	/**
	 * Unloads the interface if its load count reaches 0.
	 */
	void ReleaseInterface(const AIInterfaceKey& interfaceKey);
	/**
	 * Loads info about available AI Interfaces from Lua info-files.
	 *
	 * The files are searched in all data-dirs (see fs.GetDataDirectories())
	 * in the following sub-dirs:
	 * {AI_INTERFACES_DATA_DIR}/{*}/InterfaceInfo.lua
	 * {AI_INTERFACES_DATA_DIR}/{*}/{*}/InterfaceInfo.lua
	 *
	 * examples:
	 * AI/Interfaces/C/0.1/InterfaceInfo.lua
	 * AI/Interfaces/Java/0.1/InterfaceInfo.lua
	 */
	void GatherInterfaceLibInfo();
	/**
	 * Loads info about available Skirmish AIs from Lua info- and option-files.
	 * -> AI libraries can not corrupt the engines memory
	 *
	 * The files are searched in all data-dirs (see fs.GetDataDirectories())
	 * in the following sub-dirs:
	 * {SKIRMISH_AI_DATA_DIR}/{*}/AIInfo.lua
	 * {SKIRMISH_AI_DATA_DIR}/{*}/AIOptions.lua
	 * {SKIRMISH_AI_DATA_DIR}/{*}/{*}/AIInfo.lua
	 * {SKIRMISH_AI_DATA_DIR}/{*}/{*}/AIOptions.lua
	 *
	 * examples:
	 * AI/Skirmish/KAIK-0.13/AIInfo.lua
	 * AI/Skirmish/RAI/0.601/AIInfo.lua
	 * AI/Skirmish/RAI/0.601/AIOptions.lua
	 */
	void GatherSkirmishAILibInfo();

	void GatherSkirmishAILibInfoFromLuaFiles(T_dupSkirm& duplicateSkirmishAIInfoCheck);
	void GatherSkirmishAILibInfoFromInterfaceLib(T_dupSkirm& duplicateSkirmishAIInfoCheck);
	void StoreSkirmishAILibInfo(T_dupSkirm& duplicateSkirmishAIInfoCheck, CSkirmishAILibraryInfo& skirmishAIInfo, const std::string& sourceDesc);
	/// Filter out Skirmish AIs that are specified multiple times
	void FilterDuplicateSkirmishAILibInfo(const T_dupSkirm& duplicateSkirmishAIInfoCheck);

	/**
	 * Clears info about available AIs.
	 */
	void ClearAll();

private:
	/**
	 * Finds the best fitting interface.
	 * The short name has to fit perfectly, and the version of the interface
	 * has to be equal or higher then the requested one.
	 * If there are multiple fitting interfaces, the one with the next higher
	 * version is selected, eg:
	 * wanted: 0.2
	 * available: 0.1, 0.3, 0.5
	 * chosen: 0.3
	 *
	 * @see AILibraryManager::VersionCompare()
	 */
	static AIInterfaceKey FindFittingInterfaceKey(
		const std::string& shortName,
		const std::string& minVersion,
		const T_interfaceSpecs& specs
	);

	/**
	 * Compares two version strings.
	 * Splits the version strings at the '.' signs, and compares the parts.
	 * If the number of parts do not match, then the string with less parts
	 * is filled up with '.0' parts at its right, eg:
	 * version 1: 0.1.2   -> 0.1.2.0
	 * version 2: 0.1.2.3 -> 0.1.2.3
	 * The left most part has the highest significance.
	 * Comparison of the individual parts is done with std::string::compare(),
	 * which implies for example that letters > numbers.
	 * examples:
	 * ("2", "1") -> 1
	 * ("1", "1") -> 0
	 * ("1", "2") -> -1
	 * ("0.1.1", "0.1") -> 1
	 * ("1.a", "1.9") -> 1
	 * ("1.a", "1.A") -> 1
	 */
	static int VersionCompare(const std::string& version1, const std::string& version2);

private:
	std::map<const AIInterfaceKey, std::unique_ptr<CAIInterfaceLibrary> > loadedAIInterfaceLibs;

	T_interfaceSpecs interfaceKeys;
	T_skirmishAIKeys skirmishAIKeys;

	T_interfaceInfos interfaceInfos;
	T_skirmishAIInfos skirmishAIInfos;

	T_dupInt duplicateInterfaceInfos;
	T_dupSkirm duplicateSkirmishAIInfos;

	bool initialized = false;
};

#define aiLibManager AILibraryManager::GetInstance(true)
#endif // AI_LIBRARY_MANAGER_H