Changeset - r1942:ea8e39498c72
[Not reviewed]
master
0 13 2
matthijs - 19 years ago 2005-06-16 18:04:02
matthijs@openttd.org
(svn r2448) General cleanup of rail related code, more to follow.
* Add: rail.[ch] for rail-related enums and wrapper functions.
* Codechange: Removed dozens of magic numbers with below enums.
* Codechange: Rewrote CheckTrackCombination().
* Add: TILE_SIZE, TILE_PIXELS and TILE_HEIGHT constants.
* Add: enums RailTileType, RailTileSubtype, SignalType to mask against the map arrays.
* Add: enums Track, TrackBits, Trackdir, TrackdirBits for railway track data. (Note that the old RAIL_BIT constants are replaced by TRACK_BIT ones).
* Add: enums Direction and DiagDirection
* Codechange: Moved a bunch of track(dir) related lookup arrays from npf.[ch] to rail.[ch].
* Codechange: move RailType enum from tile.h to rail.h.
* Add: Wrapper functions for masking signal status in the map arrays: SignalAlongTrackdir, SignalAgainstTrackdir and SignalOnTrack.
* Add: Wrapper functions to access rail tiles, using above enums
* Add: Wrapper functions to modify tracks, trackdirs, directions, etc.
* Add: Wrapper functions for all lookup arrays in rail.[ch] (Arrays are still used in parts of the code)
* Codechange: Renamed some variables and arguments to better represent what they contain (railbit -> track, bits -> trackdirbits, etc.).
* Codechange: Don't use FindLandscapeHeight() in CmdRemoveSingleRail(), since it returns way too much info. Use GetTileSlope() instead.
* Codechange: [NPF] Removed some unused globals and code from npf.c.
15 files changed with 916 insertions and 640 deletions:
0 comments (0 inline, 0 general)
Makefile
Show inline comments
 
@@ -648,6 +648,7 @@ C_SOURCES += player_gui.c
 
C_SOURCES += players.c
 
C_SOURCES += pool.c
 
C_SOURCES += queue.c
 
C_SOURCES += rail.c
 
C_SOURCES += rail_cmd.c
 
C_SOURCES += rail_gui.c
 
C_SOURCES += rev.c
depot.h
Show inline comments
 
