1 // Copyright (C) 2000, 2001, 2002, 2003 Michael Bartl
2 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Ulf Lorenz
3 // Copyright (C) 2004, 2005 Andrea Paternesi
4 // Copyright (C) 2004 John Farrell
5 // Copyright (C) 2005 Bryan Duff
6 // Copyright (C) 2007, 2008, 2009, 2010, 2011, 2014, 2015, 2017,
7 // 2020 Ben Asselstine
8 // Copyright (C) 2007, 2008 Ole Laursen
9 //
10 //  This program is free software; you can redistribute it and/or modify
11 //  it under the terms of the GNU General Public License as published by
12 //  the Free Software Foundation; either version 3 of the License, or
13 //  (at your option) any later version.
14 //
15 //  This program is distributed in the hope that it will be useful,
16 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
17 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 //  GNU Library General Public License for more details.
19 //
20 //  You should have received a copy of the GNU General Public License
21 //  along with this program; if not, write to the Free Software
22 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 //  02110-1301, USA.
24 
25 #include <stdlib.h>
26 #include <assert.h>
27 #include <fstream>
28 #include <sstream>
29 #include <sigc++/functors/mem_fun.h>
30 
31 #include "MoveResult.h"
32 #include "player.h"
33 #include "playerlist.h"
34 #include "stacklist.h"
35 #include "citylist.h"
36 #include "templelist.h"
37 #include "city.h"
38 #include "path.h"
39 #include "armysetlist.h"
40 #include "real_player.h"
41 #include "ai_dummy.h"
42 #include "ai_fast.h"
43 #include "ai_smart.h"
44 #include "network_player.h"
45 #include "GameMap.h"
46 #include "counter.h"
47 #include "army.h"
48 #include "hero.h"
49 #include "heroproto.h"
50 #include "herotemplates.h"
51 #include "Configuration.h"
52 #include "GameScenarioOptions.h"
53 #include "action.h"
54 #include "network-action.h"
55 #include "history.h"
56 #include "network-history.h"
57 #include "AI_Analysis.h"
58 #include "AI_Allocation.h"
59 #include "FogMap.h"
60 #include "QuestsManager.h"
61 #include "signpost.h"
62 #include "vectoredunit.h"
63 #include "ucompose.hpp"
64 #include "armyprodbase.h"
65 #include "Triumphs.h"
66 #include "Backpack.h"
67 #include "MapBackpack.h"
68 #include "PathCalculator.h"
69 #include "stacktile.h"
70 #include "temple.h"
71 #include "QCityOccupy.h"
72 #include "QCitySack.h"
73 #include "QCityRaze.h"
74 #include "QPillageGold.h"
75 #include "Quest.h"
76 #include "QKillHero.h"
77 #include "QEnemyArmies.h"
78 #include "QEnemyArmytype.h"
79 #include "callback-enums.h"
80 #include "stackreflist.h"
81 #include "SightMap.h"
82 #include "rewardlist.h"
83 #include "Item.h"
84 #include "ItemProto.h"
85 #include "xmlhelper.h"
86 #include "rnd.h"
87 #include "game-actionlist.h"
88 #include "turn-actionlist.h"
89 #include "keeper.h"
90 
91 //#define debug(x) {std::cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<std::flush<<std::endl;}
92 #define debug(x)
93 
94 Glib::ustring Player::d_tag = "player";
95 
Player(Glib::ustring name,guint32 armyset,Gdk::RGBA color,int width,int height,Type type,int player_no)96 Player::Player(Glib::ustring name, guint32 armyset, Gdk::RGBA color, int width,
97 	       int height, Type type, int player_no)
98     :d_color(color), d_name(name), d_armyset(armyset), d_gold(1000),
99     d_dead(false), d_immortal(false), d_type(type), d_upkeep(0), d_income(0),
100     d_observable(true), surrendered(false), abort_requested(false)
101 {
102     if (player_no != -1)
103 	d_id = player_no;
104     else
105 	d_id = fl_counter->getNextId();
106     d_stacklist = new Stacklist();
107     debug("type of " << d_name << " is " << type)
108 
109     d_fogmap = new FogMap(width, height);
110 
111     //initial fight order is the order in which the armies appear
112     //in the default.xml file.
113     for (auto i: *Armysetlist::getInstance()->get(d_armyset))
114       d_fight_order.push_back(i->getId());
115 
116     for (unsigned int i = 0 ; i < MAX_PLAYERS; i++)
117     {
118       d_diplomatic_state[i] = AT_PEACE;
119       d_diplomatic_proposal[i] = NO_PROPOSAL;
120       d_diplomatic_score[i] = DIPLOMACY_STARTING_SCORE;
121     }
122     d_diplomatic_rank = 0;
123     d_diplomatic_title = Glib::ustring("");
124 
125     d_triumphs = new Triumphs();
126 }
127 
Player(const Player & player)128 Player::Player(const Player& player)
129     :sigc::trackable(player), d_color(player.d_color), d_name(player.d_name),
130     d_armyset(player.d_armyset), d_gold(player.d_gold), d_dead(player.d_dead),
131     d_immortal(player.d_immortal), d_type(player.d_type), d_id(player.d_id),
132     d_fight_order(player.d_fight_order), d_upkeep(player.d_upkeep),
133     d_income(player.d_income), d_observable(player.d_observable),
134     surrendered(player.surrendered),abort_requested(player.abort_requested)
135 {
136   // as the other player is propably dumped somehow, we need to deep copy
137   // everything.
138   d_stacklist = new Stacklist();
139   for (Stacklist::iterator it = player.d_stacklist->begin();
140        it != player.d_stacklist->end(); it++)
141     {
142       Stack* mine = new Stack(**it, true);
143       // change the stack's loyalty
144       mine->setPlayer(this);
145       d_stacklist->add(mine);
146     }
147 
148   // copy actions
149   for (auto ait: player.d_actions)
150     d_actions.push_back(Action::copy(ait));
151 
152   // copy events
153   for (auto pit: player.d_history)
154     d_history.push_back(History::copy(pit));
155 
156   // copy fogmap
157   d_fogmap = new FogMap(*player.getFogMap());
158 
159   // copy diplomatic states
160   for (unsigned int i = 0 ; i < MAX_PLAYERS; i++)
161     {
162       d_diplomatic_state[i] = player.d_diplomatic_state[i];
163       d_diplomatic_proposal[i] = player.d_diplomatic_proposal[i];
164       d_diplomatic_score[i] = player.d_diplomatic_score[i];
165     }
166   d_diplomatic_rank = player.d_diplomatic_rank;
167   d_diplomatic_title = player.d_diplomatic_title;
168 
169   d_triumphs = new Triumphs(*player.getTriumphs());
170 }
171 
Player(XML_Helper * helper)172 Player::Player(XML_Helper* helper)
173     :d_stacklist(0), d_fogmap(0), surrendered(false), abort_requested(false)
174 {
175     helper->getData(d_id, "id");
176     helper->getData(d_name, "name");
177     helper->getData(d_gold, "gold");
178     helper->getData(d_dead, "dead");
179     helper->getData(d_immortal, "immortal");
180     Glib::ustring type_str;
181     helper->getData(type_str, "type");
182     d_type = playerTypeFromString(type_str);
183     helper->getData(d_upkeep, "upkeep");
184     helper->getData(d_income, "income");
185     helper->getData(d_color, "color");
186     helper->getData(d_armyset, "armyset");
187 
188     // Read in Fight Order.  One ranking per army type.
189     Glib::ustring fight_order;
190     std::stringstream sfight_order;
191     guint32 val;
192     helper->getData(fight_order, "fight_order");
193     sfight_order.str(fight_order);
194     for (auto i: *Armysetlist::getInstance()->get (d_armyset))
195       {
196         (void)i;
197         sfight_order >> val;
198         d_fight_order.push_back(val);
199       }
200 
201     // Read in Diplomatic States.  One state per player.
202     Glib::ustring diplomatic_states;
203     std::stringstream sdiplomatic_states;
204     helper->getData(diplomatic_states, "diplomatic_states");
205     sdiplomatic_states.str(diplomatic_states);
206     for (unsigned int i = 0; i < MAX_PLAYERS; i++)
207     {
208             sdiplomatic_states >> val;
209 	    d_diplomatic_state[i] = DiplomaticState(val);
210     }
211 
212     helper->getData(d_diplomatic_rank, "diplomatic_rank");
213     helper->getData(d_diplomatic_title, "diplomatic_title");
214 
215     // Read in Diplomatic Proposals.  One proposal per player.
216     Glib::ustring diplomatic_proposals;
217     std::stringstream sdiplomatic_proposals;
218     helper->getData(diplomatic_proposals, "diplomatic_proposals");
219     sdiplomatic_proposals.str(diplomatic_proposals);
220     for (unsigned int i = 0; i < MAX_PLAYERS; i++)
221     {
222             sdiplomatic_proposals>> val;
223 	    d_diplomatic_proposal[i] = DiplomaticProposal(val);
224     }
225 
226     // Read in Diplomatic Scores.  One score per player.
227     Glib::ustring diplomatic_scores;
228     std::stringstream sdiplomatic_scores;
229     helper->getData(diplomatic_scores, "diplomatic_scores");
230     sdiplomatic_scores.str(diplomatic_scores);
231     for (unsigned int i = 0; i < MAX_PLAYERS; i++)
232     {
233             sdiplomatic_scores >> val;
234 	    d_diplomatic_score[i] = val;
235     }
236     helper->getData(d_observable, "observable");
237 
238     helper->registerTag(Action::d_tag, sigc::mem_fun(this, &Player::load));
239     helper->registerTag(History::d_tag, sigc::mem_fun(this, &Player::load));
240     helper->registerTag(Stacklist::d_tag, sigc::mem_fun(this, &Player::load));
241     helper->registerTag(FogMap::d_tag, sigc::mem_fun(this, &Player::load));
242     helper->registerTag(Triumphs::d_tag, sigc::mem_fun(this, &Player::load));
243 
244 }
245 
~Player()246 Player::~Player()
247 {
248     if (d_stacklist)
249     {
250         delete d_stacklist;
251         d_stacklist = NULL;
252     }
253     if (d_fogmap)
254       {
255         delete d_fogmap;
256         d_fogmap = NULL;
257       }
258 
259     delete d_triumphs;
260     d_triumphs = NULL;
261     clearActionlist();
262     clearHistorylist();
263 }
264 
create(Glib::ustring name,guint32 armyset,Gdk::RGBA color,int width,int height,Type type)265 Player* Player::create(Glib::ustring name, guint32 armyset, Gdk::RGBA color, int width, int height, Type type)
266 {
267   switch(type)
268   {
269   case HUMAN:
270     return (new RealPlayer(name, armyset, color, width, height));
271   case AI_FAST:
272     return (new AI_Fast(name, armyset, color, width, height));
273   case AI_DUMMY:
274     return (new AI_Dummy(name, armyset, color, width, height));
275   case AI_SMART:
276     return (new AI_Smart(name, armyset, color, width, height));
277   case NETWORKED:
278     return (new NetworkPlayer(name, armyset, color, width, height));
279   }
280 
281   return 0;
282 }
283 
create(Player * orig,Type type)284 Player* Player::create(Player* orig, Type type)
285 {
286     switch(type)
287     {
288         case HUMAN:
289             return new RealPlayer(*orig);
290         case AI_FAST:
291             return new AI_Fast(*orig);
292         case AI_DUMMY:
293             return new AI_Dummy(*orig);
294         case AI_SMART:
295             return new AI_Smart(*orig);
296         case NETWORKED:
297             return new NetworkPlayer(*orig);
298     }
299 
300     return 0;
301 }
302 
303 
initTurn()304 void Player::initTurn()
305 {
306   //printf("local: dumping %lu actions\n", d_actions.size());
307   //for (auto i: d_actions)
308     //{
309       //printf("\t%s %s\n", Action::actionTypeToString(i->getType()).c_str(), i->dump().c_str());
310     //}
311 
312   GameActionlist::getInstance()->add(new TurnActionlist (this, d_actions));
313   clearActionlist();
314   History_StartTurn* item = new History_StartTurn();
315   addHistory(item);
316   guint32 order = Playerlist::getInstance()->getTurnOrderNumber(this);
317   Action_InitTurn* action = new Action_InitTurn(order);
318   addAction(action);
319 }
320 
setColor(Gdk::RGBA c)321 void Player::setColor(Gdk::RGBA c)
322 {
323     d_color = c;
324 }
325 
addGold(int gold)326 void Player::addGold(int gold)
327 {
328     d_gold += gold;
329     schangingStats.emit();
330 }
331 
withdrawGold(int gold)332 void Player::withdrawGold(int gold)
333 {
334     d_gold -= gold;
335     if (d_gold < 0)
336       d_gold = 0; /* bankrupt.  should we start turning off city production? */
337     schangingStats.emit();
338 }
339 
getName() const340 Glib::ustring Player::getName() const
341 {
342   return d_name;
343 }
344 
dumpActionlist() const345 void Player::dumpActionlist() const
346 {
347     for (auto it: d_actions)
348       std::cerr << it->dump() << std::endl;
349 }
350 
dumpHistorylist() const351 void Player::dumpHistorylist() const
352 {
353   for (auto it: d_history)
354     std::cerr << it->dump() << std::endl;
355 }
356 
clearActionlist()357 void Player::clearActionlist()
358 {
359   for (auto it: d_actions)
360     delete (it);
361   d_actions.clear();
362 }
363 
clearHistorylist(std::list<History * > & history)364 void Player::clearHistorylist(std::list<History*> &history)
365 {
366   for (auto it: history)
367     delete (it);
368   history.clear();
369 }
370 
clearHistorylist()371 void Player::clearHistorylist()
372 {
373   clearHistorylist(d_history);
374 }
375 
addStack(Stack * stack)376 void Player::addStack(Stack* stack)
377 {
378   debug("Player " << getName() << ": Stack Id: " << stack->getId() << " added to stacklist");
379     stack->setPlayer(this);
380     d_stacklist->add(stack);
381 }
382 
deleteStack(Stack * stack)383 bool Player::deleteStack(Stack* stack)
384 {
385   if (isComputer() == true)
386     {
387       AI_Analysis::deleteStack(stack->getId());
388       AI_Allocation::deleteStack(stack);
389     }
390     return d_stacklist->flRemove(stack);
391 }
392 
kill(bool record_action)393 void Player::kill(bool record_action)
394 {
395   doKill();
396   if (record_action)
397     {
398       addAction(new Action_Kill());
399       if (d_immortal == false)
400         addHistory(new History_PlayerVanquished());
401     }
402   schangingStats.emit();
403 }
404 
doKill()405 void Player::doKill()
406 {
407     if (d_immortal)
408         // ignore it
409         return;
410 
411     d_observable = false;
412 
413     d_dead = true;
414     //drop the bags of stuff that the heroes might be carrying
415     std::list<Hero*> h = getHeroes();
416     for (std::list<Hero*>::iterator it = h.begin(); it != h.end(); it++)
417       {
418 	Stack *s = d_stacklist->getArmyStackById((*it)->getId());
419 	if (s)
420 	  doStackDisband(s);
421       }
422     //get rid of all of the other stacks.
423     d_stacklist->flClear();
424 
425     // Since in some cases the player can be killed rather innocently
426     // (using reactions), we also need to clear the player's traces in the
427     // single cities
428     for (auto city: *Citylist::getInstance())
429       if (city->getOwner() == this && city->isBurnt() == false)
430         Playerlist::getInstance()->getNeutral()->takeCityInPossession(city);
431 
432     d_diplomatic_rank = 0;
433     d_diplomatic_title = Glib::ustring("");
434 }
435 
save(XML_Helper * helper) const436 bool Player::save(XML_Helper* helper) const
437 {
438     bool retval = true;
439 
440     retval &= helper->saveData("id", d_id);
441     retval &= helper->saveData("name", d_name);
442     retval &= helper->saveData("color", d_color);
443     retval &= helper->saveData("armyset", d_armyset);
444     retval &= helper->saveData("gold", d_gold);
445     retval &= helper->saveData("dead", d_dead);
446     retval &= helper->saveData("immortal", d_immortal);
447     Glib::ustring type_str = playerTypeToString(Player::Type(d_type));
448     retval &= helper->saveData("type", type_str);
449     debug("type of " << d_name << " is " << d_type)
450     retval &= helper->saveData("upkeep", d_upkeep);
451     retval &= helper->saveData("income", d_income);
452 
453     // save the fight order, one ranking per army type
454     std::stringstream fight_order;
455     for (std::list<guint32>::const_iterator it = d_fight_order.begin();
456          it != d_fight_order.end(); it++)
457       {
458         fight_order << (*it) << " ";
459       }
460     retval &= helper->saveData("fight_order", fight_order.str());
461 
462     // save the diplomatic states, one state per player
463     std::stringstream diplomatic_states;
464     for (unsigned int i = 0; i < MAX_PLAYERS; i++)
465       {
466 	diplomatic_states << d_diplomatic_state[i] << " ";
467       }
468     retval &= helper->saveData("diplomatic_states", diplomatic_states.str());
469 
470     retval &= helper->saveData("diplomatic_rank", d_diplomatic_rank);
471     retval &= helper->saveData("diplomatic_title", d_diplomatic_title);
472 
473     // save the diplomatic proposals, one proposal per player
474     std::stringstream diplomatic_proposals;
475     for (unsigned int i = 0; i < MAX_PLAYERS; i++)
476       {
477 	diplomatic_proposals << d_diplomatic_proposal[i] << " ";
478       }
479     retval &= helper->saveData("diplomatic_proposals",
480 			       diplomatic_proposals.str());
481 
482     // save the diplomatic scores, one score per player
483     std::stringstream diplomatic_scores;
484     for (unsigned int i = 0; i < MAX_PLAYERS; i++)
485       {
486 	diplomatic_scores << d_diplomatic_score[i] << " ";
487       }
488     retval &= helper->saveData("diplomatic_scores", diplomatic_scores.str());
489 
490     retval &= helper->saveData("observable", d_observable);
491 
492     //save the actionlist
493     for (auto it: d_actions)
494         retval &= it->save(helper);
495 
496     //save the pasteventlist
497     for (auto it: d_history)
498       retval &= it->save(helper);
499 
500     retval &= d_stacklist->save(helper);
501     retval &= d_fogmap->save(helper);
502     retval &= d_triumphs->save(helper);
503 
504     return retval;
505 }
506 
loadPlayer(XML_Helper * helper)507 Player* Player::loadPlayer(XML_Helper* helper)
508 {
509     Type type;
510     Glib::ustring type_str;
511     helper->getData(type_str, "type");
512     type = playerTypeFromString(type_str);
513 
514     switch (type)
515     {
516         case HUMAN:
517             return new RealPlayer(helper);
518         case AI_FAST:
519             return new AI_Fast(helper);
520         case AI_SMART:
521             return new AI_Smart(helper);
522         case AI_DUMMY:
523             return new AI_Dummy(helper);
524         case NETWORKED:
525             return new NetworkPlayer(helper);
526     }
527 
528     return 0;
529 }
530 
load(Glib::ustring tag,XML_Helper * helper)531 bool Player::load(Glib::ustring tag, XML_Helper* helper)
532 {
533     if (tag == Action::d_tag)
534     {
535         Action* action;
536         action = Action::handle_load(helper);
537         d_actions.push_back(action);
538     }
539     if (tag == History::d_tag)
540     {
541         History* history;
542         history = History::handle_load(helper);
543         d_history.push_back(history);
544     }
545 
546     if (tag == Stacklist::d_tag)
547         d_stacklist = new Stacklist(helper);
548 
549     if (tag == FogMap::d_tag)
550         d_fogmap = new FogMap(helper);
551 
552     if (tag == Triumphs::d_tag)
553 	d_triumphs = new Triumphs(helper);
554 
555     return true;
556 }
557 
addAction(Action * action)558 void Player::addAction(Action *action)
559 {
560   d_actions.push_back(action);
561   acting.emit (action, getId());
562 }
563 
addHistory(History * history)564 void Player::addHistory(History *history)
565 {
566   d_history.push_back(history);
567   history_written.emit(history, getId());
568 }
569 
getScore() const570 guint32 Player::getScore() const
571 {
572   //go get our last published score in the history
573   guint32 score = 0;
574   std::list<History*>::const_reverse_iterator it = d_history.rbegin();
575   for (; it != d_history.rend(); it++)
576     {
577       if ((*it)->getType() == History::SCORE)
578         {
579           score = static_cast<History_Score*>(*it)->getScore();
580           break;
581         }
582     }
583   return score;
584 }
585 
calculateUpkeep()586 void Player::calculateUpkeep()
587 {
588   d_upkeep = 0;
589   Stacklist *sl = getStacklist();
590   for (Stacklist::iterator i = sl->begin(), iend = sl->end(); i != iend; ++i)
591     d_upkeep += (*i)->getUpkeep();
592 }
593 
calculateIncome()594 void Player::calculateIncome()
595 {
596     d_income = 0;
597     for (auto city: *Citylist::getInstance())
598       if (city->getOwner() == this)
599         d_income += city->getGold();
600 }
601 
doSetFightOrder(std::list<guint32> order)602 void Player::doSetFightOrder(std::list<guint32> order)
603 {
604   d_fight_order = order;
605 }
606 
setFightOrder(std::list<guint32> order)607 void Player::setFightOrder(std::list<guint32> order)
608 {
609   doSetFightOrder(order);
610 
611   addAction(new Action_FightOrder(order));
612 }
613 
doStackSplitArmy(Stack * s,Army * a,Stack * & new_stack)614 bool Player::doStackSplitArmy(Stack *s, Army *a, Stack *& new_stack)
615 {
616   new_stack = s->splitArmy(a);
617   if (new_stack != NULL)
618     {
619       debug("1. split stack " << new_stack->getId() << " from stack " << s->getId());
620       addStack(new_stack);
621       supdatingStack.emit(0);
622       return true;
623     }
624   return false;
625 }
626 
627 
doStackSplitArmies(Stack * stack,std::list<guint32> armies,Stack * & new_stack)628 bool Player::doStackSplitArmies(Stack *stack, std::list<guint32> armies,
629 				Stack *& new_stack)
630 {
631   new_stack = stack->splitArmies(armies);
632   if (new_stack != NULL)
633     {
634       addStack(new_stack);
635       return true;
636     }
637   return false;
638 }
639 
stackSplitArmies(Stack * stack,std::list<guint32> armies)640 Stack *Player::stackSplitArmies(Stack *stack, std::list<guint32> armies)
641 {
642   Stack *new_stack = NULL;
643   bool retval = doStackSplitArmies(stack, armies, new_stack);
644   if (retval == true)
645     {
646       addAction(new Action_Split(stack, new_stack));
647       addAction(new Action_ReorderArmies(stack));
648       addAction(new Action_ReorderArmies(new_stack));
649     }
650   return new_stack;
651 }
652 
stackSplitArmy(Stack * stack,Army * a)653 Stack *Player::stackSplitArmy(Stack *stack, Army *a)
654 {
655   Stack *new_stack = NULL;
656   bool retval = doStackSplitArmy(stack, a, new_stack);
657   if (retval == true)
658     {
659       addAction(new Action_Split(stack, new_stack));
660       addAction(new Action_ReorderArmies(stack));
661     }
662   return new_stack;
663 }
664 
doStackJoin(Stack * receiver,Stack * joining)665 void Player::doStackJoin(Stack* receiver, Stack* joining)
666 {
667    receiver->join(joining);
668    deleteStack(joining);
669     //d_stacklist->flRemove(joining);
670 
671     d_stacklist->setActivestack(receiver);
672 }
673 
stackJoin(Stack * receiver,Stack * joining)674 bool Player::stackJoin(Stack* receiver, Stack* joining)
675 {
676 
677     if ((receiver == 0) || (joining == 0))
678         return false;
679     debug("Player::stackJoin("<<receiver->getId()<<","<<joining->getId()<<")");
680 
681     assert (receiver->getPos() == joining->getPos());
682     if (GameMap::canJoin(joining, receiver) == false)
683       return false;
684 
685     Action_Join *action = new Action_Join (receiver, joining);
686 
687     doStackJoin(receiver, joining);
688     addAction(action);
689 
690     addAction(new Action_ReorderArmies(receiver));
691 
692     supdatingStack.emit(0);
693     return true;
694 }
695 
stackSplitAndMove(Stack * s,Stack * & new_stack)696 bool Player::stackSplitAndMove(Stack* s, Stack *& new_stack)
697 {
698   if (s->hasPath() == false)
699     return false;
700   Vector<int> pos = s->getLastReachablePointInPath();
701   if (pos == Vector<int>(-1,-1))
702     return false;
703   Stack *join = GameMap::getFriendlyStack(pos);
704   if (join)
705     return stackSplitAndMoveToJoin(s, join, new_stack);
706   else
707     return stackSplitAndMoveToAttack(s, new_stack);
708 }
709 
stackSplitAndMoveToJoin(Stack * s,Stack * join,Stack * & new_stack)710 bool Player::stackSplitAndMoveToJoin(Stack* s, Stack *join, Stack *& new_stack)
711 {
712   //the stack can't get there, but maybe part of the stack can.
713   if (s->hasPath() == false)
714     return false;
715 
716   std::list<guint32> ids;
717   ids = s->determineReachableArmies(s->getLastPointInPath());
718   if (ids.size() == 0)
719     return false;
720   //if they're all reachable and we can join, just move them
721   if (ids.size() == s->size() && GameMap::canJoin(s, join) == true)
722     return stackMove(s);
723 
724   //let's take who we can fit.
725   if (ids.size() > join->getMaxArmiesToJoin())
726     {
727       int diff = ids.size() - join->getMaxArmiesToJoin();
728       for (int i = 0; i < diff; i++)
729         ids.pop_front();
730     }
731 
732   if (ids.size() == 0)
733     return false;
734   if (s->fliesWithItemAndNonFlyersOverWaterOrMountains())
735     return false;
736   //okay, ids.size armies can make the move.  but can that tile accept it?
737   new_stack = stackSplitArmies(s, ids);
738   if (new_stack)
739     {
740       setActivestack(new_stack);
741       return stackMove(new_stack);
742     }
743   return false;
744 }
745 
stackSplitAndMoveToAttack(Stack * s,Stack * & new_stack)746 bool Player::stackSplitAndMoveToAttack(Stack* s, Stack *& new_stack)
747 {
748   //the stack can't get there, but maybe part of the stack can.
749   if (s->getPath()->empty())
750     return false;
751 
752   std::list<guint32> ids;
753   ids = s->determineReachableArmies(s->getLastPointInPath());
754   if (ids.size() == 0)
755     return false;
756   if (ids.size() == s->size())
757     return stackMove(s);
758   if (s->fliesWithItemAndNonFlyersOverWaterOrMountains())
759     return false;
760 
761   new_stack = stackSplitArmies(s, ids);
762   if (new_stack)
763     {
764       setActivestack(new_stack);
765       return stackMove(new_stack);
766     }
767   return false;
768 }
769 
stackMove(Stack * s)770 bool Player::stackMove(Stack* s)
771 {
772     debug("Player::stackMove(Stack*)")
773 
774     if (s->getPath()->empty())
775     {
776         return false;
777     }
778 
779     MoveResult *result = stackMove(s, s->getLastPointInPath(), true);
780     bool ret = result->didSomething();//result->moveSucceeded();
781     delete result;
782     result = 0;
783     return ret;
784 }
785 
nextStepOnEnemyStackOrCity(Stack * s) const786 bool Player::nextStepOnEnemyStackOrCity(Stack *s) const
787 {
788   Vector<int> dest = s->getFirstPointInPath();
789   if (dest != Vector<int>(-1,-1))
790     {
791       if (GameMap::getEnemyStack(dest))
792 	return true;
793       City *enemy = GameMap::getEnemyCity(dest);
794       if (enemy && enemy->isBurnt() == false)
795 	return true;
796     }
797   return false;
798 }
799 
stackMove(Stack * s,Vector<int> dest)800 MoveResult *Player::stackMove(Stack* s, Vector<int> dest)
801 {
802   if (dest == Vector<int>(-1,-1))
803     return stackMove(s, dest, true);
804   else
805     return stackMove(s, dest, false);
806 }
807 
stackMove(Stack * s,Vector<int> dest,bool follow)808 MoveResult *Player::stackMove(Stack* s, Vector<int> dest, bool follow)
809 {
810     bool searched_temple = false;
811     bool searched_ruin = false;
812     bool got_quest = false;
813     bool picked_up = false;
814     debug("Player::stack_move()");
815     //if follow is set to true, follow an already calculated way, else
816     //calculate it here
817 
818     smovingStack.emit(s);
819     if (!follow)
820     {
821         s->getPath()->calculate(s, dest);
822     }
823 
824     if (s->getPath()->empty())
825       {
826 	MoveResult *result = new MoveResult;
827 	result->setReachedEndOfPath(true);
828         sstoppingStack.emit();
829 	return result;
830       }
831 
832     int stepCount = 0;
833     int moves_left = s->getPath()->getMovesExhaustedAtPoint();
834     while (1)
835       {
836         if (abortRequested())
837           {
838             MoveResult *result = new MoveResult;
839             result->fillData(s, stepCount, searched_temple, searched_ruin, got_quest, picked_up);
840             result->setMoveAborted(true);
841             return result;
842           }
843 	if (s->getPath()->size() <= 1)
844 	  break;
845 	if (nextStepOnEnemyStackOrCity(s) == true)
846 	  break;
847 
848         bool step = false;
849         step = stackMoveOneStep(s);
850         if (!step)
851           step = stackMoveOneStepOverTooLargeFriendlyStacks(s);
852         if (step)
853 	  {
854 	    stepCount++;
855 	    supdatingStack.emit(0);
856             if (isComputer())
857               {
858                 MoveResult *result = new MoveResult;
859                 result->fillData(s, stepCount, searched_temple, searched_ruin, got_quest, picked_up);
860                 bool stack_died = computerSearch(s, result);
861                 searched_temple = result->getComputerSearchedTemple();
862                 searched_ruin = result->getComputerSearchedRuin();
863                 got_quest = result->getComputerGotQuest();
864                 picked_up = result->getComputerPickedUpBag();
865                 if (stack_died)
866                   return result;
867                 else
868                   delete result;
869               }
870 	    moves_left--;
871 	    if (moves_left == 1)
872 	      break;
873 	  }
874 	else
875 	  break;
876       }
877 
878     //the idea here is that we're one move away from our destination.
879     //but in some cases we've already reached the end of the path
880     //because a fight has to happen.
881 
882     //did we jump over a too large friendly stack to an enemy stack or city?
883 
884     //alright, we've walked up to the last place in the path.
885     if (s->getPath()->size() >= 1 && s->enoughMoves())
886     //now look for fight targets, joins etc.
887     {
888 
889         Vector<int> pos = s->getFirstPointInPath();
890         City* city = GameMap::getCity(pos);
891         Stack* target = GameMap::getStack(pos);
892 
893 
894         //first fight_city to avoid ambiguity with fight_army
895         if (city && (city->getOwner() != this) && (!city->isBurnt()))
896 	  {
897 	    bool treachery = false;
898 	    if (this->getDiplomaticState (city->getOwner()) != AT_WAR)
899 	      {
900 		if (streacheryStack.emit (s, city->getOwner(),
901 					  city->getPos()) == false)
902 		  {
903 		    //we decided not to be treacherous
904 		    s->getPath()->clear();
905 		    MoveResult *moveResult = new MoveResult;
906 		    moveResult->setConsideredTreachery(true);
907 		    moveResult->fillData(s, stepCount, searched_temple, searched_ruin, got_quest, picked_up);
908                     if (isComputer())
909                       computerSearch(s, moveResult);
910                     sstoppingStack.emit();
911 		    return moveResult;
912 		  }
913 		else
914 		  treachery = true;
915 	      }
916 	    MoveResult *moveResult = new MoveResult;
917 	    moveResult->setTreachery(treachery);
918 	    moveResult->setConsideredTreachery(treachery);
919 	    if (stackMoveOneStep(s))
920 	      {
921 		stepCount++;
922 	      }
923 	    else
924 	      {
925 		moveResult->fillData(s, stepCount, searched_temple, searched_ruin, got_quest, picked_up);
926 		shaltedStack.emit(s);
927 		return moveResult;
928 	      }
929 
930 	    moveResult->fillData(s, stepCount, searched_temple, searched_ruin, got_quest, picked_up);
931             if (isComputer())
932               computerSearch(s, moveResult);
933 
934             Fight::Result result;
935             std::vector<Stack*> def_in_city = city->getDefenders();
936             if (!def_in_city.empty())
937             {
938                 // This is a hack to circumvent the limitations of stackFight.
939                 if (!target)
940                   target = def_in_city[0];
941 
942                 Fight *fight = stackFight(&s, &target);
943                 result = fight->getResult();
944                 finishStackFight (fight, &s, &target);
945                 delete fight;
946             }
947             else
948                 result = Fight::ATTACKER_WON;
949 
950             moveResult->setFightResult(result);
951 
952             // We may only take the city if we have defeated all defenders
953             if (result == Fight::ATTACKER_WON)
954             {
955                 adjustDiplomacyFromConqueringCity(city);
956                 conquerCity(city, s);
957                 invadeCity(city); //let AIs determine what to do with city
958 		shaltedStack.emit(s);
959             }
960             else
961               sstoppingStack.emit();
962 
963 	    cityfight_finished(city, result);
964             supdatingStack.emit(0);
965 
966             return moveResult;
967         }
968 
969         //another friendly stack => share the tile if we're human
970         else if (target && target->getOwner() == this /*&&
971 		 getType() == Player::HUMAN*/)
972           {
973             MoveResult *moveResult = new MoveResult;
974             if (stackMoveOneStep(s))
975               stepCount++;
976             else
977               moveResult->setTooLargeStackInTheWay(true);
978 
979 	    supdatingStack.emit(0);
980 	    shaltedStack.emit(d_stacklist->getActivestack());
981 	    moveResult->fillData(s, stepCount, searched_temple, searched_ruin, got_quest, picked_up);
982             if (isComputer())
983               computerSearch(s, moveResult);
984 
985             return moveResult;
986          }
987 
988         //enemy stack => fight
989         else if (target)
990         {
991 	  bool treachery = false;
992 	  if (this->getDiplomaticState (target->getOwner()) == AT_PEACE)
993 	    {
994 	      if (streacheryStack.emit (s, target->getOwner(),
995 					target->getPos()) == false)
996 		{
997 		  s->getPath()->clear();
998 		  MoveResult *moveResult = new MoveResult;
999 		  moveResult->setConsideredTreachery(true);
1000 		  moveResult->fillData(s, stepCount, searched_temple, searched_ruin, got_quest, picked_up);
1001                   if (isComputer())
1002                     computerSearch(s, moveResult);
1003                   sstoppingStack.emit();
1004 		  return moveResult;
1005 		}
1006 	      else
1007 		treachery = true;
1008 	    }
1009             MoveResult *moveResult = new MoveResult;
1010 	    moveResult->setTreachery(treachery);
1011 	    moveResult->setConsideredTreachery(treachery);
1012 
1013 	    moveResult->fillData(s, stepCount, searched_temple, searched_ruin, got_quest, picked_up);
1014             Fight *fight = stackFight(&s, &target);
1015             Fight::Result result = fight->getResult();
1016             moveResult->setFightResult(result);
1017             finishStackFight(fight, &s, &target);
1018             delete fight;
1019             if (result == Fight::ATTACKER_WON)
1020 	      {
1021                 if (stackMoveOneStep(s))
1022 		  stepCount++;
1023 		moveResult->fillData(s, stepCount, searched_temple, searched_ruin, got_quest, picked_up);
1024                 if (isComputer())
1025                   computerSearch(s, moveResult);
1026 	      }
1027 
1028             supdatingStack.emit(0);
1029             if (result == Fight::ATTACKER_WON)
1030 	      shaltedStack.emit(s);
1031             else
1032               sstoppingStack.emit();
1033             return moveResult;
1034         }
1035 
1036         //else
1037         if (stackMoveOneStep(s))
1038           {
1039             supdatingStack.emit(0);
1040             stepCount++;
1041           }
1042 
1043 	shaltedStack.emit(s);
1044 
1045         MoveResult *moveResult = new MoveResult;
1046 	moveResult->fillData(s, stepCount, searched_temple, searched_ruin, got_quest, picked_up);
1047         if (isComputer())
1048           computerSearch(s, moveResult);
1049         return moveResult;
1050     }
1051     else if (s->getPath()->size() >= 1 && s->enoughMoves() == false)
1052     {
1053 
1054         MoveResult *moveResult = new MoveResult;
1055 	moveResult->fillData(s, stepCount, searched_temple, searched_ruin, got_quest, picked_up);
1056       /* if we can't attack a city, don't remember it in the stack's path. */
1057         Vector<int> pos = s->getFirstPointInPath();
1058         City* city = GameMap::getCity(pos);
1059 	if (city && city->getOwner() != this && city->isBurnt() == false)
1060 	  s->clearPath();
1061 
1062         if (isComputer())
1063           computerSearch(s, moveResult);
1064         sstoppingStack.emit();
1065         return moveResult;
1066     }
1067 
1068     MoveResult *moveResult = new MoveResult;
1069     moveResult->setStepCount(stepCount);
1070     sstoppingStack.emit();
1071     return moveResult;
1072 }
1073 
1074 
stackMoveOneStepOverTooLargeFriendlyStacks(Stack * s)1075 bool Player::stackMoveOneStepOverTooLargeFriendlyStacks(Stack *s)
1076 {
1077   if (!s)
1078     return false;
1079 
1080   if (!s->enoughMoves())
1081     return false;
1082 
1083   if (s->getPath()->size() <= 1)
1084     return false;
1085 
1086   Vector<int> dest = s->getFirstPointInPath();
1087   Stack *another_stack = GameMap::getStack(dest);
1088   if (!another_stack)
1089     return false;
1090 
1091   if (another_stack->getOwner() != s->getOwner())
1092     return false;
1093 
1094   if (d_stacklist->canJumpOverTooLargeStack(s) == false)
1095     return false;
1096 
1097   Action_Move *a = new Action_Move(s, dest);
1098   s->moveOneStep(true);
1099   a->setMovesLeft(s->getMoves());
1100   a->setHasShip(s->hasShip());
1101   addAction(a);
1102   return true;
1103 }
1104 
computerSearch(Stack * s,MoveResult * r)1105 bool Player::computerSearch(Stack *s, MoveResult *r)
1106 {
1107   bool stack_died = false;
1108 
1109   Maptile *tile = GameMap::getInstance()->getTile(s->getPos());
1110 
1111   if (tile->getBackpack()->size() > 0)
1112     {
1113       if (computerChoosePickupBag(s, s->getPos(), 0, 0) == true)
1114         {
1115           r->setComputerPickedUpBag(true);
1116           Hero *hero = static_cast<Hero*>(s->getFirstHero());
1117           if (hero)
1118             heroPickupAllItems(hero, s->getPos());
1119         }
1120     }
1121 
1122   //are we at a computer and happen to be a temple, or ruin?
1123   if (GameMap::can_search(s) == false)
1124     return false;
1125 
1126   if (tile->getBuilding() == Maptile::TEMPLE)
1127     {
1128       if (s->hasHero())
1129         {
1130           if (computerChooseVisitTempleForQuest(s, s->getPos(), 0, 0) == true)
1131             {
1132               r->setComputerSearchedTemple(true);
1133               svisitingTemple.emit(GameMap::getTemple(s->getPos()), s);
1134             }
1135         }
1136       else
1137         {
1138           if (computerChooseVisitTempleForBlessing(s, s->getPos(), 0, 0) == true)
1139             {
1140               r->setComputerSearchedTemple(true);
1141               bool got_quest =
1142                 svisitingTemple.emit(GameMap::getTemple(s->getPos()), s);
1143               r->setComputerGotQuest(got_quest);
1144             }
1145         }
1146     }
1147   else if (tile->getBuilding() == Maptile::RUIN)
1148     {
1149       if (s->hasHero() == true)
1150         {
1151           if (computerChooseVisitRuin(s, s->getPos(), 0, 0) == true)
1152             {
1153               r->setComputerSearchedRuin(true);
1154               guint32 oldsize = s->size();
1155               stack_died =
1156                 ssearchingRuin.emit(GameMap::getRuin(s->getPos()), s);
1157               if (stack_died)
1158                 r->setRuinFightResult(Fight::DEFENDER_WON);
1159               else
1160                 {
1161                   if (oldsize >= s->size())
1162                     r->setRuinFightResult(Fight::ATTACKER_WON);
1163                   else
1164                     r->setRuinFightResult(Fight::DEFENDER_WON);
1165                 }
1166             }
1167         }
1168     }
1169   return stack_died;
1170 }
1171 
stackMoveOneStep(Stack * s)1172 bool Player::stackMoveOneStep(Stack* s)
1173 {
1174   if (!s)
1175     return false;
1176 
1177   if (!s->enoughMoves())
1178     return false;
1179 
1180   Vector<int> dest = s->getFirstPointInPath();
1181 
1182   Stack *another_stack = GameMap::getStack(dest);
1183   if (another_stack)
1184     {
1185       if (another_stack->getOwner() == s->getOwner())
1186 	{
1187 	  if (GameMap::canJoin(s,another_stack) == false)
1188 	    return false;
1189 	}
1190       else
1191 	{
1192 	  //if we're attacking, then jump onto the square with the enemy.
1193 	  if (s->getPath()->size() != 1)
1194 	    return false;
1195 	}
1196 
1197     }
1198   Action_Move *a = new Action_Move(s, dest);
1199 
1200   s->moveOneStep();
1201   a->setMovesLeft(s->getMoves());
1202   a->setHasShip(s->hasShip());
1203   addAction(a);
1204 
1205 
1206   return true;
1207 }
1208 
cleanupAfterFight(std::list<Stack * > & attackers,std::list<Stack * > & defenders,std::list<History * > & attacker_history,std::list<History * > & defender_history)1209 void Player::cleanupAfterFight(std::list<Stack*> &attackers,
1210                                std::list<Stack*> &defenders,
1211                                std::list<History*> &attacker_history,
1212                                std::list<History*> &defender_history)
1213 {
1214   // get attacker and defender heroes and more...
1215   std::vector<guint32> attackerHeroes, defenderHeroes;
1216 
1217   getHeroes(attackers, attackerHeroes);
1218   getHeroes(defenders, defenderHeroes);
1219 
1220   // here we calculate also the total XP to add when a player have a battle
1221   // clear dead defenders
1222   //
1223   double defender_xp = countXPFromDeadArmies(defenders);
1224   debug("clean dead defenders");
1225   removeDeadArmies(defenders, attackerHeroes, defender_history);
1226 
1227   // and dead attackers
1228   double attacker_xp = countXPFromDeadArmies(attackers);
1229   debug("clean dead attackers");
1230   removeDeadArmies(attackers, defenderHeroes, attacker_history);
1231 
1232   debug("after fight: attackers empty? " << attackers.empty()
1233         << "(" << attackers.size() << ")");
1234 
1235   if (!attackers.empty() && defender_xp != 0)
1236     updateArmyValues(attackers, defender_xp);
1237 
1238   if (!defenders.empty() && attacker_xp != 0)
1239     updateArmyValues(defenders, attacker_xp);
1240 
1241   supdatingStack.emit(0);
1242 }
1243 
stackFight(Stack ** attacker,Stack ** defender)1244 Fight* Player::stackFight(Stack** attacker, Stack** defender)
1245 {
1246     debug("stackFight: player = " << getName()<<" at position "
1247           <<(*defender)->getPos().x<<","<<(*defender)->getPos().y << " with stack " << (*attacker)->getId() << " against " << (*defender)->getId() << " which is player = " <<(*defender)->getOwner()->getName());
1248 
1249     // I suppose, this should be always true, but one can never be sure
1250     bool attacker_active = *attacker == d_stacklist->getActivestack();
1251     if (attacker_active == false && (*attacker)->getOwner()->isComputer() == true)
1252       {
1253         assert(0);
1254       }
1255 
1256     Fight *fight = new Fight(*attacker, *defender);
1257     fight->battle(GameScenarioOptions::s_intense_combat);
1258     // add a fight item about the combat
1259     addAction(new Action_Fight(fight));
1260 
1261     fight_started.emit(*fight);
1262     return fight;
1263 }
1264 
finishStackFight(Fight * fight,Stack ** attacker,Stack ** defender)1265 void Player::finishStackFight (Fight *fight, Stack **attacker, Stack **defender)
1266 {
1267     std::list<Stack *> attackers = fight->getAttackers(),
1268       defenders = fight->getDefenders();
1269 
1270     Player* pd = (*defender)->getOwner();
1271     bool attacker_active = *attacker == d_stacklist->getActivestack();
1272     std::list<History*> attacker_history;
1273     std::list<History*> defender_history;
1274     cleanupAfterFight(attackers, defenders, attacker_history, defender_history);
1275 
1276     for (std::list<History*>::iterator i = attacker_history.begin();
1277          i != attacker_history.end(); i++)
1278       addHistory(*i);
1279     for (std::list<History*>::iterator i = defender_history.begin();
1280          i != defender_history.end(); i++)
1281       addHistory(*i);
1282 
1283     for (std::list<Stack*>::iterator i = attackers.begin();
1284          i != attackers.end(); i++)
1285       addAction(new Action_ReorderArmies(*i));
1286 
1287     for (std::list<Stack*>::iterator i = defenders.begin();
1288          i != defenders.end(); i++)
1289       addAction(new Action_ReorderArmies(*i));
1290 
1291     // Set the attacker and defender stack to 0 if neccessary. This is a great
1292     // help for the functions calling stackFight (e.g. if a stack attacks
1293     // another stack and destroys it without winning the battle, it may take the
1294     // position of this stack)
1295 
1296     // First, the attacker...
1297     bool exists =
1298 	std::find(d_stacklist->begin(), d_stacklist->end(), *attacker)
1299 	!= d_stacklist->end();
1300 
1301     if (!exists)
1302     {
1303         (*attacker) = 0;
1304         if (attacker_active)
1305             d_stacklist->setActivestack(0);
1306     }
1307 
1308     // ...then the defender.
1309     exists = false;
1310     if (pd)
1311       exists =
1312 	std::find(pd->getStacklist()->begin(), pd->getStacklist()->end(),
1313 		  *defender) != pd->getStacklist()->end();
1314     else
1315         exists = true;
1316     if (!exists)
1317         (*defender) = 0;
1318 
1319     schangingStats.emit();
1320     return;
1321 }
1322 
1323 /*
1324  *
1325  * To help factor in the advantage of hero experience/strength and
1326  * ruin-monster strength as well as the stack strength, I think you'll
1327  * find it'll be easier to calculate in terms of the odds of failure [than
1328  * the odds of success].  A new hero (minimum strength) with nothing in
1329  * the stack to help him might have 10-20% odds of failure at a wimpy ruin.
1330  * The same novice hero facing a dragon in the ruin might have 50% odds of
1331  * failure.  So a rule of thumb would be to start with a 25% chance of
1332  * failure.  The odds would be doubled by the worst monster and halved by
1333  * the easiest.  I agree that a strength-9 hero with 8 in the stack should i
1334  * definitely be at 99%.  A reasonable formula might be:
1335  *
1336  * OddsOfFailure = BaseOdds * MonsterFactor * StackFactor * HeroFactor,
1337  *
1338  * with
1339  *        BaseOdds = 0.10
1340  * and
1341  *        MonsterFactor = 2, 1 or 0.5 depending on hard vs. easy
1342  * and
1343  *        StackFactor = (9 - SizeOfStack)/8,
1344  * and
1345  *        HeroFactor = (10-StrengthOfHero)/5.
1346  */
ruinfight(Stack ** attacker,Stack ** defender)1347 Fight::Result ruinfight (Stack **attacker, Stack **defender)
1348 {
1349   Stack *loser;
1350   Fight::Result result;
1351   guint32 hero_strength, monster_strength;
1352   hero_strength = (*attacker)->getFirstHero()->getStat(Army::STRENGTH, true);
1353   monster_strength = (*defender)->getStrongestArmy()->getStat(Army::STRENGTH, true);
1354   float base_factor = 0.28;
1355   float stack_factor = ((float)(MAX_STACK_SIZE + 1) - (*attacker)->size()) / (float)MAX_STACK_SIZE;
1356   float hero_factor = (10.0 - hero_strength) / 5.0;
1357   float monster_factor;
1358   if (monster_strength >= 8)
1359     monster_factor = 2.0;
1360   else if (monster_strength >= 6)
1361     monster_factor = 1.0;
1362   else
1363     monster_factor = 0.5;
1364   float fail = base_factor * monster_factor * stack_factor * hero_factor;
1365 
1366   if (Rnd::rand() % 100 > fail * 100.0)
1367     {
1368       result = Fight::ATTACKER_WON;
1369       loser = *defender;
1370       for (Stack::iterator sit = loser->begin(); sit != loser->end();)
1371         {
1372           (*sit)->setHP (0);
1373           sit++;
1374         }
1375     }
1376   else
1377     {
1378       result = Fight::DEFENDER_WON;
1379       loser = *attacker;
1380       loser->getFirstHero()->setHP(0); /* only the hero dies */
1381     }
1382 
1383   return result;
1384 }
1385 
stackRuinFight(Stack ** attacker,Keeper * defender,bool & stackdied,std::list<History * > & attacker_history,std::list<History * > & defender_history)1386 Fight::Result Player::stackRuinFight (Stack **attacker, Keeper *defender,
1387                                       bool &stackdied,
1388                                       std::list<History*> &attacker_history,
1389                                       std::list<History*> &defender_history)
1390 {
1391     Fight::Result result = Fight::DRAW;
1392     if (defender->getStack () == NULL)
1393       return Fight::ATTACKER_WON;
1394     debug("stackRuinFight: player = " << getName()<<" at position "
1395           <<(*defender)->getStack ()->getPos().x<<","<<(*defender)->getStack ()->getPos().y);
1396 
1397     ruinfight_started.emit(*attacker, defender);
1398     Stack *defender_stack = defender->getStack ();
1399     result = ruinfight (attacker, &defender_stack);
1400 
1401     ruinfight_finished.emit(result);
1402     // cleanup
1403 
1404     // get attacker and defender heroes and more...
1405     std::list<Stack*> attackers;
1406     attackers.push_back(*attacker);
1407     std::list<Stack*> defenders;
1408     defenders.push_back(defender_stack);
1409 
1410     cleanupAfterFight(attackers, defenders, attacker_history, defender_history);
1411     bool exists =
1412 	std::find(d_stacklist->begin(), d_stacklist->end(), *attacker)
1413 	!= d_stacklist->end();
1414 
1415     if (!exists)
1416       {
1417         (*attacker) = 0;
1418         stackdied = true;
1419       }
1420     else
1421       stackdied = false;
1422 
1423     schangingStats.emit();
1424     return result;
1425 }
1426 
doStackSearchRuin(Stack * s,Ruin * r,Fight::Result result)1427 void Player::doStackSearchRuin(Stack *s, Ruin *r, Fight::Result result)
1428 {
1429   if (result == Fight::DEFENDER_WON)
1430     {
1431       r->setSearched(false);
1432       return;
1433     }
1434   else if (result == Fight::ATTACKER_WON)
1435     {
1436       r->setSearched(true);
1437       r->clearOccupant();
1438       r->setOwner(s->getOwner());
1439     }
1440   return;
1441 }
1442 
stackSearchRuin(Stack * s,Ruin * r,bool & stackdied)1443 Reward* Player::stackSearchRuin(Stack* s, Ruin* r, bool &stackdied)
1444 {
1445   std::list<History*> attacker_history;
1446   std::list<History*> defender_history;
1447   Keeper *keeper = r->getOccupant();
1448   if (keeper)
1449     {
1450       Fight::Result result = stackRuinFight(&s, keeper, stackdied,
1451                                             attacker_history, defender_history);
1452       //we delete it here because keepers are not in any players' stacklist.
1453       if (result == Fight::ATTACKER_WON)
1454         delete keeper;
1455       for (std::list<History*>::iterator i = attacker_history.begin();
1456            i != attacker_history.end(); i++)
1457         addHistory(*i);
1458       clearHistorylist(defender_history);
1459 
1460       if (result == Fight::ATTACKER_WON &&
1461           r->getReward() == NULL && r->hasSage() == false)
1462         r->populateWithRandomReward();
1463       doStackSearchRuin(s, r, result);
1464       if (result == Fight::DEFENDER_WON)
1465         {
1466           addAction(new Action_Ruin(r,s));
1467           return NULL;
1468         }
1469     }
1470   else
1471     {
1472       if (r->getReward() == NULL && r->hasSage() == false)
1473         r->populateWithRandomReward();
1474       doStackSearchRuin(s, r, Fight::ATTACKER_WON);
1475     }
1476 
1477   Reward *reward = r->takeReward();
1478   addAction(new Action_Ruin(r, s));
1479   if (r->isSearched())
1480     {
1481       if (r->hasSage())
1482         addHistory(new History_FoundSage(dynamic_cast<Hero *>(s->getFirstHero())));
1483       addHistory(new History_HeroRuinExplored(dynamic_cast<Hero*>(s->getFirstHero()), r));
1484     }
1485   supdatingStack.emit(0);
1486   return reward;
1487 }
1488 
doStackVisitTemple(Stack * s)1489 int Player::doStackVisitTemple(Stack *s)
1490 {
1491   // you have your stack blessed (+1 strength)
1492   int count = s->bless();
1493 
1494   supdatingStack.emit(0);
1495 
1496   return count;
1497 }
1498 
stackVisitTemple(Stack * s,Temple * t)1499 int Player::stackVisitTemple(Stack* s, Temple* t)
1500 {
1501   debug("Player::stackVisitTemple");
1502 
1503   addAction(new Action_Temple(t,s));
1504 
1505   return doStackVisitTemple(s);
1506 }
1507 
doHeroGetQuest(Hero * hero,bool except_raze)1508 Quest* Player::doHeroGetQuest(Hero *hero, bool except_raze)
1509 {
1510   std::vector<Quest*> quests =
1511     QuestsManager::getInstance()->getPlayerQuests(Playerlist::getActiveplayer());
1512   if (quests.size() > 0 && GameScenarioOptions::s_play_with_quests == GameParameters::ONE_QUEST_PER_PLAYER)
1513     return NULL;
1514 
1515   Quest *q = NULL;
1516   if (hero)
1517     q = QuestsManager::getInstance()->createNewQuest (hero->getId(), except_raze);
1518 
1519   supdatingStack.emit(0);
1520   // couldn't assign a quest for various reasons
1521   if (!q)
1522     return NULL;
1523   return q;
1524 }
1525 
heroGetQuest(Hero * hero,Temple * t,bool except_raze)1526 Quest* Player::heroGetQuest(Hero *hero, Temple* t, bool except_raze)
1527 {
1528   debug("Player::stackGetQuest")
1529   (void) t;
1530   Quest *q = doHeroGetQuest(hero, except_raze);
1531   if (q == NULL)
1532     return q;
1533 
1534   // Now fill the action item
1535   addAction(new Action_Quest(q));
1536 
1537   // and record it for posterity
1538   addHistory(new History_HeroQuestStarted(hero));
1539   return q;
1540 }
1541 
stackFightAdvise(Stack * s,Vector<int> tile,bool intense_combat)1542 float Player::stackFightAdvise(Stack* s, Vector<int> tile,
1543                                bool intense_combat)
1544 {
1545   float percent = 0.0;
1546 
1547   City* city = GameMap::getCity(tile);
1548   Stack* target = GameMap::getEnemyStack(tile);
1549 
1550   if (!target && city)
1551     {
1552       std::vector<Stack*> def_in_city = city->getDefenders();
1553       if (def_in_city.empty())
1554 	return 100.0;
1555       target = def_in_city[0];
1556     }
1557 
1558   //what chance is there that stack will defeat defenders?
1559 
1560   for (unsigned int i = 0; i < 100; i++)
1561     {
1562       Fight fight(s, target, Fight::FOR_KICKS);
1563       fight.battle(intense_combat);
1564       if (fight.getResult() == Fight::ATTACKER_WON)
1565 	percent += 1.0;
1566     }
1567 
1568   advice_asked.emit(percent);
1569   return percent;
1570 }
1571 
adjustDiplomacyFromConqueringCity(City * city)1572 void Player::adjustDiplomacyFromConqueringCity(City *city)
1573 {
1574   Player *defender = city->getOwner();
1575 
1576   // See if this is the last city for that player, and alter the
1577   // diplomatic scores.
1578   if (Citylist::getInstance()->countCities(defender) == 1)
1579   {
1580     if (defender->getDiplomaticRank() < getDiplomaticRank())
1581       deteriorateDiplomaticRelationship (2);
1582     else if (defender->getDiplomaticRank() > getDiplomaticRank())
1583       improveDiplomaticRelationship (2, defender);
1584   }
1585 }
1586 
calculateLoot(Player * looted,guint32 & added,guint32 & subtracted)1587 void Player::calculateLoot(Player *looted, guint32 &added, guint32 &subtracted)
1588 {
1589   Player *defender = looted;
1590 
1591   // if the attacked city isn't neutral, loot some gold
1592   if (defender != Playerlist::getInstance()->getNeutral())
1593   {
1594     int amt = (defender->getGold() /
1595                (2 * (Citylist::getInstance()->countCities (defender)+1)) * 2);
1596     // give (Enemy-Gold/(2Enemy-Cities)) to the attacker
1597     // and then take away twice that from the defender.
1598     // the idea here is that some money is taken in the invasion
1599     // and other monies are lost forever
1600     // NOTE: +1 because the looted player just lost a city
1601     subtracted = amt;
1602     amt /= 2;
1603     added = amt;
1604   }
1605 
1606   return;
1607 }
1608 
doConquerCity(City * city)1609 void Player::doConquerCity(City *city)
1610 {
1611   takeCityInPossession(city);
1612 }
1613 
1614 //this helps us test.
conquerAllCities()1615 void Player::conquerAllCities()
1616 {
1617   for (auto city: *Citylist::getInstance())
1618     {
1619       if (city->getOwner() != this)
1620         {
1621           for (auto stack: city->getDefenders())
1622               GameMap::getInstance()->removeStack(stack);
1623           conquerCity (city, NULL);
1624         }
1625     }
1626 }
1627 
conquerCity(City * city,Stack * stack)1628 void Player::conquerCity(City *city, Stack *stack)
1629 {
1630   /*
1631      fixme:
1632      there is some weirdness here where we conquer the initial cities twice.
1633      we have to make sure it works with the city history report dialog,
1634      and getFirstCity.
1635      i guess the histories are getting erased somewhere after we conquer
1636      the city the first time.
1637    */
1638   Player *original_owner = city->getOwner();
1639   Action_ConquerCity *action = new Action_ConquerCity(city);
1640 
1641   doConquerCity(city);
1642   addAction(action);
1643   addHistory(new History_CityWon(city));
1644   if (stack && stack->hasHero())
1645   {
1646     Hero *hero = dynamic_cast<Hero *>(stack->getFirstHero());
1647     addHistory(new History_HeroCityWon(city, hero));
1648   }
1649   if (original_owner != this)
1650     lootCity(city, original_owner);
1651 }
1652 
lootCity(City * city,Player * looted)1653 void Player::lootCity(City *city, Player *looted)
1654 {
1655   guint32 added = 0;
1656   guint32 subtracted = 0;
1657   calculateLoot(looted, added, subtracted);
1658   sinvadingCity.emit(city, added);
1659   doLootCity(looted, added, subtracted);
1660   addAction(new Action_Loot(this, looted, added, subtracted));
1661   return;
1662 }
1663 
doLootCity(Player * looted,guint32 added,guint32 subtracted)1664 void Player::doLootCity(Player *looted, guint32 added, guint32 subtracted)
1665 {
1666   addGold(added);
1667   looted->withdrawGold(subtracted);
1668   return;
1669 }
1670 
takeCityInPossession(City * c)1671 void Player::takeCityInPossession(City* c)
1672 {
1673   c->conquer(this);
1674 
1675   //set the production to the cheapest armytype
1676   c->setActiveProductionSlot(-1);
1677   if (c->getArmytype(0) != -1)
1678     c->setActiveProductionSlot(0);
1679 
1680   supdatingCity.emit(c);
1681 }
1682 
doCityOccupy(City * c)1683 void Player::doCityOccupy(City *c)
1684 {
1685   assert (c->getOwner() == this);
1686 
1687   soccupyingCity.emit(c, getActivestack());
1688   QuestsManager::getInstance()->cityOccupied(c, getActivestack());
1689 }
1690 
cityOccupy(City * c)1691 void Player::cityOccupy(City* c)
1692 {
1693   debug("cityOccupy");
1694   doCityOccupy(c);
1695 
1696   addAction(new Action_Occupy(c));
1697 }
1698 
doCityPillage(City * c,int & gold,int * pillaged_army_type)1699 void Player::doCityPillage(City *c, int& gold, int* pillaged_army_type)
1700 {
1701   gold = 0;
1702   if (pillaged_army_type)
1703     *pillaged_army_type = -1;
1704 
1705   // get rid of the most expensive army type and trade it in for
1706   // half it's cost
1707   // it is presumed that the last army type is the most expensive
1708 
1709   if (c->getNoOfProductionBases() > 0)
1710     {
1711       unsigned int i;
1712       unsigned int max_cost = 0;
1713       int slot = -1;
1714       for (i = 0; i < c->getNoOfProductionBases(); i++)
1715 	{
1716 	  const ArmyProdBase *a = c->getProductionBase(i);
1717 	  if (a != NULL)
1718 	    {
1719 	      if (a->getNewProductionCost() == 0)
1720 		{
1721 		  slot = i;
1722 		  break;
1723 		}
1724 	      if (a->getNewProductionCost() > max_cost)
1725 		{
1726 		  max_cost = a->getNewProductionCost();
1727 		  slot = i;
1728 		}
1729 	    }
1730 	}
1731       if (slot > -1)
1732 	{
1733 	  const ArmyProdBase *a = c->getProductionBase(slot);
1734 	  if (pillaged_army_type)
1735 	    *pillaged_army_type = a->getTypeId();
1736 	  if (a->getNewProductionCost() == 0)
1737 	    gold += 1500;
1738 	  else
1739 	    gold += a->getNewProductionCost() / 2;
1740 	  c->removeProductionBase(slot);
1741 	}
1742       addGold(gold);
1743       Stack *s = getActivestack();
1744       spillagingCity.emit(c, s, gold, *pillaged_army_type);
1745       QuestsManager::getInstance()->cityPillaged(c, s, gold);
1746     }
1747 
1748 }
1749 
cityPillage(City * c,int & gold,int * pillaged_army_type)1750 void Player::cityPillage(City* c, int& gold, int* pillaged_army_type)
1751 {
1752   debug("Player::cityPillage");
1753 
1754   addAction(new Action_Pillage(c));
1755 
1756   doCityPillage(c, gold, pillaged_army_type);
1757 }
1758 
doCitySack(City * c,int & gold,std::list<guint32> * sacked_types)1759 void Player::doCitySack(City* c, int& gold, std::list<guint32> *sacked_types)
1760 {
1761   gold = 0;
1762   //trade in all of the army types except for one
1763   //presumes that the army types are listed in order of expensiveness
1764 
1765   if (c->getNoOfProductionBases() > 1)
1766     {
1767       const ArmyProdBase *a;
1768       unsigned int i, max = 0;
1769       for (i = 0; i < c->getNoOfProductionBases(); i++)
1770 	{
1771 	  a = c->getProductionBase(i);
1772 	  if (a)
1773 	    max++;
1774 	}
1775 
1776       i = c->getNoOfProductionBases() - 1;
1777       while (max > 1)
1778 	{
1779 	  a = c->getProductionBase(i);
1780 	  if (a != NULL)
1781 	    {
1782 	      sacked_types->push_back(a->getTypeId());
1783 	      if (a->getNewProductionCost() == 0)
1784 		gold += 1500;
1785 	      else
1786 		gold += a->getNewProductionCost() / 2;
1787 	      c->removeProductionBase(i);
1788 	      max--;
1789 	    }
1790 	  i--;
1791 	}
1792     }
1793 
1794   addGold(gold);
1795   Stack *s = getActivestack();
1796   ssackingCity.emit(c, s, gold, *sacked_types);
1797   QuestsManager::getInstance()->citySacked(c, s, gold);
1798 }
1799 
citySack(City * c,int & gold,std::list<guint32> * sacked_types)1800 void Player::citySack(City* c, int& gold, std::list<guint32> *sacked_types)
1801 {
1802   debug("Player::citySack");
1803 
1804   addAction(new Action_Sack(c));
1805 
1806   doCitySack(c, gold, sacked_types);
1807 }
1808 
doCityRaze(City * c)1809 void Player::doCityRaze(City *c)
1810 {
1811   c->conquer(this);
1812   c->setBurnt(true);
1813 
1814   supdatingCity.emit(c);
1815 
1816   srazingCity.emit(c, getActivestack());
1817   QuestsManager::getInstance()->cityRazed(c, getActivestack());
1818 }
1819 
cityRaze(City * c)1820 void Player::cityRaze(City* c)
1821 {
1822   debug("Player::cityRaze");
1823 
1824   addAction(new Action_Raze(c));
1825 
1826   addHistory(new History_CityRazed(c));
1827 
1828   doCityRaze(c);
1829 }
1830 
doCityBuyProduction(City * c,int slot,int type)1831 void Player::doCityBuyProduction(City* c, int slot, int type)
1832 {
1833   guint32 as = c->getOwner()->getArmyset();
1834 
1835   c->removeProductionBase(slot);
1836   c->addProductionBase(slot, new ArmyProdBase
1837                        (*Armysetlist::getInstance()->getArmy(as, type)));
1838 
1839   // and do the rest of the neccessary actions
1840   withdrawGold(Armysetlist::getInstance()->getArmy(as, type)->getNewProductionCost());
1841 }
1842 
cityBuyProduction(City * c,int slot,int type)1843 bool Player::cityBuyProduction(City* c, int slot, int type)
1844 {
1845   guint32 as = c->getOwner()->getArmyset();
1846 
1847   // sort out unusual values (-1 is allowed and means "scrap production")
1848   if (type <= -1 || Armysetlist::getInstance()->getArmy(d_armyset, type) == NULL)
1849     return false;
1850 
1851   // return if we don't have enough money
1852   if (type != -1 &&
1853       (int)Armysetlist::getInstance()->getArmy(as, type)->getNewProductionCost() > d_gold)
1854     return false;
1855 
1856   // return if the city already has the production
1857   if (c->hasProductionBase(type))
1858     return false;
1859 
1860   // can't put it in that slot
1861   if (slot >= (int)c->getMaxNoOfProductionBases())
1862     return false;
1863 
1864   addAction(new Action_Buy (c, slot, Armysetlist::getInstance()->getArmy(as, type)));
1865 
1866   doCityBuyProduction(c, slot, type);
1867 
1868   return true;
1869 }
1870 
doCityChangeProduction(City * c,int slot)1871 void Player::doCityChangeProduction(City* c, int slot)
1872 {
1873   c->setActiveProductionSlot(slot);
1874   if (slot < 0)
1875     c->setVectoring(Vector<int>(-1,-1));
1876 }
1877 
cityChangeProduction(City * c,int slot)1878 bool Player::cityChangeProduction(City* c, int slot)
1879 {
1880   doCityChangeProduction(c, slot);
1881   addAction(new Action_Production(c, slot));
1882   return true;
1883 }
1884 
doGiveReward(Stack * s,Reward * reward,StackReflist * stacks)1885 void Player::doGiveReward(Stack *s, Reward *reward, StackReflist *stacks)
1886 {
1887   switch (reward->getType())
1888     {
1889     case Reward::GOLD:
1890       addGold(dynamic_cast<Reward_Gold*>(reward)->getGold());
1891       break;
1892     case Reward::ALLIES:
1893         {
1894           const ArmyProto *a = dynamic_cast<Reward_Allies*>(reward)->getArmy();
1895 
1896           Reward_Allies::addAllies(s->getOwner(), s->getPos(), a,
1897       			     dynamic_cast<Reward_Allies*>(reward)->getNoOfAllies(), stacks);
1898         }
1899       break;
1900     case Reward::ITEM:
1901         {
1902           Item *i = new Item (*dynamic_cast<Reward_Item*>(reward)->getItem());
1903           Hero *hero = static_cast<Hero*>(s->getFirstHero());
1904           hero->getBackpack()->addToBackpack(i);
1905         }
1906       break;
1907     case Reward::RUIN:
1908         {
1909           //assign the hidden ruin to this player
1910           Ruin *r = dynamic_cast<Reward_Ruin*>(reward)->getRuin();
1911           r->setHidden(true);
1912           r->setOwner(this);
1913 	  r->deFog(this);
1914         }
1915       break;
1916     case Reward::MAP:
1917         {
1918           Reward_Map *map = dynamic_cast<Reward_Map*>(reward);
1919           d_fogmap->alterFog(map->getSightMap());
1920         }
1921       break;
1922     }
1923 }
1924 
giveReward(Stack * s,Reward * reward,StackReflist * stacks,bool quest)1925 bool Player::giveReward(Stack *s, Reward *reward, StackReflist *stacks, bool quest)
1926 {
1927   debug("Player::give_reward");
1928 
1929   Action_Reward *action = new Action_Reward(s, reward);
1930   doGiveReward(s, reward, stacks);
1931 
1932   addAction(action);
1933 
1934   if (reward->getType() == Reward::RUIN && !quest)
1935     {
1936       Ruin *r = dynamic_cast<Reward_Ruin*>(reward)->getRuin();
1937       addHistory(new History_HeroRewardRuin(dynamic_cast<Hero*>(s->getFirstHero()), r));
1938     }
1939   schangingStats.emit();
1940   return true;
1941 }
1942 
doStackDisband(Stack * s)1943 bool Player::doStackDisband(Stack* s)
1944 {
1945     getStacklist()->setActivestack(0);
1946     s->kill();
1947     std::list<History*> history;
1948     removeDeadArmies(s, history);
1949     clearHistorylist(history);
1950     supdatingStack.emit(0);
1951     return true;
1952 }
1953 
stackDisband(Stack * s)1954 bool Player::stackDisband(Stack* s)
1955 {
1956   debug("Player::stackDisband(Stack*)")
1957     if (!s)
1958       s = getActivestack();
1959 
1960   addAction(new Action_Disband(s));
1961 
1962   bool retval = doStackDisband(s);
1963   schangingStats.emit();
1964   return retval;
1965 }
1966 
doHeroDropItem(Hero * h,Item * i,Vector<int> pos,bool & splash)1967 void Player::doHeroDropItem(Hero *h, Item *i, Vector<int> pos, bool &splash)
1968 {
1969   if (GameMap::getInstance()->canDropBag(pos) == false)
1970     {
1971       h->getBackpack()->removeFromBackpack(i);
1972       delete i;
1973       splash = true;
1974     }
1975   else
1976     {
1977       GameMap::getInstance()->getTile(pos)->getBackpack()->addToBackpack(i);
1978       h->getBackpack()->removeFromBackpack(i);
1979       splash = false;
1980     }
1981   supdatingStack.emit(0);
1982 }
1983 
heroDropItem(Hero * h,Item * i,Vector<int> pos,bool & splash)1984 bool Player::heroDropItem(Hero *h, Item *i, Vector<int> pos, bool &splash)
1985 {
1986   doHeroDropItem(h, i, pos, splash);
1987   addAction(new Action_Equip(h, i, Action_Equip::GROUND, pos));
1988   return true;
1989 }
1990 
heroDropAllItems(Hero * h,Vector<int> pos,bool & splash)1991 bool Player::heroDropAllItems(Hero *h, Vector<int> pos, bool &splash)
1992 {
1993   while (h->getBackpack()->empty() == false)
1994     heroDropItem(h, h->getBackpack()->front(), pos, splash);
1995   return true;
1996 }
1997 
doHeroDropAllItems(Hero * h,Vector<int> pos,bool & splash)1998 bool Player::doHeroDropAllItems(Hero *h, Vector<int> pos, bool &splash)
1999 {
2000   while (h->getBackpack()->empty() == false)
2001     doHeroDropItem(h, h->getBackpack()->front(), pos, splash);
2002   sbagdropped.emit ();
2003   supdatingStack.emit(0);
2004   return true;
2005 }
2006 
doHeroPickupItem(Hero * h,Item * i,Vector<int> pos)2007 void Player::doHeroPickupItem(Hero *h, Item *i, Vector<int> pos)
2008 {
2009   bool found = GameMap::getInstance()->getTile(pos)->getBackpack()->removeFromBackpack(i);
2010   if (found)
2011     h->getBackpack()->addToBackpack(i);
2012   supdatingStack.emit(0);
2013 }
2014 
heroPickupItem(Hero * h,Item * i,Vector<int> pos)2015 bool Player::heroPickupItem(Hero *h, Item *i, Vector<int> pos)
2016 {
2017   doHeroPickupItem(h, i, pos);
2018   addAction(new Action_Equip(h, i, Action_Equip::BACKPACK, pos));
2019   return true;
2020 }
2021 
doHeroPickupAllItems(Hero * h,Vector<int> pos)2022 bool Player::doHeroPickupAllItems(Hero *h, Vector<int> pos)
2023 {
2024   MapBackpack *backpack = GameMap::getInstance()->getTile(pos)->getBackpack();
2025   while (backpack->empty() == false)
2026     doHeroPickupItem(h, backpack->front(), pos);
2027   return true;
2028 }
2029 
heroPickupAllItems(Hero * h,Vector<int> pos)2030 bool Player::heroPickupAllItems(Hero *h, Vector<int> pos)
2031 {
2032   MapBackpack *backpack = GameMap::getInstance()->getTile(pos)->getBackpack();
2033   while (backpack->empty() == false)
2034     heroPickupItem(h, backpack->front(), pos);
2035   return true;
2036 }
2037 
heroCompletesQuest(Hero * h)2038 bool Player::heroCompletesQuest(Hero *h)
2039 {
2040   // record it for posterity
2041   addHistory(new History_HeroQuestCompleted(h));
2042   return true;
2043 }
2044 
doResign(std::list<History * > & histories)2045 void Player::doResign(std::list<History*> &histories)
2046 {
2047   //disband all stacks
2048   std::list<Stack*> stacks = getStacklist()->kill();
2049   removeDeadArmies(stacks, histories);
2050 
2051   //raze all cities
2052   for (auto city: *Citylist::getInstance())
2053     {
2054       if (city->getOwner() == this)
2055 	{
2056 	  city->setBurnt(true);
2057           histories.push_back(new History_CityRazed(city));
2058 	}
2059     }
2060   withdrawGold(getGold()); //empty the coffers!
2061 
2062   getStacklist()->setActivestack(0);
2063   supdatingStack.emit(0);
2064 }
2065 
resign()2066 void Player::resign()
2067 {
2068   std::list<History*> history;
2069   doResign(history);
2070   for (std::list<History*>::iterator i = history.begin(); i != history.end();
2071        i++)
2072     addHistory(*i);
2073 
2074   addAction(new Action_Resign());
2075   schangingStats.emit();
2076 }
2077 
doSignpostChange(Signpost * s,Glib::ustring message)2078 void Player::doSignpostChange(Signpost *s, Glib::ustring message)
2079 {
2080   s->setName(message);
2081 }
2082 
signpostChange(Signpost * s,Glib::ustring message)2083 bool Player::signpostChange(Signpost *s, Glib::ustring message)
2084 {
2085   if (!s)
2086     return false;
2087 
2088   doSignpostChange(s, message);
2089 
2090   addAction(new Action_ModifySignpost(s, message));
2091   return true;
2092 }
2093 
doCityRename(City * c,Glib::ustring name)2094 void Player::doCityRename(City *c, Glib::ustring name)
2095 {
2096   c->setName(name);
2097 }
2098 
cityRename(City * c,Glib::ustring name)2099 bool Player::cityRename(City *c, Glib::ustring name)
2100 {
2101   if (!c)
2102     return false;
2103 
2104   doCityRename(c, name);
2105 
2106   addAction(new Action_RenameCity(c, name));
2107   return true;
2108 }
2109 
doRename(Glib::ustring name)2110 void Player::doRename(Glib::ustring name)
2111 {
2112   setName(name);
2113 }
2114 
rename(Glib::ustring name)2115 void Player::rename(Glib::ustring name)
2116 {
2117   doRename(name);
2118   addAction(new Action_RenamePlayer(name));
2119   return;
2120 }
2121 
doVectorFromCity(City * c,Vector<int> dest)2122 void Player::doVectorFromCity(City * c, Vector<int> dest)
2123 {
2124   c->setVectoring(dest);
2125 }
2126 
vectorFromCity(City * c,Vector<int> dest)2127 bool Player::vectorFromCity(City * c, Vector<int> dest)
2128 {
2129   if (dest != Vector<int>(-1,-1))
2130     {
2131       std::list<City*> cities;
2132       cities = Citylist::getInstance()->getCitiesVectoringTo(dest);
2133       if (cities.size() >= MAX_CITIES_VECTORED_TO_ONE_CITY)
2134 	return false;
2135     }
2136   doVectorFromCity(c, dest);
2137 
2138   addAction(new Action_Vector(c, dest));
2139   return true;
2140 }
2141 
doChangeVectorDestination(Vector<int> src,Vector<int> dest,std::list<City * > & vectored)2142 bool Player::doChangeVectorDestination(Vector<int> src, Vector<int> dest,
2143 				       std::list<City*> &vectored)
2144 {
2145   //DEST can be a flag.
2146   //SRC can be a flag too.
2147   //Note: we don't actually have a way in the gui to change the vectoring
2148   //from the planted standard (flag).
2149   bool retval = true;
2150   //sanity checks:
2151   //disallow changing vectoring from or to a city that isn't ours
2152   //disallow vectoring to something that isn't our city or our planted
2153   //standard.
2154   City *src_city = GameMap::getCity(src);
2155   if (src_city == NULL)
2156     {
2157       //maybe it's a flag we're changing the vector destination from.
2158       if (GameMap::getInstance()->findPlantedStandard(this) != src)
2159 	return false;
2160     }
2161   else
2162     {
2163       if (src_city->getOwner() != this)
2164 	return false;
2165     }
2166   City *dest_city = GameMap::getCity(dest);
2167   if (dest_city == NULL)
2168     {
2169       if (GameMap::getInstance()->findPlantedStandard(this) != dest)
2170 	return false;
2171     }
2172   else
2173     {
2174       if (dest_city->getOwner() != this)
2175 	return false;
2176     }
2177 
2178   //check to see if the destination has enough room to accept all of the
2179   //cities we want to send to it.
2180   std::list<City*> sources = Citylist::getInstance()->getCitiesVectoringTo(src);
2181   std::list<City*> alreadyvectored =
2182     Citylist::getInstance()->getCitiesVectoringTo(dest);
2183 
2184   if (alreadyvectored.size() + sources.size() > MAX_CITIES_VECTORED_TO_ONE_CITY)
2185     return false;
2186 
2187   //okay, do the vectoring changes.
2188   std::list<City*>::iterator it = sources.begin();
2189   for (; it != sources.end(); it++)
2190     retval &= (*it)->changeVectorDestination(dest);
2191   vectored = sources;
2192   return retval;
2193 }
2194 
changeVectorDestination(Vector<int> src,Vector<int> dest)2195 bool Player::changeVectorDestination(Vector<int> src, Vector<int> dest)
2196 {
2197   std::list<City*> vectored;
2198   bool retval = doChangeVectorDestination(src, dest, vectored);
2199   if (retval == false)
2200     return retval;
2201 
2202   std::list<City*>::iterator it = vectored.begin();
2203   for (; it != vectored.end(); it++)
2204     addAction(new Action_Vector((*it), dest));
2205   return true;
2206 }
2207 
heroPlantStandard(Stack * s)2208 bool Player::heroPlantStandard(Stack* s)
2209 {
2210   debug("Player::heroPlantStandard(Stack*)");
2211   if (!s)
2212     s = getActivestack();
2213 
2214   for (Stack::iterator it = s->begin(); it != s->end(); it++)
2215   {
2216     if ((*it)->isHero())
2217     {
2218       Hero *hero = dynamic_cast<Hero*>((*it));
2219       Item *item = hero->getBackpack()->getPlantableItem(this);
2220       if (item)
2221         {
2222           //drop the item, and plant it
2223           doHeroPlantStandard(hero, item, s->getPos());
2224 
2225           addAction(new Action_Plant(hero, item));
2226           return true;
2227         }
2228     }
2229   }
2230   return true;
2231 }
2232 
doHeroPlantStandard(Hero * hero,Item * item,Vector<int> pos)2233 void Player::doHeroPlantStandard(Hero *hero, Item *item, Vector<int> pos)
2234 {
2235   item->setPlanted(true);
2236   GameMap::getInstance()->getTile(pos)->getBackpack()->addToBackpack(item);
2237   hero->getBackpack()->removeFromBackpack(item);
2238   supdatingStack.emit(0);
2239 }
2240 
getHeroes(const std::list<Stack * > stacks,std::vector<guint32> & dst)2241 void Player::getHeroes(const std::list<Stack*> stacks, std::vector<guint32>& dst)
2242 {
2243     std::list<Stack*>::const_iterator it;
2244     for (it = stacks.begin(); it != stacks.end(); it++)
2245         (*it)->getHeroes(dst);
2246 }
2247 
removeDeadArmies(Stack * stack,std::list<History * > & history)2248 guint32 Player::removeDeadArmies(Stack *stack, std::list<History*> &history)
2249 {
2250   std::list<Stack*> stacks;
2251   stacks.push_back(stack);
2252   return removeDeadArmies(stacks, history);
2253 }
2254 
removeDeadArmies(std::list<Stack * > & stacks,std::list<History * > & history)2255 guint32 Player::removeDeadArmies(std::list<Stack*>& stacks,
2256                                  std::list<History*> &history)
2257 {
2258   std::vector<guint32> culprits;
2259   return removeDeadArmies(stacks, culprits, history);
2260 }
2261 
removeDeadArmies(std::list<Stack * > & stacks,std::vector<guint32> & culprits,std::list<History * > & history)2262 guint32 Player::removeDeadArmies(std::list<Stack*>& stacks,
2263                                  std::vector<guint32>& culprits,
2264                                  std::list<History*> &history)
2265 {
2266   guint32 count = 0;
2267   Player *owner = NULL;
2268   if (stacks.empty() == false)
2269     {
2270       owner = (*stacks.begin())->getOwner();
2271       debug("Owner = " << owner);
2272       if (owner)
2273         {
2274           debug("Owner of the stacks: " << owner->getName()
2275                 << ", his stacklist = " << owner->getStacklist());
2276         }
2277     }
2278   for (unsigned int i = 0; i < culprits.size(); i++)
2279     debug("Culprit: " << culprits[i]);
2280 
2281   tallyDeadArmyTriumphs(stacks);
2282   handleDeadHeroes(stacks, history);
2283   handleDeadArmiesForQuests(stacks, culprits);
2284 
2285   std::list<Stack*>::iterator it;
2286   for (it = stacks.begin(); it != stacks.end(); )
2287     {
2288       debug("Stack: " << (*it))
2289         if ((*it))
2290           {
2291             debug("Stack id: " << (*it)->getId());
2292           }
2293       for (Stack::iterator sit = (*it)->begin(); sit != (*it)->end();)
2294         {
2295           debug("Army: " << (*sit) << " " << (*sit)->getId())
2296             if ((*sit)->getHP() <= 0)
2297               {
2298                 debug("Dead Army: " << (*sit)->getName())
2299 
2300                   count++;
2301                 sit = (*it)->flErase(sit);
2302                 continue;
2303               }
2304 
2305           sit++;
2306         }
2307 
2308       debug("Is stack empty?")
2309 
2310         if ((*it)->empty())
2311           {
2312             bool ruinstack = false;
2313             if (owner == Playerlist::getInstance ()->getNeutral () &&
2314                 GameMap::getInstance ()->getBuilding ((*it)->getPos ()) ==
2315                 Maptile::RUIN)
2316               ruinstack = true;
2317 
2318             if (!ruinstack)
2319               {
2320                 debug("Yes, removing this stack from the owner's stacklist");
2321                 bool found = owner->deleteStack(*it);
2322                 if (found == false)
2323                   {
2324                     printf("couldn't find stack id %d for player %d\n", (*it)->getId(), owner->getId());
2325                     printf("is it in our own stacklist?");
2326                     Stack *a = getStacklist()->getStackById((*it)->getId());
2327                     if  (a)
2328                       printf(" yes\n");
2329                     else
2330                       printf(" no\n");
2331                   }
2332                 assert (found == true);
2333               }
2334             else // there is no owner - like for the ruin's occupants
2335               {
2336                 debug("No owner for this stack - do stacklist too");
2337               }
2338 
2339             debug("Removing from the vector too (the vector had "
2340                   << stacks.size() << " left)");
2341             it = stacks.erase(it);
2342           }
2343         else
2344           it++;
2345     }
2346   debug("after removeDead: num stacks = " << stacks.size());
2347   return count;
2348 }
2349 
doHeroGainsLevel(Hero * hero,Army::Stat stat)2350 void Player::doHeroGainsLevel(Hero *hero, Army::Stat stat)
2351 {
2352   hero->gainLevel(stat);
2353 }
2354 
updateArmyValues(std::list<Stack * > & stacks,double xp_sum)2355 void Player::updateArmyValues(std::list<Stack*>& stacks, double xp_sum)
2356 {
2357   std::list<Stack*>::iterator it;
2358   double numberarmy = 0;
2359 
2360   for (it = stacks.begin(); it != stacks.end(); it++)
2361     numberarmy += (*it)->size();
2362 
2363   for (it = stacks.begin(); it != stacks.end(); )
2364     {
2365       debug("Stack: " << (*it))
2366 
2367 	for (Stack::iterator sit = (*it)->begin(); sit != (*it)->end();)
2368 	  {
2369 	    Army *army = *sit;
2370 	    debug("Army: " << army)
2371 
2372 	      // here we adds XP
2373 	      army->gainXp((double)((xp_sum)/numberarmy));
2374 	    debug("Army gets " << (double)((xp_sum)/numberarmy) << " XP")
2375 
2376 	      // here we adds 1 to number of battles
2377 	      army->setBattlesNumber(army->getBattlesNumber()+1);
2378 	    debug("Army battles " <<  army->getBattlesNumber())
2379 
2380 	      // medals only go to non-ally armies.
2381 	      if ((*it)->hasHero() && army->isHero() == false &&
2382 		  army->getAwardable() == false)
2383 		{
2384 		  if((army->getBattlesNumber())>10 &&
2385 		     !(army->getMedalBonus(2)))
2386 		    {
2387 		      army->setMedalBonus(2,true);
2388 		      // We must recalculate the XPValue of this unit since it
2389 		      // got a medal
2390 		      army->setXpReward(army->getXpReward()+1);
2391 		      // We get the medal bonus here
2392 		      army->setStat(Army::STRENGTH, army->getStat(Army::STRENGTH, false)+1);
2393 		      // Emit signal
2394 		      snewMedalArmy.emit(army, 2);
2395 		    }
2396 
2397 		  debug("Army hits " <<  army->getNumberHasHit())
2398 
2399 		    // Only give medals if the unit has attacked often enough, else
2400 		    // medals lose the flair of something special; a value of n
2401 		    // means roughly to hit an equally strong unit around n
2402 		    // times. (note: one hit! An attack can consist of up to
2403 		    // strength hits)
2404 		    if((army->getNumberHasHit()>50) && !army->getMedalBonus(0))
2405 		      {
2406 			army->setMedalBonus(0,true);
2407 			// We must recalculate the XPValue of this unit since it
2408 			// got a medal
2409 			army->setXpReward(army->getXpReward()+1);
2410 			// We get the medal bonus here
2411 			army->setStat(Army::STRENGTH, army->getStat(Army::STRENGTH, false)+1);
2412 			// Emit signal
2413 			snewMedalArmy.emit(army, 0);
2414 		      }
2415 
2416 		  debug("army being hit " <<  army->getNumberHasBeenHit())
2417 
2418 		    // Gives the medal for good defense. The more negative the
2419 		    // number the more blows the unit evaded. n means roughly
2420 		    // avoid n hits from an equally strong unit. Since we want
2421 		    // to punish the case of the unit hiding among many others,
2422 		    // we set this value quite high.
2423 		    if((army->getNumberHasBeenHit() < -100) && !army->getMedalBonus(1))
2424 		      {
2425 			army->setMedalBonus(1,true);
2426 			// We must recalculate the XPValue of this unit since it
2427 			// got a medal
2428 			army->setXpReward(army->getXpReward()+1);
2429 			// We get the medal bonus here
2430 			army->setStat(Army::STRENGTH, army->getStat(Army::STRENGTH, false)+1);
2431 			// Emit signal
2432 			snewMedalArmy.emit(army, 1);
2433 		      }
2434 		  debug("Army hits " <<  army->getNumberHasHit())
2435 
2436 		    for(int i=0;i<3;i++)
2437 		      {
2438 			debug("MEDAL[" << i << "]==" << army->getMedalBonus(i))
2439 		      }
2440 		}
2441 
2442 	    // We reset the hit values after the battle
2443 	    army->setNumberHasHit(0);
2444 	    army->setNumberHasBeenHit(0);
2445 
2446 	    if (army->isHero() && getType() != Player::NETWORKED)
2447 	      {
2448 		Hero *h = dynamic_cast<Hero*>(army);
2449 		while(h->canGainLevel())
2450 		  {
2451 		    // Units not associated to a player never raise levels.
2452 		    if (h->getOwner() == Playerlist::getInstance()->getNeutral())
2453 		      break;
2454 
2455 		    //Here this for is to check if army must raise 2 or more
2456 		    //levels per time depending on the XP and level itself
2457 
2458 		    h->getOwner()->heroGainsLevel(h);
2459 		  }
2460 		debug("Hero new XP=" << h->getXP())
2461 	      }
2462 	    sit++;
2463 	  }
2464       it++;
2465     }
2466 }
2467 
doRecruitHero(HeroProto * herotemplate,City * city,int cost,int alliesCount,const ArmyProto * ally,StackReflist * stacks)2468 Hero* Player::doRecruitHero(HeroProto* herotemplate, City *city, int cost, int alliesCount, const ArmyProto *ally, StackReflist *stacks)
2469 {
2470   Hero *newhero = new Hero(*herotemplate);
2471   newhero->setOwner(this);
2472   Stack *s = GameMap::getInstance()->addArmy(city, newhero);
2473   if (stacks)
2474     {
2475       if (stacks->contains(s->getId()) == false)
2476         stacks->addStack(s);
2477     }
2478 
2479   if (alliesCount > 0)
2480     {
2481       Reward_Allies::addAllies(this, city->getPos(), ally, alliesCount,
2482                                stacks);
2483       hero_arrives_with_allies.emit(alliesCount);
2484     }
2485 
2486   if (cost == 0)
2487     {
2488       // Initially give the first hero the player's standard.
2489       Glib::ustring name = String::ucompose(_("%1 Standard"), getName());
2490       Item *battle_standard = new Item (name, true, this);
2491       battle_standard->addBonus(Item::ADD1STACK);
2492       newhero->getBackpack()->addToBackpack(battle_standard, 0);
2493     }
2494   withdrawGold(cost);
2495   supdatingStack.emit(0);
2496   return newhero;
2497 }
2498 
recruitHero(HeroProto * heroproto,City * city,int cost,int alliesCount,const ArmyProto * ally,StackReflist * stacks)2499 void Player::recruitHero(HeroProto* heroproto, City *city, int cost, int alliesCount, const ArmyProto *ally, StackReflist *stacks)
2500 {
2501   //alright, we may have picked another sex for the hero.
2502   HeroProto *h;
2503   Glib::ustring name = heroproto->getName();
2504   Hero::Gender g = Hero::Gender(heroproto->getGender());
2505   h = HeroTemplates::getInstance()->getRandomHero(g, getId());
2506   h->setGender(g);
2507   h->setName(name);
2508   addAction(new Action_RecruitHero(h, city, cost, alliesCount, ally));
2509 
2510   Hero *hero = doRecruitHero(h, city, cost, alliesCount, ally, stacks);
2511   if (hero)
2512     addHistory(new History_HeroEmerges(hero, city));
2513 }
2514 
doDeclareDiplomacy(DiplomaticState state,Player * player)2515 void Player::doDeclareDiplomacy (DiplomaticState state, Player *player)
2516 {
2517   if (Playerlist::getInstance()->getNeutral() == player)
2518     return;
2519   if (player == this)
2520     return;
2521   if (state == d_diplomatic_state[player->getId()])
2522     return;
2523   d_diplomatic_state[player->getId()] = state;
2524 }
2525 
declareDiplomacy(DiplomaticState state,Player * player,bool treachery)2526 void Player::declareDiplomacy (DiplomaticState state, Player *player, bool treachery)
2527 {
2528   doDeclareDiplomacy(state, player);
2529 
2530   addAction(new Action_DiplomacyState(player, state));
2531 
2532   switch (state)
2533     {
2534     case AT_PEACE:
2535       addHistory(new History_DiplomacyPeace(player));
2536       break;
2537     case AT_WAR_IN_FIELD:
2538       break;
2539     case AT_WAR:
2540       addHistory(new History_DiplomacyWar(player));
2541       break;
2542     }
2543   if (treachery)
2544     addHistory(new History_DiplomacyTreachery(player));
2545   // FIXME: update diplomatic scores?
2546 }
2547 
doProposeDiplomacy(DiplomaticProposal proposal,Player * player)2548 void Player::doProposeDiplomacy (DiplomaticProposal proposal, Player *player)
2549 {
2550   if (GameScenarioOptions::s_diplomacy == false)
2551     return;
2552   if (Playerlist::getInstance()->getNeutral() == player)
2553     return;
2554   if (player == this)
2555     return;
2556   if (proposal == d_diplomatic_proposal[player->getId()])
2557     return;
2558   if (proposal == PROPOSE_PEACE)
2559     {
2560       Glib::ustring s =
2561         String::ucompose(_("Peace negotiated with %1."),player->getName());
2562       if (getDiplomaticState(player) == AT_PEACE ||
2563 	  getDiplomaticProposal(player) == PROPOSE_PEACE)
2564 	schangingStatus.emit(s);
2565     }
2566   else if (proposal == PROPOSE_WAR)
2567     {
2568       Glib::ustring s =
2569         String::ucompose(_("War declared with %1."), player->getName());
2570       if (getDiplomaticState(player) == AT_WAR ||
2571 	  getDiplomaticProposal(player) == PROPOSE_WAR)
2572       schangingStatus.emit(s);
2573     }
2574   d_diplomatic_proposal[player->getId()] = proposal;
2575 }
2576 
proposeDiplomacy(DiplomaticProposal proposal,Player * player)2577 void Player::proposeDiplomacy (DiplomaticProposal proposal, Player *player)
2578 {
2579   doProposeDiplomacy(proposal, player);
2580 
2581   addAction(new Action_DiplomacyProposal(player, proposal));
2582 
2583   // FIXME: update diplomatic scores?
2584 }
2585 
negotiateDiplomacy(Player * player)2586 Player::DiplomaticState Player::negotiateDiplomacy (Player *player)
2587 {
2588   DiplomaticState state = getDiplomaticState(player);
2589   DiplomaticProposal them = player->getDiplomaticProposal(this);
2590   DiplomaticProposal me = getDiplomaticProposal(player);
2591   DiplomaticProposal winning_proposal;
2592 
2593   /* Check if we both want the status quo. */
2594   if (me == NO_PROPOSAL && them == NO_PROPOSAL)
2595     return state;
2596 
2597   /* Okay, we both want a change from the status quo. */
2598 
2599   /* In the absense of a new proposal, the status quo is the proposal. */
2600   if (me == NO_PROPOSAL)
2601     {
2602       switch (state)
2603 	{
2604 	case AT_PEACE: me = PROPOSE_PEACE; break;
2605 	case AT_WAR_IN_FIELD: me = PROPOSE_WAR_IN_FIELD; break;
2606 	case AT_WAR: me = PROPOSE_WAR; break;
2607 	}
2608     }
2609   if (them == NO_PROPOSAL)
2610     {
2611       switch (state)
2612 	{
2613 	case AT_PEACE: them = PROPOSE_PEACE; break;
2614 	case AT_WAR_IN_FIELD: them = PROPOSE_WAR_IN_FIELD; break;
2615 	case AT_WAR: them = PROPOSE_WAR; break;
2616 	}
2617     }
2618 
2619   /* Check if we have agreement. */
2620   if (me == PROPOSE_PEACE && them == PROPOSE_PEACE)
2621     return AT_PEACE;
2622   else if (me == PROPOSE_WAR_IN_FIELD && them == PROPOSE_WAR_IN_FIELD)
2623     return AT_WAR_IN_FIELD;
2624   else if (me == PROPOSE_WAR && them == PROPOSE_WAR)
2625     return AT_WAR;
2626 
2627   /* Still we don't have an agreement.
2628      Unfortunately the greater violence is the new diplomatic state.
2629      Because there are two different proposals and the proposal with
2630      greater violence will be the new status quo, there can't
2631      possibly be peace at this juncture.  */
2632 
2633   winning_proposal = me;
2634   if (them > me)
2635     winning_proposal = them;
2636 
2637   switch (winning_proposal)
2638     {
2639     case PROPOSE_WAR_IN_FIELD: return AT_WAR_IN_FIELD; break;
2640     case PROPOSE_WAR: return AT_WAR; break;
2641     default: return AT_PEACE; break; //impossible
2642     }
2643 
2644 }
2645 
getDiplomaticState(Player * player) const2646 Player::DiplomaticState Player::getDiplomaticState (Player *player) const
2647 {
2648   if (player == Playerlist::getInstance()->getNeutral())
2649     return AT_WAR;
2650   if (player == this)
2651     return AT_PEACE;
2652   return d_diplomatic_state[player->getId()];
2653 }
2654 
getDiplomaticProposal(Player * player) const2655 Player::DiplomaticProposal Player::getDiplomaticProposal (Player *player) const
2656 {
2657   if (player == Playerlist::getInstance()->getNeutral())
2658     return PROPOSE_WAR;
2659   if (player == this)
2660     return NO_PROPOSAL;
2661   return d_diplomatic_proposal[player->getId()];
2662 }
2663 
getDiplomaticScore(Player * player) const2664 guint32 Player::getDiplomaticScore (Player *player) const
2665 {
2666   if (Playerlist::getInstance()->getNeutral() == player)
2667     return 8;
2668   return d_diplomatic_score[player->getId()];
2669 }
2670 
alterDiplomaticRelationshipScore(Player * player,int amount)2671 void Player::alterDiplomaticRelationshipScore (Player *player, int amount)
2672 {
2673   if (amount > 0)
2674     {
2675       if (d_diplomatic_score[player->getId()] + amount > DIPLOMACY_MAX_SCORE)
2676 	d_diplomatic_score[player->getId()] = DIPLOMACY_MAX_SCORE;
2677       else
2678 	d_diplomatic_score[player->getId()] += amount;
2679     }
2680   else if (amount < 0)
2681     {
2682       if ((guint32) (amount * -1) > d_diplomatic_score[player->getId()])
2683 	d_diplomatic_score[player->getId()] = DIPLOMACY_MIN_SCORE;
2684       else
2685 	d_diplomatic_score[player->getId()] += amount;
2686     }
2687 }
2688 
improveDiplomaticRelationship(Player * player,guint32 amount)2689 void Player::improveDiplomaticRelationship (Player *player, guint32 amount)
2690 {
2691   if (Playerlist::getInstance()->getNeutral() == player || player == this)
2692     return;
2693 
2694   alterDiplomaticRelationshipScore (player, amount);
2695 
2696   addAction(new Action_DiplomacyScore(player, amount));
2697 }
2698 
deteriorateDiplomaticRelationship(Player * player,guint32 amount)2699 void Player::deteriorateDiplomaticRelationship (Player *player, guint32 amount)
2700 {
2701   if (Playerlist::getInstance()->getNeutral() == player || player == this)
2702     return;
2703 
2704   alterDiplomaticRelationshipScore (player, -amount);
2705 
2706   addAction(new Action_DiplomacyScore(player, -amount));
2707 }
2708 
deteriorateDiplomaticRelationship(guint32 amount)2709 void Player::deteriorateDiplomaticRelationship (guint32 amount)
2710 {
2711   for (auto it: *Playerlist::getInstance())
2712     {
2713       if (it->isDead())
2714 	continue;
2715       if (Playerlist::getInstance()->getNeutral() == it)
2716 	continue;
2717       if (it == this)
2718 	continue;
2719       it->deteriorateDiplomaticRelationship (this, amount);
2720     }
2721 }
2722 
improveDiplomaticRelationship(guint32 amount,Player * except)2723 void Player::improveDiplomaticRelationship (guint32 amount, Player *except)
2724 {
2725   for (auto it: *Playerlist::getInstance())
2726     {
2727       if (it->isDead())
2728 	continue;
2729       if (Playerlist::getInstance()->getNeutral() == it)
2730 	continue;
2731       if (it == this)
2732 	continue;
2733       if (except && it == except)
2734 	continue;
2735       it->improveDiplomaticRelationship (this, amount);
2736     }
2737 }
2738 
deteriorateAlliesRelationship(Player * player,guint32 amount,Player::DiplomaticState state)2739 void Player::deteriorateAlliesRelationship(Player *player, guint32 amount,
2740 					   Player::DiplomaticState state)
2741 {
2742   for (auto it: *Playerlist::getInstance())
2743     {
2744       if (it->isDead())
2745 	continue;
2746       if (Playerlist::getInstance()->getNeutral() == it)
2747 	continue;
2748       if (it == this)
2749 	continue;
2750       if (getDiplomaticState(it) == state)
2751 	it->deteriorateDiplomaticRelationship (player, amount);
2752     }
2753 }
2754 
improveAlliesRelationship(Player * player,guint32 amount,Player::DiplomaticState state)2755 void Player::improveAlliesRelationship(Player *player, guint32 amount,
2756 				       Player::DiplomaticState state)
2757 {
2758   for (auto it: *Playerlist::getInstance())
2759     {
2760       if (it->isDead())
2761 	continue;
2762       if (Playerlist::getInstance()->getNeutral() == it)
2763 	continue;
2764       if (it == this)
2765 	continue;
2766       if (player->getDiplomaticState(it) == state)
2767 	it->improveDiplomaticRelationship (this, amount);
2768     }
2769 }
2770 
AI_maybeBuyScout(City * c)2771 void Player::AI_maybeBuyScout(City *c)
2772 {
2773   if (c->getBuildProduction() == false)
2774     return;
2775   bool one_turn_army_exists = false;
2776   //do we already have something that can be produced in one turn?
2777   for (unsigned int i = 0; i < c->getMaxNoOfProductionBases(); i++)
2778     {
2779       if (c->getArmytype(i) == -1)    // no production in this slot
2780         continue;
2781 
2782       const ArmyProdBase *proto = c->getProductionBase(i);
2783       if (proto->getProduction() == 1)
2784         {
2785           one_turn_army_exists = true;
2786           break;
2787         }
2788     }
2789   if (one_turn_army_exists == false)
2790     {
2791       int free_slot = c->getFreeSlot();
2792       if (free_slot == -1)
2793         free_slot = 0;
2794       ArmyProto *scout =
2795         Armysetlist::getInstance()->lookupWeakestQuickestArmy(getArmyset());
2796       cityBuyProduction(c, free_slot, scout->getId());
2797     }
2798 }
2799 
AI_maybeContinueQuest(Stack * s,Quest * quest,bool & completed_quest,bool & stack_died)2800 bool Player::AI_maybeContinueQuest(Stack *s, Quest *quest, bool &completed_quest, bool &stack_died)
2801 {
2802   bool stack_moved = false;
2803   Vector<int> quest_tile = AI_getQuestDestination(quest, s);
2804 
2805   if (quest_tile == Vector<int>(-1,-1))
2806     return false;
2807 
2808   //are we not standing on it?
2809   if (s->getPos() != quest_tile)
2810     {
2811       //can we really reach it?
2812       Vector<int> old_dest(-1,-1);
2813       if (s->getPath()->size())
2814 	old_dest = s->getLastPointInPath();
2815       guint32 moves = 0, turns = 0, left = 0;
2816       s->getPath()->calculate(s, quest_tile, moves, turns, left);
2817       bool go_there = computerChooseContinueQuest(s, quest, quest_tile, moves,
2818                                                   turns);
2819       if (!go_there)
2820         {
2821           s->clearPath();
2822 	  if (old_dest != Vector<int>(-1,-1))
2823 	    s->getPath()->calculate(s, old_dest);
2824           return false;
2825         }
2826       d_stacklist->setActivestack(s);
2827       stack_moved = stackMove(s);
2828       //maybe we died either en route or at our destination.
2829       if (!d_stacklist->getActivestack())
2830 	{
2831 	  stack_died = true;
2832 	  return true;
2833 	}
2834       s = d_stacklist->getActivestack();
2835     }
2836 
2837   //are we standing on it now?
2838   if (s->getPos() == quest_tile)
2839     completed_quest = true;
2840 
2841   return stack_moved;
2842 }
2843 
AI_maybePickUpItems(Stack * s,int max_dist,bool & picked_up,bool & stack_died)2844 bool Player::AI_maybePickUpItems(Stack *s, int max_dist,
2845 				 bool &picked_up, bool &stack_died)
2846 {
2847   int min_dist = -1;
2848   bool stack_moved = false;
2849   Vector<int> item_tile(-1, -1);
2850 
2851   // do we not have a hero?
2852   if (s->hasHero() == false)
2853     return false;
2854 
2855   //ok, which bag of stuff is closest?
2856   for (auto tile: GameMap::getInstance()->getItems())
2857     {
2858       //don't consider bags of stuff that are inside enemy cities
2859       City *c = GameMap::getCity(tile);
2860       if (c)
2861 	{
2862 	  if (c->getOwner() != s->getOwner())
2863 	    continue;
2864 	}
2865 
2866       int distance = dist (tile, s->getPos());
2867       if (distance < min_dist || min_dist == -1)
2868 	{
2869 	  min_dist = distance;
2870 	  item_tile = tile;
2871 	}
2872     }
2873 
2874   //if no bags of stuff, or the bag is too far away
2875   if (min_dist == -1 || min_dist > max_dist)
2876     return false;
2877 
2878   //are we not standing on it?
2879   if (s->getPos() != item_tile)
2880     {
2881       //can we really reach it?
2882       Vector<int> old_dest(-1,-1);
2883       if (s->getPath()->size())
2884 	old_dest = s->getLastPointInPath();
2885       guint32 moves = 0, turns = 0, left = 0;
2886       s->getPath()->calculate(s, item_tile, moves, turns, left);
2887       bool go_there = computerChoosePickupBag(s, item_tile, moves, turns);
2888       if (!go_there)
2889         {
2890           s->clearPath();
2891 	  if (old_dest != Vector<int>(-1,-1))
2892 	    s->getPath()->calculate(s, old_dest);
2893           return false;
2894         }
2895       d_stacklist->setActivestack(s);
2896       stack_moved = stackMove(s);
2897       //maybe we died -- an enemy stack was guarding the bag.
2898       if (!d_stacklist->getActivestack())
2899 	{
2900 	  stack_died = true;
2901 	  return true;
2902 	}
2903       s = d_stacklist->getActivestack();
2904     }
2905 
2906   //are we standing on it now?
2907   if (s->getPos() == item_tile)
2908     {
2909       bool pickitup = computerChoosePickupBag(s, item_tile, 0, 0);
2910       if (!pickitup)
2911         {
2912           s->clearPath();
2913           return stack_moved;
2914         }
2915       Hero *hero = static_cast<Hero*>(s->getFirstHero());
2916       if (hero)
2917 	picked_up = heroPickupAllItems(hero, s->getPos());
2918     }
2919 
2920   return stack_moved;
2921 }
2922 
AI_maybeVisitTempleForQuest(Stack * s,int dist,bool & got_quest,bool & stack_died)2923 bool Player::AI_maybeVisitTempleForQuest(Stack *s, int dist, bool &got_quest, bool &stack_died)
2924 {
2925   bool stack_moved = false;
2926 
2927   //if this stack doesn't have a hero then we can't get a quest with this stack.
2928   if (s->hasHero() == false)
2929     return false;
2930 
2931   //if the player already has a hero who has a quest, then we can't get a
2932   //quest with this stack when playing one quest per player.
2933   if (QuestsManager::getInstance()->getPlayerQuests(this).size() > 0 &&
2934       GameScenarioOptions::s_play_with_quests ==
2935       GameParameters::ONE_QUEST_PER_PLAYER)
2936     return false;
2937 
2938   Temple *temple =
2939     Templelist::getInstance()->getNearestVisibleTemple(s->getPos(), dist);
2940   if (!temple)
2941     return false;
2942 
2943   //if we're not there yet
2944   if (temple->contains(s->getPos()) == false)
2945     {
2946       //can we really reach it?
2947       Vector<int> old_dest(-1,-1);
2948       if (s->getPath()->size())
2949 	old_dest = s->getLastPointInPath();
2950       guint32 moves = 0, turns = 0, left = 0;
2951       s->getPath()->calculate(s, s->getPos(), moves, turns, left);
2952       bool go_there = computerChooseVisitTempleForQuest(s, temple->getPos(), moves, turns);
2953       if (!go_there)
2954         {
2955           s->clearPath();
2956 	  if (old_dest != Vector<int>(-1,-1))
2957 	    s->getPath()->calculate(s, old_dest);
2958           return false;
2959         }
2960       d_stacklist->setActivestack(s);
2961       stack_moved = stackMove(s);
2962 
2963       //maybe we died -- an enemy stack was guarding the temple
2964       if (!d_stacklist->getActivestack())
2965 	{
2966 	  stack_died = true;
2967 	  return true;
2968 	}
2969       s = d_stacklist->getActivestack();
2970     }
2971 
2972   //are we there yet?
2973   if (temple->contains(s->getPos()) == true && GameMap::can_search(s))
2974     {
2975       bool searchit = computerChooseVisitTempleForQuest(s, s->getPos(), 0, 0);
2976       if (!searchit)
2977         {
2978           s->clearPath();
2979           return stack_moved;
2980         }
2981       svisitingTemple.emit(temple, s);
2982       got_quest = true;
2983     }
2984 
2985   return stack_moved;
2986 }
2987 
AI_maybeVisitRuin(Stack * s,int dist,bool & visited_ruin,bool & stack_died)2988 bool Player::AI_maybeVisitRuin(Stack *s, int dist, bool &visited_ruin, bool &stack_died)
2989 {
2990   bool stack_moved = false;
2991 
2992   //if this stack doesn't have a hero then we can't search the ruin.
2993   if (s->hasHero() == false)
2994     return false;
2995 
2996   Ruin *ruin = Ruinlist::getInstance()->getNearestUnsearchedRuin(s->getPos(), dist);
2997   if (!ruin)
2998     return false;
2999 
3000   //if we're not there yet
3001   if (ruin->contains(s->getPos()) == false)
3002     {
3003       //can we really reach it?
3004       Vector<int> old_dest(-1,-1);
3005       if (s->getPath()->size())
3006 	old_dest = s->getLastPointInPath();
3007       guint32 moves = 0, turns = 0, left = 0;
3008       s->getPath()->calculate(s, ruin->getPos(), moves, turns, left);
3009       bool go_there = computerChooseVisitRuin(s, ruin->getPos(), moves, turns);
3010       if (!go_there)
3011         {
3012           s->clearPath();
3013 	  if (old_dest != Vector<int>(-1,-1))
3014 	    s->getPath()->calculate(s, old_dest);
3015           return false;
3016         }
3017       d_stacklist->setActivestack(s);
3018       stack_moved = stackMove(s);
3019 
3020       //maybe we died -- an enemy stack was guarding the temple
3021       if (!d_stacklist->getActivestack())
3022 	{
3023 	  stack_died = true;
3024 	  return true;
3025 	}
3026       s = d_stacklist->getActivestack();
3027     }
3028 
3029   //are we there yet?
3030   if (ruin->contains(s->getPos()) == true && GameMap::can_search(s))
3031     {
3032       bool searchit = computerChooseVisitRuin(s, s->getPos(), 0, 0);
3033       if (!searchit)
3034         {
3035           s->clearPath();
3036           return stack_moved;
3037         }
3038       stack_died = ssearchingRuin.emit(ruin, s);
3039       if (!stack_died)
3040         visited_ruin = true;
3041     }
3042 
3043   return stack_moved;
3044 }
3045 
AI_maybeVisitTempleForBlessing(Stack * s,int dist,double percent_can_be_blessed,bool & blessed,bool & stack_died)3046 bool Player::AI_maybeVisitTempleForBlessing(Stack *s, int dist,
3047 					    double percent_can_be_blessed,
3048 					    bool &blessed, bool &stack_died)
3049 {
3050   bool stack_moved = false;
3051 
3052   Temple *temple = Templelist::getInstance()->getNearestVisibleAndUsefulTemple
3053     (s, percent_can_be_blessed, dist);
3054   if (!temple)
3055     return false;
3056 
3057   //if we're not there yet
3058   if (s->getPos() != temple->getPos())
3059     {
3060       //can we really reach it?
3061       Vector<int> old_dest(-1,-1);
3062       if (s->getPath()->size())
3063 	old_dest = s->getLastPointInPath();
3064       guint32 moves = 0, turns = 0, left = 0;
3065       s->getPath()->calculate(s, temple->getPos(), moves, turns, left);
3066       bool go_there = computerChooseVisitTempleForBlessing(s, temple->getPos(), moves, turns);
3067       if (!go_there)
3068         {
3069           s->clearPath();
3070 	  if (old_dest != Vector<int>(-1,-1))
3071 	    s->getPath()->calculate(s, old_dest);
3072           return false;
3073         }
3074       d_stacklist->setActivestack(s);
3075       stack_moved = stackMove(s);
3076 
3077       //maybe we died -- an enemy stack was guarding the temple
3078       if (!d_stacklist->getActivestack())
3079 	{
3080 	  stack_died = true;
3081 	  return true;
3082 	}
3083       s = d_stacklist->getActivestack();
3084     }
3085 
3086   int num_blessed = 0;
3087   //are we there yet?
3088   if (temple->contains(s->getPos()) == true && GameMap::can_search(s))
3089     {
3090       bool searchit = computerChooseVisitTempleForBlessing(s, s->getPos(),
3091                                                            0, 0);
3092       if (!searchit)
3093         {
3094           s->clearPath();
3095           return stack_moved;
3096         }
3097       num_blessed = stackVisitTemple(s, temple);
3098     }
3099 
3100   blessed = num_blessed > 0;
3101   return stack_moved;
3102 }
3103 
safeFromAttack(City * c,guint32 safe_mp,guint32 min_defenders)3104 bool Player::safeFromAttack(City *c, guint32 safe_mp, guint32 min_defenders)
3105 {
3106   //if there isn't an enemy city nearby to the source
3107   // calculate mp to nearest enemy city
3108   //   needs to be less than 18 mp with a scout
3109   //does the source city contain at least 3 defenders?
3110 
3111   City *enemy_city = Citylist::getInstance()->getNearestEnemyCity(c->getPos());
3112   if (enemy_city)
3113     {
3114       PathCalculator pc(c->getOwner(), c->getPos());
3115       int mp = pc.calculate(enemy_city->getPos());
3116       if (mp <= 0 || mp >= (int)safe_mp)
3117 	{
3118 	  if (c->countDefenders() >= min_defenders)
3119 	    return true;
3120 	}
3121     }
3122 
3123   return false;
3124 }
3125 
AI_maybeDisband(Stack * s,int safe_mp,bool & stack_killed)3126 bool Player::AI_maybeDisband(Stack *s, int safe_mp, bool &stack_killed)
3127 {
3128   bool disbanded = false;
3129   //see if we're near to enemy stacks
3130   PathCalculator pc(s);
3131   if (GameMap::getEnemyStacks(pc.getReachablePositions(safe_mp)).size() > 0)
3132     return false;
3133 
3134   //upgroup the whole stack if it doesn't contain a hero
3135   if (s->hasHero() == false)
3136     {
3137       stack_killed = stackDisband (s);
3138       return stack_killed;
3139     }
3140 
3141   //ungroup the lucky ones not being disbanded
3142   for (Stack::reverse_iterator i = s->rbegin(); i != s->rend(); i++)
3143     {
3144       if ((*i)->isHero() == false)
3145 	{
3146 	  Stack *new_stack = stackSplitArmy(s, *i);
3147 	  if (new_stack)
3148 	    {
3149 	    if (stackDisband(new_stack))
3150 	      disbanded = true;
3151 	    }
3152 	}
3153     }
3154   return disbanded;
3155 }
3156 
AI_maybeDisband(Stack * s,City * city,guint32 min_defenders,int safe_mp,bool & stack_killed)3157 bool Player::AI_maybeDisband(Stack *s, City *city, guint32 min_defenders,
3158 			     int safe_mp, bool &stack_killed)
3159 {
3160   bool disbanded = false;
3161   //is the city in danger from a city?
3162   if (safeFromAttack(city, safe_mp, 0) == false)
3163     return false;
3164 
3165   if (city->countDefenders() - s->size() >= min_defenders)
3166     {
3167       if (s->hasHero())
3168 	min_defenders = s->size() + 1;
3169       else
3170 	{
3171 	  stack_killed = stackDisband(s);
3172 	  return stack_killed;
3173 	}
3174     }
3175 
3176   //okay, we need to disband part of our stack
3177 
3178   //before we move, ungroup the lucky ones not being disbanded
3179   unsigned int count = 0;
3180   for (Stack::reverse_iterator i = s->rbegin(); i != s->rend(); i++)
3181     {
3182       if (count == min_defenders)
3183 	break;
3184       if ((*i)->isHero() == false)
3185 	{
3186 	  Stack *new_stack = stackSplitArmy(s, *i);
3187 	  if (new_stack)
3188 	    {
3189 	      count++;
3190 	      if (stackDisband(new_stack))
3191 		disbanded = true;
3192 	    }
3193 	}
3194     }
3195   return disbanded;
3196 }
3197 
AI_maybeVector(City * c,guint32 safe_mp,guint32 min_defenders,City * target,City ** vector_city)3198 bool Player::AI_maybeVector(City *c, guint32 safe_mp, guint32 min_defenders,
3199 			    City *target, City **vector_city)
3200 {
3201   assert (c->getOwner() == this);
3202   if (vector_city)
3203     *vector_city = NULL;
3204 
3205   //is this city producing anything that we can vector?
3206   if (c->getActiveProductionSlot() == -1)
3207     return false;
3208 
3209   //is it safe to vector from this city?
3210   bool safe = safeFromAttack(c, safe_mp, min_defenders);
3211 
3212   if (!safe)
3213     return false;
3214 
3215   //get the nearest city to the enemy city that can accept vectored units
3216   City *near_city =
3217     Citylist::getInstance()->getNearestFriendlyVectorableCity(target->getPos());
3218   if (!near_city)
3219     return false;
3220   assert (near_city->getOwner() == this);
3221   if (GameMap::getCity(near_city->getPos()) != near_city)
3222     {
3223       printf("nearCity is %s (%d)\n", near_city->getName().c_str(), near_city->getId());
3224       printf("it is located at %d,%d\n", near_city->getPos().x, near_city->getPos().y);
3225       City *other = GameMap::getCity(near_city->getPos());
3226       if (other)
3227 	{
3228       printf("the OTHER nearCity is %s (%d)\n", other->getName().c_str(), other->getId());
3229       printf("it is located at %d,%d\n", other->getPos().x, other->getPos().y);
3230 	}
3231       else
3232 	printf("no city there!\n");
3233       assert (1 == 0);
3234     }
3235 
3236   //if it's us then it's easier to just walk.
3237   if (near_city == c)
3238     return false;
3239 
3240   //is that city already vectoring?
3241   if (near_city->getVectoring() != Vector<int>(-1, -1))
3242     return false;
3243 
3244   //can i just walk there faster?
3245 
3246   //find turns from source to target city
3247   const ArmyProdBase *proto = c->getActiveProductionBase();
3248   PathCalculator pc1(c->getOwner(), c->getPos(), proto);
3249   guint32 moves1 = 0, turns1 = 0, left1 = 0;
3250   guint32 moves2 = 0, turns2 = 0, left2 = 0;
3251   Path *p = pc1.calculate(target->getPos(), moves1, turns1, left1);
3252   if (p)
3253     delete p;
3254 
3255   //find turns from nearer vectorable city to target city
3256   PathCalculator pc2(c->getOwner(), near_city->getPos(), proto);
3257   p = pc2.calculate(target->getPos(), moves2, turns2, left2);
3258   if (p)
3259     delete p;
3260   turns2+=VectoredUnit::get_travel_turns(near_city->getPos(), target->getPos());
3261   if (turns1 <= turns2)
3262     return false;
3263 
3264   //great.  now do the vectoring.
3265   c->changeVectorDestination(near_city->getPos());
3266 
3267   if (vector_city)
3268     *vector_city = near_city;
3269   return true;
3270 }
3271 
AI_setupVectoring(guint32 safe_mp,guint32 min_defenders,guint32 mp_to_front)3272 void Player::AI_setupVectoring(guint32 safe_mp, guint32 min_defenders,
3273 			       guint32 mp_to_front)
3274 {
3275   //turn off vectoring where it isn't safe anymore
3276   //turn off vectoring for destinations that are far away from the
3277   //nearest enemy city
3278 
3279   for (auto c: *Citylist::getInstance())
3280     {
3281       if (c->getOwner() != this || c->isBurnt())
3282 	continue;
3283       Vector<int> dest = c->getVectoring();
3284       if (dest == Vector<int>(-1, -1))
3285 	continue;
3286       if (safeFromAttack(c, safe_mp, min_defenders) == false)
3287 	{
3288 	  //City *target_city = Citylist::getInstance()->getObjectAt(dest);
3289 	  //debug("stopping vectoring from " << c->getName() <<" to " << target_city->getName() << " because it's not safe to anymore!\n")
3290 	  c->setVectoring(Vector<int>(-1,-1));
3291 	  continue;
3292 	}
3293 
3294       City *enemy_city = Citylist::getInstance()->getNearestEnemyCity(dest);
3295       if (!enemy_city)
3296 	{
3297 	  //City *target_city = Citylist::getInstance()->getObjectAt(dest);
3298 	  //debug("stopping vectoring from " << c->getName() <<" to " << target_city->getName() << " because there aren't any more enemy cities!\n")
3299 	  c->setVectoring(Vector<int>(-1,-1));
3300 	  continue;
3301 	}
3302 
3303       PathCalculator pc(this, dest, NULL);
3304       int mp = pc.calculate(enemy_city->getPos());
3305       if (mp <= 0 || mp > (int)mp_to_front)
3306 	{
3307 
3308 	  //City *target_city = Citylist::getInstance()->getObjectAt(dest);
3309 	  //debug("stopping vectoring from " << c->getName() <<" to " << target_city->getName() << " because it's too far away from an enemy city!\n")
3310 	  c->setVectoring(Vector<int>(-1,-1));
3311 	  continue;
3312 	}
3313     }
3314 
3315   for (auto c : *Citylist::getInstance())
3316     {
3317       if (c->getOwner() != this || c->isBurnt())
3318 	continue;
3319       City *enemy_city = Citylist::getInstance()->getNearestEnemyCity(c->getPos());
3320       if (!enemy_city)
3321 	continue;
3322       City *vector_city = NULL;
3323       //if the city isn't already vectoring
3324       if (c->getVectoring() == Vector<int>(-1,-1))
3325 	{
3326 	  bool vectored = AI_maybeVector(c, safe_mp, min_defenders, enemy_city,
3327 					 &vector_city);
3328 	  if (vectored)
3329             {
3330               debug("begin vectoring from " << c->getName() <<" to " << vector_city->getName() << "!\n");
3331             }
3332 	}
3333     }
3334 }
3335 
doCityProducesArmy(City * city,Stack * & s,bool & vectored)3336 const Army * Player::doCityProducesArmy(City *city, Stack *& s, bool &vectored)
3337 {
3338   vectored = false;
3339   int cost = city->getActiveProductionBase()->getProductionCost();
3340   if (cost > d_gold)
3341     return NULL;
3342   withdrawGold(cost);
3343   const Army *a = city->armyArrives(s);
3344   if (city->getVectoring() != Vector<int>(-1,-1))
3345     vectored = true;
3346   return a;
3347 }
3348 
cityProducesArmy(City * city)3349 bool Player::cityProducesArmy(City *city)
3350 {
3351   assert(city->getOwner() == this);
3352   Stack *stack = NULL;
3353   bool vectored = false;
3354   const Army *army = doCityProducesArmy(city, stack, vectored);
3355   if (army)
3356     {
3357       if (!stack)
3358         {
3359           printf("we dropped an army down but it doesn't have a stack!\n");
3360           return false;
3361         }
3362       const ArmyProdBase *source_army;
3363       source_army = city->getProductionBaseBelongingTo(army);
3364       if (stack)
3365         {
3366           addAction(new Action_Produce(source_army, city, false, stack->getPos(), army->getId(), stack->getId()));
3367           addAction(new Action_ReorderArmies(stack));
3368         }
3369     }
3370   else
3371     {
3372       if (vectored)
3373         {
3374           //send vectoring action.
3375           const ArmyProdBase *source_army = city->getActiveProductionBase();
3376           addAction(new Action_Produce(source_army, city, true,
3377                                        city->getVectoring(), 0, 0));
3378         }
3379     }
3380   return true;
3381 }
3382 
doVectoredUnitArrives(VectoredUnit * unit,Stack * & s)3383 Army* Player::doVectoredUnitArrives(VectoredUnit *unit, Stack *& s)
3384 {
3385   Army *army = unit->armyArrives(s);
3386   return army;
3387 }
3388 
vectoredUnitArrives(VectoredUnit * unit)3389 bool Player::vectoredUnitArrives(VectoredUnit *unit)
3390 {
3391   Stack *stack = NULL;
3392   Army *army = doVectoredUnitArrives(unit, stack);
3393   if (!army)
3394     {
3395       printf("this was supposed to be impossible because of operations on the vectoredunitlist after the city is conquered.\n");
3396       printf("whooops... this vectored unit failed to show up.\n");
3397       City *dest = GameMap::getCity(unit->getDestination());
3398       printf("the unit was being vectored to: %s, from %s by %s\n",
3399              dest->getName().c_str(),
3400              GameMap::getCity(unit->getPos())->getName().c_str(), getName().c_str());
3401       printf("Army is a %s, turns is %d + 1\n", unit->getArmy()->getName().c_str(), unit->getArmy()->getProduction());
3402 
3403 
3404       int turn = -1;
3405       std::list<History*> h = dest->getOwner()->getHistoryForCityId(dest->getId());
3406       std::list<History*>::const_iterator pit;
3407       for (pit = h.begin(); pit != h.end(); pit++)
3408         {
3409           switch ((*pit)->getType())
3410             {
3411             case History::START_TURN:
3412                 {
3413                   turn++;
3414                   break;
3415                 }
3416             case History::CITY_WON:
3417               break;
3418             case History::CITY_RAZED:
3419               break;
3420             default:
3421               break;
3422             }
3423         }
3424       printf("was the destination city owned by us way back then?\n");
3425       exit (1);
3426     }
3427   else
3428     addAction(new Action_ProduceVectored(unit->getArmy(),
3429                                          unit->getDestination(),
3430                                          unit->getPos(), army->getId(),
3431                                          stack->getId()));
3432 
3433   return true;
3434 }
3435 
getUnitsProducedThisTurn() const3436 std::list<Action_Produce *> Player::getUnitsProducedThisTurn() const
3437 {
3438   std::list<Action_Produce *> actions;
3439   std::list<Action *>::const_reverse_iterator it = d_actions.rbegin();
3440   for (; it != d_actions.rend(); it++)
3441     {
3442       if ((*it)->getType() == Action::PRODUCE_UNIT)
3443 	actions.push_back(dynamic_cast<Action_Produce*>(*it));
3444       else if ((*it)->getType() == Action::INIT_TURN)
3445 	break;
3446     }
3447   return actions;
3448 }
3449 
getReportableActions() const3450 std::list<Action *> Player::getReportableActions() const
3451 {
3452   std::list<Action *> actions;
3453   for (auto it: d_actions)
3454     {
3455       if (it->getType() == Action::PRODUCE_UNIT ||
3456 	  it->getType() == Action::PRODUCE_VECTORED_UNIT ||
3457 	  it->getType() == Action::CITY_DESTITUTE)
3458 	actions.push_back(it);
3459     }
3460   return actions;
3461 }
3462 
cityTooPoorToProduce(City * city,int slot)3463 void Player::cityTooPoorToProduce(City *city, int slot)
3464 {
3465   cityChangeProduction(city, -1);
3466   const ArmyProdBase *a = city->getProductionBase(slot);
3467   addAction(new Action_CityTooPoorToProduce(city, a));
3468 }
3469 
pruneActionlist()3470 void Player::pruneActionlist()
3471 {
3472   pruneActionlist(d_actions);
3473 }
3474 
pruneCityProductions(std::list<Action * > & actions)3475 void Player::pruneCityProductions(std::list<Action*> &actions)
3476 {
3477   //remove duplicate city production actions
3478 
3479   //enumerate the ones we want
3480   std::list<Action_Production*> keepers;
3481   std::list<Action*>::reverse_iterator ait;
3482   for (ait = actions.rbegin(); ait != actions.rend(); ait++)
3483     {
3484       if ((*ait)->getType() != Action::CITY_PROD)
3485 	continue;
3486       //if this city isn't already in the keepers list, then add it.
3487 
3488       Action_Production *action = static_cast<Action_Production*>(*ait);
3489       bool found = false;
3490       std::list<Action_Production*>::const_iterator it;
3491       for (it = keepers.begin(); it != keepers.end(); it++)
3492 	{
3493 	  if (action->getCityId() == (*it)->getCityId())
3494 	    {
3495 	      found = true;
3496 	      break;
3497 	    }
3498 	}
3499       if (found == false)
3500 	keepers.push_back(action);
3501 
3502     }
3503 
3504   //now delete all city production events that aren't in keepers
3505   int total = 0;
3506   std::list<Action*>::iterator bit;
3507   for (bit = actions.begin(); bit != actions.end(); bit++)
3508     {
3509       if ((*bit)->getType() != Action::CITY_PROD)
3510 	continue;
3511       if (find (keepers.begin(), keepers.end(), (*bit)) == keepers.end())
3512 	{
3513 	  total++;
3514           delete *bit;
3515 	  actions.erase (bit);
3516 	  bit = actions.begin();
3517 	  continue;
3518 	}
3519     }
3520 }
3521 
pruneCityVectorings(std::list<Action * > & actions)3522 void Player::pruneCityVectorings(std::list<Action*> &actions)
3523 {
3524   //remove duplicate city vectoring actions
3525 
3526   //enumerate the ones we want
3527   std::list<Action_Vector*> keepers;
3528   std::list<Action*>::reverse_iterator ait;
3529   for (ait = actions.rbegin(); ait != actions.rend(); ait++)
3530     {
3531       if ((*ait)->getType() != Action::CITY_VECTOR)
3532 	continue;
3533       //if this city isn't already in the keepers list, then add it.
3534 
3535       Action_Vector *action = static_cast<Action_Vector *>(*ait);
3536       bool found = false;
3537       std::list<Action_Vector*>::const_iterator it;
3538       for (it = keepers.begin(); it != keepers.end(); it++)
3539 	{
3540 	  if (action->getCityId() == (*it)->getCityId())
3541 	    {
3542 	      found = true;
3543 	      break;
3544 	    }
3545 	}
3546       if (found == false)
3547 	keepers.push_back(action);
3548 
3549     }
3550 
3551   //now delete all city vector events that aren't in keepers
3552   int total = 0;
3553   std::list<Action*>::iterator bit;
3554   for (bit = actions.begin(); bit != actions.end(); bit++)
3555     {
3556       if ((*bit)->getType() != Action::CITY_VECTOR)
3557 	continue;
3558       if (find (keepers.begin(), keepers.end(), (*bit)) == keepers.end())
3559 	{
3560 	  total++;
3561           delete *bit;
3562 	  actions.erase (bit);
3563 	  bit = actions.begin();
3564 	  continue;
3565 	}
3566     }
3567 }
3568 
pruneActionlist(std::list<Action * > & actions)3569 void Player::pruneActionlist(std::list<Action*> &actions)
3570 {
3571   pruneCityProductions(actions);
3572   pruneCityVectorings(actions);
3573 
3574 }
3575 
playerTypeToString(const Player::Type type)3576 Glib::ustring Player::playerTypeToString(const Player::Type type)
3577 {
3578   switch (type)
3579     {
3580     case Player::HUMAN: return "Player::HUMAN";
3581     case Player::AI_FAST: return "Player::AI_FAST";
3582     case Player::AI_DUMMY: return "Player::AI_DUMMY";
3583     case Player::AI_SMART: return "Player::AI_SMART";
3584     case Player::NETWORKED: return "Player::NETWORKED";
3585     }
3586   return "Player::HUMAN";
3587 }
3588 
playerTypeFromString(const Glib::ustring str)3589 Player::Type Player::playerTypeFromString(const Glib::ustring str)
3590 {
3591   if (str.size() > 0 && isdigit(str.c_str()[0]))
3592     return Player::Type(atoi(str.c_str()));
3593   if (str == "Player::HUMAN") return Player::HUMAN;
3594   else if (str == "Player::AI_FAST") return Player::AI_FAST;
3595   else if (str == "Player::AI_DUMMY") return Player::AI_DUMMY;
3596   else if (str == "Player::AI_SMART") return Player::AI_SMART;
3597   else if (str == "Player::NETWORKED") return Player::NETWORKED;
3598   return Player::HUMAN;
3599 }
3600 
hasAlreadyInitializedTurn() const3601 bool Player::hasAlreadyInitializedTurn() const
3602 {
3603   for (auto it: d_actions)
3604     if (it->getType() == Action::INIT_TURN)
3605       return true;
3606   return false;
3607 }
3608 
hasAlreadyCollectedTaxesAndPaidUpkeep() const3609 bool Player::hasAlreadyCollectedTaxesAndPaidUpkeep() const
3610 {
3611   for (auto it: d_actions)
3612     if (it->getType() == Action::COLLECT_TAXES_AND_PAY_UPKEEP)
3613       return true;
3614   return false;
3615 }
3616 
hasAlreadyEndedTurn() const3617 bool Player::hasAlreadyEndedTurn() const
3618 {
3619   for (auto it: d_actions)
3620     if (it->getType() == Action::END_TURN)
3621       return true;
3622   return false;
3623 }
3624 
countEndTurnHistoryEntries() const3625 guint32 Player::countEndTurnHistoryEntries() const
3626 {
3627   guint32 count = 0;
3628   for (std::list<History*>::const_iterator it = d_history.begin();
3629        it != d_history.end(); it++)
3630     {
3631       if ((*it)->getType() == History::END_TURN)
3632 	count++;
3633     }
3634   return count;
3635 }
3636 
searchedRuin(Ruin * r) const3637 bool Player::searchedRuin(Ruin *r) const
3638 {
3639   if (!r)
3640     return false;
3641   for (std::list<History*>::const_iterator it = d_history.begin();
3642        it != d_history.end(); it++)
3643     {
3644       if ((*it)->getType() == History::HERO_RUIN_EXPLORED)
3645 	{
3646 	  History_HeroRuinExplored *event =
3647             dynamic_cast<History_HeroRuinExplored*>(*it);
3648 	  if (event->getRuinId() == r->getId())
3649 	    return true;
3650 	}
3651     }
3652   return false;
3653 }
3654 
conqueredCity(City * c,guint32 & turns_ago) const3655 bool Player::conqueredCity(City *c, guint32 &turns_ago) const
3656 {
3657   if (!c)
3658     return false;
3659   for (std::list<History*>::const_reverse_iterator it = d_history.rbegin();
3660        it != d_history.rend(); it++)
3661     {
3662       if ((*it)->getType() == History::CITY_WON)
3663 	{
3664 	  History_CityWon *event = dynamic_cast<History_CityWon*>(*it);
3665 	  if (event->getCityId() == c->getId())
3666 	    return true;
3667 	}
3668       else if ((*it)->getType() == History::START_TURN)
3669         turns_ago++;
3670 
3671     }
3672   return false;
3673 }
3674 
getStackTrack(Stack * s) const3675 std::list<Vector<int> > Player::getStackTrack(Stack *s) const
3676 {
3677   std::list<Vector<int> > points;
3678   Vector<int> delta = Vector<int>(0,0);
3679   for (auto it: d_actions)
3680     {
3681       if (it->getType() == Action::STACK_MOVE)
3682 	{
3683 	  Action_Move *action = dynamic_cast<Action_Move*>(it);
3684 	  if (action->getStackId() == s->getId())
3685 	    {
3686 	      if (points.size() == 0)
3687 		delta = action->getPositionDelta();
3688 	      points.push_back(action->getEndingPosition());
3689 	    }
3690 	}
3691     }
3692   if (points.size() >= 1)
3693     {
3694       Vector<int> pos = points.front() - delta;
3695       if (pos != points.front())
3696 	points.push_front(pos);
3697     }
3698   return points;
3699 }
3700 
getHistoryForCityId(guint32 id) const3701 std::list<History *>Player::getHistoryForCityId(guint32 id) const
3702 {
3703   std::list<History*> events;
3704   std::list<History*>::const_iterator pit;
3705   for (pit = d_history.begin(); pit != d_history.end(); pit++)
3706     {
3707       switch ((*pit)->getType())
3708 	{
3709 	case History::START_TURN:
3710 	    {
3711 	      events.push_back(*pit);
3712 	      break;
3713 	    }
3714 	case History::CITY_WON:
3715 	    {
3716 	      History_CityWon *event;
3717 	      event = dynamic_cast<History_CityWon*>(*pit);
3718 	      if (event->getCityId() == id)
3719 		events.push_back(*pit);
3720 	      break;
3721 	    }
3722 	case History::CITY_RAZED:
3723 	    {
3724 	      History_CityRazed *event;
3725 	      event = dynamic_cast<History_CityRazed*>(*pit);
3726 	      if (event->getCityId() == id)
3727 		events.push_back(*pit);
3728 	      break;
3729 	    }
3730 	default:
3731 	  break;
3732 	}
3733     }
3734   return events;
3735 }
3736 
getHistoryForHeroId(guint32 id) const3737 std::list<History *>Player::getHistoryForHeroId(guint32 id) const
3738 {
3739   Glib::ustring hero_name = "";
3740   std::list<History*> events;
3741   std::list<History*>::const_iterator pit;
3742   for (pit = d_history.begin(); pit != d_history.end(); pit++)
3743     {
3744       switch ((*pit)->getType())
3745 	{
3746 	case History::HERO_EMERGES:
3747 	    {
3748 	      History_HeroEmerges *event;
3749 	      event = dynamic_cast<History_HeroEmerges *>(*pit);
3750 	      if (event->getHeroId() == id)
3751 		{
3752 		  hero_name = event->getHeroName();
3753 		  events.push_back(*pit);
3754 		}
3755 	      break;
3756 	    }
3757 	case History::FOUND_SAGE:
3758 	    {
3759 	      History_FoundSage *event;
3760 	      event = dynamic_cast<History_FoundSage*>(*pit);
3761 	      if (event->getHeroName() == hero_name)
3762 		events.push_back(*pit);
3763 	      break;
3764 	    }
3765 	case History::HERO_QUEST_STARTED:
3766 	    {
3767 	      History_HeroQuestStarted *event;
3768 	      event = dynamic_cast<History_HeroQuestStarted*>(*pit);
3769 	      if (event->getHeroName() == hero_name)
3770 		events.push_back(*pit);
3771 	      break;
3772 	    }
3773 	case History::HERO_QUEST_COMPLETED:
3774 	    {
3775 	      History_HeroQuestCompleted *event;
3776 	      event = dynamic_cast<History_HeroQuestCompleted*>(*pit);
3777 	      if (event->getHeroName() == hero_name)
3778 		events.push_back(*pit);
3779 	      break;
3780 	    }
3781 	case History::HERO_KILLED_IN_CITY:
3782 	    {
3783 	      History_HeroKilledInCity *event;
3784 	      event = dynamic_cast<History_HeroKilledInCity*>(*pit);
3785 	      if (event->getHeroName() == hero_name)
3786 		events.push_back(*pit);
3787 	      break;
3788 	    }
3789 	case History::HERO_KILLED_IN_BATTLE:
3790 	    {
3791 	      History_HeroKilledInBattle *event;
3792 	      event = dynamic_cast<History_HeroKilledInBattle*>(*pit);
3793 	      if (event->getHeroName() == hero_name)
3794 		events.push_back(*pit);
3795 	      break;
3796 	    }
3797 	case History::HERO_KILLED_SEARCHING:
3798 	    {
3799 	      History_HeroKilledSearching*event;
3800 	      event = dynamic_cast<History_HeroKilledSearching*>(*pit);
3801 	      if (event->getHeroName() == hero_name)
3802 		events.push_back(*pit);
3803 	      break;
3804 	    }
3805 	case History::HERO_CITY_WON:
3806 	    {
3807 	      History_HeroCityWon *event;
3808 	      event = dynamic_cast<History_HeroCityWon*>(*pit);
3809 	      if (event->getHeroName() == hero_name)
3810 		events.push_back(*pit);
3811 	      break;
3812 	    }
3813 	case History::HERO_FINDS_ALLIES:
3814 	    {
3815 	      History_HeroFindsAllies *event;
3816 	      event = dynamic_cast<History_HeroFindsAllies*>(*pit);
3817 	      if (event->getHeroName() == hero_name)
3818 		events.push_back(*pit);
3819 	      break;
3820 	    }
3821 	default:
3822 	  break;
3823 	}
3824     }
3825   return events;
3826 }
3827 
setSurrendered(bool surr)3828 void Player::setSurrendered(bool surr)
3829 {
3830   surrendered = surr;
3831 }
3832 
getHeroes() const3833 std::list<Hero*> Player::getHeroes() const
3834 {
3835   return d_stacklist->getHeroes();
3836 }
3837 
countArmies() const3838 guint32 Player::countArmies() const
3839 {
3840   return d_stacklist->countArmies();
3841 }
3842 
getActivestack() const3843 Stack * Player::getActivestack() const
3844 {
3845   return d_stacklist->getActivestack();
3846 }
3847 
setActivestack(Stack * s)3848 void Player::setActivestack(Stack *s)
3849 {
3850   d_stacklist->setActivestack(s);
3851 }
3852 
getPositionOfArmyById(guint32 id) const3853 Vector<int> Player::getPositionOfArmyById(guint32 id) const
3854 {
3855   return d_stacklist->getPosition(id);
3856 }
3857 
immobilize()3858 void Player::immobilize()
3859 {
3860   d_stacklist->drainAllMovement();
3861 }
3862 
clearStacklist()3863 void Player::clearStacklist()
3864 {
3865   d_stacklist->flClear();
3866 }
3867 
clearFogMap()3868 void Player::clearFogMap()
3869 {
3870   d_fogmap->fill(FogMap::OPEN);
3871 }
3872 
getActionsThisTurn(int type) const3873 std::list<Action *> Player::getActionsThisTurn(int type) const
3874 {
3875   std::list<Action *> actions;
3876   for (auto it: d_actions)
3877     if (it->getType() == Action::Type(type))
3878       actions.push_back(it);
3879   return actions;
3880 }
3881 
getMovesThisTurn() const3882 std::list<Action *> Player::getMovesThisTurn() const
3883 {
3884   return getActionsThisTurn(Action::STACK_MOVE);
3885 }
3886 
countDestituteCitiesThisTurn() const3887 int Player::countDestituteCitiesThisTurn() const
3888 {
3889   return getActionsThisTurn(Action::CITY_DESTITUTE).size();
3890 }
3891 
AI_getQuestDestination(Quest * quest,Stack * stack) const3892 Vector<int> Player::AI_getQuestDestination(Quest *quest, Stack *stack) const
3893 {
3894   Vector<int> dest = Vector<int>(-1,-1);
3895   switch (quest->getType())
3896     {
3897     case Quest::KILLHERO:
3898         {
3899           QuestKillHero *q = dynamic_cast<QuestKillHero*>(quest);
3900           guint32 hero_id = q->getVictim();
3901           Stack *enemy = NULL;
3902           for (auto it: *Playerlist::getInstance())
3903             {
3904               if (it == this)
3905                 continue;
3906               enemy = it->getStacklist()->getArmyStackById(hero_id);
3907               if(enemy)
3908                 break;
3909             }
3910           if (enemy)
3911             dest = enemy->getPos();
3912 
3913         }
3914       break;
3915     case Quest::KILLARMYTYPE:
3916         {
3917           QuestEnemyArmytype *q = dynamic_cast<QuestEnemyArmytype*>(quest);
3918           guint32 army_type = q->getArmytypeToKill();
3919           std::vector<Stack*> s =
3920             GameMap::getNearbyEnemyStacks(stack->getPos(), GameMap::getWidth());
3921           for (std::vector<Stack*>::iterator i = s.begin(); i != s.end(); i++)
3922             {
3923               if ((*i)->hasArmyType(army_type) == true)
3924                 {
3925                   dest = (*i)->getPos();
3926                   break;
3927                 }
3928             }
3929         }
3930       break;
3931     case Quest::KILLARMIES:
3932         {
3933           QuestEnemyArmies *q = dynamic_cast<QuestEnemyArmies*>(quest);
3934           auto enemy = Playerlist::getInstance()->getPlayer(q->getVictimPlayerId());
3935           auto s = GameMap::getNearbyEnemyStacks(stack->getPos(), GameMap::getWidth());
3936           for (std::vector<Stack*>::iterator i = s.begin(); i != s.end(); i++)
3937             {
3938               if ((*i)->getOwner() != enemy)
3939                 continue;
3940               dest = (*i)->getPos();
3941             }
3942         }
3943       break;
3944 
3945     case Quest::PILLAGEGOLD:
3946     case Quest::CITYSACK:
3947     case Quest::CITYRAZE:
3948     case Quest::CITYOCCUPY:
3949       //attack the nearest enemy city.
3950         {
3951           City *c = Citylist::getInstance()->getClosestEnemyCity(stack);
3952           if (c)
3953             dest = c->getNearestPos(stack->getPos());
3954         }
3955       break;
3956     }
3957   return dest;
3958 }
3959 
AI_invadeCityQuestPreference(City * c,CityDefeatedAction & action) const3960 bool Player::AI_invadeCityQuestPreference(City *c, CityDefeatedAction &action) const
3961 {
3962   bool found = false;
3963   std::vector<Quest*> q = QuestsManager::getInstance()->getPlayerQuests(this);
3964   for (std::vector<Quest*>::iterator i = q.begin(); i != q.end(); i++)
3965     {
3966       if (*i == NULL)
3967         continue;
3968       switch ((*i)->getType())
3969         {
3970         case Quest::CITYOCCUPY:
3971             {
3972               QuestCityOccupy* qu = dynamic_cast<QuestCityOccupy*>(*i);
3973               if (qu->getCityId() == c->getId())
3974                 {
3975                   action = CITY_DEFEATED_OCCUPY;
3976                   found = true;
3977                 }
3978             }
3979           break;
3980         case Quest::CITYSACK:
3981             {
3982               QuestCitySack * qu = dynamic_cast<QuestCitySack*>(*i);
3983               if (qu->getCityId() == c->getId())
3984                 {
3985                   action = CITY_DEFEATED_SACK;
3986                   found = true;
3987                 }
3988             }
3989           break;
3990         case Quest::CITYRAZE:
3991             {
3992               QuestCityRaze* qu = dynamic_cast<QuestCityRaze*>(*i);
3993               if (qu->getCityId() == c->getId())
3994                 {
3995                   action = CITY_DEFEATED_RAZE;
3996                   found = true;
3997                 }
3998             }
3999           break;
4000         case Quest::PILLAGEGOLD:
4001           action = CITY_DEFEATED_SACK;
4002           found = true;
4003           break;
4004         }
4005     }
4006   return found;
4007 }
4008 
4009 /*
4010  *
4011  * what are the chances of a hero showing up?
4012  *
4013  * 1 in 6 if you have enough gold, where "enough gold" is...
4014  *
4015  * ... 1500 if the player already has a hero, then:  1500 is generally
4016  * enough to buy all the heroes.  I forget the exact distribution of
4017  * hero prices but memory says from 1000 to 1500.  (But, if you don't
4018  * have 1500 gold, and the price is less, you still get the offer...
4019  * So, calculate price, compare to available gold, then decided whether
4020  * or not to offer...)
4021  *
4022  * ...500 if all your heroes are dead: then prices are cut by about
4023  * a factor of 3.
4024  */
maybeRecruitHero()4025 bool Player::maybeRecruitHero ()
4026 {
4027   bool accepted = false;
4028 
4029   City *city = NULL;
4030   int gold_needed = 0;
4031   if (Citylist::getInstance()->countCities(this) == 0)
4032     return false;
4033   //give the player a hero if it's the first round.
4034   //otherwise we get a hero based on chance
4035   //a hero costs a random number of gold pieces
4036   if (GameScenarioOptions::s_round == 1 && getHeroes().size() == 0)
4037     gold_needed = 0;
4038   else
4039     {
4040       bool exists = false;
4041       if (getHeroes().size() > 0)
4042         exists = true;
4043 
4044       gold_needed = (Rnd::rand() % 500) + 1000;
4045       if (exists == false)
4046 	gold_needed /= 2;
4047     }
4048 
4049   if ((((Rnd::rand() % 6) == 0 && gold_needed < getGold()) || gold_needed == 0))
4050     {
4051       HeroProto *heroproto =
4052         HeroTemplates::getInstance()->getRandomHero(getId());
4053       if (gold_needed == 0)
4054 	{
4055 	  //we do it this way because maybe quickstart is on.
4056           city = Citylist::getInstance()->getCapitalCity(this);
4057           if (!city || city->isBurnt() == true)
4058 	    city = getFirstCity();
4059 	}
4060       else
4061         city = Citylist::getInstance()->getRandomCityForHero(this);
4062 
4063       if (srecruitingHero.empty())
4064         accepted = true;
4065       else if (city)
4066         accepted = srecruitingHero.emit(heroproto, city, gold_needed);
4067 
4068       if (accepted) {
4069         /* now maybe add a few allies */
4070         int alliesCount;
4071         if (gold_needed > 1300)
4072           alliesCount = 3;
4073         else if (gold_needed > 1000)
4074           alliesCount = 2;
4075         else if (gold_needed > 800)
4076           alliesCount = 1;
4077         else
4078           alliesCount = 0;
4079 
4080         const ArmyProto *ally = 0;
4081         if (alliesCount > 0)
4082         {
4083           ally = Reward_Allies::randomArmyAlly();
4084           if (!ally)
4085             alliesCount = 0;
4086         }
4087 
4088         StackReflist *stacks = new StackReflist();
4089         recruitHero(heroproto, city, gold_needed, alliesCount, ally, stacks);
4090         delete stacks;
4091       }
4092     }
4093   return accepted;
4094 }
4095 
getStacksWithItems() const4096 std::list<Stack*> Player::getStacksWithItems() const
4097 {
4098   return getStacklist()->getStacksWithItems();
4099 }
4100 
setPathOfStackToPreviousDestination(Stack * stack)4101 bool Player::setPathOfStackToPreviousDestination(Stack *stack)
4102 {
4103   std::list<Action*>moves = getMovesThisTurn();
4104   if (moves.size() > 0)
4105     {
4106       Vector<int> dest = Vector<int>(-1,-1);
4107       std::list<Action*>::const_reverse_iterator it =
4108         moves.rbegin();
4109       for (;it != moves.rend(); it++)
4110         {
4111           if ((*it)->getType() != Action::STACK_MOVE)
4112             continue;
4113           Action_Move *move = dynamic_cast<Action_Move*>(*it);
4114           guint32 id = move->getStackId();
4115           if (id == stack->getId())
4116             continue;
4117           Stack *prev = d_stacklist->getStackById(id);
4118           if (!prev)
4119             dest = move->getEndingPosition();
4120           else
4121             {
4122               dest = prev->getLastPointInPath();
4123               if (dest == Vector<int>(-1,-1))
4124                 dest = move->getEndingPosition();
4125             }
4126           break;
4127         }
4128       if (dest != Vector<int>(-1,-1))
4129         {
4130           PathCalculator *path_calculator = new PathCalculator(stack);
4131           guint32 total_moves = 0, turns = 0, left = 0;
4132           Path *new_path = path_calculator->calculate(dest, total_moves, turns,
4133                                                       left, true);
4134           if (new_path->size())
4135             stack->setPath(*new_path);
4136           delete new_path;
4137           delete path_calculator;
4138 
4139           return true;
4140         }
4141     }
4142   return false;
4143 }
4144 
doHeroUseItem(Hero * hero,Item * item,Player * victim,City * friendly_city,City * enemy_city,City * neutral_city,City * city)4145 bool Player::doHeroUseItem(Hero *hero, Item *item, Player *victim,
4146                            City *friendly_city, City *enemy_city, City *neutral_city, City *city)
4147 {
4148   if (item->getBonus() & ItemProto::STEAL_GOLD)
4149     {
4150       assert (victim != NULL);
4151       double percent = item->getPercentGoldToSteal();
4152       if (percent > 100)
4153         percent = 100;
4154       else if (percent < 0)
4155         percent = 0;
4156       int gold = victim->getGold() * (percent / 100.0);
4157       if (gold > 0)
4158         {
4159           victim->withdrawGold(gold);
4160           addGold(gold);
4161           stole_gold.emit(victim, gold);
4162         }
4163     }
4164   if (item->getBonus() & ItemProto::SINK_SHIPS)
4165     {
4166       assert (victim != NULL);
4167       std::list<Stack*> sunk = victim->getStacklist()->killArmyUnitsInBoats();
4168       std::list<History*> history;
4169       guint32 num_armies = removeDeadArmies(sunk, history);
4170       sunk_ships.emit(victim, num_armies);
4171     }
4172   if (item->getBonus() & ItemProto::PICK_UP_BAGS)
4173     {
4174       guint32 num_bags = 0;
4175       std::list<MapBackpack*> bags = GameMap::getInstance()->getBackpacks();
4176       num_bags = bags.size();
4177       std::list<MapBackpack*>::iterator it = bags.begin();
4178       for (; it != bags.end(); it++)
4179         doHeroPickupAllItems(hero, (*it)->getPos());
4180       bags_picked_up.emit(hero, num_bags);
4181     }
4182   if (item->getBonus() & ItemProto::ADD_2MP_STACK)
4183     {
4184       guint32 mp = 2;
4185       Stack *stack = getStacklist()->getArmyStackById(hero->getId());
4186       stack->incrementMoves(mp);
4187       mp_added_to_hero_stack.emit(hero, mp);
4188     }
4189   if (item->getBonus() & ItemProto::BANISH_WORMS)
4190     {
4191       guint32 num_worms_killed = 0;
4192       std::list<History*> history;
4193       for (auto j: *Playerlist::getInstance())
4194         {
4195           std::list<Stack*> affected =
4196             j->getStacklist()->killArmies(item->getArmyTypeToKill());
4197           if (affected.size())
4198             num_worms_killed += removeDeadArmies(affected, history);
4199         }
4200       const ArmyProto *a = Armysetlist::getInstance()->getArmy(Playerlist::getActiveplayer()->getArmyset(), item->getArmyTypeToKill());
4201       worms_killed.emit(hero, a->getName(), num_worms_killed);
4202     }
4203   if (item->getBonus() & ItemProto::BURN_BRIDGE)
4204     {
4205       //am i on a bridge?
4206       Vector<int> pos = d_stacklist->getPosition(hero->getId());
4207       bool burned = GameMap::getInstance()->burnBridge(pos);
4208       if (burned)
4209         bridge_burned.emit(hero);
4210     }
4211   if (item->getBonus() & ItemProto::CAPTURE_KEEPER)
4212     {
4213       Vector<int> pos = d_stacklist->getPosition(hero->getId());
4214       Ruin *ruin = GameMap::getInstance()->getRuin(pos);
4215       if (ruin && ruin->isSearched() == false)
4216         {
4217           if (ruin->getOccupant() && ruin->getOccupant ()->getStack () &&
4218               ruin->getOccupant()->getStack ()->size() > 0)
4219             {
4220               Glib::ustring name = ruin->getOccupant()->getName();
4221               addStack(ruin->getOccupant()->getStack ());
4222               ruin->clearOccupant();
4223               keeper_captured.emit(hero, ruin, name);
4224             }
4225         }
4226     }
4227   if (item->getBonus() & ItemProto::SUMMON_MONSTER)
4228     {
4229       Vector<int> pos = d_stacklist->getPosition(hero->getId());
4230       Maptile::Building building = GameMap::getInstance()->getBuilding(pos);
4231       if (building == item->getBuildingTypeToSummonOn() ||
4232           item->getBuildingTypeToSummonOn() == 0)
4233         {
4234           Stack *stack = getStacklist()->getArmyStackById(hero->getId());
4235           StackReflist *stacks = new StackReflist();
4236           //okay we're going to add some allies now.
4237           const ArmyProto *a = Armysetlist::getInstance()->getArmy(Playerlist::getActiveplayer()->getArmyset(), item->getArmyTypeToSummon());
4238           Reward *reward = new Reward_Allies(a, 1);
4239           giveReward(stack, reward, stacks, false);
4240           delete reward;
4241           delete stacks;
4242           monster_summoned.emit(hero, a->getName());
4243         }
4244     }
4245   if (item->getBonus() & ItemProto::DISEASE_CITY)
4246     {
4247       if (enemy_city)
4248         {
4249           std::list<History*> history;
4250           std::list<Stack*> affected =
4251             enemy_city->diseaseDefenders(item->getPercentArmiesToKill());
4252           guint32 num_armies_killed = removeDeadArmies(affected, history);
4253           city_diseased.emit(hero, enemy_city->getName(), num_armies_killed);
4254         }
4255     }
4256   if (item->getBonus() & ItemProto::RAISE_DEFENDERS)
4257     {
4258       if (friendly_city)
4259         {
4260           //okay we're going to add some allies now.
4261           const ArmyProto *a = Armysetlist::getInstance()->getArmy(Playerlist::getActiveplayer()->getArmyset(), item->getArmyTypeToRaise());
4262           GameMap::getInstance()->addArmies(a, item->getNumberOfArmiesToRaise(),
4263                                             friendly_city->getPos());
4264           city_defended.emit(hero, friendly_city->getName(), a->getName(),
4265                              item->getNumberOfArmiesToRaise());
4266         }
4267     }
4268   if (item->getBonus() & ItemProto::PERSUADE_NEUTRALS)
4269     {
4270       if (neutral_city)
4271         {
4272           Stack *stack = getStacklist()->getArmyStackById(hero->getId());
4273           neutral_city->persuadeDefenders(this);
4274           takeCityInPossession(neutral_city);
4275           QuestsManager::getInstance()->cityOccupied(neutral_city, stack);
4276           city_persuaded.emit(hero, neutral_city->getName(),
4277                               neutral_city->countDefenders());
4278         }
4279     }
4280   if (item->getBonus() & ItemProto::TELEPORT_TO_CITY)
4281     {
4282       if (city)
4283         {
4284           Stack *s = getStacklist()->getArmyStackById(hero->getId());
4285           for (Stack::iterator i = s->begin(); i != s->end(); ++i)
4286             {
4287               if (city->getOwner() != s->getOwner())
4288                 GameMap::getInstance()->addArmyAtPos(city->getPos(), *i);
4289               else
4290                 GameMap::getInstance()->addArmy(city->getPos(), *i);
4291             }
4292           s->clear();
4293           deleteStack(s);
4294           //where do we teleport to?
4295           stack_teleported.emit(hero, city->getName());
4296           supdatingStack.emit(getStacklist()->getArmyStackById(hero->getId()));
4297         }
4298     }
4299 
4300   hero->getBackpack()->useItem(item);
4301   supdatingStack.emit(0);
4302   return true;
4303 }
4304 
heroUseItem(Hero * hero,Item * item,Player * victim,City * friendly_city,City * enemy_city,City * neutral_city,City * city)4305 bool Player::heroUseItem(Hero *hero, Item *item, Player *victim,
4306                          City *friendly_city, City *enemy_city,
4307                          City *neutral_city, City *city)
4308 {
4309   if (doHeroUseItem(hero, item, victim, friendly_city, enemy_city,
4310                     neutral_city, city))
4311     {
4312       addAction(new Action_UseItem(hero, item, victim, friendly_city,
4313                                    enemy_city, neutral_city, city));
4314       addHistory (new History_HeroUseItem(hero, item, victim, friendly_city,
4315                                           enemy_city, neutral_city, city));
4316       return true;
4317     }
4318   return false;
4319 }
4320 
getUsableItems() const4321 std::list<Item*> Player::getUsableItems() const
4322 {
4323   return d_stacklist->getUsableItems();
4324 }
4325 
hasUsableItem() const4326 bool Player::hasUsableItem() const
4327 {
4328   return d_stacklist->hasUsableItem();
4329 }
4330 
getItemHolder(Item * item,Stack ** stack,Hero ** hero) const4331 bool Player::getItemHolder(Item *item, Stack **stack, Hero **hero) const
4332 {
4333   return d_stacklist->getItemHolder(item, stack, hero);
4334 }
4335 
tallyDeadArmyTriumphs(std::list<Stack * > & stacks)4336 void Player::tallyDeadArmyTriumphs(std::list<Stack*> &stacks)
4337 {
4338   std::list<Stack*>::iterator it;
4339   for (it = stacks.begin(); it != stacks.end(); it++)
4340     {
4341       for (Stack::iterator sit = (*it)->begin(); sit != (*it)->end(); sit++)
4342         {
4343           if ((*sit)->getHP() > 0)
4344             continue;
4345           //Tally up the triumphs
4346           Player *enemy = (*sit)->getOwner();
4347           if ((*sit)->getAwardable()) //hey a special ally died
4348             d_triumphs->tallyTriumph(enemy, Triumphs::TALLY_SPECIAL);
4349           else if ((*sit)->isHero())
4350             {
4351               d_triumphs->tallyTriumph(enemy, Triumphs::TALLY_HERO);
4352               Hero *hero = dynamic_cast<Hero*>((*sit));
4353               guint32 count = hero->getBackpack()->countPlantableItems();
4354               for (guint32 i = 0; i < count; i++)
4355                 d_triumphs->tallyTriumph(enemy, Triumphs::TALLY_FLAG);
4356             }
4357           else if ((*sit)->getStat(Army::SHIP, false)) //hey it was on a boat
4358             d_triumphs->tallyTriumph(enemy, Triumphs::TALLY_SHIP);
4359           else if ((*sit)->isHero() == false)
4360             d_triumphs->tallyTriumph(enemy, Triumphs::TALLY_NORMAL);
4361         }
4362     }
4363   return;
4364 }
4365 
handleDeadHero(Hero * h,Maptile * tile,Vector<int> pos)4366 History* Player::handleDeadHero(Hero *h, Maptile *tile, Vector<int> pos)
4367 {
4368   if (tile->getBuilding() == Maptile::RUIN)
4369     return new History_HeroKilledSearching(h);
4370   else if (tile->getBuilding() == Maptile::CITY)
4371     {
4372       City* c = GameMap::getCity(pos);
4373       return new History_HeroKilledInCity(h, c);
4374     }
4375   else //somewhere else
4376     return new History_HeroKilledInBattle(h);
4377   return NULL;
4378 }
4379 
handleDeadHeroes(std::list<Stack * > & stacks,std::list<History * > & history)4380 void Player::handleDeadHeroes(std::list<Stack*> &stacks, std::list<History*> &history)
4381 {
4382   std::list<Stack*>::iterator it;
4383   for (it = stacks.begin(); it != stacks.end(); it++)
4384     {
4385       for (Stack::iterator sit = (*it)->begin(); sit != (*it)->end(); sit++)
4386         {
4387           if ((*sit)->getHP() > 0)
4388             continue;
4389           if ((*sit)->isHero() == false)
4390             continue;
4391           //one of our heroes died
4392           //drop hero's stuff
4393           //now record the details of the death
4394 
4395           bool splash = false;
4396           doHeroDropAllItems (static_cast<Hero*>(*sit), (*it)->getPos(),
4397                               splash);
4398           Maptile *tile = GameMap::getInstance()->getTile((*it)->getPos());
4399 
4400           History *item = handleDeadHero (static_cast<Hero*>(*sit), tile,
4401                                           (*it)->getPos());
4402           if (item)
4403             history.push_back(item);
4404         }
4405     }
4406   return;
4407 }
4408 
handleDeadArmiesForQuests(std::list<Stack * > & stacks,std::vector<guint32> & culprits)4409 void Player::handleDeadArmiesForQuests(std::list<Stack*> &stacks,
4410                                        std::vector<guint32> &culprits)
4411 {
4412   std::list<Stack*>::iterator it;
4413   for (it = stacks.begin(); it != stacks.end(); it++)
4414     {
4415       if ((*it)->getOwner() == this)
4416         continue;
4417       for (Stack::iterator sit = (*it)->begin(); sit != (*it)->end(); sit++)
4418         {
4419           if ((*sit)->getHP() == 0)
4420             QuestsManager::getInstance()->armyDied(*sit, culprits);
4421         }
4422     }
4423   return;
4424 }
4425 
countXPFromDeadArmies(std::list<Stack * > & stacks)4426 double Player::countXPFromDeadArmies(std::list<Stack*>& stacks)
4427 {
4428   double total = 0.0;
4429   std::list<Stack*>::iterator it;
4430   for (it = stacks.begin(); it != stacks.end(); it++)
4431     {
4432       if ((*it)->getOwner() == this)
4433         continue;
4434       for (Stack::iterator sit = (*it)->begin(); sit != (*it)->end(); sit++)
4435         {
4436           if ((*sit)->getHP() > 0)
4437             continue;
4438 
4439           //Add the XP bonus to the total of the battle;
4440           total += (*sit)->getXpReward();
4441         }
4442     }
4443   return total;
4444 }
4445 
doStackSort(Stack * s,std::list<guint32> army_ids)4446 void Player::doStackSort(Stack *s, std::list<guint32> army_ids)
4447 {
4448   return s->sortByIds(army_ids);
4449 }
4450 
doStacksReset()4451 void Player::doStacksReset()
4452 {
4453   getStacklist()->resetStacks();
4454 }
4455 
stacksReset()4456 void Player::stacksReset()
4457 {
4458   doStacksReset();
4459   addAction(new Action_ResetStacks(this));
4460 }
4461 
doRuinsReset()4462 void Player::doRuinsReset()
4463 {
4464   if (this != Playerlist::getInstance()->getNeutral())
4465     return;
4466   for (auto it: *Ruinlist::getInstance())
4467     {
4468       Keeper* keeper = it->getOccupant();
4469       if (keeper)
4470         {
4471           if (keeper->getStack ())
4472             keeper->getStack ()->reset();
4473         }
4474     }
4475 }
4476 
ruinsReset()4477 void Player::ruinsReset()
4478 {
4479   doRuinsReset();
4480   addAction(new Action_ResetRuins());
4481 }
4482 
doCollectTaxesAndPayUpkeep()4483 void Player::doCollectTaxesAndPayUpkeep()
4484 {
4485   //collect monies from cities
4486   Citylist::getInstance()->collectTaxes(this);
4487 
4488   //factor in the gold-per-city items that heroes may hold
4489   guint32 num_cities = Citylist::getInstance()->countCities(this);
4490   getStacklist()->collectTaxes(this, num_cities);
4491 
4492   //pay for existing armies
4493   getStacklist()->payUpkeep(this);
4494 }
4495 
collectTaxesAndPayUpkeep()4496 void Player::collectTaxesAndPayUpkeep()
4497 {
4498   if (hasAlreadyCollectedTaxesAndPaidUpkeep())
4499     return;
4500   int prev_gold = getGold();
4501   doCollectTaxesAndPayUpkeep();
4502   Action_CollectTaxesAndPayUpkeep *a =
4503     new Action_CollectTaxesAndPayUpkeep (prev_gold, getGold());
4504   addAction(a);
4505 }
4506 
doStackDefend(Stack * s)4507 void Player::doStackDefend(Stack *s)
4508 {
4509   s->setDefending(true);
4510 }
4511 
stackDefend(Stack * s)4512 void Player::stackDefend(Stack *s)
4513 {
4514   doStackDefend(s);
4515   addAction(new Action_DefendStack(s));
4516 }
4517 
doStackUndefend(Stack * s)4518 void Player::doStackUndefend(Stack *s)
4519 {
4520   s->setDefending(false);
4521 }
4522 
stackUndefend(Stack * s)4523 void Player::stackUndefend(Stack *s)
4524 {
4525   doStackUndefend(s);
4526   addAction(new Action_UndefendStack(s));
4527 }
4528 
doStackPark(Stack * s)4529 void Player::doStackPark(Stack *s)
4530 {
4531   s->setParked(true);
4532 }
4533 
stackPark(Stack * s)4534 void Player::stackPark(Stack *s)
4535 {
4536   doStackPark(s);
4537   addAction(new Action_ParkStack(s));
4538 }
4539 
parkAllStacks()4540 void Player::parkAllStacks()
4541 {
4542   for (auto s : *getStacklist())
4543     {
4544       if (s->getParked() == false)
4545         stackPark (s);
4546     }
4547 }
4548 
doStackUnpark(Stack * s)4549 void Player::doStackUnpark(Stack *s)
4550 {
4551   s->setParked(false);
4552 }
4553 
stackUnpark(Stack * s)4554 void Player::stackUnpark(Stack *s)
4555 {
4556   doStackUnpark(s);
4557   addAction(new Action_UnparkStack(s));
4558 }
4559 
doStackSelect(Stack * s)4560 void Player::doStackSelect(Stack *s)
4561 {
4562   d_stacklist->setActivestack(s);
4563 }
4564 
stackSelect(Stack * s)4565 void Player::stackSelect(Stack *s)
4566 {
4567   doStackSelect(s);
4568   addAction(new Action_SelectStack(s));
4569 }
4570 
doStackDeselect()4571 void Player::doStackDeselect ()
4572 {
4573   d_stacklist->setActivestack(0);
4574 }
4575 
stackDeselect()4576 void Player::stackDeselect ()
4577 {
4578   doStackDeselect();
4579   addAction(new Action_DeselectStack());
4580 }
4581 
reportEndOfRound(guint32 score)4582 void Player::reportEndOfRound(guint32 score)
4583 {
4584   addHistory(new History_Score(score));
4585   addHistory(new History_GoldTotal(d_gold));
4586 }
4587 
reportEndOfTurn()4588 void Player::reportEndOfTurn()
4589 {
4590   addHistory(new History_EndTurn);
4591   addAction(new Action_EndTurn);
4592 }
4593 
getFirstCity() const4594 City *Player::getFirstCity() const
4595 {
4596   std::list<History*>::const_iterator it;
4597   for (it = d_history.begin(); it != d_history.end(); it++)
4598     {
4599       if ((*it)->getType() == History::CITY_WON)
4600         {
4601           History_CityWon *h = dynamic_cast<History_CityWon*>(*it);
4602           City *c = Citylist::getInstance()->getById(h->getCityId());
4603           if (c->isBurnt() == false && c->getOwner() == this)
4604             return c;
4605         }
4606     }
4607   return NULL;
4608 }
4609 // End of file
4610