Loading

Revision differences

Old revision #pubn57tm0New revision #pbcgoaplf
  1Index: src/pathfinder/npf/npf.cpp  
  2===================================================================  
  3--- src/pathfinder/npf/npf.cpp    (revision 27833)  
  4+++ src/pathfinder/npf/npf.cpp    (working copy)  
  5@@ -536,8 +536,13 @@  
  6     AyStarUserData *user = (AyStarUserData *)as->user_data;  
  7     /* It's not worth caching the result with NPF_FLAG_IS_TARGET here as below,  
  8      * since checking the cache not that much faster than the actual check */  
  9-    return IsDepotTypeTile(current->path.node.tile, user->type) ?  
  10-        AYSTAR_FOUND_END_NODE : AYSTAR_DONE;  
  11+    if (user->type != TRANSPORT_WATER) {  
  12+        return IsDepotTypeTile(current->path.node.tile, user->type) ?  
  13+            AYSTAR_FOUND_END_NODE : AYSTAR_DONE;  
  14+    } else {  
  15+        return IsShipDepotTile(current->path.node.tile) && GetShipDepotPart(current->path.node.tile) == DEPOT_PART_NORTH && IsTileOwner(current->path.node.tile, user->owner) ?  
  16+            AYSTAR_FOUND_END_NODE : AYSTAR_DONE;  
  17+    }  
  18 }  
  19   
  20 /** Find any safe and free tile. */  
  21@@ -1161,6 +1166,24 @@  
  22   
  23 /*** Ships ***/  
  24   
  25+FindDepotData NPFShipFindNearestDepot(const Ship *v, int max_distance)  
  26+{  
  27+    Trackdir trackdir = v->GetVehicleTrackdir();  
  28+    Trackdir trackdir_rev = ReverseTrackdir(trackdir);  
  29+    NPFFindStationOrTileData fstd;  
  30+    fstd.v = v;  
  31+    fstd.reserve_path = false;  
  32+  
  33+    assert(trackdir != INVALID_TRACKDIR);  
  34+    AyStarUserData user = { v->owner, TRANSPORT_WATER, INVALID_RAILTYPES, ROADTYPES_NONE };  
  35+    NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, false, v->tile, trackdir_rev, false, &fstd, &user, NPF_INFINITE_PENALTY);  
  36+    if (ftd.best_bird_dist != 0) return FindDepotData();  
  37+  
  38+    /* Found target */  
  39+    /* Our caller wants the distance to depot. We provide it in distance manhattan */  
  40+    return FindDepotData(ftd.node.tile, DistanceManhattan(v->tile, ftd.node.tile), NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE));  
  41+}  
  42+  
  43 Track NPFShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found)  
  44 {  
  45     NPFFindStationOrTileData fstd;  
  46Index: src/pathfinder/npf/npf_func.h  
  47===================================================================  
  48--- src/pathfinder/npf/npf_func.h    (revision 27833)  
  49+++ src/pathfinder/npf/npf_func.h    (working copy)  
  50@@ -39,6 +39,14 @@  
  51 Trackdir NPFRoadVehicleChooseTrack(const RoadVehicle *v, TileIndex tile, DiagDirection enterdir, TrackdirBits trackdirs, bool &path_found);  
  52   
  53 /**  
  54+ * Used when user sends ship to the nearest depot or if ship needs servicing using NPF  
  55+ * @param v            ship that needs to go to some depot  
  56+ * @param max_distance not used  
  57+ * @return             the data about the depot  
  58+ */  
  59+FindDepotData NPFShipFindNearestDepot(const Ship *v, int max_distance);  
  60+  
  61+/**  
  62  * Finds the best path for given ship using NPF.  
  63  * @param v        the ship that needs to find a path  
  64  * @param tile     the tile to find the path from (should be next tile the ship is about to enter)  
  65Index: src/pathfinder/opf/opf_ship.cpp  
  66===================================================================  
  67--- src/pathfinder/opf/opf_ship.cpp    (revision 27833)  
  68+++ src/pathfinder/opf/opf_ship.cpp    (working copy)  
  69@@ -14,6 +14,7 @@  
  70 #include "../../tunnelbridge.h"  
  71 #include "../../ship.h"  
  72 #include "../../core/random_func.hpp"  
  73+#include "../pathfinder_type.h"  
  74   
  75 #include "../../safeguards.h"  
  76   
  77@@ -212,3 +213,8 @@  
  78     if (dist <= distr) return track;  
  79     return INVALID_TRACK; // We could better reverse  
  80 }  
  81+  
  82+FindDepotData OPFShipFindNearestDepot(const Ship *v, int max_distance) // todo  
  83+{  
  84+    return FindDepotData();  
  85+}  
  86Index: src/pathfinder/opf/opf_ship.h  
  87===================================================================  
  88--- src/pathfinder/opf/opf_ship.h    (revision 27833)  
  89+++ src/pathfinder/opf/opf_ship.h    (working copy)  
  90@@ -28,4 +28,13 @@  
  91  */  
  92 Track OPFShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found);  
  93   
  94+/**  
  95+ * Used when user sends ship to the nearest depot or if ship needs servicing using OPF.  
  96+ * @todo               this is just a placeholder, it's currently not implemented  
  97+ * @param v            vehicle that needs to go to some depot  
  98+ * @param max_distance not used  
  99+ * @return             the data about the depot  
  100+ */  
  101+FindDepotData OPFShipFindNearestDepot(const Ship *v, int max_distance);  
  102+  
  103 #endif /* OPF_SHIP_H */  
