tron@2186: /* $Id$ */ tron@2186: celestar@2232: /** @file rail.h */ celestar@2232: matthijs@1942: #ifndef RAIL_H matthijs@1942: #define RAIL_H matthijs@1942: matthijs@1942: #include "tile.h" matthijs@1942: matthijs@1942: /* matthijs@1942: * Some enums for accesing the map bytes for rail tiles matthijs@1942: */ matthijs@1942: celestar@2232: /** These types are used in the map5 byte for rail tiles. Use GetRailTileType() to matthijs@1942: * get these values */ matthijs@1942: typedef enum RailTileTypes { matthijs@1942: RAIL_TYPE_NORMAL = 0x0, matthijs@1942: RAIL_TYPE_SIGNALS = 0x40, matthijs@1942: RAIL_TYPE_UNUSED = 0x80, /* XXX: Maybe this could become waypoints? */ matthijs@1942: RAIL_TYPE_DEPOT_WAYPOINT = 0xC0, /* Is really depots and waypoints... */ matthijs@1942: RAIL_TILE_TYPE_MASK = 0xC0, matthijs@1942: } RailTileType; matthijs@1942: matthijs@1942: enum { /* DEPRECATED TODO: Rewrite all uses of this */ matthijs@1942: RAIL_TYPE_SPECIAL = 0x80, /* This used to say "If this bit is set, then it's matthijs@1942: * not a regular track.", but currently, you matthijs@1942: * should rather view map5[6..7] as one type, matthijs@1942: * containing a value from RailTileTypes above. matthijs@1942: * This value is only maintained for backwards matthijs@1942: * compatibility */ matthijs@1942: matthijs@1942: /* There used to be RAIL_BIT_* enums here, they moved to (for now) npf.c as matthijs@1942: * TRACK_BIT_* */ matthijs@1942: }; matthijs@1942: celestar@2232: /** These subtypes are used in the map5 byte when the main rail type is matthijs@1942: * RAIL_TYPE_DEPOT_WAYPOINT */ matthijs@1944: typedef enum RailTileSubtypes { matthijs@1942: RAIL_SUBTYPE_DEPOT = 0x00, matthijs@1942: RAIL_SUBTYPE_WAYPOINT = 0x04, matthijs@1942: RAIL_SUBTYPE_MASK = 0x3C, matthijs@1942: } RailTileSubtype; matthijs@1942: matthijs@1944: typedef enum SignalTypes { tron@2049: /* Stored in m4[0..1] for MP_RAILWAY */ tron@2548: SIGTYPE_NORMAL = 0, // normal signal tron@2548: SIGTYPE_ENTRY = 1, // presignal block entry tron@2548: SIGTYPE_EXIT = 2, // presignal block exit tron@2548: SIGTYPE_COMBO = 3, // presignal inter-block hackykid@2008: SIGTYPE_PBS = 4, // pbs signal matthijs@1942: SIGTYPE_END, hackykid@2008: SIGTYPE_MASK = 7, matthijs@1942: } SignalType; matthijs@1942: matthijs@1944: typedef enum RailTypes { matthijs@1942: RAILTYPE_RAIL = 0, matthijs@1942: RAILTYPE_MONO = 1, matthijs@1942: RAILTYPE_MAGLEV = 2, matthijs@1942: RAILTYPE_END, matthijs@1942: RAILTYPE_MASK = 0x3, matthijs@1942: INVALID_RAILTYPE = 0xFF, matthijs@1942: } RailType; matthijs@1942: matthijs@1942: enum { celestar@2001: SIG_SEMAPHORE_MASK = 1 << 3, matthijs@1942: }; matthijs@1942: celestar@2232: /** These are used to specify a single track. Can be translated to a trackbit matthijs@1942: * with TrackToTrackbit */ matthijs@1944: typedef enum Tracks { tron@2548: TRACK_DIAG1 = 0, tron@2548: TRACK_DIAG2 = 1, tron@2548: TRACK_UPPER = 2, tron@2548: TRACK_LOWER = 3, tron@2548: TRACK_LEFT = 4, tron@2548: TRACK_RIGHT = 5, tron@2548: TRACK_END, tron@2548: INVALID_TRACK = 0xFF, matthijs@1942: } Track; matthijs@1942: celestar@2232: /** These are the bitfield variants of the above */ matthijs@1944: typedef enum TrackBits { tron@2548: TRACK_BIT_DIAG1 = 1, // 0 tron@2548: TRACK_BIT_DIAG2 = 2, // 1 tron@2548: TRACK_BIT_UPPER = 4, // 2 tron@2548: TRACK_BIT_LOWER = 8, // 3 tron@2548: TRACK_BIT_LEFT = 16, // 4 tron@2548: TRACK_BIT_RIGHT = 32, // 5 matthijs@1942: TRACK_BIT_MASK = 0x3F, matthijs@1942: } TrackBits; matthijs@1942: celestar@2232: /** These are a combination of tracks and directions. Values are 0-5 in one matthijs@1942: direction (corresponding to the Track enum) and 8-13 in the other direction. */ matthijs@1944: typedef enum Trackdirs { tron@2548: TRACKDIR_DIAG1_NE = 0, tron@2548: TRACKDIR_DIAG2_SE = 1, tron@2548: TRACKDIR_UPPER_E = 2, tron@2548: TRACKDIR_LOWER_E = 3, tron@2548: TRACKDIR_LEFT_S = 4, tron@2548: TRACKDIR_RIGHT_S = 5, matthijs@1948: /* Note the two missing values here. This enables trackdir -> track matthijs@1948: * conversion by doing (trackdir & 7) */ tron@2548: TRACKDIR_DIAG1_SW = 8, tron@2548: TRACKDIR_DIAG2_NW = 9, tron@2548: TRACKDIR_UPPER_W = 10, tron@2548: TRACKDIR_LOWER_W = 11, tron@2548: TRACKDIR_LEFT_N = 12, tron@2548: TRACKDIR_RIGHT_N = 13, tron@2548: TRACKDIR_END, tron@2548: INVALID_TRACKDIR = 0xFF, matthijs@1942: } Trackdir; matthijs@1942: celestar@2232: /** These are a combination of tracks and directions. Values are 0-5 in one matthijs@1942: direction (corresponding to the Track enum) and 8-13 in the other direction. */ matthijs@1944: typedef enum TrackdirBits { tron@2548: TRACKDIR_BIT_DIAG1_NE = 0x1, tron@2548: TRACKDIR_BIT_DIAG2_SE = 0x2, tron@2548: TRACKDIR_BIT_UPPER_E = 0x4, tron@2548: TRACKDIR_BIT_LOWER_E = 0x8, tron@2548: TRACKDIR_BIT_LEFT_S = 0x10, tron@2548: TRACKDIR_BIT_RIGHT_S = 0x20, matthijs@1942: /* Again, note the two missing values here. This enables trackdir -> track conversion by doing (trackdir & 0xFF) */ tron@2548: TRACKDIR_BIT_DIAG1_SW = 0x0100, tron@2548: TRACKDIR_BIT_DIAG2_NW = 0x0200, tron@2548: TRACKDIR_BIT_UPPER_W = 0x0400, tron@2548: TRACKDIR_BIT_LOWER_W = 0x0800, tron@2548: TRACKDIR_BIT_LEFT_N = 0x1000, tron@2548: TRACKDIR_BIT_RIGHT_N = 0x2000, matthijs@1942: TRACKDIR_BIT_MASK = 0x3F3F, tron@2548: INVALID_TRACKDIR_BIT = 0xFFFF, matthijs@1942: } TrackdirBits; matthijs@1942: celestar@2232: /** These are states in which a signal can be. Currently these are only two, so matthijs@1942: * simple boolean logic will do. But do try to compare to this enum instead of matthijs@1942: * normal boolean evaluation, since that will make future additions easier. matthijs@1942: */ matthijs@1944: typedef enum SignalStates { matthijs@1944: SIGNAL_STATE_RED = 0, matthijs@1944: SIGNAL_STATE_GREEN = 1, matthijs@1942: } SignalState; matthijs@1942: celestar@2233: /** This struct contains all the info that is needed to draw and construct tracks. celestar@2233: */ celestar@2233: typedef struct RailtypeInfo { celestar@2274: /** Struct containing the main sprites. @note not all sprites are listed, but only celestar@2274: * the ones used directly in the code */ celestar@2233: struct { celestar@2233: SpriteID track_y; ///< single piece of rail in Y direction, with ground celestar@2233: SpriteID track_ns; ///< two pieces of rail in North and South corner (East-West direction) celestar@2233: SpriteID ground; ///< ground sprite for a 3-way switch celestar@2233: SpriteID single_y; ///< single piece of rail in Y direction, without ground celestar@2233: SpriteID single_x; ///< single piece of rail in X direction celestar@2233: SpriteID single_n; ///< single piece of rail in the northern corner celestar@2233: SpriteID single_s; ///< single piece of rail in the southern corner celestar@2233: SpriteID single_e; ///< single piece of rail in the eastern corner celestar@2233: SpriteID single_w; ///< single piece of rail in the western corner tron@2511: SpriteID crossing; ///< level crossing, rail in X direction tron@2511: SpriteID tunnel; ///< tunnel sprites base celestar@2233: } base_sprites; celestar@2233: celestar@2274: /** struct containing the sprites for the rail GUI. @note only sprites referred to celestar@2274: * directly in the code are listed */ celestar@2274: struct { celestar@2274: SpriteID build_ns_rail; ///< button for building single rail in N-S direction celestar@2274: SpriteID build_x_rail; ///< button for building single rail in X direction celestar@2274: SpriteID build_ew_rail; ///< button for building single rail in E-W direction celestar@2274: SpriteID build_y_rail; ///< button for building single rail in Y direction celestar@2274: SpriteID auto_rail; ///< button for the autorail construction celestar@2274: SpriteID build_depot; ///< button for building depots celestar@2274: SpriteID build_tunnel; ///< button for building a tunnel celestar@2274: SpriteID convert_rail; ///< button for converting rail celestar@2274: } gui_sprites; celestar@2274: celestar@2274: struct { tron@2514: CursorID rail_ns; tron@2514: CursorID rail_swne; tron@2514: CursorID rail_ew; tron@2514: CursorID rail_nwse; tron@2514: CursorID autorail; tron@2514: CursorID depot; tron@2514: CursorID tunnel; tron@2514: CursorID convert; tron@2514: } cursor; tron@2514: tron@2514: struct { celestar@2274: StringID toolbar_caption; celestar@2274: } strings; celestar@2274: celestar@2233: /** sprite number difference between a piece of track on a snowy ground and the corresponding one on normal ground */ celestar@2233: SpriteID snow_offset; celestar@2233: celestar@2233: /** bitmask to the OTHER railtypes that can be used by an engine of THIS railtype */ celestar@2233: byte compatible_railtypes; celestar@2254: celestar@2254: /** celestar@2254: * Offset between the current railtype and normal rail. This means that:

celestar@2254: * 1) All the sprites in a railset MUST be in the same order. This order celestar@2254: * is determined by normal rail. Check sprites 1005 and following for this order

celestar@2254: * 2) The position where the railtype is loaded must always be the same, otherwise celestar@2254: * the offset will fail.

celestar@2254: * @note: Something more flexible might be desirable in the future. celestar@2254: */ celestar@2254: SpriteID total_offset; celestar@2536: celestar@2536: /** celestar@2536: * Bridge offset celestar@2536: */ celestar@2536: SpriteID bridge_offset; celestar@2233: } RailtypeInfo; celestar@2233: ludde@2236: extern const RailtypeInfo _railtypes[RAILTYPE_END]; celestar@2233: hackykid@2008: // these are the maximums used for updating signal blocks, and checking if a depot is in a pbs block hackykid@2008: enum { hackykid@2008: NUM_SSD_ENTRY = 256, // max amount of blocks hackykid@2008: NUM_SSD_STACK = 32 ,// max amount of blocks to check recursively hackykid@2008: }; matthijs@1942: matthijs@1948: /** matthijs@1948: * Maps a Trackdir to the corresponding TrackdirBits value matthijs@1948: */ matthijs@1948: static inline TrackdirBits TrackdirToTrackdirBits(Trackdir trackdir) { return (TrackdirBits)(1 << trackdir); } matthijs@1948: celestar@2232: /** matthijs@1942: * These functions check the validity of Tracks and Trackdirs. assert against matthijs@1942: * them when convenient. matthijs@1942: */ matthijs@1942: static inline bool IsValidTrack(Track track) { return track < TRACK_END; } matthijs@1948: static inline bool IsValidTrackdir(Trackdir trackdir) { return (TrackdirToTrackdirBits(trackdir) & TRACKDIR_BIT_MASK) != 0; } matthijs@1942: celestar@2232: /** matthijs@1942: * Functions to map tracks to the corresponding bits in the signal matthijs@1942: * presence/status bytes in the map. You should not use these directly, but matthijs@1942: * wrapper functions below instead. XXX: Which are these? matthijs@1942: */ matthijs@1942: matthijs@1942: /** matthijs@1942: * Maps a trackdir to the bit that stores its status in the map arrays, in the matthijs@1942: * direction along with the trackdir. matthijs@1942: */ matthijs@1947: extern const byte _signal_along_trackdir[TRACKDIR_END]; matthijs@1942: static inline byte SignalAlongTrackdir(Trackdir trackdir) {return _signal_along_trackdir[trackdir];} matthijs@1942: matthijs@1942: /** matthijs@1942: * Maps a trackdir to the bit that stores its status in the map arrays, in the matthijs@1942: * direction against the trackdir. matthijs@1942: */ matthijs@1948: static inline byte SignalAgainstTrackdir(Trackdir trackdir) { matthijs@1948: extern const byte _signal_against_trackdir[TRACKDIR_END]; matthijs@1948: return _signal_against_trackdir[trackdir]; matthijs@1948: } matthijs@1942: matthijs@1942: /** matthijs@1942: * Maps a Track to the bits that store the status of the two signals that can matthijs@1942: * be present on the given track. matthijs@1942: */ matthijs@1948: static inline byte SignalOnTrack(Track track) { matthijs@1948: extern const byte _signal_on_track[TRACK_END]; matthijs@1948: return _signal_on_track[track]; matthijs@1948: } matthijs@1942: matthijs@1942: /* matthijs@1942: * Some functions to query rail tiles matthijs@1942: */ matthijs@1942: matthijs@1942: /** matthijs@1942: * Returns the RailTileType of a given rail tile. (ie normal, with signals, matthijs@1942: * depot, etc.) matthijs@1942: */ matthijs@1942: static inline RailTileType GetRailTileType(TileIndex tile) matthijs@1942: { matthijs@1942: assert(IsTileType(tile, MP_RAILWAY)); tron@2548: return _m[tile].m5 & RAIL_TILE_TYPE_MASK; matthijs@1942: } matthijs@1942: matthijs@1942: /** matthijs@1942: * Returns the rail type of the given rail tile (ie rail, mono, maglev). matthijs@1942: */ tron@2049: static inline RailType GetRailType(TileIndex tile) { return (RailType)(_m[tile].m3 & RAILTYPE_MASK); } matthijs@1942: matthijs@1942: /** matthijs@1942: * Checks if a rail tile has signals. matthijs@1942: */ matthijs@1942: static inline bool HasSignals(TileIndex tile) matthijs@1942: { matthijs@1942: return GetRailTileType(tile) == RAIL_TYPE_SIGNALS; matthijs@1942: } matthijs@1942: matthijs@1942: /** matthijs@1942: * Returns the RailTileSubtype of a given rail tile with type matthijs@1942: * RAIL_TYPE_DEPOT_WAYPOINT matthijs@1942: */ matthijs@1942: static inline RailTileSubtype GetRailTileSubtype(TileIndex tile) matthijs@1942: { matthijs@1942: assert(GetRailTileType(tile) == RAIL_TYPE_DEPOT_WAYPOINT); tron@2049: return (RailTileSubtype)(_m[tile].m5 & RAIL_SUBTYPE_MASK); matthijs@1942: } matthijs@1942: matthijs@1942: /** matthijs@1942: * Returns whether this is plain rails, with or without signals. Iow, if this matthijs@1942: * tiles RailTileType is RAIL_TYPE_NORMAL or RAIL_TYPE_SIGNALS. matthijs@1942: */ matthijs@1942: static inline bool IsPlainRailTile(TileIndex tile) matthijs@1942: { matthijs@1942: RailTileType rtt = GetRailTileType(tile); matthijs@1942: return rtt == RAIL_TYPE_NORMAL || rtt == RAIL_TYPE_SIGNALS; matthijs@1942: } matthijs@1942: matthijs@1942: /** matthijs@1942: * Returns the tracks present on the given plain rail tile (IsPlainRailTile()) matthijs@1942: */ matthijs@1942: static inline TrackBits GetTrackBits(TileIndex tile) matthijs@1942: { matthijs@1942: assert(GetRailTileType(tile) == RAIL_TYPE_NORMAL || GetRailTileType(tile) == RAIL_TYPE_SIGNALS); tron@2049: return (TrackBits)(_m[tile].m5 & TRACK_BIT_MASK); matthijs@1942: } matthijs@1942: matthijs@1942: /** matthijs@1942: * Returns whether the given track is present on the given tile. Tile must be matthijs@1942: * a plain rail tile (IsPlainRailTile()). matthijs@1942: */ matthijs@1942: static inline bool HasTrack(TileIndex tile, Track track) matthijs@1942: { matthijs@1942: assert(IsValidTrack(track)); matthijs@1942: return HASBIT(GetTrackBits(tile), track); matthijs@1942: } matthijs@1942: matthijs@1942: /* matthijs@1942: * Functions describing logical relations between Tracks, TrackBits, Trackdirs matthijs@1942: * TrackdirBits, Direction and DiagDirections. matthijs@1942: * matthijs@1942: * TODO: Add #unndefs or something similar to remove the arrays used below matthijs@1942: * from the global scope and expose direct uses of them. matthijs@1942: */ matthijs@1942: matthijs@1942: /** matthijs@1944: * Maps a trackdir to the reverse trackdir. matthijs@1944: */ matthijs@1948: static inline Trackdir ReverseTrackdir(Trackdir trackdir) { matthijs@1948: extern const Trackdir _reverse_trackdir[TRACKDIR_END]; matthijs@1948: return _reverse_trackdir[trackdir]; matthijs@1948: } matthijs@1944: matthijs@1944: /* matthijs@1944: * Maps a Track to the corresponding TrackBits value matthijs@1944: */ matthijs@1944: static inline TrackBits TrackToTrackBits(Track track) { return (TrackBits)(1 << track); } matthijs@1944: matthijs@1944: /* Returns the Track that a given Trackdir represents */ matthijs@1944: static inline Track TrackdirToTrack(Trackdir trackdir) { return (Track)(trackdir & 0x7); } matthijs@1944: matthijs@1944: /* Returns a Trackdir for the given Track. Since every Track corresponds to matthijs@1944: * two Trackdirs, we choose the one which points between NE and S. matthijs@1944: * Note that the actual implementation is quite futile, but this might change matthijs@1944: * in the future. matthijs@1944: */ matthijs@1944: static inline Trackdir TrackToTrackdir(Track track) { return (Trackdir)track; } matthijs@1944: matthijs@1944: /* Returns a TrackdirBit mask that contains the two TrackdirBits that matthijs@1944: * correspond with the given Track (one for each direction). matthijs@1944: */ matthijs@1944: static inline TrackdirBits TrackToTrackdirBits(Track track) { Trackdir td = TrackToTrackdir(track); return TrackdirToTrackdirBits(td) | TrackdirToTrackdirBits(ReverseTrackdir(td));} matthijs@1944: matthijs@1944: /** matthijs@1942: * Maps a trackdir to the trackdir that you will end up on if you go straight matthijs@1942: * ahead. This will be the same trackdir for diagonal trackdirs, but a matthijs@1942: * different (alternating) one for straight trackdirs matthijs@1942: */ matthijs@1948: static inline Trackdir NextTrackdir(Trackdir trackdir) { matthijs@1948: extern const Trackdir _next_trackdir[TRACKDIR_END]; matthijs@1948: return _next_trackdir[trackdir]; matthijs@1948: } matthijs@1942: matthijs@1942: /** matthijs@1942: * Maps a track to all tracks that make 90 deg turns with it. matthijs@1942: */ matthijs@1948: static inline TrackBits TrackCrossesTracks(Track track) { matthijs@1948: extern const TrackBits _track_crosses_tracks[TRACK_END]; matthijs@1948: return _track_crosses_tracks[track]; matthijs@1948: } matthijs@1942: matthijs@1942: /** matthijs@1942: * Maps a trackdir to the (4-way) direction the tile is exited when following matthijs@1942: * that trackdir. matthijs@1942: */ matthijs@1948: static inline DiagDirection TrackdirToExitdir(Trackdir trackdir) { matthijs@1948: extern const DiagDirection _trackdir_to_exitdir[TRACKDIR_END]; matthijs@1948: return _trackdir_to_exitdir[trackdir]; matthijs@1948: } matthijs@1942: matthijs@1942: /** matthijs@1942: * Maps a track and an (4-way) dir to the trackdir that represents the track matthijs@1942: * with the exit in the given direction. matthijs@1942: */ matthijs@1948: static inline Trackdir TrackExitdirToTrackdir(Track track, DiagDirection diagdir) { matthijs@1948: extern const Trackdir _track_exitdir_to_trackdir[TRACK_END][DIAGDIR_END]; matthijs@1948: return _track_exitdir_to_trackdir[track][diagdir]; matthijs@1948: } matthijs@1942: matthijs@1942: /** hackykid@2008: * Maps a track and an (4-way) dir to the trackdir that represents the track hackykid@2008: * with the exit in the given direction. hackykid@2008: */ hackykid@2008: static inline Trackdir TrackEnterdirToTrackdir(Track track, DiagDirection diagdir) { hackykid@2008: extern const Trackdir _track_enterdir_to_trackdir[TRACK_END][DIAGDIR_END]; hackykid@2008: return _track_enterdir_to_trackdir[track][diagdir]; hackykid@2008: } hackykid@2008: hackykid@2008: /** matthijs@1942: * Maps a track and a full (8-way) direction to the trackdir that represents matthijs@1942: * the track running in the given direction. matthijs@1942: */ matthijs@1948: static inline Trackdir TrackDirectionToTrackdir(Track track, Direction dir) { matthijs@1948: extern const Trackdir _track_direction_to_trackdir[TRACK_END][DIR_END]; matthijs@1948: return _track_direction_to_trackdir[track][dir]; matthijs@1948: } matthijs@1942: matthijs@1942: /** matthijs@1942: * Maps a (4-way) direction to the diagonal trackdir that runs in that matthijs@1942: * direction. matthijs@1942: */ matthijs@1948: static inline Trackdir DiagdirToDiagTrackdir(DiagDirection diagdir) { matthijs@1948: extern const Trackdir _dir_to_diag_trackdir[DIAGDIR_END]; matthijs@1948: return _dir_to_diag_trackdir[diagdir]; matthijs@1948: } matthijs@1942: matthijs@1942: /** matthijs@1942: * Maps a trackdir to the trackdirs that can be reached from it (ie, when matthijs@1942: * entering the next tile. This matthijs@1942: */ matthijs@1947: extern const TrackdirBits _exitdir_reaches_trackdirs[DIAGDIR_END]; matthijs@1942: /* Note that there is no direct table for this function (there used to be), matthijs@1942: * but it uses two simpeler tables to achieve the result */ matthijs@1942: static inline TrackdirBits TrackdirReachesTrackdirs(Trackdir trackdir) { return _exitdir_reaches_trackdirs[TrackdirToExitdir(trackdir)]; } matthijs@1942: matthijs@1942: /** matthijs@1942: * Maps a trackdir to all trackdirs that make 90 deg turns with it. matthijs@1942: */ matthijs@1948: static inline TrackdirBits TrackdirCrossesTrackdirs(Trackdir trackdir) { matthijs@1948: extern const TrackdirBits _track_crosses_trackdirs[TRACKDIR_END]; matthijs@1948: return _track_crosses_trackdirs[TrackdirToTrack(trackdir)]; matthijs@1948: } matthijs@1942: matthijs@1942: /** matthijs@1942: * Maps a (4-way) direction to the reverse. matthijs@1942: */ matthijs@1948: static inline DiagDirection ReverseDiagdir(DiagDirection diagdir) { matthijs@1948: extern const DiagDirection _reverse_diagdir[DIAGDIR_END]; matthijs@1948: return _reverse_diagdir[diagdir]; matthijs@1948: } matthijs@1942: hackykid@2008: /** hackykid@2008: * Maps a (8-way) direction to a (4-way) DiagDirection hackykid@2008: */ hackykid@2008: static inline DiagDirection DirToDiagdir(Direction dir) { hackykid@2008: assert(dir < DIR_END); hackykid@2008: return (DiagDirection)(dir >> 1); hackykid@2008: } hackykid@2008: matthijs@1942: /* Checks if a given Track is diagonal */ matthijs@1944: static inline bool IsDiagonalTrack(Track track) { return (track == TRACK_DIAG1) || (track == TRACK_DIAG2); } matthijs@1942: matthijs@1942: /* Checks if a given Trackdir is diagonal. */ matthijs@1942: static inline bool IsDiagonalTrackdir(Trackdir trackdir) { return IsDiagonalTrack(TrackdirToTrack(trackdir)); } matthijs@1942: matthijs@1942: /* matthijs@1942: * Functions quering signals on tiles. matthijs@1942: */ matthijs@1942: matthijs@1942: /** matthijs@1944: * Checks for the presence of signals (either way) on the given track on the matthijs@1944: * given rail tile. matthijs@1942: */ matthijs@1942: static inline bool HasSignalOnTrack(TileIndex tile, Track track) matthijs@1942: { matthijs@1942: assert(IsValidTrack(track)); tron@2049: return ((GetRailTileType(tile) == RAIL_TYPE_SIGNALS) && ((_m[tile].m3 & SignalOnTrack(track)) != 0)); matthijs@1944: } matthijs@1944: matthijs@1944: /** matthijs@1944: * Checks for the presence of signals along the given trackdir on the given matthijs@1944: * rail tile. matthijs@1944: * matthijs@1944: * Along meaning if you are currently driving on the given trackdir, this is matthijs@1944: * the signal that is facing us (for which we stop when it's red). matthijs@1944: */ matthijs@1944: static inline bool HasSignalOnTrackdir(TileIndex tile, Trackdir trackdir) matthijs@1944: { matthijs@1944: assert (IsValidTrackdir(trackdir)); tron@2049: return (GetRailTileType(tile) == RAIL_TYPE_SIGNALS) && (_m[tile].m3 & SignalAlongTrackdir(trackdir)); matthijs@1942: } matthijs@1942: matthijs@1942: /** matthijs@1942: * Gets the state of the signal along the given trackdir. matthijs@1942: * matthijs@1942: * Along meaning if you are currently driving on the given trackdir, this is matthijs@1942: * the signal that is facing us (for which we stop when it's red). matthijs@1942: */ matthijs@1942: static inline SignalState GetSignalState(TileIndex tile, Trackdir trackdir) matthijs@1942: { matthijs@1942: assert(IsValidTrackdir(trackdir)); matthijs@1942: assert(HasSignalOnTrack(tile, TrackdirToTrack(trackdir))); tron@2049: return ((_m[tile].m2 & SignalAlongTrackdir(trackdir))?SIGNAL_STATE_GREEN:SIGNAL_STATE_RED); matthijs@1942: } matthijs@1942: matthijs@1942: /** matthijs@1942: * Gets the type of signal on a given track on a given rail tile with signals. matthijs@1942: * matthijs@1942: * Note that currently, the track argument is not used, since matthijs@1942: * signal types cannot be mixed. This function is trying to be matthijs@1942: * future-compatible, though. matthijs@1942: */ matthijs@1942: static inline SignalType GetSignalType(TileIndex tile, Track track) matthijs@1942: { matthijs@1942: assert(IsValidTrack(track)); matthijs@1942: assert(GetRailTileType(tile) == RAIL_TYPE_SIGNALS); tron@2049: return (SignalType)(_m[tile].m4 & SIGTYPE_MASK); matthijs@1942: } matthijs@1942: matthijs@1942: /** matthijs@1942: * Checks if this tile contains semaphores (returns true) or normal signals matthijs@1942: * (returns false) on the given track. Does not check if there are actually matthijs@1942: * signals on the track, you should use HasSignalsOnTrack() for that. matthijs@1942: * matthijs@1942: * Note that currently, the track argument is not used, since matthijs@1942: * semaphores/electric signals cannot be mixed. This function is trying to be matthijs@1942: * future-compatible, though. matthijs@1942: */ matthijs@1942: static inline bool HasSemaphores(TileIndex tile, Track track) matthijs@1942: { matthijs@1942: assert(IsValidTrack(track)); tron@2049: return (_m[tile].m4 & SIG_SEMAPHORE_MASK); matthijs@1942: } matthijs@1942: matthijs@1950: /** matthijs@1950: * Return the rail type of tile, or INVALID_RAILTYPE if this is no rail tile. matthijs@1950: * Note that there is no check if the given trackdir is actually present on matthijs@1950: * the tile! matthijs@1950: * The given trackdir is used when there are (could be) multiple rail types on matthijs@1950: * one tile. matthijs@1950: */ matthijs@2006: RailType GetTileRailType(TileIndex tile, Trackdir trackdir); matthijs@1950: matthijs@1967: /** matthijs@1967: * Returns whether the given tile is a level crossing. matthijs@1967: */ matthijs@1967: static inline bool IsLevelCrossing(TileIndex tile) matthijs@1967: { tron@2049: return (_m[tile].m5 & 0xF0) == 0x10; matthijs@1967: } matthijs@1967: matthijs@1967: /** matthijs@1967: * Gets the transport type of the given track on the given crossing tile. matthijs@1967: * @return The transport type of the given track, either TRANSPORT_ROAD, matthijs@1967: * TRANSPORT_RAIL. matthijs@1967: */ matthijs@1967: static inline TransportType GetCrossingTransportType(TileIndex tile, Track track) matthijs@1967: { matthijs@1967: /* XXX: Nicer way to write this? */ matthijs@1967: switch(track) matthijs@1967: { matthijs@1967: /* When map5 bit 3 is set, the road runs in the y direction (DIAG2) */ matthijs@1967: case TRACK_DIAG1: tron@2049: return (HASBIT(_m[tile].m5, 3) ? TRANSPORT_RAIL : TRANSPORT_ROAD); matthijs@1967: case TRACK_DIAG2: tron@2049: return (HASBIT(_m[tile].m5, 3) ? TRANSPORT_ROAD : TRANSPORT_RAIL); matthijs@1967: default: matthijs@1967: assert(0); matthijs@1967: } matthijs@1967: return INVALID_TRANSPORT; matthijs@1967: } matthijs@1967: matthijs@2006: /** celestar@2233: * Returns a pointer to the Railtype information for a given railtype celestar@2233: * @param railtype the rail type which the information is requested for celestar@2233: * @return The pointer to the RailtypeInfo celestar@2233: */ ludde@2236: static inline const RailtypeInfo *GetRailTypeInfo(RailType railtype) celestar@2233: { celestar@2233: assert(railtype < RAILTYPE_END); ludde@2236: return &_railtypes[railtype]; celestar@2233: } celestar@2233: celestar@2233: /** matthijs@2006: * Checks if an engine of the given RailType can drive on a tile with a given matthijs@2006: * RailType. This would normally just be an equality check, but for electric matthijs@2006: * rails (which also support non-electric engines). matthijs@2006: * @return Whether the engine can drive on this tile. matthijs@2006: * @param enginetype The RailType of the engine we are considering. matthijs@2006: * @param tiletype The RailType of the tile we are considering. matthijs@2006: */ matthijs@2006: static inline bool IsCompatibleRail(RailType enginetype, RailType tiletype) matthijs@2006: { celestar@2233: return HASBIT(GetRailTypeInfo(enginetype)->compatible_railtypes, tiletype); matthijs@2006: } matthijs@2006: peter1138@2472: void DrawTrackBits(TileInfo *ti, TrackBits track, bool earth, bool snow, bool flat); tron@2520: void DrawTrainDepotSprite(int x, int y, int image, RailType railtype); tron@2520: void DrawDefaultWaypointSprite(int x, int y, RailType railtype); celestar@2536: #endif /* RAIL_H */