Browse Source

AI: tweak explore to work with new pathfinding.

Andrii Danylchenko 6 năm trước cách đây
mục cha
commit
edc5abe49d

+ 0 - 85
AI/VCAI/AIUtility.cpp

@@ -403,46 +403,6 @@ bool canBeEmbarkmentPoint(const TerrainTile * t, bool fromWater)
 	return false;
 }
 
-int3 whereToExplore(HeroPtr h)
-{
-	TimeCheck tc("where to explore");
-	int radius = h->getSightRadius();
-	int3 hpos = h->visitablePos();
-
-	//look for nearby objs -> visit them if they're close enouh
-	const int DIST_LIMIT = 3;
-	const int MP_LIMIT = DIST_LIMIT * 150; // aproximate cost of diagonal movement
-
-	std::vector<const CGObjectInstance *> nearbyVisitableObjs;
-	for(int x = hpos.x - DIST_LIMIT; x <= hpos.x + DIST_LIMIT; ++x) //get only local objects instead of all possible objects on the map
-	{
-		for(int y = hpos.y - DIST_LIMIT; y <= hpos.y + DIST_LIMIT; ++y)
-		{
-			for(auto obj : cb->getVisitableObjs(int3(x, y, hpos.z), false))
-			{
-				if(ai->isGoodForVisit(obj, h, MP_LIMIT))
-				{
-					nearbyVisitableObjs.push_back(obj);
-				}
-			}
-		}
-	}
-	vstd::removeDuplicates(nearbyVisitableObjs); //one object may occupy multiple tiles
-	boost::sort(nearbyVisitableObjs, CDistanceSorter(h.get()));
-	if(nearbyVisitableObjs.size())
-		return nearbyVisitableObjs.back()->visitablePos();
-
-	try //check if nearby tiles allow us to reveal anything - this is quick
-	{
-		return ai->explorationBestNeighbour(hpos, radius, h);
-	}
-	catch(cannotFulfillGoalException & e)
-	{
-		//perform exhaustive search
-		return ai->explorationNewPoint(h);
-	}
-}
-
 bool isBlockedBorderGate(int3 tileToHit) //TODO: is that function needed? should be handled by pathfinder
 {
 	if(cb->getTile(tileToHit)->topVisitableId() != Obj::BORDER_GATE)
@@ -461,51 +421,6 @@ bool isBlockVisitObj(const int3 & pos)
 	return false;
 }
 
