Loading

FindClosestReachableShipD

  1. Index: src/pathfinder/yapf/yapf.h
  2. ===================================================================
  3. --- src/pathfinder/yapf/yapf.h  (revision 27829)
  4. +++ src/pathfinder/yapf/yapf.h  (working copy)
  5. @@ -97,4 +97,14 @@
  6.   */
  7.  bool YapfTrainFindNearestSafeTile(const Train *v, TileIndex tile, Trackdir td, bool override_railtype);
  8.  
  9. +/**
  10. + * Used when user sends ship to the nearest depot or if ship needs servicing using YAPF.
  11. + * @param v            vehicle that needs to go to some depot
  12. + * @param max_distance max distance (in pathfinder penalty) from the current vehicle position
  13. + *                     (used also as optimization - the pathfinder can stop path finding if max_penalty
  14. + *                     was reached and no depot was seen)
  15. + * @return             the data about the depot
  16. + */
  17. +FindDepotData YapfShipFindNearestDepot(const Ship *v, int max_distance);
  18. +
  19.  #endif /* YAPF_H */
  20. Index: src/pathfinder/yapf/yapf_node_ship.hpp
  21. ===================================================================
  22. --- src/pathfinder/yapf/yapf_node_ship.hpp  (revision 27829)
  23. +++ src/pathfinder/yapf/yapf_node_ship.hpp  (working copy)
  24. @@ -14,8 +14,20 @@
  25.  
  26.  /** Yapf Node for ships */
  27.  template <class Tkey_>
  28. -struct CYapfShipNodeT : CYapfNodeT<Tkey_, CYapfShipNodeT<Tkey_> > { };
  29. +struct CYapfShipNodeT : CYapfNodeT<Tkey_, CYapfShipNodeT<Tkey_> > {
  30. +   typedef CYapfNodeT<Tkey_, CYapfShipNodeT<Tkey_> > base;
  31.  
  32. +   TileIndex m_segment_last_tile;
  33. +   Trackdir  m_segment_last_td;
  34. +
  35. +   void Set(CYapfShipNodeT *parent, TileIndex tile, Trackdir td, bool is_choice)
  36. +   {
  37. +       base::Set(parent, tile, td, is_choice);
  38. +       m_segment_last_tile = tile;
  39. +       m_segment_last_td = td;
  40. +   }
  41. +};
  42. +
  43.  /* now define two major node types (that differ by key type) */
  44.  typedef CYapfShipNodeT<CYapfNodeKeyExitDir>  CYapfShipNodeExitDir;
  45.  typedef CYapfShipNodeT<CYapfNodeKeyTrackDir> CYapfShipNodeTrackDir;
  46. Index: src/pathfinder/yapf/yapf_ship.cpp
  47. ===================================================================
  48. --- src/pathfinder/yapf/yapf_ship.cpp   (revision 27829)
  49. +++ src/pathfinder/yapf/yapf_ship.cpp   (working copy)
  50. @@ -139,6 +139,43 @@
  51.         assert(best_trackdir == td1 || best_trackdir == td2);
  52.         return best_trackdir == td2;
  53.     }
  54. +
  55. +   static bool stFindNearestDepot(const Ship *v, TileIndex tile, Trackdir td1, Trackdir td2, TileIndex *depot_tile, bool *reversed)
  56. +   {
  57. +       Tpf pf;
  58. +       bool result = pf.FindNearestDepot(v, tile, td1, td2, depot_tile, reversed);
  59. +       return result;
  60. +   }
  61. +
  62. +   /**
  63. +    * Find the best depot for a ship.
  64. +    * @param v Vehicle
  65. +    * @param tile Tile of the vehicle.
  66. +    * @param td1 Trackdir of the vehicle.
  67. +    * @param td2 reversed Trackdir of the vehicle.
  68. +    * @param depot_tile the tile of the depot.
  69. +    * @param reversed whether the path to depot was found on reversed Trackdir.
  70. +    */
  71. +   inline bool FindNearestDepot(const Ship *v, TileIndex tile, Trackdir td1, Trackdir td2, TileIndex *depot_tile, bool *reversed)
  72. +   {
  73. +       Tpf pf1;
  74. +       Tpf pf2;
  75. +       /* Set origin. */
  76. +       pf1.SetOrigin(tile, TrackdirToTrackdirBits(td1));
  77. +       pf2.SetOrigin(tile, TrackdirToTrackdirBits(td2));
  78. +
  79. +       bool path_found1 = pf1.FindPath(v);
  80. +       bool path_found2 = pf2.FindPath(v);
  81. +       if (!path_found1 && !path_found2) return false;
  82. +
  83. +       Node *n;
  84. +       if (path_found1 || path_found2) {
  85. +           n = path_found1 ? pf1.GetBestNode() : pf2.GetBestNode();
  86. +           *depot_tile = n->m_segment_last_tile;
  87. +           *reversed = !path_found1 && path_found2;
  88. +       }
  89. +       return true;
  90. +   }
  91.  };
  92.  
  93.  /** Cost Provider module of YAPF for ships */
  94. @@ -188,15 +225,53 @@
  95.     }
  96.  };
  97.  
  98. +template <class Types>
  99. +class CYapfDestinationAnyDepotShipT
  100. +{
  101. +public:
  102. +   typedef typename Types::Tpf Tpf;                     ///< the pathfinder class (derived from THIS class)
  103. +   typedef typename Types::TrackFollower TrackFollower;
  104. +   typedef typename Types::NodeList::Titem Node;        ///< this will be our node type
  105. +   typedef typename Node::Key Key;                      ///< key to hash tables
  106. +
  107. +   /** to access inherited path finder */
  108. +   Tpf& Yapf()
  109. +   {
  110. +       return *static_cast<Tpf *>(this);
  111. +   }
  112. +
  113. +   /** Called by YAPF to detect if node ends in the desired destination */
  114. +   inline bool PfDetectDestination(Node &n)
  115. +   {
  116. +       bool bDest = IsShipDepotTile(n.m_segment_last_tile) && GetShipDepotPart(n.m_segment_last_tile) == DEPOT_PART_NORTH;
  117. +       return bDest;
  118. +   }
  119. +
  120. +   inline bool PfDetectDestinationTile(TileIndex tile, Trackdir trackdir)
  121. +   {
  122. +       return IsShipDepotTile(n.m_segment_last_tile) && GetShipDepotPart(n.m_segment_last_tile) == DEPOT_PART_NORTH;
  123. +   }
  124. +
  125. +   /**
  126. +    * Called by YAPF to calculate cost estimate. Calculates distance to the destination
  127. +    *  adds it to the actual cost from origin and stores the sum to the Node::m_estimate
  128. +    */
  129. +   inline bool PfCalcEstimate(Node &n)
  130. +   {
  131. +       n.m_estimate = n.m_cost;
  132. +       return true;
  133. +   }
  134. +};
  135. +
  136.  /**
  137.   * Config struct of YAPF for ships.
  138.   *  Defines all 6 base YAPF modules as classes providing services for CYapfBaseT.
  139.   */
  140. -template <class Tpf_, class Ttrack_follower, class Tnode_list>
  141. +template <class Tpf_, class Ttrack_follower, class Tnode_list, template <class Types> class CYapfDestinationTileT>
  142.  struct CYapfShip_TypesT
  143.  {
  144.     /** Types - shortcut for this struct type */
  145. -   typedef CYapfShip_TypesT<Tpf_, Ttrack_follower, Tnode_list>  Types;
  146. +   typedef CYapfShip_TypesT<Tpf_, Ttrack_follower, Tnode_list, CYapfDestinationTileT>  Types;
  147.  
  148.     /** Tpf - pathfinder type */
  149.     typedef Tpf_                              Tpf;
  150. @@ -215,12 +290,16 @@
  151.  };
  152.  
  153.  /* YAPF type 1 - uses TileIndex/Trackdir as Node key, allows 90-deg turns */
  154. -struct CYapfShip1 : CYapfT<CYapfShip_TypesT<CYapfShip1, CFollowTrackWater    , CShipNodeListTrackDir> > {};
  155. +struct CYapfShip1         : CYapfT<CYapfShip_TypesT<CYapfShip1        , CFollowTrackWater    , CShipNodeListTrackDir, CYapfDestinationTileT > > {};
  156.  /* YAPF type 2 - uses TileIndex/DiagDirection as Node key, allows 90-deg turns */
  157. -struct CYapfShip2 : CYapfT<CYapfShip_TypesT<CYapfShip2, CFollowTrackWater    , CShipNodeListExitDir > > {};
  158. +struct CYapfShip2         : CYapfT<CYapfShip_TypesT<CYapfShip2        , CFollowTrackWater    , CShipNodeListExitDir , CYapfDestinationTileT > > {};
  159.  /* YAPF type 3 - uses TileIndex/Trackdir as Node key, forbids 90-deg turns */
  160. -struct CYapfShip3 : CYapfT<CYapfShip_TypesT<CYapfShip3, CFollowTrackWaterNo90, CShipNodeListTrackDir> > {};
  161. +struct CYapfShip3         : CYapfT<CYapfShip_TypesT<CYapfShip3        , CFollowTrackWaterNo90, CShipNodeListTrackDir, CYapfDestinationTileT > > {};
  162.  
  163. +struct CYapfShipAnyDepot1 : CYapfT<CYapfShip_TypesT<CYapfShipAnyDepot1, CFollowTrackWater    , CShipNodeListTrackDir, CYapfDestinationAnyDepotShipT > > {};
  164. +struct CYapfShipAnyDepot2 : CYapfT<CYapfShip_TypesT<CYapfShipAnyDepot2, CFollowTrackWater    , CShipNodeListExitDir , CYapfDestinationAnyDepotShipT > > {};
  165. +struct CYapfShipAnyDepot3 : CYapfT<CYapfShip_TypesT<CYapfShipAnyDepot3, CFollowTrackWaterNo90, CShipNodeListTrackDir, CYapfDestinationAnyDepotShipT > > {};
  166. +
  167.  /** Ship controller helper - path finder invoker */
  168.  Track YapfShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found)
  169.  {
  170. @@ -239,6 +318,30 @@
  171.     return (td_ret != INVALID_TRACKDIR) ? TrackdirToTrack(td_ret) : INVALID_TRACK;
  172.  }
  173.  
  174. +FindDepotData YapfShipFindNearestDepot(const Ship *v, int max_penalty)
  175. +{
  176. +   FindDepotData fdd;
  177. +
  178. +   Trackdir td = v->GetVehicleTrackdir();
  179. +   Trackdir td_rev = ReverseTrackdir(td);
  180. +   TileIndex tile = v->tile;
  181. +
  182. +   /* default is YAPF type 2 */
  183. +   typedef bool(*PfnFindNearestDepot)(const Ship*, TileIndex, Trackdir, Trackdir, TileIndex*, bool*);
  184. +   PfnFindNearestDepot pfnFindNearestDepot = &CYapfShipAnyDepot2::stFindNearestDepot;
  185. +
  186. +   /* check if non-default YAPF type should be used */
  187. +   if (_settings_game.pf.forbid_90_deg) {
  188. +       pfnFindNearestDepot = &CYapfShipAnyDepot3::stFindNearestDepot; // Trackdir, forbid 90-deg
  189. +   } else if (_settings_game.pf.yapf.disable_node_optimization) {
  190. +       pfnFindNearestDepot = &CYapfShipAnyDepot1::stFindNearestDepot; // Trackdir, allow 90-deg
  191. +   }
  192. +
  193. +   bool ret = pfnFindNearestDepot(v, tile, td, td_rev, &fdd.tile, &fdd.reverse);
  194. +   fdd.best_length = ret ? max_penalty / 2 : UINT_MAX; // some fake distance or NOT_FOUND
  195. +   return fdd;
  196. +}
  197. +
  198.  bool YapfShipCheckReverse(const Ship *v)
  199.  {
  200.     Trackdir td = v->GetVehicleTrackdir();
  201. Index: src/ship_cmd.cpp
  202. ===================================================================
  203. --- src/ship_cmd.cpp    (revision 27829)
  204. +++ src/ship_cmd.cpp    (working copy)
  205. @@ -138,30 +138,17 @@
  206.     result->Set(_ship_sprites[spritenum] + direction);
  207.  }
  208.  
  209. -static const Depot *FindClosestShipDepot(const Vehicle *v, uint max_distance)
  210. +static FindDepotData FindClosestReachableShipDepot(const Ship *v, int max_distance)
  211.  {
  212. -   /* Find the closest depot */
  213. -   const Depot *depot;
  214. -   const Depot *best_depot = NULL;
  215. -   /* If we don't have a maximum distance, i.e. distance = 0,
  216. -    * we want to find any depot so the best distance of no
  217. -    * depot must be more than any correct distance. On the
  218. -    * other hand if we have set a maximum distance, any depot
  219. -    * further away than max_distance can safely be ignored. */
  220. -   uint best_dist = max_distance == 0 ? UINT_MAX : max_distance + 1;
  221. +   if (IsShipDepotTile(v->tile) && GetShipDepotPart(v->tile) == DEPOT_PART_NORTH) return FindDepotData(v->tile, 0);
  222.  
  223. -   FOR_ALL_DEPOTS(depot) {
  224. -       TileIndex tile = depot->xy;
  225. -       if (IsShipDepotTile(tile) && IsTileOwner(tile, v->owner)) {
  226. -           uint dist = DistanceManhattan(tile, v->tile);
  227. -           if (dist < best_dist) {
  228. -               best_dist = dist;
  229. -               best_depot = depot;
  230. -           }
  231. -       }
  232. +   switch (_settings_game.pf.pathfinder_for_ships) {
  233. +// case VPF_OPF: return OPFShipFindNearestDepot(v, max_distance); //TODO
  234. +// case VPF_NPF: return NPFShipFindNearestDepot(v, max_distance); //TODO
  235. +   case VPF_YAPF: return YapfShipFindNearestDepot(v, max_distance);
  236. +
  237. +   default: NOT_REACHED();
  238.     }
  239. -
  240. -   return best_depot;
  241.  }
  242.  
  243.  static void CheckIfShipNeedsService(Vehicle *v)
  244. @@ -180,9 +167,9 @@
  245.         default: NOT_REACHED();
  246.     }
  247.  
  248. -   const Depot *depot = FindClosestShipDepot(v, max_distance);
  249. +   const FindDepotData depot = FindClosestReachableShipDepot(Ship::From(v), max_distance);
  250.  
  251. -   if (depot == NULL) {
  252. +   if (depot.best_length == UINT_MAX) {
  253.         if (v->current_order.IsType(OT_GOTO_DEPOT)) {
  254.             v->current_order.MakeDummy();
  255.             SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
  256. @@ -190,8 +177,8 @@
  257.         return;
  258.     }
  259.  
  260. -   v->current_order.MakeGoToDepot(depot->index, ODTFB_SERVICE);
  261. -   v->dest_tile = depot->xy;
  262. +   v->current_order.MakeGoToDepot(GetDepotIndex(depot.tile), ODTFB_SERVICE);
  263. +   v->dest_tile = depot.tile;
  264.     SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
  265.  }
  266.  
  267. @@ -712,12 +699,11 @@
  268.  
  269.  bool Ship::FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse)
  270.  {
  271. -   const Depot *depot = FindClosestShipDepot(this, 0);
  272. +   FindDepotData sfdd = FindClosestReachableShipDepot(this, 0);
  273. +   if (sfdd.best_length == UINT_MAX) return false;
  274.  
  275. -   if (depot == NULL) return false;
  276. +   if (location != NULL) *location = sfdd.tile;
  277. +   if (destination != NULL) *destination = GetDepotIndex(sfdd.tile);
  278.  
  279. -   if (location    != NULL) *location    = depot->xy;
  280. -   if (destination != NULL) *destination = depot->index;
  281. -
  282.     return true;
  283.  }

Version history

Revision # Author Created at
pxmwekzc2 Anonymous 26 Mar 2017, 23:13:14 UTC Diff
phoeeb6pa Anonymous 26 Mar 2017, 14:13:24 UTC Diff
ppqwyyw9s Anonymous 26 Mar 2017, 01:16:13 UTC Diff

Comments