(svn r3907) Replace many bridge related direct map accesses with calls to shiny new functions and mark some strange constructs with XXX
authortron
Thu, 16 Mar 2006 15:16:27 +0000
changeset 3234 a2791a480b71
parent 3233 9e09534dcac1
child 3235 a4c6479870ae
(svn r3907) Replace many bridge related direct map accesses with calls to shiny new functions and mark some strange constructs with XXX
ai/default/default.c
ai/trolly/pathfinder.c
bridge_map.h
npf.c
pathfind.c
rail.c
rail_cmd.c
road_cmd.c
road_map.c
smallmap_gui.c
train_cmd.c
tunnelbridge_cmd.c
water_cmd.c
--- a/ai/default/default.c	Thu Mar 16 13:35:35 2006 +0000
+++ b/ai/default/default.c	Thu Mar 16 15:16:27 2006 +0000
@@ -2157,8 +2157,7 @@
 			return true;
 		}
 
-		if (!(_m[tile].m5 & 0x40)) {
-
+		if (IsBridgeRamp(tile)) {
 			// Check if the bridge points in the right direction.
 			// This is not really needed the first place AiRemoveTileAndGoForward is called.
 			if (DiagDirToAxis(GetBridgeRampDirection(tile)) != (p->ai.cur_dir_a & 1U)) return false;
@@ -3669,8 +3668,12 @@
 				CMD_REMOVE_ROAD);
 		}
 	} else if (IsTileType(tile, MP_TUNNELBRIDGE)) {
-		if (!IsTileOwner(tile, _current_player) || (_m[tile].m5 & 0xC6) != 0x80)
+		if (!IsTileOwner(tile, _current_player) ||
+				!IsBridge(tile) ||
+				!IsBridgeRamp(tile) ||
+				GetBridgeTransportType(tile) != TRANSPORT_RAIL) {
 			return;
+		}
 
 		m5 = 0;
 
--- a/ai/trolly/pathfinder.c	Thu Mar 16 13:35:35 2006 +0000
+++ b/ai/trolly/pathfinder.c	Thu Mar 16 15:16:27 2006 +0000
@@ -2,6 +2,7 @@
 
 #include "../../stdafx.h"
 #include "../../openttd.h"
+#include "../../bridge_map.h"
 #include "../../debug.h"
 #include "../../functions.h"
 #include "../../map.h"
@@ -44,8 +45,7 @@
 		(IsTileType(tile, MP_STREET) && !IsTileDepotType(tile, TRANSPORT_ROAD)) ||
 		(IsTileType(tile, MP_TUNNELBRIDGE) && (
 			(IsTunnel(tile) && GetTunnelTransportType(tile) == TRANSPORT_ROAD) ||
-			// road bridge?
-			((_m[tile].m5 & 0x80) != 0 && (_m[tile].m5 & 0x2) == 0x2)
+			(IsBridge(tile) && GetBridgeTransportType(tile) == TRANSPORT_ROAD)
 		));
 }
 
@@ -234,7 +234,7 @@
 					if (IsTunnel(atile)) {
 						if (GetTunnelDirection(atile) != i) continue;
 					} else {
-						if ((_m[atile].m5 & 1U) != DiagDirToAxis(i)) continue;
+						if (GetBridgeRampDirection(atile) != i) continue;
 					}
 				}
 			}
--- a/bridge_map.h	Thu Mar 16 13:35:35 2006 +0000
+++ b/bridge_map.h	Thu Mar 16 15:16:27 2006 +0000
@@ -7,9 +7,21 @@
 #include "macros.h"
 #include "map.h"
 #include "rail.h"
+#include "road_map.h"
 #include "tile.h"
 
 
+static inline bool IsBridge(TileIndex t)
+{
+	return HASBIT(_m[t].m5, 7);
+}
+
+static inline bool IsBridgeTile(TileIndex t)
+{
+	return IsTileType(t, MP_TUNNELBRIDGE) && IsBridge(t);
+}
+
+
 static inline bool IsBridgeRamp(TileIndex t)
 {
 	return !HASBIT(_m[t].m5, 6);
@@ -61,6 +73,12 @@
 }
 
 
+static inline TransportType GetBridgeTransportType(TileIndex t)
+{
+	return (TransportType)GB(_m[t].m5, 1, 2);
+}
+
+
 static inline bool IsClearUnderBridge(TileIndex t)
 {
 	return GB(_m[t].m5, 3, 3) == 0;
@@ -82,6 +100,16 @@
 	return (TransportType)GB(_m[t].m5, 3, 2);
 }
 
