src/pathfind.cpp
branchnoai
changeset 9869 6404afe43575
parent 9826 9707ad4c9b60
child 10181 54df587fef5d
--- a/src/pathfind.cpp	Sun Apr 06 14:12:19 2008 +0000
+++ b/src/pathfind.cpp	Sun Apr 06 23:07:42 2008 +0000
@@ -17,6 +17,7 @@
 #include "depot.h"
 #include "tunnelbridge_map.h"
 #include "core/random_func.hpp"
+#include "core/alloc_func.hpp"
 #include "tunnelbridge.h"
 
 /* remember which tiles we have already visited so we don't visit them again. */
@@ -111,34 +112,7 @@
 	return true;
 }
 
-static const byte _bits_mask[4] = {
-	0x19,
-	0x16,
-	0x25,
-	0x2A,
-};
-
-static const DiagDirection _tpf_new_direction[14] = {
-	DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_SW, DIAGDIR_SE,
-	INVALID_DIAGDIR, INVALID_DIAGDIR,
-	DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NW, DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NE,
-};
-
-static const DiagDirection _tpf_prev_direction[14] = {
-	DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_SE, DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_SW,
-	INVALID_DIAGDIR, INVALID_DIAGDIR,
-	DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NE, DIAGDIR_NW,
-};
-
-
-static const byte _otherdir_mask[4] = {
-	0x10,
-	0,
-	0x5,
-	0x2A,
-};
-
-static void TPFMode2(TrackPathFinder* tpf, TileIndex tile, DiagDirection direction)
+static void TPFModeShip(TrackPathFinder* tpf, TileIndex tile, DiagDirection direction)
 {
 	RememberData rd;
 
@@ -152,8 +126,7 @@
 	if (++tpf->rd.cur_length > 50)
 		return;
 
-	TrackStatus ts = GetTileTrackStatus(tile, tpf->tracktype, tpf->sub_type);
-	TrackBits bits = (TrackBits)(TrackStatusToTrackBits(ts) & _bits_mask[direction]);
+	TrackBits bits = TrackStatusToTrackBits(GetTileTrackStatus(tile, tpf->tracktype, tpf->sub_type)) & DiagdirReachesTracks(direction);
 	if (bits == TRACK_BIT_NONE) return;
 
 	assert(TileX(tile) != MapMaxX() && TileY(tile) != MapMaxY());
@@ -173,10 +146,10 @@
 			tpf->rd.last_choosen_track = track;
 		}
 
-		tpf->the_dir = (Trackdir)(track + (HasBit(_otherdir_mask[direction], track) ? 8 : 0));
+		tpf->the_dir = TrackEnterdirToTrackdir(track, direction);
 
 		if (!tpf->enum_proc(tile, tpf->userdata, tpf->the_dir, tpf->rd.cur_length)) {
-			TPFMode2(tpf, tile, _tpf_new_direction[tpf->the_dir]);
+			TPFModeShip(tpf, tile, TrackdirToExitdir(tpf->the_dir));
 		}
 
 		tpf->rd = rd;
@@ -208,9 +181,7 @@
 	return true;
 }
 
-static const uint16 _tpfmode1_and[4] = { 0x1009, 0x16, 0x520, 0x2A00 };
-
-static void TPFMode1(TrackPathFinder* tpf, TileIndex tile, DiagDirection direction)
+static void TPFModeNormal(TrackPathFinder* tpf, TileIndex tile, DiagDirection direction)
 {
 	const TileIndex tile_org = tile;
 
@@ -252,78 +223,70 @@
 		}
 	}
 
-	uint32 bits = TrackStatusToTrackdirBits(GetTileTrackStatus(tile, tpf->tracktype, tpf->sub_type));
+	TrackdirBits trackdirbits = TrackStatusToTrackdirBits(GetTileTrackStatus(tile, tpf->tracktype, tpf->sub_type));
 
 	/* Check in case of rail if the owner is the same */
 	if (tpf->tracktype == TRANSPORT_RAIL) {
-		if (bits != 0 && TrackStatusToTrackdirBits(GetTileTrackStatus(tile_org, TRANSPORT_RAIL, 0)) != TRACKDIR_BIT_NONE) {
+		if (trackdirbits != TRACKDIR_BIT_NONE && TrackStatusToTrackdirBits(GetTileTrackStatus(tile_org, TRANSPORT_RAIL, 0)) != TRACKDIR_BIT_NONE) {
 			if (GetTileOwner(tile_org) != GetTileOwner(tile)) return;
 		}
 	}
 
 	tpf->rd.cur_length++;
 
-	if ((byte)bits != tpf->var2) {
-		bits &= _tpfmode1_and[direction];
-		bits |= bits >> 8;
-	}
-	bits &= 0xBF;
+	trackdirbits &= DiagdirReachesTrackdirs(direction);
+	TrackBits bits = TrackdirBitsToTrackBits(trackdirbits);
 
-	if (bits != 0) {
+	if (bits != TRACK_BIT_NONE) {
 		if (!tpf->disable_tile_hash || (tpf->rd.cur_length <= 64 && (KillFirstBit(bits) == 0 || ++tpf->rd.depth <= 7))) {
 			do {
-				int i = FIND_FIRST_BIT(bits);
-				bits = KillFirstBit(bits);
+				Track track = RemoveFirstTrack(&bits);
 
-				tpf->the_dir = (Trackdir)((_otherdir_mask[direction] & (byte)(1 << i)) ? (i + 8) : i);
+				tpf->the_dir = TrackEnterdirToTrackdir(track, direction);
 				RememberData rd = tpf->rd;
 
 				/* make sure we are not leaving from invalid side */
 				if (TPFSetTileBit(tpf, tile, tpf->the_dir) && CanAccessTileInDir(tile, TrackdirToExitdir(tpf->the_dir), tpf->tracktype) &&
 						!tpf->enum_proc(tile, tpf->userdata, tpf->the_dir, tpf->rd.cur_length) ) {
-					TPFMode1(tpf, tile, _tpf_new_direction[tpf->the_dir]);
+					TPFModeNormal(tpf, tile, TrackdirToExitdir(tpf->the_dir));
 				}
 				tpf->rd = rd;
-			} while (bits != 0);
+			} while (bits != TRACK_BIT_NONE);
 		}
 	}
 }
 
