# yapf_node_rail.hpp

Go to the documentation of this file.

    00001 /* $Id: yapf_node_rail.hpp 16704 2009-06-30 20:11:36Z rubidium $ */
    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 /* Enum used in PfCalcCost() to see why was the segment closed. */
    00058 enum EndSegmentReason {
    00059   /* The following reasons can be saved into cached segment */
    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   /* The following reasons are used only internally by PfCalcCost().
    00071    *  They should not be found in the cached segment. */
    00072   ESR_PATH_TOO_LONG,
    00073   ESR_FIRST_TWO_WAY_RED,
    00074   ESR_LOOK_AHEAD_END,
    00075   ESR_TARGET_REACHED,
    00076
    00077   /* Special values */
    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   /* Additional (composite) values. */
    00100
    00101   /* What reasons mean that the target can be found and needs to be detected. */
    00102   ESRB_POSSIBLE_TARGET = ESRB_DEPOT | ESRB_WAYPOINT | ESRB_STATION | ESRB_SAFE_TILE,
    00103
    00104   /* What reasons can be stored back into cached segment. */
    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   /* Reasons to abort pathfinding in this direction. */
    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", "SAFE_TILE",
    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 /* now define two major node types (that differ by key type) */
    00270 typedef CYapfRailNodeT<CYapfNodeKeyExitDir>  CYapfRailNodeExitDir;
    00271 typedef CYapfRailNodeT<CYapfNodeKeyTrackDir> CYapfRailNodeTrackDir;
    00272
    00273 /* Default NodeList types */
    00274 typedef CNodeList_HashTableT<CYapfRailNodeExitDir , 10, 12> CRailNodeListExitDir;
    00275 typedef CNodeList_HashTableT<CYapfRailNodeTrackDir, 12, 16> CRailNodeListTrackDir;
    00276
    00277 #endif /* YAPF_NODE_RAIL_HPP */