1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-26 22:57:00 +02:00

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

This commit is contained in:
DjWarmonger 2016-11-28 19:29:11 +01:00
parent a1b7c9d8d2
commit 9b5af484b7
3 changed files with 28 additions and 7 deletions

View File

@ -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 && return cb->getTile(tileToHit)->topVisitableId() == Obj::BORDER_GATE &&
(dynamic_cast <const CGKeys *>(cb->getTile(tileToHit)->visitableObjects.back()))->wasMyColorVisited (ai->playerID); (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) int howManyTilesWillBeDiscovered(const int3 &pos, int radious, CCallback * cbp)
{ //TODO: do not explore dead-end boundaries { //TODO: do not explore dead-end boundaries

View File

@ -145,6 +145,7 @@ void getVisibleNeighbours(const std::vector<int3> &tiles, std::vector<int3> &out
bool canBeEmbarkmentPoint(const TerrainTile *t, bool fromWater); bool canBeEmbarkmentPoint(const TerrainTile *t, bool fromWater);
bool isBlockedBorderGate(int3 tileToHit); bool isBlockedBorderGate(int3 tileToHit);
bool isBlockVisitObj(const int3 &pos);
bool isWeeklyRevisitable (const CGObjectInstance * obj); bool isWeeklyRevisitable (const CGObjectInstance * obj);
bool shouldVisit (HeroPtr h, const CGObjectInstance * obj); bool shouldVisit (HeroPtr h, const CGObjectInstance * obj);

View File

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