1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-06 09:09:40 +02:00

AI pathfinding const api and updatePaths

This commit is contained in:
Andrii Danylchenko
2019-02-06 23:11:51 +02:00
parent b24c037129
commit 35f696b695
11 changed files with 115 additions and 74 deletions

View File

@@ -330,7 +330,7 @@ bool AINodeStorage::isTileAccessible(const int3 & pos, const EPathfindingLayer l
return node.action != CGPathNode::ENodeAction::UNKNOWN;
}
std::vector<AIPath> AINodeStorage::getChainInfo(int3 pos, bool isOnLand) const
std::vector<AIPath> AINodeStorage::getChainInfo(const int3 & pos, bool isOnLand) const
{
std::vector<AIPath> paths;
auto chains = nodes[pos.x][pos.y][pos.z][isOnLand ? EPathfindingLayer::LAND : EPathfindingLayer::SAIL];

View File

@@ -99,7 +99,7 @@ public:
bool isBattleNode(const CGPathNode * node) const;
bool hasBetterChain(const PathNodeInfo & source, CDestinationNodeInfo & destination) const;
boost::optional<AIPathNode *> getOrCreateNode(const int3 & coord, const EPathfindingLayer layer, int chainNumber);
std::vector<AIPath> getChainInfo(int3 pos, bool isOnLand) const;
std::vector<AIPath> getChainInfo(const int3 & pos, bool isOnLand) const;
bool isTileAccessible(const int3 & pos, const EPathfindingLayer layer) const;
void setHero(HeroPtr heroPtr);

View File

@@ -15,41 +15,29 @@
std::vector<std::shared_ptr<AINodeStorage>> AIPathfinder::storagePool;
std::map<HeroPtr, std::shared_ptr<AINodeStorage>> AIPathfinder::storageMap;
boost::mutex AIPathfinder::storageMutex;
AIPathfinder::AIPathfinder(CPlayerSpecificInfoCallback * cb, VCAI * ai)
:cb(cb), ai(ai)
{
}
void AIPathfinder::clear()
{
boost::unique_lock<boost::mutex> storageLock(storageMutex);
storageMap.clear();
}
void AIPathfinder::init()
{
boost::unique_lock<boost::mutex> storageLock(storageMutex);
storagePool.clear();
storageMap.clear();
}
bool AIPathfinder::isTileAccessible(const HeroPtr & hero, const int3 & tile)
bool AIPathfinder::isTileAccessible(const HeroPtr & hero, const int3 & tile) const
{
boost::unique_lock<boost::mutex> storageLock(storageMutex);
std::shared_ptr<AINodeStorage> nodeStorage = getOrCreateStorage(hero);
std::shared_ptr<const AINodeStorage> nodeStorage = getStorage(hero);
return nodeStorage->isTileAccessible(tile, EPathfindingLayer::LAND)
|| nodeStorage->isTileAccessible(tile, EPathfindingLayer::SAIL);
}
std::vector<AIPath> AIPathfinder::getPathInfo(HeroPtr hero, int3 tile)
std::vector<AIPath> AIPathfinder::getPathInfo(const HeroPtr & hero, const int3 & tile) const
{
boost::unique_lock<boost::mutex> storageLock(storageMutex);
std::shared_ptr<AINodeStorage> nodeStorage = getOrCreateStorage(hero);
std::shared_ptr<const AINodeStorage> nodeStorage = getStorage(hero);
const TerrainTile * tileInfo = cb->getTile(tile, false);
@@ -61,13 +49,14 @@ std::vector<AIPath> AIPathfinder::getPathInfo(HeroPtr hero, int3 tile)
return nodeStorage->getChainInfo(tile, !tileInfo->isWater());
}
std::shared_ptr<AINodeStorage> AIPathfinder::getOrCreateStorage(const HeroPtr & hero)
void AIPathfinder::updatePaths(std::vector<HeroPtr> heroes)
{
std::shared_ptr<AINodeStorage> nodeStorage;
storageMap.clear();
if(!vstd::contains(storageMap, hero))
// TODO: go parallel?
for(HeroPtr hero : heroes)
{
logAi->debug("Recalculate paths for %s", hero->name);
std::shared_ptr<AINodeStorage> nodeStorage;
if(storageMap.size() < storagePool.size())
{
@@ -84,13 +73,43 @@ std::shared_ptr<AINodeStorage> AIPathfinder::getOrCreateStorage(const HeroPtr &
auto config = std::make_shared<AIPathfinding::AIPathfinderConfig>(cb, ai, nodeStorage);
logAi->debug("Recalculate paths for %s", hero->name);
cb->calculatePaths(config, hero.get());
}
}
void AIPathfinder::updatePaths(const HeroPtr & hero)
{
std::shared_ptr<AINodeStorage> nodeStorage;
if(!vstd::contains(storageMap, hero))
{
if(storageMap.size() < storagePool.size())
{
nodeStorage = storagePool.at(storageMap.size());
}
else
{
nodeStorage = std::make_shared<AINodeStorage>(cb->getMapSize());
storagePool.push_back(nodeStorage);
}
storageMap[hero] = nodeStorage;
nodeStorage->setHero(hero.get());
}
else
{
nodeStorage = storageMap.at(hero);
}
return nodeStorage;
logAi->debug("Recalculate paths for %s", hero->name);
auto config = std::make_shared<AIPathfinding::AIPathfinderConfig>(cb, ai, nodeStorage);
cb->calculatePaths(config, hero.get());
}
std::shared_ptr<const AINodeStorage> AIPathfinder::getStorage(const HeroPtr & hero) const
{
return storageMap.at(hero);
}

View File

@@ -19,15 +19,15 @@ class AIPathfinder
private:
static std::vector<std::shared_ptr<AINodeStorage>> storagePool;
static std::map<HeroPtr, std::shared_ptr<AINodeStorage>> storageMap;
static boost::mutex storageMutex;
CPlayerSpecificInfoCallback * cb;
VCAI * ai;
std::shared_ptr<AINodeStorage> getOrCreateStorage(const HeroPtr & hero);
std::shared_ptr<const AINodeStorage> getStorage(const HeroPtr & hero) const;
public:
AIPathfinder(CPlayerSpecificInfoCallback * cb, VCAI * ai);
std::vector<AIPath> getPathInfo(HeroPtr hero, int3 tile);
bool isTileAccessible(const HeroPtr & hero, const int3 & tile);
void clear();
std::vector<AIPath> getPathInfo(const HeroPtr & hero, const int3 & tile) const;
bool isTileAccessible(const HeroPtr & hero, const int3 & tile) const;
void updatePaths(std::vector<HeroPtr> heroes);
void updatePaths(const HeroPtr & heroes);
void init();
};

View File

@@ -32,7 +32,7 @@ void PathfindingManager::setAI(VCAI * AI)
ai = AI;
}
Goals::TGoalVec PathfindingManager::howToVisitTile(int3 tile)
Goals::TGoalVec PathfindingManager::howToVisitTile(const int3 & tile) const
{
Goals::TGoalVec result;
@@ -47,7 +47,7 @@ Goals::TGoalVec PathfindingManager::howToVisitTile(int3 tile)
return result;
}
Goals::TGoalVec PathfindingManager::howToVisitObj(ObjectIdRef obj)
Goals::TGoalVec PathfindingManager::howToVisitObj(ObjectIdRef obj) const
{
Goals::TGoalVec result;
@@ -62,7 +62,7 @@ Goals::TGoalVec PathfindingManager::howToVisitObj(ObjectIdRef obj)
return result;
}
Goals::TGoalVec PathfindingManager::howToVisitTile(HeroPtr hero, int3 tile, bool allowGatherArmy)
Goals::TGoalVec PathfindingManager::howToVisitTile(const HeroPtr & hero, const int3 & tile, bool allowGatherArmy) const
{
auto result = findPath(hero, tile, allowGatherArmy, [&](int3 firstTileToGet) -> Goals::TSubgoal
{
@@ -77,7 +77,7 @@ Goals::TGoalVec PathfindingManager::howToVisitTile(HeroPtr hero, int3 tile, bool
return result;
}
Goals::TGoalVec PathfindingManager::howToVisitObj(HeroPtr hero, ObjectIdRef obj, bool allowGatherArmy)
Goals::TGoalVec PathfindingManager::howToVisitObj(const HeroPtr & hero, ObjectIdRef obj, bool allowGatherArmy) const
{
if(!obj)
{
@@ -102,7 +102,7 @@ Goals::TGoalVec PathfindingManager::howToVisitObj(HeroPtr hero, ObjectIdRef obj,
return result;
}
std::vector<AIPath> PathfindingManager::getPathsToTile(HeroPtr hero, int3 tile)
std::vector<AIPath> PathfindingManager::getPathsToTile(const HeroPtr & hero, const int3 & tile) const
{
return pathfinder->getPathInfo(hero, tile);
}
@@ -111,7 +111,7 @@ Goals::TGoalVec PathfindingManager::findPath(
HeroPtr hero,
crint3 dest,
bool allowGatherArmy,
const std::function<Goals::TSubgoal(int3)> doVisitTile)
const std::function<Goals::TSubgoal(int3)> doVisitTile) const
{
Goals::TGoalVec result;
boost::optional<uint64_t> armyValueRequired;
@@ -184,7 +184,7 @@ Goals::TGoalVec PathfindingManager::findPath(
return result;
}
Goals::TSubgoal PathfindingManager::clearWayTo(HeroPtr hero, int3 firstTileToGet)
Goals::TSubgoal PathfindingManager::clearWayTo(HeroPtr hero, int3 firstTileToGet) const
{
if(isBlockedBorderGate(firstTileToGet))
{
@@ -235,8 +235,13 @@ Goals::TSubgoal PathfindingManager::clearWayTo(HeroPtr hero, int3 firstTileToGet
return sptr(Goals::VisitTile(firstTileToGet).sethero(hero).setisAbstract(true));
}
void PathfindingManager::resetPaths()
void PathfindingManager::updatePaths(std::vector<HeroPtr> heroes)
{
logAi->debug("AIPathfinder has been reseted.");
pathfinder->clear();
pathfinder->updatePaths(heroes);
}
void PathfindingManager::updatePaths(const HeroPtr & hero)
{
pathfinder->updatePaths(hero);
}

View File

@@ -20,12 +20,13 @@ public:
virtual void init(CPlayerSpecificInfoCallback * CB) = 0;
virtual void setAI(VCAI * AI) = 0;
virtual void resetPaths() = 0;
virtual Goals::TGoalVec howToVisitTile(HeroPtr hero, int3 tile, bool allowGatherArmy = true) = 0;
virtual Goals::TGoalVec howToVisitObj(HeroPtr hero, ObjectIdRef obj, bool allowGatherArmy = true) = 0;
virtual Goals::TGoalVec howToVisitTile(int3 tile) = 0;
virtual Goals::TGoalVec howToVisitObj(ObjectIdRef obj) = 0;
virtual std::vector<AIPath> getPathsToTile(HeroPtr hero, int3 tile) = 0;
virtual void updatePaths(std::vector<HeroPtr> heroes) = 0;
virtual void updatePaths(const HeroPtr & hero) = 0;
virtual Goals::TGoalVec howToVisitTile(const HeroPtr & hero, const int3 & tile, bool allowGatherArmy = true) const = 0;
virtual Goals::TGoalVec howToVisitObj(const HeroPtr & hero, ObjectIdRef obj, bool allowGatherArmy = true) const = 0;
virtual Goals::TGoalVec howToVisitTile(const int3 & tile) const = 0;
virtual Goals::TGoalVec howToVisitObj(ObjectIdRef obj) const = 0;
virtual std::vector<AIPath> getPathsToTile(const HeroPtr & hero, const int3 & tile) const = 0;
};
class DLL_EXPORT PathfindingManager : public IPathfindingManager
@@ -41,15 +42,16 @@ public:
PathfindingManager() = default;
PathfindingManager(CPlayerSpecificInfoCallback * CB, VCAI * AI = nullptr); //for tests only
Goals::TGoalVec howToVisitTile(HeroPtr hero, int3 tile, bool allowGatherArmy = true) override;
Goals::TGoalVec howToVisitObj(HeroPtr hero, ObjectIdRef obj, bool allowGatherArmy = true) override;
Goals::TGoalVec howToVisitTile(int3 tile) override;
Goals::TGoalVec howToVisitObj(ObjectIdRef obj) override;
std::vector<AIPath> getPathsToTile(HeroPtr hero, int3 tile) override;
void resetPaths() override;
Goals::TGoalVec howToVisitTile(const HeroPtr & hero, const int3 & tile, bool allowGatherArmy = true) const override;
Goals::TGoalVec howToVisitObj(const HeroPtr & hero, ObjectIdRef obj, bool allowGatherArmy = true) const override;
Goals::TGoalVec howToVisitTile(const int3 & tile) const override;
Goals::TGoalVec howToVisitObj(ObjectIdRef obj) const override;
std::vector<AIPath> getPathsToTile(const HeroPtr & hero, const int3 & tile) const override;
void updatePaths(std::vector<HeroPtr> heroes) override;
void updatePaths(const HeroPtr & hero) override;
STRONG_INLINE
bool isTileAccessible(const HeroPtr & hero, const int3 & tile)
bool isTileAccessible(const HeroPtr & hero, const int3 & tile) const
{
return pathfinder->isTileAccessible(hero, tile);
}
@@ -62,7 +64,7 @@ private:
HeroPtr hero,
crint3 dest,
bool allowGatherArmy,
const std::function<Goals::TSubgoal(int3)> goalFactory);
const std::function<Goals::TSubgoal(int3)> goalFactory) const;
Goals::TSubgoal clearWayTo(HeroPtr hero, int3 firstTileToGet);
Goals::TSubgoal clearWayTo(HeroPtr hero, int3 firstTileToGet) const;
};