OpenTTD
yapf_destrail.hpp
Go to the documentation of this file.
1 /* $Id: yapf_destrail.hpp 23640 2011-12-20 17:57:56Z truebrain $ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * 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.
6  * 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.
7  * 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/>.
8  */
9 
12 #ifndef YAPF_DESTRAIL_HPP
13 #define YAPF_DESTRAIL_HPP
14 
16 {
17 protected:
18  RailTypes m_compatible_railtypes;
19 
20 public:
21  void SetDestination(const Train *v, bool override_rail_type = false)
22  {
23  m_compatible_railtypes = v->compatible_railtypes;
24  if (override_rail_type) m_compatible_railtypes |= GetRailTypeInfo(v->railtype)->compatible_railtypes;
25  }
26 
27  bool IsCompatibleRailType(RailType rt)
28  {
29  return HasBit(m_compatible_railtypes, rt);
30  }
31 
32  RailTypes GetCompatibleRailTypes() const
33  {
34  return m_compatible_railtypes;
35  }
36 };
37 
38 template <class Types>
41 {
42 public:
43  typedef typename Types::Tpf Tpf;
44  typedef typename Types::NodeList::Titem Node;
45  typedef typename Node::Key Key;
46 
48  Tpf& Yapf()
49  {
50  return *static_cast<Tpf*>(this);
51  }
52 
54  inline bool PfDetectDestination(Node& n)
55  {
56  return PfDetectDestination(n.GetLastTile(), n.GetLastTrackdir());
57  }
58 
60  inline bool PfDetectDestination(TileIndex tile, Trackdir td)
61  {
62  bool bDest = IsRailDepotTile(tile);
63  return bDest;
64  }
65 
70  inline bool PfCalcEstimate(Node& n)
71  {
72  n.m_estimate = n.m_cost;
73  return true;
74  }
75 };
76 
77 template <class Types>
80 {
81 public:
82  typedef typename Types::Tpf Tpf;
83  typedef typename Types::NodeList::Titem Node;
84  typedef typename Node::Key Key;
85  typedef typename Types::TrackFollower TrackFollower;
86 
88  Tpf& Yapf()
89  {
90  return *static_cast<Tpf*>(this);
91  }
92 
94  inline bool PfDetectDestination(Node& n)
95  {
96  return PfDetectDestination(n.GetLastTile(), n.GetLastTrackdir());
97  }
98 
100  inline bool PfDetectDestination(TileIndex tile, Trackdir td)
101  {
102  return IsSafeWaitingPosition(Yapf().GetVehicle(), tile, td, true, !TrackFollower::Allow90degTurns()) &&
103  IsWaitingPositionFree(Yapf().GetVehicle(), tile, td, !TrackFollower::Allow90degTurns());
104  }
105 
110  inline bool PfCalcEstimate(Node& n)
111  {
112  n.m_estimate = n.m_cost;
113  return true;
114  }
115 };
116 
117 template <class Types>
119  : public CYapfDestinationRailBase
120 {
121 public:
122  typedef typename Types::Tpf Tpf;
123  typedef typename Types::NodeList::Titem Node;
124  typedef typename Node::Key Key;
125 
126 protected:
127  TileIndex m_destTile;
128  TrackdirBits m_destTrackdirs;
129  StationID m_dest_station_id;
130 
133  {
134  return *static_cast<Tpf*>(this);
135  }
136 
137 public:
138  void SetDestination(const Train *v)
139  {
140  switch (v->current_order.GetType()) {
141  case OT_GOTO_WAYPOINT:
142  if (!Waypoint::Get(v->current_order.GetDestination())->IsSingleTile()) {
143  /* In case of 'complex' waypoints we need to do a look
144  * ahead. This look ahead messes a bit about, which
145  * means that it 'corrupts' the cache. To prevent this
146  * we disable caching when we're looking for a complex
147  * waypoint. */
148  Yapf().DisableCache(true);
149  }
150  /* FALL THROUGH */
151  case OT_GOTO_STATION:
152  m_destTile = CalcClosestStationTile(v->current_order.GetDestination(), v->tile, v->current_order.IsType(OT_GOTO_STATION) ? STATION_RAIL : STATION_WAYPOINT);
153  m_dest_station_id = v->current_order.GetDestination();
154  m_destTrackdirs = INVALID_TRACKDIR_BIT;
155  break;
156 
157  default:
158  m_destTile = v->dest_tile;
159  m_dest_station_id = INVALID_STATION;
161  break;
162  }
163  CYapfDestinationRailBase::SetDestination(v);
164  }
165 
167  inline bool PfDetectDestination(Node& n)
168  {
169  return PfDetectDestination(n.GetLastTile(), n.GetLastTrackdir());
170  }
171 
173  inline bool PfDetectDestination(TileIndex tile, Trackdir td)
174  {
175  bool bDest;
176  if (m_dest_station_id != INVALID_STATION) {
177  bDest = HasStationTileRail(tile)
178  && (GetStationIndex(tile) == m_dest_station_id)
179  && (GetRailStationTrack(tile) == TrackdirToTrack(td));
180  } else {
181  bDest = (tile == m_destTile)
182  && ((m_destTrackdirs & TrackdirToTrackdirBits(td)) != TRACKDIR_BIT_NONE);
183  }
184  return bDest;
185  }
186 
191  inline bool PfCalcEstimate(Node& n)
192  {
193  static const int dg_dir_to_x_offs[] = {-1, 0, 1, 0};
194  static const int dg_dir_to_y_offs[] = {0, 1, 0, -1};
195  if (PfDetectDestination(n)) {
196  n.m_estimate = n.m_cost;
197  return true;
198  }
199 
200  TileIndex tile = n.GetLastTile();
201  DiagDirection exitdir = TrackdirToExitdir(n.GetLastTrackdir());
202  int x1 = 2 * TileX(tile) + dg_dir_to_x_offs[(int)exitdir];
203  int y1 = 2 * TileY(tile) + dg_dir_to_y_offs[(int)exitdir];
204  int x2 = 2 * TileX(m_destTile);
205  int y2 = 2 * TileY(m_destTile);
206  int dx = abs(x1 - x2);
207  int dy = abs(y1 - y2);
208  int dmin = min(dx, dy);
209  int dxy = abs(dx - dy);
210  int d = dmin * YAPF_TILE_CORNER_LENGTH + (dxy - 1) * (YAPF_TILE_LENGTH / 2);
211  n.m_estimate = n.m_cost + d;
212  assert(n.m_estimate >= n.m_parent->m_estimate);
213  return true;
214  }
215 };
216 
217 #endif /* YAPF_DESTRAIL_HPP */