changeset 1330:173a680c6b5f draft

(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO - Add: asserts to find the v->u.rail.track == 0 problem. - Add: IsValidDepot(), IsValidTown(), IsValidSign(), IsValidVehicle(), IsValidStation() - Add: GetTileOwner(), IsTileOwner() - Codechange: Replaced IsShipDepotTile(), IsTrainDepotTile(), IsRoadDepotTile() by IsTileDepotType(). - Codechange: typedeffed the MAP_OWNERS as Owner. Should be used as variable type. - Codechange: Replaced a few uint by TileIndex.
author matthijs <matthijs@openttd.org>
date Sun, 06 Feb 2005 22:36:08 +0000
parents 51edb33bc458
children 92744e02c8be
files ai.c ai_new.c ai_pathfinder.c depot.c depot.h industry.h map.h npf.c npf.h order_gui.c rail_cmd.c roadveh_cmd.c roadveh_gui.c ship_cmd.c ship_gui.c signs.h station.h tile.h town.h train_cmd.c train_gui.c ttd.h tunnelbridge_cmd.c vehicle.h
diffstat 24 files changed, 180 insertions(+), 130 deletions(-) [+]
line wrap: on
line diff
--- a/ai.c
+++ b/ai.c
@@ -284,7 +284,7 @@
 	uint tile;
 
 	// wait until the vehicle reaches the depot.
-	if (!IsTrainDepotTile(v->tile) || v->u.rail.track != 0x80 || !(v->vehstatus&VS_STOPPED)) {
+	if (!IsTileDepotType(v->tile, TRANSPORT_RAIL) || v->u.rail.track != 0x80 || !(v->vehstatus&VS_STOPPED)) {
 		AiHandleGotoDepot(p, CMD_TRAIN_GOTO_DEPOT);
 		return;
 	}
@@ -312,7 +312,7 @@
 	int veh;
 	uint tile;
 
-	if (!IsRoadDepotTile(v->tile) || v->u.road.state != 254 || !(v->vehstatus&VS_STOPPED)) {
+	if (!IsTileDepotType(v->tile, TRANSPORT_ROAD) || v->u.road.state != 254 || !(v->vehstatus&VS_STOPPED)) {
 		AiHandleGotoDepot(p, CMD_SEND_ROADVEH_TO_DEPOT);
 		return;
 	}
@@ -3561,7 +3561,7 @@
 	if (v->owner == _current_player) {
 		if (v->type == VEH_Train) {
 
-			if (!IsTrainDepotTile(v->tile) || v->u.rail.track != 0x80 || !(v->vehstatus&VS_STOPPED)) {
+			if (!IsTileDepotType(v->tile, TRANSPORT_RAIL) || v->u.rail.track != 0x80 || !(v->vehstatus&VS_STOPPED)) {
 				if (v->current_order.type != OT_GOTO_DEPOT)
 					DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_TRAIN_GOTO_DEPOT);
 				goto going_to_depot;
@@ -3571,7 +3571,7 @@
 			DoCommandByTile(v->tile, v->index, 1, DC_EXEC, CMD_SELL_RAIL_WAGON);
 
 		} else if (v->type == VEH_Road) {
-			if (!IsRoadDepotTile(v->tile) || v->u.road.state != 254 || !(v->vehstatus&VS_STOPPED)) {
+			if (!IsTileDepotType(v->tile, TRANSPORT_ROAD) || v->u.road.state != 254 || !(v->vehstatus&VS_STOPPED)) {
 				if (v->current_order.type != OT_GOTO_DEPOT)
 					DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SEND_ROADVEH_TO_DEPOT);
 				goto going_to_depot;
--- a/ai_new.c
+++ b/ai_new.c
@@ -1213,7 +1213,7 @@
 
 			// We are already sending him back
 			if (AiNew_GetSpecialVehicleFlag(p, v) & AI_VEHICLEFLAG_SELL) {
-				if (v->type == VEH_Road && IsRoadDepotTile(v->tile) &&
+				if (v->type == VEH_Road && IsTileDepotType(v->tile, TRANSPORT_ROAD) &&
 					(v->vehstatus&VS_STOPPED)) {
 					// We are at the depot, sell the vehicle
 					DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_ROAD_VEH);
--- a/ai_pathfinder.c
+++ b/ai_pathfinder.c
@@ -5,6 +5,7 @@
 #include "tile.h"
 #include "command.h"
 #include "ai.h"
+#include "depot.h"
 
 #define TEST_STATION_NO_DIR 0xFF
 
@@ -35,7 +36,7 @@
 {
 	return
 		// MP_STREET, but not a road depot?
-		(IsTileType(tile, MP_STREET) && !(_map5[tile] & 0x20)) ||
+		(IsTileType(tile, MP_STREET) && !(IsTileDepotType(tile, TRANSPORT_ROAD))) ||
 		(IsTileType(tile, MP_TUNNELBRIDGE) && (
 			// road tunnel?
 			((_map5[tile] & 0x80) == 0 && (_map5[tile] & 0x4) == 0x4) ||
--- a/depot.c
+++ b/depot.c
@@ -46,33 +46,6 @@
 }
 
 /**
- * Check if a tile is a road-depot
- */
-bool IsRoadDepotTile(TileIndex tile)
-{
-	return IsTileType(tile, MP_STREET) &&
-			(_map5[tile] & 0xF0) == 0x20;
-}
-
-/**
- * Check if a tile is a train-depot
- */
-bool IsTrainDepotTile(TileIndex tile)
-{
-	return IsTileType(tile, MP_RAILWAY) &&
-			(_map5[tile] & 0xFC) == 0xC0;
-}
-
-/**
- * Check if a tile is a ship-depot
- */
-bool IsShipDepotTile(TileIndex tile)
-{
-	return IsTileType(tile, MP_WATER) &&
-			(_map5[tile] & ~3) == 0x80;
-}
-
-/**
  * Allocate a new depot
  */
 Depot *AllocateDepot(void)
@@ -80,7 +53,7 @@
 	Depot *depot;
 
 	FOR_ALL_DEPOTS(depot) {
-		if (depot->xy == 0) {
+		if (!IsValidDepot(depot)) {
 			uint index = depot->index;
 
 			memset(depot, 0, sizeof(Depot));
@@ -142,7 +115,7 @@
 	Depot *depot;
 
 	FOR_ALL_DEPOTS(depot) {
-		if (depot->xy != 0) {
+		if (IsValidDepot(depot)) {
 			SlSetArrayIndex(depot->index);
 			SlObject(depot, _depot_desc);
 		}
--- a/depot.h
+++ b/depot.h
@@ -2,6 +2,7 @@
 #define DEPOT_H
 
 #include "pool.h"
+#include "tile.h"
 
 struct Depot {
 	TileIndex xy;
@@ -40,12 +41,39 @@
 VARDEF TileIndex _last_built_aircraft_depot_tile;
 VARDEF TileIndex _last_built_ship_depot_tile;
 
-bool IsTrainDepotTile(TileIndex tile);
-bool IsRoadDepotTile(TileIndex tile);
+/**
+ * Check if a depot really exists.
+ */
+static inline bool IsValidDepot(Depot* depot)
+{
+	return depot->xy != 0; /* XXX: Replace by INVALID_TILE someday */
+}
+
+/**
+ * Check if a tile is a depot of the given type.
+ */
+static inline bool IsTileDepotType(TileIndex tile, TransportType type)
+{
+	switch(type)
+	{
+		case TRANSPORT_RAIL:
+			return IsTileType(tile, MP_RAILWAY) && (_map5[tile] & 0xFC) == 0xC0;
+			break;
+		case TRANSPORT_ROAD:
+			return IsTileType(tile, MP_STREET) && (_map5[tile] & 0xF0) == 0x20;
+			break;
+		case TRANSPORT_WATER:
+			return IsTileType(tile, MP_WATER) && (_map5[tile] & ~3) == 0x80;
+			break;
+		default:
+			assert(0);
+			return false;
+	}
+}
+
 Depot *GetDepotByTile(uint tile);
 void InitializeDepot(void);
 Depot *AllocateDepot(void);
-bool IsShipDepotTile(TileIndex tile);
 void DoDeleteDepot(uint tile);
 
 #endif /* DEPOT_H */
--- a/industry.h
+++ b/industry.h
@@ -32,6 +32,14 @@
 extern MemoryPool _industry_pool;
 
 /**
+ * Check if an Industry really exists.
+ */
+static inline bool IsValidIndustry(Industry* industry)
+{
+	return industry->xy != 0; /* XXX: Replace by INVALID_TILE someday */
+}
+
+/**
  * Get the pointer to the industry with index 'index'
  */
 static inline Industry *GetIndustry(uint index)
--- a/map.h
+++ b/map.h
@@ -35,6 +35,14 @@
 uint ScaleByMapSize1D(uint); // Scale relative to the circumference of the map
 
 typedef uint32 TileIndex;
+
+typedef enum {
+	OWNER_TOWN			= 0xf,	// a town owns the tile
+	OWNER_NONE			= 0x10,	// nobody owns the tile
+	OWNER_WATER			= 0x11,	// "water" owns the tile
+	OWNER_SPECTATOR	= 0xff,	// spectator in MP or in scenario editor
+} Owner;
+
 enum {
 	INVALID_TILE = (uint32) -1
 };
--- a/npf.c
+++ b/npf.c
@@ -319,24 +319,7 @@
 /* Will find any depot */
 int32 NPFFindDepot(AyStar* as, OpenListNode *current) {
 	TileIndex tile = current->path.node.tile;
-	bool isDepot;
-	switch(GetTileType(tile)) {
-		case MP_RAILWAY:
-			/* Check if this is a rail depot */
-			isDepot = IsTrainDepotTile(tile);
-			break;
-		case MP_STREET:
-			/* Check if this is a road depot */
-			isDepot = IsRoadDepotTile(tile);
-			break;
-		case MP_WATER:
-			isDepot = IsShipDepotTile(tile);
-			break;
-		default:
-			isDepot = false;
-			break;
-	}
-	if (isDepot)
+	if (IsTileDepotType(tile, as->user_data[NPF_TYPE]))
 		return AYSTAR_FOUND_END_NODE;
 	else
 		return AYSTAR_DONE;
@@ -397,11 +380,7 @@
 		flotr = FindLengthOfTunnel(src_tile, src_exitdir);
 		dst_tile = flotr.tile;
 	} else {
-		if (
-			(type == TRANSPORT_ROAD && IsRoadStationTile(src_tile))
-			|| (type == TRANSPORT_ROAD && IsRoadDepotTile(src_tile))
-			|| (type == TRANSPORT_RAIL && IsTrainDepotTile(src_tile))
-			){
+		if (IsTileDepotType(src_tile, type)){
 			/* This is a road station or a train or road depot. We can enter and exit
 			 * those from one side only. Trackdirs don't support that (yet), so we'll
 			 * do this here. */
@@ -429,19 +408,29 @@
 	}
 
 	// TODO: check correct rail type (mono, maglev, etc)
-	// TODO: check tile owner
+
+	/* Check the owner of the tile */
+	if (
+		IsTileType(dst_tile, MP_RAILWAY) /* Rail tile */
+		|| IsTileDepotType(dst_tile, TRANSPORT_ROAD) /* Road depot tile */
+		|| IsTileType(dst_tile, MP_STATION) /* 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;
 
 	/* Determine available tracks */
-	if (type == TRANSPORT_ROAD && (IsRoadStationTile(dst_tile) || IsRoadDepotTile(dst_tile))){
-		byte exitdir;
+	if (type == TRANSPORT_ROAD && (IsRoadStationTile(dst_tile) || IsTileDepotType(dst_tile, TRANSPORT_ROAD))){
 		/* Road stations and depots return 0 on GTTS, so we have to do this by hand... */
-			if (IsRoadStationTile(dst_tile))
-				exitdir = GetRoadStationDir(dst_tile);
-			else /* Road depot */
-				exitdir = _map5[dst_tile] & 3; /* Extract the direction from the map */
-			ts = (1 << _dir_to_diag_trackdir[exitdir]) |
-					(1 << _dir_to_diag_trackdir[_reverse_dir[exitdir]]);
-					/* Find the trackdirs that are available for a station with this orientation. They are in both directions */
+		byte exitdir;
+		if (IsRoadStationTile(dst_tile))
+			exitdir = GetRoadStationDir(dst_tile);
+		else /* Road depot */
+			/* Find the trackdirs that are available for a depot with this orientation. They are in both directions */
+			exitdir = _map5[dst_tile] & 3; /* Extract the direction from the map */
+			ts = (1 << _dir_to_diag_trackdir[exitdir])
+			     | (1 << _dir_to_diag_trackdir[_reverse_dir[exitdir]]);
 	} else {
 		ts = GetTileTrackStatus(dst_tile, type);
 	}
@@ -500,7 +489,7 @@
  * multiple targets that are spread around, we should perform a breadth first
  * search by specifiying CalcZero as our heuristic.
  */
-NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start2, NPFFindStationOrTileData* target, AyStar_EndNodeCheck target_proc, AyStar_CalculateH heuristic_proc, TransportType type) {
+NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start2, NPFFindStationOrTileData* target, AyStar_EndNodeCheck target_proc, AyStar_CalculateH heuristic_proc, TransportType type, Owner owner) {
 	int r;
 	NPFFoundTargetData result;
 
@@ -539,6 +528,7 @@
 
 	/* Initialize user_data */
 	_npf_aystar.user_data[NPF_TYPE] = type;
+	_npf_aystar.user_data[NPF_OWNER] = owner;
 
 	/* GO! */
 	r = AyStarMain_Main(&_npf_aystar);
@@ -556,7 +546,7 @@
 	return result;
 }
 
-NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, byte trackdir1, TileIndex tile2, byte trackdir2, NPFFindStationOrTileData* target, TransportType type) {
+NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, byte trackdir1, TileIndex tile2, byte trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner) {
 	AyStarNode start1;
 	AyStarNode start2;
 
@@ -565,10 +555,10 @@
 	start1.direction = trackdir1;
 	start2.direction = trackdir2;
 
-	return NPFRouteInternal(&start1, &start2, target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type);
+	return NPFRouteInternal(&start1, &start2, target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type, owner);
 }
 
-NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, byte trackdir, NPFFindStationOrTileData* target, TransportType type) {
+NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, byte trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner) {
 	AyStarNode start;
 
 	assert(tile != 0);
@@ -579,10 +569,10 @@
 	 * return a not found then */
 	start.user_data[NPF_TRACKDIR_CHOICE] = 0xff;
 
-	return NPFRouteInternal(&start, NULL, target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type);
+	return NPFRouteInternal(&start, NULL, target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type, owner);
 }
 
-NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, byte trackdir, TransportType type) {
+NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, byte trackdir, TransportType type, Owner owner) {
 	AyStarNode start;
 
 	start.tile = tile;
@@ -593,10 +583,10 @@
 
 	/* perform a breadth first search. Target is NULL,
 	 * since we are just looking for any depot...*/
-	return NPFRouteInternal(&start, NULL, NULL, NPFFindDepot, NPFCalcZero, type);
+	return NPFRouteInternal(&start, NULL, NULL, NPFFindDepot, NPFCalcZero, type, owner);
 }
 
-NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, byte trackdir, TransportType type) {
+NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, byte trackdir, TransportType type, Owner owner) {
 	/* 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
 	 * distance. We start by trying to plan a route to the closest, then
@@ -629,7 +619,10 @@
 	init_InsSort(&depots);
 	/* Okay, let's find all depots that we can use first */
 	FOR_ALL_DEPOTS(depot) {
-		if (IsTileType(depot->xy, tiletype))
+		/* Check if this is really a valid depot, it is of the needed type and
+		 * owner */
+		if (IsValidDepot(depot) && IsTileDepotType(depot->xy, tiletype) && IsTileOwner(depot->xy, owner))
+			/* If so, let's add it to the queue, sorted by distance */
 			depots.push(&depots, depot, DistanceManhattan(tile, depot->xy));
 	}
 
@@ -655,6 +648,7 @@
 
 	/* Initialize user_data */
 	_npf_aystar.user_data[NPF_TYPE] = type;
+	_npf_aystar.user_data[NPF_OWNER] = owner;
 
 	/* Initialize Start Node */
 	start.tile = tile;
@@ -663,11 +657,12 @@
 	/* Initialize Result */
 	_npf_aystar.user_path = &result;
 	best_result.best_path_dist = (uint)-1;
+	best_result.best_bird_dist = (uint)-1;
 
 	/* Just iterate the depots in order of increasing distance */
 	while ((current = depots.pop(&depots))) {
 		/* Check to see if we already have a path shorter than this
-		 * depot's manhattan distance. Hack: We call DistanceManhattan
+		 * depot's manhattan distance. HACK: We call DistanceManhattan
 		 * again, we should probably modify the queue to give us that
 		 * value... */
 		if ( DistanceManhattan(tile, current->xy * NPF_TILE_LENGTH) > best_result.best_path_dist)
--- a/npf.h
+++ b/npf.h
@@ -15,7 +15,8 @@
 } NPFFindStationOrTileData;
 
 enum { /* Indices into AyStar.userdata[] */
-	NPF_TYPE = 0, /* Contains an TransportTypes value */
+	NPF_TYPE = 0, /* Contains a TransportTypes value */
+	NPF_OWNER, /* Contains an Owner value */
 };
 
 enum { /* Indices into AyStarNode.userdata[] */
@@ -30,7 +31,7 @@
 typedef struct NPFFoundTargetData { /* Meant to be stored in AyStar.userpath */
 	uint best_bird_dist; /* The best heuristic found. Is 0 if the target was found */
 	uint best_path_dist; /* The shortest path. Is (uint)-1 if no path is found */
-	byte best_trackdir; /* The trackdir that leads to the shortes path/closest birds dist */
+	byte best_trackdir; /* The trackdir that leads to the shortest path/closest birds dist */
 	AyStarNode node; /* The node within the target the search led us to */
 } NPFFoundTargetData;
 
@@ -39,20 +40,20 @@
 /* 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, byte trackdir, NPFFindStationOrTileData* target, TransportType type);
+NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, byte trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner);
 /* Will search as above, but with two start nodes, the second being the
  * reverse. Look at the NPF_NODE_REVERSE flag in the result node to see which
  * direction was taken */
-NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, byte trackdir1, TileIndex tile2, byte trackdir2, NPFFindStationOrTileData* target, TransportType type);
+NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, byte trackdir1, TileIndex tile2, byte trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner);
 
 /* 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, byte trackdir, TransportType type);
+NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, byte trackdir, TransportType type, Owner owner);
 /* 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, byte trackdir, TransportType type);
+ * of choices and accurate heuristics, such as water. */
+NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, byte trackdir, TransportType type, Owner owner);
 
 void NPFFillWithOrderData(NPFFindStationOrTileData* fstd, Vehicle* v);
 
--- a/order_gui.c
+++ b/order_gui.c
@@ -194,7 +194,7 @@
 
 		case MP_WATER:
 			if (v->type != VEH_Ship) break;
-			if ( IsShipDepotTile(tile) && _map_owner[tile] == _local_player) {
+			if ( IsTileDepotType(tile, TRANSPORT_ROAD) && IsTileOwner(tile, _local_player)) {
 				switch (_map5[tile]) {
 				case 0x81: tile--; break;
 				case 0x83: tile-= TILE_XY(0,1); break;
--- a/rail_cmd.c
+++ b/rail_cmd.c
@@ -2260,6 +2260,7 @@
 			if ((v=v->next) != NULL) {
 				v->vehstatus &= ~VS_HIDDEN;
 				v->u.rail.track = _depot_track_mask[dir];
+				assert(v->u.rail.track);
 			}
 		}
 	}
--- a/roadveh_cmd.c
+++ b/roadveh_cmd.c
@@ -116,12 +116,12 @@
 	int32 cost;
 	Vehicle *v;
 	UnitID unit_num;
-	uint tile = TILE_FROM_XY(x,y);
+	TileIndex tile = TILE_FROM_XY(x,y);
 	Engine *e;
 
 	if (!IsEngineBuildable(p1, VEH_Road)) return CMD_ERROR;
 
-	if (!IsRoadDepotTile((TileIndex)tile)) return CMD_ERROR;
+	if (!IsTileDepotType(tile, TRANSPORT_ROAD)) return CMD_ERROR;
 
 	if (_map_owner[tile] != _current_player) return CMD_ERROR;
 
@@ -243,7 +243,7 @@
 
 	SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
 
-	if (!IsRoadDepotTile(v->tile) || v->u.road.state != 254 || !(v->vehstatus&VS_STOPPED))
+	if (!IsTileDepotType(v->tile, TRANSPORT_ROAD) || v->u.road.state != 254 || !(v->vehstatus&VS_STOPPED))
 		return_cmd_error(STR_9013_MUST_BE_STOPPED_INSIDE);
 
 	if (flags & DC_EXEC) {
@@ -297,7 +297,7 @@
 		NPFFoundTargetData ftd;
 		/* See where we are now */
 		byte trackdir = _dir_to_diag_trackdir[(v->direction>>1)&3];
-		ftd = NPFRouteToDepotBreadthFirst(v->tile, trackdir, TRANSPORT_ROAD);
+		ftd = NPFRouteToDepotBreadthFirst(v->tile, trackdir, TRANSPORT_ROAD, v->owner);
 		if (ftd.best_bird_dist == 0)
 			return GetDepotByTile(ftd.node.tile); /* Target found */
 		else
@@ -1104,7 +1104,7 @@
 		trackdir = _dir_to_diag_trackdir[enterdir];
 		//debug("Finding path. Enterdir: %d, Trackdir: %d", enterdir, trackdir);
 
-		ftd = NPFRouteToStationOrTile(tile - TileOffsByDir(enterdir), trackdir, &fstd, TRANSPORT_ROAD);
+		ftd = NPFRouteToStationOrTile(tile - TileOffsByDir(enterdir), trackdir, &fstd, TRANSPORT_ROAD, v->owner);
 		if (ftd.best_bird_dist != 0 || ftd.best_trackdir == 0xff) {
 			/* Not found, just do something, or we are already there */
 			//TODO: maybe display error?
--- a/roadveh_gui.c
+++ b/roadveh_gui.c
@@ -822,7 +822,7 @@
 			DrawVehicleProfitButton(v, x, y + 13);
 
 			SetDParam(0, v->unitnumber);
-			if (IsRoadDepotTile(v->tile) && (v->vehstatus & VS_HIDDEN))
+			if (IsTileDepotType(v->tile, TRANSPORT_ROAD) && (v->vehstatus & VS_HIDDEN))
 				str = STR_021F;
 			else
 				str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2;
@@ -881,7 +881,7 @@
 
 			tile = _last_built_road_depot_tile;
 			do {
-				if (_map_owner[tile] == _local_player && IsRoadDepotTile(tile)) {
+				if (IsTileOwner(tile, _local_player) && IsTileDepotType(tile, TRANSPORT_ROAD)) {
 					ShowRoadDepotWindow(tile);
 					ShowBuildRoadVehWindow(tile);
 					return;
--- a/ship_cmd.c
+++ b/ship_cmd.c
@@ -69,14 +69,12 @@
 	Depot *depot;
 	Depot *best_depot = NULL;
 	uint tile, dist, best_dist = (uint)-1;
-	byte owner = v->owner;
 	uint tile2 = v->tile;
 
 	if (_patches.new_pathfinding_all) {
 		NPFFoundTargetData ftd;
 		byte trackdir = _track_direction_to_trackdir[FIND_FIRST_BIT(v->u.ship.state)][v->direction];
-		/* XXX --- SLOW!!!! */
-		ftd = NPFRouteToDepotTrialError(v->tile, trackdir, TRANSPORT_WATER);
+		ftd = NPFRouteToDepotTrialError(v->tile, trackdir, TRANSPORT_WATER, v->owner);
 		if (ftd.best_bird_dist == 0)
 			best_depot = GetDepotByTile(ftd.node.tile); /* Found target */
 		else
@@ -84,7 +82,7 @@
 	} else {
 		FOR_ALL_DEPOTS(depot) {
 			tile = depot->xy;
-			if (IsTileType(tile, MP_WATER) && _map_owner[tile] == owner) {
+			if (IsValidDepot(depot) && IsTileDepotType(tile, TRANSPORT_WATER) && IsTileOwner(tile, v->owner)) {
 				dist = DistanceManhattan(tile, tile2);
 				if (dist < best_dist) {
 					best_dist = dist;
@@ -598,7 +596,7 @@
 
 		NPFFillWithOrderData(&fstd, v);
 
-		ftd = NPFRouteToStationOrTile(src_tile, _track_direction_to_trackdir[track][v->direction], &fstd, TRANSPORT_WATER);
+		ftd = NPFRouteToStationOrTile(src_tile, _track_direction_to_trackdir[track][v->direction], &fstd, TRANSPORT_WATER, v->owner);
 
 		if (ftd.best_bird_dist == 0 && ftd.best_trackdir != 0xff)
 			/* Found the target, and it is not our current tile */
@@ -876,12 +874,12 @@
 	int32 value;
 	Vehicle *v;
 	UnitID unit_num;
-	uint tile = TILE_FROM_XY(x,y);
+	TileIndex tile = TILE_FROM_XY(x,y);
 	Engine *e;
 
 	if (!IsEngineBuildable(p1, VEH_Ship)) return CMD_ERROR;
 
-	if (!IsShipDepotTile((TileIndex)tile)) return CMD_ERROR;
+	if (!IsTileDepotType(tile, TRANSPORT_WATER)) return CMD_ERROR;
 
 	if (_map_owner[tile] != _current_player) return CMD_ERROR;
 
@@ -964,7 +962,7 @@
 
 	SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
 
-	if (!IsShipDepotTile(v->tile) || v->u.road.state != 0x80 || !(v->vehstatus&VS_STOPPED))
+	if (!IsTileDepotType(v->tile, TRANSPORT_WATER) || v->u.road.state != 0x80 || !(v->vehstatus&VS_STOPPED))
 		return_cmd_error(STR_980B_SHIP_MUST_BE_STOPPED_IN);
 
 	if (flags & DC_EXEC) {
@@ -1088,7 +1086,7 @@
 		return CMD_ERROR;
 
 	if (!( SkipStoppedInDepotCheck )) {
-		if (!IsShipDepotTile(v->tile) ||
+		if (!IsTileDepotType(v->tile, TRANSPORT_WATER) ||
 				!(v->vehstatus&VS_STOPPED) ||
 				v->u.ship.state != 0x80)
 			return_cmd_error(STR_980B_SHIP_MUST_BE_STOPPED_IN);
--- a/ship_gui.c
+++ b/ship_gui.c
@@ -491,7 +491,7 @@
 		if (ShipVehInfo(v->engine_type)->refittable &&
 				v->vehstatus&VS_STOPPED &&
 				v->u.ship.state == 0x80 &&
-				IsShipDepotTile(v->tile))
+				IsTileDepotType(v->tile, TRANSPORT_WATER))
 			disabled = 0;
 
 		if (v->owner != _local_player)
@@ -979,7 +979,7 @@
 			DrawVehicleProfitButton(v, x, y + 13);
 
 			SetDParam(0, v->unitnumber);
-			if (IsShipDepotTile(v->tile) && (v->vehstatus & VS_HIDDEN))
+			if (IsTileDepotType(v->tile, TRANSPORT_WATER) && (v->vehstatus & VS_HIDDEN))
 				str = STR_021F;
 			else
 				str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2;
@@ -1040,7 +1040,7 @@
 
 			tile = _last_built_ship_depot_tile;
 			do {
-				if (_map_owner[tile] == _local_player && IsShipDepotTile(tile)) {
+				if (_map_owner[tile] == _local_player && IsTileDepotType(tile, TRANSPORT_WATER)) {
 					ShowShipDepotWindow(tile);
 					ShowBuildShipWindow(tile);
 					return;
--- a/signs.h
+++ b/signs.h
@@ -18,6 +18,14 @@
 extern MemoryPool _sign_pool;
 
 /**
+ * Check if a Sign really exists.
+ */
+static inline bool IsValidSign(SignStruct* ss)
+{
+	return ss->str != 0;
+}
+
+/**
  * Get the pointer to the sign with index 'index'
  */
 static inline SignStruct *GetSign(uint index)
--- a/station.h
+++ b/station.h
@@ -272,6 +272,14 @@
 	return IsTileType(tile, MP_STATION) && IS_BYTE_INSIDE(_map5[tile], 0x43, 0x4B);
 }
 
+/**
+ * Check if a station really exists.
+ */
+static inline bool IsValidStation(Station* station)
+{
+	return station->xy != 0; /* XXX: Replace by INVALID_TILE someday */
+}
+
 /* Get's the direction the station exit points towards. Ie, returns 0 for a
  * station with the exit NE. */
 static inline byte GetRoadStationDir(uint tile) {
--- a/tile.h
+++ b/tile.h
@@ -57,4 +57,14 @@
 	return GetTileType(tile) == type;
 }
 
+static inline bool GetTileOwner(TileIndex tile)
+{
+	return _map_owner[tile];
+}
+
+static inline bool IsTileOwner(TileIndex tile, Owner owner)
+{
+	return GetTileOwner(tile) == owner;
+}
+
 #endif
--- a/town.h
+++ b/town.h
@@ -134,6 +134,14 @@
 extern MemoryPool _town_pool;
 
 /**
+ * Check if a Town really exists.
+ */
+static inline bool IsValidTown(Town* town)
+{
+	return town->xy != 0; /* XXX: Replace by INVALID_TILE someday */
+}
+
+/**
  * Get the pointer to the town with index 'index'
  */
 static inline Town *GetTown(uint index)
--- a/train_cmd.c
+++ b/train_cmd.c
@@ -538,11 +538,11 @@
 	Vehicle *v, *u;
 	UnitID unit_num;
 	Engine *e;
-	uint tile = TILE_FROM_XY(x,y);
+	TileIndex tile = TILE_FROM_XY(x,y);
 
 	if (!IsEngineBuildable(p1, VEH_Train)) return CMD_ERROR;
 
-	if (!IsTrainDepotTile((TileIndex)tile)) return CMD_ERROR;
+	if (!IsTileDepotType(tile, TRANSPORT_RAIL)) return CMD_ERROR;
 
 	if (_map_owner[tile] != _current_player) return CMD_ERROR;
 
@@ -641,7 +641,7 @@
 	TileIndex tile = v->tile;
 
 	/* check if stopped in a depot */
-	if (!IsTrainDepotTile(tile) || v->cur_speed != 0) {
+	if (!IsTileDepotType(tile, TRANSPORT_RAIL) || v->cur_speed != 0) {
 errmsg:
 		_error_message = STR_881A_TRAINS_CAN_ONLY_BE_ALTERED;
 		return -1;
@@ -1128,7 +1128,7 @@
 	int l = 0, r = -1;
 	Vehicle *u;
 
-	if (IsTrainDepotTile(v->tile))
+	if (IsTileDepotType(v->tile, TRANSPORT_RAIL))
 		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 
 	/* Check if we were approaching a rail/road-crossing */
@@ -1156,7 +1156,7 @@
 		ReverseTrainSwapVeh(v, l++, r--);
 	} while (l <= r);
 
-	if (IsTrainDepotTile(v->tile))
+	if (IsTileDepotType(v->tile, TRANSPORT_RAIL))
 		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 
 	CLRBIT(v->u.rail.flags, VRF_REVERSING);
@@ -1176,7 +1176,7 @@
 
 	_error_message = STR_EMPTY;
 
-//	if (v->u.rail.track & 0x80 || IsTrainDepotTile(v->tile))
+//	if (v->u.rail.track & 0x80 || IsTileDepotType(v->tile, TRANSPORT_RAIL))
 //		return CMD_ERROR;
 
 	if (v->u.rail.crash_anim_pos != 0 || v->breakdown_ctr != 0)
@@ -1300,7 +1300,7 @@
 	tfdd.owner = v->owner;
 	tfdd.best_length = (uint)-1;
 
-	if (IsTrainDepotTile(tile)){
+	if (IsTileDepotType(tile, TRANSPORT_RAIL)){
 		tfdd.tile = tile;
 		tfdd.best_length = 0;
 		return tfdd;
@@ -1311,7 +1311,7 @@
 	if (_patches.new_pathfinding_all) {
 		NPFFoundTargetData ftd;
 		byte trackdir = _track_direction_to_trackdir[FIND_FIRST_BIT(v->u.rail.track)][v->direction];
-		ftd = NPFRouteToDepotBreadthFirst(v->tile, trackdir, TRANSPORT_RAIL);
+		ftd = NPFRouteToDepotBreadthFirst(v->tile, trackdir, TRANSPORT_RAIL, v->owner);
 		if (ftd.best_bird_dist == 0) {
 			/* Found target */
 			tfdd.tile = ftd.node.tile;
@@ -1442,7 +1442,7 @@
 		switch (RailVehInfo(engtype)->engclass) {
 		case 0:
 			// steam smoke.
-			if ( (v->tick_counter&0xF) == 0 && !IsTrainDepotTile(v->tile) && !IsTunnelTile(v->tile)) {
+			if ( (v->tick_counter&0xF) == 0 && !IsTileDepotType(v->tile, TRANSPORT_RAIL) && !IsTunnelTile(v->tile)) {
 				CreateEffectVehicleRel(v,
 					(_vehicle_smoke_pos[v->direction]),
 					(_vehicle_smoke_pos[v->direction+8]),
@@ -1453,14 +1453,14 @@
 
 		case 1:
 			// diesel smoke
-			if (u->cur_speed <= 40 && !IsTrainDepotTile(v->tile) && !IsTunnelTile(v->tile) && (uint16)Random() <= 0x1E00) {
+			if (u->cur_speed <= 40 && !IsTileDepotType(v->tile, TRANSPORT_RAIL) && !IsTunnelTile(v->tile) && (uint16)Random() <= 0x1E00) {
 				CreateEffectVehicleRel(v, 0,0,10, EV_SMOKE_3);
 			}
 			break;
 
 		case 2:
 			// blue spark
-			if ( (v->tick_counter&0x3) == 0 && !IsTrainDepotTile(v->tile) && !IsTunnelTile(v->tile) && (uint16)Random() <= 0x5B0) {
+			if ( (v->tick_counter&0x3) == 0 && !IsTileDepotType(v->tile, TRANSPORT_RAIL) && !IsTunnelTile(v->tile) && (uint16)Random() <= 0x5B0) {
 				CreateEffectVehicleRel(v, 0,0,10, EV_SMOKE_2);
 			}
 			break;
@@ -1671,7 +1671,7 @@
 		trackdir = _track_exitdir_to_trackdir[FIND_FIRST_BIT(v->u.rail.track)][enterdir];
 		assert(trackdir != 0xff);
 
-		ftd = NPFRouteToStationOrTile(tile - TileOffsByDir(enterdir), trackdir, &fstd, TRANSPORT_RAIL);
+		ftd = NPFRouteToStationOrTile(tile - TileOffsByDir(enterdir), trackdir, &fstd, TRANSPORT_RAIL, v->owner);
 		if (ftd.best_bird_dist != 0 || ftd.best_trackdir == 0xff) {
 			/* Not found, or we are already there. Just do something */
 			//TODO: maybe display error?
@@ -1804,7 +1804,7 @@
 		assert(trackdir != 0xff);
 		assert(trackdir_rev != 0xff);
 
-		ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, last->tile, trackdir_rev, &fstd, TRANSPORT_RAIL);
+		ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, last->tile, trackdir_rev, &fstd, TRANSPORT_RAIL, v->owner);
 		if (ftd.best_bird_dist != 0) {
 			/* We didn't find anything, just keep on going straight ahead */
 			reverse_best = false;
@@ -2493,6 +2493,7 @@
 				if (!(r&0x4)) {
 					v->tile = gp.new_tile;
 					v->u.rail.track = chosen_track;
+					assert(v->u.rail.track);
 				}
 
 				if (v->subtype == TS_Front_Engine)
--- a/train_gui.c
+++ b/train_gui.c
@@ -1321,7 +1321,7 @@
 			DrawVehicleProfitButton(v, x, y + 13);
 
 			SetDParam(0, v->unitnumber);
-			if (IsTrainDepotTile(v->tile) && (v->vehstatus & VS_HIDDEN))
+			if (IsTileDepotType(v->tile, TRANSPORT_RAIL) && (v->vehstatus & VS_HIDDEN))
 				str = STR_021F;
 			else
 				str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2;
@@ -1382,7 +1382,7 @@
 
 			tile = _last_built_train_depot_tile;
 			do {
-				if (_map_owner[tile] == _local_player && IsTrainDepotTile(tile)) {
+				if (_map_owner[tile] == _local_player && IsTileDepotType(tile, TRANSPORT_RAIL)) {
 					ShowTrainDepotWindow(tile);
 					ShowBuildTrainWindow(tile);
 					return;
--- a/ttd.h
+++ b/ttd.h
@@ -510,13 +510,6 @@
 
 typedef void PlaceProc(uint tile);
 
-enum MAP_OWNERS {
-	OWNER_TOWN			= 0xf,	// a town owns the tile
-	OWNER_NONE			= 0x10,	// nobody owns the tile
-	OWNER_WATER			= 0x11,	// "water" owns the tile
-	OWNER_SPECTATOR	= 0xff,	// spectator in MP or in scenario editor
-};
-
 VARDEF bool _savegame_sort_dirty;
 VARDEF byte _savegame_sort_order;
 
--- a/tunnelbridge_cmd.c
+++ b/tunnelbridge_cmd.c
@@ -1435,6 +1435,7 @@
 				/* We're at the tunnel exit ?? */
 				v->tile = tile;
 				v->u.rail.track = _exit_tunnel_track[dir];
+				assert(v->u.rail.track);
 				v->vehstatus &= ~VS_HIDDEN;
 				return 4;
 			}
--- a/vehicle.h
+++ b/vehicle.h
@@ -372,6 +372,14 @@
 #define FOR_ALL_VEHICLES(v) FOR_ALL_VEHICLES_FROM(v, 0)
 
 /**
+ * Check if a Vehicle really exists.
+ */
+static inline bool IsValidVehicle(Vehicle* v)
+{
+	return v->type != 0;
+}
+
+/**
  * Check if an index is a vehicle-index (so between 0 and max-vehicles)
  *
  * @return Returns true if the vehicle-id is in range