initial commit, lordsawar source, slightly modified
[lordsawar] / src / army.h
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 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 #ifndef ARMY_H
23 #define ARMY_H
24
25 #include <gtkmm.h>
26 #include <string>
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 std::string 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         };
97
98         //! Copy constructor. 
99         Army(const ArmyProdBase& armyprodbase, Player* owner = 0);
100
101         //! Copy constructor. 
102         Army(const ArmyProto& armyproto, Player* owner = 0);
103
104         //! Copy constructor. 
105         Army(const Army& army, Player *owner = 0);
106
107         /** 
108          * Load an Army from an opened saved-game file or from an opened
109          * armyset configuration file.
110          *
111          * The constructor has to care for all three cases. Sometimes, an army
112          * prototype is loaded, from which other units are cloned, sometimes
113          * actual Army instances have to be loaded, and sometimes we load
114          * up a production base when loading the Army units that a City
115          * can produce.
116          *
117          * @param helper       The opened saved-game file to load from.
118          */
119         //! Loading constructor.
120         Army(XML_Helper* helper);
121         
122         /**  
123          * Creates an empty prototype Army unit.  This constructor is only
124          * used in the ArmySetWindow (the Armyset editor).
125          */
126         //! Create an empty army.
127         Army();
128
129         //! Destructor.
130         virtual ~Army();
131
132         static Army* createNonUniqueArmy(const ArmyProto& a, Player *p=NULL);
133         static Army* createNonUniqueArmy(const ArmyProdBase& a, Player *p=NULL);
134
135
136         // Set Methods
137         
138         //! Set the Id of Armyset and type that this Army belongs to.
139         void setArmyset(guint32 armyset, guint32 type);
140         
141         //! Change the armyset that the army type for this army belongs to.
142         void setArmyset(guint32 armyset_id) {d_armyset = armyset_id;};
143
144         //! Set an Army statistic.
145         void setStat(Stat stat, guint32 value);
146
147         //! Set the current number of hitpoints of this army.
148         void setHP(guint32 hp) {d_hp = hp;}
149
150         //! Sets whether or not the Army has a particular medal.
151         void setMedalBonus(guint32 index, bool value) 
152           {d_medal_bonus[index]=value;}
153         
154         //! Sets the number of battles the Army unit participated in.
155         void setBattlesNumber(guint32 value) {d_battles_number=value;}
156          
157         //! Sets the number of hits this Army unit has scored against a foe.
158         void setNumberHasHit(double value) {d_number_hashit=value;}
159
160         //! Sets the number of hits this Army unit has suffered against a foe.
161         void setNumberHasBeenHit(double value) {d_number_hasbeenhit=value;}
162
163         //! Sets whether or not this Army unit is in a boat.
164         void setInShip (bool s);
165
166         //! Sets whether or not this Army unit is in a tower.
167         void setFortified (bool f);
168
169
170         // Get Methods 
171         
172         //! Get the Id of the Armyset to which the Army's type belongs.
173         guint32 getArmyset() const {return d_armyset;}
174         
175         //! Get the type of this army.
176         /**
177          * The type of the Army is the index of it's type in the Armyset.
178          */
179         guint32 getTypeId() const {return d_type_id;}
180
181         /** 
182          * If modified is set to false, you get the raw, inherent value of
183          * the army. Set it to true to get the modified one. This is not
184          * important for generic armies, but heroes can have their stats
185          * modified by wearing items.
186          *
187          * @param stat     The statistic to get the value of.
188          * @param modified Whether or not we get the modified stat value.
189          *
190          * @return The value of the statistic.
191          */
192         //! Returns the value of the given stat for the Army.
193         virtual guint32 getStat(Stat stat, bool modified=true) const;
194
195         //! Get the current number of hitpoints that the Army has.
196         guint32 getHP() const {return d_hp;}
197
198         //! Get the current number of movement points that the Army has.
199         guint32 getMoves() const {return d_moves;}
200
201         //! Get the current number of experience points that the Army unit has.
202         double getXP() const {return d_xp;}
203
204         //! Get the current level of the Army.
205         guint32 getLevel() const {return d_level;}
206
207         //! Return which medals this Army unit has.
208         bool* getMedalBonuses() const {return (bool*)&d_medal_bonus;}
209
210         //! Return whether or not the Army has a particular medal.
211         bool getMedalBonus(guint32 index) const {return d_medal_bonus[index];}
212
213         //! Returns the number of battles the Army unit participated in.
214         guint32 getBattlesNumber() const {return d_battles_number;}
215
216         //! Returns the number of blows the Army unit has scored against a foe.
217         double getNumberHasHit() const {return d_number_hashit;}
218
219         //! Returns the number of hits this Army unit has suffered.
220         double getNumberHasBeenHit() const {return d_number_hasbeenhit;}
221
222         //! Return whether or not the Army is in a tower.
223         bool getFortified () const;
224
225         //! Is this army a hero?
226         /**
227          * isHero is overridden by the Hero class.
228          */
229         virtual bool isHero() const {return false;};
230
231         //! This army is of an army type that can be awarded as a reward.
232         bool getAwardable() const;
233
234         //! This army is of an army type that can be the keeper in a ruin.
235         bool getDefendsRuins() const;
236
237         //! This army is of an army type that has this name.
238         virtual std::string getName() const;
239
240         //Methods that operate on class data and modify the class data
241         /** 
242          * Regenerate an amount of the Army unit's hitpoints but not 
243          * exceeding the maximum number of hitpoints.
244          *
245          * @param hp       The amount of hitpoints to heal.  Set to zero for 
246          *                 "natural" healing -- but this feature is not 
247          *                 currently used because wounded army units are always 
248          *                 fully healed after battle.
249          */
250         //! Heal the Army unit.
251         void heal(guint32 hp = 0);
252
253         /** 
254          * Decrease the number of hitpoints that this Army has.
255          * 
256          * @param damageDone       The amount of damage that the Army suffers.
257          *
258          * @return True if the Army unit has died, otherwise false.
259          */
260         //! Damage the Army.
261         bool damage(guint32 damageDone);
262
263         /** 
264          * Reduce the number of moves that the Army unit has.
265          * @note This method doesn't reduce the maximum number of movement 
266          * points; it reduces the current number of movement points, which 
267          * get restored at the start of the next turn.
268          * 
269          * @param moves      The number of movement points to consume.
270          */
271         //! Consume some movement points.
272         void decrementMoves(guint32 moves);
273
274         //! Restores the number of movement points to the maximum level.
275         void resetMoves();
276
277         /**
278          * Add 1 to the strength of the Army unit if it has not already
279          * visited the Temple at which it's parent stack is currently
280          * sitting on.
281          *
282          * @param temple   The temple that the army is being blessed at.
283          *
284          * @return True if the Army unit was blessed, otherwise false.
285          */
286         //! Bless the Army unit if it hasn't already visited this Temple.
287         bool bless(Temple *temple);
288
289         //! Increases the experience points of the Army by the given amount.
290         void gainXp(double n);
291
292         //! Make this army look and behave like another one.
293         void morph(const ArmyProto *armyproto);
294
295         //Methods that operate on class data and do not modify the class data
296
297         //! Returns whether or not the army was blessed at the given temple.
298         bool blessedAtTemple(guint32 temple_id) const;
299
300         void printAllDebugInfo() const;
301
302         //! Saves the Army to an opened saved-game file.
303         virtual bool save(XML_Helper* helper) const;
304
305         //signals
306         
307         /**
308          * @note This signal is static because sometimes the army doesn't 
309          * exist yet when the signal is connected.
310          *
311          * @param army  The army that has died.
312          */
313         //! Emitted when an Army has died.
314         static sigc::signal<void, Army*> sdying;
315
316     protected:
317
318         //! Generic method for saving Army data.  Useful to the Hero class.
319         bool saveData(XML_Helper* helper) const;
320
321         //! The index of the Army unit's type in it's Armyset.
322         guint32 d_type_id;
323
324         //! The Id of the Armyset that the Army prototype belongs to.
325         guint32 d_armyset;
326
327         /**
328          * The maximum number of hitpoints is the secondmost important
329          * factor when calculating the outgoing of a Fight.
330          *
331          * This value should always be 2.
332          *
333          * This value does not change during gameplay.
334          */
335         //! The maximum number of hitpoints this Army unit has.
336         guint32 d_max_hp;
337
338         //! Movement point multiplier of the Army unit.
339         /**
340          * If an Army unit is being affected by a Hero unit's Item that
341          * confers the Item::DOUBLEMOVESTACK Item::Bonus, the effect is
342          * stored in d_max_moves_multiplier.
343          *
344          * This value must be 1 or more.
345          *
346          * This value typically changes from 1 to 2, and back to 1 during
347          * gameplay.
348          */
349         guint32 d_max_moves_multiplier;
350
351         //! Movement point bonus due to resting.
352         /**
353          * When an army unit doesn't use all of it's movement points in a
354          * turn, some of those points get held-over until the following turn.
355          * If a unit has 3 movement points remaining, the bonus is 2.  If the
356          * unit has 2 movement points remaining, the bonus is 2.  If the unit
357          * has 1 movement point remaining, the bonus is 1.
358          *
359          * This value is a number between 0 and 2.
360          */
361         guint32 d_max_moves_rest_bonus;
362
363         /**
364          * Being in a ship affects the Army's strength in battle.
365          * Every army has a strength of 4 when fighting on a boat.
366          * It also affects the number of moves that the Army has.
367          * See MAX_BOAT_MOVES.
368          *
369          * This value gets set and unset as Army unit's stack goes in
370          * and out of the water.
371          */
372         //! Whether or not this Army unit is afloat in a boat.
373         bool d_ship;
374
375         //! The current number of hitpoints that the Army unit has.
376         /**
377          * When this value is 0 it means the Army unit is dead.
378          * 
379          * During a Fight this value gets decremented as the Army unit
380          * suffers attacks by enemy Army units.
381          *
382          * After a Fight, this value gets restored to d_max_hp.
383          *
384          * d_hp does not exceed d_max_hp.
385          */
386         guint32 d_hp;
387
388         //! The current number of movement points that the Army unit has.
389         /**
390          * As the Army unit moves around in a Stack on the GameMap, it travels
391          * over certain terrain tiles.  As the Army unit moves over a
392          * particular terrain Tile, d_moves dwindles in value.
393          *
394          * At the end of a round, this value gets restored to d_max_moves.
395          *
396          * d_moves does not exceed d_moves_hp.
397          */
398         guint32 d_moves;
399
400         //! The current level of experience points the Army unit has.
401         /**
402          * This value increases as the Army unit assists in killing enemy
403          * Army units.  This value does not decrease during gameplay.
404          *
405          * This value affects what d_level the Army unit is.
406          */
407         double d_xp;
408
409         //! The experience level the Army unit has attained.
410         /**
411          * This value increases as the Army unit increases it's experience
412          * points.  d_level increases when a multiple of Army::xp_per_level 
413          * is surpassed.  d_level does not decrease during gameplay.
414          *
415          * d_level is not factored into any calculations that affect the
416          * outcome of the game.  It's just for show.
417          *
418          * @note Only Hero units advance in levels.
419          */
420         guint32 d_level;
421
422         /**
423          * There are three different medals that an Army unit can win.
424          *
425          * Merciless Medal: medal for being extremely merciless.  A unit 
426          *                  gets this medal if in a combat it scores more 
427          *                  than 90% of hits.
428          * Defender Medal: medal for being very good in defense.  A unit 
429          *                 gets this medal if in a combat is never hit.
430          * Veteran Medal: medal for being very good in combat.  A unit gets 
431          *                this medal if it survives 10 battles.
432          *
433          * Medals do not affect the game outcome and are just for show.
434          */
435         //! The medals that the Army unit has been given.
436         bool d_medal_bonus[3];
437
438         //! The total number of battles that this Army unit has fought in.
439         /**
440          * d_battles_number is a counter that is used to know when to
441          * award the Veteran's medal to this Army unit.
442          *
443          * This value does not decrease during gameplay.
444          */
445         guint32 d_battles_number;
446
447         //! The weighted number of hits per battle for this Army unit.
448         /**
449          * d_number_hashit is a counter that is used to know when to award
450          * the Merciless medal to this Army unit.
451          *
452          * This value does not decrease during gameplay.
453          */
454         double d_number_hashit;
455
456         //! The weighted number of times the Army unit has been hit in a battle.
457         /**
458          * d_number_hasbeenhit is a counter that is used to know when to award
459          * the Defender medal to this Army unit.
460          *
461          * This value does not decrease during gameplay.
462          */
463         double d_number_hasbeenhit;
464
465         //! A list of the Ids of Temples the Army unit has visited.
466         /**
467          * As the Army unit gets blessed at various Temple objects, this
468          * list grows with unique Temple Ids.
469          * The purpose of the list is to prevent the Army unit from being
470          * blessed at the same Temple more than once.
471          *
472          * The length of the list does not decrease during gameplay.
473          */
474         std::list<guint32> d_visitedTemples;
475
476         //! The number of experience points per experience level.
477         /**
478          * When an Army unit's d_xp surpasses a multiple of xp_per_level,
479          * it increases it's d_level by 1.
480          */
481         static const int xp_per_level = 10;
482
483     private:
484
485         //! Create an army with a non-unique id from an army prototype.
486         Army(const ArmyProto& a, guint32 id, Player *player = NULL);
487         //! Create an army with a non-unique id from an army production base.
488         Army(const ArmyProdBase& a, guint32 id, Player *player = NULL);
489
490 };
491
492 #endif // ARMY_H