OpenTTD Source 20241224-master-gf74b0cf984
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", "wt");
28 auto f2 = FileHandle::Open("yapf2.txt", "wt");
29 assert(f1.has_value());
30 assert(f2.has_value());
31 fwrite(dmp1.m_out.c_str(), 1, dmp1.m_out.size(), *f1);
32 fwrite(dmp2.m_out.c_str(), 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
84
85 return true;
86 }
87
90 {
91 Trackdir rev_td = ReverseTrackdir(td);
92 if (IsRailStationTile(tile)) {
94 /* Platform could not be reserved, undo. */
95 this->res_fail_tile = tile;
96 this->res_fail_td = td;
97 }
98 } else {
99 if (!TryReserveRailTrack(tile, TrackdirToTrack(td))) {
100 /* Tile couldn't be reserved, undo. */
101 this->res_fail_tile = tile;
102 this->res_fail_td = td;
103 return false;
104 }
105
106 /* Green path signal opposing the path? Turn to red. */
107 if (HasPbsSignalOnTrackdir(tile, rev_td) && GetSignalStateByTrackdir(tile, rev_td) == SIGNAL_STATE_GREEN) {
108 this->signals_set_to_red.emplace_back(tile, rev_td);
111 }
112 }
113
114 return tile != this->res_dest_tile || td != this->res_dest_td;
115 }
116
119 {
120 if (IsRailStationTile(tile)) {
121 TileIndex start = tile;
123 while ((tile != this->res_fail_tile || td != this->res_fail_td) && IsCompatibleTrainStationTile(tile, start)) {
124 SetRailStationReservation(tile, false);
125 tile = TileAdd(tile, diff);
126 }
127 } else if (tile != this->res_fail_tile || td != this->res_fail_td) {
129 }
130 return (tile != this->res_dest_tile || td != this->res_dest_td) && (tile != this->res_fail_tile || td != this->res_fail_td);
131 }
132
133public:
135 inline void SetReservationTarget(Node *node, TileIndex tile, Trackdir td)
136 {
137 this->res_dest_node = node;
138 this->res_dest_tile = tile;
139 this->res_dest_td = td;
140 }
141
143 inline void FindSafePositionOnNode(Node *node)
144 {
145 assert(node->parent != nullptr);
146
147 /* We will never pass more than two signals, no need to check for a safe tile. */
148 if (node->parent->num_signals_passed >= 2) return;
149
150 if (!node->IterateTiles(Yapf().GetVehicle(), Yapf(), *this, &CYapfReserveTrack<Types>::FindSafePositionProc)) {
151 this->res_dest_node = node;
152 }
153 }
154
157 {
158 this->res_fail_tile = INVALID_TILE;
159 this->origin_tile = origin;
160
161 if (target != nullptr) {
162 target->tile = this->res_dest_tile;
163 target->trackdir = this->res_dest_td;
164 target->okay = false;
165 }
166
167 /* Don't bother if the target is reserved. */
168 if (!IsWaitingPositionFree(Yapf().GetVehicle(), this->res_dest_tile, this->res_dest_td)) return false;
169
170 this->signals_set_to_red.clear();
171 for (Node *node = this->res_dest_node; node->parent != nullptr; node = node->parent) {
172 node->IterateTiles(Yapf().GetVehicle(), Yapf(), *this, &CYapfReserveTrack<Types>::ReserveSingleTrack);
173 if (this->res_fail_tile != INVALID_TILE) {
174 /* Reservation failed, undo. */
175 Node *fail_node = this->res_dest_node;
176 TileIndex stop_tile = this->res_fail_tile;
177 do {
178 /* If this is the node that failed, stop at the failed tile. */
179 this->res_fail_tile = fail_node == node ? stop_tile : INVALID_TILE;
180 fail_node->IterateTiles(Yapf().GetVehicle(), Yapf(), *this, &CYapfReserveTrack<Types>::UnreserveSingleTrack);
181 } while (fail_node != node && (fail_node = fail_node->parent) != nullptr);
182
183 /* Re-instate green path signals we turned to red. */
184 for (auto [sig_tile, td] : this->signals_set_to_red) {
186 }
187
188 return false;
189 }
190 }
191
192 if (target != nullptr) target->okay = true;
193
194 if (Yapf().CanUseGlobalCache(*this->res_dest_node)) {
196 }
197
198 return true;
199 }
200};
201
202template <class Types>
204{
205public:
206 typedef typename Types::Tpf Tpf;
207 typedef typename Types::TrackFollower TrackFollower;
208 typedef typename Types::NodeList::Item Node;
209 typedef typename Node::Key Key;
210
211protected:
213 inline Tpf &Yapf()
214 {
215 return *static_cast<Tpf *>(this);
216 }
217
218public:
224 inline void PfFollowNode(Node &old_node)
225 {
226 TrackFollower F(Yapf().GetVehicle());
227 if (F.Follow(old_node.GetLastTile(), old_node.GetLastTrackdir())) {
228 Yapf().AddMultipleNodes(&old_node, F);
229 }
230 }
231
233 inline char TransportTypeChar() const
234 {
235 return 't';
236 }
237
238 static FindDepotData stFindNearestDepotTwoWay(const Train *v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int max_penalty, int reverse_penalty)
239 {
240 Tpf pf1;
241 /*
242 * With caching enabled it simply cannot get a reliable result when you
243 * have limited the distance a train may travel. This means that the
244 * cached result does not match uncached result in all cases and that
245 * causes desyncs. So disable caching when finding for a depot that is
246 * nearby. This only happens with automatic servicing of vehicles,
247 * so it will only impact performance when you do not manually set
248 * depot orders and you do not disable automatic servicing.
249 */
250 if (max_penalty != 0) pf1.DisableCache(true);
251 FindDepotData result1 = pf1.FindNearestDepotTwoWay(v, t1, td1, t2, td2, max_penalty, reverse_penalty);
252
253 if (_debug_desync_level >= 2) {
254 Tpf pf2;
255 pf2.DisableCache(true);
256 FindDepotData result2 = pf2.FindNearestDepotTwoWay(v, t1, td1, t2, td2, max_penalty, reverse_penalty);
257 if (result1.tile != result2.tile || (result1.reverse != result2.reverse)) {
258 Debug(desync, 2, "warning: FindNearestDepotTwoWay cache mismatch: {} vs {}",
259 result1.tile != INVALID_TILE ? "T" : "F",
260 result2.tile != INVALID_TILE ? "T" : "F");
261 DumpState(pf1, pf2);
262 }
263 }
264
265 return result1;
266 }
267
268 inline FindDepotData FindNearestDepotTwoWay(const Train *v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int max_penalty, int reverse_penalty)
269 {
270 /* set origin and destination nodes */
271 Yapf().SetOrigin(t1, td1, t2, td2, reverse_penalty);
272 Yapf().SetTreatFirstRedTwoWaySignalAsEOL(true);
273 Yapf().SetDestination(v);
274 Yapf().SetMaxCost(max_penalty);
275
276 /* find the best path */
277 if (!Yapf().FindPath(v)) return FindDepotData();
278
279 /* Some path found. */
280 Node *n = Yapf().GetBestNode();
281
282 /* walk through the path back to the origin */
283 Node *pNode = n;
284 while (pNode->parent != nullptr) {
285 pNode = pNode->parent;
286 }
287
288 /* if the origin node is our front vehicle tile/Trackdir then we didn't reverse
289 * but we can also look at the cost (== 0 -> not reversed, == reverse_penalty -> reversed) */
290 return FindDepotData(n->GetLastTile(), n->cost, pNode->cost != 0);
291 }
292};
293
294template <class Types>
296{
297public:
298 typedef typename Types::Tpf Tpf;
299 typedef typename Types::TrackFollower TrackFollower;
300 typedef typename Types::NodeList::Item Node;
301 typedef typename Node::Key Key;
302
303protected:
305 inline Tpf &Yapf()
306 {
307 return *static_cast<Tpf *>(this);
308 }
309
310public:
316 inline void PfFollowNode(Node &old_node)
317 {
318 TrackFollower F(Yapf().GetVehicle(), Yapf().GetCompatibleRailTypes());
319 if (F.Follow(old_node.GetLastTile(), old_node.GetLastTrackdir()) && F.MaskReservedTracks()) {
320 Yapf().AddMultipleNodes(&old_node, F);
321 }
322 }
323
325 inline char TransportTypeChar() const
326 {
327 return 't';
328 }
329
330 static bool stFindNearestSafeTile(const Train *v, TileIndex t1, Trackdir td, bool override_railtype)
331 {
332 /* Create pathfinder instance */
333 Tpf pf1;
334 bool result1;
335 if (_debug_desync_level < 2) {
336 result1 = pf1.FindNearestSafeTile(v, t1, td, override_railtype, false);
337 } else {
338 bool result2 = pf1.FindNearestSafeTile(v, t1, td, override_railtype, true);
339 Tpf pf2;
340 pf2.DisableCache(true);
341 result1 = pf2.FindNearestSafeTile(v, t1, td, override_railtype, false);
342 if (result1 != result2) {
343 Debug(desync, 2, "warning: FindSafeTile cache mismatch: {} vs {}", result2 ? "T" : "F", result1 ? "T" : "F");
344 DumpState(pf1, pf2);
345 }
346 }
347
348 return result1;
349 }
350
351 bool FindNearestSafeTile(const Train *v, TileIndex t1, Trackdir td, bool override_railtype, bool dont_reserve)
352 {
353 /* Set origin and destination. */
354 Yapf().SetOrigin(t1, td);
355 Yapf().SetTreatFirstRedTwoWaySignalAsEOL(false);
356 Yapf().SetDestination(v, override_railtype);
357
358 if (!Yapf().FindPath(v)) return false;
359
360 /* Found a destination, set as reservation target. */
361 Node *pNode = Yapf().GetBestNode();
362 this->SetReservationTarget(pNode, pNode->GetLastTile(), pNode->GetLastTrackdir());
363
364 /* Walk through the path back to the origin. */
365 Node *pPrev = nullptr;
366 while (pNode->parent != nullptr) {
367 pPrev = pNode;
368 pNode = pNode->parent;
369
370 this->FindSafePositionOnNode(pPrev);
371 }
372
373 return dont_reserve || this->TryReservePath(nullptr, pNode->GetLastTile());
374 }
375};
376
377template <class Types>
379{
380public:
381 typedef typename Types::Tpf Tpf;
382 typedef typename Types::TrackFollower TrackFollower;
383 typedef typename Types::NodeList::Item Node;
384 typedef typename Node::Key Key;
385
386protected:
388 inline Tpf &Yapf()
389 {
390 return *static_cast<Tpf *>(this);
391 }
392
393public:
399 inline void PfFollowNode(Node &old_node)
400 {
401 TrackFollower F(Yapf().GetVehicle());
402 if (F.Follow(old_node.GetLastTile(), old_node.GetLastTrackdir())) {
403 Yapf().AddMultipleNodes(&old_node, F);
404 }
405 }
406
408 inline char TransportTypeChar() const
409 {
410 return 't';
411 }
412
413 static Trackdir stChooseRailTrack(const Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found, bool reserve_track, PBSTileInfo *target, TileIndex *dest)
414 {
415 /* create pathfinder instance */
416 Tpf pf1;
417 Trackdir result1;
418
419 if (_debug_desync_level < 2) {
420 result1 = pf1.ChooseRailTrack(v, tile, enterdir, tracks, path_found, reserve_track, target, dest);
421 } else {
422 result1 = pf1.ChooseRailTrack(v, tile, enterdir, tracks, path_found, false, nullptr, nullptr);
423 Tpf pf2;
424 pf2.DisableCache(true);
425 Trackdir result2 = pf2.ChooseRailTrack(v, tile, enterdir, tracks, path_found, reserve_track, target, dest);
426 if (result1 != result2) {
427 Debug(desync, 2, "warning: ChooseRailTrack cache mismatch: {} vs {}", result1, result2);
428 DumpState(pf1, pf2);
429 }
430 }
431
432 return result1;
433 }
434
435 inline Trackdir ChooseRailTrack(const Train *v, TileIndex, DiagDirection, TrackBits, bool &path_found, bool reserve_track, PBSTileInfo *target, TileIndex *dest)
436 {
437 if (target != nullptr) target->tile = INVALID_TILE;
438 if (dest != nullptr) *dest = INVALID_TILE;
439
440 /* set origin and destination nodes */
442 Yapf().SetOrigin(origin.tile, origin.trackdir, INVALID_TILE, INVALID_TRACKDIR, 1);
443 Yapf().SetTreatFirstRedTwoWaySignalAsEOL(true);
444 Yapf().SetDestination(v);
445
446 /* find the best path */
447 path_found = Yapf().FindPath(v);
448
449 /* if path not found - return INVALID_TRACKDIR */
450 Trackdir next_trackdir = INVALID_TRACKDIR;
451 Node *pNode = Yapf().GetBestNode();
452 if (pNode != nullptr) {
453 /* reserve till end of path */
454 this->SetReservationTarget(pNode, pNode->GetLastTile(), pNode->GetLastTrackdir());
455
456 /* path was found or at least suggested
457 * walk through the path back to the origin */
458 Node *pPrev = nullptr;
459 while (pNode->parent != nullptr) {
460 pPrev = pNode;
461 pNode = pNode->parent;
462
463 this->FindSafePositionOnNode(pPrev);
464 }
465
466 /* If the best PF node has no parent, then there is no (valid) best next trackdir to return.
467 * This occurs when the PF is called while the train is already at its destination. */
468 if (pPrev == nullptr) return INVALID_TRACKDIR;
469
470 /* return trackdir from the best origin node (one of start nodes) */
471 Node &best_next_node = *pPrev;
472 next_trackdir = best_next_node.GetTrackdir();
473
474 if (reserve_track && path_found) {
475 if (dest != nullptr) *dest = Yapf().GetBestNode()->GetLastTile();
476 this->TryReservePath(target, pNode->GetLastTile());
477 }
478 }
479
480 /* Treat the path as found if stopped on the first two way signal(s). */
481 path_found |= Yapf().stopped_on_first_two_way_signal;
482 return next_trackdir;
483 }
484
485 static bool stCheckReverseTrain(const Train *v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int reverse_penalty)
486 {
487 Tpf pf1;
488 bool result1 = pf1.CheckReverseTrain(v, t1, td1, t2, td2, reverse_penalty);
489
490 if (_debug_desync_level >= 2) {
491 Tpf pf2;
492 pf2.DisableCache(true);
493 bool result2 = pf2.CheckReverseTrain(v, t1, td1, t2, td2, reverse_penalty);
494 if (result1 != result2) {
495 Debug(desync, 2, "warning: CheckReverseTrain cache mismatch: {} vs {}", result1 ? "T" : "F", result2 ? "T" : "F");
496 DumpState(pf1, pf2);
497 }
498 }
499
500 return result1;
501 }
502
503 inline bool CheckReverseTrain(const Train *v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int reverse_penalty)
504 {
505 /* create pathfinder instance
506 * set origin and destination nodes */
507 Yapf().SetOrigin(t1, td1, t2, td2, reverse_penalty);
508 Yapf().SetTreatFirstRedTwoWaySignalAsEOL(false);
509 Yapf().SetDestination(v);
510
511 /* find the best path */
512 if (!Yapf().FindPath(v)) return false;
513
514 /* path was found
515 * walk through the path back to the origin */
516 Node *pNode = Yapf().GetBestNode();
517 while (pNode->parent != nullptr) {
518 pNode = pNode->parent;
519 }
520
521 /* check if it was reversed origin */
522 bool reversed = (pNode->cost != 0);
523 return reversed;
524 }
525};
526
527template <class Tpf_, class Ttrack_follower, class Tnode_list, template <class Types> class TdestinationT, template <class Types> class TfollowT>
529{
531
532 typedef Tpf_ Tpf;
533 typedef Ttrack_follower TrackFollower;
534 typedef Tnode_list NodeList;
535 typedef Train VehicleType;
537 typedef TfollowT<Types> PfFollow;
539 typedef TdestinationT<Types> PfDestination;
542};
543
544struct CYapfRail1 : CYapfT<CYapfRail_TypesT<CYapfRail1 , CFollowTrackRail , CRailNodeListTrackDir, CYapfDestinationTileOrStationRailT, CYapfFollowRailT> > {};
545struct CYapfRail2 : CYapfT<CYapfRail_TypesT<CYapfRail2 , CFollowTrackRailNo90, CRailNodeListTrackDir, CYapfDestinationTileOrStationRailT, CYapfFollowRailT> > {};
546
547struct CYapfAnyDepotRail1 : CYapfT<CYapfRail_TypesT<CYapfAnyDepotRail1, CFollowTrackRail , CRailNodeListTrackDir, CYapfDestinationAnyDepotRailT , CYapfFollowAnyDepotRailT> > {};
548struct CYapfAnyDepotRail2 : CYapfT<CYapfRail_TypesT<CYapfAnyDepotRail2, CFollowTrackRailNo90, CRailNodeListTrackDir, CYapfDestinationAnyDepotRailT , CYapfFollowAnyDepotRailT> > {};
549
550struct CYapfAnySafeTileRail1 : CYapfT<CYapfRail_TypesT<CYapfAnySafeTileRail1, CFollowTrackFreeRail , CRailNodeListTrackDir, CYapfDestinationAnySafeTileRailT , CYapfFollowAnySafeTileRailT> > {};
551struct CYapfAnySafeTileRail2 : CYapfT<CYapfRail_TypesT<CYapfAnySafeTileRail2, CFollowTrackFreeRailNo90, CRailNodeListTrackDir, CYapfDestinationAnySafeTileRailT , CYapfFollowAnySafeTileRailT> > {};
552
553
554Track YapfTrainChooseTrack(const Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found, bool reserve_track, PBSTileInfo *target, TileIndex *dest)
555{
557 ? CYapfRail2::stChooseRailTrack(v, tile, enterdir, tracks, path_found, reserve_track, target, dest)
558 : CYapfRail1::stChooseRailTrack(v, tile, enterdir, tracks, path_found, reserve_track, target, dest);
559
560 return (td_ret != INVALID_TRACKDIR) ? TrackdirToTrack(td_ret) : FindFirstTrack(tracks);
561}
562
564{
565 const Train *last_veh = v->Last();
566
567 /* get trackdirs of both ends */
569 Trackdir td_rev = ReverseTrackdir(last_veh->GetVehicleTrackdir());
570
571 /* tiles where front and back are */
572 TileIndex tile = v->tile;
573 TileIndex tile_rev = last_veh->tile;
574
575 int reverse_penalty = 0;
576
577 if (v->track == TRACK_BIT_WORMHOLE) {
578 /* front in tunnel / on bridge */
579 DiagDirection dir_into_wormhole = GetTunnelBridgeDirection(tile);
580
581 if (TrackdirToExitdir(td) == dir_into_wormhole) tile = GetOtherTunnelBridgeEnd(tile);
582 /* Now 'tile' is the tunnel entry/bridge ramp the train will reach when driving forward */
583
584 /* Current position of the train in the wormhole */
585 TileIndex cur_tile = TileVirtXY(v->x_pos, v->y_pos);
586
587 /* Add distance to drive in the wormhole as penalty for the forward path, i.e. bonus for the reverse path
588 * Note: Negative penalties are ok for the start tile. */
589 reverse_penalty -= DistanceManhattan(cur_tile, tile) * YAPF_TILE_LENGTH;
590 }
591
592 if (last_veh->track == TRACK_BIT_WORMHOLE) {
593 /* back in tunnel / on bridge */
594 DiagDirection dir_into_wormhole = GetTunnelBridgeDirection(tile_rev);
595
596 if (TrackdirToExitdir(td_rev) == dir_into_wormhole) tile_rev = GetOtherTunnelBridgeEnd(tile_rev);
597 /* Now 'tile_rev' is the tunnel entry/bridge ramp the train will reach when reversing */
598
599 /* Current position of the last wagon in the wormhole */
600 TileIndex cur_tile = TileVirtXY(last_veh->x_pos, last_veh->y_pos);
601
602 /* Add distance to drive in the wormhole as penalty for the revere path. */
603 reverse_penalty += DistanceManhattan(cur_tile, tile_rev) * YAPF_TILE_LENGTH;
604 }
605
606 /* slightly hackish: If the pathfinders finds a path, the cost of the first node is tested to distinguish between forward- and reverse-path. */
607 if (reverse_penalty == 0) reverse_penalty = 1;
608
609 bool reverse = _settings_game.pf.forbid_90_deg
610 ? CYapfRail2::stCheckReverseTrain(v, tile, td, tile_rev, td_rev, reverse_penalty)
611 : CYapfRail1::stCheckReverseTrain(v, tile, td, tile_rev, td_rev, reverse_penalty);
612
613 return reverse;
614}
615
617{
618 const Train *last_veh = v->Last();
619
621 TileIndex last_tile = last_veh->tile;
622 Trackdir td_rev = ReverseTrackdir(last_veh->GetVehicleTrackdir());
623
625 ? CYapfAnyDepotRail2::stFindNearestDepotTwoWay(v, origin.tile, origin.trackdir, last_tile, td_rev, max_penalty, YAPF_INFINITE_PENALTY)
626 : CYapfAnyDepotRail1::stFindNearestDepotTwoWay(v, origin.tile, origin.trackdir, last_tile, td_rev, max_penalty, YAPF_INFINITE_PENALTY);
627}
628
629bool YapfTrainFindNearestSafeTile(const Train *v, TileIndex tile, Trackdir td, bool override_railtype)
630{
632 ? CYapfAnySafeTileRail2::stFindNearestSafeTile(v, tile, td, override_railtype)
633 : CYapfAnySafeTileRail1::stFindNearestSafeTile(v, tile, td, override_railtype);
634}
635
638
640{
641 CSegmentCostCacheBase::NotifyTrackLayoutChange(tile, track);
642}
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:89
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, const std::string &mode)
Open an RAII file handle if possible.
Definition fileio.cpp:1170
Hash table based node list multi-container class.
Definition nodelist.hpp:21
#define Debug(category, level, format_string,...)
Ouptut 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:146
constexpr TileIndex TileAdd(TileIndex tile, TileIndexDiff offset)
Adds a given offset to a tile.
Definition map_func.h:454
TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition map_func.h:567
static debug_inline TileIndex TileVirtXY(uint x, uint y)
Get a tile from the virtual XY-coordinate.
Definition map_func.h:404
int32_t TileIndexDiff
An offset value between two tiles.
Definition map_type.h:23
void TriggerStationRandomisation(Station *st, TileIndex trigger_tile, StationRandomTrigger trigger, CargoID cargo_type)
Trigger station randomisation.
@ SRT_PATH_RESERVATION
Trigger platform when train reserves path.
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:288
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:426
void UnreserveRailTrack(TileIndex tile, Track t)
Lift the reservation of a specific track on a tile.
Definition pbs.cpp:140
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:380
void SetSignalStateByTrackdir(Tile tile, Trackdir trackdir, SignalState state)
Sets the state of the signal along the given trackdir.
Definition rail_map.h:449
bool HasPbsSignalOnTrackdir(Tile tile, Trackdir td)
Is a pbs signal present along the trackdir?
Definition rail_map.h:463
SignalState GetSignalStateByTrackdir(Tile tile, Trackdir trackdir)
Gets the state of the signal along the given trackdir.
Definition rail_map.h:438
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:57
@ 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 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.
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.
Definition dbg_helpers.h:95
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:89
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:67
@ INVALID_TRACKDIR
Flag for an invalid trackdir.
Definition track_type.h:86
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.