~ubuntu-branches/ubuntu/saucy/lordsawar/saucy

« back to all changes in this revision

Viewing changes to src/stack.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Barry deFreese, Barry deFreese
  • Date: 2008-12-20 13:52:12 UTC
  • mfrom: (1.1.6 upstream) (5.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20081220135212-noeb2w3y98ebo7o9
Tags: 0.1.4-1
[ Barry deFreese ]
* New upstream release.
* Move 0.0.8-2.1 changelog entry to correct point in changelog.
* Make lordsawar-data suggest lordsawar.
* Update my e-mail address.
* Add build-depends on intltool, uuid-dev, and libboost-dev.
* Don't install locales since there are no translations currently.
* Add simple man page for new lordsawar-pbm binary.
* Drop gcc4.3 patches as they have been fixed upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
#include "armysetlist.h"
32
32
#include "counter.h"
33
33
#include "army.h"
34
 
#include "citylist.h"
 
34
#include "templelist.h"
35
35
#include "hero.h"
36
36
#include "GameMap.h"
37
37
#include "vector.h"
38
38
#include "xmlhelper.h"
39
39
#include "FogMap.h"
40
40
#include "player.h"
41
 
#include "portlist.h"
42
 
#include "port.h"
 
41
#include "Backpack.h"
43
42
 
 
43
std::string Stack::d_tag = "stack";
44
44
using namespace std;
45
45
 
46
46
//#define debug(x) {cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<endl<<flush;}
53
53
    d_path = new Path();
54
54
}
55
55
 
56
 
Stack::Stack(Stack& s)
 
56
Stack::Stack(Uint32 id, Player* player, Vector<int> pos)
 
57
    : UniquelyIdentified(id), Movable(pos), Ownable(player), 
 
58
    d_defending(false), d_parked(false), d_deleting(false)
 
59
{
 
60
    d_path = new Path();
 
61
}
 
62
 
 
63
Stack::Stack(const Stack& s)
57
64
    : UniquelyIdentified(s), Movable(s), Ownable(s), 
58
65
    d_defending(s.d_defending), d_parked(s.d_parked), d_deleting(false)
59
66
{
61
68
    d_path = new Path();
62
69
    //deep copy the other stack's armies
63
70
    
64
 
    for (iterator sit = s.begin(); sit != s.end(); sit++)
 
71
    for (const_iterator sit = s.begin(); sit != s.end(); sit++)
65
72
    {
66
 
        Army* a;
67
 
        Army* h;
68
73
        if ((*sit)->isHero())
69
74
          {
70
 
            h = new Hero(dynamic_cast<Hero&>(**sit));
 
75
            Army *h = new Hero(dynamic_cast<Hero&>(**sit));
71
76
            push_back(h);
72
77
          }
73
78
        else
74
79
          {
75
 
            a = new Army((**sit), (*sit)->getOwner());
 
80
            Army *a = new Army((**sit), (*sit)->getOwner());
76
81
            push_back(a);
77
82
          }
78
83
    }
85
90
  helper->getData(d_defending, "defending");
86
91
  helper->getData(d_parked, "parked");
87
92
 
88
 
  helper->registerTag("path", sigc::mem_fun((*this), &Stack::load));
89
 
  helper->registerTag("army", sigc::mem_fun((*this), &Stack::load));
90
 
  helper->registerTag("hero", sigc::mem_fun((*this), &Stack::load));
 
93
  helper->registerTag(Path::d_tag, sigc::mem_fun((*this), &Stack::load));
 
94
  helper->registerTag(Army::d_tag, sigc::mem_fun((*this), &Stack::load));
 
95
  helper->registerTag(Hero::d_tag, sigc::mem_fun((*this), &Stack::load));
91
96
}
92
97
 
93
98
Stack::~Stack()
94
99
{
95
100
  d_deleting = true;
96
 
  sdying.emit(this);
 
101
  if (d_unique)
 
102
    sdying.emit(this);
97
103
 
98
104
  delete d_path;
99
105
  flClear();
107
113
    (*it)->setOwner(p);
108
114
}
109
115
 
110
 
void Stack::moveOneStep()
 
116
void Stack::moveOneStep(bool skipping)
111
117
{
112
 
  debug("move_one_step()");
 
118
  debug("moveOneStep()");
113
119
 
114
120
  Vector<int> dest = *getPath()->front();
115
 
  moveToDest(dest);
 
121
  moveToDest(dest, skipping);
116
122
 
117
123
  //now remove first point of the path
118
124
  d_path->eraseFirstPoint();
119
125
}
120
126
 
121
 
