OpenTTD Source  20241120-master-g6d3adc6169
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 
22 template <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 
35 template <class Types>
37 {
38 public:
39  typedef typename Types::Tpf Tpf;
40  typedef typename Types::TrackFollower TrackFollower;
41  typedef typename Types::NodeList::Item Node;
42 
43 protected:
45  inline Tpf &Yapf()
46  {
47  return *static_cast<Tpf *>(this);
48  }
49 
50 private:
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;
74  TileIndexDiff diff = TileOffsByDiagDir(dir);
75 
76  do {
77  if (HasStationReservation(tile)) return false;
78  SetRailStationReservation(tile, true);
79  MarkTileDirtyByTile(tile);
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)) {
93  if (!ReserveRailStationPlatform(tile, TrackdirToExitdir(rev_td))) {
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);
110  MarkTileDirtyByTile(tile);
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 
133 public:
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 
156  bool TryReservePath(PBSTileInfo *target, TileIndex origin)
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 
202 template <class Types>
204 {
205 public:
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 
211 protected:
213  inline Tpf &Yapf()
214  {
215  return *static_cast<Tpf *>(this);
216  }
217 
218 public:
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, true);
272  Yapf().SetDestination(v);
273  Yapf().SetMaxCost(max_penalty);
274 
275  /* find the best path */
276  if (!Yapf().FindPath(v)) return FindDepotData();
277 
278  /* Some path found. */
279  Node *n = Yapf().GetBestNode();
280 
281  /* walk through the path back to the origin */
282  Node *pNode = n;
283  while (pNode->parent != nullptr) {
284  pNode = pNode->parent;
285  }
286 
287  /* if the origin node is our front vehicle tile/Trackdir then we didn't reverse
288  * but we can also look at the cost (== 0 -> not reversed, == reverse_penalty -> reversed) */
289  return FindDepotData(n->GetLastTile(), n->cost, pNode->cost != 0);
290  }
291 };
292 
293 template <class Types>
295 {
296 public:
297  typedef typename Types::Tpf Tpf;
298  typedef typename Types::TrackFollower TrackFollower;
299  typedef typename Types::NodeList::Item Node;
300  typedef typename Node::Key Key;
301 
302 protected:
304  inline Tpf &Yapf()
305  {
306  return *static_cast<Tpf *>(this);
307  }
308 
309 public:
315  inline void PfFollowNode(Node &old_node)
316  {
317  TrackFollower F(Yapf().GetVehicle(), Yapf().GetCompatibleRailTypes());
318  if (F.Follow(old_node.GetLastTile(), old_node.GetLastTrackdir()) && F.MaskReservedTracks()) {
319  Yapf().AddMultipleNodes(&old_node, F);
320  }
321  }
322 
324  inline char TransportTypeChar() const
325  {
326  return 't';
327  }
328 
329  static bool stFindNearestSafeTile(const Train *v, TileIndex t1, Trackdir td, bool override_railtype)
330  {
331  /* Create pathfinder instance */
332  Tpf pf1;
333  bool result1;
334  if (_debug_desync_level < 2) {
335  result1 = pf1.FindNearestSafeTile(v, t1, td, override_railtype, false);
336  } else {
337  bool result2 = pf1.FindNearestSafeTile(v, t1, td, override_railtype, true);
338  Tpf pf2;
339  pf2.DisableCache(true);
340  result1 = pf2.FindNearestSafeTile(v, t1, td, override_railtype, false);
341  if (result1 != result2) {
342  Debug(desync, 2, "warning: FindSafeTile cache mismatch: {} vs {}", result2 ? "T" : "F", result1 ? "T" : "F");
343  DumpState(pf1, pf2);
344  }
345  }
346 
347  return result1;
348  }
349 
350  bool FindNearestSafeTile(const Train *v, TileIndex t1, Trackdir td, bool override_railtype, bool dont_reserve)
351  {
352  /* Set origin and destination. */
353  Yapf().SetOrigin(t1, td);
354  Yapf().SetDestination(v, override_railtype);
355 
356  if (!Yapf().FindPath(v)) return false;
357 
358  /* Found a destination, set as reservation target. */
359  Node *pNode = Yapf().GetBestNode();
360  this->SetReservationTarget(pNode, pNode->GetLastTile(), pNode->GetLastTrackdir());
361 
362  /* Walk through the path back to the origin. */
363  Node *pPrev = nullptr;
364  while (pNode->parent != nullptr) {
365  pPrev = pNode;
366  pNode = pNode->parent;
367 
368  this->FindSafePositionOnNode(pPrev);
369  }
370 
371  return dont_reserve || this->TryReservePath(nullptr, pNode->GetLastTile());
372  }
373 };
374 
375 template <class Types>
376 class CYapfFollowRailT : public CYapfReserveTrack<Types>
377 {
378 public:
379  typedef typename Types::Tpf Tpf;
380  typedef typename Types::TrackFollower TrackFollower;
381  typedef typename Types::NodeList::Item Node;
382  typedef typename Node::Key Key;
383 
384 protected:
386  inline Tpf &Yapf()
387  {
388  return *static_cast<Tpf *>(this);
389  }
390 
391 public:
397  inline void PfFollowNode(Node &old_node)
398  {
399  TrackFollower F(Yapf().GetVehicle());
400  if (F.Follow(old_node.GetLastTile(), old_node.GetLastTrackdir())) {
401  Yapf().AddMultipleNodes(&old_node, F);
402  }
403  }
404 
406  inline char TransportTypeChar() const
407  {
408  return 't';
409  }
410 
411  static Trackdir stChooseRailTrack(const Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found, bool reserve_track, PBSTileInfo *target, TileIndex *dest)
412  {
413  /* create pathfinder instance */
414  Tpf pf1;
415  Trackdir result1;
416 
417  if (_debug_desync_level < 2) {
418  result1 = pf1.ChooseRailTrack(v, tile, enterdir, tracks, path_found, reserve_track, target, dest);
419  } else {
420  result1 = pf1.ChooseRailTrack(v, tile, enterdir, tracks, path_found, false, nullptr, nullptr);
421  Tpf pf2;
422  pf2.DisableCache(true);
423  Trackdir result2 = pf2.ChooseRailTrack(v, tile, enterdir, tracks, path_found, reserve_track, target, dest);
424  if (result1 != result2) {
425  Debug(desync, 2, "warning: ChooseRailTrack cache mismatch: {} vs {}", result1, result2);
426  DumpState(pf1, pf2);
427  }
428  }
429 
430  return result1;
431  }
432 
433  inline Trackdir ChooseRailTrack(const Train *v, TileIndex, DiagDirection, TrackBits, bool &path_found, bool reserve_track, PBSTileInfo *target, TileIndex *dest)
434  {
435  if (target != nullptr) target->tile = INVALID_TILE;
436  if (dest != nullptr) *dest = INVALID_TILE;
437 
438  /* set origin and destination nodes */
440  Yapf().SetOrigin(origin.tile, origin.trackdir, INVALID_TILE, INVALID_TRACKDIR, 1, true);
441  Yapf().SetDestination(v);
442 
443  /* find the best path */
444  path_found = Yapf().FindPath(v);
445 
446  /* if path not found - return INVALID_TRACKDIR */
447  Trackdir next_trackdir = INVALID_TRACKDIR;
448  Node *pNode = Yapf().GetBestNode();
449  if (pNode != nullptr) {
450  /* reserve till end of path */
451  this->SetReservationTarget(pNode, pNode->GetLastTile(), pNode->GetLastTrackdir());
452 
453  /* path was found or at least suggested
454  * walk through the path back to the origin */
455  Node *pPrev = nullptr;
456  while (pNode->parent != nullptr) {
457  pPrev = pNode;
458  pNode = pNode->parent;
459 
460  this->FindSafePositionOnNode(pPrev);
461  }
462 
463  /* If the best PF node has no parent, then there is no (valid) best next trackdir to return.
464  * This occurs when the PF is called while the train is already at its destination. */
465  if (pPrev == nullptr) return INVALID_TRACKDIR;
466 
467  /* return trackdir from the best origin node (one of start nodes) */
468  Node &best_next_node = *pPrev;
469  next_trackdir = best_next_node.GetTrackdir();
470 
471  if (reserve_track && path_found) {
472  if (dest != nullptr) *dest = Yapf().GetBestNode()->GetLastTile();
473  this->TryReservePath(target, pNode->GetLastTile());
474  }
475  }
476 
477  /* Treat the path as found if stopped on the first two way signal(s). */
478  path_found |= Yapf().stopped_on_first_two_way_signal;
479  return next_trackdir;
480  }
481 
482  static bool stCheckReverseTrain(const Train *v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int reverse_penalty)
483  {
484  Tpf pf1;
485  bool result1 = pf1.CheckReverseTrain(v, t1, td1, t2, td2, reverse_penalty);
486 
487  if (_debug_desync_level >= 2) {
488  Tpf pf2;
489  pf2.DisableCache(true);
490  bool result2 = pf2.CheckReverseTrain(v, t1, td1, t2, td2, reverse_penalty);
491  if (result1 != result2) {
492  Debug(desync, 2, "warning: CheckReverseTrain cache mismatch: {} vs {}", result1 ? "T" : "F", result2 ? "T" : "F");
493  DumpState(pf1, pf2);
494  }
495  }
496 
497  return result1;
498  }
499 
500  inline bool CheckReverseTrain(const Train *v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int reverse_penalty)
501  {
502  /* create pathfinder instance
503  * set origin and destination nodes */
504  Yapf().SetOrigin(t1, td1, t2, td2, reverse_penalty, false);
505  Yapf().SetDestination(v);
506 
507  /* find the best path */
508  if (!Yapf().FindPath(v)) return false;
509 
510  /* path was found
511  * walk through the path back to the origin */
512  Node *pNode = Yapf().GetBestNode();
513  while (pNode->parent != nullptr) {
514  pNode = pNode->parent;
515  }
516 
517  /* check if it was reversed origin */
518  bool reversed = (pNode->cost != 0);
519  return reversed;
520  }
521 };
522 
523 template <class Tpf_, class Ttrack_follower, class Tnode_list, template <class Types> class TdestinationT, template <class Types> class TfollowT>
525 {
527 
528  typedef Tpf_ Tpf;
529  typedef Ttrack_follower TrackFollower;
530  typedef Tnode_list NodeList;
531  typedef Train VehicleType;
532  typedef CYapfBaseT<Types> PfBase;
533  typedef TfollowT<Types> PfFollow;
535  typedef TdestinationT<Types> PfDestination;
538 };
539 
540 struct CYapfRail1 : CYapfT<CYapfRail_TypesT<CYapfRail1 , CFollowTrackRail , CRailNodeListTrackDir, CYapfDestinationTileOrStationRailT, CYapfFollowRailT> > {};
541 struct CYapfRail2 : CYapfT<CYapfRail_TypesT<CYapfRail2 , CFollowTrackRailNo90, CRailNodeListTrackDir, CYapfDestinationTileOrStationRailT, CYapfFollowRailT> > {};
542 
543 struct CYapfAnyDepotRail1 : CYapfT<CYapfRail_TypesT<CYapfAnyDepotRail1, CFollowTrackRail , CRailNodeListTrackDir, CYapfDestinationAnyDepotRailT , CYapfFollowAnyDepotRailT> > {};
544 struct CYapfAnyDepotRail2 : CYapfT<CYapfRail_TypesT<CYapfAnyDepotRail2, CFollowTrackRailNo90, CRailNodeListTrackDir, CYapfDestinationAnyDepotRailT , CYapfFollowAnyDepotRailT> > {};
545 
546 struct CYapfAnySafeTileRail1 : CYapfT<CYapfRail_TypesT<CYapfAnySafeTileRail1, CFollowTrackFreeRail , CRailNodeListTrackDir, CYapfDestinationAnySafeTileRailT , CYapfFollowAnySafeTileRailT> > {};
547 struct CYapfAnySafeTileRail2 : CYapfT<CYapfRail_TypesT<CYapfAnySafeTileRail2, CFollowTrackFreeRailNo90, CRailNodeListTrackDir, CYapfDestinationAnySafeTileRailT , CYapfFollowAnySafeTileRailT> > {};
548 
549 
550 Track YapfTrainChooseTrack(const Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found, bool reserve_track, PBSTileInfo *target, TileIndex *dest)
551 {
553  ? CYapfRail2::stChooseRailTrack(v, tile, enterdir, tracks, path_found, reserve_track, target, dest)
554  : CYapfRail1::stChooseRailTrack(v, tile, enterdir, tracks, path_found, reserve_track, target, dest);
555 
556  return (td_ret != INVALID_TRACKDIR) ? TrackdirToTrack(td_ret) : FindFirstTrack(tracks);
557 }
558 
560 {
561  const Train *last_veh = v->Last();
562 
563  /* get trackdirs of both ends */
564  Trackdir td = v->GetVehicleTrackdir();
565  Trackdir td_rev = ReverseTrackdir(last_veh->GetVehicleTrackdir());
566 
567  /* tiles where front and back are */
568  TileIndex tile = v->tile;
569  TileIndex tile_rev = last_veh->tile;
570 
571  int reverse_penalty = 0;
572 
573  if (v->track == TRACK_BIT_WORMHOLE) {
574  /* front in tunnel / on bridge */
575  DiagDirection dir_into_wormhole = GetTunnelBridgeDirection(tile);
576 
577  if (TrackdirToExitdir(td) == dir_into_wormhole) tile = GetOtherTunnelBridgeEnd(tile);
578  /* Now 'tile' is the tunnel entry/bridge ramp the train will reach when driving forward */
579 
580  /* Current position of the train in the wormhole */
581  TileIndex cur_tile = TileVirtXY(v->x_pos, v->y_pos);
582 
583  /* Add distance to drive in the wormhole as penalty for the forward path, i.e. bonus for the reverse path
584  * Note: Negative penalties are ok for the start tile. */
585  reverse_penalty -= DistanceManhattan(cur_tile, tile) * YAPF_TILE_LENGTH;
586  }
587 
588  if (last_veh->track == TRACK_BIT_WORMHOLE) {
589  /* back in tunnel / on bridge */
590  DiagDirection dir_into_wormhole = GetTunnelBridgeDirection(tile_rev);
591 
592  if (TrackdirToExitdir(td_rev) == dir_into_wormhole) tile_rev = GetOtherTunnelBridgeEnd(tile_rev);
593  /* Now 'tile_rev' is the tunnel entry/bridge ramp the train will reach when reversing */
594 
595  /* Current position of the last wagon in the wormhole */
596  TileIndex cur_tile = TileVirtXY(last_veh->x_pos, last_veh->y_pos);
597 
598  /* Add distance to drive in the wormhole as penalty for the revere path. */
599  reverse_penalty += DistanceManhattan(cur_tile, tile_rev) * YAPF_TILE_LENGTH;
600  }
601 
602  /* slightly hackish: If the pathfinders finds a path, the cost of the first node is tested to distinguish between forward- and reverse-path. */
603  if (reverse_penalty == 0) reverse_penalty = 1;
604 
605  bool reverse = _settings_game.pf.forbid_90_deg
606  ? CYapfRail2::stCheckReverseTrain(v, tile, td, tile_rev, td_rev, reverse_penalty)
607  : CYapfRail1::stCheckReverseTrain(v, tile, td, tile_rev, td_rev, reverse_penalty);
608 
609  return reverse;
610 }
611 
613 {
614  const Train *last_veh = v->Last();
615 
617  TileIndex last_tile = last_veh->tile;
618  Trackdir td_rev = ReverseTrackdir(last_veh->GetVehicleTrackdir());
619 
621  ? CYapfAnyDepotRail2::stFindNearestDepotTwoWay(v, origin.tile, origin.trackdir, last_tile, td_rev, max_penalty, YAPF_INFINITE_PENALTY)
622  : CYapfAnyDepotRail1::stFindNearestDepotTwoWay(v, origin.tile, origin.trackdir, last_tile, td_rev, max_penalty, YAPF_INFINITE_PENALTY);
623 }
624 
625 bool YapfTrainFindNearestSafeTile(const Train *v, TileIndex tile, Trackdir td, bool override_railtype)
626 {
628  ? CYapfAnySafeTileRail2::stFindNearestSafeTile(v, tile, td, override_railtype)
629  : CYapfAnySafeTileRail1::stFindNearestSafeTile(v, tile, td, override_railtype);
630 }
631 
634 
636 {
637  CSegmentCostCacheBase::NotifyTrackLayoutChange(tile, track);
638 }
CYapfBaseT - A-star type path finder base class.
Definition: yapf_base.hpp:49
Types::Tpf Tpf
the pathfinder class (derived from THIS class)
Definition: yapf_rail.cpp:206
Tpf & Yapf()
to access inherited path finder
Definition: yapf_rail.cpp:213
void PfFollowNode(Node &old_node)
Called by YAPF to move from the given node to the next tile.
Definition: yapf_rail.cpp:224
char TransportTypeChar() const
return debug report character to identify the transportation type
Definition: yapf_rail.cpp:233
Types::NodeList::Item Node
this will be our node type
Definition: yapf_rail.cpp:208
Node::Key Key
key to hash tables
Definition: yapf_rail.cpp:209
Tpf & Yapf()
to access inherited path finder
Definition: yapf_rail.cpp:304
char TransportTypeChar() const
Return debug report character to identify the transportation type.
Definition: yapf_rail.cpp:324
Node::Key Key
key to hash tables
Definition: yapf_rail.cpp:300
Types::Tpf Tpf
the pathfinder class (derived from THIS class)
Definition: yapf_rail.cpp:297
void PfFollowNode(Node &old_node)
Called by YAPF to move from the given node to the next tile.
Definition: yapf_rail.cpp:315
Types::NodeList::Item Node
this will be our node type
Definition: yapf_rail.cpp:299
Node::Key Key
key to hash tables
Definition: yapf_rail.cpp:382
char TransportTypeChar() const
return debug report character to identify the transportation type
Definition: yapf_rail.cpp:406
Tpf & Yapf()
to access inherited path finder
Definition: yapf_rail.cpp:386
Types::Tpf Tpf
the pathfinder class (derived from THIS class)
Definition: yapf_rail.cpp:379
Types::NodeList::Item Node
this will be our node type
Definition: yapf_rail.cpp:381
void PfFollowNode(Node &old_node)
Called by YAPF to move from the given node to the next tile.
Definition: yapf_rail.cpp:397
YAPF origin provider base class - used when there are two tile/trackdir origins.
Definition: yapf_common.hpp:60
void SetReservationTarget(Node *node, TileIndex tile, Trackdir td)
Set the target to where the reservation should be extended.
Definition: yapf_rail.cpp:135
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.
Definition: yapf_rail.cpp:118
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.
Definition: yapf_rail.cpp:156
void FindSafePositionOnNode(Node *node)
Check the node for a possible reservation target.
Definition: yapf_rail.cpp:143
Trackdir res_dest_td
The reservation target trackdir.
Definition: yapf_rail.cpp:52
Tpf & Yapf()
to access inherited pathfinder
Definition: yapf_rail.cpp:45
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.
Definition: viewport.cpp:2057
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.
Definition: station_map.h:544
bool IsRailStationTile(Tile t)
Is this tile a station tile and a rail station?
Definition: station_map.h:102
void SetRailStationReservation(Tile t, bool b)
Set the reservation state of the rail station.
Definition: station_map.h:571
bool HasStationReservation(Tile t)
Get the reservation state of the rail station.
Definition: station_map.h:559
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
Definition: dbg_helpers.h:118
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.
Definition: train_cmd.cpp:4220
int32_t y_pos
y coordinate.
Definition: vehicle_base.h:305
int32_t x_pos
x coordinate.
Definition: vehicle_base.h:304
TileIndex tile
Current tile index.
Definition: vehicle_base.h:264
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.
Definition: yapf_rail.cpp:635
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.
Definition: yapf_rail.cpp:625
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.
Definition: yapf_rail.cpp:550
FindDepotData YapfTrainFindNearestDepot(const Train *v, int max_penalty)
Used when user sends train to the nearest depot or if train needs servicing using YAPF.
Definition: yapf_rail.cpp:612
bool YapfTrainCheckReverse(const Train *v)
Returns true if it is better to reverse the train before leaving station using YAPF.
Definition: yapf_rail.cpp:559