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