// ============================================================== // This file is part of Glest (www.glest.org) // // Copyright (C) 2001-2008 MartiƱo Figueroa // // You can redistribute this code and/or modify it under // the terms of the GNU General Public License as published // by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version // ============================================================== #ifndef _GLEST_GAME_AI_H_ #define _GLEST_GAME_AI_H_ #include #include #include "world.h" #include "commander.h" #include "command.h" #include "randomgen.h" #include "leak_dumper.h" using std::deque; using std::vector; using std::list; using Shared::Util::RandomGen; namespace Glest{ namespace Game{ class AiInterface; class AiRule; // ===================================================== // class Task // /// An action that has to be performed by the IA // ===================================================== enum TaskClass{ tcProduce, tcBuild, tcUpgrade }; class Task{ protected: TaskClass taskClass; public: Task(); virtual ~Task(){} TaskClass getClass() const {return taskClass;} virtual string toString() const= 0; virtual void saveGame(XmlNode *rootNode) const = 0; }; // ==================== ProduceTask ==================== class ProduceTask: public Task{ private: UnitClass unitClass; const UnitType *unitType; const ResourceType *resourceType; ProduceTask(); public: explicit ProduceTask(UnitClass unitClass); explicit ProduceTask(const UnitType *unitType); explicit ProduceTask(const ResourceType *resourceType); UnitClass getUnitClass() const {return unitClass;} const UnitType *getUnitType() const {return unitType;} const ResourceType *getResourceType() const {return resourceType;} virtual string toString() const; virtual void saveGame(XmlNode *rootNode) const; static ProduceTask * loadGame(const XmlNode *rootNode, Faction *faction); }; // ==================== BuildTask ==================== class BuildTask: public Task{ private: const UnitType *unitType; const ResourceType *resourceType; bool forcePos; Vec2i pos; BuildTask(); public: explicit BuildTask(const UnitType *unitType); explicit BuildTask(const ResourceType *resourceType); BuildTask(const UnitType *unitType, const Vec2i &pos); const UnitType *getUnitType() const {return unitType;} const ResourceType *getResourceType() const {return resourceType;} bool getForcePos() const {return forcePos;} Vec2i getPos() const {return pos;} virtual string toString() const; virtual void saveGame(XmlNode *rootNode) const; static BuildTask * loadGame(const XmlNode *rootNode, Faction *faction); }; // ==================== UpgradeTask ==================== class UpgradeTask: public Task{ private: const UpgradeType *upgradeType; UpgradeTask(); public: explicit UpgradeTask(const UpgradeType *upgradeType); const UpgradeType *getUpgradeType() const {return upgradeType;} virtual string toString() const; virtual void saveGame(XmlNode *rootNode) const; static UpgradeTask * loadGame(const XmlNode *rootNode, Faction *faction); }; // =============================== // class AI // /// Main AI class // =============================== class Ai { private: int maxBuildRadius; int minMinWarriors; int minMinWarriorsExpandCpuEasy; int minMinWarriorsExpandCpuMega; int minMinWarriorsExpandCpuUltra; int minMinWarriorsExpandCpuNormal; int maxMinWarriors; int maxExpansions; int villageRadius; int scoutResourceRange; int minWorkerAttackersHarvesting; int minBuildSpacing; public: enum ResourceUsage { ruHarvester, ruWarrior, ruBuilding, ruUpgrade }; private: typedef vector AiRules; typedef list Tasks; typedef deque Positions; private: AiInterface *aiInterface; AiRules aiRules; int startLoc; bool randomMinWarriorsReached; Tasks tasks; Positions expansionPositions; RandomGen random; std::map factionSwitchTeamRequestCount; int minWarriors; bool getAdjacentUnits(std::map > &signalAdjacentUnits, const Unit *unit); public: Ai() { // Defaults that used to be static which can now be overriden maxBuildRadius = 40; minMinWarriors = 7; minMinWarriorsExpandCpuEasy = 1; minMinWarriorsExpandCpuMega = 3; minMinWarriorsExpandCpuUltra = 3; minMinWarriorsExpandCpuNormal = 3; maxMinWarriors = 20; maxExpansions = 2; villageRadius = 15; scoutResourceRange = 20; minWorkerAttackersHarvesting = 3; minBuildSpacing = 1; aiInterface = NULL; startLoc = -1; randomMinWarriorsReached = false; minWarriors = 0; } ~Ai(); void init(AiInterface *aiInterface,int useStartLocation=-1); void update(); //state requests AiInterface *getAiInterface() const {return aiInterface;} RandomGen* getRandom(); int getCountOfType(const UnitType *ut); int getMinWarriors() const { return minWarriors; } int getCountOfClass(UnitClass uc,UnitClass *additionalUnitClassToExcludeFromCount=NULL); float getRatioOfClass(UnitClass uc,UnitClass *additionalUnitClassToExcludeFromCount=NULL); const ResourceType *getNeededResource(int unitIndex); bool isStableBase(); bool findPosForBuilding(const UnitType* building, const Vec2i &searchPos, Vec2i &pos); bool findAbleUnit(int *unitIndex, CommandClass ability, bool idleOnly); bool findAbleUnit(int *unitIndex, CommandClass ability, CommandClass currentCommand); //vector findUnitsDoingCommand(CommandClass currentCommand); vector findUnitsHarvestingResourceType(const ResourceType *rt); bool beingAttacked(Vec2i &pos, Field &field, int radius); //tasks void addTask(const Task *task); void addPriorityTask(const Task *task); bool anyTask(); const Task *getTask() const; void removeTask(const Task *task); void retryTask(const Task *task); //expansions void addExpansion(const Vec2i &pos); Vec2i getRandomHomePosition(); //actions void sendScoutPatrol(); void massiveAttack(const Vec2i &pos, Field field, bool ultraAttack= false); void returnBase(int unitIndex); void harvest(int unitIndex); bool haveBlockedUnits(); void unblockUnits(); bool outputAIBehaviourToConsole() const; void saveGame(XmlNode *rootNode) const; void loadGame(const XmlNode *rootNode, Faction *faction); }; }}//end namespace #endif