mirror of https://github.com/OpenTTD/OpenTTD
(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.release/0.4.5
parent
fc5784a310
commit
9cb58e0bb3
1
Makefile
1
Makefile
|
@ -648,6 +648,7 @@ C_SOURCES += player_gui.c
|
||||||
C_SOURCES += players.c
|
C_SOURCES += players.c
|
||||||
C_SOURCES += pool.c
|
C_SOURCES += pool.c
|
||||||
C_SOURCES += queue.c
|
C_SOURCES += queue.c
|
||||||
|
C_SOURCES += rail.c
|
||||||
C_SOURCES += rail_cmd.c
|
C_SOURCES += rail_cmd.c
|
||||||
C_SOURCES += rail_gui.c
|
C_SOURCES += rail_gui.c
|
||||||
C_SOURCES += rev.c
|
C_SOURCES += rev.c
|
||||||
|
|
12
depot.h
12
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.
|
* 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));
|
assert(IsTileDepotType(tile, type));
|
||||||
|
|
||||||
|
@ -102,13 +102,13 @@ static inline uint GetDepotDirection(TileIndex tile, TransportType type)
|
||||||
case TRANSPORT_WATER:
|
case TRANSPORT_WATER:
|
||||||
/* Water is stubborn, it stores the directions in a different order. */
|
/* Water is stubborn, it stores the directions in a different order. */
|
||||||
switch (_map5[tile] & 3) {
|
switch (_map5[tile] & 3) {
|
||||||
case 0: return 0;
|
case 0: return DIAGDIR_NE;
|
||||||
case 1: return 2;
|
case 1: return DIAGDIR_SW;
|
||||||
case 2: return 3;
|
case 2: return DIAGDIR_NW;
|
||||||
case 3: return 1;
|
case 3: return DIAGDIR_SE;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return 0; /* Not reached */
|
return INVALID_DIAGDIR; /* Not reached */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
7
map.h
7
map.h
|
@ -48,6 +48,13 @@ enum {
|
||||||
INVALID_TILE = (uint32) -1
|
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)
|
static inline uint TileX(TileIndex tile)
|
||||||
{
|
{
|
||||||
return tile & MapMaxX();
|
return tile & MapMaxX();
|
||||||
|
|
184
npf.c
184
npf.c
|
@ -9,92 +9,8 @@
|
||||||
#include "tile.h"
|
#include "tile.h"
|
||||||
#include "depot.h"
|
#include "depot.h"
|
||||||
|
|
||||||
AyStar _train_find_station;
|
|
||||||
AyStar _train_find_depot;
|
|
||||||
AyStar _road_find_station;
|
|
||||||
AyStar _road_find_depot;
|
|
||||||
AyStar _npf_aystar;
|
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 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
|
* 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) {
|
uint NPFTunnelCost(AyStarNode* current) {
|
||||||
byte exitdir = _trackdir_to_exitdir[current->direction];
|
byte exitdir = _trackdir_to_exitdir[current->direction];
|
||||||
TileIndex tile = current->tile;
|
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
|
/* We just popped out if this tunnel, since were
|
||||||
* facing the tunnel exit */
|
* facing the tunnel exit */
|
||||||
FindLengthOfTunnelResult flotr;
|
FindLengthOfTunnelResult flotr;
|
||||||
flotr = FindLengthOfTunnel(tile, _reverse_dir[exitdir]);
|
flotr = FindLengthOfTunnel(tile, ReverseDiagdir(exitdir));
|
||||||
return flotr.length * NPF_TILE_LENGTH;
|
return flotr.length * NPF_TILE_LENGTH;
|
||||||
//TODO: Penalty for tunnels?
|
//TODO: Penalty for tunnels?
|
||||||
} else {
|
} else {
|
||||||
|
@ -233,13 +149,15 @@ uint NPFSlopeCost(AyStarNode* current) {
|
||||||
int x,y;
|
int x,y;
|
||||||
int8 z1,z2;
|
int8 z1,z2;
|
||||||
|
|
||||||
x = TileX(current->tile) * 16;
|
x = TileX(current->tile) * TILE_SIZE;
|
||||||
y = TileY(current->tile) * 16;
|
y = TileY(current->tile) * TILE_SIZE;
|
||||||
z1 = GetSlopeZ(x+8, y+8);
|
/* get the height of the center of the current tile */
|
||||||
|
z1 = GetSlopeZ(x+TILE_HEIGHT, y+TILE_HEIGHT);
|
||||||
|
|
||||||
x = TileX(next) * 16;
|
x = TileX(next) * TILE_SIZE;
|
||||||
y = TileY(next) * 16;
|
y = TileY(next) * TILE_SIZE;
|
||||||
z2 = GetSlopeZ(x+8, y+8);
|
/* get the height of the center of the next tile */
|
||||||
|
z2 = GetSlopeZ(x+TILE_HEIGHT, y+TILE_HEIGHT);
|
||||||
|
|
||||||
if ((z2 - z1) > 1) {
|
if ((z2 - z1) > 1) {
|
||||||
/* Slope up */
|
/* Slope up */
|
||||||
|
@ -499,7 +417,7 @@ static inline RailType GetTileRailType(TileIndex tile, byte trackdir)
|
||||||
/* railway bridge ending */
|
/* railway bridge ending */
|
||||||
if ((_map5[tile] & 0xC6) == 0x80) type = _map3_lo[tile] & RAILTYPE_MASK;
|
if ((_map5[tile] & 0xC6) == 0x80) type = _map3_lo[tile] & RAILTYPE_MASK;
|
||||||
/* on railway bridge */
|
/* 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;
|
type = (_map3_lo[tile] >> 4) & RAILTYPE_MASK;
|
||||||
/* under bridge (any type) */
|
/* under bridge (any type) */
|
||||||
if ((_map5[tile] & 0xC0) == 0xC0 && (_map5[tile] & 0x1) != (trackdir & 0x1))
|
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
|
* otherwise (only for trains, since only with trains you can
|
||||||
* (sometimes) reach tiles after reversing that you couldn't reach
|
* (sometimes) reach tiles after reversing that you couldn't reach
|
||||||
* without reversing. */
|
* 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
|
/* We are headed inwards. We can only reverse here, so we'll not
|
||||||
* consider this direction, but jump ahead to the reverse direction.
|
* consider this direction, but jump ahead to the reverse direction.
|
||||||
* It would be nicer to return one neighbour here (the reverse
|
* 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
|
* orientation. They are only "inwards", since we are reaching this tile
|
||||||
* from some other tile. This prevents vehicles driving into depots from
|
* from some other tile. This prevents vehicles driving into depots from
|
||||||
* the back */
|
* the back */
|
||||||
ts = (1 << _dir_to_diag_trackdir[_reverse_dir[exitdir]]);
|
ts = TrackdirToTrackdirBits(DiagdirToDiagTrackdir(ReverseDiagdir(exitdir)));
|
||||||
} else {
|
} else {
|
||||||
ts = GetTileTrackStatus(dst_tile, type);
|
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);
|
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 */
|
/* 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 */
|
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];
|
trackdirs &= ~_trackdir_crosses_trackdirs[src_trackdir];
|
||||||
DEBUG(npf,6)("After filtering: (%d, %d), possible trackdirs: %#x", TileX(dst_tile), TileY(dst_tile), trackdirs);
|
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);
|
assert(0);
|
||||||
|
|
||||||
/* Initialize Start Node(s) */
|
/* 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;
|
start1->user_data[NPF_NODE_FLAGS] = 0;
|
||||||
_npf_aystar.addstart(&_npf_aystar, start1, 0);
|
_npf_aystar.addstart(&_npf_aystar, start1, 0);
|
||||||
if (start2) {
|
if (start2) {
|
||||||
start2->user_data[NPF_TRACKDIR_CHOICE] = 0xff;
|
start2->user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
|
||||||
start2->user_data[NPF_NODE_FLAGS] = 0;
|
start2->user_data[NPF_NODE_FLAGS] = 0;
|
||||||
NPFSetFlag(start2, NPF_FLAG_REVERSE, true);
|
NPFSetFlag(start2, NPF_FLAG_REVERSE, true);
|
||||||
_npf_aystar.addstart(&_npf_aystar, start2, reverse_penalty);
|
_npf_aystar.addstart(&_npf_aystar, start2, reverse_penalty);
|
||||||
|
@ -695,7 +613,7 @@ NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start2, NPFF
|
||||||
/* Initialize result */
|
/* Initialize result */
|
||||||
result.best_bird_dist = (uint)-1;
|
result.best_bird_dist = (uint)-1;
|
||||||
result.best_path_dist = (uint)-1;
|
result.best_path_dist = (uint)-1;
|
||||||
result.best_trackdir = 0xff;
|
result.best_trackdir = INVALID_TRACKDIR;
|
||||||
_npf_aystar.user_path = &result;
|
_npf_aystar.user_path = &result;
|
||||||
|
|
||||||
/* Initialize target */
|
/* Initialize target */
|
||||||
|
@ -721,7 +639,7 @@ NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start2, NPFF
|
||||||
return result;
|
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 start1;
|
||||||
AyStarNode start2;
|
AyStarNode start2;
|
||||||
|
|
||||||
|
@ -729,19 +647,19 @@ NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, byte trackdir1
|
||||||
start2.tile = tile2;
|
start2.tile = tile2;
|
||||||
/* We set this in case the target is also the start tile, we will just
|
/* We set this in case the target is also the start tile, we will just
|
||||||
* return a not found then */
|
* return a not found then */
|
||||||
start1.user_data[NPF_TRACKDIR_CHOICE] = 0xff;
|
start1.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
|
||||||
start1.direction = trackdir1;
|
start1.direction = trackdir1;
|
||||||
start2.direction = trackdir2;
|
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);
|
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);
|
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 start1;
|
||||||
AyStarNode start2;
|
AyStarNode start2;
|
||||||
|
|
||||||
|
@ -749,21 +667,21 @@ NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, byte track
|
||||||
start2.tile = tile2;
|
start2.tile = tile2;
|
||||||
/* We set this in case the target is also the start tile, we will just
|
/* We set this in case the target is also the start tile, we will just
|
||||||
* return a not found then */
|
* return a not found then */
|
||||||
start1.user_data[NPF_TRACKDIR_CHOICE] = 0xff;
|
start1.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
|
||||||
start1.direction = trackdir1;
|
start1.direction = trackdir1;
|
||||||
start2.direction = trackdir2;
|
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,
|
/* perform a breadth first search. Target is NULL,
|
||||||
* since we are just looking for any depot...*/
|
* since we are just looking for any depot...*/
|
||||||
return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), NULL, NPFFindDepot, NPFCalcZero, type, owner, reverse_penalty);
|
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);
|
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
|
/* 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
|
* 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
|
* 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 */
|
/* Initialize Start Node */
|
||||||
/* We set this in case the target is also the start tile, we will just
|
/* We set this in case the target is also the start tile, we will just
|
||||||
* return a not found then */
|
* 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;
|
start.user_data[NPF_NODE_FLAGS] = 0;
|
||||||
_npf_aystar.addstart(&_npf_aystar, &start, 0);
|
_npf_aystar.addstart(&_npf_aystar, &start, 0);
|
||||||
|
|
||||||
/* Initialize result */
|
/* Initialize result */
|
||||||
result.best_bird_dist = (uint)-1;
|
result.best_bird_dist = (uint)-1;
|
||||||
result.best_path_dist = (uint)-1;
|
result.best_path_dist = (uint)-1;
|
||||||
result.best_trackdir = 0xff;
|
result.best_trackdir = INVALID_TRACKDIR;
|
||||||
|
|
||||||
/* Initialize target */
|
/* Initialize target */
|
||||||
target.dest_coords = current->xy;
|
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
|
/* We will limit the number of nodes for now, until we have a better
|
||||||
* solution to really fix performance */
|
* solution to really fix performance */
|
||||||
_npf_aystar.max_search_nodes = _patches.npf_max_search_nodes;
|
_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) {
|
void NPFFillWithOrderData(NPFFindStationOrTileData* fstd, Vehicle* v) {
|
||||||
|
|
107
npf.h
107
npf.h
|
@ -1,11 +1,11 @@
|
||||||
#ifndef NPF_H
|
#ifndef NPF_H
|
||||||
#define NPF_H
|
#define NPF_H
|
||||||
|
|
||||||
/* Blaat */
|
|
||||||
|
|
||||||
#include "openttd.h"
|
#include "openttd.h"
|
||||||
#include "aystar.h"
|
#include "aystar.h"
|
||||||
#include "vehicle.h"
|
#include "vehicle.h"
|
||||||
|
#include "tile.h"
|
||||||
|
#include "rail.h"
|
||||||
|
|
||||||
//mowing grass
|
//mowing grass
|
||||||
enum {
|
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 */
|
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_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 */
|
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 */
|
AyStarNode node; /* The node within the target the search led us to */
|
||||||
} NPFFoundTargetData;
|
} 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
|
/* Will search from the given tile and direction, for a route to the given
|
||||||
* station for the given transport type. See the declaration of
|
* station for the given transport type. See the declaration of
|
||||||
* NPFFoundTargetData above for the meaning of the result. */
|
* 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
|
/* 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
|
* reverse. Look at the NPF_FLAG_REVERSE flag in the result node to see which
|
||||||
* direction was taken (NPFGetBit(result.node, NPF_FLAG_REVERSE)) */
|
* 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. */
|
/* Will search a route to the closest depot. */
|
||||||
|
|
||||||
/* Search using breadth first. Good for little track choice and inaccurate
|
/* Search using breadth first. Good for little track choice and inaccurate
|
||||||
* heuristic, such as railway/road.*/
|
* 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
|
/* 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
|
* NPFGetBit(result.node, NPF_FLAG_REVERSE) to see from which node the path
|
||||||
* orginated. All pathfs from the second node will have the given
|
* orginated. All pathfs from the second node will have the given
|
||||||
* reverse_penalty applied (NPF_TILE_LENGTH is the equivalent of one full
|
* reverse_penalty applied (NPF_TILE_LENGTH is the equivalent of one full
|
||||||
* tile).
|
* 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
|
/* Search by trying each depot in order of Manhattan Distance. Good for lots
|
||||||
* of choices and accurate heuristics, such as water. */
|
* 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);
|
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);
|
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
|
#endif // NPF_H
|
||||||
|
|
|
@ -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
|
||||||
|
};
|
|
@ -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
|
649
rail_cmd.c
649
rail_cmd.c
File diff suppressed because it is too large
Load Diff
|
@ -9,7 +9,6 @@
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "town.h"
|
#include "town.h"
|
||||||
#include "gfx.h"
|
#include "gfx.h"
|
||||||
#include "npf.h"
|
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
#include "depot.h"
|
#include "depot.h"
|
||||||
|
|
||||||
|
|
|
@ -317,7 +317,7 @@ static Depot *FindClosestRoadDepot(Vehicle *v)
|
||||||
if (_patches.new_pathfinding_all) {
|
if (_patches.new_pathfinding_all) {
|
||||||
NPFFoundTargetData ftd;
|
NPFFoundTargetData ftd;
|
||||||
/* See where we are now */
|
/* See where we are now */
|
||||||
byte trackdir = GetVehicleTrackdir(v);
|
Trackdir trackdir = GetVehicleTrackdir(v);
|
||||||
|
|
||||||
ftd = NPFRouteToDepotBreadthFirst(v->tile, trackdir, TRANSPORT_ROAD, v->owner);
|
ftd = NPFRouteToDepotBreadthFirst(v->tile, trackdir, TRANSPORT_ROAD, v->owner);
|
||||||
if (ftd.best_bird_dist == 0)
|
if (ftd.best_bird_dist == 0)
|
||||||
|
@ -1101,7 +1101,7 @@ static int RoadFindPathToDest(Vehicle *v, uint tile, int enterdir)
|
||||||
byte trackdir;
|
byte trackdir;
|
||||||
|
|
||||||
NPFFillWithOrderData(&fstd, v);
|
NPFFillWithOrderData(&fstd, v);
|
||||||
trackdir = _dir_to_diag_trackdir[enterdir];
|
trackdir = DiagdirToDiagTrackdir(enterdir);
|
||||||
//debug("Finding path. Enterdir: %d, Trackdir: %d", enterdir, trackdir);
|
//debug("Finding path. Enterdir: %d, Trackdir: %d", enterdir, trackdir);
|
||||||
|
|
||||||
ftd = NPFRouteToStationOrTile(tile - TileOffsByDir(enterdir), trackdir, &fstd, TRANSPORT_ROAD, v->owner);
|
ftd = NPFRouteToStationOrTile(tile - TileOffsByDir(enterdir), trackdir, &fstd, TRANSPORT_ROAD, v->owner);
|
||||||
|
|
|
@ -568,7 +568,7 @@ static int ChooseShipTrack(Vehicle *v, uint tile, int enterdir, uint tracks)
|
||||||
if (_patches.new_pathfinding_all) {
|
if (_patches.new_pathfinding_all) {
|
||||||
NPFFindStationOrTileData fstd;
|
NPFFindStationOrTileData fstd;
|
||||||
NPFFoundTargetData ftd;
|
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);
|
byte trackdir = GetVehicleTrackdir(v);
|
||||||
assert (trackdir != 0xFF); /* Check that we are not in a depot */
|
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;
|
tot_dist = (uint)-1;
|
||||||
|
|
||||||
/* Let's find out how far it would be if we would reverse first */
|
/* 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) {
|
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)
|
if (dist != (uint)-1)
|
||||||
tot_dist = dist + 1;
|
tot_dist = dist + 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "airport.h"
|
#include "airport.h"
|
||||||
#include "sprite.h"
|
#include "sprite.h"
|
||||||
#include "npf.h"
|
|
||||||
#include "depot.h"
|
#include "depot.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|
33
tile.h
33
tile.h
|
@ -18,17 +18,30 @@ typedef enum TileType {
|
||||||
MP_UNMOVABLE
|
MP_UNMOVABLE
|
||||||
} TileType;
|
} TileType;
|
||||||
|
|
||||||
/* XXX: This should be moved out to a new file (rail.h) along with some other
|
/* TODO: Find out values */
|
||||||
* cleanups. I'll do that after 0.4) */
|
/* Direction as commonly used in v->direction, 8 way. */
|
||||||
typedef enum {
|
typedef enum Directions {
|
||||||
RAILTYPE_RAIL = 0,
|
DIR_N = 0,
|
||||||
RAILTYPE_MONO = 1,
|
DIR_NE = 1, /* Northeast, upper right on your monitor */
|
||||||
RAILTYPE_MAGLEV = 2,
|
DIR_E = 2,
|
||||||
RAILTYPE_END,
|
DIR_SE = 3,
|
||||||
RAILTYPE_MASK = 0x3,
|
DIR_S = 4,
|
||||||
INVALID_RAILTYPE = 0xFF,
|
DIR_SW = 5,
|
||||||
} RailType;
|
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);
|
void SetMapExtraBits(TileIndex tile, byte flags);
|
||||||
uint GetMapExtraBits(TileIndex tile);
|
uint GetMapExtraBits(TileIndex tile);
|
||||||
|
|
52
train_cmd.c
52
train_cmd.c
|
@ -459,8 +459,8 @@ static int32 CmdBuildRailWagon(uint engine, uint tile, uint32 flags)
|
||||||
v->direction = (byte)(dir*2+1);
|
v->direction = (byte)(dir*2+1);
|
||||||
v->tile = (TileIndex)tile;
|
v->tile = (TileIndex)tile;
|
||||||
|
|
||||||
x = TileX(tile) * 16 | _vehicle_initial_x_fract[dir];
|
x = TileX(tile) * TILE_SIZE | _vehicle_initial_x_fract[dir];
|
||||||
y = TileY(tile) * 16 | _vehicle_initial_y_fract[dir];
|
y = TileY(tile) * TILE_SIZE | _vehicle_initial_y_fract[dir];
|
||||||
|
|
||||||
v->x_pos = x;
|
v->x_pos = x;
|
||||||
v->y_pos = y;
|
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 CheckTrainStoppedInDepot(const Vehicle *v)
|
||||||
{
|
{
|
||||||
int count;
|
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
|
// make sure the train doesn't run against a oneway signal
|
||||||
if ((_map5[tile] & 0xC0) == 0x40) {
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1559,10 +1562,10 @@ static TrainFindDepotData FindClosestTrainDepot(Vehicle *v)
|
||||||
if (_patches.new_pathfinding_all) {
|
if (_patches.new_pathfinding_all) {
|
||||||
NPFFoundTargetData ftd;
|
NPFFoundTargetData ftd;
|
||||||
Vehicle* last = GetLastVehicleInChain(v);
|
Vehicle* last = GetLastVehicleInChain(v);
|
||||||
byte trackdir = GetVehicleTrackdir(v);
|
Trackdir trackdir = GetVehicleTrackdir(v);
|
||||||
byte trackdir_rev = REVERSE_TRACKDIR(GetVehicleTrackdir(last));
|
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);
|
ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, last->tile, trackdir_rev, TRANSPORT_RAIL, v->owner, NPF_INFINITE_PENALTY);
|
||||||
if (ftd.best_bird_dist == 0) {
|
if (ftd.best_bird_dist == 0) {
|
||||||
/* Found target */
|
/* Found target */
|
||||||
|
@ -1808,14 +1811,14 @@ static bool TrainTrackFollower(uint tile, TrainTrackFollowerData *ttfd, int trac
|
||||||
if (IsTileType(tile, MP_RAILWAY) && (_map5[tile]&0xC0) == 0x40) {
|
if (IsTileType(tile, MP_RAILWAY) && (_map5[tile]&0xC0) == 0x40) {
|
||||||
// the tile has a signal
|
// the tile has a signal
|
||||||
byte m3 = _map3_lo[tile];
|
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 one way signal not pointing towards us, stop going in this direction.
|
||||||
if (m3 & _signal_against_trackdir[track])
|
if (m3 & SignalAgainstTrackdir(track))
|
||||||
return true;
|
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.
|
// green signal in our direction. either one way or two way.
|
||||||
*state = true;
|
*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,
|
// two way signal. unless we passed another green signal on the way,
|
||||||
// stop going in this direction.
|
// stop going in this direction.
|
||||||
if (!*state) return true;
|
if (!*state) return true;
|
||||||
|
@ -1904,26 +1907,25 @@ unsigned int rdtsc()
|
||||||
|
|
||||||
|
|
||||||
/* choose a track */
|
/* 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;
|
TrainTrackFollowerData fd;
|
||||||
int bits = trackbits;
|
|
||||||
uint best_track;
|
uint best_track;
|
||||||
#if PF_BENCHMARK
|
#if PF_BENCHMARK
|
||||||
int time = rdtsc();
|
int time = rdtsc();
|
||||||
static float f;
|
static float f;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
assert( (bits & ~0x3F) == 0);
|
assert( (trackdirbits & ~0x3F) == 0);
|
||||||
|
|
||||||
/* quick return in case only one possible track is available */
|
/* quick return in case only one possible track is available */
|
||||||
if (KILL_FIRST_BIT(bits) == 0)
|
if (KILL_FIRST_BIT(trackdirbits) == 0)
|
||||||
return FIND_FIRST_BIT(bits);
|
return FIND_FIRST_BIT(trackdirbits);
|
||||||
|
|
||||||
if (_patches.new_pathfinding_all) { /* Use a new pathfinding for everything */
|
if (_patches.new_pathfinding_all) { /* Use a new pathfinding for everything */
|
||||||
NPFFindStationOrTileData fstd;
|
NPFFindStationOrTileData fstd;
|
||||||
NPFFoundTargetData ftd;
|
NPFFoundTargetData ftd;
|
||||||
byte trackdir;
|
Trackdir trackdir;
|
||||||
|
|
||||||
NPFFillWithOrderData(&fstd, v);
|
NPFFillWithOrderData(&fstd, v);
|
||||||
/* The enterdir for the new tile, is the exitdir for the old tile */
|
/* 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 */
|
/* We are already at our target. Just do something */
|
||||||
//TODO: maybe display error?
|
//TODO: maybe display error?
|
||||||
//TODO: go straight ahead if possible?
|
//TODO: go straight ahead if possible?
|
||||||
best_track = FIND_FIRST_BIT(bits);
|
best_track = FIND_FIRST_BIT(trackdirbits);
|
||||||
} else {
|
} else {
|
||||||
/* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains
|
/* 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,
|
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) {
|
if (fd.best_track == 0xff) {
|
||||||
// blaha
|
// blaha
|
||||||
best_track = FIND_FIRST_BIT(bits);
|
best_track = FIND_FIRST_BIT(trackdirbits);
|
||||||
} else {
|
} else {
|
||||||
best_track = fd.best_track & 7;
|
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;
|
best_track = (uint)-1;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
i = FIND_FIRST_BIT(bits);
|
i = FIND_FIRST_BIT(trackdirbits);
|
||||||
bits = KILL_FIRST_BIT(bits);
|
trackdirbits = KILL_FIRST_BIT(trackdirbits);
|
||||||
|
|
||||||
fd.best_bird_dist = (uint)-1;
|
fd.best_bird_dist = (uint)-1;
|
||||||
fd.best_track_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_bird_dist = fd.best_bird_dist;
|
||||||
best_track_dist = fd.best_track_dist;
|
best_track_dist = fd.best_track_dist;
|
||||||
bad:;
|
bad:;
|
||||||
} while (bits != 0);
|
} while (trackdirbits != 0);
|
||||||
// printf("Train %d %s\n", v->unitnumber, best_track_dist == -1 ? "NOTFOUND" : "FOUND");
|
// printf("Train %d %s\n", v->unitnumber, best_track_dist == -1 ? "NOTFOUND" : "FOUND");
|
||||||
assert(best_track != (uint)-1);
|
assert(best_track != (uint)-1);
|
||||||
}
|
}
|
||||||
|
@ -2064,7 +2066,7 @@ static bool CheckReverseTrain(Vehicle *v)
|
||||||
NPFFillWithOrderData(&fstd, v);
|
NPFFillWithOrderData(&fstd, v);
|
||||||
|
|
||||||
trackdir = GetVehicleTrackdir(v);
|
trackdir = GetVehicleTrackdir(v);
|
||||||
trackdir_rev = REVERSE_TRACKDIR(GetVehicleTrackdir(last));
|
trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last));
|
||||||
assert(trackdir != 0xff);
|
assert(trackdir != 0xff);
|
||||||
assert(trackdir_rev != 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)
|
if (_patches.new_pathfinding_all && _patches.forbid_90_deg && prev == NULL)
|
||||||
/* We allow wagons to make 90 deg turns, because forbid_90_deg
|
/* We allow wagons to make 90 deg turns, because forbid_90_deg
|
||||||
* can be switched on halfway a turn */
|
* 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) {
|
if ( bits == 0) {
|
||||||
//debug("%x == 0", bits);
|
//debug("%x == 0", bits);
|
||||||
|
@ -2821,13 +2823,13 @@ red_light: {
|
||||||
* FIND_FIRST_BIT only handles 6 bits at a time. */
|
* FIND_FIRST_BIT only handles 6 bits at a time. */
|
||||||
i = FindFirstBit2x64(ts);
|
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->cur_speed = 0;
|
||||||
v->subspeed = 0;
|
v->subspeed = 0;
|
||||||
v->progress = 255-100;
|
v->progress = 255-100;
|
||||||
if (++v->load_unload_time_rem < _patches.wait_oneway_signal * 20)
|
if (++v->load_unload_time_rem < _patches.wait_oneway_signal * 20)
|
||||||
return;
|
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->cur_speed = 0;
|
||||||
v->subspeed = 0;
|
v->subspeed = 0;
|
||||||
v->progress = 255-10;
|
v->progress = 255-10;
|
||||||
|
|
|
@ -15,10 +15,10 @@
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "npf.h"
|
|
||||||
#include "vehicle_gui.h"
|
#include "vehicle_gui.h"
|
||||||
#include "depot.h"
|
#include "depot.h"
|
||||||
#include "station.h"
|
#include "station.h"
|
||||||
|
#include "rail.h"
|
||||||
|
|
||||||
#define INVALID_COORD (-0x8000)
|
#define INVALID_COORD (-0x8000)
|
||||||
#define GEN_HASH(x,y) (((x & 0x1F80)>>7) + ((y & 0xFC0)))
|
#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];
|
return _track_direction_to_trackdir[FIND_FIRST_BIT(v->u.rail.track)][v->direction];
|
||||||
break;
|
break;
|
||||||
case VEH_Ship:
|
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 _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];
|
return _track_direction_to_trackdir[FIND_FIRST_BIT(v->u.ship.state)][v->direction];
|
||||||
|
|
Loading…
Reference in New Issue