1Index: src/pathfinder/yapf/yapf.h  104Index: src/pathfinder/yapf/yapf.h  
2===================================================================  105===================================================================  
3--- src/pathfinder/yapf/yapf.h    (revision 27829)  3--- src/pathfinder/yapf/yapf.h    (revision 27833)
4+++ src/pathfinder/yapf/yapf.h    (working copy)  107+++ src/pathfinder/yapf/yapf.h    (working copy)  
5@@ -97,4 +97,14 @@  5@@ -97,4 +97,12 @@
6  */  109  */  
7 bool YapfTrainFindNearestSafeTile(const Train *v, TileIndex tile, Trackdir td, bool override_railtype);  110 bool YapfTrainFindNearestSafeTile(const Train *v, TileIndex tile, Trackdir td, bool override_railtype);  
8   111   
9+/**  112+/**  
10+ * Used when user sends ship to the nearest depot or if ship needs servicing using YAPF.  113+ * 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  114+ * @param v            vehicle that needs to go to some depot  
12+ * @param max_distance max distance (in pathfinder penalty) from the current vehicle position  12+ * @param max_distance not used
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  116+ * @return             the data about the depot  
16+ */  117+ */  
17+FindDepotData YapfShipFindNearestDepot(const Ship *v, int max_distance);  118+FindDepotData YapfShipFindNearestDepot(const Ship *v, int max_distance);  
18+  119+  
19 #endif /* YAPF_H */  120 #endif /* YAPF_H */  
20Index: 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;    
46Index: src/pathfinder/yapf/yapf_ship.cpp  121Index: src/pathfinder/yapf/yapf_ship.cpp  
47===================================================================  122===================================================================  
48--- src/pathfinder/yapf/yapf_ship.cpp    (revision 27829)  48--- src/pathfinder/yapf/yapf_ship.cpp    (revision 27833)
49+++ src/pathfinder/yapf/yapf_ship.cpp    (working copy)  124+++ src/pathfinder/yapf/yapf_ship.cpp    (working copy)  
50@@ -139,6 +139,43 @@  50@@ -139,6 +139,48 @@
51         assert(best_trackdir == td1 || best_trackdir == td2);  126         assert(best_trackdir == td1 || best_trackdir == td2);  
52         return best_trackdir == td2;  127         return best_trackdir == td2;  
53     }  128     }  
  
