1
// Copyright (C) 2000, 2001, 2002, 2003 Michael Bartl
2
// Copyright (C) 2000, Anluan O'Brien
3
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Ulf Lorenz
4
// Copyright (C) 2004 John Farrell
5
// Copyright (C) 2004, 2005 Andrea Paternesi
6
// Copyright (C) 2006, 2007, 2008 Ben Asselstine
7
// Copyright (C) 2007, 2008 Ole Laursen
1
9
// This program is free software; you can redistribute it and/or modify
2
10
// it under the terms of the GNU General Public License as published by
3
11
// the Free Software Foundation; either version 2 of the License, or
11
19
// You should have received a copy of the GNU General Public License
12
20
// along with this program; if not, write to the Free Software
13
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15
24
#include <sigc++/functors/mem_fun.h>
16
25
#include <assert.h>
36
49
Stack::Stack(Player* player, Vector<int> pos)
37
: Object(pos), d_player(player), d_defending(false), d_parked(false),
38
d_deleting(false), d_moves_exhausted_at_point(0)
50
: UniquelyIdentified(), Movable(pos), Ownable(player), d_defending(false),
51
d_parked(false), d_deleting(false)
40
53
d_path = new Path();
43
56
Stack::Stack(Stack& s)
44
: Object(s), d_player(s.d_player), d_defending(s.d_defending),
45
d_parked(s.d_parked), d_deleting(false),
46
d_moves_exhausted_at_point(s.d_moves_exhausted_at_point)
57
: UniquelyIdentified(s), Movable(s), Ownable(s),
58
d_defending(s.d_defending), d_parked(s.d_parked), d_deleting(false)
49
61
d_path = new Path();
50
62
//deep copy the other stack's armies
51
64
for (iterator sit = s.begin(); sit != s.end(); sit++)
62
a = new Army((**sit), (*sit)->getPlayer());
75
a = new Army((**sit), (*sit)->getOwner());
68
81
Stack::Stack(XML_Helper* helper)
69
: Object(helper), d_deleting(false)
82
: UniquelyIdentified(helper), Movable(helper), Ownable(helper),
71
85
helper->getData(d_defending, "defending");
72
86
helper->getData(d_parked, "parked");
75
helper->getData(i, "player");
79
d_player = Playerlist::getInstance()->getPlayer(i);
81
helper->getData(d_moves_exhausted_at_point, "moves_exhausted_at_point");
83
88
helper->registerTag("path", sigc::mem_fun((*this), &Stack::load));
84
89
helper->registerTag("army", sigc::mem_fun((*this), &Stack::load));
85
90
helper->registerTag("hero", sigc::mem_fun((*this), &Stack::load));
97
102
void Stack::setPlayer(Player* p)
99
104
// we need to change the armies' loyalties as well!!
101
106
for (iterator it = begin(); it != end(); it++)
105
bool Stack::moveOneStep()
110
void Stack::moveOneStep()
107
112
debug("move_one_step()");
109
d_pos = **d_path->begin();
114
Vector<int> dest = *getPath()->front();
117
//now remove first point of the path
118
d_path->eraseFirstPoint();
121
void Stack::moveToDest(Vector<int> dest)
123
Vector<int> pos = getPos();
125
Uint32 maptype = GameMap::getInstance()->getTile(dest.x,dest.y)->getMaptileType();
126
City* to_city = Citylist::getInstance()->getObjectAt(dest.x, dest.y);
127
City* on_city = Citylist::getInstance()->getObjectAt(pos.x, pos.y);
128
Port* on_port = Portlist::getInstance()->getObjectAt(pos.x, pos.y);
129
bool on_water = (GameMap::getInstance()->getTile(pos.x,pos.y)->getMaptileType() == Tile::WATER);
130
bool to_water = (GameMap::getInstance()->getTile(dest.x,dest.y)->getMaptileType() == Tile::WATER);
131
bool ship_load_unload = false;
132
//here we mark the armies as being on or off a boat
135
if ((on_water && to_city) ||
136
(on_water && on_port && !to_water) ||
137
((on_city || on_port) && to_water))
139
ship_load_unload = true;
140
for (Stack::iterator it = begin(); it != end(); it++)
143
((*it)->getStat(Army::MOVE_BONUS) & Tile::WATER) == 0)
144
(*it)->setInShip(true);
146
(*it)->setInShip(false);
152
for (Stack::iterator it = begin(); it != end(); it++)
153
(*it)->setInShip(false);
156
//how many moves does the stack need to travel to dest?
157
int needed_moves = calculateTileMovementCost(dest);
159
for (Stack::iterator it = begin(); it != end(); it++)
161
if (ship_load_unload)
162
(*it)->decrementMoves((*it)->getMoves());
165
//maybe the army has a natural movement ability
166
if ((*it)->getStat(Army::MOVE_BONUS) & maptype && needed_moves > 1)
167
(*it)->decrementMoves(2);
169
(*it)->decrementMoves(needed_moves);
173
//update position and status
111
176
setFortified(false);
112
177
setDefending(false);
113
178
setParked(false);
115
//now remove first point of the path
116
d_path->flErase(d_path->begin());
118
//and decrement the point at which we exhaust our path
119
if (getMovesExhaustedAtPoint())
120
setMovesExhaustedAtPoint(getMovesExhaustedAtPoint()-1);
181
getOwner()->getFogMap()->alterFogRadius(dest, getMaxSight(), FogMap::OPEN);
125
184
bool Stack::isGrouped()
161
220
int Stack::getMinTileMoves() const
163
222
GameMap *map = GameMap::getInstance();
164
Rectangle bounds = GameMap::get_boundary();
223
Rectangle bounds = map->get_boundary();
166
225
std::vector<Vector<int> > tiles;
167
226
tiles.push_back(Vector<int>(getPos().x + 1, getPos().y - 1));
208
267
Army* Stack::getStrongestArmy() const
210
269
assert(!empty());
212
Uint32 highest_strength = 0;
214
for (const_iterator it = begin(); it != end(); ++it)
221
else if ((*it)->getStat(Army::STRENGTH) > highest_strength)
223
highest_strength = (*it)->getStat(Army::STRENGTH);
270
return getStrongestArmy(false);
230
273
Army* Stack::getStrongestHero() const
275
return getStrongestArmy(true);
278
Army* Stack::getStrongestArmy(bool hero) const
232
280
Army *strongest = 0;
233
281
Uint32 highest_strength = 0;
235
283
for (const_iterator it = begin(); it != end(); ++it)
285
if ((*it)->isHero() && hero || !hero)
240
287
if ((*it)->getStat(Army::STRENGTH) > highest_strength)
313
380
Maptile* tile = GameMap::getInstance()->getTile(pos);
314
381
Uint32 moves = tile->getMoves();
315
if (isFlying() && moves > 1)
382
Uint32 bonus = calculateMoveBonus();
383
if (bonus & tile->getMaptileType() && moves > 1)
385
else if (isFlying() && moves > 1)
320
390
bool Stack::enoughMoves() const
392
if (d_path->size() == 0)
393
return true; //we have enough moves to move nowhere!
322
395
Vector<int> p = **(d_path->begin());
323
396
Uint32 needed = calculateTileMovementCost(p);
430
499
retval &= helper->openTag("stack");
431
500
retval &= helper->saveData("id", d_id);
433
retval &= helper->saveData("player", d_player->getId());
501
retval &= helper->saveData("x", getPos().x);
502
retval &= helper->saveData("y", getPos().y);
504
retval &= helper->saveData("owner", d_owner->getId());
435
retval &= helper->saveData("player", -1);
436
retval &= helper->saveData("x", d_pos.x);
437
retval &= helper->saveData("y", d_pos.y);
506
retval &= helper->saveData("owner", -1);
438
507
retval &= helper->saveData("defending", d_defending);
439
508
retval &= helper->saveData("parked", d_parked);
441
retval &= helper->saveData("moves_exhausted_at_point",
442
d_moves_exhausted_at_point);
445
512
retval &= d_path->save(helper);
610
677
bool Stack::armyCompareFightOrder (const Army *lhs, const Army *rhs)
612
std::list<Uint32> lhs_fight_order = lhs->getPlayer()->getFightOrder();
613
std::list<Uint32> rhs_fight_order = rhs->getPlayer()->getFightOrder();
679
std::list<Uint32> lhs_fight_order = lhs->getOwner()->getFightOrder();
680
std::list<Uint32> rhs_fight_order = rhs->getOwner()->getFightOrder();
614
681
Uint32 lhs_rank = getFightOrder (lhs_fight_order, lhs->getType());
615
682
Uint32 rhs_rank = getFightOrder (rhs_fight_order, rhs->getType());
616
683
//if (lhs_rank == rhs_rank)
661
728
upkeep += (*it)->getUpkeep();
732
bool Stack::canJoin(const Stack *stack) const
734
Uint32 joinSize = countGroupedArmies();
738
/* this is necessary because human players "group" armies in stacks,
739
* while the computer player does not.
741
if ((stack->size() + joinSize) > MAX_STACK_SIZE)
748
std::vector<Uint32> Stack::determineReachableArmies(Vector<int> dest)
750
std::vector<Uint32> ids;
751
//try each army individually to see if it reaches
752
for (iterator it = begin(); it != end(); it++)
754
if ((*it)->getMoves() > 0)
756
Stack *stack = new Stack(getOwner(), getPos());
757
stack->push_back(*it);
758
if (stack->getGroupMoves() >=
759
stack->getPath()->calculate(stack, dest))
760
ids.push_back((*it)->getId());
763
//fixme: can't delete stacks like this because it deletes the army
769
//now try to see if any army units can tag along
770
for (iterator it = begin(); it != end(); it++)
772
//skip over armies that are already known to be reachable
773
if (find(ids.begin(), ids.end(), (*it)->getId()) != ids.end())
775
if ((*it)->getMoves() > 0)
777
Stack *stack = new Stack(getOwner(), getPos());
778
stack->push_back(*it);
779
//also push back the rest of the known reachables
780
std::vector<Uint32>::iterator iit = ids.begin();
781
for (; iit != ids.end(); iit++)
783
Army *army = getArmyById(*iit);
785
stack->push_back(army);
787
if (stack->getGroupMoves() >=
788
stack->getPath()->calculate(stack, dest))
789
ids.push_back((*it)->getId());
798
Uint32 Stack::countArmiesBlessedAtTemple(Uint32 temple_id)
801
for (iterator it = begin(); it != end(); it++)
803
if ((*it)->blessedAtTemple(temple_id))
809
Uint32 Stack::scout(Player *p, Vector<int> src, Vector<int> dest,
812
Stack *stack = new Stack(p, src);
815
proto = Armysetlist::getInstance()->getScout(p->getArmyset());
819
Army *army = new Army (*proto);
822
stack->push_back(army);
823
Uint32 mp = stack->getPath()->calculate(stack, dest);
827
Uint32 Stack::scout(Stack *stack, Vector<int> dest)
829
Stack *scout_stack = new Stack(*stack);
830
Uint32 mp = scout_stack->getPath()->calculate(scout_stack, dest);