1
0
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:
Andrii Danylchenko 2018-12-29 15:55:20 +02:00
parent edc5abe49d
commit 04047d0a1a
10 changed files with 89 additions and 28 deletions

View File

@ -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();

View File

@ -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:

View File

@ -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);
}
});

View File

@ -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;
};
}

View File

@ -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;

View File

@ -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)
{

View File

@ -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;
}

View File

@ -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();
};

View File

@ -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,

View File

@ -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: