changeset 13853:ce07aa728b20 draft

(svn r18382) -Codechange: make road vehicles behave more like trains 'around' stations and use pathfinder penalties to determine to which 'part' to go. Note that the pathfinder penalties for drive through stops are currently only looking at the occupation of the first in a row, but this is to change later on.
author rubidium <rubidium@openttd.org>
date Wed, 02 Dec 2009 17:56:02 +0000
parents 5caf1ea3a9f9
children f0479d827ebf
files src/pathfinder/npf/npf.cpp src/pathfinder/npf/npf.h src/pathfinder/yapf/yapf_road.cpp
diffstat 3 files changed, 52 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/src/pathfinder/npf/npf.cpp
+++ b/src/pathfinder/npf/npf.cpp
@@ -21,6 +21,7 @@
 #include "../../roadveh.h"
 #include "../../ship.h"
 #include "../../train.h"
+#include "../../roadstop_base.h"
 #include "../pathfinder_func.h"
 #include "../pathfinder_type.h"
 #include "npf.h"
@@ -104,8 +105,8 @@
 	uint dist;
 
 	/* for train-stations, we are going to aim for the closest station tile */
-	if (as->user_data[NPF_TYPE] == TRANSPORT_RAIL && fstd->station_index != INVALID_STATION)
-		to = CalcClosestStationTile(fstd->station_index, from, STATION_RAIL);
+	if (as->user_data[NPF_TYPE] != TRANSPORT_WATER && fstd->station_index != INVALID_STATION)
+		to = CalcClosestStationTile(fstd->station_index, from, fstd->station_type);
 
 	if (as->user_data[NPF_TYPE] == TRANSPORT_ROAD) {
 		/* Since roads only have diagonal pieces, we use manhattan distance here */
@@ -279,11 +280,13 @@
 			if (IsLevelCrossing(tile)) cost += _settings_game.pf.npf.npf_crossing_penalty;
 			break;
 
-		case MP_STATION:
+		case MP_STATION: {
 			cost = NPF_TILE_LENGTH;
 			/* Increase the cost for drive-through road stops */
 			if (IsDriveThroughStopTile(tile)) cost += _settings_game.pf.npf.npf_road_drive_through_penalty;
-			break;
+			RoadStop *rs = RoadStop::GetByTile(tile, GetRoadStopType(tile));
+			cost += 8 * NPF_TILE_LENGTH * ((!rs->IsFreeBay(0)) + (!rs->IsFreeBay(1)));
+		} break;
 
 		default:
 			break;
@@ -447,16 +450,14 @@
 	AyStarNode *node = &current->path.node;
 	TileIndex tile = node->tile;
 
-	/* If GetNeighbours said we could get here, we assume the station type
-	 * is correct */
-	if (
-		(fstd->station_index == INVALID_STATION && tile == fstd->dest_coords) || // We've found the tile, or
-		(IsTileType(tile, MP_STATION) && GetStationIndex(tile) == fstd->station_index) // the station
-	) {
-		return AYSTAR_FOUND_END_NODE;
-	} else {
-		return AYSTAR_DONE;
+	if (fstd->station_index == INVALID_STATION && tile == fstd->dest_coords) return AYSTAR_FOUND_END_NODE;
+
+	if (IsTileType(tile, MP_STATION) && GetStationIndex(tile) == fstd->station_index) {
+		if (fstd->station_type == STATION_RAIL) return AYSTAR_FOUND_END_NODE;
+		/* Only if it is a valid station *and* we can stop there */
+		if (GetStationType(tile) == fstd->station_type && (fstd->not_articulated || IsDriveThroughStopTile(tile))) return AYSTAR_FOUND_END_NODE;
 	}
+	return AYSTAR_DONE;
 }
 
 /**
@@ -1086,10 +1087,13 @@
 	 * dest_tile, not just any stop of that station.
 	 * So only for train orders to stations we fill fstd->station_index, for all
 	 * others only dest_coords */
-	if (v->type == VEH_TRAIN && (v->current_order.IsType(OT_GOTO_STATION) || v->current_order.IsType(OT_GOTO_WAYPOINT))) {
+	if (v->type != VEH_SHIP && (v->current_order.IsType(OT_GOTO_STATION) || v->current_order.IsType(OT_GOTO_WAYPOINT))) {
+		assert(v->type == VEH_TRAIN || v->type == VEH_ROAD);
 		fstd->station_index = v->current_order.GetDestination();
-		/* Let's take the closest tile of the station as our target for trains */
-		fstd->dest_coords = CalcClosestStationTile(fstd->station_index, v->tile, STATION_RAIL);
+		fstd->station_type = (v->type == VEH_TRAIN) ? STATION_RAIL : (RoadVehicle::From(v)->IsBus() ? STATION_BUS : STATION_TRUCK);
+		fstd->not_articulated = v->type == VEH_ROAD && !RoadVehicle::From(v)->HasArticulatedPart();
+		/* Let's take the closest tile of the station as our target for vehicles */
+		fstd->dest_coords = CalcClosestStationTile(fstd->station_index, v->tile, fstd->station_type);
 	} else {
 		fstd->dest_coords = v->dest_tile;
 		fstd->station_index = INVALID_STATION;
--- a/src/pathfinder/npf/npf.h
+++ b/src/pathfinder/npf/npf.h
@@ -33,10 +33,12 @@
 
 /* Meant to be stored in AyStar.targetdata */
 struct NPFFindStationOrTileData {
-	TileIndex dest_coords;   ///< An indication of where the station is, for heuristic purposes, or the target tile
-	StationID station_index; ///< station index we're heading for, or INVALID_STATION when we're heading for a tile
-	bool      reserve_path;  ///< Indicates whether the found path should be reserved
-	const Vehicle *v;        ///< The vehicle we are pathfinding for
+	TileIndex dest_coords;    ///< An indication of where the station is, for heuristic purposes, or the target tile
+	StationID station_index;  ///< station index we're heading for, or INVALID_STATION when we're heading for a tile
+	bool reserve_path;        ///< Indicates whether the found path should be reserved
+	StationType station_type; ///< The type of station we're heading for
+	bool not_articulated;     ///< The (road) vehicle is not articulated
+	const Vehicle *v;         ///< The vehicle we are pathfinding for
 };
 
 /* Indices into AyStar.userdata[] */
--- a/src/pathfinder/yapf/yapf_road.cpp
+++ b/src/pathfinder/yapf/yapf_road.cpp
@@ -66,11 +66,11 @@
 					}
 					break;
 
-				case MP_STATION:
-					if (IsDriveThroughStopTile(tile)) {
-						cost += Yapf().PfGetSettings().road_stop_penalty;
-					}
-					break;
+				case MP_STATION: {
+					if (IsDriveThroughStopTile(tile)) cost += Yapf().PfGetSettings().road_stop_penalty;
+					RoadStop *rs = RoadStop::GetByTile(tile, GetRoadStopType(tile));
+					cost += 8 * YAPF_TILE_LENGTH * ((!rs->IsFreeBay(0)) + (!rs->IsFreeBay(1)));
+				} break;
 
 				default:
 					break;
@@ -268,12 +268,24 @@
 protected:
 	TileIndex    m_destTile;
 	TrackdirBits m_destTrackdirs;
+	StationID    m_dest_station;
+	bool         m_bus;
+	bool         m_non_artic;
 
 public:
 	void SetDestination(const RoadVehicle *v)
 	{
-		m_destTile      = v->dest_tile;
-		m_destTrackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_ROAD, v->compatible_roadtypes));
+		if (v->current_order.IsType(OT_GOTO_STATION)) {
+			m_dest_station  = v->current_order.GetDestination();
+			m_bus           = v->IsBus();
+			m_destTile      = CalcClosestStationTile(m_dest_station, v->tile, m_bus ? STATION_BUS : STATION_TRUCK);
+			m_non_artic     = !v->HasArticulatedPart();
+			m_destTrackdirs = INVALID_TRACKDIR_BIT;
+		} else {
+			m_dest_station  = INVALID_STATION;
+			m_destTile      = v->dest_tile;
+			m_destTrackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_ROAD, v->compatible_roadtypes));
+		}
 	}
 
 protected:
@@ -292,6 +304,13 @@
 
 	FORCEINLINE bool PfDetectDestinationTile(TileIndex tile, Trackdir trackdir)
 	{
+		if (m_dest_station != INVALID_STATION) {
+			return IsTileType(tile, MP_STATION) &&
+				GetStationIndex(tile) == m_dest_station &&
+				(m_bus ? IsBusStop(tile) : IsTruckStop(tile)) &&
+				(m_non_artic || IsDriveThroughStopTile(tile));
+		}
+
 		return tile == m_destTile && ((m_destTrackdirs & TrackdirToTrackdirBits(trackdir)) != TRACKDIR_BIT_NONE);
 	}