70+     */  145+     */  
71+    inline bool FindNearestDepot(const Ship *v, TileIndex tile, Trackdir td1, Trackdir td2, TileIndex *depot_tile, bool *reversed)  146+    inline bool FindNearestDepot(const Ship *v, TileIndex tile, Trackdir td1, Trackdir td2, TileIndex *depot_tile, bool *reversed)  
72+    {  147+    {  
73+        Tpf pf1;  73+        Tpf pf;
74+        Tpf pf2;    
75+        /* Set origin. */  149+        /* Set origin. */  
76+        pf1.SetOrigin(tile, TrackdirToTrackdirBits(td1));  150+        pf.SetOrigin(tile, TrackdirToTrackdirBits(td1) | TrackdirToTrackdirBits(td2));
77+        pf2.SetOrigin(tile, TrackdirToTrackdirBits(td2));  151+
78+  152+        /* find the best path */
79+        bool path_found1 = pf1.FindPath(v);  153+        bool bFound = pf.FindPath(v);
80+        bool path_found2 = pf2.FindPath(v);  154+        if (!bFound) return false;
81+        if (!path_found1 && !path_found2) return false;  155+
82+  156+        /* some path found
83+        Node *n;  157+         * get found depot tile */
84+        if (path_found1 || path_found2) {  158+        Node *n = pf.GetBestNode();
85+            n = path_found1 ? pf1.GetBestNode() : pf2.GetBestNode();  159+        *depot_tile = n->m_key.m_tile;
86+            *depot_tile = n->m_segment_last_tile;  160+
87+            *reversed = !path_found1 && path_found2;  161+        /* walk through the path back to the origin */
   162+        Node *pNode = n;
   163+        while (pNode->m_parent != NULL) {
   164+            pNode = pNode->m_parent;
88+        }  165+        }  
  166+  
  167+        /* if the origin node is the ship's Trackdir then we didn't reverse */  
  168+        *reversed = (pNode->m_key.m_td != td1);  
89+        return true;  169+        return true;  
90+    }  170+    }  
91 };  171 };  
92   172   
93 /** Cost Provider module of YAPF for ships */  173 /** Cost Provider module of YAPF for ships */  
94@@ -188,15 +225,53 @@  94@@ -188,15 +230,54 @@
95     }  175     }  
96 };  176 };  
97   177   
  
