diff --git a/docs/landscape.html b/docs/landscape.html
index 9a92ba9c0b..15333cc8f3 100644
--- a/docs/landscape.html
+++ b/docs/landscape.html
@@ -407,6 +407,39 @@
m4 bits 7..4: bit clear = signal 3..0 shows red
+ m2 bits 8..10: track reserved for pbs
+
+
+ 0 |
+ not reserved |
+
+
+ 1 |
+ X direction |
+
+
+ 2 |
+ Y direction |
+
+
+ 3 |
+ north corner (W-E) |
+
+
+ 4 |
+ south corner (W-E) |
+
+
+ 5 |
+ west corner (N-S) |
+
+
+ 6 |
+ east corner (N-S) |
+
+
+
+ m2 bit 11: opposite track is reserved, too
m5 bit 7 set, bit 6 clear: checkpoint
@@ -425,6 +458,7 @@
+ m5 bit 4: pbs reservation state
m5 bit 7 set, bit 6 set: railway depot
@@ -452,6 +486,7 @@
+ m5 bit 4: pbs reservation state
m6 bits 7..6 : Possibility of a bridge above, in the direction specified
@@ -582,6 +617,7 @@
m4 bit 5: set if crossing lights are on
m4 bits 4..0: owner of the road type 0 (normal road)
+ m5 bit 4: pbs reservation state
@@ -898,6 +934,7 @@
m6 bits 5..3: the station type (rail, airport, truck, bus, oilrig, dock, buoy)
m6 bit 2: 1 when a drive through road stop is built over a town owned road, otherwise 0
+ m6 bit 2: pbs reservation state for railway stations
m6 bits 1..0 : Tropic zone definition
m7: animation frame
@@ -1370,6 +1407,7 @@
m3 bits 3..0: track type for railway
m3 bits 2..0: present road types for road
m4 bit 7 set = on snow or desert
+ m5 bit 4: pbs reservation state for railway
m5 bits 7 clear: tunnel entrance/exit
m5 bit 7 set: bridge ramp
diff --git a/docs/landscape_grid.html b/docs/landscape_grid.html
index 291447f30a..e01d32460d 100644
--- a/docs/landscape_grid.html
+++ b/docs/landscape_grid.html
@@ -90,7 +90,7 @@ the array so you can quickly see what is used and what is not.
rail |
XXXX XXXX |
~~~X XXXX |
- OOOO OOOO OOOO OOOO |
+ OOOO XXXX OOOO OOOO |
OOOO ~~XX |
OOOO XXXX |
XXXX XXXX |
@@ -101,7 +101,7 @@ the array so you can quickly see what is used and what is not.
rail with signals |
-inherit- |
-inherit- |
- OOOO OOOO OXXX OXXX |
+ OOOO XXXX OXXX OXXX |
XXXX ~~XX |
XXXX XXXX |
-inherit- |
@@ -115,7 +115,7 @@ the array so you can quickly see what is used and what is not.
OOOO OOOO OOOO OOOO |
OOOO ~~XX |
OOOO XXXX |
- XXOO OOXX |
+ XXOX OXXX |
XXOO OOXX |
OOOO OOOO |
@@ -126,7 +126,7 @@ the array so you can quickly see what is used and what is not.
XXXX XXXX XXXX XXXX |
OOOO ~~XX |
OOOO XXXX |
- XXOO OOOX |
+ XXOX OOOX |
XXOO OOXX |
OOOO OOOO |
@@ -149,7 +149,7 @@ the array so you can quickly see what is used and what is not.
-inherit- |
XXXX ~~XX |
OXXX XXXX |
- XXOO XXXX |
+ XXOX XXXX |
XXOO OOXX |
-inherit- |
@@ -197,7 +197,7 @@ the array so you can quickly see what is used and what is not.
XXXX ~~XX |
XXXX XXXX |
XXXX XXXX |
- OOXX XOXX |
+ OOXX XXXX |
XXXX XXXX |
@@ -310,7 +310,7 @@ the array so you can quickly see what is used and what is not.
OOOO OOOO OOOO OOOO |
OOOO ~XXX |
XOOO OOOO |
- XOOO ~XXX |
+ XOOX ~XXX |
XXOO OOXX |
OOOO OOOO |
@@ -321,7 +321,7 @@ the array so you can quickly see what is used and what is not.
OOOO OOOO XXXX OOOO |
OOOO ~XXX |
XOOO OOOO |
- XOOO ~XXX |
+ XOOX ~XXX |
XXOO OOXX |
OOOO OOOO |
diff --git a/src/rail_map.h b/src/rail_map.h
index 8c436d055b..56eecc4732 100644
--- a/src/rail_map.h
+++ b/src/rail_map.h
@@ -224,6 +224,87 @@ static inline WaypointID GetWaypointIndex(TileIndex t)
return (WaypointID)_m[t].m2;
}
+
+/**
+ * Returns the reserved track bits of the tile
+ * @pre IsPlainRailTile(t)
+ * @param t the tile to query
+ * @return the track bits
+ */
+static inline TrackBits GetTrackReservation(TileIndex t)
+{
+ assert(IsPlainRailTile(t));
+ byte track_b = GB(_m[t].m2, 8, 3);
+ Track track = (Track)(track_b - 1); // map array saves Track+1
+ if (track_b == 0) return TRACK_BIT_NONE;
+ return (TrackBits)(TrackToTrackBits(track) | (HasBit(_m[t].m2, 11) ? TrackToTrackBits(TrackToOppositeTrack(track)) : 0));
+}
+
+/**
+ * Sets the reserved track bits of the tile
+ * @pre IsPlainRailTile(t) && !TracksOverlap(b)
+ * @param t the tile to change
+ * @param b the track bits
+ */
+static inline void SetTrackReservation(TileIndex t, TrackBits b)
+{
+ assert(IsPlainRailTile(t));
+ assert(b != INVALID_TRACK_BIT);
+ assert(!TracksOverlap(b));
+ Track track = RemoveFirstTrack(&b);
+ SB(_m[t].m2, 8, 3, track == INVALID_TRACK ? 0 : track+1);
+ SB(_m[t].m2, 11, 1, (byte)(b != TRACK_BIT_NONE));
+}
+
+/**
+ * Get the reservation state of the waypoint or depot
+ * @note Works for both waypoints and rail depots
+ * @pre IsRailWaypoint(t) || IsRailDepot(t)
+ * @param t the waypoint/depot tile
+ * @return reservation state
+ */
+static inline bool GetDepotWaypointReservation(TileIndex t)
+{
+ assert(IsRailWaypoint(t) || IsRailDepot(t));
+ return HasBit(_m[t].m5, 4);
+}
+
+/**
+ * Set the reservation state of the waypoint or depot
+ * @note Works for both waypoints and rail depots
+ * @pre IsRailWaypoint(t) || IsRailDepot(t)
+ * @param t the waypoint/depot tile
+ * @param b the reservation state
+ */
+static inline void SetDepotWaypointReservation(TileIndex t, bool b)
+{
+ assert(IsRailWaypoint(t) || IsRailDepot(t));
+ SB(_m[t].m5, 4, 1, (byte)b);
+}
+
+/**
+ * Get the reserved track bits for a waypoint
+ * @pre IsRailWaypoint(t)
+ * @param t the tile
+ * @return reserved track bits
+ */
+static inline TrackBits GetRailWaypointReservation(TileIndex t)
+{
+ return GetDepotWaypointReservation(t) ? GetRailWaypointBits(t) : TRACK_BIT_NONE;
+}
+
+/**
+ * Get the reserved track bits for a depot
+ * @pre IsRailDepot(t)
+ * @param t the tile
+ * @return reserved track bits
+ */
+static inline TrackBits GetRailDepotReservation(TileIndex t)
+{
+ return GetDepotWaypointReservation(t) ? TrackToTrackBits(GetRailDepotTrack(t)) : TRACK_BIT_NONE;
+}
+
+
static inline SignalType GetSignalType(TileIndex t, Track track)
{
assert(GetRailTileType(t) == RAIL_TILE_SIGNALS);
diff --git a/src/road_map.h b/src/road_map.h
index 756e3fcb7a..dfd88ae3fc 100644
--- a/src/road_map.h
+++ b/src/road_map.h
@@ -253,6 +253,43 @@ static inline TrackBits GetCrossingRailBits(TileIndex tile)
return AxisToTrackBits(GetCrossingRailAxis(tile));
}
+
+/**
+ * Get the reservation state of the rail crossing
+ * @pre IsLevelCrossingTile(t)
+ * @param t the crossing tile
+ * @return reservation state
+ */
+static inline bool GetCrossingReservation(TileIndex t)
+{
+ assert(IsLevelCrossingTile(t));
+ return HasBit(_m[t].m5, 4);
+}
+
+/**
+ * Set the reservation state of the rail crossing
+ * @note Works for both waypoints and rail depots
+ * @pre IsLevelCrossingTile(t)
+ * @param t the crossing tile
+ * @param b the reservation state
+ */
+static inline void SetCrossingReservation(TileIndex t, bool b)
+{
+ assert(IsLevelCrossingTile(t));
+ SB(_m[t].m5, 4, 1, b ? 1 : 0);
+}
+
+/**
+ * Get the reserved track bits for a rail crossing
+ * @pre IsLevelCrossingTile(t)
+ * @param t the tile
+ * @return reserved track bits
+ */
+static inline TrackBits GetRailCrossingReservation(TileIndex t)
+{
+ return GetCrossingReservation(t) ? GetCrossingRailBits(t) : TRACK_BIT_NONE;
+}
+
static inline bool IsCrossingBarred(TileIndex t)
{
assert(IsLevelCrossing(t));
diff --git a/src/station_map.h b/src/station_map.h
index 7422a32e5d..77d4279584 100644
--- a/src/station_map.h
+++ b/src/station_map.h
@@ -204,6 +204,41 @@ static inline bool IsCompatibleTrainStationTile(TileIndex t1, TileIndex t2)
!IsStationTileBlocked(t1);
}
+/**
+ * Get the reservation state of the rail station
+ * @pre IsRailwayStationTile(t)
+ * @param t the station tile
+ * @return reservation state
+ */
+static inline bool GetRailwayStationReservation(TileIndex t)
+{
+ assert(IsRailwayStationTile(t));
+ return HasBit(_m[t].m6, 2);
+}
+
+/**
+ * Set the reservation state of the rail station
+ * @pre IsRailwayStationTile(t)
+ * @param t the station tile
+ * @param b the reservation state
+ */
+static inline void SetRailwayStationReservation(TileIndex t, bool b)
+{
+ assert(IsRailwayStationTile(t));
+ SB(_m[t].m6, 2, 1, b ? 1 : 0);
+}
+
+/**
+ * Get the reserved track bits for a waypoint
+ * @pre IsRailwayStationTile(t)
+ * @param t the tile
+ * @return reserved track bits
+ */
+static inline TrackBits GetRailStationReservation(TileIndex t)
+{
+ return GetRailwayStationReservation(t) ? AxisToTrackBits(GetRailStationAxis(t)) : TRACK_BIT_NONE;
+}
+
static inline DiagDirection GetDockDirection(TileIndex t)
{
@@ -277,6 +312,7 @@ static inline void MakeRailStation(TileIndex t, Owner o, StationID sid, Axis a,
{
MakeStation(t, o, sid, STATION_RAIL, section + a);
SetRailType(t, rt);
+ SetRailwayStationReservation(t, false);
}
static inline void MakeRoadStop(TileIndex t, Owner o, StationID sid, RoadStopType rst, RoadTypes rt, DiagDirection d)
diff --git a/src/track_func.h b/src/track_func.h
index e6591212a7..144ea03e88 100644
--- a/src/track_func.h
+++ b/src/track_func.h
@@ -197,6 +197,21 @@ static inline bool IsValidTrackdir(Trackdir trackdir)
* TrackdirBits, Direction and DiagDirections.
*/
+/**
+ * Find the opposite track to a given track.
+ *
+ * TRACK_LOWER -> TRACK_UPPER and vice versa, likewise for left/right.
+ * TRACK_X is mapped to TRACK_Y and reversed.
+ *
+ * @param t the track to convert
+ * @return the opposite track
+ */
+static inline Track TrackToOppositeTrack(Track t)
+{
+ assert(t != INVALID_TRACK);
+ return (Track)(t ^ 1);
+}
+
/**
* Maps a trackdir to the reverse trackdir.
*
diff --git a/src/tunnelbridge_map.h b/src/tunnelbridge_map.h
index bdc709944c..5b5c6e4470 100644
--- a/src/tunnelbridge_map.h
+++ b/src/tunnelbridge_map.h
@@ -11,6 +11,7 @@
#include "bridge_map.h"
#include "tunnel_map.h"
#include "transport_type.h"
+#include "track_func.h"
/**
@@ -80,4 +81,42 @@ static inline TileIndex GetOtherTunnelBridgeEnd(TileIndex t)
return IsTunnel(t) ? GetOtherTunnelEnd(t) : GetOtherBridgeEnd(t);
}
+
+/**
+ * Get the reservation state of the rail tunnel/bridge
+ * @pre IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL
+ * @param t the tile
+ * @return reservation state
+ */
+static inline bool GetTunnelBridgeReservation(TileIndex t)
+{
+ assert(IsTileType(t, MP_TUNNELBRIDGE));
+ assert(GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL);
+ return HasBit(_m[t].m5, 4);
+}
+
+/**
+ * Set the reservation state of the rail tunnel/bridge
+ * @pre IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL
+ * @param t the tile
+ * @param b the reservation state
+ */
+static inline void SetTunnelBridgeReservation(TileIndex t, bool b)
+{
+ assert(IsTileType(t, MP_TUNNELBRIDGE));
+ assert(GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL);
+ SB(_m[t].m5, 4, 1, b ? 1 : 0);
+}
+
+/**
+ * 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
+ */
+static inline TrackBits GetRailTunnelBridgeReservation(TileIndex t)
+{
+ return GetTunnelBridgeReservation(t) ? DiagDirToDiagTrackBits(GetTunnelBridgeDirection(t)) : TRACK_BIT_NONE;
+}
+
#endif /* TUNNELBRIDGE_MAP_H */