mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
AI: optimizae explore logically, reduce amount of scanned tiles during full map scan for new exploration point
This commit is contained in:
parent
a0d1808b62
commit
c96be75f41
@ -148,11 +148,6 @@ std::vector<AIPath> AIhelper::getPathsToTile(HeroPtr hero, int3 tile)
|
||||
return pathfindingManager->getPathsToTile(hero, tile);
|
||||
}
|
||||
|
||||
bool AIhelper::isTileAccessible(HeroPtr hero, int3 tile)
|
||||
{
|
||||
return pathfindingManager->isTileAccessible(hero, tile);
|
||||
}
|
||||
|
||||
void AIhelper::resetPaths()
|
||||
{
|
||||
pathfindingManager->resetPaths();
|
||||
|
@ -60,9 +60,14 @@ public:
|
||||
Goals::TGoalVec howToVisitTile(int3 tile) override;
|
||||
Goals::TGoalVec howToVisitObj(ObjectIdRef obj) override;
|
||||
std::vector<AIPath> getPathsToTile(HeroPtr hero, int3 tile) override;
|
||||
bool isTileAccessible(HeroPtr hero, int3 tile) override;
|
||||
void resetPaths() override;
|
||||
|
||||
STRONG_INLINE
|
||||
bool isTileAccessible(const HeroPtr & hero, const int3 & tile)
|
||||
{
|
||||
return pathfindingManager->isTileAccessible(hero, tile);
|
||||
}
|
||||
|
||||
private:
|
||||
bool notifyGoalCompleted(Goals::TSubgoal goal) override;
|
||||
|
||||
|
@ -26,6 +26,208 @@ extern FuzzyHelper * fh;
|
||||
|
||||
using namespace Goals;
|
||||
|
||||
namespace Goals
|
||||
{
|
||||
struct ExplorationHelper
|
||||
{
|
||||
HeroPtr hero;
|
||||
int sightRadius;
|
||||
float bestValue;
|
||||
TSubgoal bestGoal;
|
||||
VCAI * aip;
|
||||
CCallback * cbp;
|
||||
const TeamState * ts;
|
||||
int3 ourPos;
|
||||
bool allowDeadEndCancellation;
|
||||
bool allowGatherArmy;
|
||||
|
||||
ExplorationHelper(HeroPtr h, bool gatherArmy)
|
||||
{
|
||||
cbp = cb.get();
|
||||
aip = ai.get();
|
||||
hero = h;
|
||||
ts = cbp->getPlayerTeam(ai->playerID);
|
||||
sightRadius = hero->getSightRadius();
|
||||
bestGoal = sptr(Goals::Invalid());
|
||||
bestValue = 0;
|
||||
ourPos = h->convertPosition(h->pos, false);
|
||||
allowDeadEndCancellation = true;
|
||||
allowGatherArmy = gatherArmy;
|
||||
}
|
||||
|
||||
void scanSector(int scanRadius)
|
||||
{
|
||||
for(int x = ourPos.x - scanRadius; x <= ourPos.x + scanRadius; x++)
|
||||
{
|
||||
for(int y = ourPos.y - scanRadius; y <= ourPos.y + scanRadius; y++)
|
||||
{
|
||||
int3 tile = int3(x, y, ourPos.z);
|
||||
|
||||
if(cbp->isInTheMap(tile) && ts->fogOfWarMap[tile.x][tile.y][tile.z])
|
||||
{
|
||||
scanTile(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void scanMap()
|
||||
{
|
||||
int3 mapSize = cbp->getMapSize();
|
||||
int perimeter = 2 * sightRadius * (mapSize.x + mapSize.y);
|
||||
|
||||
std::vector<int3> from;
|
||||
std::vector<int3> to;
|
||||
|
||||
from.reserve(perimeter);
|
||||
to.reserve(perimeter);
|
||||
|
||||
foreach_tile_pos([&](const int3 & pos)
|
||||
{
|
||||
if(ts->fogOfWarMap[pos.x][pos.y][pos.z])
|
||||
{
|
||||
bool hasInvisibleNeighbor = false;
|
||||
|
||||
foreach_neighbour(cbp, pos, [&](CCallback * cbp, int3 neighbour)
|
||||
{
|
||||
if(!ts->fogOfWarMap[neighbour.x][neighbour.y][neighbour.z])
|
||||
{
|
||||
hasInvisibleNeighbor = true;
|
||||
}
|
||||
});
|
||||
|
||||
if(hasInvisibleNeighbor)
|
||||
from.push_back(pos);
|
||||
}
|
||||
});
|
||||
|
||||
logAi->debug("Exploration scan visible area perimeter for hero %s", hero.name);
|
||||
|
||||
for(const int3 & tile : from)
|
||||
{
|
||||
scanTile(tile);
|
||||
}
|
||||
|
||||
if(!bestGoal->invalid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
allowDeadEndCancellation = false;
|
||||
|
||||
for(int i = 0; i < sightRadius; i++)
|
||||
{
|
||||
getVisibleNeighbours(from, to);
|
||||
vstd::concatenate(from, to);
|
||||
vstd::removeDuplicates(from);
|
||||
}
|
||||
|
||||
logAi->debug("Exploration scan all possible tiles for hero %s", hero.name);
|
||||
|
||||
for(const int3 & tile : from)
|
||||
{
|
||||
scanTile(tile);
|
||||
}
|
||||
}
|
||||
|
||||
void scanTile(const int3 & tile)
|
||||
{
|
||||
if(tile == ourPos
|
||||
|| !aip->ah->isTileAccessible(hero, tile)) //shouldn't happen, but it does
|
||||
return;
|
||||
|
||||
int tilesDiscovered = howManyTilesWillBeDiscovered(tile);
|
||||
if(!tilesDiscovered)
|
||||
return;
|
||||
|
||||
auto waysToVisit = aip->ah->howToVisitTile(hero, tile, allowGatherArmy);
|
||||
for(auto goal : waysToVisit)
|
||||
{
|
||||
if(goal->evaluationContext.movementCost <= 0.0) // should not happen
|
||||
continue;
|
||||
|
||||
float ourValue = (float)tilesDiscovered * tilesDiscovered / goal->evaluationContext.movementCost;
|
||||
|
||||
if(ourValue > bestValue) //avoid costly checks of tiles that don't reveal much
|
||||
{
|
||||
auto obj = cb->getTopObj(tile);
|
||||
|
||||
// picking up resources does not yield any exploration at all.
|
||||
// if it blocks the way to some explorable tile AIPathfinder will take care of it
|
||||
if(obj && obj->blockVisit)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(isSafeToVisit(hero, tile))
|
||||
{
|
||||
bestGoal = goal;
|
||||
bestValue = ourValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void getVisibleNeighbours(const std::vector<int3> & tiles, std::vector<int3> & out) const
|
||||
{
|
||||
for(const int3 & tile : tiles)
|
||||
{
|
||||
foreach_neighbour(cbp, tile, [&](CCallback * cbp, int3 neighbour)
|
||||
{
|
||||
if(ts->fogOfWarMap[neighbour.x][neighbour.y][neighbour.z])
|
||||
{
|
||||
out.push_back(neighbour);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
int howManyTilesWillBeDiscovered(
|
||||
const int3 & pos) const
|
||||
{
|
||||
int ret = 0;
|
||||
for(int x = pos.x - sightRadius; x <= pos.x + sightRadius; x++)
|
||||
{
|
||||
for(int y = pos.y - sightRadius; y <= pos.y + sightRadius; y++)
|
||||
{
|
||||
int3 npos = int3(x, y, pos.z);
|
||||
if(cbp->isInTheMap(npos)
|
||||
&& pos.dist2d(npos) - 0.5 < sightRadius
|
||||
&& !ts->fogOfWarMap[npos.x][npos.y][npos.z])
|
||||
{
|
||||
if(allowDeadEndCancellation
|
||||
&& !hasReachableNeighbor(npos))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool hasReachableNeighbor(const int3 &pos) const
|
||||
{
|
||||
for(crint3 dir : int3::getDirs())
|
||||
{
|
||||
int3 tile = pos + dir;
|
||||
if(cbp->isInTheMap(tile))
|
||||
{
|
||||
auto isAccessible = aip->ah->isTileAccessible(hero, tile);
|
||||
|
||||
if(isAccessible)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
bool Explore::operator==(const Explore & other) const
|
||||
{
|
||||
return other.hero.h == hero.h && other.allowGatherArmy == allowGatherArmy;
|
||||
@ -38,18 +240,7 @@ std::string Explore::completeMessage() const
|
||||
|
||||
TSubgoal Explore::whatToDoToAchieve()
|
||||
{
|
||||
auto ret = fh->chooseSolution(getAllPossibleSubgoals());
|
||||
if(hero) //use best step for this hero
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ret->hero.get(true))
|
||||
return sptr(Explore().sethero(ret->hero.h)); //choose this hero and then continue with him
|
||||
else
|
||||
return ret; //other solutions, like buying hero from tavern
|
||||
}
|
||||
return fh->chooseSolution(getAllPossibleSubgoals());
|
||||
}
|
||||
|
||||
TGoalVec Explore::getAllPossibleSubgoals()
|
||||
@ -143,6 +334,8 @@ TGoalVec Explore::getAllPossibleSubgoals()
|
||||
{
|
||||
for(auto h : heroes)
|
||||
{
|
||||
logAi->trace("Exploration searching for a new point for hero %s", h->name);
|
||||
|
||||
TSubgoal goal = explorationNewPoint(h);
|
||||
|
||||
if(goal->invalid())
|
||||
@ -180,197 +373,43 @@ bool Explore::fulfillsMe(TSubgoal goal)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Explore::hasReachableNeighbor(const int3 &pos, HeroPtr hero, CCallback * cbp, VCAI * vcai) const
|
||||
TSubgoal Explore::explorationBestNeighbour(int3 hpos, HeroPtr h) const
|
||||
{
|
||||
for(crint3 dir : int3::getDirs())
|
||||
{
|
||||
int3 tile = pos + dir;
|
||||
if(cbp->isInTheMap(tile))
|
||||
{
|
||||
auto isAccessible = vcai->ah->isTileAccessible(hero, tile);
|
||||
|
||||
if(isAccessible)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int Explore::howManyTilesWillBeDiscovered(
|
||||
const int3 & pos,
|
||||
int radious,
|
||||
CCallback * cbp,
|
||||
const TeamState * ts,
|
||||
VCAI * aip,
|
||||
HeroPtr h) const
|
||||
{
|
||||
int ret = 0;
|
||||
for(int x = pos.x - radious; x <= pos.x + radious; x++)
|
||||
{
|
||||
for(int y = pos.y - radious; y <= pos.y + radious; y++)
|
||||
{
|
||||
int3 npos = int3(x, y, pos.z);
|
||||
if(cbp->isInTheMap(npos)
|
||||
&& pos.dist2d(npos) - 0.5 < radious
|
||||
&& !ts->fogOfWarMap[npos.x][npos.y][npos.z]
|
||||
&& hasReachableNeighbor(npos, h, cbp, aip))
|
||||
{
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
TSubgoal Explore::explorationBestNeighbour(int3 hpos, int radius, HeroPtr h) const
|
||||
{
|
||||
std::map<int3, int> dstToRevealedTiles;
|
||||
VCAI * aip = ai.get();
|
||||
CCallback * cbp = cb.get();
|
||||
const TeamState * ts = cbp->getPlayerTeam(ai->playerID);
|
||||
ExplorationHelper scanResult(h, allowGatherArmy);
|
||||
|
||||
for(crint3 dir : int3::getDirs())
|
||||
{
|
||||
int3 tile = hpos + dir;
|
||||
if(cb->isInTheMap(tile))
|
||||
{
|
||||
if(isBlockVisitObj(tile))
|
||||
continue;
|
||||
|
||||
if(isSafeToVisit(h, tile) && ai->isAccessibleForHero(tile, h))
|
||||
{
|
||||
auto distance = hpos.dist2d(tile); // diagonal movement opens more tiles but spends more mp
|
||||
int tilesDiscovered = howManyTilesWillBeDiscovered(tile, radius, cbp, ts, aip, h);
|
||||
|
||||
if(tilesDiscovered > 0)
|
||||
dstToRevealedTiles[tile] = tilesDiscovered / distance;
|
||||
}
|
||||
scanResult.scanTile(tile);
|
||||
}
|
||||
}
|
||||
|
||||
if(dstToRevealedTiles.empty()) //yes, it DID happen!
|
||||
return sptr(Invalid());
|
||||
|
||||
auto paths = cb->getPathsInfo(h.get());
|
||||
|
||||
auto best = dstToRevealedTiles.begin();
|
||||
for(auto i = dstToRevealedTiles.begin(); i != dstToRevealedTiles.end(); i++)
|
||||
{
|
||||
const CGPathNode * pn = paths->getPathInfo(i->first);
|
||||
if(best->second < i->second && pn->reachable() && pn->accessible == CGPathNode::ACCESSIBLE)
|
||||
best = i;
|
||||
}
|
||||
|
||||
if(best->second)
|
||||
return sptr(VisitTile(best->first).sethero(h));
|
||||
|
||||
return sptr(Invalid());
|
||||
return scanResult.bestGoal;
|
||||
}
|
||||
|
||||
|
||||
TSubgoal Explore::explorationNewPoint(HeroPtr h) const
|
||||
{
|
||||
int radius = h->getSightRadius();
|
||||
CCallback * cbp = cb.get();
|
||||
VCAI *aip = ai.get();
|
||||
const TeamState * ts = cbp->getPlayerTeam(aip->playerID);
|
||||
ExplorationHelper scanResult(h, allowGatherArmy);
|
||||
|
||||
int3 mapSize = cbp->getMapSize();
|
||||
int perimiter = 2 * radius * (mapSize.x + mapSize.y);
|
||||
scanResult.scanSector(10);
|
||||
|
||||
std::vector<int3> from;
|
||||
std::vector<int3> to;
|
||||
|
||||
from.reserve(perimiter);
|
||||
to.reserve(perimiter);
|
||||
|
||||
foreach_tile_pos([&](const int3 & pos)
|
||||
if(!scanResult.bestGoal->invalid())
|
||||
{
|
||||
if(ts->fogOfWarMap[pos.x][pos.y][pos.z])
|
||||
{
|
||||
bool hasInvisibleNeighbor = false;
|
||||
|
||||
foreach_neighbour(cbp, pos, [&](CCallback * cbp, int3 neighbour)
|
||||
{
|
||||
if(!ts->fogOfWarMap[neighbour.x][neighbour.y][neighbour.z])
|
||||
{
|
||||
hasInvisibleNeighbor = true;
|
||||
}
|
||||
});
|
||||
|
||||
if(hasInvisibleNeighbor)
|
||||
from.push_back(pos);
|
||||
}
|
||||
});
|
||||
|
||||
for(int i = 0; i < radius; i++)
|
||||
{
|
||||
getVisibleNeighbours(from, to, cbp, ts);
|
||||
vstd::concatenate(from, to);
|
||||
vstd::removeDuplicates(from);
|
||||
return scanResult.bestGoal;
|
||||
}
|
||||
|
||||
return explorationScanRange(h, from);
|
||||
scanResult.scanMap();
|
||||
|
||||
return scanResult.bestGoal;
|
||||
}
|
||||
|
||||
TSubgoal Explore::explorationScanRange(HeroPtr h, std::vector<int3> & range) const
|
||||
{
|
||||
int radius = h->getSightRadius();
|
||||
CCallback * cbp = cb.get();
|
||||
VCAI *aip = ai.get();
|
||||
const TeamState * ts = cbp->getPlayerTeam(aip->playerID);
|
||||
|
||||
float bestValue = 0; //discovered tile to node distance ratio
|
||||
TSubgoal bestWay = sptr(Invalid());
|
||||
int3 ourPos = h->convertPosition(h->pos, false);
|
||||
|
||||
for(const int3 & tile : range)
|
||||
{
|
||||
if(tile == ourPos) //shouldn't happen, but it does
|
||||
continue;
|
||||
|
||||
int tilesDiscovered = howManyTilesWillBeDiscovered(tile, radius, cbp, ts, aip, h);
|
||||
if(!tilesDiscovered)
|
||||
continue;
|
||||
|
||||
auto waysToVisit = aip->ah->howToVisitTile(h, tile, allowGatherArmy);
|
||||
for(auto goal : waysToVisit)
|
||||
{
|
||||
if(goal->evaluationContext.movementCost <= 0.0) // should not happen
|
||||
continue;
|
||||
|
||||
float ourValue = (float)tilesDiscovered * tilesDiscovered / goal->evaluationContext.movementCost;
|
||||
|
||||
if(ourValue > bestValue) //avoid costly checks of tiles that don't reveal much
|
||||
{
|
||||
auto obj = cb->getTopObj(tile);
|
||||
if(obj && obj->blockVisit && !isObjectRemovable(obj)) //we can't stand on that object
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(isSafeToVisit(h, tile))
|
||||
{
|
||||
bestWay = goal;
|
||||
bestValue = ourValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!bestWay->invalid())
|
||||
{
|
||||
return bestWay;
|
||||
}
|
||||
|
||||
return bestWay;
|
||||
}
|
||||
|
||||
TSubgoal Explore::exploreNearestNeighbour(HeroPtr h) const
|
||||
{
|
||||
TimeCheck tc("where to explore");
|
||||
int radius = h->getSightRadius();
|
||||
int3 hpos = h->visitablePos();
|
||||
|
||||
//look for nearby objs -> visit them if they're close enough
|
||||
@ -406,19 +445,5 @@ TSubgoal Explore::exploreNearestNeighbour(HeroPtr h) const
|
||||
}
|
||||
|
||||
//check if nearby tiles allow us to reveal anything - this is quick
|
||||
return explorationBestNeighbour(hpos, radius, h);
|
||||
}
|
||||
|
||||
void Explore::getVisibleNeighbours(const std::vector<int3> & tiles, std::vector<int3> & out, CCallback * cbp, const TeamState * ts) const
|
||||
{
|
||||
for(const int3 & tile : tiles)
|
||||
{
|
||||
foreach_neighbour(cbp, tile, [&](CCallback * cbp, int3 neighbour)
|
||||
{
|
||||
if(ts->fogOfWarMap[neighbour.x][neighbour.y][neighbour.z])
|
||||
{
|
||||
out.push_back(neighbour);
|
||||
}
|
||||
});
|
||||
}
|
||||
return explorationBestNeighbour(hpos, h);
|
||||
}
|
||||
|
@ -17,6 +17,8 @@ class FuzzyHelper;
|
||||
|
||||
namespace Goals
|
||||
{
|
||||
struct ExplorationHelper;
|
||||
|
||||
class DLL_EXPORT Explore : public CGoal<Explore>
|
||||
{
|
||||
private:
|
||||
@ -49,8 +51,8 @@ namespace Goals
|
||||
private:
|
||||
TSubgoal exploreNearestNeighbour(HeroPtr h) const;
|
||||
TSubgoal explorationNewPoint(HeroPtr h) const;
|
||||
TSubgoal explorationBestNeighbour(int3 hpos, int radius, HeroPtr h) const;
|
||||
TSubgoal explorationScanRange(HeroPtr h, std::vector<int3> & range) const;
|
||||
TSubgoal explorationBestNeighbour(int3 hpos, HeroPtr h) const;
|
||||
void explorationScanTile(const int3 & tile, ExplorationHelper & scanResult) const;
|
||||
bool hasReachableNeighbor(const int3 &pos, HeroPtr hero, CCallback * cbp, VCAI * vcai) const;
|
||||
|
||||
void getVisibleNeighbours(
|
||||
@ -59,12 +61,6 @@ namespace Goals
|
||||
CCallback * cbp,
|
||||
const TeamState * ts) const;
|
||||
|
||||
int howManyTilesWillBeDiscovered(
|
||||
const int3 & pos,
|
||||
int radious,
|
||||
CCallback * cbp,
|
||||
const TeamState * ts,
|
||||
VCAI * aip,
|
||||
HeroPtr h) const;
|
||||
int howManyTilesWillBeDiscovered(const int3 & pos, ExplorationHelper & scanResult) const;
|
||||
};
|
||||
}
|
||||
|
@ -220,18 +220,18 @@ std::vector<CGPathNode *> AINodeStorage::calculateTeleportations(
|
||||
|
||||
if(source.isNodeObjectVisitable())
|
||||
{
|
||||
auto accessibleExits = pathfinderHelper->getTeleportExits(source);
|
||||
auto srcNode = getAINode(source.node);
|
||||
auto accessibleExits = pathfinderHelper->getTeleportExits(source);
|
||||
auto srcNode = getAINode(source.node);
|
||||
|
||||
for(auto & neighbour : accessibleExits)
|
||||
{
|
||||
auto node = getOrCreateNode(neighbour, source.node->layer, srcNode->chainMask);
|
||||
for(auto & neighbour : accessibleExits)
|
||||
{
|
||||
auto node = getOrCreateNode(neighbour, source.node->layer, srcNode->chainMask);
|
||||
|
||||
if(!node)
|
||||
continue;
|
||||
if(!node)
|
||||
continue;
|
||||
|
||||
neighbours.push_back(node.get());
|
||||
}
|
||||
neighbours.push_back(node.get());
|
||||
}
|
||||
}
|
||||
|
||||
if(hero->getPosition(false) == source.coord)
|
||||
@ -342,19 +342,11 @@ bool AINodeStorage::hasBetterChain(const PathNodeInfo & source, CDestinationNode
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AINodeStorage::isTileAccessible(int3 pos, const EPathfindingLayer layer) const
|
||||
bool AINodeStorage::isTileAccessible(const int3 & pos, const EPathfindingLayer layer) const
|
||||
{
|
||||
auto chains = nodes[pos.x][pos.y][pos.z][layer];
|
||||
const AIPathNode & node = nodes[pos.x][pos.y][pos.z][layer][0];
|
||||
|
||||
for(const AIPathNode & node : chains)
|
||||
{
|
||||
if(node.action != CGPathNode::ENodeAction::UNKNOWN)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return node.action != CGPathNode::ENodeAction::UNKNOWN;
|
||||
}
|
||||
|
||||
std::vector<AIPath> AINodeStorage::getChainInfo(int3 pos, bool isOnLand) const
|
||||
|
@ -114,7 +114,7 @@ public:
|
||||
bool hasBetterChain(const PathNodeInfo & source, CDestinationNodeInfo & destination) const;
|
||||
boost::optional<AIPathNode *> getOrCreateNode(const int3 & coord, const EPathfindingLayer layer, int chainNumber);
|
||||
std::vector<AIPath> getChainInfo(int3 pos, bool isOnLand) const;
|
||||
bool isTileAccessible(int3 pos, const EPathfindingLayer layer) const;
|
||||
bool isTileAccessible(const int3 & pos, const EPathfindingLayer layer) const;
|
||||
|
||||
void setHero(HeroPtr heroPtr);
|
||||
|
||||
|
@ -35,7 +35,7 @@ void AIPathfinder::init()
|
||||
storageMap.clear();
|
||||
}
|
||||
|
||||
bool AIPathfinder::isTileAccessible(HeroPtr hero, int3 tile)
|
||||
bool AIPathfinder::isTileAccessible(const HeroPtr & hero, const int3 & tile)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> storageLock(storageMutex);
|
||||
|
||||
@ -61,7 +61,7 @@ std::vector<AIPath> AIPathfinder::getPathInfo(HeroPtr hero, int3 tile)
|
||||
return nodeStorage->getChainInfo(tile, !tileInfo->isWater());
|
||||
}
|
||||
|
||||
std::shared_ptr<AINodeStorage> AIPathfinder::getOrCreateStorage(HeroPtr hero)
|
||||
std::shared_ptr<AINodeStorage> AIPathfinder::getOrCreateStorage(const HeroPtr & hero)
|
||||
{
|
||||
std::shared_ptr<AINodeStorage> nodeStorage;
|
||||
|
||||
|
@ -23,11 +23,11 @@ private:
|
||||
CPlayerSpecificInfoCallback * cb;
|
||||
VCAI * ai;
|
||||
|
||||
std::shared_ptr<AINodeStorage> getOrCreateStorage(HeroPtr hero);
|
||||
std::shared_ptr<AINodeStorage> getOrCreateStorage(const HeroPtr & hero);
|
||||
public:
|
||||
AIPathfinder(CPlayerSpecificInfoCallback * cb, VCAI * ai);
|
||||
std::vector<AIPath> getPathInfo(HeroPtr hero, int3 tile);
|
||||
bool isTileAccessible(HeroPtr hero, int3 tile);
|
||||
bool isTileAccessible(const HeroPtr & hero, const int3 & tile);
|
||||
void clear();
|
||||
void init();
|
||||
};
|
||||
|
@ -107,11 +107,6 @@ std::vector<AIPath> PathfindingManager::getPathsToTile(HeroPtr hero, int3 tile)
|
||||
return pathfinder->getPathInfo(hero, tile);
|
||||
}
|
||||
|
||||
bool PathfindingManager::isTileAccessible(HeroPtr hero, int3 tile)
|
||||
{
|
||||
return pathfinder->isTileAccessible(hero, tile);
|
||||
}
|
||||
|
||||
Goals::TGoalVec PathfindingManager::findPath(
|
||||
HeroPtr hero,
|
||||
crint3 dest,
|
||||
|
@ -26,7 +26,6 @@ public:
|
||||
virtual Goals::TGoalVec howToVisitTile(int3 tile) = 0;
|
||||
virtual Goals::TGoalVec howToVisitObj(ObjectIdRef obj) = 0;
|
||||
virtual std::vector<AIPath> getPathsToTile(HeroPtr hero, int3 tile) = 0;
|
||||
virtual bool isTileAccessible(HeroPtr hero, int3 tile) = 0;
|
||||
};
|
||||
|
||||
class DLL_EXPORT PathfindingManager : public IPathfindingManager
|
||||
@ -47,9 +46,14 @@ public:
|
||||
Goals::TGoalVec howToVisitTile(int3 tile) override;
|
||||
Goals::TGoalVec howToVisitObj(ObjectIdRef obj) override;
|
||||
std::vector<AIPath> getPathsToTile(HeroPtr hero, int3 tile) override;
|
||||
bool isTileAccessible(HeroPtr hero, int3 tile) override;
|
||||
void resetPaths() override;
|
||||
|
||||
STRONG_INLINE
|
||||
bool isTileAccessible(const HeroPtr & hero, const int3 & tile)
|
||||
{
|
||||
return pathfinder->isTileAccessible(hero, tile);
|
||||
}
|
||||
|
||||
private:
|
||||
void init(CPlayerSpecificInfoCallback * CB) override;
|
||||
void setAI(VCAI * AI) override;
|
||||
|
Loading…
Reference in New Issue
Block a user