/* * Nullkiller.h, part of VCMI engine * * Authors: listed in file AUTHORS in main folder * * License: GNU General Public License v2.0 or later * Full text of license available in license.txt file, in main folder * */ #pragma once #include "PriorityEvaluator.h" #include "FuzzyHelper.h" #include "Settings.h" #include "AIMemory.h" #include "DeepDecomposer.h" #include "../Analyzers/DangerHitMapAnalyzer.h" #include "../Analyzers/BuildAnalyzer.h" #include "../Analyzers/ArmyManager.h" #include "../Analyzers/HeroManager.h" #include "../Analyzers/ObjectClusterizer.h" #include "../Helpers/ArmyFormation.h" namespace NKAI { const float MIN_PRIORITY = 0.01f; const float SMALL_SCAN_MIN_PRIORITY = 0.4f; enum class HeroLockedReason { NOT_LOCKED = 0, STARTUP = 1, DEFENCE = 2, HERO_CHAIN = 3 }; enum class ScanDepth { MAIN_FULL = 0, SMALL = 1, ALL_FULL = 2 }; struct TaskPlanItem { std::vector affectedObjects; Goals::TSubgoal task; TaskPlanItem(Goals::TSubgoal goal); }; class TaskPlan { private: std::vector tasks; public: Goals::TTaskVec getTasks() const; void merge(Goals::TSubgoal task); }; class Nullkiller { private: const CGHeroInstance * activeHero; int3 targetTile; ObjectInstanceID targetObject; std::map lockedHeroes; ScanDepth scanDepth; TResources lockedResources; bool useHeroChain; AIGateway * gateway; bool openMap; bool useObjectGraph; public: static std::unique_ptr baseGraph; std::unique_ptr dangerHitMap; std::unique_ptr buildAnalyzer; std::unique_ptr objectClusterizer; std::unique_ptr priorityEvaluator; std::unique_ptr> priorityEvaluators; std::unique_ptr pathfinder; std::unique_ptr heroManager; std::unique_ptr armyManager; std::unique_ptr memory; std::unique_ptr dangerEvaluator; std::unique_ptr decomposer; std::unique_ptr armyFormation; std::unique_ptr settings; PlayerColor playerID; std::shared_ptr cb; std::mutex aiStateMutex; Nullkiller(); void init(std::shared_ptr cb, AIGateway * gateway); void makeTurn(); bool isActive(const CGHeroInstance * hero) const { return activeHero == hero; } bool isHeroLocked(const CGHeroInstance * hero) const; HeroPtr getActiveHero() { return activeHero; } HeroLockedReason getHeroLockedReason(const CGHeroInstance * hero) const; int3 getTargetTile() const { return targetTile; } ObjectInstanceID getTargetObject() const { return targetObject; } void setTargetObject(int objid) { targetObject = ObjectInstanceID(objid); } void setActive(const CGHeroInstance * hero, int3 tile) { activeHero = hero; targetTile = tile; } void lockHero(const CGHeroInstance * hero, HeroLockedReason lockReason) { lockedHeroes[hero] = lockReason; } void unlockHero(const CGHeroInstance * hero) { lockedHeroes.erase(hero); } bool arePathHeroesLocked(const AIPath & path) const; TResources getFreeResources() const; int32_t getFreeGold() const { return getFreeResources()[EGameResID::GOLD]; } void lockResources(const TResources & res); const TResources & getLockedResources() const { return lockedResources; } ScanDepth getScanDepth() const { return scanDepth; } bool isOpenMap() const { return openMap; } bool isObjectGraphAllowed() const { return useObjectGraph; } bool handleTrading(); private: void resetAiState(); void updateAiState(int pass, bool fast = false); void decompose(Goals::TGoalVec & result, Goals::TSubgoal behavior, int decompositionMaxDepth) const; Goals::TTask choseBestTask(Goals::TGoalVec & tasks) const; Goals::TTaskVec buildPlan(Goals::TGoalVec & tasks, int priorityTier) const; bool executeTask(Goals::TTask task); bool areAffectedObjectsPresent(Goals::TTask task) const; HeroRole getTaskRole(Goals::TTask task) const; }; }