1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-06 09:09:40 +02:00

Pathfinder now uses IGameInfoCallback instead of CGameState

This commit is contained in:
Ivan Savenko
2025-05-15 21:23:54 +03:00
parent fe2f5f9217
commit c0850f41b3
26 changed files with 139 additions and 128 deletions

View File

@@ -112,7 +112,7 @@ AINodeStorage::AINodeStorage(const Nullkiller * ai, const int3 & Sizes)
AINodeStorage::~AINodeStorage() = default; AINodeStorage::~AINodeStorage() = default;
void AINodeStorage::initialize(const PathfinderOptions & options, const CGameState * gs) void AINodeStorage::initialize(const PathfinderOptions & options, const IGameInfoCallback & gameInfo)
{ {
if(heroChainPass != EHeroChainPass::INITIAL) if(heroChainPass != EHeroChainPass::INITIAL)
return; return;
@@ -121,8 +121,8 @@ void AINodeStorage::initialize(const PathfinderOptions & options, const CGameSta
//TODO: fix this code duplication with NodeStorage::initialize, problem is to keep `resetTile` inline //TODO: fix this code duplication with NodeStorage::initialize, problem is to keep `resetTile` inline
const PlayerColor fowPlayer = ai->playerID; const PlayerColor fowPlayer = ai->playerID;
const auto & fow = static_cast<const IGameInfoCallback *>(gs)->getPlayerTeam(fowPlayer)->fogOfWarMap; const auto & fow = gameInfo.getPlayerTeam(fowPlayer)->fogOfWarMap;
const int3 sizes = gs->getMapSize(); const int3 sizes = gameInfo.getMapSize();
//Each thread gets different x, but an array of y located next to each other in memory //Each thread gets different x, but an array of y located next to each other in memory
@@ -140,23 +140,23 @@ void AINodeStorage::initialize(const PathfinderOptions & options, const CGameSta
{ {
for(pos.y = 0; pos.y < sizes.y; ++pos.y) for(pos.y = 0; pos.y < sizes.y; ++pos.y)
{ {
const TerrainTile & tile = gs->getMap().getTile(pos); const TerrainTile * tile = gameInfo.getTile(pos);
if (!tile.getTerrain()->isPassable()) if (!tile->getTerrain()->isPassable())
continue; continue;
if (tile.isWater()) if (tile->isWater())
{ {
resetTile(pos, ELayer::SAIL, PathfinderUtil::evaluateAccessibility<ELayer::SAIL>(pos, tile, fow, player, gs)); resetTile(pos, ELayer::SAIL, PathfinderUtil::evaluateAccessibility<ELayer::SAIL>(pos, *tile, fow, player, gameInfo));
if (useFlying) if (useFlying)
resetTile(pos, ELayer::AIR, PathfinderUtil::evaluateAccessibility<ELayer::AIR>(pos, tile, fow, player, gs)); resetTile(pos, ELayer::AIR, PathfinderUtil::evaluateAccessibility<ELayer::AIR>(pos, *tile, fow, player, gameInfo));
if (useWaterWalking) if (useWaterWalking)
resetTile(pos, ELayer::WATER, PathfinderUtil::evaluateAccessibility<ELayer::WATER>(pos, tile, fow, player, gs)); resetTile(pos, ELayer::WATER, PathfinderUtil::evaluateAccessibility<ELayer::WATER>(pos, *tile, fow, player, gameInfo));
} }
else else
{ {
resetTile(pos, ELayer::LAND, PathfinderUtil::evaluateAccessibility<ELayer::LAND>(pos, tile, fow, player, gs)); resetTile(pos, ELayer::LAND, PathfinderUtil::evaluateAccessibility<ELayer::LAND>(pos, *tile, fow, player, gameInfo));
if (useFlying) if (useFlying)
resetTile(pos, ELayer::AIR, PathfinderUtil::evaluateAccessibility<ELayer::AIR>(pos, tile, fow, player, gs)); resetTile(pos, ELayer::AIR, PathfinderUtil::evaluateAccessibility<ELayer::AIR>(pos, *tile, fow, player, gameInfo));
} }
} }
} }

View File

@@ -186,7 +186,7 @@ public:
AINodeStorage(const Nullkiller * ai, const int3 & sizes); AINodeStorage(const Nullkiller * ai, const int3 & sizes);
~AINodeStorage(); ~AINodeStorage();
void initialize(const PathfinderOptions & options, const CGameState * gs) override; void initialize(const PathfinderOptions & options, const IGameInfoCallback & gameInfo) override;
bool increaseHeroChainTurnLimit(); bool increaseHeroChainTurnLimit();
bool selectFirstActor(); bool selectFirstActor();

View File

@@ -56,14 +56,14 @@ namespace AIPathfinding
AIPathfinderConfig::~AIPathfinderConfig() = default; AIPathfinderConfig::~AIPathfinderConfig() = default;
CPathfinderHelper * AIPathfinderConfig::getOrCreatePathfinderHelper(const PathNodeInfo & source, const CGameState & gs) CPathfinderHelper * AIPathfinderConfig::getOrCreatePathfinderHelper(const PathNodeInfo & source, const IGameInfoCallback & gameInfo)
{ {
auto hero = aiNodeStorage->getHero(source.node); auto hero = aiNodeStorage->getHero(source.node);
auto & helper = pathfindingHelpers[hero]; auto & helper = pathfindingHelpers[hero];
if(!helper) if(!helper)
{ {
helper.reset(new CPathfinderHelper(gs, hero, options)); helper.reset(new CPathfinderHelper(gameInfo, hero, options));
} }
return helper.get(); return helper.get();

View File

@@ -35,7 +35,7 @@ namespace AIPathfinding
~AIPathfinderConfig(); ~AIPathfinderConfig();
CPathfinderHelper * getOrCreatePathfinderHelper(const PathNodeInfo & source, const CGameState & gs) override; CPathfinderHelper * getOrCreatePathfinderHelper(const PathNodeInfo & source, const IGameInfoCallback & gameInfo) override;
}; };
} }

View File

@@ -29,11 +29,11 @@ AINodeStorage::AINodeStorage(const int3 & Sizes)
AINodeStorage::~AINodeStorage() = default; AINodeStorage::~AINodeStorage() = default;
void AINodeStorage::initialize(const PathfinderOptions & options, const CGameState * gs) void AINodeStorage::initialize(const PathfinderOptions & options, const IGameInfoCallback & gameInfo)
{ {
int3 pos; int3 pos;
const int3 sizes = gs->getMapSize(); const int3 sizes = gameInfo.getMapSize();
const auto & fow = static_cast<const IGameInfoCallback *>(gs)->getPlayerTeam(hero->tempOwner)->fogOfWarMap; const auto & fow = gameInfo.getPlayerTeam(hero->tempOwner)->fogOfWarMap;
const PlayerColor player = hero->tempOwner; const PlayerColor player = hero->tempOwner;
//make 200% sure that these are loop invariants (also a bit shorter code), let compiler do the rest(loop unswitching) //make 200% sure that these are loop invariants (also a bit shorter code), let compiler do the rest(loop unswitching)
@@ -46,23 +46,23 @@ void AINodeStorage::initialize(const PathfinderOptions & options, const CGameSta
{ {
for(pos.y=0; pos.y < sizes.y; ++pos.y) for(pos.y=0; pos.y < sizes.y; ++pos.y)
{ {
const TerrainTile & tile = gs->getMap().getTile(pos); const TerrainTile * tile = gameInfo.getTile(pos);
if(!tile.getTerrain()->isPassable()) if(!tile->getTerrain()->isPassable())
continue; continue;
if(tile.getTerrain()->isWater()) if(tile->getTerrain()->isWater())
{ {
resetTile(pos, ELayer::SAIL, PathfinderUtil::evaluateAccessibility<ELayer::SAIL>(pos, tile, fow, player, gs)); resetTile(pos, ELayer::SAIL, PathfinderUtil::evaluateAccessibility<ELayer::SAIL>(pos, *tile, fow, player, gameInfo));
if(useFlying) if(useFlying)
resetTile(pos, ELayer::AIR, PathfinderUtil::evaluateAccessibility<ELayer::AIR>(pos, tile, fow, player, gs)); resetTile(pos, ELayer::AIR, PathfinderUtil::evaluateAccessibility<ELayer::AIR>(pos, *tile, fow, player, gameInfo));
if(useWaterWalking) if(useWaterWalking)
resetTile(pos, ELayer::WATER, PathfinderUtil::evaluateAccessibility<ELayer::WATER>(pos, tile, fow, player, gs)); resetTile(pos, ELayer::WATER, PathfinderUtil::evaluateAccessibility<ELayer::WATER>(pos, *tile, fow, player, gameInfo));
} }
else else
{ {
resetTile(pos, ELayer::LAND, PathfinderUtil::evaluateAccessibility<ELayer::LAND>(pos, tile, fow, player, gs)); resetTile(pos, ELayer::LAND, PathfinderUtil::evaluateAccessibility<ELayer::LAND>(pos, *tile, fow, player, gameInfo));
if(useFlying) if(useFlying)
resetTile(pos, ELayer::AIR, PathfinderUtil::evaluateAccessibility<ELayer::AIR>(pos, tile, fow, player, gs)); resetTile(pos, ELayer::AIR, PathfinderUtil::evaluateAccessibility<ELayer::AIR>(pos, *tile, fow, player, gameInfo));
} }
} }
} }

View File

@@ -83,7 +83,7 @@ public:
AINodeStorage(const int3 & sizes); AINodeStorage(const int3 & sizes);
~AINodeStorage(); ~AINodeStorage();
void initialize(const PathfinderOptions & options, const CGameState * gs) override; void initialize(const PathfinderOptions & options, const IGameInfoCallback & gameInfo) override;
std::vector<CGPathNode *> getInitialNodes() override; std::vector<CGPathNode *> getInitialNodes() override;

View File

@@ -51,11 +51,11 @@ namespace AIPathfinding
AIPathfinderConfig::~AIPathfinderConfig() = default; AIPathfinderConfig::~AIPathfinderConfig() = default;
CPathfinderHelper * AIPathfinderConfig::getOrCreatePathfinderHelper(const PathNodeInfo & source, const CGameState & gs) CPathfinderHelper * AIPathfinderConfig::getOrCreatePathfinderHelper(const PathNodeInfo & source, const IGameInfoCallback & gameInfo)
{ {
if(!helper) if(!helper)
{ {
helper.reset(new CPathfinderHelper(gs, hero, options)); helper.reset(new CPathfinderHelper(gameInfo, hero, options));
} }
return helper.get(); return helper.get();

View File

@@ -30,6 +30,6 @@ namespace AIPathfinding
~AIPathfinderConfig(); ~AIPathfinderConfig();
CPathfinderHelper * getOrCreatePathfinderHelper(const PathNodeInfo & source, const CGameState & gs) override; CPathfinderHelper * getOrCreatePathfinderHelper(const PathNodeInfo & source, const IGameInfoCallback & gameInfo) override;
}; };
} }

View File

@@ -973,6 +973,13 @@ void CGameInfoCallback::getAllowedSpells(std::vector<SpellID> & out, std::option
} }
} }
bool CGameInfoCallback::checkForVisitableDir(const int3 & src, const int3 & dst) const
{
const CMap & map = gameState().getMap();
const TerrainTile * pom = &map.getTile(dst);
return map.checkForVisitableDir(src, pom, dst);
}
#if SCRIPTING_ENABLED #if SCRIPTING_ENABLED
scripting::Pool * CGameInfoCallback::getGlobalContextPool() const scripting::Pool * CGameInfoCallback::getGlobalContextPool() const
{ {

View File

@@ -75,8 +75,8 @@ public:
const IMarket * getMarket(ObjectInstanceID objid) const; const IMarket * getMarket(ObjectInstanceID objid) const;
//map //map
int3 guardingCreaturePosition (int3 pos) const; int3 guardingCreaturePosition (int3 pos) const override;
std::vector<const CGObjectInstance*> getGuardingCreatures (int3 pos) const; std::vector<const CGObjectInstance*> getGuardingCreatures (int3 pos) const override;
bool isTileGuardedUnchecked(int3 tile) const; bool isTileGuardedUnchecked(int3 tile) const;
const CMapHeader * getMapHeader()const override; const CMapHeader * getMapHeader()const override;
int3 getMapSize() const override; int3 getMapSize() const override;
@@ -86,6 +86,7 @@ public:
void getVisibleTilesInRange(std::unordered_set<int3> &tiles, int3 pos, int radious, int3::EDistanceFormula distanceFormula = int3::DIST_2D) const; void getVisibleTilesInRange(std::unordered_set<int3> &tiles, int3 pos, int radious, int3::EDistanceFormula distanceFormula = int3::DIST_2D) const;
void calculatePaths(const std::shared_ptr<PathfinderConfig> & config) const override; void calculatePaths(const std::shared_ptr<PathfinderConfig> & config) const override;
EDiggingStatus getTileDigStatus(int3 tile, bool verbose = true) const override; EDiggingStatus getTileDigStatus(int3 tile, bool verbose = true) const override;
bool checkForVisitableDir(const int3 & src, const int3 & dst) const override;
//town //town
const CGTownInstance* getTown(ObjectInstanceID objid) const override; const CGTownInstance* getTown(ObjectInstanceID objid) const override;

View File

@@ -141,6 +141,13 @@ public:
/// Calculates pathfinding data into specified pathfinder config /// Calculates pathfinding data into specified pathfinder config
virtual void calculatePaths(const std::shared_ptr<PathfinderConfig> & config) const = 0; virtual void calculatePaths(const std::shared_ptr<PathfinderConfig> & config) const = 0;
/// Returns position of creature that guards specified tile, or invalid tile if there are no guards
virtual int3 guardingCreaturePosition (int3 pos) const = 0;
/// Return true if src tile is visitable from dst tile
virtual bool checkForVisitableDir(const int3 & src, const int3 & dst) const = 0;
/// Returns all wandering monsters that guard specified tile
virtual std::vector<const CGObjectInstance*> getGuardingCreatures (int3 pos) const = 0;
/// Returns all tiles within specified range with specific tile visibility mode /// Returns all tiles within specified range with specific tile visibility mode
virtual void getTilesInRange(std::unordered_set<int3> & tiles, const int3 & pos, int radius, ETileVisibility mode, std::optional<PlayerColor> player = std::optional<PlayerColor>(), int3::EDistanceFormula formula = int3::DIST_2D) const = 0; virtual void getTilesInRange(std::unordered_set<int3> & tiles, const int3 & pos, int radius, ETileVisibility mode, std::optional<PlayerColor> player = std::optional<PlayerColor>(), int3::EDistanceFormula formula = int3::DIST_2D) const = 0;

View File

@@ -1190,11 +1190,7 @@ bool CGameState::isVisibleFor(const CGObjectInstance * obj, PlayerColor player)
return false; return false;
} }
bool CGameState::checkForVisitableDir(const int3 & src, const int3 & dst) const
{
const TerrainTile * pom = &map->getTile(dst);
return map->checkForVisitableDir(src, pom, dst);
}
EVictoryLossCheckResult CGameState::checkForVictoryAndLoss(const PlayerColor & player) const EVictoryLossCheckResult CGameState::checkForVictoryAndLoss(const PlayerColor & player) const
{ {

View File

@@ -100,7 +100,6 @@ public:
BattleField battleGetBattlefieldType(int3 tile, vstd::RNG & randomGenerator); BattleField battleGetBattlefieldType(int3 tile, vstd::RNG & randomGenerator);
PlayerRelations getPlayerRelations(PlayerColor color1, PlayerColor color2) const override; PlayerRelations getPlayerRelations(PlayerColor color1, PlayerColor color2) const override;
bool checkForVisitableDir(const int3 & src, const int3 & dst) const; //check if src tile is visitable from dst tile
void calculatePaths(const std::shared_ptr<PathfinderConfig> & config) const override; void calculatePaths(const std::shared_ptr<PathfinderConfig> & config) const override;
std::vector<const CGObjectInstance*> guardingCreatures (int3 pos) const; std::vector<const CGObjectInstance*> guardingCreatures (int3 pos) const;

View File

@@ -322,10 +322,10 @@ bool CGTeleport::isConnected(const CGObjectInstance * src, const CGObjectInstanc
return isConnected(srcObj, dstObj); return isConnected(srcObj, dstObj);
} }
bool CGTeleport::isExitPassable(const CGameState & gs, const CGHeroInstance * h, const CGObjectInstance * obj) bool CGTeleport::isExitPassable(const IGameInfoCallback & gameInfo, const CGHeroInstance * h, const CGObjectInstance * obj)
{ {
ObjectInstanceID topObjectID = gs.getMap().getTile(obj->visitablePos()).topVisitableObj(); ObjectInstanceID topObjectID = gameInfo.getTile(obj->visitablePos())->topVisitableObj();
const CGObjectInstance * topObject = gs.getObjInstance(topObjectID); const CGObjectInstance * topObject = gameInfo.getObjInstance(topObjectID);
if(topObject->ID == Obj::HERO) if(topObject->ID == Obj::HERO)
{ {
@@ -333,7 +333,7 @@ bool CGTeleport::isExitPassable(const CGameState & gs, const CGHeroInstance * h,
return false; return false;
// Check if it's friendly hero or not // Check if it's friendly hero or not
if(gs.getPlayerRelations(h->tempOwner, topObject->tempOwner) != PlayerRelations::ENEMIES) if(gameInfo.getPlayerRelations(h->tempOwner, topObject->tempOwner) != PlayerRelations::ENEMIES)
{ {
// Exchange between heroes only possible via subterranean gates // Exchange between heroes only possible via subterranean gates
if(!dynamic_cast<const CGSubterraneanGate *>(obj)) if(!dynamic_cast<const CGSubterraneanGate *>(obj))
@@ -343,11 +343,11 @@ bool CGTeleport::isExitPassable(const CGameState & gs, const CGHeroInstance * h,
return true; return true;
} }
std::vector<ObjectInstanceID> CGTeleport::getPassableExits(const CGameState & gs, const CGHeroInstance * h, std::vector<ObjectInstanceID> exits) std::vector<ObjectInstanceID> CGTeleport::getPassableExits(const IGameInfoCallback & gameInfo, const CGHeroInstance * h, std::vector<ObjectInstanceID> exits)
{ {
vstd::erase_if(exits, [&](const ObjectInstanceID & exit) -> bool vstd::erase_if(exits, [&](const ObjectInstanceID & exit) -> bool
{ {
return !isExitPassable(gs, h, gs.getObj(exit)); return !isExitPassable(gameInfo, h, gameInfo.getObj(exit));
}); });
return exits; return exits;
} }

View File

@@ -220,8 +220,8 @@ public:
static bool isConnected(const CGTeleport * src, const CGTeleport * dst); static bool isConnected(const CGTeleport * src, const CGTeleport * dst);
static bool isConnected(const CGObjectInstance * src, const CGObjectInstance * dst); static bool isConnected(const CGObjectInstance * src, const CGObjectInstance * dst);
static void addToChannel(std::map<TeleportChannelID, std::shared_ptr<TeleportChannel> > &channelsList, const CGTeleport * obj); static void addToChannel(std::map<TeleportChannelID, std::shared_ptr<TeleportChannel> > &channelsList, const CGTeleport * obj);
static std::vector<ObjectInstanceID> getPassableExits(const CGameState & gs, const CGHeroInstance * h, std::vector<ObjectInstanceID> exits); static std::vector<ObjectInstanceID> getPassableExits(const IGameInfoCallback & gameInfo, const CGHeroInstance * h, std::vector<ObjectInstanceID> exits);
static bool isExitPassable(const CGameState & gs, const CGHeroInstance * h, const CGObjectInstance * obj); static bool isExitPassable(const IGameInfoCallback & gameInfo, const CGHeroInstance * h, const CGObjectInstance * obj);
template <typename Handler> void serialize(Handler &h) template <typename Handler> void serialize(Handler &h)
{ {

View File

@@ -100,7 +100,7 @@ PathNodeInfo::PathNodeInfo()
{ {
} }
void PathNodeInfo::setNode(const CGameState & gs, CGPathNode * n) void PathNodeInfo::setNode(const IGameInfoCallback & gameInfo, CGPathNode * n)
{ {
node = n; node = n;
guarded = false; guarded = false;
@@ -110,14 +110,14 @@ void PathNodeInfo::setNode(const CGameState & gs, CGPathNode * n)
assert(node->coord.isValid()); assert(node->coord.isValid());
coord = node->coord; coord = node->coord;
tile = gs.getTile(coord); tile = gameInfo.getTile(coord);
nodeObject = nullptr; nodeObject = nullptr;
nodeHero = nullptr; nodeHero = nullptr;
ObjectInstanceID topObjectID = tile->topVisitableObj(); ObjectInstanceID topObjectID = tile->topVisitableObj();
if (topObjectID.hasValue()) if (topObjectID.hasValue())
{ {
nodeObject = gs.getObjInstance(topObjectID); nodeObject = gameInfo.getObjInstance(topObjectID);
if (nodeObject->ID == Obj::HERO) if (nodeObject->ID == Obj::HERO)
{ {
@@ -125,28 +125,28 @@ void PathNodeInfo::setNode(const CGameState & gs, CGPathNode * n)
ObjectInstanceID bottomObjectID = tile->topVisitableObj(true); ObjectInstanceID bottomObjectID = tile->topVisitableObj(true);
if (bottomObjectID.hasValue()) if (bottomObjectID.hasValue())
nodeObject = gs.getObjInstance(bottomObjectID); nodeObject = gameInfo.getObjInstance(bottomObjectID);
} }
} }
} }
} }
void PathNodeInfo::updateInfo(CPathfinderHelper * hlp, const CGameState & gs) void PathNodeInfo::updateInfo(CPathfinderHelper * hlp, const IGameInfoCallback & gameInfo)
{ {
if(gs.guardingCreaturePosition(node->coord).isValid() && !isInitialPosition) if(gameInfo.guardingCreaturePosition(node->coord).isValid() && !isInitialPosition)
{ {
guarded = true; guarded = true;
} }
if(nodeObject) if(nodeObject)
{ {
objectRelations = gs.getPlayerRelations(hlp->owner, nodeObject->tempOwner); objectRelations = gameInfo.getPlayerRelations(hlp->owner, nodeObject->tempOwner);
} }
if(nodeHero) if(nodeHero)
{ {
heroRelations = gs.getPlayerRelations(hlp->owner, nodeHero->tempOwner); heroRelations = gameInfo.getPlayerRelations(hlp->owner, nodeHero->tempOwner);
} }
} }
@@ -164,9 +164,9 @@ CDestinationNodeInfo::CDestinationNodeInfo():
{ {
} }
void CDestinationNodeInfo::setNode(const CGameState & gs, CGPathNode * n) void CDestinationNodeInfo::setNode(const IGameInfoCallback & gameInfo, CGPathNode * n)
{ {
PathNodeInfo::setNode(gs, n); PathNodeInfo::setNode(gameInfo, n);
blocked = false; blocked = false;
action = EPathNodeAction::UNKNOWN; action = EPathNodeAction::UNKNOWN;

View File

@@ -219,9 +219,9 @@ struct DLL_LINKAGE PathNodeInfo
PathNodeInfo(); PathNodeInfo();
virtual void setNode(const CGameState & gs, CGPathNode * n); virtual void setNode(const IGameInfoCallback & gameInfo, CGPathNode * n);
void updateInfo(CPathfinderHelper * hlp, const CGameState & gs); void updateInfo(CPathfinderHelper * hlp, const IGameInfoCallback & gameInfo);
bool isNodeObjectVisitable() const; bool isNodeObjectVisitable() const;
}; };
@@ -237,7 +237,7 @@ struct DLL_LINKAGE CDestinationNodeInfo : public PathNodeInfo
CDestinationNodeInfo(); CDestinationNodeInfo();
void setNode(const CGameState & gs, CGPathNode * n) override; void setNode(const IGameInfoCallback & gameInfo, CGPathNode * n) override;
virtual bool isBetterWay() const; virtual bool isBetterWay() const;
}; };

View File

@@ -15,7 +15,6 @@
#include "PathfindingRules.h" #include "PathfindingRules.h"
#include "TurnInfo.h" #include "TurnInfo.h"
#include "../gameState/CGameState.h"
#include "../IGameSettings.h" #include "../IGameSettings.h"
#include "../CPlayerState.h" #include "../CPlayerState.h"
#include "../TerrainHandler.h" #include "../TerrainHandler.h"
@@ -75,8 +74,8 @@ void CPathfinderHelper::calculateNeighbourTiles(NeighbourTilesVector & result, c
} }
} }
CPathfinder::CPathfinder(const CGameState & gamestate, std::shared_ptr<PathfinderConfig> config): CPathfinder::CPathfinder(const IGameInfoCallback & gameInfo, std::shared_ptr<PathfinderConfig> config):
gamestate(gamestate), gameInfo(gameInfo),
config(std::move(config)) config(std::move(config))
{ {
initializeGraph(); initializeGraph();
@@ -112,14 +111,14 @@ void CPathfinder::calculatePaths()
for(auto * initialNode : initialNodes) for(auto * initialNode : initialNodes)
{ {
if(!gamestate.isInTheMap(initialNode->coord)/* || !gameState().getMap().isInTheMap(dest)*/) //check input if(!gameInfo.isInTheMap(initialNode->coord)/* || !gameInfo.getMap().isInTheMap(dest)*/) //check input
{ {
logGlobal->error("CGameState::calculatePaths: Hero outside the gameState().map? How dare you..."); logGlobal->error("CgameInfo::calculatePaths: Hero outside the gameInfo.map? How dare you...");
throw std::runtime_error("Wrong checksum"); throw std::runtime_error("Wrong checksum");
} }
source.setNode(gamestate, initialNode); source.setNode(gameInfo, initialNode);
auto * hlp = config->getOrCreatePathfinderHelper(source, gamestate); auto * hlp = config->getOrCreatePathfinderHelper(source, gameInfo);
if(hlp->isHeroPatrolLocked()) if(hlp->isHeroPatrolLocked())
continue; continue;
@@ -134,14 +133,14 @@ void CPathfinder::calculatePaths()
counter++; counter++;
auto * node = topAndPop(); auto * node = topAndPop();
source.setNode(gamestate, node); source.setNode(gameInfo, node);
source.node->locked = true; source.node->locked = true;
int movement = source.node->moveRemains; int movement = source.node->moveRemains;
uint8_t turn = source.node->turns; uint8_t turn = source.node->turns;
float cost = source.node->getCost(); float cost = source.node->getCost();
auto * hlp = config->getOrCreatePathfinderHelper(source, gamestate); auto * hlp = config->getOrCreatePathfinderHelper(source, gameInfo);
hlp->updateTurnInfo(turn); hlp->updateTurnInfo(turn);
if(movement == 0) if(movement == 0)
@@ -155,7 +154,7 @@ void CPathfinder::calculatePaths()
} }
source.isInitialPosition = source.nodeHero == hlp->hero; source.isInitialPosition = source.nodeHero == hlp->hero;
source.updateInfo(hlp, gamestate); source.updateInfo(hlp, gameInfo);
//add accessible neighbouring nodes to the queue //add accessible neighbouring nodes to the queue
for(EPathfindingLayer layer = EPathfindingLayer::LAND; layer < EPathfindingLayer::NUM_LAYERS; layer.advance(1)) for(EPathfindingLayer layer = EPathfindingLayer::LAND; layer < EPathfindingLayer::NUM_LAYERS; layer.advance(1))
@@ -170,8 +169,8 @@ void CPathfinder::calculatePaths()
if(neighbour->locked) if(neighbour->locked)
continue; continue;
destination.setNode(gamestate, neighbour); destination.setNode(gameInfo, neighbour);
hlp = config->getOrCreatePathfinderHelper(destination, gamestate); hlp = config->getOrCreatePathfinderHelper(destination, gameInfo);
if(!hlp->isPatrolMovementAllowed(neighbour->coord)) if(!hlp->isPatrolMovementAllowed(neighbour->coord))
continue; continue;
@@ -183,7 +182,7 @@ void CPathfinder::calculatePaths()
destination.turn = turn; destination.turn = turn;
destination.movementLeft = movement; destination.movementLeft = movement;
destination.cost = cost; destination.cost = cost;
destination.updateInfo(hlp, gamestate); destination.updateInfo(hlp, gameInfo);
destination.isGuardianTile = destination.guarded && isDestinationGuardian(); destination.isGuardianTile = destination.guarded && isDestinationGuardian();
for(const auto & rule : config->rules) for(const auto & rule : config->rules)
@@ -201,7 +200,7 @@ void CPathfinder::calculatePaths()
} }
//just add all passable teleport exits //just add all passable teleport exits
hlp = config->getOrCreatePathfinderHelper(source, gamestate); hlp = config->getOrCreatePathfinderHelper(source, gameInfo);
/// For now we disable teleports usage for patrol movement /// For now we disable teleports usage for patrol movement
/// VCAI not aware about patrol and may stuck while attempt to use teleport /// VCAI not aware about patrol and may stuck while attempt to use teleport
@@ -221,7 +220,7 @@ void CPathfinder::calculatePaths()
if(teleportNode->accessible == EPathAccessibility::BLOCKED) if(teleportNode->accessible == EPathAccessibility::BLOCKED)
continue; continue;
destination.setNode(gamestate, teleportNode); destination.setNode(gameInfo, teleportNode);
destination.turn = turn; destination.turn = turn;
destination.movementLeft = movement; destination.movementLeft = movement;
destination.cost = cost; destination.cost = cost;
@@ -244,20 +243,20 @@ TeleporterTilesVector CPathfinderHelper::getAllowedTeleportChannelExits(const Te
{ {
TeleporterTilesVector allowedExits; TeleporterTilesVector allowedExits;
for(const auto & objId : gameState().getTeleportChannelExits(channelID, hero->tempOwner)) for(const auto & objId : gameInfo.getTeleportChannelExits(channelID, hero->tempOwner))
{ {
const auto * obj = gameState().getObj(objId); const auto * obj = gameInfo.getObj(objId);
if(dynamic_cast<const CGWhirlpool *>(obj)) if(dynamic_cast<const CGWhirlpool *>(obj))
{ {
auto pos = obj->getBlockedPos(); auto pos = obj->getBlockedPos();
for(const auto & p : pos) for(const auto & p : pos)
{ {
ObjectInstanceID topObject = gameState().getMap().getTile(p).topVisitableObj(); ObjectInstanceID topObject = gameInfo.getTile(p)->topVisitableObj();
if(topObject.hasValue() && gameState().getObj(topObject)->ID == obj->ID) if(topObject.hasValue() && gameInfo.getObj(topObject)->ID == obj->ID)
allowedExits.push_back(p); allowedExits.push_back(p);
} }
} }
else if(obj && CGTeleport::isExitPassable(gameState(), hero, obj)) else if(obj && CGTeleport::isExitPassable(gameInfo, hero, obj))
allowedExits.push_back(obj->visitablePos()); allowedExits.push_back(obj->visitablePos());
} }
@@ -268,7 +267,7 @@ TeleporterTilesVector CPathfinderHelper::getCastleGates(const PathNodeInfo & sou
{ {
TeleporterTilesVector allowedExits; TeleporterTilesVector allowedExits;
for(const auto & town : gameState().getPlayerState(hero->tempOwner)->getTowns()) for(const auto & town : gameInfo.getPlayerState(hero->tempOwner)->getTowns())
{ {
if(town->id != source.nodeObject->id && town->getVisitingHero() == nullptr if(town->id != source.nodeObject->id && town->getVisitingHero() == nullptr
&& town->hasBuilt(BuildingSubID::CASTLE_GATE)) && town->hasBuilt(BuildingSubID::CASTLE_GATE))
@@ -391,19 +390,19 @@ EPathNodeAction CPathfinder::getTeleportDestAction() const
bool CPathfinder::isDestinationGuardian() const bool CPathfinder::isDestinationGuardian() const
{ {
return gamestate.guardingCreaturePosition(destination.node->coord) == destination.node->coord; return gameInfo.guardingCreaturePosition(destination.node->coord) == destination.node->coord;
} }
void CPathfinderHelper::initializePatrol() void CPathfinderHelper::initializePatrol()
{ {
auto state = PATROL_NONE; auto state = PATROL_NONE;
if(hero->patrol.patrolling && !gameState().getPlayerState(hero->tempOwner)->human) if(hero->patrol.patrolling && !gameInfo.getPlayerState(hero->tempOwner)->human)
{ {
if(hero->patrol.patrolRadius) if(hero->patrol.patrolRadius)
{ {
state = PATROL_RADIUS; state = PATROL_RADIUS;
gameState().getTilesInRange(patrolTiles, hero->patrol.initialPos, hero->patrol.patrolRadius, ETileVisibility::REVEALED, std::optional<PlayerColor>(), int3::DIST_MANHATTAN); gameInfo.getTilesInRange(patrolTiles, hero->patrol.initialPos, hero->patrol.patrolRadius, ETileVisibility::REVEALED, std::optional<PlayerColor>(), int3::DIST_MANHATTAN);
} }
else else
state = PATROL_LOCKED; state = PATROL_LOCKED;
@@ -415,17 +414,17 @@ void CPathfinderHelper::initializePatrol()
void CPathfinder::initializeGraph() void CPathfinder::initializeGraph()
{ {
INodeStorage * nodeStorage = config->nodeStorage.get(); INodeStorage * nodeStorage = config->nodeStorage.get();
nodeStorage->initialize(config->options, &gamestate); nodeStorage->initialize(config->options, gameInfo);
} }
bool CPathfinderHelper::canMoveBetween(const int3 & a, const int3 & b) const bool CPathfinderHelper::canMoveBetween(const int3 & a, const int3 & b) const
{ {
return gameState().checkForVisitableDir(a, b); return gameInfo.checkForVisitableDir(a, b);
} }
bool CPathfinderHelper::isAllowedTeleportEntrance(const CGTeleport * obj) const bool CPathfinderHelper::isAllowedTeleportEntrance(const CGTeleport * obj) const
{ {
if(!obj || !gameState().isTeleportEntrancePassable(obj, hero->tempOwner)) if(!obj || !gameInfo.isTeleportEntrancePassable(obj, hero->tempOwner))
return false; return false;
const auto * whirlpool = dynamic_cast<const CGWhirlpool *>(obj); const auto * whirlpool = dynamic_cast<const CGWhirlpool *>(obj);
@@ -442,14 +441,14 @@ bool CPathfinderHelper::isAllowedTeleportEntrance(const CGTeleport * obj) const
bool CPathfinderHelper::addTeleportTwoWay(const CGTeleport * obj) const bool CPathfinderHelper::addTeleportTwoWay(const CGTeleport * obj) const
{ {
return options.useTeleportTwoWay && gameState().isTeleportChannelBidirectional(obj->channel, hero->tempOwner); return options.useTeleportTwoWay && gameInfo.isTeleportChannelBidirectional(obj->channel, hero->tempOwner);
} }
bool CPathfinderHelper::addTeleportOneWay(const CGTeleport * obj) const bool CPathfinderHelper::addTeleportOneWay(const CGTeleport * obj) const
{ {
if(options.useTeleportOneWay && gameState().isTeleportChannelUnidirectional(obj->channel, hero->tempOwner)) if(options.useTeleportOneWay && gameInfo.isTeleportChannelUnidirectional(obj->channel, hero->tempOwner))
{ {
auto passableExits = CGTeleport::getPassableExits(gameState(), hero, gameState().getTeleportChannelExits(obj->channel, hero->tempOwner)); auto passableExits = CGTeleport::getPassableExits(gameInfo, hero, gameInfo.getTeleportChannelExits(obj->channel, hero->tempOwner));
if(passableExits.size() == 1) if(passableExits.size() == 1)
return true; return true;
} }
@@ -458,9 +457,9 @@ bool CPathfinderHelper::addTeleportOneWay(const CGTeleport * obj) const
bool CPathfinderHelper::addTeleportOneWayRandom(const CGTeleport * obj) const bool CPathfinderHelper::addTeleportOneWayRandom(const CGTeleport * obj) const
{ {
if(options.useTeleportOneWayRandom && gameState().isTeleportChannelUnidirectional(obj->channel, hero->tempOwner)) if(options.useTeleportOneWayRandom && gameInfo.isTeleportChannelUnidirectional(obj->channel, hero->tempOwner))
{ {
auto passableExits = CGTeleport::getPassableExits(gameState(), hero, gameState().getTeleportChannelExits(obj->channel, hero->tempOwner)); auto passableExits = CGTeleport::getPassableExits(gameInfo, hero, gameInfo.getTeleportChannelExits(obj->channel, hero->tempOwner));
if(passableExits.size() > 1) if(passableExits.size() > 1)
return true; return true;
} }
@@ -495,11 +494,11 @@ bool CPathfinderHelper::passOneTurnLimitCheck(const PathNodeInfo & source) const
int CPathfinderHelper::getGuardiansCount(int3 tile) const int CPathfinderHelper::getGuardiansCount(int3 tile) const
{ {
return gameState().getGuardingCreatures(tile).size(); return gameInfo.getGuardingCreatures(tile).size();
} }
CPathfinderHelper::CPathfinderHelper(const CGameState & gs, const CGHeroInstance * Hero, const PathfinderOptions & Options): CPathfinderHelper::CPathfinderHelper(const IGameInfoCallback & gameInfo, const CGHeroInstance * Hero, const PathfinderOptions & Options):
gs(gs), gameInfo(gameInfo),
turn(-1), turn(-1),
owner(Hero->tempOwner), owner(Hero->tempOwner),
hero(Hero), hero(Hero),
@@ -573,7 +572,6 @@ void CPathfinderHelper::getNeighbours(
const boost::logic::tribool & onLand, const boost::logic::tribool & onLand,
const bool limitCoastSailing) const const bool limitCoastSailing) const
{ {
const CMap * map = &gameState().getMap();
const TerrainType * sourceTerrain = sourceTile.getTerrain(); const TerrainType * sourceTerrain = sourceTile.getTerrain();
static constexpr std::array dirs = { static constexpr std::array dirs = {
@@ -585,11 +583,11 @@ void CPathfinderHelper::getNeighbours(
for(const auto & dir : dirs) for(const auto & dir : dirs)
{ {
const int3 destCoord = srcCoord + dir; const int3 destCoord = srcCoord + dir;
if(!map->isInTheMap(destCoord)) if(!gameInfo.isInTheMap(destCoord))
continue; continue;
const TerrainTile & destTile = map->getTile(destCoord); const TerrainTile * destTile = gameInfo.getTile(destCoord);
const TerrainType * destTerrain = destTile.getTerrain(); const TerrainType * destTerrain = destTile->getTerrain();
if(!destTerrain->isPassable()) if(!destTerrain->isPassable())
continue; continue;
@@ -598,7 +596,7 @@ void CPathfinderHelper::getNeighbours(
{ {
const int3 horizontalNeighbour = srcCoord + int3{dir.x, 0, 0}; const int3 horizontalNeighbour = srcCoord + int3{dir.x, 0, 0};
const int3 verticalNeighbour = srcCoord + int3{0, dir.y, 0}; const int3 verticalNeighbour = srcCoord + int3{0, dir.y, 0};
if(map->getTile(horizontalNeighbour).isLand() || map->getTile(verticalNeighbour).isLand()) if(gameInfo.getTile(horizontalNeighbour)->isLand() || gameInfo.getTile(verticalNeighbour)->isLand())
continue; continue;
} }
@@ -670,7 +668,7 @@ int CPathfinderHelper::getMovementCost(
} }
else if(isAirLayer) else if(isAirLayer)
{ {
int baseCost = gameState().getSettings().getInteger(EGameSettings::HEROES_MOVEMENT_COST_BASE); int baseCost = gameInfo.getSettings().getInteger(EGameSettings::HEROES_MOVEMENT_COST_BASE);
vstd::amin(movementCost, baseCost + ti->getFlyingMovementValue()); vstd::amin(movementCost, baseCost + ti->getFlyingMovementValue());
} }
else if(isWaterLayer && ti->hasWaterWalking()) else if(isWaterLayer && ti->hasWaterWalking())
@@ -716,7 +714,7 @@ ui32 CPathfinderHelper::getTileMovementCost(const TerrainTile & dest, const Terr
//if hero can move without penalty - either all-native army, or creatures like Nomads in army //if hero can move without penalty - either all-native army, or creatures like Nomads in army
if(ti->hasNoTerrainPenalty(from.getTerrainID())) if(ti->hasNoTerrainPenalty(from.getTerrainID()))
{ {
int baseCost = gameState().getSettings().getInteger(EGameSettings::HEROES_MOVEMENT_COST_BASE); int baseCost = gameInfo.getSettings().getInteger(EGameSettings::HEROES_MOVEMENT_COST_BASE);
return std::min(baseCost, costWithPathfinding); return std::min(baseCost, costWithPathfinding);
} }

View File

@@ -32,13 +32,13 @@ public:
friend class CPathfinderHelper; friend class CPathfinderHelper;
CPathfinder( CPathfinder(
const CGameState & _gs, const IGameInfoCallback & gameInfo,
std::shared_ptr<PathfinderConfig> config); std::shared_ptr<PathfinderConfig> config);
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:
const CGameState & gamestate; const IGameInfoCallback & gameInfo;
using ELayer = EPathfindingLayer; using ELayer = EPathfindingLayer;
@@ -68,7 +68,7 @@ class DLL_LINKAGE CPathfinderHelper
/// returns base movement cost for movement between specific tiles. Does not accounts for diagonal movement or last tile exception /// returns base movement cost for movement between specific tiles. Does not accounts for diagonal movement or last tile exception
ui32 getTileMovementCost(const TerrainTile & dest, const TerrainTile & from, const TurnInfo * ti) const; ui32 getTileMovementCost(const TerrainTile & dest, const TerrainTile & from, const TurnInfo * ti) const;
const CGameState & gs; const IGameInfoCallback & gameInfo;
public: public:
enum EPatrolState enum EPatrolState
{ {
@@ -87,9 +87,8 @@ public:
bool canCastWaterWalk; bool canCastWaterWalk;
bool whirlpoolProtection; bool whirlpoolProtection;
CPathfinderHelper(const CGameState & gs, const CGHeroInstance * Hero, const PathfinderOptions & Options); CPathfinderHelper(const IGameInfoCallback & gameInfo, const CGHeroInstance * Hero, const PathfinderOptions & Options);
virtual ~CPathfinderHelper(); virtual ~CPathfinderHelper();
const CGameState & gameState() const { return gs; }
void initializePatrol(); void initializePatrol();
bool isHeroPatrolLocked() const; bool isHeroPatrolLocked() const;
bool canMoveFromNode(const PathNodeInfo & source) const; bool canMoveFromNode(const PathNodeInfo & source) const;

View File

@@ -45,7 +45,7 @@ public:
virtual void commit(CDestinationNodeInfo & destination, const PathNodeInfo & source) = 0; virtual void commit(CDestinationNodeInfo & destination, const PathNodeInfo & source) = 0;
virtual void initialize(const PathfinderOptions & options, const CGameState * gs) = 0; virtual void initialize(const PathfinderOptions & options, const IGameInfoCallback & gameInfo) = 0;
}; };
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@@ -21,14 +21,14 @@
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
void NodeStorage::initialize(const PathfinderOptions & options, const CGameState * gs) void NodeStorage::initialize(const PathfinderOptions & options, const IGameInfoCallback & gameInfo)
{ {
//TODO: fix this code duplication with AINodeStorage::initialize, problem is to keep `resetTile` inline //TODO: fix this code duplication with AINodeStorage::initialize, problem is to keep `resetTile` inline
int3 pos; int3 pos;
const PlayerColor player = out.hero->tempOwner; const PlayerColor player = out.hero->tempOwner;
const int3 sizes = gs->getMapSize(); const int3 sizes = gameInfo.getMapSize();
const auto & fow = static_cast<const IGameInfoCallback *>(gs)->getPlayerTeam(player)->fogOfWarMap; const auto & fow = gameInfo.getPlayerTeam(player)->fogOfWarMap;
//make 200% sure that these are loop invariants (also a bit shorter code), let compiler do the rest(loop unswitching) //make 200% sure that these are loop invariants (also a bit shorter code), let compiler do the rest(loop unswitching)
const bool useFlying = options.useFlying; const bool useFlying = options.useFlying;
@@ -40,20 +40,20 @@ void NodeStorage::initialize(const PathfinderOptions & options, const CGameState
{ {
for(pos.y=0; pos.y < sizes.y; ++pos.y) for(pos.y=0; pos.y < sizes.y; ++pos.y)
{ {
const TerrainTile & tile = gs->getMap().getTile(pos); const TerrainTile * tile = gameInfo.getTile(pos);
if(tile.isWater()) if(tile->isWater())
{ {
resetTile(pos, ELayer::SAIL, PathfinderUtil::evaluateAccessibility<ELayer::SAIL>(pos, tile, fow, player, gs)); resetTile(pos, ELayer::SAIL, PathfinderUtil::evaluateAccessibility<ELayer::SAIL>(pos, *tile, fow, player, gameInfo));
if(useFlying) if(useFlying)
resetTile(pos, ELayer::AIR, PathfinderUtil::evaluateAccessibility<ELayer::AIR>(pos, tile, fow, player, gs)); resetTile(pos, ELayer::AIR, PathfinderUtil::evaluateAccessibility<ELayer::AIR>(pos, *tile, fow, player, gameInfo));
if(useWaterWalking) if(useWaterWalking)
resetTile(pos, ELayer::WATER, PathfinderUtil::evaluateAccessibility<ELayer::WATER>(pos, tile, fow, player, gs)); resetTile(pos, ELayer::WATER, PathfinderUtil::evaluateAccessibility<ELayer::WATER>(pos, *tile, fow, player, gameInfo));
} }
if(tile.isLand()) if(tile->isLand())
{ {
resetTile(pos, ELayer::LAND, PathfinderUtil::evaluateAccessibility<ELayer::LAND>(pos, tile, fow, player, gs)); resetTile(pos, ELayer::LAND, PathfinderUtil::evaluateAccessibility<ELayer::LAND>(pos, *tile, fow, player, gameInfo));
if(useFlying) if(useFlying)
resetTile(pos, ELayer::AIR, PathfinderUtil::evaluateAccessibility<ELayer::AIR>(pos, tile, fow, player, gs)); resetTile(pos, ELayer::AIR, PathfinderUtil::evaluateAccessibility<ELayer::AIR>(pos, *tile, fow, player, gameInfo));
} }
} }
} }

View File

@@ -31,7 +31,7 @@ public:
return out.getNode(coord, layer); return out.getNode(coord, layer);
} }
void initialize(const PathfinderOptions & options, const CGameState * gs) override; void initialize(const PathfinderOptions & options, const IGameInfoCallback & gameInfo) override;
virtual ~NodeStorage() = default; virtual ~NodeStorage() = default;
std::vector<CGPathNode *> getInitialNodes() override; std::vector<CGPathNode *> getInitialNodes() override;

View File

@@ -65,10 +65,10 @@ SingleHeroPathfinderConfig::SingleHeroPathfinderConfig(CPathsInfo & out, const I
{ {
} }
CPathfinderHelper * SingleHeroPathfinderConfig::getOrCreatePathfinderHelper(const PathNodeInfo & source, const CGameState & gs) CPathfinderHelper * SingleHeroPathfinderConfig::getOrCreatePathfinderHelper(const PathNodeInfo & source, const IGameInfoCallback & gameInfo)
{ {
if (!pathfinderHelper) if (!pathfinderHelper)
pathfinderHelper = std::make_unique<CPathfinderHelper>(gs, hero, options); pathfinderHelper = std::make_unique<CPathfinderHelper>(gameInfo, hero, options);
return pathfinderHelper.get(); return pathfinderHelper.get();
} }

View File

@@ -101,7 +101,7 @@ public:
std::vector<std::shared_ptr<IPathfindingRule>> rules); std::vector<std::shared_ptr<IPathfindingRule>> rules);
virtual ~PathfinderConfig() = default; virtual ~PathfinderConfig() = default;
virtual CPathfinderHelper * getOrCreatePathfinderHelper(const PathNodeInfo & source, const CGameState & gs) = 0; virtual CPathfinderHelper * getOrCreatePathfinderHelper(const PathNodeInfo & source, const IGameInfoCallback & gameInfo) = 0;
}; };
class DLL_LINKAGE SingleHeroPathfinderConfig : public PathfinderConfig class DLL_LINKAGE SingleHeroPathfinderConfig : public PathfinderConfig
@@ -114,7 +114,7 @@ public:
SingleHeroPathfinderConfig(CPathsInfo & out, const IGameInfoCallback & gs, const CGHeroInstance * hero); SingleHeroPathfinderConfig(CPathsInfo & out, const IGameInfoCallback & gs, const CGHeroInstance * hero);
virtual ~SingleHeroPathfinderConfig(); virtual ~SingleHeroPathfinderConfig();
CPathfinderHelper * getOrCreatePathfinderHelper(const PathNodeInfo & source, const CGameState & gs) override; CPathfinderHelper * getOrCreatePathfinderHelper(const PathNodeInfo & source, const IGameInfoCallback & gameInfo) override;
static std::vector<std::shared_ptr<IPathfindingRule>> buildRuleSet(); static std::vector<std::shared_ptr<IPathfindingRule>> buildRuleSet();
}; };

View File

@@ -23,7 +23,7 @@ namespace PathfinderUtil
using ELayer = EPathfindingLayer; using ELayer = EPathfindingLayer;
template<EPathfindingLayer::Type layer> template<EPathfindingLayer::Type layer>
EPathAccessibility evaluateAccessibility(const int3 & pos, const TerrainTile & tinfo, const FoW & fow, const PlayerColor player, const CGameState * gs) EPathAccessibility evaluateAccessibility(const int3 & pos, const TerrainTile & tinfo, const FoW & fow, const PlayerColor player, const IGameInfoCallback & gameInfo)
{ {
if(!fow[pos.z][pos.x][pos.y]) if(!fow[pos.z][pos.x][pos.y])
return EPathAccessibility::BLOCKED; return EPathAccessibility::BLOCKED;
@@ -34,8 +34,8 @@ namespace PathfinderUtil
case ELayer::SAIL: case ELayer::SAIL:
if(tinfo.visitable()) if(tinfo.visitable())
{ {
auto frontVisitable = gs->getObjInstance(tinfo.visitableObjects.front()); auto frontVisitable = gameInfo.getObjInstance(tinfo.visitableObjects.front());
auto backVisitable = gs->getObjInstance(tinfo.visitableObjects.front()); auto backVisitable = gameInfo.getObjInstance(tinfo.visitableObjects.front());
if(frontVisitable->ID == Obj::SANCTUARY && backVisitable->ID == Obj::HERO && backVisitable->getOwner() != player) //non-owned hero stands on Sanctuary if(frontVisitable->ID == Obj::SANCTUARY && backVisitable->ID == Obj::HERO && backVisitable->getOwner() != player) //non-owned hero stands on Sanctuary
{ {
@@ -48,7 +48,7 @@ namespace PathfinderUtil
for(const auto objID : tinfo.visitableObjects) for(const auto objID : tinfo.visitableObjects)
{ {
auto obj = gs->getObjInstance(objID); auto obj = gameInfo.getObjInstance(objID);
if(obj->isBlockedVisitable()) if(obj->isBlockedVisitable())
hasBlockedVisitable = true; hasBlockedVisitable = true;
@@ -68,7 +68,7 @@ namespace PathfinderUtil
{ {
return EPathAccessibility::BLOCKED; return EPathAccessibility::BLOCKED;
} }
else if(gs->guardingCreaturePosition(pos).isValid()) else if(gameInfo.guardingCreaturePosition(pos).isValid())
{ {
// Monster close by; blocked visit for battle // Monster close by; blocked visit for battle
return EPathAccessibility::GUARDED; return EPathAccessibility::GUARDED;

View File

@@ -75,6 +75,10 @@ public:
MOCK_CONST_METHOD2(isTeleportChannelBidirectional, bool(TeleportChannelID id, PlayerColor player)); MOCK_CONST_METHOD2(isTeleportChannelBidirectional, bool(TeleportChannelID id, PlayerColor player));
MOCK_CONST_METHOD2(isTeleportChannelUnidirectional, bool(TeleportChannelID id, PlayerColor player)); MOCK_CONST_METHOD2(isTeleportChannelUnidirectional, bool(TeleportChannelID id, PlayerColor player));
MOCK_CONST_METHOD2(isTeleportEntrancePassable, bool(const CGTeleport * obj, PlayerColor player)); MOCK_CONST_METHOD2(isTeleportEntrancePassable, bool(const CGTeleport * obj, PlayerColor player));
MOCK_CONST_METHOD1(guardingCreaturePosition, int3(int3 pos));
MOCK_CONST_METHOD2(checkForVisitableDir, bool(const int3 & src, const int3 & dst));
MOCK_CONST_METHOD1(getGuardingCreatures, std::vector<const CGObjectInstance *>(int3 pos));
MOCK_METHOD2(pickAllowedArtsSet, void(std::vector<ArtifactID> & out, vstd::RNG & rand)); MOCK_METHOD2(pickAllowedArtsSet, void(std::vector<ArtifactID> & out, vstd::RNG & rand));
#if SCRIPTING_ENABLED #if SCRIPTING_ENABLED