1 // -------------------------------------------------------------------------
2 // AAI
3 //
4 // A skirmish AI for the Spring engine.
5 // Copyright Alexander Seizinger
6 //
7 // Released under GPL license: see LICENSE.html for more information.
8 // -------------------------------------------------------------------------
9 
10 #ifndef AAI_BUILDTABLE_H
11 #define AAI_BUILDTABLE_H
12 
13 class AAI;
14 
15 namespace springLegacyAI {
16 	struct UnitDef;
17 }
18 using namespace springLegacyAI;
19 
20 
21 #include "aidef.h"
22 #include <assert.h>
23 #include <list>
24 #include <vector>
25 #include <string>
26 
27 using namespace std;
28 
29 struct UnitTypeDynamic
30 {
31 	int under_construction;	// how many units of that type are under construction
32 	int requested;			// how many units of that type have been requested
33 	int active;				// how many units of that type are currently alive
34 	int constructorsAvailable;	// how many factories/builders available being able to build that unit
35 	int constructorsRequested;	// how many factories/builders requested being able to build that unit
36 };
37 
38 struct UnitTypeStatic
39 {
40 	int def_id;
41 	int side;				// 0 if side has not been set
42 	list<int> canBuildList;
43 	list<int> builtByList;
44 	vector<float> efficiency;		// 0 -> ground assault, 1 -> air assault, 2 -> hover assault
45 									// 3 -> sea assault, 4 -> submarine , 5 -> stat. defences
46 	float range;              // max weapon range (0 for unarmed units)
47 	float cost;
48 	float builder_cost;
49 	UnitCategory category;
50 
51 	unsigned int unit_type;
52 	unsigned int movement_type;
53 };
54 
55 
56 class AAIBuildTable
57 {
58 public:
59 	AAIBuildTable(AAI* ai);
60 	~AAIBuildTable(void);
61 
62 	// call before you want to use the buildtable
63 	// loads everything from a cache file or creates a new one
64 	void Init();
65 
66 	void SaveBuildTable(int game_period, MapType map_type);
67 	// cache for combat eff (needs side, thus initialized later)
68 	void InitCombatEffCache(int side);
69 
70 	// returns true, if a builder can build a certain unit (use UnitDef.id)
71 	bool CanBuildUnit(int id_builder, int id_unit);
72 
73 	// returns side of a certian unittype (use UnitDef->id)
74 	int GetSideByID(int unit_id);
75 
76 	// return unit type (for groups)
77 	UnitType GetUnitType(int def_id);
78 
79 	// ******************************************************************************************************
80 	// the following functions are used to determine units that suit a certain purpose
81 	// if water == true, only water based units/buildings will be returned
82 	// randomness == 1 means no randomness at all; never set randomnes to zero -> crash
83 	// ******************************************************************************************************
84 	// returns power plant
85 	int GetPowerPlant(int side, float cost, float urgency, float max_power, float current_energy, bool water, bool geo, bool canBuild);
86 
87 	// returns a extractor from the list based on certain factors
88 	int GetMex(int side, float cost, float effiency, bool armed, bool water, bool canBuild);
89 
90 	// returns mex with the biggest yardmap
91 	int GetBiggestMex();
92 
93 	// return defence buildings to counter a certain category
94 	int GetDefenceBuilding(int side, double efficiency, double combat_power, double cost, double ground_eff, double air_eff, double hover_eff, double sea_eff, double submarine_eff, double urgency, double range, int randomness, bool water, bool canBuild);
95 
96 	// returns a cheap defence building (= avg_cost taken
97 	int GetCheapDefenceBuilding(int side, double efficiency, double combat_power, double cost, double urgency, double ground_eff, double air_eff, double hover_eff, double sea_eff, double submarine_eff, bool water);
98 
99 	// returns a metal maker
100 	int GetMetalMaker(int side, float cost, float efficiency, float metal, float urgency, bool water, bool canBuild);
101 
102 	// returns a storage
103 	int GetStorage(int side, float cost, float metal, float energy, float urgency, bool water, bool canBuild);
104 
105 	// return repair pad
106 	int GetAirBase(int side, float cost, bool water, bool canBuild);
107 
108 	// returns a ground unit according to the following criteria
109 	int GetGroundAssault(int side, float power, float gr_eff, float air_eff, float hover_eff, float sea_eff, float stat_eff, float efficiency, float speed, float range, float cost, int randomness, bool canBuild);
110 
111 	int GetHoverAssault(int side, float power, float gr_eff, float air_eff, float hover_eff, float sea_eff, float stat_eff, float efficiency, float speed, float range, float cost, int randomness, bool canBuild);
112 
113 	// returns an air unit according to the following criteria
114 	int GetAirAssault(int side, float power, float gr_eff, float air_eff, float hover_eff, float sea_eff, float stat_eff, float efficiency, float speed, float range, float cost, int randomness, bool canBuild);
115 
116 	int GetSeaAssault(int side, float power, float gr_eff, float air_eff, float hover_eff, float sea_eff, float submarine_eff, float stat_eff, float efficiency, float speed, float range, float cost, int randomness, bool canBuild);
117 
118 	int GetSubmarineAssault(int side, float power, float sea_eff, float submarine_eff, float stat_eff, float efficiency, float speed, float range, float cost, int randomness, bool canBuild);
119 
120 	// returns a random unit from the list
121 	int GetRandomUnit(list<int> unit_list);
122 
123 	// compares two units with respect to their combat power
124 	int DetermineBetterUnit(int unit1, int unit2, float ground_eff, float air_eff, float hover_eff, float sea_eff, float submarine_eff, float speed, float range, float cost);
125 
126 	int GetRandomDefence(int side, UnitCategory category);
127 
128 	int GetStationaryArty(int side, float cost, float range, float efficiency, bool water, bool canBuild);
129 
130 	// returns a scout
131 	int GetScout(int side, float los, float cost, unsigned int allowed_movement_types, int randomness, bool cloakable, bool canBuild);
132 
133 	int GetRadar(int side, float cost, float range, bool water, bool canBuild);
134 
135 	int GetJammer(int side, float cost, float range, bool water, bool canBuild);
136 
137 	// checks which factory is needed for a specific unit and orders it to be built
138 	void BuildFactoryFor(int unit_def_id);
139 
140 	// tries to build another builder for a certain building
141 	void BuildBuilderFor(int building_def_id);
142 
143 	// tries to build an assistant for the specified kind of unit
144 	void AddAssistant(unsigned int allowed_movement_types, bool canBuild);
145 
146 	// returns the allowed movement types for an assisters to assist constrcution of a specified building
147 	unsigned int GetAllowedMovementTypesForAssister(int building);
148 
149 	float GetFactoryRating(int def_id);
150 	float GetBuilderRating(int def_id);
151 
152 	// updates unit table
153 	void UpdateTable(const UnitDef* def_killer, int killer, const UnitDef *def_killed, int killed);
154 
155 	// updates max and average eff. values of the different categories
156 	void UpdateMinMaxAvgEfficiency();
157 
158 	// returns max range of all weapons
159 	float GetMaxRange(int unit_id);
160 
161 	// returns max damage of all weapons
162 	float GetMaxDamage(int unit_id);
163 
164 	// returns true, if unit is arty
165 	bool IsArty(int id);
166 
167 	// returns true, if unit is a scout
168 	bool IsScout(int id);
169 
170 	// returns true if the unit is marked as attacker (so that it won't be classed as something else even if it can build etc.)
171 	bool IsAttacker(int id);
172 
173 	bool IsMissileLauncher(int def_id);
174 
175 	bool IsDeflectionShieldEmitter(int def_id);
176 
177 	// returns false if unit is a member of the dont_build list
178 	bool AllowedToBuild(int id);
179 
180 	//sadly can't detect metal makers anymore, read them from config
181 	bool IsMetalMaker(int id);
182 
183 	// returns true, if unit is a transporter
184 	bool IsTransporter(int id);
185 
186 	// return a units eff. against a certain category
187 	float GetEfficiencyAgainst(int unit_def_id, UnitCategory category);
188 
189 	// returns true if unit is starting unit
190 	bool IsStartingUnit(int def_id);
191 
192 	bool IsCommander(int def_id);
193 
194 	bool IsBuilder(int def_id);
195 	bool IsFactory(int def_id);
196 
197 	bool IsGround(int def_id);
198 	bool IsAir(int def_id);
199 	bool IsHover(int def_id);
200 	bool IsSea(int def_id);
201 	bool IsStatic(int def_id);
202 
203 	bool CanMoveLand(int def_id);
204 	bool CanMoveWater(int def_id);
205 
206 	bool CanPlacedLand(int def_id);
207 	bool CanPlacedWater(int def_id);
208 
209 	// returns id of assault category
210 	int GetIDOfAssaultCategory(UnitCategory category);
211 	UnitCategory GetAssaultCategoryOfID(int id);
212 
213 
214 	//
215 	// these data are shared by several instances of aai
216 	//
217 
218 	// number of assault categories
219 	static const int ass_categories = 5;
220 
221 	// number of assault cat + arty & stat defences
222 	static const int combat_categories = 6;
223 
224 	// path/name of the file in which AAI stores the build table
225 	static char buildtable_filename[500];
226 
227 	// cached values of average costs and buildtime
228 	static vector<vector<float>> avg_cost;
229 	static vector<vector<float>> avg_buildtime;
230 	static vector<vector<float>> avg_value;	// used for different things, range of weapons, radar range, mex efficiency
231 	static vector<vector<float>> max_cost;
232 	static vector<vector<float>> max_buildtime;
233 	static vector<vector<float>> max_value;
234 	static vector<vector<float>> min_cost;
235 	static vector<vector<float>> min_buildtime;
236 	static vector<vector<float>> min_value;
237 
238 	static vector<vector<float>> avg_speed;
239 	static vector<vector<float>> min_speed;
240 	static vector<vector<float>> max_speed;
241 	static vector<vector<float>> group_speed;
242 
243 	// combat categories that attacked AI in certain game period attacked_by_category_learned[map_type][period][cat]
244 	static vector< vector< vector<float> > > attacked_by_category_learned;
245 
246 	// combat categories that attacked AI in certain game period attacked_by_category_current[period][cat]
247 	static vector< vector<float> > attacked_by_category_current;
248 
249 	// units of the different categories
250 	static vector<vector<list<int>>> units_of_category;
251 
252 	// AAI unit defs (static things like id, side, etc.)
253 	static vector<UnitTypeStatic> units_static;
254 
255 	// storage for def. building selection
256 	static vector<vector<double> > def_power;
257 	static vector<double> max_pplant_eff;
258 
259 	// cached combat efficiencies
260 	static vector< vector< vector<float> > > avg_eff;
261 	static vector< vector< vector<float> > > max_eff;
262 	static vector< vector< vector<float> > > min_eff;
263 	static vector< vector< vector<float> > > total_eff;
264 
265 	// stores the combat eff. of units at the beginning of the game. due to learning these values will change during the game
266 	// however for some purposes its necessary to have constant values (e.g. adding and subtracting stationary defences to/from the defense map)
267 	static vector< vector<float> > fixed_eff;
268 
269 	//
270 	//	non static variales
271 	//
272 
273 	// number of sides
274 	int numOfSides;
275 
276 	// side names
277 	vector<string> sideNames;
278 
279 	// start units of each side (e.g. commander)
280 	vector<int> startUnits;
281 
282 
283 	vector<float> combat_eff;
284 
285 	// true if initialized correctly
286 	bool initialized;
287 
288 
289 	// AAI unit defs with aai-instance specific information (number of requested, active units, etc.)
290 	vector<UnitTypeDynamic> units_dynamic;
291 
292 	// for internal use
293 	const char* GetCategoryString(int def_id);
294 	const char* GetCategoryString2(UnitCategory category);
295 
296 	// all assault unit categories
297 	list<UnitCategory> assault_categories;
298 
GetUnitDef(int i)299 	const UnitDef& GetUnitDef(int i) { assert(IsValidUnitDefID(i));	return *unitList[i];}
IsValidUnitDefID(int i)300 	bool IsValidUnitDefID(int i) { return (i>=0) && (i<=unitList.size()); }
301 private:
302 	std::string GetBuildCacheFileName();
303 	// precaches speed/cost/buildtime/range stats
304 	void PrecacheStats();
305 
306 	// only precaches costs (called after possible cost multipliers have been assigned)
307 	void PrecacheCosts();
308 
309 	// returns side of a unit
310 	int GetSide(int unit);
311 
312 	// returns true, if unitid is in the list
313 	bool MemberOf(int unit_id, list<int> unit_list);
314 	// for internal use
315 	void CalcBuildTree(int unit);
316 	bool LoadBuildTable();
317 	float GetUnitRating(int unit, float ground_eff, float air_eff, float hover_eff, float sea_eff, float submarine_eff);
318 	void DebugPrint();
319 
320 	AAI * ai;
321 
322 //	FILE *file;
323 
324 	// all the unit defs, FIXME: this can't be made static as spring seems to free the memory returned by GetUnitDefList()
325 	std::vector<const UnitDef*> unitList;
326 };
327 
328 #endif
329 
330