void Stack::moveToDest(Vector<int> dest)
 
127
bool Stack::isMovingToOrFromAShip(Vector<int> dest, bool &on_ship) const
122
128
{
123
129
  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);
 
130
 
 
131
  bool to_city = GameMap::getInstance()->getTile(dest)->getBuilding() == Maptile::CITY;
 
132
  bool on_city = GameMap::getInstance()->getTile(pos)->getBuilding() == Maptile::CITY;
 
133
 
 
134
  bool on_port = GameMap::getInstance()->getTile(pos)->getBuilding() == Maptile::PORT;
 
135
  bool on_bridge = GameMap::getInstance()->getTile(pos)->getBuilding() == Maptile::BRIDGE;
 
136
  bool to_bridge = GameMap::getInstance()->getTile(dest)->getBuilding() == Maptile::BRIDGE;
129
137
  bool on_water = (GameMap::getInstance()->getTile(pos.x,pos.y)->getMaptileType() == Tile::WATER);
130
138
  bool to_water = (GameMap::getInstance()->getTile(dest.x,dest.y)->getMaptileType() == Tile::WATER);
 
139
  //here we mark the armies as being on or off a boat
 
140
  /* skipping refers to when we have to move over another friendly stack
 
141
   * of a size that's too big to join with. */
 
142
  if ((on_water && to_city && !on_bridge) || 
 
143
      (on_water && on_port && !to_water && on_ship) ||
 
144
      ((on_city || on_port) && to_water && !to_bridge) ||
 
145
      (on_bridge && to_water && !to_bridge) ||
 
146
      (on_bridge && !to_water && on_ship) ||
 
147
      (on_water && to_water && !on_bridge && !on_port && !to_bridge &&
 
148
       on_ship == false) ||
 
149
      (!on_water && !to_water && on_ship == true))
 
150
    {
 
151
      on_ship = !on_ship;
 
152
      return true;
 
153
    }
 
154
  return false;
 
155
}
 
156
 
 
157
void Stack::moveToDest(Vector<int> dest, bool skipping)
 
158
{
131
159
  bool ship_load_unload = false;
132
 
  //here we mark the armies as being on or off a boat
133
160
  if (!isFlying())
134
161
    {
135
 
      if ((on_water && to_city) || 
136
 
          (on_water && on_port && !to_water) ||
137
 
          ((on_city || on_port) && to_water))
 
162
      bool on_ship = hasShip();
 
163
      if (isMovingToOrFromAShip(dest, on_ship) == true)
138
164
        {
139
 
          ship_load_unload = true;
140
 
          for (Stack::iterator it = begin(); it != end(); it++)
 
165
          if (!skipping)
141
166
            {
142
 
              if (to_water && 
143
 
                  ((*it)->getStat(Army::MOVE_BONUS) & Tile::WATER) == 0)
144
 
                (*it)->setInShip(true);
145
 
              else
146
 
                (*it)->setInShip(false);
 
167
              ship_load_unload = true;
 
168
              Vector<int> pos = getPos();
 
169
              GameMap *gm = GameMap::getInstance();
 
170
              bool to_water = (gm->getTile(dest.x,dest.y)->getMaptileType() 
 
171
                               == Tile::WATER);
 
172
              for (Stack::iterator it = begin(); it != end(); it++)
 
173
                {
 
174
                  if (to_water && 
 
175
                      ((*it)->getStat(Army::MOVE_BONUS) & Tile::WATER) == 0)
 
176
                    (*it)->setInShip(true);
 
177
                  else
 
178
                    (*it)->setInShip(false);
 
179
                }
147
180
            }
148
181
        }
149
182
    }
153
186
        (*it)->setInShip(false);
154
187
    }
155
188
 
 
189
  Uint32 maptype = GameMap::getInstance()->getTile(dest.x,dest.y)->getMaptileType();
156
190
  //how many moves does the stack need to travel to dest?
157
191
  int needed_moves = calculateTileMovementCost(dest);
158
192
 
178
212
  setParked(false);
179
213
 
180
214
  //update fogmap
181
 
  getOwner()->getFogMap()->alterFogRadius(dest, getMaxSight(), FogMap::OPEN);
 
215
  deFog();
 
216
}
 
217
 
 
218
void Stack::deFog()
 
219
{
 
220
  getOwner()->getFogMap()->alterFogRadius(getPos(), getMaxSight(), 
 
221
                                          FogMap::OPEN);
 
222
  return;
182
223
}
183
224
 
184
225
bool Stack::isGrouped()
282
323
 
283
324
  for (const_iterator it = begin(); it != end(); ++it)
