initial commit, lordsawar source, slightly modified
[lordsawar] / src / stack.h
diff --git a/src/stack.h b/src/stack.h
new file mode 100644 (file)
index 0000000..82596a8
--- /dev/null
@@ -0,0 +1,480 @@
+// Copyright (C) 2000, 2001, 2003 Michael Bartl
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Ulf Lorenz
+// Copyright (C) 2004, 2005, 2006 Andrea Paternesi
+// Copyright (C) 2007, 2008, 2009 Ben Asselstine
+// Copyright (C) 2007, 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 STACK_H
+#define STACK_H
+
+#include <list>
+#include <vector>
+#include "vector.h"
+#include <sigc++/trackable.h>
+#include <sigc++/signal.h>
+#include <sstream>
+
+#include "UniquelyIdentified.h"
+#include "Ownable.h"
+#include "Movable.h"
+
+class Player;
+class Path;
+class Army;
+class ArmyProdBase;
+class XML_Helper;
+class Temple;
+class Hero;
+
+//! A set of up to eight Army units that move as a single entity on the map.
+/** 
+ * While Army units are the actual troops you command, they always belong to a
+ * stack. The stack holds these armies together in one object. The player
+ * usually doesn't command the armies but the stack, so all functionality and
+ * data which affects player's controls is bundled in the stack class. Among
+ * this is the location of the units, the intended movement path, and more.
+ */
+
+class Stack : public ::UniquelyIdentified, public Movable, public Ownable, public std::list<Army*>, public sigc::trackable
+{
+    public:
+       //! The xml tag of this object in a saved-game file.
+       static std::string d_tag; 
+
+        /** 
+        * Make a new stack.
+         * 
+         * @param player       A pointer to the owning player.
+         * @param pos          The position on the map where the stack is to 
+        *                     be created.
+         */
+       //! Default constructor.
+        Stack(Player* player, Vector<int> pos);
+
+       /**
+        * Copy the whole stack into a new stack.  This method performs a 
+        * deep copy of the stack's Army units.
+        */
+        //! Copy constructor.
+        Stack(const Stack& s);
+
+        //! Loading constructor.
+        Stack(XML_Helper* helper);
+
+       //! Destructor.
+        ~Stack();
+
+       // Get Methods
+
+        //! Returns the minimum number of movement points of all Army units.
+        guint32 getMoves() const;
+
+       //! Returns the maximum MP the stack would have if it were on land
+        guint32 getMaxLandMoves() const;
+
+       //! Returns the max MP the stack would have if it were in the water
+        guint32 getMaxBoatMoves() const;
+
+        //! Returns the Path object of the stack.
+        Path* getPath() const {return d_path;}
+
+       //! Return true if any of the Army units in the stack are fortified.
+       bool getFortified() const;
+       
+       //! Calculate the number of gold pieces this stack costs this turn.
+       guint32 getUpkeep() const;
+
+        //! How many army units can be put into this stack?
+        guint32 getMaxArmiesToJoin() const;
+
+        guint32 countAllies() const;
+
+       // Set Methods
+
+        //! Change the loyalty of the stack.
+        void setPlayer(Player* p);
+
+        /** 
+        * Sets the defending value.  Defending entails that this stack is 
+        * ignored when a user cycles through the list of stacks with 
+        * Stacklist::getNextMovable().  If a stack stays defending to the
+        * next round, it gets a fortify bonus in battle.
+        */
+       //! Set the defending status of the stack.
+        void setDefending(bool defending){d_defending = defending;}
+
+        /** 
+        * Sets the parked value. Parking entails that this stack is ignored
+         * when a player cycles through his list of stacks with 
+        * Stacklist::getNextMovable().  This value behaves just like 
+        * defending, but there's no bonus conferred if a stack remains in 
+        * this state.
+         */
+       //! Set the parked status of the stack.
+        void setParked(bool parked){d_parked = parked;}
+
+       //! Sets the path object for this stack.
+       void setPath(const Path p);
+
+       //! Set all Army units in the stack to have this fortified state.
+       void setFortified(bool fortified);
+
+
+
+       // Methods that operate on class data and modify the class
+       
+       /**
+        * When the end of a turn occurs, this callback is used to calculate
+        * stack bonuses, moves, paths, and it also charges the player the
+        * upkeep fee for every Army unit in the Stack.
+        */
+        //! Callback when the end of a turn happens.
+        void nextTurn();
+
+        //! Reduces movement points of the Army units in the Stack.
+        void decrementMoves(guint32 moves);
+
+        //! Sets the stack's position to the next point in it's Path.
+        void moveOneStep(bool skipping = false);
+
+        void moveToDest(Vector<int> dest, bool skipping = false);
+
+       /**
+        * Adds one to the strength of each Army unit in the stack.
+        * If the Army unit has already visited the temple co-located with
+        * the stack's position, no strength bonus will be added.
+        *
+        * @return The number of Army units blessed.
+        */
+       //! Bless the Army units in the stack.
+        int bless();
+
+       //! Uncovers some of the hidden map around this stack.
+       void deFog();
+
+        //! Erase the stack, deleting the Army units too.
+        void flClear();
+
+        /** 
+        * Erase an Army unit from the Stack, and free the contents of 
+        * the Army unit too (e.g. Items a Hero might be carrying).
+        *
+        * @param it   The place in the Stack to erase.
+        *
+        * @return The place in the stack that was erased.
+         */
+       //! Erase an Army unit from the list.
+        iterator flErase(iterator object);
+
+       /**
+        * Alter the order of the Army units in the stack according to each
+        * unit's groupedness, and fight order.
+        *
+        * The purpose of this sorting is to show the units in the stack
+        * info window.
+        *
+        * @param reverse     Invert the sort.
+        */
+       //! Sort the Army units in the stack.
+       void sortForViewing(bool reverse);
+
+        void sortByStrength(bool reverse);
+
+       //! Have the stack collect it's upkeep from a given player (owner).
+       void payUpkeep(Player *p);
+
+       //! Merge the given stack with this stack.
+       void join(Stack *join);
+
+       //! Return a new stack that holds the given armies from this stack.
+       Stack *splitArmies(std::list<Army*> armies);
+
+       //! Return a new stack that holds the given armies from this stack.
+       Stack *splitArmies(std::list<guint32> armies);
+
+       // Return a new stack holds the given army from this stack.
+       Stack *splitArmy(Army *army);
+
+       //! Return a new stack that holds armies that have some mp.
+       Stack *splitArmiesWithMovement(guint32 mp = 1);
+
+       //! Add an army to this stack.
+       /**
+        * This method should be used instead of push_back.
+        */
+       void add(Army *army);
+
+       //! Remove this stack's path.  Return true if anything was cleared.
+       bool clearPath();
+
+       // Methods that operate on class and do not modify the class
+
+        //! Returns true if the stack has any points in it's path.
+        bool hasPath() const;
+
+        //! Is there at least one hero in this stack who has a quest?
+        bool hasQuest() const;
+
+        //! Does the stack contain this kind of army?
+        bool hasArmyType(guint32 army_type) const;
+
+        //! Save the stack to an opened saved-game file.
+        bool save(XML_Helper* helper) const;
+
+       /**
+         * @return True if the stack has enough moves to traverse to
+        * the next step in it's Path.  Otherwise, false.
+        */
+       //! Returns whether or not the stack can move.
+        bool enoughMoves() const;
+
+       /**
+        * @return Whether or not the stack has enough moves to travel to
+        *         an adjacent tile.  The adjacent tile does not have to be
+        *         in the stack's Path.
+        */
+       //! Returns whether the stack can move in any direction.
+       bool canMove() const;
+        
+       /**
+        * Scan all adjacent tiles relative to the stack's position and 
+        * see how much a move would cost in terms of movement points.
+        * Determine the minimum amount of movement points to make a move.
+        * 
+        * @return The minimum number of movement points to travel to the
+        *         cheapest adjacent tile that the stack can afford to
+        *         move to.  If the stack cannot afford to move there, this
+        *         method returns -1.
+        */
+        int getMinTileMoves() const;
+
+        //! Return the Army unit in the Stack that has the best strength value.
+        Army* getStrongestArmy() const;
+
+        //! Return the Hero unit in the Stack that has the best strength value.
+        Army* getStrongestHero() const;
+
+       //! Go find the army with this identifier in the stack and return it.
+        Army* getArmyById(guint32 id) const;
+        
+        //! True if the stack contains a Hero unit.  Otherwise, false.
+        bool hasHero() const;
+
+        //! Return the first Hero unit in the stack, or NULL if no Hero found.
+        Army* getFirstHero() const;
+
+        //! Return the first hero unit in the stack that is on a quest.
+        Hero *getFirstHeroWithAQuest() const;
+
+        //! Return the first hero unit in the stack that isn't questing.
+        Hero *getFirstHeroWithoutAQuest() const;
+
+        //! Returns the ids of all (living) heroes in the stack in the dst reference
+       /**
+        * Scan the Army units in the Stack for heroes that have more than
+        * zero hitpoints.
+        *
+        * @param dst       Passed in as an empty or non-empty list, and
+        *                  filled up with the Ids belonging to Hero army 
+        *                  units in the stack.
+        */
+       // Return the Ids of all of the Hero units in the Stack.
+        void getHeroes(std::vector<guint32>& dst) const;
+
+        //! Return the defending status of the stack.
+        bool getDefending() const {return d_defending;}
+
+        //! Return the parked status of the stack.
+        bool getParked() const {return d_parked;}
+
+        //! Returns whether the stack is being deleted.
+        bool getDeleting() const {return d_deleting;}
+
+        //! Return the maximum sight of the stack.
+        guint32 getMaxSight() const;
+
+       /** 
+       * Determine which terrain kinds (Tile::Type) the Stack can travel 
+       * efficiently on.  When one Army unit is good at traveling through 
+       * the forest, and another in the same stack is good at traveling 
+       * through the hills, the movement capabilities of each individual 
+       * army is given to the other Army units in the Stack.  This means 
+       * the whole stack can move well through hills and forest.
+       * Traveling efficently on a tile means it takes 2 movement points
+       * to traverse.
+       *
+       * The calculation also takes into account a movement-changing Item
+       * that the Hero may be carrying (e.g. `Wings of Flying', or 
+       * `Swamp Boots').
+       *
+       * This calculation also lets Hero units `ride' flying Army units;
+       * meaning that the Hero doesn't have the ability to fly, but it
+       * has the special ability to ride on the back of another flying
+       * Army unit.
+       *
+       * @return A bitwise OR-ing of the values in Tile::Type.
+        */
+       //! Calculate the move bonus for the Stack.
+        guint32 calculateMoveBonus() const;
+
+       //! Calculate if the Stack has the gift of flight.
+        bool isFlying () const;
+
+       //! Calculate if the Stack is in a boat.
+        bool hasShip () const;
+
+       /**
+        * Calculate the number of movement points it costs for the Stack
+        * to move to an adjacent tile.
+        *
+        * @note This is not a distance calculation.
+        *
+        * @param pos    The adjacent tile to calculate the movement points for.
+        *
+        * @return The number of movement points, or -1 if moving to the
+        *         adjacent tile is impossible.
+        */
+       //! Return the movement points it costs to travel to an adjacent tile.
+       guint32 calculateTileMovementCost(Vector<int> pos) const;
+
+       //! Returns true if this stack can join the given stack.
+       /**
+        * @note This is not a distance calculation.  It checks to see if
+        * the stack sizes are such that the amalgamated stack would be less
+        * than 8.
+        */
+       bool canJoin(const Stack *stack) const;
+
+       //! Return a list of army Ids in the stack that can reach the given 
+       //! destination.
+       std::list<guint32> determineReachableArmies(Vector<int> dest) const;
+
+        //! Return a list of army ids whose strength totals strength.
+        std::list<guint32> determineWeakArmies(float strength) const;
+        std::list<guint32> determineStrongArmies(float strength) const;
+
+       //! Returns how many armies in the stack have visited the given temple.
+       guint32 countArmiesBlessedAtTemple(guint32 temple_id) const;
+
+       //!If this stack were at the given pos, would it move in/out of a ship?
+       /**
+        * The on_ship paramater holds whether or not the stack is in a ship
+        * at the given position.  This is an out-parameter so that we can
+        * subsequently call this method for a series of points on a path.
+        */
+       bool isMovingToOrFromAShip(Vector<int> dest, bool &on_ship) const;
+
+       //! Get the starting point in the stack's intended path.
+       /**
+        * Returns a position of -1,-1 if there isn't a path.
+        */
+       Vector<int> getFirstPointInPath() const;
+
+       //! Get the final point in the stack's intended path.
+       /**
+        * Returns a position of -1,-1 if there isn't a path.
+        */
+       Vector<int> getLastPointInPath() const;
+
+       //! Gets the final point in the stack's path that we have mp to reach.
+       /**
+        *
+        * This method checks how many movement points the stack currently 
+        * has, and calculates how far along it's intended path it can go.
+        *
+        * Returns the final reachable spot in the path, or returns a 
+        * position of -1,-1 if there isn't a path, or none are reachable.
+        */
+       Vector<int> getLastReachablePointInPath() const;
+
+       //! Does everything in this stack look okay?
+       bool validate() const;
+
+       //! Does this stack have 8 units in it?
+       bool isFull() const;
+
+       // Signals
+
+       //! Emitted when this stack dies.
+        sigc::signal<void, Stack*> sdying;
+
+       //! Emitted when this stack is about to move one step
+       sigc::signal<void, Stack*> smoving;
+
+       //! Emitted when this stack has finished moving that one step
+       sigc::signal<void, Stack*> smoved;
+
+       //! Emitted when this stack is grouped or ungrouped
+       sigc::signal<void, Stack*, bool> sgrouped;
+
+
+       // Static Methods
+        
+       /**
+        * This comparator function compares the fight order of two Army units.
+        *
+        * @param left    An army that we want to sort by fight order.
+        * @param right   An army that we want to sort by fight order.
+        *
+        * @return True if the fight order of the left army is more than
+        *         the fight order of the right army.
+        */
+       //! Comparator function to assist in sorting the armies in the stack.
+       static bool armyCompareFightOrder (const Army *left, const Army *right);
+       static bool armyCompareStrength (const Army *left, const Army *right);
+
+       //! Create a stack with an id that isn't unique.
+       static Stack* createNonUniqueStack(Player *player, Vector<int> pos);
+
+        bool isOnCity() const;
+    private:    
+
+        std::list<guint32> determineArmiesByStrength(bool strongest, float strength) const;
+
+       //! Private constructor.
+       Stack(guint32 id, Player* player, Vector<int> pos);
+
+        //! Callback for loading the object from an opened saved-game file.
+        bool load(std::string tag, XML_Helper* helper);
+    
+       //! Helper method for returning strongest army.
+       Army* getStrongestArmy(bool hero) const;
+
+        // DATA
+
+       //! The stack's intended path.
+        Path* d_path;
+
+       //! Whether or not the stack is defending.
+        bool d_defending;
+
+       //! Whether or not the stack is parked.
+        bool d_parked;
+        
+       /**
+        * True if the stack is currently being deleted. This is neccessary as
+        * some things may happen in the destructor of the contained armies and
+        * we don't want bigmap to draw the stack when it is being removed.
+        */
+       //! Whether or not this stack is in the midst of being deleted.
+        bool d_deleting;
+};
+
+#endif // STACK_H
+
+// End of file