From 1beacf2260429a1665fcd0706f84f92c702734c0 Mon Sep 17 00:00:00 2001 From: ArseniyShestakov Date: Mon, 12 Oct 2015 08:13:10 +0300 Subject: [PATCH] CPathfinder: move guard checks into functions --- lib/CGameState.cpp | 55 ++++++++++++++++++++++++++++++++++------------ lib/CGameState.h | 5 +++++ 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index e4a7b0412..3279a5db6 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -3360,12 +3360,50 @@ void CPathfinder::getTeleportExits(bool noTeleportExcludes) } } +int3 CPathfinder::getSourceGuardPosition() +{ + return gs->map->guardingCreaturePositions[cp->coord.x][cp->coord.y][cp->coord.z]; +} + +bool CPathfinder::isSourceGuarded() +{ + //TODO: find out why exactly source can't be guarded if hero on it. Why this quirk was nessesaary in first place? Map where hero start on guarded tile? + if(getSourceGuardPosition() != int3(-1, -1, -1) + && cp->coord != hero->getPosition(false)) + { + //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 + || !cp->theNodeBefore->land + || ct->topVisitableId() != Obj::BOAT) + { + return true; + } + } + + return false; +} + +bool CPathfinder::isDestinationGuarded() +{ + if(gs->map->guardingCreaturePositions[dp->coord.x][dp->coord.y][dp->coord.z].valid() + && dp->accessible == CGPathNode::BLOCKVIS) + { + return true; + } + + return false; +} + +bool CPathfinder::isDestinationGuardian() +{ + return getSourceGuardPosition() == dp->coord; +} + void CPathfinder::calculatePaths() { bool flying = hero->hasBonusOfType(Bonus::FLYING_MOVEMENT); int maxMovePointsLand = hero->maxMovePoints(true); int maxMovePointsWater = hero->maxMovePoints(false); - int3 src = hero->getPosition(false); auto maxMovePoints = [&](CGPathNode *cp) -> int { @@ -3395,9 +3433,6 @@ void CPathfinder::calculatePaths() cp = mq.front(); mq.pop_front(); - const int3 sourceGuardPosition = gs->map->guardingCreaturePositions[cp->coord.x][cp->coord.y][cp->coord.z]; - bool guardedSource = (sourceGuardPosition != int3(-1, -1, -1) && cp->coord != src); - int movement = cp->moveRemains, turn = cp->turns; if(!movement) { @@ -3412,7 +3447,6 @@ void CPathfinder::calculatePaths() dp = getNode(neighbour); dt = &gs->map->getTile(neighbour); useEmbarkCost = 0; //0 - usual movement; 1 - embark; 2 - disembark - const bool destIsGuardian = sourceGuardPosition == neighbour; if(!isMovementPossible()) continue; @@ -3435,23 +3469,16 @@ void CPathfinder::calculatePaths() remains = moveAtNextTile - cost; } - //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 && guardedSource && cp->theNodeBefore->land && ct->topVisitableId() == Obj::BOAT) - guardedSource = false; - if((dp->turns==0xff //we haven't been here before || dp->turns > turnAtNextTile || (dp->turns >= turnAtNextTile && dp->moveRemains < remains)) //this route is faster - && (!guardedSource || destIsGuardian)) // Can step into tile of guard + && (!isSourceGuarded() || isDestinationGuardian())) // Can step into tile of guard { assert(dp != cp->theNodeBefore); //two tiles can't point to each other dp->moveRemains = remains; dp->turns = turnAtNextTile; dp->theNodeBefore = cp; - const bool guardedDst = gs->map->guardingCreaturePositions[dp->coord.x][dp->coord.y][dp->coord.z].valid() - && dp->accessible == CGPathNode::BLOCKVIS; - auto checkDestinationTile = [&]() -> bool { if(dp->accessible == CGPathNode::ACCESSIBLE) @@ -3462,7 +3489,7 @@ void CPathfinder::calculatePaths() return true; // For now we'll walways allos transit for teleports if(useEmbarkCost && allowEmbarkAndDisembark) return true; - if(guardedDst && !guardedSource) + if(isDestinationGuarded() && !isSourceGuarded()) return true; // Can step into a hostile tile once return false; diff --git a/lib/CGameState.h b/lib/CGameState.h index 983951dc9..0ca0e9ef6 100644 --- a/lib/CGameState.h +++ b/lib/CGameState.h @@ -307,6 +307,11 @@ private: void initializeGraph(); bool isMovementPossible(); //checks if current move will be between sea<->land. If so, checks it legality (returns false if movement is not possible) and sets useEmbarkCost + int3 getSourceGuardPosition(); + bool isSourceGuarded(); + bool isDestinationGuarded(); + bool isDestinationGuardian(); + void getNeighbours(const int3 &coord); void getTeleportExits(bool noTeleportExcludes = false);