(svn r3777) Add some functions to handle tunnels
authortron
Mon, 06 Mar 2006 20:55:24 +0000
changeset 3154 a8fffb204d0e
parent 3153 301c1d71122b
child 3155 b2cd7bc9f90f
(svn r3777) Add some functions to handle tunnels
Makefile
direction.h
npf.c
pathfind.c
rail_cmd.c
road_map.c
town_cmd.c
train_cmd.c
tunnel_map.c
tunnel_map.h
tunnelbridge_cmd.c
--- a/Makefile	Mon Mar 06 20:28:28 2006 +0000
+++ b/Makefile	Mon Mar 06 20:55:24 2006 +0000
@@ -700,6 +700,7 @@
 SRCS += train_cmd.c
 SRCS += train_gui.c
 SRCS += tree_cmd.c
+SRCS += tunnel_map.c
 SRCS += tunnelbridge_cmd.c
 SRCS += unmovable_cmd.c
 SRCS += vehicle.c
--- a/direction.h	Mon Mar 06 20:28:28 2006 +0000
+++ b/direction.h	Mon Mar 06 20:55:24 2006 +0000
@@ -52,4 +52,10 @@
 	AXIS_Y = 1
 } Axis;
 
+
+static inline Axis DiagDirToAxis(DiagDirection d)
+{
+	return (Axis)(d & 1);
+}
+
 #endif
--- a/npf.c	Mon Mar 06 20:28:28 2006 +0000
+++ b/npf.c	Mon Mar 06 20:55:24 2006 +0000
@@ -11,6 +11,7 @@
 #include "station.h"
 #include "tile.h"
 #include "depot.h"
+#include "tunnel_map.h"
 
 static AyStar _npf_aystar;
 
