1 // ==============================================================
2 //	This file is part of Glest (www.glest.org)
3 //
4 //	Copyright (C) 2001-2008 Martiño Figueroa
5 //
6 //	You can redistribute this code and/or modify it under
7 //	the terms of the GNU General Public License as published
8 //	by the Free Software Foundation; either version 2 of the
9 //	License, or (at your option) any later version
10 // ==============================================================
11 
12 #ifndef _GLEST_GAME_FACTION_H_
13 #define _GLEST_GAME_FACTION_H_
14 
15 #ifdef WIN32
16     #include <winsock2.h>
17     #include <winsock.h>
18 #endif
19 
20 #include <vector>
21 #include <map>
22 #include "upgrade.h"
23 #include "texture.h"
24 #include "resource.h"
25 #include "game_constants.h"
26 #include "command_type.h"
27 #include "base_thread.h"
28 #include <set>
29 #include "faction_type.h"
30 #include "leak_dumper.h"
31 
32 using std::map;
33 using std::vector;
34 using std::set;
35 
36 using Shared::Graphics::Texture2D;
37 using namespace Shared::PlatformCommon;
38 
39 namespace Glest{ namespace Game{
40 
41 class Unit;
42 class TechTree;
43 class FactionType;
44 class ProducibleType;
45 class RequirableType;
46 class CommandType;
47 class UnitType;
48 class Game;
49 class ScriptManager;
50 class World;
51 class Faction;
52 class GameSettings;
53 class SurfaceCell;
54 
55 class FowAlphaCellsLookupItem {
56 public:
57 
58 	std::map<Vec2i,float> surfPosAlphaList;
59 };
60 
61 class ExploredCellsLookupItem {
62 public:
63 
ExploredCellsLookupItem()64 	ExploredCellsLookupItem() {
65 		ExploredCellsLookupItemCacheTimerCountIndex = 0;
66 	}
67 	int ExploredCellsLookupItemCacheTimerCountIndex;
68 	std::vector<SurfaceCell *> exploredCellList;
69 	std::vector<SurfaceCell *> visibleCellList;
70 
71 	static time_t lastDebug;
72 };
73 
74 // =====================================================
75 // 	class Faction
76 //
77 ///	Each of the game players
78 // =====================================================
79 
80 struct CommandGroupUnitSorter {
81 	bool operator()(const Unit *l, const Unit *r);
82 	bool compare(const Unit *l, const Unit *r);
83 };
84 
85 struct CommandGroupUnitSorterId {
86 	Faction *faction;
87 	bool operator()(const int l, const int r);
88 };
89 
90 class FactionThread : public BaseThread, public SlaveThreadControllerInterface {
91 protected:
92 
93 	Faction *faction;
94 	Semaphore semTaskSignalled;
95 	Mutex *triggerIdMutex;
96 	std::pair<int,bool> frameIndex;
97 	MasterSlaveThreadController *masterController;
98 
99 	virtual void setQuitStatus(bool value);
100 	virtual void setTaskCompleted(int frameIndex);
101 	virtual bool canShutdown(bool deleteSelfIfShutdownDelayed=false);
102 
103 public:
104 	FactionThread(Faction *faction);
105 	virtual ~FactionThread();
106     virtual void execute();
107 
setMasterController(MasterSlaveThreadController * master)108 	virtual void setMasterController(MasterSlaveThreadController *master) { masterController = master; }
signalSlave(void * userdata)109 	virtual void signalSlave(void *userdata) { signalPathfinder(*((int *)(userdata))); }
110 
111     void signalPathfinder(int frameIndex);
112     bool isSignalPathfinderCompleted(int frameIndex);
113 };
114 
115 class SwitchTeamVote {
116 public:
117 
118 	int factionIndex;
119 	int oldTeam;
120 	int newTeam;
121 	bool voted;
122 	bool allowSwitchTeam;
123 };
124 
125 class Faction {
126 private:
127     typedef vector<Resource> Resources;
128     typedef vector<Resource> Store;
129 	typedef vector<Faction*> Allies;
130 	typedef vector<Unit*> Units;
131 	typedef map<int, Unit*> UnitMap;
132 
133 private:
134 	UpgradeManager upgradeManager;
135 
136     Resources resources;
137     Store store;
138 	Allies allies;
139 
140 	Mutex *unitsMutex;
141 	Units units;
142 	UnitMap unitMap;
143 	World *world;
144 	ScriptManager *scriptManager;
145 
146 	FactionPersonalityType overridePersonalityType;
147     ControlType control;
148 
149 	Texture2D *texture;
150 	FactionType *factionType;
151 
152 	int index;
153 	int teamIndex;
154 	int startLocationIndex;
155 
156 	bool thisFaction;
157 
158 	bool factionDisconnectHandled;
159 
160 	bool cachingDisabled;
161 	std::map<Vec2i,int> cacheResourceTargetList;
162 	std::map<Vec2i,bool> cachedCloseResourceTargetLookupList;
163 
164 	RandomGen random;
165 	FactionThread *workerThread;
166 
167 	std::map<int,SwitchTeamVote> switchTeamVotes;
168 	int currentSwitchTeamVoteFactionIndex;
169 
170 	bool allowSharedTeamUnits;
171 	set<int> livingUnits;
172 	set<Unit*> livingUnitsp;
173 
174 	std::map<int,int> unitsMovingList;
175 	std::map<int,int> unitsPathfindingList;
176 
177 	std::set<const UnitType*> lockedUnits;
178 
179 	TechTree *techTree;
180 	const XmlNode *loadWorldNode;
181 
182 	std::vector<string> worldSynchThreadedLogList;
183 
184 	std::map<int,string> crcWorldFrameDetails;
185 
186 	std::map<int,const Unit *> aliveUnitListCache;
187 	std::map<int,const Unit *> mobileUnitListCache;
188 	std::map<int,const Unit *> beingBuiltUnitListCache;
189 
190 	std::map<std::string, bool> resourceTypeCostCache;
191 
192 public:
193 	Faction();
194 	~Faction();
195 
Faction(const Faction & obj)196 	Faction(const Faction& obj) {
197 		init();
198 		throw megaglest_runtime_error("class Faction is NOT safe to copy!");
199 	}
200 	Faction & operator=(const Faction& obj) {
201 		init();
202 		throw megaglest_runtime_error("class Faction is NOT safe to assign!");
203 	}
204 
205 	void notifyUnitAliveStatusChange(const Unit *unit);
206 	void notifyUnitTypeChange(const Unit *unit, const UnitType *newType);
207 	void notifyUnitSkillTypeChange(const Unit *unit, const SkillType *newType);
208 	bool hasAliveUnits(bool filterMobileUnits, bool filterBuiltUnits) const;
209 
addWorldSynchThreadedLogList(const string & data)210 	inline void addWorldSynchThreadedLogList(const string &data) {
211 		if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true) {
212 			worldSynchThreadedLogList.push_back(data);
213 		}
214 	}
clearWorldSynchThreadedLogList()215 	inline void clearWorldSynchThreadedLogList() {
216 		if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true) {
217 			worldSynchThreadedLogList.clear();
218 		}
219 	}
dumpWorldSynchThreadedLogList()220 	inline void dumpWorldSynchThreadedLogList() {
221 		if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true) {
222 			if(worldSynchThreadedLogList.empty() == false) {
223 				for(unsigned int index = 0; index < worldSynchThreadedLogList.size(); ++index) {
224 					SystemFlags::OutputDebug(SystemFlags::debugWorldSynch,worldSynchThreadedLogList[index].c_str());
225 				}
226 				worldSynchThreadedLogList.clear();
227 			}
228 		}
229 	}
230 
addLivingUnits(int id)231 	inline void addLivingUnits(int id) { livingUnits.insert(id); }
addLivingUnitsp(Unit * unit)232 	inline void addLivingUnitsp(Unit *unit) { livingUnitsp.insert(unit); }
233 
isUnitInLivingUnitsp(Unit * unit)234 	inline bool isUnitInLivingUnitsp(Unit *unit) { return (livingUnitsp.find(unit) != livingUnitsp.end()); }
deleteLivingUnits(int id)235 	inline void deleteLivingUnits(int id) { livingUnits.erase(id); }
deleteLivingUnitsp(Unit * unit)236 	inline void deleteLivingUnitsp(Unit *unit) { livingUnitsp.erase(unit); }
237 
238 	//std::map<int,int> unitsMovingList;
239 	void addUnitToMovingList(int unitId);
240 	void removeUnitFromMovingList(int unitId);
241 	int getUnitMovingListCount();
242 
243 	void addUnitToPathfindingList(int unitId);
244 	void removeUnitFromPathfindingList(int unitId);
245 	int getUnitPathfindingListCount();
246 	void clearUnitsPathfinding();
247 	bool canUnitsPathfind();
248 
249 	void setLockedUnitForFaction(const UnitType *ut, bool lock);
isUnitLocked(const UnitType * ut)250 	bool isUnitLocked(const UnitType *ut) const { return lockedUnits.find(ut)!=lockedUnits.end(); }
251 
252     void init(
253 		FactionType *factionType, ControlType control, TechTree *techTree, Game *game,
254 		int factionIndex, int teamIndex, int startLocationIndex, bool thisFaction,
255 		bool giveResources, const XmlNode *loadWorldNode=NULL);
256 	void end();
257 
getFactionDisconnectHandled()258 	inline bool getFactionDisconnectHandled() const { return factionDisconnectHandled;}
setFactionDisconnectHandled(bool value)259 	void setFactionDisconnectHandled(bool value) { factionDisconnectHandled=value;}
260 
261     //get
262 	const Resource *getResource(const ResourceType *rt,bool localFactionOnly=false) const;
getResource(int i)263 	inline const Resource *getResource(int i) const			{return &resources[i];}
264 	int getStoreAmount(const ResourceType *rt,bool localFactionOnly=false) const;
getType()265 	inline const FactionType *getType() const					{return factionType;}
getIndex()266 	inline int getIndex() const								{return index;}
267 
getTeam()268 	inline int getTeam() const									{return teamIndex;}
setTeam(int team)269 	void setTeam(int team) 								{teamIndex=team;}
270 
getTechTree()271 	inline TechTree * getTechTree() const						{ return techTree; }
272 	const SwitchTeamVote * getFirstSwitchTeamVote() const;
273 	SwitchTeamVote * getSwitchTeamVote(int factionIndex);
274 	void setSwitchTeamVote(SwitchTeamVote &vote);
getCurrentSwitchTeamVoteFactionIndex()275 	inline int getCurrentSwitchTeamVoteFactionIndex() const { return currentSwitchTeamVoteFactionIndex; }
setCurrentSwitchTeamVoteFactionIndex(int index)276 	void setCurrentSwitchTeamVoteFactionIndex(int index) { currentSwitchTeamVoteFactionIndex = index; }
277 
278 	bool getCpuControl(bool enableServerControlledAI, bool isNetworkGame, NetworkRole role) const;
279 	bool getCpuControl() const;
getCpuEasyControl()280 	inline bool getCpuEasyControl() const						{return control==ctCpuEasy;}
getCpuUltraControl()281 	inline bool getCpuUltraControl() const						{return control==ctCpuUltra;}
getCpuMegaControl()282 	inline bool getCpuMegaControl() const						{return control==ctCpuMega;}
getControlType()283 	inline ControlType getControlType() const					{return control;}
284 
285 	FactionPersonalityType getPersonalityType() const;
setPersonalityType(FactionPersonalityType pType)286 	void setPersonalityType(FactionPersonalityType pType) { overridePersonalityType=pType; }
287 	int getAIBehaviorStaticOverideValue(AIBehaviorStaticValueCategory type) const;
288 
getUnit(int i)289 	inline Unit *getUnit(int i) const {
290 		Unit *result = units[i];
291 		return result;
292 	}
getUnitCount()293 	inline int getUnitCount() const {
294 		int result = (int)units.size();
295 		return result;
296 	}
getUnitMutex()297 	inline Mutex * getUnitMutex() {return unitsMutex;}
298 
getUpgradeManager()299 	inline const UpgradeManager *getUpgradeManager() const		{return &upgradeManager;}
getTexture()300 	inline const Texture2D *getTexture() const					{return texture;}
getStartLocationIndex()301 	inline int getStartLocationIndex() const					{return startLocationIndex;}
getThisFaction()302 	inline bool getThisFaction() const							{return thisFaction;}
303 
304 	//upgrades
305 	void startUpgrade(const UpgradeType *ut);
306 	void cancelUpgrade(const UpgradeType *ut);
307 	void finishUpgrade(const UpgradeType *ut);
308 
309 	//cost application
310 	bool applyCosts(const ProducibleType *p,const CommandType *ct);
311 	void applyDiscount(const ProducibleType *p, int discount);
312 	void applyStaticCosts(const ProducibleType *p,const CommandType *ct);
313 	void applyStaticProduction(const ProducibleType *p,const CommandType *ct);
314 	void deApplyCosts(const ProducibleType *p,const CommandType *ct);
315 	void deApplyStaticCosts(const ProducibleType *p,const CommandType *ct);
316 	void deApplyStaticConsumption(const ProducibleType *p,const CommandType *ct);
317 	void applyCostsOnInterval(const ResourceType *rtApply);
318 	bool checkCosts(const ProducibleType *pt,const CommandType *ct);
319 
320 	//reqs
321 	bool reqsOk(const RequirableType *rt) const;
322 	bool reqsOk(const CommandType *ct) const;
323     int getCountForMaxUnitCount(const UnitType *unitType) const;
324 
325 	//diplomacy
326 	bool isAlly(const Faction *faction);
327 
328     //other
329 	Unit *findUnit(int id) const;
330 	void addUnit(Unit *unit);
331 	void removeUnit(Unit *unit);
332 	void addStore(const UnitType *unitType);
333 	void removeStore(const UnitType *unitType);
334 
335 	//resources
336 	void incResourceAmount(const ResourceType *rt, int amount);
337 	void setResourceBalance(const ResourceType *rt, int balance);
338 
setControlType(ControlType value)339 	void setControlType(ControlType value) { control = value; }
340 
341 	bool isResourceTargetInCache(const Vec2i &pos,bool incrementUseCounter=false);
342 	void addResourceTargetToCache(const Vec2i &pos,bool incrementUseCounter=true);
343 	void removeResourceTargetFromCache(const Vec2i &pos);
344 	void addCloseResourceTargetToCache(const Vec2i &pos);
345 	Vec2i getClosestResourceTypeTargetFromCache(Unit *unit, const ResourceType *type,int frameIndex);
346 	Vec2i getClosestResourceTypeTargetFromCache(const Vec2i &pos, const ResourceType *type);
347 	void cleanupResourceTypeTargetCache(std::vector<Vec2i> *deleteListPtr,int frameIndex);
getCacheResourceTargetListSize()348 	inline int getCacheResourceTargetListSize() const { return (int)cacheResourceTargetList.size(); }
349 
350 	Unit * findClosestUnitWithSkillClass(const Vec2i &pos,const CommandClass &cmdClass,
351 										const std::vector<SkillClass> &skillClassList,
352 										const UnitType *unitType);
353 
354 	void deletePixels();
355 
getWorld()356 	inline World * getWorld() { return world; }
357 	int getFrameCount();
358 
359 	void signalWorkerThread(int frameIndex);
360 	bool isWorkerThreadSignalCompleted(int frameIndex);
getWorkerThread()361 	FactionThread *getWorkerThread() { return workerThread; }
362 
363 	void limitResourcesToStore();
364 
365 	void sortUnitsByCommandGroups();
366 
367 	bool canCreateUnit(const UnitType *ut, bool checkBuild, bool checkProduce, bool checkMorph) const;
368 
369 	string getCacheStats();
370 	uint64 getCacheKBytes(uint64 *cache1Size, uint64 *cache2Size, uint64 *cache3Size, uint64 *cache4Size, uint64 *cache5Size);
371 
372 	std::string toString(bool crcMode=false) const;
373 
374 	void saveGame(XmlNode *rootNode);
375 	void loadGame(const XmlNode *rootNode, int factionIndex,GameSettings *settings,World *world);
376 
377 	void clearCaches();
378 
379 	Checksum getCRC();
380 	void addCRC_DetailsForWorldFrame(int worldFrameCount,bool isNetworkServer);
381 	string getCRC_DetailsForWorldFrame(int worldFrameCount);
382 	std::pair<int,string> getCRC_DetailsForWorldFrameIndex(int worldFrameIndex) const;
383 	string getCRC_DetailsForWorldFrames() const;
384 	uint64 getCRC_DetailsForWorldFrameCount() const;
385 
386 	void updateUnitTypeWithResourceCostCache(const ResourceType *rt);
387 	bool hasUnitTypeWithResourceCostInCache(const ResourceType *rt) const;
388 
389 private:
390 	void init();
391 	void resetResourceAmount(const ResourceType *rt);
392 	bool hasUnitTypeWithResouceCost(const ResourceType *rt);
393 };
394 
395 }}//end namespace
396 
397 #endif
398