File indexing completed on 2024-05-12 08:00:45

0001 // kate: space-indent on; indent-width 2; replace-tabs on;
0002 /* This file is part of KsirK.
0003    Copyright (C) 2006-2007 Gael de Chalendar <kleag@free.fr>
0004 
0005    This file was initialy part of XFrisk
0006    Copyright (C) 1995 and later Jean-Claude Colson and Others <who@nowhere.org>
0007 
0008    KsirK is free software; you can redistribute it and/or
0009    modify it under the terms of the GNU General Public
0010    License as published by the Free Software Foundation, either version 2
0011    of the License, or (at your option) any later version.
0012 
0013    This program is distributed in the hope that it will be useful,
0014    but WITHOUT ANY WARRANTY; without even the implied warranty of
0015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0016    General Public License for more details.
0017 
0018    *   You should have received a copy of the GNU General Public License
0019    *   along with this program; if not, write to the Free Software
0020    *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
0021    *   02110-1301, USA
0022    */
0023 /***********************************************************************
0024  *
0025  *   18-8-95  Created by Jean-Claude Colson.
0026  *
0027  *   RISK game player.
0028  *   $Id: aiColson.c,v 1.5 1999/11/07 15:57:29 tony Exp $
0029  *
0030  ***********************************************************************/
0031 
0032 #include "aiColsonPlayer.h"
0033 
0034 #include "onu.h"
0035 #include "goal.h"
0036 #include "continent.h"
0037 #include "gameautomaton.h"
0038 #include "kgamewin.h"
0039 #include "xfriskaiclient.h"
0040 #include "aiplayerio.h"
0041 #include "dice.h"
0042 
0043 #include <assert.h>
0044 
0045 namespace Ksirk
0046 {
0047 
0048 namespace GameLogic
0049 {
0050 
0051 
0052 AIColsonPlayer::AIColsonPlayer(
0053         const QString & nomPlayer, unsigned int nbArmies,
0054         Nationality * myNation,  PlayersArray& players, ONU* world,
0055         GameAutomaton* game ) :
0056   AIPlayer(nomPlayer, nbArmies, myNation, players, world, game ),
0057   m_levelEnemy(0),
0058   m_initialized(false),
0059   Attack_SrcCountry(-1),
0060   Attack_DestCountry(-1),
0061   m_placeData(nullptr)
0062 {
0063   qCDebug(KSIRK_LOG);
0064 }
0065 
0066 AIColsonPlayer::~AIColsonPlayer() 
0067 {
0068   delete m_placeData;
0069 }
0070 
0071 //////////////////////////////////////////////////////////
0072 // Virtual functions reimplemented from AIPlayer
0073 //////////////////////////////////////////////////////////
0074 
0075 QPair< const Country*, const Country* > AIColsonPlayer::chooseBelligerant()
0076 {
0077   qCDebug(KSIRK_LOG);
0078   Fortify();
0079   Country* src = nullptr;
0080   Country* dest = nullptr;
0081   
0082 //   Attack_SrcCountry = -1;
0083 //   Attack_DestCountry = -1;
0084 
0085   // no attack was tempted
0086   if (!Attack())
0087   {
0088     Attack_SrcCountry = -1;
0089     Attack_DestCountry = -1;
0090     return qMakePair<const Country*, const Country*>(static_cast<Country*>(nullptr), static_cast<Country*>(nullptr));
0091   }
0092 
0093   if ( (Attack_SrcCountry>=0) && (Attack_SrcCountry<m_world->getCountries().size() ) )
0094     src = m_world->getCountries().at(Attack_SrcCountry);
0095   if ( (Attack_DestCountry>=0) && (Attack_DestCountry<m_world->getCountries().size() ) )
0096     dest = m_world->getCountries().at(Attack_DestCountry);
0097 //   qCDebug(KSIRK_LOG) << "chose belligerants " << src << " and " << dest;
0098   return qMakePair(src,dest);
0099 }
0100 
0101 /**
0102   * Chooses the next action. Attack by default and if no attack is possible,
0103   * try to move armies and in the last resort, choose next player
0104   */
0105 void AIColsonPlayer::chooseAttackMoveArmiesOrNextPlayer()
0106 {
0107   qCDebug(KSIRK_LOG);
0108   if (m_game->game()->haveAnimFighters() || m_game->game()->haveMovingArmies())
0109   {
0110     return;
0111   }
0112   if (!m_initialized)
0113   {
0114     finalize();
0115   }
0116 
0117   if (!attackAction())
0118   {
0119     if (!moveArmiesAction())
0120     {
0121       nextPlayerAction();
0122     }
0123   }
0124 //    qCDebug(KSIRK_LOG) <<"OUT AIColsonPlayer::chooseAttackMoveArmiesOrNextPlayer()";
0125 }
0126 
0127 /**
0128   * Chooses a country to receive a new army in dotation
0129   */
0130 Country* AIColsonPlayer::chooseReceivingCountry()
0131 {
0132   qCDebug(KSIRK_LOG);
0133   if (m_placeData == nullptr)
0134   {
0135     if (!Place())
0136     {
0137       return nullptr;
0138     }
0139   }
0140   Country* res = m_placeData->dest;
0141   m_placeData->nb--;
0142   if (m_placeData->nb == 0)
0143   {
0144     delete m_placeData;
0145     m_placeData = nullptr;
0146   }
0147   return res;
0148 }
0149 
0150 /**
0151  * chooses to continue invasion with a certain amount of armies or to stop it
0152  */
0153 void AIColsonPlayer::chooseInvasionAction()
0154 {
0155   qCDebug(KSIRK_LOG);
0156   qCDebug(KSIRK_LOG) << "    Attack_SrcCountry  = " << Attack_SrcCountry;
0157   qCDebug(KSIRK_LOG) << "    Attack_DestCountry = " << Attack_DestCountry;
0158   if (Attack_SrcCountry == - 1 || Attack_DestCountry == -1)
0159   {
0160     stop();
0161     QByteArray buffer;
0162     QDataStream stream(&buffer, QIODevice::WriteOnly);
0163     QPointF point;
0164     stream << QString("actionInvasionFinished") << point;
0165     aiPlayerIO()->sendInput(stream,true);
0166     m_toMove = std::numeric_limits< unsigned int>::max();
0167     return;
0168   }
0169 
0170   if (m_toMove == std::numeric_limits< unsigned int>::max())
0171   {
0172     int nbEnemiesAdjacentToSrc = NbToEqualEnemyAdjacent(m_world->getCountries().at(Attack_SrcCountry));
0173     int nbEnemiesAdjacentToDest = NbToEqualEnemyAdjacent(m_world->getCountries().at(Attack_DestCountry));
0174     qCDebug(KSIRK_LOG) << "    nb on src  = " << RISK_GetNumArmiesOfCountry(Attack_SrcCountry);
0175     qCDebug(KSIRK_LOG) << "    nb adj to src  = " << nbEnemiesAdjacentToSrc;
0176     qCDebug(KSIRK_LOG) << "    nb adj to dest = " << nbEnemiesAdjacentToDest;
0177     int diff = nbEnemiesAdjacentToDest - nbEnemiesAdjacentToSrc;
0178     qCDebug(KSIRK_LOG) << "    diff  = " << diff;
0179   
0180   
0181     
0182     m_toMove = (diff>RISK_GetNumArmiesOfCountry(Attack_SrcCountry)-1)?RISK_GetNumArmiesOfCountry(Attack_SrcCountry)-1:(diff<0?0:diff);
0183     qCDebug(KSIRK_LOG) << "    moves " << m_toMove;
0184   }
0185 
0186   QByteArray buffer;
0187   QDataStream stream(&buffer, QIODevice::WriteOnly);
0188   QPoint point;
0189   qCDebug(KSIRK_LOG) << "Moves *****************" << m_toMove;
0190   if (m_toMove >= 10)
0191   {
0192     qCDebug(KSIRK_LOG) << "    choosing actionInvade10";
0193     stop(); 
0194     stream << QString("actionInvade10") << point;
0195     aiPlayerIO()->sendInput(stream,true);
0196     m_toMove -= 10;
0197   }
0198   else if (m_toMove >= 5)
0199   { 
0200     qCDebug(KSIRK_LOG) << "    choosing actionInvade5";
0201     stop();
0202     stream << QString("actionInvade5") << point;
0203     aiPlayerIO()->sendInput(stream,true);
0204     m_toMove -= 5;
0205   }
0206   else if (m_toMove >= 1)
0207   { 
0208     qCDebug(KSIRK_LOG) << "    choosing actionInvade1";
0209     stop();
0210     stream << QString("actionInvade1") << point;
0211     aiPlayerIO()->sendInput(stream,true);
0212     m_toMove--;
0213   }
0214   else
0215   {
0216     qCDebug(KSIRK_LOG) << "    choosing actionInvasionFinished";
0217     stop();
0218     stream << QString("actionInvasionFinished") << point;
0219     aiPlayerIO()->sendInput(stream,true);
0220     m_toMove = std::numeric_limits< unsigned int>::max();
0221   }
0222 }
0223 
0224 /**
0225   * makes all what is necessary to prepare and start the moving of armies
0226   */
0227 bool AIColsonPlayer::moveArmiesAction() 
0228 {
0229   qCDebug(KSIRK_LOG);
0230   bool res = Move();
0231   qCDebug(KSIRK_LOG) << "Move got " << res;
0232   return res;
0233 }
0234 
0235 //////////////////////////////////////////////////////////
0236 // XFrisk AIColson functions
0237 //////////////////////////////////////////////////////////
0238 int AIColsonPlayer::getTotalArmiesOfPlayer(const Player* player)
0239 {
0240   int nb = 0;
0241   for (int i=0; i<m_world->getCountries().size(); i++)
0242   {
0243     if (m_world->getCountries().at(i)->owner() == player)
0244     {
0245       nb += m_world->getCountries().at(i)->nbArmies();
0246     }
0247   }
0248   return nb;
0249 }
0250 
0251 
0252 bool AIColsonPlayer::isContinentOfMission(const Player* player, const Continent* continent)
0253 {
0254   if (player->goal().type() != Goal::Continents)
0255       return false;
0256   return (player->goal().continents().contains(continent->name()));
0257 }
0258 
0259 bool AIColsonPlayer::isEnemyPlayer(const Player* player)
0260 {
0261   return m_isEnemyPlayer[player];
0262 }
0263 
0264 bool AIColsonPlayer::isFriendPlayer(const Player* player)
0265 {
0266 return (player==this);
0267 //   return m_isEnemyPlayer[player] < m_levelEnemy;
0268 }
0269 
0270 int AIColsonPlayer::getNumEnemy()
0271 {
0272   qCDebug(KSIRK_LOG);
0273   int nb = 0;
0274 
0275   PlayersArray::iterator it = m_game->playerList()->begin();
0276   PlayersArray::iterator it_end = m_game->playerList()->end();
0277   for (; it != it_end; it++)
0278   {
0279     if (m_isEnemyPlayer[((Player*)(*it))]>= m_levelEnemy)
0280     {
0281       nb++;
0282     }
0283   }
0284   if (m_levelEnemy == 1)
0285       nb--;
0286   return(nb);
0287 }
0288 
0289 bool AIColsonPlayer::isStrongerPlayer(const Player* player)
0290 {
0291   int nb;
0292 
0293   nb = getTotalArmiesOfPlayer(player);
0294   nb = nb + nb/5;
0295   PlayersArray::iterator it = m_game->playerList()->begin();
0296   PlayersArray::iterator it_end = m_game->playerList()->end();
0297   for (; it != it_end; it++)
0298   {
0299     if (getTotalArmiesOfPlayer(((Player*)(*it))) > nb)
0300     {
0301       return false;
0302     }
0303   }
0304   return true;
0305 }
0306 
0307 bool AIColsonPlayer::isSmallerPlayer(const Player* player)
0308 {
0309   int nb = 3 * getTotalArmiesOfPlayer(player);
0310   PlayersArray::iterator it = m_game->playerList()->begin();
0311   PlayersArray::iterator it_end = m_game->playerList()->end();
0312   for (; it != it_end; it++)
0313   {
0314     if (getTotalArmiesOfPlayer(((Player*)(*it))) > nb)
0315     {
0316       return false;
0317     }
0318   }
0319   return false;
0320 }
0321 
0322 bool AIColsonPlayer::isContinentOfPlayer(const Continent* continent, const Player* player)
0323 {
0324   if (continent == nullptr)
0325   {
0326     return false;
0327   } 
0328   return (continent->owner() == player);
0329 }
0330 
0331 const Continent* AIColsonPlayer::computeChoiceOfContinent(void)
0332 {
0333 //   qCDebug(KSIRK_LOG);
0334   std::map< const KPlayer*, std::map <const Continent*, int > > piCount;
0335   std::map< const KPlayer*, std::map <const Continent*, bool > > maxContinent;
0336   std::map< const KPlayer*, std::map <const Continent*, bool > > posContinent;
0337   std::map<const KPlayer*, const Continent*> m_piContinent;
0338 
0339   QList<Continent*>::iterator continentsIt = (m_world->getContinents().begin());
0340   QList<Continent*>::iterator continentsIt_end = (m_world->getContinents().end());
0341 
0342   PlayersArray::iterator it = m_game->playerList()->begin();
0343   PlayersArray::iterator it_end = m_game->playerList()->end();
0344   for (; it != it_end; it++)
0345   {
0346     
0347     continentsIt = m_world->getContinents().begin();
0348     continentsIt_end = m_world->getContinents().end();
0349     for (; continentsIt != continentsIt_end; continentsIt++)
0350     {
0351       Continent *continent = *continentsIt;
0352 //       qCDebug(KSIRK_LOG) << "    " << continent;
0353       if (continent == nullptr) continue;
0354 //       qCDebug(KSIRK_LOG) << "    " << continent->name();
0355       piCount[((Player*)(*it))][continent] = 0;
0356       maxContinent[((Player*)(*it))][continent] = false;
0357       posContinent[((Player*)(*it))][continent] = false;
0358     }
0359   }
0360 
0361   for (int i=0; i<m_world->getCountries().size(); i++)
0362   {
0363 /*  QList<Country*>::iterator countriesIt(m_world->getCountries().begin());
0364   QList<Country*>::iterator countriesIt_end(m_world->getCountries().end());
0365   for (; countriesIt != countriesIt_end; countriesIt++)
0366   {*/
0367     Country* country = m_world->getCountries().at(i);
0368 //     qCDebug(KSIRK_LOG) << "country " << country << ;
0369 //     qCDebug(KSIRK_LOG) << "country " << country->name().toUtf8().data();
0370     if ( country->owner() != nullptr && country->continent() != nullptr)
0371     {
0372       piCount[country->owner()][country->continent()]++;
0373 //       qCDebug(KSIRK_LOG) << "piCount[" << country->owner()->name().toUtf8().data() << "][" << country->continent()->name().toUtf8().data() << "] ";
0374 //       qCDebug(KSIRK_LOG) << " is now " << piCount[country->owner()][country->continent()];
0375     }
0376     else 
0377     {
0378 //       qCDebug(KSIRK_LOG) << "owner or continent of country " << country->name().toUtf8().data() << " is null...";
0379     }
0380   }
0381 
0382   it = m_game->playerList()->begin();
0383   it_end = m_game->playerList()->end();
0384   for (; it != it_end; it++)
0385   {
0386     int min = 10000;
0387     int max = 0;
0388     int bonus = 0;
0389     for (continentsIt = m_world->getContinents().begin();
0390           continentsIt!=continentsIt_end; ++continentsIt)
0391     {
0392       const Continent* continent = *continentsIt;
0393       if (piCount[*it][continent] > 0)
0394       {
0395         if (min == 0)
0396         {
0397           if ( (piCount[*it][continent] == continent->getMembers().size())
0398                 && (continent->getBonus()>bonus))
0399           {
0400             qCDebug(KSIRK_LOG) << "pt2";
0401             max = piCount[*it][continent];
0402             bonus = continent->getBonus();
0403             maxContinent[*it][continent] = true;
0404             m_piContinent[*it] = continent;
0405           }
0406         }
0407         else if (piCount[*it][continent] == continent->getMembers().size())
0408         {
0409           min = 0;
0410           max = piCount[*it][continent];
0411           maxContinent[*it][continent] = true;
0412           m_piContinent[*it] = continent;
0413         }
0414         else if (piCount[*it][continent] > max)
0415         {
0416           QList<Continent*>::iterator jit(m_world->getContinents().begin());
0417           QList<Continent*>::iterator jit_end(m_world->getContinents().end());
0418           for (; jit!=jit_end; jit++)
0419           {
0420             Continent* j = *jit;
0421             maxContinent[*it][j] = false;
0422             if (piCount[*it][j] < max-1)
0423                 posContinent[*it][j] = (piCount[*it][continent] < continent->getMembers().size()/2);
0424             else
0425                 posContinent[*it][j] = true;
0426           }
0427           min = continent->getMembers().size() - piCount[*it][continent];
0428           max = piCount[*it][continent];
0429           bonus = continent->getBonus();
0430           maxContinent[*it][continent] = true;
0431         }
0432         else if (   (piCount[*it][continent] == max)
0433                   &&  isContinentOfMission(dynamic_cast<Player*>(*it), continent))
0434         {
0435           min = continent->getMembers().size() 
0436                 - piCount[*it][continent];
0437           bonus = 2 * continent->getBonus();
0438           maxContinent[*it][continent] = true;
0439         }
0440         else if (   (piCount[*it][continent] == max)
0441                   && (continent->getBonus() > bonus))
0442         {
0443           min = continent->getMembers().size() - piCount[*it][continent];
0444           bonus = continent->getBonus();
0445           maxContinent[*it][continent] = true;
0446         }
0447         else if (piCount[*it][continent] >= continent->getMembers().size()/2)
0448         {
0449           posContinent[*it][continent] = true;
0450         }
0451       }
0452     }
0453   }
0454 
0455   /* Search a continent with no conflict */
0456   const Continent* continent = nullptr;
0457   QList<Continent*>::iterator contIt(m_world->getContinents().begin());
0458   QList<Continent*>::iterator contIt_end(m_world->getContinents().end());
0459   for (;(contIt!=contIt_end) && (continent==nullptr);contIt++)
0460   {
0461     const Continent* cont = *contIt;
0462     
0463     if (maxContinent[this][cont])
0464     {
0465       continent = cont;
0466 
0467       PlayersArray::iterator iit = m_game->playerList()->begin();
0468       PlayersArray::iterator iit_end = m_game->playerList()->end();
0469       for (;iit!=iit_end;iit++)
0470       {
0471         Player* i = static_cast<Player*>(*iit);
0472         if (i != this) 
0473         {
0474           if ( m_piContinent[i] == cont)
0475               continent = *(m_world->getContinents().begin());
0476           else if (    (maxContinent[i][cont])
0477                     && (piCount[i][cont] > piCount[this][cont]))
0478             continent = nullptr;
0479         }
0480       }
0481     }
0482   }
0483 
0484   if (isFriendPlayer(this) && (continent!=nullptr))
0485   {
0486     QList<Continent*>::iterator contIt(m_world->getContinents().begin());
0487     QList<Continent*>::iterator contIt_end(m_world->getContinents().end());
0488 
0489     // FIXME: continent can not be 0 in this code path - everything in this for loop is dead code
0490 
0491     for (;(contIt!=contIt_end) && (continent==nullptr);contIt++)
0492     {
0493       const Continent* cont = *contIt;
0494       if (cont != continent)
0495       {
0496         maxContinent[this][cont] = false;
0497         posContinent[this][cont] = false;
0498       }
0499     }
0500     PlayersArray::iterator iit = m_game->playerList()->begin();
0501     PlayersArray::iterator iit_end = m_game->playerList()->end();
0502     for (;iit!=iit_end;iit++)
0503     {
0504       Player* i = static_cast<Player*>(*iit);
0505       posContinent[i][continent] = false;
0506     }
0507     return continent;
0508   }
0509 
0510   /* Search a continent with no computer conflict */
0511   continent = nullptr;
0512   contIt = m_world->getContinents().begin();
0513   contIt_end = m_world->getContinents().end();
0514   for (;(contIt!=contIt_end) && (continent==nullptr);contIt++)
0515   {
0516     const Continent* cont = *contIt;
0517     if (maxContinent[this][cont])
0518     {
0519       continent = cont;
0520       PlayersArray::iterator iit = m_game->playerList()->begin();
0521       PlayersArray::iterator iit_end = m_game->playerList()->end();
0522       for (;iit!=iit_end;iit++)
0523       {
0524         Player* i = static_cast<Player*>(*iit);
0525         if (isFriendPlayer(i) && (i != this)) 
0526         {
0527           if ( m_piContinent[i] == cont)
0528               continent = nullptr;
0529           else if (    (maxContinent[i][cont])
0530                     && (piCount[i][cont] > piCount[this][cont]))
0531               continent = nullptr;
0532         }
0533       }
0534     }
0535   }
0536 
0537   if (continent!=nullptr)
0538   {
0539     QList<Continent*>::iterator contIt(m_world->getContinents().begin());
0540     QList<Continent*>::iterator contIt_end(m_world->getContinents().end());
0541     for (;contIt!=contIt_end;contIt++)
0542     {
0543       const Continent* cont = *contIt;
0544     //for (cont=0; cont!=m_world->getContinents().count(); cont++)
0545       if (cont != continent)
0546       {
0547         maxContinent[this][cont] = false;
0548         posContinent[this][cont] = false;
0549       }
0550     }
0551     PlayersArray::iterator iit = m_game->playerList()->begin();
0552     PlayersArray::iterator iit_end = m_game->playerList()->end();
0553     for (;iit!=iit_end;iit++)
0554     {
0555       Player* pi = static_cast<Player*>(*iit);
0556       posContinent[pi][continent] = false;
0557     }
0558     qCDebug(KSIRK_LOG) << "pt5";
0559     return continent;
0560   }
0561 
0562 
0563   /* Search a possible continent with no conflict */
0564   continent = nullptr;
0565   contIt = m_world->getContinents().begin();
0566   contIt_end = m_world->getContinents().end();
0567   for (;(contIt!=contIt_end) && (continent==nullptr);contIt++)
0568   {
0569     const Continent* cont = *contIt;
0570     if (posContinent[this][cont])
0571     {
0572       continent = cont;
0573       PlayersArray::iterator iit = m_game->playerList()->begin();
0574       PlayersArray::iterator iit_end = m_game->playerList()->end();
0575       for (;iit!=iit_end;iit++)
0576       {
0577         Player* pi = static_cast<Player*>(*iit);
0578         if (isFriendPlayer(pi) && (pi != this)) 
0579         {
0580           if ( m_piContinent[pi] == cont)
0581               continent = nullptr;
0582           else if (    (maxContinent[pi][cont])
0583                     && (piCount[pi][cont] > piCount[this][cont]))
0584               continent = nullptr;
0585         }
0586       }
0587     }
0588   }
0589 
0590   if (continent!=nullptr)
0591   {
0592     QList<Continent*>::iterator contIt(m_world->getContinents().begin());
0593     QList<Continent*>::iterator contIt_end(m_world->getContinents().end());
0594     for (;contIt!=contIt_end;contIt++)
0595     {
0596       const Continent* cont = *contIt;
0597     //for (cont=0; cont!=m_world->getContinents().count(); cont++)
0598       if (cont != continent)
0599       {
0600         maxContinent[this][cont] = false;
0601         posContinent[this][cont] = false;
0602       }
0603     }
0604     PlayersArray::iterator iit = m_game->playerList()->begin();
0605     PlayersArray::iterator iit_end = m_game->playerList()->end();
0606     for (;iit!=iit_end;iit++)
0607     {
0608       Player* pi = static_cast<Player*>(*iit);
0609       posContinent[pi][continent] = false;
0610     }
0611     qCDebug(KSIRK_LOG) << "pt6";
0612     return continent;
0613   }
0614 
0615   /* Search a possible continent with no computer conflict */
0616   continent = nullptr;
0617   contIt = m_world->getContinents().begin();
0618   contIt_end = m_world->getContinents().end();
0619   for (;(contIt!=contIt_end) && (continent==nullptr);contIt++)
0620   {
0621     const Continent* cont = *contIt;
0622     if (posContinent[this][cont])
0623     {
0624       continent = cont;
0625       PlayersArray::iterator iit = m_game->playerList()->begin();
0626       PlayersArray::iterator iit_end = m_game->playerList()->end();
0627       for (;iit!=iit_end;iit++)
0628       {
0629         Player* pi = static_cast<Player*>(*iit);
0630         if (isFriendPlayer(pi) && (pi != this)) 
0631         {
0632           if ( m_piContinent[pi] == cont)
0633               continent = nullptr;
0634           else if (    (maxContinent[pi][cont])
0635                     && (piCount[pi][cont] > piCount[this][cont]))
0636               continent = nullptr;
0637         }
0638       }
0639     }
0640   }
0641 
0642   if (continent!=nullptr)
0643   {
0644     QList<Continent*>::iterator contIt(m_world->getContinents().begin());
0645     QList<Continent*>::iterator contIt_end(m_world->getContinents().end());
0646     for (;contIt!=contIt_end;contIt++)
0647     {
0648       const Continent* cont = *contIt;
0649       if (cont != continent)
0650       {
0651         maxContinent[this][cont] = false;
0652       }
0653     }
0654     qCDebug(KSIRK_LOG) << "pt7";
0655     return continent;
0656   }
0657 
0658   continent = nullptr;
0659 
0660   /* Search a continent */
0661   contIt = m_world->getContinents().begin();
0662   contIt_end = m_world->getContinents().end();
0663   for (;(contIt!=contIt_end) && (continent==nullptr);contIt++)
0664   {
0665     const Continent* cont = *contIt;
0666     if (piCount[this][cont]>0)
0667     {
0668       continent = cont;
0669       PlayersArray::iterator iit = m_game->playerList()->begin();
0670       PlayersArray::iterator iit_end = m_game->playerList()->end();
0671       for (;iit!=iit_end;iit++)
0672       {
0673         Player* pi = static_cast<Player*>(*iit);
0674         if (isFriendPlayer(pi) && (pi != this))
0675           continent = nullptr;
0676       }
0677     }
0678   }
0679 
0680   if (continent!=nullptr)
0681   {
0682     QList<Continent*>::iterator contIt(m_world->getContinents().begin());
0683     QList<Continent*>::iterator contIt_end(m_world->getContinents().end());
0684     for (;contIt!=contIt_end;contIt++)
0685     {
0686       const Continent* cont = *contIt;
0687       if (cont!=continent)
0688       {
0689         maxContinent[this][cont] = false;
0690       }
0691     }
0692     qCDebug(KSIRK_LOG) << "pt8";
0693     return continent;
0694   }
0695 
0696   continent = nullptr;
0697 
0698   /* Search a continent */
0699   contIt = m_world->getContinents().begin();
0700   contIt_end = m_world->getContinents().end();
0701   for (;(contIt!=contIt_end) && (continent==nullptr);contIt++)
0702   {
0703     const Continent* cont = *contIt;
0704     if (maxContinent[this][cont])
0705         continent = cont;
0706   }
0707 
0708 //   qCDebug(KSIRK_LOG) << "AIColsonPlayer::computeChoiceOfContinent for " << name().toUtf8().data()
0709 //     << " is " << continent;
0710   return continent;
0711 }
0712 
0713 /**
0714   * Gets the continent already selected for this player
0715   * @param attack This is the number of countries of the selected continent
0716   * that have at least one adjacent enemy
0717   */
0718 const Continent* AIColsonPlayer::GetContinentToFortify(int *attack)
0719 {
0720   qCDebug(KSIRK_LOG);
0721   const Continent* continent = computeChoiceOfContinent();
0722   qCDebug(KSIRK_LOG) << "  computeChoiceOfContinent got " << continent;
0723   *attack = 0;
0724   for (int i=0; i!=m_world->getCountries().size(); i++)
0725   {
0726     if (    (RISK_GetOwnerOfCountry(i) == this)
0727            && (RISK_GetContinentOfCountry(i) == continent)
0728            &&  GAME_IsEnemyAdjacent(i))
0729     {
0730       (*attack)++;
0731     }
0732   }
0733   qCDebug(KSIRK_LOG) << "found " << continent;
0734   return(continent);
0735 }
0736 
0737 /** 
0738   * @param attack Number of countries with adjacent ennemies in the selected
0739   * continent
0740   */
0741 const Continent* AIColsonPlayer::getContinentToConquier(int *attack)
0742 {
0743   qCDebug(KSIRK_LOG);
0744   std::map<const Continent*, int> piCount;
0745   std::map<const Continent*, int> piOppo;
0746   std::map<const Continent*, int> piAttac;
0747 
0748   /* Init. */
0749   QList<Continent*>::iterator contIt(m_world->getContinents().begin());
0750   QList<Continent*>::iterator contIt_end(m_world->getContinents().end());
0751   for (;contIt!=contIt_end;contIt++)
0752   {
0753     const Continent* cont = *contIt;
0754     piCount[cont] = 0;
0755     piOppo[cont] = 0;
0756     piAttac[cont] = 0;
0757   }
0758 
0759   /* Count up how many countries the player has in each of the continents */
0760   QList<Country*>::iterator countriesIt(m_world->getCountries().begin());
0761   QList<Country*>::iterator countriesIt_end(m_world->getCountries().end());
0762   for (; countriesIt != countriesIt_end; countriesIt++)
0763   {
0764     Country* country = *countriesIt;
0765     if (country->owner() == this)
0766     {
0767       piCount[country->continent()]++;
0768       piOppo[country->continent()] -= country->nbArmies();
0769       if (country->hasAdjacentEnemy())
0770         piAttac[country->continent()]++;
0771     }
0772     else
0773     {
0774       if (isEnemyPlayer(country->owner()))
0775         piOppo[country->continent()] += country->nbArmies();
0776       else
0777         piOppo[country->continent()] += 2 * country->nbArmies();
0778     }
0779   }
0780 
0781   const Continent* continent = nullptr;
0782   int min = 10000;
0783   contIt = m_world->getContinents().begin();
0784   contIt_end = m_world->getContinents().end();
0785   for (; contIt != contIt_end; contIt++)
0786   {
0787     const Continent* cont = *contIt;
0788     qCDebug(KSIRK_LOG) << "    " << cont;
0789     if (cont != nullptr)
0790       qCDebug(KSIRK_LOG) << "    " << cont->name();
0791     if (isContinentOfMission(this, cont))
0792     {
0793       piOppo[cont] -= piOppo[cont]/3;
0794     }
0795     if (piCount[cont] < cont->getMembers().size())
0796     {
0797       if (piOppo[cont] < min)
0798       {
0799         continent = cont;
0800         min = piOppo[cont];
0801       }
0802     }
0803   }
0804 
0805   *attack = piAttac[continent];
0806   return(continent);
0807 }
0808 
0809 int AIColsonPlayer::NbEnemyAdjacent(Country* iCountry)
0810 {
0811   std::map<Player*, unsigned int> NumEnemy;
0812   std::map<Player*, bool> fIsEnemy;
0813   bool  fIAmStrong;
0814 
0815   Player* player = iCountry->owner();
0816   fIAmStrong = isStrongerPlayer(player);
0817   PlayersArray::iterator pit = m_game->playerList()->begin();
0818   PlayersArray::iterator pit_end = m_game->playerList()->end();
0819   for (; pit != pit_end; pit++)
0820   {
0821     fIsEnemy[(Player*)(*pit)] = false;
0822   }
0823   Player* iEnemy = nullptr;
0824   Country* destCountry;
0825   QList<Country*>::const_iterator it, it_end;
0826   it = iCountry->neighbours().constBegin();
0827   it_end = iCountry->neighbours().constEnd();
0828   for (;it != it_end; it++)
0829     {
0830       destCountry = *it;
0831       iEnemy = destCountry->owner();
0832       if (iEnemy != player)
0833       {
0834         if (NumEnemy[iEnemy] < destCountry->nbArmies())
0835             NumEnemy[iEnemy] = destCountry->nbArmies();
0836         fIsEnemy[iEnemy] = true;
0837       }
0838     }
0839   int max = 0;
0840   pit = m_game->playerList()->begin();
0841   pit_end = m_game->playerList()->end();
0842   for (; pit != pit_end; pit++)
0843   {
0844     Player* i = (Player*)(*pit);
0845     if ((i != player) && fIsEnemy[i])
0846     {
0847       int nb = NumEnemy[iEnemy];
0848       if (!fIAmStrong && isStrongerPlayer(i))
0849           nb = nb + 10;
0850       if (isEnemyPlayer(i))
0851           nb = nb + 5;
0852       if (nb > max)
0853           max = nb;
0854     }
0855   }
0856   return max;
0857 }
0858 
0859 int AIColsonPlayer::NbToAverageEnemyAdjacent(Country* iCountry)
0860 {
0861   int nbe = 0;
0862   int nb = 0;
0863   int i = 0;
0864   QList<Country*>::const_iterator neighbourIt, neighbourIt_end;
0865   neighbourIt = iCountry->neighbours().constBegin();
0866   neighbourIt_end = iCountry->neighbours().constEnd();
0867   for (;neighbourIt != neighbourIt_end; neighbourIt++)
0868   {
0869     Country* destCountry = *neighbourIt;
0870     Player* iEnemy = destCountry->owner();
0871     if (iEnemy != this)
0872     {
0873       nbe -= destCountry->nbArmies();
0874       nb++;
0875     }
0876     i++;
0877   }
0878   int nbi = iCountry->nbArmies();
0879   nbe = (nbe + nbi)/nb;
0880 //   if ((nbi - nbe)< 10)
0881 //       nbe = nbi - 10;
0882   qCDebug(KSIRK_LOG) << "NbToAverageEnemyAdjacent of " << iCountry->name() << " is " << nbe;
0883   return nbe;
0884 }
0885 
0886 
0887 int AIColsonPlayer::NbToEqualEnemyAdjacent(Country* iCountry)
0888 {
0889   int nbe = 0;
0890   QList<Country*>::const_iterator neighbourIt, neighbourIt_end;
0891   neighbourIt = iCountry->neighbours().constBegin();
0892   neighbourIt_end = iCountry->neighbours().constEnd();
0893   for (;neighbourIt != neighbourIt_end; neighbourIt++)
0894   {
0895     Country* destCountry = *neighbourIt;
0896     Player* iEnemy = destCountry->owner();
0897     if (iEnemy != this)
0898     {
0899       nbe += destCountry->nbArmies();
0900     }
0901   }
0902   int nbi = iCountry->nbArmies();
0903   int nb = (nbe - nbi);
0904   qCDebug(KSIRK_LOG) << "NbToEqualEnemyAdjacent of " << iCountry->name() << " is " << nb;
0905   return nb;
0906 }
0907 
0908 
0909 /************************************************************************/
0910 
0911 bool AIColsonPlayer::ComputerAttack(int destCountry, bool die, int dif)
0912 {
0913   qCDebug(KSIRK_LOG) << destCountry;
0914 
0915   if (Attack_SrcCountry!=-1 && Attack_DestCountry!=-1
0916     && (RISK_GetOwnerOfCountry(Attack_SrcCountry) == this)
0917     && (RISK_GetOwnerOfCountry(Attack_DestCountry) != this)
0918     && (RISK_GetNumArmiesOfCountry(Attack_SrcCountry) > 1)
0919           && (die || (   RISK_GetNumArmiesOfCountry(Attack_SrcCountry)
0920                        > RISK_GetNumArmiesOfCountry(Attack_DestCountry))))
0921   {
0922     qCDebug(KSIRK_LOG) << "    Retry attack";
0923     return true;
0924   }
0925 
0926   int srcCountry = -1;
0927   int max = RISK_GetNumArmiesOfCountry(destCountry) + dif;
0928   int i = 0;
0929   while ((i < 6) && (RISK_GetAdjCountryOfCountry(destCountry, i) != -1))
0930   {
0931     int iCountry = RISK_GetAdjCountryOfCountry(destCountry, i);
0932     if ( (RISK_GetOwnerOfCountry(iCountry) == this)
0933         && (RISK_GetNumArmiesOfCountry(iCountry) > max) )
0934     {
0935       max = RISK_GetNumArmiesOfCountry(iCountry);
0936       srcCountry = iCountry;
0937     }
0938     i++;
0939   }
0940   if (srcCountry == -1)
0941   {
0942     Attack_SrcCountry = -1;
0943     Attack_DestCountry = -1;
0944     return false;
0945   }
0946   qCDebug(KSIRK_LOG) << "    srcCountry = " << srcCountry;
0947 
0948   Attack_SrcCountry = srcCountry;
0949   Attack_DestCountry = destCountry;
0950 //   AI_Attack (srcCountry, destCountry, ATTACK_DOORDIE, DICE_MAXIMUM, iMove);
0951   return true;
0952 }
0953 
0954 bool AIColsonPlayer::Fortify()
0955 {
0956   qCDebug(KSIRK_LOG) << "1";
0957 
0958   int nb;
0959   const Continent* continent = GetContinentToFortify(&nb);
0960   
0961   qCDebug(KSIRK_LOG) << "2";
0962   if (nb > 0)
0963   {
0964     nb = rand() % nb;
0965     for ( int iCountry = 0;
0966           iCountry < m_world->getCountries().size();
0967           iCountry++)
0968     {
0969       if ((RISK_GetOwnerOfCountry(iCountry) == this) &&
0970           (RISK_GetContinentOfCountry(iCountry) == continent) &&
0971           GAME_IsEnemyAdjacent(iCountry))
0972       {
0973         if (nb <= 0)
0974         {
0975           AI_Place (iCountry, 1);
0976           return true;
0977         }
0978         nb--;
0979       }
0980     }
0981   }
0982   
0983   qCDebug(KSIRK_LOG) << "3";
0984   for ( int iCountry = 0;
0985         iCountry < m_world->getCountries().size();
0986         iCountry++)
0987   {
0988     if (    (RISK_GetOwnerOfCountry(iCountry) == this)
0989           &&  GAME_IsEnemyAdjacent(iCountry))
0990     {
0991       AI_Place (iCountry, 1);
0992       return true;
0993     }
0994   }
0995   
0996   qCDebug(KSIRK_LOG) << "4";
0997   for ( int iCountry = 0;
0998         iCountry < m_world->getCountries().size();
0999         iCountry++)
1000   {
1001     if (RISK_GetOwnerOfCountry(iCountry) == this)
1002     {
1003       AI_Place (iCountry, 1);
1004       return true;
1005     }
1006   }
1007   return false;
1008 }
1009 
1010 bool AIColsonPlayer::Place()
1011 {
1012   qCDebug(KSIRK_LOG);
1013 
1014   /* Try to destroy a weak enemy player. 
1015    * NOTE this could be an error
1016    * if destroying this player is another player goal... */
1017   qCDebug(KSIRK_LOG) << "1. Try to destroy a enemy player";
1018   
1019   for (int iCountry = 0; iCountry < m_world->getCountries().size(); iCountry++)
1020   {
1021     if ((RISK_GetOwnerOfCountry(iCountry) == this) &&
1022           GAME_IsEnemyAdjacent(iCountry))
1023     {
1024       int i = 0;
1025       while ((i < 6) && (RISK_GetAdjCountryOfCountry(iCountry, i) != -1))
1026       {
1027         int destCountry = RISK_GetAdjCountryOfCountry(iCountry, i);
1028         Player* iEnemy = RISK_GetOwnerOfCountry(destCountry);
1029         if (    (iEnemy != this) && isEnemyPlayer(iEnemy)
1030               && (getTotalArmiesOfPlayer(iEnemy)
1031                   < (   RISK_GetNumArmiesOfPlayer(this)
1032                       + RISK_GetNumArmiesOfCountry(iCountry) - 5))
1033               && (RISK_GetNumArmiesOfCountry(iCountry) < (2*RISK_GetNumArmiesOfCountry(destCountry))+3) )
1034         {
1035           qCDebug(KSIRK_LOG) << " iCountry: " << RISK_GetNumArmiesOfCountry(iCountry)
1036             << " ; destCountry: " << RISK_GetNumArmiesOfCountry(destCountry);
1037           AI_Place (iCountry, 1);
1038           return true;
1039         }
1040         i++;
1041       }
1042     }
1043   }
1044 
1045   int nbCountriesWithAdjacentEnemies;
1046   const Continent* continent = GetContinentToFortify(&nbCountriesWithAdjacentEnemies);
1047   /* Try to conquier an entire continent, attack enemy */
1048   qCDebug(KSIRK_LOG) << "2. Try to conquier an entire continent, attack enemy";
1049   
1050   for (int destCountry = 0; 
1051        destCountry < m_world->getCountries().size();
1052        destCountry++)
1053   {
1054     Player* iEnemy = RISK_GetOwnerOfCountry(destCountry);
1055     if (    (iEnemy != this) && isEnemyPlayer(iEnemy)
1056           && (RISK_GetContinentOfCountry(destCountry) == continent))
1057     {
1058       int i = 0;
1059       while ((i < 6) && (RISK_GetAdjCountryOfCountry(destCountry, i) != -1))
1060       {
1061         int iCountry = RISK_GetAdjCountryOfCountry(destCountry, i);
1062         if ( (RISK_GetOwnerOfCountry(iCountry) == this)
1063             && (RISK_GetNumArmiesOfCountry(iCountry) < (1.5*RISK_GetNumArmiesOfCountry(destCountry))+3)
1064             )
1065         {
1066           AI_Place (iCountry, 1);
1067           return true;
1068         }
1069         i++;
1070       }
1071     }
1072   }
1073 
1074   /* Try to destroy a player */
1075   qCDebug(KSIRK_LOG) << "3. Try to destroy a player";
1076   for (int iCountry = 0;
1077        iCountry < m_world->getCountries().size();
1078        iCountry++)
1079   {
1080     if ((RISK_GetOwnerOfCountry(iCountry) == this) &&
1081           GAME_IsEnemyAdjacent(iCountry))
1082     {
1083       int i = 0;
1084       while ((i < 6) && (RISK_GetAdjCountryOfCountry(iCountry, i) != -1))
1085       {
1086         int destCountry = RISK_GetAdjCountryOfCountry(iCountry, i);
1087         Player* iEnemy = RISK_GetOwnerOfCountry(destCountry);
1088         if (    (iEnemy != this)
1089               && (getTotalArmiesOfPlayer(iEnemy)
1090                   < (   RISK_GetNumArmiesOfPlayer(this)
1091                       + RISK_GetNumArmiesOfCountry(iCountry) - 5))
1092               && (RISK_GetNumArmiesOfCountry(iCountry) < (1.5*RISK_GetNumArmiesOfCountry(destCountry))+3)
1093 
1094             )
1095         {
1096           AI_Place (iCountry, 1);
1097           return true;
1098         }
1099         i++;
1100       }
1101     }
1102   }
1103 
1104   /* Try to conquier an entire continent */
1105   qCDebug(KSIRK_LOG) << "4. Try to conquier an entire continent";
1106   for (int destCountry = 0; 
1107        destCountry < m_world->getCountries().size();
1108        destCountry++)
1109   {
1110     Player* iEnemy = RISK_GetOwnerOfCountry(destCountry);
1111     if (    (RISK_GetContinentOfCountry(destCountry) == continent)
1112           && (iEnemy != this))
1113     {
1114       int i = 0;
1115       while ((i < 6) && (RISK_GetAdjCountryOfCountry(destCountry, i) != -1))
1116       {
1117         int iCountry = RISK_GetAdjCountryOfCountry(destCountry, i);
1118         if (RISK_GetOwnerOfCountry(iCountry) == this
1119             && (RISK_GetNumArmiesOfCountry(iCountry) < (1.5*RISK_GetNumArmiesOfCountry(destCountry))+3)
1120             )
1121         {
1122           AI_Place (iCountry, 1);
1123           return true;
1124         }
1125         i++;
1126       }
1127     }
1128   }
1129 
1130   /* Try to defend an entire continent */
1131   qCDebug(KSIRK_LOG) << "5. Try to defend an entire continent";
1132   if ( (nbCountriesWithAdjacentEnemies > 0) 
1133         && (RISK_GetNumArmiesOfPlayer(this) > 0) )
1134   {
1135     int min = 0;
1136     bool boool = false;
1137     int destCountry = -1;
1138     for (int iCountry = 0; 
1139          iCountry < m_world->getCountries().size();
1140          iCountry++)
1141     {
1142       if (    (RISK_GetOwnerOfCountry(iCountry) == this)
1143             && (RISK_GetContinentOfCountry(iCountry) == continent)
1144             &&  GAME_IsEnemyAdjacent(iCountry))
1145       {
1146         int nb = NbToAverageEnemyAdjacent(m_world->getCountries().at(iCountry));
1147         if (nb < min)
1148         {
1149           min = nb ;
1150           destCountry = iCountry;
1151           boool = true;
1152         }
1153       }
1154     }
1155     if (boool)
1156     {
1157       AI_Place (destCountry, 1);
1158       return true;
1159     }
1160   }
1161 
1162   qCDebug(KSIRK_LOG) << "6. Try to conquier an entire continent, attack enemy";
1163   continent = getContinentToConquier(&nbCountriesWithAdjacentEnemies);
1164   /* Try to conquier an entire continent, attack enemy */
1165   for (int iCountry = 0;
1166        iCountry < m_world->getCountries().size();
1167        iCountry++)
1168   {
1169     if ((RISK_GetOwnerOfCountry(iCountry) == this) &&
1170         (RISK_GetContinentOfCountry(iCountry) == continent) &&
1171         GAME_IsEnemyAdjacent(iCountry))
1172     {
1173       int i = 0;
1174       while ((i < 6) && (RISK_GetAdjCountryOfCountry(iCountry, i) != -1))
1175       {
1176         int destCountry = RISK_GetAdjCountryOfCountry(iCountry, i);
1177         Player* iEnemy = RISK_GetOwnerOfCountry(destCountry);
1178         if (    (iEnemy != this) && isEnemyPlayer(iEnemy)
1179               && (RISK_GetContinentOfCountry(destCountry) == continent)
1180               && (RISK_GetNumArmiesOfCountry(iCountry) < (1.5*RISK_GetNumArmiesOfCountry(destCountry))+3)
1181             )
1182         {
1183           qCDebug(KSIRK_LOG) << "iCountry " << RISK_GetNumArmiesOfCountry(iCountry)
1184                     << " ; destCountry " 
1185                     << RISK_GetNumArmiesOfCountry(destCountry);
1186           AI_Place (iCountry, 1);
1187           return true;
1188         }
1189         i++;
1190       }
1191     }
1192   }
1193 
1194   qCDebug(KSIRK_LOG) << "7. Try to conquier an entire continent";
1195   /* Try to conquier an entire continent */
1196   for (int   iCountry = 0;
1197        iCountry < m_world->getCountries().size();
1198        ++iCountry)
1199   {
1200     if ((RISK_GetOwnerOfCountry(iCountry) == this) &&
1201         (RISK_GetContinentOfCountry(iCountry) == continent) &&
1202           GAME_IsEnemyAdjacent(iCountry))
1203     {
1204       int i = 0;
1205       while ((i < 6) && (RISK_GetAdjCountryOfCountry(iCountry, i) != -1))
1206       {
1207         int destCountry = RISK_GetAdjCountryOfCountry(iCountry, i);
1208         Player* iEnemy = RISK_GetOwnerOfCountry(destCountry);
1209         if (    (iEnemy != this)
1210               && (RISK_GetContinentOfCountry(destCountry) == continent)
1211               && (RISK_GetNumArmiesOfCountry(iCountry) < (1.5*RISK_GetNumArmiesOfCountry(destCountry))+3)
1212             )
1213         {
1214           AI_Place (iCountry, 1);
1215           return true;
1216         }
1217         i++;
1218       }
1219     }
1220   }
1221 
1222   qCDebug(KSIRK_LOG) << "8. Try to defend an entire continent";
1223   /* Try to defend an entire continent */
1224   if (nbCountriesWithAdjacentEnemies > 0)
1225   {
1226     int min = 2; // a la place de 1000
1227     bool boool = false;
1228     int destCountry = -1;
1229     for (int iCountry = 0;
1230          iCountry < m_world->getCountries().size();
1231          iCountry++)
1232     {
1233       if (    (RISK_GetOwnerOfCountry(iCountry) == this)
1234           && (RISK_GetContinentOfCountry(iCountry) == continent)
1235           &&  GAME_IsEnemyAdjacent(iCountry))
1236       {
1237         int nb = NbToAverageEnemyAdjacent(m_world->getCountries().at(iCountry));
1238         if (nb < min)
1239         {
1240 //           min = RISK_GetNumArmiesOfCountry(iCountry);
1241           min = nb;
1242           destCountry = iCountry;
1243           boool = true;
1244         }
1245       }
1246     }
1247     if (boool)
1248     {
1249       AI_Place (destCountry, 1);
1250       return true;
1251     }
1252   }
1253 
1254   qCDebug(KSIRK_LOG) << "9. Try to prepare an enemy attack, find a lowest defence";
1255   /* Try to prepare an enemy attack, find a lowest defence */
1256   int selected = 0;
1257   int myDefenceDelta = std::numeric_limits<int>::max();
1258   bool boool9 = false;
1259   for (int iCountry = 0;
1260        iCountry < m_world->getCountries().size(); 
1261        iCountry++)
1262   {
1263     if (    (RISK_GetOwnerOfCountry(iCountry) == this)
1264         &&  GAME_IsEnemyAdjacent(iCountry))
1265     {
1266       int i = 0;
1267       while ((i < 6) && (RISK_GetAdjCountryOfCountry(iCountry, i) != -1))
1268       {
1269         int destCountry = RISK_GetAdjCountryOfCountry(iCountry, i);
1270         int delta = RISK_GetNumArmiesOfCountry(iCountry) - RISK_GetNumArmiesOfCountry(destCountry);
1271         Player* iEnemy = RISK_GetOwnerOfCountry(destCountry);
1272         if (    (RISK_GetContinentOfCountry(destCountry) == continent)
1273              && (iEnemy != this) && isEnemyPlayer(iEnemy)
1274              && ( (   RISK_GetNumArmiesOfCountry(iCountry) < 
1275                       (1.5*RISK_GetNumArmiesOfCountry(destCountry))+3 ) 
1276                    || (RISK_GetNumArmiesOfCountry(iCountry)==1) ) 
1277               && (delta < myDefenceDelta ) )
1278         {
1279           selected = iCountry;
1280           myDefenceDelta = delta;
1281           boool9 = true;
1282         }
1283         i++;
1284       }
1285     }
1286   }
1287   if (boool9)
1288   {
1289     AI_Place (selected, 1);
1290     return true;
1291   }
1292 
1293   qCDebug(KSIRK_LOG) << "10. Try to prepare an enemy attack";
1294   /* Try to prepare an enemy attack */
1295   bool boool10 = false;
1296   myDefenceDelta = std::numeric_limits<int>::max();
1297   for (int iCountry = 0; 
1298        iCountry < m_world->getCountries().size();
1299        iCountry++)
1300   {
1301 //     qCDebug(KSIRK_LOG) << "    looking at iCountry " << iCountry;
1302 //     qCDebug(KSIRK_LOG) << "    owner " << RISK_GetOwnerOfCountry(iCountry);
1303     if (    (RISK_GetOwnerOfCountry(iCountry) == this)
1304           &&  GAME_IsEnemyAdjacent(iCountry))
1305     {
1306       int i = 0;
1307       while ((i < 6) && (RISK_GetAdjCountryOfCountry(iCountry, i) != -1))
1308       {
1309         int destCountry = RISK_GetAdjCountryOfCountry(iCountry, i);
1310         int delta = RISK_GetNumArmiesOfCountry(iCountry) - RISK_GetNumArmiesOfCountry(destCountry);
1311         Player* iEnemy = RISK_GetOwnerOfCountry(destCountry);
1312 //         qCDebug(KSIRK_LOG) << "        looking at destCountry " << destCountry;
1313 //         qCDebug(KSIRK_LOG) << "        iEnemy " << RISK_GetOwnerOfCountry(destCountry);
1314 //         qCDebug(KSIRK_LOG) << "        isEnemyPlayer? " << isEnemyPlayer(iEnemy);
1315 //         qCDebug(KSIRK_LOG) << "    delta / myDefenceDelta " << delta << " / " << myDefenceDelta;
1316         if ((iEnemy != this) && isEnemyPlayer(iEnemy) 
1317               && (delta < myDefenceDelta ) )
1318         {
1319 //           qCDebug(KSIRK_LOG) << "    GOT IT " << iCountry;
1320           myDefenceDelta = delta;
1321           boool10 = true;
1322           selected = iCountry;
1323         }
1324         i++;
1325       }
1326     }
1327   }
1328   if (boool10)
1329   {
1330     AI_Place (selected, 1);
1331     //AI_Place (iCountry, RISK_GetNumArmiesOfPlayer(this));
1332     return true;
1333   }
1334 
1335   // cannot reach this line ???
1336 //   assert(false);
1337 
1338   qCDebug(KSIRK_LOG) << "11. Try to prepare an attack";
1339   /* Try to prepare an attack */
1340   for (int iCountry = 0;
1341        iCountry < m_world->getCountries().size();
1342        iCountry++)
1343   {
1344     if (    (RISK_GetOwnerOfCountry(iCountry) == this)
1345           &&  GAME_IsEnemyAdjacent(iCountry))
1346     {
1347       AI_Place (iCountry, 1);
1348       return true;
1349     }
1350   }
1351 
1352   qCDebug(KSIRK_LOG) << "12. Try to place";
1353   /* Try to place */
1354   for (int iCountry = 0; 
1355        iCountry < m_world->getCountries().size(); 
1356        iCountry++)
1357   {
1358     if (RISK_GetOwnerOfCountry(iCountry) == this)
1359     {
1360       AI_Place (iCountry, 1);
1361       return true;
1362     }
1363   }
1364   return false;
1365 }
1366 
1367 /** @return KsirK change: true if an attack have been tempted; false otherwise */
1368 bool AIColsonPlayer::AttackEnemy()
1369 {
1370   qCDebug(KSIRK_LOG);
1371 
1372   int nbCountriesWithAdjacentEnemies;
1373   const Continent* continent = GetContinentToFortify(&nbCountriesWithAdjacentEnemies);
1374 
1375   if (Attack_SrcCountry!=-1 && Attack_DestCountry != -1
1376     && (RISK_GetOwnerOfCountry(Attack_SrcCountry)==this)
1377     && (RISK_GetOwnerOfCountry(Attack_DestCountry)!=this)
1378     && ComputerAttack (Attack_DestCountry, true,
1379                             (RISK_GetNumArmiesOfCountry(Attack_DestCountry) < 5)?1:
1380                                 ((nbCountriesWithAdjacentEnemies > 4)?RISK_GetNumArmiesOfCountry(Attack_DestCountry):3)))
1381   {
1382     qCDebug(KSIRK_LOG) << "Attack tempted again.";
1383     return true;
1384   }
1385 
1386 
1387   qCDebug(KSIRK_LOG) << "1 Try to conquier an entire continent, attack player of other species ";
1388   /* Try to conquier an entire continent, attack player of other species */
1389   for ( int destCountry = 0;
1390         destCountry < m_world->getCountries().size();
1391         destCountry++)
1392   {
1393 //     qCDebug(KSIRK_LOG) << "destCountry=" << destCountry << " / m_world->getCountries().size()=" << m_world->getCountries().size();
1394     Player* iEnemy = RISK_GetOwnerOfCountry(destCountry);
1395     if (    (RISK_GetContinentOfCountry(destCountry) == continent)
1396           && (iEnemy != this) && isEnemyPlayer(iEnemy))
1397     {
1398       if (ComputerAttack (destCountry, true,
1399                                 (RISK_GetNumArmiesOfCountry(destCountry) < 5)?1:
1400                                     ((nbCountriesWithAdjacentEnemies > 4)?RISK_GetNumArmiesOfCountry(destCountry):3)))
1401       {
1402         destCountry = 0;
1403         qCDebug(KSIRK_LOG) << "Attack tempted.";
1404         return true;
1405       }
1406     }
1407   }
1408 
1409   qCDebug(KSIRK_LOG) << "2 Try to conquier an entire continent: " << continent;
1410   /* Try to conquier an entire continent */
1411   
1412   for (int destCountry = 0; destCountry < m_world->getCountries().size(); destCountry++)
1413   {
1414     if (     (RISK_GetContinentOfCountry(destCountry) == continent)
1415         && (RISK_GetOwnerOfCountry(destCountry) != this))
1416     {
1417       if (ComputerAttack (destCountry, true,
1418                           (RISK_GetNumArmiesOfCountry(destCountry) < 3)?1:50))
1419       {
1420         destCountry = 0;
1421         qCDebug(KSIRK_LOG) << "Attack tempted.";
1422         return true;
1423       }
1424     }
1425   }
1426 
1427   qCDebug(KSIRK_LOG) << "should abandon ?";
1428   if (    !isContinentOfPlayer(continent, this)
1429        && (m_numTurn[this] <= 2)
1430        && (allPlayers.count() > m_world->getContinents().size()/2))
1431   {
1432     qCDebug(KSIRK_LOG) << "No attack tried";
1433     Attack_SrcCountry = -1;
1434     Attack_DestCountry = -1;
1435     return false;
1436   }
1437 
1438   qCDebug(KSIRK_LOG) << "3 Try to destroy a human player";
1439   /* Try to destroy a human player */
1440   continent = getContinentToConquier(&nbCountriesWithAdjacentEnemies);
1441 
1442   
1443   for (int destCountry = 0;
1444         destCountry < m_world->getCountries().size();
1445         destCountry++)
1446   {
1447     if (    (RISK_GetOwnerOfCountry(destCountry) != this)
1448           && (!RISK_GetOwnerOfCountry(destCountry)->isAI())
1449           && (RISK_GetNumCountriesOfPlayer(RISK_GetOwnerOfCountry(destCountry)) == 1))
1450     {
1451         if (ComputerAttack (destCountry, true,
1452                                   (nbCountriesWithAdjacentEnemies > 2)?10:2))
1453         {
1454           qCDebug(KSIRK_LOG) << "Attack tempted.";
1455           return true;
1456         }
1457     }
1458   }
1459 
1460   qCDebug(KSIRK_LOG) << "4 Try to destroy a enemy player";
1461   /* Try to destroy a enemy player */
1462   for (int destCountry = 0;
1463         destCountry < m_world->getCountries().size();
1464         destCountry++)
1465   {
1466     if (   isEnemyPlayer(RISK_GetOwnerOfCountry(destCountry))
1467           && (RISK_GetNumCountriesOfPlayer(RISK_GetOwnerOfCountry(destCountry)) == 1))
1468     {
1469       if (ComputerAttack (destCountry, true,
1470                                 (nbCountriesWithAdjacentEnemies > 2)?20:2))
1471       {
1472         qCDebug(KSIRK_LOG) << "Attack tempted.";
1473         return true;
1474       }
1475     }
1476   }
1477 
1478   qCDebug(KSIRK_LOG) << "Try to destroy a player";
1479   /* Try to destroy a player */
1480   for (int destCountry = 0;
1481         destCountry < m_world->getCountries().size();
1482         destCountry++)
1483   {
1484     if (    (RISK_GetOwnerOfCountry(destCountry) != this)
1485           && (RISK_GetNumCountriesOfPlayer(RISK_GetOwnerOfCountry(destCountry)) == 1))
1486     {
1487       if (ComputerAttack (destCountry, true,
1488                                 (nbCountriesWithAdjacentEnemies> 2)?20:2))
1489       {
1490         qCDebug(KSIRK_LOG) << "Attack tempted.";
1491         return true;
1492       }
1493     }
1494   }
1495 
1496   qCDebug(KSIRK_LOG) << "5 Try to conquier an entire continent, attack player of other species";
1497   /* Try to conquier an entire continent, attack player of other species */
1498   for (int destCountry = 0;
1499         destCountry < m_world->getCountries().size();
1500         destCountry++)
1501   {
1502     if (    (RISK_GetContinentOfCountry(destCountry) == continent)
1503           && (RISK_GetOwnerOfCountry(destCountry) != this)
1504           &&  isEnemyPlayer(RISK_GetOwnerOfCountry(destCountry)))
1505     {
1506       if (ComputerAttack (destCountry, true,
1507                                 (RISK_GetNumArmiesOfCountry(destCountry) < 5)?1:
1508                                     ((nbCountriesWithAdjacentEnemies > 4)?RISK_GetNumArmiesOfCountry(destCountry):3)))
1509       {
1510         destCountry = 0;
1511         qCDebug(KSIRK_LOG) << "Attack tempted.";
1512         return true;
1513       }
1514     }
1515   }
1516 
1517   qCDebug(KSIRK_LOG) << "6 Try to conquier an entire continent";
1518   /* Try to conquier an entire continent */
1519   for (int destCountry = 0;
1520         destCountry < m_world->getCountries().size();
1521         destCountry++)
1522   {
1523     if (    (RISK_GetContinentOfCountry(destCountry) == continent)
1524           && (RISK_GetOwnerOfCountry(destCountry) != this))
1525     {
1526       if (ComputerAttack (destCountry, true,
1527                           (RISK_GetNumArmiesOfCountry(destCountry) < 3)?1:50))
1528       {
1529         destCountry = 0;
1530         qCDebug(KSIRK_LOG) << "Attack tempted.";
1531         return true;
1532       }
1533     }
1534   }
1535 
1536   qCDebug(KSIRK_LOG) << "7 Try to attack a stronger human player for a card";
1537   /* Try to attack a stronger human player for a card */
1538   for (int destCountry = 0;
1539         destCountry < m_world->getCountries().size();
1540         destCountry++)
1541   {
1542     Player* iEnemy = RISK_GetOwnerOfCountry(destCountry);
1543     if (    (iEnemy != this) && isEnemyPlayer(iEnemy)
1544           && (!iEnemy->isAI())
1545           && isStrongerPlayer(RISK_GetOwnerOfCountry(destCountry)))
1546     {
1547       if (ComputerAttack (destCountry, false,
1548                           (RISK_GetNumArmiesOfCountry(destCountry) < 3)?1:((nbCountriesWithAdjacentEnemies > 2)?10:2)))
1549       {
1550         qCDebug(KSIRK_LOG) << "Attack tempted.";
1551         return true;
1552       }
1553     }
1554   }
1555 
1556   qCDebug(KSIRK_LOG) << "8 Try to attack an human player for a card";
1557   /* Try to attack an human player for a card */
1558   for (int destCountry = 0;
1559         destCountry < m_world->getCountries().size();
1560         destCountry++)
1561   {
1562     Player* iEnemy = RISK_GetOwnerOfCountry(destCountry);
1563     if (    (iEnemy != this) && isEnemyPlayer(iEnemy)
1564           && (!iEnemy->isAI()))
1565     {
1566       if (ComputerAttack (destCountry, false,
1567                           (RISK_GetNumArmiesOfCountry(destCountry) < 3)?1:((nbCountriesWithAdjacentEnemies > 2)?10:2)))
1568       {
1569         qCDebug(KSIRK_LOG) << "Attack tempted.";
1570         return true;
1571       }
1572     }
1573   }
1574 
1575   qCDebug(KSIRK_LOG) << "9 Try to attack enemy player for a card";
1576   /* Try to attack enemy player for a card */
1577   for (int destCountry = 0;
1578         destCountry < m_world->getCountries().size();
1579         destCountry++)
1580   {
1581     Player* iEnemy = RISK_GetOwnerOfCountry(destCountry);
1582     if (    (iEnemy != this) && isEnemyPlayer(iEnemy))
1583         if (ComputerAttack (destCountry, false,
1584                             (RISK_GetNumArmiesOfCountry(destCountry) < 3)?1:((nbCountriesWithAdjacentEnemies > 2)?10:2)))
1585     {
1586       {
1587         qCDebug(KSIRK_LOG) << "Attack tempted.";
1588         return true;
1589       }
1590     }
1591   }
1592 
1593   qCDebug(KSIRK_LOG) << "10 Try to attack for a card, attack a stronger player";
1594   /* Try to attack for a card, attack a stronger player */
1595   for (int destCountry = 0;
1596         destCountry < m_world->getCountries().size();
1597         destCountry++)
1598   {
1599     Player* iEnemy = RISK_GetOwnerOfCountry(destCountry);
1600     if (    (iEnemy != this)
1601           && isStrongerPlayer(iEnemy))
1602     {
1603       if (ComputerAttack (destCountry, false,
1604                           (RISK_GetNumArmiesOfCountry(destCountry) < 2)?1:100))
1605       {
1606         qCDebug(KSIRK_LOG) << "Attack tempted.";
1607         return true;
1608       }
1609     }
1610   }
1611 
1612   qCDebug(KSIRK_LOG) << "11 Try to attack for a card";
1613   /* Try to attack for a card */
1614   for (int destCountry = 0;
1615         destCountry < m_world->getCountries().size();
1616         destCountry++)
1617   {
1618     if (RISK_GetOwnerOfCountry(destCountry) != this)
1619     {
1620       if (ComputerAttack (destCountry, false,
1621                           RISK_GetNumArmiesOfCountry(destCountry)
1622 //                           (RISK_GetNumArmiesOfCountry(destCountry) < 2)?1:100
1623                           ))
1624       {
1625         qCDebug(KSIRK_LOG) << "Attack tempted.";
1626         return true;
1627       }
1628     }
1629   }
1630 
1631   qCDebug(KSIRK_LOG) << "No attack tried";
1632   // No attack tried
1633   Attack_SrcCountry = -1;
1634   Attack_DestCountry = -1;
1635   return false;
1636 }
1637 
1638 bool AIColsonPlayer::Attack()
1639 {
1640   qCDebug(KSIRK_LOG);
1641   int enemyAlive;
1642 
1643 //   if (RISK_GetAttackModeOfPlayer (player) != ACTION_DOORDIE)
1644 //       RISK_SetAttackModeOfPlayer (player, ACTION_DOORDIE);
1645 //   if (RISK_GetDiceModeOfPlayer (player) != ATTACK_AUTO)
1646 //       RISK_SetDiceModeOfPlayer (player, ATTACK_AUTO);
1647 
1648   enemyAlive = getNumEnemy();
1649   while ((enemyAlive == 0) && (m_levelEnemy >0))
1650     {
1651       m_levelEnemy--;
1652       enemyAlive = getNumEnemy();
1653     }
1654 
1655   return AttackEnemy();
1656 }
1657 
1658 void AIColsonPlayer::HowManyArmiesToMove(int *nb)
1659 {
1660   if ((Attack_SrcCountry == -1) || (Attack_DestCountry == -1))
1661       return;
1662 
1663   if (!GAME_IsEnemyAdjacent(Attack_SrcCountry))
1664       *nb = 0;
1665   else if (!GAME_IsEnemyAdjacent(Attack_DestCountry))
1666       *nb = *nb;
1667   else
1668       *nb = *nb/2;
1669   Attack_SrcCountry  = -1;
1670   Attack_DestCountry = -1;
1671 }
1672 
1673 int AIColsonPlayer::FindEnemyAdjacent(int iCountry, int distance)
1674 {
1675   if (m_enemyAdjacent.find(std::make_pair(iCountry,distance))!=m_enemyAdjacent.end())
1676   {
1677     return m_enemyAdjacent[std::make_pair(iCountry,distance)];
1678   }
1679   qCDebug(KSIRK_LOG) << iCountry << distance;
1680   int i, min, res, dest;
1681 
1682   Player* iPlayer = RISK_GetOwnerOfCountry(iCountry);
1683   min = 100000;
1684   for (i=0; i!=6 && RISK_GetAdjCountryOfCountry(iCountry, i)!=-1; i++)
1685   {
1686     dest = RISK_GetAdjCountryOfCountry(iCountry, i);
1687     if (RISK_GetOwnerOfCountry(dest) == iPlayer)
1688     {
1689       if (distance <= 3)
1690       {
1691         res = FindEnemyAdjacent(dest, distance + 1);
1692         m_enemyAdjacent.insert(std::make_pair(std::make_pair(dest,distance+1),res));
1693 
1694         if (res < min)
1695             min = res;
1696       }
1697     }
1698     else
1699     {
1700       min = 0;
1701     }
1702   }
1703 
1704   return (min + 1);
1705 }
1706 
1707 int AIColsonPlayer::GAME_FindEnemyAdjacent(int iCountry)
1708 {
1709   qCDebug(KSIRK_LOG) << iCountry;
1710   m_enemyAdjacent.clear();
1711   int i, min, res, dest, destCountry;
1712   Player* iPlayer = RISK_GetOwnerOfCountry(iCountry);
1713   destCountry = -1;
1714   min = 100000;
1715   for (i=0; i!=6 && RISK_GetAdjCountryOfCountry(iCountry, i)!=-1; i++)
1716   {
1717     qCDebug(KSIRK_LOG) << "  i = " << i;
1718     dest = RISK_GetAdjCountryOfCountry(iCountry, i);
1719     if (RISK_GetOwnerOfCountry(dest) == iPlayer)
1720     {
1721       res = FindEnemyAdjacent(dest, 0);
1722       m_enemyAdjacent.insert(std::make_pair(std::make_pair(dest,0),res));
1723       if (res < min)
1724       {
1725         min = res;
1726         destCountry = dest;
1727       }
1728     }
1729     else
1730     {
1731       min = 0;
1732     }
1733   }
1734 
1735   return (destCountry);
1736 }
1737 
1738 
1739 bool AIColsonPlayer::Move()
1740 {
1741   qCDebug(KSIRK_LOG);
1742 
1743   /* Try to move an unused max army in a frontier */
1744   int iCountry = -1;
1745   int max = 1;
1746   for (int i=0; i < m_world->getCountries().size();i++)
1747   {
1748     qCDebug(KSIRK_LOG) << "1: " << i;
1749     if (    (RISK_GetOwnerOfCountry(i) == this)
1750           && (RISK_GetNumArmiesOfCountry(i) > max)
1751           && !GAME_IsEnemyAdjacent(i))
1752     {
1753       max = RISK_GetNumArmiesOfCountry(i);
1754       qCDebug(KSIRK_LOG) << "country " << i << ", num armies:" << max;
1755       iCountry = i;
1756     }
1757   }
1758   qCDebug(KSIRK_LOG) << "1p iCountry=" << iCountry << "; max=" << max;
1759   if (iCountry>=0)
1760   {
1761     int destCountry = GAME_FindEnemyAdjacent(iCountry);
1762     qCDebug(KSIRK_LOG) << "  found adjacent enemy " << destCountry;
1763     if (destCountry >= 0)
1764     {
1765       AI_Move (iCountry, destCountry,
1766                   RISK_GetNumArmiesOfCountry(iCountry)-1);
1767       qCDebug(KSIRK_LOG) << "    Moved " << RISK_GetNumArmiesOfCountry(iCountry)-1;
1768       return true;
1769     }
1770   }
1771 
1772   qCDebug(KSIRK_LOG) << "2";
1773   /* Try to move an unused army in a country witch have a frontier */
1774   for (int iCountry = 0;iCountry < m_world->getCountries().size();iCountry++)
1775   {
1776     if (    (RISK_GetOwnerOfCountry(iCountry) == this)
1777           && (RISK_GetNumArmiesOfCountry(iCountry) > 2)
1778           && !GAME_IsEnemyAdjacent(iCountry))
1779     {
1780       int destCountry = GAME_FindEnemyAdjacent(iCountry);
1781       if (destCountry >= 0)
1782       {
1783         AI_Move (iCountry, destCountry,
1784                   RISK_GetNumArmiesOfCountry(iCountry)-1);
1785       qCDebug(KSIRK_LOG) << "    Moved " << RISK_GetNumArmiesOfCountry(iCountry)-1;
1786         return true;
1787       }
1788     }
1789   }
1790 
1791   qCDebug(KSIRK_LOG) << "3";
1792   for (int iCountry = 0;(iCountry < m_world->getCountries().size()); iCountry++)
1793   {
1794     if (    (RISK_GetOwnerOfCountry(iCountry) == this)
1795           && (RISK_GetNumArmiesOfCountry(iCountry) > 2)
1796           && !GAME_IsEnemyAdjacent(iCountry))
1797     {
1798       for (int i = 0; (i < 6) && (RISK_GetAdjCountryOfCountry(iCountry, i) != -1);i++)
1799       {
1800         int destCountry = RISK_GetAdjCountryOfCountry(iCountry, i);
1801         if (RISK_GetNumArmiesOfCountry(destCountry) == 1)
1802         {
1803           AI_Move (iCountry, destCountry,
1804                     RISK_GetNumArmiesOfCountry(iCountry)/2);
1805           qCDebug(KSIRK_LOG) << "    Moved " << RISK_GetNumArmiesOfCountry(iCountry)/2;
1806           return true;
1807         }
1808       }
1809     }
1810   }
1811   qCDebug(KSIRK_LOG) << "    Nothing Moved ";
1812 
1813   return false;
1814 }
1815 
1816 // void AIColsonPlayer::ExchangeCards(const Player* player)
1817 // {
1818 //   int i, this, nb, typ, piCards[4], nbCards[4], piCardValues[MAX_CARDS];
1819 //   bool fOptimal, fStronger, fSmaller;
1820 // 
1821 //   fStronger = isStrongerPlayer(player);
1822 //   fSmaller = isSmallerPlayer(player);
1823 //   nb = RISK_GetNumCardsOfPlayer(player);
1824 //   do
1825 //     {
1826 //       piCards[0]=piCards[1]=piCards[2]=piCards[3]=-1;
1827 //       nbCards[0]=nbCards[1]=nbCards[2]=nbCards[3]=0;
1828 //       fOptimal = false;
1829 //       for (i=0; i<nb; i++)
1830 //         {
1831 //           piCardValues[i] = RISK_GetCardOfPlayer(player, i);
1832 //           /* Set the type of the card */
1833 //           if (piCardValues[i]<m_world->getCountries().size())
1834 //             {
1835 //               typ = piCardValues[i] % 3;
1836 //        nbCards[typ]++;
1837 //               if (RISK_GetOwnerOfCountry(piCardValues[i]) == player)
1838 //            piCards[typ] = i;
1839 //               else if (piCards[typ] == -1)
1840 //                piCards[typ] = i;
1841 //             }
1842 //    else  /* Joker */
1843 //             {
1844 //        piCards[3] = i;
1845 //        nbCards[3]++;
1846 //      }
1847 //         }
1848 //       if ((nbCards[0]>0)&&(nbCards[1]>0)&&(nbCards[2]>0))
1849 //         {
1850 //           AI_ExchangeCards(piCards);
1851 //           fOptimal = true;
1852 //         }
1853 //       else if ((nbCards[3]>=2)&&((nbCards[0]>0)||(nbCards[1]>0)||(nbCards[2]>0)))
1854 //         {
1855 //           if (nbCards[2]>1)
1856 //             {
1857 //               piCards[1] = piCards[3];
1858 //               j = 0;
1859 //             }
1860 //           else if (nbCards[1]>1)
1861 //             {
1862 //               piCards[0] = piCards[3];
1863 //               j = 2;
1864 //             }
1865 //           else if (nbCards[0]>1)
1866 //             {
1867 //               piCards[2] = piCards[3];
1868 //               j = 1;
1869 //             }
1870 //           else if (nbCards[2]>0)
1871 //             {
1872 //               piCards[1] = piCards[3];
1873 //               j = 0;
1874 //             }
1875 //           else if (nbCards[1]>0)
1876 //             {
1877 //               piCards[0] = piCards[3];
1878 //               j = 2;
1879 //             }
1880 //           else
1881 //             {
1882 //               piCards[2] = piCards[3];
1883 //               j = 1;
1884 //             }
1885 //           i = 0;
1886 //           while (i<nb)
1887 //             {
1888 //               if (piCardValues[i] >= m_world->getCountries().size())
1889 //                 {
1890 //                   piCards[j]=i;
1891 //                   i = nb;
1892 //                 }
1893 //               else
1894 //                   i++;
1895 //             }
1896 //           AI_ExchangeCards(piCards);
1897 //           fOptimal = true;
1898 //         }
1899 //       else if (!fStronger && (nbCards[0]>=3))
1900 //         {
1901 //           j = 0;
1902 //           for (i=0; i<nb; i++)
1903 //               if ((piCardValues[i] % 3) == 0)
1904 //                   piCards[j++]=i;
1905 //           AI_ExchangeCards(piCards);
1906 //         }
1907 //       else if (fSmaller && (nbCards[1]>=3))
1908 //         {
1909 //           j = 0;
1910 //           for (i=0; i<nb; i++)
1911 //               if ((piCardValues[i] % 3) == 1)
1912 //                   piCards[j++]=i;
1913 //           AI_ExchangeCards(piCards);
1914 //         }
1915 //       else if (fSmaller && (nbCards[2]>=3))
1916 //         {
1917 //           j = 0;
1918 //           for (i=0; i<nb; i++)
1919 //               if ((piCardValues[i] % 3) == 2)
1920 //                   piCards[j++]=i;
1921 //           AI_ExchangeCards(piCards);
1922 //         }
1923 //       else if (nb >= 5)
1924 //         {
1925 //           if ((nbCards[0]>0)&&(nbCards[1]>0)&&(nbCards[3]>0))
1926 //               piCards[2] = piCards[3];
1927 //           else if ((nbCards[0]>0)&&(nbCards[3]>0)&&(nbCards[2]>0))
1928 //               piCards[1] = piCards[3];
1929 //           else if ((nbCards[3]>0)&&(nbCards[1]>0)&&(nbCards[2]>0))
1930 //               piCards[0] = piCards[3];
1931 //           else if (nbCards[0]>=3)
1932 //             {
1933 //               j = 0;
1934 //               for (i=0; i<nb; i++)
1935 //                   if ((piCardValues[i] % 3) == 0)
1936 //                       piCards[j++]=i;
1937 //             }
1938 //           else if (nbCards[1]>=3)
1939 //             {
1940 //               j = 0;
1941 //               for (i=0; i<nb; i++)
1942 //                   if ((piCardValues[i] % 3) == 1)
1943 //                       piCards[j++]=i;
1944 //             }
1945 //           else if (nbCards[2]>=3)
1946 //             {
1947 //               j = 0;
1948 //               for (i=0; i<nb; i++)
1949 //                   if ((piCardValues[i] % 3) == 2)
1950 //                       piCards[j++]=i;
1951 //             }
1952 //           else
1953 //             {
1954 //               piCards[0] = 0;
1955 //               piCards[1] = 1;
1956 //               piCards[2] = 2;
1957 //             }
1958 //           AI_ExchangeCards(piCards);
1959 //         }
1960 //       nb = RISK_GetNumCardsOfPlayer(player);
1961 //     }
1962 //   while ((fOptimal && (nb >= 3)) || (nb >= 5));
1963 // }
1964 
1965 // void AIColsonPlayer::COLSON_Play(void *pData, int iCommand, void *pArgs)
1966 // {
1967 //   switch(iCommand)
1968 //     {
1969 //     case AI_INIT_ONCE:
1970 //     {
1971 //       /* InitClient((int)pArgs); */
1972 //     }
1973 //     break;
1974 // 
1975 //     case AI_INIT_TURN:
1976 //     {
1977 //       m_numTurn[m_game->currentPlayer()]++;
1978 //     }
1979 //     break;
1980 // 
1981 //     case AI_FORTIFY:
1982 //     {
1983 //       Fortify();
1984 //     }
1985 //     break;
1986 // 
1987 //     case AI_PLACE:
1988 //     {
1989 //       Place();
1990 //     }
1991 //     break;
1992 // 
1993 //     case AI_ATTACK:
1994 //     {
1995 //       Attack();
1996 //     }
1997 //     break;
1998 // 
1999 //     case AI_MOVE_MANUAL:
2000 //     {
2001 //       HowManyArmiesToMove((int *)pArgs);
2002 //     }
2003 //     break;
2004 // 
2005 //     case AI_MOVE:
2006 //     {
2007 //       Move();
2008 //     }
2009 //     break;
2010 // 
2011 //     case AI_EXCHANGE_CARDS:
2012 //     {
2013 // //         ExchangeCards(m_game->currentPlayer());
2014 //     }
2015 //     break;
2016 // 
2017 //     case AI_SERVER_MESSAGE:
2018 //     {
2019 //     }
2020 //     break;
2021 // 
2022 //   }
2023 // 
2024 // //   return pData;
2025 // }
2026 
2027 void AIColsonPlayer::finalize()
2028 {
2029   qCDebug(KSIRK_LOG); 
2030 
2031   for (int i=0; i<m_game->playerList()->count(); i++)
2032   {
2033     m_isEnemyPlayer[(Player*)m_game->playerList()->at(i)] = 0;
2034   }
2035   PlayersArray::iterator it = m_game->playerList()->begin();
2036   PlayersArray::iterator it_end = m_game->playerList()->end();
2037   for (; it != it_end; it++)
2038   {
2039     Player* player = (Player*)*it;
2040     m_numTurn[player] = 0;
2041     if (dynamic_cast<AIColsonPlayer*>(player)!=nullptr)
2042         m_isEnemyPlayer[player] = 1;
2043     else if (player->author() == AUTHOR)
2044         m_isEnemyPlayer[player] = 2;
2045     else if (player->isAI())
2046         m_isEnemyPlayer[player] = 3;
2047     else
2048         m_isEnemyPlayer[player] = 4;
2049   }
2050   m_levelEnemy = 3;
2051   computeChoiceOfContinent();
2052   m_initialized = true;
2053   qCDebug(KSIRK_LOG) <<"    init done.";
2054 }
2055 
2056 int AIColsonPlayer::AI_Place(int iCountry, int iNumArmies)
2057 {
2058   qCDebug(KSIRK_LOG) << iNumArmies 
2059             << " on country number " << iCountry;
2060   if (m_placeData != nullptr)
2061   {
2062     delete m_placeData;
2063   }
2064   m_placeData = new PlaceData();
2065   m_placeData->dest = m_game->game()->theWorld()->getCountries()[iCountry];
2066   m_placeData->nb = iNumArmies;
2067   return 0;
2068 }
2069 
2070 int AIColsonPlayer::AI_Move(int iSrcCountry, int iDstCountry, int iNumArmies)
2071 {
2072   qCDebug(KSIRK_LOG) << iSrcCountry << ", " << iDstCountry << ", " << iNumArmies;
2073   m_src = m_game->game()->theWorld()->getCountries()[iSrcCountry];
2074   m_dest = m_game->game()->theWorld()->getCountries()[iDstCountry];
2075   m_toMove = iNumArmies;
2076   qCDebug(KSIRK_LOG) << iNumArmies << " armies from "
2077       << m_src->name() << " to " << m_dest->name();
2078   
2079   QByteArray buffer;
2080   QDataStream stream(&buffer, QIODevice::WriteOnly);
2081   stream << QString("actionLButtonDown") << m_src->centralPoint();
2082   aiPlayerIO()->sendInput(stream,true);
2083 
2084   QByteArray buffer2;
2085   QDataStream stream2(&buffer2, QIODevice::WriteOnly);
2086   stream2 << QString("actionLButtonUp") << m_dest->centralPoint();
2087   aiPlayerIO()->sendInput(stream2,true);
2088 
2089   Attack_SrcCountry = m_game->game()->theWorld()->getCountries().indexOf(const_cast<Country*>(m_src));
2090   Attack_DestCountry = m_game->game()->theWorld()->getCountries().indexOf(const_cast<Country*>(m_dest));
2091 
2092   stop();
2093   return 0;
2094 }
2095 
2096 
2097 //////////////////////////////////////////////////////////
2098 // Tool functions reimplemented from other parts of XFrisk
2099 //////////////////////////////////////////////////////////
2100 
2101 Player* AIColsonPlayer::RISK_GetOwnerOfCountry(int i)
2102 {
2103   return m_world->getCountries().at(i)->owner();
2104 }
2105 
2106 Continent* AIColsonPlayer::RISK_GetContinentOfCountry(int i)
2107 {
2108   return m_world->getCountries().at(i)->continent();
2109 }
2110 
2111 
2112 bool AIColsonPlayer::GAME_IsEnemyAdjacent(int i)
2113 {
2114   qCDebug(KSIRK_LOG) << i;
2115   return m_game->game()->theWorld()->getCountries()[i]->hasAdjacentEnemy();
2116 }
2117 
2118 int AIColsonPlayer::RISK_GetNumArmiesOfCountry(int i)
2119 {
2120   return m_world->getCountries().at(i)->nbArmies();
2121 }
2122 
2123 
2124 /** Returns the position in the countries list of the ith adjacent country of country iCountry */
2125 int AIColsonPlayer::RISK_GetAdjCountryOfCountry(int iCountry, int j)
2126 {
2127   Country* country = m_world->getCountries().at(iCountry);
2128   if (j >= country->neighbours().size())
2129   {
2130     return -1;
2131   }
2132   Country* neighbour = country->neighbours()[j];
2133   for (int i=0; i<m_world->getCountries().size(); i++)
2134   {
2135     if (m_world->getCountries().at(i) == neighbour)
2136     {
2137       return i;
2138     }
2139   }
2140   return -1;
2141 }
2142 
2143 int AIColsonPlayer::RISK_GetNumArmiesOfPlayer(Player* player)
2144 {
2145   return player->getNbAvailArmies();
2146 }
2147 
2148 int AIColsonPlayer::RISK_GetNumCountriesOfPlayer(const Player* player)
2149 {
2150   return player->countries().size();
2151 }
2152 
2153 
2154 } // closing namespace GameLogic
2155 
2156 } // closing namespace Ksirk
2157