22
29
#include <sigc++/signal.h>
32
#include "UniquelyIdentified.h"
32
/** Group of up to eight armies
34
* While armies are the actual troops you command, they always belong to a
35
* stack. The stack holds these armies together in one object. The player
36
* usually doesn't command the armies but the stack, so all functionality and
37
* data which affects player's controls is bundled in the stack class. Among
38
* this is the location of the units, the movement etc.
41
//! A set of up to eight Army units that move as a single entity on the map.
43
* While Army units are the actual troops you command, they always belong to a
44
* stack. The stack holds these armies together in one object. The player
45
* usually doesn't command the armies but the stack, so all functionality and
46
* data which affects player's controls is bundled in the stack class. Among
47
* this is the location of the units, the intended movement path, and more.
41
class Stack : public ::Object, public std::list<Army*>, public sigc::trackable
50
class Stack : public ::UniquelyIdentified, public Movable, public Ownable, public std::list<Army*>, public sigc::trackable
44
/** Default constructor
46
* @param player the owning player or 0 if e.g. ruin keeper
47
* @param pos the position where the stack is created
56
* @param player A pointer to the owning player.
57
* @param pos The position on the map where the stack is to
60
//! Default constructor.
49
61
Stack(Player* player, Vector<int> pos);
51
//! Copy constructor, it does a deep copy of the other stack's armies!
64
* Copy the whole stack into a new stack. This method performs a
65
* deep copy of the stack's Army units.
54
//! Loading constructor. See XML_Helper for details
70
//! Loading constructor.
55
71
Stack(XML_Helper* helper);
59
//! In rare cases it may be wanted to change the stack's loyality...
76
//! Change the loyalty of the stack.
60
77
void setPlayer(Player* p);
62
//! ...or its position (for testing reasons)
63
void setPosition(Vector<int> pos){d_pos = pos;}
65
/** Sets the defending value. Defending means that this stack is ignored
66
* when a player cycles through his list of stacks with Stack::setNext().
67
* If a stack stays defending, it gets a fortify bonus.
68
* (this isn't implemented yet) fixme
80
* Sets the defending value. Defending entails that this stack is
81
* ignored when a user cycles through the list of stacks with
82
* Stacklist::getNextMovable(). If a stack stays defending to the
83
* next round, it gets a fortify bonus in battle.
85
//! Set the defending status of the stack.
70
86
void setDefending(bool defending){d_defending = defending;}
71
/** Sets the parked value. Parked means that this stack is ignored
72
* when a player cycles through his list of stacks with Stack::setNext().
73
* this is just like defending, but there's no bonus conferred if
74
* a stack remains in this state.
89
* Sets the parked value. Parking entails that this stack is ignored
90
* when a player cycles through his list of stacks with
91
* Stacklist::getNextMovable(). This value behaves just like
92
* defending, but there's no bonus conferred if a stack remains in
95
//! Set the parked status of the stack.
76
96
void setParked(bool parked){d_parked = parked;}
79
//! Save the stack's data. See XML_Helper for more details.
98
//! Save the stack to an opened saved-game file.
80
99
bool save(XML_Helper* helper) const;
82
//! Heals the armies of the stack etc.
102
* When the end of a turn occurs, this callback is used to calculate
103
* stack bonuses, moves, paths, and it also charges the player the
104
* upkeep fee for every Army unit in the Stack.
106
//! Callback when the end of a turn happens.
85
//! Reduces movement points of the armies.
109
//! Reduces movement points of the Army units in the Stack.
86
110
void decrementMoves(Uint32 moves);
88
//! Sets the stack's position to the next item of the internal path
91
//! Blesses all armies of the stack (strength +1)
92
//! Returns the number of blessed armies.
112
//! Sets the stack's position to the next point in it's Path.
115
void moveToDest(Vector<int> dest);
118
* Adds one to the strength of each Army unit in the stack.
119
* If the Army unit has already visited the temple co-located with
120
* the stack's position, no strength bonus will be added.
122
* @return The number of Army units blessed.
124
//! Bless the Army units in the stack.
95
//! Returns whether the stack has enough moves for the next step
128
* @return True if the stack has enough moves to traverse to
129
* the next step in it's Path. Otherwise, false.
131
//! Returns whether or not the stack can move.
96
132
bool enoughMoves() const;
98
// returns whether the stack can move in any direction
135
* @return Whether or not the stack has enough moves to travel to
136
* an adjacent tile. The adjacent tile does not have to be
137
* in the stack's Path.
139
//! Returns whether the stack can move in any direction.
99
140
bool canMove() const;
101
//! Returns the owning player
102
Player* getPlayer() const {return d_player;}
104
//! Returns the internal path object of the stack
142
//! Returns the Path object of the stack.
105
143
Path* getPath() const {return d_path;}
107
//! Returns the minimum number of MP of all armies
145
//! Returns the minimum number of movement points of all Army units.
108
146
Uint32 getGroupMoves() const;
110
//! Returns true if all armies in the stack are grouped
148
//! Returns true if all Army units in the stack are grouped.
111
149
bool isGrouped();
113
//! Returns the minimum number of MP of all tiles around the stack, or
114
// -1 if the stack can't move
152
* Scan all adjacent tiles relative to the stack's position and
153
* see how much a move would cost in terms of movement points.
154
* Determine the minimum amount of movement points to make a move.
156
* @return The minimum number of movement points to travel to the
157
* cheapest adjacent tile that the stack can afford to
158
* move to. If the stack cannot afford to move there, this
115
161
int getMinTileMoves() const;
117
//! Get the next item of the stack's path
163
//! Get the next position in the stack's intended Path.
118
164
Vector<int> nextStep();
120
//! Get the strongest army (most strength) for displaying
166
//! Return the Army unit in the Stack that has the best strength value.
121
167
Army* getStrongestArmy() const;
123
//! Get the strongest hero (most strength) for bonus calculations
169
//! Return the Hero unit in the Stack that has the best strength value.
124
170
Army* getStrongestHero() const;
125
// FIXME: reconcile these "strongest" functions into one
127
//! Used for splitting stacks. See Player::stackSplit how it works.
173
* Scan through the Army units in the stack and return the first
174
* one that is ungrouped. This method is used for splitting stacks.
175
* See Player::stackSplit for more information.
177
* @return A pointer to the first ungrouped army in the stack or NULL
178
* if an ungrouped Army unit could not be found.
180
//! Get the first ungrouped Army unit in the Stack.
128
181
Army* getFirstUngroupedArmy() const;
130
//! True if the stack has a hero. They add strength to the other armies.
183
Army* getArmyById(Uint32 id) const;
185
//! True if the stack contains a Hero unit. Otherwise, false.
131
186
bool hasHero() const;
133
//! Return the first hero in the stack
188
//! Return the first Hero unit in the stack, or NULL if no Hero found.
134
189
Army* getFirstHero() const;
136
191
//! Returns the ids of all (living) heroes in the stack in the dst reference
193
* Scan the Army units in the Stack for heroes that have more than
196
* @param dst Passed in as an empty or non-empty list, and
197
* filled up with the Ids belonging to Hero army
198
* units in the stack.
200
// Return the Ids of all of the Hero units in the Stack.
137
201
void getHeroes(std::vector<Uint32>& dst) const;
139
//! Return true if the stack belongs to player or his allies
140
bool isFriend(Player* player) const;
142
//! Return the defending status of the stack (see setDefending)
203
//! Return the defending status of the stack.
143
204
bool getDefending() const {return d_defending;}
144
//! Return the parked status of the stack (see setParked)
206
//! Return the parked status of the stack.
145
207
bool getParked() const {return d_parked;}
147
//! Returns whether the stack is being deleted (set to true in the destructor)
209
//! Returns whether the stack is being deleted.
148
210
bool getDeleting() const {return d_deleting;}
150
//! Return the maximum sight of the stack
212
//! Return the maximum sight of the stack.
151
213
Uint32 getMaxSight() const;
154
//! The same as std::list::clear, but alse frees pointers
215
//! Erase the stack, deleting the Army units too.
157
//! The same as std::list::erase, but also frees pointers
219
* Erase an Army unit from the Stack, and free the contents of
220
* the Army unit too (e.g. Items a Hero might be carrying).
222
* @param it The place in the Stack to erase.
224
* @return The place in the stack that was erased.
226
//! Erase an Army unit from the list.
158
227
iterator flErase(iterator object);
160
/** Calculates group move bonuses.
230
* Determine which terrain kinds (Tile::Type) the Stack can travel
231
* efficiently on. When one Army unit is good at traveling through
232
* the forest, and another in the same stack is good at traveling
233
* through the hills, the movement capabilities of each individual
234
* army is given to the other Army units in the Stack. This means
235
* the whole stack can move well through hills and forest.
236
* Traveling efficently on a tile means it takes 2 movement points
239
* The calculation also takes into account a movement-changing Item
240
* that the Hero may be carrying (e.g. `Wings of Flying', or
243
* This calculation also lets Hero units `ride' flying Army units;
244
* meaning that the Hero doesn't have the ability to fly, but it
245
* has the special ability to ride on the back of another flying
248
* @return A bitwise OR-ing of the values in Tile::Type.
250
//! Calculate the move bonus for the Stack.
163
251
Uint32 calculateMoveBonus() const;
253
//! Calculate if the Stack has the gift of flight.
164
254
bool isFlying () const;
256
//! Calculate if the Stack is in a boat.
165
257
bool hasShip () const;
167
//! how much does it cost in movement points for the stack
168
//to move to move onto a tile that has the characteristics of the
169
//tile located at POS. (this is not a distance calculation)
260
* Calculate the number of movement points it costs for the Stack
261
* to move to an adjacent tile.
263
* @note This is not a distance calculation.
265
* @param pos The adjacent tile to calculate the movement points for.
267
* @return The number of movement points, or -1 if moving to the
268
* adjacent tile is impossible.
270
//! Return the movement points it costs to travel to an adjacent tile.
170
271
Uint32 calculateTileMovementCost(Vector<int> pos) const;
172
sigc::signal<void, Stack*> sdying;
273
//! Set each Army unit in the Stack to a grouped state.
276
//! Set all armies in the Stack except the first one to be ungrouped.
280
* Alter the order of the Army units in the stack according to each
281
* unit's groupedness, and fight order.
283
* The purpose of this sorting is to show the units in the stack
286
* @param reverse Invert the sort.
288
//! Sort the Army units in the stack.
176
289
void sortForViewing(bool reverse);
291
//! Set all Army units in the stack to have this fortified state.
177
292
void setFortified(bool fortified);
294
//! Return true if any of the Army units in the stack are fortified.
178
295
bool getFortified();
297
//! Calculate the number of gold pieces this stack costs this turn.
179
298
Uint32 getUpkeep();
181
static bool armyCompareFightOrder (const Army *, const Army *);
182
Uint32 getMovesExhaustedAtPoint() {return d_moves_exhausted_at_point;}
183
void setMovesExhaustedAtPoint(Uint32 index) {d_moves_exhausted_at_point = index;}
301
* This comparator function compares the fight order of two Army units.
303
* @param left An army that we want to sort by fight order.
304
* @param right An army that we want to sort by fight order.
306
* @return True if the fight order of the left army is more than
307
* the fight order of the right army.
309
//! Comparator function to assist in sorting the armies in the stack.
310
static bool armyCompareFightOrder (const Army *left, const Army *right);
312
//! Emitted when a stack dies.
313
sigc::signal<void, Stack*> sdying;
185
317
//! Callback for loading the stack
186
318
bool load(std::string tag, XML_Helper* helper);
320
//! Helper method for returning strongest army.
321
Army* getStrongestArmy(bool hero) const;
324
//! The stack's intended path.
326
//! Whether or not the stack is defending.
191
327
bool d_defending;
328
//! Whether or not the stack is parked.
194
// true if the stack is currently being deleted. This is neccessary as
195
// some things may happen in the destructor of the contained armies and
196
// we don't want bigmap to draw the stack when it is being removed.
332
* True if the stack is currently being deleted. This is neccessary as
333
* some things may happen in the destructor of the contained armies and
334
* we don't want bigmap to draw the stack when it is being removed.
336
//! Whether or not this stack is in the midst of being deleted.
198
Uint32 d_moves_exhausted_at_point;
201
340
#endif // STACK_H