Changeset - r12833:78c3d44bc582
[Not reviewed]
master
0 3 0
rubidium - 15 years ago 2009-08-31 19:16:18
rubidium@openttd.org
(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
3 files changed with 62 insertions and 40 deletions:
0 comments (0 inline, 0 general)
src/roadveh_cmd.cpp
Show inline comments
 
@@ -387,11 +387,24 @@ static bool EnumRoadSignalFindDepot(Tile
 
	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
 

	
 
			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(R
 
		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(R
 
	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);
 
}
 

	
src/yapf/yapf.h
Show inline comments
 
@@ -53,20 +53,25 @@ Trackdir YapfChooseRailTrack(const Vehic
 
 */
 
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);
 

	
src/yapf/yapf_road.cpp
Show inline comments
 
@@ -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 Veh
 
	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 Ve
 
	}
 

	
 
	/* 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 Ve
 
		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;
 
}
0 comments (0 inline, 0 general)