initial commit, lordsawar source, slightly modified
[lordsawar] / src / fight.h
1 // Copyright (C) 2001, 2002, 2003 Michael Bartl
2 // Copyright (C) 2001, 2002, 2004, 2005, 2006 Ulf Lorenz
3 // Copyright (C) 2004 Bryan Duff
4 // Copyright (C) 2006 Andrea Paternesi
5 // Copyright (C) 2007, 2008 Ben Asselstine
6 // Copyright (C) 2008 Ole Laursen
7 //
8 //  This program is free software; you can redistribute it and/or modify
9 //  it under the terms of the GNU General Public License as published by
10 //  the Free Software Foundation; either version 3 of the License, or
11 //  (at your option) any later version.
12 //
13 //  This program is distributed in the hope that it will be useful,
14 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 //  GNU Library General Public License for more details.
17 //
18 //  You should have received a copy of the GNU General Public License
19 //  along with this program; if not, write to the Free Software
20 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
21 //  02110-1301, USA.
22
23 #ifndef FIGHT_H
24 #define FIGHT_H
25
26 #include <gtkmm.h>
27 #include <list>
28 #include <vector>
29 #include <map>
30
31 class Stack;
32 class Fighter;
33 class Hero;
34 class Army;
35 class LocationBox;
36
37 //! A description of a round of casualties during a Fight.
38 /** 
39  * This is the structure that describes the events of the fight.  It is 
40  * played back by a fight dialog to reconstruct and show what transpired.
41  */
42 struct FightItem
43 {
44   //! The round number of the battle.
45   int turn;
46   //! The id of the army who was attacked in this event.
47   guint32 id;
48   //! The amount of damage that the army sustained.
49   int damage;
50 };
51
52
53 //! Calculate the outcome of a battle.
54 /** 
55  * This class is solely responsible for the _calculation_ of the fight.
56  * It gets the participating stacks and damages the units within according
57  * to the calculation. Furthermore, it creates a history of the fight, which
58  * can later be used by the fight dialog to reconstruct the fight or be sent
59  * over the network. For the graphical display, see the FightDialog class.
60  *
61  * Two things should be noted. First, the fight can include more than the
62  * initial two stacks, since all stacks around the defender are considered
63  * as potential "contributors". Second, irrespective of that, a fight is
64  * always considered as "won", if the defending stack was destroyed and
65  * "lost" if the attacking stack was crushed.
66  */
67 class Fight
68 {
69     public:
70         //! The three possibilities how a fight can end
71         enum Result {
72           //! There was no winner.
73           /**
74            * Although it is in the enumeration, every fight should always
75            * have a winner.  No draws allowed because MAX_ROUNDS is 0.
76            */
77           DRAW = 0, 
78
79           //! The attacking list of stacks won the battle.
80           ATTACKER_WON = 1, 
81
82           //! The defending list of stacks won the battle.
83           DEFENDER_WON = 2
84         };
85
86         //! The kind of fight.  Whether the outcome is realized or not.
87         enum FightType {
88           //! The fight doesn't mean anything, it's just to see who would win.
89           /**
90            * @note This value is used to assist in the implementation of the
91            *       `Miltary Advisor' feature.
92            */
93           FOR_KICKS = 0, 
94
95           //! The fight is real.  If an army dies, it stays dead.
96           FOR_KEEPS = 1
97         };
98
99         //! Make a new fight between two lists of stacks.
100         /**
101          * @param attacker         The list of attacking stacks.
102          * @param defender         The list of defending stacks
103          * @param type             Optionally heal all stacks afterwards.
104          */
105         Fight(Stack* attacker, Stack* defender, FightType type = FOR_KEEPS);
106
107         // construct from serialized action
108         Fight(std::list<Stack*> attackers, std::list<Stack*> defenders,
109               std::list<FightItem> history);
110         
111         //! Destructor.
112         ~Fight();
113
114         //! Determine the outcome of the fight.
115         /**
116          * This method fills out a set of FightItem events in d_actions.
117          *
118          * @param intense   Whether or not to Use 24 sided dice instead of 
119          *                  20 sided dice.  Makes battles harder to win when 
120          *                  set to True.
121          */
122         void battle(bool intense);
123
124         Result battleFromHistory();
125         
126         //! Returns the result of the fight.
127         Result getResult() const {return d_result;}
128
129         //! Returns the list of things that happened in chronological order.
130         std::list<FightItem> getCourseOfEvents() const {return d_actions;};
131         
132         //! Returns the participating attacker stacks.
133         std::list<Stack*> getAttackers() const {return d_attackers;}
134
135         //! Returns the participating defender stacks.
136         std::list<Stack*> getDefenders() const {return d_defenders;}
137         
138         //! Get the modified strength bonus of the given Army unit.
139         guint32 getModifiedStrengthBonus(Army *a);
140
141         // CONSTANTS
142         //! The number of rounds the fight lasts.
143         /**
144          * @note If this is 0, then there is no maximum.
145          */
146         static const int MAX_ROUNDS = 0;
147
148         //! Turn a list of stacks into an ordered list of armies.
149         /**
150          * @note This is used for calculation and display purposes.
151          */
152         static void orderArmies(std::list<Stack*> stacks, 
153                                 std::vector<Army*> &armies);
154
155         std::map<guint32, guint32> getInitialHPs() { return initial_hps; }
156         
157         static LocationBox calculateFightBox(Fight &fight);
158     private:
159         //! Calculates one round of the fight.
160         /** 
161          * @return false if the maximum number of fight rounds has been
162          * exceeded or one side has lost.
163          */
164         bool doRound();
165
166         //! Calculates the attack/defense bonus of the armies.
167         void calculateBonus();
168
169         //! Calculates the base strength of the armies fighting in the battle.
170         void calculateBaseStrength(std::list<Fighter*> fighters);
171
172         //! Add the bonuses provided by terrain.
173         void calculateTerrainModifiers(std::list<Fighter*> fighters);
174
175         //! Add the bonuses by opponents.
176         void calculateModifiedStrengths (std::list<Fighter*>friendly, 
177                                          std::list<Fighter*>enemy, 
178                                          bool friendlyIsDefending,
179                                          Hero *strongestHero);
180
181         //! Subtract stack bonuses of the opponent.
182         void calculateFinalStrengths (std::list<Fighter*> friendly, 
183                                       std::list<Fighter*> enemy);
184
185         /** 
186          * This function just has two armies fight against each other. It
187          * applies the bonuses and several special bonuses to attacker and 
188          * defender and calculates the result.
189          *
190          * @param attacker     The attacking army.
191          * @param defender     The defending army.
192          */
193         void fightArmies(Fighter* attacker, Fighter* defender);
194
195         //! Removes an army from the fight.
196         void remove(Fighter* f);
197
198         void fillInInitialHPs();
199         
200         // DATA
201
202         //! The attackers.
203         std::list<Stack*> d_attackers;
204
205         //! The defenders.
206         std::list<Stack*> d_defenders;
207         
208         //!The attackers in the fight.
209         std::list<Fighter*> d_att_close;
210
211         //! The defenders in the fight.
212         std::list<Fighter*> d_def_close;
213
214         std::map<guint32, guint32> initial_hps;
215         
216         //! The list of fight events that gets calculated.
217         std::list<FightItem> d_actions;
218         
219         //! The round of the fight.
220         int d_turn;
221
222         //! The result of the fight.
223         Result d_result;
224
225         //! The kind of fight.
226         FightType d_type;
227
228         //! Whether or not we're rolling 24-sided dice or 20 sided dice.
229         bool d_intense_combat;
230 };
231
232 #endif // FIGHT_H
233