Ver código fonte

AI: refactor explore further

Andrii Danylchenko 6 anos atrás
pai
commit
04047d0a1a

+ 5 - 0
AI/VCAI/AIhelper.cpp

@@ -143,6 +143,11 @@ std::vector<AIPath> AIhelper::getPathsToTile(HeroPtr hero, int3 tile)
 	return pathfindingManager->getPathsToTile(hero, tile);
 }
 
+bool AIhelper::isTileAccessible(HeroPtr hero, int3 tile)
+{
+	return pathfindingManager->isTileAccessible(hero, tile);
+}
+
 void AIhelper::resetPaths()
 {
 	pathfindingManager->resetPaths();

+ 1 - 0
AI/VCAI/AIhelper.h

@@ -59,6 +59,7 @@ public:
 	Goals::TGoalVec howToVisitTile(int3 tile) override;
 	Goals::TGoalVec howToVisitObj(ObjectIdRef obj) override;
 	std::vector<AIPath> getPathsToTile(HeroPtr hero, int3 tile) override;
+	bool isTileAccessible(HeroPtr hero, int3 tile) override;
 	void resetPaths() override;
 
 private:

+ 19 - 16
AI/VCAI/Goals/Explore.cpp

@@ -18,6 +18,7 @@
 #include "../../../lib/mapping/CMap.h" //for victory conditions
 #include "../../../lib/CPathfinder.h"
 #include "../../../lib/StringConstants.h"
+#include "../../../lib/CPlayerState.h"
 
 extern boost::thread_specific_ptr<CCallback> cb;
 extern boost::thread_specific_ptr<VCAI> ai;
@@ -175,9 +176,10 @@ bool Explore::hasReachableNeighbor(const int3 &pos, HeroPtr hero, CCallback * cb
 		int3 tile = pos + dir;
 		if(cbp->isInTheMap(tile))
 		{
-			auto paths = vcai->ah->getPathsToTile(hero, tile);
+			auto isAccessible = vcai->ah->isTileAccessible(hero, tile);
 
-			return paths.size();
+			if(isAccessible)
+				return true;
 		}
 	}
 
@@ -188,8 +190,9 @@ int Explore::howManyTilesWillBeDiscovered(
 	const int3 & pos, 
 	int radious, 
 	CCallback * cbp, 
-	HeroPtr hero, 
-	std::function<bool (const int3 &)> filter) const
+	const TeamState * ts,
+	VCAI * aip,
+	HeroPtr h) const
 {
 	int ret = 0;
 	for(int x = pos.x - radious; x <= pos.x + radious; x++)
@@ -199,8 +202,8 @@ int Explore::howManyTilesWillBeDiscovered(
 			int3 npos = int3(x, y, pos.z);
 			if(cbp->isInTheMap(npos) 
 				&& pos.dist2d(npos) - 0.5 < radious 
-				&& !cbp->isVisible(npos)
-				&& filter(npos))
+				&& !ts->fogOfWarMap[npos.x][npos.y][npos.z]
+				&& hasReachableNeighbor(npos, h, cbp, aip))
 			{
 				ret++;
 			}
@@ -215,6 +218,7 @@ TSubgoal Explore::explorationBestNeighbour(int3 hpos, int radius, HeroPtr h) con
 	std::map<int3, int> dstToRevealedTiles;
 	VCAI * aip = ai.get();
 	CCallback * cbp = cb.get();
+	const TeamState * ts = cbp->getPlayerTeam(ai->playerID);
 
 	for(crint3 dir : int3::getDirs())
 	{
@@ -227,9 +231,7 @@ TSubgoal Explore::explorationBestNeighbour(int3 hpos, int radius, HeroPtr h) con
 			if(isSafeToVisit(h, tile) && ai->isAccessibleForHero(tile, h))
 			{
 				auto distance = hpos.dist2d(tile); // diagonal movement opens more tiles but spends more mp
-				int tilesDiscovered = howManyTilesWillBeDiscovered(tile, radius, cbp, h, [&](int3 neighbor) -> bool { 
-					return hasReachableNeighbor(neighbor, h, cbp, aip);
-				});
+				int tilesDiscovered = howManyTilesWillBeDiscovered(tile, radius, cbp, ts, aip, h);
 
 				dstToRevealedTiles[tile] = tilesDiscovered / distance;
 			}
@@ -259,6 +261,7 @@ TSubgoal Explore::explorationNewPoint(HeroPtr h) const
 	int radius = h->getSightRadius();
 	CCallback * cbp = cb.get();
 	VCAI *aip = ai.get();
+	const TeamState * ts = cbp->getPlayerTeam(aip->playerID);
 
 	std::vector<std::vector<int3>> tiles; //tiles[distance_to_fow]
 	tiles.resize(radius);
@@ -275,7 +278,7 @@ TSubgoal Explore::explorationNewPoint(HeroPtr h) const
 
 	for(int i = 1; i < radius; i++)
 	{
-		getVisibleNeighbours(tiles[i - 1], tiles[i], cbp);
+		getVisibleNeighbours(tiles[i - 1], tiles[i], cbp, ts);
 		vstd::removeDuplicates(tiles[i]);
 
 		for(const int3 & tile : tiles[i])
@@ -289,7 +292,7 @@ TSubgoal Explore::explorationNewPoint(HeroPtr h) const
 				if(goal->evaluationContext.movementCost == 0) // should not happen
 					continue;
 				
-				int tilesDiscovered = howManyTilesWillBeDiscovered(tile, radius, cbp, h, [](int3 neighbor) -> bool { return true; });
+				int tilesDiscovered = howManyTilesWillBeDiscovered(tile, radius, cbp, ts, aip, h);
 				float ourValue = (float) tilesDiscovered / goal->evaluationContext.movementCost; //+1 prevents erratic jumps
 
 				if(ourValue > bestValue) //avoid costly checks of tiles that don't reveal much
@@ -368,17 +371,17 @@ TSubgoal Explore::howToExplore(HeroPtr h) const
 	return result;
 }
 
-void Explore::getVisibleNeighbours(const std::vector<int3> & tiles, std::vector<int3> & out, CCallback * cbp) const
+void Explore::getVisibleNeighbours(const std::vector<int3> & tiles, std::vector<int3> & out, CCallback * cbp, const TeamState * ts) const
 {
 	for(const int3 & tile : tiles)
 	{
-		foreach_neighbour(tile, [&](int3 neighbour)
+		foreach_neighbour(cbp, tile, [&](CCallback * cbp, int3 neighbour)
 		{
-			if(cbp->isVisible(neighbour))
+			if(ts->fogOfWarMap[neighbour.x][neighbour.y][neighbour.z])
 			{
-				auto tile = cbp->getTile(neighbour);
+				//auto tile = cbp->getTile(neighbour);
 
-				if(tile && !tile->blocked)
+				//if(tile && !tile->blocked)
 					out.push_back(neighbour);
 			}
 		});

+ 10 - 3
AI/VCAI/Goals/Explore.h

@@ -42,12 +42,19 @@ namespace Goals
 		TSubgoal explorationNewPoint(HeroPtr h) const;
 		TSubgoal explorationBestNeighbour(int3 hpos, int radius, HeroPtr h) const;
 		bool hasReachableNeighbor(const int3 &pos, HeroPtr hero, CCallback * cbp, VCAI * vcai) const;
-		void getVisibleNeighbours(const std::vector<int3> & tiles, std::vector<int3> & out, CCallback * cbp) const;
+
+		void getVisibleNeighbours(
+			const std::vector<int3> & tiles, 
+			std::vector<int3> & out, 
+			CCallback * cbp, 
+			const TeamState * ts) const;
+
 		int howManyTilesWillBeDiscovered(
 			const int3 & pos,
 			int radious,
 			CCallback * cbp,
-			HeroPtr hero, 
-			std::function<bool(const int3 &)> filter) const;
+			const TeamState * ts,
+			VCAI * aip,
+			HeroPtr h) const;
 	};
 }

+ 17 - 0
AI/VCAI/Pathfinding/AINodeStorage.cpp

@@ -189,6 +189,23 @@ bool AINodeStorage::hasBetterChain(const PathNodeInfo & source, CDestinationNode
 	return false;
 }
 
+bool AINodeStorage::isTileAccessible(int3 pos, const EPathfindingLayer layer) const
+{
+	std::vector<AIPath> paths;
+	auto chains = nodes[pos.x][pos.y][pos.z][layer];
+	auto initialPos = hero->visitablePos();
+
+	for(const AIPathNode & node : chains)
+	{
+		if(node.action != CGPathNode::ENodeAction::UNKNOWN)
+		{
+			return true;
+		}
+	}
+
+	return false;
+}
+
 std::vector<AIPath> AINodeStorage::getChainInfo(int3 pos, bool isOnLand) const
 {
 	std::vector<AIPath> paths;

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

@@ -111,6 +111,7 @@ public:
 	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;
+	bool isTileAccessible(int3 pos, const EPathfindingLayer layer) const;
 
 	void setHero(HeroPtr heroPtr)
 	{

+ 27 - 9
AI/VCAI/Pathfinding/AIPathfinder.cpp

@@ -28,9 +28,33 @@ void AIPathfinder::clear()
 	storageMap.clear();
 }
 
+bool AIPathfinder::isTileAccessible(HeroPtr hero, int3 tile)
+{
+	boost::unique_lock<boost::mutex> storageLock(storageMutex);
+
+	std::shared_ptr<AINodeStorage> nodeStorage = getOrCreateStorage(hero);
+
+	return nodeStorage->isTileAccessible(tile, EPathfindingLayer::LAND)
+		|| nodeStorage->isTileAccessible(tile, EPathfindingLayer::SAIL);
+}
 std::vector<AIPath> AIPathfinder::getPathInfo(HeroPtr hero, int3 tile)
 {
 	boost::unique_lock<boost::mutex> storageLock(storageMutex);
+
+	std::shared_ptr<AINodeStorage> nodeStorage = getOrCreateStorage(hero);
+
+	const TerrainTile * tileInfo = cb->getTile(tile, false);
+
+	if(!tileInfo)
+	{
+		return std::vector<AIPath>();
+	}
+
+	return nodeStorage->getChainInfo(tile, !tileInfo->isWater());
+}
+
+std::shared_ptr<AINodeStorage> AIPathfinder::getOrCreateStorage(HeroPtr hero)
+{
 	std::shared_ptr<AINodeStorage> nodeStorage;
 
 	if(!vstd::contains(storageMap, hero))
@@ -49,7 +73,7 @@ std::vector<AIPath> AIPathfinder::getPathInfo(HeroPtr hero, int3 tile)
 
 		storageMap[hero] = nodeStorage;
 		nodeStorage->setHero(hero.get());
-		
+
 		auto config = std::make_shared<AIPathfinding::AIPathfinderConfig>(cb, ai, nodeStorage);
 
 		cb->calculatePaths(config, hero.get());
@@ -59,12 +83,6 @@ std::vector<AIPath> AIPathfinder::getPathInfo(HeroPtr hero, int3 tile)
 		nodeStorage = storageMap.at(hero);
 	}
 
-	const TerrainTile * tileInfo = cb->getTile(tile, false);
-
-	if(!tileInfo)
-	{
-		return std::vector<AIPath>();
-	}
-
-	return nodeStorage->getChainInfo(tile, !tileInfo->isWater());
+	return nodeStorage;
 }
+

+ 2 - 0
AI/VCAI/Pathfinding/AIPathfinder.h

@@ -26,5 +26,7 @@ private:
 public:
 	AIPathfinder(CPlayerSpecificInfoCallback * cb, VCAI * ai);
 	std::vector<AIPath> getPathInfo(HeroPtr hero, int3 tile);
+	bool isTileAccessible(HeroPtr hero, int3 tile);
+	std::shared_ptr<AINodeStorage> getOrCreateStorage(HeroPtr hero);
 	void clear();
 };

+ 5 - 0
AI/VCAI/Pathfinding/PathfindingManager.cpp

@@ -104,6 +104,11 @@ std::vector<AIPath> PathfindingManager::getPathsToTile(HeroPtr hero, int3 tile)
 	return pathfinder->getPathInfo(hero, tile);
 }
 
+bool PathfindingManager::isTileAccessible(HeroPtr hero, int3 tile)
+{
+	return pathfinder->isTileAccessible(hero, tile);
+}
+
 Goals::TGoalVec PathfindingManager::findPath(
 	HeroPtr hero,
 	crint3 dest,

+ 2 - 0
AI/VCAI/Pathfinding/PathfindingManager.h

@@ -26,6 +26,7 @@ public:
 	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 bool isTileAccessible(HeroPtr hero, int3 tile) = 0;
 };
 	
 class PathfindingManager : public IPathfindingManager
@@ -46,6 +47,7 @@ public:
 	Goals::TGoalVec howToVisitTile(int3 tile) override;
 	Goals::TGoalVec howToVisitObj(ObjectIdRef obj) override;
 	std::vector<AIPath> getPathsToTile(HeroPtr hero, int3 tile) override;
+	bool isTileAccessible(HeroPtr hero, int3 tile) override;
 	void resetPaths() override;
 
 private: