~ubuntu-branches/ubuntu/trusty/lordsawar/trusty

« back to all changes in this revision

Viewing changes to src/stack.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Barry deFreese
  • Date: 2008-06-17 16:07:00 UTC
  • mto: (5.1.1 lenny) (1.1.5 upstream)
  • mto: This revision was merged to the branch mainline in revision 8.
  • Revision ID: james.westby@ubuntu.com-20080617160700-6d8ofoz0qkasxlnw
ImportĀ upstreamĀ versionĀ 0.1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
8
//
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
10
18
//
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 
 
22
//  02110-1301, USA.
14
23
 
15
24
#include <sigc++/functors/mem_fun.h>
16
25
#include <assert.h>
27
36
#include "GameMap.h"
28
37
#include "vector.h"
29
38
#include "xmlhelper.h"
 
39
#include "FogMap.h"
 
40
#include "player.h"
 
41
#include "portlist.h"
 
42
#include "port.h"
30
43
 
31
44
using namespace std;
32
45
 
34
47
#define debug(x)
35
48
 
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)
39
52
{
40
53
    d_path = new Path();
41
54
}
42
55
 
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)
47
59
{
48
60
    clear();
49
61
    d_path = new Path();
50
62
    //deep copy the other stack's armies
 
63
    
51
64
    for (iterator sit = s.begin(); sit != s.end(); sit++)
52
65
    {
53
66
        Army* a;
59
72
          }
60
73
        else
61
74
          {
62
 
            a = new Army((**sit), (*sit)->getPlayer());
 
75
            a = new Army((**sit), (*sit)->getOwner());
63
76
            push_back(a);
64
77
          }
65
78
    }
66
79
}
67
80
 
68
81
Stack::Stack(XML_Helper* helper)
69
 
: Object(helper), d_deleting(false)
 
82
  : UniquelyIdentified(helper), Movable(helper), Ownable(helper), 
 
83
    d_deleting(false)
70
84
{
71
85
  helper->getData(d_defending, "defending");
72
86
  helper->getData(d_parked, "parked");
73
87
 
74
 
  int i;
75
 
  helper->getData(i, "player");
76
 
  if (i == -1)
77
 
    d_player = 0;
78
 
  else
79
 
    d_player = Playerlist::getInstance()->getPlayer(i);
80
 
 
81
 
  helper->getData(d_moves_exhausted_at_point, "moves_exhausted_at_point");
82
 
 
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)
98
103
{
99
104
  // we need to change the armies' loyalties as well!!
100
 
  d_player = p;
 
105
  setOwner(p);
101
106
  for (iterator it = begin(); it != end(); it++)
102
 
    (*it)->setPlayer(p);
 
107
    (*it)->setOwner(p);
103
108
}
104
109
 
105
 
bool Stack::moveOneStep()
 
110
void Stack::moveOneStep()
106
111
{
107
112
  debug("move_one_step()");
108
113
 
109
 
  d_pos = **d_path->begin();
 
114
  Vector<int> dest = *getPath()->front();
 
115
  moveToDest(dest);
 
116
 
 
117
  //now remove first point of the path
 
118
  d_path->eraseFirstPoint();
 
119
}
 
120
 
 
121
void Stack::moveToDest(Vector<int> dest)
 
122
{
 
123
  Vector<int> pos = getPos();
 
124
    
 
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
 
133
  if (!isFlying())
 
134
    {
 
135
      if ((on_water && to_city) || 
 
136
          (on_water && on_port && !to_water) ||
 
137
          ((on_city || on_port) && to_water))
 
138
        {
 
139
          ship_load_unload = true;
 
140
          for (Stack::iterator it = begin(); it != end(); it++)
 
141
            {
 
142
              if (to_water && 
 
143
                  ((*it)->getStat(Army::MOVE_BONUS) & Tile::WATER) == 0)
 
144
                (*it)->setInShip(true);
 
145
              else
 
146
                (*it)->setInShip(false);
 
147
            }
 
148
        }
 
149
    }
 
150
  else
 
151
    {
 
152
      for (Stack::iterator it = begin(); it != end(); it++)
 
153
        (*it)->setInShip(false);
 
154
    }
 
155
 
 
156
  //how many moves does the stack need to travel to dest?
 
157
  int needed_moves = calculateTileMovementCost(dest);
 
158
 
 
159
  for (Stack::iterator it = begin(); it != end(); it++)
 
160
    {
 
161
      if (ship_load_unload)
 
162
        (*it)->decrementMoves((*it)->getMoves());
 
163
      else 
 
164
        {
 
165
          //maybe the army has a natural movement ability
 
166
          if ((*it)->getStat(Army::MOVE_BONUS) & maptype && needed_moves > 1)
 
167
            (*it)->decrementMoves(2);
 
168
          else
 
169
            (*it)->decrementMoves(needed_moves);
 
170
        }
 
171
    }
 
172
 
 
173
  //update position and status
 
174
  setPos(dest);
110
175
 
111
176
  setFortified(false);
112
177
  setDefending(false);
113
178
  setParked(false);
114
179
 
115
 
  //now remove first point of the path
116
 
  d_path->flErase(d_path->begin());
117
 
 
118
 
  //and decrement the point at which we exhaust our path
119
 
  if (getMovesExhaustedAtPoint())
120
 
    setMovesExhaustedAtPoint(getMovesExhaustedAtPoint()-1);
121
 
  return true;
 
180
  //update fogmap
 
181
  getOwner()->getFogMap()->alterFogRadius(dest, getMaxSight(), FogMap::OPEN);
122
182
}
123
183
 
