diff --git a/AI/VCAI/AIUtility.cpp b/AI/VCAI/AIUtility.cpp index 728c27f1e..a6b6e9e63 100644 --- a/AI/VCAI/AIUtility.cpp +++ b/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 (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 diff --git a/AI/VCAI/AIUtility.h b/AI/VCAI/AIUtility.h index bbe96f897..94f54963e 100644 --- a/AI/VCAI/AIUtility.h +++ b/AI/VCAI/AIUtility.h @@ -145,6 +145,7 @@ void getVisibleNeighbours(const std::vector &tiles, std::vector &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); diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index 4b7ffd12a..a09a0193d 100644 --- a/AI/VCAI/VCAI.cpp +++ b/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 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;