initial commit, lordsawar source, slightly modified
[lordsawar] / src / fight.h
diff --git a/src/fight.h b/src/fight.h
new file mode 100644 (file)
index 0000000..5cd9798
--- /dev/null
@@ -0,0 +1,233 @@
+// Copyright (C) 2001, 2002, 2003 Michael Bartl
+// Copyright (C) 2001, 2002, 2004, 2005, 2006 Ulf Lorenz
+// Copyright (C) 2004 Bryan Duff
+// Copyright (C) 2006 Andrea Paternesi
+// Copyright (C) 2007, 2008 Ben Asselstine
+// Copyright (C) 2008 Ole Laursen
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU Library General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
+//  02110-1301, USA.
+
+#ifndef FIGHT_H
+#define FIGHT_H
+
+#include <gtkmm.h>
+#include <list>
+#include <vector>
+#include <map>
+
+class Stack;
+class Fighter;
+class Hero;
+class Army;
+class LocationBox;
+
+//! A description of a round of casualties during a Fight.
+/** 
+ * This is the structure that describes the events of the fight.  It is 
+ * played back by a fight dialog to reconstruct and show what transpired.
+ */
+struct FightItem
+{
+  //! The round number of the battle.
+  int turn;
+  //! The id of the army who was attacked in this event.
+  guint32 id;
+  //! The amount of damage that the army sustained.
+  int damage;
+};
+
+
+//! Calculate the outcome of a battle.
+/** 
+ * This class is solely responsible for the _calculation_ of the fight.
+ * It gets the participating stacks and damages the units within according
+ * to the calculation. Furthermore, it creates a history of the fight, which
+ * can later be used by the fight dialog to reconstruct the fight or be sent
+ * over the network. For the graphical display, see the FightDialog class.
+ *
+ * Two things should be noted. First, the fight can include more than the
+ * initial two stacks, since all stacks around the defender are considered
+ * as potential "contributors". Second, irrespective of that, a fight is
+ * always considered as "won", if the defending stack was destroyed and
+ * "lost" if the attacking stack was crushed.
+ */
+class Fight
+{
+    public:
+        //! The three possibilities how a fight can end
+        enum Result {
+         //! There was no winner.
+         /**
+          * Although it is in the enumeration, every fight should always
+          * have a winner.  No draws allowed because MAX_ROUNDS is 0.
+          */
+         DRAW = 0, 
+
+         //! The attacking list of stacks won the battle.
+         ATTACKER_WON = 1, 
+
+         //! The defending list of stacks won the battle.
+         DEFENDER_WON = 2
+       };
+
+       //! The kind of fight.  Whether the outcome is realized or not.
+        enum FightType {
+         //! The fight doesn't mean anything, it's just to see who would win.
+         /**
+          * @note This value is used to assist in the implementation of the
+          *       `Miltary Advisor' feature.
+          */
+         FOR_KICKS = 0, 
+
+         //! The fight is real.  If an army dies, it stays dead.
+         FOR_KEEPS = 1
+       };
+
+       //! Make a new fight between two lists of stacks.
+        /**
+         * @param attacker         The list of attacking stacks.
+         * @param defender         The list of defending stacks
+        * @param type             Optionally heal all stacks afterwards.
+         */
+        Fight(Stack* attacker, Stack* defender, FightType type = FOR_KEEPS);
+
+        // construct from serialized action
+        Fight(std::list<Stack*> attackers, std::list<Stack*> defenders,
+              std::list<FightItem> history);
+        
+       //! Destructor.
+        ~Fight();
+
+        //! Determine the outcome of the fight.
+       /**
+        * This method fills out a set of FightItem events in d_actions.
+        *
+        * @param intense   Whether or not to Use 24 sided dice instead of 
+        *                  20 sided dice.  Makes battles harder to win when 
+        *                  set to True.
+        */
+        void battle(bool intense);
+
+        Result battleFromHistory();
+        
+        //! Returns the result of the fight.
+        Result getResult() const {return d_result;}
+
+        //! Returns the list of things that happened in chronological order.
+        std::list<FightItem> getCourseOfEvents() const {return d_actions;};
+        
+        //! Returns the participating attacker stacks.
+        std::list<Stack*> getAttackers() const {return d_attackers;}
+
+        //! Returns the participating defender stacks.
+        std::list<Stack*> getDefenders() const {return d_defenders;}
+        
+       //! Get the modified strength bonus of the given Army unit.
+       guint32 getModifiedStrengthBonus(Army *a);
+
+        // CONSTANTS
+        //! The number of rounds the fight lasts.
+       /**
+        * @note If this is 0, then there is no maximum.
+        */
+        static const int MAX_ROUNDS = 0;
+
+       //! Turn a list of stacks into an ordered list of armies.
+       /**
+        * @note This is used for calculation and display purposes.
+        */
+        static void orderArmies(std::list<Stack*> stacks, 
+                               std::vector<Army*> &armies);
+
+        std::map<guint32, guint32> getInitialHPs() { return initial_hps; }
+        
+       static LocationBox calculateFightBox(Fight &fight);
+    private:
+       //! Calculates one round of the fight.
+        /** 
+         * @return false if the maximum number of fight rounds has been
+         * exceeded or one side has lost.
+         */
+        bool doRound();
+
+        //! Calculates the attack/defense bonus of the armies.
+        void calculateBonus();
+
+       //! Calculates the base strength of the armies fighting in the battle.
+        void calculateBaseStrength(std::list<Fighter*> fighters);
+
+       //! Add the bonuses provided by terrain.
+        void calculateTerrainModifiers(std::list<Fighter*> fighters);
+
+       //! Add the bonuses by opponents.
+        void calculateModifiedStrengths (std::list<Fighter*>friendly, 
+                                         std::list<Fighter*>enemy, 
+                                         bool friendlyIsDefending,
+                                         Hero *strongestHero);
+
+       //! Subtract stack bonuses of the opponent.
+        void calculateFinalStrengths (std::list<Fighter*> friendly, 
+                                     std::list<Fighter*> enemy);
+
+        /** 
+        * This function just has two armies fight against each other. It
+         * applies the bonuses and several special bonuses to attacker and 
+        * defender and calculates the result.
+         *
+         * @param attacker     The attacking army.
+         * @param defender     The defending army.
+         */
+        void fightArmies(Fighter* attacker, Fighter* defender);
+
+        //! Removes an army from the fight.
+        void remove(Fighter* f);
+
+        void fillInInitialHPs();
+        
+        // DATA
+
+       //! The attackers.
+        std::list<Stack*> d_attackers;
+
+       //! The defenders.
+        std::list<Stack*> d_defenders;
+        
+       //!The attackers in the fight.
+        std::list<Fighter*> d_att_close;
+
+       //! The defenders in the fight.
+        std::list<Fighter*> d_def_close;
+
+        std::map<guint32, guint32> initial_hps;
+        
+       //! The list of fight events that gets calculated.
+        std::list<FightItem> d_actions;
+        
+       //! The round of the fight.
+        int d_turn;
+
+       //! The result of the fight.
+        Result d_result;
+
+       //! The kind of fight.
+       FightType d_type;
+
+       //! Whether or not we're rolling 24-sided dice or 20 sided dice.
+       bool d_intense_combat;
+};
+
+#endif // FIGHT_H
+