124
 
 
125
184
bool Stack::isGrouped()
126
185
{
127
186
  if (empty())
161
220
int Stack::getMinTileMoves() const
162
221
{
163
222
  GameMap *map = GameMap::getInstance();
164
 
  Rectangle bounds = GameMap::get_boundary();
 
223
  Rectangle bounds = map->get_boundary();
165
224
 
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
209
268
{
210
269
  assert(!empty());
211
 
  Army *strongest = 0;
212
 
  Uint32 highest_strength = 0;
213
 
 
214
 
  for (const_iterator it = begin(); it != end(); ++it)
215
 
    {
216
 
      // if hero
217
 
      if ((*it)->isHero())
218
 
        {
219
 
          return *it;
220
 
        }
221
 
      else if ((*it)->getStat(Army::STRENGTH) > highest_strength)
222
 
        {
223
 
          highest_strength = (*it)->getStat(Army::STRENGTH);
224
 
          strongest = *it;
225
 
        }
226
 
    }
227
 
  return strongest;
 
270
  return getStrongestArmy(false);
228
271
}
229
272
 
230
273
Army* Stack::getStrongestHero() const
231
274
{
 
275
  return getStrongestArmy(true);
 
276
}
 
277
 
 
278
Army* Stack::getStrongestArmy(bool hero) const
 
279
{
232
280
  Army *strongest = 0;
233
281
  Uint32 highest_strength = 0;
234
282
 
235
283
  for (const_iterator it = begin(); it != end(); ++it)
236
284
    {
237
 
      // if hero
238
 
      if ((*it)->isHero())
 
285
      if ((*it)->isHero() && hero || !hero)
239
286
        {
240
287
          if ((*it)->getStat(Army::STRENGTH) > highest_strength)
241
288
            {
247
294
  return strongest;
248
295
}
249
296
 
 
297
Army *Stack::getArmyById(Uint32 id) const
 
298
{
 
299
  for (Stack::const_iterator i = begin(), e = end(); i != e; ++i)
 
300
    if ((*i)->getId() == id)
 
301
      return *i;
 
302
  
 
303
  return 0;
 
304
}
 
305
 
 
306
Uint32 Stack::countGroupedArmies() const
 
307
{
 
308
  Uint32 count = 0;
 
309
  if (empty())
 
310
    return 0;
 
311
  for (const_iterator it = begin(); it != end(); ++it)
 
312
    if ((*it)->isGrouped() == true)
 
313
      count++;
 
314
  return count;
 
315
}
 
316
 
250
317
void Stack::group()
251
318
{
252
319
  if (empty())
312
379
{
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)
 
384
    moves = 2;
 
385
  else if (isFlying() && moves > 1)
316
386
    moves = 2;
317
387
  return moves;
318
388
}
319
389
 
320
390
bool Stack::enoughMoves() const
321
391
{
 
392
  if (d_path->size() == 0)
 
393
    return true; //we have enough moves to move nowhere!
 
394
 
322
395
  Vector<int> p = **(d_path->begin());
323
396
  Uint32 needed = calculateTileMovementCost(p);
324
397
 
335
408
  int tile_moves = getMinTileMoves();
336
409
  int group_moves = getGroupMoves();
337
410
 
 
411
  assert (tile_moves != -1);
338
412
  return group_moves > 0 && tile_moves >= 0 && group_moves >= tile_moves;
339
413
}
340
414
 
350
424
  return 0;
351
425
}
352
426
 
353
 
bool Stack::isFriend(Player* player) const
354
 
{
355
 
  return d_player == player;
356
 
}
357
 
 
358
427
Uint32 Stack::getMaxSight() const
359
428
{
360
429
  Uint32 max = 0;
379
448
        for (item = backpack.begin(); item != backpack.end(); item++)
380
449
          {
381
450
            if ((*item)->getBonus(Item::DOUBLEMOVESTACK))
382
 
              movement_multiplier++;
 
451
              movement_multiplier*=2;
383
452
          }
384
453
      }
385
454
 
395
464
        std::list<Item*>::const_iterator item;
396
465
        for (item = backpack.begin(); item != backpack.end(); item++)
397
466
          {
398
 
            Player *p = d_player;
 
467
            Player *p = d_owner;
399
468
            if ((*item)->getBonus(Item::ADD2GOLDPERCITY))
400
469
              p->addGold(2 * Citylist::getInstance()->countCities(p));
401
470
            if ((*item)->getBonus(Item::ADD3GOLDPERCITY))
413
482
    {
414
483
      (*it)->resetMoves();
415
484
      // TODO: should be moved in a more appropriate place => class Player
416
 
      if (d_player)
417
 
        d_player->withdrawGold((*it)->getUpkeep());
 
485
      if (d_owner)
 
486
        d_owner->withdrawGold((*it)->getUpkeep());
418
487
      (*it)->heal();
419
488
    }
420
489
 
429
498
 
430
499
  retval &= helper->openTag("stack");
431
500
  retval &= helper->saveData("id", d_id);
432
 
  if (d_player)
433
 
    retval &= helper->saveData("player", d_player->getId());
 
501
  retval &= helper->saveData("x", getPos().x);
 
502
  retval &= helper->saveData("y", getPos().y);
 
503
  if (d_owner)
 
504
    retval &= helper->saveData("owner", d_owner->getId());
434
505
  else
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);
440
509
 
441
 
  retval &= helper->saveData("moves_exhausted_at_point", 
442
 
                             d_moves_exhausted_at_point);
443
510
 
444
511
  //save path
445
512
  retval &= d_path->save(helper);
465
532
  if (tag == "army")
466
533
    {
467
534
      Army* a = new Army(helper);
468
 
      a->setPlayer(d_player);
 
535
      a->setOwner(d_owner);
469
536
      push_back(a);
470
537
 
471
538
      return true;
474
541
  if (tag == "hero")
475
542
    {
476
543
      Hero* h = new Hero(helper);
477
 
      h->setPlayer(d_player);
 
544
      h->setOwner(d_owner);
478
545
      push_back(h);
479
546
 
480
547
      return true;
609
676
 
610
677
bool Stack::armyCompareFightOrder (const Army *lhs, const Army *rhs)  
611
678
{
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();
662
729
  return upkeep;
663
730
}
 
731
 
 
732
bool Stack::canJoin(const Stack *stack) const
 
733
{
 
734
  Uint32 joinSize = countGroupedArmies();
 
735
  if (joinSize == 0)
 
736
    joinSize = size();
 
737
 
 
738
  /* this is necessary because human players "group" armies in stacks,
 
739
   * while the computer player does not.
 
740
   */
 
741
  if ((stack->size() + joinSize) > MAX_STACK_SIZE)
 
742
    return false;
 
743
 
 
744
  return true;
 
745
 
 
746
}
 
747
 
 
748
std::vector<Uint32> Stack::determineReachableArmies(Vector<int> dest)
 
749
{
 
750
  std::vector<Uint32> ids;
 
751
  //try each army individually to see if it reaches
 
752
  for (iterator it = begin(); it != end(); it++)
 
753
    {
 
754
      if ((*it)->getMoves() > 0)
 
755
        {
 
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());
 
761
          stack->clear();
 
762
          delete stack;
 
763
          //fixme: can't delete stacks like this because it deletes the army
 
764
        }
 
765
    }
 
766
  if (ids.size() == 0)
 
767
    return ids;
 
768
 
 
769
  //now try to see if any army units can tag along
 
770
  for (iterator it = begin(); it != end(); it++)
 
771
    {
 
772
      //skip over armies that are already known to be reachable
 
773
      if (find(ids.begin(), ids.end(), (*it)->getId()) != ids.end())
 
774
        continue;
 
775
      if ((*it)->getMoves() > 0)
 
776
        {
 
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++)
 
782
            {
 
783
              Army *army = getArmyById(*iit);
 
784
              if (army)
 
785
                stack->push_back(army);
 
786
            }
 
787
          if (stack->getGroupMoves() >= 
 
788
              stack->getPath()->calculate(stack, dest))
 
789
            ids.push_back((*it)->getId());
 
790
          stack->clear();
 
791
          delete stack;
 
792
        }
 
793
    }
 
794
 
 
795
  return ids;
 
796
}
 
797
 
 
798
Uint32 Stack::countArmiesBlessedAtTemple(Uint32 temple_id)
 
799
{
 
800
  Uint32 blessed = 0;
 
801
  for (iterator it = begin(); it != end(); it++)
 
802
    {
 
803
      if ((*it)->blessedAtTemple(temple_id))
 
804
        blessed++;
 
805
    }
 
806
    return blessed;
 
807
}
 
808
        
 
809
Uint32 Stack::scout(Player *p, Vector<int> src, Vector<int> dest, 
 
810
                    const Army *proto)
 
811
{
 
812
  Stack *stack = new Stack(p, src);
 
813
 
 
814
  if (!proto)
 
815
    proto = Armysetlist::getInstance()->getScout(p->getArmyset());
 
816
  if (!proto)
 
817
    return 0;
 
818
 
 
819
  Army *army = new Army (*proto);
 
820
  if (!army)
 
821
    return 0;
 
822
  stack->push_back(army);
 
823
  Uint32 mp = stack->getPath()->calculate(stack, dest);
 
824
  delete stack;
 
825
  return mp;
 
826
}
 
827
Uint32 Stack::scout(Stack *stack, Vector<int> dest)
 
828
{
 
829
  Stack *scout_stack = new Stack(*stack);
 
830
  Uint32 mp = scout_stack->getPath()->calculate(scout_stack, dest);
 
831
  delete scout_stack;
 
832
  return mp;
 
833
}
664
834
// End of file