OpenTTD: src/pathfinder/yapf/yapf_node_rail.hpp Source File

OpenTTD

- Main Page
- Related Pages
- Modules
- Namespaces
- Data Structures
- Files

- File List
- Globals

yapf_node_rail.hpp
Go to the documentation of this file.
1 /* $Id: yapf_node_rail.hpp 27362 2015-08-08 10:06:24Z alberth $ */
2
3 /*
4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
8 */
9
12 #ifndef YAPF_NODE_RAIL_HPP
13 #define YAPF_NODE_RAIL_HPP
14
16 struct CYapfRailSegmentKey
17 {
18 uint32 m_value;
19
20 inline CYapfRailSegmentKey(const CYapfRailSegmentKey &src) : m_value(src.m_value) {}
21
22 inline CYapfRailSegmentKey(const CYapfNodeKeyTrackDir &node_key)
23 {
24 Set(node_key);
25 }
26
27 inline void Set(const CYapfRailSegmentKey &src)
28 {
29 m_value = src.m_value;
30 }
31
32 inline void Set(const CYapfNodeKeyTrackDir &node_key)
33 {
34 m_value = (((int)node_key.m_tile) << 4) | node_key.m_td;
35 }
36
37 inline int32 CalcHash() const
38 {
39 return m_value;
40 }
41
42 inline TileIndex GetTile() const
43 {
44 return (TileIndex)(m_value >> 4);
45 }
46
47 inline Trackdir GetTrackdir() const
48 {
49 return (Trackdir)(m_value & 0x0F);
50 }
51
52 inline bool operator==(const CYapfRailSegmentKey &other) const
53 {
54 return m_value == other.m_value;
55 }
56
57 void Dump(DumpTarget &dmp) const
58 {
59 dmp.WriteTile("tile", GetTile());
60 dmp.WriteEnumT("td", GetTrackdir());
61 }
62 };
63
65 struct CYapfRailSegment
66 {
67 typedef CYapfRailSegmentKey Key;
68
69 CYapfRailSegmentKey m_key;
70 TileIndex m_last_tile;
71 Trackdir m_last_td;
72 int m_cost;
73 TileIndex m_last_signal_tile;
74 Trackdir m_last_signal_td;
75 EndSegmentReasonBits m_end_segment_reason;
76 CYapfRailSegment *m_hash_next;
77
78 inline CYapfRailSegment(const CYapfRailSegmentKey &key)
79 : m_key(key)
80 , m_last_tile(INVALID_TILE)
81 , m_last_td(INVALID_TRACKDIR)
82 , m_cost(-1)
83 , m_last_signal_tile(INVALID_TILE)
84 , m_last_signal_td(INVALID_TRACKDIR)
85 , m_end_segment_reason(ESRB_NONE)
86 , m_hash_next(NULL)
87 {}
88
89 inline const Key& GetKey() const
90 {
91 return m_key;
92 }
93
94 inline TileIndex GetTile() const
95 {
96 return m_key.GetTile();
97 }
98
99 inline CYapfRailSegment *GetHashNext()
100 {
101 return m_hash_next;
102 }
103
104 inline void SetHashNext(CYapfRailSegment *next)
105 {
106 m_hash_next = next;
107 }
108
109 void Dump(DumpTarget &dmp) const
110 {
111 dmp.WriteStructT("m_key", &m_key);
112 dmp.WriteTile("m_last_tile", m_last_tile);
113 dmp.WriteEnumT("m_last_td", m_last_td);
114 dmp.WriteLine("m_cost = %d", m_cost);
115 dmp.WriteTile("m_last_signal_tile", m_last_signal_tile);
116 dmp.WriteEnumT("m_last_signal_td", m_last_signal_td);
117 dmp.WriteEnumT("m_end_segment_reason", m_end_segment_reason);
118 }
119 };
120
122 template <class Tkey_>
123 struct CYapfRailNodeT
124 : CYapfNodeT<Tkey_, CYapfRailNodeT<Tkey_> >
125 {
126 typedef CYapfNodeT<Tkey_, CYapfRailNodeT<Tkey_> > base;
127 typedef CYapfRailSegment CachedData;
128
129 CYapfRailSegment *m_segment;
130 uint16 m_num_signals_passed;
131 union {
132 uint32 m_inherited_flags;
133 struct {
134 bool m_targed_seen : 1;
135 bool m_choice_seen : 1;
136 bool m_last_signal_was_red : 1;
137 } flags_s;
138 } flags_u;
139 SignalType m_last_red_signal_type;
140 SignalType m_last_signal_type;
141
142 inline void Set(CYapfRailNodeT *parent, TileIndex tile, Trackdir td, bool is_choice)
143 {
144 base::Set(parent, tile, td, is_choice);
145 m_segment = NULL;
146 if (parent == NULL) {
147 m_num_signals_passed = 0;
148 flags_u.m_inherited_flags = 0;
149 m_last_red_signal_type = SIGTYPE_NORMAL;
150 /* We use PBS as initial signal type because if we are in
151 * a PBS section and need to route, i.e. we're at a safe
152 * waiting point of a station, we need to account for the
153 * reservation costs. If we are in a normal block then we
154 * should be alone in there and as such the reservation
155 * costs should be 0 anyway. If there would be another
156 * train in the block, i.e. passing signals at danger
157 * then avoiding that train with help of the reservation
158 * costs is not a bad thing, actually it would probably
159 * be a good thing to do. */
160 m_last_signal_type = SIGTYPE_PBS;
161 } else {
162 m_num_signals_passed = parent->m_num_signals_passed;
163 flags_u.m_inherited_flags = parent->flags_u.m_inherited_flags;
164 m_last_red_signal_type = parent->m_last_red_signal_type;
165 m_last_signal_type = parent->m_last_signal_type;
166 }
167 flags_u.flags_s.m_choice_seen |= is_choice;
168 }
169
170 inline TileIndex GetLastTile() const
171 {
172 assert(m_segment != NULL);
173 return m_segment->m_last_tile;
174 }
175
176 inline Trackdir GetLastTrackdir() const
177 {
178 assert(m_segment != NULL);
179 return m_segment->m_last_td;
180 }
181
182 inline void SetLastTileTrackdir(TileIndex tile, Trackdir td)
183 {
184 assert(m_segment != NULL);
185 m_segment->m_last_tile = tile;
186 m_segment->m_last_td = td;
187 }
188
189 template <class Tbase, class Tfunc, class Tpf>
190 bool IterateTiles(const Train *v, Tpf &yapf, Tbase &obj, bool (Tfunc::*func)(TileIndex, Trackdir)) const
191 {
192 typename Tbase::TrackFollower ft(v, yapf.GetCompatibleRailTypes());
193 TileIndex cur = base::GetTile();
194 Trackdir cur_td = base::GetTrackdir();
195
196 while (cur != GetLastTile() || cur_td != GetLastTrackdir()) {
197 if (!((obj.*func)(cur, cur_td))) return false;
198
199 if (!ft.Follow(cur, cur_td)) break;
200 cur = ft.m_new_tile;
201 assert(KillFirstBit(ft.m_new_td_bits) == TRACKDIR_BIT_NONE);
202 cur_td = FindFirstTrackdir(ft.m_new_td_bits);
203 }
204
205 return (obj.*func)(cur, cur_td);
206 }
207
208 void Dump(DumpTarget &dmp) const
209 {
210 base::Dump(dmp);
211 dmp.WriteStructT("m_segment", m_segment);
212 dmp.WriteLine("m_num_signals_passed = %d", m_num_signals_passed);
213 dmp.WriteLine("m_targed_seen = %s", flags_u.flags_s.m_targed_seen ? "Yes" : "No");
214 dmp.WriteLine("m_choice_seen = %s", flags_u.flags_s.m_choice_seen ? "Yes" : "No");
215 dmp.WriteLine("m_last_signal_was_red = %s", flags_u.flags_s.m_last_signal_was_red ? "Yes" : "No");
216 dmp.WriteEnumT("m_last_red_signal_type", m_last_red_signal_type);
217 }
218 };
219
220 /* now define two major node types (that differ by key type) */
221 typedef CYapfRailNodeT<CYapfNodeKeyExitDir> CYapfRailNodeExitDir;
222 typedef CYapfRailNodeT<CYapfNodeKeyTrackDir> CYapfRailNodeTrackDir;
223
224 /* Default NodeList types */
225 typedef CNodeList_HashTableT<CYapfRailNodeExitDir , 8, 10> CRailNodeListExitDir;
226 typedef CNodeList_HashTableT<CYapfRailNodeTrackDir, 8, 10> CRailNodeListTrackDir;
227
228 #endif /* YAPF_NODE_RAIL_HPP */