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:
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user