Ver Fonte

AI pathfinding const api and updatePaths

Andrii Danylchenko há 6 anos atrás
pai
commit
35f696b695

+ 12 - 7
AI/VCAI/AIhelper.cpp

@@ -123,32 +123,37 @@ TResource AIhelper::allGold() const
 	return resourceManager->allGold();
 	return resourceManager->allGold();
 }
 }
 
 
-Goals::TGoalVec AIhelper::howToVisitTile(int3 tile)
+Goals::TGoalVec AIhelper::howToVisitTile(const int3 & tile) const
 {
 {
 	return pathfindingManager->howToVisitTile(tile);
 	return pathfindingManager->howToVisitTile(tile);
 }
 }
 
 
-Goals::TGoalVec AIhelper::howToVisitObj(ObjectIdRef obj)
+Goals::TGoalVec AIhelper::howToVisitObj(ObjectIdRef obj) const
 {
 {
 	return pathfindingManager->howToVisitObj(obj);
 	return pathfindingManager->howToVisitObj(obj);
 }
 }
 
 
-Goals::TGoalVec AIhelper::howToVisitTile(HeroPtr hero, int3 tile, bool allowGatherArmy)
+Goals::TGoalVec AIhelper::howToVisitTile(const HeroPtr & hero, const int3 & tile, bool allowGatherArmy) const
 {
 {
 	return pathfindingManager->howToVisitTile(hero, tile, allowGatherArmy);
 	return pathfindingManager->howToVisitTile(hero, tile, allowGatherArmy);
 }
 }
 
 
-Goals::TGoalVec AIhelper::howToVisitObj(HeroPtr hero, ObjectIdRef obj, bool allowGatherArmy)
+Goals::TGoalVec AIhelper::howToVisitObj(const HeroPtr & hero, ObjectIdRef obj, bool allowGatherArmy) const
 {
 {
 	return pathfindingManager->howToVisitObj(hero, obj, allowGatherArmy);
 	return pathfindingManager->howToVisitObj(hero, obj, allowGatherArmy);
 }
 }
 
 
-std::vector<AIPath> AIhelper::getPathsToTile(HeroPtr hero, int3 tile)
+std::vector<AIPath> AIhelper::getPathsToTile(const HeroPtr & hero, const int3 & tile) const
 {
 {
 	return pathfindingManager->getPathsToTile(hero, tile);
 	return pathfindingManager->getPathsToTile(hero, tile);
 }
 }
 
 
-void AIhelper::resetPaths()
+void AIhelper::updatePaths(std::vector<HeroPtr> heroes)
 {
 {
-	pathfindingManager->resetPaths();
+	pathfindingManager->updatePaths(heroes);
+}
+
+void AIhelper::updatePaths(const HeroPtr & hero)
+{
+	pathfindingManager->updatePaths(hero);
 }
 }

+ 8 - 7
AI/VCAI/AIhelper.h

@@ -55,15 +55,16 @@ public:
 	boost::optional<PotentialBuilding> expensiveBuilding() const override;
 	boost::optional<PotentialBuilding> expensiveBuilding() const override;
 	boost::optional<BuildingID> canBuildAnyStructure(const CGTownInstance * t, const std::vector<BuildingID> & buildList, unsigned int maxDays = 7) const override;
 	boost::optional<BuildingID> canBuildAnyStructure(const CGTownInstance * t, const std::vector<BuildingID> & buildList, unsigned int maxDays = 7) const override;
 
 
-	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
 	STRONG_INLINE
-	bool isTileAccessible(const HeroPtr & hero, const int3 & tile)
+	bool isTileAccessible(const HeroPtr & hero, const int3 & tile) const
 	{
 	{
 		return pathfindingManager->isTileAccessible(hero, tile);
 		return pathfindingManager->isTileAccessible(hero, tile);
 	}
 	}

+ 0 - 1
AI/VCAI/Goals/AdventureSpellCast.cpp

@@ -58,7 +58,6 @@ void AdventureSpellCast::accept(VCAI * ai)
 
 
 	cb->waitTillRealize = true;
 	cb->waitTillRealize = true;
 	cb->castSpell(hero.h, spellID, tile);
 	cb->castSpell(hero.h, spellID, tile);
