OpenTTD Source 20250905-master-g122023be8d
yapf_node_rail.hpp
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#ifndef YAPF_NODE_RAIL_HPP
11#define YAPF_NODE_RAIL_HPP
12
13#include "../../misc/dbg_helpers.h"
14#include "../../train.h"
15#include "nodelist.hpp"
16#include "yapf_node.hpp"
17#include "yapf_type.hpp"
18
21 uint32_t value;
22
23 inline CYapfRailSegmentKey(const CYapfNodeKeyTrackDir &node_key)
24 {
25 this->Set(node_key);
26 }
27
28 inline void Set(const CYapfRailSegmentKey &src)
29 {
30 this->value = src.value;
31 }
32
33 inline void Set(const CYapfNodeKeyTrackDir &node_key)
34 {
35 this->value = (node_key.tile.base() << 4) | node_key.td;
36 }
37
38 inline int32_t CalcHash() const
39 {
40 return this->value;
41 }
42
43 inline TileIndex GetTile() const
44 {
45 return (TileIndex)(this->value >> 4);
46 }
47
48 inline Trackdir GetTrackdir() const
49 {
50 return (Trackdir)(this->value & 0x0F);
51 }
52
53 inline bool operator==(const CYapfRailSegmentKey &other) const
54 {
55 return this->value == other.value;
56 }
57
58 void Dump(DumpTarget &dmp) const
59 {
60 dmp.WriteTile("tile", this->GetTile());
61 dmp.WriteEnumT("td", this->GetTrackdir());
62 }
63};
64
68
70 TileIndex last_tile = INVALID_TILE;
71 Trackdir last_td = INVALID_TRACKDIR;
72 int cost = -1;
73 TileIndex last_signal_tile = INVALID_TILE;
74 Trackdir last_signal_td = INVALID_TRACKDIR;
75 EndSegmentReasons end_segment_reason{};
76 CYapfRailSegment *hash_next = nullptr;
77
78 inline CYapfRailSegment(const CYapfRailSegmentKey &key) : key(key) {}
79
80 inline const Key &GetKey() const
81 {
82 return this->key;
83 }
84
85 inline TileIndex GetTile() const
86 {
87 return this->key.GetTile();
88 }
89
90 inline CYapfRailSegment *GetHashNext()
91 {
92 return this->hash_next;
93 }
94
95 inline void SetHashNext(CYapfRailSegment *next)
96 {
97 this->hash_next = next;
98 }
99
100 void Dump(DumpTarget &dmp) const
101 {
102 dmp.WriteStructT("key", &this->key);
103 dmp.WriteTile("last_tile", this->last_tile);
104 dmp.WriteEnumT("last_td", this->last_td);
105 dmp.WriteValue("cost", this->cost);
106 dmp.WriteTile("last_signal_tile", this->last_signal_tile);
107 dmp.WriteEnumT("last_signal_td", this->last_signal_td);
108 dmp.WriteEnumT("end_segment_reason", this->end_segment_reason);
109 }
110};
111
113template <class Tkey_>
114struct CYapfRailNodeT : CYapfNodeT<Tkey_, CYapfRailNodeT<Tkey_>> {
117
118 CYapfRailSegment *segment;
119 uint16_t num_signals_passed;
120 union {
121 uint32_t inherited_flags;
122 struct {
123 bool target_seen;
124 bool choice_seen;
125 bool last_signal_was_red;
126 } flags_s;
127 } flags_u;
128 SignalType last_red_signal_type;
129 SignalType last_signal_type;
130
131 inline void Set(CYapfRailNodeT *parent, TileIndex tile, Trackdir td, bool is_choice)
132 {
133 this->base::Set(parent, tile, td, is_choice);
134 this->segment = nullptr;
135 if (parent == nullptr) {
136 this->num_signals_passed = 0;
137 this->flags_u.inherited_flags = 0;
138 this->last_red_signal_type = SIGTYPE_BLOCK;
139 /* We use PBS as initial signal type because if we are in
140 * a PBS section and need to route, i.e. we're at a safe
141 * waiting point of a station, we need to account for the
142 * reservation costs. If we are in a normal block then we
143 * should be alone in there and as such the reservation
144 * costs should be 0 anyway. If there would be another
145 * train in the block, i.e. passing signals at danger
146 * then avoiding that train with help of the reservation
147 * costs is not a bad thing, actually it would probably
148 * be a good thing to do. */
149 this->last_signal_type = SIGTYPE_PBS;
150 } else {
151 this->num_signals_passed = parent->num_signals_passed;
152 this->flags_u.inherited_flags = parent->flags_u.inherited_flags;
153 this->last_red_signal_type = parent->last_red_signal_type;
154 this->last_signal_type = parent->last_signal_type;
155 }
156 this->flags_u.flags_s.choice_seen |= is_choice;
157 }
158
159 inline TileIndex GetLastTile() const
160 {
161 assert(this->segment != nullptr);
162 return this->segment->last_tile;
163 }
164
165 inline Trackdir GetLastTrackdir() const
166 {
167 assert(this->segment != nullptr);
168 return this->segment->last_td;
169 }
170
171 inline void SetLastTileTrackdir(TileIndex tile, Trackdir td)
172 {
173 assert(this->segment != nullptr);
174 this->segment->last_tile = tile;
175 this->segment->last_td = td;
176 }
177
178 template <class Tbase, class Tfunc, class Tpf>
179 bool IterateTiles(const Train *v, Tpf &yapf, Tbase &obj, bool (Tfunc::*func)(TileIndex, Trackdir)) const
180 {
181 typename Tbase::TrackFollower ft(v, yapf.GetCompatibleRailTypes());
182 TileIndex cur = this->base::GetTile();
183 Trackdir cur_td = this->base::GetTrackdir();
184
185 while (cur != this->GetLastTile() || cur_td != this->GetLastTrackdir()) {
186 if (!((obj.*func)(cur, cur_td))) return false;
187
188 if (!ft.Follow(cur, cur_td)) break;
189 cur = ft.new_tile;
190 assert(KillFirstBit(ft.new_td_bits) == TRACKDIR_BIT_NONE);
191 cur_td = FindFirstTrackdir(ft.new_td_bits);
192 }
193
194 return (obj.*func)(cur, cur_td);
195 }
196
197 void Dump(DumpTarget &dmp) const
198 {
199 this->base::Dump(dmp);
200 dmp.WriteStructT("segment", this->segment);
201 dmp.WriteValue("num_signals_passed", this->num_signals_passed);
202 dmp.WriteValue("target_seen", this->flags_u.flags_s.target_seen ? "Yes" : "No");
203 dmp.WriteValue("choice_seen", this->flags_u.flags_s.choice_seen ? "Yes" : "No");
204 dmp.WriteValue("last_signal_was_red", this->flags_u.flags_s.last_signal_was_red ? "Yes" : "No");
205 dmp.WriteEnumT("last_red_signal_type", this->last_red_signal_type);
206 }
207};
208
209/* now define two major node types (that differ by key type) */
212
213/* Default NodeList types */
216
217#endif /* YAPF_NODE_RAIL_HPP */
constexpr T KillFirstBit(T value)
Clear the first bit in an integer.
Hash table based node list multi-container class.
Definition nodelist.hpp:21
List of nodes used for the A-star pathfinder.
SignalType
Type of signal, i.e.
Definition signal_type.h:23
@ SIGTYPE_PBS
normal pbs signal
Definition signal_type.h:28
@ SIGTYPE_BLOCK
block signal
Definition signal_type.h:24
Yapf Node base.
Definition yapf_node.hpp:61
Yapf Node for rail YAPF.
key for cached segment cost for rail YAPF
cached segment cost for rail YAPF
Class that represents the dump-into-string target.
void WriteTile(std::string_view name, TileIndex t)
Write name & TileIndex to the output.
void WriteStructT(std::string_view name, const S *s)
Dump nested object (or only its name if this instance is already known).
void WriteEnumT(std::string_view name, E e)
Dump given enum value (as a number and as named value)
void WriteValue(std::string_view name, const auto &value)
Write 'name = value' with indent and new-line.
'Train' is either a loco or a wagon.
Definition train.h:91
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:95
Trackdir FindFirstTrackdir(TrackdirBits trackdirs)
Returns first Trackdir from TrackdirBits or INVALID_TRACKDIR.
Definition track_func.h:211
Trackdir
Enumeration for tracks and directions.
Definition track_type.h:66
@ INVALID_TRACKDIR
Flag for an invalid trackdir.
Definition track_type.h:85
@ TRACKDIR_BIT_NONE
No track build.
Definition track_type.h:98
Node in the pathfinder's graph.
Types used by YAPF.