113+    /** Called by YAPF to detect if node ends in the desired destination */  193+    /** Called by YAPF to detect if node ends in the desired destination */  
114+    inline bool PfDetectDestination(Node &n)  194+    inline bool PfDetectDestination(Node &n)  
115+    {  195+    {  
116+        bool bDest = IsShipDepotTile(n.m_segment_last_tile) && GetShipDepotPart(n.m_segment_last_tile) == DEPOT_PART_NORTH;  196+       
   197+        bool bDest = (IsShipDepotTile(n.m_key.m_tile) && GetShipDepotPart(n.m_key.m_tile) == DEPOT_PART_NORTH) && IsTileOwner(n.m_key.m_tile, Yapf().GetVehicle()->owner);
117+        return bDest;  198+        return bDest;  
118+    }  199+    }  
119+  200+  
120+    inline bool PfDetectDestinationTile(TileIndex tile, Trackdir trackdir)  201+    inline bool PfDetectDestinationTile(TileIndex tile, Trackdir trackdir)  
121+    {  202+    {  
122+        return IsShipDepotTile(n.m_segment_last_tile) && GetShipDepotPart(n.m_segment_last_tile) == DEPOT_PART_NORTH;  122+        return (IsShipDepotTile(n.m_key.m_tile) && GetShipDepotPart(n.m_key.m_tile) == DEPOT_PART_NORTH) && IsTileOwner(n.m_key.m_tile, Yapf().GetVehicle()->owner);
123+    }  204+    }  
124+  205+  
125+    /**  206+    /**  
  
147   228   
148     /** Tpf - pathfinder type */  229     /** Tpf - pathfinder type */  
149     typedef Tpf_                              Tpf;  230     typedef Tpf_                              Tpf;  
150@@ -215,12 +290,16 @@  150@@ -215,12 +296,16 @@
151 };  232 };  
152   233   
153 /* YAPF type 1 - uses TileIndex/Trackdir as Node key, allows 90-deg turns */  234 /* YAPF type 1 - uses TileIndex/Trackdir as Node key, allows 90-deg turns */  
154-struct CYapfShip1 : CYapfT<CYapfShip_TypesT<CYapfShip1, CFollowTrackWater    , CShipNodeListTrackDir> > {};  235-struct CYapfShip1 : CYapfT<CYapfShip_TypesT<CYapfShip1, CFollowTrackWater    , CShipNodeListTrackDir> > {};  
155+struct CYapfShip1         : CYapfT<CYapfShip_TypesT<CYapfShip1        , CFollowTrackWater    , CShipNodeListTrackDir, CYapfDestinationTileT > > {};  155+struct CYapfShip1         : CYapfT<CYapfShip_TypesT<CYapfShip1        , CFollowTrackWater    , CShipNodeListTrackDir, CYapfDestinationTileT> > {};
156 /* YAPF type 2 - uses TileIndex/DiagDirection as Node key, allows 90-deg turns */  237 /* YAPF type 2 - uses TileIndex/DiagDirection as Node key, allows 90-deg turns */  
157-struct CYapfShip2 : CYapfT<CYapfShip_TypesT<CYapfShip2, CFollowTrackWater    , CShipNodeListExitDir > > {};  238-struct CYapfShip2 : CYapfT<CYapfShip_TypesT<CYapfShip2, CFollowTrackWater    , CShipNodeListExitDir > > {};  
158+struct CYapfShip2         : CYapfT<CYapfShip_TypesT<CYapfShip2        , CFollowTrackWater    , CShipNodeListExitDir , CYapfDestinationTileT > > {};  158+struct CYapfShip2         : CYapfT<CYapfShip_TypesT<CYapfShip2        , CFollowTrackWater    , CShipNodeListExitDir , CYapfDestinationTileT> > {};
159 /* YAPF type 3 - uses TileIndex/Trackdir as Node key, forbids 90-deg turns */  240 /* YAPF type 3 - uses TileIndex/Trackdir as Node key, forbids 90-deg turns */  
160-struct CYapfShip3 : CYapfT<CYapfShip_TypesT<CYapfShip3, CFollowTrackWaterNo90, CShipNodeListTrackDir> > {};  241-struct CYapfShip3 : CYapfT<CYapfShip_TypesT<CYapfShip3, CFollowTrackWaterNo90, CShipNodeListTrackDir> > {};  
161+struct CYapfShip3         : CYapfT<CYapfShip_TypesT<CYapfShip3        , CFollowTrackWaterNo90, CShipNodeListTrackDir, CYapfDestinationTileT > > {};  161+struct CYapfShip3         : CYapfT<CYapfShip_TypesT<CYapfShip3        , CFollowTrackWaterNo90, CShipNodeListTrackDir, CYapfDestinationTileT> > {};
162   162 
163+struct CYapfShipAnyDepot1 : CYapfT<CYapfShip_TypesT<CYapfShipAnyDepot1, CFollowTrackWater    , CShipNodeListTrackDir, CYapfDestinationAnyDepotShipT > > {};  163+struct CYapfShipAnyDepot1 : CYapfT<CYapfShip_TypesT<CYapfShipAnyDepot1, CFollowTrackWater    , CShipNodeListTrackDir, CYapfDestinationAnyDepotShipT> > {};
164+struct CYapfShipAnyDepot2 : CYapfT<CYapfShip_TypesT<CYapfShipAnyDepot2, CFollowTrackWater    , CShipNodeListExitDir , CYapfDestinationAnyDepotShipT > > {};  164+struct CYapfShipAnyDepot2 : CYapfT<CYapfShip_TypesT<CYapfShipAnyDepot2, CFollowTrackWater    , CShipNodeListExitDir , CYapfDestinationAnyDepotShipT> > {};
165+struct CYapfShipAnyDepot3 : CYapfT<CYapfShip_TypesT<CYapfShipAnyDepot3, CFollowTrackWaterNo90, CShipNodeListTrackDir, CYapfDestinationAnyDepotShipT > > {};  165+struct CYapfShipAnyDepot3 : CYapfT<CYapfShip_TypesT<CYapfShipAnyDepot3, CFollowTrackWaterNo90, CShipNodeListTrackDir, CYapfDestinationAnyDepotShipT> > {};
166+  247+  
167 /** Ship controller helper - path finder invoker */  248 /** Ship controller helper - path finder invoker */  
168 Track YapfShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found)  249 Track YapfShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found)  
169 {  250 {  
170@@ -239,6 +318,30 @@  170@@ -239,6 +324,31 @@
171     return (td_ret != INVALID_TRACKDIR) ? TrackdirToTrack(td_ret) : INVALID_TRACK;  252     return (td_ret != INVALID_TRACKDIR) ? TrackdirToTrack(td_ret) : INVALID_TRACK;  
172 }  253 }  
173   254   
174+FindDepotData YapfShipFindNearestDepot(const Ship *v, int max_penalty)  174+FindDepotData YapfShipFindNearestDepot(const Ship *v, int max_distance)
175+{  256+{  
176+    FindDepotData fdd;  257+    FindDepotData fdd;  
177+  258+  
  
191+    }  272+    }  
192+  273+  
193+    bool ret = pfnFindNearestDepot(v, tile, td, td_rev, &fdd.tile, &fdd.reverse);  274+    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  275+
   276+    fdd.best_length = ret ? DistanceManhattan(tile, fdd.tile) : UINT_MAX; // distance manhattan or NOT_FOUND
