# yapf_road.cpp

Go to the documentation of this file.

    00001 /* $Id: yapf_road.cpp 17516 2009-09-12 20:44:12Z rubidium $ */
    00002
    00005 #include "../stdafx.h"
    00006 #include "../depot_base.h"
    00007 #include "../station_base.h"
    00008 #include "../roadveh.h"
    00009 #include "../cargotype.h"
    00010 #include "../newgrf_cargo.h"
    00011
    00012 #include "yapf.hpp"
    00013 #include "yapf_node_road.hpp"
    00014
    00015
    00016 template <class Types>
    00017 class CYapfCostRoadT
    00018 {
    00019 public:
    00020   typedef typename Types::Tpf Tpf;
    00021   typedef typename Types::TrackFollower TrackFollower;
    00022   typedef typename Types::NodeList::Titem Node;
    00023   typedef typename Node::Key Key;
    00024
    00025 protected:
    00027   Tpf& Yapf()
    00028   {
    00029     return *static_cast<Tpf*>(this);
    00030   }
    00031
    00032   int SlopeCost(TileIndex tile, TileIndex next_tile, Trackdir trackdir)
    00033   {
    00034     /* height of the center of the current tile */
    00035     int x1 = TileX(tile) * TILE_SIZE;
    00036     int y1 = TileY(tile) * TILE_SIZE;
    00037     int z1 = GetSlopeZ(x1 + TILE_SIZE / 2, y1 + TILE_SIZE / 2);
    00038
    00039     /* height of the center of the next tile */
    00040     int x2 = TileX(next_tile) * TILE_SIZE;
    00041     int y2 = TileY(next_tile) * TILE_SIZE;
    00042     int z2 = GetSlopeZ(x2 + TILE_SIZE / 2, y2 + TILE_SIZE / 2);
    00043
    00044     if (z2 - z1 > 1) {
    00045       /* Slope up */
    00046       return Yapf().PfGetSettings().road_slope_penalty;
    00047     }
    00048     return 0;
    00049   }
    00050
    00052   FORCEINLINE int OneTileCost(TileIndex tile, Trackdir trackdir)
    00053   {
    00054     int cost = 0;
    00055     /* set base cost */
    00056     if (IsDiagonalTrackdir(trackdir)) {
    00057       cost += YAPF_TILE_LENGTH;
    00058       switch (GetTileType(tile)) {
    00059         case MP_ROAD:
    00060           /* Increase the cost for level crossings */
    00061           if (IsLevelCrossing(tile)) {
    00062             cost += Yapf().PfGetSettings().road_crossing_penalty;
    00063           }
    00064           break;
    00065
    00066         case MP_STATION:
    00067           if (IsDriveThroughStopTile(tile)) {
    00068             cost += Yapf().PfGetSettings().road_stop_penalty;
    00069           }
    00070           break;
    00071
    00072         default:
    00073           break;
    00074       }
    00075     } else {
    00076       /* non-diagonal trackdir */
    00077       cost = YAPF_TILE_CORNER_LENGTH + Yapf().PfGetSettings().road_curve_penalty;
    00078     }
    00079     return cost;
    00080   }
    00081
    00082 public:
    00086   FORCEINLINE bool PfCalcCost(Node& n, const TrackFollower *tf)
    00087   {
    00088     int segment_cost = 0;
    00089     /* start at n.m_key.m_tile / n.m_key.m_td and walk to the end of segment */
    00090     TileIndex tile = n.m_key.m_tile;
    00091     Trackdir trackdir = n.m_key.m_td;
    00092     while (true) {
    00093       /* base tile cost depending on distance between edges */
    00094       segment_cost += Yapf().OneTileCost(tile, trackdir);
    00095
    00096       const Vehicle *v = Yapf().GetVehicle();
    00097       /* we have reached the vehicle's destination - segment should end here to avoid target skipping */
    00098       if (Yapf().PfDetectDestinationTile(tile, trackdir)) break;
    00099
    00100       /* stop if we have just entered the depot */
    00101       if (IsRoadDepotTile(tile) && trackdir == DiagDirToDiagTrackdir(ReverseDiagDir(GetRoadDepotDirection(tile)))) {
    00102         /* next time we will reverse and leave the depot */
    00103         break;
    00104       }
    00105
    00106       /* if there are no reachable trackdirs on new tile, we have end of road */
    00107       TrackFollower F(Yapf().GetVehicle());
    00108       if (!F.Follow(tile, trackdir)) break;
    00109
    00110       /* if there are more trackdirs available & reachable, we are at the end of segment */
    00111       if (KillFirstBit(F.m_new_td_bits) != TRACKDIR_BIT_NONE) break;
    00112
    00113       Trackdir new_td = (Trackdir)FindFirstBit2x64(F.m_new_td_bits);
    00114
    00115       /* stop if RV is on simple loop with no junctions */
    00116       if (F.m_new_tile == n.m_key.m_tile && new_td == n.m_key.m_td) return false;
    00117
    00118       /* if we skipped some tunnel tiles, add their cost */
    00119       segment_cost += F.m_tiles_skipped * YAPF_TILE_LENGTH;
    00120
    00121       /* add hilly terrain penalty */
    00122       segment_cost += Yapf().SlopeCost(tile, F.m_new_tile, trackdir);
    00123
    00124       /* add min/max speed penalties */
    00125       int min_speed = 0;
    00126       int max_speed = F.GetSpeedLimit(&min_speed);
    00127       if (max_speed < v->max_speed) segment_cost += 1 * (v->max_speed - max_speed);
    00128       if (min_speed > v->max_speed) segment_cost += 10 * (min_speed - v->max_speed);
    00129
    00130       /* move to the next tile */
    00131       tile = F.m_new_tile;
    00132       trackdir = new_td;
    00133     };
    00134
    00135     /* save end of segment back to the node */
    00136     n.m_segment_last_tile = tile;
    00137     n.m_segment_last_td = trackdir;
    00138
    00139     /* save also tile cost */
    00140     int parent_cost = (n.m_parent != NULL) ? n.m_parent->m_cost : 0;
    00141     n.m_cost = parent_cost + segment_cost;
    00142     return true;
    00143   }
    00144 };
    00145
    00146
    00147 template <class Types>
    00148 class CYapfDestinationAnyDepotRoadT
    00149 {
    00150 public:
    00151   typedef typename Types::Tpf Tpf;
    00152   typedef typename Types::TrackFollower TrackFollower;
    00153   typedef typename Types::NodeList::Titem Node;
    00154   typedef typename Node::Key Key;
    00155
    00157   Tpf& Yapf()
    00158   {
    00159     return *static_cast<Tpf*>(this);
    00160   }
    00161
    00163   FORCEINLINE bool PfDetectDestination(Node& n)
    00164   {
    00165     bool bDest = IsRoadDepotTile(n.m_segment_last_tile);
    00166     return bDest;
    00167   }
    00168
    00169   FORCEINLINE bool PfDetectDestinationTile(TileIndex tile, Trackdir trackdir)
    00170   {
    00171     return IsRoadDepotTile(tile);
    00172   }
    00173
    00176   FORCEINLINE bool PfCalcEstimate(Node& n)
    00177   {
    00178     n.m_estimate = n.m_cost;
    00179     return true;
    00180   }
    00181 };
    00182
    00183
    00184 template <class Types>
    00185 class CYapfDestinationAnyRoadVehicleCompatibleStopOfGivenStationT
    00186 {
    00187 public:
    00188   typedef typename Types::Tpf Tpf;
    00189   typedef typename Types::TrackFollower TrackFollower;
    00190   typedef typename Types::NodeList::Titem Node;
    00191   typedef typename Node::Key Key;
    00192
    00193   TileIndex      m_destTile;
    00194   StationID      m_dest_station;
    00195   bool           m_bus;
    00196   bool           m_non_artic;
    00197
    00199   Tpf& Yapf()
    00200   {
    00201     return *static_cast<Tpf*>(this);
    00202   }
    00203
    00204   void SetDestination(const Vehicle *v, StationID sid, TileIndex destTile)
    00205   {
    00206     m_dest_station = sid;
    00207     m_destTile     = destTile;
    00208     m_bus          = IsCargoInClass(v->cargo_type, CC_PASSENGERS);
    00209     m_non_artic    = !RoadVehHasArticPart(v);
    00210   }
    00211
    00213   FORCEINLINE bool PfDetectDestination(Node& n)
    00214   {
    00215     return PfDetectDestinationTile(n.m_segment_last_tile, INVALID_TRACKDIR);
    00216   }
    00217
    00218   FORCEINLINE bool PfDetectDestinationTile(TileIndex tile, Trackdir trackdir)
    00219   {
    00220     return
    00221       IsTileType(tile, MP_STATION) &&
    00222       GetStationIndex(tile) == m_dest_station &&
    00223       (m_bus ? IsBusStop(tile) : IsTruckStop(tile)) &&
    00224       (m_non_artic || IsDriveThroughStopTile(tile));
    00225   }
    00226
    00229   FORCEINLINE bool PfCalcEstimate(Node& n)
    00230   {
    00231     static const int dg_dir_to_x_offs[] = {-1, 0, 1, 0};
    00232     static const int dg_dir_to_y_offs[] = {0, 1, 0, -1};
    00233     if (PfDetectDestination(n)) {
    00234       n.m_estimate = n.m_cost;
    00235       return true;
    00236     }
    00237
    00238     TileIndex tile = n.m_segment_last_tile;
    00239     DiagDirection exitdir = TrackdirToExitdir(n.m_segment_last_td);
    00240     int x1 = 2 * TileX(tile) + dg_dir_to_x_offs[(int)exitdir];
    00241     int y1 = 2 * TileY(tile) + dg_dir_to_y_offs[(int)exitdir];
    00242     int x2 = 2 * TileX(m_destTile);
    00243     int y2 = 2 * TileY(m_destTile);
    00244     int dx = abs(x1 - x2);
    00245     int dy = abs(y1 - y2);
    00246     int dmin = min(dx, dy);
    00247     int dxy = abs(dx - dy);
    00248     int d = dmin * YAPF_TILE_CORNER_LENGTH + (dxy - 1) * (YAPF_TILE_LENGTH / 2);
    00249     n.m_estimate = n.m_cost + d;
    00250     assert(n.m_estimate >= n.m_parent->m_estimate);
    00251     return true;
    00252   }
    00253 };
    00254
    00255
    00256 template <class Types>
    00257 class CYapfDestinationTileRoadT
    00258 {
    00259 public:
    00260   typedef typename Types::Tpf Tpf;
    00261   typedef typename Types::TrackFollower TrackFollower;
    00262   typedef typename Types::NodeList::Titem Node;
    00263   typedef typename Node::Key Key;
    00264
    00265 protected:
    00266   TileIndex    m_destTile;
    00267   TrackdirBits m_destTrackdirs;
    00268
    00269 public:
    00270   void SetDestination(TileIndex tile, TrackdirBits trackdirs)
    00271   {
    00272     m_destTile = tile;
    00273     m_destTrackdirs = trackdirs;
    00274   }
    00275
    00276 protected:
    00278   Tpf& Yapf()
    00279   {
    00280     return *static_cast<Tpf*>(this);
    00281   }
    00282
    00283 public:
    00285   FORCEINLINE bool PfDetectDestination(Node& n)
    00286   {
    00287     bool bDest = (n.m_segment_last_tile == m_destTile) && ((m_destTrackdirs & TrackdirToTrackdirBits(n.m_segment_last_td)) != TRACKDIR_BIT_NONE);
    00288     return bDest;
    00289   }
    00290
    00291   FORCEINLINE bool PfDetectDestinationTile(TileIndex tile, Trackdir trackdir)
    00292   {
    00293     return tile == m_destTile && ((m_destTrackdirs & TrackdirToTrackdirBits(trackdir)) != TRACKDIR_BIT_NONE);
    00294   }
    00295
    00298   inline bool PfCalcEstimate(Node& n)
    00299   {
    00300     static int dg_dir_to_x_offs[] = {-1, 0, 1, 0};
    00301     static int dg_dir_to_y_offs[] = {0, 1, 0, -1};
    00302     if (PfDetectDestination(n)) {
    00303       n.m_estimate = n.m_cost;
    00304       return true;
    00305     }
    00306
    00307     TileIndex tile = n.m_segment_last_tile;
    00308     DiagDirection exitdir = TrackdirToExitdir(n.m_segment_last_td);
    00309     int x1 = 2 * TileX(tile) + dg_dir_to_x_offs[(int)exitdir];
    00310     int y1 = 2 * TileY(tile) + dg_dir_to_y_offs[(int)exitdir];
    00311     int x2 = 2 * TileX(m_destTile);
    00312     int y2 = 2 * TileY(m_destTile);
    00313     int dx = abs(x1 - x2);
    00314     int dy = abs(y1 - y2);
    00315     int dmin = min(dx, dy);
    00316     int dxy = abs(dx - dy);
    00317     int d = dmin * YAPF_TILE_CORNER_LENGTH + (dxy - 1) * (YAPF_TILE_LENGTH / 2);
    00318     n.m_estimate = n.m_cost + d;
    00319     assert(n.m_estimate >= n.m_parent->m_estimate);
    00320     return true;
    00321   }
    00322 };
    00323
    00324
    00325
    00326 template <class Types>
    00327 class CYapfFollowRoadT
    00328 {
    00329 public:
    00330   typedef typename Types::Tpf Tpf;
    00331   typedef typename Types::TrackFollower TrackFollower;
    00332   typedef typename Types::NodeList::Titem Node;
    00333   typedef typename Node::Key Key;
    00334
    00335 protected:
    00337   FORCEINLINE Tpf& Yapf()
    00338   {
    00339     return *static_cast<Tpf*>(this);
    00340   }
    00341
    00342 public:
    00343
    00347   inline void PfFollowNode(Node& old_node)
    00348   {
    00349     TrackFollower F(Yapf().GetVehicle());
    00350     if (F.Follow(old_node.m_segment_last_tile, old_node.m_segment_last_td)) {
    00351       Yapf().AddMultipleNodes(&old_node, F);
    00352     }
    00353   }
    00354
    00356   FORCEINLINE char TransportTypeChar() const
    00357   {
    00358     return 'r';
    00359   }
    00360
    00361   static Trackdir stChooseRoadTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir)
    00362   {
    00363     Tpf pf;
    00364     return pf.ChooseRoadTrack(v, tile, enterdir);
    00365   }
    00366
    00367   FORCEINLINE Trackdir ChooseRoadTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir)
    00368   {
    00369     /* handle special case - when next tile is destination tile */
    00370     if (tile == v->dest_tile) {
    00371       /* choose diagonal trackdir reachable from enterdir */
    00372       return DiagDirToDiagTrackdir(enterdir);
    00373     }
    00374     /* our source tile will be the next vehicle tile (should be the given one) */
    00375     TileIndex src_tile = tile;
    00376     /* get available trackdirs on the start tile */
    00377     TrackdirBits src_trackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes));
    00378     /* select reachable trackdirs only */
    00379     src_trackdirs &= DiagdirReachesTrackdirs(enterdir);
    00380
    00381     /* get available trackdirs on the destination tile */
    00382     TileIndex dest_tile = v->dest_tile;
    00383     TrackdirBits dest_trackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(dest_tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes));
    00384
    00385     /* set origin and destination nodes */
    00386     Yapf().SetOrigin(src_tile, src_trackdirs);
    00387     Yapf().SetDestination(dest_tile, dest_trackdirs);
    00388
    00389     /* find the best path */
    00390     Yapf().FindPath(v);
    00391
    00392     /* if path not found - return INVALID_TRACKDIR */
    00393     Trackdir next_trackdir = INVALID_TRACKDIR;
    00394     Node *pNode = Yapf().GetBestNode();
    00395     if (pNode != NULL) {
    00396       /* path was found or at least suggested
    00397        * walk through the path back to its origin */
    00398       while (pNode->m_parent != NULL) {
    00399         pNode = pNode->m_parent;
    00400       }
    00401       /* return trackdir from the best origin node (one of start nodes) */
    00402       Node& best_next_node = *pNode;
    00403       assert(best_next_node.GetTile() == tile);
    00404       next_trackdir = best_next_node.GetTrackdir();
    00405     }
    00406     return next_trackdir;
    00407   }
    00408
    00409   static uint stDistanceToTile(const Vehicle *v, TileIndex tile)
    00410   {
    00411     Tpf pf;
    00412     return pf.DistanceToTile(v, tile);
    00413   }
    00414
    00415   FORCEINLINE uint DistanceToTile(const Vehicle *v, TileIndex dst_tile)
    00416   {
    00417     /* handle special case - when current tile is the destination tile */
    00418     if (dst_tile == v->tile) {
    00419       /* distance is zero in this case */
    00420       return 0;
    00421     }
    00422
    00423     if (!SetOriginFromVehiclePos(v)) return UINT_MAX;
    00424
    00425     /* set destination tile, trackdir
    00426      *   get available trackdirs on the destination tile */
    00427     TrackdirBits dst_td_bits = TrackStatusToTrackdirBits(GetTileTrackStatus(dst_tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes));
    00428     Yapf().SetDestination(dst_tile, dst_td_bits);
    00429
    00430     /* if path not found - return distance = UINT_MAX */
    00431     uint dist = UINT_MAX;
    00432
    00433     /* find the best path */
    00434     if (!Yapf().FindPath(v)) return dist;
    00435
    00436     Node *pNode = Yapf().GetBestNode();
    00437     if (pNode != NULL) {
    00438       /* path was found
    00439        * get the path cost estimate */
    00440       dist = pNode->GetCostEstimate();
    00441     }
    00442
    00443     return dist;
    00444   }
    00445
    00447   FORCEINLINE bool SetOriginFromVehiclePos(const Vehicle *v)
    00448   {
    00449     /* set origin (tile, trackdir) */
    00450     TileIndex src_tile = v->tile;
    00451     Trackdir src_td = GetVehicleTrackdir(v);
    00452     if ((TrackStatusToTrackdirBits(GetTileTrackStatus(src_tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes)) & TrackdirToTrackdirBits(src_td)) == 0) {
    00453       /* sometimes the roadveh is not on the road (it resides on non-existing track)
    00454        * how should we handle that situation? */
    00455       return false;
    00456     }
    00457     Yapf().SetOrigin(src_tile, TrackdirToTrackdirBits(src_td));
    00458     return true;
    00459   }
    00460
    00461   static Depot *stFindNearestDepot(const Vehicle *v, TileIndex tile, Trackdir td)
    00462   {
    00463     Tpf pf;
    00464     return pf.FindNearestDepot(v, tile, td);
    00465   }
    00466
    00467   FORCEINLINE Depot *FindNearestDepot(const Vehicle *v, TileIndex tile, Trackdir td)
    00468   {
    00469     /* set origin and destination nodes */
    00470     Yapf().SetOrigin(tile, TrackdirToTrackdirBits(td));
    00471
    00472     /* find the best path */
    00473     bool bFound = Yapf().FindPath(v);
    00474     if (!bFound) return false;
    00475
    00476     /* some path found
    00477      * get found depot tile */
    00478     Node *n = Yapf().GetBestNode();
    00479     TileIndex depot_tile = n->m_segment_last_tile;
    00480     assert(IsRoadDepotTile(depot_tile));
    00481     Depot *ret = GetDepotByTile(depot_tile);
    00482     return ret;
    00483   }
    00484
    00485   static bool stFindNearestRoadVehicleCompatibleStop(const Vehicle *v, TileIndex tile, TileIndex destTile, Trackdir td, StationID sid, TileIndex *stop_tile)
    00486   {
    00487     Tpf pf;
    00488     return pf.FindNearestRoadVehicleCompatibleStop(v, tile, destTile, td, sid, stop_tile);
    00489   }
    00490
    00491   FORCEINLINE bool FindNearestRoadVehicleCompatibleStop(const Vehicle *v, TileIndex tile, TileIndex destTile, Trackdir td, StationID sid, TileIndex *stop_tile)
    00492   {
    00493     /* set origin and destination nodes */
    00494     Yapf().SetOrigin(tile, TrackdirToTrackdirBits(td));
    00495     Yapf().SetDestination(v, sid, destTile);
    00496
    00497     /* find the best path */
    00498     bool bFound = Yapf().FindPath(v);
    00499     if (!bFound) return false;
    00500
    00501     /* some path found
    00502      * get found depot tile */
    00503     const Node *n = Yapf().GetBestNode();
    00504
    00505     *stop_tile = n->m_segment_last_tile;
    00506     return true;
    00507   }
    00508 };
    00509
    00510 template <class Tpf_, class Tnode_list, template <class Types> class Tdestination>
    00511 struct CYapfRoad_TypesT
    00512 {
    00513   typedef CYapfRoad_TypesT<Tpf_, Tnode_list, Tdestination>  Types;
    00514
    00515   typedef Tpf_                              Tpf;
    00516   typedef CFollowTrackRoad                  TrackFollower;
    00517   typedef Tnode_list                        NodeList;
    00518   typedef CYapfBaseT<Types>                 PfBase;
    00519   typedef CYapfFollowRoadT<Types>           PfFollow;
    00520   typedef CYapfOriginTileT<Types>           PfOrigin;
    00521   typedef Tdestination<Types>               PfDestination;
    00522   typedef CYapfSegmentCostCacheNoneT<Types> PfCache;
    00523   typedef CYapfCostRoadT<Types>             PfCost;
    00524 };
    00525
    00526 struct CYapfRoad1         : CYapfT<CYapfRoad_TypesT<CYapfRoad1        , CRoadNodeListTrackDir, CYapfDestinationTileRoadT    > > {};
    00527 struct CYapfRoad2         : CYapfT<CYapfRoad_TypesT<CYapfRoad2        , CRoadNodeListExitDir , CYapfDestinationTileRoadT    > > {};
    00528
    00529 struct CYapfRoadAnyDepot1 : CYapfT<CYapfRoad_TypesT<CYapfRoadAnyDepot1, CRoadNodeListTrackDir, CYapfDestinationAnyDepotRoadT> > {};
    00530 struct CYapfRoadAnyDepot2 : CYapfT<CYapfRoad_TypesT<CYapfRoadAnyDepot2, CRoadNodeListExitDir , CYapfDestinationAnyDepotRoadT> > {};
    00531
    00532 struct CYapfRoadAnyRoadVehicleCompatibleStopOfGivenStation1 : CYapfT<CYapfRoad_TypesT<CYapfRoadAnyRoadVehicleCompatibleStopOfGivenStation1, CRoadNodeListTrackDir, CYapfDestinationAnyRoadVehicleCompatibleStopOfGivenStationT> > {};
    00533 struct CYapfRoadAnyRoadVehicleCompatibleStopOfGivenStation2 : CYapfT<CYapfRoad_TypesT<CYapfRoadAnyRoadVehicleCompatibleStopOfGivenStation2, CRoadNodeListExitDir , CYapfDestinationAnyRoadVehicleCompatibleStopOfGivenStationT> > {};
    00534
    00535
    00536 Trackdir YapfChooseRoadTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir)
    00537 {
    00538   /* default is YAPF type 2 */
    00539   typedef Trackdir (*PfnChooseRoadTrack)(const Vehicle*, TileIndex, DiagDirection);
    00540   PfnChooseRoadTrack pfnChooseRoadTrack = &CYapfRoad2::stChooseRoadTrack; // default: ExitDir, allow 90-deg
    00541
    00542   /* check if non-default YAPF type should be used */
    00543   if (_settings_game.pf.yapf.disable_node_optimization) {
    00544     pfnChooseRoadTrack = &CYapfRoad1::stChooseRoadTrack; // Trackdir, allow 90-deg
    00545   }
    00546
    00547   Trackdir td_ret = pfnChooseRoadTrack(v, tile, enterdir);
    00548   return td_ret;
    00549 }
    00550
    00551 uint YapfRoadVehDistanceToTile(const Vehicle *v, TileIndex tile)
    00552 {
    00553   /* default is YAPF type 2 */
    00554   typedef uint (*PfnDistanceToTile)(const Vehicle*, TileIndex);
    00555   PfnDistanceToTile pfnDistanceToTile = &CYapfRoad2::stDistanceToTile; // default: ExitDir, allow 90-deg
    00556
    00557   /* check if non-default YAPF type should be used */
    00558   if (_settings_game.pf.yapf.disable_node_optimization) {
    00559     pfnDistanceToTile = &CYapfRoad1::stDistanceToTile; // Trackdir, allow 90-deg
    00560   }
    00561
    00562   /* measure distance in YAPF units */
    00563   uint dist = pfnDistanceToTile(v, tile);
    00564   /* convert distance to tiles */
    00565   if (dist != UINT_MAX) {
    00566     dist = (dist + YAPF_TILE_LENGTH - 1) / YAPF_TILE_LENGTH;
    00567   }
    00568
    00569   return dist;
    00570 }
    00571
    00572 Depot *YapfFindNearestRoadDepot(const Vehicle *v)
    00573 {
    00574   TileIndex tile = v->tile;
    00575   Trackdir trackdir = GetVehicleTrackdir(v);
    00576   if ((TrackStatusToTrackdirBits(GetTileTrackStatus(tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes)) & TrackdirToTrackdirBits(trackdir)) == 0) {
    00577     return NULL;
    00578   }
    00579
    00580   /* handle the case when our vehicle is already in the depot tile */
    00581   if (IsRoadDepotTile(tile)) {
    00582     /* only what we need to return is the Depot* */
    00583     return GetDepotByTile(tile);
    00584   }
    00585
    00586   /* default is YAPF type 2 */
    00587   typedef Depot *(*PfnFindNearestDepot)(const Vehicle*, TileIndex, Trackdir);
    00588   PfnFindNearestDepot pfnFindNearestDepot = &CYapfRoadAnyDepot2::stFindNearestDepot;
    00589
    00590   /* check if non-default YAPF type should be used */
    00591   if (_settings_game.pf.yapf.disable_node_optimization) {
    00592     pfnFindNearestDepot = &CYapfRoadAnyDepot1::stFindNearestDepot; // Trackdir, allow 90-deg
    00593   }
    00594
    00595   Depot *ret = pfnFindNearestDepot(v, tile, trackdir);
    00596   return ret;
    00597 }
    00598
    00599 bool YapfFindNearestRoadVehicleCompatibleStop(const Vehicle *v, StationID station, TileIndex *stop_tile)
    00600 {
    00601   *stop_tile = INVALID_TILE;
    00602
    00603   const RoadStop *rs = GetStation(station)->GetPrimaryRoadStop(v);
    00604   if (rs == NULL) return false;
    00605
    00606   TileIndex tile = v->tile;
    00607   Trackdir trackdir = GetVehicleTrackdir(v);
    00608   if ((TrackStatusToTrackdirBits(GetTileTrackStatus(tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes)) & TrackdirToTrackdirBits(trackdir)) == 0) {
    00609     return false;
    00610   }
    00611
    00612   /* default is YAPF type 2 */
    00613   typedef bool (*PfnFindNearestRoadVehicleCompatibleStop)(const Vehicle*, TileIndex, TileIndex, Trackdir, StationID, TileIndex*);
    00614   PfnFindNearestRoadVehicleCompatibleStop pfnFindNearestRoadVehicleCompatibleStop = &CYapfRoadAnyRoadVehicleCompatibleStopOfGivenStation2::stFindNearestRoadVehicleCompatibleStop;
    00615
    00616   /* check if non-default YAPF type should be used */
    00617   if (_settings_game.pf.yapf.disable_node_optimization) {
    00618     pfnFindNearestRoadVehicleCompatibleStop = &CYapfRoadAnyRoadVehicleCompatibleStopOfGivenStation1::stFindNearestRoadVehicleCompatibleStop; // Trackdir, allow 90-deg
    00619   }
    00620
    00621   bool ret = pfnFindNearestRoadVehicleCompatibleStop(v, tile, rs->xy, trackdir, station, stop_tile);
    00622   return ret;
    00623 }