Explorar o código

Fixed AI getting stuck at blockVisit objects (Tavern, Borderguards/gates etc).

DjWarmonger %!s(int64=9) %!d(string=hai) anos
pai
achega
9b5af484b7
Modificáronse 3 ficheiros con 28 adicións e 7 borrados
  1. 9 1
      AI/VCAI/AIUtility.cpp
  2. 1 0
      AI/VCAI/AIUtility.h
  3. 18 6
      AI/VCAI/VCAI.cpp

+ 9 - 1
AI/VCAI/AIUtility.cpp

@@ -400,11 +400,19 @@ int3 whereToExplore(HeroPtr h)
 	}
 }
 
-bool isBlockedBorderGate(int3 tileToHit)
+bool isBlockedBorderGate(int3 tileToHit) //TODO: is that function needed? should be handled by pathfinder
 {
     return cb->getTile(tileToHit)->topVisitableId() == Obj::BORDER_GATE &&
 	       (dynamic_cast <const CGKeys *>(cb->getTile(tileToHit)->visitableObjects.back()))->wasMyColorVisited (ai->playerID);
 }
+bool isBlockVisitObj(const int3 &pos)
+{
+	if (auto obj = cb->getTopObj(pos))
+		if (obj->blockVisit) //we can't stand on that object
+			return true;
+
+	return false;
+}
 
 int howManyTilesWillBeDiscovered(const int3 &pos, int radious, CCallback * cbp)
 { //TODO: do not explore dead-end boundaries

+ 1 - 0
AI/VCAI/AIUtility.h

@@ -145,6 +145,7 @@ 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);
 
 bool isWeeklyRevisitable (const CGObjectInstance * obj);
 bool shouldVisit (HeroPtr h, const CGObjectInstance * obj);

+ 18 - 6
AI/VCAI/VCAI.cpp

@@ -1870,6 +1870,8 @@ bool VCAI::isAccessibleForHero(const int3 & pos, HeroPtr h, bool includeAllies /
 
 bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
 {
+	//TODO: consider if blockVisit objects change something in our checks: AIUtility::isBlockVisitObj()
+
 	auto afterMovementCheck = [&]() -> void
 	{
 		waitTillFree(); //movement may cause battle or blocking dialog
@@ -2558,11 +2560,19 @@ int3 VCAI::explorationBestNeighbour(int3 hpos, int radius, HeroPtr h)
 {
 	int3 ourPos = h->convertPosition(h->pos, false);
 	std::map<int3, int> dstToRevealedTiles;
-	for(crint3 dir : int3::getDirs())
-		if(cb->isInTheMap(hpos+dir))
+	for (crint3 dir : int3::getDirs())
+	{
+		int3 tile = hpos + dir;
+		if (cb->isInTheMap(tile))
 			if (ourPos != dir) //don't stand in place
-				if (isSafeToVisit(h, hpos + dir) && isAccessibleForHero (hpos + dir, h))
-					dstToRevealedTiles[hpos + dir] = howManyTilesWillBeDiscovered(radius, hpos, dir);
+				if (isSafeToVisit(h, tile) && isAccessibleForHero(tile, h))
+				{
+					if (isBlockVisitObj(tile))
+						continue;
+					else
+						dstToRevealedTiles[tile] = howManyTilesWillBeDiscovered(radius, hpos, dir);
+				}
+	}
 
 	if (dstToRevealedTiles.empty()) //yes, it DID happen!
 		throw cannotFulfillGoalException("No neighbour will bring new discoveries!");
@@ -2619,8 +2629,10 @@ int3 VCAI::explorationNewPoint(HeroPtr h)
 
 			if (ourValue > bestValue) //avoid costly checks of tiles that don't reveal much
 			{
-				if(isSafeToVisit(h, tile) && !isBlockedBorderGate(tile))
+				if(isSafeToVisit(h, tile))
 				{
+					if (isBlockVisitObj(tile)) //we can't stand on that object
+						continue;
 					bestTile = tile;
 					bestValue = ourValue;
 				}
@@ -2667,7 +2679,7 @@ int3 VCAI::explorationDesperate(HeroPtr h)
 				ui64 ourDanger = evaluateDanger(t, h.h);
 				if (ourDanger < lowestDanger)
 				{
-					if(!isBlockedBorderGate(t))
+					if(!isBlockVisitObj(t))
 					{
 						if (!ourDanger) //at least one safe place found
 							return t;