# yapf_node_rail.hpp

Go to the documentation of this file.

    00001 /* $Id: yapf_node_rail.hpp 14949 2009-01-10 00:31:47Z 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   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   ESR_SAFE_TILE,
    00043
    00044   /* The following reasons are used only internally by PfCalcCost().
    00045   *   They should not be found in the cached segment. */
    00046   ESR_PATH_TOO_LONG,
    00047   ESR_FIRST_TWO_WAY_RED,
    00048   ESR_LOOK_AHEAD_END,
    00049   ESR_TARGET_REACHED,
    00050
    00051   /* Special values */
    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   /* Additional (composite) values. */
    00074
    00075   /* What reasons mean that the target can be found and needs to be detected. */
    00076   ESRB_POSSIBLE_TARGET = ESRB_DEPOT | ESRB_WAYPOINT | ESRB_STATION | ESRB_SAFE_TILE,
    00077
    00078   /* What reasons can be stored back into cached segment. */
    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   /* Reasons to abort pathfinding in this direction. */
    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 // now define two major node types (that differ by key type)
    00214 typedef CYapfRailNodeT<CYapfNodeKeyExitDir>  CYapfRailNodeExitDir;
    00215 typedef CYapfRailNodeT<CYapfNodeKeyTrackDir> CYapfRailNodeTrackDir;
    00216
    00217 // Default NodeList types
    00218 typedef CNodeList_HashTableT<CYapfRailNodeExitDir , 10, 12> CRailNodeListExitDir;
    00219 typedef CNodeList_HashTableT<CYapfRailNodeTrackDir, 12, 16> CRailNodeListTrackDir;
    00220
    00221
    00222
    00223 #endif /* YAPF_NODE_RAIL_HPP */