(svn r4919) - Backport from trunk (r4812, r4008, r4110): 0.4
authorDarkvater
Sat, 20 May 2006 15:54:46 +0000
branch0.4
changeset 10013 b6dc91f0cd71
parent 10012 dddbb8033ba3
child 10014 9157e384afb6
(svn r4919) - Backport from trunk (r4812, r4008, r4110):
NTP properly checks for railtypes on non-plain-rail-tiles
npf.c
npf.h
pathfind.c
pathfind.h
train_cmd.c
vehicle.h
--- a/npf.c	Tue May 16 22:11:15 2006 +0000
+++ b/npf.c	Sat May 20 15:54:46 2006 +0000
@@ -576,7 +576,7 @@
 	/* check correct rail type (mono, maglev, etc) */
 	if (type == TRANSPORT_RAIL) {
 		RailType dst_type = GetTileRailType(dst_tile, src_trackdir);
-		if (!IsCompatibleRail(aystar->user_data[NPF_RAILTYPE], dst_type))
+		if (!HASBIT(aystar->user_data[NPF_RAILTYPES], dst_type))
 			return;
 	}
 
@@ -649,7 +649,7 @@
  * multiple targets that are spread around, we should perform a breadth first
  * search by specifiying CalcZero as our heuristic.
  */
-static NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start2, NPFFindStationOrTileData* target, AyStar_EndNodeCheck target_proc, AyStar_CalculateH heuristic_proc, TransportType type, Owner owner, RailType railtype, uint reverse_penalty)
+static NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start2, NPFFindStationOrTileData* target, AyStar_EndNodeCheck target_proc, AyStar_CalculateH heuristic_proc, TransportType type, Owner owner, byte railtypes, uint reverse_penalty)
 {
 	int r;
 	NPFFoundTargetData result;
@@ -691,7 +691,7 @@
 	/* Initialize user_data */
 	_npf_aystar.user_data[NPF_TYPE] = type;
 	_npf_aystar.user_data[NPF_OWNER] = owner;
-	_npf_aystar.user_data[NPF_RAILTYPE] = railtype;
+	_npf_aystar.user_data[NPF_RAILTYPES] = railtypes;
 
 	/* GO! */
 	r = AyStarMain_Main(&_npf_aystar);
@@ -709,7 +709,7 @@
 	return result;
 }
 
-NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailType railtype)
+NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner, byte railtypes)
 {
 	AyStarNode start1;
 	AyStarNode start2;
@@ -723,15 +723,15 @@
 	start2.direction = trackdir2;
 	start2.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
 
-	return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type, owner, railtype, 0);
+	return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type, owner, railtypes, 0);
 }
 
-NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailType railtype)
+NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner, byte railtypes)
 {
-	return NPFRouteToStationOrTileTwoWay(tile, trackdir, INVALID_TILE, 0, target, type, owner, railtype);
+	return NPFRouteToStationOrTileTwoWay(tile, trackdir, INVALID_TILE, 0, target, type, owner, railtypes);
 }
 
-NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, TransportType type, Owner owner, RailType railtype, uint reverse_penalty)
+NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, TransportType type, Owner owner, byte railtypes, uint reverse_penalty)
 {
 	AyStarNode start1;
 	AyStarNode start2;
@@ -747,15 +747,15 @@
 
 	/* perform a breadth first search. Target is NULL,
 	 * since we are just looking for any depot...*/
-	return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), NULL, NPFFindDepot, NPFCalcZero, type, owner, railtype, reverse_penalty);
+	return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), NULL, NPFFindDepot, NPFCalcZero, type, owner, railtypes, reverse_penalty);
 }
 
-NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, RailType railtype)
+NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, byte railtypes)
 {
-	return NPFRouteToDepotBreadthFirstTwoWay(tile, trackdir, INVALID_TILE, 0, type, owner, railtype, 0);
+	return NPFRouteToDepotBreadthFirstTwoWay(tile, trackdir, INVALID_TILE, 0, type, owner, railtypes, 0);
 }
 
-NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, RailType railtype)
+NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, byte railtypes)
 {
 	/* Okay, what we're gonna do. First, we look at all depots, calculate
 	 * the manhatten distance to get to each depot. We then sort them by
--- a/npf.h	Tue May 16 22:11:15 2006 +0000
+++ b/npf.h	Sat May 20 15:54:46 2006 +0000
@@ -37,7 +37,7 @@
 enum { /* Indices into AyStar.userdata[] */
 	NPF_TYPE = 0, /* Contains a TransportTypes value */
 	NPF_OWNER, /* Contains an Owner value */
-	NPF_RAILTYPE, /* Contains the RailType value of the engine when NPF_TYPE == TRANSPORT_RAIL. Unused otherwise. */
+	NPF_RAILTYPES, /* Contains a bitmask the compatible RailTypes of the engine when NPF_TYPE == TRANSPORT_RAIL. Unused otherwise. */
 };
 
 enum { /* Indices into AyStarNode.userdata[] */
@@ -63,27 +63,27 @@
 /* Will search from the given tile and direction, for a route to the given
  * station for the given transport type. See the declaration of
  * NPFFoundTargetData above for the meaning of the result. */
-NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailType railtype);
+NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner, byte railtypes);
 /* Will search as above, but with two start nodes, the second being the
  * reverse. Look at the NPF_FLAG_REVERSE flag in the result node to see which
  * direction was taken (NPFGetBit(result.node, NPF_FLAG_REVERSE)) */
-NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailType railtype);
+NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner, byte railtypes);
 
 /* Will search a route to the closest depot. */
 
 /* Search using breadth first. Good for little track choice and inaccurate
  * heuristic, such as railway/road.*/
-NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, RailType railtype);
+NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, byte railtypes);
 /* Same as above but with two start nodes, the second being the reverse. Call
  * NPFGetBit(result.node, NPF_FLAG_REVERSE) to see from which node the path
  * orginated. All pathfs from the second node will have the given
  * reverse_penalty applied (NPF_TILE_LENGTH is the equivalent of one full
  * tile).
  */
-NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, TransportType type, Owner owner, RailType railtype, uint reverse_penalty);
+NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, TransportType type, Owner owner, byte railtypes, uint reverse_penalty);
 /* Search by trying each depot in order of Manhattan Distance. Good for lots
  * of choices and accurate heuristics, such as water. */
-NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, RailType railtype);
+NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, byte railtypes);
 
 void NPFFillWithOrderData(NPFFindStationOrTileData* fstd, Vehicle* v);
 
--- a/pathfind.c	Tue May 16 22:11:15 2006 +0000
+++ b/pathfind.c	Sat May 20 15:54:46 2006 +0000
@@ -5,8 +5,8 @@
 #include "functions.h"
 #include "map.h"
 #include "tile.h"
+#include "rail.h"
 #include "pathfind.h"
-#include "rail.h"
 #include "debug.h"
 #include "variables.h"
 #include "depot.h"
@@ -442,7 +442,8 @@
 	void *userdata;
 	TileIndex dest;
 
-	byte tracktype;
+	TransportType tracktype;
+	byte railtypes;
 	uint maxlength;
 
 	HashLink *new_link;
@@ -728,6 +729,11 @@
 					/* We are not driving into the tunnel, or it
 					 * is an invalid tunnel */
 					continue;
+
+				if (!HASBIT(tpf->railtypes, GetRailType(tile))) {
+					bits = 0;
+					break;
+				}
 				flotr = FindLengthOfTunnel(tile, direction);
 				si.cur_length += flotr.length * DIAG_FACTOR;
 				tile = flotr.tile;
@@ -760,6 +766,12 @@
 				// Check that the tile contains exactly one track
 				if (bits == 0 || KILL_FIRST_BIT(bits) != 0) break;
 
