summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2009-08-31 19:16:18 +0000
committerrubidium <rubidium@openttd.org>2009-08-31 19:16:18 +0000
commitd938896691164bd7d06c79c2943e4368ae321af5 (patch)
treeb994dab79bfbdd1f1388042e95e6579f5e764db2
parenta1c7271eb0be00daee57100a4d9b815e6aa42067 (diff)
downloadopenttd-d938896691164bd7d06c79c2943e4368ae321af5.tar.xz
(svn r17333) -Codechange: make the road pathfinder 'interface' like the one for the rail pathfinder
-Fix [FS#3057]: road vehicles forgetting their servicing order when the path takes them away (in bird distance) from their destination first
-rw-r--r--src/roadveh_cmd.cpp62
-rw-r--r--src/yapf/yapf.h17
-rw-r--r--src/yapf/yapf_road.cpp23
3 files changed, 62 insertions, 40 deletions
diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp
index 98f655365..6f656bb9a 100644
--- a/src/roadveh_cmd.cpp
+++ b/src/roadveh_cmd.cpp
@@ -387,11 +387,24 @@ static bool EnumRoadSignalFindDepot(TileIndex tile, void *data, Trackdir trackdi
return false;
}
-static const Depot *FindClosestRoadDepot(const RoadVehicle *v)
+static RoadFindDepotData FindClosestRoadDepot(const RoadVehicle *v, int max_distance)
{
+ RoadFindDepotData rfdd;
+ rfdd.owner = v->owner;
+
+ if (IsRoadDepotTile(v->tile)) {
+ rfdd.tile = v->tile;
+ rfdd.best_length = 0;
+ return rfdd;
+ }
+
+ rfdd.best_length = UINT_MAX;
+
switch (_settings_game.pf.pathfinder_for_roadvehs) {
- case VPF_YAPF: // YAPF
- return YapfFindNearestRoadDepot(v);
+ case VPF_YAPF: { // YAPF
+ bool found = YapfFindNearestRoadDepot(v, max_distance, &rfdd.tile);
+ rfdd.best_length = found ? max_distance / 2 : UINT_MAX; // some fake distance or NOT_FOUND
+ } break;
case VPF_NPF: { // NPF
/* See where we are now */
@@ -399,36 +412,31 @@ static const Depot *FindClosestRoadDepot(const RoadVehicle *v)
NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, false, v->tile, ReverseTrackdir(trackdir), false, TRANSPORT_ROAD, v->compatible_roadtypes, v->owner, INVALID_RAILTYPES, 0);
- if (ftd.best_bird_dist == 0) return Depot::GetByTile(ftd.node.tile); // Target found
+ if (ftd.best_bird_dist == 0) {
+ rfdd.tile = ftd.node.tile;
+ rfdd.best_length = ftd.best_path_dist / NPF_TILE_LENGTH;
+ }
} break;
default:
- case VPF_OPF: { // OPF
- RoadFindDepotData rfdd;
-
- rfdd.owner = v->owner;
- rfdd.best_length = UINT_MAX;
-
+ case VPF_OPF: // OPF
/* search in all directions */
for (DiagDirection d = DIAGDIR_BEGIN; d < DIAGDIR_END; d++) {
FollowTrack(v->tile, PATHFIND_FLAGS_NONE, TRANSPORT_ROAD, v->compatible_roadtypes, d, EnumRoadSignalFindDepot, NULL, &rfdd);
}
-
- if (rfdd.best_length != UINT_MAX) return Depot::GetByTile(rfdd.tile);
- } break;
+ break;
}
- return NULL; // Target not found
+ return rfdd; // Target not found
}
bool RoadVehicle::FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse)
{
- const Depot *depot = FindClosestRoadDepot(this);
+ RoadFindDepotData rfdd = FindClosestRoadDepot(this, 0);
+ if (rfdd.best_length == UINT_MAX) return false;
- if (depot == NULL) return false;
-
- if (location != NULL) *location = depot->xy;
- if (destination != NULL) *destination = depot->index;
+ if (location != NULL) *location = rfdd.tile;
+ if (destination != NULL) *destination = Depot::GetByTile(rfdd.tile)->index;
return true;
}
@@ -1834,6 +1842,8 @@ bool RoadVehicle::Tick()
static void CheckIfRoadVehNeedsService(RoadVehicle *v)
{
+ static const uint MAX_ACCEPTABLE_DEPOT_DIST = 16;
+
/* If we already got a slot at a stop, use that FIRST, and go to a depot later */
if (v->slot != NULL || Company::Get(v->owner)->settings.vehicle.servint_roadveh == 0 || !v->NeedsAutomaticServicing()) return;
if (v->IsInDepot()) {
@@ -1841,17 +1851,21 @@ static void CheckIfRoadVehNeedsService(RoadVehicle *v)
return;
}
- /* XXX If we already have a depot order, WHY do we search over and over? */
- const Depot *depot = FindClosestRoadDepot(v);
-
- if (depot == NULL || DistanceManhattan(v->tile, depot->xy) > 12) {
+ RoadFindDepotData rfdd = FindClosestRoadDepot(v, MAX_ACCEPTABLE_DEPOT_DIST);
+ /* Only go to the depot if it is not too far out of our way. */
+ if (rfdd.best_length == UINT_MAX || rfdd.best_length > MAX_ACCEPTABLE_DEPOT_DIST) {
if (v->current_order.IsType(OT_GOTO_DEPOT)) {
+ /* If we were already heading for a depot but it has
+ * suddenly moved farther away, we continue our normal
+ * schedule? */
v->current_order.MakeDummy();
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
}
return;
}
+ const Depot *depot = Depot::GetByTile(rfdd.tile);
+
if (v->current_order.IsType(OT_GOTO_DEPOT) &&
v->current_order.GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS &&
!Chance16(1, 20)) {
@@ -1862,7 +1876,7 @@ static void CheckIfRoadVehNeedsService(RoadVehicle *v)
ClearSlot(v);
v->current_order.MakeGoToDepot(depot->index, ODTFB_SERVICE);
- v->dest_tile = depot->xy;
+ v->dest_tile = rfdd.tile;
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
}
diff --git a/src/yapf/yapf.h b/src/yapf/yapf.h
index 9adf22532..aaff42028 100644
--- a/src/yapf/yapf.h
+++ b/src/yapf/yapf.h
@@ -53,20 +53,25 @@ Trackdir YapfChooseRailTrack(const Vehicle *v, TileIndex tile, DiagDirection ent
*/
uint YapfRoadVehDistanceToTile(const Vehicle *v, TileIndex tile);
-/** Used when user sends RV to the nearest depot or if RV needs servicing.
- * Returns the nearest depot (or NULL if depot was not found).
+/** Used when user sends road vehicle to the nearest depot or if road vehicle needs servicing.
+ * @param v vehicle that needs to go to some depot
+ * @param max_distance max distance (number of track tiles) from the current vehicle position
+ * (used also as optimization - the pathfinder can stop path finding if max_distance
+ * was reached and no depot was seen)
+ * @param depot_tile receives the depot tile if depot was found
+ * @return true if depot was found.
*/
-Depot *YapfFindNearestRoadDepot(const Vehicle *v);
+bool YapfFindNearestRoadDepot(const Vehicle *v, int max_distance, TileIndex *depot_tile);
/** Used when user sends train to the nearest depot or if train needs servicing.
* @param v train that needs to go to some depot
* @param max_distance max distance (number of track tiles) from the current train position
- * (used also as optimization - the pathfinder can stop path finding if max_distance
- * was reached and no depot was seen)
+ * (used also as optimization - the pathfinder can stop path finding if max_distance
+ * was reached and no depot was seen)
* @param reverse_penalty penalty that should be added for the path that requires reversing the train first
* @param depot_tile receives the depot tile if depot was found
* @param reversed receives true if train needs to reversed first
- * @return the true if depot was found.
+ * @return true if depot was found.
*/
bool YapfFindNearestRailDepotTwoWay(const Vehicle *v, int max_distance, int reverse_penalty, TileIndex *depot_tile, bool *reversed);
diff --git a/src/yapf/yapf_road.cpp b/src/yapf/yapf_road.cpp
index a32eba665..2fe1e2374 100644
--- a/src/yapf/yapf_road.cpp
+++ b/src/yapf/yapf_road.cpp
@@ -390,13 +390,13 @@ public:
return true;
}
- static Depot *stFindNearestDepot(const Vehicle *v, TileIndex tile, Trackdir td)
+ static bool stFindNearestDepot(const Vehicle *v, TileIndex tile, Trackdir td, int max_distance, TileIndex *depot_tile)
{
Tpf pf;
- return pf.FindNearestDepot(v, tile, td);
+ return pf.FindNearestDepot(v, tile, td, max_distance, depot_tile);
}
- FORCEINLINE Depot *FindNearestDepot(const Vehicle *v, TileIndex tile, Trackdir td)
+ FORCEINLINE bool FindNearestDepot(const Vehicle *v, TileIndex tile, Trackdir td, int max_distance, TileIndex *depot_tile)
{
/* set origin and destination nodes */
Yapf().SetOrigin(tile, TrackdirToTrackdirBits(td));
@@ -408,10 +408,11 @@ public:
/* some path found
* get found depot tile */
Node *n = Yapf().GetBestNode();
- TileIndex depot_tile = n->m_segment_last_tile;
- assert(IsRoadDepotTile(depot_tile));
- Depot *ret = Depot::GetByTile(depot_tile);
- return ret;
+
+ if (max_distance > 0 && n->m_cost > max_distance * YAPF_TILE_LENGTH) return false;
+
+ *depot_tile = n->m_segment_last_tile;
+ return true;
}
};
@@ -474,8 +475,10 @@ uint YapfRoadVehDistanceToTile(const Vehicle *v, TileIndex tile)
return dist;
}
-Depot *YapfFindNearestRoadDepot(const Vehicle *v)
+bool YapfFindNearestRoadDepot(const Vehicle *v, int max_distance, TileIndex *depot_tile)
{
+ *depot_tile = INVALID_TILE;
+
TileIndex tile = v->tile;
Trackdir trackdir = v->GetVehicleTrackdir();
if ((TrackStatusToTrackdirBits(GetTileTrackStatus(tile, TRANSPORT_ROAD, RoadVehicle::From(v)->compatible_roadtypes)) & TrackdirToTrackdirBits(trackdir)) == 0) {
@@ -489,7 +492,7 @@ Depot *YapfFindNearestRoadDepot(const Vehicle *v)
}
/* default is YAPF type 2 */
- typedef Depot *(*PfnFindNearestDepot)(const Vehicle*, TileIndex, Trackdir);
+ typedef bool (*PfnFindNearestDepot)(const Vehicle*, TileIndex, Trackdir, int, TileIndex*);
PfnFindNearestDepot pfnFindNearestDepot = &CYapfRoadAnyDepot2::stFindNearestDepot;
/* check if non-default YAPF type should be used */
@@ -497,6 +500,6 @@ Depot *YapfFindNearestRoadDepot(const Vehicle *v)
pfnFindNearestDepot = &CYapfRoadAnyDepot1::stFindNearestDepot; // Trackdir, allow 90-deg
}
- Depot *ret = pfnFindNearestDepot(v, tile, trackdir);
+ bool ret = pfnFindNearestDepot(v, tile, trackdir, max_distance, depot_tile);
return ret;
}