-void FollowTrack(TileIndex tile, uint16 flags, uint sub_type, DiagDirection direction, TPFEnumProc *enum_proc, TPFAfterProc *after_proc, void *data)
+void FollowTrack(TileIndex tile, PathfindFlags flags, TransportType tt, uint sub_type, DiagDirection direction, TPFEnumProc *enum_proc, TPFAfterProc *after_proc, void *data)
 {
-	TrackPathFinder tpf;
+	assert(IsValidDiagDirection(direction));
 
-	assert(direction < 4);
+	SmallStackSafeStackAlloc<TrackPathFinder, 1> tpf;
 
 	/* initialize path finder variables */
-	tpf.userdata = data;
-	tpf.enum_proc = enum_proc;
-	tpf.new_link = tpf.links;
-	tpf.num_links_left = lengthof(tpf.links);
-
-	tpf.rd.cur_length = 0;
-	tpf.rd.depth = 0;
-	tpf.rd.last_choosen_track = INVALID_TRACK;
+	tpf->userdata = data;
+	tpf->enum_proc = enum_proc;
+	tpf->new_link = tpf->links;
+	tpf->num_links_left = lengthof(tpf->links);
 
-	tpf.var2 = HasBit(flags, 15) ? 0x43 : 0xFF; // 0x8000
-
-	tpf.disable_tile_hash = HasBit(flags, 12);  // 0x1000
-
+	tpf->rd.cur_length = 0;
+	tpf->rd.depth = 0;
+	tpf->rd.last_choosen_track = INVALID_TRACK;
 
-	tpf.tracktype = (TransportType)(flags & 0xFF);
-	tpf.sub_type = sub_type;
+	tpf->disable_tile_hash = (flags & PATHFIND_FLAGS_DISABLE_TILE_HASH) != 0;
 
-	if (HasBit(flags, 11)) {
-		tpf.enum_proc(tile, data, INVALID_TRACKDIR, 0);
-		TPFMode2(&tpf, tile, direction);
+	tpf->tracktype = tt;
+	tpf->sub_type = sub_type;
+
+	if ((flags & PATHFIND_FLAGS_SHIP_MODE) != 0) {
+		tpf->enum_proc(tile, data, INVALID_TRACKDIR, 0);
+		TPFModeShip(tpf, tile, direction);
 	} else {
 		/* clear the hash_heads */
-		memset(tpf.hash_head, 0, sizeof(tpf.hash_head));
-		TPFMode1(&tpf, tile, direction);
+		memset(tpf->hash_head, 0, sizeof(tpf->hash_head));
+		TPFModeNormal(tpf, tile, direction);
 	}
 
-	if (after_proc != NULL)
-		after_proc(&tpf);
+	if (after_proc != NULL) after_proc(tpf);
 }
 
 struct StackedItem {
@@ -336,15 +299,6 @@
 	byte first_track;
 };
 
-static const Trackdir _new_trackdir[6][4] = {
-{TRACKDIR_X_NE,    INVALID_TRACKDIR, TRACKDIR_X_SW,    INVALID_TRACKDIR,},
-{INVALID_TRACKDIR, TRACKDIR_Y_SE,    INVALID_TRACKDIR, TRACKDIR_Y_NW,},
-{INVALID_TRACKDIR, TRACKDIR_UPPER_E, TRACKDIR_UPPER_W, INVALID_TRACKDIR,},
-{TRACKDIR_LOWER_E, INVALID_TRACKDIR, INVALID_TRACKDIR, TRACKDIR_LOWER_W,},
-{TRACKDIR_LEFT_N,  TRACKDIR_LEFT_S,  INVALID_TRACKDIR, INVALID_TRACKDIR,},
-{INVALID_TRACKDIR, INVALID_TRACKDIR, TRACKDIR_RIGHT_S, TRACKDIR_RIGHT_N,},
-};
-
 struct HashLink {
 	TileIndex tile;
 	uint16 typelength;
@@ -595,7 +549,7 @@
 
 			HeapifyDown(tpf);
 			/* Make sure we havn't already visited this tile. */
-		} while (!NtpCheck(tpf, tile, _tpf_prev_direction[si.track], si.cur_length));
+		} while (!NtpCheck(tpf, tile, ReverseDiagDir(TrackdirToExitdir(ReverseTrackdir(si.track))), si.cur_length));
 
 		/* Add the length of this track. */
 		si.cur_length += _length_of_track[si.track];
