1 // Copyright (C) 2000, 2001, 2003 Michael Bartl
2 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Ulf Lorenz
3 // Copyright (C) 2004, 2005 Andrea Paternesi
4 // Copyright (C) 2007, 2008, 2011, 2014, 2015, 2017 Ben Asselstine
5 // Copyright (C) 2007, 2008 Ole Laursen
6 //
7 //  This program is free software; you can redistribute it and/or modify
8 //  it under the terms of the GNU General Public License as published by
9 //  the Free Software Foundation; either version 3 of the License, or
10 //  (at your option) any later version.
11 //
12 //  This program is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 //  GNU Library General Public License for more details.
16 //
17 //  You should have received a copy of the GNU General Public License
18 //  along with this program; if not, write to the Free Software
19 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 //  02110-1301, USA.
21 
22 #pragma once
23 #ifndef ARMY_H
24 #define ARMY_H
25 
26 #include <gtkmm.h>
27 #include <sigc++/trackable.h>
28 #include <sigc++/signal.h>
29 
30 #include "Ownable.h"
31 #include "armybase.h"
32 #include "UniquelyIdentified.h"
33 
34 class Player;
35 class Temple;
36 class XML_Helper;
37 class ArmyProto;
38 class ArmyProdBase;
39 
40 //! An instance of an Army unit, an Army unit type, or an Army production base.
41  /**
42   * This class is the atom of every army.  It contains values such as
43   * strength, movement points, upkeep, and so on.
44   *
45   * The purpose of the Army class is three-fold; an Army class can hold a
46   * an Army prototype, or a production base, or an Army instance.
47   *
48   * The Army instance is the most frequently used purpose of the Army class.
49   * An Army instance has a unique Id among all other game objects, has an
50   * owner (Player), and is included in a Stack.
51   *
52   * The Army unit prototype purpose is the second-most frequently used
53   * purpose of the Army class.  These types originate from a configuration
54   * file; for example: army/default/default.xml.  Every Army unit type has an
55   * type value that makes it unique among all other Army unit types in an
56   * Armyset.
57   *
58   * The production base purpose refers to the Army units that are included
59   * in the City class as potential Army units that the City can produce.
60   * This purpose is exactly the same as the Army unit prototype purpose,
61   * except it knows which Armyset it comes from, and it knows which Army
62   * unit type it derives from.
63   *
64   * Maybe these three purposes will be split up into three or more classes
65   * in the future.
66   */
67 class Army :public ArmyBase, public UniquelyIdentified, public Ownable, public sigc::trackable
68 {
69     public:
70 
71 	//! The xml tag of this object in a saved-game file.
72 	static Glib::ustring d_tag;
73 
74 	//! Various kinds of statistics that an instance of Army unit has.
75 	/**
76 	 * This enumeration assists in getting and setting of statistics in
77 	 * an instance of an Army unit.
78 	 */
79         enum Stat {
80 	  //! How strong the Army unit is in battle.
81 	  STRENGTH = 0,
82 	  //! The maximum number of hitpoints that the Army unit can have.
83 	  HP = 3,
84 	  //! The maximum number of moves the Army unit has.
85 	  MOVES = 4,
86 	  //! The various Tile::Type that the Army moves efficiently in.
87 	  MOVE_BONUS = 5,
88 	  //! The special bonus the Army has (Army::Bonus).
89 	  ARMY_BONUS = 6,
90 	  //! How far the Army unit can see on a hidden map.
91 	  SIGHT = 7,
92 	  //! If the Army unit is in a boat or not.
93 	  SHIP = 8,
94 	  //! If the Army unit is having it's movement doubled/tripled or not.
95 	  MOVES_MULTIPLIER = 9,
96           //! If SHIP, then this is how strong the army is on a boat.
97           BOAT_STRENGTH = 10
98         };
99 
100 	//! Copy constructor.
101         Army(const ArmyProdBase& armyprodbase, Player* owner = 0);
102 
103 	//! Copy constructor.
104         Army(const ArmyProto& armyproto, Player* owner = 0);
105 
106 	//! Copy constructor.
107         Army(const Army& army, Player *owner = 0);
108 
109         /**
110 	 * Load an Army from an opened saved-game file or from an opened
111 	 * armyset configuration file.
112          *
113          * The constructor has to care for all three cases. Sometimes, an army
114          * prototype is loaded, from which other units are cloned, sometimes
115          * actual Army instances have to be loaded, and sometimes we load
116 	 * up a production base when loading the Army units that a City
117 	 * can produce.
118          *
119          * @param helper       The opened saved-game file to load from.
120          */
121 	//! Loading constructor.
122         Army(XML_Helper* helper);
123 
124 	/**
125 	 * Creates an empty prototype Army unit.  This constructor is only
126 	 * used in the ArmySetWindow (the Armyset editor).
127 	 */
128 	//! Create an empty army.
129 	Army();
130 
131 	//! Destructor.
132         virtual ~Army();
133 
134 	static Army* createNonUniqueArmy(const ArmyProto& a, Player *p=NULL);
135 	static Army* createNonUniqueArmy(const ArmyProdBase& a, Player *p=NULL);
136 
137 
138         // Set Methods
139 
140         //! Set the Id of Armyset and type that this Army belongs to.
141         void setArmyset(guint32 armyset, guint32 type);
142 
143 	//! Change the armyset that the army type for this army belongs to.
setArmyset(guint32 armyset_id)144 	void setArmyset(guint32 armyset_id) {d_armyset = armyset_id;};
145 
146         //! Set an Army statistic.
147         void setStat(Stat stat, guint32 value);
148 
149         //! Set the current number of hitpoints of this army.
setHP(guint32 hp)150         void setHP(guint32 hp) {d_hp = hp;}
151 
152         //! Set the current number of hitpoints of this army to zero.
kill()153         void kill() {setHP(0);}
154 
155         //! Sets whether or not the Army has a particular medal.
setMedalBonus(guint32 index,bool value)156         void setMedalBonus(guint32 index, bool value)
157 	  {d_medal_bonus[index]=value;}
158 
159         //! Sets the number of battles the Army unit participated in.
setBattlesNumber(guint32 value)160         void setBattlesNumber(guint32 value) {d_battles_number=value;}
161 
162         //! Sets the number of hits this Army unit has scored against a foe.
setNumberHasHit(double value)163         void setNumberHasHit(double value) {d_number_hashit=value;}
164 
165         //! Sets the number of hits this Army unit has suffered against a foe.
setNumberHasBeenHit(double value)166         void setNumberHasBeenHit(double value) {d_number_hasbeenhit=value;}
167 
168 	//! Sets whether or not this Army unit is in a boat.
169 	void setInShip (bool s);
170 
171 	//! Sets whether or not this Army unit is in a tower.
172 	void setFortified (bool f);
173 
174         // Get Methods
175 
176 	//! Get the Id of the Armyset to which the Army's type belongs.
getArmyset()177         guint32 getArmyset() const {return d_armyset;}
178 
179         //! Get the type of this army.
180 	/**
181 	 * The type of the Army is the index of it's type in the Armyset.
182 	 */
getTypeId()183         guint32 getTypeId() const {return d_type_id;}
184 
185         /**
186          * If modified is set to false, you get the raw, inherent value of
187          * the army. Set it to true to get the modified one. This is not
188          * important for generic armies, but heroes can have their stats
189          * modified by wearing items.
190 	 *
191 	 * @param stat     The statistic to get the value of.
192 	 * @param modified Whether or not we get the modified stat value.
193 	 *
194 	 * @return The value of the statistic.
195          */
196 	//! Returns the value of the given stat for the Army.
197         virtual guint32 getStat(Stat stat, bool modified=true) const;
198 
199         //! Get the current number of hitpoints that the Army has.
getHP()200         guint32 getHP() const {return d_hp;}
201 
202         //! Get the current number of movement points that the Army has.
getMoves()203         guint32 getMoves() const {return d_moves;}
204 
205         //! Get the current number of experience points that the Army unit has.
getXP()206         double getXP() const {return d_xp;}
207 
208         //! Get the current level of the Army.
getLevel()209         guint32 getLevel() const {return d_level;}
210 
211         //! Return which medals this Army unit has.
getMedalBonuses()212         bool* getMedalBonuses() const {return (bool*)&d_medal_bonus;}
213 
214         //! Return whether or not the Army has a particular medal.
getMedalBonus(guint32 index)215         bool getMedalBonus(guint32 index) const {return d_medal_bonus[index];}
216 
217         //! Returns the number of battles the Army unit participated in.
getBattlesNumber()218         guint32 getBattlesNumber() const {return d_battles_number;}
219 
220         //! Returns the number of blows the Army unit has scored against a foe.
getNumberHasHit()221         double getNumberHasHit() const {return d_number_hashit;}
222 
223         //! Returns the number of hits this Army unit has suffered.
getNumberHasBeenHit()224         double getNumberHasBeenHit() const {return d_number_hasbeenhit;}
225 
226 	//! Return whether or not the Army is in a tower.
227 	bool getFortified () const;
228 
229 	//! Is this army a hero?
230 	/**
231 	 * isHero is overridden by the Hero class.
232 	 */
isHero()233 	virtual bool isHero() const {return false;};
234 
235 	//! This army is of an army type that can be awarded as a reward.
236 	bool getAwardable() const;
237 
238 	//! This army is of an army type that can be the keeper in a ruin.
239 	bool getDefendsRuins() const;
240 
241 	//! This army is of an army type that has this name.
242 	virtual Glib::ustring getName() const;
243 
244         //! Does this army unit have wings?
245         virtual bool isFlyer() const;
246 
247 	//Methods that operate on class data and modify the class data
248         /**
249 	 * Regenerate an amount of the Army unit's hitpoints but not
250 	 * exceeding the maximum number of hitpoints.
251 	 *
252          * @param hp       The amount of hitpoints to heal.  Set to zero for
253 	 *                 "natural" healing -- but this feature is not
254 	 *                 currently used because wounded army units are always
255 	 *                 fully healed after battle.
256          */
257 	//! Heal the Army unit.
258         void heal(guint32 hp = 0);
259 
260         /**
261 	 * Decrease the number of hitpoints that this Army has.
262          *
263          * @param damageDone       The amount of damage that the Army suffers.
264 	 *
265          * @return True if the Army unit has died, otherwise false.
266          */
267 	//! Damage the Army.
268         bool damage(guint32 damageDone);
269 
270         /**
271 	 * Reduce the number of moves that the Army unit has.
272 	 * @note This method doesn't reduce the maximum number of movement
273 	 * points; it reduces the current number of movement points, which
274 	 * get restored at the start of the next turn.
275          *
276          * @param moves      The number of movement points to consume.
277          */
278 	//! Consume some movement points.
279         void decrementMoves(guint32 moves);
280 
281         /**
282 	 * Add to the number of moves that the Army unit has.
283 	 * @note This method doesn't increase the maximum number of movement
284 	 * points; it adds to the current number of movement points, which
285 	 * get restored at the start of the next turn.
286          *
287          * @param moves      The number of movement points to add.
288          */
289 	//! Add some movement points.
290         void incrementMoves(guint32 moves);
291 
292         //! Restores the number of movement points to the maximum level.
293         void resetMoves();
294 
295 	/**
296 	 * Add 1 to the strength of the Army unit if it has not already
297 	 * visited the Temple at which it's parent stack is currently
298 	 * sitting on.
299 	 *
300 	 * @param temple   The temple that the army is being blessed at.
301 	 *
302 	 * @return True if the Army unit was blessed, otherwise false.
303 	 */
304 	//! Bless the Army unit if it hasn't already visited this Temple.
305         bool bless(Temple *temple);
306 
307         //! Increases the experience points of the Army by the given amount.
308         void gainXp(double n);
309 
310 	//! Make this army look and behave like another one.
311 	void morph(const ArmyProto *armyproto);
312 
313 	//Methods that operate on class data and do not modify the class data
314 
315 	//! Returns whether or not the army was blessed at the given temple.
316         bool blessedAtTemple(guint32 temple_id) const;
317 
318         //! Saves the Army to an opened saved-game file.
319         virtual bool save(XML_Helper* helper) const;
320 
321 	//signals
322 
323 	/**
324 	 * @note This signal is static because sometimes the army doesn't
325 	 * exist yet when the signal is connected.
326 	 *
327 	 * @param army  The army that has died.
328 	 */
329 	//! Emitted when an Army has died.
330         static sigc::signal<void, Army*> sdying;
331 
332     protected:
333 
334         //! Generic method for saving Army data.  Useful to the Hero class.
335         bool saveData(XML_Helper* helper) const;
336 
337 	//! The index of the Army unit's type in it's Armyset.
338         guint32 d_type_id;
339 
340 	//! The Id of the Armyset that the Army prototype belongs to.
341         guint32 d_armyset;
342 
343 	/**
344 	 * The maximum number of hitpoints is the secondmost important
345 	 * factor when calculating the outgoing of a Fight.
346 	 *
347 	 * This value should always be 2.
348 	 *
349 	 * This value does not change during gameplay.
350 	 */
351 	//! The maximum number of hitpoints this Army unit has.
352         guint32 d_max_hp;
353 
354 	//! Movement point multiplier of the Army unit.
355 	/**
356 	 * If an Army unit is being affected by a Hero unit's Item that
357 	 * confers the Item::DOUBLEMOVESTACK Item::Bonus, the effect is
358 	 * stored in d_max_moves_multiplier.
359 	 *
360 	 * This value must be 1 or more.
361 	 *
362 	 * This value typically changes from 1 to 2, and back to 1 during
363 	 * gameplay.
364 	 */
365 	guint32 d_max_moves_multiplier;
366 
367 	//! Movement point bonus due to resting.
368 	/**
369 	 * When an army unit doesn't use all of it's movement points in a
370 	 * turn, some of those points get held-over until the following turn.
371 	 * If a unit has 3 movement points remaining, the bonus is 2.  If the
372 	 * unit has 2 movement points remaining, the bonus is 2.  If the unit
373 	 * has 1 movement point remaining, the bonus is 1.
374 	 *
375 	 * This value is a number between 0 and 2.
376 	 */
377 	guint32 d_max_moves_rest_bonus;
378 
379 	/**
380 	 * Being in a ship affects the Army's strength in battle.
381 	 * Every army has a strength of 4 when fighting on a boat.
382 	 * It also affects the number of moves that the Army has.
383 	 * See MAX_BOAT_MOVES.
384 	 *
385 	 * This value gets set and unset as Army unit's stack goes in
386 	 * and out of the water.
387 	 */
388 	//! Whether or not this Army unit is afloat in a boat.
389 	bool d_ship;
390 
391 	//! The current number of hitpoints that the Army unit has.
392 	/**
393 	 * When this value is 0 it means the Army unit is dead.
394 	 *
395 	 * During a Fight this value gets decremented as the Army unit
396 	 * suffers attacks by enemy Army units.
397 	 *
398 	 * After a Fight, this value gets restored to d_max_hp.
399 	 *
400 	 * d_hp does not exceed d_max_hp.
401 	 */
402         guint32 d_hp;
403 
404 	//! The current number of movement points that the Army unit has.
405 	/**
406 	 * As the Army unit moves around in a Stack on the GameMap, it travels
407 	 * over certain terrain tiles.  As the Army unit moves over a
408 	 * particular terrain Tile, d_moves dwindles in value.
409 	 *
410 	 * At the end of a round, this value gets restored to d_max_moves.
411 	 *
412 	 * d_moves does not exceed d_moves_hp.
413 	 */
414         guint32 d_moves;
415 
416 	//! The current level of experience points the Army unit has.
417 	/**
418 	 * This value increases as the Army unit assists in killing enemy
419 	 * Army units.  This value does not decrease during gameplay.
420 	 *
421 	 * This value affects what d_level the Army unit is.
422 	 */
423         double d_xp;
424 
425 	//! The experience level the Army unit has attained.
426 	/**
427 	 * This value increases as the Army unit increases it's experience
428 	 * points.  d_level increases when a multiple of Army::xp_per_level
429 	 * is surpassed.  d_level does not decrease during gameplay.
430 	 *
431 	 * d_level is not factored into any calculations that affect the
432 	 * outcome of the game.  It's just for show.
433 	 *
434 	 * @note Only Hero units advance in levels.
435 	 */
436         guint32 d_level;
437 
438 	/**
439 	 * There are three different medals that an Army unit can win.
440 	 *
441 	 * Merciless Medal: medal for being extremely merciless.  A unit
442 	 *                  gets this medal if in a combat it scores more
443 	 *                  than 90% of hits.
444 	 * Defender Medal: medal for being very good in defense.  A unit
445 	 *                 gets this medal if in a combat is never hit.
446 	 * Veteran Medal: medal for being very good in combat.  A unit gets
447 	 *                this medal if it survives 10 battles.
448 	 *
449 	 * Medals do not affect the game outcome and are just for show.
450 	 */
451 	//! The medals that the Army unit has been given.
452         bool d_medal_bonus[3];
453 
454         //! The total number of battles that this Army unit has fought in.
455 	/**
456 	 * d_battles_number is a counter that is used to know when to
457 	 * award the Veteran's medal to this Army unit.
458 	 *
459 	 * This value does not decrease during gameplay.
460 	 */
461         guint32 d_battles_number;
462 
463         //! The weighted number of hits per battle for this Army unit.
464 	/**
465 	 * d_number_hashit is a counter that is used to know when to award
466 	 * the Merciless medal to this Army unit.
467 	 *
468 	 * This value does not decrease during gameplay.
469 	 */
470         double d_number_hashit;
471 
472         //! The weighted number of times the Army unit has been hit in a battle.
473 	/**
474 	 * d_number_hasbeenhit is a counter that is used to know when to award
475 	 * the Defender medal to this Army unit.
476 	 *
477 	 * This value does not decrease during gameplay.
478 	 */
479         double d_number_hasbeenhit;
480 
481 	//! A list of the Ids of Temples the Army unit has visited.
482 	/**
483 	 * As the Army unit gets blessed at various Temple objects, this
484 	 * list grows with unique Temple Ids.
485 	 * The purpose of the list is to prevent the Army unit from being
486 	 * blessed at the same Temple more than once.
487 	 *
488 	 * The length of the list does not decrease during gameplay.
489 	 */
490         std::list<guint32> d_visitedTemples;
491 
492 	//! The number of experience points per experience level.
493 	/**
494 	 * When an Army unit's d_xp surpasses a multiple of xp_per_level,
495 	 * it increases it's d_level by 1.
496 	 */
497         static const int xp_per_level = 10;
498 
499     private:
500 
501 	//! Create an army with a non-unique id from an army prototype.
502 	Army(const ArmyProto& a, guint32 id, Player *player = NULL);
503 	//! Create an army with a non-unique id from an army production base.
504 	Army(const ArmyProdBase& a, guint32 id, Player *player = NULL);
505 
506 };
507 
508 #endif // ARMY_H
509