-bool hasReachableNeighbor(const int3 &pos, HeroPtr hero, CCallback * cbp)
-{
-	for(crint3 dir : int3::getDirs())
-	{
-		int3 tile = pos + dir;
-		if(cbp->isInTheMap(tile) && cbp->getPathsInfo(hero.get())->getPathInfo(tile)->reachable())
-		{
-			return true;
-		}
-	}
-
-	return false;
-}
-
-int howManyTilesWillBeDiscovered(const int3 & pos, int radious, CCallback * cbp, HeroPtr hero)
-{
-	int ret = 0;
-	for(int x = pos.x - radious; x <= pos.x + radious; x++)
-	{
-		for(int y = pos.y - radious; y <= pos.y + radious; y++)
-		{
-			int3 npos = int3(x, y, pos.z);
-			if(cbp->isInTheMap(npos) && pos.dist2d(npos) - 0.5 < radious && !cbp->isVisible(npos))
-			{
-				if(hasReachableNeighbor(npos, hero, cbp))
-					ret++;
-			}
-		}
-	}
-
-	return ret;
-}
-
-void getVisibleNeighbours(const std::vector<int3> & tiles, std::vector<int3> & out)
-{
-	for(const int3 & tile : tiles)
-	{
-		foreach_neighbour(tile, [&](int3 neighbour)
-		{
-			if(cb->isVisible(neighbour))
-				out.push_back(neighbour);
-		});
-	}
-}
-
 creInfo infoFromDC(const dwellingContent & dc)
 {
 	creInfo ci;

+ 0 - 4
AI/VCAI/AIUtility.h

@@ -159,9 +159,6 @@ void foreach_tile_pos(CCallback * cbp, std::function<void(CCallback * cbp, const
 void foreach_neighbour(const int3 & pos, std::function<void(const int3 & pos)> foo);
 void foreach_neighbour(CCallback * cbp, const int3 & pos, std::function<void(CCallback * cbp, const int3 & pos)> foo); // avoid costly retrieval of thread-specific pointer
 
-int howManyTilesWillBeDiscovered(const int3 & pos, int radious, CCallback * cbp, HeroPtr hero);
-void getVisibleNeighbours(const std::vector<int3> & tiles, std::vector<int3> & out);
-
 bool canBeEmbarkmentPoint(const TerrainTile * t, bool fromWater);
 bool isBlockedBorderGate(int3 tileToHit);
 bool isBlockVisitObj(const int3 & pos);
@@ -181,7 +178,6 @@ bool compareArmyStrength(const CArmedInstance * a1, const CArmedInstance * a2);
 bool compareArtifacts(const CArtifactInstance * a1, const CArtifactInstance * a2);
 ui64 howManyReinforcementsCanBuy(const CArmedInstance * h, const CGDwelling * t);
 ui64 howManyReinforcementsCanGet(const CArmedInstance * h, const CGTownInstance * t);
-int3 whereToExplore(HeroPtr h);
 uint32_t distanceToTile(const CGHeroInstance * hero, int3 pos);
 
 class CDistanceSorter

+ 12 - 1
AI/VCAI/FuzzyEngines.cpp

@@ -318,8 +318,15 @@ void HeroMovementGoalEngineBase::setSharedFuzzyVariables(Goals::AbstractGoal & g
 {
 	float turns = calculateTurnDistanceInputValue(goal);
 	float missionImportanceData = 0;
+
 	if(vstd::contains(ai->lockedHeroes, goal.hero))
+	{
 		missionImportanceData = ai->lockedHeroes[goal.hero]->priority;
+	}
+	else if(goal.parent)
+	{
+		missionImportanceData = goal.parent->priority;
+	}
 
 	float strengthRatioData = 10.0f; //we are much stronger than enemy
 	ui64 danger = evaluateDanger(goal.tile, goal.hero.h);
@@ -410,6 +417,9 @@ VisitTileEngine::VisitTileEngine() //so far no VisitTile-specific variables that
 
 float VisitTileEngine::evaluate(Goals::VisitTile & goal)
 {
+	// for now any visit tile is usually much more in priority then visit obj so lets reduce it
+	const int scale = 2;
+
 	//we assume that hero is already set and we want to choose most suitable one for the mission
 	if(!goal.hero)
 		return 0;
@@ -421,7 +431,8 @@ float VisitTileEngine::evaluate(Goals::VisitTile & goal)
 	try
 	{
 		engine.process();
-		goal.priority = value->getValue();
+
+		goal.priority = value->getValue() / scale;
 	}
 	catch(fl::Exception & fe)
 	{

+ 10 - 0
AI/VCAI/FuzzyHelper.cpp

@@ -78,6 +78,11 @@ ui64 FuzzyHelper::estimateBankDanger(const CBank * bank)
 
 float FuzzyHelper::evaluate(Goals::VisitTile & g)
 {
+	if(g.parent)
+	{
+		g.parent->accept(this);
+	}
+
 	return visitTileEngine.evaluate(g);
 }
 
@@ -108,6 +113,11 @@ float FuzzyHelper::evaluate(Goals::CompleteQuest & g)
 
 float FuzzyHelper::evaluate(Goals::VisitObj & g)
 {
+	if(g.parent)
+	{
+		g.parent->accept(this);
+	}
+
 	return visitObjEngine.evaluate(g);
 }
 float FuzzyHelper::evaluate(Goals::VisitHero & g)

+ 223 - 18
AI/VCAI/Goals/Explore.cpp

@@ -19,7 +19,6 @@
 #include "../../../lib/CPathfinder.h"
 #include "../../../lib/StringConstants.h"
 
-
 extern boost::thread_specific_ptr<CCallback> cb;
 extern boost::thread_specific_ptr<VCAI> ai;
 extern FuzzyHelper * fh;
@@ -132,29 +131,18 @@ TGoalVec Explore::getAllPossibleSubgoals()
 			vstd::concatenate(ret, waysToVisitObj);
 		}
 
-		int3 t = whereToExplore(h);
-		if(t.valid())
+		TSubgoal goal = howToExplore(h);
+
+		if(goal->invalid())
 		{
-			ret.push_back(sptr(VisitTile(t).sethero(h)));
+			ai->markHeroUnableToExplore(h); //there is no freely accessible tile, do not poll this hero anymore
 		}
 		else
 		{
-			//FIXME: possible issues when gathering army to break
-			if(hero.h == h || //exporation is assigned to this hero
-				(!hero && h == primaryHero)) //not assigned to specific hero, let our main hero do the job
-			{
-				t = ai->explorationDesperate(h);  //check this only ONCE, high cost
-				if (t.valid()) //don't waste time if we are completely blocked
-				{
-					auto waysToVisitTile = ai->ah->howToVisitTile(h, t);
-
-					vstd::concatenate(ret, waysToVisitTile);
-					continue;
-				}
-			}
-			ai->markHeroUnableToExplore(h); //there is no freely accessible tile, do not poll this hero anymore
+			ret.push_back(goal);
 		}
 	}
+
 	//we either don't have hero yet or none of heroes can explore
 	if((!hero || ret.empty()) && ai->canRecruitAnyHero())
 		ret.push_back(sptr(RecruitHero()));
@@ -179,3 +167,220 @@ bool Explore::fulfillsMe(TSubgoal goal)
 	}
 	return false;
 }
+
+bool Explore::hasReachableNeighbor(const int3 &pos, HeroPtr hero, CCallback * cbp, VCAI * vcai) const
+{
+	for(crint3 dir : int3::getDirs())
+	{
+		int3 tile = pos + dir;
+		if(cbp->isInTheMap(tile))
+		{
+			auto paths = vcai->ah->getPathsToTile(hero, tile);
+
+			return paths.size();
+		}
+	}
+
+	return false;
+}
+
+int Explore::howManyTilesWillBeDiscovered(
+	const int3 & pos, 
+	int radious, 
+	CCallback * cbp, 
+	HeroPtr hero, 
+	std::function<bool (const int3 &)> filter) const
+{
+	int ret = 0;
+	for(int x = pos.x - radious; x <= pos.x + radious; x++)
+	{
+		for(int y = pos.y - radious; y <= pos.y + radious; y++)
+		{
+			int3 npos = int3(x, y, pos.z);
+			if(cbp->isInTheMap(npos) 
+				&& pos.dist2d(npos) - 0.5 < radious 
+				&& !cbp->isVisible(npos)
+				&& filter(npos))
+			{
+				ret++;
+			}
+		}
+	}
+
+	return ret;
+}
+
+TSubgoal Explore::explorationBestNeighbour(int3 hpos, int radius, HeroPtr h) const
+{
+	std::map<int3, int> dstToRevealedTiles;
+	VCAI * aip = ai.get();
+	CCallback * cbp = cb.get();
+
+	for(crint3 dir : int3::getDirs())
+	{
+		int3 tile = hpos + dir;
+		if(cb->isInTheMap(tile))
+		{
+			if(isBlockVisitObj(tile))
+				continue;
+
+			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);
+				});
+
+				dstToRevealedTiles[tile] = tilesDiscovered / distance;
+			}
+		}
+	}
+
+	if(dstToRevealedTiles.empty()) //yes, it DID happen!
+		return sptr(Invalid());
+
+	auto best = dstToRevealedTiles.begin();
+	for(auto i = dstToRevealedTiles.begin(); i != dstToRevealedTiles.end(); i++)
+	{
+		const CGPathNode * pn = cb->getPathsInfo(h.get())->getPathInfo(i->first);
+		//const TerrainTile *t = cb->getTile(i->first);
+		if(best->second < i->second && pn->reachable() && pn->accessible == CGPathNode::ACCESSIBLE)
+			best = i;
+	}
+
+	if(best->second)
+		return sptr(VisitTile(best->first).sethero(h));
+
+	return sptr(Invalid());
+}
+
+TSubgoal Explore::explorationNewPoint(HeroPtr h) const
+{
+	int radius = h->getSightRadius();
+	CCallback * cbp = cb.get();
+	VCAI *aip = ai.get();
+
+	std::vector<std::vector<int3>> tiles; //tiles[distance_to_fow]
+	tiles.resize(radius);
+
+	foreach_tile_pos([&](const int3 & pos)
+	{
+		if(!cbp->isVisible(pos))
+			tiles[0].push_back(pos);
+	});
+
+	float bestValue = 0; //discovered tile to node distance ratio
+	TSubgoal bestWay = sptr(Invalid());
+	int3 ourPos = h->convertPosition(h->pos, false);
+
+	for(int i = 1; i < radius; i++)
+	{
+		getVisibleNeighbours(tiles[i - 1], tiles[i], cbp);
+		vstd::removeDuplicates(tiles[i]);
+
+		for(const int3 & tile : tiles[i])
+		{
+			if(tile == ourPos) //shouldn't happen, but it does
+				continue;
+						
+			auto waysToVisit = aip->ah->howToVisitTile(h, tile);
+			for(auto goal : waysToVisit)
+			{
+				if(goal->evaluationContext.movementCost == 0) // should not happen
+					continue;
+				
+				int tilesDiscovered = howManyTilesWillBeDiscovered(tile, radius, cbp, h, [](int3 neighbor) -> bool { return true; });
+				float ourValue = (float) tilesDiscovered / goal->evaluationContext.movementCost; //+1 prevents erratic jumps
+
+				if(ourValue > bestValue) //avoid costly checks of tiles that don't reveal much
+				{
+					auto obj = cb->getTopObj(tile);
+					if(obj && obj->blockVisit && !isObjectRemovable(obj)) //we can't stand on that object
+					{
+						continue;
+					}
+
+					if(isSafeToVisit(h, tile))
+					{
+						bestWay = goal;
+						bestValue = ourValue;
+					}
+				}
+			}
+		}
+
+		if(!bestWay->invalid())
+		{
+			return bestWay;
+		}
+	}
+
+	return bestWay;
+}
+
+TSubgoal Explore::howToExplore(HeroPtr h) const
+{
+	TimeCheck tc("where to explore");
+	int radius = h->getSightRadius();
+	int3 hpos = h->visitablePos();
+
+	//look for nearby objs -> visit them if they're close enouh
+	const int DIST_LIMIT = 3;
+	const int MP_LIMIT = DIST_LIMIT * 150; // aproximate cost of diagonal movement
+
+	std::vector<const CGObjectInstance *> nearbyVisitableObjs;
+	for(int x = hpos.x - DIST_LIMIT; x <= hpos.x + DIST_LIMIT; ++x) //get only local objects instead of all possible objects on the map
+	{
+		for(int y = hpos.y - DIST_LIMIT; y <= hpos.y + DIST_LIMIT; ++y)
+		{
+			for(auto obj : cb->getVisitableObjs(int3(x, y, hpos.z), false))
+			{
+				if(ai->isGoodForVisit(obj, h, MP_LIMIT))
+				{
+					nearbyVisitableObjs.push_back(obj);
+				}
+			}
+		}
+	}
+
+	vstd::removeDuplicates(nearbyVisitableObjs); //one object may occupy multiple tiles
+	boost::sort(nearbyVisitableObjs, CDistanceSorter(h.get()));
+
+	if(nearbyVisitableObjs.size())
+	{
+		TSubgoal pickupNearestObj = fh->chooseSolution(ai->ah->howToVisitObj(h, nearbyVisitableObjs.back(), false));
+
+		if(!pickupNearestObj->invalid())
+		{
+			return pickupNearestObj;
+		}
+	}
+
+	//check if nearby tiles allow us to reveal anything - this is quick
+	TSubgoal result = explorationBestNeighbour(hpos, radius, h);
+	
+	if(result->invalid())
+	{
+		//perform exhaustive search
+		result = explorationNewPoint(h);
+	}
+
+	return result;
+}
+
+void Explore::getVisibleNeighbours(const std::vector<int3> & tiles, std::vector<int3> & out, CCallback * cbp) const
+{
+	for(const int3 & tile : tiles)
+	{
+		foreach_neighbour(tile, [&](int3 neighbour)
+		{
+			if(cbp->isVisible(neighbour))
+			{
+				auto tile = cbp->getTile(neighbour);
+
+				if(tile && !tile->blocked)
+					out.push_back(neighbour);
+			}
+		});
+	}
+}

