1 // Copyright (C) 2000, 2001, 2003 Michael Bartl
2 // Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Ulf Lorenz
3 // Copyright (C) 2004, 2005, 2006 Andrea Paternesi
4 // Copyright (C) 2007, 2008, 2009 Ben Asselstine
5 // Copyright (C) 2007, 2008 Ole Laursen
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.
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.
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
28 #include <sigc++/trackable.h>
29 #include <sigc++/signal.h>
32 #include "UniquelyIdentified.h"
44 //! A set of up to eight Army units that move as a single entity on the map.
46 * While Army units are the actual troops you command, they always belong to a
47 * stack. The stack holds these armies together in one object. The player
48 * usually doesn't command the armies but the stack, so all functionality and
49 * data which affects player's controls is bundled in the stack class. Among
50 * this is the location of the units, the intended movement path, and more.
53 class Stack : public ::UniquelyIdentified, public Movable, public Ownable, public std::list<Army*>, public sigc::trackable
56 //! The xml tag of this object in a saved-game file.
57 static std::string d_tag;
62 * @param player A pointer to the owning player.
63 * @param pos The position on the map where the stack is to
66 //! Default constructor.
67 Stack(Player* player, Vector<int> pos);
70 * Copy the whole stack into a new stack. This method performs a
71 * deep copy of the stack's Army units.
74 Stack(const Stack& s);
76 //! Loading constructor.
77 Stack(XML_Helper* helper);
84 //! Returns the minimum number of movement points of all Army units.
85 guint32 getMoves() const;
87 //! Returns the maximum MP the stack would have if it were on land
88 guint32 getMaxLandMoves() const;
90 //! Returns the max MP the stack would have if it were in the water
91 guint32 getMaxBoatMoves() const;
93 //! Returns the Path object of the stack.
94 Path* getPath() const {return d_path;}
96 //! Return true if any of the Army units in the stack are fortified.
97 bool getFortified() const;
99 //! Calculate the number of gold pieces this stack costs this turn.
100 guint32 getUpkeep() const;
102 //! How many army units can be put into this stack?
103 guint32 getMaxArmiesToJoin() const;
105 guint32 countAllies() const;
109 //! Change the loyalty of the stack.
110 void setPlayer(Player* p);
113 * Sets the defending value. Defending entails that this stack is
114 * ignored when a user cycles through the list of stacks with
115 * Stacklist::getNextMovable(). If a stack stays defending to the
116 * next round, it gets a fortify bonus in battle.
118 //! Set the defending status of the stack.
119 void setDefending(bool defending){d_defending = defending;}
122 * Sets the parked value. Parking entails that this stack is ignored
123 * when a player cycles through his list of stacks with
124 * Stacklist::getNextMovable(). This value behaves just like
125 * defending, but there's no bonus conferred if a stack remains in
128 //! Set the parked status of the stack.
129 void setParked(bool parked){d_parked = parked;}
131 //! Sets the path object for this stack.
132 void setPath(const Path p);
134 //! Set all Army units in the stack to have this fortified state.
135 void setFortified(bool fortified);
139 // Methods that operate on class data and modify the class
142 * When the end of a turn occurs, this callback is used to calculate
143 * stack bonuses, moves, paths, and it also charges the player the
144 * upkeep fee for every Army unit in the Stack.
146 //! Callback when the end of a turn happens.
149 //! Reduces movement points of the Army units in the Stack.
150 void decrementMoves(guint32 moves);
152 //! Sets the stack's position to the next point in it's Path.
153 void moveOneStep(bool skipping = false);
155 void moveToDest(Vector<int> dest, bool skipping = false);
158 * Adds one to the strength of each Army unit in the stack.
159 * If the Army unit has already visited the temple co-located with
160 * the stack's position, no strength bonus will be added.
162 * @return The number of Army units blessed.
164 //! Bless the Army units in the stack.
167 //! Uncovers some of the hidden map around this stack.
170 //! Erase the stack, deleting the Army units too.
174 * Erase an Army unit from the Stack, and free the contents of
175 * the Army unit too (e.g. Items a Hero might be carrying).
177 * @param it The place in the Stack to erase.
179 * @return The place in the stack that was erased.
181 //! Erase an Army unit from the list.
182 iterator flErase(iterator object);
185 * Alter the order of the Army units in the stack according to each
186 * unit's groupedness, and fight order.
188 * The purpose of this sorting is to show the units in the stack
191 * @param reverse Invert the sort.
193 //! Sort the Army units in the stack.
194 void sortForViewing(bool reverse);
196 void sortByStrength(bool reverse);
198 //! Have the stack collect it's upkeep from a given player (owner).
199 void payUpkeep(Player *p);
201 //! Merge the given stack with this stack.
202 void join(Stack *join);
204 //! Return a new stack that holds the given armies from this stack.
205 Stack *splitArmies(std::list<Army*> armies);
207 //! Return a new stack that holds the given armies from this stack.
208 Stack *splitArmies(std::list<guint32> armies);
210 // Return a new stack holds the given army from this stack.
211 Stack *splitArmy(Army *army);
213 //! Return a new stack that holds armies that have some mp.
214 Stack *splitArmiesWithMovement(guint32 mp = 1);
216 //! Add an army to this stack.
218 * This method should be used instead of push_back.
220 void add(Army *army);
222 //! Remove this stack's path. Return true if anything was cleared.
225 // Methods that operate on class and do not modify the class
227 //! Returns true if the stack has any points in it's path.
228 bool hasPath() const;
230 //! Is there at least one hero in this stack who has a quest?
231 bool hasQuest() const;
233 //! Does the stack contain this kind of army?
234 bool hasArmyType(guint32 army_type) const;
236 //! Save the stack to an opened saved-game file.
237 bool save(XML_Helper* helper) const;
240 * @return True if the stack has enough moves to traverse to
241 * the next step in it's Path. Otherwise, false.
243 //! Returns whether or not the stack can move.
244 bool enoughMoves() const;
247 * @return Whether or not the stack has enough moves to travel to
248 * an adjacent tile. The adjacent tile does not have to be
249 * in the stack's Path.
251 //! Returns whether the stack can move in any direction.
252 bool canMove() const;
255 * Scan all adjacent tiles relative to the stack's position and
256 * see how much a move would cost in terms of movement points.
257 * Determine the minimum amount of movement points to make a move.
259 * @return The minimum number of movement points to travel to the
260 * cheapest adjacent tile that the stack can afford to
261 * move to. If the stack cannot afford to move there, this
264 int getMinTileMoves() const;
266 //! Return the Army unit in the Stack that has the best strength value.
267 Army* getStrongestArmy() const;
269 //! Return the Hero unit in the Stack that has the best strength value.
270 Army* getStrongestHero() const;
272 //! Go find the army with this identifier in the stack and return it.
273 Army* getArmyById(guint32 id) const;
275 //! True if the stack contains a Hero unit. Otherwise, false.
276 bool hasHero() const;
278 //! Return the first Hero unit in the stack, or NULL if no Hero found.
279 Army* getFirstHero() const;
281 //! Return the first hero unit in the stack that is on a quest.
282 Hero *getFirstHeroWithAQuest() const;
284 //! Return the first hero unit in the stack that isn't questing.
285 Hero *getFirstHeroWithoutAQuest() const;
287 //! Returns the ids of all (living) heroes in the stack in the dst reference
289 * Scan the Army units in the Stack for heroes that have more than
292 * @param dst Passed in as an empty or non-empty list, and
293 * filled up with the Ids belonging to Hero army
294 * units in the stack.
296 // Return the Ids of all of the Hero units in the Stack.
297 void getHeroes(std::vector<guint32>& dst) const;
299 //! Return the defending status of the stack.
300 bool getDefending() const {return d_defending;}
302 //! Return the parked status of the stack.
303 bool getParked() const {return d_parked;}
305 //! Returns whether the stack is being deleted.
306 bool getDeleting() const {return d_deleting;}
308 //! Return the maximum sight of the stack.
309 guint32 getMaxSight() const;
312 * Determine which terrain kinds (Tile::Type) the Stack can travel
313 * efficiently on. When one Army unit is good at traveling through
314 * the forest, and another in the same stack is good at traveling
315 * through the hills, the movement capabilities of each individual
316 * army is given to the other Army units in the Stack. This means
317 * the whole stack can move well through hills and forest.
318 * Traveling efficently on a tile means it takes 2 movement points
321 * The calculation also takes into account a movement-changing Item
322 * that the Hero may be carrying (e.g. `Wings of Flying', or
325 * This calculation also lets Hero units `ride' flying Army units;
326 * meaning that the Hero doesn't have the ability to fly, but it
327 * has the special ability to ride on the back of another flying
330 * @return A bitwise OR-ing of the values in Tile::Type.
332 //! Calculate the move bonus for the Stack.
333 guint32 calculateMoveBonus() const;
335 //! Calculate if the Stack has the gift of flight.
336 bool isFlying () const;
338 //! Calculate if the Stack is in a boat.
339 bool hasShip () const;
342 * Calculate the number of movement points it costs for the Stack
343 * to move to an adjacent tile.
345 * @note This is not a distance calculation.
347 * @param pos The adjacent tile to calculate the movement points for.
349 * @return The number of movement points, or -1 if moving to the
350 * adjacent tile is impossible.
352 //! Return the movement points it costs to travel to an adjacent tile.
353 guint32 calculateTileMovementCost(Vector<int> pos) const;
355 //! Returns true if this stack can join the given stack.
357 * @note This is not a distance calculation. It checks to see if
358 * the stack sizes are such that the amalgamated stack would be less
361 bool canJoin(const Stack *stack) const;
363 //! Return a list of army Ids in the stack that can reach the given
365 std::list<guint32> determineReachableArmies(Vector<int> dest) const;
367 //! Return a list of army ids whose strength totals strength.
368 std::list<guint32> determineWeakArmies(float strength) const;
369 std::list<guint32> determineStrongArmies(float strength) const;
371 //! Returns how many armies in the stack have visited the given temple.
372 guint32 countArmiesBlessedAtTemple(guint32 temple_id) const;
374 //!If this stack were at the given pos, would it move in/out of a ship?
376 * The on_ship paramater holds whether or not the stack is in a ship
377 * at the given position. This is an out-parameter so that we can
378 * subsequently call this method for a series of points on a path.
380 bool isMovingToOrFromAShip(Vector<int> dest, bool &on_ship) const;
382 //! Get the starting point in the stack's intended path.
384 * Returns a position of -1,-1 if there isn't a path.
386 Vector<int> getFirstPointInPath() const;
388 //! Get the final point in the stack's intended path.
390 * Returns a position of -1,-1 if there isn't a path.
392 Vector<int> getLastPointInPath() const;
394 //! Gets the final point in the stack's path that we have mp to reach.
397 * This method checks how many movement points the stack currently
398 * has, and calculates how far along it's intended path it can go.
400 * Returns the final reachable spot in the path, or returns a
401 * position of -1,-1 if there isn't a path, or none are reachable.
403 Vector<int> getLastReachablePointInPath() const;
405 //! Does everything in this stack look okay?
406 bool validate() const;
408 //! Does this stack have 8 units in it?
413 //! Emitted when this stack dies.
414 sigc::signal<void, Stack*> sdying;
416 //! Emitted when this stack is about to move one step
417 sigc::signal<void, Stack*> smoving;
419 //! Emitted when this stack has finished moving that one step
420 sigc::signal<void, Stack*> smoved;
422 //! Emitted when this stack is grouped or ungrouped
423 sigc::signal<void, Stack*, bool> sgrouped;
429 * This comparator function compares the fight order of two Army units.
431 * @param left An army that we want to sort by fight order.
432 * @param right An army that we want to sort by fight order.
434 * @return True if the fight order of the left army is more than
435 * the fight order of the right army.
437 //! Comparator function to assist in sorting the armies in the stack.
438 static bool armyCompareFightOrder (const Army *left, const Army *right);
439 static bool armyCompareStrength (const Army *left, const Army *right);
441 //! Create a stack with an id that isn't unique.
442 static Stack* createNonUniqueStack(Player *player, Vector<int> pos);
444 bool isOnCity() const;
447 std::list<guint32> determineArmiesByStrength(bool strongest, float strength) const;
449 //! Private constructor.
450 Stack(guint32 id, Player* player, Vector<int> pos);
452 //! Callback for loading the object from an opened saved-game file.
453 bool load(std::string tag, XML_Helper* helper);
455 //! Helper method for returning strongest army.
456 Army* getStrongestArmy(bool hero) const;
460 //! The stack's intended path.
463 //! Whether or not the stack is defending.
466 //! Whether or not the stack is parked.
470 * True if the stack is currently being deleted. This is neccessary as
471 * some things may happen in the destructor of the contained armies and
472 * we don't want bigmap to draw the stack when it is being removed.
474 //! Whether or not this stack is in the midst of being deleted.