+static inline RoadBits GetRoadBitsUnderBridge(TileIndex t)
+{
+	return GetBridgeAxis(t) == AXIS_X ? ROAD_Y : ROAD_X;
+}
+
+static inline TrackBits GetRailBitsUnderBridge(TileIndex t)
+{
+	return GetBridgeAxis(t) == AXIS_X ? TRACK_BIT_Y : TRACK_BIT_X;
+}
+
 
 /**
  * Finds the end of a bridge in the specified direction starting at a middle tile
--- a/npf.c	Thu Mar 16 13:35:35 2006 +0000
+++ b/npf.c	Thu Mar 16 15:16:27 2006 +0000
@@ -2,6 +2,7 @@
 
 #include "stdafx.h"
 #include "openttd.h"
+#include "bridge_map.h"
 #include "debug.h"
 #include "functions.h"
 #include "npf.h"
@@ -484,8 +485,10 @@
 			/* if we were on a railway middle part, we are now at a railway bridge ending */
 #endif
 			if ((IsTunnel(tile) && GetTunnelTransportType(tile) == TRANSPORT_RAIL) ||
-					(_m[tile].m5 & 0xC6) == 0x80 || /* railway bridge ending */
-					((_m[tile].m5 & 0xF8) == 0xE0 && GB(_m[tile].m5, 0, 1) != (enterdir & 0x1))) { /* railway under bridge */
+					(IsBridge(tile) && (
+						(IsBridgeRamp(tile) && GetBridgeTransportType(tile) == TRANSPORT_RAIL) ||
+						(IsBridgeMiddle(tile) && IsTransportUnderBridge(tile) && GetTransportTypeUnderBridge(tile) == TRANSPORT_RAIL)
+					))) {
 				return IsTileOwner(tile, owner);
 			}
 			break;
--- a/pathfind.c	Thu Mar 16 13:35:35 2006 +0000
+++ b/pathfind.c	Thu Mar 16 15:16:27 2006 +0000
@@ -2,6 +2,7 @@
 
 #include "stdafx.h"
 #include "openttd.h"
+#include "bridge_map.h"
 #include "functions.h"
 #include "map.h"
 #include "tile.h"
@@ -137,11 +138,18 @@
 
 	/* XXX: Mode 2 is currently only used for ships, why is this code here? */
 	if (tpf->tracktype == TRANSPORT_RAIL) {
-		if (IsTileType(tile, MP_RAILWAY) || IsTileType(tile, MP_STATION) || IsTileType(tile, MP_TUNNELBRIDGE)) {
-			owner = GetTileOwner(tile);
-			/* Check if we are on the middle of a bridge (has no owner) */
-			if (IsTileType(tile, MP_TUNNELBRIDGE) && (_m[tile].m5 & 0xC0) == 0xC0)
-				owner = -1;
+		switch (GetTileType(tile)) {
+			case MP_TUNNELBRIDGE:
+				// bridge middle has no owner
+				if (IsBridge(tile) && IsBridgeMiddle(tile)) break;
+				/* FALLTHROUGH */
+
+			case MP_RAILWAY:
+			case MP_STATION:
+				owner = GetTileOwner(tile);
+				break;
+
+			default: break; // XXX can this occur?
 		}
 	}
 
@@ -152,11 +160,19 @@
 
 	/* Check in case of rail if the owner is the same */
 	if (tpf->tracktype == TRANSPORT_RAIL) {
-		if (IsTileType(tile, MP_RAILWAY) || IsTileType(tile, MP_STATION) || IsTileType(tile, MP_TUNNELBRIDGE))
-			/* Check if we are on the middle of a bridge (has no owner) */
-			if (!IsTileType(tile, MP_TUNNELBRIDGE) || (_m[tile].m5 & 0xC0) != 0xC0)
-				if (owner != -1 && !IsTileOwner(tile, owner))
-					return;
+		switch (GetTileType(tile)) {
+			case MP_TUNNELBRIDGE:
+				// bridge middle has no owner
+				if (IsBridge(tile) && IsBridgeMiddle(tile)) break;
+				/* FALLTHROUGH */
+
+			case MP_RAILWAY:
+			case MP_STATION:
+				if (owner != -1 && !IsTileOwner(tile, owner)) return;
+				break;
+
+			default: break; // XXX can this occur?
+		}
 	}
 
 	if (++tpf->rd.cur_length > 50)
@@ -296,8 +312,8 @@
 		if (IsTileType(tile_org, MP_RAILWAY) || IsTileType(tile_org, MP_STATION) || IsTileType(tile_org, MP_TUNNELBRIDGE))
 			if (IsTileType(tile, MP_RAILWAY) || IsTileType(tile, MP_STATION) || IsTileType(tile, MP_TUNNELBRIDGE))
 				/* Check if we are on a bridge (middle parts don't have an owner */
-				if (!IsTileType(tile, MP_TUNNELBRIDGE) || (_m[tile].m5 & 0xC0) != 0xC0)
-					if (!IsTileType(tile_org, MP_TUNNELBRIDGE) || (_m[tile_org].m5 & 0xC0) != 0xC0)
+				if (!IsBridgeTile(tile) || !IsBridgeMiddle(tile))
+					if (!IsBridgeTile(tile_org) || !IsBridgeMiddle(tile_org))
 						if (GetTileOwner(tile_org) != GetTileOwner(tile))
 							return;
 	}
--- a/rail.c	Thu Mar 16 13:35:35 2006 +0000
+++ b/rail.c	Thu Mar 16 15:16:27 2006 +0000
@@ -2,6 +2,7 @@
 
 #include "stdafx.h"
 #include "openttd.h"