+				if ((IsTileType(tile, MP_STREET) && !HASBIT(tpf->railtypes, GB(_m[tile].m4, 0, 4))) ||
+				      !HASBIT(tpf->railtypes, GetRailType(tile))) {
+					bits = 0;
+					break;
+				}
+
 				///////////////////
 				// If we reach here, the tile has exactly one track.
 				//   tile - index to a tile that is not rail tile, but still straight (with optional signals)
@@ -781,6 +793,11 @@
 			 * bits, not just reachable ones, to prevent infinite loops. */
 			if (bits == 0 || TracksOverlap(allbits)) break;
 
+			if (!HASBIT(tpf->railtypes, GetRailType(tile))) {
+				bits = 0;
+				break;
+			}
+
 			/* If we reach here, the tile has exactly one track, and this
 			 track is reachable => Rail segment continues */
 
@@ -916,14 +933,15 @@
 
 
 // new pathfinder for trains. better and faster.
-void NewTrainPathfind(TileIndex tile, TileIndex dest, byte direction, NTPEnumProc *enum_proc, void *data)
+void NewTrainPathfind(TileIndex tile, TileIndex dest, byte railtypes, byte direction, NTPEnumProc *enum_proc, void *data)
 {
 	NewTrackPathFinder tpf;
 
 	tpf.dest = dest;
 	tpf.userdata = data;
 	tpf.enum_proc = enum_proc;
-	tpf.tracktype = 0;
+	tpf.tracktype = TRANSPORT_RAIL;
+	tpf.railtypes = railtypes;
 	tpf.maxlength = min(_patches.pf_maxlength * 3, 10000);
 	tpf.nstack = 0;
 	tpf.new_link = tpf.links;
--- a/pathfind.h	Tue May 16 22:11:15 2006 +0000
+++ b/pathfind.h	Sat May 20 15:54:46 2006 +0000
@@ -66,6 +66,6 @@
 } FindLengthOfTunnelResult;
 FindLengthOfTunnelResult FindLengthOfTunnel(TileIndex tile, uint direction);
 
-void NewTrainPathfind(TileIndex tile, TileIndex dest, byte direction, NTPEnumProc *enum_proc, void *data);
+void NewTrainPathfind(TileIndex tile, TileIndex dest, byte railtypes, byte direction, NTPEnumProc *enum_proc, void *data);
 
 #endif /* PATHFIND_H */
--- a/train_cmd.c	Tue May 16 22:11:15 2006 +0000
+++ b/train_cmd.c	Sat May 20 15:54:46 2006 +0000
@@ -88,6 +88,7 @@
 	rvi_v = RailVehInfo(v->engine_type);
 	first_engine = IsFrontEngine(v) ? v->engine_type : INVALID_VEHICLE;
 	v->u.rail.cached_total_length = 0;
+	v->u.rail.compatible_railtypes = 0;
 
 	for (u = v; u != NULL; u = u->next) {
 		const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type);
@@ -98,6 +99,7 @@
 
 		// update the 'first engine'
 		u->u.rail.first_engine = (v == u) ? INVALID_VEHICLE : first_engine;
+		u->u.rail.railtype = GetEngine(u->engine_type)->railtype;
 
 		if (rvi_u->visual_effect != 0) {
 			u->u.rail.cached_vis_effect = rvi_u->visual_effect;
@@ -135,6 +137,11 @@
 				}
 			}
 
+			/* Do not count powered wagons for the compatible railtypes, as
+			 * wagons always have railtype normal */
+			if (rvi_u->power > 0)
+				v->u.rail.compatible_railtypes |= GetRailTypeInfo(u->u.rail.railtype)->compatible_railtypes;
+
 			// max speed is the minimum of the speed limits of all vehicles in the consist
 			if (!(rvi_u->flags & RVI_WAGON) || _patches.wagon_speed_limits)
 				if (rvi_u->max_speed != 0 && !UsesWagonOverride(u))