-	ai->ah->resetPaths();
 
 
 	if(town && spellID == SpellID::TOWN_PORTAL)
 	if(town && spellID == SpellID::TOWN_PORTAL)
 	{
 	{

+ 1 - 1
AI/VCAI/Pathfinding/AINodeStorage.cpp

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

+ 1 - 1
AI/VCAI/Pathfinding/AINodeStorage.h

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

+ 40 - 21
AI/VCAI/Pathfinding/AIPathfinder.cpp

@@ -15,41 +15,29 @@
 
 
 std::vector<std::shared_ptr<AINodeStorage>> AIPathfinder::storagePool;
 std::vector<std::shared_ptr<AINodeStorage>> AIPathfinder::storagePool;
 std::map<HeroPtr, std::shared_ptr<AINodeStorage>> AIPathfinder::storageMap;
 std::map<HeroPtr, std::shared_ptr<AINodeStorage>> AIPathfinder::storageMap;
-boost::mutex AIPathfinder::storageMutex;
 
 
 AIPathfinder::AIPathfinder(CPlayerSpecificInfoCallback * cb, VCAI * ai)
 AIPathfinder::AIPathfinder(CPlayerSpecificInfoCallback * cb, VCAI * ai)
 	:cb(cb), ai(ai)
 	:cb(cb), ai(ai)
 {
 {
 }
 }
 
 
-void AIPathfinder::clear()
-{
-	boost::unique_lock<boost::mutex> storageLock(storageMutex);
-	storageMap.clear();
-}
-
 void AIPathfinder::init()
 void AIPathfinder::init()
 {
 {
-	boost::unique_lock<boost::mutex> storageLock(storageMutex);
 	storagePool.clear();
 	storagePool.clear();
 	storageMap.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)
 	return nodeStorage->isTileAccessible(tile, EPathfindingLayer::LAND)
 		|| nodeStorage->isTileAccessible(tile, EPathfindingLayer::SAIL);
 		|| 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);
 	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());
 	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())
 		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);
 		auto config = std::make_shared<AIPathfinding::AIPathfinderConfig>(cb, ai, nodeStorage);
 
 
+		logAi->debug("Recalculate paths for %s", hero->name);
 		cb->calculatePaths(config, hero.get());
 		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
 	else
 	{
 	{
 		nodeStorage = storageMap.at(hero);
 		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);
 }
 }
 
 

+ 5 - 5
AI/VCAI/Pathfinding/AIPathfinder.h

@@ -19,15 +19,15 @@ class AIPathfinder
 private:
 private:
 	static std::vector<std::shared_ptr<AINodeStorage>> storagePool;
 	static std::vector<std::shared_ptr<AINodeStorage>> storagePool;
 	static std::map<HeroPtr, std::shared_ptr<AINodeStorage>> storageMap;
 	static std::map<HeroPtr, std::shared_ptr<AINodeStorage>> storageMap;
-	static boost::mutex storageMutex;
 	CPlayerSpecificInfoCallback * cb;
 	CPlayerSpecificInfoCallback * cb;
 	VCAI * ai;
 	VCAI * ai;
 
 
-	std::shared_ptr<AINodeStorage> getOrCreateStorage(const HeroPtr & hero);
+	std::shared_ptr<const AINodeStorage> getStorage(const HeroPtr & hero) const;
 public:
 public:
 	AIPathfinder(CPlayerSpecificInfoCallback * cb, VCAI * ai);
 	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();
 	void init();
 };
 };

+ 14 - 9
AI/VCAI/Pathfinding/PathfindingManager.cpp

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

+ 17 - 15
AI/VCAI/Pathfinding/PathfindingManager.h

@@ -20,12 +20,13 @@ public:
 	virtual void init(CPlayerSpecificInfoCallback * CB) = 0;
 	virtual void init(CPlayerSpecificInfoCallback * CB) = 0;
 	virtual void setAI(VCAI * AI) = 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
 class DLL_EXPORT PathfindingManager : public IPathfindingManager
@@ -41,15 +42,16 @@ public:
 	PathfindingManager() = default;
 	PathfindingManager() = default;
 	PathfindingManager(CPlayerSpecificInfoCallback * CB, VCAI * AI = nullptr); //for tests only
 	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
 	STRONG_INLINE
-	bool isTileAccessible(const HeroPtr & hero, const int3 & tile)
+	bool isTileAccessible(const HeroPtr & hero, const int3 & tile) const
 	{
 	{
 		return pathfinder->isTileAccessible(hero, tile);
 		return pathfinder->isTileAccessible(hero, tile);
 	}
 	}
@@ -62,7 +64,7 @@ private:
 		HeroPtr hero,
 		HeroPtr hero,
 		crint3 dest,
 		crint3 dest,
 		bool allowGatherArmy,
 		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;
 };
 };

+ 16 - 7
AI/VCAI/VCAI.cpp

@@ -96,7 +96,6 @@ void VCAI::heroMoved(const TryMoveHero & details)
 
 
 	validateObject(details.id); //enemy hero may have left visible area
 	validateObject(details.id); //enemy hero may have left visible area
 	auto hero = cb->getHero(details.id);
 	auto hero = cb->getHero(details.id);
