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