@@ -1793,7 +1800,7 @@
 		Trackdir trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last));
 
 		assert (trackdir != INVALID_TRACKDIR);
-		ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, last->tile, trackdir_rev, TRANSPORT_RAIL, v->owner, v->u.rail.railtype, NPF_INFINITE_PENALTY);
+		ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, last->tile, trackdir_rev, TRANSPORT_RAIL, v->owner, v->u.rail.compatible_railtypes, NPF_INFINITE_PENALTY);
 		if (ftd.best_bird_dist == 0) {
 			/* Found target */
 			tfdd.tile = ftd.node.tile;
@@ -1809,13 +1816,13 @@
 		// search in the forward direction first.
 		i = v->direction >> 1;
 		if (!(v->direction & 1) && v->u.rail.track != _state_dir_table[i]) i = (i - 1) & 3;
-		NewTrainPathfind(tile, 0, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd);
+		NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd);
 		if (tfdd.best_length == (uint)-1){
 			tfdd.reverse = true;
 			// search in backwards direction
 			i = (v->direction^4) >> 1;
 			if (!(v->direction & 1) && v->u.rail.track != _state_dir_table[i]) i = (i - 1) & 3;
-			NewTrainPathfind(tile, 0, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd);
+			NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd);
 		}
 	}
 
@@ -2137,7 +2144,7 @@
 		trackdir = GetVehicleTrackdir(v);
 		assert(trackdir != 0xff);
 
-		ftd = NPFRouteToStationOrTile(tile - TileOffsByDir(enterdir), trackdir, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.railtype);
+		ftd = NPFRouteToStationOrTile(tile - TileOffsByDir(enterdir), trackdir, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.compatible_railtypes);
 
 		if (ftd.best_trackdir == 0xff) {
 			/* We are already at our target. Just do something */
@@ -2161,7 +2168,7 @@
 		fd.best_track = 0xFF;
 
 		NewTrainPathfind(tile - TileOffsByDir(enterdir), v->dest_tile,
-			enterdir, (NTPEnumProc*)NtpCallbFindStation, &fd);
+			v->u.rail.compatible_railtypes, enterdir, (NTPEnumProc*)NtpCallbFindStation, &fd);
 
 		if (fd.best_track == 0xff) {
 			// blaha
@@ -2217,7 +2224,7 @@
 		assert(trackdir != 0xff);
 		assert(trackdir_rev != 0xff);
 
-		ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, last->tile, trackdir_rev, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.railtype);
+		ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, last->tile, trackdir_rev, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.compatible_railtypes);
 		if (ftd.best_bird_dist != 0) {
 			/* We didn't find anything, just keep on going straight ahead */
 			reverse_best = false;
@@ -2232,7 +2239,7 @@
 			fd.best_bird_dist = (uint)-1;
 			fd.best_track_dist = (uint)-1;
 
-			NewTrainPathfind(v->tile, v->dest_tile, reverse ^ i, (NTPEnumProc*)NtpCallbFindStation, &fd);
+			NewTrainPathfind(v->tile, v->dest_tile, v->u.rail.compatible_railtypes, reverse ^ i, (NTPEnumProc*)NtpCallbFindStation, &fd);
 
 			if (best_track != -1) {
 				if (best_bird_dist != 0) {
@@ -2601,7 +2608,7 @@
 	return
 		IsTileOwner(tile, v->owner) && (
 			!IsFrontEngine(v) ||
-			IsCompatibleRail(v->u.rail.railtype, GetRailType(tile))
+			HASBIT(v->u.rail.compatible_railtypes, GetRailType(tile))
 		);
 }
 
--- a/vehicle.h	Tue May 16 22:11:15 2006 +0000
+++ b/vehicle.h	Sat May 20 15:54:46 2006 +0000
@@ -71,6 +71,7 @@
 	byte track;
 	byte force_proceed;
 	byte railtype;
+	byte compatible_railtypes;
 
 	byte flags;