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 */

Generated on Mon Feb 16 23:12:13 2009 for openttd by  doxygen 1.5.6