-	ah->resetPaths();
 
 
 	const int3 from = CGHeroInstance::convertPosition(details.start, false);
 	const int3 from = CGHeroInstance::convertPosition(details.start, false);
 	const int3 to = CGHeroInstance::convertPosition(details.end, false);
 	const int3 to = CGHeroInstance::convertPosition(details.end, false);
@@ -376,8 +375,6 @@ void VCAI::newObject(const CGObjectInstance * obj)
 	NET_EVENT_HANDLER;
 	NET_EVENT_HANDLER;
 	if(obj->isVisitable())
 	if(obj->isVisitable())
 		addVisitableObj(obj);
 		addVisitableObj(obj);
-
-	ah->resetPaths();
 }
 }
 
 
 //to prevent AI from accessing objects that got deleted while they became invisible (Cover of Darkness, enemy hero moved etc.) below code allows AI to know deletion of objects out of sight
 //to prevent AI from accessing objects that got deleted while they became invisible (Cover of Darkness, enemy hero moved etc.) below code allows AI to know deletion of objects out of sight
@@ -437,8 +434,6 @@ void VCAI::objectRemoved(const CGObjectInstance * obj)
 		}
 		}
 	}
 	}
 
 
-	ah->resetPaths();
-
 	//TODO
 	//TODO
 	//there are other places where CGObjectinstance ptrs are stored...
 	//there are other places where CGObjectinstance ptrs are stored...
 	//
 	//
@@ -795,7 +790,6 @@ void VCAI::makeTurn()
 	}
 	}
 	markHeroAbleToExplore(primaryHero());
 	markHeroAbleToExplore(primaryHero());
 	visitedHeroes.clear();
 	visitedHeroes.clear();
-	ai->ah->resetPaths();
 
 
 	try
 	try
 	{
 	{
@@ -829,6 +823,18 @@ void VCAI::makeTurn()
 	endTurn();
 	endTurn();
 }
 }
 
 
+std::vector<HeroPtr> VCAI::getMyHeroes() const
+{
+	std::vector<HeroPtr> ret;
+
+	for(auto h : cb->getHeroesInfo())
+	{
+		ret.push_back(h);
+	}
+
+	return ret;
+}
+
 void VCAI::mainLoop()
 void VCAI::mainLoop()
 {
 {
 	std::vector<Goals::TSubgoal> elementarGoals; //no duplicates allowed (operator ==)
 	std::vector<Goals::TSubgoal> elementarGoals; //no duplicates allowed (operator ==)
@@ -861,6 +867,8 @@ void VCAI::mainLoop()
 		goalsToRemove.clear();
 		goalsToRemove.clear();
 		elementarGoals.clear();
 		elementarGoals.clear();
 		ultimateGoalsFromBasic.clear();
 		ultimateGoalsFromBasic.clear();
+		
+		ah->updatePaths(getMyHeroes());
 
 
 		logAi->debug("Main loop: decomposing %i basic goals", basicGoals.size());
 		logAi->debug("Main loop: decomposing %i basic goals", basicGoals.size());
 
 
@@ -1392,6 +1400,8 @@ void VCAI::wander(HeroPtr h)
 	while(h->movement)
 	while(h->movement)
 	{
 	{
 		validateVisitableObjs();
 		validateVisitableObjs();
+		ah->updatePaths(h);
+
 		std::vector<ObjectIdRef> dests;
 		std::vector<ObjectIdRef> dests;
 
 
 		//also visit our reserved objects - but they are not prioritized to avoid running back and forth
 		//also visit our reserved objects - but they are not prioritized to avoid running back and forth
@@ -1676,7 +1686,6 @@ bool VCAI::isAbleToExplore(HeroPtr h)
 void VCAI::clearPathsInfo()
 void VCAI::clearPathsInfo()
 {
 {
 	heroesUnableToExplore.clear();
 	heroesUnableToExplore.clear();
-	ah->resetPaths();
 }
 }
 
 
 void VCAI::validateVisitableObjs()
 void VCAI::validateVisitableObjs()

+ 1 - 0
AI/VCAI/VCAI.h

@@ -257,6 +257,7 @@ public:
 	Goals::TSubgoal getGoal(HeroPtr h) const;
 	Goals::TSubgoal getGoal(HeroPtr h) const;
 	bool canAct(HeroPtr h) const;
 	bool canAct(HeroPtr h) const;
 	std::vector<HeroPtr> getUnblockedHeroes() const;
 	std::vector<HeroPtr> getUnblockedHeroes() const;
+	std::vector<HeroPtr> getMyHeroes() const;
 	HeroPtr primaryHero() const;
 	HeroPtr primaryHero() const;
 	void checkHeroArmy(HeroPtr h);
 	void checkHeroArmy(HeroPtr h);