2023-06-21 12:46:09 +02:00
/*
* CPathfinder . h , part of VCMI engine
*
* Authors : listed in file AUTHORS in main folder
*
* License : GNU General Public License v2 .0 or later
* Full text of license available in license . txt file , in main folder
*
*/
# pragma once
# include "CGPathNode.h"
# include "../IGameCallback.h"
# include "../bonuses/BonusEnum.h"
2024-07-03 20:06:56 +02:00
# include <boost/container/static_vector.hpp>
# include <boost/container/small_vector.hpp>
2023-06-21 12:46:09 +02:00
VCMI_LIB_NAMESPACE_BEGIN
class CGWhirlpool ;
struct TurnInfo ;
struct PathfinderOptions ;
2024-07-03 20:06:56 +02:00
// Optimized storage - tile can have 0-8 neighbour tiles
// static_vector uses fixed, preallocated storage (capacity) and dynamic size
// this avoid dynamic allocations on huge number of neighbour list queries
using NeighbourTilesVector = boost : : container : : static_vector < int3 , 8 > ;
// Optimized storage to minimize dynamic allocations - most of teleporters have only one exit, but some may have more (premade maps, castle gates)
using TeleporterTilesVector = boost : : container : : small_vector < int3 , 4 > ;
2023-09-19 22:17:25 +02:00
class DLL_LINKAGE CPathfinder
2023-06-21 12:46:09 +02:00
{
public :
friend class CPathfinderHelper ;
CPathfinder (
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 ;
using ELayer = EPathfindingLayer ;
std : : shared_ptr < PathfinderConfig > config ;
boost : : heap : : fibonacci_heap < CGPathNode * , boost : : heap : : compare < NodeComparer < CGPathNode > > > pq ;
PathNodeInfo source ; //current (source) path node -> we took it from the queue
CDestinationNodeInfo destination ; //destination node -> it's a neighbour of source that we consider
bool isLayerTransitionPossible ( ) const ;
2023-06-21 14:38:57 +02:00
EPathNodeAction getTeleportDestAction ( ) const ;
2023-06-21 12:46:09 +02:00
bool isDestinationGuardian ( ) const ;
void initializeGraph ( ) ;
STRONG_INLINE
void push ( CGPathNode * node ) ;
STRONG_INLINE
CGPathNode * topAndPop ( ) ;
} ;
class DLL_LINKAGE CPathfinderHelper : private CGameInfoCallback
{
public :
enum EPatrolState
{
PATROL_NONE = 0 ,
PATROL_LOCKED = 1 ,
PATROL_RADIUS
} patrolState ;
std : : unordered_set < int3 > patrolTiles ;
int turn ;
PlayerColor owner ;
const CGHeroInstance * hero ;
std : : vector < TurnInfo * > turnsInfo ;
const PathfinderOptions & options ;
2023-09-16 11:33:02 +02:00
bool canCastFly ;
bool canCastWaterWalk ;
2024-07-20 17:36:07 +02:00
bool whirlpoolProtection ;
2023-06-21 12:46:09 +02:00
CPathfinderHelper ( CGameState * gs , const CGHeroInstance * Hero , const PathfinderOptions & Options ) ;
virtual ~ CPathfinderHelper ( ) ;
void initializePatrol ( ) ;
bool isHeroPatrolLocked ( ) const ;
2023-11-27 23:19:19 +02:00
bool canMoveFromNode ( const PathNodeInfo & source ) const ;
2023-06-21 12:46:09 +02:00
bool isPatrolMovementAllowed ( const int3 & dst ) const ;
void updateTurnInfo ( const int turn = 0 ) ;
bool isLayerAvailable ( const EPathfindingLayer & layer ) const ;
const TurnInfo * getTurnInfo ( ) const ;
2023-10-05 15:13:52 +02:00
bool hasBonusOfType ( BonusType type ) const ;
2023-06-21 12:46:09 +02:00
int getMaxMovePoints ( const EPathfindingLayer & layer ) const ;
2024-07-03 20:06:56 +02:00
TeleporterTilesVector getCastleGates ( const PathNodeInfo & source ) const ;
2023-06-21 12:46:09 +02:00
bool isAllowedTeleportEntrance ( const CGTeleport * obj ) const ;
2024-07-03 20:06:56 +02:00
TeleporterTilesVector getAllowedTeleportChannelExits ( const TeleportChannelID & channelID ) const ;
2023-06-21 12:46:09 +02:00
bool addTeleportTwoWay ( const CGTeleport * obj ) const ;
bool addTeleportOneWay ( const CGTeleport * obj ) const ;
bool addTeleportOneWayRandom ( const CGTeleport * obj ) const ;
bool addTeleportWhirlpool ( const CGWhirlpool * obj ) const ;
bool canMoveBetween ( const int3 & a , const int3 & b ) const ; //checks only for visitable objects that may make moving between tiles impossible, not other conditions (like tiles itself accessibility)
2024-07-03 20:06:56 +02:00
void calculateNeighbourTiles ( NeighbourTilesVector & result , const PathNodeInfo & source ) const ;
TeleporterTilesVector getTeleportExits ( const PathNodeInfo & source ) const ;
2023-06-21 12:46:09 +02:00
void getNeighbours (
const TerrainTile & srcTile ,
const int3 & srcCoord ,
2024-07-03 20:06:56 +02:00
NeighbourTilesVector & vec ,
2023-06-21 12:46:09 +02:00
const boost : : logic : : tribool & onLand ,
const bool limitCoastSailing ) const ;
int getMovementCost (
const int3 & src ,
const int3 & dst ,
const TerrainTile * ct ,
const TerrainTile * dt ,
const int remainingMovePoints = - 1 ,
const bool checkLast = true ,
boost : : logic : : tribool isDstSailLayer = boost : : logic : : indeterminate ,
boost : : logic : : tribool isDstWaterLayer = boost : : logic : : indeterminate ) const ;
int getMovementCost (
const PathNodeInfo & src ,
const PathNodeInfo & dst ,
const int remainingMovePoints = - 1 ,
const bool checkLast = true ) const ;
int movementPointsAfterEmbark ( int movement , int basicCost , bool disembark ) const ;
bool passOneTurnLimitCheck ( const PathNodeInfo & source ) const ;
2023-09-16 11:29:35 +02:00
int getGuardiansCount ( int3 tile ) const ;
2023-06-21 12:46:09 +02:00
} ;
VCMI_LIB_NAMESPACE_END