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

Pathfinder now uses CGameState directly instead of inheriting callback

This commit is contained in:
Ivan Savenko
2025-05-15 19:53:29 +03:00
parent e79c8b9fe1
commit fe2f5f9217
11 changed files with 36 additions and 37 deletions

View File

@@ -56,7 +56,7 @@ namespace AIPathfinding
AIPathfinderConfig::~AIPathfinderConfig() = default;
CPathfinderHelper * AIPathfinderConfig::getOrCreatePathfinderHelper(const PathNodeInfo & source, CGameState & gs)
CPathfinderHelper * AIPathfinderConfig::getOrCreatePathfinderHelper(const PathNodeInfo & source, const CGameState & gs)
{
auto hero = aiNodeStorage->getHero(source.node);
auto & helper = pathfindingHelpers[hero];

View File

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

View File

@@ -51,7 +51,7 @@ namespace AIPathfinding
AIPathfinderConfig::~AIPathfinderConfig() = default;
CPathfinderHelper * AIPathfinderConfig::getOrCreatePathfinderHelper(const PathNodeInfo & source, CGameState & gs)
CPathfinderHelper * AIPathfinderConfig::getOrCreatePathfinderHelper(const PathNodeInfo & source, const CGameState & gs)
{
if(!helper)
{

View File

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

View File

@@ -1089,7 +1089,7 @@ void CGameState::apply(CPackForClient & pack)
void CGameState::calculatePaths(const std::shared_ptr<PathfinderConfig> & config) const
{
CPathfinder pathfinder(*const_cast<CGameState*>(this), config);
CPathfinder pathfinder(*this, config);
pathfinder.calculatePaths();
}

View File

@@ -100,7 +100,7 @@ PathNodeInfo::PathNodeInfo()
{
}
void PathNodeInfo::setNode(CGameState & gs, CGPathNode * n)
void PathNodeInfo::setNode(const CGameState & gs, CGPathNode * n)
{
node = n;
guarded = false;
@@ -132,7 +132,7 @@ void PathNodeInfo::setNode(CGameState & gs, CGPathNode * n)
}
void PathNodeInfo::updateInfo(CPathfinderHelper * hlp, CGameState & gs)
void PathNodeInfo::updateInfo(CPathfinderHelper * hlp, const CGameState & gs)
{
if(gs.guardingCreaturePosition(node->coord).isValid() && !isInitialPosition)
{
@@ -164,7 +164,7 @@ CDestinationNodeInfo::CDestinationNodeInfo():
{
}
void CDestinationNodeInfo::setNode(CGameState & gs, CGPathNode * n)
void CDestinationNodeInfo::setNode(const CGameState & gs, CGPathNode * n)
{
PathNodeInfo::setNode(gs, n);

View File

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

View File

@@ -75,7 +75,7 @@ void CPathfinderHelper::calculateNeighbourTiles(NeighbourTilesVector & result, c
}
}
CPathfinder::CPathfinder(CGameState & gamestate, std::shared_ptr<PathfinderConfig> config):
CPathfinder::CPathfinder(const CGameState & gamestate, std::shared_ptr<PathfinderConfig> config):
gamestate(gamestate),
config(std::move(config))
{
@@ -244,16 +244,16 @@ TeleporterTilesVector CPathfinderHelper::getAllowedTeleportChannelExits(const Te
{
TeleporterTilesVector allowedExits;
for(const auto & objId : getTeleportChannelExits(channelID, hero->tempOwner))
for(const auto & objId : gameState().getTeleportChannelExits(channelID, hero->tempOwner))
{
const auto * obj = getObj(objId);
const auto * obj = gameState().getObj(objId);
if(dynamic_cast<const CGWhirlpool *>(obj))
{
auto pos = obj->getBlockedPos();
for(const auto & p : pos)
{
ObjectInstanceID topObject = gameState().getMap().getTile(p).topVisitableObj();
if(topObject.hasValue() && getObj(topObject)->ID == obj->ID)
if(topObject.hasValue() && gameState().getObj(topObject)->ID == obj->ID)
allowedExits.push_back(p);
}
}
@@ -268,7 +268,7 @@ TeleporterTilesVector CPathfinderHelper::getCastleGates(const PathNodeInfo & sou
{
TeleporterTilesVector allowedExits;
for(const auto & town : getPlayerState(hero->tempOwner)->getTowns())
for(const auto & town : gameState().getPlayerState(hero->tempOwner)->getTowns())
{
if(town->id != source.nodeObject->id && town->getVisitingHero() == nullptr
&& town->hasBuilt(BuildingSubID::CASTLE_GATE))
@@ -398,7 +398,7 @@ void CPathfinderHelper::initializePatrol()
{
auto state = PATROL_NONE;
if(hero->patrol.patrolling && !getPlayerState(hero->tempOwner)->human)
if(hero->patrol.patrolling && !gameState().getPlayerState(hero->tempOwner)->human)
{
if(hero->patrol.patrolRadius)
{
@@ -425,7 +425,7 @@ bool CPathfinderHelper::canMoveBetween(const int3 & a, const int3 & b) const
bool CPathfinderHelper::isAllowedTeleportEntrance(const CGTeleport * obj) const
{
if(!obj || !isTeleportEntrancePassable(obj, hero->tempOwner))
if(!obj || !gameState().isTeleportEntrancePassable(obj, hero->tempOwner))
return false;
const auto * whirlpool = dynamic_cast<const CGWhirlpool *>(obj);
@@ -442,14 +442,14 @@ bool CPathfinderHelper::isAllowedTeleportEntrance(const CGTeleport * obj) const
bool CPathfinderHelper::addTeleportTwoWay(const CGTeleport * obj) const
{
return options.useTeleportTwoWay && isTeleportChannelBidirectional(obj->channel, hero->tempOwner);
return options.useTeleportTwoWay && gameState().isTeleportChannelBidirectional(obj->channel, hero->tempOwner);
}
bool CPathfinderHelper::addTeleportOneWay(const CGTeleport * obj) const
{
if(options.useTeleportOneWay && isTeleportChannelUnidirectional(obj->channel, hero->tempOwner))
if(options.useTeleportOneWay && gameState().isTeleportChannelUnidirectional(obj->channel, hero->tempOwner))
{
auto passableExits = CGTeleport::getPassableExits(gameState(), hero, getTeleportChannelExits(obj->channel, hero->tempOwner));
auto passableExits = CGTeleport::getPassableExits(gameState(), hero, gameState().getTeleportChannelExits(obj->channel, hero->tempOwner));
if(passableExits.size() == 1)
return true;
}
@@ -458,9 +458,9 @@ bool CPathfinderHelper::addTeleportOneWay(const CGTeleport * obj) const
bool CPathfinderHelper::addTeleportOneWayRandom(const CGTeleport * obj) const
{
if(options.useTeleportOneWayRandom && isTeleportChannelUnidirectional(obj->channel, hero->tempOwner))
if(options.useTeleportOneWayRandom && gameState().isTeleportChannelUnidirectional(obj->channel, hero->tempOwner))
{
auto passableExits = CGTeleport::getPassableExits(gameState(), hero, getTeleportChannelExits(obj->channel, hero->tempOwner));
auto passableExits = CGTeleport::getPassableExits(gameState(), hero, gameState().getTeleportChannelExits(obj->channel, hero->tempOwner));
if(passableExits.size() > 1)
return true;
}
@@ -495,10 +495,10 @@ bool CPathfinderHelper::passOneTurnLimitCheck(const PathNodeInfo & source) const
int CPathfinderHelper::getGuardiansCount(int3 tile) const
{
return getGuardingCreatures(tile).size();
return gameState().getGuardingCreatures(tile).size();
}
CPathfinderHelper::CPathfinderHelper(CGameState & gs, const CGHeroInstance * Hero, const PathfinderOptions & Options):
CPathfinderHelper::CPathfinderHelper(const CGameState & gs, const CGHeroInstance * Hero, const PathfinderOptions & Options):
gs(gs),
turn(-1),
owner(Hero->tempOwner),
@@ -670,7 +670,7 @@ int CPathfinderHelper::getMovementCost(
}
else if(isAirLayer)
{
int baseCost = getSettings().getInteger(EGameSettings::HEROES_MOVEMENT_COST_BASE);
int baseCost = gameState().getSettings().getInteger(EGameSettings::HEROES_MOVEMENT_COST_BASE);
vstd::amin(movementCost, baseCost + ti->getFlyingMovementValue());
}
else if(isWaterLayer && ti->hasWaterWalking())
@@ -716,7 +716,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(ti->hasNoTerrainPenalty(from.getTerrainID()))
{
int baseCost = getSettings().getInteger(EGameSettings::HEROES_MOVEMENT_COST_BASE);
int baseCost = gameState().getSettings().getInteger(EGameSettings::HEROES_MOVEMENT_COST_BASE);
return std::min(baseCost, costWithPathfinding);
}

View File

@@ -32,13 +32,13 @@ public:
friend class CPathfinderHelper;
CPathfinder(
CGameState & _gs,
const CGameState & _gs,
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
private:
CGameState & gamestate;
const CGameState & gamestate;
using ELayer = EPathfindingLayer;
@@ -63,12 +63,12 @@ private:
CGPathNode * topAndPop();
};
class DLL_LINKAGE CPathfinderHelper : private CGameInfoCallback
class DLL_LINKAGE CPathfinderHelper
{
/// 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;
CGameState & gs;
const CGameState & gs;
public:
enum EPatrolState
{
@@ -87,10 +87,9 @@ public:
bool canCastWaterWalk;
bool whirlpoolProtection;
CPathfinderHelper(CGameState & gs, const CGHeroInstance * Hero, const PathfinderOptions & Options);
CPathfinderHelper(const CGameState & gs, const CGHeroInstance * Hero, const PathfinderOptions & Options);
virtual ~CPathfinderHelper();
CGameState & gameState() final { return gs; }
const CGameState & gameState() const final { return gs; }
const CGameState & gameState() const { return gs; }
void initializePatrol();
bool isHeroPatrolLocked() const;
bool canMoveFromNode(const PathNodeInfo & source) const;

View File

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

View File

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