00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #ifndef YAPF_NODE_RAIL_HPP
00013 #define YAPF_NODE_RAIL_HPP
00014
00016 struct CYapfRailSegmentKey
00017 {
00018 uint32 m_value;
00019
00020 FORCEINLINE CYapfRailSegmentKey(const CYapfRailSegmentKey& src) : m_value(src.m_value) {}
00021
00022 FORCEINLINE CYapfRailSegmentKey(const CYapfNodeKeyTrackDir& node_key)
00023 {
00024 Set(node_key);
00025 }
00026
00027 FORCEINLINE void Set(const CYapfRailSegmentKey& src)
00028 {
00029 m_value = src.m_value;
00030 }
00031
00032 FORCEINLINE void Set(const CYapfNodeKeyTrackDir& node_key)
00033 {
00034 m_value = (((int)node_key.m_tile) << 4) | node_key.m_td;
00035 }
00036
00037 FORCEINLINE int32 CalcHash() const
00038 {
00039 return m_value;
00040 }
00041
00042 FORCEINLINE TileIndex GetTile() const
00043 {
00044 return (TileIndex)(m_value >> 4);
00045 }
00046
00047 FORCEINLINE Trackdir GetTrackdir() const
00048 {
00049 return (Trackdir)(m_value & 0x0F);
00050 }
00051
00052 FORCEINLINE bool operator == (const CYapfRailSegmentKey& other) const
00053 {
00054 return m_value == other.m_value;
00055 }
00056
00057 void Dump(DumpTarget &dmp) const
00058 {
00059 dmp.WriteTile("tile", GetTile());
00060 dmp.WriteEnumT("td", GetTrackdir());
00061 }
00062 };
00063
00064
00065 enum EndSegmentReason {
00066
00067 ESR_DEAD_END = 0,
00068 ESR_RAIL_TYPE,
00069 ESR_INFINITE_LOOP,
00070 ESR_SEGMENT_TOO_LONG,
00071 ESR_CHOICE_FOLLOWS,
00072 ESR_DEPOT,
00073 ESR_WAYPOINT,
00074 ESR_STATION,
00075 ESR_SAFE_TILE,
00076
00077
00078
00079 ESR_PATH_TOO_LONG,
00080 ESR_FIRST_TWO_WAY_RED,
00081 ESR_LOOK_AHEAD_END,
00082 ESR_TARGET_REACHED,
00083
00084
00085 ESR_NONE = 0xFF,
00086 };
00087
00088 enum EndSegmentReasonBits {
00089 ESRB_NONE = 0,
00090
00091 ESRB_DEAD_END = 1 << ESR_DEAD_END,
00092 ESRB_RAIL_TYPE = 1 << ESR_RAIL_TYPE,
00093 ESRB_INFINITE_LOOP = 1 << ESR_INFINITE_LOOP,
00094 ESRB_SEGMENT_TOO_LONG = 1 << ESR_SEGMENT_TOO_LONG,
00095 ESRB_CHOICE_FOLLOWS = 1 << ESR_CHOICE_FOLLOWS,
00096 ESRB_DEPOT = 1 << ESR_DEPOT,
00097 ESRB_WAYPOINT = 1 << ESR_WAYPOINT,
00098 ESRB_STATION = 1 << ESR_STATION,
00099 ESRB_SAFE_TILE = 1 << ESR_SAFE_TILE,
00100
00101 ESRB_PATH_TOO_LONG = 1 << ESR_PATH_TOO_LONG,
00102 ESRB_FIRST_TWO_WAY_RED = 1 << ESR_FIRST_TWO_WAY_RED,
00103 ESRB_LOOK_AHEAD_END = 1 << ESR_LOOK_AHEAD_END,
00104 ESRB_TARGET_REACHED = 1 << ESR_TARGET_REACHED,
00105
00106
00107
00108
00109 ESRB_POSSIBLE_TARGET = ESRB_DEPOT | ESRB_WAYPOINT | ESRB_STATION | ESRB_SAFE_TILE,
00110
00111
00112 ESRB_CACHED_MASK = ESRB_DEAD_END | ESRB_RAIL_TYPE | ESRB_INFINITE_LOOP | ESRB_SEGMENT_TOO_LONG | ESRB_CHOICE_FOLLOWS | ESRB_DEPOT | ESRB_WAYPOINT | ESRB_STATION | ESRB_SAFE_TILE,
00113
00114
00115 ESRB_ABORT_PF_MASK = ESRB_DEAD_END | ESRB_PATH_TOO_LONG | ESRB_INFINITE_LOOP | ESRB_FIRST_TWO_WAY_RED,
00116 };
00117
00118 DECLARE_ENUM_AS_BIT_SET(EndSegmentReasonBits)
00119
00120 inline CStrA ValueStr(EndSegmentReasonBits bits)
00121 {
00122 static const char * const end_segment_reason_names[] = {
00123 "DEAD_END", "RAIL_TYPE", "INFINITE_LOOP", "SEGMENT_TOO_LONG", "CHOICE_FOLLOWS",
00124 "DEPOT", "WAYPOINT", "STATION", "SAFE_TILE",
00125 "PATH_TOO_LONG", "FIRST_TWO_WAY_RED", "LOOK_AHEAD_END", "TARGET_REACHED"
00126 };
00127
00128 CStrA out;
00129 out.Format("0x%04X (%s)", bits, ComposeNameT(bits, end_segment_reason_names, "UNK", ESRB_NONE, "NONE").Data());
00130 return out.Transfer();
00131 }
00132
00134 struct CYapfRailSegment
00135 {
00136 typedef CYapfRailSegmentKey Key;
00137
00138 CYapfRailSegmentKey m_key;
00139 TileIndex m_last_tile;
00140 Trackdir m_last_td;
00141 int m_cost;
00142 TileIndex m_last_signal_tile;
00143 Trackdir m_last_signal_td;
00144 EndSegmentReasonBits m_end_segment_reason;
00145 CYapfRailSegment *m_hash_next;
00146
00147 FORCEINLINE CYapfRailSegment(const CYapfRailSegmentKey& key)
00148 : m_key(key)
00149 , m_last_tile(INVALID_TILE)
00150 , m_last_td(INVALID_TRACKDIR)
00151 , m_cost(-1)
00152 , m_last_signal_tile(INVALID_TILE)
00153 , m_last_signal_td(INVALID_TRACKDIR)
00154 , m_end_segment_reason(ESRB_NONE)
00155 , m_hash_next(NULL)
00156 {}
00157
00158 FORCEINLINE const Key& GetKey() const
00159 {
00160 return m_key;
00161 }
00162
00163 FORCEINLINE TileIndex GetTile() const
00164 {
00165 return m_key.GetTile();
00166 }
00167
00168 FORCEINLINE CYapfRailSegment *GetHashNext()
00169 {
00170 return m_hash_next;
00171 }
00172
00173 FORCEINLINE void SetHashNext(CYapfRailSegment *next)
00174 {
00175 m_hash_next = next;
00176 }
00177
00178 void Dump(DumpTarget &dmp) const
00179 {
00180 dmp.WriteStructT("m_key", &m_key);
00181 dmp.WriteTile("m_last_tile", m_last_tile);
00182 dmp.WriteEnumT("m_last_td", m_last_td);
00183 dmp.WriteLine("m_cost = %d", m_cost);
00184 dmp.WriteTile("m_last_signal_tile", m_last_signal_tile);
00185 dmp.WriteEnumT("m_last_signal_td", m_last_signal_td);
00186 dmp.WriteEnumT("m_end_segment_reason", m_end_segment_reason);
00187 }
00188 };
00189
00191 template <class Tkey_>
00192 struct CYapfRailNodeT
00193 : CYapfNodeT<Tkey_, CYapfRailNodeT<Tkey_> >
00194 {
00195 typedef CYapfNodeT<Tkey_, CYapfRailNodeT<Tkey_> > base;
00196 typedef CYapfRailSegment CachedData;
00197
00198 CYapfRailSegment *m_segment;
00199 uint16 m_num_signals_passed;
00200 union {
00201 uint32 m_inherited_flags;
00202 struct {
00203 bool m_targed_seen : 1;
00204 bool m_choice_seen : 1;
00205 bool m_last_signal_was_red : 1;
00206 } flags_s;
00207 } flags_u;
00208 SignalType m_last_red_signal_type;
00209 SignalType m_last_signal_type;
00210
00211 FORCEINLINE void Set(CYapfRailNodeT *parent, TileIndex tile, Trackdir td, bool is_choice)
00212 {
00213 base::Set(parent, tile, td, is_choice);
00214 m_segment = NULL;
00215 if (parent == NULL) {
00216 m_num_signals_passed = 0;
00217 flags_u.m_inherited_flags = 0;
00218 m_last_red_signal_type = SIGTYPE_NORMAL;
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229 m_last_signal_type = SIGTYPE_PBS;
00230 } else {
00231 m_num_signals_passed = parent->m_num_signals_passed;
00232 flags_u.m_inherited_flags = parent->flags_u.m_inherited_flags;
00233 m_last_red_signal_type = parent->m_last_red_signal_type;
00234 m_last_signal_type = parent->m_last_signal_type;
00235 }
00236 flags_u.flags_s.m_choice_seen |= is_choice;
00237 }
00238
00239 FORCEINLINE TileIndex GetLastTile() const
00240 {
00241 assert(m_segment != NULL);
00242 return m_segment->m_last_tile;
00243 }
00244
00245 FORCEINLINE Trackdir GetLastTrackdir() const
00246 {
00247 assert(m_segment != NULL);
00248 return m_segment->m_last_td;
00249 }
00250
00251 FORCEINLINE void SetLastTileTrackdir(TileIndex tile, Trackdir td)
00252 {
00253 assert(m_segment != NULL);
00254 m_segment->m_last_tile = tile;
00255 m_segment->m_last_td = td;
00256 }
00257
00258 template <class Tbase, class Tfunc, class Tpf>
00259 bool IterateTiles(const Train *v, Tpf &yapf, Tbase &obj, bool (Tfunc::*func)(TileIndex, Trackdir)) const
00260 {
00261 typename Tbase::TrackFollower ft(v, yapf.GetCompatibleRailTypes());
00262 TileIndex cur = base::GetTile();
00263 Trackdir cur_td = base::GetTrackdir();
00264
00265 while (cur != GetLastTile() || cur_td != GetLastTrackdir()) {
00266 if (!((obj.*func)(cur, cur_td))) return false;
00267
00268 ft.Follow(cur, cur_td);
00269 cur = ft.m_new_tile;
00270 assert(KillFirstBit(ft.m_new_td_bits) == TRACKDIR_BIT_NONE);
00271 cur_td = FindFirstTrackdir(ft.m_new_td_bits);
00272 }
00273
00274 return (obj.*func)(cur, cur_td);
00275 }
00276
00277 void Dump(DumpTarget &dmp) const
00278 {
00279 base::Dump(dmp);
00280 dmp.WriteStructT("m_segment", m_segment);
00281 dmp.WriteLine("m_num_signals_passed = %d", m_num_signals_passed);
00282 dmp.WriteLine("m_targed_seen = %s", flags_u.flags_s.m_targed_seen ? "Yes" : "No");
00283 dmp.WriteLine("m_choice_seen = %s", flags_u.flags_s.m_choice_seen ? "Yes" : "No");
00284 dmp.WriteLine("m_last_signal_was_red = %s", flags_u.flags_s.m_last_signal_was_red ? "Yes" : "No");
00285 dmp.WriteEnumT("m_last_red_signal_type", m_last_red_signal_type);
00286 }
00287 };
00288
00289
00290 typedef CYapfRailNodeT<CYapfNodeKeyExitDir> CYapfRailNodeExitDir;
00291 typedef CYapfRailNodeT<CYapfNodeKeyTrackDir> CYapfRailNodeTrackDir;
00292
00293
00294 typedef CNodeList_HashTableT<CYapfRailNodeExitDir , 10, 12> CRailNodeListExitDir;
00295 typedef CNodeList_HashTableT<CYapfRailNodeTrackDir, 12, 16> CRailNodeListTrackDir;
00296
00297 #endif