mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-26 22:57:00 +02:00
Pathfinding: make related code aware that layers exist
This commit is contained in:
parent
118039a368
commit
b8253206c7
@ -79,7 +79,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 = *getNode(out.hpos);
|
CGPathNode &initialNode = *getNode(out.hpos, hero->boat ? EPathfindingLayer::SAIL : EPathfindingLayer::LAND);
|
||||||
initialNode.turns = 0;
|
initialNode.turns = 0;
|
||||||
initialNode.moveRemains = hero->movement;
|
initialNode.moveRemains = hero->movement;
|
||||||
mq.push_back(&initialNode);
|
mq.push_back(&initialNode);
|
||||||
@ -100,7 +100,7 @@ void CPathfinder::calculatePaths()
|
|||||||
addNeighbours(cp->coord);
|
addNeighbours(cp->coord);
|
||||||
for(auto & neighbour : neighbours)
|
for(auto & neighbour : neighbours)
|
||||||
{
|
{
|
||||||
dp = getNode(neighbour);
|
dp = getNode(neighbour, EPathfindingLayer::LAND);
|
||||||
dt = &gs->map->getTile(neighbour);
|
dt = &gs->map->getTile(neighbour);
|
||||||
useEmbarkCost = 0; //0 - usual movement; 1 - embark; 2 - disembark
|
useEmbarkCost = 0; //0 - usual movement; 1 - embark; 2 - disembark
|
||||||
|
|
||||||
@ -138,12 +138,12 @@ void CPathfinder::calculatePaths()
|
|||||||
} //neighbours loop
|
} //neighbours loop
|
||||||
|
|
||||||
//just add all passable teleport exits
|
//just add all passable teleport exits
|
||||||
if(sTileObj)
|
if(sTileObj && canVisitObject())
|
||||||
{
|
{
|
||||||
addTeleportExits();
|
addTeleportExits();
|
||||||
for(auto & neighbour : neighbours)
|
for(auto & neighbour : neighbours)
|
||||||
{
|
{
|
||||||
dp = getNode(neighbour);
|
dp = getNode(neighbour, EPathfindingLayer::LAND);
|
||||||
if(isBetterWay(movement, turn))
|
if(isBetterWay(movement, turn))
|
||||||
{
|
{
|
||||||
dp->moveRemains = movement;
|
dp->moveRemains = movement;
|
||||||
@ -164,13 +164,18 @@ void CPathfinder::addNeighbours(const int3 &coord)
|
|||||||
std::vector<int3> tiles;
|
std::vector<int3> tiles;
|
||||||
gs->getNeighbours(*ct, coord, tiles, boost::logic::indeterminate, !cp->land);
|
gs->getNeighbours(*ct, coord, tiles, boost::logic::indeterminate, !cp->land);
|
||||||
sTileObj = ct->topVisitableObj(coord == CGHeroInstance::convertPosition(hero->pos, false));
|
sTileObj = ct->topVisitableObj(coord == CGHeroInstance::convertPosition(hero->pos, false));
|
||||||
if(sTileObj)
|
if(canVisitObject())
|
||||||
{
|
{
|
||||||
for(int3 tile: tiles)
|
if(sTileObj)
|
||||||
{
|
{
|
||||||
if(canMoveBetween(tile, sTileObj->visitablePos()))
|
for(int3 tile: tiles)
|
||||||
neighbours.push_back(tile);
|
{
|
||||||
|
if(canMoveBetween(tile, sTileObj->visitablePos()))
|
||||||
|
neighbours.push_back(tile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
vstd::concatenate(neighbours, tiles);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
vstd::concatenate(neighbours, tiles);
|
vstd::concatenate(neighbours, tiles);
|
||||||
@ -310,7 +315,20 @@ bool CPathfinder::isDestinationGuardian()
|
|||||||
void CPathfinder::initializeGraph()
|
void CPathfinder::initializeGraph()
|
||||||
{
|
{
|
||||||
int3 pos;
|
int3 pos;
|
||||||
CGPathNode ***graph = out.nodes;
|
CGPathNode ****graph = out.nodes;
|
||||||
|
const TerrainTile *tinfo;
|
||||||
|
auto addNode = [&](EPathfindingLayer layer)
|
||||||
|
{
|
||||||
|
CGPathNode &node = graph[pos.x][pos.y][pos.z][layer];
|
||||||
|
node.accessible = evaluateAccessibility(pos, tinfo);
|
||||||
|
node.turns = 0xff;
|
||||||
|
node.moveRemains = 0;
|
||||||
|
node.coord = pos;
|
||||||
|
node.land = tinfo->terType != ETerrainType::WATER;
|
||||||
|
node.theNodeBefore = nullptr;
|
||||||
|
node.layer = layer;
|
||||||
|
};
|
||||||
|
|
||||||
for(pos.x=0; pos.x < out.sizes.x; ++pos.x)
|
for(pos.x=0; pos.x < out.sizes.x; ++pos.x)
|
||||||
{
|
{
|
||||||
for(pos.y=0; pos.y < out.sizes.y; ++pos.y)
|
for(pos.y=0; pos.y < out.sizes.y; ++pos.y)
|
||||||
@ -318,21 +336,33 @@ void CPathfinder::initializeGraph()
|
|||||||
for(pos.z=0; pos.z < out.sizes.z; ++pos.z)
|
for(pos.z=0; pos.z < out.sizes.z; ++pos.z)
|
||||||
{
|
{
|
||||||
const TerrainTile *tinfo = &gs->map->getTile(pos);
|
const TerrainTile *tinfo = &gs->map->getTile(pos);
|
||||||
CGPathNode &node = graph[pos.x][pos.y][pos.z];
|
switch (tinfo->terType)
|
||||||
node.accessible = evaluateAccessibility(pos, tinfo);
|
{
|
||||||
node.turns = 0xff;
|
case ETerrainType::WRONG:
|
||||||
node.moveRemains = 0;
|
case ETerrainType::BORDER:
|
||||||
node.coord = pos;
|
case ETerrainType::ROCK:
|
||||||
node.land = tinfo->terType != ETerrainType::WATER;
|
break;
|
||||||
node.theNodeBefore = nullptr;
|
case ETerrainType::WATER:
|
||||||
|
addNode(EPathfindingLayer::SAIL);
|
||||||
|
if(options.useFlying)
|
||||||
|
addNode(EPathfindingLayer::AIR);
|
||||||
|
if(options.useWaterWalking)
|
||||||
|
addNode(EPathfindingLayer::WATER);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
addNode(EPathfindingLayer::LAND);
|
||||||
|
if(options.useFlying)
|
||||||
|
addNode(EPathfindingLayer::AIR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CGPathNode *CPathfinder::getNode(const int3 &coord)
|
CGPathNode *CPathfinder::getNode(const int3 &coord, const EPathfindingLayer &layer)
|
||||||
{
|
{
|
||||||
return &out.nodes[coord.x][coord.y][coord.z];
|
return &out.nodes[coord.x][coord.y][coord.z][layer];
|
||||||
}
|
}
|
||||||
|
|
||||||
CGPathNode::EAccessibility CPathfinder::evaluateAccessibility(const int3 &pos, const TerrainTile *tinfo) const
|
CGPathNode::EAccessibility CPathfinder::evaluateAccessibility(const int3 &pos, const TerrainTile *tinfo) const
|
||||||
@ -415,6 +445,12 @@ bool CPathfinder::addTeleportWhirlpool(const CGWhirlpool * obj) const
|
|||||||
return options.useTeleportWhirlpool && obj;
|
return options.useTeleportWhirlpool && obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CPathfinder::canVisitObject() const
|
||||||
|
{
|
||||||
|
//hero can't visit objects while walking on water or flying
|
||||||
|
return cp->layer == EPathfindingLayer::LAND || cp->layer == EPathfindingLayer::SAIL;
|
||||||
|
}
|
||||||
|
|
||||||
CGPathNode::CGPathNode()
|
CGPathNode::CGPathNode()
|
||||||
:coord(-1,-1,-1)
|
:coord(-1,-1,-1)
|
||||||
{
|
{
|
||||||
@ -455,13 +491,17 @@ CPathsInfo::CPathsInfo( const int3 &Sizes )
|
|||||||
:sizes(Sizes)
|
:sizes(Sizes)
|
||||||
{
|
{
|
||||||
hero = nullptr;
|
hero = nullptr;
|
||||||
nodes = new CGPathNode**[sizes.x];
|
nodes = new CGPathNode***[sizes.x];
|
||||||
for(int i = 0; i < sizes.x; i++)
|
for(int i = 0; i < sizes.x; i++)
|
||||||
{
|
{
|
||||||
nodes[i] = new CGPathNode*[sizes.y];
|
nodes[i] = new CGPathNode**[sizes.y];
|
||||||
for(int j = 0; j < sizes.y; j++)
|
for(int j = 0; j < sizes.y; j++)
|
||||||
{
|
{
|
||||||
nodes[i][j] = new CGPathNode[sizes.z];
|
nodes[i][j] = new CGPathNode*[sizes.z];
|
||||||
|
for (int z = 0; z < sizes.z; z++)
|
||||||
|
{
|
||||||
|
nodes[i][j][z] = new CGPathNode[EPathfindingLayer::NUM_LAYERS];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -472,6 +512,10 @@ CPathsInfo::~CPathsInfo()
|
|||||||
{
|
{
|
||||||
for(int j = 0; j < sizes.y; j++)
|
for(int j = 0; j < sizes.y; j++)
|
||||||
{
|
{
|
||||||
|
for (int z = 0; z < sizes.z; z++)
|
||||||
|
{
|
||||||
|
delete [] nodes[i][j][z];
|
||||||
|
}
|
||||||
delete [] nodes[i][j];
|
delete [] nodes[i][j];
|
||||||
}
|
}
|
||||||
delete [] nodes[i];
|
delete [] nodes[i];
|
||||||
@ -479,21 +523,21 @@ CPathsInfo::~CPathsInfo()
|
|||||||
delete [] nodes;
|
delete [] nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CGPathNode * CPathsInfo::getPathInfo( int3 tile ) const
|
const CGPathNode * CPathsInfo::getPathInfo(const int3 &tile, const EPathfindingLayer &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)
|
if(tile.x >= sizes.x || tile.y >= sizes.y || tile.z >= sizes.z || layer >= EPathfindingLayer::NUM_LAYERS)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return &nodes[tile.x][tile.y][tile.z];
|
return &nodes[tile.x][tile.y][tile.z][layer];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CPathsInfo::getPath( const int3 &dst, CGPath &out ) const
|
bool CPathsInfo::getPath(const int3 &dst, const EPathfindingLayer &layer, CGPath &out) const
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::mutex> pathLock(pathMx);
|
boost::unique_lock<boost::mutex> pathLock(pathMx);
|
||||||
|
|
||||||
out.nodes.clear();
|
out.nodes.clear();
|
||||||
const CGPathNode *curnode = &nodes[dst.x][dst.y][dst.z];
|
const CGPathNode *curnode = &nodes[dst.x][dst.y][dst.z][layer];
|
||||||
if(!curnode->theNodeBefore)
|
if(!curnode->theNodeBefore)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -507,12 +551,12 @@ bool CPathsInfo::getPath( const int3 &dst, CGPath &out ) const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CPathsInfo::getDistance( int3 tile ) const
|
int CPathsInfo::getDistance(const int3 &tile, const EPathfindingLayer &layer) const
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::mutex> pathLock(pathMx);
|
boost::unique_lock<boost::mutex> pathLock(pathMx);
|
||||||
|
|
||||||
CGPath ret;
|
CGPath ret;
|
||||||
if(getPath(tile, ret))
|
if(getPath(tile, layer, ret))
|
||||||
return ret.nodes.size();
|
return ret.nodes.size();
|
||||||
else
|
else
|
||||||
return 255;
|
return 255;
|
||||||
|
@ -36,6 +36,7 @@ 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;
|
||||||
|
|
||||||
CGPathNode();
|
CGPathNode();
|
||||||
bool reachable() const;
|
bool reachable() const;
|
||||||
@ -57,13 +58,13 @@ struct DLL_LINKAGE CPathsInfo
|
|||||||
const CGHeroInstance *hero;
|
const CGHeroInstance *hero;
|
||||||
int3 hpos;
|
int3 hpos;
|
||||||
int3 sizes;
|
int3 sizes;
|
||||||
CGPathNode ***nodes; //[w][h][level]
|
CGPathNode ****nodes; //[w][h][level][layer]
|
||||||
|
|
||||||
CPathsInfo(const int3 &Sizes);
|
CPathsInfo(const int3 &Sizes);
|
||||||
~CPathsInfo();
|
~CPathsInfo();
|
||||||
const CGPathNode * getPathInfo( int3 tile ) const;
|
const CGPathNode * getPathInfo(const int3 &tile, const EPathfindingLayer &layer) const;
|
||||||
bool getPath(const int3 &dst, CGPath &out) const;
|
bool getPath(const int3 &dst, const EPathfindingLayer &layer, CGPath &out) const;
|
||||||
int getDistance( int3 tile ) const;
|
int getDistance(const int3 &tile, const EPathfindingLayer &layer) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CPathfinder : private CGameInfoCallback
|
class CPathfinder : private CGameInfoCallback
|
||||||
@ -113,7 +114,7 @@ private:
|
|||||||
|
|
||||||
void initializeGraph();
|
void initializeGraph();
|
||||||
|
|
||||||
CGPathNode *getNode(const int3 &coord);
|
CGPathNode *getNode(const int3 &coord, const EPathfindingLayer &layer);
|
||||||
CGPathNode::EAccessibility evaluateAccessibility(const int3 &pos, const TerrainTile *tinfo) const;
|
CGPathNode::EAccessibility evaluateAccessibility(const int3 &pos, const TerrainTile *tinfo) const;
|
||||||
bool canMoveBetween(const int3 &a, const int3 &b) const; //checks only for visitable objects that may make moving between tiles impossible, not other conditions (like tiles itself accessibility)
|
bool canMoveBetween(const int3 &a, const int3 &b) const; //checks only for visitable objects that may make moving between tiles impossible, not other conditions (like tiles itself accessibility)
|
||||||
|
|
||||||
@ -121,4 +122,6 @@ private:
|
|||||||
bool addTeleportOneWay(const CGTeleport * obj) const;
|
bool addTeleportOneWay(const CGTeleport * obj) const;
|
||||||
bool addTeleportOneWayRandom(const CGTeleport * obj) const;
|
bool addTeleportOneWayRandom(const CGTeleport * obj) const;
|
||||||
bool addTeleportWhirlpool(const CGWhirlpool * obj) const;
|
bool addTeleportWhirlpool(const CGWhirlpool * obj) const;
|
||||||
|
|
||||||
|
bool canVisitObject() const;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user