File indexing completed on 2024-04-28 07:53:30

0001 /* This file is part of KsirK.
0002    Copyright (C) 2002-2007 Gael de Chalendar <kleag@free.fr>
0003 
0004    KsirK is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU General Public
0006    License as published by the Free Software Foundation, either version 2
0007    of the License, or (at your option) any later version.
0008 
0009    This program is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    General Public License for more details.
0013 
0014    You should have received a copy of the GNU General Public License
0015    along with this program; if not, write to the Free Software
0016    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
0017    02110-1301, USA
0018 */
0019 
0020 #ifndef AIPLAYER_H
0021 #define AIPLAYER_H
0022 
0023 #include "GameLogic/gameautomaton.h"
0024 #include "GameLogic/player.h"
0025 #include "GameLogic/country.h"
0026 
0027 #include <QThread>
0028 
0029 namespace Ksirk
0030 {
0031 
0032 namespace GameLogic
0033 {
0034 
0035 class Nationality;
0036 class ONU;
0037 class AIPlayerIO;
0038 class GameAutomaton;
0039 
0040 /**
0041   * This class represents a computer player. It holds all strategic routines.
0042   * @author Gael de Chalendar (aka Kleag)
0043   */
0044 class AIPlayer : public Player
0045 {
0046 Q_OBJECT
0047 
0048 public: 
0049   /** 
0050     * Constructor with simple initializations
0051     */
0052   explicit AIPlayer(
0053           const QString & nomPlayer, unsigned int nbArmies,
0054           Nationality * myNation,  PlayersArray& players, ONU* world,
0055           GameAutomaton* game );
0056 
0057   /** Default destructor. */
0058   ~AIPlayer() override;
0059 
0060   /**
0061     * The idendification of the player. Overwrite this in
0062     * classes inherting KPlayer to run time identify them.
0063     *
0064     * @return 2 for this class.
0065   */
0066   int rtti() const override {return 2;}
0067   
0068   /**
0069     * Returns true (an AIPlayer is an AI)
0070     */
0071   bool isAI() const override;
0072 
0073     /** set stopMe to true in order for the run method to return */
0074   void stop();
0075     
0076   /**
0077     * Saves this AI player as XML. Used in game saving.
0078     * @param xmlStream The stream on which to write the XML
0079     */
0080   void saveXml(QTextStream& xmlStream) override;
0081 
0082   bool isRunning () const {return m_thread.isRunning();}
0083 
0084 public Q_SLOTS:
0085   void start ( QThread::Priority priority = QThread::InheritPriority ) {m_thread.start(priority);}
0086 
0087 protected:
0088   /** 
0089     * This function is called whenever the player should choose an action 
0090     * (attack, defense, etc.). It has the responsibility to choose the correct
0091     * action depending on the state of the game.
0092     */
0093   void actionChoice(GameLogic::GameAutomaton::GameState state) override;
0094 
0095   /** Returns a pair of countries where the attacker have enough armies to 
0096     * attack and the defender is a ennemy neighbour of the attacker */
0097   virtual QPair< const Country*, const Country* > chooseBelligerant();
0098 
0099   /**
0100     * Chooses the next action. In the current basic setting, chooses at random
0101     * between the three possibilities. For each, chooses randomly the
0102     * parameters.If the randomly chosen parameters end by an impossible
0103     * action, continue with next player.
0104     */
0105   virtual void chooseAttackMoveArmiesOrNextPlayer();
0106 
0107   /**
0108     * Chooses a country to receive a new army in dotation
0109     */
0110   virtual Country* chooseReceivingCountry();
0111   
0112   /**
0113     * chooses to continue invasion with a certain amount of armies or to stop it
0114     */
0115   virtual void chooseInvasionAction();
0116   
0117   /**
0118     * make all what is necessary to prepare and launch an attack
0119     * @return true if was able to prepare an attack ; false otherwise
0120     */
0121   bool attackAction();
0122   
0123   /**
0124     * makes all what is necessary to prepare and start the moving of armies
0125     */
0126   virtual bool moveArmiesAction();
0127   
0128   /**
0129     * makes what is necessary to finish my turn
0130     */
0131   void nextPlayerAction();
0132 
0133 protected: // Private attributes
0134   class MyThread: public QThread
0135   {
0136   protected:
0137     void run () override;
0138     
0139   public:
0140     explicit MyThread(AIPlayer& p) : me(p) {}
0141     void setStopMe ( bool value ) { stopMe = value; }
0142   private:
0143     /** indicates to the thread if the run method should return */
0144     bool stopMe;
0145     AIPlayer& me;
0146   };
0147 
0148   AIPlayerIO* aiPlayerIO();
0149   
0150 /**
0151     * Pointer to the players. Information about them is necessary decide of
0152     * a strategy
0153     */
0154   PlayersArray& allPlayers;
0155 
0156   /**
0157     * Pointer to the World to consult it in order to decide the actions
0158     */
0159   ONU* m_world;
0160 
0161   /**
0162     * a pointer to the game. Necessary to be able to access the number of
0163     * attackers, etc. This solution is not very pretty... but an important
0164     * architectural change should be done to avoid it (@todo).
0165     */
0166   GameAutomaton* m_game;
0167 
0168  /**
0169    * a pointer to the game attribute defenseAuto
0170    *
0171    */
0172  // GameAutomaton* m_defenseAuto;
0173 
0174   /** pointers to the source and target country of an attack */
0175   const Country* m_src;
0176   const Country* m_dest;
0177 
0178   /** number of armies to move during an invasion or an end of turn moving */
0179   unsigned int m_toMove;
0180     
0181   bool m_hasVoted;
0182   bool m_actionWaitingStart;
0183   
0184   MyThread m_thread;
0185 
0186 private: // Private methods
0187   /**
0188     * chooses whether to defend with one or two armies. Always chooses the maximum possible
0189     */
0190   void chooseDefenseAction();
0191   
0192   /**
0193     * Takes the decision to recycle armies or not
0194     */
0195   void chooseWetherToRecycle();
0196   
0197   /**
0198     * chooses a country where to place a new army
0199     */
0200   void placeArmiesAction();
0201   
0202   /** Makes the choice of nb armies to move during an invasion or an end of turn moving */
0203   void chooseNbToMoveOrStop();
0204   
0205   /** Starts the timer of this player that will make it "think" all 200 ms. */
0206   void run();
0207 
0208   void requestAck();
0209 };
0210 
0211 } // closing namespace GameLogic
0212 } // closing namespace Ksirk
0213 #endif
0214