1 #pragma once
2 
3 /** Handles an individual sector.
4 */
5 
6 namespace Gigalomania {
7 	class Image;
8 	class PanelPage;
9 	class Button;
10 }
11 
12 using namespace Gigalomania;
13 
14 class Feature;
15 class Sector;
16 class PlayingGameState;
17 class Invention;
18 
19 using std::vector;
20 using std::string;
21 using std::stringstream;
22 
23 #include "TinyXML/tinyxml.h"
24 
25 #include "common.h"
26 
27 const int element_multiplier_c = 2;
28 const int n_gatherable_rate_c = 500;
29 const int max_grow_population_c = 500;
30 const int growth_rate_c = 200; // higher is slower; beware of having a growth rate too fast, as it means a killer strategy is just to wait around letting the population grow first
31 const int mine_rate_c = 30; // higher is slower
32 const int combat_rate_c = 50; // higher is slower combat
33 const int bombard_rate_c = 5; // higher is slower damage
34 const int max_gatherables_stored_c = 22;
35 
36 bool isAirUnit(int epoch);
37 bool defenceNeedsMan(int epoch);
38 
39 class Particle {
40 	float xpos, ypos; // floats to allow for movement
41 	int birth_time;
42 public:
43 	Particle();
44 
getX()45 	float getX() const {
46 		return this->xpos;
47 	}
getY()48 	float getY() const {
49 		return this->ypos;
50 	}
setPos(float xpos,float ypos)51 	void setPos(float xpos, float ypos) {
52 		this->xpos = xpos;
53 		this->ypos = ypos;
54 	}
getBirthTime()55 	int getBirthTime() const {
56 		return this->birth_time;
57 	}
58 };
59 
60 class ParticleSystem {
61 protected:
62 	vector<Particle> particles;
63 	const Image *image;
64 	float size;
65 
66 public:
ParticleSystem(const Image * image)67 	ParticleSystem(const Image *image) : image(image), size(1.0f) {
68 	}
~ParticleSystem()69 	virtual ~ParticleSystem() {
70 	}
71 
setSize(float size)72 	void setSize(float size) {
73 		this->size = size;
74 	}
75 
76 	void draw(int xpos, int ypos) const;
77 	virtual void update()=0;
78 };
79 
80 class SmokeParticleSystem : public ParticleSystem {
81 	float birth_rate;
82 	int life_exp;
83 	int last_emit_time;
84 	float move_x, move_y;
85 public:
86 	SmokeParticleSystem(const Image *image);
~SmokeParticleSystem()87 	virtual ~SmokeParticleSystem() {
88 	}
89 
90 	void setBirthRate(float birth_rate);
setMove(float move_x,float move_y)91 	void setMove(float move_x, float move_y) {
92 		this->move_x = move_x;
93 		this->move_y = move_y;
94 	}
setLifeExp(int life_exp)95 	void setLifeExp(int life_exp) {
96 		this->life_exp = life_exp;
97 	}
98 
99 	virtual void update();
100 };
101 
102 class Army {
103 	int soldiers[n_epochs_c+1]; // unarmed men are soldiers[n_epochs_c]; // saved
104 	int player; // no need to save, saved by caller
105 	Sector *sector; // no need to save
106 	PlayingGameState *gamestate;
107 
108 public:
109 	Army(PlayingGameState *gamestate, Sector *sector, int player);
~Army()110 	~Army() {
111 	}
112 
getPlayer()113 	int getPlayer() const {
114 		return this->player;
115 	}
getSector()116 	Sector *getSector() const {
117 		return this->sector;
118 	}
119 	int getTotal() const;
120 	int getTotalMen() const;
121 	bool any(bool include_unarmed) const;
122 	int getStrength() const;
123 	int getBombardStrength() const;
getSoldiers(int index)124 	int getSoldiers(int index) const {
125 		return this->soldiers[index];
126 	}
127 	void add(int i,int n);
128 	void add(Army *army);
129 	void remove(int i,int n);
130 	void kill(int index);
empty()131 	void empty() {
132 		for(int i=0;i<n_epochs_c+1;i++)
133 			soldiers[i] = 0;
134 	}
135 	bool canLeaveSafely() const;
136 	void retreat(bool only_air);
137 
138 	int getIndividualStrength(int i) const;
139 	static int getIndividualStrength(int player, int i);
140 	static int getIndividualBombardStrength(int i);
141 
142 	void saveState(stringstream &stream) const;
143 	void loadStateParseXMLNode(const TiXmlNode *parent);
144 };
145 
146 class Element {
147 	string name;
148 public:
149 	enum Type {
150 		GATHERABLE = 0,
151 		OPENPITMINE = 1,
152 		DEEPMINE = 2
153 	};
154 private:
155 	Id id;
156 	Type type;
157 
158 public:
159 	Element(const char *name,Id id,Type type);
160 	~Element();
161 
162 	Image *getImage() const;
getName()163 	const char *getName() const {
164 		return this->name.c_str();
165 	}
getType()166 	Type getType() const {
167 		return this->type;
168 	}
169 };
170 
171 class Design {
172 	Invention *invention;
173 	bool ergonomically_terrific;
174 	int cost[N_ID];
175 	int save_id;
176 
177 public:
178 	Design(Invention *invention,bool ergonomically_terrific);
179 
setCost(Id id,float cost)180 	void setCost(Id id, float cost) {
181 		this->cost[(int)id] = (int)(cost * element_multiplier_c);
182 	}
getCost(Id id)183 	int getCost(Id id) {
184 		return this->cost[(int)id];
185 	}
isErgonomicallyTerrific()186 	bool isErgonomicallyTerrific() const {
187 		return this->ergonomically_terrific;
188 	}
getInvention()189 	Invention *getInvention() const {
190 		return this->invention;
191 	}
setSaveId(int save_id)192 	void setSaveId(int save_id) {
193 		this->save_id = save_id;
194 	}
getSaveId()195 	int getSaveId() const {
196 		return this->save_id;
197 	}
198 
199 	static bool setupDesigns();
200 };
201 
202 class Invention {
203 protected:
204 	string name;
205 public:
206 	enum Type {
207 		UNKNOWN_TYPE = -1,
208 		SHIELD = 0,
209 		DEFENCE = 1,
210 		WEAPON = 2,
211 		N_TYPES = 3
212 	};
213 
214 protected:
215 	Type type;
216 	int epoch;
217 	vector<Design *> designs;
218 
219 public:
220 	Invention(const char *name,Type type,int epoch);
221 	~Invention();
222 
223 	//int getRelativeEpoch();
224 	Image *getImage() const;
getName()225 	const char *getName() const {
226 		return this->name.c_str();
227 	}
getType()228 	Type getType() const {
229 		return this->type;
230 	}
getEpoch()231 	int getEpoch() const {
232 		return this->epoch;
233 	}
234 	void addDesign(Design *design);
getNDesigns()235 	size_t getNDesigns() const {
236 		return this->designs.size();
237 	}
getDesign(size_t i)238 	Design *getDesign(size_t i) const {
239 		return this->designs.at(i);
240 	}
241 	Design *findDesign(int save_id) const;
242 
243 	static Invention *getInvention(Invention::Type type,int epoch);
244 };
245 
246 class Weapon : public Invention {
247 	int n_men;
248 public:
Weapon(const char * name,int epoch,int n_men)249 	Weapon(const char *name,int epoch,int n_men) : Invention(name,WEAPON,epoch) {
250 		this->n_men = n_men;
251 	}
~Weapon()252 	~Weapon() {
253 	}
getNMen()254 	int getNMen() const {
255 		return this->n_men;
256 	}
257 };
258 
259 const int max_building_turrets_c = 4;
260 
261 class Building {
262 private:
263 	Type type; // saved
264 	Sector *sector;
265 	int health; // saved
266 	int max_health;
267 	int pos_x, pos_y;
268 	int n_turrets;
269 	int turret_man[max_building_turrets_c]; // saved
270 	int turret_man_frame[max_building_turrets_c];
271 	PanelPage *building_button;
272 	PanelPage *turret_buttons[max_building_turrets_c];
273 	PlayingGameState *gamestate;
274 
275 public:
276 	Building(PlayingGameState *gamestate, Sector *sector, Type type);
277 	~Building();
278 
getType()279 	Type getType() const {
280 		return this->type;
281 	}
getX()282 	int getX() const {
283 		return this->pos_x;
284 	}
getY()285 	int getY() const {
286 		return this->pos_y;
287 	}
getHealth()288 	int getHealth() const {
289 		return this->health;
290 	}
getMaxHealth()291 	int getMaxHealth() const {
292 		return this->max_health;
293 	}
addHealth(int v)294 	void addHealth(int v) {
295 		this->health += v;
296 		if( this->health > this->max_health )
297 			this->health = this->max_health;
298 	}
299 	Image **getImages();
300 	void rotateDefenders();
getNDefenders()301 	int getNDefenders() const {
302 		int n = 0;
303 		for(int i=0;i<n_turrets;i++) {
304 			if( turret_man[i] != -1 )
305 				n++;
306 		}
307 		return n;
308 	}
getNDefenders(int type)309 	int getNDefenders(int type) const {
310 		int n = 0;
311 		for(int i=0;i<n_turrets;i++) {
312 			if( turret_man[i] == type )
313 				n++;
314 		}
315 		return n;
316 	}
317 	int getDefenderStrength() const;
318 	void killIthDefender(int i);
319 	void killDefender(int index);
getBuildingButton()320 	PanelPage *getBuildingButton() const {
321 		return this->building_button;
322 	}
getNTurrets()323 	int getNTurrets() const {
324 		return this->n_turrets;
325 	}
326 	int getTurretMan(int turret) const;
327 	int getTurretManFrame(int turret) const;
328 	PanelPage *getTurretButton(int turret) const;
329 	void clearTurretMan(int turret);
330 	void setTurretMan(int turret, int epoch);
331 
332 	void saveState(stringstream &stream) const;
333 	void loadStateParseXMLNode(const TiXmlNode *parent);
334 };
335 
336 class Sector {
337 	vector<Feature *> features;
338 	int xpos, ypos; // saved
339 	int epoch; // saved
340 	int player; // saved
341 	bool is_shutdown; // saved
342 	//int shutdown_player;
343 
344 	bool nuked; // saved
345 	int nuke_by_player; // saved
346 	int nuke_time; // saved
347 	bool nuke_defence_animation; // saved
348 	int nuke_defence_time; // saved
349 	int nuke_defence_x; // saved
350 	int nuke_defence_y; // saved
351 
352 	int population; // saved
353 	int n_designers; // saved
354 	int n_miners[N_ID]; // saved
355 	int n_builders[N_BUILDINGS]; // saved
356 	int n_workers; // saved
357 	int n_famount; // saved
358 	Design *current_design; // saved
359 	Design *current_manufacture; // saved
360 	int researched; // saved
361 	int researched_lasttime; // saved
362 	int manufactured; // saved
363 	int manufactured_lasttime; // saved
364 	int growth_lasttime; // saved
365 	int mined_lasttime; // saved
366 	int built_towers[n_players_c]; // for neutral sectors // saved
367 	int built[N_BUILDINGS]; // NB: built[BUILDING_TOWER] should never be used // saved
368 	int built_lasttime; // saved
369 
370 	int elements[N_ID]; // elements remaining // saved
371 	int elementstocks[N_ID]; // elements mined // saved
372 	int partial_elementstocks[N_ID]; // saved
373 
374 	void initTowerStuff();
375 	void consumeStocks(Design *design);
376 
377 	int getInventionCost() const;
378 	int getManufactureCost() const;
379 	bool inventions_known[3][n_epochs_c]; // not saved, inferred fom designs
380 	vector<Design *> designs; // saved
381 
382 	static int getBuildingCost(Type type, int building_player);
383 	void destroyBuilding(Type building_type,int client_player);
384 	void destroyBuilding(Type building_type,bool silent,int client_player);
385 	void updateWorkers();
386 
387 	float getDefenceStrength() const;
388 	void doCombat(int client_player);
389 	void doPlayer(int client_player);
390 
391 	Design *loadStateParseXMLDesign(const TiXmlAttribute *attribute);
392 
393 	Building *buildings[N_BUILDINGS]; // saved
394 	Army *assembled_army;
395 	Army *stored_army; // saved
396 	Army *armies[n_players_c]; // saved
397 	int stored_defenders[n_epochs_c]; // saved
398 	int stored_shields[4]; // saved
399 	SmokeParticleSystem *smokeParticleSystem;
400 	SmokeParticleSystem *jetParticleSystem;
401 	SmokeParticleSystem *nukeParticleSystem;
402 	SmokeParticleSystem *nukeDefenceParticleSystem;
403 
404 	PlayingGameState *gamestate;
405 public:
406 
407 	Sector(PlayingGameState *gamestate, int epoch, int xpos, int ypos, MapColour map_colour);
408 	~Sector();
409 
410 	void createTower(int player,int population);
411 	void destroyTower(bool nuked, int client_player);
412 	bool canShutdown() const;
413 	void shutdown(int client_player);
isShutdown()414 	bool isShutdown() const {
415 		return this->is_shutdown;
416 	}
417 	Building *getBuilding(Type type) const;
418 	int getNDefenders() const;
419 	int getNDefenders(int type) const;
420 	int getDefenderStrength() const;
421 	void killDefender(int index);
422 	bool canBuild(Type type) const;
423 	bool canMine(Id id) const;
424 	Design *canBuildDesign(Invention::Type type,int epoch) const;
425 	bool canBuildDesign(Design *design) const;
426 	bool canEverBuildDesign(Design *design) const;
427 	void autoTrashDesigns();
428 	bool tryMiningMore() const;
429 	bool usedUp() const;
430 	void cheat(int client_player); // for testing
431 	Design *knownDesign(Invention::Type type,int epoch) const;
432 	Design *bestDesign(Invention::Type type,int epoch) const;
433 	Design *canResearch(Invention::Type type,int epoch) const;
434 	int getNDesigns() const;
435 	//void consumeStocks(Design *design);
436 	bool assembleArmy(int epoch,int n);
437 	bool deployDefender(Building *building,int turret,int epoch);
438 	void returnDefender(Building *building,int turret);
439 	int getStoredDefenders(int epoch) const;
440 	bool useShield(Building *building,int shield);
441 	int getStoredShields(int shield) const;
442 	void update(int client_player);
443 
getNFeatures()444 	int getNFeatures() const {
445 		return this->features.size();
446 	}
getFeature(int i)447 	const Feature *getFeature(int i) const {
448 		return this->features.at(i);
449 	}
getSmokeParticleSystem()450 	const ParticleSystem *getSmokeParticleSystem() const {
451 		return this->smokeParticleSystem;
452 	}
getSmokeParticleSystem()453 	ParticleSystem *getSmokeParticleSystem() {
454 		return this->smokeParticleSystem;
455 	}
getJetParticleSystem()456 	const ParticleSystem *getJetParticleSystem() const {
457 		return this->jetParticleSystem;
458 	}
getJetParticleSystem()459 	ParticleSystem *getJetParticleSystem() {
460 		return this->jetParticleSystem;
461 	}
getNukeParticleSystem()462 	const ParticleSystem *getNukeParticleSystem() const {
463 		return this->nukeParticleSystem;
464 	}
getNukeParticleSystem()465 	ParticleSystem *getNukeParticleSystem() {
466 		return this->nukeParticleSystem;
467 	}
getNukeDefenceParticleSystem()468 	const ParticleSystem *getNukeDefenceParticleSystem() const {
469 		return this->nukeDefenceParticleSystem;
470 	}
getNukeDefenceParticleSystem()471 	ParticleSystem *getNukeDefenceParticleSystem() {
472 		return this->nukeDefenceParticleSystem;
473 	}
474 	void setEpoch(int epoch);
475 	int getEpoch() const;
476 	int getBuildingEpoch() const;
getXPos()477 	int getXPos() const {
478 		return xpos;
479 	}
getYPos()480 	int getYPos() const {
481 		return ypos;
482 	}
483 
484 	int getPlayer() const;
485 	int getActivePlayer() const;
486 
487 	void setCurrentDesign(Design *current_design);
488 	const Design *getCurrentDesign() const;
489 	void setCurrentManufacture(Design *current_manufacture);
490 	const Design *getCurrentManufacture() const;
491 	void inventionTimeLeft(int *halfdays,int *hours) const;
492 	void manufactureTotalTime(int *halfdays,int *hours) const;
493 	void manufactureTimeLeft(int *halfdays,int *hours) const;
494 	bool inventionKnown(Invention::Type type,int epoch) const;
495 	void trashDesign(Invention *invention);
496 	void trashDesign(Design *design);
497 	bool nukeSector(Sector *source);
beingNuked(int * nuke_time)498 	int beingNuked(int *nuke_time) const {
499 		*nuke_time = this->nuke_time;
500 		return nuke_by_player;
501 	}
isBeingNuked()502 	bool isBeingNuked() const {
503 		return nuke_by_player != -1;
504 	}
isNuked()505 	bool isNuked() const {
506 		return this->nuked;
507 	}
508 	void getNukePos(int *nuke_x, int *nuke_y) const;
hasNuclearDefenceAnimation(int * nuke_defence_time,int * nuke_defence_x,int * nuke_defence_y)509 	bool hasNuclearDefenceAnimation(int *nuke_defence_time, int *nuke_defence_x, int *nuke_defence_y) const {
510 		*nuke_defence_time = this->nuke_defence_time;
511 		*nuke_defence_x = this->nuke_defence_x;
512 		*nuke_defence_y = this->nuke_defence_y;
513 		return nuke_defence_animation;
514 	}
515 
516 	void setElements(Id id,int n_elements);
517 	void getElements(int *n,int *fraction,Id id) const;
518 	bool anyElements(Id id) const;
519 	void reduceElementStocks(Id id,int reduce);
520 	void getElementStocks(int *n,int *fraction,Id id) const;
521 	void getTotalElements(int *n,int *fraction,Id id) const;
522 
523 	void buildingTowerTimeLeft(int player,int *halfdays,int *hours) const;
524 	void buildingTimeLeft(Type type,int *halfdays,int *hours) const;
525 
526 	void setPopulation(int population);
527 	void setDesigners(int n_designers);
528 	void setWorkers(int n_workers);
529 	void setFAmount(int n_famount);
530 	void setMiners(Id id,int n_miners);
531 	void setBuilders(Type type,int n_builders);
532 
533 	int getPopulation() const;
534 	int getSparePopulation() const;
535 	int getAvailablePopulation() const;
536 	int getDesigners() const;
537 	int getWorkers() const;
538 	int getFAmount() const;
539 	int getMiners(Id id) const;
540 	int getBuilders(Type type) const;
getAssembledArmy()541 	const Army *getAssembledArmy() const {
542 		return assembled_army;
543 	}
getAssembledArmy()544 	Army *getAssembledArmy() {
545 		return assembled_army;
546 	}
getStoredArmy()547 	const Army *getStoredArmy() const {
548 		return stored_army;
549 	}
getStoredArmy()550 	Army *getStoredArmy() {
551 		return stored_army;
552 	}
553 	const Army *getArmy(int player) const;
554 	Army *getArmy(int player);
555 	bool enemiesPresent() const;
556 	bool enemiesPresentWithBombardment() const;
557 	bool enemiesPresent(int player) const;
558 	bool enemiesPresent(int player,bool include_unarmed) const;
559 	void returnAssembledArmy();
560 	bool returnArmy();
561 	bool returnArmy(Army *army);
562 	bool moveArmy(Army *army);
563 	void evacuate();
564 	void assembleAll(bool include_unarmed);
565 	bool mineElement(int client_player, Id i);
566 	void invent(int client_player);
567 	void buildDesign();
568 	void buildBuilding(Type type);
569 	void updateForNewBuilding(Type type);
570 
571 	void saveState(stringstream &stream) const;
572 	void loadStateParseXMLNode(const TiXmlNode *parent);
573 
574 	void printDebugInfo() const;
575 };
576