diff options
author | rubidium <rubidium@openttd.org> | 2009-08-31 19:16:18 +0000 |
---|---|---|
committer | rubidium <rubidium@openttd.org> | 2009-08-31 19:16:18 +0000 |
commit | d938896691164bd7d06c79c2943e4368ae321af5 (patch) | |
tree | b994dab79bfbdd1f1388042e95e6579f5e764db2 | |
parent | a1c7271eb0be00daee57100a4d9b815e6aa42067 (diff) | |
download | openttd-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.cpp | 62 | ||||
-rw-r--r-- | src/yapf/yapf.h | 17 | ||||
-rw-r--r-- | src/yapf/yapf_road.cpp | 23 |
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; } |