+#include "bridge_map.h"
 #include "rail.h"
 #include "station.h"
 #include "tunnel_map.h"
@@ -124,18 +125,32 @@
 				type = _m[tile].m3 & RAILTYPE_MASK;
 			break;
 		case MP_TUNNELBRIDGE:
-			if (IsTunnel(tile) && GetTunnelTransportType(tile) == TRANSPORT_RAIL) {
-				return _m[tile].m3 & RAILTYPE_MASK;
+			if (IsTunnel(tile)) {
+				if (GetTunnelTransportType(tile) == TRANSPORT_RAIL) {
+					return _m[tile].m3 & RAILTYPE_MASK;
+				}
+			} else {
+				if (IsBridgeRamp(tile)) {
+					if (GetBridgeTransportType(tile) == TRANSPORT_RAIL) {
+						return _m[tile].m3 & RAILTYPE_MASK;
+					}
+				} else {
+					if (GetBridgeAxis(tile) == DiagDirToAxis(exitdir)) {
+						if (GetBridgeTransportType(tile) == TRANSPORT_RAIL) {
+							/* on the bridge */
+							return (_m[tile].m3 >> 4) & RAILTYPE_MASK;
+						}
+					} else {
+						if (IsTransportUnderBridge(tile) &&
+								GetTransportTypeUnderBridge(tile) == TRANSPORT_RAIL) {
+							/* under the bridge */
+							return _m[tile].m3 & RAILTYPE_MASK;
+						}
+					}
+				}
 			}
-			/* railway bridge ending */
-			if ((_m[tile].m5 & 0xC6) == 0x80) type = _m[tile].m3 & RAILTYPE_MASK;
-			/* on railway bridge */
-			if ((_m[tile].m5 & 0xC6) == 0xC0 && ((DiagDirection)(_m[tile].m5 & 0x1)) == (exitdir & 0x1))
-				type = (_m[tile].m3 >> 4) & RAILTYPE_MASK;
-			/* under bridge (any type) */
-			if ((_m[tile].m5 & 0xF8) == 0xE0 && (_m[tile].m5 & 0x1U) != (exitdir & 0x1))
-				type = _m[tile].m3 & RAILTYPE_MASK;
 			break;
+
 		default:
 			break;
 	}
