mirror of
https://github.com/vcmi/vcmi.git
synced 2025-02-03 13:01:33 +02:00
AI: refactor explore further
This commit is contained in:
parent
edc5abe49d
commit
04047d0a1a
@ -143,6 +143,11 @@ 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();
|
||||
|
@ -59,6 +59,7 @@ 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;
|
||||
|
||||
private:
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "../../../lib/mapping/CMap.h" //for victory conditions
|
||||
#include "../../../lib/CPathfinder.h"
|
||||
#include "../../../lib/StringConstants.h"
|
||||
#include "../../../lib/CPlayerState.h"
|
||||
|
||||
extern boost::thread_specific_ptr<CCallback> cb;
|
||||
extern boost::thread_specific_ptr<VCAI> ai;
|
||||
@ -175,9 +176,10 @@ bool Explore::hasReachableNeighbor(const int3 &pos, HeroPtr hero, CCallback * cb
|
||||
int3 tile = pos + dir;
|
||||
if(cbp->isInTheMap(tile))
|
||||
{
|
||||
auto paths = vcai->ah->getPathsToTile(hero, tile);
|
||||
auto isAccessible = vcai->ah->isTileAccessible(hero, tile);
|
||||
|
||||
return paths.size();
|
||||
if(isAccessible)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -188,8 +190,9 @@ int Explore::howManyTilesWillBeDiscovered(
|
||||
const int3 & pos,
|
||||
int radious,
|
||||
CCallback * cbp,
|
||||
HeroPtr hero,
|
||||
std::function<bool (const int3 &)> filter) const
|
||||
const TeamState * ts,
|
||||
VCAI * aip,
|
||||
HeroPtr h) const
|
||||
{
|
||||
int ret = 0;
|
||||
for(int x = pos.x - radious; x <= pos.x + radious; x++)
|
||||
@ -199,8 +202,8 @@ int Explore::howManyTilesWillBeDiscovered(
|
||||
int3 npos = int3(x, y, pos.z);
|
||||
if(cbp->isInTheMap(npos)
|
||||
&& pos.dist2d(npos) - 0.5 < radious
|
||||
&& !cbp->isVisible(npos)
|
||||
&& filter(npos))
|
||||
&& !ts->fogOfWarMap[npos.x][npos.y][npos.z]
|
||||
&& hasReachableNeighbor(npos, h, cbp, aip))
|
||||
{
|
||||
ret++;
|
||||
}
|
||||
@ -215,6 +218,7 @@ TSubgoal Explore::explorationBestNeighbour(int3 hpos, int radius, HeroPtr h) con
|
||||
std::map<int3, int> dstToRevealedTiles;
|
||||
VCAI * aip = ai.get();
|
||||
CCallback * cbp = cb.get();
|
||||
const TeamState * ts = cbp->getPlayerTeam(ai->playerID);
|
||||
|
||||
for(crint3 dir : int3::getDirs())
|
||||
{
|
||||
@ -227,9 +231,7 @@ TSubgoal Explore::explorationBestNeighbour(int3 hpos, int radius, HeroPtr h) con
|
||||
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, h, [&](int3 neighbor) -> bool {
|
||||
return hasReachableNeighbor(neighbor, h, cbp, aip);
|
||||
});
|
||||
int tilesDiscovered = howManyTilesWillBeDiscovered(tile, radius, cbp, ts, aip, h);
|
||||
|
||||
dstToRevealedTiles[tile] = tilesDiscovered / distance;
|
||||
}
|
||||
@ -259,6 +261,7 @@ 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);
|
||||
|
||||
std::vector<std::vector<int3>> tiles; //tiles[distance_to_fow]
|
||||
tiles.resize(radius);
|
||||
@ -275,7 +278,7 @@ TSubgoal Explore::explorationNewPoint(HeroPtr h) const
|
||||
|
||||
for(int i = 1; i < radius; i++)
|
||||
{
|
||||
getVisibleNeighbours(tiles[i - 1], tiles[i], cbp);
|
||||
getVisibleNeighbours(tiles[i - 1], tiles[i], cbp, ts);
|
||||
vstd::removeDuplicates(tiles[i]);
|
||||
|
||||
for(const int3 & tile : tiles[i])
|
||||
@ -289,7 +292,7 @@ TSubgoal Explore::explorationNewPoint(HeroPtr h) const
|
||||
if(goal->evaluationContext.movementCost == 0) // should not happen
|
||||
continue;
|
||||
|
||||
int tilesDiscovered = howManyTilesWillBeDiscovered(tile, radius, cbp, h, [](int3 neighbor) -> bool { return true; });
|
||||
int tilesDiscovered = howManyTilesWillBeDiscovered(tile, radius, cbp, ts, aip, h);
|
||||
float ourValue = (float) tilesDiscovered / goal->evaluationContext.movementCost; //+1 prevents erratic jumps
|
||||
|
||||
if(ourValue > bestValue) //avoid costly checks of tiles that don't reveal much
|
||||
@ -368,17 +371,17 @@ TSubgoal Explore::howToExplore(HeroPtr h) const
|
||||
return result;
|
||||
}
|
||||
|
||||
void Explore::getVisibleNeighbours(const std::vector<int3> & tiles, std::vector<int3> & out, CCallback * cbp) const
|
||||
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(tile, [&](int3 neighbour)
|
||||
foreach_neighbour(cbp, tile, [&](CCallback * cbp, int3 neighbour)
|
||||
{
|
||||
if(cbp->isVisible(neighbour))
|
||||
if(ts->fogOfWarMap[neighbour.x][neighbour.y][neighbour.z])
|
||||
{
|
||||
auto tile = cbp->getTile(neighbour);
|
||||
//auto tile = cbp->getTile(neighbour);
|
||||
|
||||
if(tile && !tile->blocked)
|
||||
//if(tile && !tile->blocked)
|
||||
out.push_back(neighbour);
|
||||
}
|
||||
});
|
||||
|
@ -42,12 +42,19 @@ namespace Goals
|
||||
TSubgoal explorationNewPoint(HeroPtr h) const;
|
||||
TSubgoal explorationBestNeighbour(int3 hpos, int radius, HeroPtr h) const;
|
||||
bool hasReachableNeighbor(const int3 &pos, HeroPtr hero, CCallback * cbp, VCAI * vcai) const;
|
||||
void getVisibleNeighbours(const std::vector<int3> & tiles, std::vector<int3> & out, CCallback * cbp) const;
|
||||
|
||||
void getVisibleNeighbours(
|
||||
const std::vector<int3> & tiles,
|
||||
std::vector<int3> & out,
|
||||
CCallback * cbp,
|
||||
const TeamState * ts) const;
|
||||
|
||||
int howManyTilesWillBeDiscovered(
|
||||
const int3 & pos,
|
||||
int radious,
|
||||
CCallback * cbp,
|
||||
HeroPtr hero,
|
||||
std::function<bool(const int3 &)> filter) const;
|
||||
const TeamState * ts,
|
||||
VCAI * aip,
|
||||
HeroPtr h) const;
|
||||
};
|
||||
}
|
||||
|
@ -189,6 +189,23 @@ bool AINodeStorage::hasBetterChain(const PathNodeInfo & source, CDestinationNode
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AINodeStorage::isTileAccessible(int3 pos, const EPathfindingLayer layer) const
|
||||
{
|
||||
std::vector<AIPath> paths;
|
||||
auto chains = nodes[pos.x][pos.y][pos.z][layer];
|
||||
auto initialPos = hero->visitablePos();
|
||||
|
||||
for(const AIPathNode & node : chains)
|
||||
{
|
||||
if(node.action != CGPathNode::ENodeAction::UNKNOWN)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<AIPath> AINodeStorage::getChainInfo(int3 pos, bool isOnLand) const
|
||||
{
|
||||
std::vector<AIPath> paths;
|
||||
|
@ -111,6 +111,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;
|
||||
|
||||
void setHero(HeroPtr heroPtr)
|
||||
{
|
||||
|
@ -28,9 +28,33 @@ void AIPathfinder::clear()
|
||||
storageMap.clear();
|
||||
}
|
||||
|
||||
bool AIPathfinder::isTileAccessible(HeroPtr hero, int3 tile)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> storageLock(storageMutex);
|
||||
|
||||
std::shared_ptr<AINodeStorage> nodeStorage = getOrCreateStorage(hero);
|
||||
|
||||
return nodeStorage->isTileAccessible(tile, EPathfindingLayer::LAND)
|
||||
|| nodeStorage->isTileAccessible(tile, EPathfindingLayer::SAIL);
|
||||
}
|
||||
std::vector<AIPath> AIPathfinder::getPathInfo(HeroPtr hero, int3 tile)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> storageLock(storageMutex);
|
||||
|
||||
std::shared_ptr<AINodeStorage> nodeStorage = getOrCreateStorage(hero);
|
||||
|
||||
const TerrainTile * tileInfo = cb->getTile(tile, false);
|
||||
|
||||
if(!tileInfo)
|
||||
{
|
||||
return std::vector<AIPath>();
|
||||
}
|
||||
|
||||
return nodeStorage->getChainInfo(tile, !tileInfo->isWater());
|
||||
}
|
||||
|
||||
std::shared_ptr<AINodeStorage> AIPathfinder::getOrCreateStorage(HeroPtr hero)
|
||||
{
|
||||
std::shared_ptr<AINodeStorage> nodeStorage;
|
||||
|
||||
if(!vstd::contains(storageMap, hero))
|
||||
@ -49,7 +73,7 @@ std::vector<AIPath> AIPathfinder::getPathInfo(HeroPtr hero, int3 tile)
|
||||
|
||||
storageMap[hero] = nodeStorage;
|
||||
nodeStorage->setHero(hero.get());
|
||||
|
||||
|
||||
auto config = std::make_shared<AIPathfinding::AIPathfinderConfig>(cb, ai, nodeStorage);
|
||||
|
||||
cb->calculatePaths(config, hero.get());
|
||||
@ -59,12 +83,6 @@ std::vector<AIPath> AIPathfinder::getPathInfo(HeroPtr hero, int3 tile)
|
||||
nodeStorage = storageMap.at(hero);
|
||||
}
|
||||
|
||||
const TerrainTile * tileInfo = cb->getTile(tile, false);
|
||||
|
||||
if(!tileInfo)
|
||||
{
|
||||
return std::vector<AIPath>();
|
||||
}
|
||||
|
||||
return nodeStorage->getChainInfo(tile, !tileInfo->isWater());
|
||||
return nodeStorage;
|
||||
}
|
||||
|
||||
|
@ -26,5 +26,7 @@ private:
|
||||
public:
|
||||
AIPathfinder(CPlayerSpecificInfoCallback * cb, VCAI * ai);
|
||||
std::vector<AIPath> getPathInfo(HeroPtr hero, int3 tile);
|
||||
bool isTileAccessible(HeroPtr hero, int3 tile);
|
||||
std::shared_ptr<AINodeStorage> getOrCreateStorage(HeroPtr hero);
|
||||
void clear();
|
||||
};
|
||||
|
@ -104,6 +104,11 @@ 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,6 +26,7 @@ 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 PathfindingManager : public IPathfindingManager
|
||||
@ -46,6 +47,7 @@ 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;
|
||||
|
||||
private:
|
||||
|
Loading…
x
Reference in New Issue
Block a user