1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-03-23 21:29:13 +02:00

Pathfinding: re-introduce EAccessibility::FLYABLE

That let us get rid of really hacky code in initializeGraph and also fix flying over tiles that aren't visible.
This commit is contained in:
ArseniyShestakov 2015-11-17 03:59:02 +03:00
parent c2ba3e3faf
commit fe12b8f664
2 changed files with 70 additions and 52 deletions

View File

@ -321,10 +321,13 @@ bool CPathfinder::isLayerTransitionPossible() const
bool CPathfinder::isMovementToDestPossible() const bool CPathfinder::isMovementToDestPossible() const
{ {
if(dp->accessible == CGPathNode::BLOCKED)
return false;
switch(dp->layer) switch(dp->layer)
{ {
case ELayer::LAND: case ELayer::LAND:
if(!canMoveBetween(cp->coord, dp->coord) || dp->accessible == CGPathNode::BLOCKED) if(!canMoveBetween(cp->coord, dp->coord))
return false; return false;
if(isSourceGuarded()) if(isSourceGuarded())
{ {
@ -338,7 +341,7 @@ bool CPathfinder::isMovementToDestPossible() const
break; break;
case ELayer::SAIL: case ELayer::SAIL:
if(!canMoveBetween(cp->coord, dp->coord) || dp->accessible == CGPathNode::BLOCKED) if(!canMoveBetween(cp->coord, dp->coord))
return false; return false;
if(isSourceGuarded()) if(isSourceGuarded())
{ {
@ -531,17 +534,10 @@ bool CPathfinder::isDestinationGuardian() const
void CPathfinder::initializeGraph() void CPathfinder::initializeGraph()
{ {
auto updateNode = [&](int3 pos, ELayer layer, const TerrainTile * tinfo, bool blockNotAccessible) auto updateNode = [&](int3 pos, ELayer layer, const TerrainTile * tinfo)
{ {
auto node = out.getNode(pos, layer); auto node = out.getNode(pos, layer);
auto accessibility = evaluateAccessibility(pos, tinfo, layer);
auto accessibility = evaluateAccessibility(pos, tinfo);
/// TODO: Probably this shouldn't be handled by initializeGraph
if(blockNotAccessible
&& (accessibility != CGPathNode::ACCESSIBLE || tinfo->terType == ETerrainType::WATER))
{
accessibility = CGPathNode::BLOCKED;
}
node->update(pos, layer, accessibility); node->update(pos, layer, accessibility);
}; };
@ -557,17 +553,19 @@ void CPathfinder::initializeGraph()
{ {
case ETerrainType::ROCK: case ETerrainType::ROCK:
break; break;
case ETerrainType::WATER: case ETerrainType::WATER:
updateNode(pos, ELayer::SAIL, tinfo, false); updateNode(pos, ELayer::SAIL, tinfo);
if(options.useFlying) if(options.useFlying)
updateNode(pos, ELayer::AIR, tinfo, true); updateNode(pos, ELayer::AIR, tinfo);
if(options.useWaterWalking) if(options.useWaterWalking)
updateNode(pos, ELayer::WATER, tinfo, false); updateNode(pos, ELayer::WATER, tinfo);
break; break;
default: default:
updateNode(pos, ELayer::LAND, tinfo, false); updateNode(pos, ELayer::LAND, tinfo);
if(options.useFlying) if(options.useFlying)
updateNode(pos, ELayer::AIR, tinfo, true); updateNode(pos, ELayer::AIR, tinfo);
break; break;
} }
} }
@ -575,13 +573,15 @@ void CPathfinder::initializeGraph()
} }
} }
CGPathNode::EAccessibility CPathfinder::evaluateAccessibility(const int3 & pos, const TerrainTile * tinfo) const CGPathNode::EAccessibility CPathfinder::evaluateAccessibility(const int3 & pos, const TerrainTile * tinfo, const ELayer layer) const
{ {
CGPathNode::EAccessibility ret = (tinfo->blocked ? CGPathNode::BLOCKED : CGPathNode::ACCESSIBLE);
if(tinfo->terType == ETerrainType::ROCK || !isVisible(pos, hero->tempOwner)) if(tinfo->terType == ETerrainType::ROCK || !isVisible(pos, hero->tempOwner))
return CGPathNode::BLOCKED; return CGPathNode::BLOCKED;
switch(layer)
{
case ELayer::LAND:
case ELayer::SAIL:
if(tinfo->visitable) if(tinfo->visitable)
{ {
if(tinfo->visitableObjects.front()->ID == Obj::SANCTUARY && tinfo->visitableObjects.back()->ID == Obj::HERO && tinfo->visitableObjects.back()->tempOwner != hero->tempOwner) //non-owned hero stands on Sanctuary if(tinfo->visitableObjects.front()->ID == Obj::SANCTUARY && tinfo->visitableObjects.back()->ID == Obj::HERO && tinfo->visitableObjects.back()->tempOwner != hero->tempOwner) //non-owned hero stands on Sanctuary
@ -594,7 +594,7 @@ CGPathNode::EAccessibility CPathfinder::evaluateAccessibility(const int3 & pos,
{ {
if(obj->passableFor(hero->tempOwner)) if(obj->passableFor(hero->tempOwner))
{ {
ret = CGPathNode::ACCESSIBLE; return CGPathNode::ACCESSIBLE;
} }
else if(obj->blockVisit) else if(obj->blockVisit)
{ {
@ -602,18 +602,35 @@ CGPathNode::EAccessibility CPathfinder::evaluateAccessibility(const int3 & pos,
} }
else if(obj->ID != Obj::EVENT) //pathfinder should ignore placed events else if(obj->ID != Obj::EVENT) //pathfinder should ignore placed events
{ {
ret = CGPathNode::VISITABLE; return CGPathNode::VISITABLE;
} }
} }
} }
} }
else if(guardingCreaturePosition(pos).valid() && !tinfo->blocked) else if(guardingCreaturePosition(pos).valid() && !tinfo->blocked)
{ {
// Monster close by; blocked visit for battle. // Monster close by; blocked visit for battle
return CGPathNode::BLOCKVIS; return CGPathNode::BLOCKVIS;
} }
else if(tinfo->blocked)
return CGPathNode::BLOCKED;
return ret; break;
case ELayer::WATER:
if(tinfo->blocked || tinfo->terType != ETerrainType::WATER)
return CGPathNode::BLOCKED;
break;
case ELayer::AIR:
if(tinfo->blocked || tinfo->terType == ETerrainType::WATER)
return CGPathNode::FLYABLE;
break;
}
return CGPathNode::ACCESSIBLE;
} }
bool CPathfinder::canMoveBetween(const int3 & a, const int3 & b) const bool CPathfinder::canMoveBetween(const int3 & a, const int3 & b) const

View File

@ -43,6 +43,7 @@ struct DLL_LINKAGE CGPathNode
ACCESSIBLE = 1, //tile can be entered and passed ACCESSIBLE = 1, //tile can be entered and passed
VISITABLE, //tile can be entered as the last tile in path VISITABLE, //tile can be entered as the last tile in path
BLOCKVIS, //visitable from neighbouring tile but not passable BLOCKVIS, //visitable from neighbouring tile but not passable
FLYABLE, //can only be accessed in air layer
BLOCKED //tile can't be entered nor visited BLOCKED //tile can't be entered nor visited
}; };
@ -181,7 +182,7 @@ private:
void initializeGraph(); void initializeGraph();
CGPathNode::EAccessibility evaluateAccessibility(const int3 & pos, const TerrainTile * tinfo) const; CGPathNode::EAccessibility evaluateAccessibility(const int3 & pos, const TerrainTile * tinfo, const ELayer layer) 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)
bool isAllowedTeleportEntrance(const CGTeleport * obj) const; bool isAllowedTeleportEntrance(const CGTeleport * obj) const;