summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormatthijs <matthijs@openttd.org>2005-06-16 18:04:02 +0000
committermatthijs <matthijs@openttd.org>2005-06-16 18:04:02 +0000
commit9cb58e0bb3799224f48a6c9e278b288551c59bec (patch)
tree13bfcb2e646ad2b6e44031f7353f93fe0551bc96
parentfc5784a3103d5e4fc0dbfec5f905a6ebbfd9c84b (diff)
downloadopenttd-9cb58e0bb3799224f48a6c9e278b288551c59bec.tar.xz
(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.
-rw-r--r--Makefile1
-rw-r--r--depot.h12
-rw-r--r--map.h7
-rw-r--r--npf.c184
-rw-r--r--npf.h107
-rw-r--r--rail.c93
-rw-r--r--rail.h397
-rw-r--r--rail_cmd.c657
-rw-r--r--road_cmd.c1
-rw-r--r--roadveh_cmd.c4
-rw-r--r--ship_cmd.c6
-rw-r--r--station_cmd.c1
-rw-r--r--tile.h35
-rw-r--r--train_cmd.c52
-rw-r--r--vehicle.c5
15 files changed, 919 insertions, 643 deletions
diff --git a/Makefile b/Makefile
index f154b0690..22cfb5395 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/depot.h b/depot.h
index 05a6df08d..502f4f136 100644
--- a/depot.h
+++ b/depot.h
@@ -89,7 +89,7 @@ static inline bool IsTileDepotType(TileIndex tile, TransportType type)
/**
* 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(TileIndex tile, TransportType type)
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 */
}
}
diff --git a/map.h b/map.h
index 3bf619b24..348e22bc4 100644
--- a/map.h
+++ b/map.h
@@ -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();
diff --git a/npf.c b/npf.c
index f8fb7ed0c..3c9cb08c3 100644
--- a/npf.c
+++ b/npf.c
@@ -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* current, OpenListNode* parent)
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(TileIndex tile, byte trackdir)
/* 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, OpenListNode* current) {
* 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, OpenListNode* current) {
* 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, OpenListNode* current) {
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(AyStarNode* start1, AyStarNode* start2, NPFF
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(AyStarNode* start1, AyStarNode* start2, NPFF
/* 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(AyStarNode* start1, AyStarNode* start2, NPFF
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 NPFRouteToStationOrTileTwoWay(TileIndex tile1, byte trackdir1
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 NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, byte track
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 NPFRouteToDepotTrialError(TileIndex tile, byte trackdir, Tran
/* 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) {
diff --git a/npf.h b/npf.h
index e239c8971..f0d021cc7 100644
--- a/npf.h
+++ b/npf.h
@@ -1,11 +1,11 @@
#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.userdata[NPF_NODE_FLAGS]. Use NPFGetBit()
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 { /* Meant to be stored in AyStar.userpath */
/* 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* node, NPFNodeFlag flag, bool value)
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
diff --git a/rail.c b/rail.c
new file mode 100644
index 000000000..24f383b50
--- /dev/null
+++ b/rail.c
@@ -0,0 +1,93 @@
+#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
+};
diff --git a/rail.h b/rail.h
new file mode 100644
index 000000000..e2d13baa6
--- /dev/null
+++ b/rail.h
@@ -0,0 +1,397 @@
+#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
diff --git a/rail_cmd.c b/rail_cmd.c
index a5c9dc8f3..fddc3a546 100644
--- a/rail_cmd.c
+++ b/rail_cmd.c
@@ -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 */
- 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;
- }
+ /* 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;
- 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);
+ /* Are we really building something new? */
+ if (current == future) {
+ /* Nothing new is being built */
+ _error_message = STR_1007_ALREADY_BUILT;
+ return false;
+ }
- 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][15] = {
// 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,
-
- 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,
-
- 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,
-
- 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_LEFT,
+ TRACK_BIT_LOWER,
+ TRACK_BIT_DIAG2 | 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,
+ 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,
+
+ 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,
+
+ 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,
-
- 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,
-
- 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,
-
- 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_LEFT,
+ TRACK_BIT_LOWER,
+ TRACK_BIT_DIAG2|TRACK_BIT_LEFT|TRACK_BIT_LOWER,
+
+ 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,
+
+ 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,
+
+ 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 bits)
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, uint rail_bits, uint existing, TileInde
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, uint rail_bits, uint existing, TileInde
}
/* 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, uint32 flags, uint32 p1, uint32 p2)
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, uint32 flags, uint32 p1, uint32 p2)
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, uint32 flags, uint32 p1, uint32 p2)
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, uint32 flags, uint32 p1, uint32 p2)
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 = ti.tile;
+ tile = TILE_FROM_XY(x, y);
+ tileh = GetTileSlope(tile, NULL);
- 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;
-
- if (ti.map5 & 0xE0)
- return CMD_ERROR;
-
- if (ti.map5 & 8) {
- m5 = 5;
- if (rail_bit != 1)
+ _map5[tile] = _map5[tile] & 0xC7;
+ break;
+ case MP_STREET:
+ if (!(_map5[tile] & 0xF0))
return CMD_ERROR;
- } else {
- m5 = 10;
- if (rail_bit != 2)
+
+ if (_map5[tile] & 0xE0)
return CMD_ERROR;
- }
- if (!(flags & DC_EXEC))
- return _price.remove_rail;
+ /* 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;
+ }
- _map5[tile] = m5;
- SetTileOwner(tile, _map3_lo[tile]);
- _map2[tile] = 0;
- } else {
- assert(ti.type == MP_RAILWAY);
+ if (!(flags & DC_EXEC))
+ return _price.remove_rail;
- if (ti.map5 & RAIL_TYPE_SPECIAL)
- return CMD_ERROR;
+ _map5[tile] = m5;
+ SetTileOwner(tile, _map3_lo[tile]);
+ _map2[tile] = 0;
+ break;
+ case MP_RAILWAY:
- if (!(ti.map5 & rail_bit))
- return CMD_ERROR;
+ if (!IsPlainRailTile(tile))
+ 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])
+ /* See if the track to remove is actually there */
+ if (!(GetTrackBits(tile) & trackbit))
return CMD_ERROR;
- }
- if (!(flags & DC_EXEC))
- return _price.remove_rail;
+ /* don't allow remove if there are signals on the track */
+ if (HasSignalOnTrack(tile, track))
+ return CMD_ERROR;
- if ( (_map5[tile] ^= rail_bit) == 0) {
- DoClearSquare(tile);
- goto skip_mark_dirty;
- }
+ if (!(flags & DC_EXEC))
+ return _price.remove_rail;
+
+ /* We remove the trackbit here. */
+ _map5[tile] &= ~trackbit;
+
+ 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, uint32 flags, uint32 p1, uint32 p2)
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 *railbit, int x, int y, int ex, int ey)
// (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 *railbit, int x, int y, int ex, int ey)
* @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, int y, uint32 flags, uint32 p1, uint32 p2
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, uint32 flags, uint32 p1, uint32 p2)
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, uint32 flags, uint32 p1, uint32 p2)
* 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, uint32 flags, uint32 p1, uint32 p2)
}
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, uint32 flags, uint32 p1, uint32 p2)
}
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, uint32 flags, uint32 p1, uint32 p2)
}
} 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, uint32 flags, uint32 p1, uint32 p2)
* @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, int y, uint32 flags, uint32 p1, uint32
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, int y, uint32 flags, uint32 p1, uint32
/* 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(&trackdir, x, y, ex, ey))) return CMD_ERROR;
- if (CmdFailed(ValidateAutoDrag(&railbit, 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, int y, uint32 flags, uint32 p1, uint32
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, uint32 flags, uint32 p1, uint32 p2)
/** 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, uint32 flags, uint32 p1, uint32 p2)
/* 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, uint totype, bool exec)
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, uint totype, bool exec)
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, uint32 flags, uint32 p1, uint32 p2)
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, uint32 flags)
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 tile, byte flags)
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 tile, byte flags)
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 tile, byte flags)
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, SetSignalsData *ssd, int track, uint l
{
// 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(uint tile, TransportType mode) {
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 tile, TileDesc *td)
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 *v, uint tile, int x, int y)
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 */
diff --git a/road_cmd.c b/road_cmd.c
index ad59a0936..27818d80c 100644
--- a/road_cmd.c
+++ b/road_cmd.c
@@ -9,7 +9,6 @@
#include "player.h"
#include "town.h"
#include "gfx.h"
-#include "npf.h"
#include "sound.h"
#include "depot.h"
diff --git a/roadveh_cmd.c b/roadveh_cmd.c
index 1c7432786..7cde8e1ed 100644
--- a/roadveh_cmd.c
+++ b/roadveh_cmd.c
@@ -317,7 +317,7 @@ static Depot *FindClosestRoadDepot(Vehicle *v)
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, uint tile, int enterdir)
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);
diff --git a/ship_cmd.c b/ship_cmd.c
index a1c64a3af..98a6f6fb7 100644
--- a/ship_cmd.c
+++ b/ship_cmd.c
@@ -568,7 +568,7 @@ static int ChooseShipTrack(Vehicle *v, uint tile, int enterdir, uint tracks)
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, uint tile, int enterdir, uint tracks)
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;
}
diff --git a/station_cmd.c b/station_cmd.c
index dfc41fbd3..4ff8cfbe5 100644
--- a/station_cmd.c
+++ b/station_cmd.c
@@ -18,7 +18,6 @@
#include "player.h"
#include "airport.h"
#include "sprite.h"
-#include "npf.h"
#include "depot.h"
enum {
diff --git a/tile.h b/tile.h
index 9b0b45dfd..36c07e750 100644
--- a/tile.h
+++ b/tile.h
@@ -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);
diff --git a/train_cmd.c b/train_cmd.c
index 1bb394558..414c34b43 100644
--- a/train_cmd.c
+++ b/train_cmd.c
@@ -459,8 +459,8 @@ static int32 CmdBuildRailWagon(uint engine, uint tile, uint32 flags)
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 tile, TrainFindDepotData *tfdd, int trac
// 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 FindClosestTrainDepot(Vehicle *v)
if (_patches.new_pathfinding_all) {
NPFFoundTargetData ftd;
Vehicle* last = GetLastVehicleInChain(v);
- byte trackdir = GetVehicleTrackdir(v);
- byte trackdir_rev = REVERSE_TRACKDIR(GetVehicleTrackdir(last));
+ Trackdir trackdir = GetVehicleTrackdir(v);
+ Trackdir trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last));
- assert (trackdir != 0xFF);
+ 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, TrainTrackFollowerData *ttfd, int trac
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, uint tile, int enterdir, byte trackbits
/* 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, uint tile, int enterdir, byte trackbits
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, uint tile, int enterdir, byte trackbits
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, uint tile, int enterdir, byte trackbits
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;
diff --git a/vehicle.c b/vehicle.c
index a5d3010b9..76ead42cd 100644
--- a/vehicle.c
+++ b/vehicle.c
@@ -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];