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