initial commit, lordsawar source, slightly modified
[lordsawar] / src / ai_fast.cpp
1 // Copyright (C) 2002, 2003, 2004, 2005, 2006 Ulf Lorenz
2 // Copyright (C) 2003 Michael Bartl
3 // Copyright (C) 2004, 2006 Andrea Paternesi
4 // Copyright (C) 2004 John Farrell
5 // Copyright (C) 2006, 2007, 2008, 2009 Ben Asselstine
6 // Copyright (C) 2007, 2008 Ole Laursen
7 //
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.
12 //
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.
17 //
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 
21 //  02110-1301, USA.
22
23 #include <stdlib.h>
24 #include <algorithm>
25 #include <fstream>
26 #include <assert.h>
27
28 #include "ai_fast.h"
29
30 #include "playerlist.h"
31 #include "armysetlist.h"
32 #include "stacklist.h"
33 #include "citylist.h"
34 #include "city.h"
35 #include "templelist.h"
36 #include "ruinlist.h"
37 #include "path.h"
38 #include "GameMap.h"
39 #include "Threatlist.h"
40 #include "action.h"
41 #include "xmlhelper.h"
42 #include "AI_Diplomacy.h"
43 #include "stack.h"
44 #include "GameScenarioOptions.h"
45 #include "hero.h"
46 #include "vectoredunitlist.h"
47 #include "PathCalculator.h"
48 #include "stacktile.h"
49 #include "armyprodbase.h"
50 #include "QuestsManager.h"
51 #include "Quest.h"
52 #include "Sage.h"
53
54 using namespace std;
55
56 #define debug(x) {cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<flush<<endl;}
57 //#define debug(x)
58
59 AI_Fast::AI_Fast(string name, guint32 armyset, Gdk::Color color, int width, int height, int player_no)
60     :RealPlayer(name, armyset, color, width, height, Player::AI_FAST, player_no), d_join(true),
61     d_maniac(false), d_analysis(0), d_diplomacy(0)
62 {
63 }
64
65 AI_Fast::AI_Fast(const Player& player)
66     :RealPlayer(player), d_join(true), d_maniac(false), d_analysis(0), 
67     d_diplomacy(0)
68 {
69     d_type = AI_FAST;
70 }
71
72 AI_Fast::AI_Fast(XML_Helper* helper)
73     :RealPlayer(helper), d_analysis(0), d_diplomacy(0)
74 {
75     helper->getData(d_join, "join");
76     helper->getData(d_maniac, "maniac");
77 }
78
79 AI_Fast::~AI_Fast()
80 {
81     if (d_analysis)
82         delete d_analysis;
83     if (d_diplomacy)
84         delete d_diplomacy;
85 }
86
87 bool AI_Fast::save(XML_Helper* helper) const
88 {
89     bool retval = true;
90
91     retval &= helper->openTag(Player::d_tag);
92     retval &= helper->saveData("join", d_join);
93     retval &= helper->saveData("maniac", d_maniac);
94     retval &= Player::save(helper);
95     retval &= helper->closeTag();
96
97     return retval;
98 }
99
100 void AI_Fast::abortTurn()
101 {
102   abort_requested = true;
103   if (surrendered)
104     aborted_turn.emit();
105   else if (Playerlist::getInstance()->countPlayersAlive() == 1)
106     aborted_turn.emit();
107 }
108
109 bool AI_Fast::startTurn()
110 {
111     sbusy.emit();
112
113     sbusy.emit();
114     if (getStacklist()->getHeroes().size() == 0 &&
115         Citylist::getInstance()->countCities(this) == 1)
116       AI_maybeBuyScout(Citylist::getInstance()->getFirstCity(this));
117     sbusy.emit();
118
119     debug(getName() << ": AI_Fast::start_turn")
120     debug("being in " <<(d_maniac?"maniac":"normal") <<" mode")
121     debug((d_join?"":"not ") <<"joining armies")
122
123     d_analysis = new AI_Analysis(this);
124     d_diplomacy = new AI_Diplomacy(this);
125
126     d_diplomacy->considerCuspOfWar();
127     
128     d_maniac = false;
129     float ratio = 2.0;
130     if (getUpkeep() > getIncome() * ratio)
131       d_maniac = true;
132
133     //setup production
134     debug("examining cities");
135     Citylist *cl = Citylist::getInstance();
136     for (Citylist::iterator cit = cl->begin(); cit != cl->end(); ++cit)
137       {
138         City *c = *cit;
139         if (c->getOwner() != this || c->isBurnt())
140           continue;
141         if (c->getActiveProductionSlot() == -1)
142           setBestProduction(c);
143       }
144
145     //setup vectoring
146     debug("setting up vectoring");
147     if (!d_maniac)
148         AI_setupVectoring(18, 3, 30);
149
150     sbusy.emit();
151
152     debug("trying to complete quests");
153     //try to complete our quests
154     std::vector<Quest*> q = QuestsManager::getInstance()->getPlayerQuests(this);
155     for (std::vector<Quest*>::iterator it = q.begin(); it != q.end(); it++)
156       {
157         Quest *quest = *it;
158         if (quest->isPendingDeletion())
159           continue;
160         Stack *s = getStacklist()->getArmyStackById(quest->getHeroId());
161         if (!s)
162           continue;
163         Vector<int> dest = AI_getQuestDestination(quest, s);
164         if (dest == Vector<int>(-1,-1))
165             continue;
166         d_stacklist->setActivestack(s);
167         s->getPath()->calculate(s, dest);
168         bool stack_moved = stackMove(s);
169         if (d_stacklist->getActivestack() && stack_moved)
170           GameMap::groupStacks(s);
171       }
172
173     while (computerTurn() == true)
174       {
175         sbusy.emit();
176         bool found = false;
177     
178         //are there any stacks with paths that can move?
179         for (Stacklist::reverse_iterator it = d_stacklist->rbegin(); it != d_stacklist->rend(); it++)
180           {
181             Stack *s = (*it);
182             if (s->getPath()->size() > 0 && s->enoughMoves())
183               {
184                 int mp = s->getPath()->calculate(s, s->getLastPointInPath());
185                 if (mp <= 0)
186                   continue;
187                 debug ("AI_FAST stack " << s->getId() << " can still potentially move");
188                 debug ("moving from (" << s->getPos().x << "," << s->getPos().y
189                        << ") to (" <<s->getFirstPointInPath().x << "," <<
190                        s->getFirstPointInPath().y << ") with " << s->getMoves() <<" left");
191
192             
193                 found = true;
194               }
195             //are there any stacks without paths that still have some moves?
196             else if (s->getPath()->size() == 0 && s->getMoves() > 1)
197               found = true;
198           }
199         if (!found)
200           break;
201         if (found)
202           found = false;
203         if (abort_requested)
204           break;
205       }
206
207     delete d_analysis;
208     d_analysis = 0;
209
210     d_stacklist->setActivestack(0);
211
212     // Declare war with enemies, make peace with friends
213     if (GameScenarioOptions::s_diplomacy)
214       d_diplomacy->makeProposals();
215
216     if (abort_requested)
217       aborted_turn.emit();
218     return true;
219 }
220
221 int AI_Fast::scoreArmyType(const ArmyProdBase *a)
222 {
223   int max_strength = a->getStrength();
224
225   int production;
226   if (a->getProduction() == 1)
227     production = 6;
228   else if (a->getProduction() == 2)
229     production = 2;
230   else
231     production = 1;
232
233   int upkeep = 0;
234   if (a->getUpkeep() < 5)
235     upkeep = 6;
236   else if (a->getUpkeep() < 10)
237     upkeep = 2;
238   else 
239     upkeep = 1;
240
241   int newcost = 0;
242   if (a->getProductionCost() < 5)
243     newcost = 6;
244   else if (a->getProductionCost() < 10)
245     newcost = 2;
246   else
247     newcost = 1;
248
249   //we prefer armies that move farther
250   int move_bonus = 0;
251   if (a->getMaxMoves() >  10)
252     move_bonus += 2;
253   if (a->getMaxMoves() >=  20)
254     move_bonus += 4;
255
256   return max_strength + move_bonus + production + upkeep + newcost;
257 }
258
259 int AI_Fast::setBestProduction(City *c)
260 {
261   int select = -1;
262   int score = -1;
263
264   // we try to determine the most attractive basic production
265   for (guint32 i = 0; i < c->getMaxNoOfProductionBases(); i++)
266     {
267       if (c->getArmytype(i) == -1)    // no production in this slot
268         continue;
269
270       const ArmyProdBase *proto = c->getProductionBase(i);
271       if (scoreArmyType(proto) > score)
272         {
273           select = i;
274           score = scoreArmyType(proto);
275         }
276     }
277
278
279   if (select != c->getActiveProductionSlot())
280     {
281       cityChangeProduction(c, select);
282       debug(getName() << " Set production to slot " << select << " in " << c->getName())
283     }
284
285   return c->getActiveProductionSlot();
286 }
287
288 void AI_Fast::invadeCity(City* c)
289 {
290   CityDefeatedAction action = CITY_DEFEATED_OCCUPY;
291   bool quest_preference = AI_invadeCityQuestPreference(c, action);
292   debug("Invaded city " <<c->getName());
293
294   if (quest_preference == false)
295     {
296       if (getIncome() < getUpkeep())
297         action = CITY_DEFEATED_OCCUPY;
298       else if (d_maniac)
299         action = CITY_DEFEATED_RAZE;
300       else
301         action = CITY_DEFEATED_OCCUPY;
302     }
303   int gold = 0;
304   int pillaged_army_type = -1;
305   std::list<guint32> sacked_army_types;
306   switch (action)
307     {
308     case CITY_DEFEATED_OCCUPY:
309       cityOccupy(c);
310       setBestProduction(c);
311       break;
312     case CITY_DEFEATED_PILLAGE:
313       cityPillage(c, gold, &pillaged_army_type);
314       AI_maybeBuyScout(c);
315       setBestProduction(c);
316       break;
317     case CITY_DEFEATED_RAZE:
318       cityRaze(c);
319       break;
320     case CITY_DEFEATED_SACK:
321       citySack(c, gold, &sacked_army_types);
322       AI_maybeBuyScout(c);
323       setBestProduction(c);
324       break;
325     }
326 }
327
328 void AI_Fast::heroGainsLevel(Hero * a)
329 {
330     debug("Army raised a level, id = " <<a->getId())
331     
332     //advancing a level
333     // increase the strength attack (uninnovative, but enough here)
334     Army::Stat stat = Army::STRENGTH;
335     doHeroGainsLevel(a, stat);
336
337     Action_Level* item = new Action_Level();
338     item->fillData(a, stat);
339     addAction(item);
340 }
341
342 Stack *AI_Fast::findNearOwnStackToJoin(Stack *s, int max_distance)
343 {
344   int min_mp = -1;
345   std::list<Stack*> stks;
346   stks = GameMap::getNearbyFriendlyStacks(s->getPos(), max_distance);
347   if (stks.size() <= 0)
348     return NULL;
349   PathCalculator pc(s);
350   Stack* target = NULL;
351   for (std::list<Stack*>::iterator it = stks.begin(); it != stks.end(); it++)
352     {
353       //is this us?
354       if (s == (*it))
355         continue;
356       //is this a stack that is co-located?
357       if (s->getPos() == (*it)->getPos())
358         return s;
359
360       //does the destination have few enough army units to join?
361       if (GameMap::canJoin(s, (*it)) == false)
362         continue;
363
364       //is the tile distance under the threshold?
365       int distance = dist(s->getPos(), (*it)->getPos());
366
367       if (distance <= max_distance)
368         {
369           //can we actually get there?
370           int mp = pc.calculate((*it)->getPos());
371           if (mp <= 0)
372             continue;
373           if (mp < min_mp || min_mp == -1)
374             {
375               target = (*it);
376               min_mp = mp;
377             }
378         }
379
380
381     }
382   return target;
383 }
384
385 bool AI_Fast::computerTurn()
386 {
387   bool stack_moved = false;
388     // we have configurable behaviour in two ways:
389     // 1. join => merges close stacks
390     // 2. maniac => attack at any costs, raze everything in the path
391     //
392     // So the basic algorithm is like
393     // for all armies
394     //      if !maniac, and close to a temple, visit it
395     //      if (army_to_join close && d_join)
396     //          join armies
397     //      if (!maniac && army_damaged)
398     //          resupply
399     //      if (!maniac)
400     //          find next enemy city
401     //      else
402     //          find next enemy unit with preference to cities
403     //      attack
404     //
405     // return true if any stack moved
406
407     // we are using reversed order because new stacks come behind old stacks
408     // and we want the freshly created stacks join the veterans and not the other
409     // way round.
410     //d_stacklist->dump();
411  
412   std::list<Vector<int> > points = d_stacklist->getPositions();
413     for (std::list<Vector<int> >::iterator it = points.begin(); 
414          it != points.end(); it++)
415     {
416       Stack *s = GameMap::getFriendlyStack(*it);
417       if (!s)
418         continue;
419
420         d_stacklist->setActivestack(s);
421         
422         //go to a temple or ruin
423         if (!d_maniac)
424           {
425             bool stack_died = false;
426             bool blessed = false;
427             if (s->isOnCity() == false && s->hasHero() == false)
428               {
429                 stack_moved = AI_maybeVisitTempleForBlessing
430                   (s, s->getMoves(), s->getMoves() + 7, 50.0, 
431                    blessed, stack_died);
432                 if (stack_died)
433                   return true;
434                 s = d_stacklist->getActivestack();
435                 if (stack_moved)
436                   {
437                     GameMap::groupStacks(s);
438                     s->clearPath();
439                     continue;
440                   }
441               }
442             else if (s->isOnCity() == false && s->hasHero() == true)
443               {
444                 stack_moved = AI_maybeVisitTempleForQuest
445                   (s, s->getMoves(), s->getMoves() + 15, stack_died);
446                 if (stack_died)
447                   return true;
448                 if (!stack_moved)
449                   {
450                     stack_moved = AI_maybeVisitRuin
451                       (s, s->getMoves(), s->getMoves() + 15, stack_died);
452                     if (stack_died)
453                       return true;
454                   }
455                 s = d_stacklist->getActivestack();
456                 if (stack_moved)
457                   {
458                     GameMap::groupStacks(s);
459                     s->clearPath();
460                     continue;
461                   }
462               }
463           }
464
465         //pick up items
466         if (!d_maniac)
467           {
468             bool stack_died = false;
469             bool picked_up = false;
470
471             stack_moved = AI_maybePickUpItems(s, s->getMoves(), 
472                                                s->getMoves() + 7, 
473                                                picked_up, stack_died);
474             if (stack_died)
475               return true;
476             s = d_stacklist->getActivestack();
477             if (picked_up && stack_moved)
478               stack_moved = false; //do this so we move it later on
479             else if (stack_moved)
480               continue;
481           }
482
483         debug(">>>> What to do with stack " <<s->getId() <<" at (" <<s->getPos().x
484                <<"," <<s->getPos().y <<") containing " <<s->size() << " armies ?")
485
486         // join armies if close
487         if (d_join && s->isFull() == false)
488         {
489             Stack* target = NULL;
490             target = findNearOwnStackToJoin(s, 5);
491
492             if (target)
493             {
494                 debug("Joining with stack " <<target->getId() <<" at (" <<target->getPos().x <<"," <<target->getPos().y <<")")
495                 s->getPath()->calculate(s, target->getPos());
496                 stack_moved |= stackMove(s);
497                 //in case we lost our stack
498                 if (!d_stacklist->getActivestack())
499                   return true;
500                 if (s->getPos() == target->getPos())
501                   {
502                     GameMap::groupStacks(s);
503                     continue;
504                   }
505                 continue;
506             }
507         }
508         
509         // second step: try to resupply
510         if (!d_maniac)
511         {
512             City *target = Citylist::getInstance()->getNearestFriendlyCity(s->getPos());
513             if (s->isFull() == false && target)
514             {
515                 debug("Restocking in " <<target->getName())
516                 // try to move to the north west part of the city (where the units
517                 // move after production), otherwise just wait and stand around
518
519                 if (target->contains(s->getPos()) == false)
520                   {
521                     debug("Stack is not in " << target->getName() << " yet" <<endl);
522                     int mp = s->getPath()->calculateToCity(s, target);
523                     if (mp > 0)
524                       {
525                         stack_moved |= stackMove(s);
526
527                         // the stack could have joined another stack waiting there
528                         if (!d_stacklist->getActivestack())
529                           return true;
530                         if (stack_moved)
531                           {
532                             GameMap::groupStacks(s);
533                             s->clearPath();
534                             continue;
535                           }
536                       }
537                   }
538                 else if (s->getPos() != target->getPos())
539                   {
540                     debug("Stack is inside " << target->getName() << endl);
541                     //if we're not in the upper right corner
542                     s->getPath()->calculate(s, target->getPos());
543                     //go there, and take as many as we can
544                     Stack *new_stack = NULL;
545                     stack_moved |= stackSplitAndMove(s, new_stack);
546                     //in case we lost our stack
547                     if (!d_stacklist->getActivestack())
548                       return true;
549                     if (stack_moved)
550                       {
551                             GameMap::groupStacks(s);
552                             s->clearPath();
553                             GameMap::groupStacks(target->getPos());
554                             return true;
555                       }
556                   }
557                 else
558                   {
559                 //otherwise just stay put in the city
560                     GameMap::groupStacks(s);
561                     continue;
562                   }
563             }
564
565             // third step: non-maniac players attack only enemy cities
566             else
567               {
568                 target = NULL;
569                 PathCalculator pc(s, true, 10, -1);
570                 guint32 moves1 = 0, turns1 = 0, moves2 = 0, turns2 = 0;
571                 Path *target1_path = NULL;
572                 Path *target2_path = NULL;
573                 Citylist *cl = Citylist::getInstance();
574                 City *target1 = cl->getNearestEnemyCity(s->getPos());
575                 City *target2 = cl->getNearestForeignCity(s->getPos());
576                 if (target1)
577                   target1_path = pc.calculateToCity(target1, moves1, turns1);
578                 else
579                   target1_path = new Path();
580                 if (!target2)
581                   {
582                     delete target1_path;
583                     return false; //it's game over and we're still moving
584                   }
585                 target2_path = pc.calculateToCity(target2, moves2, turns2);
586
587                 //no enemies?  then go for the nearest foreign city.
588                 //if diplomacy isn't on and we hit this, then it's game over
589                 if (!target1)
590                   target = target2;
591
592                 //is the enemy city far enough away that a foreign city
593                 //outweighs it?
594                 else if (target1_path->size() / 13 > target2_path->size())
595                   target = target2;
596                 else
597                   target = target1;
598                 delete target1_path;
599                 delete target2_path;
600
601                 if (target == target2)
602                   {
603                     if (GameScenarioOptions::s_diplomacy == true)
604                       d_diplomacy->needNewEnemy(target->getOwner());
605                     // try to wait a turn until we're at war
606                     if (target1)
607                       target = target1;
608                   }
609
610                 if (!target)    // strange situation
611                   {
612                     cerr << "yet another bad situation!!\n";
613                     s->setParked(true);
614                     return true;
615                   }
616
617                 debug("Attacking " << target->getName() << " (" << 
618                       target->getPos().x <<","<< target->getPos().y << ")")
619                   int moves = s->getPath()->calculateToCity(s, target);
620                 debug("Moves to enemy city: " << moves);
621
622                 if (moves >= 1)
623                   {
624                     stack_moved |= stackMove(s);
625                     s = d_stacklist->getActivestack();
626                     if (!d_stacklist->getActivestack())
627                       return true;
628                     //if we didn't get there
629                     if (target->getOwner() != s->getOwner())
630                       {
631                         //and the target city is empty
632                         if (target->countDefenders() == 0)
633                           {
634                             //attack it if we can reach it.
635                             Stack *new_stack = NULL;
636                             int moved = stackSplitAndMove(s, new_stack);
637                             stack_moved |=  moved;
638                             if (moved)
639                               {
640                                 GameMap::groupStacks(s);
641                                 GameMap::groupStacks(target->getPos());
642                                 return true;
643                               }
644                           }
645                       }
646                   }
647                 else
648                   {
649                    // an enemy city is completely surrouned by other stacks, or the way is blocked by a signle enemy stack
650                     //let us presume this is temporary and just leave the stack here
651                     //for some reason we can't set parked on this thing
652                     //and have it realize it, after we return true.
653                     //why is that?
654                     printf("crap, it happened with a stack at %d,%d\n", s->getPos().x, s->getPos().y);
655                     printf("moves is %d\n", moves);
656                     printf("Destination was %d,%d (%s)\n", target->getPos().x, target->getPos().y, target->getName().c_str());
657                     stackDisband(s);
658                     return true;
659                   }
660
661                 // a stack has died ->restart
662                 if (!d_stacklist->getActivestack())
663                   return true;
664
665                 continue;
666               }
667         }
668
669
670         // fourth step: maniac players attack everything that is close if they can
671         // reach it or cities otherwise.
672         if (d_maniac)
673           {
674             const Threatlist* threats = d_analysis->getThreatsInOrder(s->getPos());
675             Threatlist::const_iterator tit = threats->begin();
676             const Threat* target = 0;
677
678             // prefer weak forces (take strong if neccessary) and stop after 10
679             // stacks
680             for (int i = 0; tit != threats->end() && i < 10; tit++, i++)
681               {
682                 // in a first step, we only look at enemy stacks
683                 if ((*tit)->isCity() || (*tit)->isRuin())
684                   continue;
685
686                 // ignore stacks out of reach
687                 Vector<int> threatpos = (*tit)->getClosestPoint(s->getPos());
688                 if (threatpos == Vector<int>(-1, -1))
689                   continue;
690
691                 guint32 mp = s->getPath()->calculate(s, threatpos);
692                 if ((int)mp <= 0 || mp > s->getMoves())
693                   continue;
694
695                 target = *tit;
696                 break;
697
698               }
699
700             // now we need to choose. If we found a target, attack it, otherwise
701             // attack the closest city.
702             Vector<int> pos = Vector<int>(-1,-1);
703             if (target)
704               {
705                 pos = target->getClosestPoint(s->getPos());
706                 debug("Maniac mode, found target at (" <<pos.x <<"," <<pos.y <<")")
707               }
708             else
709               {
710                 Citylist *cl = Citylist::getInstance();
711                 City *enemy_city = cl->getNearestForeignCity(s->getPos());
712                 if (enemy_city)
713                   {
714                     pos  = enemy_city->getPos();
715                     debug("Maniac, found no targets, attacking city " << enemy_city->getName() << " at (" <<pos.x <<"," <<pos.y <<")")
716                   }
717               }
718
719             if (pos == Vector<int>(-1,-1))
720               return false;
721
722             int mp = s->getPath()->calculate(s, pos);
723             if (mp > 0)
724               {
725               //printf ("stack %d at %d,%d moving %d with %d moves\n",
726                       //s->getId(), s->getPos().x, s->getPos().y,
727                       //mp, s->getMoves());
728                 bool moved = stackMove(s);
729                 //printf("result of move: %d\n", moved);
730                 stack_moved |= moved;
731                 //in case we lost our stack
732                 if (!d_stacklist->getActivestack())
733                   return true;
734                 s = d_stacklist->getActivestack();
735               }
736             else
737               {
738                 printf ("we're going the wrong way (mp is %d)!!\n", mp);
739                 printf ("this means we couldn't calculate a path from %d,%d to %d,%d\n", s->getPos().x, s->getPos().y, pos.x, pos.y);
740                 //sleep (10);
741                 Citylist *cl = Citylist::getInstance();
742                 City *friendly_city = cl->getNearestFriendlyCity(s->getPos());
743                 if (friendly_city)
744                   {
745                     mp = s->getPath()->calculate(s, friendly_city->getPos());
746                     if (mp > 0)
747                       {
748                       stack_moved |= stackMove(s);
749                 //in case we lost our stack
750                 if (!d_stacklist->getActivestack())
751                   return true;
752                       }
753                     else
754                       stack_moved |= false;
755                   }
756                 else
757                   {
758                     //we can't find anyplace to move to!
759                     //so we stay put.
760                     stack_moved |= false;
761                   }
762               }
763
764             if (!d_stacklist->getActivestack())
765               return true;
766             continue;
767
768           }
769         if (abort_requested)
770           break;
771     }
772     return stack_moved;
773 }
774
775 bool AI_Fast::chooseTreachery (Stack *stack, Player *player, Vector <int> pos)
776 {
777   bool performTreachery = true;
778   return performTreachery;
779 }
780
781 bool AI_Fast::chooseHero(HeroProto *hero, City *city, int gold)
782 {
783   return true;
784 }
785
786 Reward *AI_Fast::chooseReward(Ruin *ruin, Sage *sage, Stack *stack)
787 {
788   //always pick the money.
789   for (Sage::iterator it = sage->begin(); it != sage->end(); it++)
790     if ((*it)->getType() == Reward::GOLD)
791       return (*it);
792   return sage->front();
793 }
794
795 Army::Stat AI_Fast::chooseStat(Hero *hero)
796 {
797   return Army::STRENGTH;
798 }
799
800 bool AI_Fast::chooseQuest(Hero *hero)
801 {
802   return true;
803 }
804 // End of file