1 // Copyright (C) 2000, 2001, 2002, 2003 Michael Bartl
2 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Ulf Lorenz
3 // Copyright (C) 2004, 2005 Andrea Paternesi
4 // Copyright (C) 2004 Andrea Paternesi
5 // Copyright (C) 2007, 2008, 2009 Ben Asselstine
6 // Copyright (C) 2008 Ole Laursen
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.
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.
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
30 #include <sigc++/trackable.h>
34 #include <sigc++/signal.h>
42 //! A list of Stack objects for a single player.
44 * All stacks owned by a Player are contained in a Stacklist. This class
45 * covers the loading and saving of stack lists, and also some methods for
46 * getting and managing groups of stacks.
49 class Stacklist : public std::list<Stack*>, public sigc::trackable
53 //! The xml tag of this object in a saved-game file.
54 static std::string d_tag;
56 //! Default constructor.
60 Stacklist(Stacklist *stacklist);
62 //! Loading constructor.
63 Stacklist(XML_Helper* helper);
70 //!Set the stack the player is currently working with.
72 * Sets the currently selected stack. The purpose of this method is
73 * to designate a stack to be the one the player is currently touching.
74 * It is important to use this method because several functions
75 * expect that there is an active stack.
77 * @param activestack The stack currently selected by the player.
79 void setActivestack(Stack* activestack);
84 //! Returns the currently selected stack.
85 Stack* getActivestack() const {return d_activestack;}
88 // Methods that operate on class data and do not modify the class.
91 * This method finds stacks which occupy the same tile.
92 * For internal and logical reasons, we always assume that a tile is
93 * occupied by at most one stack as strange bugs may happen when this
94 * is violated. However, in some cases, it does happen that stacks
95 * temporarily occupy the same tile. Reasons may be that, on its
96 * route, a stack crosses another stacks tile and can't move further.
98 * We only expect one ambiguity at a time with stacks of the same
99 * player. This never happens except when a stack comes to halt on
100 * another stack during long movements.
102 * @param stack The stack which we search an ambiguity for.
104 * @return The other stack on the same tile occupied by stack.
106 //! Get the other stack on a tile that has more than one stack on it.
107 static Stack* getAmbiguity(Stack* stack);
109 //! Returns the total number of armies in the list.
110 unsigned int countArmies() const;
112 //! Returns the total number of armies in the list that are awardable.
113 unsigned int countAllies() const;
116 * Scan through the list of stacks to find one that is not defending,
117 * and not parked, and can move to another tile.
119 * @return A pointer to the next moveable stack or NULL if no more
122 //! Return the next moveable stack in the list.
123 Stack* getNextMovable() const;
126 * @return True if any stacks in the list have enough moves for
127 * it's next step along it's Path. Otherwise, false.
129 //! Returns whether or not any stacks can move.
130 bool enoughMoves() const;
132 //! Save the data to an opened saved-game file.
133 bool save(XML_Helper* helper) const;
135 //! Find a stack in this stacklist given this id.
136 Stack *getStackById(guint32 id) const;
138 //! Find the stack in this stacklist that contains an army with this id.
139 Stack *getArmyStackById(guint32 army) const;
141 //! Collect gold pieces from army units in the list that give money.
143 * Heroes in a stacklist can provide gold pieces by carrying items.
144 * These items are +3 gold per city, etc so the number of cities
145 * must be passed into this method.
147 * This method increases the given player's treasury.
149 void collectTaxes(Player *p, guint32 num_cities) const;
151 //! Return a list of the heroes in the stacklist.
152 std::list<Hero*> getHeroes() const;
154 //! Return a hero from this stacklist that is closest to the given pos.
156 * The hero must be within a given distance, provided by the dist
157 * parameter. The distance is measured in tiles (not movement points).
159 Hero *getNearestHero(Vector<int> pos, int dist) const;
162 // Methods that operate on class data and modify the class.
164 //! remove all movement points from every army in every stack.
165 void drainAllMovement();
167 //! Callback method executed at the end of every turn.
170 //! Have everyone in this stacklist collect their upkeep from a player.
172 * This method decreases the given player's treasury.
174 void payUpkeep(Player *p);
176 //! Erase all stacks from the list, and their contents too.
179 //! Add a stack to the list.
180 void add(Stack *stack);
183 * Erase a Stack from the list, and free the contents of the Stack.
185 * @param it The place in the Stacklist to erase.
187 * @return The place in the list that was erased.
189 //! Erase a stack from the list.
190 iterator flErase(iterator object);
193 * Scan the list of stacks for a particular stack. If it is found,
194 * remove it from the list of stacks and free it's contents.
196 * @param stack The stack in the Stacklist to remove.
198 * @return Whether or not the stack was found and deleted.
200 //! Erase a stack from the list.
201 bool flRemove(Stack* stack);
203 //! Erase a stack from the list, given the stack id.
204 bool flRemove(guint32 id);
209 //! The stack in the stacklist has been grouped or ungrouped.
210 sigc::signal<void, Stack*, bool> sgrouped;
212 //! The stack in the stacklist is arriving on a new tile.
213 sigc::signal<void, Stack*, Vector<int> > snewpos;
215 //! The stack in the stacklist is leaving an old tile.
216 sigc::signal<void, Stack*, Vector<int> > soldpos;
221 //! Searches through the all players Stacklists and deletes the stack.
222 static bool deleteStack(Stack* stack);
224 //! Searches for the stack id in all lists, and deletes it.
225 static bool deleteStack(guint32 id);
228 * Scan each tile occupied by the given city and return a list of
229 * stacks who are in the city.
231 * When a city is attacked, all stacks which occupy a city tile are
232 * regarded as defenders. The purpose of this function is to
233 * enumerate the defending stacks when a stack has attacked a city.
235 * @param city The city to search for stacks in.
237 * @return A list of all stacks defending the city.
239 //! Return a list of stacks defending a city.
240 static std::vector<Stack*> getDefendersInCity(const City* city);
242 //! Returns the total number of stacks owned by all players.
243 static unsigned int getNoOfStacks();
245 //! Returns the total number of armies owned by all players.
246 static unsigned int getNoOfArmies();
249 * This method removes the given stack from it's owner's stacklist and
250 * places it in the new owner's stacklist.
252 //! Change allegience of the given stack to a new owner.
253 static void changeOwnership(Stack *stack, Player *new_owner);
255 //! Can this stack reach a point where it is not blocked by friendlies?
257 * The idea here is that the stack is blocked by a friendly stack on
258 * it's path. This method checks to see if the stack has enough
259 * movement points to proceed through the friendly stacks (that are
260 * too big to join with), and land on a point in it's path beyond it.
262 static bool canJumpOverTooLargeStack(Stack *s);
264 //! Return position of an Army with the given id in this stacklist.
266 * Scan through all stacks in the list, and then through each Army
267 * unit of every Stack for an Army unit with a particular Id.
269 * @param id The Id of the Army unit that we're looking for.
271 * @return The position of the Army unit. If no Army unit could be
272 * found with the given Id, the position of (-1,-1) is
275 static Vector<int> getPosition(guint32 id);
278 std::list<Vector<int> > getPositions() const;
281 //! Callback for loading this object from an opened saved-game file.
282 bool load(std::string tag, XML_Helper* helper);
284 //! Callback for when a stack initiates movement after being stopped.
285 void on_stack_starts_moving (Stack *s);
287 //! Callback for when a stack halts.
288 void on_stack_stops_moving (Stack *s);
290 //! Callback for when a stack has been killed, or disbanded.
291 void on_stack_died (Stack *stack);
293 //! Callback for when a stack has been grouped or ungrouped.
294 void on_stack_grouped (Stack *stack, bool grouped);
296 void getHeroes(std::vector<guint32>& dst) const;
298 //! Notify the game map that a stack is leaving it's tile.
299 bool deletePositionFromMap(Stack *stack);
301 //! Notify the game map that a stack is arriving on a tile.
302 bool addPositionToMap(Stack *s);
306 //! A pointer to the currently selected Stack.
307 Stack* d_activestack;
309 typedef std::map<Stack *, std::list<sigc::connection> > ConnectionMap;
310 // A set of signal connections for each stack in our list.
312 * We can use this map to lookup the outstanding signals connections
313 * that a given stack has. This is so that we can destroy them
314 * when the stack is deleted.
316 ConnectionMap d_connections;
318 typedef std::map<guint32, Stack*> IdMap;
319 //! A map to quickly lookup the stack by it's unique id.
324 #endif // STACKLIST_H