22template <
typename Tpf>
void DumpState(Tpf &pf1, Tpf &pf2)
29 assert(f1.has_value());
30 assert(f2.has_value());
38 typedef typename Types::Tpf
Tpf;
39 typedef typename Types::TrackFollower TrackFollower;
40 typedef typename Types::NodeList::Item
Node;
46 return *
static_cast<Tpf *
>(
this);
62 this->res_dest_tile = tile;
63 this->res_dest_td = td;
106 this->res_fail_tile = tile;
107 this->res_fail_td = td;
112 this->res_fail_tile = tile;
113 this->res_fail_td = td;
119 this->signals_set_to_red.emplace_back(tile, rev_td);
131 return tile != this->res_dest_tile || td != this->res_dest_td;
149 }
else if (tile != this->res_fail_tile || td != this->res_fail_td) {
152 return (tile != this->res_dest_tile || td != this->res_dest_td) && (tile != this->res_fail_tile || td != this->res_fail_td);
164 this->res_dest_node = node;
165 this->res_dest_tile = tile;
166 this->res_dest_td = td;
175 assert(node->parent !=
nullptr);
178 if (node->parent->num_signals_passed >= 2)
return;
180 if (!node->IterateTiles(
Yapf().GetVehicle(),
Yapf(), *
this, &CYapfReserveTrack<Types>::FindSafePositionProc)) {
181 this->res_dest_node = node;
194 this->origin_tile = origin;
196 if (target !=
nullptr) {
197 target->
tile = this->res_dest_tile;
198 target->
trackdir = this->res_dest_td;
199 target->
okay =
false;
205 this->signals_set_to_red.clear();
206 for (
Node *node = this->res_dest_node; node->parent !=
nullptr; node = node->parent) {
210 Node *fail_node = this->res_dest_node;
211 TileIndex stop_tile = this->res_fail_tile;
214 this->res_fail_tile = fail_node == node ? stop_tile :
INVALID_TILE;
216 }
while (fail_node != node && (fail_node = fail_node->parent) !=
nullptr);
219 for (
auto [sig_tile, td] : this->signals_set_to_red) {
227 if (target !=
nullptr) target->
okay =
true;
229 if (
Yapf().CanUseGlobalCache(*this->res_dest_node)) {
237template <
class Types>
240 typedef typename Types::Tpf
Tpf;
241 typedef typename Types::TrackFollower TrackFollower;
242 typedef typename Types::NodeList::Item
Node;
243 typedef typename Node::Key
Key;
249 return *
static_cast<Tpf *
>(
this);
256 TrackFollower follower{
Yapf().GetVehicle()};
257 if (follower.Follow(old_node.GetLastTile(), old_node.GetLastTrackdir())) {
258 Yapf().AddMultipleNodes(&old_node, follower);
280 if (max_penalty != 0) pf1.DisableCache(
true);
281 FindDepotData result1 = pf1.FindNearestDepotTwoWay(v, t1, td1, t2, td2, max_penalty, reverse_penalty);
283 if (_debug_desync_level >= 2) {
285 pf2.DisableCache(
true);
286 FindDepotData result2 = pf2.FindNearestDepotTwoWay(v, t1, td1, t2, td2, max_penalty, reverse_penalty);
288 Debug(desync, 2,
"warning: FindNearestDepotTwoWay cache mismatch: {} vs {}",
301 Yapf().SetOrigin(t1, td1, t2, td2, reverse_penalty);
302 Yapf().SetTreatFirstRedTwoWaySignalAsEOL(
true);
303 Yapf().SetDestination(v);
304 Yapf().SetMaxCost(max_penalty);
307 if (!
Yapf().FindPath(v))
return FindDepotData();
314 while (node->parent !=
nullptr) {
320 return FindDepotData(n->GetLastTile(), n->cost, node->cost != 0);
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;
336 return *
static_cast<Tpf *
>(
this);
343 TrackFollower follower{
Yapf().GetVehicle(),
Yapf().GetCompatibleRailTypes()};
344 if (follower.Follow(old_node.GetLastTile(), old_node.GetLastTrackdir()) && follower.MaskReservedTracks()) {
345 Yapf().AddMultipleNodes(&old_node, follower);
360 if (_debug_desync_level < 2) {
361 result1 = pf1.FindNearestSafeTile(v, t1, td, override_railtype,
false);
363 bool result2 = pf1.FindNearestSafeTile(v, t1, td, override_railtype,
true);
365 pf2.DisableCache(
true);
366 result1 = pf2.FindNearestSafeTile(v, t1, td, override_railtype,
false);
367 if (result1 != result2) {
368 Debug(desync, 2,
"warning: FindSafeTile cache mismatch: {} vs {}", result2 ?
"T" :
"F", result1 ?
"T" :
"F");
376 bool FindNearestSafeTile(
const Train *v,
TileIndex t1,
Trackdir td,
bool override_railtype,
bool dont_reserve)
379 Yapf().SetOrigin(t1, td);
380 Yapf().SetTreatFirstRedTwoWaySignalAsEOL(
true);
381 Yapf().SetDestination(v, override_railtype);
383 if (!
Yapf().FindPath(v))
return false;
390 Node *prev =
nullptr;
391 while (node->parent !=
nullptr) {
398 return dont_reserve || this->
TryReservePath(
nullptr, node->GetLastTile());
402template <
class Types>
405 typedef typename Types::Tpf
Tpf;
406 typedef typename Types::TrackFollower TrackFollower;
407 typedef typename Types::NodeList::Item
Node;
408 typedef typename Node::Key
Key;
414 return *
static_cast<Tpf *
>(
this);
421 TrackFollower follower{
Yapf().GetVehicle()};
422 if (follower.Follow(old_node.GetLastTile(), old_node.GetLastTrackdir())) {
423 Yapf().AddMultipleNodes(&old_node, follower);
439 if (_debug_desync_level < 2) {
440 result1 = pf1.ChooseRailTrack(v, tile, enterdir, tracks, path_found, reserve_track, target, dest);
442 result1 = pf1.ChooseRailTrack(v, tile, enterdir, tracks, path_found,
false,
nullptr,
nullptr);
444 pf2.DisableCache(
true);
445 Trackdir result2 = pf2.ChooseRailTrack(v, tile, enterdir, tracks, path_found, reserve_track, target, dest);
446 if (result1 != result2) {
447 Debug(desync, 2,
"warning: ChooseRailTrack cache mismatch: {} vs {}", result1, result2);
463 Yapf().SetTreatFirstRedTwoWaySignalAsEOL(
true);
464 Yapf().SetDestination(v);
467 path_found =
Yapf().FindPath(v);
472 if (node !=
nullptr) {
478 Node *prev =
nullptr;
479 while (node->parent !=
nullptr) {
491 Node &best_next_node = *prev;
492 next_trackdir = best_next_node.GetTrackdir();
494 if (reserve_track && path_found) {
495 if (dest !=
nullptr) *dest =
Yapf().GetBestNode()->GetLastTile();
501 path_found |=
Yapf().stopped_on_first_two_way_signal;
502 return next_trackdir;
508 bool result1 = pf1.CheckReverseTrain(v, t1, td1, t2, td2, reverse_penalty);
510 if (_debug_desync_level >= 2) {
512 pf2.DisableCache(
true);
513 bool result2 = pf2.CheckReverseTrain(v, t1, td1, t2, td2, reverse_penalty);
514 if (result1 != result2) {
515 Debug(desync, 2,
"warning: CheckReverseTrain cache mismatch: {} vs {}", result1 ?
"T" :
"F", result2 ?
"T" :
"F");
527 Yapf().SetOrigin(t1, td1, t2, td2, reverse_penalty);
528 Yapf().SetTreatFirstRedTwoWaySignalAsEOL(
false);
529 Yapf().SetDestination(v);
532 if (!
Yapf().FindPath(v))
return false;
537 while (node->parent !=
nullptr) {
542 bool reversed = (node->cost != 0);
547template <
class Tpf_,
class Ttrack_follower,
template <
class Types>
class TdestinationT,
template <
class Types>
class TfollowT>
552 typedef Ttrack_follower TrackFollower;
553 typedef CRailNodeList NodeList;
554 typedef Train VehicleType;
556 typedef TfollowT<Types> PfFollow;
558 typedef TdestinationT<Types> PfDestination;
563template <
typename Types>
565 typedef typename Types::NodeList::Item Node;
578 bool intermediate_on_branch =
false;
580 if (n == this->best_intermediate_node) intermediate_on_branch =
true;
583 if (intermediate_on_branch) this->best_intermediate_node = n;
587struct CYapfRail :
CYapfRailBase<CYapfRail_TypesT<CYapfRail , CFollowTrackRail , CYapfDestinationTileOrStationRailT, CYapfFollowRailT>> {};
588struct CYapfRailNo90 :
CYapfRailBase<CYapfRail_TypesT<CYapfRailNo90 , CFollowTrackRailNo90, CYapfDestinationTileOrStationRailT, CYapfFollowRailT>> {};
600 ? CYapfRailNo90::stChooseRailTrack(v, tile, enterdir, tracks, path_found, reserve_track, target, dest)
601 : CYapfRail::stChooseRailTrack(v, tile, enterdir, tracks, path_found, reserve_track, target, dest);
619 int reverse_penalty = 0;
627 reverse_penalty += DRIVING_BACKWARDS_PENALTY;
661 if (reverse_penalty == 0) reverse_penalty = 1;
664 ? CYapfRailNo90::stCheckReverseTrain(v, tile, td, tile_rev, td_rev, reverse_penalty)
665 : CYapfRail::stCheckReverseTrain(v, tile, td, tile_rev, td_rev, reverse_penalty);
686 ? CYapfAnySafeTileRailNo90::stFindNearestSafeTile(v, tile, td, override_railtype)
687 : CYapfAnySafeTileRail::stFindNearestSafeTile(v, tile, td, override_railtype);
695 CSegmentCostCacheBase::NotifyTrackLayoutChange(tile, track);
@ DrivingBackwards
Vehicle is driving backwards.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
CYapfBaseT - A-star type path finder base class.
Types::Tpf Tpf
the pathfinder class (derived from THIS class)
Tpf & Yapf()
Access the inherited path finder.
void PfFollowNode(Node &old_node)
Called by YAPF to move from the given node to the next tile.
char TransportTypeChar() const
Return debug report character to identify the transportation type.
Types::NodeList::Item Node
this will be our node type
Node::Key Key
key to hash tables
char TransportTypeChar() const
Return debug report character to identify the transportation type.
Node::Key Key
key to hash tables
Types::Tpf Tpf
the pathfinder class (derived from THIS class)
void PfFollowNode(Node &old_node)
Called by YAPF to move from the given node to the next tile.
Types::NodeList::Item Node
this will be our node type
Tpf & Yapf()
Access the inherited path finder.
Node::Key Key
key to hash tables
Tpf & Yapf()
Access the inherited path finder.
char TransportTypeChar() const
Return debug report character to identify the transportation type.
Types::Tpf Tpf
the pathfinder class (derived from THIS class)
Types::NodeList::Item Node
this will be our node type
void PfFollowNode(Node &old_node)
Called by YAPF to move from the given node to the next tile.
YAPF origin provider base class - used when there are two tile/trackdir origins.
void SetReservationTarget(Node *node, TileIndex tile, Trackdir td)
Set the target to where the reservation should be extended.
Types::NodeList::Item Node
this will be our node type
TileIndex res_fail_tile
The tile where the reservation failed.
bool UnreserveSingleTrack(TileIndex tile, Trackdir td)
Unreserve a single track/platform.
bool ReserveRailStationPlatform(TileIndex &tile, DiagDirection dir)
Reserve a railway platform.
bool ReserveSingleTrack(TileIndex tile, Trackdir td)
Reserve a single track/platform.
std::vector< std::pair< TileIndex, Trackdir > > signals_set_to_red
List of signals turned red during a path reservation.
Trackdir res_fail_td
The trackdir where the reservation failed.
Node * res_dest_node
The reservation target node.
TileIndex origin_tile
Tile our reservation will originate from.
TileIndex res_dest_tile
The reservation target tile.
bool TryReservePath(PBSTileInfo *target, TileIndex origin)
Try to reserve the path till the reservation target.
Tpf & Yapf()
Access the inherited path finder.
void FindSafePositionOnNode(Node *node)
Check the node for a possible reservation target.
Trackdir res_dest_td
The reservation target trackdir.
Types::Tpf Tpf
the pathfinder class (derived from THIS class)
CYapfSegmentCostCacheGlobalT - the yapf cost cache provider that adds the segment cost caching functi...
YAPF template that uses Ttypes template argument to determine all YAPF components (base classes) from...
static std::optional< FileHandle > Open(const std::string &filename, std::string_view mode)
Open an RAII file handle if possible.
#define Debug(category, level, format_string,...)
Output a line of debugging information.
DiagDirection
Enumeration for diagonal directions.
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset, int tile_height_override)
Mark a tile given by its index dirty for repaint.
uint DistanceManhattan(TileIndex t0, TileIndex t1)
Gets the Manhattan distance between the two given tiles.
static TileIndex TileVirtXY(uint x, uint y)
Get a tile from the virtual XY-coordinate.
constexpr TileIndex TileAdd(TileIndex tile, TileIndexDiff offset)
Adds a given offset to a tile.
TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
int32_t TileIndexDiff
An offset value between two tiles.
void TriggerStationRandomisation(BaseStation *st, TileIndex trigger_tile, StationRandomTrigger trigger, CargoType cargo_type)
Trigger station randomisation.
Header file for NewGRF stations.
static const int YAPF_INFINITE_PENALTY
This penalty is the equivalent of "infinite", which means that paths that get this penalty will be ch...
static const int YAPF_TILE_LENGTH
Length (penalty) of one tile with YAPF.
bool TryReserveRailTrack(TileIndex tile, Track t, bool trigger_stations)
Try to reserve a specific track on a tile.
bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bool forbid_90deg)
Check if a safe position is free.
void UnreserveRailTrack(TileIndex tile, Track t)
Lift the reservation of a specific track on a tile.
PBSTileInfo FollowTrainReservation(const Train *consist, Vehicle **train_on_res)
Follow a train reservation to the last tile.
bool IsSafeWaitingPosition(const Train *v, TileIndex tile, Trackdir trackdir, bool include_line_end, bool forbid_90deg)
Determine whether a certain track on a tile is a safe position to end a path.
void SetSignalStateByTrackdir(Tile tile, Trackdir trackdir, SignalState state)
Sets the state of the signal along the given trackdir.
bool HasPbsSignalOnTrackdir(Tile tile, Trackdir td)
Is a pbs signal present along the trackdir?
SignalState GetSignalStateByTrackdir(Tile tile, Trackdir trackdir)
Gets the state of the signal along the given trackdir.
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
@ None
Trains cannot flip anywhere and must back up if the track ends.
@ SIGNAL_STATE_RED
The signal is red.
@ SIGNAL_STATE_GREEN
The signal is green.
bool IsRailWaypointTile(Tile t)
Is this tile a station tile and a rail waypoint?
bool IsCompatibleTrainStationTile(Tile test_tile, Tile station_tile)
Check if a tile is a valid continuation to a railstation tile.
bool IsRailStationTile(Tile t)
Is this tile a station tile and a rail station?
void SetRailStationReservation(Tile t, bool b)
Set the reservation state of the rail station.
bool HasStationReservation(Tile t)
Get the reservation state of the rail station.
@ PathReservation
Trigger platform when train reserves path.
@ PathReservation
Trigger platform when train reserves path.
Definition of base types and functions in a cross-platform compatible way.
VehicleFlags vehicle_flags
Used for gradual loading and other miscellaneous things (.
static BaseStation * GetByTile(TileIndex tile)
Get the base station belonging to a specific tile.
static int s_rail_change_counter
if any track changes, this counter is incremented - that will invalidate segment cost cache
void PruneIntermediateNodeBranch(Node *n)
In some cases an intermediate node branch should be pruned.
Class that represents the dump-into-string target.
std::string output_buffer
The output string.
Helper container to find a depot.
bool reverse
True if reversing is necessary for the train to get to this depot.
TileIndex tile
The tile of the depot.
bool CanLeadTrain() const
Check if this vehicle can lead a train.
This struct contains information about the end of a reserved path.
Trackdir trackdir
The reserved trackdir on the tile.
TileIndex tile
Tile the path ends, INVALID_TILE if no valid path was found.
bool okay
True if tile is a safe waiting position, false otherwise.
T * GetMovingFront() const
Get the moving front of the vehicle chain.
T * Last()
Get the last vehicle in the chain.
T * GetMovingBack() const
Get the moving back of the vehicle chain.
'Train' is either a loco or a wagon.
Trackdir GetVehicleTrackdir() const override
Get the tracks of the train vehicle.
TrackBits track
On which track the train currently is.
int32_t y_pos
y coordinate.
int32_t x_pos
x coordinate.
TileIndex tile
Current tile index.
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.
Track TrackdirToTrack(Trackdir trackdir)
Returns the Track that a given Trackdir represents.
Trackdir ReverseTrackdir(Trackdir trackdir)
Maps a trackdir to the reverse trackdir.
Track FindFirstTrack(TrackBits tracks)
Returns first Track from TrackBits or INVALID_TRACK.
DiagDirection TrackdirToExitdir(Trackdir trackdir)
Maps a trackdir to the (4-way) direction the tile is exited when following that trackdir.
TrackBits
Allow incrementing of Track variables.
@ TRACK_BIT_WORMHOLE
Bitflag for a wormhole (used for tunnels).
Trackdir
Enumeration for tracks and directions.
@ INVALID_TRACKDIR
Flag for an invalid trackdir.
Track
These are used to specify a single track.
@ INVALID_TRACK
Flag for an invalid track.
DiagDirection GetTunnelBridgeDirection(Tile t)
Get the direction pointing to the other end.
TileIndex GetOtherTunnelBridgeEnd(Tile t)
Determines type of the wormhole and returns its other end.
Functions related to (drawing on) viewports.
Base includes/functions for YAPF.
Entry point for OpenTTD to YAPF's cache.
Cost determination for rails.
Determining the destination for rail vehicles.
Node tailored for rail pathfinding.
void YapfNotifyTrackLayoutChange(TileIndex tile, Track track)
Use this function to notify YAPF that track layout (or signal configuration) has change.
bool YapfTrainFindNearestSafeTile(const Train *v, TileIndex tile, Trackdir td, bool override_railtype)
Try to extend the reserved path of a train to the nearest safe tile using YAPF.
Track YapfTrainChooseTrack(const Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found, bool reserve_track, PBSTileInfo *target, TileIndex *dest)
Finds the best path for given train using YAPF.
FindDepotData YapfTrainFindNearestDepot(const Train *v, int max_penalty)
Used when user sends train to the nearest depot or if train needs servicing using YAPF.
bool YapfTrainCheckReverse(const Train *v)
Returns true if it is better to reverse the train before leaving station using YAPF.
@ ChoiceFollows
the next tile contains a choice (the track splits to more than one segments)