|
@@ -15,7 +15,6 @@
|
|
|
#include "PathfindingRules.h"
|
|
|
#include "TurnInfo.h"
|
|
|
|
|
|
-#include "../gameState/CGameState.h"
|
|
|
#include "../IGameSettings.h"
|
|
|
#include "../CPlayerState.h"
|
|
|
#include "../TerrainHandler.h"
|
|
@@ -75,8 +74,8 @@ void CPathfinderHelper::calculateNeighbourTiles(NeighbourTilesVector & result, c
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-CPathfinder::CPathfinder(const CGameState & gamestate, std::shared_ptr<PathfinderConfig> config):
|
|
|
- gamestate(gamestate),
|
|
|
+CPathfinder::CPathfinder(const IGameInfoCallback & gameInfo, std::shared_ptr<PathfinderConfig> config):
|
|
|
+ gameInfo(gameInfo),
|
|
|
config(std::move(config))
|
|
|
{
|
|
|
initializeGraph();
|
|
@@ -112,14 +111,14 @@ void CPathfinder::calculatePaths()
|
|
|
|
|
|
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");
|
|
|
}
|
|
|
|
|
|
- source.setNode(gamestate, initialNode);
|
|
|
- auto * hlp = config->getOrCreatePathfinderHelper(source, gamestate);
|
|
|
+ source.setNode(gameInfo, initialNode);
|
|
|
+ auto * hlp = config->getOrCreatePathfinderHelper(source, gameInfo);
|
|
|
|
|
|
if(hlp->isHeroPatrolLocked())
|
|
|
continue;
|
|
@@ -134,14 +133,14 @@ void CPathfinder::calculatePaths()
|
|
|
counter++;
|
|
|
auto * node = topAndPop();
|
|
|
|
|
|
- source.setNode(gamestate, node);
|
|
|
+ source.setNode(gameInfo, node);
|
|
|
source.node->locked = true;
|
|
|
|
|
|
int movement = source.node->moveRemains;
|
|
|
uint8_t turn = source.node->turns;
|
|
|
float cost = source.node->getCost();
|
|
|
|
|
|
- auto * hlp = config->getOrCreatePathfinderHelper(source, gamestate);
|
|
|
+ auto * hlp = config->getOrCreatePathfinderHelper(source, gameInfo);
|
|
|
|
|
|
hlp->updateTurnInfo(turn);
|
|
|
if(movement == 0)
|
|
@@ -155,7 +154,7 @@ void CPathfinder::calculatePaths()
|
|
|
}
|
|
|
|
|
|
source.isInitialPosition = source.nodeHero == hlp->hero;
|
|
|
- source.updateInfo(hlp, gamestate);
|
|
|
+ source.updateInfo(hlp, gameInfo);
|
|
|
|
|
|
//add accessible neighbouring nodes to the queue
|
|
|
for(EPathfindingLayer layer = EPathfindingLayer::LAND; layer < EPathfindingLayer::NUM_LAYERS; layer.advance(1))
|
|
@@ -170,8 +169,8 @@ void CPathfinder::calculatePaths()
|
|
|
if(neighbour->locked)
|
|
|
continue;
|
|
|
|
|
|
- destination.setNode(gamestate, neighbour);
|
|
|
- hlp = config->getOrCreatePathfinderHelper(destination, gamestate);
|
|
|
+ destination.setNode(gameInfo, neighbour);
|
|
|
+ hlp = config->getOrCreatePathfinderHelper(destination, gameInfo);
|
|
|
|
|
|
if(!hlp->isPatrolMovementAllowed(neighbour->coord))
|
|
|
continue;
|
|
@@ -183,7 +182,7 @@ void CPathfinder::calculatePaths()
|
|
|
destination.turn = turn;
|
|
|
destination.movementLeft = movement;
|
|
|
destination.cost = cost;
|
|
|
- destination.updateInfo(hlp, gamestate);
|
|
|
+ destination.updateInfo(hlp, gameInfo);
|
|
|
destination.isGuardianTile = destination.guarded && isDestinationGuardian();
|
|
|
|
|
|
for(const auto & rule : config->rules)
|
|
@@ -201,7 +200,7 @@ void CPathfinder::calculatePaths()
|
|
|
}
|
|
|
|
|
|
//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
|
|
|
/// 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)
|
|
|
continue;
|
|
|
|
|
|
- destination.setNode(gamestate, teleportNode);
|
|
|
+ destination.setNode(gameInfo, teleportNode);
|
|
|
destination.turn = turn;
|
|
|
destination.movementLeft = movement;
|
|
|
destination.cost = cost;
|
|
@@ -244,20 +243,20 @@ TeleporterTilesVector CPathfinderHelper::getAllowedTeleportChannelExits(const Te
|
|
|
{
|
|
|
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))
|
|
|
{
|
|
|
auto pos = obj->getBlockedPos();
|
|
|
for(const auto & p : pos)
|
|
|
{
|
|
|
- ObjectInstanceID topObject = gameState().getMap().getTile(p).topVisitableObj();
|
|
|
- if(topObject.hasValue() && gameState().getObj(topObject)->ID == obj->ID)
|
|
|
+ ObjectInstanceID topObject = gameInfo.getTile(p)->topVisitableObj();
|
|
|
+ if(topObject.hasValue() && gameInfo.getObj(topObject)->ID == obj->ID)
|
|
|
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());
|
|
|
}
|
|
|
|
|
@@ -268,7 +267,7 @@ TeleporterTilesVector CPathfinderHelper::getCastleGates(const PathNodeInfo & sou
|
|
|
{
|
|
|
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
|
|
|
&& town->hasBuilt(BuildingSubID::CASTLE_GATE))
|
|
@@ -391,19 +390,19 @@ EPathNodeAction CPathfinder::getTeleportDestAction() 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()
|
|
|
{
|
|
|
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)
|
|
|
{
|
|
|
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
|
|
|
state = PATROL_LOCKED;
|
|
@@ -415,17 +414,17 @@ void CPathfinderHelper::initializePatrol()
|
|
|
void CPathfinder::initializeGraph()
|
|
|
{
|
|
|
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
|
|
|
{
|
|
|
- return gameState().checkForVisitableDir(a, b);
|
|
|
+ return gameInfo.checkForVisitableDir(a, b);
|
|
|
}
|
|
|
|
|
|
bool CPathfinderHelper::isAllowedTeleportEntrance(const CGTeleport * obj) const
|
|
|
{
|
|
|
- if(!obj || !gameState().isTeleportEntrancePassable(obj, hero->tempOwner))
|
|
|
+ if(!obj || !gameInfo.isTeleportEntrancePassable(obj, hero->tempOwner))
|
|
|
return false;
|
|
|
|
|
|
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
|
|
|
{
|
|
|
- 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
|
|
|
{
|
|
|
- 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)
|
|
|
return true;
|
|
|
}
|
|
@@ -458,9 +457,9 @@ bool CPathfinderHelper::addTeleportOneWay(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)
|
|
|
return true;
|
|
|
}
|
|
@@ -495,11 +494,11 @@ bool CPathfinderHelper::passOneTurnLimitCheck(const PathNodeInfo & source) 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):
|
|
|
- gs(gs),
|
|
|
+CPathfinderHelper::CPathfinderHelper(const IGameInfoCallback & gameInfo, const CGHeroInstance * Hero, const PathfinderOptions & Options):
|
|
|
+ gameInfo(gameInfo),
|
|
|
turn(-1),
|
|
|
owner(Hero->tempOwner),
|
|
|
hero(Hero),
|
|
@@ -573,7 +572,6 @@ void CPathfinderHelper::getNeighbours(
|
|
|
const boost::logic::tribool & onLand,
|
|
|
const bool limitCoastSailing) const
|
|
|
{
|
|
|
- const CMap * map = &gameState().getMap();
|
|
|
const TerrainType * sourceTerrain = sourceTile.getTerrain();
|
|
|
|
|
|
static constexpr std::array dirs = {
|
|
@@ -585,11 +583,11 @@ void CPathfinderHelper::getNeighbours(
|
|
|
for(const auto & dir : dirs)
|
|
|
{
|
|
|
const int3 destCoord = srcCoord + dir;
|
|
|
- if(!map->isInTheMap(destCoord))
|
|
|
+ if(!gameInfo.isInTheMap(destCoord))
|
|
|
continue;
|
|
|
|
|
|
- const TerrainTile & destTile = map->getTile(destCoord);
|
|
|
- const TerrainType * destTerrain = destTile.getTerrain();
|
|
|
+ const TerrainTile * destTile = gameInfo.getTile(destCoord);
|
|
|
+ const TerrainType * destTerrain = destTile->getTerrain();
|
|
|
if(!destTerrain->isPassable())
|
|
|
continue;
|
|
|
|
|
@@ -598,7 +596,7 @@ void CPathfinderHelper::getNeighbours(
|
|
|
{
|
|
|
const int3 horizontalNeighbour = srcCoord + int3{dir.x, 0, 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;
|
|
|
}
|
|
|
|
|
@@ -670,7 +668,7 @@ int CPathfinderHelper::getMovementCost(
|
|
|
}
|
|
|
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());
|
|
|
}
|
|
|
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(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);
|
|
|
}
|
|
|
|