+ 13 - 0
AI/VCAI/Goals/Explore.h

@@ -36,5 +36,18 @@ namespace Goals
 		std::string completeMessage() const override;
 		bool fulfillsMe(TSubgoal goal) override;
 		virtual bool operator==(const Explore & other) const override;
+
+	private:
+		TSubgoal howToExplore(HeroPtr h) const;
+		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;
+		int howManyTilesWillBeDiscovered(
+			const int3 & pos,
+			int radious,
+			CCallback * cbp,
+			HeroPtr hero, 
+			std::function<bool(const int3 &)> filter) const;
 	};
 }

+ 27 - 166
AI/VCAI/VCAI.cpp

@@ -1531,33 +1531,42 @@ void VCAI::wander(HeroPtr h)
 				vstd::concatenate(targetObjectGoals, ah->howToVisitObj(h, destination, false));
 			}
 
-			auto bestObjectGoal = fh->chooseSolution(targetObjectGoals);
-
-			//wander should not cause heroes to be reserved - they are always considered free
-			if(bestObjectGoal->goalType == Goals::VISIT_OBJ)
+			if(targetObjectGoals.size())
 			{
-				auto chosenObject = cb->getObjInstance(ObjectInstanceID(bestObjectGoal->objid));
-				if(chosenObject != nullptr)
-					logAi->debug("Of all %d destinations, object %s at pos=%s seems nice", dests.size(), chosenObject->getObjectName(), chosenObject->pos.toString());
-			}
-			else
-				logAi->debug("Trying to realize goal of type %s as part of wandering.", bestObjectGoal->name());
+				auto bestObjectGoal = fh->chooseSolution(targetObjectGoals);
 