284
325
    {
285
 
      if ((*it)->isHero() && hero || !hero)
 
326
      if (((*it)->isHero() && hero) || !hero)
286
327
        {
287
328
          if ((*it)->getStat(Army::STRENGTH) > highest_strength)
288
329
            {
316
357
 
317
358
void Stack::group()
318
359
{
 
360
  debug("Stack::group()")
319
361
  if (empty())
320
362
    return;
321
363
  for (iterator it = begin(); it != end(); ++it)
325
367
 
326
368
void Stack::ungroup()
327
369
{
 
370
  debug("Stack::ungroup()")
328
371
  if (empty())
329
372
    return;
330
373
  for (iterator it = begin(); it != end(); ++it)
358
401
    for (const_iterator it = begin(); it != end(); ++it)
359
402
      {
360
403
        // if hero - add it to the vector
361
 
        debug("Army type: " << (*it)->getType())
 
404
        debug("Army type: " << (*it)->getTypeId())
362
405
          if ((*it)->isHero() && (*it)->getHP() > 0)
363
406
            dst.push_back((*it)->getId());
364
407
      }
369
412
  int count = 0;
370
413
  for (iterator it = begin(); it != end(); it++)
371
414
    {
372
 
      if ((*it)->bless())
 
415
      Temple *temple = Templelist::getInstance()->getObjectAt(getPos());
 
416
      if ((*it)->bless(temple))
373
417
        count++;
374
418
    }
375
419
  return count;
434
478
  return max;
435
479
}
436
480
 
 
481
void Stack::payUpkeep(Player *p)
 
482
{
 
483
  for (iterator it = begin(); it != end(); ++it)
 
484
      p->withdrawGold((*it)->getUpkeep());
 
485
}
 
486
 
437
487
void Stack::nextTurn()
438
488
{
439
489
  Uint32 movement_multiplier = 1;
443
493
  for (const_iterator it = begin(); it != end(); it++)
444
494
    if ((*it)->isHero())
445
495
      {
446
 
        std::list<Item*> backpack = dynamic_cast<Hero*>((*it))->getBackpack();
447
 
        std::list<Item*>::const_iterator item;
448
 
        for (item = backpack.begin(); item != backpack.end(); item++)
449
 
          {
450
 
            if ((*item)->getBonus(Item::DOUBLEMOVESTACK))
451
 
              movement_multiplier*=2;
452
 
          }
 
496
        Hero *hero = dynamic_cast<Hero*>(*it);
 
497
        Uint32 bonus = hero->getBackpack()->countMovementDoublers();
 
498
        for (Uint32 i = 0; i < bonus; i++)
 
499
          movement_multiplier*=2;
453
500
      }
454
501
 
455
502
  //set the multipler on all armies in the stack
456
503
  for (const_iterator it = begin(); it != end(); it++)
457
504
    (*it)->setStat(Army::MOVES_MULTIPLIER, movement_multiplier);
458
505
 
459
 
  //now let's see if we have any items that give us gold per city
460
 
  for (const_iterator it = begin(); it != end(); it++)
461
 
    if ((*it)->isHero())
462
 
      {
463
 
        std::list<Item*> backpack = dynamic_cast<Hero*>((*it))->getBackpack();
464
 
        std::list<Item*>::const_iterator item;
465
 
        for (item = backpack.begin(); item != backpack.end(); item++)
466
 
          {
467
 
            Player *p = d_owner;
468
 
            if ((*item)->getBonus(Item::ADD2GOLDPERCITY))
469
 
              p->addGold(2 * Citylist::getInstance()->countCities(p));
470
 
            if ((*item)->getBonus(Item::ADD3GOLDPERCITY))
471
 
              p->addGold(3 * Citylist::getInstance()->countCities(p));
472
 
            if ((*item)->getBonus(Item::ADD4GOLDPERCITY))
473
 
              p->addGold(4 * Citylist::getInstance()->countCities(p));
474
 
            if ((*item)->getBonus(Item::ADD5GOLDPERCITY))
475
 
              p->addGold(5 * Citylist::getInstance()->countCities(p));
476
 
          }
477
 
      }
478
506
  if (d_defending == true)
479
507
    setFortified(true);
480
508
 
481
509
  for (iterator it = begin(); it != end(); ++it)
482
510
    {
483
511
      (*it)->resetMoves();
484
 
      // TODO: should be moved in a more appropriate place => class Player
485
 
      if (d_owner)
486
 
        d_owner->withdrawGold((*it)->getUpkeep());
487
512
      (*it)->heal();
488
513
    }
489
514
 
496
521
{
497
522
  bool retval = true;
498
523
 
499
 
  retval &= helper->openTag("stack");
 
524
  retval &= helper->openTag(Stack::d_tag);
500
525
  retval &= helper->saveData("id", d_id);
501
526
  retval &= helper->saveData("x", getPos().x);
502
527
  retval &= helper->saveData("y", getPos().y);
522
547
 
523
548
bool Stack::load(std::string tag, XML_Helper* helper)
524
549
{
525
 
  if (tag == "path")
 
550
  if (tag == Path::d_tag)
526
551
    {
527
552
      d_path = new Path(helper);
528
553
 
529
554
      return true;
530
555
    }
531
556
 
532
 
  if (tag == "army")
 
557
  if (tag == Army::d_tag)
533
558
    {
534
559
      Army* a = new Army(helper);
535
560
      a->setOwner(d_owner);
538
563
      return true;
539
564
    }
540
565
 
541
 
  if (tag == "hero")
 
566
  if (tag == Hero::d_tag)
542
567
    {
543
568
      Hero* h = new Hero(helper);
544
569
      h->setOwner(d_owner);
575
600
  int num_landedother = 0;
576
601
  if (size() == 0)
577
602
    return 0;
 
603
  bool grouped = countGroupedArmies() > 0;
578
604
  for (const_iterator it = this->begin(); it != this->end(); it++)
579
605
    {
580
 
      if ((*it)->isGrouped() == false)
 
606
      if ((*it)->isGrouped() == false && grouped)
581
607
        continue;
582
608
      bonus = (*it)->getStat(Army::MOVE_BONUS);
583
609
      if (bonus == Tile::GRASS || (bonus & Tile::WATER) == 0 || 
598
624
  if (landed == false ||
599
625
      (num_landedother == 0 && num_landedhero <= num_flyer)) 
600
626
    {
601
 
      d_bonus = Tile::GRASS | Tile::WATER | Tile::FOREST | Tile::HILLS |
602
 
        Tile::MOUNTAIN | Tile::SWAMP;
 
627
      d_bonus = Tile::isFlying();
603
628
      return d_bonus;
604
629
    }
605
630
 
609
634
      if ((*it)->isHero())
610
635
        {
611
636
          Hero *h = dynamic_cast<Hero*>(*it);
612
 
          std::list<Item*> backpack = h->getBackpack();
613
 
          std::list<Item*>::const_iterator item;
614
 
          for (item = backpack.begin(); item != backpack.end(); item++)
 
637
          if (h->getBackpack()->countStackFlightGivers() > 0)
615
638
            {
616
 
              if ((*item)->getBonus(Item::FLYSTACK))
617
 
                {
618
 
                  d_bonus = Tile::GRASS | Tile::WATER | Tile::FOREST | 
619
 
                    Tile::HILLS | Tile::MOUNTAIN | Tile::SWAMP;
620
 
                  return d_bonus;
621
 
                }
 
639
              d_bonus = Tile::isFlying();
 
640
              return d_bonus;
622
641
            }
623
642
        }
624
643
    }
640
659
bool Stack::isFlying () const
641
660
{
642
661
  Uint32 d_bonus = calculateMoveBonus();
643
 
  if (d_bonus == (Tile::GRASS | Tile::WATER | Tile::FOREST | Tile::HILLS |
644
 
                  Tile::MOUNTAIN | Tile::SWAMP))
 
662
  if (d_bonus == Tile::isFlying())
645
663
    return true;
646
664
  else
647
665
    return false;
678
696
{
679
697
  std::list<Uint32> lhs_fight_order = lhs->getOwner()->getFightOrder();
680
698
  std::list<Uint32> rhs_fight_order = rhs->getOwner()->getFightOrder();
681
 
  Uint32 lhs_rank = getFightOrder (lhs_fight_order, lhs->getType());
682
 
  Uint32 rhs_rank = getFightOrder (rhs_fight_order, rhs->getType());
683
 
  //if (lhs_rank == rhs_rank)
684
 
    //return lhs->getId() < rhs->getId();
 
699
  Uint32 lhs_rank = getFightOrder (lhs_fight_order, lhs->getTypeId());
 
700
  Uint32 rhs_rank = getFightOrder (rhs_fight_order, rhs->getTypeId());
685
701
  return lhs_rank < rhs_rank; 
686
702
}
687
703
 
753
769
    {
754
770
      if ((*it)->getMoves() > 0)
755
771
        {
756
 
          Stack *stack = new Stack(getOwner(), getPos());
 
772
          Stack *stack = Stack::createNonUniqueStack(getOwner(), getPos());
757
773
          stack->push_back(*it);
758
774
          if (stack->getGroupMoves() >= 
759
775
              stack->getPath()->calculate(stack, dest))
774
790
        continue;
775
791
      if ((*it)->getMoves() > 0)
776
792
        {
777
 
          Stack *stack = new Stack(getOwner(), getPos());
 
793
          Stack *stack = Stack::createNonUniqueStack(getOwner(), getPos());
778
794
          stack->push_back(*it);
779
795
          //also push back the rest of the known reachables
780
796
          std::vector<Uint32>::iterator iit = ids.begin();
807
823
}
808
824
        
809
825
Uint32 Stack::scout(Player *p, Vector<int> src, Vector<int> dest, 
810
 
                    const Army *proto)
 
826
                    const ArmyProdBase *prodbase)
811
827
{
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);
 
828
  Stack *stack = Stack::createNonUniqueStack(p, src);
 
829
 
 
830
  Army *army;
 
831
  if (!prodbase)
 
832
    {
 
833
      ArmyProto *proto = Armysetlist::getInstance()->getScout(p->getArmyset());
 
834
      if (!proto)
 
835
        return 0;
 
836
      army = Army::createNonUniqueArmy (*proto, p);
 
837
    }
 
838
  else
 
839
    army = Army::createNonUniqueArmy (*prodbase, p);
 
840
 
820
841
  if (!army)
821
842
    return 0;
822
843
  stack->push_back(army);
824
845
  delete stack;
825
846
  return mp;
826
847
}
 
848
 
827
849
Uint32 Stack::scout(Stack *stack, Vector<int> dest)
828
850
{
829
851
  Stack *scout_stack = new Stack(*stack);
831
853
  delete scout_stack;
832
854
  return mp;
833
855
}
 
856
 
 
857
Stack* Stack::createNonUniqueStack(Player *player, Vector<int> pos)
 
858
{
 
859
  return new Stack(0, player, pos);
 
860
}
 
861
 
 
862
Uint32 Stack::getMaxGroupLandMoves() const
 
863
{
 
864
  if (empty())
 
865
    return 0;
 
866
 
 
867
  assert(!empty());
 
868
 
 
869
  //copy the stack, reset the moves and return the group moves
 
870
  Stack *copy = new Stack (*this);
 
871
  if (copy->countGroupedArmies() == 0)
 
872
    copy->group();
 
873
  copy->decrementMoves(copy->getGroupMoves());
 
874
  copy->nextTurn();
 
875
  Uint32 moves = copy->getGroupMoves();
 
876
  if (isFlying() == true)
 
877
    {
 
878
      delete copy;
 
879
      return moves;
 
880
    }
 
881
 
 
882
  //alright, we're not flying.  what would our group moves be if we were on land
 
883
  //remove ship status from all army units
 
884
  copy->decrementMoves(copy->getGroupMoves());
 
885
  for (Stack::iterator it = copy->begin(); it != copy->end(); it++)
 
886
    (*it)->setInShip(false);
 
887
  copy->nextTurn();
 
888
 
 
889
  moves = copy->getGroupMoves();
 
890
  delete copy;
 
891
  return moves;
 
892
}
 
893
 
 
894
Uint32 Stack::getMaxGroupBoatMoves() const
 
895
{
 
896
  if (empty())
 
897
    return 0;
 
898
 
 
899
  assert(!empty());
 
900
 
 
901
  //copy the stack, reset the moves and return the group moves
 
902
  Stack *copy = new Stack (*this);
 
903
  if (copy->countGroupedArmies() == 0)
 
904
    copy->group();
 
905
  copy->nextTurn();
 
906
  Uint32 moves = copy->getGroupMoves();
 
907
  if (isFlying() == true)
 
908
    {
 
909
      delete copy;
 
910
      return moves;
 
911
    }
 
912
  //alright, we're not flying.  what would our group moves be if we were on water?
 
913
  copy->decrementMoves(copy->getGroupMoves());
 
914
              
 
915
  for (Stack::iterator it = copy->begin(); it != copy->end(); it++)
 
916
    {
 
917
      if (((*it)->getStat(Army::MOVE_BONUS) & Tile::WATER) == 0)
 
918
        (*it)->setInShip(true);
 
919
      else
 
920
        (*it)->setInShip(false);
 
921
    }
 
922
  copy->nextTurn();
 
923
 
 
924
  moves = copy->getGroupMoves();
 
925
  delete copy;
 
926
  return moves;
 
927
}
834
928
// End of file