changeset 1967:4abec8c70409 draft

(svn r2473) - Add: VehicleMayEnterTile(), which checks if the tile owner of a tile is correct for a vehicle to enter it. Based upon glx's code. - Fix: [ 1203769 ] [NPF] NPF tries to plan over bridges, through tunnels, over level crossings of other players. (glx) - Codechange: Renamed TRANSPORT_MAX to TRANSPORT_END and added INVALID_TRANSPORT. - Codechange: Moved IsLevelCrossing() from tile.h to rail.h - Add: GetCrossingTransportType(), which returns the transport type (road, rail) of both tracks on a level crossing. - Removed old TODO that was fulfilled already.
author matthijs <matthijs@openttd.org>
date Wed, 22 Jun 2005 22:38:18 +0000
parents f2dd793ad872
children 612b06511120
files npf.c openttd.h rail.h tile.h
diffstat 4 files changed, 88 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/npf.c
+++ b/npf.c
@@ -399,6 +399,60 @@
 	ftd->node = current->path.node;
 }
 
+/**
+ * Finds out if a given player's vehicles are allowed to enter a given tile.
+ * @param owner    The owner of the vehicle.
+ * @param tile     The tile that is about to be entered.
+ * @param enterdir The direction from which the vehicle wants to enter the tile.
+ * @return         true if the vehicle can enter the tile.
+ * @todo           This function should be used in other places than just NPF,
+ *                 maybe moved to another file too.
+ */
+bool VehicleMayEnterTile(Owner owner, TileIndex tile, DiagDirection enterdir)
+{
+	if (
+		IsTileType(tile, MP_RAILWAY) /* Rail tile (also rail depot) */
+		|| IsTrainStationTile(tile) /* Rail station tile */
+		|| IsTileDepotType(tile, TRANSPORT_ROAD) /* Road depot tile */
+		|| IsRoadStationTile(tile) /* Road station tile */
+		|| IsTileDepotType(tile, TRANSPORT_WATER) /* Water depot tile */
+		)
+		return IsTileOwner(tile, owner); /* You need to own these tiles entirely to use them */
+
+	switch (GetTileType(tile)) {
+		case MP_STREET:
+			/* rail-road crossing : are we looking at the railway part? */
+			if (IsLevelCrossing(tile) && GetCrossingTransportType(tile, TrackdirToTrack(DiagdirToDiagTrackdir(enterdir))) == TRANSPORT_RAIL)
+				return IsTileOwner(tile, owner); /* Railway needs owner check, while the street is public */
+			break;
+		case MP_TUNNELBRIDGE:
+#if 0
+/* OPTIMISATION: If we are on the middle of a bridge, we will not do the cpu
+ * intensive owner check, instead we will just assume that if the vehicle
+ * managed to get on the bridge, it is probably allowed to :-)
+ */
+			if ((_map5[tile] & 0xC6) == 0xC0 && (unsigned)(_map5[tile] & 0x1) == (enterdir & 0x1)) {
+				/* on the middle part of a railway bridge: find bridge ending */
+				while (IsTileType(tile, MP_TUNNELBRIDGE) && !((_map5[tile] & 0xC6) == 0x80)) {
+					tile += TileOffsByDir(_map5[tile] & 0x1);
+				}
+			}
+			/* if we were on a railway middle part, we are now at a railway bridge ending */
+#endif
+			if (
+				(_map5[tile] & 0xFC) == 0 /* railway tunnel */
+				|| (_map5[tile] & 0xC6) == 0x80 /* railway bridge ending */
+				|| ((_map5[tile] & 0xF8) == 0xE0 && ((unsigned)_map5[tile] & 0x1) != (enterdir & 0x1)) /* railway under bridge */
+				)
+				return IsTileOwner(tile, owner);
+			break;
+		default:
+			break;
+	}
+
+	return true; /* no need to check */
+}
+
 /* Will just follow the results of GetTileTrackStatus concerning where we can
  * go and where not. Uses AyStar.user_data[NPF_TYPE] as the transport type and
  * an argument to GetTileTrackStatus. Will skip tunnels, meaning that the
@@ -480,16 +534,9 @@
 	}
 
 	/* Check the owner of the tile */
-	if (
-		IsTileType(dst_tile, MP_RAILWAY) /* Rail tile (also rail depot) */
-		|| IsTrainStationTile(dst_tile) /* Rail station tile */
-		|| IsTileDepotType(dst_tile, TRANSPORT_ROAD) /* Road depot tile */
-		|| IsRoadStationTile(dst_tile) /* Road station tile */
-		|| IsTileDepotType(dst_tile, TRANSPORT_WATER) /* Water depot tile */
-	) /* TODO: Crossings, tunnels and bridges are "public" now */
-		/* The above cases are "private" tiles, we need to check the owner */
-		if (!IsTileOwner(dst_tile, aystar->user_data[NPF_OWNER]))
-			return;
+	if (!VehicleMayEnterTile(aystar->user_data[NPF_OWNER], dst_tile, TrackdirToExitdir(src_trackdir))) {
+		return;
+	}
 
 	/* Determine available tracks */
 	if (type != TRANSPORT_WATER && (IsRoadStationTile(dst_tile) || IsTileDepotType(dst_tile, type))){
--- a/openttd.h
+++ b/openttd.h
@@ -106,7 +106,8 @@
   TRANSPORT_RAIL = 0,
 	TRANSPORT_ROAD = 1,
 	TRANSPORT_WATER,	// = 2
-	TRANSPORT_MAX			// = 3
+	TRANSPORT_END,
+	INVALID_TRANSPORT = 0xff,
 } TransportType;
 
 typedef struct TileInfo {
--- a/rail.h
+++ b/rail.h
@@ -443,4 +443,33 @@
  */
 RailType GetTileRailType(TileIndex tile, byte trackdir);
 
+/**
+ * Returns whether the given tile is a level crossing.
+ */
+static inline bool IsLevelCrossing(TileIndex tile)
+{
+	return (_map5[tile] & 0xF0) == 0x10;
+}
+
+/**
+ * Gets the transport type of the given track on the given crossing tile.
+ * @return  The transport type of the given track, either TRANSPORT_ROAD,
+ * TRANSPORT_RAIL.
+ */
+static inline TransportType GetCrossingTransportType(TileIndex tile, Track track)
+{
+	/* XXX: Nicer way to write this? */
+	switch(track)
+	{
+		/* When map5 bit 3 is set, the road runs in the y direction (DIAG2) */
+		case TRACK_DIAG1:
+			return (HASBIT(_map5[tile], 3) ? TRANSPORT_RAIL : TRANSPORT_ROAD);
+		case TRACK_DIAG2:
+			return (HASBIT(_map5[tile], 3) ? TRANSPORT_ROAD : TRANSPORT_RAIL);
+		default:
+			assert(0);
+	}
+	return INVALID_TRANSPORT;
+}
+
 #endif // RAIL_H
--- a/tile.h
+++ b/tile.h
@@ -18,7 +18,6 @@
 	MP_UNMOVABLE
 } TileType;
 
-/* TODO: Find out values */
 /* Direction as commonly used in v->direction, 8 way. */
 typedef enum Directions {
 	DIR_N   = 0,
@@ -116,9 +115,4 @@
 	return GetTileOwner(tile) == owner;
 }
 
-static inline bool IsLevelCrossing(TileIndex tile)
-{
-	return (_map5[tile] & 0xF0) == 0x10;
-}
-
 #endif