-			try
-			{
-				decomposeGoal(bestObjectGoal)->accept(this);
+				//wander should not cause heroes to be reserved - they are always considered free
+				if(bestObjectGoal->goalType == Goals::VISIT_OBJ)
+				{
+					auto chosenObject = cb->getObjInstance(ObjectInstanceID(bestObjectGoal->objid));
+					if(chosenObject != nullptr)
+						logAi->debug("Of all %d destinations, object %s at pos=%s seems nice", dests.size(), chosenObject->getObjectName(), chosenObject->pos.toString());
+				}
+				else
+					logAi->debug("Trying to realize goal of type %s as part of wandering.", bestObjectGoal->name());
+
+				try
+				{
+					decomposeGoal(bestObjectGoal)->accept(this);
+				}
+				catch(const goalFulfilledException & e)
+				{
+					if(e.goal->goalType == Goals::EGoals::VISIT_TILE || e.goal->goalType == Goals::EGoals::VISIT_OBJ)
+						continue;
+
+					throw e;
+				}
 			}
-			catch(const goalFulfilledException & e)
+			else
 			{
-				if(e.goal->goalType == Goals::EGoals::VISIT_TILE || e.goal->goalType == Goals::EGoals::VISIT_OBJ)
-					continue;
-
-				throw e;
+				logAi->debug("Nowhere more to go...");
+				break;
 			}
 
 			visitTownIfAny(h);
 		}
 	}