@@ -89,7 +89,7 @@ static inline bool IsTileDepotType(TileI
 
/**
 
 * Returns the direction the exit of the depot on the given tile is facing.
 
 */
 
static inline uint GetDepotDirection(TileIndex tile, TransportType type)
 
static inline DiagDirection GetDepotDirection(TileIndex tile, TransportType type)
 
{
 
	assert(IsTileDepotType(tile, type));
 

	
 
@@ -102,13 +102,13 @@ static inline uint GetDepotDirection(Til
 
		case TRANSPORT_WATER:
 
			/* Water is stubborn, it stores the directions in a different order. */
 
			switch (_map5[tile] & 3) {
 
				case 0: return 0;
 
				case 1: return 2;
 
				case 2: return 3;
 
				case 3: return 1;
 
				case 0: return DIAGDIR_NE;
 
				case 1: return DIAGDIR_SW;
 
				case 2: return DIAGDIR_NW;
 
				case 3: return DIAGDIR_SE;
 
			}
 
		default:
 
			return 0; /* Not reached */
 
			return INVALID_DIAGDIR; /* Not reached */
 
	}
 
}
 

	
map.h
Show inline comments
 
@@ -48,6 +48,13 @@ enum {
 
	INVALID_TILE = (uint32) -1
 
};
 

	
 
enum {
 
	TILE_SIZE   = 16,   /* Tiles are 16x16 "units" in size */
 
	TILE_PIXELS = 32,   /* a tile is 32x32 pixels */
 
	TILE_HEIGHT = 8,    /* The standard height-difference between tiles on two levels is 8 (z-diff 8) */
 
};
 

	
 

	
 
static inline uint TileX(TileIndex tile)
 
{
 
	return tile & MapMaxX();
npf.c
Show inline comments
 
@@ -9,92 +9,8 @@
 
#include "tile.h"
 
#include "depot.h"
 

	
 
AyStar _train_find_station;
 
AyStar _train_find_depot;
 
AyStar _road_find_station;
 
AyStar _road_find_depot;
 
AyStar _npf_aystar;
 

	
 
/* Maps a trackdir to the bit that stores its status in the map arrays, in the
 
 * direction along with the trackdir */
 
const byte _signal_along_trackdir[14] = {
 
	0x80, 0x80, 0x80, 0x20, 0x40, 0x10, 0, 0,
 
	0x40, 0x40, 0x40, 0x10, 0x80, 0x20
 
};
 

	
 
/* Maps a trackdir to the bit that stores its status in the map arrays, in the
 
 * direction against the trackdir */
 
const byte _signal_against_trackdir[14] = {
 
	0x40, 0x40, 0x40, 0x10, 0x80, 0x20, 0, 0,
 
	0x80, 0x80, 0x80, 0x20, 0x40, 0x10
 
};
 

	
 
/* Maps a trackdir to the trackdirs that can be reached from it (ie, when
 
 * entering the next tile */
 
const uint16 _trackdir_reaches_trackdirs[14] = {
 
	0x1009, 0x0016, 0x1009, 0x0016, 0x0520, 0x0016, 0, 0,
 
	0x0520, 0x2A00, 0x2A00, 0x0520, 0x2A00, 0x1009
 
};
 

	
 
const uint16 _next_trackdir[14] = {
 
	0,  1,  3,  2,  5,  4, 0, 0,
 
	8,  9,  11, 10, 13, 12
 
};
 

	
 
/* Maps a trackdir to all trackdirs that make 90 deg turns with it. */
 
const uint16 _trackdir_crosses_trackdirs[14] = {
 
	0x0202, 0x0101, 0x3030, 0x3030, 0x0C0C, 0x0C0C, 0, 0,
 
	0x0202, 0x0101, 0x3030, 0x3030, 0x0C0C, 0x0C0C
 
};
 

	
 
/* Maps a track to all tracks that make 90 deg turns with it. */
 
const byte _track_crosses_tracks[6] = {
 
	0x2, /* Track 1 -> Track 2 */
 
	0x1, /* Track 2 -> Track 1 */
 
	0x30, /* Upper -> Left | Right */
 
	0x30, /* Lower -> Left | Right */
 
	0x0C, /* Left -> Upper | Lower */
 
	0x0C, /* Right -> Upper | Lower */
 
};
 

	
 
/* Maps a trackdir to the (4-way) direction the tile is exited when following
 
 * that trackdir */
 
const byte _trackdir_to_exitdir[14] = {
 
	0,1,0,1,2,1, 0,0,
 
	2,3,3,2,3,0,
 
};
 

	
 
const byte _track_exitdir_to_trackdir[6][4] = {
 
	{0,    0xff, 8,    0xff},
 
	{0xff, 1,    0xff, 9},
 
	{2,    0xff, 0xff, 10},
 
	{0xff, 3,    11,   0xf},
 
	{0xff, 0xff, 4,    12},
 
	{13,   5,    0xff, 0xff}
 
};
 

	
 
const byte _track_direction_to_trackdir[6][8] = {
 
	{0xff, 0,    0xff, 0xff, 0xff, 8,    0xff, 0xff},
 
	{0xff, 0xff, 0xff, 1,    0xff, 0xff, 0xff, 9},
 
	{0xff, 0xff, 2,    0xff, 0xff, 0xff, 10,   0xff},
 
	{0xff, 0xff, 3,    0xff, 0xff, 0xff, 11,   0xff},
 
	{12,   0xff, 0xff, 0xff, 4,    0xff, 0xff, 0xff},
 
	{13,   0xff, 0xff, 0xff, 5,    0xff, 0xff, 0xff}
 
};
 

	
 
const byte _dir_to_diag_trackdir[4] = {
 
	0, 1, 8, 9,
 
};
 

	
 
const byte _reverse_dir[4] = {
 
	2, 3, 0, 1
 
};
 

	
 
const byte _reverse_trackdir[14] = {
 
	8, 9, 10, 11, 12, 13, 0xFF, 0xFF,
 
	0, 1, 2,  3,  4,  5
 
};
 

	
 
/* The cost of each trackdir. A diagonal piece is the full NPF_TILE_LENGTH,
 
 * the shorter piece is sqrt(2)/2*NPF_TILE_LENGTH =~ 0.7071
 
 */
 
@@ -214,11 +130,11 @@ void NPFFillTrackdirChoice(AyStarNode* c
 
uint NPFTunnelCost(AyStarNode* current) {
 
	byte exitdir = _trackdir_to_exitdir[current->direction];
 
	TileIndex tile = current->tile;
 
	if ( (uint)(_map5[tile] & 3) == _reverse_dir[exitdir]) {
 
	if ( (uint)(_map5[tile] & 3) == ReverseDiagdir(exitdir)) {
 
		/* We just popped out if this tunnel, since were
 
		 * facing the tunnel exit */
 
		FindLengthOfTunnelResult flotr;
 
		flotr = FindLengthOfTunnel(tile, _reverse_dir[exitdir]);
 
		flotr = FindLengthOfTunnel(tile, ReverseDiagdir(exitdir));
 
		return flotr.length * NPF_TILE_LENGTH;
 
		//TODO: Penalty for tunnels?
 
	} else {
 
@@ -233,13 +149,15 @@ uint NPFSlopeCost(AyStarNode* current) {
 
	int x,y;
 
	int8 z1,z2;
 

	
 
	x = TileX(current->tile) * 16;
 
	y = TileY(current->tile) * 16;
 
	z1 = GetSlopeZ(x+8, y+8);
 
	x = TileX(current->tile) * TILE_SIZE;
 
	y = TileY(current->tile) * TILE_SIZE;
 
	/* get the height of the center of the current tile */
 
	z1 = GetSlopeZ(x+TILE_HEIGHT, y+TILE_HEIGHT);
 

	
 
	x = TileX(next) * 16;
 
	y = TileY(next) * 16;
 
	z2 = GetSlopeZ(x+8, y+8);
 
	x = TileX(next) * TILE_SIZE;
 
	y = TileY(next) * TILE_SIZE;
 
	/* get the height of the center of the next tile */
 
	z2 = GetSlopeZ(x+TILE_HEIGHT, y+TILE_HEIGHT);
 

	
 
	if ((z2 - z1) > 1) {
 
		/* Slope up */
 
@@ -499,7 +417,7 @@ static inline RailType GetTileRailType(T
 
			/* railway bridge ending */
 
			if ((_map5[tile] & 0xC6) == 0x80) type = _map3_lo[tile] & RAILTYPE_MASK;
 
			/* on railway bridge */
 
			if ((_map5[tile] & 0xC6) == 0xC0 && (_map5[tile] & 0x1) == (_trackdir_to_exitdir[trackdir] & 0x1))
 
			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))
 
@@ -554,7 +472,7 @@ void NPFFollowTrack(AyStar* aystar, Open
 
			 * otherwise (only for trains, since only with trains you can
 
			 * (sometimes) reach tiles after reversing that you couldn't reach
 
			 * without reversing. */
 
			if (src_trackdir == _dir_to_diag_trackdir[_reverse_dir[exitdir]] && type == TRANSPORT_RAIL)
 
			if (src_trackdir == _dir_to_diag_trackdir[ReverseDiagdir(exitdir)] && type == TRANSPORT_RAIL)
 
				/* We are headed inwards. We can only reverse here, so we'll not
 
				 * consider this direction, but jump ahead to the reverse direction.
 
				 * It would be nicer to return one neighbour here (the reverse
 
@@ -609,7 +527,7 @@ void NPFFollowTrack(AyStar* aystar, Open
 
		 * orientation. They are only "inwards", since we are reaching this tile
 
		 * from some other tile. This prevents vehicles driving into depots from
 
		 * the back */
 
		ts = (1 << _dir_to_diag_trackdir[_reverse_dir[exitdir]]);
 
		ts = TrackdirToTrackdirBits(DiagdirToDiagTrackdir(ReverseDiagdir(exitdir)));
 
	} else {
 
		ts = GetTileTrackStatus(dst_tile, type);
 
	}
 
@@ -617,7 +535,7 @@ void NPFFollowTrack(AyStar* aystar, Open
 

	
 
	DEBUG(npf, 4)("Next node: (%d, %d) [%d], possible trackdirs: %#x", TileX(dst_tile), TileY(dst_tile), dst_tile, trackdirs);
 
	/* Select only trackdirs we can reach from our current trackdir */
 
	trackdirs &= _trackdir_reaches_trackdirs[src_trackdir];
 
	trackdirs &= TrackdirReachesTrackdirs(src_trackdir);
 
	if (_patches.forbid_90_deg && (type == TRANSPORT_RAIL || type == TRANSPORT_WATER)) /* Filter out trackdirs that would make 90 deg turns for trains */
 
		trackdirs &= ~_trackdir_crosses_trackdirs[src_trackdir];
 
	DEBUG(npf,6)("After filtering: (%d, %d), possible trackdirs: %#x", TileX(dst_tile), TileY(dst_tile), trackdirs);
 
@@ -682,11 +600,11 @@ NPFFoundTargetData NPFRouteInternal(AySt
 
		assert(0);
 

	
 
	/* Initialize Start Node(s) */
 
	start1->user_data[NPF_TRACKDIR_CHOICE] = 0xff;
 
	start1->user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
 
	start1->user_data[NPF_NODE_FLAGS] = 0;
 
	_npf_aystar.addstart(&_npf_aystar, start1, 0);
 
	if (start2) {
 
		start2->user_data[NPF_TRACKDIR_CHOICE] = 0xff;
 
		start2->user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
 
		start2->user_data[NPF_NODE_FLAGS] = 0;
 
		NPFSetFlag(start2, NPF_FLAG_REVERSE, true);
 
		_npf_aystar.addstart(&_npf_aystar, start2, reverse_penalty);
 
@@ -695,7 +613,7 @@ NPFFoundTargetData NPFRouteInternal(AySt
 
	/* Initialize result */
 
	result.best_bird_dist = (uint)-1;
 
	result.best_path_dist = (uint)-1;
 
	result.best_trackdir = 0xff;
 
	result.best_trackdir = INVALID_TRACKDIR;
 
	_npf_aystar.user_path = &result;
 

	
 
	/* Initialize target */
 
@@ -721,7 +639,7 @@ NPFFoundTargetData NPFRouteInternal(AySt
 
	return result;
 
}
 

	
 
NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, byte trackdir1, TileIndex tile2, byte trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner) {
 
NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner) {
 
	AyStarNode start1;
 
	AyStarNode start2;
 

	
 
@@ -729,19 +647,19 @@ NPFFoundTargetData NPFRouteToStationOrTi
 
	start2.tile = tile2;
 
	/* We set this in case the target is also the start tile, we will just
 
	 * return a not found then */
 
	start1.user_data[NPF_TRACKDIR_CHOICE] = 0xff;
 
	start1.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
 
	start1.direction = trackdir1;
 
	start2.direction = trackdir2;
 
	start2.user_data[NPF_TRACKDIR_CHOICE] = 0xff;
 
	start2.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
 

	
 
	return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type, owner, 0);
 
}
 

	
 
NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, byte trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner) {
 
NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner) {
 
	return NPFRouteToStationOrTileTwoWay(tile, trackdir, INVALID_TILE, 0, target, type, owner);
 
}
 

	
 
NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, byte trackdir1, TileIndex tile2, byte trackdir2, TransportType type, Owner owner, uint reverse_penalty) {
 
NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, TransportType type, Owner owner, uint reverse_penalty) {
 
	AyStarNode start1;
 
	AyStarNode start2;
 

	
 
@@ -749,21 +667,21 @@ NPFFoundTargetData NPFRouteToDepotBreadt
 
	start2.tile = tile2;
 
	/* We set this in case the target is also the start tile, we will just
 
	 * return a not found then */
 
	start1.user_data[NPF_TRACKDIR_CHOICE] = 0xff;
 
	start1.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
 
	start1.direction = trackdir1;
 
	start2.direction = trackdir2;
 
	start2.user_data[NPF_TRACKDIR_CHOICE] = 0xff;
 
	start2.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
 

	
 
	/* perform a breadth first search. Target is NULL,
 
	 * since we are just looking for any depot...*/
 
	return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), NULL, NPFFindDepot, NPFCalcZero, type, owner, reverse_penalty);
 
}
 

	
 
NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, byte trackdir, TransportType type, Owner owner) {
 
NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner) {
 
	return NPFRouteToDepotBreadthFirstTwoWay(tile, trackdir, INVALID_TILE, 0, type, owner, 0);
 
}
 

	
 
NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, byte trackdir, TransportType type, Owner owner) {
 
NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir 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
 
@@ -836,14 +754,14 @@ NPFFoundTargetData NPFRouteToDepotTrialE
 
		/* Initialize Start Node */
 
		/* We set this in case the target is also the start tile, we will just
 
		 * return a not found then */
 
		start.user_data[NPF_TRACKDIR_CHOICE] = 0xff;
 
		start.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
 
		start.user_data[NPF_NODE_FLAGS] = 0;
 
		_npf_aystar.addstart(&_npf_aystar, &start, 0);
 

	
 
		/* Initialize result */
 
		result.best_bird_dist = (uint)-1;
 
		result.best_path_dist = (uint)-1;
 
		result.best_trackdir = 0xff;
 
		result.best_trackdir = INVALID_TRACKDIR;
 

	
 
		/* Initialize target */
 
		target.dest_coords = current->xy;
 
@@ -871,52 +789,6 @@ void InitializeNPF(void)
 
	/* We will limit the number of nodes for now, until we have a better
 
	 * solution to really fix performance */
 
	_npf_aystar.max_search_nodes = _patches.npf_max_search_nodes;
 
#if 0
 
	init_AyStar(&_train_find_station, NTPHash, 1024);
 
	init_AyStar(&_train_find_depot, NTPHash, 1024);
 
	init_AyStar(&_road_find_station, NTPHash, 1024);
 
	init_AyStar(&_road_find_depot, NTPHash, 1024);
 

	
 
	_train_find_station.loops_per_tick = 0;
 
	_train_find_depot.loops_per_tick = 0;
 
	_road_find_station.loops_per_tick = 0;
 
	_road_find_depot.loops_per_tick = 0;
 

	
 
	_train_find_station.max_path_cost = 0;
 
	_train_find_depot.max_path_cost = 0;
 
	_road_find_station.max_path_cost = 0;
 
	_road_find_depot.max_path_cost = 0;
 

	
 
	_train_find_station.max_search_nodes = 0;
 
	_train_find_depot.max_search_nodes = 0;
 
	_road_find_station.max_search_nodes = 0;
 
	_road_find_depot.max_search_nodes = 0;
 

	
 
	_train_find_station.CalculateG = NPFRailPathCost;
 
	_train_find_depot.CalculateG = NPFRailPathCost;
 
	_road_find_station.CalculateG = NPFRoadPathCost;
 
	_road_find_depot.CalculateG = NPFRoadPathCost;
 

	
 
	_train_find_station.CalculateH = NPFCalcStationHeuristic;
 
	_train_find_depot.CalculateH = NPFCalcStationHeuristic;
 
	_road_find_station.CalculateH = NPFCalcStationHeuristic;
 
	_road_find_depot.CalculateH = NPFCalcStationHeuristic;
 

	
 
	_train_find_station.EndNodeCheck = NPFFindStationOrTile;
 
	_train_find_depot.EndNodeCheck = NPFFindStationOrTile;
 
	_road_find_station.EndNodeCheck = NPFFindStationOrTile;
 
	_road_find_depot.EndNodeCheck = NPFFindStationOrTile;
 

	
 
	_train_find_station.FoundEndNode = NPFSaveTargetData;
 
	_train_find_depot.FoundEndNode = NPFSaveTargetData;
 
	_road_find_station.FoundEndNode = NPFSaveTargetData;
 
	_road_find_depot.FoundEndNode = NPFSaveTargetData;
 

	
 
	_train_find_station.GetNeighbours = NPFFollowTrack;
 
	_train_find_depot.GetNeighbours = NPFFollowTrack;
 
	_road_find_station.GetNeighbours = NPFFollowTrack;
 
	_road_find_depot.GetNeighbours = NPFFollowTrack;
 
#endif
 
}
 

	
 
void NPFFillWithOrderData(NPFFindStationOrTileData* fstd, Vehicle* v) {
npf.h
Show inline comments
 
#ifndef NPF_H
 
#define NPF_H
 

	
 
/* Blaat */
 

	
 
#include "openttd.h"
 
#include "aystar.h"
 
#include "vehicle.h"
 
#include "tile.h"
 
#include "rail.h"
 

	
 
//mowing grass
 
enum {
 
@@ -50,7 +50,7 @@ typedef enum { /* Flags for AyStarNode.u
 
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 shortest path/closest birds dist */
 
	Trackdir 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;
 

	
 
@@ -59,27 +59,27 @@ typedef struct NPFFoundTargetData { /* M
 
/* 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, Owner owner);
 
NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, Trackdir 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_FLAG_REVERSE flag in the result node to see which
 
 * direction was taken (NPFGetBit(result.node, NPF_FLAG_REVERSE)) */
 
NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, byte trackdir1, TileIndex tile2, byte trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner);
 
NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir 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, Owner owner);
 
NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner);
 
/* Same as above but with two start nodes, the second being the reverse. Call
 
 * NPFGetBit(result.node, NPF_FLAG_REVERSE) to see from which node the path
 
 * orginated. All pathfs from the second node will have the given
 
 * reverse_penalty applied (NPF_TILE_LENGTH is the equivalent of one full
 
 * tile).
 
 */
 
NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, byte trackdir1, TileIndex tile2, byte trackdir2, TransportType type, Owner owner, uint reverse_penalty);
 
NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, TransportType type, Owner owner, uint reverse_penalty);
 
/* 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, Owner owner);
 
NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner);
 

	
 
void NPFFillWithOrderData(NPFFindStationOrTileData* fstd, Vehicle* v);
 

	
 
@@ -107,95 +107,4 @@ static inline void NPFSetFlag(AyStarNode
 
		CLRBIT(node->user_data[NPF_NODE_FLAGS], flag);
 
}
 

	
 
/*
 
 * Some tables considering tracks, directions and signals.
 
 * XXX: Better place to but these?
 
 */
 

	
 
/**
 
 * Maps a trackdir to the bit that stores its status in the map arrays, in the
 
 * direction along with the trackdir.
 
 */
 
const byte _signal_along_trackdir[14];
 

	
 
/**
 
 * Maps a trackdir to the bit that stores its status in the map arrays, in the
 
 * direction against the trackdir.
 
 */
 
const byte _signal_against_trackdir[14];
 

	
 
/**
 
 * Maps a trackdir to the trackdirs that can be reached from it (ie, when
 
 * entering the next tile.
 
 */
 
const uint16 _trackdir_reaches_trackdirs[14];
 

	
 
/**
 
 * Maps a trackdir to the trackdir that you will end up on if you go straight
 
 * ahead. This will be the same trackdir for diagonal trackdirs, but a
 
 * different (alternating) one for straight trackdirs */
 
const uint16 _next_trackdir[14];
 
/**
 
 * Maps a trackdir to all trackdirs that make 90 deg turns with it.
 
 */
 
const uint16 _trackdir_crosses_trackdirs[14];
 

	
 
/**
 
 * Maps a track to all tracks that make 90 deg turns with it.
 
 */
 
const byte _track_crosses_tracks[6];
 

	
 
/**
 
 * Maps a trackdir to the (4-way) direction the tile is exited when following
 
 * that trackdir.
 
 */
 
const byte _trackdir_to_exitdir[14];
 

	
 
/**
 
 * Maps a track and an (4-way) dir to the trackdir that represents the track
 
 * with the exit in the given direction.
 
 */
 
const byte _track_exitdir_to_trackdir[6][4];
 

	
 
/**
 
 * Maps a track and a full (8-way) direction to the trackdir that represents
 
 * the track running in the given direction.
 
 */
 
const byte _track_direction_to_trackdir[6][8];
 

	
 
/**
 
 * Maps a (4-way) direction to the diagonal track that runs in that
 
 * direction.
 
 */
 
const byte _dir_to_diag_trackdir[4];
 

	
 
/**
 
 * Maps a (4-way) direction to the reverse.
 
 */
 
const byte _reverse_dir[4];
 

	
 
/**
 
 * Maps a trackdir to the reverse trackdir.
 
 */
 
const byte _reverse_trackdir[14];
 

	
 
/* Returns the Track that a given Trackdir represents */
 
static inline byte TrackdirToTrack(byte trackdir) { return trackdir & 0x7; }
 

	
 
/* Returns a Trackdir for the given Track. Since every Track corresponds to
 
 * two Trackdirs, we choose the one which points between N and SE.
 
 * Note that the actual implementation is quite futile, but this might change
 
 * in the future.
 
 */
 
static inline byte TrackToTrackdir(byte track) { return track; }
 

	
 
/* Checks if a given Track is diagonal */
 
static inline bool IsDiagonalTrack(byte track) { return track == 0x0 || track == 0x1; }
 

	
 
/* Checks if a given Trackdir is diagonal. */
 
static inline bool IsDiagonalTrackdir(byte trackdir) { return IsDiagonalTrack(TrackdirToTrack(trackdir)); }
 

	
 

	
 
#define REVERSE_TRACKDIR(trackdir) (trackdir ^ 0x8)
 

	
 
#endif // NPF_H
rail.c
Show inline comments
 
new file 100644
 
#include "rail.h"
 

	
 
/* Maps a trackdir to the bit that stores its status in the map arrays, in the
 
 * direction along with the trackdir */
 
const byte _signal_along_trackdir[] = {
 
	0x80, 0x80, 0x80, 0x20, 0x40, 0x10, 0, 0,
 
	0x40, 0x40, 0x40, 0x10, 0x80, 0x20
 
};
 

	
 
/* Maps a trackdir to the bit that stores its status in the map arrays, in the
 
 * direction against the trackdir */
 
const byte _signal_against_trackdir[] = {
 
	0x40, 0x40, 0x40, 0x10, 0x80, 0x20, 0, 0,
 
	0x80, 0x80, 0x80, 0x20, 0x40, 0x10
 
};
 

	
 
/* Maps a Track to the bits that store the status of the two signals that can
 
 * be present on the given track */
 
const byte _signal_on_track[] = {
 
	0xC0, 0xC0, 0xC0, 0x30, 0xC0, 0x30
 
};
 

	
 
/* Maps a diagonal direction to the all trackdirs that are connected to any
 
 * track entering in this direction (including those making 90 degree turns)
 
 */
 
const TrackdirBits _exitdir_reaches_trackdirs[] = {
 
	TRACKDIR_BIT_DIAG1_NE|TRACKDIR_BIT_LOWER_E|TRACKDIR_BIT_LEFT_N,  /* DIAGDIR_NE */
 
	TRACKDIR_BIT_DIAG2_SE|TRACKDIR_BIT_LEFT_S |TRACKDIR_BIT_UPPER_E, /* DIAGDIR_SE */
 
	TRACKDIR_BIT_DIAG1_SW|TRACKDIR_BIT_UPPER_W|TRACKDIR_BIT_RIGHT_S, /* DIAGDIR_SW */
 
	TRACKDIR_BIT_DIAG2_NW|TRACKDIR_BIT_RIGHT_N|TRACKDIR_BIT_LOWER_W  /* DIAGDIR_NW */
 
};
 

	
 
/* TODO: Remove magic numbers from tables below just like
 
 * _exitdir_reaches_trackdirs[] */
 

	
 
const Trackdir _next_trackdir[14] = {
 
	0,  1,  3,  2,  5,  4, 0, 0,
 
	8,  9,  11, 10, 13, 12
 
};
 

	
 
/* Maps a trackdir to all trackdirs that make 90 deg turns with it. */
 
const TrackdirBits _trackdir_crosses_trackdirs[] = {
 
	0x0202, 0x0101, 0x3030, 0x3030, 0x0C0C, 0x0C0C, 0, 0,
 
	0x0202, 0x0101, 0x3030, 0x3030, 0x0C0C, 0x0C0C
 
};
 

	
 
/* Maps a track to all tracks that make 90 deg turns with it. */
 
const TrackBits _track_crosses_tracks[] = {
 
	0x2, /* Track 1 -> Track 2 */
 
	0x1, /* Track 2 -> Track 1 */
 
	0x30, /* Upper -> Left | Right */
 
	0x30, /* Lower -> Left | Right */
 
	0x0C, /* Left -> Upper | Lower */
 
	0x0C, /* Right -> Upper | Lower */
 
};
 

	
 
/* Maps a trackdir to the (4-way) direction the tile is exited when following
 
 * that trackdir */
 
const DiagDirection _trackdir_to_exitdir[] = {
 
	0,1,0,1,2,1, 0,0,
 
	2,3,3,2,3,0,
 
};
 

	
 
const Trackdir _track_exitdir_to_trackdir[][DIAGDIR_END] = {
 
	{0,    0xff, 8,    0xff},
 
	{0xff, 1,    0xff, 9},
 
	{2,    0xff, 0xff, 10},
 
	{0xff, 3,    11,   0xf},
 
	{0xff, 0xff, 4,    12},
 
	{13,   5,    0xff, 0xff}
 
};
 

	
 
const Trackdir _track_direction_to_trackdir[][DIR_END] = {
 
	{0xff, 0,    0xff, 0xff, 0xff, 8,    0xff, 0xff},
 
	{0xff, 0xff, 0xff, 1,    0xff, 0xff, 0xff, 9},
 
	{0xff, 0xff, 2,    0xff, 0xff, 0xff, 10,   0xff},
 
	{0xff, 0xff, 3,    0xff, 0xff, 0xff, 11,   0xff},
 
	{12,   0xff, 0xff, 0xff, 4,    0xff, 0xff, 0xff},
 
	{13,   0xff, 0xff, 0xff, 5,    0xff, 0xff, 0xff}
 
};
 

	
 
const Trackdir _dir_to_diag_trackdir[] = {
 
	0, 1, 8, 9,
 
};
 

	
 
const DiagDirection _reverse_diagdir[] = {
 
	2, 3, 0, 1
 
};
 

	
 
const Trackdir _reverse_trackdir[] = {
 
	8, 9, 10, 11, 12, 13, 0xFF, 0xFF,
 
	0, 1, 2,  3,  4,  5
 
};
rail.h
Show inline comments
 
new file 100644
 
#ifndef RAIL_H
 
#define RAIL_H
 

	
 
#include "stdafx.h"
 
#include "openttd.h"
 
#include "tile.h"
 

	
 
/*
 
 * Some enums for accesing the map bytes for rail tiles
 
 */
 

	
 
/* These types are used in the map5 byte for rail tiles. Use GetRailTileType() to
 
 * get these values */
 
typedef enum RailTileTypes {
 
	RAIL_TYPE_NORMAL         = 0x0,
 
	RAIL_TYPE_SIGNALS        = 0x40,
 
	RAIL_TYPE_UNUSED         = 0x80, /* XXX: Maybe this could become waypoints? */
 
	RAIL_TYPE_DEPOT_WAYPOINT = 0xC0, /* Is really depots and waypoints... */
 
	RAIL_TILE_TYPE_MASK      = 0xC0,
 
} RailTileType;
 

	
 
enum { /* DEPRECATED TODO: Rewrite all uses of this */
 
	RAIL_TYPE_SPECIAL = 0x80, /* This used to say "If this bit is set, then it's
 
														 * not a regular track.", but currently, you
 
														 * should rather view map5[6..7] as one type,
 
														 * containing a value from RailTileTypes above.
 
														 * This value is only maintained for backwards
 
														 * compatibility */
 

	
 
	/* There used to be RAIL_BIT_* enums here, they moved to (for now) npf.c as
 
	 * TRACK_BIT_* */
 
};
 

	
 
/* These subtypes are used in the map5 byte when the main rail type is
 
 * RAIL_TYPE_DEPOT_WAYPOINT */
 
typedef enum {
 
	RAIL_SUBTYPE_DEPOT    = 0x00,
 
	RAIL_SUBTYPE_WAYPOINT = 0x04,
 
	RAIL_SUBTYPE_MASK     = 0x3C,
 
} RailTileSubtype;
 

	
 
typedef enum {
 
	/* Stored in _map3_hi[0..1] for MP_RAILWAY */
 
  SIGTYPE_NORMAL  = 0,        // normal signal
 
  SIGTYPE_ENTRY   = 1,        // presignal block entry
 
  SIGTYPE_EXIT    = 2,        // presignal block exit
 
  SIGTYPE_COMBO   = 3,        // presignal inter-block
 
	SIGTYPE_END,
 
	SIGTYPE_MASK    = 3,
 
} SignalType;
 

	
 
typedef enum {
 
	RAILTYPE_RAIL   = 0,
 
	RAILTYPE_MONO   = 1,
 
	RAILTYPE_MAGLEV = 2,
 
	RAILTYPE_END,
 
	RAILTYPE_MASK   = 0x3,
 
	INVALID_RAILTYPE = 0xFF,
 
} RailType;
 

	
 
enum {
 
	SIG_SEMAPHORE_MASK = 4,
 
};
 

	
 
/* These are used to specify a single track. Can be translated to a trackbit
 
 * with TrackToTrackbit */
 
typedef enum {
 
  TRACK_DIAG1 = 0,
 
  TRACK_DIAG2 = 1,
 
  TRACK_UPPER = 2,
 
  TRACK_LOWER = 3,
 
  TRACK_LEFT  = 4,
 
  TRACK_RIGHT = 5,
 
  TRACK_END,
 
  INVALID_TRACK = 0xFF,
 
} Track;
 

	
 
/* These are the bitfield variants of the above */
 
typedef enum {
 
  TRACK_BIT_DIAG1 = 1,  // 0
 
  TRACK_BIT_DIAG2 = 2,  // 1
 
  TRACK_BIT_UPPER = 4,  // 2
 
  TRACK_BIT_LOWER = 8,  // 3
 
  TRACK_BIT_LEFT  = 16, // 4
 
  TRACK_BIT_RIGHT = 32, // 5
 
	TRACK_BIT_MASK  = 0x3F,
 
} TrackBits;
 

	
 
/* These are a combination of tracks and directions. Values are 0-5 in one
 
direction (corresponding to the Track enum) and 8-13 in the other direction. */
 
typedef enum {
 
  TRACKDIR_DIAG1_NE = 0,
 
  TRACKDIR_DIAG2_SE = 1,
 
  TRACKDIR_UPPER_E  = 2,
 
  TRACKDIR_LOWER_E  = 3,
 
  TRACKDIR_LEFT_S   = 4,
 
  TRACKDIR_RIGHT_S  = 5,
 
	/* Note the two missing values here. This enables trackdir -> track conversion by doing (trackdir & 7) */
 
  TRACKDIR_DIAG1_SW = 8,
 
  TRACKDIR_DIAG2_NW = 9,
 
  TRACKDIR_UPPER_W  = 10,
 
  TRACKDIR_LOWER_W  = 11,
 
  TRACKDIR_LEFT_N   = 12,
 
  TRACKDIR_RIGHT_N  = 13,
 
  TRACKDIR_END,
 
  INVALID_TRACKDIR  = 0xFF,
 
} Trackdir;
 

	
 
/* These are a combination of tracks and directions. Values are 0-5 in one
 
direction (corresponding to the Track enum) and 8-13 in the other direction. */
 
typedef enum {
 
  TRACKDIR_BIT_DIAG1_NE = 0x1,
 
  TRACKDIR_BIT_DIAG2_SE = 0x2,
 
  TRACKDIR_BIT_UPPER_E  = 0x4,
 
  TRACKDIR_BIT_LOWER_E  = 0x8,
 
  TRACKDIR_BIT_LEFT_S   = 0x10,
 
  TRACKDIR_BIT_RIGHT_S  = 0x20,
 
	/* Again, note the two missing values here. This enables trackdir -> track conversion by doing (trackdir & 0xFF) */
 
  TRACKDIR_BIT_DIAG1_SW = 0x0100,
 
  TRACKDIR_BIT_DIAG2_NW = 0x0200,
 
  TRACKDIR_BIT_UPPER_W  = 0x0400,
 
  TRACKDIR_BIT_LOWER_W  = 0x0800,
 
  TRACKDIR_BIT_LEFT_N   = 0x1000,
 
  TRACKDIR_BIT_RIGHT_N  = 0x2000,
 
	TRACKDIR_BIT_MASK			= 0x3F3F,
 
  INVALID_TRACKDIR_BIT  = 0xFFFF,
 
} TrackdirBits;
 

	
 
/* These are states in which a signal can be. Currently these are only two, so
 
 * simple boolean logic will do. But do try to compare to this enum instead of
 
 * normal boolean evaluation, since that will make future additions easier.
 
 */
 
typedef enum {
 
	SIGNALSTATE_RED = 0,
 
	SIGNALSTATE_GREEN = 1,
 
} SignalState;
 

	
 

	
 
/*
 
 * These functions check the validity of Tracks and Trackdirs. assert against
 
 * them when convenient.
 
 */
 
static inline bool IsValidTrack(Track track) { return track < TRACK_END; }
 
static inline bool IsValidTrackdir(Trackdir trackdir) { return trackdir < TRACKDIR_END; }
 

	
 
/*
 
 * Functions to map tracks to the corresponding bits in the signal
 
 * presence/status bytes in the map. You should not use these directly, but
 
 * wrapper functions below instead. XXX: Which are these?
 
 */
 

	
 
/**
 
 * Maps a trackdir to the bit that stores its status in the map arrays, in the
 
 * direction along with the trackdir.
 
 */
 
const byte _signal_along_trackdir[TRACKDIR_END];
 
static inline byte SignalAlongTrackdir(Trackdir trackdir) {return _signal_along_trackdir[trackdir];}
 

	
 
/**
 
 * Maps a trackdir to the bit that stores its status in the map arrays, in the
 
 * direction against the trackdir.
 
 */
 
const byte _signal_against_trackdir[TRACKDIR_END];
 
static inline byte SignalAgainstTrackdir(Trackdir trackdir) { return _signal_against_trackdir[trackdir]; }
 

	
 
/**
 
 * Maps a Track to the bits that store the status of the two signals that can
 
 * be present on the given track.
 
 */
 
const byte _signal_on_track[TRACK_END];
 
static inline byte SignalOnTrack(Track track) { return _signal_on_track[track]; }
 

	
 
/*
 
 * Some functions to query rail tiles
 
 */
 

	
 
/**
 
 * Returns the RailTileType of a given rail tile. (ie normal, with signals,
 
 * depot, etc.)
 
 */
 
static inline RailTileType GetRailTileType(TileIndex tile)
 
{
 
	assert(IsTileType(tile, MP_RAILWAY));
 
	return (_map5[tile] & RAIL_TILE_TYPE_MASK);
 
}
 

	
 
/**
 
 * Returns the rail type of the given rail tile (ie rail, mono, maglev).
 
 */
 
static inline RailType GetRailType(TileIndex tile) { return _map3_lo[tile] & RAILTYPE_MASK; }
 

	
 
/**
 
 * Checks if a rail tile has signals.
 
 */
 
static inline bool HasSignals(TileIndex tile)
 
{
 
	return GetRailTileType(tile) == RAIL_TYPE_SIGNALS;
 
}
 

	
 
/**
 
 * Returns the RailTileSubtype of a given rail tile with type
 
 * RAIL_TYPE_DEPOT_WAYPOINT
 
 */
 
static inline RailTileSubtype GetRailTileSubtype(TileIndex tile)
 
{
 
	assert(GetRailTileType(tile) == RAIL_TYPE_DEPOT_WAYPOINT);
 
	return _map5[tile] & RAIL_SUBTYPE_MASK;
 
}
 

	
 
/**
 
 * Returns whether this is plain rails, with or without signals. Iow, if this
 
 * tiles RailTileType is RAIL_TYPE_NORMAL or RAIL_TYPE_SIGNALS.
 
 */
 
static inline bool IsPlainRailTile(TileIndex tile)
 
{
 
	RailTileType rtt = GetRailTileType(tile);
 
	return rtt == RAIL_TYPE_NORMAL || rtt == RAIL_TYPE_SIGNALS;
 
}
 

	
 
/**
 
 * Returns the tracks present on the given plain rail tile (IsPlainRailTile())
 
 */
 
static inline TrackBits GetTrackBits(TileIndex tile)
 
{
 
	assert(GetRailTileType(tile) == RAIL_TYPE_NORMAL || GetRailTileType(tile) == RAIL_TYPE_SIGNALS);
 
	return _map5[tile] & TRACK_BIT_MASK;
 
}
 

	
 
/**
 
 * Returns whether the given track is present on the given tile. Tile must be
 
 * a plain rail tile (IsPlainRailTile()).
 
 */
 
static inline bool HasTrack(TileIndex tile, Track track)
 
{
 
	assert(IsValidTrack(track));
 
	return HASBIT(GetTrackBits(tile), track);
 
}
 

	
 
/*
 
 * Functions describing logical relations between Tracks, TrackBits, Trackdirs
 
 * TrackdirBits, Direction and DiagDirections.
 
 *
 
 * TODO: Add #unndefs or something similar to remove the arrays used below
 
 * from the global scope and expose direct uses of them.
 
 */
 

	
 
/**
 
 * Maps a trackdir to the trackdir that you will end up on if you go straight
 
 * ahead. This will be the same trackdir for diagonal trackdirs, but a
 
 * different (alternating) one for straight trackdirs
 
 */
 
const Trackdir _next_trackdir[TRACKDIR_END];
 
static inline Trackdir NextTrackdir(Trackdir trackdir) { return _next_trackdir[trackdir]; }
 

	
 
/**
 
 * Maps a track to all tracks that make 90 deg turns with it.
 
 */
 
const TrackBits _track_crosses_tracks[TRACK_END];
 
static inline TrackBits TrackCrossesTracks(Track track) { return _track_crosses_tracks[track]; }
 

	
 
/**
 
 * Maps a trackdir to the (4-way) direction the tile is exited when following
 
 * that trackdir.
 
 */
 
const DiagDirection _trackdir_to_exitdir[TRACKDIR_END];
 
static inline DiagDirection TrackdirToExitdir(Trackdir trackdir) { return _trackdir_to_exitdir[trackdir]; }
 

	
 
/**
 
 * Maps a track and an (4-way) dir to the trackdir that represents the track
 
 * with the exit in the given direction.
 
 */
 
const Trackdir _track_exitdir_to_trackdir[TRACK_END][DIAGDIR_END];
 
static inline Trackdir TrackExitdirToTrackdir(Track track, DiagDirection diagdir) { return _track_exitdir_to_trackdir[track][diagdir]; }
 

	
 
/**
 
 * Maps a track and a full (8-way) direction to the trackdir that represents
 
 * the track running in the given direction.
 
 */
 
const Trackdir _track_direction_to_trackdir[TRACK_END][DIR_END];
 
static inline Trackdir TrackDirectionToTrackdir(Track track, Direction dir) { return _track_direction_to_trackdir[track][dir]; }
 

	
 
/**
 
 * Maps a (4-way) direction to the diagonal trackdir that runs in that
 
 * direction.
 
 */
 
const Trackdir _dir_to_diag_trackdir[DIAGDIR_END];
 
static inline Trackdir DiagdirToDiagTrackdir(DiagDirection diagdir) { return _dir_to_diag_trackdir[diagdir]; }
 

	
 
/**
 
 * Maps a trackdir to the trackdirs that can be reached from it (ie, when
 
 * entering the next tile. This
 
 */
 
const TrackdirBits _exitdir_reaches_trackdirs[DIAGDIR_END];
 
/* Note that there is no direct table for this function (there used to be),
 
 * but it uses two simpeler tables to achieve the result */
 
static inline TrackdirBits TrackdirReachesTrackdirs(Trackdir trackdir) { return _exitdir_reaches_trackdirs[TrackdirToExitdir(trackdir)]; }
 

	
 
/**
 
 * Maps a trackdir to all trackdirs that make 90 deg turns with it.
 
 */
 
const TrackdirBits _trackdir_crosses_trackdirs[TRACKDIR_END];
 
static inline TrackdirBits TrackdirCrossesTrackdirs(Trackdir trackdir) { return _trackdir_crosses_trackdirs[trackdir]; }
 

	
 
/**
 
 * Maps a (4-way) direction to the reverse.
 
 */
 
const DiagDirection _reverse_diagdir[DIAGDIR_END];
 
static inline DiagDirection ReverseDiagdir(DiagDirection diagdir) { return _reverse_diagdir[diagdir]; }
 

	
 
/**
 
 * Maps a trackdir to the reverse trackdir.
 
 */
 
const Trackdir _reverse_trackdir[TRACKDIR_END];
 
static inline Trackdir ReverseTrackdir(Trackdir trackdir) { return _reverse_trackdir[trackdir]; }
 

	
 
/**
 
 * Maps a Trackdir to the corresponding TrackdirBits value
 
 */
 
static inline TrackdirBits TrackdirToTrackdirBits(Trackdir trackdir) { return 1 << trackdir; }
 

	
 
/*
 
 * Maps a Track to the corresponding TrackBits value
 
 */
 
static inline TrackBits TrackToTrackBits(Track track) { return 1 << track; }
 

	
 
/* Returns the Track that a given Trackdir represents */
 
static inline Track TrackdirToTrack(Trackdir trackdir) { return trackdir & 0x7; }
 

	
 
/* Returns a Trackdir for the given Track. Since every Track corresponds to
 
 * two Trackdirs, we choose the one which points between N and SE.
 
 * Note that the actual implementation is quite futile, but this might change
 
 * in the future.
 
 */
 
static inline Trackdir TrackToTrackdir(Track track) { return track; }
 

	
 
/* Checks if a given Track is diagonal */
 
static inline bool IsDiagonalTrack(Track track) { return track == TRACK_DIAG1 || track == TRACK_DIAG2; }
 

	
 
/* Checks if a given Trackdir is diagonal. */
 
static inline bool IsDiagonalTrackdir(Trackdir trackdir) { return IsDiagonalTrack(TrackdirToTrack(trackdir)); }
 

	
 
/*
 
 * Functions quering signals on tiles.
 
 */
 

	
 
/**
 
 * Checks for the presence of signals on the given track on the given tile
 
 */
 
static inline bool HasSignalOnTrack(TileIndex tile, Track track)
 
{
 
	assert(IsValidTrack(track));
 
	return (GetRailTileType(tile) == RAIL_TYPE_SIGNALS && (_map3_lo[tile] & SignalOnTrack(track)));
 
}
 

	
 
/**
 
 * Gets the state of the signal along the given trackdir.
 
 *
 
 * Along meaning if you are currently driving on the given trackdir, this is
 
 * the signal that is facing us (for which we stop when it's red).
 
 */
 
static inline SignalState GetSignalState(TileIndex tile, Trackdir trackdir)
 
{
 
	assert(IsValidTrackdir(trackdir));
 
	assert(HasSignalOnTrack(tile, TrackdirToTrack(trackdir)));
 
	return ((_map2[tile] & SignalAlongTrackdir(trackdir))?SIGNALSTATE_GREEN:SIGNALSTATE_RED);
 
}
 

	
 
/**
 
 * Gets the type of signal on a given track on a given rail tile with signals.
 
 *
 
 * Note that currently, the track argument is not used, since
 
 * signal types cannot be mixed. This function is trying to be
 
 * future-compatible, though.
 
 */
 
static inline SignalType GetSignalType(TileIndex tile, Track track)
 
{
 
	assert(IsValidTrack(track));
 
	assert(GetRailTileType(tile) == RAIL_TYPE_SIGNALS);
 
	return _map3_hi[tile] & SIGTYPE_MASK;
 
}
 

	
 
/**
 
 * Checks if this tile contains semaphores (returns true) or normal signals
 
 * (returns false) on the given track. Does not check if there are actually
 
 * signals on the track, you should use HasSignalsOnTrack() for that.
 
 *
 
 * Note that currently, the track argument is not used, since
 
 * semaphores/electric signals cannot be mixed. This function is trying to be
 
 * future-compatible, though.
 
 */
 
static inline bool HasSemaphores(TileIndex tile, Track track)
 
{
 
	assert(IsValidTrack(track));
 
	return _map3_hi[tile] & SIG_SEMAPHORE_MASK;
 
}
 

	
 
#endif // RAIL_H
rail_cmd.c
Show inline comments
 
@@ -17,41 +17,12 @@
 
#include "sprite.h"
 
#include "depot.h"
 
#include "waypoint.h"
 
#include "rail.h"
 

	
 
extern uint16 _custom_sprites_base;
 

	
 
void ShowTrainDepotWindow(uint tile);
 

	
 
enum { /* These values are bitmasks for the map5 byte */
 
	RAIL_TYPE_NORMAL = 0,
 
	RAIL_TYPE_SIGNALS = 0x40,
 
	RAIL_TYPE_SPECIAL = 0x80, // If this bit is set, then it's not a regular track.
 
	RAIL_TYPE_DEPOT = 0xC0,
 
	RAIL_TYPE_MASK = 0xC0,
 

	
 
	RAIL_BIT_DIAG1 = 1,  // 0
 
	RAIL_BIT_DIAG2 = 2,  // 1
 
	RAIL_BIT_UPPER = 4,  // 2
 
	RAIL_BIT_LOWER = 8,  // 3
 
	RAIL_BIT_LEFT  = 16, // 4
 
	RAIL_BIT_RIGHT = 32, // 5
 
	RAIL_BIT_MASK = 0x3F,
 

	
 
	RAIL_DEPOT_TRACK_MASK = 1,
 
	RAIL_DEPOT_DIR = 3,
 

	
 
	RAIL_SUBTYPE_MASK     = 0x3C,
 
	RAIL_SUBTYPE_DEPOT    = 0x00,
 
	RAIL_SUBTYPE_WAYPOINT = 0x04
 
};
 

	
 
static inline bool IsRailDepot(byte m5)
 
{
 
	return
 
		(m5 & RAIL_TYPE_MASK) == RAIL_TYPE_DEPOT &&
 
		(m5 & RAIL_SUBTYPE_MASK) == RAIL_SUBTYPE_DEPOT;
 
}
 

	
 
/* Format of rail map5 byte.
 
 * 00 abcdef  => Normal rail
 
 * 01 abcdef  => Rail with signals
 
@@ -111,40 +82,38 @@ enum RailMap2Lower4 {
 
 *               11uuuudd => rail depot
 
 */
 

	
 
static bool CheckTrackCombination(uint map5, uint trackbits, uint flags)
 
static bool CheckTrackCombination(TileIndex tile, TrackBits to_build, uint flags)
 
{
 
	RailTileType type = GetRailTileType(tile);
 
	TrackBits current; /* The current track layout */
 
	TrackBits future; /* The track layout we want to build */
 
	_error_message = STR_1001_IMPOSSIBLE_TRACK_COMBINATION;
 

	
 
	switch (map5 & RAIL_TYPE_MASK) {
 
		case RAIL_TYPE_NORMAL:
 
			if (map5 & trackbits) {
 
				_error_message = STR_1007_ALREADY_BUILT;
 
				return false;
 
			}
 
	if (type != RAIL_TYPE_NORMAL && type != RAIL_TYPE_SIGNALS)
 
		return false; /* Cannot build anything on depots and checkpoints */
 

	
 
	/* So, we have a tile with tracks on it (and possibly signals). Let's see
 
	 * what tracks first */
 
	current = GetTrackBits(tile);
 
	future = current & to_build;
 

	
 
			if (flags & DC_NO_RAIL_OVERLAP) {
 
				// Computer players are not allowed to intersect pieces of rail.
 
				map5 |= trackbits;
 
				return
 
					map5 == (RAIL_BIT_UPPER | RAIL_BIT_LOWER) ||
 
					map5 == (RAIL_BIT_LEFT  | RAIL_BIT_RIGHT);
 
			} else {
 
				return true;
 
			}
 
	/* Are we really building something new? */
 
	if (current == future) {
 
		/* Nothing new is being built */
 
		_error_message = STR_1007_ALREADY_BUILT;
 
		return false;
 
	}
 

	
 
		case RAIL_TYPE_SIGNALS:
 
			if (map5 & trackbits) {
 
				_error_message = STR_1007_ALREADY_BUILT;
 
				return false;
 
			}
 

	
 
			map5 |= trackbits;
 
			return
 
				map5 == (RAIL_TYPE_SIGNALS | RAIL_BIT_UPPER | RAIL_BIT_LOWER) ||
 
				map5 == (RAIL_TYPE_SIGNALS | RAIL_BIT_LEFT  | RAIL_BIT_RIGHT);
 

	
 
		default:
 
			return false;
 
	/* Let's see if we may build this */
 
	if ((flags & DC_NO_RAIL_OVERLAP) || type == RAIL_TYPE_SIGNALS) {
 
		/* If we are not allowed to overlap (flag is on for ai players or we have
 
		 * signals on the tile), check that */
 
		return
 
			future == (TRACK_BIT_UPPER | TRACK_BIT_LOWER) ||
 
			future == (TRACK_BIT_LEFT  | TRACK_BIT_RIGHT);
 
	} else {
 
		/* Normally, we may overlap and any combination is valid */
 
		return true;
 
	}
 
}
 

	
 
@@ -153,68 +122,68 @@ static const byte _valid_tileh_slopes[4]
 

	
 
// set of normal ones
 
{
 
	RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT,
 
	RAIL_BIT_RIGHT,
 
	RAIL_BIT_UPPER,
 
	RAIL_BIT_DIAG1,
 
	TRACK_BIT_DIAG1|TRACK_BIT_DIAG2|TRACK_BIT_UPPER|TRACK_BIT_LOWER|TRACK_BIT_LEFT|TRACK_BIT_RIGHT,
 
	TRACK_BIT_RIGHT,
 
	TRACK_BIT_UPPER,
 
	TRACK_BIT_DIAG1,
 

	
 
	RAIL_BIT_LEFT,
 
	TRACK_BIT_LEFT,
 
	0,
 
	RAIL_BIT_DIAG2,
 
	RAIL_BIT_LOWER,
 
	TRACK_BIT_DIAG2,
 
	TRACK_BIT_LOWER,
 

	
 
	RAIL_BIT_LOWER,
 
	RAIL_BIT_DIAG2,
 
	TRACK_BIT_LOWER,
 
	TRACK_BIT_DIAG2,
 
	0,
 
	RAIL_BIT_LEFT,
 
	TRACK_BIT_LEFT,
 

	
 
	RAIL_BIT_DIAG1,
 
	RAIL_BIT_UPPER,
 
	RAIL_BIT_RIGHT,
 
	TRACK_BIT_DIAG1,
 
	TRACK_BIT_UPPER,
 
	TRACK_BIT_RIGHT,
 
},
 

	
 
// allowed rail for an evenly raised platform
 
{
 
	0,
 
	RAIL_BIT_LEFT,
 
	RAIL_BIT_LOWER,
 
	RAIL_BIT_DIAG2 | RAIL_BIT_LOWER | RAIL_BIT_LEFT,
 
	TRACK_BIT_LEFT,
 
	TRACK_BIT_LOWER,
 
	TRACK_BIT_DIAG2 | TRACK_BIT_LOWER | TRACK_BIT_LEFT,
 

	
 
	RAIL_BIT_RIGHT,
 
	RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT,
 
	RAIL_BIT_DIAG1 | RAIL_BIT_LOWER | RAIL_BIT_RIGHT,
 
	RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT,
 
	TRACK_BIT_RIGHT,
 
	TRACK_BIT_DIAG1|TRACK_BIT_DIAG2|TRACK_BIT_UPPER|TRACK_BIT_LOWER|TRACK_BIT_LEFT|TRACK_BIT_RIGHT,
 
	TRACK_BIT_DIAG1 | TRACK_BIT_LOWER | TRACK_BIT_RIGHT,
 
	TRACK_BIT_DIAG1|TRACK_BIT_DIAG2|TRACK_BIT_UPPER|TRACK_BIT_LOWER|TRACK_BIT_LEFT|TRACK_BIT_RIGHT,
 

	
 
	RAIL_BIT_UPPER,
 
	RAIL_BIT_DIAG1 | RAIL_BIT_UPPER | RAIL_BIT_LEFT,
 
	RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT,
 
	RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT,
 
	TRACK_BIT_UPPER,
 
	TRACK_BIT_DIAG1 | TRACK_BIT_UPPER | TRACK_BIT_LEFT,
 
	TRACK_BIT_DIAG1|TRACK_BIT_DIAG2|TRACK_BIT_UPPER|TRACK_BIT_LOWER|TRACK_BIT_LEFT|TRACK_BIT_RIGHT,
 
	TRACK_BIT_DIAG1|TRACK_BIT_DIAG2|TRACK_BIT_UPPER|TRACK_BIT_LOWER|TRACK_BIT_LEFT|TRACK_BIT_RIGHT,
 

	
 
	RAIL_BIT_DIAG2 | RAIL_BIT_UPPER | RAIL_BIT_RIGHT,
 
	RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT,
 
	RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT,
 
	TRACK_BIT_DIAG2 | TRACK_BIT_UPPER | TRACK_BIT_RIGHT,
 
	TRACK_BIT_DIAG1|TRACK_BIT_DIAG2|TRACK_BIT_UPPER|TRACK_BIT_LOWER|TRACK_BIT_LEFT|TRACK_BIT_RIGHT,
 
	TRACK_BIT_DIAG1|TRACK_BIT_DIAG2|TRACK_BIT_UPPER|TRACK_BIT_LOWER|TRACK_BIT_LEFT|TRACK_BIT_RIGHT,
 
},
 

	
 
// allowed rail on coast tile
 
{
 
	0,
 
	RAIL_BIT_LEFT,
 
	RAIL_BIT_LOWER,
 
	RAIL_BIT_DIAG2|RAIL_BIT_LEFT|RAIL_BIT_LOWER,
 
	TRACK_BIT_LEFT,
 
	TRACK_BIT_LOWER,
 
	TRACK_BIT_DIAG2|TRACK_BIT_LEFT|TRACK_BIT_LOWER,
 

	
 
	RAIL_BIT_RIGHT,
 
	RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT,
 
	RAIL_BIT_DIAG1|RAIL_BIT_RIGHT|RAIL_BIT_LOWER,
 
	RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT,
 
	TRACK_BIT_RIGHT,
 
	TRACK_BIT_DIAG1|TRACK_BIT_DIAG2|TRACK_BIT_UPPER|TRACK_BIT_LOWER|TRACK_BIT_LEFT|TRACK_BIT_RIGHT,
 
	TRACK_BIT_DIAG1|TRACK_BIT_RIGHT|TRACK_BIT_LOWER,
 
	TRACK_BIT_DIAG1|TRACK_BIT_DIAG2|TRACK_BIT_UPPER|TRACK_BIT_LOWER|TRACK_BIT_LEFT|TRACK_BIT_RIGHT,
 

	
 
	RAIL_BIT_UPPER,
 
	RAIL_BIT_DIAG1|RAIL_BIT_LEFT|RAIL_BIT_UPPER,
 
	RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT,
 
	RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT,
 
	TRACK_BIT_UPPER,
 
	TRACK_BIT_DIAG1|TRACK_BIT_LEFT|TRACK_BIT_UPPER,
 
	TRACK_BIT_DIAG1|TRACK_BIT_DIAG2|TRACK_BIT_UPPER|TRACK_BIT_LOWER|TRACK_BIT_LEFT|TRACK_BIT_RIGHT,
 
	TRACK_BIT_DIAG1|TRACK_BIT_DIAG2|TRACK_BIT_UPPER|TRACK_BIT_LOWER|TRACK_BIT_LEFT|TRACK_BIT_RIGHT,
 

	
 
	RAIL_BIT_DIAG2|RAIL_BIT_RIGHT|RAIL_BIT_UPPER,
 
	RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT,
 
	RAIL_BIT_DIAG1|RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LOWER|RAIL_BIT_LEFT|RAIL_BIT_RIGHT,
 
	TRACK_BIT_DIAG2|TRACK_BIT_RIGHT|TRACK_BIT_UPPER,
 
	TRACK_BIT_DIAG1|TRACK_BIT_DIAG2|TRACK_BIT_UPPER|TRACK_BIT_LOWER|TRACK_BIT_LEFT|TRACK_BIT_RIGHT,
 
	TRACK_BIT_DIAG1|TRACK_BIT_DIAG2|TRACK_BIT_UPPER|TRACK_BIT_LOWER|TRACK_BIT_LEFT|TRACK_BIT_RIGHT,
 
	},
 

	
 
	// valid railway crossings on slopes
 
@@ -237,14 +206,14 @@ uint GetRailFoundation(uint tileh, uint 
 
	if ((~_valid_tileh_slopes[1][tileh] & bits) == 0)
 
		return tileh;
 

	
 
	if ( ((i=0, tileh == 1) || (i+=2, tileh == 2) || (i+=2, tileh == 4) || (i+=2, tileh == 8)) && (bits == RAIL_BIT_DIAG1 || (i++, bits == RAIL_BIT_DIAG2)))
 
	if ( ((i=0, tileh == 1) || (i+=2, tileh == 2) || (i+=2, tileh == 4) || (i+=2, tileh == 8)) && (bits == TRACK_BIT_DIAG1 || (i++, bits == TRACK_BIT_DIAG2)))
 
		return i + 15;
 

	
 
	return 0;
 
}
 

	
 
//
 
static uint32 CheckRailSlope(uint tileh, uint rail_bits, uint existing, TileIndex tile)
 
static uint32 CheckRailSlope(uint tileh, TrackBits rail_bits, TrackBits existing, TileIndex tile)
 
{
 
	// never allow building on top of steep tiles
 
	if (!(tileh & 0x10)) {
 
@@ -261,7 +230,7 @@ static uint32 CheckRailSlope(uint tileh,
 
			return 0;
 

	
 
		if ((~_valid_tileh_slopes[1][tileh] & rail_bits) == 0 || ( // whole tile is leveled up
 
					(rail_bits == RAIL_BIT_DIAG1 || rail_bits == RAIL_BIT_DIAG2) &&
 
					(rail_bits == TRACK_BIT_DIAG1 || rail_bits == TRACK_BIT_DIAG2) &&
 
					(tileh == 1 || tileh == 2 || tileh == 4 || tileh == 8)
 
				)) { // partly up
 
			if (existing != 0) {
 
@@ -278,42 +247,43 @@ static uint32 CheckRailSlope(uint tileh,
 
}
 

	
 
/* Validate functions for rail building */
 
static inline bool ValParamTrackOrientation(uint32 rail) {return rail <= 5;}
 
static inline bool ValParamTrackOrientation(Track track) {return IsValidTrack(track);}
 

	
 
/** Build a single piece of rail
 
 * @param x,y coordinates on where to build
 
 * @param p1 railtype of being built piece (normal, mono, maglev)
 
 * @param p2 rail combination to build
 
 * @param p2 rail track to build
 
 */
 
int32 CmdBuildSingleRail(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	TileIndex tile;
 
	uint tileh;
 
	uint m5;
 
	uint rail_bit;
 
	uint m5; /* XXX: Used only as a cache, should probably be removed? */
 
	Track track = (Track)p2;
 
	TrackBits trackbit;
 
	int32 cost = 0;
 
	int32 ret;
 

	
 
	if (!ValParamRailtype(p1) || !ValParamTrackOrientation(p2)) return CMD_ERROR;
 
	if (!ValParamRailtype(p1) || !ValParamTrackOrientation(track)) return CMD_ERROR;
 

	
 
	tile = TILE_FROM_XY(x, y);
 
	tileh = GetTileSlope(tile, NULL);
 
	m5 = _map5[tile];
 
	rail_bit = 1 << p2;
 
	trackbit = TrackToTrackBits(track);
 

	
 
	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 

	
 
	switch (GetTileType(tile)) {
 
		case MP_TUNNELBRIDGE:
 
			if ((m5 & 0xC0) != 0xC0 || // not bridge middle part?
 
					(m5 & 0x01 ? 1 : 2) != rail_bit) { // wrong direction?
 
					(m5 & 0x01 ? 1 : 2) != trackbit) { // wrong direction?
 
				// 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, rail_bit, 0, tile);
 
					ret = CheckRailSlope(tileh, trackbit, 0, tile);
 
					if (CmdFailed(ret)) return ret;
 
					cost += ret;
 

	
 
@@ -335,7 +305,7 @@ int32 CmdBuildSingleRail(int x, int y, u
 
			break;
 

	
 
		case MP_RAILWAY:
 
			if (!CheckTrackCombination(m5, rail_bit, flags) ||
 
			if (!CheckTrackCombination(tile, trackbit, flags) ||
 
					!EnsureNoVehicle(tile)) {
 
				return CMD_ERROR;
 
			}
 
@@ -346,13 +316,13 @@ int32 CmdBuildSingleRail(int x, int y, u
 
				return DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 
			}
 

	
 
			ret = CheckRailSlope(tileh, rail_bit, m5 & RAIL_BIT_MASK, tile);
 
			ret = CheckRailSlope(tileh, trackbit, GetTrackBits(tile), tile);
 
			if (CmdFailed(ret)) return ret;
 
			cost += ret;
 

	
 
			if (flags & DC_EXEC) {
 
				_map2[tile] &= ~RAIL_MAP2LO_GROUND_MASK; // Bare land
 
				_map5[tile] = m5 | rail_bit;
 
				_map5[tile] = m5 | trackbit;
 
			}
 
			break;
 

	
 
@@ -362,24 +332,24 @@ int32 CmdBuildSingleRail(int x, int y, u
 
			if (!EnsureNoVehicle(tile)) return CMD_ERROR;
 

	
 
			if ((m5 & 0xF0) == 0 && ( // normal road?
 
						(rail_bit == 1 && m5 == 0x05) ||
 
						(rail_bit == 2 && m5 == 0x0A) // correct direction?
 
						(track == TRACK_DIAG1 && m5 == 0x05) ||
 
						(track == TRACK_DIAG2 && m5 == 0x0A) // correct direction?
 
					)) {
 
				if (flags & DC_EXEC) {
 
					_map3_lo[tile] = GetTileOwner(tile);
 
					SetTileOwner(tile, _current_player);
 
					_map3_hi[tile] = p1;
 
					_map5[tile] = 0x10 | (rail_bit == 1 ? 0x08 : 0x00); // level crossing
 
					_map5[tile] = 0x10 | (track == TRACK_DIAG1 ? 0x08 : 0x00); // level crossing
 
				}
 
				break;
 
			}
 

	
 
			if (IsLevelCrossing(tile) && (m5 & 0x08 ? 1 : 2) == rail_bit)
 
			if (IsLevelCrossing(tile) && (m5 & 0x08 ? TRACK_DIAG1 : TRACK_DIAG2) == track)
 
				return_cmd_error(STR_1007_ALREADY_BUILT);
 
			/* FALLTHROUGH */
 

	
 
		default:
 
			ret = CheckRailSlope(tileh, rail_bit, 0, tile);
 
			ret = CheckRailSlope(tileh, trackbit, 0, tile);
 
			if (CmdFailed(ret)) return ret;
 
			cost += ret;
 

	
 
@@ -392,14 +362,14 @@ int32 CmdBuildSingleRail(int x, int y, u
 
				SetTileOwner(tile, _current_player);
 
				_map2[tile] = 0; // Bare land
 
				_map3_lo[tile] = p1; // No signals, rail type
 
				_map5[tile] = rail_bit;
 
				_map5[tile] = trackbit;
 
			}
 
			break;
 
	}
 

	
 
	if (flags & DC_EXEC) {
 
		MarkTileDirtyByTile(tile);
 
		SetSignalsOnBothDir(tile, p2);
 
		SetSignalsOnBothDir(tile, track);
 
	}
 

	
 
	return cost + _price.build_rail;
 
@@ -428,89 +398,101 @@ static const byte _signals_table_both[] 
 
 */
 
int32 CmdRemoveSingleRail(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	TileInfo ti;
 
	Track track = (Track)p2;
 
	TrackBits trackbit;
 
	uint tileh;
 
	TileIndex tile;
 
	byte rail_bit = 1 << p2;
 
	byte m5;
 

	
 
	if (!ValParamTrackOrientation(p2)) return CMD_ERROR;
 
	trackbit = TrackToTrackBits(track);
 

	
 
	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 

	
 
	FindLandscapeHeight(&ti, x, y);
 
	tile = TILE_FROM_XY(x, y);
 
	tileh = GetTileSlope(tile, NULL);
 

	
 
	tile = ti.tile;
 

	
 
	if (!((1<<ti.type) & ((1<<MP_TUNNELBRIDGE)|(1<<MP_STREET)|(1<<MP_RAILWAY))))
 
	if (!IsTileType(tile, MP_TUNNELBRIDGE) && !IsTileType(tile, MP_STREET) && !IsTileType(tile, MP_RAILWAY))
 
		return CMD_ERROR;
 

	
 
	if (_current_player != OWNER_WATER && !CheckTileOwnership(tile))
 
		return CMD_ERROR;
 

	
 
	// allow building rail under bridge
 
	if (ti.type != MP_TUNNELBRIDGE && !EnsureNoVehicle(tile))
 
	if (!IsTileType(tile, MP_TUNNELBRIDGE) && !EnsureNoVehicle(tile))
 
		return CMD_ERROR;
 

	
 
	if (ti.type == MP_TUNNELBRIDGE) {
 
		if (!EnsureNoVehicleZ(tile, TilePixelHeight(tile)))
 
			return CMD_ERROR;
 
	switch(GetTileType(tile))
 
	{
 
		case MP_TUNNELBRIDGE:
 
			if (!EnsureNoVehicleZ(tile, TilePixelHeight(tile)))
 
				return CMD_ERROR;
 

	
 
		if ((ti.map5 & 0xF8) != 0xE0)
 
			return CMD_ERROR;
 
			if ((_map5[tile] & 0xF8) != 0xE0)
 
				return CMD_ERROR;
 

	
 
		if ( ((ti.map5 & 1) ? 1 : 2) != rail_bit )
 
			return CMD_ERROR;
 
			if ( ((_map5[tile] & 1) ? 1 : 2) != trackbit )
 
				return CMD_ERROR;
 

	
 
		if (!(flags & DC_EXEC))
 
			return _price.remove_rail;
 
			if (!(flags & DC_EXEC))
 
				return _price.remove_rail;
 

	
 
		SetTileOwner(tile, OWNER_NONE);
 
		_map5[tile] = ti.map5 & 0xC7;
 
	} else if (ti.type == MP_STREET) {
 
		byte m5;
 
		if (!(ti.map5 & 0xF0))
 
			return CMD_ERROR;
 
			_map5[tile] = _map5[tile] & 0xC7;
 
			break;
 
		case MP_STREET:
 
			if (!(_map5[tile] & 0xF0))
 
				return CMD_ERROR;
 

	
 
		if (ti.map5 & 0xE0)
 
			return CMD_ERROR;
 
			if (_map5[tile] & 0xE0)
 
				return CMD_ERROR;
 

	
 
		if (ti.map5 & 8) {
 
			m5 = 5;
 
			if (rail_bit != 1)
 
				return CMD_ERROR;
 
		} else {
 
			m5 = 10;
 
			if (rail_bit != 2)
 
				return CMD_ERROR;
 
		}
 
			/* This is a crossing, let's check if the direction is correct */
 
			if (_map5[tile] & 8) {
 
				m5 = 5;
 
				if (track != TRACK_DIAG1)
 
					return CMD_ERROR;
 
			} else {
 
				m5 = 10;
 
				if (track != TRACK_DIAG2)
 
					return CMD_ERROR;
 
			}
 

	
 
		if (!(flags & DC_EXEC))
 
			return _price.remove_rail;
 
			if (!(flags & DC_EXEC))
 
				return _price.remove_rail;
 

	
 
		_map5[tile] = m5;
 
		SetTileOwner(tile, _map3_lo[tile]);
 
		_map2[tile] = 0;
 
	} else {
 
		assert(ti.type == MP_RAILWAY);
 
			_map5[tile] = m5;
 
			SetTileOwner(tile, _map3_lo[tile]);
 
			_map2[tile] = 0;
 
			break;
 
		case MP_RAILWAY:
 

	
 
		if (ti.map5 & RAIL_TYPE_SPECIAL)
 
			return CMD_ERROR;
 
			if (!IsPlainRailTile(tile))
 
				return CMD_ERROR;
 

	
 
		if (!(ti.map5 & rail_bit))
 
			return CMD_ERROR;
 
			/* See if the track to remove is actually there */
 
			if (!(GetTrackBits(tile) & trackbit))
 
				return CMD_ERROR;
 

	
 
		// don't allow remove if there are signals on the track
 
		if (ti.map5 & RAIL_TYPE_SIGNALS) {
 
			if (_map3_lo[tile] & _signals_table_both[p2])
 
				return CMD_ERROR;
 
		}
 
			/* don't allow remove if there are signals on the track */
 
			if (HasSignalOnTrack(tile, track))
 
					return CMD_ERROR;
 

	
 
			if (!(flags & DC_EXEC))
 
				return _price.remove_rail;
 

	
 
			/* We remove the trackbit here. */
 
			_map5[tile] &= ~trackbit;
 

	
 
		if (!(flags & DC_EXEC))
 
			return _price.remove_rail;
 

	
 
		if ( (_map5[tile] ^= rail_bit) == 0) {
 
			DoClearSquare(tile);
 
			goto skip_mark_dirty;
 
		}
 
			if (GetTrackBits(tile)  == 0) {
 
				/* The tile has no tracks left, it is no longer a rail tile */
 
				DoClearSquare(tile);
 
				/* XXX: This is an optimisation, right? Is it really worth the ugly goto? */
 
				goto skip_mark_dirty;
 
			}
 
			break;
 
		default:
 
			assert(0);
 
	}
 

	
 
	/* mark_dirty */
 
@@ -518,7 +500,7 @@ int32 CmdRemoveSingleRail(int x, int y, 
 

	
 
skip_mark_dirty:;
 

	
 
	SetSignalsOnBothDir(tile, (byte)p2);
 
	SetSignalsOnBothDir(tile, track);
 

	
 
	return _price.remove_rail;
 
}
 
@@ -535,30 +517,30 @@ static const struct {
 
	  0,-16,-16,  0,-16,  0,    0,  0,
 
}};
 

	
 
static int32 ValidateAutoDrag(byte *railbit, int x, int y, int ex, int ey)
 
static int32 ValidateAutoDrag(Trackdir *trackdir, int x, int y, int ex, int ey)
 
{
 
	int dx, dy, trdx, trdy;
 

	
 
	if (!ValParamTrackOrientation(*railbit)) return CMD_ERROR;
 
	if (!ValParamTrackOrientation(*trackdir)) return CMD_ERROR;
 

	
 
	// calculate delta x,y from start to end tile
 
	dx = ex - x;
 
	dy = ey - y;
 

	
 
	// calculate delta x,y for the first direction
 
	trdx = _railbit.xinc[*railbit];
 
	trdy = _railbit.yinc[*railbit];
 
	trdx = _railbit.xinc[*trackdir];
 
	trdy = _railbit.yinc[*trackdir];
 

	
 
	if (*railbit & 0x6) {
 
		trdx += _railbit.xinc[*railbit ^ 1];
 
		trdy += _railbit.yinc[*railbit ^ 1];
 
	if (!IsDiagonalTrackdir(*trackdir)) {
 
		trdx += _railbit.xinc[*trackdir ^ 1];
 
		trdy += _railbit.yinc[*trackdir ^ 1];
 
	}
 

	
 
	// validate the direction
 
	while (((trdx <= 0) && (dx > 0)) || ((trdx >= 0) && (dx < 0)) ||
 
	       ((trdy <= 0) && (dy > 0)) || ((trdy >= 0) && (dy < 0))) {
 
		if (!HASBIT(*railbit, 3)) { // first direction is invalid, try the other
 
			SETBIT(*railbit, 3); // reverse the direction
 
		if (!HASBIT(*trackdir, 3)) { // first direction is invalid, try the other
 
			SETBIT(*trackdir, 3); // reverse the direction
 
			trdx = -trdx;
 
			trdy = -trdy;
 
		} else // other direction is invalid too, invalid drag
 
@@ -567,9 +549,9 @@ static int32 ValidateAutoDrag(byte *rail
 

	
 
	// (for diagonal tracks, this is already made sure of by above test), but:
 
	// for non-diagonal tracks, check if the start and end tile are on 1 line
 
	if (*railbit & 0x6) {
 
		trdx = _railbit.xinc[*railbit];
 
		trdy = _railbit.yinc[*railbit];
 
	if (!IsDiagonalTrackdir(*trackdir)) {
 
		trdx = _railbit.xinc[*trackdir];
 
		trdy = _railbit.yinc[*trackdir];
 
		if ((abs(dx) != abs(dy)) && (abs(dx) + abs(trdy) != abs(dy) + abs(trdx)))
 
			return CMD_ERROR;
 
	}
 
@@ -582,31 +564,33 @@ static int32 ValidateAutoDrag(byte *rail
 
 * @param p1 end tile of drag
 
 * @param p2 various bitstuffed elements
 
 * - p2 = (bit 0-3) - railroad type normal/maglev (0 = normal, 1 = mono, 2 = maglev)
 
 * - p2 = (bit 4-6) - track-orientation, valid values: 0-5
 
 * - p2 = (bit 4-6) - track-orientation, valid values: 0-5 (Track enum)
 
 * - p2 = (bit 7)   - 0 = build, 1 = remove tracks
 
 */
 
static int32 CmdRailTrackHelper(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	int ex, ey;
 
	int32 ret, total_cost = 0;
 
	byte railbit = (p2 >> 4) & 7;
 
	Track track = (Track)((p2 >> 4) & 7);
 
	Trackdir trackdir;
 
	byte mode = HASBIT(p2, 7);
 

	
 
	if (!ValParamRailtype(p2 & 0x3) || !ValParamTrackOrientation(railbit)) return CMD_ERROR;
 
	if (!ValParamRailtype(p2 & 0x3) || !ValParamTrackOrientation(track)) return CMD_ERROR;
 
	if (p1 > MapSize()) return CMD_ERROR;
 
	trackdir = TrackToTrackdir(track);
 

	
 
	/* unpack end point */
 
	ex = TileX(p1) * 16;
 
	ey = TileY(p1) * 16;
 
	ex = TileX(p1) * TILE_SIZE;
 
	ey = TileY(p1) * TILE_SIZE;
 

	
 
	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 

	
 
	if (CmdFailed(ValidateAutoDrag(&railbit, x, y, ex, ey))) return CMD_ERROR;
 
	if (CmdFailed(ValidateAutoDrag(&trackdir, x, y, ex, ey))) return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) SndPlayTileFx(SND_20_SPLAT_2, TILE_FROM_XY(x,y));
 

	
 
	for(;;) {
 
		ret = DoCommand(x, y, p2 & 0x3, railbit & 7, flags, (mode == 0) ? CMD_BUILD_SINGLE_RAIL : CMD_REMOVE_SINGLE_RAIL);
 
		ret = DoCommand(x, y, p2 & 0x3, TrackdirToTrack(trackdir), flags, (mode == 0) ? CMD_BUILD_SINGLE_RAIL : CMD_REMOVE_SINGLE_RAIL);
 

	
 
		if (CmdFailed(ret)) {
 
			if ((_error_message != STR_1007_ALREADY_BUILT) && (mode == 0))
 
@@ -617,11 +601,11 @@ static int32 CmdRailTrackHelper(int x, i
 
		if (x == ex && y == ey)
 
			break;
 

	
 
		x += _railbit.xinc[railbit];
 
		y += _railbit.yinc[railbit];
 
		x += _railbit.xinc[trackdir];
 
		y += _railbit.yinc[trackdir];
 

	
 
		// toggle railbit for the non-diagonal tracks
 
		if (railbit & 0x6) railbit ^= 1;
 
		if (!IsDiagonalTrackdir(trackdir)) trackdir ^= 1;
 
	}
 

	
 
	return (total_cost == 0) ? CMD_ERROR : total_cost;
 
@@ -685,7 +669,7 @@ int32 CmdBuildTrainDepot(int x, int y, u
 
			MP_SETTYPE(MP_RAILWAY) |
 
			MP_MAP3LO | MP_MAPOWNER_CURRENT | MP_MAP5,
 
			p1, /* map3_lo */
 
			p2 | RAIL_TYPE_DEPOT /* map5 */
 
			p2 | RAIL_TYPE_DEPOT_WAYPOINT /* map5 */
 
		);
 

	
 
		d->xy = tile;
 
@@ -702,59 +686,55 @@ int32 CmdBuildTrainDepot(int x, int y, u
 
 * pre/exit/combo-signals, and what-else not
 
 * @param x,y coordinates where signals is being built
 
 * @param p1 various bitstuffed elements
 
 * - p1 = (bit 0-2) - track-orientation, valid values: 0-5
 
 * - p1 = (bit 0-2) - track-orientation, valid values: 0-5 (Track enum)
 
 * - p1 = (bit 3)   - choose semaphores/signals or cycle normal/pre/exit/combo depending on context
 
 * @param p2 used for CmdBuildManySignals() to copy style of first signal
 
 * @param p2 used for CmdBuildManySignals() to copy direction of first signal
 
 * TODO: p2 should be replaced by two bits for "along" and "against" the track.
 
 */
 
int32 CmdBuildSingleSignal(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	TileIndex tile = TILE_FROM_XY(x, y);
 
	bool semaphore;
 
	bool pre_signal;
 
	uint track = p1 & 0x7;
 
	Track track = (Track)(p1 & 0x7);
 
	byte m5;
 
	int32 cost;
 

	
 
	// Same bit, used in different contexts
 
	semaphore = pre_signal = HASBIT(p1, 3);
 

	
 
	if (!ValParamTrackOrientation(track) || !IsTileType(tile, MP_RAILWAY) || !EnsureNoVehicle(tile))
 
		return CMD_ERROR;
 

	
 
	/* Protect against invalid signal copying */
 
	if (p2 != 0 && (p2 & _signals_table_both[track]) == 0) return CMD_ERROR;
 
	if (p2 != 0 && (p2 & SignalOnTrack(track)) == 0) return CMD_ERROR;
 

	
 
	m5 = _map5[tile];
 

	
 
	/* You can't build signals in a depot, and the selected track must exist */
 
	if (m5 & 0x80 || !HASBIT(m5, track)) return CMD_ERROR;
 
	/* You can only build signals on plain rail tiles, and the selected track must exist */
 
	if (!IsPlainRailTile(tile) || !HasTrack(tile, track)) return CMD_ERROR;
 

	
 
	if (!CheckTileOwnership(tile)) return CMD_ERROR;
 

	
 
	_error_message = STR_1005_NO_SUITABLE_RAILROAD_TRACK;
 

	
 
	{
 
		byte m = m5 & RAIL_BIT_MASK;
 
		if (m != RAIL_BIT_DIAG1 &&
 
				m != RAIL_BIT_DIAG2 &&
 
				m != RAIL_BIT_UPPER &&
 
				m != RAIL_BIT_LOWER &&
 
				m != RAIL_BIT_LEFT &&
 
				m != RAIL_BIT_RIGHT &&
 
				m != (RAIL_BIT_UPPER | RAIL_BIT_LOWER) &&
 
				m != (RAIL_BIT_LEFT | RAIL_BIT_RIGHT))
 
 		/* See if this is a valid track combination for signals, (ie, no overlap) */
 
 		TrackBits trackbits = GetTrackBits(tile);
 
		if (KILL_FIRST_BIT(trackbits) != 0 && /* More than one track present */
 
				trackbits != (TRACK_BIT_UPPER | TRACK_BIT_LOWER) && /* Horizontal parallel, non-intersecting tracks */
 
				trackbits != (TRACK_BIT_LEFT | TRACK_BIT_RIGHT) /* Vertical parallel, non-intersecting tracks */
 
		)
 
			return CMD_ERROR;
 
	}
 

	
 
	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 

	
 
	// Same bit, used in different contexts
 
	semaphore = pre_signal = HASBIT(p1, 3);
 

	
 
	if ((_map3_lo[tile] & _signals_table_both[track]) == 0) {
 
	if (!HasSignalOnTrack(tile, track)) {
 
		// build new signals
 
		cost = _price.build_signals;
 
	} else {
 
		if (p2 != 0 &&
 
				((semaphore && !HASBIT(_map3_hi[tile], 2)) ||
 
				(!semaphore && HASBIT(_map3_hi[tile], 2)))) {
 
		if (p2 != 0 && semaphore != HasSemaphores(tile, track)) {
 
			// convert signals <-> semaphores
 
			cost = _price.build_signals + _price.remove_signals;
 
		} else {
 
@@ -764,7 +744,7 @@ int32 CmdBuildSingleSignal(int x, int y,
 
	}
 

	
 
	if (flags & DC_EXEC) {
 
		if (!(m5 & RAIL_TYPE_SIGNALS)) {
 
		if (GetRailTileType(tile) != RAIL_TYPE_SIGNALS) {
 
			// there are no signals at all on this tile yet
 
			_map5[tile] |= RAIL_TYPE_SIGNALS; // change into signals
 
			_map2[tile] |= 0xF0;              // all signals are on
 
@@ -773,20 +753,21 @@ int32 CmdBuildSingleSignal(int x, int y,
 
		}
 

	
 
		if (p2 == 0) {
 
			if ((_map3_lo[tile] & _signals_table_both[track]) == 0) {
 
			if (!HasSignalOnTrack(tile, track)) {
 
				// build new signals
 
				_map3_lo[tile] |= _signals_table_both[track];
 
				_map3_lo[tile] |= SignalOnTrack(track);
 
			} else {
 
				if (pre_signal) {
 
					// cycle between normal -> pre -> exit -> combo -> ...
 
					byte type = (_map3_hi[tile] + 1) & 0x03;
 
					byte type = (GetSignalType(tile, track) + 1) & 0x03;
 
					_map3_hi[tile] &= ~0x03;
 
					_map3_hi[tile] |= type;
 
				} else {
 
					// cycle between two-way -> one-way -> one-way -> ...
 
					/* TODO: Rewrite switch into something more general */
 
					switch (track) {
 
						case 3:
 
						case 5: {
 
						case TRACK_LOWER:
 
						case TRACK_RIGHT: {
 
							byte signal = (_map3_lo[tile] - 0x10) & 0x30;
 
							if (signal == 0) signal = 0x30;
 
							_map3_lo[tile] &= ~0x30;
 
@@ -806,9 +787,9 @@ int32 CmdBuildSingleSignal(int x, int y,
 
			}
 
		} else {
 
			/* If CmdBuildManySignals is called with copying signals, just copy the
 
			 * style of the first signal given as parameter by CmdBuildManySignals */
 
			_map3_lo[tile] &= ~_signals_table_both[track];
 
			_map3_lo[tile] |= p2 & _signals_table_both[track];
 
			 * direction of the first signal given as parameter by CmdBuildManySignals */
 
			_map3_lo[tile] &= ~SignalOnTrack(track);
 
			_map3_lo[tile] |= p2 & SignalOnTrack(track);
 
			// convert between signal<->semaphores when dragging
 
			if (semaphore)
 
				SETBIT(_map3_hi[tile], 2);
 
@@ -829,7 +810,7 @@ int32 CmdBuildSingleSignal(int x, int y,
 
 * @param p2 various bitstuffed elements
 
 * - p2 = (bit  0)    - 0 = build, 1 = remove signals
 
 * - p2 = (bit  3)    - 0 = signals, 1 = semaphores
 
 * - p2 = (bit  4- 6) - track-orientation, valid values: 0-5
 
 * - p2 = (bit  4- 6) - track-orientation, valid values: 0-5 (Track enum)
 
 * - p2 = (bit 24-31) - user defined signals_density
 
 */
 
static int32 CmdSignalTrackHelper(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 
@@ -841,8 +822,9 @@ static int32 CmdSignalTrackHelper(int x,
 
	bool error = true;
 

	
 
	int mode = p2 & 0x1;
 
	Track track = (p2 >> 4) & 7;
 
	Trackdir trackdir = TrackToTrackdir(track);
 
	byte semaphores = (HASBIT(p2, 3)) ? 8 : 0;
 
	byte railbit = (p2 >> 4) & 0x7;
 
	byte signal_density = (p2 >> 24);
 

	
 
	if (p1 > MapSize()) return CMD_ERROR;
 
@@ -852,37 +834,40 @@ static int32 CmdSignalTrackHelper(int x,
 

	
 
	/* for vertical/horizontal tracks, double the given signals density
 
	* since the original amount will be too dense (shorter tracks) */
 
	if (railbit & 0x6) signal_density *= 2;
 
	if (!IsDiagonalTrack(track))
 
		signal_density *= 2;
 

	
 
	// unpack end tile
 
	ex = TileX(p1) * 16;
 
	ey = TileY(p1) * 16;
 
	ex = TileX(p1) * TILE_SIZE;
 
	ey = TileY(p1) * TILE_SIZE;
 

	
 
	if (CmdFailed(ValidateAutoDrag(&railbit, x, y, ex, ey))) return CMD_ERROR;
 
	if (CmdFailed(ValidateAutoDrag(&trackdir, x, y, ex, ey))) return CMD_ERROR;
 

	
 
	track = TrackdirToTrack(trackdir); /* trackdir might have changed, keep track in sync */
 

	
 
	// copy the signal-style of the first rail-piece if existing
 
	m5 = _map5[tile];
 
	if (!(m5 & RAIL_TYPE_SPECIAL) && (m5 & RAIL_BIT_MASK) && (m5 & RAIL_TYPE_SIGNALS)) {
 
		signals = _map3_lo[tile] & _signals_table_both[railbit];
 
		if (signals == 0) signals = _signals_table_both[railbit];
 
	if (GetRailTileType(tile) == RAIL_TYPE_SIGNALS && GetTrackBits(tile) != 0) { /* XXX: GetTrackBits check useless? */
 
		signals = _map3_lo[tile] & SignalOnTrack(track);
 
		if (signals == 0) signals = SignalOnTrack(track); /* Can this actually occur? */
 

	
 
		semaphores = (_map3_hi[tile] & ~3) ? 8 : 0; // copy signal/semaphores style (independent of CTRL)
 
		semaphores = (HasSemaphores(tile, track) ? 8 : 0); // copy signal/semaphores style (independent of CTRL)
 
	} else // no signals exist, drag a two-way signal stretch
 
		signals = _signals_table_both[railbit];
 
		signals = SignalOnTrack(track);
 

	
 
	/* signal_density_ctr	- amount of tiles already processed
 
	 * signals_density		- patch setting to put signal on every Nth tile (double space on |, -- tracks)
 
	/* signal_ctr       	- amount of tiles already processed
 
	 * signals_density    - patch setting to put signal on every Nth tile (double space on |, -- tracks)
 
	 **********
 
	 * railbit		- direction of autorail
 
	 * trackdir		- trackdir to build with autorail
 
	 * semaphores	- semaphores or signals
 
	 * signals		- is there a signal/semaphore on the first tile, copy its style (two-way/single-way)
 
									and convert all others to semaphore/signal
 
	 * signals    - is there a signal/semaphore on the first tile, copy its style (two-way/single-way)
 
	                and convert all others to semaphore/signal
 
	 * mode				- 1 remove signals, 0 build signals */
 
	signal_ctr = total_cost = 0;
 
	for (;;) {
 
		// only build/remove signals with the specified density
 
		if ((signal_ctr %	signal_density) == 0 ) {
 
			ret = DoCommand(x, y, (railbit & 7) | semaphores, signals, flags, (mode == 1) ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS);
 
			ret = DoCommand(x, y, TrackdirToTrack(trackdir) | semaphores, signals, flags, (mode == 1) ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS);
 

	
 
			/* Abort placement for any other error than NOT_SUITABLE_TRACK
 
			 * This includes vehicles on track, competitor's tracks, etc. */
 
@@ -896,12 +881,12 @@ static int32 CmdSignalTrackHelper(int x,
 

	
 
		if (ex == x && ey == y) break; // reached end of drag
 

	
 
		x += _railbit.xinc[railbit];
 
		y += _railbit.yinc[railbit];
 
		x += _railbit.xinc[trackdir];
 
		y += _railbit.yinc[trackdir];
 
		signal_ctr++;
 

	
 
		// toggle railbit for the non-diagonal tracks (|, -- tracks)
 
		if (railbit & 0x6) railbit ^= 1;
 
		if (!IsDiagonalTrackdir(trackdir)) trackdir ^= 1;
 
	}
 

	
 
	return (error) ? CMD_ERROR : total_cost;
 
@@ -918,18 +903,17 @@ int32 CmdBuildSignalTrack(int x, int y, 
 

	
 
/** Remove signals
 
 * @param x,y coordinates where signal is being deleted from
 
 * @param p1 track combination to remove signal from
 
 * @param p1 track to remove signal from (Track enum)
 
 */
 
int32 CmdRemoveSingleSignal(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	TileIndex tile = TILE_FROM_XY(x, y);
 
	uint track = p1 & 0x7;
 
	Track track = (Track)(p1 & 0x7);
 

	
 
	if (!ValParamTrackOrientation(track) || !IsTileType(tile, MP_RAILWAY) || !EnsureNoVehicle(tile))
 
		return CMD_ERROR;
 

	
 
	if ((_map5[tile] & RAIL_TYPE_MASK) != RAIL_TYPE_SIGNALS ||
 
			(_map3_lo[tile] & _signals_table_both[track]) == 0) // signals on track?
 
	if (!HasSignalOnTrack(tile, track)) // no signals on track?
 
		return CMD_ERROR;
 

	
 
	/* Only water can remove signals from anyone */
 
@@ -939,7 +923,7 @@ int32 CmdRemoveSingleSignal(int x, int y
 

	
 
	/* Do it? */
 
	if (flags & DC_EXEC) {
 
		_map3_lo[tile] &= ~_signals_table_both[track];
 
		_map3_lo[tile] &= ~SignalOnTrack(track);
 

	
 
		/* removed last signal from tile? */
 
		if ((_map3_lo[tile] & 0xF0) == 0) {
 
@@ -973,7 +957,7 @@ static int32 DoConvertRail(uint tile, ui
 
		return CMD_ERROR;
 

	
 
	// tile is already of requested type?
 
	if ( (uint)(_map3_lo[tile] & 0xF) == totype)
 
	if ( GetRailType(tile) == totype)
 
		return CMD_ERROR;
 

	
 
	// change type.
 
@@ -982,7 +966,7 @@ static int32 DoConvertRail(uint tile, ui
 
		MarkTileDirtyByTile(tile);
 
	}
 

	
 
	return _price.build_rail >> 1;
 
	return _price.build_rail / 2;
 
}
 

	
 
extern int32 DoConvertStationRail(uint tile, uint totype, bool exec);
 
@@ -1006,16 +990,16 @@ int32 CmdConvertRail(int ex, int ey, uin
 
	if (p1 > MapSize()) return CMD_ERROR;
 

	
 
	// make sure sx,sy are smaller than ex,ey
 
	sx = TileX(p1) * 16;
 
	sy = TileY(p1) * 16;
 
	sx = TileX(p1) * TILE_SIZE;
 
	sy = TileY(p1) * TILE_SIZE;
 
	if (ex < sx) intswap(ex, sx);
 
	if (ey < sy) intswap(ey, sy);
 

	
 
	money = GetAvailableMoneyForCommand();
 
	cost = 0;
 

	
 
	for (x = sx; x <= ex; x += 16) {
 
		for (y = sy; y <= ey; y += 16) {
 
	for (x = sx; x <= ex; x += TILE_SIZE) {
 
		for (y = sy; y <= ey; y += TILE_SIZE) {
 
			TileIndex tile = TILE_FROM_XY(x,y);
 
			DoConvertRailProc *proc;
 

	
 
@@ -1048,7 +1032,7 @@ static int32 RemoveTrainDepot(uint tile,
 
		return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) {
 
		int track = _map5[tile] & RAIL_DEPOT_TRACK_MASK;
 
		int track = TrackdirToTrack(DiagdirToDiagTrackdir(GetDepotDirection(tile, TRANSPORT_RAIL)));
 

	
 
		DoDeleteDepot(tile);
 
		SetSignalsOnBothDir(tile, track);
 
@@ -1077,7 +1061,7 @@ static int32 ClearTile_Track(TileIndex t
 

	
 
	cost = 0;
 

	
 
	switch (m5 & RAIL_TYPE_MASK) {
 
	switch (GetRailTileType(tile)) {
 
		case RAIL_TYPE_SIGNALS:
 
			if (_map3_lo[tile] & _signals_table_both[0]) {
 
				ret = DoCommandByTile(tile, 0, 0, flags, CMD_REMOVE_SIGNALS);
 
@@ -1090,7 +1074,7 @@ static int32 ClearTile_Track(TileIndex t
 
				cost += ret;
 
			}
 

	
 
			m5 &= RAIL_BIT_MASK;
 
			m5 &= TRACK_BIT_MASK;
 
			if (!(flags & DC_EXEC)) {
 
				for (; m5 != 0; m5 >>= 1) if (m5 & 1) cost += _price.remove_rail;
 
				return cost;
 
@@ -1110,7 +1094,7 @@ static int32 ClearTile_Track(TileIndex t
 
			return cost;
 
		}
 

	
 
		case RAIL_TYPE_DEPOT:
 
		case RAIL_TYPE_DEPOT_WAYPOINT:
 
			switch (m5 & RAIL_SUBTYPE_MASK) {
 
				case RAIL_SUBTYPE_DEPOT:
 
					return RemoveTrainDepot(tile, flags);
 
@@ -1334,28 +1318,28 @@ static void DrawTile_Track(TileInfo *ti)
 
	if (!(m5 & RAIL_TYPE_SPECIAL)) {
 
		bool special;
 

	
 
		m5 &= RAIL_BIT_MASK;
 
		m5 &= TRACK_BIT_MASK;
 

	
 
		special = false;
 

	
 
		// select the sprite to use based on the map5 byte.
 
		(image = 0x3F3, m5 == RAIL_BIT_DIAG2) ||
 
		(image++,				m5 == RAIL_BIT_DIAG1) ||
 
		(image++,				m5 == RAIL_BIT_UPPER) ||
 
		(image++,				m5 == RAIL_BIT_LOWER) ||
 
		(image++,				m5 == RAIL_BIT_RIGHT) ||
 
		(image++,				m5 == RAIL_BIT_LEFT) ||
 
		(image++,				m5 == (RAIL_BIT_DIAG1|RAIL_BIT_DIAG2)) ||
 
		(image = 0x3F3, m5 == TRACK_BIT_DIAG2) ||
 
		(image++,				m5 == TRACK_BIT_DIAG1) ||
 
		(image++,				m5 == TRACK_BIT_UPPER) ||
 
		(image++,				m5 == TRACK_BIT_LOWER) ||
 
		(image++,				m5 == TRACK_BIT_RIGHT) ||
 
		(image++,				m5 == TRACK_BIT_LEFT) ||
 
		(image++,				m5 == (TRACK_BIT_DIAG1|TRACK_BIT_DIAG2)) ||
 

	
 
		(image = 0x40B, m5 == (RAIL_BIT_UPPER|RAIL_BIT_LOWER)) ||
 
		(image++,				m5 == (RAIL_BIT_LEFT|RAIL_BIT_RIGHT)) ||
 
		(image = 0x40B, m5 == (TRACK_BIT_UPPER|TRACK_BIT_LOWER)) ||
 
		(image++,				m5 == (TRACK_BIT_LEFT|TRACK_BIT_RIGHT)) ||
 

	
 
		(special=true, false) ||
 

	
 
		(image = 0x3FA, !(m5 & (RAIL_BIT_RIGHT|RAIL_BIT_UPPER|RAIL_BIT_DIAG1))) ||
 
		(image++,				!(m5 & (RAIL_BIT_LEFT|RAIL_BIT_LOWER|RAIL_BIT_DIAG1))) ||
 
		(image++,				!(m5 & (RAIL_BIT_LEFT|RAIL_BIT_UPPER|RAIL_BIT_DIAG2))) ||
 
		(image++,				!(m5 & (RAIL_BIT_RIGHT|RAIL_BIT_LOWER|RAIL_BIT_DIAG2))) ||
 
		(image = 0x3FA, !(m5 & (TRACK_BIT_RIGHT|TRACK_BIT_UPPER|TRACK_BIT_DIAG1))) ||
 
		(image++,				!(m5 & (TRACK_BIT_LEFT|TRACK_BIT_LOWER|TRACK_BIT_DIAG1))) ||
 
		(image++,				!(m5 & (TRACK_BIT_LEFT|TRACK_BIT_UPPER|TRACK_BIT_DIAG2))) ||
 
		(image++,				!(m5 & (TRACK_BIT_RIGHT|TRACK_BIT_LOWER|TRACK_BIT_DIAG2))) ||
 
		(image++, true);
 

	
 
		if (ti->tileh != 0) {
 
@@ -1374,12 +1358,12 @@ static void DrawTile_Track(TileInfo *ti)
 
		DrawGroundSprite(image + tracktype_offs);
 

	
 
		if (special) {
 
			if (m5 & RAIL_BIT_DIAG1) DrawGroundSprite(0x3ED + tracktype_offs);
 
			if (m5 & RAIL_BIT_DIAG2) DrawGroundSprite(0x3EE + tracktype_offs);
 
			if (m5 & RAIL_BIT_UPPER) DrawGroundSprite(0x3EF + tracktype_offs);
 
			if (m5 & RAIL_BIT_LOWER) DrawGroundSprite(0x3F0 + tracktype_offs);
 
			if (m5 & RAIL_BIT_LEFT)  DrawGroundSprite(0x3F2 + tracktype_offs);
 
			if (m5 & RAIL_BIT_RIGHT) DrawGroundSprite(0x3F1 + tracktype_offs);
 
			if (m5 & TRACK_BIT_DIAG1) DrawGroundSprite(0x3ED + tracktype_offs);
 
			if (m5 & TRACK_BIT_DIAG2) DrawGroundSprite(0x3EE + tracktype_offs);
 
			if (m5 & TRACK_BIT_UPPER) DrawGroundSprite(0x3EF + tracktype_offs);
 
			if (m5 & TRACK_BIT_LOWER) DrawGroundSprite(0x3F0 + tracktype_offs);
 
			if (m5 & TRACK_BIT_LEFT)  DrawGroundSprite(0x3F2 + tracktype_offs);
 
			if (m5 & TRACK_BIT_RIGHT) DrawGroundSprite(0x3F1 + tracktype_offs);
 
		}
 

	
 
		if (_display_opt & DO_FULL_DETAIL) {
 
@@ -1399,21 +1383,21 @@ static void DrawTile_Track(TileInfo *ti)
 
#define ISON_SIGNAL(x) (m23 & (byte)(0x10 << (x)))
 
#define MAYBE_DRAW_SIGNAL(x,y,z) if (HAS_SIGNAL(x)) DrawSignalHelper(ti, ISON_SIGNAL(x), ((y-0x4FB) << 4)|(z))
 

	
 
		if (!(m5 & RAIL_BIT_DIAG2)) {
 
			if (!(m5 & RAIL_BIT_DIAG1)) {
 
				if (m5 & RAIL_BIT_LEFT) {
 
		if (!(m5 & TRACK_BIT_DIAG2)) {
 
			if (!(m5 & TRACK_BIT_DIAG1)) {
 
				if (m5 & TRACK_BIT_LEFT) {
 
					MAYBE_DRAW_SIGNAL(2, 0x509, 0);
 
					MAYBE_DRAW_SIGNAL(3, 0x507, 1);
 
				}
 
				if (m5 & RAIL_BIT_RIGHT) {
 
				if (m5 & TRACK_BIT_RIGHT) {
 
					MAYBE_DRAW_SIGNAL(0, 0x509, 2);
 
					MAYBE_DRAW_SIGNAL(1, 0x507, 3);
 
				}
 
				if (m5 & RAIL_BIT_UPPER) {
 
				if (m5 & TRACK_BIT_UPPER) {
 
					MAYBE_DRAW_SIGNAL(3, 0x505, 4);
 
					MAYBE_DRAW_SIGNAL(2, 0x503, 5);
 
				}
 
				if (m5 & RAIL_BIT_LOWER) {
 
				if (m5 & TRACK_BIT_LOWER) {
 
					MAYBE_DRAW_SIGNAL(1, 0x505, 6);
 
					MAYBE_DRAW_SIGNAL(0, 0x503, 7);
 
				}
 
@@ -1431,8 +1415,11 @@ static void DrawTile_Track(TileInfo *ti)
 
		const DrawTrackSeqStruct *drss;
 
		byte type = m5 & 0x3F; // 0-3: depots, 4-5: waypoints
 

	
 
		if (!(m5 & (RAIL_TYPE_MASK&~RAIL_TYPE_SPECIAL)))
 
			return;
 
		if (!(m5 & (RAIL_TILE_TYPE_MASK&~RAIL_TYPE_SPECIAL)))
 
			/* XXX: There used to be "return;" here, but since I could not find out
 
			 * why this would ever occur, I put assert(0) here. Let's see if someone
 
			 * complains about it. If not, we'll remove this check. (Matthijs). */
 
			 assert(0);
 

	
 
		if (ti->tileh != 0) { DrawFoundation(ti, ti->tileh); }
 

	
 
@@ -1551,32 +1538,28 @@ static bool SetSignalsEnumProc(uint tile
 
{
 
	// the tile has signals?
 
	if (IsTileType(tile, MP_RAILWAY)) {
 
		if ((_map5[tile]&RAIL_TYPE_MASK) == RAIL_TYPE_SIGNALS) {
 
			if ((_map3_lo[tile] & _signals_table_both[track]) != 0) {
 

	
 
				// is the signal pointing in to the segment existing?
 
				if ((_map3_lo[tile] & _signals_table[track]) != 0) {
 
					// yes, add the signal to the list of signals
 
					if (ssd->cur != NUM_SSD_ENTRY) {
 
						ssd->tile[ssd->cur] = tile; // remember the tile index
 
						ssd->bit[ssd->cur] = track; // and the controlling bit number
 
						ssd->cur++;
 
					}
 

	
 
					// remember if this block has a presignal.
 
					ssd->has_presignal |= (_map3_hi[tile]&1);
 
		if (HasSignalOnTrack(tile, TrackdirToTrack(track))) {
 
			if ((_map3_lo[tile] & _signals_table[track]) != 0) {
 
				// yes, add the signal to the list of signals
 
				if (ssd->cur != NUM_SSD_ENTRY) {
 
					ssd->tile[ssd->cur] = tile; // remember the tile index
 
					ssd->bit[ssd->cur] = track; // and the controlling bit number
 
					ssd->cur++;
 
				}
 

	
 
				// is this an exit signal that points out from the segment?
 
				if ((_map3_hi[tile]&2) && _map3_lo[tile]&_signals_table_other[track]) {
 
					ssd->presignal_exits++;
 
					if ((_map2[tile]&_signals_table_other[track]) != 0)
 
						ssd->presignal_exits_free++;
 
				}
 
				// remember if this block has a presignal.
 
				ssd->has_presignal |= (_map3_hi[tile]&1);
 
			}
 

	
 
				return true;
 
			// is this an exit signal that points out from the segment?
 
			if ((_map3_hi[tile]&2) && _map3_lo[tile]&_signals_table_other[track]) {
 
				ssd->presignal_exits++;
 
				if ((_map2[tile]&_signals_table_other[track]) != 0)
 
					ssd->presignal_exits_free++;
 
			}
 
		} else if (IsRailDepot(_map5[tile]))
 

	
 
			return true;
 
		} else if (IsTileDepotType(tile, TRANSPORT_RAIL))
 
			return true; // don't look further if the tile is a depot
 
	}
 
	return false;
 
@@ -1891,44 +1874,44 @@ static void TileLoop_Track(uint tile)
 

	
 
	if (m2 != RAIL_GROUND_BROWN) { /* wait until bottom is green */
 
		/* determine direction of fence */
 
		rail = _map5[tile] & RAIL_BIT_MASK;
 
		rail = _map5[tile] & TRACK_BIT_MASK;
 

	
 
		if (rail == RAIL_BIT_UPPER) {
 
		if (rail == TRACK_BIT_UPPER) {
 
			a2 = RAIL_GROUND_FENCE_HORIZ1;
 
		} else if (rail == RAIL_BIT_LOWER) {
 
		} else if (rail == TRACK_BIT_LOWER) {
 
			a2 = RAIL_GROUND_FENCE_HORIZ2;
 
		} else if (rail == RAIL_BIT_LEFT) {
 
		} else if (rail == TRACK_BIT_LEFT) {
 
			a2 = RAIL_GROUND_FENCE_VERT1;
 
		} else if (rail == RAIL_BIT_RIGHT) {
 
		} else if (rail == TRACK_BIT_RIGHT) {
 
			a2 = RAIL_GROUND_FENCE_VERT2;
 
		} else {
 
			owner = GetTileOwner(tile);
 

	
 
			if ( (!(rail&(RAIL_BIT_DIAG2|RAIL_BIT_UPPER|RAIL_BIT_LEFT)) && (rail&RAIL_BIT_DIAG1)) || rail==(RAIL_BIT_LOWER|RAIL_BIT_RIGHT)) {
 
			if ( (!(rail&(TRACK_BIT_DIAG2|TRACK_BIT_UPPER|TRACK_BIT_LEFT)) && (rail&TRACK_BIT_DIAG1)) || rail==(TRACK_BIT_LOWER|TRACK_BIT_RIGHT)) {
 
				if (!IsTileType(tile + TILE_XY(0,-1), MP_RAILWAY) ||
 
						!IsTileOwner(tile + TILE_XY(0, -1), owner) ||
 
						(_map5[tile + TILE_XY(0,-1)]==RAIL_BIT_UPPER || _map5[tile + TILE_XY(0,-1)]==RAIL_BIT_LEFT))
 
						(_map5[tile + TILE_XY(0,-1)]==TRACK_BIT_UPPER || _map5[tile + TILE_XY(0,-1)]==TRACK_BIT_LEFT))
 
							a2 = RAIL_GROUND_FENCE_NW;
 
			}
 

	
 
			if ( (!(rail&(RAIL_BIT_DIAG2|RAIL_BIT_LOWER|RAIL_BIT_RIGHT)) && (rail&RAIL_BIT_DIAG1)) || rail==(RAIL_BIT_UPPER|RAIL_BIT_LEFT)) {
 
			if ( (!(rail&(TRACK_BIT_DIAG2|TRACK_BIT_LOWER|TRACK_BIT_RIGHT)) && (rail&TRACK_BIT_DIAG1)) || rail==(TRACK_BIT_UPPER|TRACK_BIT_LEFT)) {
 
				if (!IsTileType(tile + TILE_XY(0,1), MP_RAILWAY) ||
 
						!IsTileOwner(tile + TILE_XY(0, 1), owner) ||
 
						(_map5[tile + TILE_XY(0,1)]==RAIL_BIT_LOWER || _map5[tile + TILE_XY(0,1)]==RAIL_BIT_RIGHT))
 
						(_map5[tile + TILE_XY(0,1)]==TRACK_BIT_LOWER || _map5[tile + TILE_XY(0,1)]==TRACK_BIT_RIGHT))
 
							a2 = (a2 == RAIL_GROUND_FENCE_NW) ? RAIL_GROUND_FENCE_SENW : RAIL_GROUND_FENCE_SE;
 
			}
 

	
 
			if ( (!(rail&(RAIL_BIT_DIAG1|RAIL_BIT_UPPER|RAIL_BIT_RIGHT)) && (rail&RAIL_BIT_DIAG2)) || rail==(RAIL_BIT_LOWER|RAIL_BIT_LEFT)) {
 
			if ( (!(rail&(TRACK_BIT_DIAG1|TRACK_BIT_UPPER|TRACK_BIT_RIGHT)) && (rail&TRACK_BIT_DIAG2)) || rail==(TRACK_BIT_LOWER|TRACK_BIT_LEFT)) {
 
				if (!IsTileType(tile + TILE_XY(-1,0), MP_RAILWAY) ||
 
						!IsTileOwner(tile + TILE_XY(-1, 0), owner) ||
 
						(_map5[tile + TILE_XY(-1,0)]==RAIL_BIT_UPPER || _map5[tile + TILE_XY(-1,0)]==RAIL_BIT_RIGHT))
 
						(_map5[tile + TILE_XY(-1,0)]==TRACK_BIT_UPPER || _map5[tile + TILE_XY(-1,0)]==TRACK_BIT_RIGHT))
 
							a2 = RAIL_GROUND_FENCE_NE;
 
			}
 

	
 
			if ( (!(rail&(RAIL_BIT_DIAG1|RAIL_BIT_LOWER|RAIL_BIT_LEFT)) && (rail&RAIL_BIT_DIAG2)) || rail==(RAIL_BIT_UPPER|RAIL_BIT_RIGHT)) {
 
			if ( (!(rail&(TRACK_BIT_DIAG1|TRACK_BIT_LOWER|TRACK_BIT_LEFT)) && (rail&TRACK_BIT_DIAG2)) || rail==(TRACK_BIT_UPPER|TRACK_BIT_RIGHT)) {
 
				if (!IsTileType(tile + TILE_XY(1,0), MP_RAILWAY) ||
 
						!IsTileOwner(tile + TILE_XY(1, 0), owner) ||
 
						(_map5[tile + TILE_XY(1,0)]==RAIL_BIT_LOWER || _map5[tile + TILE_XY(1,0)]==RAIL_BIT_LEFT))
 
						(_map5[tile + TILE_XY(1,0)]==TRACK_BIT_LOWER || _map5[tile + TILE_XY(1,0)]==TRACK_BIT_LEFT))
 
							a2 = (a2 == RAIL_GROUND_FENCE_NE) ? RAIL_GROUND_FENCE_NESW : RAIL_GROUND_FENCE_SW;
 
			}
 
		}
 
@@ -1990,7 +1973,7 @@ static uint32 GetTileTrackStatus_Track(u
 

	
 
static void ClickTile_Track(uint tile)
 
{
 
	if (IsRailDepot(_map5[tile]))
 
	if (IsTileDepotType(tile, TRANSPORT_RAIL))
 
		ShowTrainDepotWindow(tile);
 
	else if (IsRailWaypoint(_map5[tile]))
 
		ShowRenameWaypointWindow(GetWaypointByTile(tile));
 
@@ -2000,7 +1983,7 @@ static void ClickTile_Track(uint tile)
 
static void GetTileDesc_Track(TileIndex tile, TileDesc *td)
 
{
 
	td->owner = GetTileOwner(tile);
 
	switch (_map5[tile] & RAIL_TYPE_MASK) {
 
	switch (GetRailTileType(tile)) {
 
		case RAIL_TYPE_NORMAL:
 
			td->str = STR_1021_RAILROAD_TRACK;
 
			break;
 
@@ -2017,7 +2000,7 @@ static void GetTileDesc_Track(TileIndex 
 
			break;
 
		}
 

	
 
		case RAIL_TYPE_DEPOT:
 
		case RAIL_TYPE_DEPOT_WAYPOINT:
 
		default:
 
			td->str = ((_map5[tile] & RAIL_SUBTYPE_MASK) == RAIL_SUBTYPE_DEPOT) ?
 
				STR_1023_RAILROAD_TRAIN_DEPOT : STR_LANDINFO_WAYPOINT;
 
@@ -2054,11 +2037,11 @@ static uint32 VehicleEnter_Track(Vehicle
 
	int length;
 

	
 
	// this routine applies only to trains in depot tiles
 
	if (v->type != VEH_Train || !IsRailDepot(_map5[tile]))
 
	if (v->type != VEH_Train || !IsTileDepotType(tile, TRANSPORT_RAIL))
 
		return 0;
 

	
 
	/* depot direction */
 
	dir = _map5[tile] & RAIL_DEPOT_DIR;
 
	dir = GetDepotDirection(tile, TRANSPORT_RAIL);
 

	
 
	/* calculate the point where the following wagon should be activated */
 
	/* this depends on the length of the current vehicle */
road_cmd.c
Show inline comments
 
@@ -9,7 +9,6 @@
 
#include "player.h"
 
#include "town.h"
 
#include "gfx.h"
 
#include "npf.h"
 
#include "sound.h"
 
#include "depot.h"
 

	
roadveh_cmd.c
Show inline comments
 
@@ -317,7 +317,7 @@ static Depot *FindClosestRoadDepot(Vehic
 
	if (_patches.new_pathfinding_all) {
 
		NPFFoundTargetData ftd;
 
		/* See where we are now */
 
		byte trackdir = GetVehicleTrackdir(v);
 
		Trackdir trackdir = GetVehicleTrackdir(v);
 

	
 
		ftd = NPFRouteToDepotBreadthFirst(v->tile, trackdir, TRANSPORT_ROAD, v->owner);
 
		if (ftd.best_bird_dist == 0)
 
@@ -1101,7 +1101,7 @@ static int RoadFindPathToDest(Vehicle *v
 
		byte trackdir;
 

	
 
		NPFFillWithOrderData(&fstd, v);
 
		trackdir = _dir_to_diag_trackdir[enterdir];
 
		trackdir = DiagdirToDiagTrackdir(enterdir);
 
		//debug("Finding path. Enterdir: %d, Trackdir: %d", enterdir, trackdir);
 

	
 
		ftd = NPFRouteToStationOrTile(tile - TileOffsByDir(enterdir), trackdir, &fstd, TRANSPORT_ROAD, v->owner);
ship_cmd.c
Show inline comments
 
@@ -568,7 +568,7 @@ static int ChooseShipTrack(Vehicle *v, u
 
	if (_patches.new_pathfinding_all) {
 
		NPFFindStationOrTileData fstd;
 
		NPFFoundTargetData ftd;
 
		uint src_tile = TILE_ADD(tile, TileOffsByDir(_reverse_dir[enterdir]));
 
		uint src_tile = TILE_ADD(tile, TileOffsByDir(ReverseDiagdir(enterdir)));
 
		byte trackdir = GetVehicleTrackdir(v);
 
		assert (trackdir != 0xFF); /* Check that we are not in a depot */
 

	
 
@@ -594,9 +594,9 @@ static int ChooseShipTrack(Vehicle *v, u
 
		tot_dist = (uint)-1;
 

	
 
		/* Let's find out how far it would be if we would reverse first */
 
		b = GetTileShipTrackStatus(tile2) & _ship_sometracks[_reverse_dir[enterdir]] & v->u.ship.state;
 
		b = GetTileShipTrackStatus(tile2) & _ship_sometracks[ReverseDiagdir(enterdir)] & v->u.ship.state;
 
		if (b != 0) {
 
			dist = FindShipTrack(v, tile2, _reverse_dir[enterdir], b, tile, &track);
 
			dist = FindShipTrack(v, tile2, ReverseDiagdir(enterdir), b, tile, &track);
 
			if (dist != (uint)-1)
 
				tot_dist = dist + 1;
 
		}
station_cmd.c
Show inline comments
 
@@ -18,7 +18,6 @@
 
#include "player.h"
 
#include "airport.h"
 
#include "sprite.h"
 
#include "npf.h"
 
#include "depot.h"
 

	
 
enum {
tile.h
Show inline comments
 
@@ -18,17 +18,30 @@ typedef enum TileType {
 
	MP_UNMOVABLE
 
} TileType;
 

	
 
/* XXX: This should be moved out to a new file (rail.h) along with some other
 
 * cleanups. I'll do that after 0.4) */
 
typedef enum {
 
	RAILTYPE_RAIL   = 0,
 
	RAILTYPE_MONO   = 1,
 
	RAILTYPE_MAGLEV = 2,
 
	RAILTYPE_END,
 
	RAILTYPE_MASK   = 0x3,
 
	INVALID_RAILTYPE = 0xFF,
 
} RailType;
 
/* TODO: Find out values */
 
/* Direction as commonly used in v->direction, 8 way. */
 
typedef enum Directions {
 
	DIR_N   = 0,
 
	DIR_NE  = 1,      /* Northeast, upper right on your monitor */
 
	DIR_E   = 2,
 
	DIR_SE  = 3,
 
	DIR_S   = 4,
 
	DIR_SW  = 5,
 
	DIR_W   = 6,
 
	DIR_NW  = 7,
 
	DIR_END,
 
	INVALID_DIR = 0xFF,
 
} Direction;
 

	
 
/* Direction commonly used as the direction of entering and leaving tiles, 4-way */
 
typedef enum DiagonalDirections {
 
	DIAGDIR_NE  = 0,      /* Northeast, upper right on your monitor */
 
	DIAGDIR_SE  = 1,
 
	DIAGDIR_SW  = 2,
 
	DIAGDIR_NW  = 3,
 
	DIAGDIR_END,
 
	INVALID_DIAGDIR = 0xFF,
 
} DiagDirection;
 

	
 
void SetMapExtraBits(TileIndex tile, byte flags);
 
uint GetMapExtraBits(TileIndex tile);
train_cmd.c
Show inline comments
 
@@ -459,8 +459,8 @@ static int32 CmdBuildRailWagon(uint engi
 
			v->direction = (byte)(dir*2+1);
 
			v->tile = (TileIndex)tile;
 

	
 
			x = TileX(tile) * 16 | _vehicle_initial_x_fract[dir];
 
			y = TileY(tile) * 16 | _vehicle_initial_y_fract[dir];
 
			x = TileX(tile) * TILE_SIZE | _vehicle_initial_x_fract[dir];
 
			y = TileY(tile) * TILE_SIZE | _vehicle_initial_y_fract[dir];
 

	
 
			v->x_pos = x;
 
			v->y_pos = y;
 
@@ -694,6 +694,9 @@ static bool IsTunnelTile(TileIndex tile)
 
}
 

	
 

	
 
/* Check if all the wagons of the given train are in a depot, returns the
 
 * number of cars (including loco) then. If not, sets the error message to
 
 * STR_881A_TRAINS_CAN_ONLY_BE_ALTERED and returns -1 */
 
int CheckTrainStoppedInDepot(const Vehicle *v)
 
{
 
	int count;
 
@@ -1525,7 +1528,7 @@ static bool TrainFindDepotEnumProc(uint 
 

	
 
		// make sure the train doesn't run against a oneway signal
 
		if ((_map5[tile] & 0xC0) == 0x40) {
 
			if (!(_map3_lo[tile] & _signal_along_trackdir[track]) && _map3_lo[tile] & _signal_against_trackdir[track])
 
			if (!(_map3_lo[tile] & SignalAlongTrackdir(track)) && _map3_lo[tile] & SignalAgainstTrackdir(track))
 
				return true;
 
		}
 
	}
 
@@ -1559,10 +1562,10 @@ static TrainFindDepotData FindClosestTra
 
	if (_patches.new_pathfinding_all) {
 
		NPFFoundTargetData ftd;
 
		Vehicle* last = GetLastVehicleInChain(v);
 
		byte trackdir = GetVehicleTrackdir(v);
 
		byte trackdir_rev = REVERSE_TRACKDIR(GetVehicleTrackdir(last));
 

	
 
		assert (trackdir != 0xFF);
 
		Trackdir trackdir = GetVehicleTrackdir(v);
 
		Trackdir trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last));
 

	
 
		assert (trackdir != INVALID_TRACKDIR);
 
		ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, last->tile, trackdir_rev, TRANSPORT_RAIL, v->owner, NPF_INFINITE_PENALTY);
 
		if (ftd.best_bird_dist == 0) {
 
			/* Found target */
 
@@ -1808,14 +1811,14 @@ static bool TrainTrackFollower(uint tile
 
	if (IsTileType(tile, MP_RAILWAY) && (_map5[tile]&0xC0) == 0x40) {
 
		// the tile has a signal
 
		byte m3 = _map3_lo[tile];
 
		if (!(m3 & _signal_along_trackdir[track])) {
 
		if (!(m3 & SignalAlongTrackdir(track))) {
 
			// if one way signal not pointing towards us, stop going in this direction.
 
			if (m3 & _signal_against_trackdir[track])
 
			if (m3 & SignalAgainstTrackdir(track))
 
				return true;
 
		} else if (_map2[tile] & _signal_along_trackdir[track]) {
 
		} else if (_map2[tile] & SignalAlongTrackdir(track)) {
 
			// green signal in our direction. either one way or two way.
 
			*state = true;
 
		} else if (m3 & _signal_against_trackdir[track]) {
 
		} else if (m3 & SignalAgainstTrackdir(track)) {
 
			// two way signal. unless we passed another green signal on the way,
 
			// stop going in this direction.
 
			if (!*state) return true;
 
@@ -1904,26 +1907,25 @@ unsigned int rdtsc()
 

	
 

	
 
/* choose a track */
 
static byte ChooseTrainTrack(Vehicle *v, uint tile, int enterdir, byte trackbits)
 
static byte ChooseTrainTrack(Vehicle *v, uint tile, int enterdir, TrackdirBits trackdirbits)
 
{
 
	TrainTrackFollowerData fd;
 
	int bits = trackbits;
 
	uint best_track;
 
#if PF_BENCHMARK
 
	int time = rdtsc();
 
	static float f;
 
#endif
 

	
 
	assert( (bits & ~0x3F) == 0);
 
	assert( (trackdirbits & ~0x3F) == 0);
 

	
 
	/* quick return in case only one possible track is available */
 
	if (KILL_FIRST_BIT(bits) == 0)
 
		return FIND_FIRST_BIT(bits);
 
	if (KILL_FIRST_BIT(trackdirbits) == 0)
 
		return FIND_FIRST_BIT(trackdirbits);
 

	
 
	if (_patches.new_pathfinding_all) { /* Use a new pathfinding for everything */
 
		NPFFindStationOrTileData fstd;
 
		NPFFoundTargetData ftd;
 
		byte trackdir;
 
		Trackdir trackdir;
 

	
 
		NPFFillWithOrderData(&fstd, v);
 
		/* The enterdir for the new tile, is the exitdir for the old tile */
 
@@ -1936,7 +1938,7 @@ static byte ChooseTrainTrack(Vehicle *v,
 
			/* We are already at our target. Just do something */
 
			//TODO: maybe display error?
 
			//TODO: go straight ahead if possible?
 
			best_track = FIND_FIRST_BIT(bits);
 
			best_track = FIND_FIRST_BIT(trackdirbits);
 
		} else {
 
			/* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains
 
			the direction we need to take to get there, if ftd.best_bird_dist is not 0,
 
@@ -1960,7 +1962,7 @@ static byte ChooseTrainTrack(Vehicle *v,
 

	
 
			if (fd.best_track == 0xff) {
 
				// blaha
 
				best_track = FIND_FIRST_BIT(bits);
 
				best_track = FIND_FIRST_BIT(trackdirbits);
 
			} else {
 
				best_track = fd.best_track & 7;
 
			}
 
@@ -1975,8 +1977,8 @@ static byte ChooseTrainTrack(Vehicle *v,
 
			best_track = (uint)-1;
 

	
 
			do {
 
				i = FIND_FIRST_BIT(bits);
 
				bits = KILL_FIRST_BIT(bits);
 
				i = FIND_FIRST_BIT(trackdirbits);
 
				trackdirbits = KILL_FIRST_BIT(trackdirbits);
 

	
 
				fd.best_bird_dist = (uint)-1;
 
				fd.best_track_dist = (uint)-1;
 
@@ -2016,7 +2018,7 @@ static byte ChooseTrainTrack(Vehicle *v,
 
				best_bird_dist = fd.best_bird_dist;
 
				best_track_dist = fd.best_track_dist;
 
		bad:;
 
			} while (bits != 0);
 
			} while (trackdirbits != 0);
 
	//		printf("Train %d %s\n", v->unitnumber, best_track_dist == -1 ? "NOTFOUND" : "FOUND");
 
			assert(best_track != (uint)-1);
 
		}
 
@@ -2064,7 +2066,7 @@ static bool CheckReverseTrain(Vehicle *v
 
		NPFFillWithOrderData(&fstd, v);
 

	
 
		trackdir = GetVehicleTrackdir(v);
 
		trackdir_rev = REVERSE_TRACKDIR(GetVehicleTrackdir(last));
 
		trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last));
 
		assert(trackdir != 0xff);
 
		assert(trackdir_rev != 0xff);
 

	
 
@@ -2704,7 +2706,7 @@ static void TrainController(Vehicle *v)
 
				if (_patches.new_pathfinding_all && _patches.forbid_90_deg && prev == NULL)
 
					/* We allow wagons to make 90 deg turns, because forbid_90_deg
 
					 * can be switched on halfway a turn */
 
					bits &= ~_track_crosses_tracks[FIND_FIRST_BIT(v->u.rail.track)];
 
					bits &= ~TrackCrossesTracks(FIND_FIRST_BIT(v->u.rail.track));
 

	
 
				if ( bits == 0) {
 
					//debug("%x == 0", bits);
 
@@ -2821,13 +2823,13 @@ red_light: {
 
		 * FIND_FIRST_BIT only handles 6 bits at a time. */
 
		i = FindFirstBit2x64(ts);
 

	
 
		if (!(_map3_lo[gp.new_tile] & _signal_against_trackdir[i])) {
 
		if (!(_map3_lo[gp.new_tile] & SignalAgainstTrackdir(i))) {
 
			v->cur_speed = 0;
 
			v->subspeed = 0;
 
			v->progress = 255-100;
 
			if (++v->load_unload_time_rem < _patches.wait_oneway_signal * 20)
 
				return;
 
		} else if (_map3_lo[gp.new_tile] & _signal_along_trackdir[i]){
 
		} else if (_map3_lo[gp.new_tile] & SignalAlongTrackdir(i)){
 
			v->cur_speed = 0;
 
			v->subspeed = 0;
 
			v->progress = 255-10;
vehicle.c
Show inline comments
 
@@ -15,10 +15,10 @@
 
#include "engine.h"
 
#include "sound.h"
 
#include "debug.h"
 
#include "npf.h"
 
#include "vehicle_gui.h"
 
#include "depot.h"
 
#include "station.h"
 
#include "rail.h"
 

	
 
#define INVALID_COORD (-0x8000)
 
#define GEN_HASH(x,y) (((x & 0x1F80)>>7) + ((y & 0xFC0)))
 
@@ -1752,7 +1752,8 @@ byte GetVehicleTrackdir(const Vehicle* v
 
			return _track_direction_to_trackdir[FIND_FIRST_BIT(v->u.rail.track)][v->direction];
 
			break;
 
		case VEH_Ship:
 
			if (v->u.ship.state == 0x80) /* We'll assume the ship is facing outwards */
 
			if (v->u.ship.state == 0x80)  /* Inside a depot? */
 
				/* We'll assume the ship is facing outwards */
 
				return _dir_to_diag_trackdir[GetDepotDirection(v->tile, TRANSPORT_WATER)]; /* Ship in depot */
 

	
 
			return _track_direction_to_trackdir[FIND_FIRST_BIT(v->u.ship.state)][v->direction];
0 comments (0 inline, 0 general)