# yapf_node_rail.hpp

Go to the documentation of this file.

    00001 /* $Id: yapf_node_rail.hpp 10393 2007-06-29 23:50:42Z KUDr $ */
    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 /* Enum used in PfCalcCost() to see why was the segment closed. */
    00032 enum EndSegmentReason {
    00033   /* The following reasons can be saved into cached segment */
    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
    00043   /* The following reasons are used only internally by PfCalcCost().
    00044   *   They should not be found in the cached segment. */
    00045   ESR_PATH_TOO_LONG,
    00046   ESR_FIRST_TWO_WAY_RED,
    00047   ESR_LOOK_AHEAD_END,
    00048   ESR_TARGET_REACHED,
    00049
    00050   /* Special values */
    00051   ESR_NONE = 0xFF,
    00052 };
    00053
    00054 enum EndSegmentReasonBits {
    00055   ESRB_NONE = 0,
    00056
    00057   ESRB_DEAD_END          = 1 << ESR_DEAD_END,
    00058   ESRB_RAIL_TYPE         = 1 << ESR_RAIL_TYPE,
    00059   ESRB_INFINITE_LOOP     = 1 << ESR_INFINITE_LOOP,
    00060   ESRB_SEGMENT_TOO_LONG  = 1 << ESR_SEGMENT_TOO_LONG,
    00061   ESRB_CHOICE_FOLLOWS    = 1 << ESR_CHOICE_FOLLOWS,
    00062   ESRB_DEPOT             = 1 << ESR_DEPOT,
    00063   ESRB_WAYPOINT          = 1 << ESR_WAYPOINT,
    00064   ESRB_STATION           = 1 << ESR_STATION,
    00065
    00066   ESRB_PATH_TOO_LONG     = 1 << ESR_PATH_TOO_LONG,
    00067   ESRB_FIRST_TWO_WAY_RED = 1 << ESR_FIRST_TWO_WAY_RED,
    00068   ESRB_LOOK_AHEAD_END    = 1 << ESR_LOOK_AHEAD_END,
    00069   ESRB_TARGET_REACHED    = 1 << ESR_TARGET_REACHED,
    00070
    00071   /* Additional (composite) values. */
    00072
    00073   /* What reasons mean that the target can be found and needs to be detected. */
    00074   ESRB_POSSIBLE_TARGET = ESRB_DEPOT | ESRB_WAYPOINT | ESRB_STATION,
    00075
    00076   /* What reasons can be stored back into cached segment. */
    00077   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,
    00078
    00079   /* Reasons to abort pathfinding in this direction. */
    00080   ESRB_ABORT_PF_MASK = ESRB_DEAD_END | ESRB_PATH_TOO_LONG | ESRB_INFINITE_LOOP | ESRB_FIRST_TWO_WAY_RED,
    00081 };
    00082
    00083 DECLARE_ENUM_AS_BIT_SET(EndSegmentReasonBits);
    00084
    00085 inline CStrA ValueStr(EndSegmentReasonBits bits)
    00086 {
    00087   static const char* end_segment_reason_names[] = {
    00088     "DEAD_END", "RAIL_TYPE", "INFINITE_LOOP", "SEGMENT_TOO_LONG", "CHOICE_FOLLOWS",
    00089     "DEPOT", "WAYPOINT", "STATION",
    00090     "PATH_TOO_LONG", "FIRST_TWO_WAY_RED", "LOOK_AHEAD_END", "TARGET_REACHED"
    00091   };
    00092
    00093   CStrA out;
    00094   out.Format("0x%04X (%s)", bits, ComposeNameT(bits, end_segment_reason_names, "UNK", ESRB_NONE, "NONE").Data());
    00095   return out.Transfer();
    00096 }
    00097
    00099 struct CYapfRailSegment
    00100 {
    00101   typedef CYapfRailSegmentKey Key;
    00102
    00103   CYapfRailSegmentKey    m_key;
    00104   TileIndex              m_last_tile;
    00105   Trackdir               m_last_td;
    00106   int                    m_cost;
    00107   TileIndex              m_last_signal_tile;
    00108   Trackdir               m_last_signal_td;
    00109   EndSegmentReasonBits   m_end_segment_reason;
    00110   CYapfRailSegment*      m_hash_next;
    00111
    00112   FORCEINLINE CYapfRailSegment(const CYapfRailSegmentKey& key)
    00113     : m_key(key)
    00114     , m_last_tile(INVALID_TILE)
    00115     , m_last_td(INVALID_TRACKDIR)
    00116     , m_cost(-1)
    00117     , m_last_signal_tile(INVALID_TILE)
    00118     , m_last_signal_td(INVALID_TRACKDIR)
    00119     , m_end_segment_reason(ESRB_NONE)
    00120     , m_hash_next(NULL)
    00121   {}
    00122
    00123   FORCEINLINE const Key& GetKey() const {return m_key;}
    00124   FORCEINLINE TileIndex GetTile() const {return m_key.GetTile();}
    00125   FORCEINLINE CYapfRailSegment* GetHashNext() {return m_hash_next;}
    00126   FORCEINLINE void SetHashNext(CYapfRailSegment* next) {m_hash_next = next;}
    00127
    00128   void Dump(DumpTarget &dmp) const
    00129   {
    00130     dmp.WriteStructT("m_key", &m_key);
    00131     dmp.WriteTile("m_last_tile", m_last_tile);
    00132     dmp.WriteEnumT("m_last_td", m_last_td);
    00133     dmp.WriteLine("m_cost = %d", m_cost);
    00134     dmp.WriteTile("m_last_signal_tile", m_last_signal_tile);
    00135     dmp.WriteEnumT("m_last_signal_td", m_last_signal_td);
    00136     dmp.WriteEnumT("m_end_segment_reason", m_end_segment_reason);
    00137   }
    00138 };
    00139
    00141 template <class Tkey_>
    00142 struct CYapfRailNodeT
    00143   : CYapfNodeT<Tkey_, CYapfRailNodeT<Tkey_> >
    00144 {
    00145   typedef CYapfNodeT<Tkey_, CYapfRailNodeT<Tkey_> > base;
    00146   typedef CYapfRailSegment CachedData;
    00147
    00148   CYapfRailSegment *m_segment;
    00149   uint16            m_num_signals_passed;
    00150   union {
    00151     uint32          m_inherited_flags;
    00152     struct {
    00153       bool          m_targed_seen : 1;
    00154       bool          m_choice_seen : 1;
    00155       bool          m_last_signal_was_red : 1;
    00156     } flags_s;
    00157   } flags_u;
    00158   SignalType        m_last_red_signal_type;
    00159
    00160   FORCEINLINE void Set(CYapfRailNodeT* parent, TileIndex tile, Trackdir td, bool is_choice)
    00161   {
    00162     base::Set(parent, tile, td, is_choice);
    00163     m_segment = NULL;
    00164     if (parent == NULL) {
    00165       m_num_signals_passed      = 0;
    00166       flags_u.m_inherited_flags = 0;
    00167       m_last_red_signal_type    = SIGTYPE_NORMAL;
    00168     } else {
    00169       m_num_signals_passed      = parent->m_num_signals_passed;
    00170       flags_u.m_inherited_flags = parent->flags_u.m_inherited_flags;
    00171       m_last_red_signal_type    = parent->m_last_red_signal_type;
    00172     }
    00173     flags_u.flags_s.m_choice_seen |= is_choice;
    00174   }
    00175
    00176   FORCEINLINE TileIndex GetLastTile() const {assert(m_segment != NULL); return m_segment->m_last_tile;}
    00177   FORCEINLINE Trackdir GetLastTrackdir() const {assert(m_segment != NULL); return m_segment->m_last_td;}
    00178   FORCEINLINE void SetLastTileTrackdir(TileIndex tile, Trackdir td) {assert(m_segment != NULL); m_segment->m_last_tile = tile; m_segment->m_last_td = td;}
    00179
    00180   void Dump(DumpTarget &dmp) const
    00181   {
    00182     base::Dump(dmp);
    00183     dmp.WriteStructT("m_segment", m_segment);
    00184     dmp.WriteLine("m_num_signals_passed = %d", m_num_signals_passed);
    00185     dmp.WriteLine("m_targed_seen = %s", flags_u.flags_s.m_targed_seen ? "Yes" : "No");
    00186     dmp.WriteLine("m_choice_seen = %s", flags_u.flags_s.m_choice_seen ? "Yes" : "No");
    00187     dmp.WriteLine("m_last_signal_was_red = %s", flags_u.flags_s.m_last_signal_was_red ? "Yes" : "No");
    00188     dmp.WriteEnumT("m_last_red_signal_type", m_last_red_signal_type);
    00189   }
    00190 };
    00191
    00192 // now define two major node types (that differ by key type)
    00193 typedef CYapfRailNodeT<CYapfNodeKeyExitDir>  CYapfRailNodeExitDir;
    00194 typedef CYapfRailNodeT<CYapfNodeKeyTrackDir> CYapfRailNodeTrackDir;
    00195
    00196 // Default NodeList types
    00197 typedef CNodeList_HashTableT<CYapfRailNodeExitDir , 10, 12> CRailNodeListExitDir;
    00198 typedef CNodeList_HashTableT<CYapfRailNodeTrackDir, 12, 16> CRailNodeListTrackDir;
    00199
    00200
    00201
    00202 #endif /* YAPF_NODE_RAIL_HPP */