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/>.
8 /** @file yapf_node_rail.hpp Node tailored for rail pathfinding. */
10 #ifndef YAPF_NODE_RAIL_HPP
11 #define YAPF_NODE_RAIL_HPP
13 /** key for cached segment cost for rail YAPF */
14 struct CYapfRailSegmentKey
18 inline CYapfRailSegmentKey(const CYapfNodeKeyTrackDir
&node_key
)
23 inline void Set(const CYapfRailSegmentKey
&src
)
25 m_value
= src
.m_value
;
28 inline void Set(const CYapfNodeKeyTrackDir
&node_key
)
30 m_value
= (node_key
.m_tile
.base() << 4) | node_key
.m_td
;
33 inline int32_t CalcHash() const
38 inline TileIndex
GetTile() const
40 return (TileIndex
)(m_value
>> 4);
43 inline Trackdir
GetTrackdir() const
45 return (Trackdir
)(m_value
& 0x0F);
48 inline bool operator==(const CYapfRailSegmentKey
&other
) const
50 return m_value
== other
.m_value
;
53 void Dump(DumpTarget
&dmp
) const
55 dmp
.WriteTile("tile", GetTile());
56 dmp
.WriteEnumT("td", GetTrackdir());
60 /** cached segment cost for rail YAPF */
61 struct CYapfRailSegment
63 typedef CYapfRailSegmentKey Key
;
65 CYapfRailSegmentKey m_key
;
66 TileIndex m_last_tile
;
69 TileIndex m_last_signal_tile
;
70 Trackdir m_last_signal_td
;
71 EndSegmentReasonBits m_end_segment_reason
;
72 CYapfRailSegment
*m_hash_next
;
74 inline CYapfRailSegment(const CYapfRailSegmentKey
&key
)
76 , m_last_tile(INVALID_TILE
)
77 , m_last_td(INVALID_TRACKDIR
)
79 , m_last_signal_tile(INVALID_TILE
)
80 , m_last_signal_td(INVALID_TRACKDIR
)
81 , m_end_segment_reason(ESRB_NONE
)
82 , m_hash_next(nullptr)
85 inline const Key
&GetKey() const
90 inline TileIndex
GetTile() const
92 return m_key
.GetTile();
95 inline CYapfRailSegment
*GetHashNext()
100 inline void SetHashNext(CYapfRailSegment
*next
)
105 void Dump(DumpTarget
&dmp
) const
107 dmp
.WriteStructT("m_key", &m_key
);
108 dmp
.WriteTile("m_last_tile", m_last_tile
);
109 dmp
.WriteEnumT("m_last_td", m_last_td
);
110 dmp
.WriteValue("m_cost", m_cost
);
111 dmp
.WriteTile("m_last_signal_tile", m_last_signal_tile
);
112 dmp
.WriteEnumT("m_last_signal_td", m_last_signal_td
);
113 dmp
.WriteEnumT("m_end_segment_reason", m_end_segment_reason
);
117 /** Yapf Node for rail YAPF */
118 template <class Tkey_
>
119 struct CYapfRailNodeT
120 : CYapfNodeT
<Tkey_
, CYapfRailNodeT
<Tkey_
> >
122 typedef CYapfNodeT
<Tkey_
, CYapfRailNodeT
<Tkey_
> > base
;
123 typedef CYapfRailSegment CachedData
;
125 CYapfRailSegment
*m_segment
;
126 uint16_t m_num_signals_passed
;
128 uint32_t m_inherited_flags
;
132 bool m_last_signal_was_red
;
135 SignalType m_last_red_signal_type
;
136 SignalType m_last_signal_type
;
138 inline void Set(CYapfRailNodeT
*parent
, TileIndex tile
, Trackdir td
, bool is_choice
)
140 base::Set(parent
, tile
, td
, is_choice
);
142 if (parent
== nullptr) {
143 m_num_signals_passed
= 0;
144 flags_u
.m_inherited_flags
= 0;
145 m_last_red_signal_type
= SIGTYPE_BLOCK
;
146 /* We use PBS as initial signal type because if we are in
147 * a PBS section and need to route, i.e. we're at a safe
148 * waiting point of a station, we need to account for the
149 * reservation costs. If we are in a normal block then we
150 * should be alone in there and as such the reservation
151 * costs should be 0 anyway. If there would be another
152 * train in the block, i.e. passing signals at danger
153 * then avoiding that train with help of the reservation
154 * costs is not a bad thing, actually it would probably
155 * be a good thing to do. */
156 m_last_signal_type
= SIGTYPE_PBS
;
158 m_num_signals_passed
= parent
->m_num_signals_passed
;
159 flags_u
.m_inherited_flags
= parent
->flags_u
.m_inherited_flags
;
160 m_last_red_signal_type
= parent
->m_last_red_signal_type
;
161 m_last_signal_type
= parent
->m_last_signal_type
;
163 flags_u
.flags_s
.m_choice_seen
|= is_choice
;
166 inline TileIndex
GetLastTile() const
168 assert(m_segment
!= nullptr);
169 return m_segment
->m_last_tile
;
172 inline Trackdir
GetLastTrackdir() const
174 assert(m_segment
!= nullptr);
175 return m_segment
->m_last_td
;
178 inline void SetLastTileTrackdir(TileIndex tile
, Trackdir td
)
180 assert(m_segment
!= nullptr);
181 m_segment
->m_last_tile
= tile
;
182 m_segment
->m_last_td
= td
;
185 template <class Tbase
, class Tfunc
, class Tpf
>
186 bool IterateTiles(const Train
*v
, Tpf
&yapf
, Tbase
&obj
, bool (Tfunc::*func
)(TileIndex
, Trackdir
)) const
188 typename
Tbase::TrackFollower
ft(v
, yapf
.GetCompatibleRailTypes());
189 TileIndex cur
= base::GetTile();
190 Trackdir cur_td
= base::GetTrackdir();
192 while (cur
!= GetLastTile() || cur_td
!= GetLastTrackdir()) {
193 if (!((obj
.*func
)(cur
, cur_td
))) return false;
195 if (!ft
.Follow(cur
, cur_td
)) break;
197 assert(KillFirstBit(ft
.m_new_td_bits
) == TRACKDIR_BIT_NONE
);
198 cur_td
= FindFirstTrackdir(ft
.m_new_td_bits
);
201 return (obj
.*func
)(cur
, cur_td
);
204 void Dump(DumpTarget
&dmp
) const
207 dmp
.WriteStructT("m_segment", m_segment
);
208 dmp
.WriteValue("m_num_signals_passed", m_num_signals_passed
);
209 dmp
.WriteValue("m_targed_seen", flags_u
.flags_s
.m_targed_seen
? "Yes" : "No");
210 dmp
.WriteValue("m_choice_seen", flags_u
.flags_s
.m_choice_seen
? "Yes" : "No");
211 dmp
.WriteValue("m_last_signal_was_red", flags_u
.flags_s
.m_last_signal_was_red
? "Yes" : "No");
212 dmp
.WriteEnumT("m_last_red_signal_type", m_last_red_signal_type
);
216 /* now define two major node types (that differ by key type) */
217 typedef CYapfRailNodeT
<CYapfNodeKeyExitDir
> CYapfRailNodeExitDir
;
218 typedef CYapfRailNodeT
<CYapfNodeKeyTrackDir
> CYapfRailNodeTrackDir
;
220 /* Default NodeList types */
221 typedef CNodeList_HashTableT
<CYapfRailNodeExitDir
, 8, 10> CRailNodeListExitDir
;
222 typedef CNodeList_HashTableT
<CYapfRailNodeTrackDir
, 8, 10> CRailNodeListTrackDir
;
224 #endif /* YAPF_NODE_RAIL_HPP */