diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index dd8309f29..5edea5f1a 100644 --- a/AI/VCAI/VCAI.cpp +++ b/AI/VCAI/VCAI.cpp @@ -1464,10 +1464,26 @@ void VCAI::wander(HeroPtr h) return false; }); - vstd::copy_if(visitableObjs, std::back_inserter(dests), [&](ObjectIdRef obj) -> bool + int pass = 0; + while(!dests.size() && pass < 3) { - return isGoodForVisit(obj, h, *sm); - }); + if(pass < 2) // optimization - first check objects in current sector; then in sectors around + { + auto objs = sm->getNearbyObjs(h, pass); + vstd::copy_if(objs, std::back_inserter(dests), [&](ObjectIdRef obj) -> bool + { + return isGoodForVisit(obj, h, *sm); + }); + } + else // we only check full objects list if for some reason there are no objects in closest sectors + { + vstd::copy_if(visitableObjs, std::back_inserter(dests), [&](ObjectIdRef obj) -> bool + { + return isGoodForVisit(obj, h, *sm); + }); + } + pass++; + } vstd::erase_if(dests, [&](ObjectIdRef obj) -> bool { @@ -3435,3 +3451,19 @@ TerrainTile* SectorMap::getTile(crint3 pos) const //still we cached this array to avoid any checks return visibleTiles->operator[](pos.x)[pos.y][pos.z]; } + +std::vector SectorMap::getNearbyObjs(HeroPtr h, bool sectorsAround) +{ + const Sector *heroSector = &infoOnSectors[retreiveTile(h->visitablePos())]; + if(sectorsAround) + { + std::vector ret; + for(auto embarkPoint : heroSector->embarkmentPoints) + { + const Sector *embarkSector = &infoOnSectors[retreiveTile(embarkPoint)]; + range::copy(embarkSector->visitableObjs, std::back_inserter(ret)); + } + return ret; + } + return heroSector->visitableObjs; +} diff --git a/AI/VCAI/VCAI.h b/AI/VCAI/VCAI.h index d42a4ccb5..b35662d2a 100644 --- a/AI/VCAI/VCAI.h +++ b/AI/VCAI/VCAI.h @@ -106,6 +106,7 @@ struct SectorMap bool markIfBlocked(ui8 &sec, crint3 pos); unsigned char &retreiveTile(crint3 pos); TerrainTile* getTile(crint3 pos) const; + std::vector getNearbyObjs(HeroPtr h, bool sectorsAround); void makeParentBFS(crint3 source);