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

Generated on Mon Dec 14 21:00:05 2009 for OpenTTD by  doxygen 1.5.6