OpenTTD Source 20250529-master-g10c159a79f
yapf_rail.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
10#include "../../stdafx.h"
11
12#include "yapf.hpp"
13#include "yapf_cache.h"
14#include "yapf_node_rail.hpp"
15#include "yapf_costrail.hpp"
16#include "yapf_destrail.hpp"
17#include "../../viewport_func.h"
18#include "../../newgrf_station.h"
19
20#include "../../safeguards.h"
21
22template <typename Tpf> void DumpState(Tpf &pf1, Tpf &pf2)
23{
24 DumpTarget dmp1, dmp2;
25 pf1.DumpBase(dmp1);
26 pf2.DumpBase(dmp2);
27 auto f1 = FileHandle::Open("yapf1.txt"sv, "wt");
28 auto f2 = FileHandle::Open("yapf2.txt"sv, "wt");
29 assert(f1.has_value());
30 assert(f2.has_value());
31 fwrite(dmp1.m_out.data(), 1, dmp1.m_out.size(), *f1);
32 fwrite(dmp2.m_out.data(), 1, dmp2.m_out.size(), *f2);
33}
34
35template <class Types>
37{
38public:
39 typedef typename Types::Tpf Tpf;
40 typedef typename Types::TrackFollower TrackFollower;
41 typedef typename Types::NodeList::Item Node;
42
43protected:
45 inline Tpf &Yapf()
46 {
47 return *static_cast<Tpf *>(this);
48 }
49
50private:
57
58 std::vector<std::pair<TileIndex, Trackdir>> signals_set_to_red;
59
60 bool FindSafePositionProc(TileIndex tile, Trackdir td)
61 {
62 if (IsSafeWaitingPosition(Yapf().GetVehicle(), tile, td, true, !TrackFollower::Allow90degTurns())) {
63 this->res_dest_tile = tile;
64 this->res_dest_td = td;
65 return false; // Stop iterating segment
66 }
67 return true;
68 }
69
72 {
73 TileIndex start = tile;
75
76 do {
77 if (HasStationReservation(tile)) return false;
78 SetRailStationReservation(tile, true);
80 tile = TileAdd(tile, diff);
81 } while (IsCompatibleTrainStationTile(tile, start) && tile != this->origin_tile);
82
83 auto *st = Station::GetByTile(start);
85 TriggerStationAnimation(st, start, StationAnimationTrigger::PathReservation);
86
87 return true;
88 }
89
92 {
93 Trackdir rev_td = ReverseTrackdir(td);
94 if (IsRailStationTile(tile)) {
96 /* Platform could not be reserved, undo. */
97 this->res_fail_tile = tile;
98 this->res_fail_td = td;
99 }
100 } else {
101 if (!TryReserveRailTrack(tile, TrackdirToTrack(td))) {
102 /* Tile couldn't be reserved, undo. */
103 this->res_fail_tile = tile;
104 this->res_fail_td = td;
105 return false;
106 }
107
108 /* Green path signal opposing the path? Turn to red. */
109 if (HasPbsSignalOnTrackdir(tile, rev_td) && GetSignalStateByTrackdir(tile, rev_td) == SIGNAL_STATE_GREEN) {
110 this->signals_set_to_red.emplace_back(tile, rev_td);
113 }
114
115 if (IsRailWaypointTile(tile)) {
116 auto *st = BaseStation::GetByTile(tile);
118 TriggerStationAnimation(st, tile, StationAnimationTrigger::PathReservation);
119 }
120 }
121
122 return tile != this->res_dest_tile || td != this->res_dest_td;
123 }
124
127 {
128 if (IsRailStationTile(tile)) {
129 TileIndex start = tile;
131 while ((tile != this->res_fail_tile || td != this->res_fail_td) && IsCompatibleTrainStationTile(tile, start)) {
132 SetRailStationReservation(tile, false);
133 tile = TileAdd(tile, diff);
134 }
135 } else if (tile != this->res_fail_tile || td != this->res_fail_td) {
137 }
138 return (tile != this->res_dest_tile || td != this->res_dest_td) && (tile != this->res_fail_tile || td != this->res_fail_td);
139 }
140
141public:
143 inline void SetReservationTarget(Node *node, TileIndex tile, Trackdir td)
144 {
145 this->res_dest_node = node;
146 this->res_dest_tile = tile;
147 this->res_dest_td = td;
148 }
149
151 inline void FindSafePositionOnNode(Node *node)
152 {
153 assert(node->parent != nullptr);
154
155 /* We will never pass more than two signals, no need to check for a safe tile. */
156 if (node->parent->num_signals_passed >= 2) return;
157
158 if (!node->IterateTiles(Yapf().GetVehicle(), Yapf(), *this, &CYapfReserveTrack<Types>::FindSafePositionProc)) {
159 this->res_dest_node = node;
160 }
161 }
162
165 {
166 this->res_fail_tile = INVALID_TILE;
167 this->origin_tile = origin;
168
169 if (target != nullptr) {
170 target->tile = this->res_dest_tile;
171 target->trackdir = this->res_dest_td;
172 target->okay = false;
173 }
174
175 /* Don't bother if the target is reserved. */
176 if (!IsWaitingPositionFree(Yapf().GetVehicle(), this->res_dest_tile, this->res_dest_td)) return false;
177
178 this->signals_set_to_red.clear();
179 for (Node *node = this->res_dest_node; node->parent != nullptr; node = node->parent) {
180 node->IterateTiles(Yapf().GetVehicle(), Yapf(), *this, &CYapfReserveTrack<Types>::ReserveSingleTrack);
181 if (this->res_fail_tile != INVALID_TILE) {
182 /* Reservation failed, undo. */
183 Node *fail_node = this->res_dest_node;
184 TileIndex stop_tile = this->res_fail_tile;
185 do {
186 /* If this is the node that failed, stop at the failed tile. */
187 this->res_fail_tile = fail_node == node ? stop_tile : INVALID_TILE;
188 fail_node->IterateTiles(Yapf().GetVehicle(), Yapf(), *this, &CYapfReserveTrack<Types>::UnreserveSingleTrack);
189 } while (fail_node != node && (fail_node = fail_node->parent) != nullptr);
190
191 /* Re-instate green path signals we turned to red. */
192 for (auto [sig_tile, td] : this->signals_set_to_red) {
194 }
195
196 return false;
197 }
198 }
199
200 if (target != nullptr) target->okay = true;
201
202 if (Yapf().CanUseGlobalCache(*this->res_dest_node)) {
204 }
205
206 return true;
207 }
208};
209
210template <class Types>
212{
213public:
214 typedef typename Types::Tpf Tpf;
215 typedef typename Types::TrackFollower TrackFollower;
216 typedef typename Types::NodeList::Item Node;
217 typedef typename Node::Key Key;
218
219protected:
221 inline Tpf &Yapf()
222 {
223 return *static_cast<Tpf *>(this);
224 }
225
226public:
232 inline void PfFollowNode(Node &old_node)
233 {
234 TrackFollower F(Yapf().GetVehicle());
235 if (F.Follow(old_node.GetLastTile(), old_node.GetLastTrackdir())) {
236 Yapf().AddMultipleNodes(&old_node, F);
237 }
238 }
239
241 inline char TransportTypeChar() const
242 {
243 return 't';
244 }
245
246 static FindDepotData stFindNearestDepotTwoWay(const Train *v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int max_penalty, int reverse_penalty)
247 {
248 Tpf pf1;
249 /*
250 * With caching enabled it simply cannot get a reliable result when you
251 * have limited the distance a train may travel. This means that the
252 * cached result does not match uncached result in all cases and that
253 * causes desyncs. So disable caching when finding for a depot that is
254 * nearby. This only happens with automatic servicing of vehicles,
255 * so it will only impact performance when you do not manually set
256 * depot orders and you do not disable automatic servicing.
257 */
258 if (max_penalty != 0) pf1.DisableCache(true);
259 FindDepotData result1 = pf1.FindNearestDepotTwoWay(v, t1, td1, t2, td2, max_penalty, reverse_penalty);
260
261 if (_debug_desync_level >= 2) {
262 Tpf pf2;
263 pf2.DisableCache(true);
264 FindDepotData result2 = pf2.FindNearestDepotTwoWay(v, t1, td1, t2, td2, max_penalty, reverse_penalty);
265 if (result1.tile != result2.tile || (result1.reverse != result2.reverse)) {
266 Debug(desync, 2, "warning: FindNearestDepotTwoWay cache mismatch: {} vs {}",
267 result1.tile != INVALID_TILE ? "T" : "F",
268 result2.tile != INVALID_TILE ? "T" : "F");
269 DumpState(pf1, pf2);
270 }
271 }
272
273 return result1;
274 }
275
276 inline FindDepotData FindNearestDepotTwoWay(const Train *v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int max_penalty, int reverse_penalty)
277 {
278 /* set origin and destination nodes */
279 Yapf().SetOrigin(t1, td1, t2, td2, reverse_penalty);
280 Yapf().SetTreatFirstRedTwoWaySignalAsEOL(true);
281 Yapf().SetDestination(v);
282 Yapf().SetMaxCost(max_penalty);
283
284 /* find the best path */
285 if (!Yapf().FindPath(v)) return FindDepotData();
286
287 /* Some path found. */
288 Node *n = Yapf().GetBestNode();
289
290 /* walk through the path back to the origin */
291 Node *node = n;
292 while (node->parent != nullptr) {
293 node = node->parent;
294 }
295
296 /* if the origin node is our front vehicle tile/Trackdir then we didn't reverse
297 * but we can also look at the cost (== 0 -> not reversed, == reverse_penalty -> reversed) */
298 return FindDepotData(n->GetLastTile(), n->cost, node->cost != 0);
299 }
300};
301
302template <class Types>
304{
305public:
306 typedef typename Types::Tpf Tpf;
307 typedef typename Types::TrackFollower TrackFollower;
308 typedef typename Types::NodeList::Item Node;
309 typedef typename Node::Key Key;
310
311protected:
313 inline Tpf &Yapf()
314 {
315 return *static_cast<Tpf *>(this);
316 }
317
318public:
324 inline void PfFollowNode(Node &old_node)
325 {
326 TrackFollower F(Yapf().GetVehicle(), Yapf().GetCompatibleRailTypes());
327 if (F.Follow(old_node.GetLastTile(), old_node.GetLastTrackdir()) && F.MaskReservedTracks()) {
328 Yapf().AddMultipleNodes(&old_node, F);
329 }
330 }
331
333 inline char TransportTypeChar() const
334 {
335 return 't';
336 }
337
338 static bool stFindNearestSafeTile(const Train *v, TileIndex t1, Trackdir td, bool override_railtype)
339 {
340 /* Create pathfinder instance */
341 Tpf pf1;
342 bool result1;
343 if (_debug_desync_level < 2) {
344 result1 = pf1.FindNearestSafeTile(v, t1, td, override_railtype, false);
345 } else {
346 bool result2 = pf1.FindNearestSafeTile(v, t1, td, override_railtype, true);
347 Tpf pf2;
348 pf2.DisableCache(true);
349 result1 = pf2.FindNearestSafeTile(v, t1, td, override_railtype, false);
350 if (result1 != result2) {
351 Debug(desync, 2, "warning: FindSafeTile cache mismatch: {} vs {}", result2 ? "T" : "F", result1 ? "T" : "F");
352 DumpState(pf1, pf2);
353 }
354 }
355
356 return result1;
357 }
358
359 bool FindNearestSafeTile(const Train *v, TileIndex t1, Trackdir td, bool override_railtype, bool dont_reserve)
360 {
361 /* Set origin and destination. */
362 Yapf().SetOrigin(t1, td);
363 Yapf().SetTreatFirstRedTwoWaySignalAsEOL(false);
364 Yapf().SetDestination(v, override_railtype);
365
366 if (!Yapf().FindPath(v)) return false;
367
368 /* Found a destination, set as reservation target. */
369 Node *node = Yapf().GetBestNode();
370 this->SetReservationTarget(node, node->GetLastTile(), node->GetLastTrackdir());
371
372 /* Walk through the path back to the origin. */
373 Node *prev = nullptr;
374 while (node->parent != nullptr) {
375 prev = node;
376 node = node->parent;
377
378 this->FindSafePositionOnNode(prev);
379 }
380
381 return dont_reserve || this->TryReservePath(nullptr, node->GetLastTile());
382 }
383};
384
385template <class Types>
387{
388public:
389 typedef typename Types::Tpf Tpf;
390 typedef typename Types::TrackFollower TrackFollower;
391 typedef typename Types::NodeList::Item Node;
392 typedef typename Node::Key Key;
393
394protected:
396 inline Tpf &Yapf()
397 {
398 return *static_cast<Tpf *>(this);
399 }
400
401public:
407 inline void PfFollowNode(Node &old_node)
408 {
409 TrackFollower F(Yapf().GetVehicle());
410 if (F.Follow(old_node.GetLastTile(), old_node.GetLastTrackdir())) {
411 Yapf().AddMultipleNodes(&old_node, F);
412 }
413 }
414
416 inline char TransportTypeChar() const
417 {
418 return 't';
419 }
420
421 static Trackdir stChooseRailTrack(const Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found, bool reserve_track, PBSTileInfo *target, TileIndex *dest)
422 {
423 /* create pathfinder instance */
424 Tpf pf1;
425 Trackdir result1;
426
427 if (_debug_desync_level < 2) {
428 result1 = pf1.ChooseRailTrack(v, tile, enterdir, tracks, path_found, reserve_track, target, dest);
429 } else {
430 result1 = pf1.ChooseRailTrack(v, tile, enterdir, tracks, path_found, false, nullptr, nullptr);
431 Tpf pf2;
432 pf2.DisableCache(true);
433 Trackdir result2 = pf2.ChooseRailTrack(v, tile, enterdir, tracks, path_found, reserve_track, target, dest);
434 if (result1 != result2) {
435 Debug(desync, 2, "warning: ChooseRailTrack cache mismatch: {} vs {}", result1, result2);
436 DumpState(pf1, pf2);
437 }
438 }
439
440 return result1;
441 }
442
443 inline Trackdir ChooseRailTrack(const Train *v, TileIndex, DiagDirection, TrackBits, bool &path_found, bool reserve_track, PBSTileInfo *target, TileIndex *dest)
444 {
445 if (target != nullptr) target->tile = INVALID_TILE;
446 if (dest != nullptr) *dest = INVALID_TILE;
447
448 /* set origin and destination nodes */
450 Yapf().SetOrigin(origin.tile, origin.trackdir, INVALID_TILE, INVALID_TRACKDIR, 1);
451 Yapf().SetTreatFirstRedTwoWaySignalAsEOL(true);
452 Yapf().SetDestination(v);
453
454 /* find the best path */
455 path_found = Yapf().FindPath(v);
456
457 /* if path not found - return INVALID_TRACKDIR */
458 Trackdir next_trackdir = INVALID_TRACKDIR;
459 Node *node = Yapf().GetBestNode();
460 if (node != nullptr) {
461 /* reserve till end of path */
462 this->SetReservationTarget(node, node->GetLastTile(), node->GetLastTrackdir());
463
464 /* path was found or at least suggested
465 * walk through the path back to the origin */
466 Node *prev = nullptr;
467 while (node->parent != nullptr) {
468 prev = node;
469 node = node->parent;
470
471 this->FindSafePositionOnNode(prev);
472 }
473
474 /* If the best PF node has no parent, then there is no (valid) best next trackdir to return.
475 * This occurs when the PF is called while the train is already at its destination. */
476 if (prev == nullptr) return INVALID_TRACKDIR;
477
478 /* return trackdir from the best origin node (one of start nodes) */
479 Node &best_next_node = *prev;
480 next_trackdir = best_next_node.GetTrackdir();
481
482 if (reserve_track && path_found) {
483 if (dest != nullptr) *dest = Yapf().GetBestNode()->GetLastTile();
484 this->TryReservePath(target, node->GetLastTile());
485 }
486 }
487
488 /* Treat the path as found if stopped on the first two way signal(s). */
489 path_found |= Yapf().stopped_on_first_two_way_signal;
490 return next_trackdir;
491 }
492
493 static bool stCheckReverseTrain(const Train *v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int reverse_penalty)
494 {
495 Tpf pf1;
496 bool result1 = pf1.CheckReverseTrain(v, t1, td1, t2, td2, reverse_penalty);
497
498 if (_debug_desync_level >= 2) {
499 Tpf pf2;
500 pf2.DisableCache(true);
501 bool result2 = pf2.CheckReverseTrain(v, t1, td1, t2, td2, reverse_penalty);
502 if (result1 != result2) {
503 Debug(desync, 2, "warning: CheckReverseTrain cache mismatch: {} vs {}", result1 ? "T" : "F", result2 ? "T" : "F");
504 DumpState(pf1, pf2);
505 }
506 }
507
508 return result1;
509 }
510
511 inline bool CheckReverseTrain(const Train *v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int reverse_penalty)
512 {
513 /* create pathfinder instance
514 * set origin and destination nodes */
515 Yapf().SetOrigin(t1, td1, t2, td2, reverse_penalty);
516 Yapf().SetTreatFirstRedTwoWaySignalAsEOL(false);
517 Yapf().SetDestination(v);
518
519 /* find the best path */
520 if (!Yapf().FindPath(v)) return false;
521
522 /* path was found
523 * walk through the path back to the origin */
524 Node *node = Yapf().GetBestNode();
525 while (node->parent != nullptr) {
526 node = node->parent;
527 }
528
529 /* check if it was reversed origin */
530 bool reversed = (node->cost != 0);
531 return reversed;
532 }
533};
534
535template <class Tpf_, class Ttrack_follower, class Tnode_list, template <class Types> class TdestinationT, template <class Types> class TfollowT>
537{
539
540 typedef Tpf_ Tpf;
541 typedef Ttrack_follower TrackFollower;
542 typedef Tnode_list NodeList;
543 typedef Train VehicleType;
545 typedef TfollowT<Types> PfFollow;
547 typedef TdestinationT<Types> PfDestination;
550};
551
552struct CYapfRail1 : CYapfT<CYapfRail_TypesT<CYapfRail1 , CFollowTrackRail , CRailNodeListTrackDir, CYapfDestinationTileOrStationRailT, CYapfFollowRailT> > {};
553struct CYapfRail2 : CYapfT<CYapfRail_TypesT<CYapfRail2 , CFollowTrackRailNo90, CRailNodeListTrackDir, CYapfDestinationTileOrStationRailT, CYapfFollowRailT> > {};
554
555struct CYapfAnyDepotRail1 : CYapfT<CYapfRail_TypesT<CYapfAnyDepotRail1, CFollowTrackRail , CRailNodeListTrackDir, CYapfDestinationAnyDepotRailT , CYapfFollowAnyDepotRailT> > {};
556struct CYapfAnyDepotRail2 : CYapfT<CYapfRail_TypesT<CYapfAnyDepotRail2, CFollowTrackRailNo90, CRailNodeListTrackDir, CYapfDestinationAnyDepotRailT , CYapfFollowAnyDepotRailT> > {};
557
558struct CYapfAnySafeTileRail1 : CYapfT<CYapfRail_TypesT<CYapfAnySafeTileRail1, CFollowTrackFreeRail , CRailNodeListTrackDir, CYapfDestinationAnySafeTileRailT , CYapfFollowAnySafeTileRailT> > {};
559struct CYapfAnySafeTileRail2 : CYapfT<CYapfRail_TypesT<CYapfAnySafeTileRail2, CFollowTrackFreeRailNo90, CRailNodeListTrackDir, CYapfDestinationAnySafeTileRailT , CYapfFollowAnySafeTileRailT> > {};
560
561
562Track YapfTrainChooseTrack(const Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found, bool reserve_track, PBSTileInfo *target, TileIndex *dest)
563{
565 ? CYapfRail2::stChooseRailTrack(v, tile, enterdir, tracks, path_found, reserve_track, target, dest)
566 : CYapfRail1::stChooseRailTrack(v, tile, enterdir, tracks, path_found, reserve_track, target, dest);
567
568 return (td_ret != INVALID_TRACKDIR) ? TrackdirToTrack(td_ret) : FindFirstTrack(tracks);
569}
570
572{
573 const Train *last_veh = v->Last();
574
575 /* get trackdirs of both ends */
577 Trackdir td_rev = ReverseTrackdir(last_veh->GetVehicleTrackdir());
578
579 /* tiles where front and back are */
580 TileIndex tile = v->tile;
581 TileIndex tile_rev = last_veh->tile;
582
583 int reverse_penalty = 0;
584
585 if (v->track == TRACK_BIT_WORMHOLE) {
586 /* front in tunnel / on bridge */
587 DiagDirection dir_into_wormhole = GetTunnelBridgeDirection(tile);
588
589 if (TrackdirToExitdir(td) == dir_into_wormhole) tile = GetOtherTunnelBridgeEnd(tile);
590 /* Now 'tile' is the tunnel entry/bridge ramp the train will reach when driving forward */
591
592 /* Current position of the train in the wormhole */
593 TileIndex cur_tile = TileVirtXY(v->x_pos, v->y_pos);
594
595 /* Add distance to drive in the wormhole as penalty for the forward path, i.e. bonus for the reverse path
596 * Note: Negative penalties are ok for the start tile. */
597 reverse_penalty -= DistanceManhattan(cur_tile, tile) * YAPF_TILE_LENGTH;
598 }
599
600 if (last_veh->track == TRACK_BIT_WORMHOLE) {
601 /* back in tunnel / on bridge */
602 DiagDirection dir_into_wormhole = GetTunnelBridgeDirection(tile_rev);
603
604 if (TrackdirToExitdir(td_rev) == dir_into_wormhole) tile_rev = GetOtherTunnelBridgeEnd(tile_rev);
605 /* Now 'tile_rev' is the tunnel entry/bridge ramp the train will reach when reversing */
606
607 /* Current position of the last wagon in the wormhole */
608 TileIndex cur_tile = TileVirtXY(last_veh->x_pos, last_veh->y_pos);
609
610 /* Add distance to drive in the wormhole as penalty for the revere path. */
611 reverse_penalty += DistanceManhattan(cur_tile, tile_rev) * YAPF_TILE_LENGTH;
612 }
613
614 /* slightly hackish: If the pathfinders finds a path, the cost of the first node is tested to distinguish between forward- and reverse-path. */
615 if (reverse_penalty == 0) reverse_penalty = 1;
616
617 bool reverse = _settings_game.pf.forbid_90_deg
618 ? CYapfRail2::stCheckReverseTrain(v, tile, td, tile_rev, td_rev, reverse_penalty)
619 : CYapfRail1::stCheckReverseTrain(v, tile, td, tile_rev, td_rev, reverse_penalty);
620
621 return reverse;
622}
623
625{
626 const Train *last_veh = v->Last();
627
629 TileIndex last_tile = last_veh->tile;
630 Trackdir td_rev = ReverseTrackdir(last_veh->GetVehicleTrackdir());
631
633 ? CYapfAnyDepotRail2::stFindNearestDepotTwoWay(v, origin.tile, origin.trackdir, last_tile, td_rev, max_penalty, YAPF_INFINITE_PENALTY)
634 : CYapfAnyDepotRail1::stFindNearestDepotTwoWay(v, origin.tile, origin.trackdir, last_tile, td_rev, max_penalty, YAPF_INFINITE_PENALTY);
635}
636
637bool YapfTrainFindNearestSafeTile(const Train *v, TileIndex tile, Trackdir td, bool override_railtype)
638{
640 ? CYapfAnySafeTileRail2::stFindNearestSafeTile(v, tile, td, override_railtype)
641 : CYapfAnySafeTileRail1::stFindNearestSafeTile(v, tile, td, override_railtype);
642}
643
646
648{
649 CSegmentCostCacheBase::NotifyTrackLayoutChange(tile, track);
650}
CYapfBaseT - A-star type path finder base class.
Definition yapf_base.hpp:49
Types::Tpf Tpf
the pathfinder class (derived from THIS class)
Tpf & Yapf()
to access 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()
to access inherited path finder
Node::Key Key
key to hash tables
Tpf & Yapf()
to access 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
Definition yapf_rail.cpp:41
TileIndex res_fail_tile
The tile where the reservation failed.
Definition yapf_rail.cpp:54
bool UnreserveSingleTrack(TileIndex tile, Trackdir td)
Unreserve a single track/platform.
bool ReserveRailStationPlatform(TileIndex &tile, DiagDirection dir)
Reserve a railway platform.
Definition yapf_rail.cpp:71
bool ReserveSingleTrack(TileIndex tile, Trackdir td)
Try to reserve a single track/platform.
Definition yapf_rail.cpp:91
std::vector< std::pair< TileIndex, Trackdir > > signals_set_to_red
List of signals turned red during a path reservation.
Definition yapf_rail.cpp:58
Trackdir res_fail_td
The trackdir where the reservation failed.
Definition yapf_rail.cpp:55
Node * res_dest_node
The reservation target node.
Definition yapf_rail.cpp:53
TileIndex origin_tile
Tile our reservation will originate from.
Definition yapf_rail.cpp:56
TileIndex res_dest_tile
The reservation target tile.
Definition yapf_rail.cpp:51
bool TryReservePath(PBSTileInfo *target, TileIndex origin)
Try to reserve the path till the reservation target.
Tpf & Yapf()
to access inherited pathfinder
Definition yapf_rail.cpp:45
void FindSafePositionOnNode(Node *node)
Check the node for a possible reservation target.
Trackdir res_dest_td
The reservation target trackdir.
Definition yapf_rail.cpp:52
Types::Tpf Tpf
the pathfinder class (derived from THIS class)
Definition yapf_rail.cpp:39
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.
Definition fileio.cpp:1168
Hash table based node list multi-container class.
Definition nodelist.hpp:21
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
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.
Definition map.cpp:142
constexpr TileIndex TileAdd(TileIndex tile, TileIndexDiff offset)
Adds a given offset to a tile.
Definition map_func.h:456
TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition map_func.h:569
static debug_inline TileIndex TileVirtXY(uint x, uint y)
Get a tile from the virtual XY-coordinate.
Definition map_func.h:403
int32_t TileIndexDiff
An offset value between two tiles.
Definition map_type.h:23
void TriggerStationRandomisation(BaseStation *st, TileIndex trigger_tile, StationRandomTrigger trigger, CargoType cargo_type)
Trigger station randomisation.
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.
PBSTileInfo FollowTrainReservation(const Train *v, Vehicle **train_on_res)
Follow a train reservation to the last tile.
Definition pbs.cpp:289
bool TryReserveRailTrack(TileIndex tile, Track t, bool trigger_stations)
Try to reserve a specific track on a tile.
Definition pbs.cpp:80
bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bool forbid_90deg)
Check if a safe position is free.
Definition pbs.cpp:427
void UnreserveRailTrack(TileIndex tile, Track t)
Lift the reservation of a specific track on a tile.
Definition pbs.cpp:144
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.
Definition pbs.cpp:381
void SetSignalStateByTrackdir(Tile tile, Trackdir trackdir, SignalState state)
Sets the state of the signal along the given trackdir.
Definition rail_map.h:448
bool HasPbsSignalOnTrackdir(Tile tile, Trackdir td)
Is a pbs signal present along the trackdir?
Definition rail_map.h:462
SignalState GetSignalStateByTrackdir(Tile tile, Trackdir trackdir)
Gets the state of the signal along the given trackdir.
Definition rail_map.h:437
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:61
@ SIGNAL_STATE_RED
The signal is red.
Definition signal_type.h:43
@ SIGNAL_STATE_GREEN
The signal is green.
Definition signal_type.h:44
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.
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
Class that represents the dump-into-string target.
std::string m_out
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.
PathfinderSettings pf
settings for all pathfinders
Node of the link graph.
Definition linkgraph.h:90
This struct contains information about the end of a reserved path.
Definition pbs.h:26
Trackdir trackdir
The reserved trackdir on the tile.
Definition pbs.h:28
TileIndex tile
Tile the path ends, INVALID_TILE if no valid path was found.
Definition pbs.h:27
bool okay
True if tile is a safe waiting position, false otherwise.
Definition pbs.h:29
bool forbid_90_deg
forbid trains to make 90 deg turns
T * Last()
Get the last vehicle in the chain.
'Train' is either a loco or a wagon.
Definition train.h:91
Trackdir GetVehicleTrackdir() const override
Get the tracks of the train vehicle.
int32_t y_pos
y coordinate.
int32_t x_pos
x coordinate.
TileIndex tile
Current tile index.
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:95
Track TrackdirToTrack(Trackdir trackdir)
Returns the Track that a given Trackdir represents.
Definition track_func.h:262
Trackdir ReverseTrackdir(Trackdir trackdir)
Maps a trackdir to the reverse trackdir.
Definition track_func.h:247
Track FindFirstTrack(TrackBits tracks)
Returns first Track from TrackBits or INVALID_TRACK.
Definition track_func.h:177
DiagDirection TrackdirToExitdir(Trackdir trackdir)
Maps a trackdir to the (4-way) direction the tile is exited when following that trackdir.
Definition track_func.h:439
TrackBits
Allow incrementing of Track variables.
Definition track_type.h:35
@ TRACK_BIT_WORMHOLE
Bitflag for a wormhole (used for tunnels)
Definition track_type.h:52
Trackdir
Enumeration for tracks and directions.
Definition track_type.h:66
@ INVALID_TRACKDIR
Flag for an invalid trackdir.
Definition track_type.h:85
Track
These are used to specify a single track.
Definition track_type.h:19
@ INVALID_TRACK
Flag for an invalid track.
Definition track_type.h:28
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.
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.