Index: npf.c =================================================================== --- npf.c (révision 3292) +++ npf.c (copie de travail) @@ -60,8 +60,8 @@ uint32 ts; /* Can always go into a tunnel */ - if (IsTileType(tile, MP_TUNNELBRIDGE) && GB(_m[tile].m5, 4, 4) == 0 && - GB(_m[tile].m5, 0, 2) == exitdir) { + if (IsTunnelTile(tile) && + GetTunnelBridgeDirection(tile) == exitdir) { return false; } @@ -90,9 +90,8 @@ return true; /* Prevent us from falling off a slope into a tunnel exit */ - if (IsTileType(dst_tile, MP_TUNNELBRIDGE) && - GB(_m[dst_tile].m5, 4, 4) == 0 && - (DiagDirection)GB(_m[dst_tile].m5, 0, 2) == ReverseDiagdir(exitdir)) { + if (IsTunnelTile(tile) && + GetTunnelBridgeDirection(tile) == ReverseDiagdir(exitdir)) { return true; } @@ -317,7 +316,7 @@ { DiagDirection exitdir = TrackdirToExitdir((Trackdir)current->direction); TileIndex tile = current->tile; - if ((DiagDirection)GB(_m[tile].m5, 0, 2) == ReverseDiagdir(exitdir)) { + if (GetTunnelBridgeDirection(tile) == ReverseDiagdir(exitdir)) { /* We just popped out if this tunnel, since were * facing the tunnel exit */ FindLengthOfTunnelResult flotr; @@ -369,7 +368,7 @@ /* DEBUG: mark visited tiles by mowing the grass under them * ;-) */ if (!IsTileDepotType(tile, TRANSPORT_RAIL)) { - SB(_m[tile].m2, 0, 4, 0); + SetRailGround(tile, RAIL_GROUND_BROWN); MarkTileDirtyByTile(tile); } break; @@ -413,7 +412,7 @@ /* Determine base length */ switch (GetTileType(tile)) { case MP_TUNNELBRIDGE: - if (GB(_m[tile].m5, 4, 4) == 0) { + if (IsTunnelTile(tile)) { cost = NPFTunnelCost(current); break; } @@ -457,7 +456,7 @@ /* Determine base length */ switch (GetTileType(tile)) { case MP_TUNNELBRIDGE: - if (GB(_m[tile].m5, 4, 4) == 0) { + if (IsTunnelTile(tile)) { cost = NPFTunnelCost(current); break; } @@ -493,6 +492,7 @@ /* Check for signals */ if (IsTileType(tile, MP_RAILWAY) && HasSignalOnTrackdir(tile, trackdir)) { /* Ordinary track with signals */ + SignalType sigtype = GetSignalType(tile, TrackdirToTrack(trackdir)); if (GetSignalState(tile, trackdir) == SIGNAL_STATE_RED) { /* Signal facing us is red */ if (!NPFGetFlag(current, NPF_FLAG_SEEN_SIGNAL)) { @@ -500,7 +500,6 @@ * encounter, if it is red */ /* Is this a presignal exit or combo? */ - SignalType sigtype = GetSignalType(tile, TrackdirToTrack(trackdir)); if (sigtype == SIGTYPE_EXIT || sigtype == SIGTYPE_COMBO) /* Penalise exit and combo signals differently (heavier) */ cost += _patches.npf_rail_firstred_exit_penalty; @@ -522,7 +521,7 @@ /* penalise a path through the pbs block if it crosses reserved tracks */ cost += 1000; } - if ((PBSIsPbsSignal(tile, trackdir)) && !NPFGetFlag(current, NPF_FLAG_SEEN_SIGNAL)) { + if ((sigtype == SIGTYPE_PBS) && !NPFGetFlag(current, NPF_FLAG_SEEN_SIGNAL)) { /* we've encountered an exit signal to the pbs block */ NPFSetFlag(current, NPF_FLAG_PBS_EXIT, true); } @@ -659,18 +658,23 @@ * intensive owner check, instead we will just assume that if the vehicle * managed to get on the bridge, it is probably allowed to :-) */ - if ((_m[tile].m5 & 0xC6) == 0xC0 && GB(_m[tile].m5, 0, 1) == (enterdir & 0x1)) { + if (IsBridgeMiddlePartTile(tile) + && GB(GetTunnelBridgeDirection(tile), 0, 1) == GB(enterdir, 0, 1) + && GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) { /* on the middle part of a railway bridge: find bridge ending */ - while (IsTileType(tile, MP_TUNNELBRIDGE) && !((_m[tile].m5 & 0xC6) == 0x80)) { - tile += TileOffsByDir(GB(_m[tile].m5, 0, 1)); + while (IsBridgeMiddlePartTile(tile)) { + tile += TileOffsByDir(enterdir); } } /* if we were on a railway middle part, we are now at a railway bridge ending */ #endif if ( - (_m[tile].m5 & 0xFC) == 0 /* railway tunnel */ - || (_m[tile].m5 & 0xC6) == 0x80 /* railway bridge ending */ - || ((_m[tile].m5 & 0xF8) == 0xE0 && GB(_m[tile].m5, 0, 1) != (enterdir & 0x1)) /* railway under bridge */ + (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL /* railway */ + && (IsTunnelTile(tile) || IsBridgeEndingTile(tile))) /* tunnel or bridge ending */ + || (IsBridgeMiddlePartTile(tile) + && GB(GetTunnelBridgeDirection(tile), 0, 1) != GB(enterdir, 0, 1) + && HasUnderBridgeTransport(tile) + && GetUnderBridgeTransportType(tile) == TRANSPORT_RAIL) /* railway under bridge */ ) return IsTileOwner(tile, owner); break; @@ -704,8 +708,7 @@ aystar->EndNodeCheck(aystar, current); /* Find dest tile */ - if (IsTileType(src_tile, MP_TUNNELBRIDGE) && GB(_m[src_tile].m5, 4, 4) == 0 && - (DiagDirection)GB(_m[src_tile].m5, 0, 2) == src_exitdir) { + if (IsTunnelTile(src_tile) && GetTunnelBridgeDirection(src_tile) == src_exitdir) { /* This is a tunnel. We know this tunnel is our type, * otherwise we wouldn't have got here. It is also facing us, * so we should skip it's body */ @@ -750,7 +753,7 @@ /* I can't enter a tunnel entry/exit tile from a tile above the tunnel. Note * that I can enter the tunnel from a tile below the tunnel entrance. This * solves the problem of vehicles wanting to drive off a tunnel entrance */ - if (IsTileType(dst_tile, MP_TUNNELBRIDGE) && GB(_m[dst_tile].m5, 4, 4) == 0 && + if (IsTunnelTile(dst_tile) && GetTileZ(dst_tile) < GetTileZ(src_tile)) { return; } Index: pbs.c =================================================================== --- pbs.c (révision 3292) +++ pbs.c (copie de travail) @@ -239,7 +239,7 @@ if (!HasSignalOnTrackdir(tile, trackdir)) return false; - if (GetSignalType(tile, TrackdirToTrack(trackdir)) == 4) + if (GetSignalType(tile, TrackdirToTrack(trackdir)) == SIGTYPE_PBS) return true; else return false; Index: rail.c =================================================================== --- rail.c (révision 3292) +++ rail.c (copie de travail) @@ -4,28 +4,9 @@ #include "openttd.h" #include "rail.h" #include "station.h" +#include "macros.h" +#include "tile.h" -/* XXX: Below 3 tables store duplicate data. Maybe remove some? */ -/* Maps a trackdir to the bit that stores its status in the map arrays, in the - * 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) */ @@ -110,36 +91,22 @@ RailType GetTileRailType(TileIndex tile, Trackdir trackdir) { - RailType type = INVALID_RAILTYPE; DiagDirection exitdir = TrackdirToExitdir(trackdir); - switch (GetTileType(tile)) { - case MP_RAILWAY: - /* railway track */ - type = _m[tile].m3 & RAILTYPE_MASK; - break; - case MP_STREET: - /* rail/road crossing */ - if (IsLevelCrossing(tile)) - type = _m[tile].m4 & RAILTYPE_MASK; - break; - case MP_STATION: - if (IsTrainStationTile(tile)) - type = _m[tile].m3 & RAILTYPE_MASK; - break; - case MP_TUNNELBRIDGE: - /* railway tunnel */ - if ((_m[tile].m5 & 0xFC) == 0) type = _m[tile].m3 & RAILTYPE_MASK; - /* railway bridge ending */ - if ((_m[tile].m5 & 0xC6) == 0x80) type = _m[tile].m3 & RAILTYPE_MASK; - /* on railway bridge */ - if ((_m[tile].m5 & 0xC6) == 0xC0 && ((DiagDirection)(_m[tile].m5 & 0x1)) == (exitdir & 0x1)) - type = (_m[tile].m3 >> 4) & RAILTYPE_MASK; - /* under bridge (any type) */ - if ((_m[tile].m5 & 0xC0) == 0xC0 && (_m[tile].m5 & 0x1U) != (exitdir & 0x1)) - type = _m[tile].m3 & RAILTYPE_MASK; - break; - default: - break; - } - return type; + if (IsTileType(tile, MP_RAILWAY) || // railway tile + IsLevelCrossing(tile) || // level crossing + IsTrainStationTile(tile)) // train station + return GetRailType(tile); + + if ((IsTunnelTile(tile) || IsBridgeTile(tile)) && // tunnel or bridge + (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) && // railway + (GB(GetTunnelBridgeDirection(tile), 0, 1) == GB(exitdir, 0, 1))) // we are on it + return GetTunnelBridgeRailType(tile); + + if (IsBridgeMiddlePartTile(tile) && // bridge middle part + HasUnderBridgeTransport(tile) && // with transport under + (GetUnderBridgeTransportType(tile) == TRANSPORT_RAIL) && // railway + (GB(GetTunnelBridgeDirection(tile), 0, 1) != GB(exitdir, 0, 1))) // we are under it + return GetRailType(tile); + + return INVALID_RAILTYPE; } Index: rail.h =================================================================== --- rail.h (révision 3292) +++ rail.h (copie de travail) @@ -6,6 +6,7 @@ #define RAIL_H #include "tile.h" +#include "macros.h" /* * Some enums for accesing the map bytes for rail tiles @@ -14,57 +15,48 @@ /** 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, + RAIL_TYPE_NORMAL = 0, + RAIL_TYPE_SIGNALS = 1, + RAIL_TYPE_UNUSED = 2, /* XXX: Maybe this could become waypoints? */ + RAIL_TYPE_DEPOT_WAYPOINT = 3, /* Is really depots and waypoints... */ + RAIL_TYPE_END, } 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 RailTileSubtypes { - RAIL_SUBTYPE_DEPOT = 0x00, - RAIL_SUBTYPE_WAYPOINT = 0x04, - RAIL_SUBTYPE_MASK = 0x3C, + RAIL_SUBTYPE_DEPOT = 0, + RAIL_SUBTYPE_WAYPOINT = 1, + RAIL_SUBTYPE_END, } RailTileSubtype; typedef enum SignalTypes { - /* Stored in m4[0..1] for MP_RAILWAY */ + /* Stored in m4[2..0] 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_PBS = 4, // pbs signal SIGTYPE_END, - SIGTYPE_MASK = 7, } SignalType; +typedef enum Signals { + /* Stored in m3[7..4] */ + SIGNAL_NONE = 0, + SIGNAL_DIR1 = 1, + SIGNAL_DIR2 = 2, + SIGNAL_BOTH = 3, + SIGNAL_END, +} Signal; + typedef enum RailTypes { RAILTYPE_RAIL = 0, RAILTYPE_MONO = 1, RAILTYPE_MAGLEV = 2, RAILTYPE_END, - RAILTYPE_MASK = 0x3, INVALID_RAILTYPE = 0xFF, } RailType; -enum { - SIG_SEMAPHORE_MASK = 1 << 3, -}; - /** These are used to specify a single track. Can be translated to a trackbit * with TrackToTrackbit */ typedef enum Tracks { @@ -86,7 +78,6 @@ 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 @@ -137,8 +128,27 @@ typedef enum SignalStates { SIGNAL_STATE_RED = 0, SIGNAL_STATE_GREEN = 1, + SIGNAL_STATE_END, } SignalState; +typedef enum RailGrounds { + RAIL_GROUND_BROWN = 0, + RAIL_GROUND_GREEN = 1, + RAIL_GROUND_FENCE_NW = 2, + RAIL_GROUND_FENCE_SE = 3, + RAIL_GROUND_FENCE_SENW = 4, + RAIL_GROUND_FENCE_NE = 5, + RAIL_GROUND_FENCE_SW = 6, + RAIL_GROUND_FENCE_NESW = 7, + RAIL_GROUND_FENCE_VERT1 = 8, + RAIL_GROUND_FENCE_VERT2 = 9, + RAIL_GROUND_FENCE_HORIZ1 = 10, + RAIL_GROUND_FENCE_HORIZ2 = 11, + RAIL_GROUND_ICE_DESERT = 12, + RAIL_GROUND_END, +} RailGround; + + /** This struct contains all the info that is needed to draw and construct tracks. */ typedef struct RailtypeInfo { @@ -222,61 +232,97 @@ static inline TrackdirBits TrackdirToTrackdirBits(Trackdir trackdir) { return (TrackdirBits)(1 << trackdir); } /** - * These functions check the validity of Tracks and Trackdirs. assert against - * them when convenient. + * These functions check the validity of Tracks, Trackdirs, Signals and Types. + * assert against them when convenient. */ static inline bool IsValidTrack(Track track) { return track < TRACK_END; } static inline bool IsValidTrackdir(Trackdir trackdir) { return (TrackdirToTrackdirBits(trackdir) & TRACKDIR_BIT_MASK) != 0; } +static inline bool IsValidSignal(Signal signal) { return signal < SIGNAL_END; } +static inline bool IsValidSignalState(SignalState state) { return state < SIGNAL_STATE_END; } +static inline bool IsValidSignalType(SignalType type) { return type < SIGTYPE_END; } +static inline bool IsValidRailTileType(RailTileType type) { return type < RAIL_TYPE_END; } +static inline bool IsValidRailTileSubtype(RailTileSubtype type) { return type < RAIL_SUBTYPE_END; } +static inline bool IsValidRailType(RailType type) { return type < RAILTYPE_END; } +static inline bool IsValidRailGround(RailGround ground) { return ground < RAIL_GROUND_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? + * Returns whether the given tile is a level crossing. */ +static inline bool IsLevelCrossing(TileIndex tile) +{ + return IsTileType(tile, MP_STREET) && GB(_m[tile].m5, 4, 4) == 1; +} +/* + * Some functions to query rail tiles + */ + /** - * Maps a trackdir to the bit that stores its status in the map arrays, in the - * direction along with the trackdir. + * Returns the RailTileType of a given rail tile. (ie normal, with signals, + * depot, etc.) */ -extern const byte _signal_along_trackdir[TRACKDIR_END]; -static inline byte SignalAlongTrackdir(Trackdir trackdir) {return _signal_along_trackdir[trackdir];} +static inline RailTileType GetRailTileType(TileIndex tile) +{ + assert(IsTileType(tile, MP_RAILWAY)); + return (RailTileType)GB(_m[tile].m5, 6, 2); +} /** - * Maps a trackdir to the bit that stores its status in the map arrays, in the - * direction against the trackdir. + * Sets the RailTileType of a given rail tile. (ie normal, with signals, + * depot, etc.) */ -static inline byte SignalAgainstTrackdir(Trackdir trackdir) { - extern const byte _signal_against_trackdir[TRACKDIR_END]; - return _signal_against_trackdir[trackdir]; +static inline void SetRailTileType(TileIndex tile, RailTileType type) +{ + assert(IsTileType(tile, MP_RAILWAY)); + assert(IsValidRailTileType(type)); + SB(_m[tile].m5, 6, 2, type); } /** - * Maps a Track to the bits that store the status of the two signals that can - * be present on the given track. + * Returns the rail type (ie rail, mono, maglev) of : + * - the given rail tile + * - under the given bridge tile + * - the given level crossing tile + * - the given station tile */ -static inline byte SignalOnTrack(Track track) { - extern const byte _signal_on_track[TRACK_END]; - return _signal_on_track[track]; +static inline RailType GetRailType(TileIndex tile) +{ + return (RailType)GB(IsLevelCrossing(tile) ? _m[tile].m4 : _m[tile].m3, 0, 4); } -/* - * Some functions to query rail tiles +/** + * Returns the rail type (ie rail, mono, maglev) of the given tunnel/bridge tile: */ +static inline RailType GetTunnelBridgeRailType(TileIndex tile) +{ + return (RailType)GB(_m[tile].m3, IsBridgeMiddlePartTile(tile) ? 4 : 0, 4); +} /** - * Returns the RailTileType of a given rail tile. (ie normal, with signals, - * depot, etc.) + * Sets the rail type (ie rail, mono, maglev) of : + * - the given rail tile + * - under the given bridge tile + * - the given level crossing tile + * - the given station tile */ -static inline RailTileType GetRailTileType(TileIndex tile) +static inline void SetRailType(TileIndex tile, RailType type) { - assert(IsTileType(tile, MP_RAILWAY)); - return _m[tile].m5 & RAIL_TILE_TYPE_MASK; + assert(IsValidRailType(type)); + if (IsLevelCrossing(tile)) { + SB(_m[tile].m4, 0, 4, type); + } else { + SB(_m[tile].m3, 0, 4, type); + } } /** - * Returns the rail type of the given rail tile (ie rail, mono, maglev). + * Sets the rail type (ie rail, mono, maglev) of the given tunnel/bridge tile: */ -static inline RailType GetRailType(TileIndex tile) { return (RailType)(_m[tile].m3 & RAILTYPE_MASK); } +static inline void SetTunnelBridgeRailType(TileIndex tile, RailType type) +{ + assert(IsValidRailType(type)); + SB(_m[tile].m3, IsBridgeMiddlePartTile(tile) ? 4 : 0, 4, type); +} /** * Checks if a rail tile has signals. @@ -293,10 +339,21 @@ static inline RailTileSubtype GetRailTileSubtype(TileIndex tile) { assert(GetRailTileType(tile) == RAIL_TYPE_DEPOT_WAYPOINT); - return (RailTileSubtype)(_m[tile].m5 & RAIL_SUBTYPE_MASK); + return (RailTileSubtype)GB(_m[tile].m5, 2, 1); } /** + * Sets the RailTileSubtype of a given rail tile with type + * RAIL_TYPE_DEPOT_WAYPOINT + */ +static inline void SetRailTileSubtype(TileIndex tile, RailTileSubtype subtype) +{ + assert(GetRailTileType(tile) == RAIL_TYPE_DEPOT_WAYPOINT); + assert(IsValidRailTileSubtype(subtype)); + SB(_m[tile].m5, 2, 1, subtype); +} + +/** * Returns whether this is plain rails, with or without signals. Iow, if this * tiles RailTileType is RAIL_TYPE_NORMAL or RAIL_TYPE_SIGNALS. */ @@ -311,8 +368,8 @@ */ static inline TrackBits GetTrackBits(TileIndex tile) { - assert(GetRailTileType(tile) == RAIL_TYPE_NORMAL || GetRailTileType(tile) == RAIL_TYPE_SIGNALS); - return (TrackBits)(_m[tile].m5 & TRACK_BIT_MASK); + assert(IsPlainRailTile(tile)); + return (TrackBits)GB(_m[tile].m5, 0, 6); } /** @@ -325,6 +382,26 @@ return HASBIT(GetTrackBits(tile), track); } +/** + * Adds the given track on the given tile. Tile must be + * a plain rail tile (IsPlainRailTile()). + */ +static inline bool AddTrack(TileIndex tile, Track track) +{ + assert(IsValidTrack(track)); + return SB(_m[tile].m5, track, 1, 1); +} + +/** + * Removes the given track on the given tile. Tile must be + * a plain rail tile (IsPlainRailTile()). + */ +static inline bool RemoveTrack(TileIndex tile, Track track) +{ + assert(IsValidTrack(track)); + return SB(_m[tile].m5, track, 1, 0); +} + /* * Functions describing logical relations between Tracks, TrackBits, Trackdirs * TrackdirBits, Direction and DiagDirections. @@ -428,10 +505,10 @@ * Maps a trackdir to the trackdirs that can be reached from it (ie, when * entering the next tile. This */ -extern 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)]; } +static inline TrackdirBits TrackdirReachesTrackdirs(Trackdir trackdir) { + extern const TrackdirBits _exitdir_reaches_trackdirs[DIAGDIR_END]; + return _exitdir_reaches_trackdirs[TrackdirToExitdir(trackdir)]; +} /** * Maps a trackdir to all trackdirs that make 90 deg turns with it. @@ -468,13 +545,68 @@ */ /** + * Gets the signals on the given track on the given rail tile. + */ +static inline Signal GetSignalOnTrack(TileIndex tile, Track track) +{ + assert(IsValidTrack(track)); + switch (track) { + case TRACK_LOWER: + case TRACK_RIGHT: + return GB(_m[tile].m3, 4, 2); + break; + default: + return GB(_m[tile].m3, 6, 2); + break; + } +} + +/** + * Sets the signals on the given track on the given rail tile. + */ +static inline void SetSignalOnTrack(TileIndex tile, Track track, Signal signal) +{ + assert(IsValidTrack(track)); + assert(HasSignals(tile)); + assert(IsValidSignal(signal)); + switch (track) { + case TRACK_LOWER: + case TRACK_RIGHT: + SB(_m[tile].m3, 4, 2, signal); + break; + default: + SB(_m[tile].m3, 6, 2, signal); + break; + } +} + +/** + * Gets the signals on all tracks on the given rail tile. + */ +static inline byte GetAllSignals(TileIndex tile) +{ + assert(HasSignals(tile)); + return GB(_m[tile].m3, 4, 4); +} + +/** + * Sets the signals on all tracks on the given rail tile. + */ +static inline void SetAllSignals(TileIndex tile, Signal signal) +{ + assert(IsValidSignal(signal)); + SB(_m[tile].m3, 4, 2, signal); + SB(_m[tile].m3, 6, 2, signal); +} + +/** * Checks for the presence of signals (either way) on the given track on the * given rail tile. */ static inline bool HasSignalOnTrack(TileIndex tile, Track track) { assert(IsValidTrack(track)); - return ((GetRailTileType(tile) == RAIL_TYPE_SIGNALS) && ((_m[tile].m3 & SignalOnTrack(track)) != 0)); + return (HasSignals(tile) && (GetSignalOnTrack(tile, track) != SIGNAL_NONE)); } /** @@ -487,7 +619,8 @@ static inline bool HasSignalOnTrackdir(TileIndex tile, Trackdir trackdir) { assert (IsValidTrackdir(trackdir)); - return (GetRailTileType(tile) == RAIL_TYPE_SIGNALS) && (_m[tile].m3 & SignalAlongTrackdir(trackdir)); + return (HasSignals(tile) && + (GetSignalOnTrack(tile, TrackdirToTrack(trackdir)) & ((HASBIT(trackdir, 3)) ? SIGNAL_DIR1 : SIGNAL_DIR2))); } /** @@ -498,12 +631,70 @@ */ static inline SignalState GetSignalState(TileIndex tile, Trackdir trackdir) { - assert(IsValidTrackdir(trackdir)); - assert(HasSignalOnTrack(tile, TrackdirToTrack(trackdir))); - return ((_m[tile].m2 & SignalAlongTrackdir(trackdir))?SIGNAL_STATE_GREEN:SIGNAL_STATE_RED); + byte state; + assert(HasSignalOnTrackdir(tile, trackdir)); + switch (TrackdirToTrack(trackdir)) { + case TRACK_LOWER: + case TRACK_RIGHT: + state = GB(_m[tile].m2, (HASBIT(trackdir, 3)) ? 4 : 5, 1); + break; + default: + state = GB(_m[tile].m2, (HASBIT(trackdir, 3)) ? 6 : 7, 1); + break; + } + return (state) ? SIGNAL_STATE_GREEN : SIGNAL_STATE_RED; } /** + * Sets 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 void SetSignalState(TileIndex tile, Trackdir trackdir, SignalState state) +{ + assert(IsValidSignalState(state)); + assert(HasSignalOnTrackdir(tile, trackdir)); + switch (TrackdirToTrack(trackdir)) { + case TRACK_LOWER: + case TRACK_RIGHT: + SB(_m[tile].m2, (HASBIT(trackdir, 3)) ? 4 : 5, 1, state); + break; + default: + SB(_m[tile].m2, (HASBIT(trackdir, 3)) ? 6 : 7, 1, state); + break; + } +} + +/** + * Gets the signals on all tracks on the given rail tile. + */ +static inline byte GetAllSignalsState(TileIndex tile) +{ + assert(HasSignals(tile)); + return GB(_m[tile].m2, 4, 4); +} + +/** + * Sets the state of all signals on the tile. + */ +static inline void SetAllSignalsState(TileIndex tile, SignalState state) +{ + assert(IsValidSignalState(state)); + assert(HasSignals(tile)); + switch (state) { + case SIGNAL_STATE_GREEN: + SB(_m[tile].m2, 4, 4, 0xF); + break; + case SIGNAL_STATE_RED: + SB(_m[tile].m2, 4, 4, 0); + break; + default: + assert(0); + } +} + +/** * 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 @@ -513,11 +704,26 @@ static inline SignalType GetSignalType(TileIndex tile, Track track) { assert(IsValidTrack(track)); - assert(GetRailTileType(tile) == RAIL_TYPE_SIGNALS); - return (SignalType)(_m[tile].m4 & SIGTYPE_MASK); + assert(HasSignals(tile)); + return (SignalType)GB(_m[tile].m4, 0, 3); } /** + * Sets 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 void SetSignalType(TileIndex tile, Track track, SignalType type) +{ + assert(IsValidTrack(track)); + assert(HasSignals(tile)); + assert(IsValidSignalType(type)); + SB(_m[tile].m4, 0, 3, type); +} + +/** * 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. @@ -529,10 +735,25 @@ static inline bool HasSemaphores(TileIndex tile, Track track) { assert(IsValidTrack(track)); - return (_m[tile].m4 & SIG_SEMAPHORE_MASK); + return GB(_m[tile].m4, 3, 1); } /** + * Sets if this tile contains semaphores 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 void SetSemaphores(TileIndex tile, Track track, bool semaphore) +{ + assert(IsValidTrack(track)); + SB(_m[tile].m4, 3, 1, (semaphore)?1:0); +} + +/** * Return the rail type of tile, or INVALID_RAILTYPE if this is no rail tile. * Note that there is no check if the given trackdir is actually present on * the tile! @@ -542,14 +763,45 @@ RailType GetTileRailType(TileIndex tile, Trackdir trackdir); /** - * Returns whether the given tile is a level crossing. + * Returns the ground of the given rail tile */ -static inline bool IsLevelCrossing(TileIndex tile) +static inline RailGround GetRailGround(TileIndex tile) { - return (_m[tile].m5 & 0xF0) == 0x10; + assert(IsTileType(tile, MP_RAILWAY)); + switch(GetRailTileType(tile)) { + case RAIL_TYPE_NORMAL: + case RAIL_TYPE_SIGNALS: + return (RailGround)GB(_m[tile].m2, 0, 4); + break; + case RAIL_TYPE_DEPOT_WAYPOINT: + return (RailGround)GB(_m[tile].m4, 0, 4); + break; + default: + break; + } } /** + * Sets the ground of the given rail tile + */ +static inline void SetRailGround(TileIndex tile, RailGround ground) +{ + assert(IsTileType(tile, MP_RAILWAY)); + assert(IsValidRailGround(ground)); + switch(GetRailTileType(tile)) { + case RAIL_TYPE_NORMAL: + case RAIL_TYPE_SIGNALS: + SB(_m[tile].m2, 0, 4, ground); + break; + case RAIL_TYPE_DEPOT_WAYPOINT: + SB(_m[tile].m4, 0, 4, ground); + break; + default: + break; + } +} + +/** * Gets the transport type of the given track on the given crossing tile. * @return The transport type of the given track, either TRANSPORT_ROAD, * TRANSPORT_RAIL. Index: depot.h =================================================================== --- depot.h (révision 3292) +++ depot.h (copie de travail) @@ -9,6 +9,7 @@ #include "pool.h" #include "tile.h" #include "variables.h" +#include "rail.h" struct Depot { TileIndex xy; @@ -78,7 +79,9 @@ switch(type) { case TRANSPORT_RAIL: - return IsTileType(tile, MP_RAILWAY) && (_m[tile].m5 & 0xFC) == 0xC0; + return IsTileType(tile, MP_RAILWAY) && + (GetRailTileType(tile) == RAIL_TYPE_DEPOT_WAYPOINT) && + (GetRailTileSubtype(tile) == RAIL_SUBTYPE_DEPOT); case TRANSPORT_ROAD: return IsTileType(tile, MP_STREET) && (_m[tile].m5 & 0xF0) == 0x20; @@ -119,6 +122,35 @@ } /** + * Sets the direction the exit of the depot on the given tile is facing. + */ +static inline void SetDepotDirection(TileIndex tile, TransportType type, DiagDirection dir) +{ + assert(IsTileDepotType(tile, type)); + assert(dir < DIAGDIR_END); + + switch (type) + { + case TRANSPORT_RAIL: + case TRANSPORT_ROAD: + /* Rail and road store a diagonal direction in bits 0 and 1 */ + SB(_m[tile].m5, 0, 2, dir); + break; + case TRANSPORT_WATER: + /* Water is stubborn, it stores the directions in a different order. */ + switch (GB(_m[tile].m5, 0, 2)) { + case DIAGDIR_NE: SB(_m[tile].m5, 0, 2, 0); + case DIAGDIR_SW: SB(_m[tile].m5, 0, 2, 1); + case DIAGDIR_NW: SB(_m[tile].m5, 0, 2, 2); + case DIAGDIR_SE: SB(_m[tile].m5, 0, 2, 3); + } + break; + default: + break; + } +} + +/** Find out if the slope of the tile is suitable to build a depot of given direction @param direction The direction in which the depot's exit points. Starts with 0 as NE and goes Clockwise @param tileh The slope of the tile in question Index: tunnelbridge_cmd.c =================================================================== --- tunnelbridge_cmd.c (révision 3292) +++ tunnelbridge_cmd.c (copie de travail) @@ -401,7 +401,7 @@ } } - SetSignalsOnBothDir(ti_start.tile, (direction & 1) ? 1 : 0); + UpdateSignalsOnBothDir(ti_start.tile, (direction & 1) ? 1 : 0); /* for human player that builds the bridge he gets a selection to choose from bridges (DC_QUERY_COST) It's unnecessary to execute this command every time for every bridge. So it is done only @@ -825,8 +825,8 @@ c += direction ? TileDiffXY(0, 1) : TileDiffXY(1, 0); } while (c <= endtile); - SetSignalsOnBothDir(tile, direction); - SetSignalsOnBothDir(endtile, direction); + UpdateSignalsOnBothDir(tile, direction); + UpdateSignalsOnBothDir(endtile, direction); } @@ -1555,7 +1555,7 @@ TileIndex GetVehicleOutOfTunnelTile(const Vehicle *v) { TileIndex tile; - TileIndexDiff delta = (v->direction & 2) ? TileDiffXY(0, 1) : TileDiffXY(1, 0); + TileIndexDiff delta = TileOffsByDir((v->direction >> 1) & 3); byte z = v->z_pos; for (tile = v->tile;; tile += delta) { Index: docs/landscape.html =================================================================== --- docs/landscape.html (révision 3292) +++ docs/landscape.html (copie de travail) @@ -60,9 +60,9 @@ 1 -m5 bit 7 clear: railway track +m5 bit 7 clear: railway track (Get|Set)RailTileType() -m5 bits 7 and 6 set: railway depot / checkpoints +m5 bits 7 and 6 set: railway depot / waypoints (Get|Set)RailTileType() @@ -170,15 +170,15 @@
  • m4 bits 4..6: 0 - on bare land, 1 - on grass, 2 - paved, 3 - with streetlights, 5 - tree-lined, 6 - on grass with road works, 7 - paved with road works
  • m4 bit 7 set = on snow or desert
  • -m5 bit 4 set, bits 7..5 clear: level crossing +m5 bit 4 set, bits 7..5 clear: level crossing IsLevelCrossing() @@ -388,7 +388,7 @@
  • m1: owner of the station
  • m2: index into the array of stations
  • -
  • m3 bits 0..3: track type for railway stations, must be 0 for all the other stations
  • +
  • m3 bits 0..3: track type for railway stations, must be 0 for all the other stations (Get|Set)RailType()
  • m3 bit 4 = use custom sprite (valid only railway stations FOR NOW)
  • m3 bit 6 set = track is reserved by pbs (railway stations only)
  • m4 = custom station id
  • @@ -554,41 +554,41 @@ 9 -m5 bits 7..4 clear: tunnel entrance/exit +m5 bits 7..4 clear: tunnel entrance/exit IsTunnelTile() -m5 bit 7 set: bridge +m5 bit 7 set: bridge IsBridgeTile()