195+    return fdd;  277+    return fdd;  
196+}  278+}  
197+  279+  
  
200     Trackdir td = v->GetVehicleTrackdir();  282     Trackdir td = v->GetVehicleTrackdir();  
201Index: src/ship_cmd.cpp  283Index: src/ship_cmd.cpp  
202===================================================================  284===================================================================  
203--- src/ship_cmd.cpp    (revision 27829)  203--- src/ship_cmd.cpp    (revision 27833)
204+++ src/ship_cmd.cpp    (working copy)  286+++ src/ship_cmd.cpp    (working copy)  
205@@ -138,30 +138,17 @@  205@@ -138,7 +138,7 @@
206     result->Set(_ship_sprites[spritenum] + direction);  288     result->Set(_ship_sprites[spritenum] + direction);  
207 }  289 }  
208   290   
209-static const Depot *FindClosestShipDepot(const Vehicle *v, uint max_distance)  291-static const Depot *FindClosestShipDepot(const Vehicle *v, uint max_distance)  
  292+static FindDepotData FindClosestShipDepot(const Ship *v, uint max_distance)  
  293 {  
  294     /* Find the closest depot */  
  295     const Depot *depot;  
  296@@ -161,9 +161,27 @@  
  297         }  
  298     }  
  299   
  300-    return best_depot;  
  301+    FindDepotData fdd;  
  302+    if (best_depot != NULL) {  
  303+        fdd.best_length = best_dist;  
  304+        fdd.tile = best_depot->xy;  
  305+    }  
  306+    return fdd;  
  307 }  
  308   
