1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-20 20:23:03 +02:00

NKAI: namespace

This commit is contained in:
Andrii Danylchenko 2022-09-26 21:01:07 +03:00
parent 5c44c8f4da
commit eeea01d778
121 changed files with 713 additions and 471 deletions

View File

@ -23,7 +23,8 @@
#include "AIGateway.h"
#include "Goals/Goals.h"
class CGVisitableOPW;
namespace NKAI
{
const float SAFE_ATTACK_CONSTANT = 1.2;
@ -1668,3 +1669,5 @@ bool AIStatus::channelProbing()
{
return ongoingChannelProbing;
}
}

View File

@ -25,11 +25,8 @@
#include "Pathfinding/AIPathfinder.h"
#include "Engine/Nullkiller.h"
VCMI_LIB_NAMESPACE_BEGIN
struct QuestInfo;
VCMI_LIB_NAMESPACE_END
namespace NKAI
{
class AIStatus
{
@ -222,3 +219,5 @@ public:
h & battlename;
}
};
}

View File

@ -20,6 +20,9 @@
#include "../../lib/CModHandler.h"
namespace NKAI
{
extern boost::thread_specific_ptr<AIGateway> ai;
//extern static const int3 dirs[8];
@ -446,3 +449,5 @@ bool shouldVisit(const Nullkiller * ai, const CGHeroInstance * h, const CGObject
return true;
}
}

View File

