mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-15 20:03:15 +02:00
Dramatically reduced exploration complexity. AI will check only nearby objects.
This commit is contained in:
@@ -213,6 +213,7 @@ bool canBeEmbarkmentPoint(const TerrainTile *t)
|
|||||||
|
|
||||||
int3 whereToExplore(HeroPtr h)
|
int3 whereToExplore(HeroPtr h)
|
||||||
{
|
{
|
||||||
|
TimeCheck tc ("where to explore");
|
||||||
//TODO it's stupid and ineffective, write sth better
|
//TODO it's stupid and ineffective, write sth better
|
||||||
cb->setSelection(*h);
|
cb->setSelection(*h);
|
||||||
int radius = h->getSightRadious();
|
int radius = h->getSightRadious();
|
||||||
@@ -221,13 +222,20 @@ int3 whereToExplore(HeroPtr h)
|
|||||||
//look for nearby objs -> visit them if they're close enouh
|
//look for nearby objs -> visit them if they're close enouh
|
||||||
const int DIST_LIMIT = 3;
|
const int DIST_LIMIT = 3;
|
||||||
std::vector<const CGObjectInstance *> nearbyVisitableObjs;
|
std::vector<const CGObjectInstance *> 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();
|
for (int y = hpos.y - DIST_LIMIT; y <= hpos.y + DIST_LIMIT; ++y)
|
||||||
CGPath p;
|
{
|
||||||
cb->getPath2(op, p);
|
for (auto obj : cb->getVisitableObjs (int3(x,y,hpos.z), false))
|
||||||
if(p.nodes.size() && p.endPos() == op && p.nodes.size() <= DIST_LIMIT)
|
{
|
||||||
nearbyVisitableObjs.push_back(obj);
|
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);
|
boost::sort(nearbyVisitableObjs, isCloser);
|
||||||
if(nearbyVisitableObjs.size())
|
if(nearbyVisitableObjs.size())
|
||||||
|
@@ -1090,6 +1090,29 @@ void VCAI::buildStructure(const CGTownInstance * t)
|
|||||||
return;
|
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<const CGObjectInstance *> VCAI::getPossibleDestinations(HeroPtr h)
|
std::vector<const CGObjectInstance *> VCAI::getPossibleDestinations(HeroPtr h)
|
||||||
{
|
{
|
||||||
validateVisitableObjs();
|
validateVisitableObjs();
|
||||||
@@ -1097,29 +1120,12 @@ std::vector<const CGObjectInstance *> VCAI::getPossibleDestinations(HeroPtr h)
|
|||||||
for(const CGObjectInstance *obj : visitableObjs)
|
for(const CGObjectInstance *obj : visitableObjs)
|
||||||
{
|
{
|
||||||
const int3 pos = obj->visitablePos();
|
const int3 pos = obj->visitablePos();
|
||||||
if (isAccessibleForHero(obj->visitablePos(), h) &&
|
if (isGoodForVisit(obj, 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))
|
|
||||||
{
|
{
|
||||||
possibleDestinations.push_back(obj);
|
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);
|
boost::sort(possibleDestinations, isCloser);
|
||||||
|
|
||||||
return possibleDestinations;
|
return possibleDestinations;
|
||||||
@@ -1995,7 +2001,6 @@ void VCAI::buildArmyIn(const CGTownInstance * t)
|
|||||||
|
|
||||||
int3 VCAI::explorationBestNeighbour(int3 hpos, int radius, HeroPtr h)
|
int3 VCAI::explorationBestNeighbour(int3 hpos, int radius, HeroPtr h)
|
||||||
{
|
{
|
||||||
TimeCheck tc("looking for best exploration neighbour");
|
|
||||||
std::map<int3, int> dstToRevealedTiles;
|
std::map<int3, int> dstToRevealedTiles;
|
||||||
for(crint3 dir : dirs)
|
for(crint3 dir : dirs)
|
||||||
if(cb->isInTheMap(hpos+dir))
|
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<std::vector<int3> > &tiles)
|
int3 VCAI::explorationNewPoint(int radius, HeroPtr h, std::vector<std::vector<int3> > &tiles)
|
||||||
{
|
{
|
||||||
TimeCheck tc("looking for new exploration point");
|
|
||||||
logAi->debugStream() << "Looking for an another place for exploration...";
|
logAi->debugStream() << "Looking for an another place for exploration...";
|
||||||
tiles.resize(radius);
|
tiles.resize(radius);
|
||||||
|
|
||||||
|
@@ -241,6 +241,7 @@ public:
|
|||||||
void striveToQuest (const QuestInfo &q);
|
void striveToQuest (const QuestInfo &q);
|
||||||
|
|
||||||
void recruitHero(const CGTownInstance * t, bool throwing = false);
|
void recruitHero(const CGTownInstance * t, bool throwing = false);
|
||||||
|
bool isGoodForVisit(const CGObjectInstance *obj, HeroPtr h);
|
||||||
std::vector<const CGObjectInstance *> getPossibleDestinations(HeroPtr h);
|
std::vector<const CGObjectInstance *> getPossibleDestinations(HeroPtr h);
|
||||||
void buildStructure(const CGTownInstance * t);
|
void buildStructure(const CGTownInstance * t);
|
||||||
//void recruitCreatures(const CGTownInstance * t);
|
//void recruitCreatures(const CGTownInstance * t);
|
||||||
|
Reference in New Issue
Block a user