@@ -605,7 +559,7 @@
 			return;
 
 		assert(si.track <= 13);
-		direction = _tpf_new_direction[si.track];
+		direction = TrackdirToExitdir(si.track);
 
 start_at:
 		/* If the tile is the entry tile of a tunnel, and we're not going out of the tunnel,
@@ -649,8 +603,7 @@
 			if (!IsTileType(tile, MP_RAILWAY) || !IsPlainRailTile(tile)) {
 				/* We found a tile which is not a normal railway tile.
 				 * Determine which tracks that exist on this tile. */
-				TrackStatus ts = GetTileTrackStatus(tile, TRANSPORT_RAIL, 0) & _tpfmode1_and[direction];
-				bits = TrackStatusToTrackBits(ts);
+				bits = TrackdirBitsToTrackBits(TrackStatusToTrackdirBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, 0)) & DiagdirReachesTrackdirs(direction));
 
 				/* Check that the tile contains exactly one track */
 				if (bits == 0 || KillFirstBit(bits) != 0) break;
@@ -666,7 +619,7 @@
 				 *   bits - bitmask of which track that exist on the tile (exactly one bit is set)
 				 *   direction - which direction are we moving in?
 				 *******************/
-				si.track = _new_trackdir[FIND_FIRST_BIT(bits)][direction];
+				si.track = TrackEnterdirToTrackdir(FindFirstTrack(bits), direction);
 				si.cur_length += _length_of_track[si.track];
 				goto callback_and_continue;
 			}
@@ -689,7 +642,7 @@
 			/* If we reach here, the tile has exactly one track, and this
 			 track is reachable = > Rail segment continues */
 
-			track = _new_trackdir[FIND_FIRST_BIT(bits)][direction];
+			track = TrackEnterdirToTrackdir(FindFirstTrack(bits), direction);
 			assert(track != INVALID_TRACKDIR);
 
 			si.cur_length += _length_of_track[track];
@@ -738,7 +691,7 @@
 			}
 
 			/* continue with the next track */
-			direction = _tpf_new_direction[track];
+			direction = TrackdirToExitdir(track);
 
 			/* safety check if we're running around chasing our tail... (infinite loop) */
 			if (tile == tile_org) {
@@ -779,7 +732,7 @@
 		si.tile = tile;
 		while (bits != TRACK_BIT_NONE) {
 			Track track = RemoveFirstTrack(&bits);
-			si.track = _new_trackdir[track][direction];
+			si.track = TrackEnterdirToTrackdir(track, direction);
 			assert(si.track != 0xFF);
 			si.priority = si.cur_length + estimation;
 
@@ -820,18 +773,18 @@
 /** new pathfinder for trains. better and faster. */
 void NewTrainPathfind(TileIndex tile, TileIndex dest, RailTypes railtypes, DiagDirection direction, NTPEnumProc* enum_proc, void* data)
 {
-	NewTrackPathFinder tpf;
+	SmallStackSafeStackAlloc<NewTrackPathFinder, 1> tpf;
 
-	tpf.dest = dest;
-	tpf.userdata = data;
-	tpf.enum_proc = enum_proc;
-	tpf.tracktype = TRANSPORT_RAIL;
-	tpf.railtypes = railtypes;
-	tpf.maxlength = min(_patches.pf_maxlength * 3, 10000);
-	tpf.nstack = 0;
-	tpf.new_link = tpf.links;
-	tpf.num_links_left = lengthof(tpf.links);
-	memset(tpf.hash_head, 0, sizeof(tpf.hash_head));
+	tpf->dest = dest;
+	tpf->userdata = data;
+	tpf->enum_proc = enum_proc;
+	tpf->tracktype = TRANSPORT_RAIL;
+	tpf->railtypes = railtypes;
+	tpf->maxlength = min(_patches.pf_maxlength * 3, 10000);
+	tpf->nstack = 0;
+	tpf->new_link = tpf->links;
+	tpf->num_links_left = lengthof(tpf->links);
+	memset(tpf->hash_head, 0, sizeof(tpf->hash_head));
 
-	NTPEnum(&tpf, tile, direction);
+	NTPEnum(tpf, tile, direction);
 }