21constexpr int NUMBER_OR_WATER_REGIONS_LOOKAHEAD = 4;
22constexpr int MAX_SHIP_PF_NODES = (NUMBER_OR_WATER_REGIONS_LOOKAHEAD + 1) * WATER_REGION_NUMBER_OF_TILES * 4;
29 typedef typename Types::Tpf
Tpf;
30 typedef typename Types::TrackFollower TrackFollower;
31 typedef typename Types::NodeList::Item
Node;
32 typedef typename Node::Key
Key;
37 StationID dest_station;
39 bool has_intermediate_dest =
false;
44 void SetDestination(
const Ship *v)
51 this->dest_station = StationID::Invalid();
59 this->has_intermediate_dest =
true;
61 this->intermediate_dest_region_patch = water_region_patch;
68 return *
static_cast<Tpf*
>(
this);
81 if (this->has_intermediate_dest) {
95 const TileIndex destination_tile = this->has_intermediate_dest ? this->intermediate_dest_tile : this->dest_tile;
102 n.estimate = n.cost +
OctileDistanceCost(n.GetTile(), n.GetTrackdir(), destination_tile);
103 assert(n.estimate >= n.parent->estimate);
109template <
class Types>
112 typedef typename Types::Tpf
Tpf;
113 typedef typename Types::TrackFollower TrackFollower;
114 typedef typename Types::NodeList::Item
Node;
115 typedef typename Node::Key
Key;
121 return *
static_cast<Tpf*
>(
this);
124 std::vector<WaterRegionDesc> water_region_corridor;
130 TrackFollower follower{
Yapf().GetVehicle()};
131 if (follower.Follow(old_node.key.tile, old_node.key.td)) {
132 if (this->water_region_corridor.empty()
133 || std::ranges::find(this->water_region_corridor,
GetWaterRegionInfo(follower.new_tile)) != this->water_region_corridor.end()) {
134 Yapf().AddMultipleNodes(&old_node, follower);
145 this->water_region_corridor.clear();
146 for (
const WaterRegionPatchDesc &path_entry : path) this->water_region_corridor.push_back(path_entry);
174 TrackFollower follower{v};
175 if (follower.Follow(tile, dir)) {
179 if (dirs.
None()) dirs = follower.new_td_bits;
195 for (
int i = 0; i < path_length; ++i) {
198 path_cache.push_back(tile_dir.second);
204 std::reverse(std::begin(path_cache), std::end(path_cache));
206 const Trackdir result = path_cache.back().trackdir;
207 path_cache.pop_back();
212 bool &path_found, ShipPathCache &path_cache,
Trackdir &best_origin_dir)
214 const std::vector<WaterRegionPatchDesc> high_level_path =
YapfShipFindWaterRegionPath(v, tile, NUMBER_OR_WATER_REGIONS_LOOKAHEAD + 1);
215 if (high_level_path.empty()) {
224 for (
int attempt = 0; attempt < 2; ++attempt) {
228 pf.SetOrigin(v->
tile, forward_dirs | reverse_dirs);
229 pf.SetDestination(v);
230 const bool is_intermediate_destination =
static_cast<int>(high_level_path.size()) >= NUMBER_OR_WATER_REGIONS_LOOKAHEAD + 1;
231 if (is_intermediate_destination) pf.SetIntermediateDestination(high_level_path.back());
235 if (attempt > 0) pf.RestrictSearch(high_level_path);
238 path_found = pf.FindPath(v);
239 Node *node = pf.GetBestNode();
240 if (attempt == 0 && !path_found)
continue;
250 const WaterRegionPatchDesc start_water_patch = high_level_path.front();
251 while (node->parent) {
254 const bool node_water_patch_on_high_level_path = std::ranges::find(high_level_path, node_water_patch) != high_level_path.end();
255 const bool add_full_path = !is_intermediate_destination && node_water_patch != end_water_patch;
259 if (add_full_path || !node_water_patch_on_high_level_path || node_water_patch == start_water_patch) {
260 path_cache.push_back(node->GetTrackdir());
266 assert(node->GetTile() == v->
tile);
269 best_origin_dir = node->GetTrackdir();
280 const Trackdir result = path_cache.back().trackdir;
281 path_cache.pop_back();
284 if (start_water_patch == end_water_patch) path_cache.clear();
301 bool path_found =
false;
302 ShipPathCache dummy_cache;
305 if (trackdir ==
nullptr) {
310 (void)ChooseShipTrack(v, v->
tile, forward_dirs, reverse_dirs, path_found, dummy_cache, best_origin_dir);
311 return path_found && best_origin_dir == reverse_dir;
316 (void)ChooseShipTrack(v, v->
tile, {}, reverse_dirs, path_found, dummy_cache, best_origin_dir);
324template <
class Types>
327 typedef typename Types::Tpf
Tpf;
328 typedef typename Types::TrackFollower TrackFollower;
329 typedef typename Types::NodeList::Item
Node;
330 typedef typename Node::Key
Key;
335 return *
static_cast<Tpf*
>(
this);
346 return Yapf().PfGetSettings().ship_curve90_penalty;
349 return Yapf().PfGetSettings().ship_curve45_penalty;
362 const bool odd_x =
TileX(tile) & 1;
363 const bool odd_y =
TileY(tile) & 1;
377 c += this->CurveCost(n.parent->GetTrackdir(), n.GetTrackdir());
383 return v->type == VehicleType::Ship && !v->vehstatus.Test(VehState::Hidden);
397 if (speed_frac > 0) c +=
YAPF_TILE_LENGTH * (1 + follower->tiles_skipped) * speed_frac / (256 - speed_frac);
407 n.cost = n.parent->cost + c;
421 typedef CShipNodeList NodeList;
422 typedef Ship VehicleType;
433struct CYapfShip :
CYapfT<CYapfShip_TypesT<CYapfShip>> {
441 const Trackdir td_ret = CYapfShip::ChooseShipTrack(v, tile, origin_dirs, {}, path_found, path_cache, best_origin_dir);
uint Count() const
Count the number of set bits.
constexpr bool None() const
Test if none of the values are set.
constexpr Timpl & Reset()
Reset all bits.
constexpr bool Any(const Timpl &other) const
Test if any of the given values are set.
std::optional< Tvalue_type > GetNthSetBit(uint n) const
Get the value of the Nth set bit.
CYapfBaseT - A-star type path finder base class.
int max_search_nodes
maximum number of nodes we are allowed to visit before we give up
Cost Provider module of YAPF for ships.
Node::Key Key
key to hash tables.
static bool IsPreferredShipDirection(TileIndex tile, Trackdir td)
Whether the provided direction is a preferred direction for a given tile.
Types::NodeList::Item Node
this will be our node type.
bool PfCalcCost(Node &n, const TrackFollower *follower)
Called by YAPF to calculate the cost from the origin to the given node.
Tpf & Yapf()
Access the inherited path finder.
Types::Tpf Tpf
the pathfinder class (derived from THIS class).
Types::Tpf Tpf
the pathfinder class (derived from THIS class).
bool PfCalcEstimate(Node &n)
Called by YAPF to calculate cost estimate.
Types::NodeList::Item Node
this will be our node type.
bool PfDetectDestination(Node &n)
Called by YAPF to detect if node ends in the desired destination.
Node::Key Key
key to hash tables.
Tpf & Yapf()
Access the inherited path finder.
bool PfDetectDestinationTile(TileIndex tile, Trackdir td)
Called by YAPF to detect if node ends in the desired destination.
Node Follower module of YAPF for ships.
static std::pair< TileIndex, Trackdir > GetRandomFollowUpTileTrackdir(const Ship *v, TileIndex tile, Trackdir dir)
Returns a random tile/trackdir that can be reached from the current tile/trackdir,...
char TransportTypeChar() const
Return debug report character to identify the transportation type.
void PfFollowNode(Node &old_node)
Called by YAPF to move from the given node to the next tile.
static Trackdir GetRandomTrackdir(TrackdirBits trackdirs)
Returns a random trackdir out of a set of trackdirs.
Node::Key Key
key to hash tables.
static Trackdir CreateRandomPath(const Ship *v, ShipPathCache &path_cache, int path_length)
Creates a random path, avoids 90 degree turns.
Types::NodeList::Item Node
this will be our node type.
Types::Tpf Tpf
the pathfinder class (derived from THIS class).
void RestrictSearch(const std::vector< WaterRegionPatchDesc > &path)
Restricts the search by creating corridor or water regions through which the ship is allowed to trave...
static bool CheckShipReverse(const Ship *v, Trackdir *trackdir)
Check whether a ship should reverse to reach its destination.
Tpf & Yapf()
Access the inherited path finder.
YAPF origin provider base class - used when origin is one tile / multiple trackdirs.
CYapfSegmentCostCacheNoneT - the formal only yapf cost cache provider that implements PfNodeCacheFetc...
YAPF template that uses Ttypes template argument to determine all YAPF components (base classes) from...
Iterate over all vehicles on a tile.
DiagDirection ReverseDiagDir(DiagDirection d)
Returns the reverse direction of the given DiagDirection.
DiagDirection
Enumeration for diagonal directions.
TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, RoadTramType sub_mode, DiagDirection side)
Returns information about trackdirs and signal states.
static uint TileY(TileIndex tile)
Get the Y component of a tile.
static uint TileX(TileIndex tile)
Get the X component of a tile.
TileIndex CalcClosestStationTile(StationID station, TileIndex tile, StationType station_type)
Calculates the tile of given station that is closest to a given tile for this we assume the station i...
static const int YAPF_TILE_CORNER_LENGTH
Length (penalty) of a corner with YAPF.
static const int YAPF_TILE_LENGTH
Length (penalty) of one tile with YAPF.
uint32_t RandomRange(uint32_t limit, const std::source_location location=std::source_location::current())
Pick a random number between 0 and limit - 1, inclusive.
A number of safeguards to prevent using unsafe methods.
bool IsShipDestinationTile(TileIndex tile, StationID station)
Test if a tile is a docking tile for the given station.
WaterClass GetEffectiveWaterClass(TileIndex tile)
Determine the effective WaterClass for a ship travelling on a tile.
static Track ChooseShipTrack(Ship *v, TileIndex tile, TrackBits tracks)
Runs the pathfinder to choose a track to continue along.
Definition of base types and functions in a cross-platform compatible way.
Config struct of YAPF for ships.
CYapfShip_TypesT< Tpf_ > Types
Shortcut for this struct type.
CYapfDestinationTileWaterT< Types > PfDestination
Destination/distance provider.
CYapfSegmentCostCacheNoneT< Types > PfCache
Segment cost cache provider.
CYapfOriginTileT< Types > PfOrigin
Origin provider.
CFollowTrackWater TrackFollower
Track follower helper class.
CYapfFollowShipT< Types > PfFollow
Node follower.
CYapfCostShipT< Types > PfCost
Cost provider.
CYapfBaseT< Types > PfBase
Pathfinder components (modules).
DestinationID GetDestination() const
Gets the destination of this order.
bool IsType(OrderType type) const
Check whether this order is of the given type.
Information about a ship vehicle.
uint8_t ocean_speed_frac
Fraction of maximum speed for ocean tiles.
uint ApplyWaterClassSpeedFrac(uint raw_speed, bool is_ocean) const
Apply ocean/canal speed fraction to a velocity.
uint16_t max_speed
Maximum speed (1 unit = 1/3.2 mph = 0.5 km-ish/h).
uint8_t canal_speed_frac
Fraction of maximum speed for canal/river tiles.
All ships have this type.
TrackBits state
The "track" the ship is following.
Trackdir GetVehicleTrackdir() const override
Returns the Trackdir on which the vehicle is currently located.
TrackdirBits trackdirs
Trackdirs present on the tile.
Direction direction
facing
Vehicle * first
NOSAVE: pointer to the first vehicle in the chain.
Order current_order
The current order (+ status, like: loading).
TileIndex tile
Current tile index.
TileIndex dest_tile
Heading for this tile.
Describes a single interconnected patch of water within a particular water region.
static bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > > TileIndex
The index/ID of a Tile.
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
static constexpr uint TILE_HEIGHT
Height of a height level in world coordinate AND in pixels in ZOOM_BASE.
Track TrackdirToTrack(Trackdir trackdir)
Returns the Track that a given Trackdir represents.
DiagDirection VehicleExitDir(Direction direction, TrackBits track)
Determine the side in which the vehicle will leave the tile.
Trackdir NextTrackdir(Trackdir trackdir)
Maps a trackdir to the trackdir that you will end up on if you go straight ahead.
Trackdir ReverseTrackdir(Trackdir trackdir)
Maps a trackdir to the reverse trackdir.
bool IsValidTrackdir(Trackdir trackdir)
Checks if a Trackdir is valid for non-road vehicles.
TrackdirBits TrackdirCrossesTrackdirs(Trackdir trackdir)
Maps a trackdir to all trackdirs that make 90 deg turns with it.
TrackdirBits DiagdirReachesTrackdirs(DiagDirection diagdir)
Returns all trackdirs that can be reached when entering a tile from a given (diagonal) direction.
bool IsDiagonalTrackdir(Trackdir trackdir)
Checks if a given Trackdir is diagonal.
TrackdirBits TrackdirToTrackdirBits(Trackdir trackdir)
Maps a Trackdir to the corresponding TrackdirBits value.
EnumBitSet< Trackdir, uint16_t > TrackdirBits
Bitset of Trackdir elements.
static constexpr TrackdirBits INVALID_TRACKDIR_BIT
Marker for an invalid TrackdirBits value.
Trackdir
Enumeration for tracks and directions.
@ Right_N
Right track and direction to north.
@ X_NE
X-axis and direction to north-east.
@ Left_S
Left track and direction to south.
@ Lower_E
Lower track and direction to east.
@ X_SW
X-axis and direction to south-west.
@ Invalid
Flag for an invalid trackdir.
@ Y_SE
Y-axis and direction to south-east.
@ Y_NW
Y-axis and direction to north-west.
@ Upper_W
Upper track and direction to west.
Track
These are used to specify a single track.
@ Invalid
Flag for an invalid track.
@ TRANSPORT_WATER
Transport over water.
Functions related to vehicles.
bool IsDockingTile(Tile t)
Checks whether the tile is marked as a dockling tile.
@ Middle
Middle part of a lock.
bool IsLock(Tile t)
Is there a lock on a given water tile?
LockPart GetLockPart(Tile t)
Get the part of a lock.
WaterRegionDesc GetWaterRegionInfo(TileIndex tile)
Returns basic water region information for the provided tile.
WaterRegionPatchDesc GetWaterRegionPatchInfo(TileIndex tile)
Returns basic water region patch information for the provided tile.
TileIndex GetWaterRegionCenterTile(const WaterRegionDesc &water_region)
Returns the center tile of a particular water region.
Handles dividing the water in the map into regions to assist pathfinding.
Base includes/functions for YAPF.
int OctileDistanceCost(TileIndex start_tile, Trackdir start_td, TileIndex destination_tile)
Calculates the octile distance cost between a starting tile / trackdir and a destination tile.
Node tailored for ship pathfinding.
constexpr int MAX_SHIP_PF_NODES
4 possible exit dirs per tile.
bool YapfShipCheckReverse(const Ship *v, Trackdir *trackdir)
Returns true if it is better to reverse the ship before leaving depot using YAPF.
constexpr int SHIP_LOST_PATH_LENGTH
The length of the (aimless) path assigned when a ship is lost.
Track YapfShipChooseTrack(const Ship *v, TileIndex tile, bool &path_found, ShipPathCache &path_cache)
Finds the best path for given ship using YAPF.
std::vector< WaterRegionPatchDesc > YapfShipFindWaterRegionPath(const Ship *v, TileIndex start_tile, int max_returned_path_length)
Finds a path at the water region level.
Implementation of YAPF for water regions, which are used for finding intermediate ship destinations.