changeset 1950:b16cb8f34731 draft

(svn r2456) * Prettyfied npf.c using enums and wrappers from rail.h. * Moved GetTileRailType() from npf.c to rail.[ch].
author matthijs <matthijs@openttd.org>
date Fri, 17 Jun 2005 17:11:05 +0000
parents efde17e01253
children 037f56b7aefc
files npf.c rail.c rail.h
diffstat 3 files changed, 78 insertions(+), 62 deletions(-) [+]
line wrap: on
line diff
--- a/npf.c
+++ b/npf.c
@@ -15,7 +15,7 @@
  * the shorter piece is sqrt(2)/2*NPF_TILE_LENGTH =~ 0.7071
  */
 #define NPF_STRAIGHT_LENGTH (uint)(NPF_TILE_LENGTH * STRAIGHT_TRACK_LENGTH)
-static const uint _trackdir_length[14] = {
+static const uint _trackdir_length[TRACKDIR_END] = {
 	NPF_TILE_LENGTH, NPF_TILE_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH,
 	0, 0,
 	NPF_TILE_LENGTH, NPF_TILE_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH
@@ -27,13 +27,22 @@
 	return PATHFIND_HASH_TILE(key1);
 }
 
+/**
+ * Calculates a hash value for use in the NPF.
+ * @param key1	The TileIndex of the tile to hash
+ * @param key1	The Trackdir of the track on the tile.
+ *
+ * @todo	Think of a better hash.
+ */
 uint NPFHash(uint key1, uint key2)
 {
 	/* TODO: think of a better hash? */
 	uint part1 = TileX(key1) & NPF_HASH_HALFMASK;
 	uint part2 = TileY(key1) & NPF_HASH_HALFMASK;
-	/* The value of 14 below is based on the maximum value of key2 (13) */
-	return ((((part1 << NPF_HASH_HALFBITS) | part2)) + (NPF_HASH_SIZE * key2 / 14)) % NPF_HASH_SIZE;
+
+	assert(IsValidTrackdir(key2));
+	assert(IsValidTile(key1));
+	return ((((part1 << NPF_HASH_HALFBITS) | part2)) + (NPF_HASH_SIZE * key2 / TRACKDIR_END)) % NPF_HASH_SIZE;
 }
 
 int32 NPFCalcZero(AyStar* as, AyStarNode* current, OpenListNode* parent) {
@@ -111,7 +120,7 @@
 void NPFFillTrackdirChoice(AyStarNode* current, OpenListNode* parent)
 {
 	if (parent->path.parent == NULL) {
-		byte trackdir = current->direction;
+		Trackdir trackdir = (Trackdir)current->direction;
 		/* This is a first order decision, so we'd better save the
 		 * direction we chose */
 		current->user_data[NPF_TRACKDIR_CHOICE] = trackdir;
@@ -128,9 +137,9 @@
  * cost of that tile. If the tile is an exit, it will return the tunnel length
  * including the exit tile. Requires that this is a Tunnel tile */
 uint NPFTunnelCost(AyStarNode* current) {
-	byte exitdir = TrackdirToExitdir(current->direction);
+	DiagDirection exitdir = TrackdirToExitdir((Trackdir)current->direction);
 	TileIndex tile = current->tile;
-	if ( (uint)(_map5[tile] & 3) == ReverseDiagdir(exitdir)) {
+	if ( (DiagDirection)(_map5[tile] & 3) == ReverseDiagdir(exitdir)) {
 		/* We just popped out if this tunnel, since were
 		 * facing the tunnel exit */
 		FindLengthOfTunnelResult flotr;
@@ -199,14 +208,14 @@
 int32 NPFWaterPathCost(AyStar* as, AyStarNode* current, OpenListNode* parent) {
 	//TileIndex tile = current->tile;
 	int32 cost = 0;
-	byte trackdir = current->direction;
+	Trackdir trackdir = (Trackdir)current->direction;
 
 	cost = _trackdir_length[trackdir]; /* Should be different for diagonal tracks */
 
-	if (IsBuoyTile(current->tile) && IsDiagonalTrackdir(current->direction))
+	if (IsBuoyTile(current->tile) && IsDiagonalTrackdir(trackdir))
 		cost += _patches.npf_buoy_penalty; /* A small penalty for going over buoys */
 
-	if (current->direction != NextTrackdir(parent->path.node.direction))
+	if (current->direction != NextTrackdir((Trackdir)parent->path.node.direction))
 		cost += _patches.npf_water_curve_penalty;
 
 	/* TODO More penalties? */
@@ -254,7 +263,7 @@
 /* Determine the cost of this node, for railway tracks */
 int32 NPFRailPathCost(AyStar* as, AyStarNode* current, OpenListNode* parent) {
 	TileIndex tile = current->tile;
-	byte trackdir = current->direction;
+	Trackdir trackdir = (Trackdir)current->direction;
 	int32 cost = 0;
 	/* HACK: We create a OpenListNode manualy, so we can call EndNodeCheck */
 	OpenListNode new_node;
@@ -318,15 +327,17 @@
 
 	/* Penalise the tile if it is a target tile and the last signal was
 	 * red */
+	/* HACK: We create a new_node here so we can call EndNodeCheck. Ugly as hell
+	 * of course... */
 	new_node.path.node = *current;
-	if (as->EndNodeCheck(as, &new_node)==AYSTAR_FOUND_END_NODE && NPFGetFlag(current, NPF_FLAG_LAST_SIGNAL_RED))
+	if (as->EndNodeCheck(as, &new_node) == AYSTAR_FOUND_END_NODE && NPFGetFlag(current, NPF_FLAG_LAST_SIGNAL_RED))
 		cost += _patches.npf_rail_lastred_penalty;
 
 	/* Check for slope */
 	cost += NPFSlopeCost(current);
 
 	/* Check for turns */
-	if (current->direction != NextTrackdir(parent->path.node.direction))
+	if (current->direction != NextTrackdir((Trackdir)parent->path.node.direction))
 		cost += _patches.npf_rail_curve_penalty;
 	//TODO, with realistic acceleration, also the amount of straight track between
 	//      curves should be taken into account, as this affects the speed limit.
@@ -382,54 +393,12 @@
  */
 void NPFSaveTargetData(AyStar* as, OpenListNode* current) {
 	NPFFoundTargetData* ftd = (NPFFoundTargetData*)as->user_path;
-	ftd->best_trackdir = current->path.node.user_data[NPF_TRACKDIR_CHOICE];
+	ftd->best_trackdir = (Trackdir)current->path.node.user_data[NPF_TRACKDIR_CHOICE];
 	ftd->best_path_dist = current->g;
 	ftd->best_bird_dist = 0;
 	ftd->node = current->path.node;
 }
 
-/**
- * Return the rail type of tile, or INVALID_RAILTYPE if this is no rail tile.
- * Note that there is no check if the given trackdir is actually present on
- * the tile!
- * The given trackdir is used when there are (could be) multiple rail types on
- * one tile.
- */
-static inline RailType GetTileRailType(TileIndex tile, byte trackdir)
-{
-	byte type = INVALID_RAILTYPE;
-	switch (GetTileType(tile)) {
-		case MP_RAILWAY:
-			/* railway track */
-			type = _map3_lo[tile] & RAILTYPE_MASK;
-			break;
-		case MP_STREET:
-			/* rail/road crossing */
-			if (IsLevelCrossing(tile))
-				type = _map3_hi[tile] & RAILTYPE_MASK;
-			break;
-		case MP_STATION:
-			if (IsTrainStationTile(tile))
-				type = _map3_lo[tile] & RAILTYPE_MASK;
-			break;
-		case MP_TUNNELBRIDGE:
-			/* railway tunnel */
-			if ((_map5[tile] & 0xFC) == 0) type = _map3_lo[tile] & RAILTYPE_MASK;
-			/* railway bridge ending */
-			if ((_map5[tile] & 0xC6) == 0x80) type = _map3_lo[tile] & RAILTYPE_MASK;
-			/* on railway bridge */
-			if ((_map5[tile] & 0xC6) == 0xC0 && ((unsigned)(_map5[tile] & 0x1)) == (TrackdirToExitdir(trackdir) & 0x1))
-				type = (_map3_lo[tile] >> 4) & RAILTYPE_MASK;
-			/* under bridge (any type) */
-			if ((_map5[tile] & 0xC0) == 0xC0 && (_map5[tile] & 0x1) != (trackdir & 0x1))
-				type = _map3_lo[tile] & RAILTYPE_MASK;
-			break;
-		default:
-			break;
-	}
-	return type;
-}
-
 /* 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
@@ -437,12 +406,12 @@
  * AyStarNode.user_data[NPF_TRACKDIR_CHOICE] with an appropriate value, and
  * copy AyStarNode.user_data[NPF_NODE_FLAGS] from the parent */
 void NPFFollowTrack(AyStar* aystar, OpenListNode* current) {
-	Trackdir src_trackdir = current->path.node.direction;
+	Trackdir src_trackdir = (Trackdir)current->path.node.direction;
 	TileIndex src_tile = current->path.node.tile;
 	DiagDirection src_exitdir = TrackdirToExitdir(src_trackdir);
 	FindLengthOfTunnelResult flotr;
 	TileIndex dst_tile;
-	int i = 0;
+	int i;
 	TrackdirBits trackdirbits, ts;
 	TransportType type = aystar->user_data[NPF_TYPE];
 	/* Initialize to 0, so we can jump out (return) somewhere an have no neighbours */
@@ -462,7 +431,7 @@
 			 * those from one side only. Trackdirs don't support that (yet), so we'll
 			 * do this here. */
 
-			byte exitdir;
+			DiagDirection exitdir;
 			/* Find out the exit direction first */
 			if (IsRoadStationTile(src_tile))
 				exitdir = GetRoadStationDir(src_tile);
@@ -497,8 +466,8 @@
 	 * problem, but it might be nicer to compare with the first tile, or even
 	 * the type of the vehicle... Maybe an NPF_RAILTYPE userdata sometime? */
 	if (type == TRANSPORT_RAIL) {
-		byte src_type = GetTileRailType(src_tile, src_trackdir);
-		byte dst_type = GetTileRailType(dst_tile, TrackdirToExitdir(src_trackdir));
+		RailType src_type = GetTileRailType(src_tile, src_trackdir);
+		RailType dst_type = GetTileRailType(dst_tile, TrackdirToExitdir(src_trackdir));
 		if (src_type != dst_type) {
 			return;
 		}
@@ -519,7 +488,7 @@
 	/* Determine available tracks */
 	if (type != TRANSPORT_WATER && (IsRoadStationTile(dst_tile) || IsTileDepotType(dst_tile, type))){
 		/* Road stations and road and train depots return 0 on GTTS, so we have to do this by hand... */
-		byte exitdir;
+		DiagDirection exitdir;
 		if (IsRoadStationTile(dst_tile))
 			exitdir = GetRoadStationDir(dst_tile);
 		else /* Road or train depot */
@@ -541,9 +510,10 @@
 		trackdirbits &= ~TrackdirCrossesTrackdirs(src_trackdir);
 	DEBUG(npf,6)("After filtering: (%d, %d), possible trackdirs: %#x", TileX(dst_tile), TileY(dst_tile), trackdirbits);
 
+	i = 0;
 	/* Enumerate possible track */
 	while (trackdirbits != 0) {
-		byte dst_trackdir;
+		Trackdir dst_trackdir;
 		dst_trackdir =  FindFirstBit2x64(trackdirbits);
 		trackdirbits = KillFirstBit2x64(trackdirbits);
 		DEBUG(npf, 5)("Expanded into trackdir: %d, remaining trackdirs: %#x", dst_trackdir, trackdirbits);
--- a/rail.c
+++ b/rail.c
@@ -1,6 +1,7 @@
 #include "stdafx.h"
 #include "openttd.h"
 #include "rail.h"
+#include "station.h"
 
 /* XXX: Below 3 tables store duplicate data. Maybe remove some? */
 /* Maps a trackdir to the bit that stores its status in the map arrays, in the
@@ -95,3 +96,39 @@
 	TRACKDIR_DIAG1_SW, TRACKDIR_DIAG2_NW, TRACKDIR_UPPER_W, TRACKDIR_LOWER_W, TRACKDIR_LEFT_N, TRACKDIR_RIGHT_N, INVALID_TRACKDIR, INVALID_TRACKDIR,
 	TRACKDIR_DIAG1_NE, TRACKDIR_DIAG2_SE, TRACKDIR_UPPER_E, TRACKDIR_LOWER_E, TRACKDIR_LEFT_S, TRACKDIR_RIGHT_S
 };
+
+RailType GetTileRailType(TileIndex tile, byte trackdir)
+{
+	RailType type = INVALID_RAILTYPE;
+	switch (GetTileType(tile)) {
+		case MP_RAILWAY:
+			/* railway track */
+			type = _map3_lo[tile] & RAILTYPE_MASK;
+			break;
+		case MP_STREET:
+			/* rail/road crossing */
+			if (IsLevelCrossing(tile))
+				type = _map3_hi[tile] & RAILTYPE_MASK;
+			break;
+		case MP_STATION:
+			if (IsTrainStationTile(tile))
+				type = _map3_lo[tile] & RAILTYPE_MASK;
+			break;
+		case MP_TUNNELBRIDGE:
+			/* railway tunnel */
+			if ((_map5[tile] & 0xFC) == 0) type = _map3_lo[tile] & RAILTYPE_MASK;
+			/* railway bridge ending */
+			if ((_map5[tile] & 0xC6) == 0x80) type = _map3_lo[tile] & RAILTYPE_MASK;
+			/* on railway bridge */
+			if ((_map5[tile] & 0xC6) == 0xC0 && ((DiagDirection)(_map5[tile] & 0x1)) == (TrackdirToExitdir(trackdir) & 0x1))
+				type = (_map3_lo[tile] >> 4) & RAILTYPE_MASK;
+			/* under bridge (any type) */
+			if ((_map5[tile] & 0xC0) == 0xC0 && (_map5[tile] & 0x1) != (trackdir & 0x1))
+				type = _map3_lo[tile] & RAILTYPE_MASK;
+			break;
+		default:
+			break;
+	}
+	return type;
+}
+
--- a/rail.h
+++ b/rail.h
@@ -434,4 +434,13 @@
 	return (_map3_hi[tile] & SIG_SEMAPHORE_MASK);
 }
 
+/**
+ * Return the rail type of tile, or INVALID_RAILTYPE if this is no rail tile.
+ * Note that there is no check if the given trackdir is actually present on
+ * the tile!
+ * The given trackdir is used when there are (could be) multiple rail types on
+ * one tile.
+ */
+RailType GetTileRailType(TileIndex tile, byte trackdir);
+
 #endif // RAIL_H