initial commit, lordsawar source, slightly modified
[lordsawar] / src / player.cpp
diff --git a/src/player.cpp b/src/player.cpp
new file mode 100644 (file)
index 0000000..0696d69
--- /dev/null
@@ -0,0 +1,3999 @@
+// Copyright (C) 2000, 2001, 2002, 2003 Michael Bartl
+// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Ulf Lorenz
+// Copyright (C) 2004, 2005 Andrea Paternesi
+// Copyright (C) 2004 John Farrell
+// Copyright (C) 2005 Bryan Duff
+// Copyright (C) 2007, 2008, 2009 Ben Asselstine
+// Copyright (C) 2007, 2008 Ole Laursen
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU Library General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
+//  02110-1301, USA.
+
+#include <stdlib.h>
+#include <assert.h>
+#include <algorithm>
+#include <fstream>
+#include <sstream>
+#include <sigc++/functors/mem_fun.h>
+
+#include "player.h"
+#include "playerlist.h"
+#include "stacklist.h"
+#include "citylist.h"
+#include "templelist.h"
+#include "city.h"
+#include "path.h"
+#include "armysetlist.h"
+#include "real_player.h"
+#include "ai_dummy.h"
+#include "ai_fast.h"
+#include "ai_smart.h"
+#include "network_player.h"
+#include "GameMap.h"
+#include "counter.h"
+#include "army.h"
+#include "hero.h"
+#include "heroproto.h"
+#include "herotemplates.h"
+#include "Configuration.h"
+#include "GameScenarioOptions.h"
+#include "action.h"
+#include "network-action.h"
+#include "history.h"
+#include "network-history.h"
+#include "AI_Analysis.h"
+#include "AI_Allocation.h"
+#include "FogMap.h"
+#include "QuestsManager.h"
+#include "signpost.h"
+#include "vectoredunit.h"
+#include "ucompose.hpp"
+#include "armyprodbase.h"
+#include "Triumphs.h"
+#include "Backpack.h"
+#include "MapBackpack.h"
+#include "PathCalculator.h"
+#include "stacktile.h"
+#include "templelist.h"
+#include "temple.h"
+#include "QCityOccupy.h"
+#include "QCitySack.h"
+#include "QCityRaze.h"
+#include "QPillageGold.h"
+#include "Quest.h"
+#include "QKillHero.h"
+#include "QEnemyArmies.h"
+#include "QEnemyArmytype.h"
+#include "callback-enums.h"
+
+using namespace std;
+
+//#define debug(x) {cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<flush<<endl;}
+#define debug(x)
+
+std::string Player::d_tag = "player";
+
+Player::Player(string name, guint32 armyset, Gdk::Color color, int width,
+              int height, Type type, int player_no)
+    :d_color(color), d_name(name), d_armyset(armyset), d_gold(1000),
+    d_dead(false), d_immortal(false), d_type(type), d_upkeep(0), d_income(0),
+    d_observable(true), surrendered(false), abort_requested(false)
+{
+    if (player_no != -1)
+       d_id = player_no;
+    else
+       d_id = fl_counter->getNextId();
+    d_stacklist = new Stacklist();
+    debug("type of " << d_name << " is " << type)
+        
+    d_fogmap = new FogMap(width, height);
+
+    //initial fight order is the order in which the armies appear
+    //in the default.xml file.
+    guint32 size = Armysetlist::getInstance()->getSize(d_armyset);
+    for (unsigned int i = 0; i < size; i++)
+    {
+      d_fight_order.push_back(i);
+    }
+
+    for (unsigned int i = 0 ; i < MAX_PLAYERS; i++)
+    {
+      d_diplomatic_state[i] = AT_PEACE;
+      d_diplomatic_proposal[i] = NO_PROPOSAL;
+      d_diplomatic_score[i] = DIPLOMACY_STARTING_SCORE;
+    }
+    d_diplomatic_rank = 0;
+    d_diplomatic_title = std::string("");
+
+    d_triumphs = new Triumphs();
+}
+
+Player::Player(const Player& player)
+    :d_color(player.d_color), d_name(player.d_name), d_armyset(player.d_armyset),
+    d_gold(player.d_gold), d_dead(player.d_dead), d_immortal(player.d_immortal),
+    d_type(player.d_type), d_id(player.d_id), 
+    d_fight_order(player.d_fight_order), d_upkeep(player.d_upkeep), 
+    d_income(player.d_income), d_observable(player.d_observable),
+    surrendered(player.surrendered),abort_requested(player.abort_requested)
+{
+    // as the other player is propably dumped somehow, we need to deep copy
+    // everything.
+    d_stacklist = new Stacklist();
+    for (Stacklist::iterator it = player.d_stacklist->begin(); 
+        it != player.d_stacklist->end(); it++)
+    {
+        Stack* mine = new Stack(**it);
+        // change the stack's loyalty
+        mine->setPlayer(this);
+        d_stacklist->add(mine);
+    }
+
+    // copy actions
+    std::list<Action*>::const_iterator ait;
+    for (ait = player.d_actions.begin(); ait != player.d_actions.end(); ait++)
+        d_actions.push_back(Action::copy(*ait));
+
+    // copy events
+    std::list<History*>::const_iterator pit;
+    for (pit = player.d_history.begin(); pit != player.d_history.end(); pit++)
+        d_history.push_back(History::copy(*pit));
+
+    // copy fogmap; TBD
+    d_fogmap = new FogMap(*player.getFogMap());
+
+    // copy diplomatic states
+    for (unsigned int i = 0 ; i < MAX_PLAYERS; i++)
+      {
+       d_diplomatic_state[i] = player.d_diplomatic_state[i];
+       d_diplomatic_proposal[i] = player.d_diplomatic_proposal[i];
+       d_diplomatic_score[i] = player.d_diplomatic_score[i];
+      }
+    d_diplomatic_rank = player.d_diplomatic_rank;
+    d_diplomatic_title = player.d_diplomatic_title;
+
+    d_triumphs = new Triumphs(*player.getTriumphs());
+}
+
+Player::Player(XML_Helper* helper)
+    :d_stacklist(0), d_fogmap(0), surrendered(false), abort_requested(false)
+{
+    helper->getData(d_id, "id");
+    helper->getData(d_name, "name");
+    helper->getData(d_gold, "gold");
+    helper->getData(d_dead, "dead");
+    helper->getData(d_immortal, "immortal");
+    std::string type_str;
+    helper->getData(type_str, "type");
+    d_type = playerTypeFromString(type_str);
+    helper->getData(d_upkeep, "upkeep");
+    helper->getData(d_income, "income");
+    helper->getData(d_color, "color");
+    helper->getData(d_armyset, "armyset");
+
+    // Read in Fight Order.  One ranking per army type.
+    std::string fight_order;
+    std::stringstream sfight_order;
+    guint32 val;
+    helper->getData(fight_order, "fight_order");
+    sfight_order.str(fight_order);
+    guint32 size = Armysetlist::getInstance()->getSize(d_armyset);
+    for (unsigned int i = 0; i < size; i++)
+    {
+            sfight_order >> val;
+            d_fight_order.push_back(val);
+    }
+
+    // Read in Diplomatic States.  One state per player.
+    std::string diplomatic_states;
+    std::stringstream sdiplomatic_states;
+    helper->getData(diplomatic_states, "diplomatic_states");
+    sdiplomatic_states.str(diplomatic_states);
+    for (unsigned int i = 0; i < MAX_PLAYERS; i++)
+    {
+            sdiplomatic_states >> val;
+           d_diplomatic_state[i] = DiplomaticState(val);
+    }
+
+    helper->getData(d_diplomatic_rank, "diplomatic_rank");
+    helper->getData(d_diplomatic_title, "diplomatic_title");
+
+    // Read in Diplomatic Proposals.  One proposal per player.
+    std::string diplomatic_proposals;
+    std::stringstream sdiplomatic_proposals;
+    helper->getData(diplomatic_proposals, "diplomatic_proposals");
+    sdiplomatic_proposals.str(diplomatic_proposals);
+    for (unsigned int i = 0; i < MAX_PLAYERS; i++)
+    {
+            sdiplomatic_proposals>> val;
+           d_diplomatic_proposal[i] = DiplomaticProposal(val);
+    }
+
+    // Read in Diplomatic Scores.  One score per player.
+    std::string diplomatic_scores;
+    std::stringstream sdiplomatic_scores;
+    helper->getData(diplomatic_scores, "diplomatic_scores");
+    sdiplomatic_scores.str(diplomatic_scores);
+    for (unsigned int i = 0; i < MAX_PLAYERS; i++)
+    {
+            sdiplomatic_scores >> val;
+           d_diplomatic_score[i] = val;
+    }
+    helper->getData(d_observable, "observable");
+
+    helper->registerTag(Action::d_tag, sigc::mem_fun(this, &Player::load));
+    helper->registerTag(History::d_tag, sigc::mem_fun(this, &Player::load));
+    helper->registerTag(Stacklist::d_tag, sigc::mem_fun(this, &Player::load));
+    helper->registerTag(FogMap::d_tag, sigc::mem_fun(this, &Player::load));
+    helper->registerTag(Triumphs::d_tag, sigc::mem_fun(this, &Player::load));
+
+}
+
+Player::~Player()
+{
+    if (d_stacklist)
+    {
+        //d_stacklist->flClear();
+        delete d_stacklist;
+    }
+    if (d_fogmap)
+        delete d_fogmap;
+
+    clearActionlist();
+    clearHistorylist();
+    d_fight_order.clear();
+}
+
+Player* Player::create(std::string name, guint32 armyset, Gdk::Color color, int width, int height, Type type)
+{
+  switch(type)
+  {
+  case HUMAN:
+    return (new RealPlayer(name, armyset, color, width, height));
+  case AI_FAST:
+    return (new AI_Fast(name, armyset, color, width, height));
+  case AI_DUMMY:
+    return (new AI_Dummy(name, armyset, color, width, height));
+  case AI_SMART:
+    return (new AI_Smart(name, armyset, color, width, height));
+  case NETWORKED:
+    return (new NetworkPlayer(name, armyset, color, width, height));
+  }
+
+  return 0;
+}
+
+Player* Player::create(Player* orig, Type type)
+{
+    switch(type)
+    {
+        case HUMAN:
+            return new RealPlayer(*orig);
+        case AI_FAST:
+            return new AI_Fast(*orig);
+        case AI_DUMMY:
+            return new AI_Dummy(*orig);
+        case AI_SMART:
+            return new AI_Smart(*orig);
+        case NETWORKED:
+            return new NetworkPlayer(*orig);
+    }
+
+    return 0;
+}
+
+void Player::initTurn()
+{
+  clearActionlist();
+  History_StartTurn* item = new History_StartTurn();
+  addHistory(item);
+  Action_InitTurn* action = new Action_InitTurn();
+  addAction(action);
+}
+
+void Player::setColor(Gdk::Color c)
+{
+    d_color = c;
+}
+
+void Player::addGold(int gold)
+{
+    d_gold += gold;
+    schangingStats.emit();
+}
+
+void Player::withdrawGold(int gold)
+{
+    d_gold -= gold;
+    if (d_gold < 0)
+      d_gold = 0; /* bankrupt.  should we start turning off city production? */
+    schangingStats.emit();
+}
+
+std::string Player::getName(bool translate) const
+{
+    if (translate)
+        return __(d_name);
+
+    return d_name;
+}
+
+void Player::dumpActionlist() const
+{
+    for (list<Action*>::const_iterator it = d_actions.begin();
+        it != d_actions.end(); it++)
+    {
+        cerr <<(*it)->dump() << endl;
+    }    
+}
+
+void Player::dumpHistorylist() const
+{
+    for (list<History*>::const_iterator it = d_history.begin();
+        it != d_history.end(); it++)
+    {
+        cerr <<(*it)->dump() << endl;
+    }    
+}
+
+void Player::clearActionlist()
+{
+    for (list<Action*>::iterator it = d_actions.begin();
+        it != d_actions.end(); it++)
+    {
+      delete (*it);
+    }
+    d_actions.clear();
+}
+
+void Player::clearHistorylist()
+{
+    for (list<History*>::iterator it = d_history.begin();
+        it != d_history.end(); it++)
+    {
+        delete (*it);
+    }
+    d_history.clear();
+}
+
+void Player::addStack(Stack* stack)
+{
+    stack->setPlayer(this);
+    d_stacklist->add(stack);
+}
+
+bool Player::deleteStack(Stack* stack)
+{
+  if (isComputer() == true)
+    {
+      AI_Analysis::deleteStack(stack->getId());
+      AI_Allocation::deleteStack(stack);
+    }
+    return d_stacklist->flRemove(stack);
+}
+
+void Player::kill()
+{
+  doKill();
+}
+
+void Player::doKill()
+{
+    if (d_immortal)
+        // ignore it
+        return;
+
+    d_observable = false;
+    History_PlayerVanquished* item;
+    item = new History_PlayerVanquished();
+    addHistory(item);
+
+    d_dead = true;
+    //drop the bags of stuff that the heroes might be carrying
+    std::list<Hero*> h = getHeroes();
+    for (std::list<Hero*>::iterator it = h.begin(); it != h.end(); it++)
+      {
+       Stack *s = d_stacklist->getArmyStackById((*it)->getId());
+       if (s)
+         stackDisband(s);
+      }
+    //get rid of all of the other stacks.
+    d_stacklist->flClear();
+
+    // Since in some cases the player can be killed rather innocently
+    // (using reactions), we also need to clear the player's traces in the
+    // single cities
+    Citylist* cl = Citylist::getInstance();
+    for (Citylist::iterator it = cl->begin(); it != cl->end(); it++)
+        if ((*it)->getOwner() == this && (*it)->isBurnt() == false)
+            Playerlist::getInstance()->getNeutral()->takeCityInPossession(*it);
+
+    d_diplomatic_rank = 0;
+    d_diplomatic_title = std::string("");
+}
+
+bool Player::save(XML_Helper* helper) const
+{
+    bool retval = true;
+
+    retval &= helper->saveData("id", d_id);
+    retval &= helper->saveData("name", d_name);
+    retval &= helper->saveData("color", d_color);
+    retval &= helper->saveData("armyset", d_armyset);
+    retval &= helper->saveData("gold", d_gold);
+    retval &= helper->saveData("dead", d_dead);
+    retval &= helper->saveData("immortal", d_immortal);
+    std::string type_str = playerTypeToString(Player::Type(d_type));
+    retval &= helper->saveData("type", type_str);
+    debug("type of " << d_name << " is " << d_type)
+    retval &= helper->saveData("upkeep", d_upkeep);
+    retval &= helper->saveData("income", d_income);
+
+    // save the fight order, one ranking per army type
+    std::stringstream fight_order;
+    for (std::list<guint32>::const_iterator it = d_fight_order.begin();
+         it != d_fight_order.end(); it++)
+      {
+        fight_order << (*it) << " ";
+      }
+    retval &= helper->saveData("fight_order", fight_order.str());
+
+    // save the diplomatic states, one state per player
+    std::stringstream diplomatic_states;
+    for (unsigned int i = 0; i < MAX_PLAYERS; i++)
+      {
+       diplomatic_states << d_diplomatic_state[i] << " ";
+      }
+    retval &= helper->saveData("diplomatic_states", diplomatic_states.str());
+
+    retval &= helper->saveData("diplomatic_rank", d_diplomatic_rank);
+    retval &= helper->saveData("diplomatic_title", d_diplomatic_title);
+
+    // save the diplomatic proposals, one proposal per player
+    std::stringstream diplomatic_proposals;
+    for (unsigned int i = 0; i < MAX_PLAYERS; i++)
+      {
+       diplomatic_proposals << d_diplomatic_proposal[i] << " ";
+      }
+    retval &= helper->saveData("diplomatic_proposals", 
+                              diplomatic_proposals.str());
+
+    // save the diplomatic scores, one score per player
+    std::stringstream diplomatic_scores;
+    for (unsigned int i = 0; i < MAX_PLAYERS; i++)
+      {
+       diplomatic_scores << d_diplomatic_score[i] << " ";
+      }
+    retval &= helper->saveData("diplomatic_scores", diplomatic_scores.str());
+
+    retval &= helper->saveData("observable", d_observable);
+
+    //save the actionlist
+    for (list<Action*>::const_iterator it = d_actions.begin();
+            it != d_actions.end(); it++)
+        retval &= (*it)->save(helper);
+    
+    //save the pasteventlist
+    for (list<History*>::const_iterator it = d_history.begin();
+            it != d_history.end(); it++)
+        retval &= (*it)->save(helper);
+
+    retval &= d_stacklist->save(helper);
+    retval &= d_fogmap->save(helper);
+    retval &= d_triumphs->save(helper);
+
+    return retval;
+}
+
+Player* Player::loadPlayer(XML_Helper* helper)
+{
+    Type type;
+    std::string type_str;
+    helper->getData(type_str, "type");
+    type = playerTypeFromString(type_str);
+
+    switch (type)
+    {
+        case HUMAN:
+            return new RealPlayer(helper);
+        case AI_FAST:
+            return new AI_Fast(helper);
+        case AI_SMART:
+            return new AI_Smart(helper);
+        case AI_DUMMY:
+            return new AI_Dummy(helper);
+        case NETWORKED:
+            return new NetworkPlayer(helper);
+    }
+
+    return 0;
+}
+
+bool Player::load(string tag, XML_Helper* helper)
+{
+    if (tag == Action::d_tag)
+    {
+        Action* action;
+        action = Action::handle_load(helper);
+        d_actions.push_back(action);
+    }
+    if (tag == History::d_tag)
+    {
+        History* history;
+        history = History::handle_load(helper);
+        d_history.push_back(history);
+    }
+
+    if (tag == Stacklist::d_tag)
+        d_stacklist = new Stacklist(helper);
+
+    if (tag == FogMap::d_tag)
+        d_fogmap = new FogMap(helper);
+
+    if (tag == Triumphs::d_tag)
+       d_triumphs = new Triumphs(helper);
+
+    return true;
+}
+
+void Player::addAction(Action *action)
+{
+  d_actions.push_back(action);
+  NetworkAction *copy = new NetworkAction(action, getId());
+  acting.emit(copy);
+  //free'd in game-server
+}
+
+void Player::addHistory(History *history)
+{
+  d_history.push_back(history);
+  NetworkHistory *copy = new NetworkHistory(history, getId());
+  history_written.emit(copy);
+  //free'd in game-server
+}
+
+
+guint32 Player::getScore() const
+{
+  //go get our last published score in the history
+  guint32 score = 0;
+  std::list<History*>::const_iterator it = d_history.begin();
+  for (; it != d_history.end(); it++)
+    {
+      if ((*it)->getType() == History::SCORE)
+       score = static_cast<History_Score*>(*it)->getScore();
+    }
+  return score;
+}
+
+void Player::calculateUpkeep()
+{
+    d_upkeep = 0;
+    Stacklist *sl = getStacklist();
+    for (Stacklist::iterator i = sl->begin(), iend = sl->end(); i != iend; ++i)
+      d_upkeep += (*i)->getUpkeep();
+}
+
+void Player::calculateIncome()
+{
+    d_income = 0;
+    Citylist *cl = Citylist::getInstance();
+    for (Citylist::iterator i = cl->begin(), iend = cl->end(); i != iend; ++i)
+      {
+       if ((*i)->getOwner() == this)
+         d_income += (*i)->getGold();
+      }
+}
+
+void Player::doSetFightOrder(std::list<guint32> order)
+{
+  d_fight_order = order;
+}
+
+void Player::setFightOrder(std::list<guint32> order) 
+{
+  doSetFightOrder(order);
+  
+  Action_FightOrder * item = new Action_FightOrder();
+  item->fillData(order);
+  addAction(item);
+}
+
+bool Player::doStackSplitArmy(Stack *s, Army *a, Stack *& new_stack)
+{
+  new_stack = s->splitArmy(a);
+  if (new_stack != NULL)
+    {
+      addStack(new_stack);
+      return true;
+    }
+  return false;
+}
+
+
+bool Player::doStackSplitArmies(Stack *stack, std::list<guint32> armies,
+                               Stack *& new_stack)
+{
+  new_stack = stack->splitArmies(armies);
+  if (new_stack != NULL)
+    {
+      addStack(new_stack);
+      return true;
+    }
+  return false;
+}
+
+Stack *Player::stackSplitArmies(Stack *stack, std::list<guint32> armies)
+{
+  Stack *new_stack = NULL;
+  bool retval = doStackSplitArmies(stack, armies, new_stack);
+  if (retval == true)
+    {
+      Action_Split* item = new Action_Split();
+      item->fillData(stack, new_stack);
+      addAction(item);
+    }
+  return new_stack;
+}
+
+Stack *Player::stackSplitArmy(Stack *stack, Army *a)
+{
+  Stack *new_stack = NULL;
+  bool retval = doStackSplitArmy(stack, a, new_stack);
+  if (retval == true)
+    {
+      Action_Split* item = new Action_Split();
+      item->fillData(stack, new_stack);
+      addAction(item);
+    }
+  return new_stack;
+}
+
+void Player::doStackJoin(Stack* receiver, Stack* joining)
+{
+    receiver->join(joining);
+   deleteStack(joining); 
+    //d_stacklist->flRemove(joining);
+    
+    d_stacklist->setActivestack(receiver);
+}
+
+bool Player::stackJoin(Stack* receiver, Stack* joining)
+{
+
+    if ((receiver == 0) || (joining == 0))
+        return false;
+    debug("Player::stackJoin("<<receiver->getId()<<","<<joining->getId()<<")");
+
+    assert (receiver->getPos() == joining->getPos());
+    if (GameMap::canJoin(joining, receiver) == false)
+      return false;
+    
+    Action_Join* item = new Action_Join();
+    item->fillData(receiver, joining);
+    addAction(item);
+
+    doStackJoin(receiver, joining);
+    supdatingStack.emit(0);
+    return true;
+}
+
+bool Player::stackSplitAndMove(Stack* s, Stack *& new_stack)
+{
+  if (s->hasPath() == false)
+    return false;
+  Vector<int> pos = s->getLastReachablePointInPath();
+  if (pos == Vector<int>(-1,-1))
+    return false;
+  Stack *join = GameMap::getFriendlyStack(pos);
+  if (join)
+    return stackSplitAndMoveToJoin(s, join, new_stack);
+  else
+    return stackSplitAndMoveToAttack(s, new_stack);
+}
+
+bool Player::stackSplitAndMoveToJoin(Stack* s, Stack *join, Stack *& new_stack)
+{
+  //the stack can't get there, but maybe part of the stack can.
+  if (s->hasPath() == false)
+    return false;
+
+  std::list<guint32> ids;
+  ids = s->determineReachableArmies(s->getLastPointInPath());
+  if (ids.size() == 0)
+    return false;
+  //if they're all reachable and we can join, just move them
+  if (ids.size() == s->size() && GameMap::canJoin(s, join) == true)
+    return stackMove(s);
+
+  //let's take who we can fit.
+  if (ids.size() > join->getMaxArmiesToJoin())
+    {
+      int diff = ids.size() - join->getMaxArmiesToJoin();
+      for (int i = 0; i < diff; i++)
+        ids.pop_front();
+    }
+
+  if (ids.size() == 0)
+    return false;
+  //okay, ids.size armies can make the move.  but can that tile accept it?
+  new_stack = stackSplitArmies(s, ids);
+  if (new_stack)
+    {
+      setActivestack(new_stack);
+      return stackMove(new_stack);
+      //if (getActivestack() != NULL)
+       //GameMap::groupStacks(new_stack);
+    }
+  return false;
+}
+
+bool Player::stackSplitAndMoveToAttack(Stack* s, Stack *& new_stack)
+{
+  //the stack can't get there, but maybe part of the stack can.
+  if (s->getPath()->empty())
+    return false;
+
+  std::list<guint32> ids;
+  ids = s->determineReachableArmies(s->getLastPointInPath());
+  if (ids.size() == 0)
+    return false;
+  if (ids.size() == s->size())
+    return stackMove(s);
+
+  new_stack = stackSplitArmies(s, ids);
+  if (new_stack)
+    {
+      setActivestack(new_stack);
+      return stackMove(new_stack);
+    }
+  return false;
+}
+
+bool Player::stackMove(Stack* s)
+{
+    debug("Player::stackMove(Stack*)")
+
+    if (s->getPath()->empty())
+    {
+        return false;
+    }
+
+    MoveResult *result = stackMove(s, s->getLastPointInPath(), true);
+    bool ret = result->didSomething();//result->moveSucceeded();
+    delete result;
+    result = 0;
+    return ret;
+}
+
+    
+bool Player::nextStepOnEnemyStackOrCity(Stack *s) const
+{
+  Vector<int> dest = s->getFirstPointInPath();
+  if (dest != Vector<int>(-1,-1))
+    {
+      if (GameMap::getEnemyStack(dest))
+       return true;
+      if (GameMap::getEnemyCity(dest))
+       return true;
+    }
+  return false;
+}
+
+MoveResult *Player::stackMove(Stack* s, Vector<int> dest)
+{
+  if (dest == Vector<int>(-1,-1))
+    return stackMove(s, dest, true);
+  else
+    return stackMove(s, dest, false);
+}
+
+MoveResult *Player::stackMove(Stack* s, Vector<int> dest, bool follow)
+{
+
+    debug("Player::stack_move()");
+    //if follow is set to true, follow an already calculated way, else
+    //calculate it here
+    if (!follow)
+    {
+        s->getPath()->calculate(s, dest);
+    }
+
+    if (s->getPath()->empty())
+      {
+       MoveResult *result = new MoveResult;
+       result->setReachedEndOfPath(true);
+       return result;
+      }
+
+    int stepCount = 0;
+    int moves_left = s->getPath()->getMovesExhaustedAtPoint();
+    while (1)
+      {
+        if (abortRequested())
+          {
+            MoveResult *result = new MoveResult;
+            result->fillData(s, stepCount);
+            result->setMoveAborted(true);
+            return result;
+          }
+       if (s->getPath()->size() <= 1)
+         break;
+       if (nextStepOnEnemyStackOrCity(s) == true)
+         break;
+
+        bool step = false;
+        step = stackMoveOneStep(s);
+        if (!step)
+          step = stackMoveOneStepOverTooLargeFriendlyStacks(s);
+        if (step)
+         {
+           stepCount++;
+           moves_left--;
+           supdatingStack.emit(0);
+           if (moves_left == 1)
+             break;
+         }
+       else
+         break;
+      }
+
+    //the idea here is that we're one move away from our destination.
+    //but in some cases we've already reached the end of the path
+    //because a fight has to happen.
+
+    //did we jump over a too large friendly stack to an enemy stack or city?
+  
+    //alright, we've walked up to the last place in the path.
+    if (s->getPath()->size() >= 1 && s->enoughMoves())
+    //now look for fight targets, joins etc.
+    {
+    
+        Vector<int> pos = s->getFirstPointInPath();
+        City* city = GameMap::getCity(pos);
+        Stack* target =GameMap::getStack(pos);
+
+
+        //first fight_city to avoid ambiguity with fight_army
+        if (city && (city->getOwner() != this) && (!city->isBurnt()))
+         {
+           bool treachery = false;
+           if (this->getDiplomaticState (city->getOwner()) != AT_WAR)
+             {
+               if (streacheryStack.emit (s, city->getOwner(), 
+                                         city->getPos()) == false)
+                 {
+                   //we decided not to be treacherous
+                   s->getPath()->clear();
+                   MoveResult *moveResult = new MoveResult;
+                   moveResult->setConsideredTreachery(true);
+                   moveResult->fillData(s, stepCount);
+                   return moveResult;
+                 }
+               else
+                 treachery = true;
+             }
+           MoveResult *moveResult = new MoveResult;
+           moveResult->setTreachery(treachery);
+           moveResult->setConsideredTreachery(treachery);
+           if (stackMoveOneStep(s))
+             {
+               stepCount++;
+             }
+           else
+             {
+               moveResult->fillData(s, stepCount);
+               shaltedStack.emit(s);
+               return moveResult;
+             }
+
+           moveResult->fillData(s, stepCount);
+            Fight::Result result;
+            vector<Stack*> def_in_city = city->getDefenders();
+            if (!def_in_city.empty())
+            {
+                // This is a hack to circumvent the limitations of stackFight.
+                if (!target)
+                  target = def_in_city[0];
+                result = stackFight(&s, &target);
+            }
+            else
+                result = Fight::ATTACKER_WON;
+
+            moveResult->setFightResult(result);
+
+            // We may only take the city if we have defeated all defenders
+            if (result == Fight::ATTACKER_WON)
+            {
+                adjustDiplomacyFromConqueringCity(city);
+                conquerCity(city, s);
+                invadeCity(city); //let AIs determine what to do with city
+               shaltedStack.emit(s);
+            }
+            
+           cityfight_finished(city, result);
+            supdatingStack.emit(0);
+            
+            return moveResult;
+        }
+        
+        //another friendly stack => share the tile if we're human
+        else if (target && target->getOwner() == this /*&& 
+                getType() == Player::HUMAN*/)
+          {
+            MoveResult *moveResult = new MoveResult;
+           bool moved = false;
+            if (stackMoveOneStep(s))
+             {
+               moved = true;
+                stepCount++;
+             }
+            else
+              moveResult->setTooLargeStackInTheWay(true);
+             
+           supdatingStack.emit(0);
+           shaltedStack.emit(d_stacklist->getActivestack());
+    
+           moveResult->fillData(s, stepCount);
+            return moveResult;
+         }
+        
+        //enemy stack => fight
+        else if (target)
+        {
+         bool treachery = false;
+         if (this->getDiplomaticState (target->getOwner()) == AT_PEACE)
+           {
+             if (streacheryStack.emit (s, target->getOwner(), 
+                                       target->getPos()) == false)
+               {
+                 s->getPath()->clear();
+                 MoveResult *moveResult = new MoveResult;
+                 moveResult->setConsideredTreachery(true);
+                 moveResult->fillData(s, stepCount);
+                 return moveResult;
+               }
+             else
+               treachery = true;
+           }
+            MoveResult *moveResult = new MoveResult;
+           moveResult->setTreachery(treachery);
+           moveResult->setConsideredTreachery(treachery);
+        
+           moveResult->fillData(s, stepCount);
+            Fight::Result result = stackFight(&s, &target);
+            moveResult->setFightResult(result);
+            if (!target)
+             {
+                if (stackMoveOneStep(s))
+                 stepCount++;
+               moveResult->fillData(s, stepCount);
+             }
+            
+            supdatingStack.emit(0);
+            if (result == Fight::ATTACKER_WON)
+             shaltedStack.emit(s);
+            return moveResult;
+        }
+        
+        //else
+        if (stackMoveOneStep(s))
+          {
+            supdatingStack.emit(0);
+            stepCount++;
+          }
+
+       shaltedStack.emit(s);
+    
+        MoveResult *moveResult = new MoveResult;
+       moveResult->fillData(s, stepCount);
+        return moveResult;
+    }
+    else if (s->getPath()->size() >= 1 && s->enoughMoves() == false)
+    {
+    
+        MoveResult *moveResult = new MoveResult;
+       moveResult->fillData(s, stepCount);
+      /* if we can't attack a city, don't remember it in the stack's path. */
+        Vector<int> pos = s->getFirstPointInPath();
+        City* city = GameMap::getCity(pos);
+       if (city && city->getOwner() != this)
+         s->clearPath();
+    
+        return moveResult;
+    }
+
+    MoveResult *moveResult = new MoveResult;
+    moveResult->setStepCount(stepCount);
+    return moveResult;
+}
+
+          
+bool Player::stackMoveOneStepOverTooLargeFriendlyStacks(Stack *s)
+{
+  if (!s)
+    return false;
+
+  if (!s->enoughMoves())
+    return false;
+
+  if (s->getPath()->size() <= 1)
+    return false;
+
+  Vector<int> dest = s->getFirstPointInPath();
+  Stack *another_stack = GameMap::getStack(dest);
+  if (!another_stack)
+    return false;
+
+  if (another_stack->getOwner() != s->getOwner())
+    return false;
+
+  if (d_stacklist->canJumpOverTooLargeStack(s) == false)
+    return false;
+
+  Action_Move* item = new Action_Move();
+  item->fillData(s, dest);
+  addAction(item);
+
+  s->moveOneStep(true);
+  return true;
+}
+
+bool Player::stackMoveOneStep(Stack* s)
+{
+  if (!s)
+    return false;
+
+  sbusy.emit();
+
+  if (!s->enoughMoves())
+    return false;
+
+  Vector<int> dest = s->getFirstPointInPath();
+  
+  Stack *another_stack = GameMap::getStack(dest);
+  if (another_stack)
+    {
+      if (another_stack->getOwner() == s->getOwner())
+       {
+         if (GameMap::canJoin(s,another_stack) == false)
+           return false;
+       }
+      else
+       {
+         //if we're attacking, then jump onto the square with the enemy.
+         if (s->getPath()->size() != 1)
+           return false;
+       }
+
+    }
+  Action_Move* item = new Action_Move();
+  item->fillData(s, dest);
+  addAction(item);
+
+  s->moveOneStep();
+
+  return true;
+}
+
+void Player::cleanupAfterFight(std::list<Stack*> &attackers,
+                               std::list<Stack*> &defenders)
+{
+  // get attacker and defender heroes and more...
+  std::vector<guint32> attackerHeroes, defenderHeroes;
+    
+  getHeroes(attackers, attackerHeroes);
+  getHeroes(defenders, defenderHeroes);
+
+  // here we calculate also the total XP to add when a player have a battle
+  // clear dead defenders
+  debug("clean dead defenders");
+  double defender_xp = removeDeadArmies(defenders, attackerHeroes);
+
+  // and dead attackers
+  debug("clean dead attackers");
+  double attacker_xp = removeDeadArmies(attackers, defenderHeroes);
+
+  debug("after fight: attackers empty? " << attackers.empty()
+        << "(" << attackers.size() << ")");
+
+  if (!attackers.empty() && defender_xp != 0)
+    updateArmyValues(attackers, defender_xp);
+    
+  if (attacker_xp != 0)
+    updateArmyValues(defenders, attacker_xp);
+
+  supdatingStack.emit(0);
+}
+
+Fight::Result Player::stackFight(Stack** attacker, Stack** defender) 
+{
+    debug("stackFight: player = " << getName()<<" at position "
+          <<(*defender)->getPos().x<<","<<(*defender)->getPos().y);
+
+    // save the defender's player for future use
+    Player* pd = (*defender)->getOwner();
+
+    // I suppose, this should be always true, but one can never be sure
+    bool attacker_active = *attacker == d_stacklist->getActivestack();
+
+    Fight fight(*attacker, *defender);
+    fight.battle(GameScenarioOptions::s_intense_combat);
+    
+    fight_started.emit(fight);
+    // cleanup
+    
+    // add a fight item about the combat
+    Action_Fight* item = new Action_Fight();
+    item->fillData(&fight);
+    addAction(item);
+
+    std::list<Stack *> attackers = fight.getAttackers(),
+      defenders = fight.getDefenders();
+
+    cleanupAfterFight(attackers, defenders);
+    
+    // Set the attacker and defender stack to 0 if neccessary. This is a great
+    // help for the functions calling stackFight (e.g. if a stack attacks
+    // another stack and destroys it without winning the battle, it may take the
+    // position of this stack)
+
+    // First, the attacker...
+    bool exists =
+       std::find(d_stacklist->begin(), d_stacklist->end(), *attacker)
+       != d_stacklist->end();
+    
+    if (!exists)
+    {
+        (*attacker) = 0;
+        if (attacker_active)
+            d_stacklist->setActivestack(0);
+    }
+
+    // ...then the defender.
+    exists = false;
+    if (pd)
+      exists = 
+       std::find(pd->getStacklist()->begin(), pd->getStacklist()->end(), 
+                 *defender) != pd->getStacklist()->end();
+    else
+        exists = true;
+    if (!exists)
+        (*defender) = 0;
+
+    return fight.getResult();
+}
+
+/*
+ *
+ * To help factor in the advantage of hero experience/strength and 
+ * ruin-monster strength as well as the stack strength, I think you'll 
+ * find it'll be easier to calculate in terms of the odds of failure [than
+ * the odds of success].  A new hero (minimum strength) with nothing in 
+ * the stack to help him might have 10-20% odds of failure at a wimpy ruin.
+ * The same novice hero facing a dragon in the ruin might have 50% odds of 
+ * failure.  So a rule of thumb would be to start with a 25% chance of
+ * failure.  The odds would be doubled by the worst monster and halved by 
+ * the easiest.  I agree that a strength-9 hero with 8 in the stack should i
+ * definitely be at 99%.  A reasonable formula might be:
+ *
+ * OddsOfFailure = BaseOdds * MonsterFactor * StackFactor * HeroFactor,
+ *
+ * with
+ *        BaseOdds = 0.10
+ * and
+ *        MonsterFactor = 2, 1 or 0.5 depending on hard vs. easy
+ * and
+ *        StackFactor = (9 - SizeOfStack)/8,
+ * and
+ *        HeroFactor = (10-StrengthOfHero)/5.
+ */
+Fight::Result ruinfight (Stack **attacker, Stack **defender)
+{
+  Stack *loser;
+  Fight::Result result;
+  guint32 hero_strength, monster_strength;
+  hero_strength = (*attacker)->getFirstHero()->getStat(Army::STRENGTH, true);
+  monster_strength = (*defender)->getStrongestArmy()->getStat(Army::STRENGTH, true);
+  float base_factor = 0.28;
+  float stack_factor = ((float)(MAX_STACK_SIZE + 1) - (*attacker)->size()) / (float)MAX_STACK_SIZE;
+  float hero_factor = (10.0 - hero_strength) / 5.0;
+  float monster_factor;
+  if (monster_strength >= 8)
+    monster_factor = 2.0;
+  else if (monster_strength >= 6)
+    monster_factor = 1.0;
+  else
+    monster_factor = 0.5;
+  float fail = base_factor * monster_factor * stack_factor * hero_factor;
+
+  if (rand() % 100 > (int)(fail * 100.0))
+    {
+      result = Fight::ATTACKER_WON;
+      loser = *defender;
+      for (Stack::iterator sit = loser->begin(); sit != loser->end();)
+        {
+          (*sit)->setHP (0);
+          sit++;
+        }
+    }
+  else
+    {
+      result = Fight::DEFENDER_WON;
+      loser = *attacker;
+      loser->getFirstHero()->setHP(0); /* only the hero dies */
+    }
+        
+  return result;
+}
+
+Fight::Result Player::stackRuinFight (Stack **attacker, Stack **defender)
+{
+    Fight::Result result = Fight::DRAW;
+    if (*defender == NULL)
+      return Fight::ATTACKER_WON;
+    debug("stackRuinFight: player = " << getName()<<" at position "
+          <<(*defender)->getPos().x<<","<<(*defender)->getPos().y);
+
+    ruinfight_started.emit(*attacker, *defender);
+    result = ruinfight (attacker, defender);
+    ruinfight_finished.emit(result);
+
+    // cleanup
+    
+    // add a ruin fight item about the combat
+    //Action_RuinFight* item = new Action_RuinFight();
+    //item->fillData(*attacker, *defender, result);
+    //addAction(item);
+    /* FIXME: do we need an Action_RuinFight? */
+
+    // get attacker and defender heroes and more...
+    std::list<Stack*> attackers;
+    attackers.push_back(*attacker);
+    std::list<Stack*> defenders;
+    defenders.push_back(*defender);
+
+    cleanupAfterFight(attackers, defenders);
+
+    return result;
+}
+
+bool Player::treachery (Stack *stack, Player *player, Vector <int> pos)
+{
+  return streachery.emit(stack, player, pos);
+}
+
+Reward* Player::stackSearchRuin(Stack* s, Ruin* r)
+{
+  Reward *retReward = NULL;
+  debug("Player::stack_search_ruin");
+
+  //throw out impossible actions
+  if ((s->getPos().x != r->getPos().x) ||
+      (s->getPos().y != r->getPos().y))
+  {
+    cerr <<  "Error: searching stack and ruin to be searched not on same position\n" ;
+    exit(-1);
+  }
+
+  if (r->isSearched())
+    return NULL;
+
+  // start the action item
+  Action_Ruin* item = new Action_Ruin();
+  item->fillData(r, s);
+
+  Stack* keeper = r->getOccupant();
+
+  if (keeper)
+  {
+    stackRuinFight(&s, &keeper);
+
+    // did the explorer not win?
+    if (keeper && !keeper->empty())
+    {
+      item->setSearched(false);
+      addAction(item);
+
+      return NULL;
+    }
+
+    r->setOccupant(0);
+    if (keeper)
+      delete keeper;
+  }
+
+  if (r->hasSage())
+  {
+    History_FoundSage* history = new History_FoundSage();
+    history->fillData(dynamic_cast<Hero *>(s->getFirstHero()));
+    addHistory(history);
+  }
+  else
+  {
+    if (r->getReward() == NULL)
+      r->populateWithRandomReward();
+  }
+
+  retReward = r->getReward();
+
+  r->setSearched(true);
+  r->setOwner(s->getOwner());
+
+  item->setSearched(true);
+  addAction(item);
+
+  History_HeroRuinExplored *history_item = new History_HeroRuinExplored();
+  history_item->fillData(dynamic_cast<Hero*>(s->getFirstHero()), r);
+  addHistory(history_item);
+
+  supdatingStack.emit(0);
+  return retReward;
+}
+
+int Player::doStackVisitTemple(Stack *s, Temple *t)
+{
+  // you have your stack blessed (+1 strength)
+  int count = s->bless();
+
+  supdatingStack.emit(0);
+  
+  return count;
+}
+
+int Player::stackVisitTemple(Stack* s, Temple* t)
+{
+  debug("Player::stackVisitTemple");
+
+  assert(s && t->getPos().x == s->getPos().x && t->getPos().y == s->getPos().y);
+
+  Action_Temple* item = new Action_Temple();
+  item->fillData(t, s);
+  addAction(item);
+  
+  return doStackVisitTemple(s, t);
+}
+
+Quest* Player::doHeroGetQuest(Hero *hero, Temple* t, bool except_raze)
+{
+  QuestsManager *qm = QuestsManager::getInstance();
+
+  std::vector<Quest*> quests = qm->getPlayerQuests(Playerlist::getActiveplayer());
+  if (quests.size() > 0 && GameScenarioOptions::s_play_with_quests == GameParameters::ONE_QUEST_PER_PLAYER)
+    return NULL;
+
+  Quest* q=0;
+  if (hero)
+    {
+      q = qm->createNewQuest (hero->getId(), except_raze);
+    }
+
+  // couldn't assign a quest for various reasons
+  if (!q)
+    return 0;
+  return q;
+}
+
+Quest* Player::heroGetQuest(Hero *hero, Temple* t, bool except_raze)
+{
+  debug("Player::stackGetQuest")
+
+  Quest *q = doHeroGetQuest(hero, t, except_raze);
+  if (q == NULL)
+    return q;
+
+  // Now fill the action item
+  Action_Quest* action = new Action_Quest();
+  action->fillData(q);
+  addAction(action);
+
+  // and record it for posterity
+  History_HeroQuestStarted * history = new History_HeroQuestStarted();
+  history->fillData(hero);
+  addHistory(history);
+  return q;
+}
+
+float Player::stackFightAdvise(Stack* s, Vector<int> tile, 
+                               bool intense_combat)
+{
+  float percent = 0.0;
+        
+  City* city = GameMap::getCity(tile);
+  Stack* target = GameMap::getEnemyStack(tile);
+                
+  if (!target && city)
+    {
+      vector<Stack*> def_in_city = city->getDefenders();
+      if (def_in_city.empty())
+       return 100.0;
+      target = def_in_city[0];
+    }
+
+  //what chance is there that stack will defeat defenders?
+    
+  for (unsigned int i = 0; i < 100; i++)
+    {
+      Fight fight(s, target, Fight::FOR_KICKS);
+      fight.battle(intense_combat);
+      if (fight.getResult() == Fight::ATTACKER_WON)
+       percent += 1.0;
+    }
+
+  advice_asked.emit(percent);
+  return percent;
+}
+
+void Player::adjustDiplomacyFromConqueringCity(City *city)
+{
+  Player *defender = city->getOwner();
+  
+  // See if this is the last city for that player, and alter the 
+  // diplomatic scores.
+  if (Citylist::getInstance()->countCities(defender) == 1)
+  {
+    if (defender->getDiplomaticRank() < getDiplomaticRank())
+      deteriorateDiplomaticRelationship (2);
+    else if (defender->getDiplomaticRank() > getDiplomaticRank())
+      improveDiplomaticRelationship (2, defender);
+  }
+}
+
+void Player::calculateLoot(Player *looted, guint32 &added, guint32 &subtracted)
+{
+  Player *defender = looted;
+  int gold = 0;
+
+  // if the attacked city isn't neutral, loot some gold
+  if (defender != Playerlist::getInstance()->getNeutral())
+  {
+    Citylist *clist = Citylist::getInstance();
+    int amt = (defender->getGold() / (2 * (clist->countCities (defender)+1)) * 2);
+    // give (Enemy-Gold/(2Enemy-Cities)) to the attacker 
+    // and then take away twice that from the defender.
+    // the idea here is that some money is taken in the invasion
+    // and other monies are lost forever
+    // NOTE: +1 because the looted player just lost a city
+    subtracted = amt;
+    amt /= 2;
+    added = amt;
+    gold = amt;
+  }
+
+  return;
+}
+
+void Player::doConquerCity(City *city, Stack *stack)
+{
+  takeCityInPossession(city);
+  
+  History_CityWon *item = new History_CityWon();
+  item->fillData(city);
+  addHistory(item);
+  if (stack->hasHero())
+  {
+    History_HeroCityWon *another = new History_HeroCityWon();
+    Hero *hero = dynamic_cast<Hero *>(stack->getFirstHero());
+    another->fillData(hero, city);
+    addHistory(another);
+  }
+}
+
+void Player::conquerCity(City *city, Stack *stack)
+{
+  
+  Action_ConquerCity *action = new Action_ConquerCity();
+  action->fillData(city, stack);
+  addAction(action);
+
+  Player *looted = city->getOwner();
+  doConquerCity(city, stack);
+  if (getType() != Player::NETWORKED)
+    lootCity(city, looted);
+}
+
+void Player::lootCity(City *city, Player *looted)
+{
+  guint32 added = 0;
+  guint32 subtracted = 0;
+  calculateLoot(looted, added, subtracted);
+  sinvadingCity.emit(city, added);
+  doLootCity(looted, added, subtracted);
+  Action_Loot *item = new Action_Loot();
+  item->fillData(this, looted, added, subtracted);
+  addAction(item);
+  return;
+}
+
+void Player::doLootCity(Player *looted, guint32 added, guint32 subtracted)
+{
+  addGold(added);
+  looted->withdrawGold(subtracted);
+  return;
+}
+
+void Player::takeCityInPossession(City* c)
+{
+  c->conquer(this);
+
+  //set the production to the cheapest armytype
+  c->setActiveProductionSlot(-1);
+  if (c->getArmytype(0) != -1)
+    c->setActiveProductionSlot(0);
+
+  supdatingCity.emit(c);
+}
+
+void Player::doCityOccupy(City *c)
+{
+  assert (c->getOwner() == this);
+  
+  soccupyingCity.emit(c, getActivestack());
+  QuestsManager::getInstance()->cityOccupied(c, getActivestack());
+}
+
+void Player::cityOccupy(City* c)
+{
+  debug("cityOccupy");
+  doCityOccupy(c);
+
+  Action_Occupy* item = new Action_Occupy();
+  item->fillData(c);
+  addAction(item);
+}
+
+void Player::doCityPillage(City *c, int& gold, int* pillaged_army_type)
+{
+  gold = 0;
+  if (pillaged_army_type)
+    *pillaged_army_type = -1;
+  
+  // get rid of the most expensive army type and trade it in for 
+  // half it's cost
+  // it is presumed that the last army type is the most expensive
+
+  if (c->getNoOfProductionBases() > 0)
+    {
+      unsigned int i;
+      unsigned int max_cost = 0;
+      int slot = -1;
+      for (i = 0; i < c->getNoOfProductionBases(); i++)
+       {
+         const ArmyProdBase *a = c->getProductionBase(i);
+         if (a != NULL)
+           {
+             if (a->getNewProductionCost() == 0)
+               {
+                 slot = i;
+                 break;
+               }
+             if (a->getNewProductionCost() > max_cost)
+               {
+                 max_cost = a->getNewProductionCost();
+                 slot = i;
+               }
+           }
+       }
+      if (slot > -1)
+       {
+         const ArmyProdBase *a = c->getProductionBase(slot);
+         if (pillaged_army_type)
+           *pillaged_army_type = a->getTypeId();
+         if (a->getNewProductionCost() == 0)
+           gold += 1500;
+         else
+           gold += a->getNewProductionCost() / 2;
+         c->removeProductionBase(slot);
+       }
+  //*pillaged_army_type = 10;
+  //gold = 300;
+      addGold(gold);
+      Stack *s = getActivestack();
+      //printf ("%s emitting %p, %p, %d, %d\n", getName().c_str(), c, s, gold, *pillaged_army_type);
+      spillagingCity.emit(c, s, gold, *pillaged_army_type);
+      QuestsManager::getInstance()->cityPillaged(c, s, gold);
+    }
+
+  //takeCityInPossession(c);
+}
+
+void Player::cityPillage(City* c, int& gold, int* pillaged_army_type)
+{
+  debug("Player::cityPillage");
+  
+  Action_Pillage* item = new Action_Pillage();
+  item->fillData(c);
+  addAction(item);
+
+  doCityPillage(c, gold, pillaged_army_type);
+}
+
+void Player::doCitySack(City* c, int& gold, std::list<guint32> *sacked_types)
+{
+  gold = 0;
+  //trade in all of the army types except for one
+  //presumes that the army types are listed in order of expensiveness
+
+  if (c->getNoOfProductionBases() > 1)
+    {
+      const ArmyProdBase *a;
+      unsigned int i, max = 0;
+      for (i = 0; i < c->getNoOfProductionBases(); i++)
+       {
+         a = c->getProductionBase(i);
+         if (a)
+           max++;
+       }
+
+      i = c->getNoOfProductionBases() - 1;
+      while (max > 1)
+       {
+         a = c->getProductionBase(i);
+         if (a != NULL)
+           {
+             sacked_types->push_back(a->getTypeId());
+             if (a->getNewProductionCost() == 0)
+               gold += 1500;
+             else
+               gold += a->getNewProductionCost() / 2;
+             c->removeProductionBase(i);
+             max--;
+           }
+         i--;
+       }
+    }
+
+  addGold(gold);
+  Stack *s = getActivestack();
+  ssackingCity.emit(c, s, gold, *sacked_types);
+  printf("notifying quests manager of city sacking!\n");
+  QuestsManager::getInstance()->citySacked(c, s, gold);
+  printf("done\n");
+  //takeCityInPossession(c);
+}
+
+void Player::citySack(City* c, int& gold, std::list<guint32> *sacked_types)
+{
+  debug("Player::citySack");
+
+  Action_Sack* item = new Action_Sack();
+  item->fillData(c);
+  addAction(item);
+
+  doCitySack(c, gold, sacked_types);
+}
+
+void Player::doCityRaze(City *c)
+{
+  History_CityRazed* history = new History_CityRazed();
+  history->fillData(c);
+  addHistory(history);
+
+  c->conquer(this);
+  c->setBurnt(true);
+
+  supdatingCity.emit(c);
+
+  srazingCity.emit(c, getActivestack());
+  QuestsManager::getInstance()->cityRazed(c, getActivestack());
+}
+
+void Player::cityRaze(City* c)
+{
+  debug("Player::cityRaze");
+
+  Action_Raze* action = new Action_Raze();
+  action->fillData(c);
+  addAction(action);
+
+  doCityRaze(c);
+}
+
+void Player::doCityBuyProduction(City* c, int slot, int type)
+{
+  const Armysetlist* al = Armysetlist::getInstance();
+  guint32 as = c->getOwner()->getArmyset();
+
+  c->removeProductionBase(slot);
+  c->addProductionBase(slot, new ArmyProdBase(*al->getArmy(as, type)));
+
+  // and do the rest of the neccessary actions
+  withdrawGold(al->getArmy(as, type)->getNewProductionCost());
+}
+
+bool Player::cityBuyProduction(City* c, int slot, int type)
+{
+  const Armysetlist* al = Armysetlist::getInstance();
+  guint32 as = c->getOwner()->getArmyset();
+
+  // sort out unusual values (-1 is allowed and means "scrap production")
+  if ((type <= -1) || (type >= (int)al->getSize(as)))
+    return false;
+
+  // return if we don't have enough money
+  if ((type != -1) && ((int)al->getArmy(as, type)->getNewProductionCost() > d_gold))
+    return false;
+
+  // return if the city already has the production
+  if (c->hasProductionBase(type, as))
+    return false;
+
+  // can't put it in that slot
+  if (slot >= (int)c->getMaxNoOfProductionBases())
+    return false;
+  
+  Action_Buy* item = new Action_Buy();
+  item->fillData(c, slot, al->getArmy(as, type));
+  addAction(item);
+
+  doCityBuyProduction(c, slot, type);
+
+  return true;
+}
+
+void Player::doCityChangeProduction(City* c, int slot)
+{
+  c->setActiveProductionSlot(slot);
+}
+
+bool Player::cityChangeProduction(City* c, int slot)
+{
+  doCityChangeProduction(c, slot);
+  
+  Action_Production* item = new Action_Production();
+  item->fillData(c, slot);
+  addAction(item);
+
+  return true;
+}
+
+void Player::doGiveReward(Stack *s, Reward *reward)
+{
+  switch (reward->getType())
+    {
+    case Reward::GOLD:
+      addGold(dynamic_cast<Reward_Gold*>(reward)->getGold());
+      break;
+    case Reward::ALLIES:
+        {
+          const ArmyProto *a = dynamic_cast<Reward_Allies*>(reward)->getArmy();
+
+          Reward_Allies::addAllies(s->getOwner(), s->getPos(), a,
+                            dynamic_cast<Reward_Allies*>(reward)->getNoOfAllies());
+  
+        }
+      break;
+    case Reward::ITEM:
+      static_cast<Hero*>(s->getFirstHero())->getBackpack()->addToBackpack
+       (dynamic_cast<Reward_Item*>(reward)->getItem());
+      break;
+    case Reward::RUIN:
+        {
+          //assign the hidden ruin to this player
+          Ruin *r = dynamic_cast<Reward_Ruin*>(reward)->getRuin();
+          r->setHidden(true);
+          r->setOwner(this);
+         r->deFog(this);
+        }
+      break;
+    case Reward::MAP:
+        {
+          Reward_Map *map = dynamic_cast<Reward_Map*>(reward);
+          d_fogmap->alterFog(map->getSightMap());
+        }
+      break;
+    }
+}
+
+bool Player::giveReward(Stack *s, Reward *reward)
+{
+  debug("Player::give_reward");
+
+  doGiveReward(s, reward);
+  
+  Action_Reward* item = new Action_Reward();
+  item->fillData(s, reward);
+  addAction(item);
+
+  if (reward->getType() == Reward::RUIN)
+    {
+      Ruin *r = dynamic_cast<Reward_Ruin*>(reward)->getRuin();
+      History_HeroRewardRuin* history_item = new History_HeroRewardRuin();
+      history_item->fillData(dynamic_cast<Hero*>(s->getFirstHero()), r);
+      addHistory(history_item);
+    }
+  //FIXME: get rid of this reward now that we're done with it
+  //but we need to show it still... (in the case of quest completions)
+
+  return true;
+}
+
+bool Player::doStackDisband(Stack* s)
+{
+    getStacklist()->setActivestack(0);
+    bool found = d_stacklist->flRemove(s);
+    supdatingStack.emit(0);
+    return found;
+}
+
+bool Player::stackDisband(Stack* s)
+{
+    debug("Player::stackDisband(Stack*)")
+    if (!s)
+      s = getActivestack();
+    
+    Action_Disband* item = new Action_Disband();
+    item->fillData(s);
+    addAction(item);
+
+    return doStackDisband(s);
+}
+
+void Player::doHeroDropItem(Hero *h, Item *i, Vector<int> pos)
+{
+  GameMap::getInstance()->getTile(pos)->getBackpack()->addToBackpack(i);
+  h->getBackpack()->removeFromBackpack(i);
+}
+
+bool Player::heroDropItem(Hero *h, Item *i, Vector<int> pos)
+{
+  doHeroDropItem(h, i, pos);
+  
+  Action_Equip* item = new Action_Equip();
+  item->fillData(h, i, Action_Equip::GROUND, pos);
+  addAction(item);
+  
+  return true;
+}
+
+bool Player::heroDropAllItems(Hero *h, Vector<int> pos)
+{
+  while (h->getBackpack()->empty() == false)
+    heroDropItem(h, h->getBackpack()->front(), pos);
+  return true;
+}
+
+bool Player::doHeroDropAllItems(Hero *h, Vector<int> pos)
+{
+  while (h->getBackpack()->empty() == false)
+    doHeroDropItem(h, h->getBackpack()->front(), pos);
+  return true;
+}
+
+void Player::doHeroPickupItem(Hero *h, Item *i, Vector<int> pos)
+{
+  bool found = GameMap::getInstance()->getTile(pos)->getBackpack()->removeFromBackpack(i);
+  if (found)
+    h->getBackpack()->addToBackpack(i);
+}
+
+bool Player::heroPickupItem(Hero *h, Item *i, Vector<int> pos)
+{
+  doHeroPickupItem(h, i, pos);
+  
+  Action_Equip* item = new Action_Equip();
+  item->fillData(h, i, Action_Equip::BACKPACK, pos);
+  addAction(item);
+  
+  return true;
+}
+
+bool Player::heroPickupAllItems(Hero *h, Vector<int> pos)
+{
+  MapBackpack *backpack = GameMap::getInstance()->getTile(pos)->getBackpack();
+  while (backpack->empty() == false)
+    heroPickupItem(h, backpack->front(), pos);
+  return true;
+}
+
+bool Player::heroCompletesQuest(Hero *h)
+{
+  // record it for posterity
+  History_HeroQuestCompleted* item = new History_HeroQuestCompleted();
+  item->fillData(h);
+  addHistory(item);
+  return true;
+}
+
+void Player::doResign()
+{
+  //disband all stacks
+  getStacklist()->flClear();
+
+  //raze all cities
+  Citylist *cl = Citylist::getInstance();
+  for (Citylist::iterator it = cl->begin(); it != cl->end(); it++)
+    {
+      if ((*it)->getOwner() == this)
+       {
+         (*it)->setBurnt(true);
+         History_CityRazed* history = new History_CityRazed();
+         history->fillData((*it));
+         addHistory(history);
+       }
+    }
+  withdrawGold(getGold()); //empty the coffers!
+
+  getStacklist()->setActivestack(0);
+  supdatingStack.emit(0);
+}
+
+void Player::resign() 
+{
+  doResign();
+  
+  Action_Resign* item = new Action_Resign();
+  item->fillData();
+  addAction(item);
+}
+
+void Player::doSignpostChange(Signpost *s, std::string message)
+{
+  s->setName(message);
+}
+
+bool Player::signpostChange(Signpost *s, std::string message)
+{
+  if (!s)
+    return false;
+  
+  doSignpostChange(s, message);
+  
+  Action_ModifySignpost* item = new Action_ModifySignpost();
+  item->fillData(s, message);
+  addAction(item);
+  return true;
+}
+
+void Player::doCityRename(City *c, std::string name)
+{
+  c->setName(name);
+}
+
+bool Player::cityRename(City *c, std::string name)
+{
+  if (!c)
+    return false;
+
+  doCityRename(c, name);
+  
+  Action_RenameCity* item = new Action_RenameCity();
+  item->fillData(c, name);
+  addAction(item);
+  return true;
+}
+
+void Player::doRename(std::string name)
+{
+  setName(name);
+}
+
+void Player::rename(std::string name)
+{
+  doRename(name);
+  Action_RenamePlayer * item = new Action_RenamePlayer();
+  item->fillData(name);
+  addAction(item);
+  return;
+}
+
+void Player::doVectorFromCity(City * c, Vector<int> dest)
+{
+  c->setVectoring(dest);
+}
+
+bool Player::vectorFromCity(City * c, Vector<int> dest)
+{
+  if (dest != Vector<int>(-1,-1))
+    {
+      std::list<City*> cities;
+      cities = Citylist::getInstance()->getCitiesVectoringTo(dest);
+      if (cities.size() >= MAX_CITIES_VECTORED_TO_ONE_CITY)
+       return false;
+    }
+  doVectorFromCity(c, dest);
+  
+  Action_Vector* item = new Action_Vector();
+  item->fillData(c, dest);
+  addAction(item);
+  return true;
+}
+
+bool Player::doChangeVectorDestination(Vector<int> src, Vector<int> dest,
+                                      std::list<City*> &vectored)
+{
+  //DEST can be a flag.
+  //SRC can be a flag too.
+  //Note: we don't actually have a way in the gui to change the vectoring 
+  //from the planted standard (flag).
+  bool retval = true;
+  //sanity checks:
+  //disallow changing vectoring from or to a city that isn't ours
+  //disallow vectoring to something that isn't our city or our planted 
+  //standard.
+  Citylist *cl = Citylist::getInstance();
+  City *src_city = GameMap::getCity(src);
+  if (src_city == NULL)
+    {
+      //maybe it's a flag we're changing the vector destination from.
+      if (GameMap::getInstance()->findPlantedStandard(this) != src)
+       return false;
+    }
+  else
+    {
+      if (src_city->getOwner() != this)
+       return false;
+    }
+  City *dest_city = GameMap::getCity(dest);
+  if (dest_city == NULL)
+    {
+      if (GameMap::getInstance()->findPlantedStandard(this) != dest)
+       return false;
+    }
+  else
+    {
+      if (dest_city->getOwner() != this)
+       return false;
+    }
+
+  //check to see if the destination has enough room to accept all of the
+  //cities we want to send to it.
+  std::list<City*> sources = cl->getCitiesVectoringTo(src);
+  std::list<City*> alreadyvectored = cl->getCitiesVectoringTo(dest);
+
+  if (alreadyvectored.size() + sources.size() > MAX_CITIES_VECTORED_TO_ONE_CITY)
+    return false;
+
+  //okay, do the vectoring changes.
+  std::list<City*>::iterator it = sources.begin();
+  for (; it != sources.end(); it++)
+    retval &= (*it)->changeVectorDestination(dest);
+  vectored = sources;
+  return retval;
+}
+
+bool Player::changeVectorDestination(Vector<int> src, Vector<int> dest)
+{
+  std::list<City*> vectored;
+  bool retval = doChangeVectorDestination(src, dest, vectored);
+  if (retval == false)
+    return retval;
+
+  std::list<City*>::iterator it = vectored.begin();
+  for (; it != vectored.end(); it++)
+    {
+      Action_Vector* item = new Action_Vector();
+      item->fillData((*it), dest);
+      addAction(item);
+    }
+  return true;
+}
+
+bool Player::heroPlantStandard(Stack* s)
+{
+  debug("Player::heroPlantStandard(Stack*)");
+  if (!s)
+    s = getActivestack();
+  
+  for (Stack::iterator it = s->begin(); it != s->end(); it++)
+  {
+    if ((*it)->isHero())
+    {
+      Hero *hero = dynamic_cast<Hero*>((*it));
+      Item *item = hero->getBackpack()->getPlantableItem(this);
+      if (item)
+        {
+          //drop the item, and plant it
+          doHeroPlantStandard(hero, item, s->getPos());
+                  
+          Action_Plant * i = new Action_Plant();
+          i->fillData(hero, item);
+          addAction(i);
+          return true;
+        }
+    }
+  }
+  return true;
+}
+
+void Player::doHeroPlantStandard(Hero *hero, Item *item, Vector<int> pos)
+{
+  item->setPlanted(true);
+  GameMap *gm = GameMap::getInstance();
+  gm->getTile(pos)->getBackpack()->addToBackpack(item);
+  hero->getBackpack()->removeFromBackpack(item);
+}
+
+void Player::getHeroes(const std::list<Stack*> stacks, std::vector<guint32>& dst)
+{
+    std::list<Stack*>::const_iterator it;
+    for (it = stacks.begin(); it != stacks.end(); it++)
+        (*it)->getHeroes(dst);
+}
+
+double Player::removeDeadArmies(std::list<Stack*>& stacks,
+                                std::vector<guint32>& culprits)
+{
+    double total=0;
+    Player *owner = NULL;
+    if (stacks.empty() == 0)
+    {
+        owner = (*stacks.begin())->getOwner();
+        debug("Owner = " << owner);
+        if (owner)
+            debug("Owner of the stacks: " << owner->getName()
+                  << ", his stacklist = " << owner->getStacklist());
+    }
+    for (unsigned int i = 0; i < culprits.size(); i++)
+        debug("Culprit: " << culprits[i]);
+
+    std::list<Stack*>::iterator it;
+    for (it = stacks.begin(); it != stacks.end(); )
+    {
+    
+        debug("Stack: " << (*it))
+        for (Stack::iterator sit = (*it)->begin(); sit != (*it)->end();)
+        {
+            debug("Army: " << (*sit))
+            if ((*sit)->getHP() <= 0)
+            {
+               //Tally up the triumphs
+               if ((*sit)->getAwardable()) //hey a special died
+                 d_triumphs->tallyTriumph((*sit)->getOwner(), 
+                                          Triumphs::TALLY_SPECIAL);
+               else if ((*sit)->isHero() == false)
+                 d_triumphs->tallyTriumph((*sit)->getOwner(), 
+                                          Triumphs::TALLY_NORMAL);
+               if ((*sit)->getStat(Army::SHIP, false)) //hey it was on a boat
+                 d_triumphs->tallyTriumph((*sit)->getOwner(), 
+                                          Triumphs::TALLY_SHIP);
+                debug("Army: " << (*sit)->getName())
+                debug("Army: " << (*sit)->getXpReward())
+                if ((*sit)->isHero())
+                {
+                 d_triumphs->tallyTriumph((*sit)->getOwner(), 
+                                          Triumphs::TALLY_HERO);
+                 Hero *hero = dynamic_cast<Hero*>((*sit));
+                 guint32 count = hero->getBackpack()->countPlantableItems();
+                 for (guint32 i = 0; i < count; i++)
+                   d_triumphs->tallyTriumph((*sit)->getOwner(), 
+                                            Triumphs::TALLY_FLAG);
+
+                 //one of our heroes died
+                 //drop hero's stuff
+                 Hero *h = static_cast<Hero *>(*sit);
+                 //now record the details of the death
+                 GameMap *gm = GameMap::getInstance();
+                 Maptile *tile = gm->getTile((*it)->getPos());
+                 if (tile->getBuilding() == Maptile::RUIN)
+                   {
+                     History_HeroKilledSearching* item;
+                     item = new History_HeroKilledSearching();
+                     item->fillData(h);
+                     h->getOwner()->addHistory(item);
+                     doHeroDropAllItems (h, (*it)->getPos());
+                   }
+                 else if (tile->getBuilding() == Maptile::CITY)
+                   {
+                     City* c = GameMap::getCity((*it)->getPos());
+                     History_HeroKilledInCity* item;
+                     item = new History_HeroKilledInCity();
+                     item->fillData(h, c);
+                     h->getOwner()->addHistory(item);
+                     doHeroDropAllItems (h, (*it)->getPos());
+                   }
+                 else //somewhere else
+                   {
+                     History_HeroKilledInBattle* item;
+                     item = new History_HeroKilledInBattle();
+                     item->fillData(h);
+                     h->getOwner()->addHistory(item);
+                     doHeroDropAllItems (h, (*it)->getPos());
+                   }
+               }
+               //Add the XP bonus to the total of the battle;
+               total+=(*sit)->getXpReward();
+               //tell the quest manager that someone died
+               //(maybe it was a hero, or a target that's an army)
+               QuestsManager::getInstance()->armyDied(*sit, culprits);
+               // here we destroy the army, so we send
+               // the signal containing the fight data
+               debug("sending sdyingArmy!")
+                 sdyingArmy.emit(*sit, culprits);
+               sit = (*it)->flErase(sit);
+               continue;
+           }
+
+           // heal this army to full hitpoints
+           (*sit)->heal((*sit)->getStat(Army::HP));
+
+           sit++;
+       }
+
+       debug("Is stack empty?")
+
+         if ((*it)->empty())
+           {
+             if (owner)
+               {
+                 debug("Removing this stack from the owner's stacklist");
+                 bool found = owner->deleteStack(*it);
+                 assert (found == true);
+               }
+             else // there is no owner - like for the ruin's occupants
+               debug("No owner for this stack - do stacklist too");
+
+             debug("Removing from the vector too (the vector had "
+                   << stacks.size() << " elt)");
+             it = stacks.erase(it);
+           }
+         else
+           it++;
+    }
+    debug("after removeDead: size = " << stacks.size());
+    return total;
+}
+
+void Player::doHeroGainsLevel(Hero *hero, Army::Stat stat)
+{
+  hero->gainLevel(stat);
+}
+
+
+void Player::updateArmyValues(std::list<Stack*>& stacks, double xp_sum)
+{
+  std::list<Stack*>::iterator it;
+  double numberarmy = 0;
+
+  for (it = stacks.begin(); it != stacks.end(); it++)
+    numberarmy += (*it)->size();
+
+  for (it = stacks.begin(); it != stacks.end(); )
+    {
+      debug("Stack: " << (*it))
+
+       for (Stack::iterator sit = (*it)->begin(); sit != (*it)->end();)
+         {
+           Army *army = *sit;
+           debug("Army: " << army)
+
+             // here we adds XP
+             army->gainXp((double)((xp_sum)/numberarmy));
+           debug("Army gets " << (double)((xp_sum)/numberarmy) << " XP")
+
+             // here we adds 1 to number of battles
+             army->setBattlesNumber(army->getBattlesNumber()+1);
+           debug("Army battles " <<  army->getBattlesNumber())
+
+             // medals only go to non-ally armies.
+             if ((*it)->hasHero() && army->isHero() == false && 
+                 army->getAwardable() == false)
+               {
+                 if((army->getBattlesNumber())>10 && 
+                    !(army->getMedalBonus(2)))
+                   {
+                     army->setMedalBonus(2,true);
+                     // We must recalculate the XPValue of this unit since it 
+                     // got a medal
+                     army->setXpReward(army->getXpReward()+1);
+                     // We get the medal bonus here
+                     army->setStat(Army::STRENGTH, army->getStat(Army::STRENGTH, false)+1);
+                     // Emit signal
+                     snewMedalArmy.emit(army, 2);
+                   }
+
+                 debug("Army hits " <<  army->getNumberHasHit())
+
+                   // Only give medals if the unit has attacked often enough, else
+                   // medals lose the flair of something special; a value of n 
+                   // means roughly to hit an equally strong unit around n 
+                   // times. (note: one hit! An attack can consist of up to 
+                   // strength hits)
+                   if((army->getNumberHasHit()>50) && !army->getMedalBonus(0))
+                     {
+                       army->setMedalBonus(0,true);
+                       // We must recalculate the XPValue of this unit since it
+                       // got a medal
+                       army->setXpReward(army->getXpReward()+1);
+                       // We get the medal bonus here
+                       army->setStat(Army::STRENGTH, army->getStat(Army::STRENGTH, false)+1);
+                       // Emit signal
+                       snewMedalArmy.emit(army, 0);
+                     }
+
+                 debug("army being hit " <<  army->getNumberHasBeenHit())
+
+                   // Gives the medal for good defense. The more negative the 
+                   // number the more blows the unit evaded. n means roughly 
+                   // avoid n hits from an equally strong unit. Since we want 
+                   // to punish the case of the unit hiding among many others, 
+                   // we set this value quite high.
+                   if((army->getNumberHasBeenHit() < -100) && !army->getMedalBonus(1))
+                     {
+                       army->setMedalBonus(1,true);
+                       // We must recalculate the XPValue of this unit since it 
+                       // got a medal
+                       army->setXpReward(army->getXpReward()+1);
+                       // We get the medal bonus here
+                       army->setStat(Army::STRENGTH, army->getStat(Army::STRENGTH, false)+1);
+                       // Emit signal
+                       snewMedalArmy.emit(army, 1);
+                     }
+                 debug("Army hits " <<  army->getNumberHasHit())
+
+                   for(int i=0;i<3;i++)
+                     {
+                       debug("MEDAL[" << i << "]==" << army->getMedalBonus(i))
+                     }
+               }
+
+           // We reset the hit values after the battle
+           army->setNumberHasHit(0);
+           army->setNumberHasBeenHit(0);
+
+           if (army->isHero() && getType() != Player::NETWORKED)
+             {
+               Hero *h = dynamic_cast<Hero*>(army);
+               while(h->canGainLevel())
+                 {
+                   // Units not associated to a player never raise levels.
+                   if (h->getOwner() == 
+                       Playerlist::getInstance()->getNeutral())
+                     break;
+
+                   //Here this for is to check if army must raise 2 or more 
+                   //levels per time depending on the XP and level itself
+
+                   h->getOwner()->heroGainsLevel(h);
+                 }
+               debug("Hero new XP=" << h->getXP())
+             }
+           sit++;
+         }
+      it++;
+    }
+}
+
+Hero* Player::doRecruitHero(HeroProto* herotemplate, City *city, int cost, int alliesCount, const ArmyProto *ally)
+{
+  Hero *newhero = new Hero(*herotemplate);
+  newhero->setOwner(this);
+  GameMap::getInstance()->addArmy(city, newhero);
+
+  if (alliesCount > 0)
+    {
+      Reward_Allies::addAllies(this, city->getPos(), ally, alliesCount);
+      hero_arrives_with_allies.emit(alliesCount);
+    }
+
+  if (cost == 0)
+    {
+      // Initially give the first hero the player's standard.
+      std::string name = String::ucompose(_("%1 Standard"), getName());
+      Item *battle_standard = new Item (name, true, this);
+      battle_standard->addBonus(Item::ADD1STACK);
+      newhero->getBackpack()->addToBackpack(battle_standard, 0);
+    }
+  withdrawGold(cost);
+  supdatingStack.emit(0);
+  return newhero;
+}
+
+void Player::recruitHero(HeroProto* heroproto, City *city, int cost, int alliesCount, const ArmyProto *ally)
+{
+  //alright, we may have picked another sex for the hero.
+  HeroProto *h;
+  std::string name = heroproto->getName();
+  Hero::Gender g = Hero::Gender(heroproto->getGender());
+  h = HeroTemplates::getInstance()->getRandomHero(g, getId());
+  h->setGender(g);
+  h->setName(name);
+  Action_RecruitHero *action = new Action_RecruitHero();
+  action->fillData(h, city, cost, alliesCount, ally);
+  addAction(action);
+
+  Hero *hero = doRecruitHero(h, city, cost, alliesCount, ally);
+  if (hero)
+    {
+      History_HeroEmerges *item = new History_HeroEmerges();
+      item->fillData(hero, city);
+      addHistory(item);
+    }
+}
+
+void Player::doDeclareDiplomacy (DiplomaticState state, Player *player)
+{
+  Playerlist *pl = Playerlist::getInstance();
+  if (pl->getNeutral() == player)
+    return;
+  if (player == this)
+    return;
+  if (state == d_diplomatic_state[player->getId()])
+    return;
+  d_diplomatic_state[player->getId()] = state;
+}
+
+void Player::declareDiplomacy (DiplomaticState state, Player *player)
+{
+  doDeclareDiplomacy(state, player);
+
+  Action_DiplomacyState * item = new Action_DiplomacyState();
+  item->fillData(player, state);
+  addAction(item);
+
+  // FIXME: update diplomatic scores? 
+}
+
+void Player::doProposeDiplomacy (DiplomaticProposal proposal, Player *player)
+{
+  if (GameScenarioOptions::s_diplomacy == false)
+    return;
+  Playerlist *pl = Playerlist::getInstance();
+  if (pl->getNeutral() == player)
+    return;
+  if (player == this)
+    return;
+  if (proposal == d_diplomatic_proposal[player->getId()])
+    return;
+  if (proposal == PROPOSE_PEACE)
+    {
+      std::string s = _("Peace negotiated with ") + player->getName();
+      if (getDiplomaticState(player) == AT_PEACE ||
+         getDiplomaticProposal(player) == PROPOSE_PEACE)
+       schangingStatus.emit(s);
+    }
+  else if (proposal == PROPOSE_WAR)
+    {
+      std::string s = _("War declared with ") + player->getName();
+      if (getDiplomaticState(player) == AT_WAR ||
+         getDiplomaticProposal(player) == PROPOSE_WAR)
+      schangingStatus.emit(s);
+    }
+  d_diplomatic_proposal[player->getId()] = proposal;
+}
+
+void Player::proposeDiplomacy (DiplomaticProposal proposal, Player *player)
+{
+  doProposeDiplomacy(proposal, player);
+
+  Action_DiplomacyProposal * item = new Action_DiplomacyProposal();
+  item->fillData(player, proposal);
+  addAction(item);
+
+  // FIXME: update diplomatic scores? 
+}
+
+Player::DiplomaticState Player::negotiateDiplomacy (Player *player)
+{
+  DiplomaticState state = getDiplomaticState(player);
+  DiplomaticProposal them = player->getDiplomaticProposal(this);
+  DiplomaticProposal me = getDiplomaticProposal(player);
+  DiplomaticProposal winning_proposal;
+
+  /* Check if we both want the status quo. */
+  if (me == NO_PROPOSAL && them == NO_PROPOSAL)
+    return state;
+
+  /* Okay, we both want a change from the status quo. */
+
+  /* In the absense of a new proposal, the status quo is the proposal. */
+  if (me == NO_PROPOSAL)
+    {
+      switch (state)
+       {
+       case AT_PEACE: me = PROPOSE_PEACE; break;
+       case AT_WAR_IN_FIELD: me = PROPOSE_WAR_IN_FIELD; break;
+       case AT_WAR: me = PROPOSE_WAR; break;
+       }
+    }
+  if (them == NO_PROPOSAL)
+    {
+      switch (state)
+       {
+       case AT_PEACE: them = PROPOSE_PEACE; break;
+       case AT_WAR_IN_FIELD: them = PROPOSE_WAR_IN_FIELD; break;
+       case AT_WAR: them = PROPOSE_WAR; break;
+       }
+    }
+
+  /* Check if we have agreement. */
+  if (me == PROPOSE_PEACE && them == PROPOSE_PEACE)
+    return AT_PEACE;
+  else if (me == PROPOSE_WAR_IN_FIELD && them == PROPOSE_WAR_IN_FIELD)
+    return AT_WAR_IN_FIELD;
+  else if (me == PROPOSE_WAR && them == PROPOSE_WAR)
+    return AT_WAR;
+
+  /* Still we don't have an agreement.  
+     Unfortunately the greater violence is the new diplomatic state. 
+     Because there are two different proposals and the proposal with
+     greater violence will be the new status quo, there can't 
+     possibly be peace at this juncture.  */
+
+  winning_proposal = me;
+  if (them > me)
+    winning_proposal = them;
+
+  switch (winning_proposal)
+    {
+    case PROPOSE_WAR_IN_FIELD: return AT_WAR_IN_FIELD; break;
+    case PROPOSE_WAR: return AT_WAR; break;
+    default: return AT_PEACE; break; //impossible
+    }
+
+}
+
+Player::DiplomaticState Player::getDiplomaticState (Player *player) const
+{
+  if (player == Playerlist::getInstance()->getNeutral())
+    return AT_WAR;
+  if (player == this)
+    return AT_PEACE;
+  return d_diplomatic_state[player->getId()];
+}
+
+Player::DiplomaticProposal Player::getDiplomaticProposal (Player *player) const
+{
+  if (player == Playerlist::getInstance()->getNeutral())
+    return PROPOSE_WAR;
+  if (player == this)
+    return NO_PROPOSAL;
+  return d_diplomatic_proposal[player->getId()];
+}
+
+guint32 Player::getDiplomaticScore (Player *player) const
+{
+  Playerlist *pl = Playerlist::getInstance();
+  if (pl->getNeutral() == player)
+    return 8;
+  return d_diplomatic_score[player->getId()];
+}
+
+void Player::alterDiplomaticRelationshipScore (Player *player, int amount)
+{
+  if (amount > 0)
+    {
+      if (d_diplomatic_score[player->getId()] + amount > DIPLOMACY_MAX_SCORE)
+       d_diplomatic_score[player->getId()] = DIPLOMACY_MAX_SCORE;
+      else
+       d_diplomatic_score[player->getId()] += amount;
+    }
+  else if (amount < 0)
+    {
+      if ((guint32) (amount * -1) > d_diplomatic_score[player->getId()])
+       d_diplomatic_score[player->getId()] = DIPLOMACY_MIN_SCORE;
+      else
+       d_diplomatic_score[player->getId()] += amount;
+    }
+}
+
+void Player::improveDiplomaticRelationship (Player *player, guint32 amount)
+{
+  Playerlist *pl = Playerlist::getInstance();
+  if (pl->getNeutral() == player || player == this)
+    return;
+
+  alterDiplomaticRelationshipScore (player, amount);
+
+  Action_DiplomacyScore* item = new Action_DiplomacyScore();
+  item->fillData(player, amount);
+  addAction(item);
+}
+
+void Player::deteriorateDiplomaticRelationship (Player *player, guint32 amount)
+{
+  Playerlist *pl = Playerlist::getInstance();
+  if (pl->getNeutral() == player || player == this)
+    return;
+
+  alterDiplomaticRelationshipScore (player, -amount);
+
+  Action_DiplomacyScore* item = new Action_DiplomacyScore();
+  item->fillData(player, -amount);
+  addAction(item);
+}
+
+void Player::deteriorateDiplomaticRelationship (guint32 amount)
+{
+  Playerlist *pl = Playerlist::getInstance();
+  for (Playerlist::iterator it = pl->begin(); it != pl->end(); ++it)
+    {
+      if ((*it)->isDead())
+       continue;
+      if (pl->getNeutral() == (*it))
+       continue;
+      if (*it == this)
+       continue;
+      (*it)->deteriorateDiplomaticRelationship (this, amount);
+    }
+}
+
+void Player::improveDiplomaticRelationship (guint32 amount, Player *except)
+{
+  Playerlist *pl = Playerlist::getInstance();
+  for (Playerlist::iterator it = pl->begin(); it != pl->end(); ++it)
+    {
+      if ((*it)->isDead())
+       continue;
+      if (pl->getNeutral() == (*it))
+       continue;
+      if (*it == this)
+       continue;
+      if (except && *it == except)
+       continue;
+      (*it)->improveDiplomaticRelationship (this, amount);
+    }
+}
+
+void Player::deteriorateAlliesRelationship(Player *player, guint32 amount,
+                                          Player::DiplomaticState state)
+{
+  Playerlist *pl = Playerlist::getInstance();
+  for (Playerlist::iterator it = pl->begin(); it != pl->end(); ++it)
+    {
+      if ((*it)->isDead())
+       continue;
+      if (pl->getNeutral() == (*it))
+       continue;
+      if (*it == this)
+       continue;
+      if (getDiplomaticState(*it) == state)
+       (*it)->deteriorateDiplomaticRelationship (player, amount);
+    }
+}
+
+void Player::improveAlliesRelationship(Player *player, guint32 amount,
+                                      Player::DiplomaticState state)
+{
+  Playerlist *pl = Playerlist::getInstance();
+  for (Playerlist::iterator it = pl->begin(); it != pl->end(); ++it)
+    {
+      if ((*it)->isDead())
+       continue;
+      if (pl->getNeutral() == (*it))
+       continue;
+      if (*it == this)
+       continue;
+      if (player->getDiplomaticState(*it) == state)
+       (*it)->improveDiplomaticRelationship (this, amount);
+    }
+}
+
+void Player::AI_maybeBuyScout(City *c)
+{
+  bool one_turn_army_exists = false;
+  //do we already have something that can be produced in one turn?
+  for (unsigned int i = 0; i < c->getMaxNoOfProductionBases(); i++)
+    {
+      if (c->getArmytype(i) == -1)    // no production in this slot
+        continue;
+
+      const ArmyProdBase *proto = c->getProductionBase(i);
+      if (proto->getProduction() == 1)
+        {
+          one_turn_army_exists = true;
+          break;
+        }
+    }
+  if (one_turn_army_exists == false)
+    {
+      const Armysetlist* al = Armysetlist::getInstance();
+      int free_slot = c->getFreeSlot();
+      if (free_slot == -1)
+        free_slot = 0;
+      ArmyProto *scout = al->getScout(getArmyset());
+      cityBuyProduction(c, free_slot, scout->getTypeId());
+    }
+}
+
+bool Player::AI_maybePickUpItems(Stack *s, int max_dist, int max_mp, 
+                                bool &picked_up, bool &stack_died)
+{
+  int min_dist = -1;
+  bool stack_moved = false;
+  Vector<int> item_tile(-1, -1);
+
+  // do we not have a hero?
+  if (s->hasHero() == false)
+    return false;
+
+  //ok, which bag of stuff is closest?
+  std::vector<Vector<int> > tiles = GameMap::getInstance()->getItems();
+  std::vector<Vector<int> >::iterator it = tiles.begin();
+  for(; it != tiles.end(); it++)
+    {
+      Vector<int> tile = *it;
+      //don't consider bags of stuff that are inside enemy cities
+      City *c = GameMap::getCity(tile);
+      if (c)
+       {
+         if (c->getOwner() != s->getOwner())
+           continue;
+       }
+
+      int distance = dist (tile, s->getPos());
+      if (distance < min_dist || min_dist == -1)
+       {
+         min_dist = distance;
+         item_tile = tile;
+       }
+    }
+
+  //if no bags of stuff, or the bag is too far away
+  if (min_dist == -1 || min_dist > max_dist)
+    return false;
+
+  //are we not standing on it?
+  if (s->getPos() != item_tile)
+    {
+      //can we really reach it?
+      Vector<int> old_dest(-1,-1);
+      if (s->getPath()->size())
+       old_dest = s->getLastPointInPath();
+      guint32 mp = s->getPath()->calculate(s, item_tile);
+      if ((int)mp > max_mp)
+       {
+         //nope.  unreachable.  set in our old path.
+         if (old_dest != Vector<int>(-1,-1))
+           s->getPath()->calculate(s, old_dest);
+         return false;
+       }
+      stack_moved = stackMove(s);
+      //maybe we died -- an enemy stack was guarding the bag.
+      if (!d_stacklist->getActivestack())
+       {
+         stack_died = true;
+         return true;
+       }
+      s = d_stacklist->getActivestack();
+    }
+
+  //are we standing on it now?
+  if (s->getPos() == item_tile)
+    {
+      Hero *hero = static_cast<Hero*>(s->getFirstHero());
+      if (hero)
+       picked_up = heroPickupAllItems(hero, s->getPos());
+    }
+
+  return stack_moved;
+}
+
+bool Player::AI_maybeVisitTempleForQuest(Stack *s, int dist, int max_mp, 
+                                         bool &stack_died)
+{
+  bool stack_moved = false;
+  Templelist *tl = Templelist::getInstance();
+
+  //if this stack doesn't have a hero then we can't get a quest with this stack.
+  if (s->hasHero() == false)
+    return false;
+
+  //if the player already has a hero who has a quest, then we can't get a
+  //quest with this stack when playing one quest per player.
+  if (QuestsManager::getInstance()->getPlayerQuests(this).size() > 0 &&
+      GameScenarioOptions::s_play_with_quests == 
+      GameParameters::ONE_QUEST_PER_PLAYER)
+    return false;
+
+  Temple *temple = tl->getNearestVisibleTemple(s->getPos(), dist);
+  if (!temple)
+    return false;
+
+  //if we're not there yet
+  if (temple->contains(s->getPos()) == false)
+    {
+      //can we really reach it?
+      Vector<int> old_dest(-1,-1);
+      if (s->getPath()->size())
+       old_dest = s->getLastPointInPath();
+      guint32 mp = s->getPath()->calculate(s, temple->getPos());
+      if ((int)mp > max_mp)
+       {
+         //nope.  unreachable.  set in our old path.
+         if (old_dest != Vector<int>(-1,-1))
+           s->getPath()->calculate(s, old_dest);
+         return false;
+       }
+      stack_moved = stackMove(s);
+
+      //maybe we died -- an enemy stack was guarding the temple
+      if (!d_stacklist->getActivestack())
+       {
+         stack_died = true;
+         return true;
+       }
+      s = d_stacklist->getActivestack();
+    }
+
+  //are we there yet?
+  if (temple->contains(s->getPos()) == true)
+    svisitingTemple.emit(temple, s);
+
+  return stack_moved;
+}
+
+bool Player::AI_maybeVisitRuin(Stack *s, int dist, int max_mp, 
+                                         bool &stack_died)
+{
+  bool stack_moved = false;
+  Ruinlist *rl = Ruinlist::getInstance();
+
+  //if this stack doesn't have a hero then we can't search the ruin.
+  if (s->hasHero() == false)
+    return false;
+
+  Ruin *ruin = rl->getNearestUnsearchedRuin(s->getPos(), dist);
+  if (!ruin)
+    return false;
+
+  //if we're not there yet
+  if (ruin->contains(s->getPos()) == false)
+    {
+      //can we really reach it?
+      Vector<int> old_dest(-1,-1);
+      if (s->getPath()->size())
+       old_dest = s->getLastPointInPath();
+      guint32 mp = s->getPath()->calculate(s, ruin->getPos());
+      if ((int)mp > max_mp)
+       {
+         //nope.  unreachable.  set in our old path.
+         if (old_dest != Vector<int>(-1,-1))
+           s->getPath()->calculate(s, old_dest);
+         return false;
+       }
+      stack_moved = stackMove(s);
+
+      //maybe we died -- an enemy stack was guarding the temple
+      if (!d_stacklist->getActivestack())
+       {
+         stack_died = true;
+         return true;
+       }
+      s = d_stacklist->getActivestack();
+    }
+
+  //are we there yet?
+  if (ruin->contains(s->getPos()) == true)
+    ssearchingRuin.emit(ruin, s);
+
+  return stack_moved;
+}
+bool Player::AI_maybeVisitTempleForBlessing(Stack *s, int dist, int max_mp, 
+                                           double percent_can_be_blessed, 
+                                           bool &blessed, bool &stack_died)
+{
+  bool stack_moved = false;
+  Templelist *tl = Templelist::getInstance();
+
+  Temple *temple = tl->getNearestVisibleAndUsefulTemple(s, percent_can_be_blessed, dist);
+  if (!temple)
+    return false;
+
+  //if we're not there yet
+  if (s->getPos() != temple->getPos())
+    {
+      //can we really reach it?
+      Vector<int> old_dest(-1,-1);
+      if (s->getPath()->size())
+       old_dest = s->getLastPointInPath();
+      guint32 mp = s->getPath()->calculate(s, temple->getPos());
+      if ((int)mp > max_mp)
+       {
+         //nope.  unreachable.  set in our old path.
+         if (old_dest != Vector<int>(-1,-1))
+           s->getPath()->calculate(s, old_dest);
+         return false;
+       }
+      stack_moved = stackMove(s);
+
+      //maybe we died -- an enemy stack was guarding the temple
+      if (!d_stacklist->getActivestack())
+       {
+         stack_died = true;
+         return true;
+       }
+      s = d_stacklist->getActivestack();
+    }
+
+  int num_blessed = 0;
+  //are we there yet?
+  if (s->getPos() == temple->getPos())
+    {
+      num_blessed = stackVisitTemple(s, temple);
+    }
+
+  blessed = num_blessed > 0;
+  return stack_moved;
+}
+
+bool Player::safeFromAttack(City *c, guint32 safe_mp, guint32 min_defenders)
+{
+  //if there isn't an enemy city nearby to the source
+  // calculate mp to nearest enemy city
+  //   needs to be less than 18 mp with a scout
+  //does the source city contain at least 3 defenders?
+
+  City *enemy_city = Citylist::getInstance()->getNearestEnemyCity(c->getPos());
+  if (enemy_city)
+    {
+      PathCalculator pc(c->getOwner(), c->getPos());
+      int mp = pc.calculate(enemy_city->getPos());
+      if (mp <= 0 || mp >= (int)safe_mp)
+       {
+         if (c->countDefenders() >= min_defenders)
+           return true;
+       }
+    }
+
+  return false;
+}
+
+bool Player::AI_maybeDisband(Stack *s, int safe_mp, bool &stack_killed)
+{
+  bool disbanded = false;
+  //see if we're near to enemy stacks
+  PathCalculator pc(s);
+  if (GameMap::getEnemyStacks(pc.getReachablePositions(safe_mp)).size() > 0)
+    return false;
+
+  //upgroup the whole stack if it doesn't contain a hero
+  if (s->hasHero() == false)
+    {
+      stack_killed = stackDisband (s);
+      return stack_killed;
+    }
+
+  //ungroup the lucky ones not being disbanded
+  for (Stack::reverse_iterator i = s->rbegin(); i != s->rend(); i++)
+    {
+      if ((*i)->isHero() == false)
+       {
+         Stack *new_stack = stackSplitArmy(s, *i);
+         if (new_stack)
+           {
+           if (stackDisband(new_stack))
+             disbanded = true;
+           }
+       }
+    }
+  return disbanded;
+}
+
+bool Player::AI_maybeDisband(Stack *s, City *city, guint32 min_defenders, 
+                            int safe_mp, bool &stack_killed)
+{
+  bool disbanded = false;
+  //is the city in danger from a city?
+  if (safeFromAttack(city, safe_mp, 0) == false)
+    return false;
+
+  if (city->countDefenders() - s->size() >= min_defenders)
+    {
+      if (s->hasHero())
+       min_defenders = s->size() + 1;
+      else
+       {
+         stack_killed = stackDisband(s);
+         return stack_killed;
+       }
+    }
+
+  //okay, we need to disband part of our stack
+
+  //before we move, ungroup the lucky ones not being disbanded
+  unsigned int count = 0;
+  for (Stack::reverse_iterator i = s->rbegin(); i != s->rend(); i++)
+    {
+      if (count == min_defenders)
+       break;
+      if ((*i)->isHero() == false)
+       {
+         Stack *new_stack = stackSplitArmy(s, *i);
+         if (new_stack)
+           {
+             count++;
+             if (stackDisband(new_stack))
+               disbanded = true;
+           }
+       }
+    }
+  return disbanded;
+}
+
+bool Player::AI_maybeVector(City *c, guint32 safe_mp, guint32 min_defenders,
+                           City *target, City **vector_city)
+{
+  assert (c->getOwner() == this);
+  if (vector_city)
+    *vector_city = NULL;
+  Citylist *cl = Citylist::getInstance();
+
+  //is this city producing anything that we can vector?
+  if (c->getActiveProductionSlot() == -1)
+    return false;
+
+  //is it safe to vector from this city?
+  bool safe = safeFromAttack(c, 18, 3);
+
+  if (!safe)
+    return false;
+
+  //get the nearest city to the enemy city that can accept vectored units
+  City *near_city = cl->getNearestFriendlyVectorableCity(target->getPos());
+  if (!near_city)
+    return false;
+  assert (near_city->getOwner() == this);
+  if (GameMap::getCity(near_city->getPos()) != near_city)
+    {
+      printf("nearCity is %s (%d)\n", near_city->getName().c_str(), near_city->getId());
+      printf("it is located at %d,%d\n", near_city->getPos().x, near_city->getPos().y);
+      City *other = GameMap::getCity(near_city->getPos());
+      if (other)
+       {
+      printf("the OTHER nearCity is %s (%d)\n", other->getName().c_str(), other->getId());
+      printf("it is located at %d,%d\n", other->getPos().x, other->getPos().y);
+       }
+      else
+       printf("no city there!\n");
+      assert (1 == 0);
+    }
+
+  //if it's us then it's easier to just walk.
+  if (near_city == c)
+    return false;
+
+  //is that city already vectoring?
+  if (near_city->getVectoring() != Vector<int>(-1, -1))
+    return false;
+
+  //can i just walk there faster?
+
+  //find mp from source to target city
+  const ArmyProdBase *proto = c->getActiveProductionBase();
+  PathCalculator pc1(c->getOwner(), c->getPos(), proto);
+  int mp_from_source_city = pc1.calculate(target->getPos());
+
+  //find mp from nearer vectorable city to target city
+  PathCalculator pc2(c->getOwner(), near_city->getPos(), proto);
+  int mp_from_near_city = pc2.calculate(target->getPos());
+
+  guint32 max_moves_per_turn = proto->getMaxMoves();
+
+  double turns_to_move_from_source_city = 
+    (double)mp_from_source_city / (double)max_moves_per_turn;
+  double turns_to_move_from_near_city = 
+    (double)mp_from_near_city / (double)max_moves_per_turn;
+  turns_to_move_from_near_city += 1.0; //add extra turn to vector
+
+  //yes i can walk there faster, so don't vector
+  if (turns_to_move_from_source_city <= turns_to_move_from_near_city)
+    return false;
+
+  //great.  now do the vectoring.
+  c->changeVectorDestination(near_city->getPos());
+
+  if (vector_city)
+    *vector_city = near_city;
+  return true;
+}
+
+void Player::AI_setupVectoring(guint32 safe_mp, guint32 min_defenders,
+                              guint32 mp_to_front)
+{
+  Citylist *cl = Citylist::getInstance();
+  //turn off vectoring where it isn't safe anymore
+  //turn off vectoring for destinations that are far away from the
+  //nearest enemy city
+
+
+  for (Citylist::iterator cit = cl->begin(); cit != cl->end(); ++cit)
+    {
+      sbusy.emit();
+      City *c = *cit;
+      if (c->getOwner() != this || c->isBurnt())
+       continue;
+      Vector<int> dest = c->getVectoring();
+      if (dest == Vector<int>(-1, -1))
+       continue;
+      if (safeFromAttack(c, safe_mp, min_defenders) == false)
+       {
+         //City *target_city = Citylist::getInstance()->getObjectAt(dest);
+         //debug("stopping vectoring from " << c->getName() <<" to " << target_city->getName() << " because it's not safe to anymore!\n")
+         c->setVectoring(Vector<int>(-1,-1));
+         continue;
+       }
+
+      City *enemy_city = cl->getNearestEnemyCity(dest);
+      if (!enemy_city)
+       {
+         //City *target_city = Citylist::getInstance()->getObjectAt(dest);
+         //debug("stopping vectoring from " << c->getName() <<" to " << target_city->getName() << " because there aren't any more enemy cities!\n")
+         c->setVectoring(Vector<int>(-1,-1));
+         continue;
+       }
+
+      PathCalculator pc(this, dest, NULL);
+      int mp = pc.calculate(enemy_city->getPos());
+      if (mp <= 0 || mp > (int)mp_to_front)
+       {
+
+         //City *target_city = Citylist::getInstance()->getObjectAt(dest);
+         //debug("stopping vectoring from " << c->getName() <<" to " << target_city->getName() << " because it's too far away from an enemy city!\n")
+         c->setVectoring(Vector<int>(-1,-1));
+         continue;
+       }
+    }
+
+  for (Citylist::iterator cit = cl->begin(); cit != cl->end(); ++cit)
+    {
+      sbusy.emit();
+      City *c = *cit;
+      if (c->getOwner() != this || c->isBurnt())
+       continue;
+      City *enemy_city = cl->getNearestEnemyCity(c->getPos());
+      if (!enemy_city)
+       continue;
+      City *vector_city = NULL;
+      //if the city isn't already vectoring
+      if (c->getVectoring() == Vector<int>(-1,-1))
+       {
+         bool vectored = AI_maybeVector(c, safe_mp, min_defenders, enemy_city, 
+                                        &vector_city);
+         if (vectored)
+           debug("begin vectoring from " << c->getName() <<" to " << vector_city->getName() << "!\n");
+       }
+    }
+}
+
+const Army * Player::doCityProducesArmy(City *city, Vector<int> &pos)
+{
+  int cost = city->getActiveProductionBase()->getProductionCost();
+  if (cost > d_gold)
+    return NULL;
+  withdrawGold(cost);
+  const Army *a = city->armyArrives(pos);
+  return a;
+}
+
+bool Player::cityProducesArmy(City *city)
+{
+  assert(city->getOwner() == this);
+  Action_Produce *item = new Action_Produce();
+  Vector<int> pos;
+  const Army *army = doCityProducesArmy(city, pos);
+  if (army)
+    {
+      const ArmyProdBase *source_army;
+      source_army = city->getProductionBaseBelongingTo(army);
+      if (city->getVectoring() == Vector<int>(-1, -1))
+       item->fillData(source_army, city, false, pos, army->getId());
+      else
+       item->fillData(source_army, city, true, city->getVectoring(), army->getId());
+      addAction(item);
+    }
+  return true;
+}
+
+Army* Player::doVectoredUnitArrives(VectoredUnit *unit)
+{
+  Army *army = unit->armyArrives();
+  return army;
+}
+
+bool Player::vectoredUnitArrives(VectoredUnit *unit)
+{
+  Action_ProduceVectored *item = new Action_ProduceVectored();
+  item->fillData(unit->getArmy(), unit->getDestination(), unit->getPos());
+  addAction(item);
+  Army *army = doVectoredUnitArrives(unit);
+  if (!army)
+    {
+      printf("this was supposed to be impossible because of operations on the vectoredunitlist after the city is conquered.\n");
+      printf("whooops... this vectored unit failed to show up.\n");
+      City *dest = GameMap::getCity(unit->getDestination());
+      printf("the unit was being vectored to: %s, from %s by %s\n", 
+            dest->getName().c_str(), 
+            GameMap::getCity(unit->getPos())->getName().c_str(), getName().c_str());
+      printf("Army is a %s, turns is %d + 1\n", unit->getArmy()->getName().c_str(), unit->getArmy()->getProduction());
+
+      
+      int turn = -1;
+  std::list<History*> h = dest->getOwner()->getHistoryForCityId(dest->getId());
+  std::list<History*>::const_iterator pit;
+  for (pit = h.begin(); pit != h.end(); pit++)
+    {
+      switch ((*pit)->getType())
+       {
+       case History::START_TURN:
+           {
+             turn++;
+             break;
+           }
+       case History::CITY_WON:
+           {
+             History_CityWon *event;
+             event = dynamic_cast<History_CityWon*>(*pit);
+             //printf("on turn %d, player %s took %s\n", turn, dest->getOwner()->getName().c_str(), dest->getName().c_str());
+             break;
+           }
+       case History::CITY_RAZED:
+           {
+             History_CityRazed *event;
+             event = dynamic_cast<History_CityRazed*>(*pit);
+             printf("on turn %d, player %s razed %s\n", turn, dest->getOwner()->getName().c_str(), dest->getName().c_str());
+             break;
+           }
+       default:
+         break;
+       }
+    }
+      printf("was the destination city owned by us way back then?\n");
+      exit (1);
+    }
+
+  return true;
+}
+
+std::list<Action_Produce *> Player::getUnitsProducedThisTurn() const
+{
+  std::list<Action_Produce *> actions;
+  std::list<Action *>::const_reverse_iterator it = d_actions.rbegin();
+  for (; it != d_actions.rend(); it++)
+    {
+      if ((*it)->getType() == Action::PRODUCE_UNIT)
+       actions.push_back(dynamic_cast<Action_Produce*>(*it));
+      else if ((*it)->getType() == Action::INIT_TURN)
+       break;
+    }
+  return actions;
+}
+std::list<Action *> Player::getReportableActions() const
+{
+  std::list<Action *> actions;
+  std::list<Action *>::const_iterator it = d_actions.begin();
+  for (; it != d_actions.end(); it++)
+    {
+      if ((*it)->getType() == Action::PRODUCE_UNIT ||
+         (*it)->getType() == Action::PRODUCE_VECTORED_UNIT ||
+         (*it)->getType() == Action::CITY_DESTITUTE)
+       actions.push_back(*it);
+    }
+  return actions;
+}
+
+void Player::cityTooPoorToProduce(City *city, int slot)
+{
+  cityChangeProduction(city, -1);
+  const ArmyProdBase *a = city->getProductionBase(slot);
+  Action_CityTooPoorToProduce *action = new Action_CityTooPoorToProduce();
+  action->fillData(city, a);
+  addAction(action);
+}
+
+void Player::pruneActionlist()
+{
+  pruneActionlist(d_actions);
+}
+
+void Player::pruneCityProductions(std::list<Action*> actions)
+{
+  //remove duplicate city production actions
+
+  //enumerate the ones we want
+  std::list<Action_Production*> keepers;
+  std::list<Action*>::reverse_iterator ait;
+  for (ait = actions.rbegin(); ait != actions.rend(); ait++)
+    {
+      if ((*ait)->getType() != Action::CITY_PROD)
+       continue;
+      //if this city isn't already in the keepers list, then add it.
+
+      Action_Production *action = static_cast<Action_Production*>(*ait);
+      bool found = false;
+      std::list<Action_Production*>::const_iterator it;
+      for (it = keepers.begin(); it != keepers.end(); it++)
+       {
+         if (action->getCityId() == (*it)->getCityId())
+           {
+             found = true;
+             break;
+           }
+       }
+      if (found == false)
+       keepers.push_back(action);
+
+    }
+
+  //now delete all city production events that aren't in keepers
+  int total = 0;
+  std::list<Action*>::iterator bit;
+  for (bit = actions.begin(); bit != actions.end(); bit++)
+    {
+      if ((*bit)->getType() != Action::CITY_PROD)
+       continue;
+      if (find (keepers.begin(), keepers.end(), (*bit)) == keepers.end())
+       {
+         total++;
+         actions.erase (bit);
+         bit = actions.begin();
+         continue;
+       }
+    }
+  //if (total)
+  //printf ("pruned %d city production actions.\n", total);
+}
+
+void Player::pruneCityVectorings(std::list<Action*> actions)
+{
+  //remove duplicate city vectoring actions
+
+  //enumerate the ones we want
+  std::list<Action_Vector*> keepers;
+  std::list<Action*>::reverse_iterator ait;
+  for (ait = actions.rbegin(); ait != actions.rend(); ait++)
+    {
+      if ((*ait)->getType() != Action::CITY_VECTOR)
+       continue;
+      //if this city isn't already in the keepers list, then add it.
+
+      Action_Vector *action = static_cast<Action_Vector *>(*ait);
+      bool found = false;
+      std::list<Action_Vector*>::const_iterator it;
+      for (it = keepers.begin(); it != keepers.end(); it++)
+       {
+         if (action->getCityId() == (*it)->getCityId())
+           {
+             found = true;
+             break;
+           }
+       }
+      if (found == false)
+       keepers.push_back(action);
+
+    }
+
+  //now delete all city vector events that aren't in keepers
+  int total = 0;
+  std::list<Action*>::iterator bit;
+  for (bit = actions.begin(); bit != actions.end(); bit++)
+    {
+      if ((*bit)->getType() != Action::CITY_VECTOR)
+       continue;
+      if (find (keepers.begin(), keepers.end(), (*bit)) == keepers.end())
+       {
+         total++;
+         actions.erase (bit);
+         bit = actions.begin();
+         continue;
+       }
+    }
+  //if (total)
+  //printf ("pruned %d city vector actions.\n", total);
+}
+
+void Player::pruneActionlist(std::list<Action*> actions)
+{
+  pruneCityProductions(actions);
+  pruneCityVectorings(actions);
+
+}
+
+std::string Player::playerTypeToString(const Player::Type type)
+{
+  switch (type)
+    {
+    case Player::HUMAN:
+      return "Player::HUMAN";
+    case Player::AI_FAST:
+      return "Player::AI_FAST";
+    case Player::AI_DUMMY:
+      return "Player::AI_DUMMY";
+    case Player::AI_SMART:
+      return "Player::AI_SMART";
+    case Player::NETWORKED:
+      return "Player::NETWORKED";
+    }
+  return "Player::HUMAN";
+}
+
+Player::Type Player::playerTypeFromString(const std::string str)
+{
+  if (str.size() > 0 && isdigit(str.c_str()[0]))
+    return Player::Type(atoi(str.c_str()));
+  if (str == "Player::HUMAN")
+    return Player::HUMAN;
+  else if (str == "Player::AI_FAST")
+    return Player::AI_FAST;
+  else if (str == "Player::AI_DUMMY")
+    return Player::AI_DUMMY;
+  else if (str == "Player::AI_SMART")
+    return Player::AI_SMART;
+  else if (str == "Player::NETWORKED")
+    return Player::NETWORKED;
+  return Player::HUMAN;
+}
+
+bool Player::hasAlreadyInitializedTurn() const
+{
+  for (list<Action*>::const_iterator it = d_actions.begin();
+       it != d_actions.end(); it++)
+    if ((*it)->getType() == Action::INIT_TURN)
+      return true;
+  return false;
+}
+
+bool Player::hasAlreadyEndedTurn() const
+{
+  for (list<Action*>::const_iterator it = d_actions.begin();
+       it != d_actions.end(); it++)
+    if ((*it)->getType() == Action::END_TURN)
+      return true;
+  return false;
+}
+
+std::list<History*> Player::getHistoryForThisTurn() const
+{
+  std::list<History*> history;
+  for (list<History*>::const_reverse_iterator it = d_history.rbegin();
+       it != d_history.rend(); it++)
+    {
+      history.push_front(*it);
+      if ((*it)->getType() == History::START_TURN)
+       break;
+    }
+  return history;
+}
+
+guint32 Player::countEndTurnHistoryEntries() const
+{
+  guint32 count = 0;
+  for (list<History*>::const_iterator it = d_history.begin();
+       it != d_history.end(); it++)
+    {
+      if ((*it)->getType() == History::END_TURN)
+       count++;
+    }
+  return count;
+}
+
+void Player::loadPbmGame() 
+{
+  for (list<Action*>::const_iterator it = d_actions.begin();
+       it != d_actions.end(); it++)
+    {
+      NetworkAction *copy = new NetworkAction(*it, getId());
+      acting.emit(copy);
+    }
+  std::list<History*> history = getHistoryForThisTurn();
+  for (list<History*>::const_iterator it = history.begin();
+       it != history.end(); it++)
+    {
+      NetworkHistory *copy = new NetworkHistory(*it, getId());
+      history_written.emit(copy);
+    }
+}
+
+void Player::saveNetworkActions(XML_Helper *helper) const
+{
+  for (list<Action*>::const_iterator it = d_actions.begin();
+       it != d_actions.end(); it++)
+    {
+      NetworkAction *copy = new NetworkAction(*it, getId());
+      copy->save(helper);
+    }
+}
+
+bool Player::searchedRuin(Ruin *r) const
+{
+  if (!r)
+    return false;
+  for (list<History*>::const_iterator it = d_history.begin();
+       it != d_history.end(); it++)
+    {
+      if ((*it)->getType() == History::HERO_RUIN_EXPLORED)
+       {
+         History_HeroRuinExplored *event = 
+            dynamic_cast<History_HeroRuinExplored*>(*it);
+         if (event->getRuinId() == r->getId())
+           return true;
+       }
+    }    
+  return false;
+}
+
+bool Player::conqueredCity(City *c) const
+{
+  if (!c)
+    return false;
+  for (list<History*>::const_iterator it = d_history.begin();
+       it != d_history.end(); it++)
+    {
+      if ((*it)->getType() == History::CITY_WON)
+       {
+         History_CityWon *event = dynamic_cast<History_CityWon*>(*it);
+         if (event->getCityId() == c->getId())
+           return true;
+       }
+    }    
+  return false;
+}
+
+std::list<Vector<int> > Player::getStackTrack(Stack *s) const
+{
+  std::list<Vector<int> > points;
+  Vector<int> delta = Vector<int>(0,0);
+  for (list<Action*>::const_iterator it = d_actions.begin();
+       it != d_actions.end(); it++)
+    {
+      if ((*it)->getType() == Action::STACK_MOVE)
+       {
+         Action_Move *action = dynamic_cast<Action_Move*>(*it);
+         if (action->getStackId() == s->getId())
+           {
+             if (points.size() == 0)
+               delta = action->getPositionDelta();
+             points.push_back(action->getEndingPosition());
+           }
+       }
+    }
+  if (points.size() >= 1)
+    {
+      Vector<int> pos = points.front() + delta;
+      if (pos != points.front())
+       points.push_front(pos);
+    }
+  return points;
+}
+       
+std::list<History *>Player::getHistoryForCityId(guint32 id) const
+{
+  std::list<History*> events;
+  std::list<History*>::const_iterator pit;
+  for (pit = d_history.begin(); pit != d_history.end(); pit++)
+    {
+      switch ((*pit)->getType())
+       {
+       case History::START_TURN:
+           {
+             events.push_back(*pit);
+             break;
+           }
+       case History::CITY_WON:
+           {
+             History_CityWon *event;
+             event = dynamic_cast<History_CityWon*>(*pit);
+             if (event->getCityId() == id)
+               events.push_back(*pit);
+             break;
+           }
+       case History::CITY_RAZED:
+           {
+             History_CityRazed *event;
+             event = dynamic_cast<History_CityRazed*>(*pit);
+             if (event->getCityId() == id)
+               events.push_back(*pit);
+             break;
+           }
+       default:
+         break;
+       }
+    }
+  return events;
+}
+
+std::list<History *>Player::getHistoryForHeroId(guint32 id) const
+{
+  std::string hero_name = "";
+  std::list<History*> events;
+  std::list<History*>::const_iterator pit;
+  for (pit = d_history.begin(); pit != d_history.end(); pit++)
+    {
+      switch ((*pit)->getType())
+       {
+       case History::HERO_EMERGES:
+           {
+             History_HeroEmerges *event;
+             event = dynamic_cast<History_HeroEmerges *>(*pit);
+             if (event->getHeroId() == id)
+               {
+                 hero_name = event->getHeroName();
+                 events.push_back(*pit);
+               }
+             break;
+           }
+       case History::FOUND_SAGE:
+           {
+             History_FoundSage *event;
+             event = dynamic_cast<History_FoundSage*>(*pit);
+             if (event->getHeroName() == hero_name)
+               events.push_back(*pit);
+             break;
+           }
+       case History::HERO_QUEST_STARTED:
+           {
+             History_HeroQuestStarted *event;
+             event = dynamic_cast<History_HeroQuestStarted*>(*pit);
+             if (event->getHeroName() == hero_name)
+               events.push_back(*pit);
+             break;
+           }
+       case History::HERO_QUEST_COMPLETED:
+           {
+             History_HeroQuestCompleted *event;
+             event = dynamic_cast<History_HeroQuestCompleted*>(*pit);
+             if (event->getHeroName() == hero_name)
+               events.push_back(*pit);
+             break;
+           }
+       case History::HERO_KILLED_IN_CITY:
+           {
+             History_HeroKilledInCity *event;
+             event = dynamic_cast<History_HeroKilledInCity*>(*pit);
+             if (event->getHeroName() == hero_name)
+               events.push_back(*pit);
+             break;
+           }
+       case History::HERO_KILLED_IN_BATTLE:
+           {
+             History_HeroKilledInBattle *event;
+             event = dynamic_cast<History_HeroKilledInBattle*>(*pit);
+             if (event->getHeroName() == hero_name)
+               events.push_back(*pit);
+             break;
+           }
+       case History::HERO_KILLED_SEARCHING:
+           {
+             History_HeroKilledSearching*event;
+             event = dynamic_cast<History_HeroKilledSearching*>(*pit);
+             if (event->getHeroName() == hero_name)
+               events.push_back(*pit);
+             break;
+           }
+       case History::HERO_CITY_WON:
+           {
+             History_HeroCityWon *event;
+             event = dynamic_cast<History_HeroCityWon*>(*pit);
+             if (event->getHeroName() == hero_name)
+               events.push_back(*pit);
+             break;
+           }
+       case History::HERO_FINDS_ALLIES:
+           {
+             History_HeroFindsAllies *event;
+             event = dynamic_cast<History_HeroFindsAllies*>(*pit);
+             if (event->getHeroName() == hero_name)
+               events.push_back(*pit);
+             break;
+           }
+       default:
+         break;
+       }
+    }
+  return events;
+}
+
+void Player::setSurrendered(bool surr)
+{
+  surrendered = surr;
+}
+std::list<Hero*> Player::getHeroes() const
+{
+  return d_stacklist->getHeroes();
+}
+guint32 Player::countArmies() const
+{
+  return d_stacklist->countArmies();
+}
+guint32 Player::countAllies() const
+{
+  return d_stacklist->countAllies();
+}
+Stack * Player::getActivestack() const
+{
+  return d_stacklist->getActivestack();
+}
+void Player::setActivestack(Stack *s)
+{
+  d_stacklist->setActivestack(s);
+}
+       
+Vector<int> Player::getPositionOfArmyById(guint32 id) const
+{
+  return d_stacklist->getPosition(id);
+}
+
+void Player::immobilize()
+{
+  d_stacklist->drainAllMovement();
+}
+
+guint32 Player::getCostOfUnitsProducedThisTurn() const
+{
+  guint32 gold = 0;
+  std::list<Action_Produce *> units = getUnitsProducedThisTurn();
+  for (std::list<Action_Produce *>::const_iterator it = units.begin(); it != units.end(); it++)
+    gold +=(*it)->getArmy()->getProductionCost();
+    
+  return gold;
+
+}
+         
+void Player::clearStacklist()
+{
+  d_stacklist->flClear();
+}
+
+void Player::clearFogMap()
+{
+  d_fogmap->fill(FogMap::OPEN);
+}
+
+
+std::list<Action *> Player::getActionsThisTurn(int type) const
+{
+  std::list<Action *> actions;
+  std::list<Action *>::const_iterator it = d_actions.begin();
+  for (; it != d_actions.end(); it++)
+    {
+      if ((*it)->getType() == Action::Type(type))
+       actions.push_back(*it);
+    }
+  return actions;
+}
+std::list<Action *> Player::getFightsThisTurn() const
+{
+  return getActionsThisTurn(Action::STACK_FIGHT);
+}
+
+int Player::countFightsThisTurn() const
+{
+  return getFightsThisTurn().size();
+}
+
+std::list<Action *> Player::getMovesThisTurn() const
+{
+  return getActionsThisTurn(Action::STACK_MOVE);
+}
+
+int Player::countMovesThisTurn() const
+{
+  return getMovesThisTurn().size();
+}
+        
+int Player::countDestituteCitiesThisTurn() const
+{
+  return getActionsThisTurn(Action::CITY_DESTITUTE).size();
+}
+
+Vector<int> Player::AI_getQuestDestination(Quest *quest, Stack *stack) const
+{
+  Playerlist *pl = Playerlist::getInstance();
+  Vector<int> dest = Vector<int>(-1,-1);
+  switch (quest->getType())
+    {
+    case Quest::KILLHERO:
+        {
+          QuestKillHero *q = dynamic_cast<QuestKillHero*>(quest);
+          guint32 hero_id = q->getVictim();
+          Stack *enemy = NULL;
+          for (Playerlist::iterator it = pl->begin(); it != pl->end(); it++)
+            {
+              if (*it == this)
+                continue;
+              enemy = (*it)->getStacklist()->getArmyStackById(hero_id);
+              if(enemy)
+                break;
+            }
+          if (enemy)
+            dest = enemy->getPos();
+
+        }
+      break;
+    case Quest::KILLARMYTYPE:
+        {
+          QuestEnemyArmytype *q = dynamic_cast<QuestEnemyArmytype*>(quest);
+          guint32 army_type = q->getArmytypeToKill();
+          std::list<Stack*> s = 
+            GameMap::getNearbyEnemyStacks(stack->getPos(), GameMap::getWidth());
+          for (std::list<Stack*>::iterator i = s.begin(); i != s.end(); i++)
+            {
+              if ((*i)->hasArmyType(army_type) == true)
+                {
+                  dest = (*i)->getPos();
+                  break;
+                }
+            }
+        }
+      break;
+    case Quest::KILLARMIES:
+        {
+          QuestEnemyArmies *q = dynamic_cast<QuestEnemyArmies*>(quest);
+          Player *enemy = pl->getPlayer(q->getVictimPlayerId());
+          std::list<Stack*> s = 
+            GameMap::getNearbyEnemyStacks(stack->getPos(), GameMap::getWidth());
+          for (std::list<Stack*>::iterator i = s.begin(); i != s.end(); i++)
+            {
+              if ((*i)->getOwner() != enemy)
+                continue;
+              dest = (*i)->getPos();
+            }
+        }
+      break;
+
+    case Quest::PILLAGEGOLD:
+    case Quest::CITYSACK:
+    case Quest::CITYRAZE:
+    case Quest::CITYOCCUPY:
+      //attack the nearest enemy city.
+        {
+          City *c = Citylist::getInstance()->getClosestEnemyCity(stack);
+          if (c)
+            dest = c->getNearestPos(stack->getPos());
+        }
+      break;
+    }
+  return dest;
+}
+
+bool Player::AI_invadeCityQuestPreference(City *c, CityDefeatedAction &action) const
+{
+  bool found = false;
+  std::vector<Quest*> q = QuestsManager::getInstance()->getPlayerQuests(this);
+  for (std::vector<Quest*>::iterator i = q.begin(); i != q.end(); i++)
+    {
+      switch ((*i)->getType())
+        {
+        case Quest::CITYOCCUPY:
+            {
+              QuestCityOccupy* qu = dynamic_cast<QuestCityOccupy*>(*i);
+              if (qu->getCityId() == c->getId())
+                {
+                  action = CITY_DEFEATED_OCCUPY;
+                  found = true;
+                }
+            }
+          break;
+        case Quest::CITYSACK:
+            {
+              QuestCitySack * qu = dynamic_cast<QuestCitySack*>(*i);
+              if (qu->getCityId() == c->getId())
+                {
+                  action = CITY_DEFEATED_SACK;
+                  found = true;
+                }
+            }
+          break;
+        case Quest::CITYRAZE:
+            {
+              QuestCityRaze* qu = dynamic_cast<QuestCityRaze*>(*i);
+              if (qu->getCityId() == c->getId())
+                {
+                  action = CITY_DEFEATED_RAZE;
+                  found = true;
+                }
+            }
+          break;
+        case Quest::PILLAGEGOLD:
+          action = CITY_DEFEATED_SACK;
+          found = true;
+          break;
+        }
+    }
+  return found;
+}
+
+/*
+ *
+ * what are the chances of a hero showing up?
+ *
+ * 1 in 6 if you have enough gold, where "enough gold" is...
+ *
+ * ... 1500 if the player already has a hero, then:  1500 is generally 
+ * enough to buy all the heroes.  I forget the exact distribution of 
+ * hero prices but memory says from 1000 to 1500.  (But, if you don't 
+ * have 1500 gold, and the price is less, you still get the offer...  
+ * So, calculate price, compare to available gold, then decided whether 
+ * or not to offer...)
+ *
+ * ...500 if all your heroes are dead: then prices are cut by about 
+ * a factor of 3.
+ */
+bool Player::maybeRecruitHero ()
+{
+  bool accepted = false;
+  
+  City *city = NULL;
+  int gold_needed = 0;
+  if (Citylist::getInstance()->countCities(this) == 0)
+    return false;
+  //give the player a hero if it's the first round.
+  //otherwise we get a hero based on chance
+  //a hero costs a random number of gold pieces
+  if (GameScenarioOptions::s_round == 1 && getHeroes().size() == 0)
+    gold_needed = 0;
+  else
+    {
+      bool exists = false;
+      if (getHeroes().size() > 0)
+         exists = true; 
+
+      gold_needed = (rand() % 500) + 1000;
+      if (exists == false)
+       gold_needed /= 2;
+    }
+
+  if ((((rand() % 6) == 0 && gold_needed < getGold()) || gold_needed == 0))
+    {
+      HeroProto *heroproto = 
+        HeroTemplates::getInstance()->getRandomHero(getId());
+      if (gold_needed == 0)
+       {
+         //we do it this way because maybe quickstart is on.
+         Citylist* cl = Citylist::getInstance();
+         for (Citylist::iterator it = cl->begin(); it != cl->end(); ++it)
+           if (!(*it)->isBurnt() && (*it)->getOwner() == this &&
+               (*it)->getCapitalOwner() == this && (*it)->isCapital())
+             {
+               city = *it;
+               break;
+             }
+         if (!city) //no capital cities
+           city = Citylist::getInstance()->getFirstCity(this);
+       }
+      else
+       {
+         std::vector<City*> cities;
+         Citylist* cl = Citylist::getInstance();
+         for (Citylist::iterator it = cl->begin(); it != cl->end(); ++it)
+           if (!(*it)->isBurnt() && (*it)->getOwner() == this)
+             cities.push_back((*it));
+         if (cities.empty())
+           return false;
+         city = cities[rand() % cities.size()];
+       }
+
+      if (srecruitingHero.empty())
+        accepted = true;
+      else if (city)
+        accepted = srecruitingHero.emit(heroproto, city, gold_needed);
+
+      if (accepted) {
+        /* now maybe add a few allies */
+        int alliesCount;
+        if (gold_needed > 1300)
+          alliesCount = 3;
+        else if (gold_needed > 1000)
+          alliesCount = 2;
+        else if (gold_needed > 800)
+          alliesCount = 1;
+        else
+          alliesCount = 0;
+
+        const ArmyProto *ally = 0;
+        if (alliesCount > 0)
+        {
+          ally = Reward_Allies::randomArmyAlly();
+          if (!ally)
+            alliesCount = 0;
+        }
+        
+        recruitHero(heroproto, city, gold_needed, alliesCount, ally);
+      }
+    }
+  return accepted;
+}
+// End of file