+
 	visitTownIfAny(h); //in case hero is just sitting in town
 }
 
@@ -2472,154 +2481,6 @@ void VCAI::buildArmyIn(const CGTownInstance * t)
 	moveCreaturesToHero(t);
 }
 
-int3 VCAI::explorationBestNeighbour(int3 hpos, int radius, HeroPtr h)
-{
-	std::map<int3, int> dstToRevealedTiles;
-
-	for(crint3 dir : int3::getDirs())
-	{
-		int3 tile = hpos + dir;
-		if(cb->isInTheMap(tile))
-		{
-			if(isBlockVisitObj(tile))
-				continue;
-
-			if(isSafeToVisit(h, tile) && isAccessibleForHero(tile, h))
-			{
-				auto distance = hpos.dist2d(tile); // diagonal movement opens more tiles but spends more mp
-				dstToRevealedTiles[tile] = howManyTilesWillBeDiscovered(tile, radius, cb.get(), h) / distance;
-			}
-		}
-	}
-
-	if(dstToRevealedTiles.empty()) //yes, it DID happen!
-		throw cannotFulfillGoalException("No neighbour will bring new discoveries!");
-
-	auto best = dstToRevealedTiles.begin();
-	for(auto i = dstToRevealedTiles.begin(); i != dstToRevealedTiles.end(); i++)
-	{
-		const CGPathNode * pn = cb->getPathsInfo(h.get())->getPathInfo(i->first);
-		//const TerrainTile *t = cb->getTile(i->first);
-		if(best->second < i->second && pn->reachable() && pn->accessible == CGPathNode::ACCESSIBLE)
-			best = i;
-	}
-
-	if(best->second)
-		return best->first;
-
-	throw cannotFulfillGoalException("No neighbour will bring new discoveries!");
-}
-
-int3 VCAI::explorationNewPoint(HeroPtr h)
-{
-	int radius = h->getSightRadius();
-	CCallback * cbp = cb.get();
-	const CGHeroInstance * hero = h.get();
-
-	std::vector<std::vector<int3>> tiles; //tiles[distance_to_fow]
-	tiles.resize(radius);
-
-	foreach_tile_pos([&](const int3 & pos)
-	{
-		if(!cbp->isVisible(pos))
-			tiles[0].push_back(pos);
-	});
-
-	float bestValue = 0; //discovered tile to node distance ratio
-	int3 bestTile(-1, -1, -1);
-	int3 ourPos = h->convertPosition(h->pos, false);
-
-	for(int i = 1; i < radius; i++)
-	{
-		getVisibleNeighbours(tiles[i - 1], tiles[i]);
-		vstd::removeDuplicates(tiles[i]);
-
-		for(const int3 & tile : tiles[i])
-		{
-			if(tile == ourPos) //shouldn't happen, but it does
-				continue;
-			if(!cb->getPathsInfo(hero)->getPathInfo(tile)->reachable()) //this will remove tiles that are guarded by monsters (or removable objects)
-				continue;
-
-			CGPath path;
-			cb->getPathsInfo(hero)->getPath(path, tile);
-			float ourValue = (float)howManyTilesWillBeDiscovered(tile, radius, cbp, h) / (path.nodes.size() + 1); //+1 prevents erratic jumps
-
-			if(ourValue > bestValue) //avoid costly checks of tiles that don't reveal much
-			{
-				auto obj = cb->getTopObj(tile);
-				if (obj)
-					if (obj->blockVisit && !isObjectRemovable(obj)) //we can't stand on that object
-						continue;
-				if(isSafeToVisit(h, tile))
-				{
-					bestTile = tile;
-					bestValue = ourValue;
-				}
-			}
-		}
-	}
-	return bestTile;
-}
-
-int3 VCAI::explorationDesperate(HeroPtr h)
-{
-	int radius = h->getSightRadius();
-
-	std::vector<std::vector<int3>> tiles; //tiles[distance_to_fow]
-	tiles.resize(radius);
-
-	CCallback * cbp = cb.get();
-
-	foreach_tile_pos([&](const int3 & pos)
-	{
-		if(!cbp->isVisible(pos))
-			tiles[0].push_back(pos);
-	});
-
-	ui64 lowestDanger = -1;
-	int3 bestTile(-1, -1, -1);
-
-	for(int i = 1; i < radius; i++)
-	{
-		getVisibleNeighbours(tiles[i - 1], tiles[i]);
-		vstd::removeDuplicates(tiles[i]);
-
-		for(const int3 & tile : tiles[i])
-		{
-			if(cbp->getTile(tile)->blocked) //does it shorten the time?
-				continue;
-			if(!howManyTilesWillBeDiscovered(tile, radius, cbp, h)) //avoid costly checks of tiles that don't reveal much
-				continue;
-
-			auto paths = ah->getPathsToTile(h, tile);
-			for(auto path : paths)
-			{
-				auto t = path.firstTileToGet();
-
-				if(t == bestTile)
-					continue;
-
-				auto obj = cb->getTopObj(t);
-				if (obj)
-					if (obj->blockVisit && !isObjectRemovable(obj)) //we can't stand on object or remove it
-						continue;
-
-				ui64 ourDanger = path.getTotalDanger(h);
-				if(ourDanger < lowestDanger)
-				{
-					if(!ourDanger) //at least one safe place found
-						return t;
-
-					bestTile = t;
-					lowestDanger = ourDanger;
-				}
-			}
-		}
-	}
-	return bestTile;
-}
-
 void VCAI::checkHeroArmy(HeroPtr h)
 {
 	auto it = lockedHeroes.find(h);

+ 0 - 3
AI/VCAI/VCAI.h

@@ -131,9 +131,6 @@ public:
 	void tryRealize(Goals::Invalid & g);
 	void tryRealize(Goals::AbstractGoal & g);
 
-	int3 explorationBestNeighbour(int3 hpos, int radius, HeroPtr h);
-	int3 explorationNewPoint(HeroPtr h);
-	int3 explorationDesperate(HeroPtr h);
 	bool isTileNotReserved(const CGHeroInstance * h, int3 t) const; //the tile is not occupied by allied hero and the object is not reserved
 
 	std::string getBattleAIName() const override;