@ -48,19 +48,19 @@
#include "../../lib/mapObjects/CObjectHandler.h"
#include "../../lib/mapObjects/CGHeroInstance.h"
#include "../../lib/CPathfinder.h"
#include "../../CCallback.h"
#include <chrono>
using namespace tbb;
class CCallback;
class Nullkiller;
struct creInfo;
typedef const int3 & crint3;
typedef const std::string & crstring;
typedef std::pair<ui32, std::vector<CreatureID>> dwellingContent;
namespace NKAI
{
struct creInfo;
class Nullkiller;
const int GOLD_MINE_PRODUCTION = 1000, WOOD_ORE_MINE_PRODUCTION = 2, RESOURCE_MINE_PRODUCTION = 1;
const int ACTUAL_RESOURCE_COUNT = 7;
const int ALLOWED_ROAMING_HEROES = 8;
@ -151,39 +151,6 @@ struct ObjectIdRef
}
};
struct TimeCheck
{
CStopWatch time;
std::string txt;
TimeCheck(crstring TXT)
: txt(TXT)
{
}
~TimeCheck()
{
logAi->trace("Time of %s was %d ms.", txt, time.getDiff());
}
};
//TODO: replace with vstd::
struct AtScopeExit
{
std::function<void()> foo;
AtScopeExit(const std::function<void()> & FOO)
: foo(FOO)
{}
~AtScopeExit()
{
foo();
}
};
class ObjsVector : public std::vector<ObjectIdRef>
{
};
template<int id>
bool objWithID(const CGObjectInstance * obj)
{
@ -278,7 +245,7 @@ uint64_t timeElapsed(std::chrono::time_point<std::chrono::high_resolution_clock>
bool shouldVisit(const Nullkiller * ai, const CGHeroInstance * h, const CGObjectInstance * obj);
template<typename TFunc>
void pforeachTilePos(crint3 mapSize, TFunc fn)
void pforeachTilePos(const int3 & mapSize, TFunc fn)
{
for(int z = 0; z < mapSize.z; ++z)
{
@ -380,3 +347,5 @@ private:
std::shared_ptr<SharedPool<T> *> instance_tracker;
boost::mutex sync;
};
}

View File

@ -14,6 +14,8 @@
#include "../../../CCallback.h"
#include "../../../lib/mapObjects/MapObjects.h"
namespace NKAI
{
class StackUpgradeInfo
{
public:
@ -497,3 +499,5 @@ ArmyUpgradeInfo ArmyManager::calculateCreaturesUpgrade(
return result;
}
}

View File

@ -17,6 +17,9 @@
#include "../../../lib/CTownHandler.h"
#include "../../../lib/CBuildingHandler.h"
namespace NKAI
{
class Nullkiller;
struct SlotInfo
@ -102,3 +105,5 @@ private:
std::vector<StackUpgradeInfo> getHillFortUpgrades(const CCreatureSet * army) const;
std::vector<StackUpgradeInfo> getDwellingUpgrades(const CCreatureSet * army, const CGDwelling * dwelling) const;
};
}

View File

@ -12,6 +12,9 @@
#include "../../../lib/mapping/CMap.h" //for victory conditions
#include "../Engine/Nullkiller.h"
namespace NKAI
{
void BuildAnalyzer::updateTownDwellings(TownDevelopmentInfo & developmentInfo)
{
auto townInfo = developmentInfo.town->town;
@ -394,3 +397,5 @@ std::string BuildingInfo::toString() const
+ " x " + creatureCost.toString()
+ ", daily: " + dailyIncome.toString();
}
}

View File

@ -12,6 +12,9 @@
#include "../AIUtility.h"
#include "../../../lib/ResourceSet.h"
namespace NKAI
{
class Nullkiller;
class DLL_EXPORT BuildingInfo
@ -104,3 +107,5 @@ private:
void updateDailyIncome();
void reset();
};
}

View File

@ -11,6 +11,9 @@
#include "lib/mapping/CMap.h" //for victory conditions
#include "../Engine/Nullkiller.h"
namespace NKAI
{
void DangerHitMapAnalyzer::updateHitMap()
{
if(upToDate)
@ -137,3 +140,5 @@ void DangerHitMapAnalyzer::reset()
{
upToDate = false;
}
}

View File

@ -11,6 +11,9 @@
#include "../AIUtility.h"
namespace NKAI
{
struct HitMapInfo
{
uint64_t danger;
@ -55,3 +58,5 @@ public:
const std::set<const CGObjectInstance *> & getOneTurnAccessibleObjects(const CGHeroInstance * enemy) const;
void reset();
};
}

View File

@ -13,6 +13,9 @@
#include "../../../lib/mapObjects/MapObjects.h"
#include "../../../lib/CHeroHandler.h"
namespace NKAI
{
SecondarySkillEvaluator HeroManager::wariorSkillsScores = SecondarySkillEvaluator(
{
std::make_shared<SecondarySkillScoreMap>(
@ -305,3 +308,5 @@ float SecondarySkillEvaluator::evaluateSecSkill(const CGHeroInstance * hero, Sec
return score;
}
}

View File

@ -17,6 +17,9 @@
#include "../../../lib/CTownHandler.h"
#include "../../../lib/CBuildingHandler.h"
namespace NKAI
{
class DLL_EXPORT IHeroManager //: public: IAbstractManager
{
public:
@ -104,3 +107,5 @@ private:
public:
void evaluateScore(const CGHeroInstance * hero, SecondarySkill skill, float & score) const override;
};
}

View File

@ -14,6 +14,9 @@
#include "../Engine/Nullkiller.h"
#include "lib/mapping/CMap.h" //for victory conditions
namespace NKAI
{
void ObjectCluster::addObject(const CGObjectInstance * obj, const AIPath & path, float priority)
{
ClusterObjects::accessor info;
@ -228,7 +231,7 @@ void ObjectClusterizer::clusterize()
if(!shouldVisitObject(obj))
return;
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Check object %s%s.", obj->getObjectName(), obj->visitablePos().toString());
#endif
@ -236,7 +239,7 @@ void ObjectClusterizer::clusterize()
if(paths.empty())
{
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("No paths found.");
#endif
continue;
@ -251,7 +254,7 @@ void ObjectClusterizer::clusterize()
{
farObjects.addObject(obj, paths.front(), 0);
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Object ignored. Moved to far objects with path %s", paths.front().toString());
#endif
@ -262,13 +265,13 @@ void ObjectClusterizer::clusterize()
for(auto & path : paths)
{
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Checking path %s", path.toString());
#endif
if(!shouldVisit(ai, path.targetHero, obj))
{
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Hero %s does not need to visit %s", path.targetHero->name, obj->getObjectName());
#endif
continue;
@ -282,7 +285,7 @@ void ObjectClusterizer::clusterize()
{
if(vstd::contains(heroesProcessed, path.targetHero))
{
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Hero %s is already processed.", path.targetHero->name);
#endif
continue;
@ -302,7 +305,7 @@ void ObjectClusterizer::clusterize()
cluster->second->addObject(obj, path, priority);
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Path added to cluster %s%s", blocker->getObjectName(), blocker->visitablePos().toString());
#endif
continue;
@ -327,7 +330,7 @@ void ObjectClusterizer::clusterize()
farObjects.addObject(obj, path, priority);
}
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Path %s added to %s objects. Turn: %d, priority: %f",
path.toString(),
interestingObject ? "near" : "far",
@ -345,7 +348,7 @@ void ObjectClusterizer::clusterize()
{
logAi->trace("Cluster %s %s count: %i", pair.first->getObjectName(), pair.first->visitablePos().toString(), pair.second->objects.size());
#if AI_TRACE_LEVEL >= 1
#if NKAI_TRACE_LEVEL >= 1
for(auto obj : pair.second->getObjects())
{
logAi->trace("Object %s %s", obj->getObjectName(), obj->visitablePos().toString());
@ -355,3 +358,5 @@ void ObjectClusterizer::clusterize()
logAi->trace("Clusterization complete in %ld", timeElapsed(start));
}
}

View File

@ -11,6 +11,9 @@
#include "../Pathfinding/AINodeStorage.h"
namespace NKAI
{
struct ClusterObjectInfo
{
float priority;
@ -72,3 +75,5 @@ public:
private:
bool shouldVisitObject(const CGObjectInstance * obj) const;
};
}

View File

@ -1,19 +0,0 @@
/*
* Behavior.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 "../AIGateway.h"
#error REMOVE THIS FILE
class Behavior : public Goals::AbstractGoal
{
public:
virtual std::string toString() const = 0;
};

View File

@ -19,6 +19,9 @@
#include "lib/CPathfinder.h"
#include "../Engine/Nullkiller.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -77,3 +80,5 @@ Goals::TGoalVec BuildingBehavior::decompose() const
return tasks;
}
}

View File

@ -13,6 +13,8 @@
#include "../AIUtility.h"
#include "../Goals/CGoal.h"
namespace NKAI
{
namespace Goals
{
class BuildingBehavior : public CGoal<BuildingBehavior>
@ -32,3 +34,4 @@ namespace Goals
};
}
}

View File

@ -16,6 +16,9 @@
#include "lib/mapping/CMap.h" //for victory conditions
#include "lib/CPathfinder.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -75,3 +78,5 @@ Goals::TGoalVec BuyArmyBehavior::decompose() const
return tasks;
}
}

View File

@ -13,6 +13,8 @@
#include "../AIUtility.h"
#include "../Goals/CGoal.h"
namespace NKAI
{
namespace Goals
{
class BuyArmyBehavior : public CGoal<BuyArmyBehavior>
@ -30,3 +32,5 @@ namespace Goals
}
};
}
}

View File

@ -12,9 +12,13 @@
#include "../Engine/Nullkiller.h"
#include "../Goals/Composition.h"
#include "../Goals/ExecuteHeroChain.h"
#include "../Goals/Invalid.h"
#include "CaptureObjectsBehavior.h"
#include "../AIUtility.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -59,13 +63,13 @@ Goals::TGoalVec CaptureObjectsBehavior::getVisitGoals(const std::vector<AIPath>
{
tasks.push_back(sptr(Goals::Invalid()));
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Path found %s", path.toString());
#endif
if(ai->nullkiller->dangerHitMap->enemyCanKillOurHeroesAlongThePath(path))
{
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Ignore path. Target hero can be killed by enemy. Our power %lld", path.heroArmy->getArmyStrength());
#endif
continue;
@ -85,7 +89,7 @@ Goals::TGoalVec CaptureObjectsBehavior::getVisitGoals(const std::vector<AIPath>
{
auto subGoal = firstBlockedAction->decompose(path.targetHero);
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Decomposing special action %s returns %s", firstBlockedAction->toString(), subGoal->toString());
#endif
@ -104,7 +108,7 @@ Goals::TGoalVec CaptureObjectsBehavior::getVisitGoals(const std::vector<AIPath>
auto isSafe = isSafeToVisit(hero, path.heroArmy, danger);
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace(
"It is %s to visit %s by %s with army %lld, danger %lld and army loss %lld",
isSafe ? "safe" : "not safe",
@ -161,7 +165,7 @@ Goals::TGoalVec CaptureObjectsBehavior::decompose() const
if(!objectMatchesFilter(objToVisit))
continue;
#if AI_TRACE_LEVEL >= 1
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Checking object %s, %s", objToVisit->getObjectName(), objToVisit->visitablePos().toString());
#endif
@ -171,7 +175,7 @@ Goals::TGoalVec CaptureObjectsBehavior::decompose() const
std::vector<std::shared_ptr<ExecuteHeroChain>> waysToVisitObj;
std::shared_ptr<ExecuteHeroChain> closestWay;
#if AI_TRACE_LEVEL >= 1
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Found %d paths", paths.size());
#endif
vstd::concatenate(tasks, getVisitGoals(paths, objToVisit));
@ -219,3 +223,5 @@ bool CaptureObjectsBehavior::objectMatchesFilter(const CGObjectInstance * obj) c
return true;
}
}

View File

@ -14,6 +14,8 @@
#include "../Goals/CGoal.h"
#include "../Pathfinding/AINodeStorage.h"
namespace NKAI
{
namespace Goals
{
class CaptureObjectsBehavior : public CGoal<CaptureObjectsBehavior>
@ -72,3 +74,5 @@ namespace Goals
};
}
}

View File

@ -16,6 +16,9 @@
#include "../Goals/Composition.h"
#include "../Behaviors/CaptureObjectsBehavior.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -50,7 +53,7 @@ Goals::TGoalVec ClusterBehavior::decomposeCluster(std::shared_ptr<ObjectCluster>
TGoalVec goals;
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace(
"Checking cluster %s %s, found %d paths",
cluster->blocker->getObjectName(),
@ -60,7 +63,7 @@ Goals::TGoalVec ClusterBehavior::decomposeCluster(std::shared_ptr<ObjectCluster>
for(auto path = paths.begin(); path != paths.end();)
{
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Checking path %s", path->toString());
#endif
@ -89,13 +92,13 @@ Goals::TGoalVec ClusterBehavior::decomposeCluster(std::shared_ptr<ObjectCluster>
for(auto & node : clonedPath.nodes)
node.parentIndex -= path->nodes.size() - clonedPath.nodes.size();
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Unlock path found %s", blockerPaths.back().toString());
#endif
path++;
}
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Decompose unlock paths");
#endif
@ -114,3 +117,5 @@ Goals::TGoalVec ClusterBehavior::decomposeCluster(std::shared_ptr<ObjectCluster>
return goals;
}
}

View File

@ -13,6 +13,9 @@
#include "../Goals/CGoal.h"
#include "../AIUtility.h"
namespace NKAI
{
struct ObjectCluster;
namespace Goals
@ -36,4 +39,6 @@ namespace Goals
private:
Goals::TGoalVec decomposeCluster(std::shared_ptr<ObjectCluster> cluster) const;
};
}
}
}

View File

@ -23,6 +23,9 @@
#include "lib/mapping/CMap.h" //for victory conditions
#include "lib/CPathfinder.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -117,7 +120,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
|| path.turn() < treat.turn - 1
|| (path.turn() < treat.turn && treat.turn >= 2))
{
#if AI_TRACE_LEVEL >= 1
#if NKAI_TRACE_LEVEL >= 1
logAi->trace(
"Hero %s can eliminate danger for town %s using path %s.",
path.targetHero->name,
@ -148,7 +151,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
if(cb->getHeroesInfo().size() < ALLOWED_ROAMING_HEROES)
{
#if AI_TRACE_LEVEL >= 1
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Hero %s can be recruited to defend %s", hero->name, town->name);
#endif
tasks.push_back(Goals::sptr(Goals::RecruitHero(town, hero).setpriority(1)));
@ -196,7 +199,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
{
auto & path = paths[i];
#if AI_TRACE_LEVEL >= 1
#if NKAI_TRACE_LEVEL >= 1
logAi->trace(
"Hero %s can defend town with force %lld in %s turns, cost: %f, path: %s",
path.targetHero->name,
@ -207,7 +210,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
#endif
if(path.turn() <= treat.turn - 2)
{
#if AI_TRACE_LEVEL >= 1
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Deffer defence of %s by %s because he has enough time to rich the town next trun",
town->name,
path.targetHero->name);
@ -220,7 +223,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
if(path.targetHero == town->visitingHero && path.exchangeCount == 1)
{
#if AI_TRACE_LEVEL >= 1
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Put %s to garrison of town %s",
path.targetHero->name,
town->name);
@ -244,7 +247,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
{
if(ai->nullkiller->arePathHeroesLocked(path))
{
#if AI_TRACE_LEVEL >= 1
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Can not move %s to defend town %s. Path is locked.",
path.targetHero->name,
town->name);
@ -272,7 +275,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
}
}
#if AI_TRACE_LEVEL >= 1
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Move %s to defend town %s",
path.targetHero->name,
town->name);
@ -286,13 +289,13 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
{
auto subGoal = firstBlockedAction->decompose(path.targetHero);
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Decomposing special action %s returns %s", firstBlockedAction->toString(), subGoal->toString());
#endif
if(subGoal->invalid())
{
#if AI_TRACE_LEVEL >= 1
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Path is invalid. Skipping");
#endif
continue;
@ -307,3 +310,5 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
logAi->debug("Found %d tasks", tasks.size());
}
}

View File

@ -13,6 +13,8 @@
#include "../Goals/CGoal.h"
#include "../AIUtility.h"
namespace NKAI
{
namespace Goals
{
class DefenceBehavior : public CGoal<DefenceBehavior>
@ -36,3 +38,5 @@ namespace Goals
};
}
}

View File

@ -19,6 +19,9 @@
#include "lib/mapping/CMap.h" //for victory conditions
#include "lib/CPathfinder.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -64,12 +67,12 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her
Goals::TGoalVec tasks;
const int3 pos = hero->visitablePos();
#if AI_TRACE_LEVEL >= 1
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Checking ways to gaher army for hero %s, %s", hero->getObjectName(), pos.toString());
#endif
if(ai->nullkiller->isHeroLocked(hero))
{
#if AI_TRACE_LEVEL >= 1
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Skipping locked hero %s, %s", hero->getObjectName(), pos.toString());
#endif
return tasks;
@ -77,13 +80,13 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her
auto paths = ai->nullkiller->pathfinder->getPathInfo(pos);
#if AI_TRACE_LEVEL >= 1
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Gather army found %d paths", paths.size());
#endif
for(const AIPath & path : paths)
{
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Path found %s", path.toString());
#endif
@ -91,7 +94,7 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her
if(ai->nullkiller->dangerHitMap->enemyCanKillOurHeroesAlongThePath(path))
{
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Ignore path. Target hero can be killed by enemy. Our power %lld", path.heroArmy->getArmyStrength());
#endif
continue;
@ -99,7 +102,7 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her
if(ai->nullkiller->arePathHeroesLocked(path))
{
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Ignore path because of locked hero");
#endif
continue;
@ -112,7 +115,7 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her
// avoid transferring very small amount of army
if(armyValue < 0.1f)
{
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Army value is too small.");
#endif
continue;
@ -121,7 +124,7 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her
// avoid trying to move bigger army to the weaker one.
if(armyValue > 1)
{
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Army value is too large.");
#endif
continue;
@ -131,7 +134,7 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her
auto isSafe = isSafeToVisit(hero, path.heroArmy, danger);
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace(
"It is %s to visit %s by %s with army %lld, danger %lld and army loss %lld",
isSafe ? "safe" : "not safe",
@ -156,7 +159,7 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her
if(blockedAction)
{
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Action is blocked. Considering decomposition.");
#endif
composition.addNext(blockedAction->decompose(path.targetHero));
@ -175,25 +178,25 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const CGTownInstance * upgrader)
const int3 pos = upgrader->visitablePos();
TResources availableResources = ai->nullkiller->getFreeResources();
#if AI_TRACE_LEVEL >= 1
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Checking ways to upgrade army in town %s, %s", upgrader->getObjectName(), pos.toString());
#endif
auto paths = ai->nullkiller->pathfinder->getPathInfo(pos);
std::vector<std::shared_ptr<ExecuteHeroChain>> waysToVisitObj;
#if AI_TRACE_LEVEL >= 1
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Found %d paths", paths.size());
#endif
for(const AIPath & path : paths)
{
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Path found %s", path.toString());
#endif
if(upgrader->visitingHero != path.targetHero)
{
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Ignore path. Town has visiting hero.");
#endif
continue;
@ -201,7 +204,7 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const CGTownInstance * upgrader)
if(ai->nullkiller->arePathHeroesLocked(path))
{
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Ignore path because of locked hero");
#endif
continue;
@ -209,7 +212,7 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const CGTownInstance * upgrader)
if(path.getFirstBlockedAction())
{
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
// TODO: decomposition?
logAi->trace("Ignore path. Action is blocked.");
#endif
@ -218,7 +221,7 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const CGTownInstance * upgrader)
if(ai->nullkiller->dangerHitMap->enemyCanKillOurHeroesAlongThePath(path))
{
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Ignore path. Target hero can be killed by enemy. Our power %lld", path.heroArmy->getArmyStrength());
#endif
continue;
@ -234,7 +237,7 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const CGTownInstance * upgrader)
auto isSafe = isSafeToVisit(path.targetHero, path.heroArmy, danger);
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace(
"It is %s to visit %s by %s with army %lld, danger %lld and army loss %lld",
isSafe ? "safe" : "not safe",
@ -257,3 +260,5 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const CGTownInstance * upgrader)
return tasks;
}
}

View File

@ -13,6 +13,8 @@
#include "../Goals/CGoal.h"
#include "../AIUtility.h"
namespace NKAI
{
namespace Goals
{
class GatherArmyBehavior : public CGoal<GatherArmyBehavior>
@ -37,3 +39,5 @@ namespace Goals
};
}
}

View File

@ -16,6 +16,9 @@
#include "lib/mapping/CMap.h" //for victory conditions
#include "lib/CPathfinder.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -46,3 +49,5 @@ Goals::TGoalVec RecruitHeroBehavior::decompose() const
return tasks;
}
}

View File

@ -13,6 +13,8 @@
#include "../Goals/CGoal.h"
#include "../AIUtility.h"
namespace NKAI
{
namespace Goals
{
class RecruitHeroBehavior : public CGoal<RecruitHeroBehavior>
@ -31,4 +33,6 @@ namespace Goals
return true;
}
};
}
}
}

View File

@ -20,6 +20,9 @@
#include "lib/CPathfinder.h"
#include "../Engine/Nullkiller.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -221,3 +224,5 @@ Goals::TGoalVec StartupBehavior::decompose() const
return tasks;
}
}

View File

@ -13,6 +13,8 @@
#include "../Goals/CGoal.h"
#include "../AIUtility.h"
namespace NKAI
{
namespace Goals
{
class StartupBehavior : public CGoal<StartupBehavior>
@ -33,3 +35,5 @@ namespace Goals
};
}
}

View File

@ -11,6 +11,9 @@
#include "AIMemory.h"
#include "../../../CCallback.h"
namespace NKAI
{
void AIMemory::removeFromMemory(const CGObjectInstance * obj)
{
vstd::erase_if_present(visitableObjs, obj);
@ -101,4 +104,6 @@ void AIMemory::removeInvisibleObjects(CCallback * cb)
vstd::erase_if(visitableObjs, shouldBeErased);
vstd::erase_if(alreadyVisited, shouldBeErased);
}
}
}

View File

@ -12,6 +12,9 @@
#include "../AIUtility.h"
#include "../../../lib/mapObjects/MapObjects.h"
namespace NKAI
{
class AIMemory
{
public:
@ -29,3 +32,5 @@ public:
bool wasVisited(const CGObjectInstance * obj) const;
void removeInvisibleObjects(CCallback * cb);
};
}

View File

@ -21,6 +21,9 @@
#include "../Goals/Invalid.h"
#include "../Goals/Composition.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -49,7 +52,7 @@ Goals::TGoalVec DeepDecomposer::decompose(TSubgoal behavior, int depthLimit)
TSubgoal current = goals[depth].back();
TGoalVec subgoals = decomposeCached(unwrapComposition(current), fromCache);
#if AI_TRACE_LEVEL >= 1
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Decomposition level %d returned %d goals", depth, subgoals.size());
#endif
@ -69,7 +72,7 @@ Goals::TGoalVec DeepDecomposer::decompose(TSubgoal behavior, int depthLimit)
// 0 - goals directly from behavior
Goals::TSubgoal task = depth >= 1 ? aggregateGoals(0, subgoal) : subgoal;
#if AI_TRACE_LEVEL >= 1
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Found task %s", task->toString());
#endif
if(!isCompositionLoop(subgoal))
@ -84,7 +87,7 @@ Goals::TGoalVec DeepDecomposer::decompose(TSubgoal behavior, int depthLimit)
}
else if(depth < depthLimit - 1)
{
#if AI_TRACE_LEVEL >= 1
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Found abstract goal %s", subgoal->toString());
#endif
if(!isCompositionLoop(subgoal))
@ -176,7 +179,7 @@ bool DeepDecomposer::isCompositionLoop(TSubgoal goal)
TGoalVec DeepDecomposer::decomposeCached(TSubgoal goal, bool & fromCache)
{
#if AI_TRACE_LEVEL >= 1
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Decomposing %s, level %s", goal->toString(), depth);
#endif
@ -188,7 +191,7 @@ TGoalVec DeepDecomposer::decomposeCached(TSubgoal goal, bool & fromCache)
if(cached != decompositionCache[i].end())
{
#if AI_TRACE_LEVEL >= 1
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Use decomposition cache for %s, level: %d", goal->toString(), depth);
#endif
fromCache = true;
@ -200,7 +203,7 @@ TGoalVec DeepDecomposer::decomposeCached(TSubgoal goal, bool & fromCache)
decompositionCache[depth][goal] = {}; // if goal decomposition yields no goals we still need it in cache to not decompose again
}
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Calling decompose on %s, level %s", goal->toString(), depth);
#endif
@ -221,7 +224,7 @@ void DeepDecomposer::addToCache(TSubgoal goal)
{
auto solution = parentDepth < depth ? aggregateGoals(parentDepth + 1, goal) : goal;
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Adding %s to decomosition cache of %s at level %d", solution->toString(), parent->toString(), parentDepth);
#endif
@ -234,4 +237,6 @@ void DeepDecomposer::addToCache(TSubgoal goal)
}
}
}
}
}
}

View File

@ -11,6 +11,9 @@
#include "../Goals/AbstractGoal.h"
namespace NKAI
{
struct GoalHash
{
uint64_t operator()(const Goals::TSubgoal & goal) const
@ -38,4 +41,6 @@ private:
bool isCompositionLoop(Goals::TSubgoal goal);
Goals::TGoalVec decomposeCached(Goals::TSubgoal goal, bool & fromCache);
void addToCache(Goals::TSubgoal goal);
};
};
}

View File

@ -14,6 +14,9 @@
#include "../../../lib/mapObjects/MapObjects.h"
#include "../AIGateway.h"
namespace NKAI
{
#define MIN_AI_STRENGTH (0.5f) //lower when combat AI gets smarter
#define UNGUARDED_OBJECT (100.0f) //we consider unguarded objects 100 times weaker than us
@ -239,3 +242,5 @@ float TacticalAdvantageEngine::getTacticalAdvantage(const CArmedInstance * we, c
return output;
}
}

View File

@ -17,6 +17,9 @@ class CArmedInstance;
VCMI_LIB_NAMESPACE_END
namespace NKAI
{
class engineBase //subclasses create fuzzylite variables with "new" that are not freed - this is desired as fl::Engine wants to destroy these...
{
protected:
@ -40,3 +43,5 @@ private:
fl::InputVariable * castleWalls;
fl::OutputVariable * threat;
};
}

View File

@ -14,6 +14,9 @@
#include "../Goals/Goals.h"
#include "Nullkiller.h"
namespace NKAI
{
ui64 FuzzyHelper::estimateBankDanger(const CBank * bank)
{
//this one is not fuzzy anymore, just calculate weighted average
@ -33,7 +36,7 @@ ui64 FuzzyHelper::estimateBankDanger(const CBank * bank)
}
ui64 FuzzyHelper::evaluateDanger(crint3 tile, const CGHeroInstance * visitor, bool checkGuards)
ui64 FuzzyHelper::evaluateDanger(const int3 & tile, const CGHeroInstance * visitor, bool checkGuards)
{
auto cb = ai->cb.get();
const TerrainTile * t = cb->getTile(tile, false);
@ -153,4 +156,6 @@ ui64 FuzzyHelper::evaluateDanger(const CGObjectInstance * obj)
default:
return 0;
}
}
}
}

View File

@ -16,6 +16,9 @@ class CBank;
VCMI_LIB_NAMESPACE_END
namespace NKAI
{
class Nullkiller;
class DLL_EXPORT FuzzyHelper
@ -30,5 +33,7 @@ public:
ui64 estimateBankDanger(const CBank * bank); //TODO: move to another class?
ui64 evaluateDanger(const CGObjectInstance * obj);
ui64 evaluateDanger(crint3 tile, const CGHeroInstance * visitor, bool checkGuards = true);
ui64 evaluateDanger(const int3 & tile, const CGHeroInstance * visitor, bool checkGuards = true);
};
}

View File

@ -21,12 +21,15 @@
#include "../Goals/Invalid.h"
#include "../Goals/Composition.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
using namespace Goals;
#if AI_TRACE_LEVEL >= 1
#if NKAI_TRACE_LEVEL >= 1
#define MAXPASS 1000000
#else
#define MAXPASS 30
@ -178,7 +181,7 @@ bool Nullkiller::arePathHeroesLocked(const AIPath & path) const
{
if(getHeroLockedReason(path.targetHero) == HeroLockedReason::STARTUP)
{
#if AI_TRACE_LEVEL >= 1
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Hero %s is locked by STARTUP. Discarding %s", path.targetHero->name, path.toString());
#endif
return true;
@ -190,7 +193,7 @@ bool Nullkiller::arePathHeroesLocked(const AIPath & path) const
if(lockReason != HeroLockedReason::NOT_LOCKED)
{
#if AI_TRACE_LEVEL >= 1
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Hero %s is locked by STARTUP. Discarding %s", path.targetHero->name, path.toString());
#endif
return true;
@ -326,3 +329,5 @@ void Nullkiller::lockResources(const TResources & res)
{
lockedResources += res;
}
}

View File

@ -19,6 +19,9 @@
#include "../Analyzers/HeroManager.h"
#include "../Analyzers/ObjectClusterizer.h"
namespace NKAI
{
const float MAX_GOLD_PEASURE = 0.3f;
const float MIN_PRIORITY = 0.01f;
const float NEXT_SCAN_MIN_PRIORITY = 0.4f;
@ -92,3 +95,5 @@ private:
Goals::TTask choseBestTask(Goals::TTaskVec & tasks) const;
void executeTask(Goals::TTask task);
};
}

View File

@ -26,6 +26,9 @@
#include "../Markers/ArmyUpgrade.h"
#include "../Markers/DefendTown.h"
namespace NKAI
{
#define MIN_AI_STRENGHT (0.5f) //lower when combat AI gets smarter
#define UNGUARDED_OBJECT (100.0f) //we consider unguarded objects 100 times weaker than us
@ -847,7 +850,7 @@ float PriorityEvaluator::evaluate(Goals::TSubgoal task)
logAi->error("evaluate VisitTile: %s", fe.getWhat());
}
#if AI_TRACE_LEVEL >= 2
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Evaluated %s, loss: %f, turn: %d, turns main: %f, scout: %f, gold: %d, cost: %d, army gain: %d, danger: %d, role: %s, strategical value: %f, cwr: %f, fear: %f, result %f",
task->toString(),
evaluationContext.armyLossPersentage,
@ -867,3 +870,5 @@ float PriorityEvaluator::evaluate(Goals::TSubgoal task)
return result;
}
}

View File

@ -18,6 +18,9 @@ class CGWitchHut;
VCMI_LIB_NAMESPACE_END
namespace NKAI
{
class BuildingInfo;
class Nullkiller;
@ -105,3 +108,5 @@ private:
EvaluationContext buildEvaluationContext(Goals::TSubgoal goal) const;
};
}

View File

@ -14,6 +14,9 @@
#include "../../../lib/CPathfinder.h"
#include "../../../lib/StringConstants.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -84,4 +87,6 @@ bool TSubgoal::operator==(const TSubgoal & rhs) const
bool AbstractGoal::invalid() const
{
return goalType == EGoals::INVALID;
}
}
}

View File

@ -15,6 +15,9 @@
#include "../../../lib/CTownHandler.h"
#include "../AIUtility.h"
namespace NKAI
{
struct HeroPtr;
class AIGateway;
class FuzzyHelper;
@ -171,8 +174,8 @@ class cannotFulfillGoalException : public std::exception
std::string msg;
public:
explicit cannotFulfillGoalException(crstring _Message)
: msg(_Message)
explicit cannotFulfillGoalException(const std::string & message)
: msg(message)
{
}
@ -208,3 +211,5 @@ public:
return msg.c_str();
}
};
}

View File

@ -13,6 +13,9 @@
#include "../../../lib/mapping/CMap.h" //for victory conditions
#include "../../../lib/CPathfinder.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -69,3 +72,5 @@ std::string AdventureSpellCast::toString() const
{
return "AdventureSpellCast " + spellID.toSpell()->name;
}
}

View File

@ -11,6 +11,9 @@
#include "CGoal.h"
namespace NKAI
{
namespace Goals
{
class DLL_EXPORT AdventureSpellCast : public ElementarGoal<AdventureSpellCast>
@ -35,3 +38,5 @@ namespace Goals
virtual bool operator==(const AdventureSpellCast & other) const override;
};
}
}

View File

@ -1,3 +1,6 @@
namespace Nullkiller
{
/*
* Build.cpp, part of VCMI engine
*
@ -91,3 +94,5 @@ bool Build::fulfillsMe(TSubgoal goal)
else
return false;
}
}

View File

@ -1,3 +1,6 @@
namespace Nullkiller
{
/*
* Build.h, part of VCMI engine
*
@ -35,3 +38,5 @@ namespace Goals
}
};
}
}

View File

@ -14,6 +14,9 @@
#include "../../../lib/CPathfinder.h"
#include "../Behaviors/CaptureObjectsBehavior.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -77,3 +80,5 @@ std::string BuildBoat::toString() const
{
return "BuildBoat";
}
}

View File

@ -11,6 +11,9 @@
#include "CGoal.h"
namespace NKAI
{
namespace Goals
{
class DLL_EXPORT BuildBoat : public ElementarGoal<BuildBoat>
@ -29,3 +32,5 @@ namespace Goals
virtual bool operator==(const BuildBoat & other) const override;
};
}
}

View File

@ -16,6 +16,9 @@
#include "../../../lib/StringConstants.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -63,4 +66,6 @@ void BuildThis::accept(AIGateway * ai)
}
throw cannotFulfillGoalException("Cannot build a given structure!");
}
}
}

View File

@ -12,6 +12,9 @@
#include "CGoal.h"
#include "../Analyzers/BuildAnalyzer.h"
namespace NKAI
{
struct HeroPtr;
class AIGateway;
class FuzzyHelper;
@ -41,3 +44,5 @@ namespace Goals
void accept(AIGateway * ai) override;
};
}
}

View File

@ -14,6 +14,9 @@
#include "../Engine/Nullkiller.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -72,4 +75,6 @@ void BuyArmy::accept(AIGateway * ai)
{
ai->moveHeroToTile(town->visitablePos(), town->visitingHero.get());
}
}
}
}

View File

@ -11,6 +11,9 @@
#include "CGoal.h"
namespace NKAI
{
struct HeroPtr;
class AIGateway;
class FuzzyHelper;
@ -40,3 +43,5 @@ namespace Goals
virtual void accept(AIGateway * ai) override;
};
}
}

View File

@ -11,6 +11,9 @@
#include "AbstractGoal.h"
namespace NKAI
{
struct HeroPtr;
class AIGateway;
@ -93,33 +96,6 @@ namespace Goals
virtual int getHeroExchangeCount() const override { return 0; }
};
class DLL_EXPORT Invalid : public ElementarGoal<Invalid>
{
public:
Invalid()
: ElementarGoal(Goals::INVALID)
{
priority = -1;
}
TGoalVec decompose() const override
{
return TGoalVec();
}
virtual bool operator==(const Invalid & other) const override
{
return true;
}
virtual std::string toString() const override
{
return "Invalid";
}
virtual void accept(AIGateway * ai) override
{
throw cannotFulfillGoalException("Can not fulfill Invalid goal!");
}
};
}
}

View File

@ -15,6 +15,9 @@
#include "../Behaviors/CaptureObjectsBehavior.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
using namespace Goals;
@ -37,4 +40,6 @@ std::string CaptureObject::toString() const
TGoalVec CaptureObject::decompose() const
{
return CaptureObjectsBehavior(cb->getObj(ObjectInstanceID(objid))).decompose();
}
}
}

View File

@ -11,6 +11,9 @@
#include "CGoal.h"
namespace NKAI
{
struct HeroPtr;
class AIGateway;
class FuzzyHelper;
@ -38,3 +41,5 @@ namespace Goals
virtual uint64_t getHash() const override;
};
}
}

View File

@ -16,6 +16,9 @@
#include "../../../lib/VCMI_Lib.h"
#include "../../../lib/CGeneralTextHandler.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -245,4 +248,6 @@ TGoalVec CompleteQuest::missionDestroyObj() const
}
return TGoalVec();
}
}
}

View File

@ -14,6 +14,8 @@
#include "../Goals/CGoal.h"
#include "../../../lib/CGameState.h"
namespace NKAI
{
namespace Goals
{
class CompleteQuest : public CGoal<CompleteQuest>
@ -47,3 +49,5 @@ namespace Goals
std::string questToString() const;
};
}
}

View File

@ -16,6 +16,9 @@
#include "../../../lib/StringConstants.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -77,4 +80,6 @@ bool Composition::isElementar() const
int Composition::getHeroExchangeCount() const
{
return isElementar() ? taskptr(*subtasks.back())->getHeroExchangeCount() : 0;
}
}
}

View File

@ -11,6 +11,8 @@
#include "CGoal.h"
namespace NKAI
{
namespace Goals
{
class DLL_EXPORT Composition : public ElementarGoal<Composition>
@ -39,3 +41,5 @@ namespace Goals
virtual int getHeroExchangeCount() const override;
};
}
}

View File

@ -13,6 +13,9 @@
#include "../AIUtility.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -35,3 +38,5 @@ bool DigAtTile::operator==(const DigAtTile & other) const
//
// return sptr(VisitTile(tile));
//}
}

View File

@ -11,6 +11,9 @@
#include "CGoal.h"
namespace NKAI
{
struct HeroPtr;
class AIGateway;
class FuzzyHelper;
@ -36,3 +39,5 @@ namespace Goals
//TSubgoal decomposeSingle() const override;
};
}
}

View File

@ -13,6 +13,9 @@
#include "../../../lib/mapping/CMap.h" //for victory conditions
#include "../../../lib/CPathfinder.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -37,3 +40,5 @@ std::string DismissHero::toString() const
{
return "DismissHero " + hero.name;
}
}

View File

@ -11,6 +11,8 @@
#include "CGoal.h"
namespace NKAI
{
namespace Goals
{
class DLL_EXPORT DismissHero : public ElementarGoal<DismissHero>
@ -27,3 +29,5 @@ namespace Goals
virtual bool operator==(const DismissHero & other) const override;
};
}
}

View File

@ -15,6 +15,9 @@
#include "../../../lib/CPathfinder.h"
#include "../Engine/Nullkiller.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -89,4 +92,6 @@ void ExchangeSwapTownHeroes::accept(AIGateway * ai)
}
logAi->debug("Put hero %s to garrison of %s", garrisonHero->name, town->name);
}
}
}

View File

@ -12,6 +12,8 @@
#include "CGoal.h"
#include "../Engine/Nullkiller.h"
namespace NKAI
{
namespace Goals
{
class DLL_EXPORT ExchangeSwapTownHeroes : public ElementarGoal<ExchangeSwapTownHeroes>
@ -32,3 +34,5 @@ namespace Goals
virtual bool operator==(const ExchangeSwapTownHeroes & other) const override;
};
}
}

View File

@ -14,6 +14,9 @@
#include "../../../lib/CPathfinder.h"
#include "../Engine/Nullkiller.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -197,4 +200,6 @@ bool ExecuteHeroChain::moveHeroToTile(const CGHeroInstance * hero, const int3 &
}
return ai->moveHeroToTile(tile, hero);
}
}
}

View File

@ -12,6 +12,8 @@
#include "CGoal.h"
#include "../Pathfinding/AIPathfinder.h"
namespace NKAI
{
namespace Goals
{
class DLL_EXPORT ExecuteHeroChain : public ElementarGoal<ExecuteHeroChain>
@ -37,3 +39,5 @@ namespace Goals
bool moveHeroToTile(const CGHeroInstance * hero, const int3 & tile);
};
}
}

View File

@ -1,3 +1,6 @@
namespace Nullkiller
{
/*
* GatherArmy.cpp, part of VCMI engine
*
@ -208,3 +211,5 @@ TGoalVec GatherArmy::getAllPossibleSubgoals()
return ret;
}
}

View File

@ -1,3 +1,6 @@
namespace Nullkiller
{
/*
* GatherArmy.h, part of VCMI engine
*
@ -36,3 +39,5 @@ namespace Goals
virtual bool operator==(const GatherArmy & other) const override;
};
}
}

View File

@ -17,4 +17,4 @@
#include "Trade.h"
#include "RecruitHero.h"
#include "DigAtTile.h"
#include "AdventureSpellCast.h"
#include "AdventureSpellCast.h"

View File

@ -11,9 +11,42 @@
#include "CGoal.h"
namespace NKAI
{
struct HeroPtr;
class AIGateway;
namespace Goals
{
class DLL_EXPORT Invalid : public ElementarGoal<Invalid>
{
public:
Invalid()
: ElementarGoal(Goals::INVALID)
{
priority = -1;
}
TGoalVec decompose() const override
{
return TGoalVec();
}
virtual bool operator==(const Invalid & other) const override
{
return true;
}
virtual std::string toString() const override
{
return "Invalid";
}
virtual void accept(AIGateway * ai) override
{
throw cannotFulfillGoalException("Can not fulfill Invalid goal!");
}
};
}
}

View File

@ -16,6 +16,9 @@
#include "../../../lib/StringConstants.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -42,4 +45,6 @@ void RecruitHero::accept(AIGateway * ai)
{
throw cannotFulfillGoalException("No town to recruit hero!");
}
}
}
}

View File

@ -11,6 +11,9 @@
#include "CGoal.h"
namespace NKAI
{
struct HeroPtr;
class AIGateway;
class FuzzyHelper;
@ -42,3 +45,5 @@ namespace Goals
void accept(AIGateway * ai) override;
};
}
}

View File

@ -14,6 +14,9 @@
#include "../../../lib/CPathfinder.h"
#include "../Behaviors/CaptureObjectsBehavior.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -37,3 +40,5 @@ std::string SaveResources::toString() const
{
return "SaveResources " + resources.toString();
}
}

View File

@ -11,6 +11,8 @@
#include "CGoal.h"
namespace NKAI
{
namespace Goals
{
class DLL_EXPORT SaveResources : public ElementarGoal<SaveResources>
@ -29,3 +31,5 @@ namespace Goals
virtual bool operator==(const SaveResources & other) const override;
};
}
}

View File

@ -10,9 +10,13 @@
#include "StdInc.h"
#include "Trade.h"
namespace NKAI
{
using namespace Goals;
bool Trade::operator==(const Trade & other) const
{
return resID == other.resID;
}
}
}

View File

@ -11,6 +11,9 @@
#include "CGoal.h"
namespace NKAI
{
struct HeroPtr;
class AIGateway;
class FuzzyHelper;
@ -34,3 +37,5 @@ namespace Goals
virtual bool operator==(const Trade & other) const override;
};
}
}

View File

@ -1,189 +0,0 @@
/*
* Win.cpp, 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
*
*/
#include "StdInc.h"
#include "Goals.h"
#include "../AIGateway.h"
#include "../AIUtility.h"
#include "../AIhelper.h"
#include "../FuzzyHelper.h"
#include "../../../lib/mapping/CMap.h" //for victory conditions
#include "../../../lib/CPathfinder.h"
#include "../../../lib/StringConstants.h"
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
extern FuzzyHelper * fh;
using namespace Goals;
TSubgoal Win::whatToDoToAchieve()
{
auto toBool = [=](const EventCondition &)
{
// TODO: proper implementation
// Right now even already fulfilled goals will be included into generated list
// Proper check should test if event condition is already fulfilled
// Easiest way to do this is to call CGameState::checkForVictory but this function should not be
// used on client side or in AI code
return false;
};
std::vector<EventCondition> goals;
for(const TriggeredEvent & event : cb->getMapHeader()->triggeredEvents)
{
//TODO: try to eliminate human player(s) using loss conditions that have isHuman element
if(event.effect.type == EventEffect::VICTORY)
{
boost::range::copy(event.trigger.getFulfillmentCandidates(toBool), std::back_inserter(goals));
}
}
//TODO: instead of returning first encountered goal AI should generate list of possible subgoals
for(const EventCondition & goal : goals)
{
switch(goal.condition)
{
case EventCondition::HAVE_ARTIFACT:
return sptr(GetArtOfType(goal.objectType));
case EventCondition::DESTROY:
{
if(goal.object)
{
auto obj = cb->getObj(goal.object->id);
/*if(obj)
if(obj->getOwner() == ai->playerID) //we can't capture our own object
return sptr(Conquer());*/
return sptr(VisitObj(goal.object->id.getNum()));
}
else
{
// TODO: destroy all objects of type goal.objectType
// This situation represents "kill all creatures" condition from H3
break;
}
}
case EventCondition::HAVE_BUILDING:
{
// TODO build other buildings apart from Grail
// goal.objectType = buidingID to build
// goal.object = optional, town in which building should be built
// Represents "Improve town" condition from H3 (but unlike H3 it consists from 2 separate conditions)
if(goal.objectType == BuildingID::GRAIL)
{
if(auto h = ai->getHeroWithGrail())
{
//hero is in a town that can host Grail
if(h->visitedTown && !vstd::contains(h->visitedTown->forbiddenBuildings, BuildingID::GRAIL))
{
const CGTownInstance * t = h->visitedTown;
return sptr(BuildThis(BuildingID::GRAIL, t).setpriority(10));
}
else
{
auto towns = cb->getTownsInfo();
towns.erase(boost::remove_if(towns,
[](const CGTownInstance * t) -> bool
{
return vstd::contains(t->forbiddenBuildings, BuildingID::GRAIL);
}),
towns.end());
boost::sort(towns, CDistanceSorter(h.get()));
if(towns.size())
{
return sptr(VisitTile(towns.front()->visitablePos()).sethero(h));
}
}
}
double ratio = 0;
// maybe make this check a bit more complex? For example:
// 0.75 -> dig randomly within 3 tiles radius
// 0.85 -> radius now 2 tiles
// 0.95 -> 1 tile radius, position is fully known
// AFAIK H3 AI does something like this
int3 grailPos = cb->getGrailPos(&ratio);
if(ratio > 0.99)
{
return sptr(DigAtTile(grailPos));
} //TODO: use FIND_OBJ
else if(const CGObjectInstance * obj = ai->getUnvisitedObj(objWithID<Obj::OBELISK>)) //there are unvisited Obelisks
return sptr(VisitObj(obj->id.getNum()));
/*else
return sptr(Explore());*/
}
break;
}
case EventCondition::CONTROL:
{
if(goal.object)
{
auto objRelations = cb->getPlayerRelations(ai->playerID, goal.object->tempOwner);
if(objRelations == PlayerRelations::ENEMIES)
{
return sptr(VisitObj(goal.object->id.getNum()));
}
else
{
// TODO: Defance
break;
}
}
else
{
//TODO: control all objects of type "goal.objectType"
// Represents H3 condition "Flag all mines"
break;
}
}
case EventCondition::HAVE_RESOURCES:
//TODO mines? piles? marketplace?
//save?
return sptr(CollectRes(static_cast<Res::ERes>(goal.objectType), goal.value));
case EventCondition::HAVE_CREATURES:
return sptr(GatherTroops(goal.objectType, goal.value));
case EventCondition::TRANSPORT:
{
//TODO. merge with bring Grail to town? So AI will first dig grail, then transport it using this goal and builds it
// Represents "transport artifact" condition:
// goal.objectType = type of artifact
// goal.object = destination-town where artifact should be transported
break;
}
case EventCondition::STANDARD_WIN:
return sptr(Invalid());
// Conditions that likely don't need any implementation
case EventCondition::DAYS_PASSED:
break; // goal.value = number of days for condition to trigger
case EventCondition::DAYS_WITHOUT_TOWN:
break; // goal.value = number of days to trigger this
case EventCondition::IS_HUMAN:
break; // Should be only used in calculation of candidates (see toBool lambda)
case EventCondition::CONST_VALUE:
break;
case EventCondition::HAVE_0:
case EventCondition::HAVE_BUILDING_0:
case EventCondition::DESTROY_0:
//TODO: support new condition format
return sptr(Invalid());
default:
assert(0);
}
}
return sptr(Invalid());
}

View File

@ -1,39 +0,0 @@
/*
* Win.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 "CGoal.h"
struct HeroPtr;
class AIGateway;
class FuzzyHelper;
namespace Goals
{
class DLL_EXPORT Win : public CGoal<Win>
{
public:
Win()
: CGoal(Goals::WIN)
{
priority = 100;
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
TSubgoal whatToDoToAchieve() override;
virtual bool operator==(const Win & other) const override
{
return true;
}
};
}

View File

@ -13,6 +13,9 @@
#include "../Engine/Nullkiller.h"
#include "../AIUtility.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -33,4 +36,6 @@ bool ArmyUpgrade::operator==(const ArmyUpgrade & other) const
std::string ArmyUpgrade::toString() const
{
return "Army upgrade at " + upgrader->getObjectName() + upgrader->visitablePos().toString();
}
}
}

View File

@ -13,6 +13,8 @@
#include "../Pathfinding/AINodeStorage.h"
#include "../Analyzers/ArmyManager.h"
namespace NKAI
{
namespace Goals
{
class DLL_EXPORT ArmyUpgrade : public CGoal<ArmyUpgrade>
@ -32,4 +34,6 @@ namespace Goals
uint64_t getUpgradeValue() const { return upgradeValue; }
uint64_t getInitialArmyValue() const { return initialValue; }
};
}
}
}

View File

@ -13,6 +13,9 @@
#include "../Engine/Nullkiller.h"
#include "../AIUtility.h"
namespace NKAI
{
using namespace Goals;
DefendTown::DefendTown(const CGTownInstance * town, const HitMapInfo & treat, const AIPath & defencePath)
@ -37,4 +40,6 @@ bool DefendTown::operator==(const DefendTown & other) const
std::string DefendTown::toString() const
{
return "Defend town " + town->getObjectName();
}
}
}

View File

@ -14,6 +14,8 @@
#include "../Analyzers/ArmyManager.h"
#include "../Analyzers/DangerHitMapAnalyzer.h"
namespace NKAI
{
namespace Goals
{
class DLL_EXPORT DefendTown : public CGoal<DefendTown>
@ -36,4 +38,6 @@ namespace Goals
uint8_t getTurn() const { return turn; }
};
}
}
}

View File

@ -14,6 +14,9 @@
#include "../AIUtility.h"
#include "../Analyzers/ArmyManager.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -34,4 +37,6 @@ uint64_t HeroExchange::getReinforcementArmyStrength() const
uint64_t armyValue = ai->nullkiller->armyManager->howManyReinforcementsCanGet(hero.get(), exchangePath.heroArmy);
return armyValue;
}
}
}

View File

@ -12,6 +12,8 @@
#include "../Goals/CGoal.h"
#include "../Pathfinding/AINodeStorage.h"
namespace NKAI
{
namespace Goals
{
class DLL_EXPORT HeroExchange : public CGoal<HeroExchange>
@ -31,4 +33,6 @@ namespace Goals
uint64_t getReinforcementArmyStrength() const;
};
}
}
}

View File

@ -13,6 +13,9 @@
#include "../Engine/Nullkiller.h"
#include "../AIUtility.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -26,4 +29,6 @@ bool UnlockCluster::operator==(const UnlockCluster & other) const
std::string UnlockCluster::toString() const
{
return "Unlock Cluster " + cluster->blocker->getObjectName() + tile.toString();
}
}
}

View File

@ -13,6 +13,9 @@
#include "../Analyzers/ObjectClusterizer.h"
namespace NKAI
{
struct HeroPtr;
class AIGateway;
class FuzzyHelper;
@ -38,4 +41,6 @@ namespace Goals
std::shared_ptr<ObjectCluster> getCluster() const { return cluster; }
const AIPath & getPathToCenter() { return pathToCenter; }
};
}
}
}

View File

@ -19,6 +19,9 @@
#include "../../../lib/PathfinderUtil.h"
#include "../../../lib/CPlayerState.h"
namespace NKAI
{
std::shared_ptr<boost::multi_array<AIPathNode, 5>> AISharedStorage::shared;
std::set<int3> commitedTiles;
std::set<int3> commitedTilesInitial;
@ -261,7 +264,7 @@ void AINodeStorage::commit(
destination->theNodeBefore = source->theNodeBefore;
destination->chainOther = nullptr;
#if PATHFINDER_TRACE_LEVEL >= 2
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
logAi->trace(
"Commited %s -> %s, cost: %f, turn: %s, mp: %d, hero: %s, mask: %x, army: %lld",
source->coord.toString(),
@ -589,7 +592,7 @@ void HeroChainCalculationTask::cleanupInefectiveChains(std::vector<ExchangeCandi
auto isNotEffective = storage.hasBetterChain(chainInfo.carrierParent, &chainInfo, chains)
|| storage.hasBetterChain(chainInfo.carrierParent, &chainInfo, result);
#if PATHFINDER_TRACE_LEVEL >= 2
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
if(isNotEffective)
{
logAi->trace(
@ -634,7 +637,7 @@ void HeroChainCalculationTask::calculateHeroChain(
|| (node->action == CGPathNode::ENodeAction::UNKNOWN && node->actor->hero)
|| (node->actor->chainMask & srcNode->actor->chainMask) != 0)
{
#if PATHFINDER_TRACE_LEVEL >= 2
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
logAi->trace(
"Skip exchange %s[%x] -> %s[%x] at %s because of %s",
node->actor->toString(),
@ -651,7 +654,7 @@ void HeroChainCalculationTask::calculateHeroChain(
continue;
}
#if PATHFINDER_TRACE_LEVEL >= 2
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
logAi->trace(
"Thy exchange %s[%x] -> %s[%x] at %s",
node->actor->toString(),
@ -675,7 +678,7 @@ void HeroChainCalculationTask::calculateHeroChain(
&& carrier->action != CGPathNode::BLOCKING_VISIT
&& (other->armyLoss == 0 || other->armyLoss < other->actor->armyValue))
{
#if PATHFINDER_TRACE_LEVEL >= 2
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
logAi->trace(
"Exchange allowed %s[%x] -> %s[%x] at %s",
other->actor->toString(),
@ -692,7 +695,7 @@ void HeroChainCalculationTask::calculateHeroChain(
if(hasLessMp && hasLessExperience)
{
#if PATHFINDER_TRACE_LEVEL >= 2
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
logAi->trace("Exchange at %s is ineficient. Blocked.", carrier->coord.toString());
#endif
return;
@ -717,7 +720,7 @@ void HeroChainCalculationTask::addHeroChain(const std::vector<ExchangeCandidate>
if(!chainNodeOptional)
{
#if PATHFINDER_TRACE_LEVEL >= 2
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
logAi->trace("Exchange at %s can not allocate node. Blocked.", carrier->coord.toString());
#endif
continue;
@ -727,7 +730,7 @@ void HeroChainCalculationTask::addHeroChain(const std::vector<ExchangeCandidate>
if(exchangeNode->action != CGPathNode::ENodeAction::UNKNOWN)
{
#if PATHFINDER_TRACE_LEVEL >= 2
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
logAi->trace(
"Skip exchange %s[%x] -> %s[%x] at %s because node is in use",
other->actor->toString(),
@ -741,7 +744,7 @@ void HeroChainCalculationTask::addHeroChain(const std::vector<ExchangeCandidate>
if(exchangeNode->turns != 0xFF && exchangeNode->getCost() < chainInfo.getCost())
{
#if PATHFINDER_TRACE_LEVEL >= 2
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
logAi->trace(
"Skip exchange %s[%x] -> %s[%x] at %s because not effective enough. %f < %f",
other->actor->toString(),
@ -772,7 +775,7 @@ void HeroChainCalculationTask::addHeroChain(const std::vector<ExchangeCandidate>
exchangeNode->chainOther = other;
exchangeNode->armyLoss = chainInfo.armyLoss;
#if PATHFINDER_TRACE_LEVEL >= 2
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
logAi->trace(
"Chain accepted at %s %s -> %s, mask %x, cost %f, turn: %s, mp: %d, army %i",
exchangeNode->coord.toString(),
@ -1096,7 +1099,7 @@ void AINodeStorage::calculateTownPortal(
if(nodeOptional)
{
#if PATHFINDER_TRACE_LEVEL >= 1
#if NKAI_PATHFINDER_TRACE_LEVEL >= 1
logAi->trace("Adding town portal node at %s", targetTown->name);
#endif
output.push_back(nodeOptional.get());
@ -1180,7 +1183,7 @@ bool AINodeStorage::hasBetterChain(
{
if(node.getCost() < candidateNode->getCost())
{
#if PATHFINDER_TRACE_LEVEL >= 2
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
logAi->trace(
"Block ineficient battle move %s->%s, hero: %s[%X], army %lld, mp diff: %i",
source->coord.toString(),
@ -1204,7 +1207,7 @@ bool AINodeStorage::hasBetterChain(
if(nodeArmyValue > candidateArmyValue
&& node.getCost() <= candidateNode->getCost())
{
#if PATHFINDER_TRACE_LEVEL >= 2
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
logAi->trace(
"Block ineficient move because of stronger army %s->%s, hero: %s[%X], army %lld, mp diff: %i",
source->coord.toString(),
@ -1230,7 +1233,7 @@ bool AINodeStorage::hasBetterChain(
continue;
}
#if PATHFINDER_TRACE_LEVEL >= 2
#if NKAI_PATHFINDER_TRACE_LEVEL >= 2
logAi->trace(
"Block ineficient move because of stronger hero %s->%s, hero: %s[%X], army %lld, mp diff: %i",
source->coord.toString(),
@ -1452,3 +1455,5 @@ std::string AIPath::toString() const
return str.str();
}
}

View File

@ -10,10 +10,8 @@
#pragma once
#define PATHFINDER_TRACE_LEVEL 0
#define AI_TRACE_LEVEL 0
#define SCOUT_TURN_DISTANCE_LIMIT 3
#define MAIN_TURN_DISTANCE_LIMIT 5
#define NKAI_PATHFINDER_TRACE_LEVEL 0
#define NKAI_TRACE_LEVEL 0
#include "../../../lib/CPathfinder.h"
#include "../../../lib/mapObjects/CGHeroInstance.h"
@ -23,6 +21,11 @@
#include "Actions/SpecialAction.h"
#include "Actors.h"
namespace NKAI
{
const int SCOUT_TURN_DISTANCE_LIMIT = 3;
const int MAIN_TURN_DISTANCE_LIMIT = 5;
namespace AIPathfinding
{
#ifdef ENVIRONMENT64
@ -256,3 +259,5 @@ private:
const std::vector<CGPathNode *> & initialNodes,
TVector & output);
};
}

View File

@ -14,6 +14,9 @@
#include "../../../lib/mapping/CMap.h"
#include "../Engine/Nullkiller.h"
namespace NKAI
{
AIPathfinder::AIPathfinder(CPlayerSpecificInfoCallback * cb, Nullkiller * ai)
:cb(cb), ai(ai)
{
@ -99,3 +102,5 @@ void AIPathfinder::updatePaths(std::map<const CGHeroInstance *, HeroRole> heroes
logAi->trace("Recalculated paths in %ld", timeElapsed(start));
}
}

View File

@ -13,6 +13,9 @@
#include "AINodeStorage.h"
#include "../AIUtility.h"
namespace NKAI
{
class Nullkiller;
struct PathfinderSettings
@ -42,3 +45,5 @@ public:
void updatePaths(std::map<const CGHeroInstance *, HeroRole> heroes, PathfinderSettings pathfinderSettings);
void init();
};
}

View File

@ -15,6 +15,8 @@
#include "Rules/AIPreviousNodeRule.h"
#include "../Engine//Nullkiller.h"
namespace NKAI
{
namespace AIPathfinding
{
std::vector<std::shared_ptr<IPathfindingRule>> makeRuleset(
@ -55,3 +57,5 @@ namespace AIPathfinding
return helper.get();
}
}
}

View File

@ -12,6 +12,9 @@
#include "AINodeStorage.h"
namespace NKAI
{
class Nullkiller;
namespace AIPathfinding
@ -31,3 +34,5 @@ namespace AIPathfinding
virtual CPathfinderHelper * getOrCreatePathfinderHelper(const PathNodeInfo & source, CGameState * gs) override;
};
}
}

View File

@ -14,6 +14,9 @@
#include "../../Goals/CompleteQuest.h"
#include "../../../../lib/mapping/CMap.h" //for victory conditions
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -28,4 +31,6 @@ namespace AIPathfinding
{
return "Battle at " + targetTile.toString();
}
}
}
}

View File

@ -13,6 +13,9 @@
#include "SpecialAction.h"
#include "../../../../lib/CGameState.h"
namespace NKAI
{
namespace AIPathfinding
{
class BattleAction : public SpecialAction
@ -30,4 +33,6 @@ namespace AIPathfinding
virtual std::string toString() const override;
};
}
}
}

View File

@ -12,11 +12,15 @@
#include "../../AIGateway.h"
#include "../../Goals/AdventureSpellCast.h"
#include "../../Goals/CaptureObject.h"
#include "../../Goals/Invalid.h"
#include "../../Goals/BuildBoat.h"
#include "../../../../lib/mapping/CMap.h"
#include "../../../../lib/mapObjects/MapObjects.h"
#include "BoatActions.h"
namespace NKAI
{
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<AIGateway> ai;
@ -34,7 +38,7 @@ namespace AIPathfinding
return Goals::sptr(Goals::CaptureObject(shipyard->o));
}
return sptr(Goals::Invalid());
return Goals::sptr(Goals::Invalid());
}
bool BuildBoatAction::canAct(const AIPathNode * source) const
@ -43,7 +47,7 @@ namespace AIPathfinding
if(cb->getPlayerRelations(hero->tempOwner, shipyard->o->tempOwner) == PlayerRelations::ENEMIES)
{
#if AI_TRACE_LEVEL > 1
#if NKAI_TRACE_LEVEL > 1
logAi->trace("Can not build a boat. Shipyard is enemy.");
#endif
return false;
@ -55,7 +59,7 @@ namespace AIPathfinding
if(!cb->getResourceAmount().canAfford(source->actor->armyCost + boatCost))
{
#if AI_TRACE_LEVEL > 1
#if NKAI_TRACE_LEVEL > 1
logAi->trace("Can not build a boat. Not enough resources.");
#endif
@ -128,4 +132,6 @@ namespace AIPathfinding
return hero->getSpellCost(summonBoat.toSpell());
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More