@@ -162,7 +163,7 @@
 {
 	DiagDirection exitdir = TrackdirToExitdir((Trackdir)current->direction);
 	TileIndex tile = current->tile;
-	if ((DiagDirection)GB(_m[tile].m5, 0, 2) == ReverseDiagDir(exitdir)) {
+	if (GetTunnelDirection(tile) == ReverseDiagDir(exitdir)) {
 		/* We just popped out if this tunnel, since were
 		 * facing the tunnel exit */
 		FindLengthOfTunnelResult flotr;
@@ -519,7 +520,7 @@
 	/* Find dest tile */
 	if (IsTileType(src_tile, MP_TUNNELBRIDGE) &&
 			GB(_m[src_tile].m5, 4, 4) == 0 &&
-			(DiagDirection)GB(_m[src_tile].m5, 0, 2) == src_exitdir) {
+			GetTunnelDirection(src_tile) == src_exitdir) {
 		/* This is a tunnel. We know this tunnel is our type,
 		 * otherwise we wouldn't have got here. It is also facing us,
 		 * so we should skip it's body */
--- a/pathfind.c	Mon Mar 06 20:28:28 2006 +0000
+++ b/pathfind.c	Mon Mar 06 20:55:24 2006 +0000
@@ -8,6 +8,7 @@
 #include "pathfind.h"
 #include "rail.h"
 #include "debug.h"
+#include "tunnel_map.h"
 #include "variables.h"
 
 // remember which tiles we have already visited so we don't visit them again.
@@ -232,8 +233,8 @@
 
 		if (IsTileType(tile, MP_TUNNELBRIDGE) &&
 				GB(_m[tile].m5, 4, 4) == 0 &&               // tunnel entrance/exit
-				// GB(_m[tile].m5, 2, 2) == type &&            // rail/road-tunnel <-- This is not necesary to check, right?
-				(GB(_m[tile].m5, 0, 2) ^ 2) == direction && // entrance towards: 0 = NE, 1 = SE, 2 = SW, 3 = NW
+				// GetTunnelTransportType(tile) == type &&  // rail/road-tunnel <-- This is not necesary to check, right?
+				ReverseDiagDir(GetTunnelDirection(tile)) == direction &&
 				GetSlopeZ(x + 8, y + 8) == z) {
 			break;
 		}
@@ -283,8 +284,8 @@
 	TileIndex tile_org = tile;
 
 	if (IsTileType(tile, MP_TUNNELBRIDGE) && GB(_m[tile].m5, 4, 4) == 0) {
-		if (GB(_m[tile].m5, 0, 2) != direction ||
-				GB(_m[tile].m5, 2, 2) != tpf->tracktype) {
+		if (GetTunnelDirection(tile) != direction ||
+				GetTunnelTransportType(tile) != tpf->tracktype) {
 			return;
 		}
 		tile = SkipToEndOfTunnel(tpf, tile, direction);
@@ -717,13 +718,14 @@
 		//   need to find the exit of the tunnel.
 		if (IsTileType(tile, MP_TUNNELBRIDGE)) {
 			if (GB(_m[tile].m5, 4, 4) == 0 &&
-					GB(_m[tile].m5, 0, 2) != (direction ^ 2)) {
+					GetTunnelDirection(tile) != ReverseDiagDir(direction)) {
 				/* This is a tunnel tile */
 				/* We are not just driving out of the tunnel */
-				if (GB(_m[tile].m5, 0, 2) != direction || GB(_m[tile].m5, 2, 2) != tpf->tracktype)
-					/* We are not driving into the tunnel, or it
-					 * is an invalid tunnel */
+				if (GetTunnelDirection(tile) != direction ||
+						GetTunnelTransportType(tile) != tpf->tracktype) {
+					// We are not driving into the tunnel, or it is an invalid tunnel
 					continue;
+				}
 				flotr = FindLengthOfTunnel(tile, direction);
 				si.cur_length += flotr.length * DIAG_FACTOR;
 				tile = flotr.tile;
--- a/rail_cmd.c	Mon Mar 06 20:28:28 2006 +0000
+++ b/rail_cmd.c	Mon Mar 06 20:55:24 2006 +0000
@@ -10,6 +10,7 @@
 #include "table/strings.h"
 #include "map.h"
 #include "tile.h"
+#include "tunnel_map.h"
 #include "vehicle.h"
 #include "viewport.h"
 #include "command.h"
@@ -1627,21 +1628,21 @@
 	if (IsTileType(tile, MP_TUNNELBRIDGE) && GB(_m[tile].m5, 4, 4) == 0) {
 		// It is a tunnel we're checking, we need to do some special stuff
 		// because VehicleFromPos will not find the vihicle otherwise
-		byte direction = GB(_m[tile].m5, 0, 2);
-		FindLengthOfTunnelResult flotr;
-		flotr = FindLengthOfTunnel(tile, direction);
+		TileIndex end = GetOtherTunnelEnd(tile);
+		DiagDirection direction = GetTunnelDirection(tile);
+
 		dest.track = 1 << (direction & 1); // get the trackbit the vehicle would have if it has not entered the tunnel yet (ie is still visible)
 
 		// check for a vehicle with that trackdir on the start tile of the tunnel
 		if (VehicleFromPos(tile, &dest, SignalVehicleCheckProc) != NULL) return true;
 
 		// check for a vehicle with that trackdir on the end tile of the tunnel
-		if (VehicleFromPos(flotr.tile, &dest, SignalVehicleCheckProc) != NULL) return true;
+		if (VehicleFromPos(end, &dest, SignalVehicleCheckProc) != NULL) return true;
 
 		// now check all tiles from start to end for a "hidden" vehicle
 		// NOTE: the hashes for tiles may overlap, so this could maybe be optimised a bit by not checking every tile?
 		dest.track = 0x40; // trackbit for vehicles "hidden" inside a tunnel
-		for (; tile != flotr.tile; tile += TileOffsByDir(direction)) {
+		for (; tile != end; tile += TileOffsByDir(direction)) {
 			if (VehicleFromPos(tile, &dest, SignalVehicleCheckProc) != NULL)
 				return true;
 		}
--- a/road_map.c	Mon Mar 06 20:28:28 2006 +0000
+++ b/road_map.c	Mon Mar 06 20:55:24 2006 +0000
@@ -5,6 +5,7 @@
 #include "functions.h"
 #include "road_map.h"
 #include "station.h"
+#include "tunnel_map.h"
 
 
 RoadBits GetAnyRoadBits(TileIndex tile)
@@ -36,8 +37,8 @@
 				}
 			} else {
 				// tunnel
-				if (GB(_m[tile].m5, 2, 2) != TRANSPORT_ROAD) return 0; // not a road tunnel
-				return DiagDirToRoadBits(ReverseDiagDir(GB(_m[tile].m5, 0, 2)));
+				if (GetTunnelTransportType(tile) != TRANSPORT_ROAD) return 0;
+				return DiagDirToRoadBits(ReverseDiagDir(GetTunnelDirection(tile)));
 			}
 
 		default: return 0;
--- a/town_cmd.c	Mon Mar 06 20:28:28 2006 +0000
+++ b/town_cmd.c	Mon Mar 06 20:55:24 2006 +0000
@@ -9,10 +9,10 @@
 #include "table/sprites.h"
 #include "map.h"
 #include "tile.h"
+#include "tunnel_map.h"
 #include "viewport.h"
 #include "town.h"
 #include "command.h"
-#include "pathfind.h"
 #include "gfx.h"
 #include "industry.h"
 #include "station.h"
@@ -624,9 +624,10 @@
 		int i;
 
 		// Reached a tunnel? Then continue at the other side of it.
-		if (IsTileType(tile, MP_TUNNELBRIDGE) && (_m[tile].m5& ~3) == 4) {
-			FindLengthOfTunnelResult flotr = FindLengthOfTunnel(tile, GB(_m[tile].m5, 0, 2));
-			*tile_ptr = flotr.tile;
+		if (IsTileType(tile, MP_TUNNELBRIDGE) &&
+				GB(_m[tile].m5, 4, 4) == 0 &&
+				GetTunnelTransportType(tile) == TRANSPORT_ROAD) {
+			*tile_ptr = GetOtherTunnelEnd(tile);
 			return;
 		}
 
--- a/train_cmd.c	Mon Mar 06 20:28:28 2006 +0000
+++ b/train_cmd.c	Mon Mar 06 20:55:24 2006 +0000
@@ -8,6 +8,7 @@
 #include "table/strings.h"
 #include "map.h"
 #include "tile.h"
+#include "tunnel_map.h"
 #include "vehicle.h"
 #include "command.h"
 #include "pathfind.h"
@@ -3121,8 +3122,10 @@
 	tile = v->tile;
 
 	// tunnel entrance?
-	if (IsTunnelTile(tile) && DiagDirToDir(GB(_m[tile].m5, 0, 2)) == v->direction)
+	if (IsTunnelTile(tile) &&
+			DiagDirToDir(GetTunnelDirection(tile)) == v->direction) {
 		return true;
+	}
 
 	// depot?
 	/* XXX -- When enabled, this makes it possible to crash trains of others
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tunnel_map.c	Mon Mar 06 20:55:24 2006 +0000
@@ -0,0 +1,25 @@
+/* $Id$ */
+
+#include "stdafx.h"
+#include "openttd.h"
+#include "tile.h"
+#include "tunnel_map.h"
+
+TileIndex GetOtherTunnelEnd(TileIndex tile)
+{
+	DiagDirection dir = GetTunnelDirection(tile);
+	TileIndexDiff delta = TileOffsByDir(dir);
+	uint z = GetTileZ(tile);
+
+	dir = ReverseDiagDir(dir);
+	do {
+		tile += delta;
+	} while (
+		!IsTileType(tile, MP_TUNNELBRIDGE) ||
+		GB(_m[tile].m5, 4, 4) != 0 ||
+		GetTunnelDirection(tile) != dir ||
+		GetTileZ(tile) != z
+	);
+
+	return tile;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tunnel_map.h	Mon Mar 06 20:55:24 2006 +0000
@@ -0,0 +1,47 @@
+/* $Id$ */
+
+#ifndef TUNNEL_MAP_H
+#define TUNNEL_MAP_H
+
+#include "direction.h"
+#include "macros.h"
+#include "map.h"
+#include "rail.h"
+
+
+static inline DiagDirection GetTunnelDirection(TileIndex t)
+{
+	return (DiagDirection)GB(_m[t].m5, 0, 2);
+}
+
+
+static inline TransportType GetTunnelTransportType(TileIndex t)
+{
+	return (TransportType)GB(_m[t].m5, 2, 2);
+}
+
+
+TileIndex GetOtherTunnelEnd(TileIndex);
+
+
+static inline void MakeRoadTunnel(TileIndex t, Owner o, DiagDirection d)
+{
+	SetTileType(t, MP_TUNNELBRIDGE);
+	SetTileOwner(t, o);
+	_m[t].m2 = 0;
+	_m[t].m3 = 0;
+	_m[t].m4 = 0;
+	_m[t].m5 = TRANSPORT_ROAD << 2 | d;
+}
+
+static inline void MakeRailTunnel(TileIndex t, Owner o, DiagDirection d, RailType r)
+{
+	SetTileType(t, MP_TUNNELBRIDGE);
+	SetTileOwner(t, o);
+	_m[t].m2 = 0;
+	_m[t].m3 = r;
+	_m[t].m4 = 0;
+	_m[t].m5 = TRANSPORT_RAIL << 2 | d;
+}
+
+#endif
--- a/tunnelbridge_cmd.c	Mon Mar 06 20:28:28 2006 +0000
+++ b/tunnelbridge_cmd.c	Mon Mar 06 20:55:24 2006 +0000
@@ -13,6 +13,7 @@
 #include "functions.h"
 #include "map.h"
 #include "tile.h"
+#include "tunnel_map.h"
 #include "vehicle.h"
 #include "viewport.h"
 #include "command.h"
@@ -440,7 +441,7 @@
 	if (z == height &&
 			IsTileType(tile, MP_TUNNELBRIDGE) &&
 			GB(_m[tile].m5, 4, 4) == 0 &&
-			GB(_m[tile].m5, 0, 2) == dir) {
+			GetTunnelDirection(tile) == dir) {
 		_error_message = STR_5003_ANOTHER_TUNNEL_IN_THE_WAY;
 		return false;
 	}
@@ -526,15 +527,13 @@
 	cost += _price.build_tunnel + ret;
 
 	if (flags & DC_EXEC) {
-		SetTileType(start_tile, MP_TUNNELBRIDGE);
-		SetTileOwner(start_tile, _current_player);
-		_m[start_tile].m3 = GB(p1, 0, 4); // rail type (if any)
-		_m[start_tile].m5 = (GB(p1, 9, 1) << 2) | direction; // transport type and entrance direction
-
-		SetTileType(end_tile, MP_TUNNELBRIDGE);
-		SetTileOwner(end_tile, _current_player);
-		_m[end_tile].m3 = GB(p1, 0, 4); // rail type (if any)
-		_m[end_tile].m5 = (GB(p1, 9, 1) << 2) | (direction ^ 2); // transport type and entrance direction
+		if (GB(p1, 9, 1) == TRANSPORT_RAIL) {
+			MakeRailTunnel(start_tile, _current_player, direction,                 GB(p1, 0, 4));
+			MakeRailTunnel(end_tile,   _current_player, ReverseDiagDir(direction), GB(p1, 0, 4));
+		} else {
+			MakeRoadTunnel(start_tile, _current_player, direction);
+			MakeRoadTunnel(end_tile,   _current_player, ReverseDiagDir(direction));
+		}
 
 		if (GB(p1, 9, 1) == 0) UpdateSignalsOnSegment(start_tile, DiagDirToDir(direction));
 	}
@@ -545,8 +544,8 @@
 TileIndex CheckTunnelBusy(TileIndex tile, uint *length)
 {
 	uint z = GetTileZ(tile);
-	byte m5 = _m[tile].m5;
-	TileIndexDiff delta = TileOffsByDir(m5 & 3);
+	DiagDirection dir = GetTunnelDirection(tile);
+	TileIndexDiff delta = TileOffsByDir(dir);
 	uint len = 0;
 	TileIndex starttile = tile;
 	Vehicle *v;
@@ -557,7 +556,7 @@
 	} while (
 		!IsTileType(tile, MP_TUNNELBRIDGE) ||
 		GB(_m[tile].m5, 4, 4) != 0 ||
-		(_m[tile].m5 ^ 2) != m5 ||
+		ReverseDiagDir(GetTunnelDirection(tile)) != dir ||
 		GetTileZ(tile) != z
 	);
 
@@ -605,8 +604,8 @@
 	if (flags & DC_EXEC) {
 		// We first need to request the direction before calling DoClearSquare
 		//  else the direction is always 0.. dah!! ;)
-		byte tile_dir = GB(_m[tile].m5, 0, 2);
-		byte endtile_dir = GB(_m[endtile].m5, 0, 2);
+		DiagDirection tile_dir    = GetTunnelDirection(tile);
+		DiagDirection endtile_dir = GetTunnelDirection(endtile);
 
 		// Adjust the town's player rating. Do this before removing the tile owner info.
 		if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR)
@@ -996,7 +995,7 @@
 
 	// draw tunnel?
 	if ((ti->map5 & 0xF0) == 0) {
-		if (GB(ti->map5, 2, 2) == 0) { /* Rail tunnel? */
+		if (GetTunnelTransportType(ti->tile) == TRANSPORT_RAIL) {
 			image = GetRailTypeInfo(GB(_m[ti->tile].m3, 0, 4))->base_sprites.tunnel;
 		} else {
 			image = SPR_TUNNEL_ENTRY_REAR_ROAD;
@@ -1004,7 +1003,7 @@
 
 		if (ice) image += 32;
 
-		image += GB(ti->map5, 0, 2) * 2;
+		image += GetTunnelDirection(ti->tile) * 2;
 		DrawGroundSprite(image);
 
 		AddSortableSpriteToDraw(image+1, ti->x + 15, ti->y + 15, 1, 1, 8, (byte)ti->z);
@@ -1266,8 +1265,8 @@
 static void GetTileDesc_TunnelBridge(TileIndex tile, TileDesc *td)
 {
 	if ((_m[tile].m5 & 0x80) == 0) {
-		td->str =
-			(GB(_m[tile].m5, 2, 2) == 0) ? STR_5017_RAILROAD_TUNNEL : STR_5018_ROAD_TUNNEL;
+		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 | GB(_m[tile].m2, 4, 4)];
 
@@ -1329,9 +1328,8 @@
 
 	if ((m5 & 0xF0) == 0) {
 		/* This is a tunnel */
-		if (GB(m5, 2, 2) == mode) {
-			/* Tranport in the tunnel is compatible */
-			return m5&1 ? 0x202 : 0x101;
+		if (GetTunnelTransportType(tile) == mode) {
+			return DiagDirToAxis(GetTunnelDirection(tile)) == AXIS_X ? 0x101 : 0x202;
 		}
 	} else if (m5 & 0x80) {
 		/* This is a bridge */
@@ -1419,7 +1417,7 @@
 		if (v->type == VEH_Train) {
 			fc = (x & 0xF) + (y << 4);
 
-			dir = GB(_m[tile].m5, 0, 2);
+			dir = GetTunnelDirection(tile);
 			vdir = DirToDiagDir(v->direction);
 
 			if (v->u.rail.track != 0x40 && dir == vdir) {
@@ -1446,7 +1444,7 @@
 			}
 		} else if (v->type == VEH_Road) {
 			fc = (x & 0xF) + (y << 4);
-			dir = GB(_m[tile].m5, 0, 2);
+			dir = GetTunnelDirection(tile);
 			vdir = DirToDiagDir(v->direction);
 
 			// Enter tunnel?