--- a/rail_cmd.c	Thu Mar 16 13:35:35 2006 +0000
+++ b/rail_cmd.c	Thu Mar 16 15:16:27 2006 +0000
@@ -288,27 +288,25 @@
 
 	switch (GetTileType(tile)) {
 		case MP_TUNNELBRIDGE:
-			if ((m5 & 0xC0) != 0xC0 || // not bridge middle part?
-					(m5 & 0x01 ? TRACK_BIT_X : TRACK_BIT_Y) != trackbit) { // wrong direction?
+			if (!IsBridge(tile) ||
+					!IsBridgeMiddle(tile) ||
+					(GetBridgeAxis(tile) == AXIS_X ? TRACK_BIT_Y : TRACK_BIT_X) != trackbit) {
 				// Get detailed error message
 				return DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 			}
 
-			switch (m5 & 0x38) { // what's under the bridge?
-				case 0x00: // clear land
-					ret = CheckRailSlope(tileh, trackbit, 0, tile);
-					if (CmdFailed(ret)) return ret;
-					cost += ret;
+			if (IsClearUnderBridge(tile)) {
+				ret = CheckRailSlope(tileh, trackbit, 0, tile);
+				if (CmdFailed(ret)) return ret;
+				cost += ret;
 
-					if (flags & DC_EXEC) SetRailUnderBridge(tile, _current_player, p1);
-					break;
-
-				case 0x20: // rail already there
-					return_cmd_error(STR_1007_ALREADY_BUILT);
-
-				default:
-					// Get detailed error message
-					return DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
+				if (flags & DC_EXEC) SetRailUnderBridge(tile, _current_player, p1);
+			} else if (IsTransportUnderBridge(tile) &&
+					GetTransportTypeUnderBridge(tile) == TRANSPORT_RAIL) {
+				return_cmd_error(STR_1007_ALREADY_BUILT);
+			} else {
+				// Get detailed error message
+				return DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 			}
 			break;
 
@@ -411,14 +409,14 @@
 	switch (GetTileType(tile))
 	{
 		case MP_TUNNELBRIDGE:
-			if (!EnsureNoVehicleZ(tile, TilePixelHeight(tile)))
+			if (!IsBridge(tile) ||
+					!IsBridgeMiddle(tile) ||
+					!IsTransportUnderBridge(tile) ||
+					GetTransportTypeUnderBridge(tile) != TRANSPORT_RAIL ||
+					GetRailBitsUnderBridge(tile) != trackbit ||
+					!EnsureNoVehicleZ(tile, TilePixelHeight(tile))) {
 				return CMD_ERROR;
-
-			if ((_m[tile].m5 & 0xF8) != 0xE0)
-				return CMD_ERROR;
-
-			if ((_m[tile].m5 & 1 ? TRACK_BIT_X : TRACK_BIT_Y) != trackbit)
-				return CMD_ERROR;
+			}
 
 			if (!(flags & DC_EXEC))
 				return _price.remove_rail;
--- a/road_cmd.c	Thu Mar 16 13:35:35 2006 +0000
+++ b/road_cmd.c	Thu Mar 16 15:16:27 2006 +0000
@@ -129,11 +129,11 @@
 		case MP_TUNNELBRIDGE:
 			if (!EnsureNoVehicleZ(tile, TilePixelHeight(tile))) return CMD_ERROR;
 
-			if ((ti.map5 & 0xE9) == 0xE8) {
-				if (pieces & ROAD_X) return CMD_ERROR;
-			} else if ((ti.map5 & 0xE9) == 0xE9) {
-				if (pieces & ROAD_Y) return CMD_ERROR;
-			} else {
+			if (!IsBridge(tile) ||
+					!IsBridgeMiddle(tile) ||
+					!IsTransportUnderBridge(tile) ||
+					GetTransportTypeUnderBridge(tile) != TRANSPORT_ROAD ||
+					(pieces & ComplementRoadBits(GetRoadBitsUnderBridge(tile))) != 0) {
 				return CMD_ERROR;
 			}
 
@@ -357,19 +357,23 @@
 				return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
 			}
 
-			/* is this middle part of a bridge? */
-			if ((ti.map5 & 0xC0) != 0xC0) goto do_clear;
+			if (!IsBridge(tile) || !IsBridgeMiddle(tile)) goto do_clear;
 
 			/* only allow roads pertendicular to bridge */
-			if (((pieces & ROAD_Y) != 0) == ((ti.map5 & 0x01U) != 0)) goto do_clear;
+			if ((pieces & (GetBridgeAxis(tile) == AXIS_X ? ROAD_X : ROAD_Y)) != 0) {
+				goto do_clear;
+			}
 
 			/* check if clear land under bridge */
-			if ((ti.map5 & 0xF8) == 0xE8) { /* road under bridge */
-				return_cmd_error(STR_1007_ALREADY_BUILT);
-			} else if ((ti.map5 & 0xE0) == 0xE0) { /* other transport route under bridge */
-				return_cmd_error(STR_1008_MUST_REMOVE_RAILROAD_TRACK);
-			} else if ((ti.map5 & 0xF8) == 0xC8) { /* water under bridge */
-				return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER);
+			if (IsTransportUnderBridge(tile)) {
+				switch (GetTransportTypeUnderBridge(tile)) {
+					case TRANSPORT_ROAD: return_cmd_error(STR_1007_ALREADY_BUILT);
+					default: return_cmd_error(STR_1008_MUST_REMOVE_RAILROAD_TRACK);
+				}
+			} else {
+				if (IsWaterUnderBridge(tile)) {
+					return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER);
+				}
 			}
 
 			/* all checked, can build road now! */
--- a/road_map.c	Thu Mar 16 13:35:35 2006 +0000
+++ b/road_map.c	Thu Mar 16 15:16:27 2006 +0000
@@ -25,15 +25,16 @@
 			return DiagDirToRoadBits(GetRoadStationDir(tile));
 
 		case MP_TUNNELBRIDGE:
-			if (_m[tile].m5 & 0x80) {
-				// bridge
-				if (_m[tile].m5 & 0x40) {
-					// middle part
-					if ((_m[tile].m5 & 0x38) != 0x28) return 0; // no road under bridge
-					return _m[tile].m5 & 1 ? ROAD_X : ROAD_Y;
+			if (IsBridge(tile)) {
+				if (IsBridgeMiddle(tile)) {
+					if (!IsTransportUnderBridge(tile) ||
+							GetBridgeTransportType(tile) != TRANSPORT_ROAD) {
+						return 0;
+					}
+					return GetRoadBitsUnderBridge(tile);
 				} else {
 					// ending
-					if (GB(_m[tile].m5, 1, 2) != TRANSPORT_ROAD) return 0; // not a road bridge
+					if (GetBridgeTransportType(tile) != TRANSPORT_ROAD) return 0;
 					return DiagDirToRoadBits(ReverseDiagDir(GetBridgeRampDirection(tile)));
 				}
 			} else {
--- a/smallmap_gui.c	Thu Mar 16 13:35:35 2006 +0000
+++ b/smallmap_gui.c	Thu Mar 16 15:16:27 2006 +0000
@@ -2,6 +2,7 @@
 
 #include "stdafx.h"
 #include "openttd.h"
+#include "bridge_map.h"
 #include "clear_map.h"
 #include "functions.h"
 #include "spritecache.h"
@@ -351,7 +352,7 @@
 		if (IsTunnel(tile)) {
 			tt = GetTunnelTransportType(tile);
 		} else {
-			tt = GB(_m[tile].m5, 1, 2);
+			tt = GetBridgeTransportType(tile);
 		}
 		switch (tt) {
 			case TRANSPORT_RAIL: t = MP_RAILWAY; break;
--- a/train_cmd.c	Thu Mar 16 13:35:35 2006 +0000
+++ b/train_cmd.c	Thu Mar 16 15:16:27 2006 +0000
@@ -2,6 +2,7 @@
 
 #include "stdafx.h"
 #include "openttd.h"
+#include "bridge_map.h"
 #include "debug.h"
 #include "functions.h"
 #include "gui.h"
@@ -2545,7 +2546,7 @@
 			break;
 
 		case MP_TUNNELBRIDGE:
-			if ((_m[tile].m5 & 0xC0) == 0xC0) { // is bridge middle part?
+			if (IsBridge(tile) && IsBridgeMiddle(tile)) {
 				uint height;
 				uint tileh = GetTileSlope(tile, &height);
 
--- a/tunnelbridge_cmd.c	Thu Mar 16 13:35:35 2006 +0000
+++ b/tunnelbridge_cmd.c	Thu Mar 16 15:16:27 2006 +0000
@@ -670,22 +670,18 @@
 		DoClearSquare(tile);
 		DoClearSquare(endtile);
 		for (c = tile + delta; c != endtile; c += delta) {
-			if (_m[c].m5 & 0x20) {
-				// transport under bridge
-				if (GB(_m[c].m5, 3, 2) == TRANSPORT_RAIL) {
-					MakeRailNormal(c, GetTileOwner(c), _m[c].m5 & 1 ? TRACK_BIT_X : TRACK_BIT_Y, GB(_m[c].m3, 0, 3));
+			if (IsTransportUnderBridge(c)) {
+				if (GetTransportTypeUnderBridge(c) == TRANSPORT_RAIL) {
+					MakeRailNormal(c, GetTileOwner(c), GetRailBitsUnderBridge(c), GB(_m[c].m3, 0, 3));
 				} else {
 					uint town = IsTileOwner(c, OWNER_TOWN) ? ClosestTownFromTile(c, (uint)-1)->index : 0;
-					MakeRoadNormal(c, GetTileOwner(c), _m[c].m5 & 1 ? ROAD_X : ROAD_Y, town);
+					MakeRoadNormal(c, GetTileOwner(c), GetRoadBitsUnderBridge(c), town);
 				}
 				MarkTileDirtyByTile(c);
 			} else {
-				// clear under bridge
-				if (GB(_m[c].m5, 3, 2) == 0) {
-					// grass under bridge
+				if (IsClearUnderBridge(c)) {
 					DoClearSquare(c);
 				} else {
-					// water under bridge
 					if (GetTileSlope(c, NULL) == 0) {
 						MakeWater(c);
 					} else {
@@ -705,12 +701,10 @@
 
 static int32 ClearTile_TunnelBridge(TileIndex tile, byte flags)
 {
-	byte m5 = _m[tile].m5;
-
 	if (IsTunnel(tile)) {
 		if (flags & DC_AUTO) return_cmd_error(STR_5006_MUST_DEMOLISH_TUNNEL_FIRST);
 		return DoClearTunnel(tile, flags);
-	} else if (m5 & 0x80) {
+	} else if (IsBridge(tile)) { // XXX Is this necessary?
 		if (flags & DC_AUTO) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
 		return DoClearBridge(tile, flags);
 	}
@@ -739,8 +733,10 @@
 			MarkTileDirtyByTile(endtile);
 		}
 		return (length + 1) * (_price.build_rail >> 1);
-	} else if ((_m[tile].m5 & 0xF8) == 0xE0) {
-		// bridge middle part with rail below
+	} else if (IsBridge(tile) &&
+			IsBridgeMiddle(tile) &&
+			IsTransportUnderBridge(tile) &&
+			GetTransportTypeUnderBridge(tile) == TRANSPORT_RAIL) {
 		// only check for train under bridge
 		if (!CheckTileOwnership(tile) || !EnsureNoVehicleZ(tile, TilePixelHeight(tile)))
 			return CMD_ERROR;
@@ -753,7 +749,7 @@
 			MarkTileDirtyByTile(tile);
 		}
 		return _price.build_rail >> 1;
-	} else if ((_m[tile].m5 & 0xC6) == 0x80) {
+	} else if (IsBridge(tile) && IsBridgeRamp(tile) && GetBridgeTransportType(tile) == TRANSPORT_RAIL) {
 		TileIndexDiff delta;
 		int32 cost;
 		uint z = TilePixelHeight(tile);
@@ -762,7 +758,6 @@
 
 		if (!CheckTileOwnership(tile)) return CMD_ERROR;
 
-		// railway bridge
 		endtile = GetOtherBridgeEnd(tile);
 		// Make sure there's no vehicle on the bridge
 		v = FindVehicleBetween(tile, endtile, z);
@@ -821,6 +816,7 @@
 
 static void DrawBridgePillars(const TileInfo *ti, int x, int y, int z)
 {
+	Axis axis = GetBridgeAxis(ti->tile);
 	const PalSpriteID *b;
 	PalSpriteID image;
 	int piece;
@@ -830,7 +826,7 @@
 	// Draw first piece
 	// (necessary for cantilever bridges)
 
-	image = b[12 + GB(ti->map5, 0, 1)];
+	image = b[axis == AXIS_X ? 12 : 13];
 	piece = GetBridgePiece(ti->tile);
 
 	if (image != 0 && piece != 0) {
@@ -838,7 +834,7 @@
 		DrawGroundSpriteAt(image, x, y, z);
 	}
 
-	image = b[GB(ti->map5, 0, 1) * 6 + piece];
+	image = b[piece + (axis == AXIS_X ? 0 : 6)];
 
 	if (image != 0) {
 		int back_height, front_height, i=z;
@@ -853,7 +849,7 @@
 
 		if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image);
 
-		p = _tileh_bits[(image & 1) * 2 + (ti->map5&0x01)];
+		p = _tileh_bits[(image & 1) * 2 + (axis == AXIS_X ? 0 : 1)];
 		front_height = ti->z + ((ti->tileh & p[0])?8:0);
 		back_height = ti->z + ((ti->tileh & p[1])?8:0);
 
@@ -920,7 +916,6 @@
 	const PalSpriteID *b;
 	bool ice = _m[ti->tile].m4 & 0x80;
 
-	// draw tunnel?
 	if (IsTunnel(ti->tile)) {
 		if (GetTunnelTransportType(ti->tile) == TRANSPORT_RAIL) {
 			image = GetRailTypeInfo(GB(_m[ti->tile].m3, 0, 4))->base_sprites.tunnel;
@@ -934,30 +929,30 @@
 		DrawGroundSprite(image);
 
 		AddSortableSpriteToDraw(image+1, ti->x + 15, ti->y + 15, 1, 1, 8, (byte)ti->z);
-	// draw bridge?
-	} else if (ti->map5 & 0x80) {
-		RailType rt;
+	} else if (IsBridge(ti->tile)) { // XXX is this necessary?
 		int base_offset;
 
-		if (HASBIT(ti->map5, 1)) { /* This is a road bridge */
-			base_offset = 8;
-		} else { /* Rail bridge */
-			if (HASBIT(ti->map5, 6)) { /* The bits we need depend on the fact whether it is a bridge head or not */
+		if (GetBridgeTransportType(ti->tile) == TRANSPORT_RAIL) {
+			RailType rt;
+
+			if (IsBridgeRamp(ti->tile)) {
+				rt = GB(_m[ti->tile].m3, 0, 3);
+			} else {
 				rt = GB(_m[ti->tile].m3, 4, 3);
-			} else {
-				rt = GB(_m[ti->tile].m3, 0, 3);
 			}
 
 			base_offset = GetRailTypeInfo(rt)->bridge_offset;
 			assert(base_offset != 8); /* This one is used for roads */
+		} else {
+			base_offset = 8;
 		}
 
 		/* as the lower 3 bits are used for other stuff, make sure they are clear */
 		assert( (base_offset & 0x07) == 0x00);
 
-		if (!(ti->map5 & 0x40)) {	// bridge ramps
+		if (IsBridgeRamp(ti->tile)) {
 			if (!(BRIDGE_NO_FOUNDATION & (1 << ti->tileh))) {	// no foundations for 0, 3, 6, 9, 12
-				int f = GetBridgeFoundation(ti->tileh, ti->map5 & 0x1);	// pass direction
+				int f = GetBridgeFoundation(ti->tileh, DiagDirToAxis(GetBridgeRampDirection(ti->tile)));
 				if (f) DrawFoundation(ti, f);
 			}
 
@@ -1002,7 +997,6 @@
 					image += rti->total_offset;
 					if (ice) image += rti->snow_offset;
 				} else {
-					// road
 					if (ti->tileh == 0) {
 						image = (axis == AXIS_X ? SPR_ROAD_Y : SPR_ROAD_X);
 					} else {
@@ -1037,12 +1031,11 @@
 			// draw rail or road component
 			image = b[0];
 			if (_display_opt & DO_TRANS_BUILDINGS) MAKE_TRANSPARENT(image);
-			AddSortableSpriteToDraw(
-				image, ti->x, ti->y,
-				axis == AXIS_X ? 16 : 11,
-				axis == AXIS_X ? 11 : 16,
-				1, z
-			);
+			if (axis == AXIS_X) {
+				AddSortableSpriteToDraw(image, ti->x, ti->y, 16, 11, 1, z);
+			} else {
+				AddSortableSpriteToDraw(image, ti->x, ti->y, 11, 16, 1, z);
+			}
 
 			x = ti->x;
 			y = ti->y;
@@ -1081,17 +1074,15 @@
 	uint tileh = ti->tileh;
 
 	// swap directions if Y tunnel/bridge to let the code handle the X case only.
-	if (ti->map5 & 1) uintswap(x,y);
+	if (ti->map5 & 1) uintswap(x,y); // XXX bogus: it could be a tunnel, bridge ramp or bridge middle tile
 
 	// to the side of the tunnel/bridge?
 	if (IS_INT_INSIDE(y, 5, 10+1)) {
-		// tunnel?
-		if ((ti->map5 & 0xF0) == 0) return z;
+		if (IsTunnel(ti->tile)) return z;
 
 		// bridge?
-		if (ti->map5 & 0x80) {
-			// bridge ending?
-			if (!(ti->map5 & 0x40)) {
+		if (IsBridge(ti->tile)) {
+			if (IsBridgeRamp(ti->tile)) {
 				if (BRIDGE_FULL_LEVELED_FOUNDATION & (1 << tileh)) // 7, 11, 13, 14
 					z += 8;
 
@@ -1105,8 +1096,6 @@
 					// ramp in opposite dir
 					return z + ((x ^ 0xF) >> 1);
 				}
-
-			// bridge middle part
 			} else {
 				// build on slopes?
 				if (tileh != 0) z += 8;
@@ -1119,8 +1108,9 @@
 
 				// in the shared area, assume that we're below the bridge, cause otherwise the hint would've caught it.
 				// if rail or road below then it means it's possibly build on slope below the bridge.
-				if (ti->map5 & 0x20) {
-					uint f = _bridge_foundations[ti->map5 & 1][tileh];
+				if (IsTransportUnderBridge(ti->tile)) {
+					uint f = _bridge_foundations[GetBridgeAxis(ti->tile)][tileh];
+
 					// make sure that the slope is not inclined foundation
 					if (IS_BYTE_INSIDE(f, 1, 15)) return z;
 
@@ -1132,11 +1122,10 @@
 			}
 		}
 	} else {
-		// if it's a bridge middle with transport route below, then we need to compensate for build on slopes
-		if ((ti->map5 & (0x80 | 0x40 | 0x20)) == (0x80 | 0x40 | 0x20)) {
+		if (IsBridge(ti->tile) && IsBridgeMiddle(ti->tile) && IsTransportUnderBridge(ti->tile)) {
 			uint f;
 			if (tileh != 0) z += 8;
-			f = _bridge_foundations[ti->map5 & 1][tileh];
+			f = _bridge_foundations[GetBridgeAxis(ti->tile)][tileh];
 			if (IS_BYTE_INSIDE(f, 1, 15)) return z;
 			if (f != 0) tileh = _inclined_tileh[f - 15];
 		}
@@ -1196,7 +1185,7 @@
 		td->str = (GetTunnelTransportType(tile) == TRANSPORT_RAIL) ?
 			STR_5017_RAILROAD_TUNNEL : STR_5018_ROAD_TUNNEL;
 	} else {
-		td->str = _bridge_tile_str[GB(_m[tile].m5, 1, 2) << 4 | GetBridgeType(tile)];
+		td->str = _bridge_tile_str[GetBridgeTransportType(tile) << 4 | GetBridgeType(tile)];
 
 		// the owner is stored at the end of the bridge
 		if (IsBridgeMiddle(tile)) tile = GetSouthernBridgeEnd(tile);
@@ -1235,8 +1224,9 @@
 			break;
 	}
 
-	// if it's a bridge with water below, call tileloop_water on it.
-	if ((_m[tile].m5 & 0xF8) == 0xC8) TileLoop_Water(tile);
+	if (IsBridge(tile) && IsBridgeMiddle(tile) && IsWaterUnderBridge(tile)) {
+		TileLoop_Water(tile);
+	}
 }
 
 static void ClickTile_TunnelBridge(TileIndex tile)
@@ -1248,41 +1238,34 @@
 static uint32 GetTileTrackStatus_TunnelBridge(TileIndex tile, TransportType mode)
 {
 	uint32 result;
-	byte m5 = _m[tile].m5;
 
 	if (IsTunnel(tile)) {
 		if (GetTunnelTransportType(tile) == mode) {
 			return DiagDirToAxis(GetTunnelDirection(tile)) == AXIS_X ? 0x101 : 0x202;
 		}
-	} else if (m5 & 0x80) {
+	} else if (IsBridge(tile)) { // XXX is this necessary?
 		/* This is a bridge */
 		result = 0;
-		if (GB(m5, 1, 2) == mode) {
+		if (GetBridgeTransportType(tile) == mode) {
 			/* Transport over the bridge is compatible */
-			result = m5 & 1 ? 0x202 : 0x101;
+			result = (GetBridgeAxis(tile) == AXIS_X ? 0x101 : 0x202);
 		}
-		if (m5 & 0x40) {
+		if (IsBridgeMiddle(tile)) {
 			/* Bridge middle part */
-			if (!(m5 & 0x20)) {
-				/* Clear ground or water underneath */
-				if ((m5 & 0x18) != 8) {
-					/* Clear ground */
+			if (IsTransportUnderBridge(tile)) {
+				if (GetTransportTypeUnderBridge(tile) != mode) return result;
+			} else {
+				if (IsClearUnderBridge(tile)) {
 					return result;
 				} else {
 					if (mode != TRANSPORT_WATER) return result;
 				}
-			} else {
-				/* Transport underneath */
-				if (GB(m5, 3, 2) != mode) {
-					/* Incompatible transport underneath */
-					return result;
-				}
 			}
 			/* If we've not returned yet, there is a compatible
 			 * transport or water beneath, so we can add it to
 			 * result */
 			/* Why is this xor'd ? Can't it just be or'd? */
-			result ^= m5 & 1 ? 0x101 : 0x202;
+			result ^= (GetBridgeAxis(tile) == AXIS_X ? 0x202 : 0x101);
 		}
 		return result;
 	} else {
@@ -1298,13 +1281,11 @@
 	if (new_player != OWNER_SPECTATOR) {
 		SetTileOwner(tile, new_player);
 	}	else {
-		if ((_m[tile].m5 & 0xE0) == 0xE0) {
+		if (IsBridge(tile) && IsBridgeMiddle(tile) && IsTransportUnderBridge(tile)) {
 			// the stuff BELOW the middle part is owned by the deleted player.
-			if (!(_m[tile].m5 & (1 << 4 | 1 << 3))) {
-				// convert railway into grass.
+			if (GetTransportTypeUnderBridge(tile) == TRANSPORT_RAIL) {
 				SetClearUnderBridge(tile);
 			} else {
-				// for road, change the owner of the road to local authority
 				SetTileOwner(tile, OWNER_NONE);
 			}
 		} else {
@@ -1396,13 +1377,13 @@
 				return 4;
 			}
 		}
-	} else if (_m[tile].m5 & 0x80) {
+	} else if (IsBridge(tile)) { // XXX is this necessary?
 		if (v->type == VEH_Road || (v->type == VEH_Train && IsFrontEngine(v))) {
 			uint h;
 
 			// Compensate for possible foundation
 			if (GetTileSlope(tile, &h) != 0) h += 8;
-			if (!(_m[tile].m5 & 0x40) || // start/end tile of bridge
+			if (IsBridgeRamp(tile) ||
 					myabs(h - v->z_pos) > 2) { // high above the ground -> on the bridge
 				/* modify speed of vehicle */
 				uint16 spd = _bridge[GetBridgeType(tile)].speed;
--- a/water_cmd.c	Thu Mar 16 13:35:35 2006 +0000
+++ b/water_cmd.c	Thu Mar 16 15:16:27 2006 +0000
@@ -241,13 +241,12 @@
 		if (IsTileType(tile, MP_WATER)) continue;
 
 		/* is middle piece of a bridge? */
-		if (IsTileType(tile, MP_TUNNELBRIDGE) && _m[tile].m5 & 0x40) { /* build under bridge */
-			if (_m[tile].m5 & 0x20) // transport route under bridge
+		if (IsBridgeTile(tile) && IsBridgeMiddle(tile)) {
+			if (IsTransportUnderBridge(tile)) {
 				return_cmd_error(STR_5800_OBJECT_IN_THE_WAY);
+			}
 
-			if (_m[tile].m5 & 0x18) { // already water under bridge
-				return_cmd_error(STR_1007_ALREADY_BUILT);
-			}
+			if (IsWaterUnderBridge(tile)) return_cmd_error(STR_1007_ALREADY_BUILT);
 
 			if (flags & DC_EXEC) SetWaterUnderBridge(tile);
 		} else {
@@ -354,8 +353,7 @@
 			return !(m5 < 75 || (m5 >= 83 && m5 <= 114));
 
 		case MP_TUNNELBRIDGE:
-			// true, if tile is middle part of bridge with water underneath
-			return (m5 & 0xF8) == 0xC8;
+			return IsBridge(tile) && IsBridgeMiddle(tile) && IsWaterUnderBridge(tile);
 
 		default:
 			return false;
@@ -542,8 +540,7 @@
 				break;
 
 			case MP_TUNNELBRIDGE:
-				// Middle part of bridge with clear land below?
-				if ((_m[target].m5 & 0xF8) == 0xC0) {
+				if (IsBridge(target) && IsBridgeMiddle(target) && IsClearUnderBridge(target)) {
 					SetWaterUnderBridge(target);
 					MarkTileDirtyByTile(target);
 				}
@@ -553,15 +550,14 @@
 				break;
 		}
 	} else {
-		if (IsTileType(target, MP_TUNNELBRIDGE)) {
-			byte m5 = _m[target].m5;
-			if ((m5 & 0xF8) == 0xC8 || (m5 & 0xF8) == 0xF0) return;
-
-			if ((m5 & 0xC0) == 0xC0) {
-				SetWaterUnderBridge(target);
-				MarkTileDirtyByTile(target);
+		if (IsBridgeTile(target) && IsBridgeMiddle(target)) {
+			if (IsWaterUnderBridge(target) ||
+					(IsTransportUnderBridge(target) && GetTransportTypeUnderBridge(target) == TRANSPORT_WATER)) { // XXX does this happen at all?
 				return;
 			}
+			SetWaterUnderBridge(target);
+			MarkTileDirtyByTile(target);
+			return;
 		}
 
 		_current_player = OWNER_WATER;