diff --git a/AI/VCAI/AIUtility.cpp b/AI/VCAI/AIUtility.cpp index a37481b21..9fcb96df1 100644 --- a/AI/VCAI/AIUtility.cpp +++ b/AI/VCAI/AIUtility.cpp @@ -213,6 +213,7 @@ bool canBeEmbarkmentPoint(const TerrainTile *t) int3 whereToExplore(HeroPtr h) { + TimeCheck tc ("where to explore"); //TODO it's stupid and ineffective, write sth better cb->setSelection(*h); int radius = h->getSightRadious(); @@ -221,13 +222,20 @@ int3 whereToExplore(HeroPtr h) //look for nearby objs -> visit them if they're close enouh const int DIST_LIMIT = 3; std::vector nearbyVisitableObjs; - for(const CGObjectInstance *obj : ai->getPossibleDestinations(h)) + for (int x = hpos.x - DIST_LIMIT; x <= hpos.y + DIST_LIMIT; ++x) //get only local objects instead of all possible objects on the map { - int3 op = obj->visitablePos(); - CGPath p; - cb->getPath2(op, p); - if(p.nodes.size() && p.endPos() == op && p.nodes.size() <= DIST_LIMIT) - nearbyVisitableObjs.push_back(obj); + for (int y = hpos.y - DIST_LIMIT; y <= hpos.y + DIST_LIMIT; ++y) + { + for (auto obj : cb->getVisitableObjs (int3(x,y,hpos.z), false)) + { + int3 op = obj->visitablePos(); + CGPath p; + cb->getPath2(op, p); + if (p.nodes.size() && p.endPos() == op && p.nodes.size() <= DIST_LIMIT) + if (ai->isGoodForVisit(obj, h)) + nearbyVisitableObjs.push_back(obj); + } + } } boost::sort(nearbyVisitableObjs, isCloser); if(nearbyVisitableObjs.size()) diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index ef029a322..c6737912b 100644 --- a/AI/VCAI/VCAI.cpp +++ b/AI/VCAI/VCAI.cpp @@ -1090,6 +1090,29 @@ void VCAI::buildStructure(const CGTownInstance * t) return; } +bool VCAI::isGoodForVisit(const CGObjectInstance *obj, HeroPtr h) +{ + const int3 pos = obj->visitablePos(); + if (isAccessibleForHero(obj->visitablePos(), h) && + !obj->wasVisited(playerID) && + (obj->tempOwner != playerID || isWeeklyRevisitable(obj)) && //flag or get weekly resources / creatures + isSafeToVisit(h, pos) && + shouldVisit(h, obj) && + !vstd::contains(alreadyVisited, obj) && + !vstd::contains(reservedObjs, obj)) + { + const CGObjectInstance *topObj = cb->getVisitableObjs(obj->visitablePos()).back(); //it may be hero visiting this obj + //we don't try visiting object on which allied or owned hero stands + // -> it will just trigger exchange windows and AI will be confused that obj behind doesn't get visited + if (topObj->ID == Obj::HERO && cb->getPlayerRelations(h->tempOwner, topObj->tempOwner) != PlayerRelations::ENEMIES) + return false; + else + return true; //all of the following is met + } + + return false; +} + std::vector VCAI::getPossibleDestinations(HeroPtr h) { validateVisitableObjs(); @@ -1097,29 +1120,12 @@ std::vector VCAI::getPossibleDestinations(HeroPtr h) for(const CGObjectInstance *obj : visitableObjs) { const int3 pos = obj->visitablePos(); - if (isAccessibleForHero(obj->visitablePos(), h) && - !obj->wasVisited(playerID) && - (obj->tempOwner != playerID || isWeeklyRevisitable(obj)) && //flag or get weekly resources / creatures - isSafeToVisit(h, pos) && - shouldVisit(h, obj) && - !vstd::contains(alreadyVisited, obj) && - !vstd::contains(reservedObjs, obj)) + if (isGoodForVisit(obj, h)) { possibleDestinations.push_back(obj); } } - possibleDestinations.erase(boost::remove_if(possibleDestinations, [&](const CGObjectInstance *obj) -> bool - { - const CGObjectInstance *topObj = cb->getVisitableObjs(obj->visitablePos()).back(); //it may be hero visiting this obj - //we don't try visiting object on which allied or owned hero stands - // -> it will just trigger exchange windows and AI will be confused that obj behind doesn't get visited - if(topObj->ID == Obj::HERO && cb->getPlayerRelations(h->tempOwner, topObj->tempOwner) != PlayerRelations::ENEMIES) - return true; - - return false; - }), possibleDestinations.end()); - boost::sort(possibleDestinations, isCloser); return possibleDestinations; @@ -1995,7 +2001,6 @@ void VCAI::buildArmyIn(const CGTownInstance * t) int3 VCAI::explorationBestNeighbour(int3 hpos, int radius, HeroPtr h) { - TimeCheck tc("looking for best exploration neighbour"); std::map dstToRevealedTiles; for(crint3 dir : dirs) if(cb->isInTheMap(hpos+dir)) @@ -2019,7 +2024,6 @@ int3 VCAI::explorationBestNeighbour(int3 hpos, int radius, HeroPtr h) int3 VCAI::explorationNewPoint(int radius, HeroPtr h, std::vector > &tiles) { - TimeCheck tc("looking for new exploration point"); logAi->debugStream() << "Looking for an another place for exploration..."; tiles.resize(radius); diff --git a/AI/VCAI/VCAI.h b/AI/VCAI/VCAI.h index b4a2f1f5f..f190079eb 100644 --- a/AI/VCAI/VCAI.h +++ b/AI/VCAI/VCAI.h @@ -241,6 +241,7 @@ public: void striveToQuest (const QuestInfo &q); void recruitHero(const CGTownInstance * t, bool throwing = false); + bool isGoodForVisit(const CGObjectInstance *obj, HeroPtr h); std::vector getPossibleDestinations(HeroPtr h); void buildStructure(const CGTownInstance * t); //void recruitCreatures(const CGTownInstance * t);