OpenTTD
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 
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 
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_>
124  : CYapfNodeT<Tkey_, CYapfRailNodeT<Tkey_> >
125 {
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) */
223 
224 /* Default NodeList types */
227 
228 #endif /* YAPF_NODE_RAIL_HPP */