210+static FindDepotData FindClosestReachableShipDepot(const Ship *v, int max_distance)  309+static FindDepotData FindClosestReachableShipDepot(const Ship *v, int max_distance)  
211 {  211+{
212-    /* Find the closest depot */  212+    if ((IsShipDepotTile(v->tile) && GetShipDepotPart(v->tile) == DEPOT_PART_NORTH) && IsTileOwner(v->tile, v->owner)) return FindDepotData(v->tile, 0);
213-    const Depot *depot;  213+
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) {  313+    switch (_settings_game.pf.pathfinder_for_ships) {  
233+//    case VPF_OPF: return OPFShipFindNearestDepot(v, max_distance); //TODO  233+    case VPF_OPF: return OPFShipFindNearestDepot(v, max_distance);
234+//    case VPF_NPF: return NPFShipFindNearestDepot(v, max_distance); //TODO  234+    case VPF_NPF: return NPFShipFindNearestDepot(v, max_distance);
235+    case VPF_YAPF: return YapfShipFindNearestDepot(v, max_distance);  316+    case VPF_YAPF: return YapfShipFindNearestDepot(v, max_distance);  
236+  317+  
237+    default: NOT_REACHED();  318+    default: NOT_REACHED();  
238     }  238+    }
239-  239+}
240-    return best_depot;  240+
241 }    
242     
243 static void CheckIfShipNeedsService(Vehicle *v)  322 static void CheckIfShipNeedsService(Vehicle *v)  
244@@ -180,9 +167,9 @@  323 {
   324     if (Company::Get(v->owner)->settings.vehicle.servint_ships == 0 || !v->NeedsAutomaticServicing()) return;
   325@@ -180,9 +198,9 @@
245         default: NOT_REACHED();  326         default: NOT_REACHED();  
246     }  327     }  
247   328   
248-    const Depot *depot = FindClosestShipDepot(v, max_distance);  329-    const Depot *depot = FindClosestShipDepot(v, max_distance);  
249+    const FindDepotData depot = FindClosestReachableShipDepot(Ship::From(v), max_distance);  249+    const FindDepotData sfdd = FindClosestReachableShipDepot(Ship::From(v), max_distance);
250   331   
251-    if (depot == NULL) {  332-    if (depot == NULL) {  
252+    if (depot.best_length == UINT_MAX) {  252+    if (sfdd.best_length == UINT_MAX || sfdd.best_length >= max_distance) {
253         if (v->current_order.IsType(OT_GOTO_DEPOT)) {  334         if (v->current_order.IsType(OT_GOTO_DEPOT)) {  
254             v->current_order.MakeDummy();  335             v->current_order.MakeDummy();  
255             SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);  336             SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);  
256@@ -190,8 +177,8 @@  256@@ -190,8 +208,8 @@
257         return;  338         return;  
258     }  339     }  
259   340   
260-    v->current_order.MakeGoToDepot(depot->index, ODTFB_SERVICE);  341-    v->current_order.MakeGoToDepot(depot->index, ODTFB_SERVICE);  
261-    v->dest_tile = depot->xy;  342-    v->dest_tile = depot->xy;  
262+    v->current_order.MakeGoToDepot(GetDepotIndex(depot.tile), ODTFB_SERVICE);  262+    v->current_order.MakeGoToDepot(GetDepotIndex(sfdd.tile), ODTFB_SERVICE);
263+    v->dest_tile = depot.tile;  263+    v->dest_tile = sfdd.tile;
264     SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);  345     SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);  
265 }  346 }  
266   347   
267@@ -712,12 +699,11 @@  267@@ -712,12 +730,15 @@
268   349   
269 bool Ship::FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse)  350 bool Ship::FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse)  
270 {  351 {  
271-    const Depot *depot = FindClosestShipDepot(this, 0);  352-    const Depot *depot = FindClosestShipDepot(this, 0);  
272+    FindDepotData sfdd = FindClosestReachableShipDepot(this, 0);  353+    FindDepotData sfdd = FindClosestReachableShipDepot(this, 0);  
273+    if (sfdd.best_length == UINT_MAX) return false;  354+    if (sfdd.best_length == UINT_MAX) {
   355+        sfdd = FindClosestShipDepot(this, 0);
   356+        if (sfdd.best_length == UINT_MAX) return false;
   357+    }
274   358   
275-    if (depot == NULL) return false;  359-    if (depot == NULL) return false;  
276+    if (location != NULL) *location = sfdd.tile;  276+    if (location    != NULL) *location = sfdd.tile;
277+    if (destination != NULL) *destination = GetDepotIndex(sfdd.tile);  361+    if (destination != NULL) *destination = GetDepotIndex(sfdd.tile);  
  362+    if (reverse     != NULL) *reverse = sfdd.reverse;  
278   363   
279-    if (location    != NULL) *location    = depot->xy;  364-    if (location    != NULL) *location    = depot->xy;  
280-    if (destination != NULL) *destination = depot->index;  365-    if (destination != NULL) *destination = depot->index;