/* * This file is part of OpenTTD. * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . */ /** @file tunnelbridge_map.h Functions that have tunnels and bridges in common */ #ifndef TUNNELBRIDGE_MAP_H #define TUNNELBRIDGE_MAP_H #include "bridge_map.h" #include "tunnel_base.h" #include "cmd_helper.h" #include "signal_type.h" #include "tunnel_map.h" #include "track_func.h" #include "settings_type.h" #include "vehicle_type.h" #include "core/bitmath_func.hpp" /** * Get the direction pointing to the other end. * * Tunnel: Get the direction facing into the tunnel * Bridge: Get the direction pointing onto the bridge * @param t The tile to analyze * @pre IsTileType(t, MP_TUNNELBRIDGE) * @return the above mentioned direction */ inline DiagDirection GetTunnelBridgeDirection(TileIndex t) { assert_tile(IsTileType(t, MP_TUNNELBRIDGE), t); return (DiagDirection)GB(_m[t].m5, 0, 2); } /** * Tunnel: Get the transport type of the tunnel (road or rail) * Bridge: Get the transport type of the bridge's ramp * @param t The tile to analyze * @pre IsTileType(t, MP_TUNNELBRIDGE) * @return the transport type in the tunnel/bridge */ inline TransportType GetTunnelBridgeTransportType(TileIndex t) { assert_tile(IsTileType(t, MP_TUNNELBRIDGE), t); return (TransportType)GB(_m[t].m5, 2, 2); } inline uint8_t GetTunnelBridgeGroundBits(TileIndex t) { assert_tile(IsTileType(t, MP_TUNNELBRIDGE), t); return GB(_me[t].m7, 5, 3); } /** * Tunnel: Is this tunnel entrance in a snowy or desert area? * Bridge: Does the bridge ramp lie in a snow or desert area? * @param t The tile to analyze * @pre IsTileType(t, MP_TUNNELBRIDGE) * @return true if and only if the tile is in a snowy/desert area */ inline bool HasTunnelBridgeSnowOrDesert(TileIndex t) { return GetTunnelBridgeGroundBits(t) == 1; } /** * Is this a rail bridge or tunnel? * @param t the tile that might be a rail bridge or tunnel * @return true if and only if this tile is a rail bridge or tunnel */ inline bool IsRailTunnelBridgeTile(TileIndex t) { return IsTileType(t, MP_TUNNELBRIDGE) && (Extract(_m[t].m5) == TRANSPORT_RAIL); } inline void SetTunnelBridgeGroundBits(TileIndex t, uint8_t bits) { assert_tile(IsTileType(t, MP_TUNNELBRIDGE), t); SB(_me[t].m7, 5, 3, bits); } /** * Tunnel: Places this tunnel entrance in a snowy or desert area, or takes it out of there. * Bridge: Sets whether the bridge ramp lies in a snow or desert area. * @param t the tunnel entrance / bridge ramp tile * @param snow_or_desert is the entrance/ramp in snow or desert (true), when * not in snow and not in desert false * @pre IsTileType(t, MP_TUNNELBRIDGE) */ inline void SetTunnelBridgeSnowOrDesert(TileIndex t, bool snow_or_desert) { SetTunnelBridgeGroundBits(t, snow_or_desert ? 1 : 0); } /** * Determines type of the wormhole and returns its other end * @param t one end * @pre IsTileType(t, MP_TUNNELBRIDGE) * @return other end */ inline TileIndex GetOtherTunnelBridgeEnd(TileIndex t) { assert_tile(IsTileType(t, MP_TUNNELBRIDGE), t); return IsTunnel(t) ? GetOtherTunnelEnd(t) : GetOtherBridgeEnd(t); } /** * Get the track bits for a rail tunnel/bridge * @pre IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL * @param t the tile * @return reserved track bits */ inline TrackBits GetTunnelBridgeTrackBits(TileIndex t) { if (IsTunnel(t)) { return DiagDirToDiagTrackBits(GetTunnelBridgeDirection(t)); } else { return GetCustomBridgeHeadTrackBits(t); } } /** * Get the primary railtype track bits for a rail tunnel/bridge * @pre IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL * @param t the tile * @return reserved track bits */ inline TrackBits GetPrimaryTunnelBridgeTrackBits(TileIndex t) { if (IsTunnel(t)) { return DiagDirToDiagTrackBits(GetTunnelBridgeDirection(t)); } else { TrackBits bits = GetCustomBridgeHeadTrackBits(t); if (bits == TRACK_BIT_HORZ || bits == TRACK_BIT_VERT) { return bits & GetAcrossBridgePossibleTrackBits(t); } else { return bits; } } } /** * Get the secondary railtype track bits for a rail tunnel/bridge * @pre IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL * @param t the tile * @return reserved track bits */ inline TrackBits GetSecondaryTunnelBridgeTrackBits(TileIndex t) { if (IsTunnel(t)) { return TRACK_BIT_NONE; } else { TrackBits bits = GetCustomBridgeHeadTrackBits(t); if (bits == TRACK_BIT_HORZ || bits == TRACK_BIT_VERT) { return bits & (~GetAcrossBridgePossibleTrackBits(t)); } else { return TRACK_BIT_NONE; } } } /** * Get the track bits for a rail tunnel/bridge onto/across the tunnel/bridge * @pre IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL * @param t the tile * @return reserved track bits */ inline TrackBits GetAcrossTunnelBridgeTrackBits(TileIndex t) { if (IsTunnel(t)) { return DiagDirToDiagTrackBits(GetTunnelBridgeDirection(t)); } else { return GetCustomBridgeHeadTrackBits(t) & GetAcrossBridgePossibleTrackBits(t); } } /** * Get the reserved track bits for a rail tunnel/bridge * @pre IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL * @param t the tile * @return reserved track bits */ inline TrackBits GetTunnelBridgeReservationTrackBits(TileIndex t) { if (IsTunnel(t)) { return HasTunnelReservation(t) ? DiagDirToDiagTrackBits(GetTunnelBridgeDirection(t)) : TRACK_BIT_NONE; } else { return GetBridgeReservationTrackBits(t); } } /** * Get the reserved track bits for a rail tunnel/bridge onto/across the tunnel/bridge * @pre IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL * @param t the tile * @return reserved track bits */ inline TrackBits GetAcrossTunnelBridgeReservationTrackBits(TileIndex t) { if (IsTunnel(t)) { return HasTunnelReservation(t) ? DiagDirToDiagTrackBits(GetTunnelBridgeDirection(t)) : TRACK_BIT_NONE; } else { return GetAcrossBridgeReservationTrackBits(t); } } /** * Get whether there are reserved track bits for a rail tunnel/bridge onto/across the tunnel/bridge * @pre IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL * @param t the tile * @return whether there are reserved track bits */ inline bool HasAcrossTunnelBridgeReservation(TileIndex t) { if (IsTunnel(t)) { return HasTunnelReservation(t); } else { return GetAcrossBridgeReservationTrackBits(t) != TRACK_BIT_NONE; } } /** * Get the rail infrastructure count of a rail tunnel/bridge head tile (excluding the tunnel/bridge middle) * @param bits the track bits * @return rail infrastructure count */ inline uint GetTunnelBridgeHeadOnlyRailInfrastructureCountFromTrackBits(TrackBits bits) { uint pieces = CountBits(bits); if (TracksOverlap(bits)) pieces *= pieces; return (TUNNELBRIDGE_TRACKBIT_FACTOR / 2) * (1 + pieces); } /** * Get the primary railtype rail infrastructure count of a rail tunnel/bridge head tile (excluding the tunnel/bridge middle) * @pre IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL * @param t the tile * @return rail infrastructure count */ inline uint GetTunnelBridgeHeadOnlyPrimaryRailInfrastructureCount(TileIndex t) { return IsBridge(t) ? GetTunnelBridgeHeadOnlyRailInfrastructureCountFromTrackBits(GetPrimaryTunnelBridgeTrackBits(t)) : TUNNELBRIDGE_TRACKBIT_FACTOR; } /** * Get the secondary railtype rail infrastructure count of a rail tunnel/bridge head tile (excluding the tunnel/bridge middle) * @pre IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL * @param t the tile * @return rail infrastructure count */ inline uint GetTunnelBridgeHeadOnlySecondaryRailInfrastructureCount(TileIndex t) { return IsBridge(t) && GetSecondaryTunnelBridgeTrackBits(t) ? (TUNNELBRIDGE_TRACKBIT_FACTOR / 2) : 0; } /** * Check if the given track direction on a rail bridge head tile enters the bridge * @pre IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL * @param t the tile * @param td track direction * @return reservation state */ inline bool TrackdirEntersTunnelBridge(TileIndex t, Trackdir td) { assert_tile(IsTileType(t, MP_TUNNELBRIDGE), t); assert_tile(GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL, t); return TrackdirToExitdir(td) == GetTunnelBridgeDirection(t); } /** * Check if the given track direction on a rail bridge head tile exits the bridge * @pre IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL * @param t the tile * @param td track direction * @return reservation state */ inline bool TrackdirExitsTunnelBridge(TileIndex t, Trackdir td) { assert_tile(IsTileType(t, MP_TUNNELBRIDGE), t); assert_tile(GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL, t); return TrackdirToExitdir(ReverseTrackdir(td)) == GetTunnelBridgeDirection(t); } /** * Check if the given track on a rail bridge head tile enters/exits the bridge * @pre IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL * @param tile the tile * @param t track * @return reservation state */ inline bool IsTrackAcrossTunnelBridge(TileIndex tile, Track t) { assert_tile(IsTileType(tile, MP_TUNNELBRIDGE), tile); assert_tile(GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL, tile); return DiagdirReachesTracks(ReverseDiagDir(GetTunnelBridgeDirection(tile))) & TrackToTrackBits(t); } /** * Lift the reservation of a specific track on a tunnel or rail bridge head tile * @pre IsTileType(tile, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL * @param tile the tile */ inline void UnreserveAcrossRailTunnelBridge(TileIndex tile) { assert_tile(IsTileType(tile, MP_TUNNELBRIDGE), tile); assert_tile(GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL, tile); if (IsTunnel(tile)) { SetTunnelReservation(tile, false); } else { UnreserveAcrossRailBridgeHead(tile); } } /** * Declare tunnel/bridge entrance with signal simulation. * @param t the tunnel/bridge tile. */ inline void SetTunnelBridgeSignalSimulationEntrance(TileIndex t) { assert_tile(IsTileType(t, MP_TUNNELBRIDGE), t); SetBit(_m[t].m5, 5); } /** * Remove tunnel/bridge entrance with signal simulation. * @param t the tunnel/bridge tile. */ inline void ClrTunnelBridgeSignalSimulationEntrance(TileIndex t) { assert_tile(IsTileType(t, MP_TUNNELBRIDGE), t); ClrBit(_m[t].m5, 5); } /** * Declare tunnel/bridge exit with signal simulation. * @param t the tunnel/bridge tile. */ inline void SetTunnelBridgeSignalSimulationExit(TileIndex t) { assert_tile(IsTileType(t, MP_TUNNELBRIDGE), t); SetBit(_m[t].m5, 6); } /** * Remove tunnel/bridge exit with signal simulation. * @param t the tunnel/bridge tile. */ inline void ClrTunnelBridgeSignalSimulationExit(TileIndex t) { assert_tile(IsTileType(t, MP_TUNNELBRIDGE), t); ClrBit(_m[t].m5, 6); } /** * Is this a tunnel/bridge pair with signal simulation? * On tunnel/bridge pair minimal one of the two bits is set. * @param t the tile that might be a tunnel/bridge. * @return true if and only if this tile is a tunnel/bridge with signal simulation. */ inline bool IsTunnelBridgeWithSignalSimulation(TileIndex t) { return IsTileType(t, MP_TUNNELBRIDGE) && (HasBit(_m[t].m5, 5) || HasBit(_m[t].m5, 6)); } /** * Is this a tunnel/bridge entrance tile with signal? * Tunnel bridge signal simulation has allways bit 5 on at entrance. * @param t the tile that might be a tunnel/bridge. * @pre IsTileType(t, MP_TUNNELBRIDGE) * @return true if and only if this tile is a tunnel/bridge entrance. */ inline bool IsTunnelBridgeSignalSimulationEntrance(TileIndex t) { assert_tile(IsTileType(t, MP_TUNNELBRIDGE), t); return HasBit(_m[t].m5, 5); } /** * Is this a tunnel/bridge entrance tile with signal? * Tunnel bridge signal simulation has allways bit 5 on at entrance. * @param t the tile that might be a tunnel/bridge. * @return true if and only if this tile is a tunnel/bridge entrance. */ inline bool IsTunnelBridgeSignalSimulationEntranceTile(TileIndex t) { return IsTileType(t, MP_TUNNELBRIDGE) && HasBit(_m[t].m5, 5); } /** * Is this a tunnel/bridge entrance tile with signal only? * @param t the tile that might be a tunnel/bridge. * @pre IsTileType(t, MP_TUNNELBRIDGE) * @return true if and only if this tile is a tunnel/bridge entrance only. */ inline bool IsTunnelBridgeSignalSimulationEntranceOnly(TileIndex t) { assert_tile(IsTileType(t, MP_TUNNELBRIDGE), t); return HasBit(_m[t].m5, 5) && !HasBit(_m[t].m5, 6); } /** * Is this a tunnel/bridge exit? * @param t the tile that might be a tunnel/bridge. * @pre IsTileType(t, MP_TUNNELBRIDGE) * @return true if and only if this tile is a tunnel/bridge exit. */ inline bool IsTunnelBridgeSignalSimulationExit(TileIndex t) { assert_tile(IsTileType(t, MP_TUNNELBRIDGE), t); return HasBit(_m[t].m5, 6); } /** * Is this a tunnel/bridge exit? * @param t the tile that might be a tunnel/bridge. * @return true if and only if this tile is a tunnel/bridge exit. */ inline bool IsTunnelBridgeSignalSimulationExitTile(TileIndex t) { return IsTileType(t, MP_TUNNELBRIDGE) && HasBit(_m[t].m5, 6); } /** * Is this a tunnel/bridge exit only? * @param t the tile that might be a tunnel/bridge. * @pre IsTileType(t, MP_TUNNELBRIDGE) * @return true if and only if this tile is a tunnel/bridge exit only. */ inline bool IsTunnelBridgeSignalSimulationExitOnly(TileIndex t) { assert_tile(IsTileType(t, MP_TUNNELBRIDGE), t); return !HasBit(_m[t].m5, 5) && HasBit(_m[t].m5, 6); } /** * Is this a tunnel/bridge entrance and exit? * @param t the tile that might be a tunnel/bridge. * @pre IsTileType(t, MP_TUNNELBRIDGE) * @return true if and only if this tile is a tunnel/bridge entrance and exit. */ inline bool IsTunnelBridgeSignalSimulationBidirectional(TileIndex t) { assert_tile(IsTileType(t, MP_TUNNELBRIDGE), t); return HasBit(_m[t].m5, 5) && HasBit(_m[t].m5, 6); } /** * Get the signal state for a tunnel/bridge entrance with signal simulation * @param t the tunnel/bridge entrance or exit tile with signal simulation * @pre IsTunnelBridgeWithSignalSimulation(t) * @return signal state */ inline SignalState GetTunnelBridgeEntranceSignalState(TileIndex t) { assert_tile(IsTunnelBridgeSignalSimulationEntrance(t), t); return HasBit(_me[t].m6, 0) ? SIGNAL_STATE_GREEN : SIGNAL_STATE_RED; } /** * Get the signal state for a tunnel/bridge exit with signal simulation * @param t the tunnel/bridge entrance or exit tile with signal simulation * @pre IsTunnelBridgeWithSignalSimulation(t) * @return signal state */ inline SignalState GetTunnelBridgeExitSignalState(TileIndex t) { assert_tile(IsTunnelBridgeSignalSimulationExit(t), t); return HasBit(_me[t].m6, 7) ? SIGNAL_STATE_GREEN : SIGNAL_STATE_RED; } /** * Set the signal state for a tunnel/bridge entrance or exit with signal simulation * @param t the tunnel/bridge entrance or exit tile with signal simulation * @pre IsTunnelBridgeWithSignalSimulation(t) * @param state signal state */ inline void SetTunnelBridgeEntranceSignalState(TileIndex t, SignalState state) { assert_tile(IsTunnelBridgeSignalSimulationEntrance(t), t); SB(_me[t].m6, 0, 1, (state == SIGNAL_STATE_GREEN) ? 1 : 0); } /** * Set the signal state for a tunnel/bridge entrance or exit with signal simulation * @param t the tunnel/bridge entrance or exit tile with signal simulation * @pre IsTunnelBridgeWithSignalSimulation(t) * @param state signal state */ inline void SetTunnelBridgeExitSignalState(TileIndex t, SignalState state) { assert_tile(IsTunnelBridgeSignalSimulationExit(t), t); SB(_me[t].m6, 7, 1, (state == SIGNAL_STATE_GREEN) ? 1 : 0); } inline bool IsTunnelBridgeSemaphore(TileIndex t) { assert_tile(IsTunnelBridgeWithSignalSimulation(t), t); return HasBit(_me[t].m6, 1); } inline void SetTunnelBridgeSemaphore(TileIndex t, bool is_semaphore) { assert_tile(IsTunnelBridgeWithSignalSimulation(t), t); SB(_me[t].m6, 1, 1, is_semaphore ? 1 : 0); } inline bool IsTunnelBridgePBS(TileIndex t) { assert_tile(IsTunnelBridgeWithSignalSimulation(t), t); return HasBit(_me[t].m6, 6); } inline bool IsTunnelBridgeEffectivelyPBS(TileIndex t) { return _settings_game.vehicle.train_braking_model == TBM_REALISTIC || IsTunnelBridgePBS(t); } inline void SetTunnelBridgePBS(TileIndex t, bool is_pbs) { assert_tile(IsTunnelBridgeWithSignalSimulation(t), t); SB(_me[t].m6, 6, 1, is_pbs ? 1 : 0); } inline uint8_t GetTunnelBridgeEntranceSignalAspect(TileIndex t) { assert_tile(IsTunnelBridgeWithSignalSimulation(t), t); return GB(_m[t].m3, 0, 3); } inline void SetTunnelBridgeEntranceSignalAspect(TileIndex t, uint8_t aspect) { assert_tile(IsTunnelBridgeWithSignalSimulation(t), t); SB(_m[t].m3, 0, 3, aspect); } inline uint8_t GetTunnelBridgeExitSignalAspect(TileIndex t) { assert_tile(IsTunnelBridgeWithSignalSimulation(t), t); return GB(_m[t].m3, 3, 3); } inline void SetTunnelBridgeExitSignalAspect(TileIndex t, uint8_t aspect) { assert_tile(IsTunnelBridgeWithSignalSimulation(t), t); SB(_m[t].m3, 3, 3, aspect); } inline uint GetTunnelBridgeSignalSimulationSpacing(TileIndex t) { assert_tile(IsRailTunnelBridgeTile(t), t); return 1 + GB(_me[t].m8, 12, 4); } inline void SetTunnelBridgeSignalSimulationSpacing(TileIndex t, uint spacing) { assert_tile(IsRailTunnelBridgeTile(t), t); SB(_me[t].m8, 12, 4, spacing - 1); } /** * Does tunnel/bridge signal tile have "one or more trace restrict mappings present" bit set * @param tile the tile to check */ inline bool IsTunnelBridgeRestrictedSignal(TileIndex tile) { assert_tile(IsTunnelBridgeWithSignalSimulation(tile), tile); return (bool) GB(_m[tile].m3, 6, 1); } /** * Set tunnel/bridge signal tile "one or more trace restrict mappings present" bit * @param tile the tile to set */ inline void SetTunnelBridgeRestrictedSignal(TileIndex tile, bool is_restricted) { assert_tile(IsTunnelBridgeWithSignalSimulation(tile), tile); SB(_m[tile].m3, 6, 1, is_restricted); } inline Trackdir GetTunnelBridgeExitTrackdir(TileIndex t, DiagDirection tunnel_bridge_dir) { return TrackEnterdirToTrackdir((Track)FindFirstBit(GetAcrossTunnelBridgeTrackBits(t)), ReverseDiagDir(tunnel_bridge_dir)); } inline Trackdir GetTunnelBridgeExitTrackdir(TileIndex t) { return GetTunnelBridgeExitTrackdir(t, GetTunnelBridgeDirection(t)); } inline Trackdir GetTunnelBridgeEntranceTrackdir(TileIndex t, DiagDirection tunnel_bridge_dir) { return TrackExitdirToTrackdir((Track)FindFirstBit(GetAcrossTunnelBridgeTrackBits(t)), tunnel_bridge_dir); } inline Trackdir GetTunnelBridgeEntranceTrackdir(TileIndex t) { return GetTunnelBridgeEntranceTrackdir(t, GetTunnelBridgeDirection(t)); } inline void SetTunnelBridgeSignalStyle(TileIndex t, TileIndex end, uint8_t style) { if (style == 0 && !HasBit(_m[t].m3, 7)) return; extern void SetTunnelBridgeSignalStyleExtended(TileIndex t, TileIndex end, uint8_t style); SetTunnelBridgeSignalStyleExtended(t, end, style); } inline uint8_t GetTunnelBridgeSignalStyle(TileIndex t) { if (likely(!HasBit(_m[t].m3, 7))) return 0; if (IsTunnel(t)) { extern uint8_t GetTunnelSignalStyleExtended(TileIndex t); return GetTunnelSignalStyleExtended(t); } else { extern uint8_t GetBridgeSignalStyleExtended(TileIndex t); return GetBridgeSignalStyleExtended(t); } } void AddRailTunnelBridgeInfrastructure(Company *c, TileIndex begin, TileIndex end); void SubtractRailTunnelBridgeInfrastructure(Company *c, TileIndex begin, TileIndex end); void AddRailTunnelBridgeInfrastructure(TileIndex begin, TileIndex end); void SubtractRailTunnelBridgeInfrastructure(TileIndex begin, TileIndex end); void AddRoadTunnelBridgeInfrastructure(TileIndex begin, TileIndex end); void SubtractRoadTunnelBridgeInfrastructure(TileIndex begin, TileIndex end); #endif /* TUNNELBRIDGE_MAP_H */