# yapf_node_rail.hpp

Go to the documentation of this file.

    00001 /* $Id: yapf_node_rail.hpp 26058 2013-11-23 13:15:07Z rubidium $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
    00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
    00008  */
    00009
    00012 #ifndef YAPF_NODE_RAIL_HPP
    00013 #define YAPF_NODE_RAIL_HPP
    00014
    00016 struct CYapfRailSegmentKey
    00017 {
    00018   uint32    m_value;
    00019
    00020   inline CYapfRailSegmentKey(const CYapfRailSegmentKey& src) : m_value(src.m_value) {}
    00021
    00022   inline CYapfRailSegmentKey(const CYapfNodeKeyTrackDir& node_key)
    00023   {
    00024     Set(node_key);
    00025   }
    00026
    00027   inline void Set(const CYapfRailSegmentKey& src)
    00028   {
    00029     m_value = src.m_value;
    00030   }
    00031
    00032   inline void Set(const CYapfNodeKeyTrackDir& node_key)
    00033   {
    00034     m_value = (((int)node_key.m_tile) << 4) | node_key.m_td;
    00035   }
    00036
    00037   inline int32 CalcHash() const
    00038   {
    00039     return m_value;
    00040   }
    00041
    00042   inline TileIndex GetTile() const
    00043   {
    00044     return (TileIndex)(m_value >> 4);
    00045   }
    00046
    00047   inline Trackdir GetTrackdir() const
    00048   {
    00049     return (Trackdir)(m_value & 0x0F);
    00050   }
    00051
    00052   inline bool operator == (const CYapfRailSegmentKey& other) const
    00053   {
    00054     return m_value == other.m_value;
    00055   }
    00056
    00057   void Dump(DumpTarget &dmp) const
    00058   {
    00059     dmp.WriteTile("tile", GetTile());
    00060     dmp.WriteEnumT("td", GetTrackdir());
    00061   }
    00062 };
    00063
    00065 struct CYapfRailSegment
    00066 {
    00067   typedef CYapfRailSegmentKey Key;
    00068
    00069   CYapfRailSegmentKey    m_key;
    00070   TileIndex              m_last_tile;
    00071   Trackdir               m_last_td;
    00072   int                    m_cost;
    00073   TileIndex              m_last_signal_tile;
    00074   Trackdir               m_last_signal_td;
    00075   EndSegmentReasonBits   m_end_segment_reason;
    00076   CYapfRailSegment      *m_hash_next;
    00077
    00078   inline CYapfRailSegment(const CYapfRailSegmentKey& key)
    00079     : m_key(key)
    00080     , m_last_tile(INVALID_TILE)
    00081     , m_last_td(INVALID_TRACKDIR)
    00082     , m_cost(-1)
    00083     , m_last_signal_tile(INVALID_TILE)
    00084     , m_last_signal_td(INVALID_TRACKDIR)
    00085     , m_end_segment_reason(ESRB_NONE)
    00086     , m_hash_next(NULL)
    00087   {}
    00088
    00089   inline const Key& GetKey() const
    00090   {
    00091     return m_key;
    00092   }
    00093
    00094   inline TileIndex GetTile() const
    00095   {
    00096     return m_key.GetTile();
    00097   }
    00098
    00099   inline CYapfRailSegment *GetHashNext()
    00100   {
    00101     return m_hash_next;
    00102   }
    00103
    00104   inline void SetHashNext(CYapfRailSegment *next)
    00105   {
    00106     m_hash_next = next;
    00107   }
    00108
    00109   void Dump(DumpTarget &dmp) const
    00110   {
    00111     dmp.WriteStructT("m_key", &m_key);
    00112     dmp.WriteTile("m_last_tile", m_last_tile);
    00113     dmp.WriteEnumT("m_last_td", m_last_td);
    00114     dmp.WriteLine("m_cost = %d", m_cost);
    00115     dmp.WriteTile("m_last_signal_tile", m_last_signal_tile);
    00116     dmp.WriteEnumT("m_last_signal_td", m_last_signal_td);
    00117     dmp.WriteEnumT("m_end_segment_reason", m_end_segment_reason);
    00118   }
    00119 };
    00120
    00122 template <class Tkey_>
    00123 struct CYapfRailNodeT
    00124   : CYapfNodeT<Tkey_, CYapfRailNodeT<Tkey_> >
    00125 {
    00126   typedef CYapfNodeT<Tkey_, CYapfRailNodeT<Tkey_> > base;
    00127   typedef CYapfRailSegment CachedData;
    00128
    00129   CYapfRailSegment *m_segment;
    00130   uint16            m_num_signals_passed;
    00131   union {
    00132     uint32          m_inherited_flags;
    00133     struct {
    00134       bool          m_targed_seen : 1;
    00135       bool          m_choice_seen : 1;
    00136       bool          m_last_signal_was_red : 1;
    00137     } flags_s;
    00138   } flags_u;
    00139   SignalType        m_last_red_signal_type;
    00140   SignalType        m_last_signal_type;
    00141
    00142   inline void Set(CYapfRailNodeT *parent, TileIndex tile, Trackdir td, bool is_choice)
    00143   {
    00144     base::Set(parent, tile, td, is_choice);
    00145     m_segment = NULL;
    00146     if (parent == NULL) {
    00147       m_num_signals_passed      = 0;
    00148       flags_u.m_inherited_flags = 0;
    00149       m_last_red_signal_type    = SIGTYPE_NORMAL;
    00150       /* We use PBS as initial signal type because if we are in
    00151        * a PBS section and need to route, i.e. we're at a safe
    00152        * waiting point of a station, we need to account for the
    00153        * reservation costs. If we are in a normal block then we
    00154        * should be alone in there and as such the reservation
    00155        * costs should be 0 anyway. If there would be another
    00156        * train in the block, i.e. passing signals at danger
    00157        * then avoiding that train with help of the reservation
    00158        * costs is not a bad thing, actually it would probably
    00159        * be a good thing to do. */
    00160       m_last_signal_type        = SIGTYPE_PBS;
    00161     } else {
    00162       m_num_signals_passed      = parent->m_num_signals_passed;
    00163       flags_u.m_inherited_flags = parent->flags_u.m_inherited_flags;
    00164       m_last_red_signal_type    = parent->m_last_red_signal_type;
    00165       m_last_signal_type        = parent->m_last_signal_type;
    00166     }
    00167     flags_u.flags_s.m_choice_seen |= is_choice;
    00168   }
    00169
    00170   inline TileIndex GetLastTile() const
    00171   {
    00172     assert(m_segment != NULL);
    00173     return m_segment->m_last_tile;
    00174   }
    00175
    00176   inline Trackdir GetLastTrackdir() const
    00177   {
    00178     assert(m_segment != NULL);
    00179     return m_segment->m_last_td;
    00180   }
    00181
    00182   inline void SetLastTileTrackdir(TileIndex tile, Trackdir td)
    00183   {
    00184     assert(m_segment != NULL);
    00185     m_segment->m_last_tile = tile;
    00186     m_segment->m_last_td = td;
    00187   }
    00188
    00189   template <class Tbase, class Tfunc, class Tpf>
    00190   bool IterateTiles(const Train *v, Tpf &yapf, Tbase &obj, bool (Tfunc::*func)(TileIndex, Trackdir)) const
    00191   {
    00192     typename Tbase::TrackFollower ft(v, yapf.GetCompatibleRailTypes());
    00193     TileIndex cur = base::GetTile();
    00194     Trackdir  cur_td = base::GetTrackdir();
    00195
    00196     while (cur != GetLastTile() || cur_td != GetLastTrackdir()) {
    00197       if (!((obj.*func)(cur, cur_td))) return false;
    00198
    00199       if (!ft.Follow(cur, cur_td)) break;
    00200       cur = ft.m_new_tile;
    00201       assert(KillFirstBit(ft.m_new_td_bits) == TRACKDIR_BIT_NONE);
    00202       cur_td = FindFirstTrackdir(ft.m_new_td_bits);
    00203     }
    00204
    00205     return (obj.*func)(cur, cur_td);
    00206   }
    00207
    00208   void Dump(DumpTarget &dmp) const
    00209   {
    00210     base::Dump(dmp);
    00211     dmp.WriteStructT("m_segment", m_segment);
    00212     dmp.WriteLine("m_num_signals_passed = %d", m_num_signals_passed);
    00213     dmp.WriteLine("m_targed_seen = %s", flags_u.flags_s.m_targed_seen ? "Yes" : "No");
    00214     dmp.WriteLine("m_choice_seen = %s", flags_u.flags_s.m_choice_seen ? "Yes" : "No");
    00215     dmp.WriteLine("m_last_signal_was_red = %s", flags_u.flags_s.m_last_signal_was_red ? "Yes" : "No");
    00216     dmp.WriteEnumT("m_last_red_signal_type", m_last_red_signal_type);
    00217   }
    00218 };
    00219
    00220 /* now define two major node types (that differ by key type) */
    00221 typedef CYapfRailNodeT<CYapfNodeKeyExitDir>  CYapfRailNodeExitDir;
    00222 typedef CYapfRailNodeT<CYapfNodeKeyTrackDir> CYapfRailNodeTrackDir;
    00223
    00224 /* Default NodeList types */
    00225 typedef CNodeList_HashTableT<CYapfRailNodeExitDir , 8, 10> CRailNodeListExitDir;
    00226 typedef CNodeList_HashTableT<CYapfRailNodeTrackDir, 8, 10> CRailNodeListTrackDir;
    00227
    00228 #endif /* YAPF_NODE_RAIL_HPP */