1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-09-16 09:26:28 +02:00

Pathfinder: shorten EPathfindingLayer to ELayer

This commit is contained in:
ArseniyShestakov
2015-11-08 08:27:51 +03:00
parent 4af9c7c29d
commit f590b364c5
2 changed files with 50 additions and 44 deletions

View File

@@ -64,14 +64,14 @@ void CPathfinder::calculatePaths()
auto maxMovePoints = [&](CGPathNode *cp) -> int auto maxMovePoints = [&](CGPathNode *cp) -> int
{ {
return cp->layer == EPathfindingLayer::SAIL ? maxMovePointsWater : maxMovePointsLand; return cp->layer == ELayer::SAIL ? maxMovePointsWater : maxMovePointsLand;
}; };
auto passOneTurnLimitCheck = [&](bool shouldCheck) -> bool auto passOneTurnLimitCheck = [&](bool shouldCheck) -> bool
{ {
if(options.oneTurnSpecialLayersLimit && shouldCheck) if(options.oneTurnSpecialLayersLimit && shouldCheck)
{ {
if((cp->layer == EPathfindingLayer::AIR || cp->layer == EPathfindingLayer::WATER) if((cp->layer == ELayer::AIR || cp->layer == ELayer::WATER)
&& cp->accessible != CGPathNode::ACCESSIBLE) && cp->accessible != CGPathNode::ACCESSIBLE)
{ {
return false; return false;
@@ -95,7 +95,7 @@ void CPathfinder::calculatePaths()
//logGlobal->infoStream() << boost::format("Calculating paths for hero %s (adress %d) of player %d") % hero->name % hero % hero->tempOwner; //logGlobal->infoStream() << boost::format("Calculating paths for hero %s (adress %d) of player %d") % hero->name % hero % hero->tempOwner;
//initial tile - set cost on 0 and add to the queue //initial tile - set cost on 0 and add to the queue
CGPathNode *initialNode = out.getNode(out.hpos, hero->boat ? EPathfindingLayer::SAIL : EPathfindingLayer::LAND); CGPathNode *initialNode = out.getNode(out.hpos, hero->boat ? ELayer::SAIL : ELayer::LAND);
initialNode->turns = 0; initialNode->turns = 0;
initialNode->moveRemains = hero->movement; initialNode->moveRemains = hero->movement;
pq.push(initialNode); pq.push(initialNode);
@@ -118,7 +118,7 @@ void CPathfinder::calculatePaths()
for(auto & neighbour : neighbours) for(auto & neighbour : neighbours)
{ {
dt = &gs->map->getTile(neighbour); dt = &gs->map->getTile(neighbour);
for(EPathfindingLayer i = EPathfindingLayer::LAND; i <= EPathfindingLayer::AIR; i.advance(1)) for(ELayer i = ELayer::LAND; i <= ELayer::AIR; i.advance(1))
{ {
dp = out.getNode(neighbour, i); dp = out.getNode(neighbour, i);
if(dp->accessible == CGPathNode::NOT_SET) if(dp->accessible == CGPathNode::NOT_SET)
@@ -199,7 +199,7 @@ void CPathfinder::addNeighbours(const int3 &coord)
ct = &gs->map->getTile(coord); ct = &gs->map->getTile(coord);
std::vector<int3> tiles; std::vector<int3> tiles;
gs->getNeighbours(*ct, coord, tiles, boost::logic::indeterminate, cp->layer == EPathfindingLayer::SAIL); // TODO: find out if we still need "limitCoastSailing" option gs->getNeighbours(*ct, coord, tiles, boost::logic::indeterminate, cp->layer == ELayer::SAIL); // TODO: find out if we still need "limitCoastSailing" option
sTileObj = ct->topVisitableObj(coord == out.hpos); sTileObj = ct->topVisitableObj(coord == out.hpos);
if(canVisitObject()) if(canVisitObject())
{ {
@@ -257,19 +257,19 @@ void CPathfinder::addTeleportExits(bool noTeleportExcludes)
bool CPathfinder::isLayerTransitionPossible() bool CPathfinder::isLayerTransitionPossible()
{ {
if((cp->layer == EPathfindingLayer::AIR || cp->layer == EPathfindingLayer::WATER) if((cp->layer == ELayer::AIR || cp->layer == ELayer::WATER)
&& dp->layer != EPathfindingLayer::LAND) && dp->layer != ELayer::LAND)
{ {
return false; return false;
} }
else if(cp->layer == EPathfindingLayer::LAND && dp->layer == EPathfindingLayer::AIR) else if(cp->layer == ELayer::LAND && dp->layer == ELayer::AIR)
{ {
if(options.lightweightFlyingMode && !isSourceInitialPosition()) if(options.lightweightFlyingMode && !isSourceInitialPosition())
return false; return false;
} }
else if(cp->layer == EPathfindingLayer::SAIL && dp->layer != EPathfindingLayer::LAND) else if(cp->layer == ELayer::SAIL && dp->layer != ELayer::LAND)
return false; return false;
else if(cp->layer == EPathfindingLayer::SAIL && dp->layer == EPathfindingLayer::LAND) else if(cp->layer == ELayer::SAIL && dp->layer == ELayer::LAND)
{ {
if(!dt->isCoastal()) if(!dt->isCoastal())
return false; return false;
@@ -279,7 +279,7 @@ bool CPathfinder::isLayerTransitionPossible()
|| dt->visitable) //TODO: passableness problem -> town says it's passable (thus accessible) but we obviously can't disembark onto town gate || dt->visitable) //TODO: passableness problem -> town says it's passable (thus accessible) but we obviously can't disembark onto town gate
return false; return false;
} }
else if(cp->layer == EPathfindingLayer::LAND && dp->layer == EPathfindingLayer::SAIL) else if(cp->layer == ELayer::LAND && dp->layer == ELayer::SAIL)
{ {
if(dp->accessible == CGPathNode::ACCESSIBLE) //cannot enter empty water tile from land -> it has to be visitable if(dp->accessible == CGPathNode::ACCESSIBLE) //cannot enter empty water tile from land -> it has to be visitable
return false; return false;
@@ -292,23 +292,23 @@ bool CPathfinder::isMovementToDestPossible()
auto obj = dt->topVisitableObj(); auto obj = dt->topVisitableObj();
switch(dp->layer) switch(dp->layer)
{ {
case EPathfindingLayer::LAND: case ELayer::LAND:
if(!canMoveBetween(cp->coord, dp->coord) || dp->accessible == CGPathNode::BLOCKED) if(!canMoveBetween(cp->coord, dp->coord) || dp->accessible == CGPathNode::BLOCKED)
return false; return false;
if(isSourceGuarded() && !isDestinationGuardian()) // Can step into tile of guard if(isSourceGuarded() && !isDestinationGuardian()) // Can step into tile of guard
return false; return false;
if(cp->layer == EPathfindingLayer::SAIL) if(cp->layer == ELayer::SAIL)
destAction = CGPathNode::DISEMBARK; destAction = CGPathNode::DISEMBARK;
break; break;
case EPathfindingLayer::SAIL: case ELayer::SAIL:
if(!canMoveBetween(cp->coord, dp->coord) || dp->accessible == CGPathNode::BLOCKED) if(!canMoveBetween(cp->coord, dp->coord) || dp->accessible == CGPathNode::BLOCKED)
return false; return false;
if(isSourceGuarded() && !isDestinationGuardian()) // Can step into tile of guard if(isSourceGuarded() && !isDestinationGuardian()) // Can step into tile of guard
return false; return false;
if(cp->layer == EPathfindingLayer::LAND) if(cp->layer == ELayer::LAND)
{ {
if(!obj) if(!obj)
return false; return false;
@@ -320,13 +320,13 @@ bool CPathfinder::isMovementToDestPossible()
} }
break; break;
case EPathfindingLayer::AIR: case ELayer::AIR:
//if(!canMoveBetween(cp->coord, dp->coord)) //if(!canMoveBetween(cp->coord, dp->coord))
// return false; // return false;
break; break;
case EPathfindingLayer::WATER: case ELayer::WATER:
if(!canMoveBetween(cp->coord, dp->coord) || dp->accessible != CGPathNode::ACCESSIBLE) if(!canMoveBetween(cp->coord, dp->coord) || dp->accessible != CGPathNode::ACCESSIBLE)
return false; return false;
if(isDestinationGuarded()) if(isDestinationGuarded())
@@ -338,7 +338,7 @@ bool CPathfinder::isMovementToDestPossible()
if(destAction == CGPathNode::UNKNOWN) if(destAction == CGPathNode::UNKNOWN)
{ {
destAction = CGPathNode::NORMAL; destAction = CGPathNode::NORMAL;
if(dp->layer == EPathfindingLayer::LAND || dp->layer == EPathfindingLayer::SAIL) if(dp->layer == ELayer::LAND || dp->layer == ELayer::SAIL)
{ {
if(obj) if(obj)
{ {
@@ -429,7 +429,7 @@ bool CPathfinder::isSourceGuarded()
{ {
//special case -> hero embarked a boat standing on a guarded tile -> we must allow to move away from that tile //special case -> hero embarked a boat standing on a guarded tile -> we must allow to move away from that tile
if(cp->accessible != CGPathNode::VISITABLE if(cp->accessible != CGPathNode::VISITABLE
|| !cp->theNodeBefore->layer != EPathfindingLayer::LAND || !cp->theNodeBefore->layer != ELayer::LAND
|| ct->topVisitableId() != Obj::BOAT) || ct->topVisitableId() != Obj::BOAT)
{ {
return true; return true;
@@ -457,7 +457,7 @@ bool CPathfinder::isDestinationGuardian()
void CPathfinder::initializeGraph() void CPathfinder::initializeGraph()
{ {
auto updateNode = [&](int3 pos, EPathfindingLayer layer, const TerrainTile *tinfo, bool blockNotAccessible) auto updateNode = [&](int3 pos, ELayer layer, const TerrainTile *tinfo, bool blockNotAccessible)
{ {
auto node = out.getNode(pos, layer); auto node = out.getNode(pos, layer);
node->reset(); node->reset();
@@ -482,16 +482,16 @@ void CPathfinder::initializeGraph()
case ETerrainType::ROCK: case ETerrainType::ROCK:
break; break;
case ETerrainType::WATER: case ETerrainType::WATER:
updateNode(pos, EPathfindingLayer::SAIL, tinfo, false); updateNode(pos, ELayer::SAIL, tinfo, false);
if(options.useFlying) if(options.useFlying)
updateNode(pos, EPathfindingLayer::AIR, tinfo, true); updateNode(pos, ELayer::AIR, tinfo, true);
if(options.useWaterWalking) if(options.useWaterWalking)
updateNode(pos, EPathfindingLayer::WATER, tinfo, true); updateNode(pos, ELayer::WATER, tinfo, true);
break; break;
default: default:
updateNode(pos, EPathfindingLayer::LAND, tinfo, false); updateNode(pos, ELayer::LAND, tinfo, false);
if(options.useFlying) if(options.useFlying)
updateNode(pos, EPathfindingLayer::AIR, tinfo, true); updateNode(pos, ELayer::AIR, tinfo, true);
break; break;
} }
} }
@@ -581,10 +581,10 @@ bool CPathfinder::addTeleportWhirlpool(const CGWhirlpool * obj) const
bool CPathfinder::canVisitObject() const bool CPathfinder::canVisitObject() const
{ {
//hero can't visit objects while walking on water or flying //hero can't visit objects while walking on water or flying
return cp->layer == EPathfindingLayer::LAND || cp->layer == EPathfindingLayer::SAIL; return cp->layer == ELayer::LAND || cp->layer == ELayer::SAIL;
} }
CGPathNode::CGPathNode(int3 Coord, EPathfindingLayer Layer) CGPathNode::CGPathNode(int3 Coord, ELayer Layer)
: coord(Coord), layer(Layer) : coord(Coord), layer(Layer)
{ {
reset(); reset();
@@ -630,28 +630,28 @@ CPathsInfo::CPathsInfo(const int3 &Sizes)
: sizes(Sizes) : sizes(Sizes)
{ {
hero = nullptr; hero = nullptr;
nodes.resize(boost::extents[sizes.x][sizes.y][sizes.z][EPathfindingLayer::NUM_LAYERS]); nodes.resize(boost::extents[sizes.x][sizes.y][sizes.z][ELayer::NUM_LAYERS]);
for(int i = 0; i < sizes.x; i++) for(int i = 0; i < sizes.x; i++)
for(int j = 0; j < sizes.y; j++) for(int j = 0; j < sizes.y; j++)
for(int z = 0; z < sizes.z; z++) for(int z = 0; z < sizes.z; z++)
for(int l = 0; l < EPathfindingLayer::NUM_LAYERS; l++) for(int l = 0; l < ELayer::NUM_LAYERS; l++)
nodes[i][j][z][l] = new CGPathNode(int3(i, j, z), static_cast<EPathfindingLayer>(l)); nodes[i][j][z][l] = new CGPathNode(int3(i, j, z), static_cast<ELayer>(l));
} }
CPathsInfo::~CPathsInfo() CPathsInfo::~CPathsInfo()
{ {
} }
const CGPathNode * CPathsInfo::getPathInfo(const int3 &tile, const EPathfindingLayer &layer) const const CGPathNode * CPathsInfo::getPathInfo(const int3 &tile, const ELayer &layer) const
{ {
boost::unique_lock<boost::mutex> pathLock(pathMx); boost::unique_lock<boost::mutex> pathLock(pathMx);
if(tile.x >= sizes.x || tile.y >= sizes.y || tile.z >= sizes.z || layer >= EPathfindingLayer::NUM_LAYERS) if(tile.x >= sizes.x || tile.y >= sizes.y || tile.z >= sizes.z || layer >= ELayer::NUM_LAYERS)
return nullptr; return nullptr;
return getNode(tile, layer); return getNode(tile, layer);
} }
bool CPathsInfo::getPath(CGPath &out, const int3 &dst, const EPathfindingLayer &layer) const bool CPathsInfo::getPath(CGPath &out, const int3 &dst, const ELayer &layer) const
{ {
boost::unique_lock<boost::mutex> pathLock(pathMx); boost::unique_lock<boost::mutex> pathLock(pathMx);
@@ -669,7 +669,7 @@ bool CPathsInfo::getPath(CGPath &out, const int3 &dst, const EPathfindingLayer &
return true; return true;
} }
int CPathsInfo::getDistance(const int3 &tile, const EPathfindingLayer &layer) const int CPathsInfo::getDistance(const int3 &tile, const ELayer &layer) const
{ {
boost::unique_lock<boost::mutex> pathLock(pathMx); boost::unique_lock<boost::mutex> pathLock(pathMx);
@@ -680,14 +680,14 @@ int CPathsInfo::getDistance(const int3 &tile, const EPathfindingLayer &layer) co
return 255; return 255;
} }
CGPathNode *CPathsInfo::getNode(const int3 &coord, const EPathfindingLayer &layer) const CGPathNode *CPathsInfo::getNode(const int3 &coord, const ELayer &layer) const
{ {
if(layer != EPathfindingLayer::AUTO) if(layer != ELayer::AUTO)
return nodes[coord.x][coord.y][coord.z][layer]; return nodes[coord.x][coord.y][coord.z][layer];
auto landNode = nodes[coord.x][coord.y][coord.z][EPathfindingLayer::LAND]; auto landNode = nodes[coord.x][coord.y][coord.z][ELayer::LAND];
if(landNode->theNodeBefore) if(landNode->theNodeBefore)
return landNode; return landNode;
else else
return nodes[coord.x][coord.y][coord.z][EPathfindingLayer::SAIL]; return nodes[coord.x][coord.y][coord.z][ELayer::SAIL];
} }

View File

@@ -23,6 +23,8 @@ struct TerrainTile;
struct DLL_LINKAGE CGPathNode struct DLL_LINKAGE CGPathNode
{ {
typedef EPathfindingLayer ELayer;
enum ENodeAction enum ENodeAction
{ {
UNKNOWN = -1, UNKNOWN = -1,
@@ -49,10 +51,10 @@ struct DLL_LINKAGE CGPathNode
ui32 moveRemains; //remaining tiles after hero reaches the tile ui32 moveRemains; //remaining tiles after hero reaches the tile
CGPathNode * theNodeBefore; CGPathNode * theNodeBefore;
int3 coord; //coordinates int3 coord; //coordinates
EPathfindingLayer layer; ELayer layer;
ENodeAction action; ENodeAction action;
CGPathNode(int3 Coord, EPathfindingLayer Layer); CGPathNode(int3 Coord, ELayer Layer);
void reset(); void reset();
bool reachable() const; bool reachable() const;
}; };
@@ -68,6 +70,8 @@ struct DLL_LINKAGE CGPath
struct DLL_LINKAGE CPathsInfo struct DLL_LINKAGE CPathsInfo
{ {
typedef EPathfindingLayer ELayer;
mutable boost::mutex pathMx; mutable boost::mutex pathMx;
const CGHeroInstance *hero; const CGHeroInstance *hero;
@@ -77,10 +81,10 @@ struct DLL_LINKAGE CPathsInfo
CPathsInfo(const int3 &Sizes); CPathsInfo(const int3 &Sizes);
~CPathsInfo(); ~CPathsInfo();
const CGPathNode * getPathInfo(const int3 &tile, const EPathfindingLayer &layer = EPathfindingLayer::AUTO) const; const CGPathNode * getPathInfo(const int3 &tile, const ELayer &layer = ELayer::AUTO) const;
bool getPath(CGPath &out, const int3 &dst, const EPathfindingLayer &layer = EPathfindingLayer::AUTO) const; bool getPath(CGPath &out, const int3 &dst, const ELayer &layer = ELayer::AUTO) const;
int getDistance(const int3 &tile, const EPathfindingLayer &layer = EPathfindingLayer::AUTO) const; int getDistance(const int3 &tile, const ELayer &layer = ELayer::AUTO) const;
CGPathNode *getNode(const int3 &coord, const EPathfindingLayer &layer) const; CGPathNode *getNode(const int3 &coord, const ELayer &layer) const;
}; };
class CPathfinder : private CGameInfoCallback class CPathfinder : private CGameInfoCallback
@@ -90,6 +94,8 @@ public:
void calculatePaths(); //calculates possible paths for hero, uses current hero position and movement left; returns pointer to newly allocated CPath or nullptr if path does not exists void calculatePaths(); //calculates possible paths for hero, uses current hero position and movement left; returns pointer to newly allocated CPath or nullptr if path does not exists
private: private:
typedef EPathfindingLayer ELayer;
struct PathfinderOptions struct PathfinderOptions
{ {
bool useFlying; bool useFlying;