From c4adf147b2b4007f7d1d62ad08e3ffa41b7753cf Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sun, 15 Jul 2007 15:07:16 +0200 Subject: Add debug level for PBS --- src/debug.cpp | 2 ++ src/debug.h | 1 + 2 files changed, 3 insertions(+), 0 deletions(-) diff --git a/src/debug.cpp b/src/debug.cpp index aefa0a6..50a3832 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -30,6 +30,7 @@ int _debug_yapf_level; int _debug_freetype_level; int _debug_sl_level; int _debug_station_level; +int _debug_pbs_level; struct DebugLevel { @@ -54,6 +55,7 @@ struct DebugLevel { DEBUG_LEVEL(freetype), DEBUG_LEVEL(sl), DEBUG_LEVEL(station), + DEBUG_LEVEL(pbs), }; #undef DEBUG_LEVEL diff --git a/src/debug.h b/src/debug.h index 5df7bfa..12dc3c5 100644 --- a/src/debug.h +++ b/src/debug.h @@ -47,6 +47,7 @@ extern int _debug_freetype_level; extern int _debug_sl_level; extern int _debug_station_level; + extern int _debug_pbs_level; void CDECL debug(const char *dbg, ...); #endif /* NO_DEBUG_MESSAGES */ -- 1.5.3.5 From eefc0589a768a019e51205a9c78b1e7e427f7c68 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Fri, 1 Feb 2008 23:18:47 +0100 Subject: Add map accessors for PBS reservations. --- docs/landscape.html | 38 +++++++++++++++++++ docs/landscape_grid.html | 14 +++--- src/rail_map.h | 92 ++++++++++++++++++++++++++++++++++++++++++++++ src/road_map.h | 37 ++++++++++++++++++ src/station_map.h | 36 ++++++++++++++++++ src/track_func.h | 15 +++++++ src/tunnelbridge_map.h | 37 ++++++++++++++++++ 7 files changed, 262 insertions(+), 7 deletions(-) diff --git a/docs/landscape.html b/docs/landscape.html index 5f21fc7..38cafd4 100644 --- a/docs/landscape.html +++ b/docs/landscape.html @@ -402,6 +402,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 @@ -420,6 +453,7 @@
  • +
  • m5 bit 4: pbs reservation state
  • m5 bit 7 set, bit 6 set: railway depot @@ -447,6 +481,7 @@
  • +
  • m5 bit 4: pbs reservation state
  • m6 bits 7..6 : Possibility of a bridge above, in the direction specified
  • @@ -577,6 +612,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
  • @@ -893,6 +929,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
  • @@ -1364,6 +1401,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 b24d4a1..68858ed 100644 --- a/docs/landscape_grid.html +++ b/docs/landscape_grid.html @@ -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 OOOO OOOO @@ -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 edd9faf..8dfd6f4 100644 --- a/src/rail_map.h +++ b/src/rail_map.h @@ -156,6 +156,17 @@ static inline DiagDirection GetRailDepotDirection(TileIndex t) return (DiagDirection)GB(_m[t].m5, 0, 2); } +/** + * Returns the track of a depot, ignoring direction + * @pre IsRailDepotTile(t) + * @param t the tile to get the depot track from + * @return the track of the depot + */ +static inline Track GetRailDepotTrack(TileIndex t) +{ + return AxisToTrack(DiagDirToAxis(GetRailDepotDirection(t))); +} + /** * Returns the axis of the waypoint @@ -201,6 +212,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 + return track_b ? (TrackBits)(TrackToTrackBits(track) | (HasBit(_m[t].m2, 11) ? TrackToTrackBits(TrackToOppositeTrack(track)) : 0)) : TRACK_BIT_NONE; +} + +/** + * 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) && b != INVALID_TRACK_BIT && !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)) & 1); +} + +/** + * 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 GetWaypointReservation(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 SetWaypointReservation(TileIndex t, bool b) +{ + assert(IsRailWaypoint(t) || IsRailDepot(t)); + SB(_m[t].m5, 4, 1, (byte)b & 1); +} + +#define GetDepotReservation GetWaypointReservation +#define SetDepotReservation SetWaypointReservation + +/** + * 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 GetWaypointReservation(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 GetWaypointReservation(t) ? TrackToTrackBits(GetRailDepotTrack(t)) : TRACK_BIT_NONE; +} + + /** Type of signal, i.e. how does the signal behave? */ enum SignalType { SIGTYPE_NORMAL = 0, ///< normal signal diff --git a/src/road_map.h b/src/road_map.h index 705961b..e94fd0f 100644 --- a/src/road_map.h +++ b/src/road_map.h @@ -191,6 +191,43 @@ static inline TrackBits GetCrossingRailBits(TileIndex tile) return AxisToTrackBits(OtherAxis(GetCrossingRoadAxis(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, (byte)b & 1); +} + +/** + * 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(GetRoadTileType(t) == ROAD_TILE_CROSSING); diff --git a/src/station_map.h b/src/station_map.h index f2a2f86..02f7850 100644 --- a/src/station_map.h +++ b/src/station_map.h @@ -185,6 +185,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, (byte)b & 1); +} + +/** + * 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) { @@ -251,6 +286,7 @@ static inline void MakeStation(TileIndex t, Owner o, StationID sid, StationType _m[t].m3 = 0; _m[t].m4 = 0; _m[t].m5 = section; + _m[t].m6 = 0; SB(_m[t].m6, 3, 3, st); } diff --git a/src/track_func.h b/src/track_func.h index 47364b8..86f1d89 100644 --- a/src/track_func.h +++ b/src/track_func.h @@ -200,6 +200,21 @@ static inline bool IsValidTrackdir(Trackdir trackdir) */ /** + * 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. * * Returns the reverse trackdir of a Trackdir value. The reverse trackdir diff --git a/src/tunnelbridge_map.h b/src/tunnelbridge_map.h index 4726644..8800618 100644 --- a/src/tunnelbridge_map.h +++ b/src/tunnelbridge_map.h @@ -10,6 +10,7 @@ #include "tile_map.h" #include "bridge_map.h" #include "tunnel_map.h" +#include "track_func.h" /** @@ -77,4 +78,40 @@ 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) && 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) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL); + SB(_m[t].m5, 4, 1, (byte)b & 1); +} + +/** + * 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) ? AxisToTrackBits(DiagDirToAxis(GetTunnelBridgeDirection(t))) : TRACK_BIT_NONE; +} + #endif /* TUNNELBRIDGE_MAP_H */ -- 1.5.3.5 From a8bac932fd76b29f7d21bb46912e1697136edeb6 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Thu, 3 Jan 2008 19:56:04 +0100 Subject: Draw reserved tracks darker if PBS debug level >= 2 --- src/rail_cmd.cpp | 15 +++++++++++++++ src/road_cmd.cpp | 5 +++++ src/station_cmd.cpp | 6 ++++++ src/tunnelbridge_cmd.cpp | 7 +++++++ 4 files changed, 33 insertions(+), 0 deletions(-) mode change 100644 => 100755 projects/determineversion.vbs diff --git a/projects/determineversion.vbs b/projects/determineversion.vbs old mode 100644 new mode 100755 diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index e3217ca..35a9cb7 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -1689,6 +1689,17 @@ static void DrawTrackBits(TileInfo* ti, TrackBits track) if (track & TRACK_BIT_RIGHT) DrawGroundSprite(rti->base_sprites.single_e, PAL_NONE); } + /* PBS debugging, draw reserved tracks darker */ + if (_debug_pbs_level >= 2) { + TrackBits pbs = GetTrackReservation(ti->tile); + if (pbs & TRACK_BIT_X && (ti->tileh == SLOPE_FLAT || ti->tileh == SLOPE_ELEVATED)) DrawGroundSprite(rti->base_sprites.single_y, PALETTE_CRASH); + if (pbs & TRACK_BIT_Y && (ti->tileh == SLOPE_FLAT || ti->tileh == SLOPE_ELEVATED)) DrawGroundSprite(rti->base_sprites.single_x, PALETTE_CRASH); + if (pbs & TRACK_BIT_UPPER) AddSortableSpriteToDraw(rti->base_sprites.single_n, PALETTE_CRASH, ti->x, ti->y, 16, 16, 0, ti->z + (ti->tileh & SLOPE_N ? 8 : 0)); + if (pbs & TRACK_BIT_LOWER) AddSortableSpriteToDraw(rti->base_sprites.single_s, PALETTE_CRASH, ti->x, ti->y, 16, 16, 0, ti->z + (ti->tileh & SLOPE_S ? 8 : 0)); + if (pbs & TRACK_BIT_LEFT) AddSortableSpriteToDraw(rti->base_sprites.single_w, PALETTE_CRASH, ti->x, ti->y, 16, 16, 0, ti->z + (ti->tileh & SLOPE_W ? 8 : 0)); + if (pbs & TRACK_BIT_RIGHT) AddSortableSpriteToDraw(rti->base_sprites.single_e, PALETTE_CRASH, ti->x, ti->y, 16, 16, 0, ti->z + (ti->tileh & SLOPE_E ? 8 : 0)); + } + if (IsValidCorner(halftile_corner)) { DrawFoundation(ti, HalftileFoundation(halftile_corner)); @@ -1825,6 +1836,10 @@ default_waypoint: DrawGroundSprite(image, PAL_NONE); + /* PBS debugging, draw reserved tracks darker */ + if (_debug_pbs_level >= 2 && GetWaypointReservation(ti->tile)) + DrawGroundSprite(GetWaypointAxis(ti->tile) == AXIS_X ? rti->base_sprites.single_y : rti->base_sprites.single_x, PALETTE_CRASH); + if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti); foreach_draw_tile_seq(dtss, dts->seq) { diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index 7610b46..d05195e 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -1089,6 +1089,11 @@ static void DrawTile_Road(TileInfo *ti) } DrawGroundSprite(image, pal); + + /* PBS debugging, draw reserved tracks darker */ + if (_debug_pbs_level >= 2 && GetCrossingReservation(ti->tile)) + DrawGroundSprite(GetCrossingRoadAxis(ti->tile) == AXIS_Y ? GetRailTypeInfo(GetRailType(ti->tile))->base_sprites.single_y : GetRailTypeInfo(GetRailType(ti->tile))->base_sprites.single_x, PALETTE_CRASH); + if (HasBit(GetRoadTypes(ti->tile), ROADTYPE_TRAM)) { DrawGroundSprite(SPR_TRAMWAY_OVERLAY + (GetCrossingRoadAxis(ti->tile) ^ 1), pal); DrawTramCatenary(ti, GetCrossingRoadBits(ti->tile)); diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 538c68b..38af7e0 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -2152,6 +2152,12 @@ static void DrawTile_Station(TileInfo *ti) * but this is something else. If AI builds station with 114 it looks all weird */ DrawGroundSprite(image, HasBit(image, PALETTE_MODIFIER_COLOR) ? palette : PAL_NONE); + /* PBS debugging, draw reserved tracks darker */ + if (_debug_pbs_level >= 2 && IsRailwayStation(ti->tile) && GetRailwayStationReservation(ti->tile)) { + const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile)); + DrawGroundSprite(GetRailStationAxis(ti->tile) == AXIS_X ? rti->base_sprites.single_y : rti->base_sprites.single_x, PALETTE_CRASH); + } + if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC && IsStationTileElectrifiable(ti->tile)) DrawCatenary(ti); if (HasBit(roadtypes, ROADTYPE_TRAM)) { diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index de2bec5..c2ccb72 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -878,6 +878,13 @@ static void DrawTile_TunnelBridge(TileInfo *ti) image += GetTunnelBridgeDirection(ti->tile) * 2; DrawGroundSprite(image, PAL_NONE); + + /* PBS debugging, draw reserved tracks darker */ + if (_debug_pbs_level >= 2 && GetTunnelBridgeTransportType(ti->tile) == TRANSPORT_RAIL && GetTunnelBridgeReservation(ti->tile)) { + const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile)); + DrawGroundSprite(DiagDirToAxis(GetTunnelBridgeDirection(ti->tile)) == AXIS_X ? rti->base_sprites.single_y : rti->base_sprites.single_x, PALETTE_CRASH); + } + if (GetTunnelBridgeTransportType(ti->tile) == TRANSPORT_ROAD) { DiagDirection dir = GetTunnelBridgeDirection(ti->tile); RoadTypes rts = GetRoadTypes(ti->tile); -- 1.5.3.5 From 6f170160d6dc3e6464e05d6c737641d84055ab8c Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Thu, 3 Jan 2008 18:19:14 +0100 Subject: Function for getting the PBS reservation state of any tile. --- projects/openttd_vs80.vcproj | 8 +++++++ projects/openttd_vs90.vcproj | 8 +++++++ source.list | 2 + src/pbs.cpp | 43 ++++++++++++++++++++++++++++++++++++++++++ src/pbs.h | 13 ++++++++++++ 5 files changed, 74 insertions(+), 0 deletions(-) create mode 100755 src/pbs.cpp create mode 100755 src/pbs.h diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj index 4bd4c4c..5d4a297 100644 --- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -656,6 +656,10 @@ > + + @@ -1060,6 +1064,10 @@ > + + diff --git a/projects/openttd_vs90.vcproj b/projects/openttd_vs90.vcproj index 9b81614..3a29077 100644 --- a/projects/openttd_vs90.vcproj +++ b/projects/openttd_vs90.vcproj @@ -653,6 +653,10 @@ > + + @@ -1057,6 +1061,10 @@ > + + diff --git a/source.list b/source.list index 4b182cf..b286361 100644 --- a/source.list +++ b/source.list @@ -55,6 +55,7 @@ os_timer.cpp ottdres.rc #end pathfind.cpp +pbs.cpp players.cpp queue.cpp rail.cpp @@ -173,6 +174,7 @@ video/null_v.h oldpool.h openttd.h pathfind.h +pbs.h player.h player_face.h queue.h diff --git a/src/pbs.cpp b/src/pbs.cpp new file mode 100755 index 0000000..c75eb8c --- /dev/null +++ b/src/pbs.cpp @@ -0,0 +1,43 @@ +/* $Id$ */ + +/** @file pbs.cpp */ + +#include "stdafx.h" +#include "openttd.h" +#include "pbs.h" +#include "rail_map.h" +#include "road_map.h" +#include "station_map.h" +#include "tunnelbridge_map.h" + +/** + * Get the reserved trackbits for any tile, regardless of type. + * @param t the tile + * @return the reserved trackbits. TRACK_BIT_NONE on nothing reserved or + * a tile without rail. + */ +TrackBits GetReservedTrackbits(TileIndex t) +{ + switch (GetTileType(t)) { + case MP_RAILWAY: + if (IsRailWaypoint(t) || IsRailDepot(t)) return GetRailWaypointReservation(t); + if (IsPlainRailTile(t)) return GetTrackReservation(t); + break; + + case MP_ROAD: + if (IsLevelCrossing(t)) return GetRailCrossingReservation(t); + break; + + case MP_STATION: + if (IsRailwayStation(t)) return GetRailStationReservation(t); + break; + + case MP_TUNNELBRIDGE: + if (GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL) return GetRailTunnelBridgeReservation(t); + break; + + default: + break; + } + return TRACK_BIT_NONE; +} diff --git a/src/pbs.h b/src/pbs.h new file mode 100755 index 0000000..51a9ba2 --- /dev/null +++ b/src/pbs.h @@ -0,0 +1,13 @@ +/* $Id$ */ + +/** @file pbs.h PBS support routines */ + +#ifndef PBS_H +#define PBS_H + +#include "tile_type.h" +#include "track_type.h" + +TrackBits GetReservedTrackbits(TileIndex t); + +#endif /* PBS_H */ -- 1.5.3.5 From 7d8806c6122a329da146668a596f6eeb707ee535 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 2 Feb 2008 13:08:20 +0100 Subject: PBS signals added to the map array. Basic support for building and drawing present, but using the old sprites. --- docs/landscape.html | 26 +++++++++++++------ docs/landscape_grid.html | 2 +- src/lang/english.txt | 13 ++++++++++ src/misc/dbg_helpers.cpp | 2 +- src/openttd.cpp | 39 +++++++++++++++++++++++++++++ src/rail_cmd.cpp | 61 ++++++++++++++++++++++++++++++++++++---------- src/rail_gui.cpp | 5 ++- src/rail_map.h | 53 ++++++++++++++++++++++++++++++++------- src/saveload.cpp | 2 +- src/settings.cpp | 8 ++++++ src/settings_gui.cpp | 6 +++- src/settings_type.h | 5 ++++ src/yapf/yapf_settings.h | 2 + 13 files changed, 186 insertions(+), 38 deletions(-) diff --git a/docs/landscape.html b/docs/landscape.html index 38cafd4..fc54b4b 100644 --- a/docs/landscape.html +++ b/docs/landscape.html @@ -371,30 +371,40 @@
        -
      • m2 bit 6: Signal 0 and 1: set = semaphore signals, clear = light signals
      • -
      • m2 bit 2: Signal 2 and 3: set = semaphore signals, clear = light signals
      • -
      • m2 bits 5..4: type of signal 0 and 1 (same values as m2 bits 1..0)
      • -
      • m2 bits 1..0: type of signal 2 and 3 +
      • m2 bit 7: Signal 0 and 1: set = semaphore signals, clear = light signals
      • +
      • m2 bit 3: Signal 2 and 3: set = semaphore signals, clear = light signals
      • +
      • m2 bits 6..4: type of signal 0 and 1 (same values as m2 bits 2..0)
      • +
      • m2 bits 2..0: type of signal 2 and 3 - + - + - + - + + + + + + + + + + +
        00: 000: normal signals
        01: 001: pre-signals
        10: 010: exit-signals
        11: 011: combo-signals
        100: pbs signals
        101: no-entry signals
      • diff --git a/docs/landscape_grid.html b/docs/landscape_grid.html index 68858ed..9113afc 100644 --- a/docs/landscape_grid.html +++ b/docs/landscape_grid.html @@ -101,7 +101,7 @@ the array so you can quickly see what is used and what is not. rail with signals -inherit- -inherit- - OOOO XXXX OXXX OXXX + OOOO XXXX XXXX XXXX XXXX ~~XX XXXX XXXX -inherit- diff --git a/src/lang/english.txt b/src/lang/english.txt index f07f2cb..332ee02 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1165,6 +1165,8 @@ STR_CONFIG_PATCHES_ALLOW_SHARES :{LTBLUE}Allow b STR_CONFIG_PATCHES_DRAG_SIGNALS_DENSITY :{LTBLUE}When dragging, place signals every: {ORANGE}{STRING1} tile(s) STR_CONFIG_PATCHES_SEMAPHORE_BUILD_BEFORE_DATE :{LTBLUE}Automatically build semaphores before: {ORANGE}{STRING1} STR_CONFIG_PATCHES_ENABLE_SIGNAL_GUI :{LTBLUE}Enable the signal GUI: {ORANGE}{STRING1} +STR_CONFIG_PATCHES_DO_PATH_RESERVATION :{LTBLUE}Make path reservations for trains (forces NPF or YAPF): {ORANGE}{STRING1} +STR_CONFIG_PATCHES_BUILD_PBS_SIG :{LTBLUE}Build advanced signals: {ORANGE}{STRING1} STR_CONFIG_PATCHES_TOWN_LAYOUT_INVALID :{WHITE}The town layout "no more roads" isn't valid in the scenario editor STR_CONFIG_PATCHES_TOWN_LAYOUT :{LTBLUE}Select town-road layout: {ORANGE}{STRING1} @@ -1634,12 +1636,23 @@ STR_RAILROAD_TRACK_WITH_NORMAL_SIGNALS :Railway track w STR_RAILROAD_TRACK_WITH_PRESIGNALS :Railway track with pre-signals STR_RAILROAD_TRACK_WITH_EXITSIGNALS :Railway track with exit-signals STR_RAILROAD_TRACK_WITH_COMBOSIGNALS :Railway track with combo-signals +STR_RAILROAD_TRACK_WITH_PBSSIGNALS :Railway track with advanced signals +STR_RAILROAD_TRACK_WITH_NOENTRYSIGNALS :Railway track with no-entry signals STR_RAILROAD_TRACK_WITH_NORMAL_PRESIGNALS :Railway track with normal and pre-signals STR_RAILROAD_TRACK_WITH_NORMAL_EXITSIGNALS :Railway track with normal and exit-signals STR_RAILROAD_TRACK_WITH_NORMAL_COMBOSIGNALS :Railway track with normal and combo-signals +STR_RAILROAD_TRACK_WITH_NORMAL_PBSSIGNALS :Railway track with normal and advanced signals +STR_RAILROAD_TRACK_WITH_NORMAL_NOENTRYSIGNALS :Railway track with normal and no-entry signals STR_RAILROAD_TRACK_WITH_PRE_EXITSIGNALS :Railway track with pre- and exit-signals STR_RAILROAD_TRACK_WITH_PRE_COMBOSIGNALS :Railway track with pre- and combo-signals +STR_RAILROAD_TRACK_WITH_PRE_PBSSIGNALS :Railway track with pre- and advanced signals +STR_RAILROAD_TRACK_WITH_PRE_NOENTRYSIGNALS :Railway track with pre- and no-entry signals STR_RAILROAD_TRACK_WITH_EXIT_COMBOSIGNALS :Railway track with exit- and combo-signals +STR_RAILROAD_TRACK_WITH_EXIT_PBSSIGNALS :Railway track with exit- and advanced signals +STR_RAILROAD_TRACK_WITH_EXIT_NOENTRYSIGNALS :Railway track with exit- and no-entry signals +STR_RAILROAD_TRACK_WITH_COMBO_PBSSIGNALS :Railway track with combo- and advanced signals +STR_RAILROAD_TRACK_WITH_COMBO_NOENTRYSIGNALS :Railway track with combo- and no-entry signals +STR_RAILROAD_TRACK_WITH_PBS_NOENTRYSIGNALS :Railway track with advanced and no-entry signals STR_MUST_REMOVE_RAILWAY_STATION_FIRST :{WHITE}Must remove railway station first diff --git a/src/misc/dbg_helpers.cpp b/src/misc/dbg_helpers.cpp index a07c5ce..4c7dbf0 100644 --- a/src/misc/dbg_helpers.cpp +++ b/src/misc/dbg_helpers.cpp @@ -47,7 +47,7 @@ CStrA ValueStr(DiagDirection dd) /** SignalType short names. */ static const char* signal_type_names[] = { - "NORMAL", "ENTRY", "EXIT", "COMBO", + "NORMAL", "ENTRY", "EXIT", "COMBO", "PBS", "NOENTRY", }; /** Return name of given SignalType. */ diff --git a/src/openttd.cpp b/src/openttd.cpp index 1b298de..ef12645 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -2352,6 +2352,45 @@ bool AfterLoadGame() } } + /* Move the signal variant back up one bit for PBS. We don't convert the old PBS + * format here, as an old layout wouldn't work properly anyway. To be safe, we + * clear any possible PBS reservations as well. */ + if (CheckSavegameVersion(87)) { + for (TileIndex t = 0; t < map_size; t++) { + switch (GetTileType(t)) { + case MP_RAILWAY: + if (HasSignals(t)) { + /* move the signal variant */ + SetSignalVariant(t, TRACK_UPPER, HasBit(_m[t].m2, 2) ? SIG_SEMAPHORE : SIG_ELECTRIC); + SetSignalVariant(t, TRACK_LOWER, HasBit(_m[t].m2, 6) ? SIG_SEMAPHORE : SIG_ELECTRIC); + ClrBit(_m[t].m2, 2); + ClrBit(_m[t].m2, 6); + } + + /* Clear PBS reservation on track */ + if (IsRailDepot(t) ||IsRailWaypoint(t)) + SetWaypointReservation(t, false); + else + SetTrackReservation(t, TRACK_BIT_NONE); + break; + + case MP_ROAD: /* Clear PBS reservation on crossing */ + if (IsLevelCrossing(t)) SetCrossingReservation(t, false); + break; + + case MP_STATION: /* Clear PBS reservation on station */ + if (IsRailwayStation(t)) SetRailwayStationReservation(t, false); + break; + + case MP_TUNNELBRIDGE: /* Clear PBS reservation on tunnels/birdges */ + if (GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL) SetTunnelBridgeReservation(t, false); + break; + + default: break; + } + } + } + return InitializeWindowsAndCaches(); } diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 35a9cb7..81258cd 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -788,8 +788,9 @@ CommandCost CmdBuildTrainDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p * - p1 = (bit 0-2) - track-orientation, valid values: 0-5 (Track enum) * - p1 = (bit 3) - 1 = override signal/semaphore, or pre/exit/combo signal or (for bit 7) toggle variant (CTRL-toggle) * - p1 = (bit 4) - 0 = signals, 1 = semaphores - * - p1 = (bit 5-6) - type of the signal, for valid values see enum SignalType in rail_map.h - * - p1 = (bit 7) - convert the present signal type and variant + * - p1 = (bit 5-7) - type of the signal, for valid values see enum SignalType in rail_map.h + * - p1 = (bit 8) - convert the present signal type and variant + * - p1 = (bit 9) - build advanced signals instead of normal signals * @param p2 used for CmdBuildManySignals() to copy direction of first signal * TODO: p2 should be replaced by two bits for "along" and "against" the track. */ @@ -798,8 +799,9 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, uint32 flags, uint32 p1, uint32 Track track = (Track)GB(p1, 0, 3); bool ctrl_pressed = HasBit(p1, 3); // was the CTRL button pressed SignalVariant sigvar = (ctrl_pressed ^ HasBit(p1, 4)) ? SIG_SEMAPHORE : SIG_ELECTRIC; // the signal variant of the new signal - SignalType sigtype = (SignalType)GB(p1, 5, 2); // the signal type of the new signal - bool convert_signal = HasBit(p1, 7); // convert button pressed + SignalType sigtype = (SignalType)GB(p1, 5, 3); // the signal type of the new signal + bool convert_signal = HasBit(p1, 8); // convert button pressed + bool build_pbs_sig = HasBit(p1, 9); CommandCost cost; if (!ValParamTrackOrientation(track) || !IsTileType(tile, MP_RAILWAY) || !EnsureNoTrainOnTrack(tile, track)) @@ -863,7 +865,7 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, uint32 flags, uint32 p1, uint32 if (p2 == 0) { if (!HasSignalOnTrack(tile, track)) { /* build new signals */ - SetPresentSignals(tile, GetPresentSignals(tile) | SignalOnTrack(track)); + SetPresentSignals(tile, GetPresentSignals(tile) | (build_pbs_sig ? KillFirstBit(SignalOnTrack(track)) : SignalOnTrack(track))); SetSignalType(tile, track, sigtype); SetSignalVariant(tile, track, sigvar); } else { @@ -881,9 +883,14 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, uint32 flags, uint32 p1, uint32 } else if (ctrl_pressed) { /* cycle between normal -> pre -> exit -> combo -> ... */ - sigtype = GetSignalType(tile, track); + sigtype = (SignalType)(GetSignalType(tile, track) + 1); - SetSignalType(tile, track, sigtype == SIGTYPE_COMBO ? SIGTYPE_NORMAL : (SignalType)(sigtype + 1)); + if (build_pbs_sig) + sigtype = sigtype > SIGTYPE_LAST ? SIGTYPE_PBS : (sigtype < SIGTYPE_PBS ? SIGTYPE_PBS : sigtype); + else + sigtype = sigtype > SIGTYPE_LAST_NOPBS ? SIGTYPE_NORMAL : sigtype; + + SetSignalType(tile, track, sigtype); } else { /* cycle the signal side: both -> left -> right -> both -> ... */ CycleSignalSide(tile, track); @@ -896,6 +903,10 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, uint32 flags, uint32 p1, uint32 SetSignalVariant(tile, track, sigvar); } + if (sigtype == SIGTYPE_PBS) { + uint mask = GetPresentSignals(tile) & SignalOnTrack(track); + SetSignalStates(tile, (GetSignalStates(tile) & ~mask) | ((HasBit(GetTrackReservation(tile), track) ? (uint)-1 : 0) & mask)); + } MarkTileDirtyByTile(tile); AddTrackToSignalBuffer(tile, track, _current_player); YapfNotifyTrackLayoutChange(tile, track); @@ -1453,7 +1464,7 @@ static void DrawSingleSignal(TileIndex tile, Track track, byte condition, uint i if (GetSignalType(tile, track) == SIGTYPE_NORMAL && GetSignalVariant(tile, track) == SIG_ELECTRIC) { sprite = SignalBase[side][GetSignalVariant(tile, track)][GetSignalType(tile, track)] + image + condition; } else { - sprite = SPR_SIGNALS_BASE + (GetSignalType(tile, track) - 1) * 16 + GetSignalVariant(tile, track) * 64 + image + condition; + sprite = SPR_SIGNALS_BASE + (GetSignalType(tile, track) - 1) * 16 + GetSignalVariant(tile, track) * 64 + image + condition + (GetSignalType(tile, track) > SIGTYPE_LAST_NOPBS ? 64 : 0); } AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, GetSaveSlopeZ(x, y, track)); @@ -2112,30 +2123,54 @@ static void GetTileDesc_Track(TileIndex tile, TileDesc *td) break; case RAIL_TILE_SIGNALS: { - const StringID signal_type[4][4] = { + const StringID signal_type[6][6] = { { STR_RAILROAD_TRACK_WITH_NORMAL_SIGNALS, STR_RAILROAD_TRACK_WITH_NORMAL_PRESIGNALS, STR_RAILROAD_TRACK_WITH_NORMAL_EXITSIGNALS, - STR_RAILROAD_TRACK_WITH_NORMAL_COMBOSIGNALS + STR_RAILROAD_TRACK_WITH_NORMAL_COMBOSIGNALS, + STR_RAILROAD_TRACK_WITH_NORMAL_PBSSIGNALS, + STR_RAILROAD_TRACK_WITH_NORMAL_NOENTRYSIGNALS }, { STR_RAILROAD_TRACK_WITH_NORMAL_PRESIGNALS, STR_RAILROAD_TRACK_WITH_PRESIGNALS, STR_RAILROAD_TRACK_WITH_PRE_EXITSIGNALS, - STR_RAILROAD_TRACK_WITH_PRE_COMBOSIGNALS + STR_RAILROAD_TRACK_WITH_PRE_COMBOSIGNALS, + STR_RAILROAD_TRACK_WITH_PRE_PBSSIGNALS, + STR_RAILROAD_TRACK_WITH_PRE_NOENTRYSIGNALS }, { STR_RAILROAD_TRACK_WITH_NORMAL_EXITSIGNALS, STR_RAILROAD_TRACK_WITH_PRE_EXITSIGNALS, STR_RAILROAD_TRACK_WITH_EXITSIGNALS, - STR_RAILROAD_TRACK_WITH_EXIT_COMBOSIGNALS + STR_RAILROAD_TRACK_WITH_EXIT_COMBOSIGNALS, + STR_RAILROAD_TRACK_WITH_EXIT_PBSSIGNALS, + STR_RAILROAD_TRACK_WITH_EXIT_NOENTRYSIGNALS }, { STR_RAILROAD_TRACK_WITH_NORMAL_COMBOSIGNALS, STR_RAILROAD_TRACK_WITH_PRE_COMBOSIGNALS, STR_RAILROAD_TRACK_WITH_EXIT_COMBOSIGNALS, - STR_RAILROAD_TRACK_WITH_COMBOSIGNALS + STR_RAILROAD_TRACK_WITH_COMBOSIGNALS, + STR_RAILROAD_TRACK_WITH_COMBO_PBSSIGNALS, + STR_RAILROAD_TRACK_WITH_COMBO_NOENTRYSIGNALS + }, + { + STR_RAILROAD_TRACK_WITH_NORMAL_PBSSIGNALS, + STR_RAILROAD_TRACK_WITH_PRE_PBSSIGNALS, + STR_RAILROAD_TRACK_WITH_EXIT_PBSSIGNALS, + STR_RAILROAD_TRACK_WITH_COMBO_PBSSIGNALS, + STR_RAILROAD_TRACK_WITH_PBSSIGNALS, + STR_RAILROAD_TRACK_WITH_PBS_NOENTRYSIGNALS + }, + { + STR_RAILROAD_TRACK_WITH_NORMAL_NOENTRYSIGNALS, + STR_RAILROAD_TRACK_WITH_PRE_NOENTRYSIGNALS, + STR_RAILROAD_TRACK_WITH_EXIT_NOENTRYSIGNALS, + STR_RAILROAD_TRACK_WITH_COMBO_NOENTRYSIGNALS, + STR_RAILROAD_TRACK_WITH_PBS_NOENTRYSIGNALS, + STR_RAILROAD_TRACK_WITH_NOENTRYSIGNALS } }; diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index 59e5161..9ea08ce 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -210,8 +210,9 @@ static void GenericPlaceSignals(TileIndex tile) uint32 p1 = track; SB(p1, 3, 1, _ctrl_pressed); SB(p1, 4, 1, _cur_signal_variant); - SB(p1, 5, 2, _patches.enable_signal_gui ? _cur_signal_type : SIGTYPE_NORMAL); - SB(p1, 7, 1, _convert_signal_button); + SB(p1, 5, 3, _patches.enable_signal_gui ? _cur_signal_type : (_patches.build_pbs_signals ? SIGTYPE_PBS : SIGTYPE_NORMAL)); + SB(p1, 8, 1, _convert_signal_button); + SB(p1, 9, 1, _patches.build_pbs_signals); DoCommandP(tile, p1, 0, CcPlaySound1E, CMD_BUILD_SIGNALS | CMD_MSG(_convert_signal_button ? STR_SIGNAL_CAN_T_CONVERT_SIGNALS_HERE : STR_1010_CAN_T_BUILD_SIGNALS_HERE)); diff --git a/src/rail_map.h b/src/rail_map.h index 8dfd6f4..c75390a 100644 --- a/src/rail_map.h +++ b/src/rail_map.h @@ -295,25 +295,34 @@ static inline TrackBits GetRailDepotReservation(TileIndex t) /** Type of signal, i.e. how does the signal behave? */ enum SignalType { - SIGTYPE_NORMAL = 0, ///< normal signal - SIGTYPE_ENTRY = 1, ///< presignal block entry - SIGTYPE_EXIT = 2, ///< presignal block exit - SIGTYPE_COMBO = 3 ///< presignal inter-block + 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, ///< normal pbs signal + SIGTYPE_NOENTRY = 5, ///< no-entry signal + SIGTYPE_LAST = SIGTYPE_NOENTRY, + SIGTYPE_LAST_NOPBS = SIGTYPE_COMBO }; +static inline bool IsPbsSignal(SignalType s) +{ + return s == SIGTYPE_PBS; +} + static inline SignalType GetSignalType(TileIndex t, Track track) { assert(GetRailTileType(t) == RAIL_TILE_SIGNALS); byte pos = (track == TRACK_LOWER || track == TRACK_RIGHT) ? 4 : 0; - return (SignalType)GB(_m[t].m2, pos, 2); + return (SignalType)GB(_m[t].m2, pos, 3); } static inline void SetSignalType(TileIndex t, Track track, SignalType s) { assert(GetRailTileType(t) == RAIL_TILE_SIGNALS); byte pos = (track == TRACK_LOWER || track == TRACK_RIGHT) ? 4 : 0; - SB(_m[t].m2, pos, 2, s); - if (track == INVALID_TRACK) SB(_m[t].m2, 4, 2, s); + SB(_m[t].m2, pos, 3, s); + if (track == INVALID_TRACK) SB(_m[t].m2, 4, 3, s); } static inline bool IsPresignalEntry(TileIndex t, Track track) @@ -344,15 +353,15 @@ enum SignalVariant { static inline SignalVariant GetSignalVariant(TileIndex t, Track track) { - byte pos = (track == TRACK_LOWER || track == TRACK_RIGHT) ? 6 : 2; + byte pos = (track == TRACK_LOWER || track == TRACK_RIGHT) ? 7 : 3; return (SignalVariant)GB(_m[t].m2, pos, 1); } static inline void SetSignalVariant(TileIndex t, Track track, SignalVariant v) { - byte pos = (track == TRACK_LOWER || track == TRACK_RIGHT) ? 6 : 2; + byte pos = (track == TRACK_LOWER || track == TRACK_RIGHT) ? 7 : 3; SB(_m[t].m2, pos, 1, v); - if (track == INVALID_TRACK) SB(_m[t].m2, 6, 1, v); + if (track == INVALID_TRACK) SB(_m[t].m2, 7, 1, v); } /** These are states in which a signal can be. Currently these are only two, so @@ -479,6 +488,30 @@ static inline void SetSignalStateByTrackdir(TileIndex tile, Trackdir trackdir, S } } +/** + * Does the tile have a no-entry signal facing us? + * @param tile the tile to check + * @param td the trackdir to check + * @return true if a no-entry signals points at us + */ +static inline bool HasNoEntrySignalOnTrackdir(TileIndex tile, Trackdir td) +{ + return HasSignalOnTrackdir(tile, td) && GetSignalType(tile, TrackdirToTrack(td)) == SIGTYPE_NOENTRY; +} + +/** + * Is a pbs signal present along the trackdir? + * @param tile the tile to check + * @param td the trackdir to check + */ +static inline bool HasPbsSignalOnTrackdir(TileIndex tile, Trackdir td) +{ + return + IsTileType(tile, MP_RAILWAY) && + HasSignalOnTrackdir(tile, td) && + IsPbsSignal(GetSignalType(tile, TrackdirToTrack(td))); +} + /** * Return the rail type of tile, or INVALID_RAILTYPE if this is no rail tile. diff --git a/src/saveload.cpp b/src/saveload.cpp index 3b62a39..83c83ac 100644 --- a/src/saveload.cpp +++ b/src/saveload.cpp @@ -34,7 +34,7 @@ #include "table/strings.h" -extern const uint16 SAVEGAME_VERSION = 86; +extern const uint16 SAVEGAME_VERSION = 87; uint16 _sl_version; ///< the major savegame version identifier byte _sl_minor_version; ///< the minor savegame version, DO NOT USE! diff --git a/src/settings.cpp b/src/settings.cpp index 5f18f3c..bde1497 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1391,6 +1391,8 @@ const SettingDesc _patch_settings[] = { SDT_VAR(Patches, drag_signals_density,SLE_UINT8,S, 0, 4, 1, 20, 0, STR_CONFIG_PATCHES_DRAG_SIGNALS_DENSITY,NULL), SDT_VAR(Patches, semaphore_build_before,SLE_INT32, S, NC, 1975, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_SEMAPHORE_BUILD_BEFORE_DATE, NULL), SDT_CONDVAR(Patches, town_layout, SLE_UINT8, 59, SL_MAX_VERSION, 0, MS, TL_ORIGINAL, TL_NO_ROADS, NUM_TLS - 1, 1, STR_CONFIG_PATCHES_TOWN_LAYOUT, CheckTownLayout), + SDT_CONDBOOL(Patches, reserve_paths, 87, SL_MAX_VERSION, 0, 0, false, STR_CONFIG_PATCHES_DO_PATH_RESERVATION, NULL), + SDT_CONDBOOL(Patches, build_pbs_signals, 87, SL_MAX_VERSION, N, 0, false, STR_CONFIG_PATCHES_BUILD_PBS_SIG, NULL), /***************************************************************************/ /* Vehicle section of the GUI-configure patches window */ @@ -1541,6 +1543,10 @@ const SettingDesc _patch_settings[] = { SDT_VAR(Patches, npf_crossing_penalty, SLE_UINT, 0, 0, (3 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL), /* This is the penalty for drive-through road, stops. */ SDT_CONDVAR (Patches, npf_road_drive_through_penalty, SLE_UINT, 47, SL_MAX_VERSION, 0, 0, 8 * NPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), + /* Penalty for crossing a reserved tile */ + SDT_CONDVAR(Patches, npf_rail_pbs_cross_penalty, SLE_UINT, 87, SL_MAX_VERSION, 0, 0, 3 * NPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), + /* Penalty for passing a pbs signal from the backside */ + SDT_CONDVAR(Patches, npf_rail_pbs_signal_back_penalty,SLE_UINT, 87, SL_MAX_VERSION, 0, 0, 50 * NPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), /* The maximum number of nodes to search */ @@ -1565,6 +1571,8 @@ const SettingDesc _patch_settings[] = { SDT_CONDVAR (Patches, yapf.rail_look_ahead_signal_p0 , SLE_INT , 28, SL_MAX_VERSION, 0, 0, 500 , -1000000, 1000000, 0, STR_NULL, NULL), SDT_CONDVAR (Patches, yapf.rail_look_ahead_signal_p1 , SLE_INT , 28, SL_MAX_VERSION, 0, 0, -100 , -1000000, 1000000, 0, STR_NULL, NULL), SDT_CONDVAR (Patches, yapf.rail_look_ahead_signal_p2 , SLE_INT , 28, SL_MAX_VERSION, 0, 0, 5 , -1000000, 1000000, 0, STR_NULL, NULL), + SDT_CONDVAR (Patches, yapf.rail_pbs_cross_penalty , SLE_UINT, 87, SL_MAX_VERSION, 0, 0, 3 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), + SDT_CONDVAR (Patches, yapf.rail_pbs_signal_back_penalty,SLE_UINT, 87, SL_MAX_VERSION, 0, 0, 25 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), /* penalties for too long or too short station platforms */ SDT_CONDVAR (Patches, yapf.rail_longer_platform_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 8 * YAPF_TILE_LENGTH, 0, 20000, 0, STR_NULL, NULL), SDT_CONDVAR (Patches, yapf.rail_longer_platform_per_tile_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 0 * YAPF_TILE_LENGTH, 0, 20000, 0, STR_NULL, NULL), diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 1c75e51..61b0f1a 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -742,6 +742,7 @@ static const char *_patches_construction[] = { "drag_signals_density", "oil_refinery_limit", "semaphore_build_before", + "build_pbs_signals", }; static const char *_patches_stations[] = { @@ -797,6 +798,7 @@ static const char *_patches_vehicles[] = { "yapf.ship_use_yapf", "yapf.road_use_yapf", "yapf.rail_use_yapf", + "reserve_paths", "train_income_warn", "order_review_system", "never_expire_vehicles", @@ -1070,7 +1072,7 @@ static const Widget _patches_selection_widgets[] = { { WWT_CLOSEBOX, RESIZE_NONE, 10, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, { WWT_CAPTION, RESIZE_NONE, 10, 11, 369, 0, 13, STR_CONFIG_PATCHES_CAPTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, { WWT_PANEL, RESIZE_NONE, 10, 0, 369, 14, 41, 0x0, STR_NULL}, -{ WWT_PANEL, RESIZE_NONE, 10, 0, 369, 42, 380, 0x0, STR_NULL}, +{ WWT_PANEL, RESIZE_NONE, 10, 0, 369, 42, 390, 0x0, STR_NULL}, { WWT_TEXTBTN, RESIZE_NONE, 3, 10, 96, 16, 27, STR_CONFIG_PATCHES_GUI, STR_NULL}, { WWT_TEXTBTN, RESIZE_NONE, 3, 97, 183, 16, 27, STR_CONFIG_PATCHES_CONSTRUCTION, STR_NULL}, @@ -1082,7 +1084,7 @@ static const Widget _patches_selection_widgets[] = { }; static const WindowDesc _patches_selection_desc = { - WDP_CENTER, WDP_CENTER, 370, 381, 370, 381, + WDP_CENTER, WDP_CENTER, 370, 391, 370, 391, WC_GAME_OPTIONS, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, _patches_selection_widgets, diff --git a/src/settings_type.h b/src/settings_type.h index 6985f63..b6165e0 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -194,6 +194,8 @@ struct Patches { uint32 npf_road_curve_penalty; ///< The penalty for curves uint32 npf_crossing_penalty; ///< The penalty for level crossings uint32 npf_road_drive_through_penalty; ///< The penalty for going through a drive-through road stop + uint32 npf_rail_pbs_cross_penalty; ///< The penalty for crossing a reserved rail track + uint32 npf_rail_pbs_signal_back_penalty; ///< The penalty for passing a pbs signal from the backside bool population_in_label; ///< Show the population of a town in his label? @@ -226,6 +228,9 @@ struct Patches { bool give_money; ///< allow giving other players money bool enable_signal_gui; ///< Show the signal GUI when the signal button is pressed + + bool reserve_paths; ///< Always reserve paths regardless of signal type + bool build_pbs_signals; ///< Build advanced PBS signals }; extern Patches _patches; diff --git a/src/yapf/yapf_settings.h b/src/yapf/yapf_settings.h index 0d84072..14def60 100644 --- a/src/yapf/yapf_settings.h +++ b/src/yapf/yapf_settings.h @@ -58,6 +58,8 @@ YS_DEF_BEGIN YS_DEF(int32 , rail_look_ahead_signal_p0) ///< constant in polynomial penalty function YS_DEF(int32 , rail_look_ahead_signal_p1) ///< constant in polynomial penalty function YS_DEF(int32 , rail_look_ahead_signal_p2) ///< constant in polynomial penalty function + YS_DEF(uint32, rail_pbs_cross_penalty) ///< penalty for crossing a reserved tile + YS_DEF(uint32, rail_pbs_signal_back_penalty) ///< penalty for passing a pbs signal from the backside YS_DEF(uint32, rail_longer_platform_penalty) ///< penalty for longer station platform than train YS_DEF(uint32, rail_longer_platform_per_tile_penalty) ///< penalty for longer station platform than train (per tile) -- 1.5.3.5 From baa4f5d600cdd9bcb7c8e9319f525293ff29c200 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Fri, 1 Feb 2008 00:21:58 +0100 Subject: PBS signals don't affect trains coming from the backside. --- src/rail_cmd.cpp | 23 ++++++++++++----------- src/rail_map.h | 6 ++++++ src/signal.cpp | 2 +- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 81258cd..8211783 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -2085,17 +2085,18 @@ static uint32 GetTileTrackStatus_Track(TileIndex tile, TransportType mode, uint b &= a; - /* When signals are not present (in neither - * direction), we pretend them to be green. (So if - * signals are only one way, the other way will - * implicitely become `red' */ - if ((a & 0xC) == 0) b |= 0xC; - if ((a & 0x3) == 0) b |= 0x3; - - if ((b & 0x8) == 0) ret |= 0x10070000; - if ((b & 0x4) == 0) ret |= 0x07100000; - if ((b & 0x2) == 0) ret |= 0x20080000; - if ((b & 0x1) == 0) ret |= 0x08200000; + /* When signals are not present (in neither direction), + * we pretend them to be green. Otherwise, it depends on + * the signal type. For signals that are only active from + * one side, we set the missing signals explicitely to + * `green'. Otherwise, they implicitely become `red'. */ + if (!IsOnewaySignal(tile, TRACK_UPPER) || (a & SignalOnTrack(TRACK_UPPER)) == 0) b |= ~a & SignalOnTrack(TRACK_UPPER); + if (!IsOnewaySignal(tile, TRACK_LOWER) || (a & SignalOnTrack(TRACK_LOWER)) == 0) b |= ~a & SignalOnTrack(TRACK_LOWER); + + if ((b & 0x8) == 0) ret |= (TRACKDIR_BIT_LEFT_N | TRACKDIR_BIT_X_NE | TRACKDIR_BIT_Y_SE | TRACKDIR_BIT_UPPER_E) << 16; + if ((b & 0x4) == 0) ret |= (TRACKDIR_BIT_X_SW | TRACKDIR_BIT_Y_NW | TRACKDIR_BIT_UPPER_W | TRACKDIR_BIT_LEFT_S) << 16; + if ((b & 0x2) == 0) ret |= (TRACKDIR_BIT_RIGHT_N | TRACKDIR_BIT_LOWER_E) << 16; + if ((b & 0x1) == 0) ret |= (TRACKDIR_BIT_LOWER_W | TRACKDIR_BIT_RIGHT_S) << 16; return ret; } diff --git a/src/rail_map.h b/src/rail_map.h index c75390a..fa28f2c 100644 --- a/src/rail_map.h +++ b/src/rail_map.h @@ -335,6 +335,12 @@ static inline bool IsPresignalExit(TileIndex t, Track track) return GetSignalType(t, track) == SIGTYPE_EXIT || GetSignalType(t, track) == SIGTYPE_COMBO; } +/** One-way signals can't be passed the 'wrong' way. */ +static inline bool IsOnewaySignal(TileIndex t, Track track) +{ + return GetSignalType(t, track) <= SIGTYPE_LAST_NOPBS; +} + static inline void CycleSignalSide(TileIndex t, Track track) { byte sig; diff --git a/src/signal.cpp b/src/signal.cpp index f45e137..3f6ec9c 100644 --- a/src/signal.cpp +++ b/src/signal.cpp @@ -418,7 +418,7 @@ static void UpdateSignalsAroundSegment(SigFlags flags) SignalState newstate = SIGNAL_STATE_GREEN; /* determine whether the new state is red */ - if (flags & SF_TRAIN) { + if ((flags & SF_TRAIN) || sig == SIGTYPE_NOENTRY) { /* train in the segment */ newstate = SIGNAL_STATE_RED; } else { -- 1.5.3.5 From b4c7eba3ed75ae7c4dad059fd415b644525e44d1 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sun, 16 Dec 2007 17:57:35 +0100 Subject: Handle no-entry signals in the pathfinders. --- src/npf.cpp | 7 ++++--- src/pathfind.cpp | 8 ++++++-- src/yapf/yapf_costrail.hpp | 5 ++++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/npf.cpp b/src/npf.cpp index 582413c..63db4a7 100644 --- a/src/npf.cpp +++ b/src/npf.cpp @@ -637,10 +637,11 @@ static void NPFFollowTrack(AyStar* aystar, OpenListNode* current) Trackdir dst_trackdir = RemoveFirstTrackdir(&trackdirbits); DEBUG(npf, 5, "Expanded into trackdir: %d, remaining trackdirs: 0x%X", dst_trackdir, trackdirbits); - /* Check for oneway signal against us */ + /* Tile with signals? */ if (IsTileType(dst_tile, MP_RAILWAY) && GetRailTileType(dst_tile) == RAIL_TILE_SIGNALS) { - if (HasSignalOnTrackdir(dst_tile, ReverseTrackdir(dst_trackdir)) && !HasSignalOnTrackdir(dst_tile, dst_trackdir)) - /* if one way signal not pointing towards us, stop going in this direction. */ + if (HasNoEntrySignalOnTrackdir(dst_tile, dst_trackdir)) break; + if (HasSignalOnTrackdir(dst_tile, ReverseTrackdir(dst_trackdir)) && !HasSignalOnTrackdir(dst_tile, dst_trackdir) && IsOnewaySignal(dst_tile, TrackdirToTrack(dst_trackdir))) + /* If there's a one-way signal not pointing towards us, stop going in this direction. */ break; } { diff --git a/src/pathfind.cpp b/src/pathfind.cpp index 0637466..6f91b47 100644 --- a/src/pathfind.cpp +++ b/src/pathfind.cpp @@ -745,9 +745,13 @@ start_at: /* railway tile with signals..? */ if (HasSignals(tile)) { - if (!HasSignalOnTrackdir(tile, track)) { + if (HasNoEntrySignalOnTrackdir(tile, track)) { + /* no-entry signal pointing to us, can't pass it. */ + bits = TRACK_BIT_NONE; + break; + } else if (!HasSignalOnTrackdir(tile, track)) { /* if one way signal not pointing towards us, stop going in this direction => End of rail segment. */ - if (HasSignalOnTrackdir(tile, ReverseTrackdir(track))) { + if (HasSignalOnTrackdir(tile, ReverseTrackdir(track)) && IsOnewaySignal(tile, TrackdirToTrack(track))) { bits = TRACK_BIT_NONE; break; } diff --git a/src/yapf/yapf_costrail.hpp b/src/yapf/yapf_costrail.hpp index 5756f04..c274e49 100644 --- a/src/yapf/yapf_costrail.hpp +++ b/src/yapf/yapf_costrail.hpp @@ -136,7 +136,10 @@ public: if (IsTileType(tile, MP_RAILWAY)) { bool has_signal_against = HasSignalOnTrackdir(tile, ReverseTrackdir(trackdir)); bool has_signal_along = HasSignalOnTrackdir(tile, trackdir); - if (has_signal_against && !has_signal_along) { + if (HasNoEntrySignalOnTrackdir(tile, trackdir)) { + // no-entry signal ahead + n.m_segment->m_end_segment_reason |= ESRB_DEAD_END; + } else if (has_signal_against && !has_signal_along && IsOnewaySignal(tile, TrackdirToTrack(trackdir))) { // one-way signal in opposite direction n.m_segment->m_end_segment_reason |= ESRB_DEAD_END; } else if (has_signal_along) { -- 1.5.3.5 From a20ef06d7599aaa6e6961b76c68e0c123954b752 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Mon, 28 Jan 2008 22:23:56 +0100 Subject: Copy signal type of first rail-piece for autofill. --- src/rail_cmd.cpp | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 8211783..ba3320c 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -1018,6 +1018,8 @@ static CommandCost CmdSignalTrackHelper(TileIndex tile, uint32 flags, uint32 p1, /* Autofill must start on a valid track to be able to avoid loops */ if (autofill && !HasTrack(tile, track)) return CMD_ERROR; + SignalType sigtype = SIGTYPE_NORMAL; + /* copy the signal-style of the first rail-piece if existing */ if (HasSignals(tile)) { signals = GetPresentSignals(tile) & SignalOnTrack(track); @@ -1025,6 +1027,8 @@ static CommandCost CmdSignalTrackHelper(TileIndex tile, uint32 flags, uint32 p1, /* copy signal/semaphores style (independent of CTRL) */ semaphores = GetSignalVariant(tile, track) != SIG_ELECTRIC; + + sigtype = GetSignalType(tile, track); } else { // no signals exist, drag a two-way signal stretch signals = SignalOnTrack(track); } @@ -1048,6 +1052,7 @@ static CommandCost CmdSignalTrackHelper(TileIndex tile, uint32 flags, uint32 p1, uint32 p1 = GB(TrackdirToTrack(trackdir), 0, 3); SB(p1, 3, 1, mode); SB(p1, 4, 1, semaphores); + SB(p1, 5, 3, sigtype); /* Pick the correct orientation for the track direction */ signals = 0; -- 1.5.3.5 From 51bbdc038af59209c497aecc664fc465e3aa4a2e Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Mon, 4 Feb 2008 02:02:37 +0100 Subject: NPF and YAPF can now reserve the found path on request. --- src/npf.cpp | 131 ++++++++++++++++++++++++++++++++++++++++++- src/npf.h | 4 +- src/pbs.cpp | 112 ++++++++++++++++++++++++++++++++++++ src/pbs.h | 18 ++++++ src/rail_map.h | 33 +++++++++++ src/yapf/yapf.h | 2 +- src/yapf/yapf_node_rail.hpp | 31 ++++++++++ src/yapf/yapf_rail.cpp | 124 +++++++++++++++++++++++++++++++++++++--- 8 files changed, 441 insertions(+), 14 deletions(-) diff --git a/src/npf.cpp b/src/npf.cpp index 63db4a7..b922fb4 100644 --- a/src/npf.cpp +++ b/src/npf.cpp @@ -440,9 +440,109 @@ static int32 NPFFindStationOrTile(AyStar* as, OpenListNode *current) } } -/* To be called when current contains the (shortest route to) the target node. +/** + * Find the node containing the first signal on the path. + * + * If the first signal is on the very first two tiles of the path, + * the second signal is returnd. If no suitable signal is present, the + * last node of the path is returned. + */ +static const PathNode* FindFirstSignal(PathNode *path) +{ + /* If there is no signal, reserve the whole path. */ + PathNode *sig = path; + + if (HasReservedTrack(path->node.tile, TrackToTrackBits(TrackdirToTrack((Trackdir)path->node.direction)))) { + NPFSetFlag(&sig->node, NPF_FLAG_TARGET_RESERVED, true); + } + + while (path) { + if (IsTileType(path->node.tile, MP_RAILWAY) && path->parent != NULL) { + /* Update node if the tile contains a signal which isn't on the very first two + * tiles of the path. We reserve till the tile in front of the current tile. */ + if (HasSignalOnTrackdir(path->node.tile, (Trackdir)path->node.direction) && path->parent->parent != NULL) { + sig = path->parent; + /* Note whether the signal tile is reserved as we can't use it + * then to avoid a possible crash. */ + if (HasReservedTrack(path->node.tile, TrackToTrackBits(TrackdirToTrack((Trackdir)path->node.direction)))) { + NPFSetFlag(&sig->node, NPF_FLAG_TARGET_RESERVED, true); + } + } + /* Depots can also be a target. */ + if (IsRailDepot(path->node.tile)) { + sig = path; + if (GetRailDepotReservation(path->node.tile)) NPFSetFlag(&sig->node, NPF_FLAG_TARGET_RESERVED, true); + } + } + path = path->parent; + } + return sig; +} + +/** + * Lift the reservation of the tiles from @p start till @p end, excluding @p end itself. + */ +static void ClearPathReservation(const PathNode *start, const PathNode *end, bool start_is_target) +{ + while (start != end) { + if (IsRailwayStationTile(start->node.tile) && start_is_target) { + SetRailwayStationPlatformReservation(start->node.tile, TrackdirToExitdir((Trackdir)start->node.direction), false); + } else { + UnreserveRailTrack(start->node.tile, TrackdirToTrack((Trackdir)start->node.direction)); + } + start_is_target = false; + start = start->parent; + } +} + +/** + * Try to reserve all compatible remaining station tiles starting from @p target. + */ +static bool ReserveTargetStation(const PathNode *target) +{ + TileIndex tile = target->node.tile; + DiagDirection dir = TrackdirToExitdir((Trackdir)target->node.direction); + TileIndexDiff diff = TileOffsByDiagDir(dir); + TileIndex next = tile; + + do { + if (GetRailwayStationReservation(next)) { + /* Sorry, already reserved, aborting... */ + while (next != tile) { + next = TILE_ADD(next, -diff); + SetRailwayStationReservation(next, false); + } + return false; + } + SetRailwayStationReservation(next, true); + if (_debug_pbs_level >= 2) + MarkTileDirtyByTile(next); + + next = TILE_ADD(next, diff); + } while (IsCompatibleTrainStationTile(next, tile)); + + /* If the tile right after the station is reserved, abort because of the danger of a crash. */ + if ((GetTileTrackStatus(next, TRANSPORT_RAIL, 0) & TRACKDIR_BIT_MASK) != TRACKDIR_BIT_NONE && + !(IsTileType(next, MP_TUNNELBRIDGE) && GetTunnelBridgeDirection(next) != dir) && + !(IsTileDepotType(next, TRANSPORT_RAIL) && GetRailDepotDirection(next) == dir) && + GetTileOwner(tile) == GetTileOwner(next)) { + if (HasReservedTrack(next, DiagdirReachesTracks(dir))) { + while (next != tile) { + next = TILE_ADD(next, -diff); + SetRailwayStationReservation(next, false); + } + return false; + } + } + + return true; +} + +/** + * To be called when @p current contains the (shortest route to) the target node. * Will fill the contents of the NPFFoundTargetData using - * AyStarNode[NPF_TRACKDIR_CHOICE]. + * AyStarNode[NPF_TRACKDIR_CHOICE]. If requested, path reservation + * is done here. */ static void NPFSaveTargetData(AyStar* as, OpenListNode* current) { @@ -451,6 +551,30 @@ static void NPFSaveTargetData(AyStar* as, OpenListNode* current) ftd->best_path_dist = current->g; ftd->best_bird_dist = 0; ftd->node = current->path.node; + + if (as->user_target != NULL && ((NPFFindStationOrTileData*)as->user_target)->reserve_path && as->user_data[NPF_TYPE] == TRANSPORT_RAIL) { + /* We are supposed to reserve a path here */ + const PathNode *cur, *target = FindFirstSignal(¤t->path); + cur = target; + + /* Don't bother if the target is already reserved. */ + if (NPFGetFlag(&target->node, NPF_FLAG_TARGET_RESERVED)) return; + + if (cur == ¤t->path && IsRailwayStationTile(cur->node.tile)) { + /* Reservation target is the destination tile and the destination is a station. */ + if (!ReserveTargetStation(cur)) return; + if ((cur = cur->parent) == NULL) return; + } + + while (cur->parent != NULL) { + if (!TryReserveRailTrack(cur->node.tile, TrackdirToTrack((Trackdir)cur->node.direction))) { + /* Reservation failed, undo */ + ClearPathReservation(target, cur, target == ¤t->path); + break; + } + cur = cur->parent; + } + } } /** @@ -889,7 +1013,7 @@ void InitializeNPF() _npf_aystar.max_search_nodes = _patches.npf_max_search_nodes; } -void NPFFillWithOrderData(NPFFindStationOrTileData* fstd, Vehicle* v) +void NPFFillWithOrderData(NPFFindStationOrTileData* fstd, Vehicle* v, bool reserve_path) { /* Ships don't really reach their stations, but the tile in front. So don't * save the station id for ships. For roadvehs we don't store it either, @@ -905,4 +1029,5 @@ void NPFFillWithOrderData(NPFFindStationOrTileData* fstd, Vehicle* v) fstd->dest_coords = v->dest_tile; fstd->station_index = INVALID_STATION; } + fstd->reserve_path = reserve_path; } diff --git a/src/npf.h b/src/npf.h index 10f55a6..afe8aee 100644 --- a/src/npf.h +++ b/src/npf.h @@ -42,6 +42,7 @@ enum { struct NPFFindStationOrTileData { TileIndex dest_coords; ///< An indication of where the station is, for heuristic purposes, or the target tile StationID station_index; ///< station index we're heading for, or INVALID_STATION when we're heading for a tile + bool reserve_path; ///< Indicates whether the found path should be reserved }; /* Indices into AyStar.userdata[] */ @@ -63,6 +64,7 @@ enum NPFNodeFlag { NPF_FLAG_SEEN_SIGNAL, ///< Used to mark that a signal was seen on the way, for rail only NPF_FLAG_REVERSE, ///< Used to mark that this node was reached from the second start node, if applicable NPF_FLAG_LAST_SIGNAL_RED, ///< Used to mark that the last signal on this path was red + NPF_FLAG_TARGET_RESERVED ///< Used to mark that the possible reservation target is already reserved }; /* Meant to be stored in AyStar.userpath */ @@ -101,7 +103,7 @@ NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir t * of choices and accurate heuristics, such as water. */ NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, TransportType type, uint sub_type, Owner owner, RailTypes railtypes); -void NPFFillWithOrderData(NPFFindStationOrTileData* fstd, Vehicle* v); +void NPFFillWithOrderData(NPFFindStationOrTileData* fstd, Vehicle* v, bool reserve_path = false); /* diff --git a/src/pbs.cpp b/src/pbs.cpp index c75eb8c..f4ada75 100755 --- a/src/pbs.cpp +++ b/src/pbs.cpp @@ -9,6 +9,10 @@ #include "road_map.h" #include "station_map.h" #include "tunnelbridge_map.h" +#include "functions.h" +#include "debug.h" +#include "direction_func.h" +#include "rail.h" /** * Get the reserved trackbits for any tile, regardless of type. @@ -41,3 +45,111 @@ TrackBits GetReservedTrackbits(TileIndex t) } return TRACK_BIT_NONE; } + +/** + * Set the reservation for a complete station platform. + * @pre IsRailwayStationTile(start) + * @param start starting tile of the platform + * @param dir the direction in which to follow the platform + * @param b the state the reservation should be set to + */ +void SetRailwayStationPlatformReservation(TileIndex start, DiagDirection dir, bool b) +{ + TileIndex tile = start; + TileIndexDiff diff = TileOffsByDiagDir(dir); + + assert(IsRailwayStationTile(start) && GetRailStationAxis(start) == DiagDirToAxis(dir)); + + do { + SetRailwayStationReservation(tile, b); + if (_debug_pbs_level >= 2) MarkTileDirtyByTile(tile); + tile = TILE_ADD(tile, diff); + } while (IsCompatibleTrainStationTile(tile, start)); +} + +/** + * Try to reserve a specific track on a tile + * @param tile the tile + * @param t the track + * @return true if reservation was successfull, i.e. the track was + * free and didn't cross any other reserved tracks. + */ +bool TryReserveRailTrack(TileIndex tile, Track t) +{ + assert((GetTileTrackStatus(tile, TRANSPORT_RAIL, 0) & TrackToTrackBits(t)) != 0); + + if (_debug_pbs_level >= 2) + MarkTileDirtyByTile(tile); + + switch (GetTileType(tile)) { + case MP_RAILWAY: + if (IsPlainRailTile(tile)) return TryReserveTrack(tile, t); + if (IsRailWaypoint(tile) || IsRailDepot(tile)) { + if (!GetWaypointReservation(tile)) { + SetWaypointReservation(tile, true); + return true; + } + } + break; + + case MP_ROAD: + if (IsLevelCrossing(tile) && !GetCrossingReservation(tile)) { + SetCrossingReservation(tile, true); + return true; + } + break; + + case MP_STATION: + if (IsRailwayStation(tile) && !GetRailwayStationReservation(tile)) { + SetRailwayStationReservation(tile, true); + return true; + } + break; + + case MP_TUNNELBRIDGE: + if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL && !GetRailTunnelBridgeReservation(tile)) { + SetTunnelBridgeReservation(tile, true); + return true; + } + break; + + default: + break; + } + return false; +} + +/** + * Lift the reservation of a specific track on a tile + * @param tile the tile + * @param t the track + */ + void UnreserveRailTrack(TileIndex tile, Track t) +{ + assert((GetTileTrackStatus(tile, TRANSPORT_RAIL, 0) & TrackToTrackBits(t)) != 0); + + if (_debug_pbs_level >= 2) + MarkTileDirtyByTile(tile); + + switch (GetTileType(tile)) { + case MP_RAILWAY: + if (IsRailWaypoint(tile) || IsRailDepot(tile)) SetWaypointReservation(tile, false); + if (IsPlainRailTile(tile)) UnreserveTrack(tile, t); + break; + + case MP_ROAD: + if (IsLevelCrossing(tile)) SetCrossingReservation(tile, false); + break; + + case MP_STATION: + if (IsRailwayStation(tile)) SetRailwayStationReservation(tile, false); + break; + + case MP_TUNNELBRIDGE: + if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) SetTunnelBridgeReservation(tile, false); + break; + + default: + break; + } +} diff --git a/src/pbs.h b/src/pbs.h index 51a9ba2..dff48df 100755 --- a/src/pbs.h +++ b/src/pbs.h @@ -6,8 +6,26 @@ #define PBS_H #include "tile_type.h" +#include "direction_type.h" #include "track_type.h" TrackBits GetReservedTrackbits(TileIndex t); +void SetRailwayStationPlatformReservation(TileIndex start, DiagDirection dir, bool b); + +bool TryReserveRailTrack(TileIndex tile, Track t); +void UnreserveRailTrack(TileIndex tile, Track t); + +/** + * Check whether some of tracks is reserved on a tile + * + * @param tile the tile + * @param tracks the tracks to test + * @return true if at least on of tracks is reserved + */ +static inline bool HasReservedTrack(TileIndex tile, TrackBits tracks) +{ + return (GetReservedTrackbits(tile) & tracks) != TRACK_BIT_NONE; +} + #endif /* PBS_H */ diff --git a/src/rail_map.h b/src/rail_map.h index fa28f2c..ad94bd8 100644 --- a/src/rail_map.h +++ b/src/rail_map.h @@ -242,6 +242,39 @@ static inline void SetTrackReservation(TileIndex t, TrackBits b) } /** + * Try to reserve a specific track on a tile + * @pre IsPlainRailTile(t) && HasTrack(tile, t) + * @param tile the tile + * @param t the rack to reserve + * @return true if successful + */ +static inline bool TryReserveTrack(TileIndex tile, Track t) +{ + assert(HasTrack(tile, t)); + TrackBits bits = TrackToTrackBits(t); + TrackBits res = GetTrackReservation(tile); + if ((res & bits) != TRACK_BIT_NONE) return false; // already reserved + res |= bits; + if (TracksOverlap(res)) return false; // crossing reservation present + SetTrackReservation(tile, res); + return true; +} + +/** + * Lift the reservation of a specific track on a tile + * @pre IsPlainRailTile(t) && HasTrack(tile, t) + * @param tile the tile + * @param t the track to free + */ +static inline void UnreserveTrack(TileIndex tile, Track t) +{ + assert(HasTrack(tile, t)); + TrackBits res = GetTrackReservation(tile); + res &= ~TrackToTrackBits(t); + SetTrackReservation(tile, res); +} + +/** * Get the reservation state of the waypoint or depot * @note Works for both waypoints and rail depots * @pre IsRailWaypoint(t) || IsRailDepot(t) diff --git a/src/yapf/yapf.h b/src/yapf/yapf.h index 632c555..6eb57f8 100644 --- a/src/yapf/yapf.h +++ b/src/yapf/yapf.h @@ -32,7 +32,7 @@ Trackdir YapfChooseRoadTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir) * @param path_not_found [out] true is returned if no path can be found (returned Trackdir is only a 'guess') * @return the best trackdir for next turn or INVALID_TRACKDIR if the path could not be found */ -Trackdir YapfChooseRailTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found); +Trackdir YapfChooseRailTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found, bool reserve_track = false); /** Used by RV multistop feature to find the nearest road stop that has a free slot. * @param v RV (its current tile will be the origin) diff --git a/src/yapf/yapf_node_rail.hpp b/src/yapf/yapf_node_rail.hpp index 3d11288..a144816 100644 --- a/src/yapf/yapf_node_rail.hpp +++ b/src/yapf/yapf_node_rail.hpp @@ -177,6 +177,37 @@ struct CYapfRailNodeT FORCEINLINE Trackdir GetLastTrackdir() const {assert(m_segment != NULL); return m_segment->m_last_td;} FORCEINLINE void SetLastTileTrackdir(TileIndex tile, Trackdir td) {assert(m_segment != NULL); m_segment->m_last_tile = tile; m_segment->m_last_td = td;} + template + bool IterateTiles(const Vehicle* v, Tbase &obj, bool (Tbase::*func)(TileIndex, Trackdir)) const + { + Tfollower ft(v); + TileIndex cur = GetTile(); + Trackdir cur_td = GetTrackdir(); + + while (cur != GetLastTile()) { + if (!((obj.*func)(cur, cur_td))) return false; + + ft.Follow(cur, cur_td); + cur = ft.m_new_tile; + assert(KillFirstBit(ft.m_new_td_bits) == TRACKDIR_BIT_NONE); + cur_td = FindFirstTrackdir(ft.m_new_td_bits); + + /* Did we skip tiles because of a station? */ + if (ft.m_is_station && ft.m_tiles_skipped > 0) { + TileIndexDiff diff = TileOffsByDiagDir(TrackdirToExitdir(cur_td)); + TileIndex tile = TILE_ADD(cur, -diff * ft.m_tiles_skipped); + + for (int i = 0; i < ft.m_tiles_skipped; ++i) { + if (!(obj.*func)(tile, cur_td)) return false; + tile = TILE_ADD(tile, diff); + } + } + } + assert(TrackdirToTrack(cur_td) == TrackdirToTrack(GetLastTrackdir())); + + return (obj.*func)(cur, cur_td); + } + void Dump(DumpTarget &dmp) const { base::Dump(dmp); diff --git a/src/yapf/yapf_rail.cpp b/src/yapf/yapf_rail.cpp index 9da0da6..e76a117 100644 --- a/src/yapf/yapf_rail.cpp +++ b/src/yapf/yapf_rail.cpp @@ -9,6 +9,7 @@ #include "yapf_costrail.hpp" #include "yapf_destrail.hpp" #include "../vehicle_func.h" +#include "../pbs.h" #define DEBUG_YAPF_CACHE 0 @@ -104,6 +105,13 @@ public: typedef typename Node::Key Key; ///< key to hash tables protected: + TileIndex m_res_dest; ///< The reservation target tile + Trackdir m_res_dest_td; ///< The reservation target trackdir + Node *m_res_node; ///< The reservation target node + bool m_res_dest_res; ///< Is the target already reserved? + bool m_res_skip_tile; ///< Flag that the first tile of a node should be skipped when determining reservation target + TileIndex m_res_fail_tile; ///< The tile where the reservation failed + /// to access inherited path finder FORCEINLINE Tpf& Yapf() {return *static_cast(this);} @@ -121,16 +129,18 @@ public: /// return debug report character to identify the transportation type FORCEINLINE char TransportTypeChar() const {return 't';} - static Trackdir stChooseRailTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found) + static Trackdir stChooseRailTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found, bool reserve_track) { // create pathfinder instance Tpf pf1; - Trackdir result1 = pf1.ChooseRailTrack(v, tile, enterdir, tracks, path_not_found); +#if !DEBUG_YAPF_CACHE + Trackdir result1 = pf1.ChooseRailTrack(v, tile, enterdir, tracks, path_not_found, reserve_track); -#if DEBUG_YAPF_CACHE +#else + Trackdir result1 = pf1.ChooseRailTrack(v, tile, enterdir, tracks, path_not_found, false); Tpf pf2; pf2.DisableCache(true); - Trackdir result2 = pf2.ChooseRailTrack(v, tile, enterdir, tracks, path_not_found); + Trackdir result2 = pf2.ChooseRailTrack(v, tile, enterdir, tracks, path_not_found, reserve_track); if (result1 != result2) { DEBUG(yapf, 0, "CACHE ERROR: ChooseRailTrack() = [%d, %d]", result1, result2); DumpTarget dmp1, dmp2; @@ -148,7 +158,7 @@ public: return result1; } - FORCEINLINE Trackdir ChooseRailTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found) + FORCEINLINE Trackdir ChooseRailTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found, bool reserve_track) { // set origin and destination nodes Yapf().SetOrigin(v->tile, GetVehicleTrackdir(v), INVALID_TILE, INVALID_TRACKDIR, 1, true); @@ -166,21 +176,117 @@ public: Trackdir next_trackdir = INVALID_TRACKDIR; Node *pNode = Yapf().GetBestNode(); if (pNode != NULL) { + // reserve till end of path + m_res_dest = pNode->GetLastTile(); + m_res_dest_td = pNode->GetLastTrackdir(); + m_res_node = pNode; + m_res_dest_res = HasReservedTrack(m_res_dest, TrackToTrackBits(TrackdirToTrack(m_res_dest_td))); + if (!m_res_dest_res && IsRailwayStationTile(m_res_dest)) { + // Check the tile after a station, if it is reserved we can't + // use it as it might lead to a crash. + TrackFollower ft(v); + if (ft.Follow(m_res_dest, m_res_dest_td)) m_res_dest_res = HasReservedTrack(ft.m_new_tile, TrackdirBitsToTrackBits(ft.m_new_td_bits)); + } + // path was found or at least suggested // walk through the path back to the origin Node* pPrev = NULL; while (pNode->m_parent != NULL) { pPrev = pNode; pNode = pNode->m_parent; + + // a reservation can only stop at the first or second signal, so no + // need to search nodes with more passed signals. + if (pPrev->m_num_signals_passed > 0 && pNode->m_num_signals_passed <= 1) Yapf().FindSignalOnNode(v, pPrev); } // return trackdir from the best origin node (one of start nodes) Node& best_next_node = *pPrev; - assert(best_next_node.GetTile() == tile); next_trackdir = best_next_node.GetTrackdir(); + + if (reserve_track) Yapf().TryReserveTrack(v); } return next_trackdir; } + bool FindSignalProc(TileIndex tile, Trackdir td) + { + if (IsTileType(tile, MP_RAILWAY) && (HasSignalOnTrackdir(tile, td) || IsRailDepot(tile)) && !m_res_skip_tile) { + m_res_dest = tile; + m_res_dest_td = td; + m_res_dest_res = HasReservedTrack(tile, TrackToTrackBits(TrackdirToTrack(td))); + return false; /* Don't continue search. */ + } + m_res_skip_tile = false; + return true; + } + + void FindSignalOnNode(const Vehicle *v, Node *node) + { + assert(node->m_parent != NULL); + + /* Skip the first tile of the second segment, otherwise we could never + * pass a signal right in front of us. */ + m_res_skip_tile = node->m_parent->m_parent == NULL; + + if (!node->IterateTiles(v, Yapf(), &Tpf::FindSignalProc)) { + if (IsTileDepotType(m_res_dest, TRANSPORT_RAIL)) { + m_res_node = node; + } else { + /* Reserve tracks only to the tile in front of the signal. */ + TrackFollower ft(v); + ft.Follow(m_res_dest, ReverseTrackdir(m_res_dest_td)); + /* Did we skip a station? */ + if (ft.m_is_station) ft.m_new_tile = TILE_ADD(ft.m_new_tile, -ft.m_tiles_skipped * TileOffsByDiagDir(ft.m_exitdir)); + + /* Update node if the current tile is the first on the old node. */ + m_res_node = m_res_dest == node->GetTile() ? node->m_parent : node; + m_res_dest = ft.m_new_tile; + m_res_dest_td = ReverseTrackdir(FindFirstTrackdir(ft.m_new_td_bits)); + } + } + } + + bool ReserveSingleTrack(TileIndex tile, Trackdir td) + { + if (!TryReserveRailTrack(tile, TrackdirToTrack(td))) { + /* Tile couldn't be reserved, undo. */ + m_res_fail_tile = tile; + return false; + } + return tile != m_res_dest; + } + + bool UnreserveSingleTrack(TileIndex tile, Trackdir td) + { + if (tile != m_res_fail_tile) UnreserveRailTrack(tile, TrackdirToTrack(td)); + return tile != m_res_dest && tile != m_res_fail_tile; + } + + void TryReserveTrack(const Vehicle *v) + { + m_res_fail_tile = INVALID_TILE; + + /* Don't bother if the target is reserved. */ + if (m_res_dest_res) return; + + Node *node = m_res_node; + while (node->m_parent != NULL) { + node->IterateTiles(v, Yapf(), &Tpf::ReserveSingleTrack); + if (m_res_fail_tile != INVALID_TILE) { + /* Reservation failed, undo. */ + Node* fail_node = m_res_node; + do { + fail_node->IterateTiles(v, Yapf(), &Tpf::UnreserveSingleTrack); + } while (fail_node != node && (fail_node = fail_node->m_parent) != NULL); + return; + } + node = node->m_parent; + } + + if (Yapf().CanUseGlobalCache(*m_res_node)) + YapfNotifyTrackLayoutChange(INVALID_TILE, INVALID_TRACK); + } + static bool stCheckReverseTrain(Vehicle* v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2) { Tpf pf1; @@ -247,10 +353,10 @@ struct CYapfAnyDepotRail1 : CYapfT > {}; -Trackdir YapfChooseRailTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found) +Trackdir YapfChooseRailTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found, bool reserve_track) { // default is YAPF type 2 - typedef Trackdir (*PfnChooseRailTrack)(Vehicle*, TileIndex, DiagDirection, TrackBits, bool*); + typedef Trackdir (*PfnChooseRailTrack)(Vehicle*, TileIndex, DiagDirection, TrackBits, bool*, bool); PfnChooseRailTrack pfnChooseRailTrack = &CYapfRail1::stChooseRailTrack; // check if non-default YAPF type needed @@ -258,7 +364,7 @@ Trackdir YapfChooseRailTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, pfnChooseRailTrack = &CYapfRail2::stChooseRailTrack; // Trackdir, forbid 90-deg } - Trackdir td_ret = pfnChooseRailTrack(v, tile, enterdir, tracks, path_not_found); + Trackdir td_ret = pfnChooseRailTrack(v, tile, enterdir, tracks, path_not_found, reserve_track); return td_ret; } -- 1.5.3.5 From beeb78892da3e951504e17920b9c05a95fb6a690 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Thu, 31 Jan 2008 23:40:17 +0100 Subject: Added PBS related penalties to YAPF. --- src/yapf/yapf_costrail.hpp | 108 +++++++++++++++++++++++++++----------------- 1 files changed, 67 insertions(+), 41 deletions(-) diff --git a/src/yapf/yapf_costrail.hpp b/src/yapf/yapf_costrail.hpp index c274e49..3468092 100644 --- a/src/yapf/yapf_costrail.hpp +++ b/src/yapf/yapf_costrail.hpp @@ -128,6 +128,22 @@ public: return cost; } + /** The cost for reserved tiles, including skipped ones. */ + FORCEINLINE int ReservationCost(Node& n, TileIndex& tile, Trackdir trackdir, int skipped) + { + if (n.m_num_signals_passed >= m_sig_look_ahead_costs.Size() / 3) return 0; + + TrackBits tdb = TrackToTrackBits(TrackdirToTrack(trackdir)); + TrackBits res = GetReservedTrackbits(tile); + if ((res & tdb) != TRACK_BIT_NONE) { + return Yapf().PfGetSettings().rail_pbs_cross_penalty * (skipped + 1); + } else { + res |= tdb; + if (TracksOverlap(res)) return Yapf().PfGetSettings().rail_pbs_cross_penalty * (skipped + 1); + } + return 0; + } + int SignalCost(Node& n, TileIndex tile, Trackdir trackdir) { int cost = 0; @@ -142,50 +158,57 @@ public: } else if (has_signal_against && !has_signal_along && IsOnewaySignal(tile, TrackdirToTrack(trackdir))) { // one-way signal in opposite direction n.m_segment->m_end_segment_reason |= ESRB_DEAD_END; - } else if (has_signal_along) { - SignalState sig_state = GetSignalStateByTrackdir(tile, trackdir); - // cache the look-ahead polynomial constant only if we didn't pass more signals than the look-ahead limit is - int look_ahead_cost = (n.m_num_signals_passed < m_sig_look_ahead_costs.Size()) ? m_sig_look_ahead_costs.Data()[n.m_num_signals_passed] : 0; - if (sig_state != SIGNAL_STATE_RED) { - // green signal - n.flags_u.flags_s.m_last_signal_was_red = false; - // negative look-ahead red-signal penalties would cause problems later, so use them as positive penalties for green signal - if (look_ahead_cost < 0) { - // add its negation to the cost - cost -= look_ahead_cost; - } - } else { - // we have a red signal in our direction - // was it first signal which is two-way? - if (Yapf().TreatFirstRedTwoWaySignalAsEOL() && n.flags_u.flags_s.m_choice_seen && has_signal_against && n.m_num_signals_passed == 0) { - // yes, the first signal is two-way red signal => DEAD END - n.m_segment->m_end_segment_reason |= ESRB_DEAD_END; - Yapf().m_stopped_on_first_two_way_signal = true; - return -1; - } - SignalType sig_type = GetSignalType(tile, TrackdirToTrack(trackdir)); - n.m_last_red_signal_type = sig_type; - n.flags_u.flags_s.m_last_signal_was_red = true; - - // look-ahead signal penalty - if (look_ahead_cost > 0) { - // add the look ahead penalty only if it is positive - cost += look_ahead_cost; - } + } else { + if (has_signal_along) { + SignalState sig_state = GetSignalStateByTrackdir(tile, trackdir); + // cache the look-ahead polynomial constant only if we didn't pass more signals than the look-ahead limit is + int look_ahead_cost = (n.m_num_signals_passed < m_sig_look_ahead_costs.Size()) ? m_sig_look_ahead_costs.Data()[n.m_num_signals_passed] : 0; + if (sig_state != SIGNAL_STATE_RED) { + // green signal + n.flags_u.flags_s.m_last_signal_was_red = false; + // negative look-ahead red-signal penalties would cause problems later, so use them as positive penalties for green signal + if (look_ahead_cost < 0) { + // add its negation to the cost + cost -= look_ahead_cost; + } + } else { + // we have a red signal in our direction + // was it first signal which is two-way? + if (Yapf().TreatFirstRedTwoWaySignalAsEOL() && n.flags_u.flags_s.m_choice_seen && has_signal_against && n.m_num_signals_passed == 0) { + // yes, the first signal is two-way red signal => DEAD END + n.m_segment->m_end_segment_reason |= ESRB_DEAD_END; + Yapf().m_stopped_on_first_two_way_signal = true; + return -1; + } + SignalType sig_type = GetSignalType(tile, TrackdirToTrack(trackdir)); + n.m_last_red_signal_type = sig_type; + n.flags_u.flags_s.m_last_signal_was_red = true; + + // look-ahead signal penalty + if (!IsPbsSignal(sig_type) && look_ahead_cost > 0) { + // add the look ahead penalty only if it is positive + cost += look_ahead_cost; + } - // special signal penalties - if (n.m_num_signals_passed == 0) { - switch (sig_type) { - case SIGTYPE_COMBO: - case SIGTYPE_EXIT: cost += Yapf().PfGetSettings().rail_firstred_exit_penalty; break; // first signal is red pre-signal-exit - case SIGTYPE_NORMAL: - case SIGTYPE_ENTRY: cost += Yapf().PfGetSettings().rail_firstred_penalty; break; - }; + // special signal penalties + if (n.m_num_signals_passed == 0) { + switch (sig_type) { + case SIGTYPE_COMBO: + case SIGTYPE_EXIT: cost += Yapf().PfGetSettings().rail_firstred_exit_penalty; break; // first signal is red pre-signal-exit + case SIGTYPE_NORMAL: + case SIGTYPE_ENTRY: cost += Yapf().PfGetSettings().rail_firstred_penalty; break; + }; + } } + + n.m_num_signals_passed++; + n.m_segment->m_last_signal_tile = tile; + n.m_segment->m_last_signal_td = trackdir; + } + + if (has_signal_against && IsPbsSignal(GetSignalType(tile, TrackdirToTrack(trackdir)))) { + cost += n.m_num_signals_passed < Yapf().PfGetSettings().rail_look_ahead_max_signals ? Yapf().PfGetSettings().rail_pbs_signal_back_penalty : 0; } - n.m_num_signals_passed++; - n.m_segment->m_last_signal_tile = tile; - n.m_segment->m_last_signal_td = trackdir; } } return cost; @@ -330,6 +353,9 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th /* Slope cost. */ segment_cost += Yapf().SlopeCost(cur.tile, cur.td); + /* Reserved tiles. */ + segment_cost += Yapf().ReservationCost(n, cur.tile, cur.td, tf->m_tiles_skipped); + /* Signal cost (routine can modify segment data). */ segment_cost += Yapf().SignalCost(n, cur.tile, cur.td); end_segment_reason = segment.m_end_segment_reason; -- 1.5.3.5 From d130edc0099e5bb8c381595adc0ff85c82e59b4c Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Mon, 4 Feb 2008 02:03:48 +0100 Subject: Added PBS related penalties to NPF. --- src/npf.cpp | 78 +++++++++++++++++++++++++++++++++++++++++++---------------- src/npf.h | 2 + 2 files changed, 59 insertions(+), 21 deletions(-) diff --git a/src/npf.cpp b/src/npf.cpp index b922fb4..e3477a8 100644 --- a/src/npf.cpp +++ b/src/npf.cpp @@ -23,6 +23,7 @@ #include "vehicle_base.h" #include "settings_type.h" #include "tunnelbridge.h" +#include "pbs.h" static AyStar _npf_aystar; @@ -220,6 +221,23 @@ static uint NPFSlopeCost(AyStarNode* current) * there is only one level of steepness... */ } +static uint NPFReservedTrackCost(AyStarNode* current) +{ + TileIndex tile = current->tile; + TrackBits track = TrackToTrackBits(TrackdirToTrack((Trackdir)current->direction)); + TrackBits res = GetReservedTrackbits(tile); + + if (NPFGetFlag(current, NPF_FLAG_3RD_SIGNAL) || (res & track) == TRACK_BIT_NONE && !TracksOverlap(res | track)) return 0; + + if (IsTileType(tile, MP_TUNNELBRIDGE)) { + DiagDirection exitdir = TrackdirToExitdir((Trackdir)current->direction); + if (GetTunnelBridgeDirection(tile) == ReverseDiagDir(exitdir)) { + return _patches.npf_rail_pbs_cross_penalty * (GetTunnelBridgeLength(tile, GetOtherTunnelBridgeEnd(tile)) + 1); + } + } + return _patches.npf_rail_pbs_cross_penalty; +} + /** * Mark tiles by mowing the grass when npf debug level >= 1. * Will not work for multiplayer games, since it can (will) cause desyncs. @@ -353,30 +371,48 @@ static int32 NPFRailPathCost(AyStar* as, AyStarNode* current, OpenListNode* pare /* Determine extra costs */ /* Check for signals */ - if (IsTileType(tile, MP_RAILWAY) && HasSignalOnTrackdir(tile, trackdir)) { - /* Ordinary track with signals */ - if (GetSignalStateByTrackdir(tile, trackdir) == SIGNAL_STATE_RED) { - /* Signal facing us is red */ - if (!NPFGetFlag(current, NPF_FLAG_SEEN_SIGNAL)) { - /* Penalize the first signal we - * 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; + if (IsTileType(tile, MP_RAILWAY)) { + if (HasSignalOnTrackdir(tile, trackdir)) { + /* Ordinary track with signals */ + if (GetSignalStateByTrackdir(tile, trackdir) == SIGNAL_STATE_RED) { + /* Signal facing us is red */ + if (!NPFGetFlag(current, NPF_FLAG_SEEN_SIGNAL)) { + /* Penalize the first signal we + * encounter, if it is red */ + + /* Is this a presignal exit or combo? */ + SignalType sigtype = GetSignalType(tile, TrackdirToTrack(trackdir)); + if (!IsPbsSignal(sigtype)) { + if (sigtype == SIGTYPE_EXIT || sigtype == SIGTYPE_COMBO) { + /* Penalise exit and combo signals differently (heavier) */ + cost += _patches.npf_rail_firstred_exit_penalty; + } else { + cost += _patches.npf_rail_firstred_penalty; + } + } + } + /* Record the state of this signal */ + NPFSetFlag(current, NPF_FLAG_LAST_SIGNAL_RED, true); + } else { + /* Record the state of this signal */ + NPFSetFlag(current, NPF_FLAG_LAST_SIGNAL_RED, false); + } + if (NPFGetFlag(current, NPF_FLAG_SEEN_SIGNAL)) { + if (NPFGetFlag(current, NPF_FLAG_2ND_SIGNAL)) { + NPFSetFlag(current, NPF_FLAG_3RD_SIGNAL, true); } else { - cost += _patches.npf_rail_firstred_penalty; + NPFSetFlag(current, NPF_FLAG_2ND_SIGNAL, true); } + } else { + NPFSetFlag(current, NPF_FLAG_SEEN_SIGNAL, true); + } + } + + if (HasSignalOnTrackdir(tile, ReverseTrackdir(trackdir))) { + if (!NPFGetFlag(current, NPF_FLAG_3RD_SIGNAL) && IsPbsSignal(GetSignalType(tile, TrackdirToTrack(trackdir)))) { + cost += _patches.npf_rail_pbs_signal_back_penalty; } - /* Record the state of this signal */ - NPFSetFlag(current, NPF_FLAG_LAST_SIGNAL_RED, true); - } else { - /* Record the state of this signal */ - NPFSetFlag(current, NPF_FLAG_LAST_SIGNAL_RED, false); } - NPFSetFlag(current, NPF_FLAG_SEEN_SIGNAL, true); } /* Penalise the tile if it is a target tile and the last signal was @@ -405,7 +441,7 @@ static int32 NPFRailPathCost(AyStar* as, AyStarNode* current, OpenListNode* pare } /* Check for occupied track */ - //TODO + cost += NPFReservedTrackCost(current); NPFMarkTile(tile); DEBUG(npf, 4, "Calculating G for: (%d, %d). Result: %d", TileX(current->tile), TileY(current->tile), cost); diff --git a/src/npf.h b/src/npf.h index afe8aee..1b2ebc0 100644 --- a/src/npf.h +++ b/src/npf.h @@ -64,6 +64,8 @@ enum NPFNodeFlag { NPF_FLAG_SEEN_SIGNAL, ///< Used to mark that a signal was seen on the way, for rail only NPF_FLAG_REVERSE, ///< Used to mark that this node was reached from the second start node, if applicable NPF_FLAG_LAST_SIGNAL_RED, ///< Used to mark that the last signal on this path was red + NPF_FLAG_2ND_SIGNAL, ///< Used to mark that two signals were seen, rail only + NPF_FLAG_3RD_SIGNAL, ///< Used to mark that three signals were seen, rail only NPF_FLAG_TARGET_RESERVED ///< Used to mark that the possible reservation target is already reserved }; -- 1.5.3.5 From 1097cad3b1eebbcd0966ed721126d2af6c3907ca Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Thu, 31 Jan 2008 23:27:25 +0100 Subject: Trains reserve paths through PBS signals. --- src/train_cmd.cpp | 155 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 138 insertions(+), 17 deletions(-) diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 612f383..9d62f1c 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -47,10 +47,13 @@ #include "autoreplace_gui.h" #include "gfx_func.h" #include "settings_type.h" +#include "pbs.h" +#include "yapf/follow_track.hpp" #include "table/strings.h" #include "table/train_cmd.h" +static Track DoTrainPathfind(Vehicle* v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found, bool do_track_reservation); static bool TrainCheckIfLineEnds(Vehicle *v); static void TrainController(Vehicle *v, bool update_image); static TileIndex TrainApproachingCrossingTile(const Vehicle *v); @@ -2223,6 +2226,44 @@ void Train::PlayLeaveStationSound() const TrainPlayLeaveStationSound(this); } +static void CheckNextTrainTile(Vehicle *v) +{ + DiagDirection dir = TrainExitDir(v->direction, v->u.rail.track); + TileIndex next_tile = TileAddByDiagDir(v->tile, dir); + + if (v->tile == v->dest_tile) return; + + /* Exit if the current order doesn't have a destination. */ + if (v->current_order.type == OT_NOTHING || v->current_order.type == OT_LEAVESTATION) return; + + /* Check if we reached our destination and it is not a TTDPatch non-stop destination */ + if (v->current_order.type == OT_GOTO_STATION && IsRailwayStationTile(v->tile)) { + if (v->current_order.dest == GetStationIndex(v->tile) && !(_patches.new_nonstop && v->current_order.flags & OFB_NON_STOP)) return; + } + + /* Tunnel/bridge entrance? */ + if (IsTileType(v->tile, MP_TUNNELBRIDGE) && GetTunnelBridgeDirection(v->tile) == dir) return; + if (IsDepotTile(v->tile) && GetRailDepotDirection(v->tile) == ReverseDiagDir(dir)) return; + + if (IsTileType(next_tile, MP_RAILWAY) && HasSignals(next_tile)) { + TrackBits bits = GetTrackBits(next_tile) & DiagdirReachesTracks(dir); + if (bits == TRACK_BIT_NONE || HasReservedTrack(next_tile, bits)) return; + /* A signal tile can't be a junction tile */ + assert(KillFirstBit(bits) == TRACK_BIT_NONE); + Track track = TrackBitsToTrack(bits); + Trackdir tdir = TrackEnterdirToTrackdir(track, dir); + if (HasPbsSignalOnTrackdir(next_tile, tdir)) { + DoTrainPathfind(v, next_tile, dir, bits, NULL, true); + + /* Did we get our reservation? */ + if (HasReservedTrack(next_tile, bits)) { + SetSignalStateByTrackdir(next_tile, tdir, SIGNAL_STATE_GREEN); + MarkTileDirtyByTile(next_tile); + } + } + } +} + static bool CheckTrainStayInDepot(Vehicle *v) { /* bail out if not all wagons are in the same depot or not in a depot at all */ @@ -2271,6 +2312,37 @@ static bool CheckTrainStayInDepot(Vehicle *v) return false; } +/** Clear the reservation of a tile that was just left by a wagon on track_dir. */ +static void ClearPathReservation(TileIndex tile, Trackdir track_dir) +{ + DiagDirection dir = TrackdirToExitdir(track_dir); + + if (IsTileType(tile, MP_TUNNELBRIDGE)) { + /* Are we just leaving a tunnel/bridge? */ + if (GetTunnelBridgeDirection(tile) == ReverseDiagDir(dir)) { + TileIndex end = GetOtherTunnelBridgeEnd(tile); + + SetTunnelBridgeReservation(tile, false); + SetTunnelBridgeReservation(end, false); + + if (_debug_pbs_level >= 2) { + MarkTileDirtyByTile(tile); + MarkTileDirtyByTile(end); + } + } + } else if (IsRailwayStationTile(tile)) { + TileIndex new_tile = TileAddByDiagDir(tile, dir); + /* If the new tile is not a further tile of the same station, we + * clear the reservation for the whole platform. */ + if (!IsRailwayStationTile(new_tile) || GetStationIndex(tile) != GetStationIndex(new_tile)) { + SetRailwayStationPlatformReservation(tile, ReverseDiagDir(dir), false); + } + } else { + /* Any other tile */ + UnreserveRailTrack(tile, TrackdirToTrack(track_dir)); + } +} + /* Check for station tiles */ struct TrainTrackFollowerData { TileIndex dest_coords; @@ -2347,34 +2419,28 @@ static const byte _search_directions[6][4] = { static const byte _pick_track_table[6] = {1, 3, 2, 2, 0, 0}; -/* choose a track */ -static Track ChooseTrainTrack(Vehicle* v, TileIndex tile, DiagDirection enterdir, TrackBits tracks) +static Track DoTrainPathfind(Vehicle* v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found, bool do_track_reservation) { Track best_track; - /* pathfinders are able to tell that route was only 'guessed' */ - bool path_not_found = false; #ifdef PF_BENCHMARK TIC() #endif - assert((tracks & ~TRACK_BIT_MASK) == 0); - - /* quick return in case only one possible track is available */ - if (KillFirstBit(tracks) == TRACK_BIT_NONE) return FindFirstTrack(tracks); + if (path_not_found) *path_not_found = false; if (_patches.yapf.rail_use_yapf) { - Trackdir trackdir = YapfChooseRailTrack(v, tile, enterdir, tracks, &path_not_found); + Trackdir trackdir = YapfChooseRailTrack(v, tile, enterdir, tracks, path_not_found, do_track_reservation); if (trackdir != INVALID_TRACKDIR) { best_track = TrackdirToTrack(trackdir); } else { best_track = FindFirstTrack(tracks); } - } else if (_patches.new_pathfinding_all) { /* Use a new pathfinding for everything */ + } else if (_patches.new_pathfinding_all || do_track_reservation) { /* Use a new pathfinding for everything */ void* perf = NpfBeginInterval(); NPFFindStationOrTileData fstd; - NPFFillWithOrderData(&fstd, v); + NPFFillWithOrderData(&fstd, v, do_track_reservation); /* The enterdir for the new tile, is the exitdir for the old tile */ Trackdir trackdir = GetVehicleTrackdir(v); assert(trackdir != 0xff); @@ -2391,7 +2457,7 @@ static Track ChooseTrainTrack(Vehicle* v, TileIndex tile, DiagDirection enterdir the direction we need to take to get there, if ftd.best_bird_dist is not 0, we did not find our target, but ftd.best_trackdir contains the direction leading to the tile closest to our target. */ - if (ftd.best_bird_dist != 0) path_not_found = true; + if (ftd.best_bird_dist != 0 && path_not_found != NULL) *path_not_found = true; /* Discard enterdir information, making it a normal track */ best_track = TrackdirToTrack(ftd.best_trackdir); } @@ -2413,7 +2479,7 @@ static Track ChooseTrainTrack(Vehicle* v, TileIndex tile, DiagDirection enterdir v->u.rail.compatible_railtypes, enterdir, (NTPEnumProc*)NtpCallbFindStation, &fd); /* check whether the path was found or only 'guessed' */ - if (fd.best_bird_dist != 0) path_not_found = true; + if (fd.best_bird_dist != 0 && path_not_found != NULL) *path_not_found = true; if (fd.best_track == 0xff) { /* blaha */ @@ -2425,6 +2491,49 @@ static Track ChooseTrainTrack(Vehicle* v, TileIndex tile, DiagDirection enterdir int time = NpfEndInterval(perf); DEBUG(yapf, 4, "[NTPT] %d us - %d rounds - %d open - %d closed -- ", time, 0, 0, 0); } + +#ifdef PF_BENCHMARK + TOC("PF time = ", 1) +#endif + + return best_track; +} + +/* choose a track */ +static Track ChooseTrainTrack(Vehicle* v, TileIndex tile, DiagDirection enterdir, TrackBits tracks) +{ + Track best_track; + /* pathfinders are able to tell that route was only 'guessed' */ + bool path_not_found = false; + bool do_track_reservation = _patches.reserve_paths; + bool turn_signal_green = false; + + assert((tracks & ~TRACK_BIT_MASK) == 0); + + TrackBits res_tracks = (TrackBits)(GetReservedTrackbits(tile) & tracks); + assert(KillFirstBit(res_tracks) == TRACK_BIT_NONE); + /* do we have a suitable reserved track? */ + if (res_tracks != TRACK_BIT_NONE) return FindFirstTrack(res_tracks); + + /* quick return in case only one possible track is available */ + if (KillFirstBit(tracks) == TRACK_BIT_NONE) { + Track track = FindFirstTrack(tracks); + /* We need to check for signals only here, as a junction tile can't have signals. */ + if (track != INVALID_TRACK && HasPbsSignalOnTrackdir(tile, TrackEnterdirToTrackdir(track, enterdir))) { + do_track_reservation = true; + turn_signal_green = true; + } else { + return track; + } + } + + best_track = DoTrainPathfind(v, tile, enterdir, tracks, &path_not_found, do_track_reservation); + + if (turn_signal_green && HasBit(GetReservedTrackbits(tile), best_track)) { + SetSignalStateByTrackdir(tile, TrackEnterdirToTrackdir(best_track, enterdir), SIGNAL_STATE_GREEN); + MarkTileDirtyByTile(tile); + } + /* handle "path not found" state */ if (path_not_found) { /* PF didn't find the route */ @@ -2450,10 +2559,6 @@ static Track ChooseTrainTrack(Vehicle* v, TileIndex tile, DiagDirection enterdir } } -#ifdef PF_BENCHMARK - TOC("PF time = ", 1) -#endif - return best_track; } @@ -3007,6 +3112,10 @@ static void TrainController(Vehicle *v, bool update_image) TrainEnterStation(v, r >> VETS_STATION_ID_OFFSET); return; } + if (v->Next() == NULL && IsTileDepotType(v->tile, TRANSPORT_RAIL) && HasBit(r, VETS_ENTERED_WORMHOLE)) { + SetDepotReservation(v->tile, false); + if (_debug_pbs_level >= 2) MarkTileDirtyByTile(v->tile); + } if (v->current_order.type == OT_LEAVESTATION) { v->current_order.Free(); @@ -3108,6 +3217,16 @@ static void TrainController(Vehicle *v, bool update_image) if (IsFrontEngine(v)) v->load_unload_time_rem = 0; if (!HasBit(r, VETS_ENTERED_WORMHOLE)) { + Track track = FindFirstTrack(chosen_track); + Trackdir tdir = TrackDirectionToTrackdir(track, chosen_dir); + if (IsFrontEngine(v) && HasPbsSignalOnTrackdir(gp.new_tile, tdir)) { + SetSignalStateByTrackdir(gp.new_tile, tdir, SIGNAL_STATE_RED); + MarkTileDirtyByTile(gp.new_tile); + } + + /* Clear any track reservation when the last vehicle leaves the tile */ + if (v->Next() == NULL) ClearPathReservation(v->tile, GetVehicleTrackdir(v)); + v->tile = gp.new_tile; if (GetTileRailType(gp.new_tile) != GetTileRailType(gp.old_tile)) { @@ -3169,6 +3288,8 @@ static void TrainController(Vehicle *v, bool update_image) if (IsLevelCrossingTile(gp.old_tile)) UpdateLevelCrossing(gp.old_tile); } } + + if (IsFrontEngine(v)) CheckNextTrainTile(v); } return; -- 1.5.3.5 From 2fb327b7c5445dce6c6d05ea7a8b9ba031a3cfa3 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Thu, 31 Jan 2008 23:30:59 +0100 Subject: Free reservation of crashed trains. --- src/map_func.h | 17 ++++++++++++++ src/rail_map.h | 5 +++- src/train.h | 2 + src/train_cmd.cpp | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 1 deletions(-) diff --git a/src/map_func.h b/src/map_func.h index 9e2a5d7..7a89a7d 100644 --- a/src/map_func.h +++ b/src/map_func.h @@ -268,6 +268,23 @@ static inline TileIndexDiffC TileIndexDiffCByDir(Direction dir) return _tileoffs_by_dir[dir]; } +/* + * Returns the DiagDirection from a TileIndexDiffC. + * + * @param diff The tile offset + * @return The diagonal direction + */ +static inline DiagDirection DiagDirByTileIndexDiff(const TileIndexDiffC& diff) +{ + assert(diff.x == 0 || diff.y == 0); + + if (diff.x == 0) { + return diff.y > 0 ? DIAGDIR_SE : DIAGDIR_NW; + } else { + return diff.x > 0 ? DIAGDIR_SW : DIAGDIR_NE; + } +} + /** * Add a TileIndexDiffC to a TileIndex and returns the new one. * diff --git a/src/rail_map.h b/src/rail_map.h index ad94bd8..d6d3b89 100644 --- a/src/rail_map.h +++ b/src/rail_map.h @@ -535,7 +535,10 @@ static inline void SetSignalStateByTrackdir(TileIndex tile, Trackdir trackdir, S */ static inline bool HasNoEntrySignalOnTrackdir(TileIndex tile, Trackdir td) { - return HasSignalOnTrackdir(tile, td) && GetSignalType(tile, TrackdirToTrack(td)) == SIGTYPE_NOENTRY; + return + IsTileType(tile, MP_RAILWAY) && + HasSignalOnTrackdir(tile, td) && + GetSignalType(tile, TrackdirToTrack(td)) == SIGTYPE_NOENTRY; } /** diff --git a/src/train.h b/src/train.h index 05b7951..50e279d 100644 --- a/src/train.h +++ b/src/train.h @@ -275,6 +275,8 @@ byte FreightWagonMult(CargoID cargo); int CheckTrainInDepot(const Vehicle *v, bool needs_to_be_stopped); int CheckTrainStoppedInDepot(const Vehicle *v); +void FreeTrainTrackReservation(const Vehicle *v); + /** * This class 'wraps' Vehicle; you do not actually instantiate this class. * You create a Vehicle using AllocateVehicle, so it is added to the pool diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 9d62f1c..5e10cd4 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -2343,6 +2343,49 @@ static void ClearPathReservation(TileIndex tile, Trackdir track_dir) } } +/** Free the reserved path in front of a vehicle. */ +void FreeTrainTrackReservation(const Vehicle *v) +{ + assert(IsFrontEngine(v)); + + CFollowTrackRail ft(v); + + bool dont_free_tile = IsRailwayStationTile(v->tile) || IsTileType(v->tile, MP_TUNNELBRIDGE); + TileIndex tile = v->tile; + Trackdir td = GetVehicleTrackdir(v); + + /* Don't free reservation if it's not ours. */ + if (TracksOverlap(GetReservedTrackbits(tile) | TrackToTrackBits(TrackdirToTrack(td)))) return; + + do { + if (!ft.Follow(tile, td)) break; + + tile = ft.m_new_tile; + TrackdirBits bits = (TrackdirBits)(ft.m_new_td_bits & (GetReservedTrackbits(tile) * 0x101)); + td = RemoveFirstTrackdir(&bits); + assert(bits == TRACKDIR_BIT_NONE); + + if (!IsValidTrackdir(td)) break; + + if (HasNoEntrySignalOnTrackdir(tile, td)) break; + if (HasPbsSignalOnTrackdir(tile, td)) { + if (GetSignalStateByTrackdir(tile, td) == SIGNAL_STATE_RED) { + /* Red PBS signal? Can't be our reservation, would be green then. */ + break; + } else { + /* Turn the signal back to red. */ + SetSignalStateByTrackdir(tile, td, SIGNAL_STATE_RED); + MarkTileDirtyByTile(tile); + } + } + + /* Don't free first station/bridge/tunnel if we are on it. */ + if (!(dont_free_tile && (ft.m_is_station || ft.m_is_tunnel || ft.m_is_bridge))) ClearPathReservation(tile, td); + + dont_free_tile = false; + } while (true); +} + /* Check for station tiles */ struct TrainTrackFollowerData { TileIndex dest_coords; @@ -3016,12 +3059,14 @@ static void *FindTrainCollideEnum(Vehicle *v, void *data) if (!(tcc->v->vehstatus & VS_CRASHED)) { /* two drivers + passengers killed in train tcc->v (if it was not crashed already) */ tcc->num += 2 + CountPassengersInTrain(tcc->v); + if (IsFrontEngine(tcc->v)) FreeTrainTrackReservation(tcc->v); SetVehicleCrashed(tcc->v); } if (!(coll->vehstatus & VS_CRASHED)) { /* two drivers + passengers killed in train coll (if it was not crashed already) */ tcc->num += 2 + CountPassengersInTrain(coll); + FreeTrainTrackReservation(coll); SetVehicleCrashed(coll); } } @@ -3341,6 +3386,26 @@ static void DeleteLastWagon(Vehicle *v) MarkSingleVehicleDirty(v); + /* Clear a possible path reservation */ + if (IsFrontEngine(v)) { + if (IsTileType(v->tile, MP_TUNNELBRIDGE) && GetTunnelBridgeReservation(v->tile)) { + DiagDirection dir = ReverseDiagDir(GetTunnelBridgeDirection(v->tile)); + ClearPathReservation(v->tile, DiagdirToDiagTrackdir(dir)); + } else if (IsRailwayStationTile(v->tile) && GetRailwayStationReservation(v->tile)) { + DiagDirection dir = AxisToDiagDir(GetRailStationAxis(v->tile)); + SetRailwayStationPlatformReservation(v->tile, dir, false); + SetRailwayStationPlatformReservation(v->tile, ReverseDiagDir(dir), false); + } else if ((v->u.rail.track == TRACK_BIT_DEPOT && GetDepotReservation(v->tile)) || HasReservedTrack(v->tile, v->u.rail.track)) { + ClearPathReservation(v->tile, TrackToTrackdir(TrackBitsToTrack(v->u.rail.track))); + } + } else if ((v->u.rail.track & ~TRACK_BIT_MASK) == TRACK_BIT_NONE && u->tile != v->tile && HasReservedTrack(v->tile, v->u.rail.track)) { + DiagDirection dir = DiagDirByTileIndexDiff(TileIndexToTileIndexDiffC(u->tile, v->tile)); + Trackdir td = TrackExitdirToTrackdir(TrackBitsToTrack(v->u.rail.track), dir); + assert(IsValidTrackdir(td)); + + ClearPathReservation(v->tile, td); + } + /* 'v' shouldn't be accessed after it has been deleted */ TrackBits track = v->u.rail.track; TileIndex tile = v->tile; -- 1.5.3.5 From 85e7b1927e424e374c286bbcfdb51edd87de7289 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Thu, 31 Jan 2008 23:32:58 +0100 Subject: Reserve a path when exiting a depot into a PBS block. --- src/signal.cpp | 32 +++++++++++++++++++++----------- src/signal_func.h | 9 ++++++++- src/train_cmd.cpp | 30 +++++++++++++++++++++++++++++- 3 files changed, 58 insertions(+), 13 deletions(-) diff --git a/src/signal.cpp b/src/signal.cpp index 3f6ec9c..696bf41 100644 --- a/src/signal.cpp +++ b/src/signal.cpp @@ -256,6 +256,7 @@ enum SigFlags { SF_GREEN = 1 << 3, ///< green exitsignal found SF_GREEN2 = 1 << 4, ///< two or more green exits found SF_FULL = 1 << 5, ///< some of buffers was full, do not continue + SF_PBS = 1 << 6, ///< pbs signal found }; DECLARE_ENUM_AS_BIT_SET(SigFlags) @@ -322,13 +323,17 @@ static SigFlags ExploreSegment(Owner owner) Trackdir trackdir = (Trackdir)FindFirstBit((tracks * 0x101) & _enterdir_to_trackdirbits[enterdir]); Trackdir reversedir = ReverseTrackdir(trackdir); /* add (tile, reversetrackdir) to 'to-be-updated' set when there is - * ANY signal in REVERSE direction + * ANY conventional signal in REVERSE direction * (if it is a presignal EXIT and it changes, it will be added to 'to-be-done' set later) */ if (HasSignalOnTrackdir(tile, reversedir)) { - if (!_tbuset.Add(tile, reversedir)) return flags | SF_FULL; + if (sig == SIGTYPE_PBS) { + flags |= SF_PBS; + } else { + if (!_tbuset.Add(tile, reversedir)) return flags | SF_FULL; + } } /* if it is a presignal EXIT in OUR direction and we haven't found 2 green exits yes, do special check */ - if (!(flags & SF_GREEN2) && (sig & SIGTYPE_EXIT) && HasSignalOnTrackdir(tile, trackdir)) { // found presignal exit + if (!(flags & SF_GREEN2) && IsPresignalExit(tile, track) && HasSignalOnTrackdir(tile, trackdir)) { // found presignal exit if (flags & SF_EXIT) flags |= SF_EXIT2; // found two (or more) exits flags |= SF_EXIT; // found at least one exit - allow for compiler optimizations if (GetSignalStateByTrackdir(tile, trackdir) == SIGNAL_STATE_GREEN) { // found green presignal exit @@ -336,6 +341,7 @@ static SigFlags ExploreSegment(Owner owner) flags |= SF_GREEN; } } + continue; } } @@ -433,13 +439,13 @@ static void UpdateSignalsAroundSegment(SigFlags flags) newstate = SIGNAL_STATE_RED; } } else { // entry, at least one exit, no green exit - if (sig & SIGTYPE_ENTRY && (flags & SF_EXIT && !(flags & SF_GREEN))) newstate = SIGNAL_STATE_RED; + if (IsPresignalEntry(tile, TrackdirToTrack(trackdir)) && (flags & SF_EXIT && !(flags & SF_GREEN))) newstate = SIGNAL_STATE_RED; } } /* only when the state changes */ if (newstate != GetSignalStateByTrackdir(tile, trackdir)) { - if (sig & SIGTYPE_EXIT) { + if (IsPresignalExit(tile, TrackdirToTrack(trackdir))) { /* for pre-signal exits, add block to the global set */ DiagDirection exitdir = TrackdirToExitdir(ReverseTrackdir(trackdir)); _globset.Add(tile, exitdir); // do not check for full global set, first update all signals @@ -465,15 +471,15 @@ static inline void ResetSets() * Updates blocks in _globset buffer * * @param owner player whose signals we are updating - * @return false iff presignal entry would be green (needed for trains leaving depot) + * @return state of the first block from _globset * @pre IsValidPlayer(owner) */ -static bool UpdateSignalsInBuffer(Owner owner) +static SigSegState UpdateSignalsInBuffer(Owner owner) { assert(IsValidPlayer(owner)); bool first = true; // first block? - bool state = false; // value to return + SigSegState state = SIGSEG_FREE; // value to return TileIndex tile; DiagDirection dir; @@ -532,7 +538,11 @@ static bool UpdateSignalsInBuffer(Owner owner) if (first) { first = false; - state = (flags & SF_TRAIN) || (flags & SF_EXIT && !(flags & SF_GREEN)) || (flags & SF_FULL); // true iff train CAN'T leave the depot + if (flags & SF_PBS) { + state = SIGSEG_PBS; + } else if ((flags & SF_TRAIN) || (flags & SF_EXIT && !(flags & SF_GREEN) || (flags & SF_FULL))) { + state = SIGSEG_FULL; + } } /* do not do anything when some buffer was full */ @@ -627,9 +637,9 @@ void AddSideToSignalBuffer(TileIndex tile, DiagDirection side, Owner owner) * @param tile tile where we start * @param side side of tile * @param owner owner whose signals we will update - * @return false iff train can leave depot + * @return the state of the signal segment */ -bool UpdateSignalsOnSegment(TileIndex tile, DiagDirection side, Owner owner) +SigSegState UpdateSignalsOnSegment(TileIndex tile, DiagDirection side, Owner owner) { assert(_globset.IsEmpty()); _globset.Add(tile, side); diff --git a/src/signal_func.h b/src/signal_func.h index a5479a3..371996b 100644 --- a/src/signal_func.h +++ b/src/signal_func.h @@ -41,7 +41,14 @@ static inline byte SignalOnTrack(Track track) return _signal_on_track[track]; } -bool UpdateSignalsOnSegment(TileIndex tile, DiagDirection side, Owner owner); +/** State of the signal segment */ +enum SigSegState { + SIGSEG_FREE, ///< Free and has no pre-signal exits or at least one green exit + SIGSEG_FULL, ///< Occupied by a train + SIGSEG_PBS ///< Segment is a PBS segment +}; + +SigSegState UpdateSignalsOnSegment(TileIndex tile, DiagDirection side, Owner owner); void SetSignalsOnBothDir(TileIndex tile, Track track, Owner owner); void AddTrackToSignalBuffer(TileIndex tile, Track track, Owner owner); void AddSideToSignalBuffer(TileIndex tile, DiagDirection side, Owner owner); diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 5e10cd4..e53f733 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -2278,7 +2278,10 @@ static bool CheckTrainStayInDepot(Vehicle *v) return true; } + SigSegState sig_state = UpdateSignalsOnSegment(v->tile, INVALID_DIAGDIR, v->owner); + if (v->u.rail.force_proceed == 0) { + /* force proceed was not pressed */ if (++v->load_unload_time_rem < 37) { InvalidateWindowClasses(WC_TRAINS_LIST); return true; @@ -2286,10 +2289,35 @@ static bool CheckTrainStayInDepot(Vehicle *v) v->load_unload_time_rem = 0; - if (UpdateSignalsOnSegment(v->tile, INVALID_DIAGDIR, v->owner)) { + if (sig_state == SIGSEG_FULL || GetDepotReservation(v->tile)) { + InvalidateWindowClasses(WC_TRAINS_LIST); + return true; + } + } + + if (sig_state == SIGSEG_PBS) { + /* Try to reserve a path */ + DiagDirection dir = GetRailDepotDirection(v->tile); + TileIndex next_tile = TileAddByDiagDir(v->tile, dir); + + uint32 ts = GetTileTrackStatus(next_tile, TRANSPORT_RAIL, 0) & DiagdirReachesTrackdirs(dir); + TrackBits bits = TrackdirBitsToTrackBits((TrackdirBits)ts); + + if ((GetDepotReservation(v->tile) || HasReservedTrack(next_tile, bits)) && v->u.rail.force_proceed == 0) { + /* tile is already reserved */ + InvalidateWindowClasses(WC_TRAINS_LIST); + return true; + } + + if (bits != TRACK_BIT_NONE) DoTrainPathfind(v, next_tile, dir, bits, NULL, true); + + /* Did we get our reservation? */ + if (!HasReservedTrack(next_tile, bits) && v->u.rail.force_proceed == 0) { InvalidateWindowClasses(WC_TRAINS_LIST); return true; } + SetDepotReservation(v->tile, true); + if (_debug_pbs_level >= 2) MarkTileDirtyByTile(v->tile); } VehicleServiceInDepot(v); -- 1.5.3.5 From 7c573004d5980b7e27fe4687e7729877c280b0c8 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Thu, 31 Jan 2008 23:39:22 +0100 Subject: Handle train reversing. --- src/train_cmd.cpp | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 140 insertions(+), 0 deletions(-) diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index e53f733..03d9f33 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -49,14 +49,17 @@ #include "settings_type.h" #include "pbs.h" #include "yapf/follow_track.hpp" +#include #include "table/strings.h" #include "table/train_cmd.h" static Track DoTrainPathfind(Vehicle* v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found, bool do_track_reservation); +static bool TryReserveSafeTrack(const Vehicle* v, TileIndex tile, Trackdir td); static bool TrainCheckIfLineEnds(Vehicle *v); static void TrainController(Vehicle *v, bool update_image); static TileIndex TrainApproachingCrossingTile(const Vehicle *v); +static bool CheckCompatibleRail(const Vehicle *v, TileIndex tile); static const byte _vehicle_initial_x_fract[4] = {10, 8, 4, 8}; static const byte _vehicle_initial_y_fract[4] = { 8, 4, 8, 10}; @@ -1767,6 +1770,9 @@ static void ReverseTrainDirection(Vehicle *v) InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); } + /* Check for path reservation */ + FreeTrainTrackReservation(v); + /* Check if we were approaching a rail/road-crossing */ TileIndex crossing = TrainApproachingCrossingTile(v); @@ -1799,6 +1805,38 @@ static void ReverseTrainDirection(Vehicle *v) /* maybe we are approaching crossing now, after reversal */ crossing = TrainApproachingCrossingTile(v); if (crossing != INVALID_TILE) MaybeBarCrossingWithSound(crossing); + + DiagDirection dir = TrainExitDir(v->direction, v->u.rail.track); + DiagDirection sig_dir = IsTileType(v->tile, MP_TUNNELBRIDGE) || IsTileDepotType(v->tile, TRANSPORT_RAIL) ? INVALID_DIAGDIR : dir; + if (UpdateSignalsOnSegment(v->tile, sig_dir, v->owner) == SIGSEG_PBS) { + /* Try to reserve a path if the train is in a pbs block. */ + TileIndex tile = TileAddByDiagDir(v->tile, dir); + TrackBits bits = TrackdirBitsToTrackBits((TrackdirBits)GetTileTrackStatus(tile, TRANSPORT_RAIL, 0) & DiagdirReachesTrackdirs(dir)); + + /* TODO: Don't reverse if no reservation possible or simply continue anyway + * and maybe crash? Simple variant implemented for now. */ + if (!HasReservedTrack(tile, bits)) { + /* We might find an alternative path to the target, try it. */ + bool path_not_found = true; + DoTrainPathfind(v, tile, dir, bits, &path_not_found, true); + if (path_not_found) FreeTrainTrackReservation(v); + + if (!HasReservedTrack(tile, bits)) { + /* Still no reservation, try for any possible track. */ + TryReserveSafeTrack(v, tile, GetVehicleTrackdir(v)); + } + + /* If we have a reservation, check for a signal to turn green. */ + TrackBits new_bits = GetReservedTrackbits(tile) & bits; + if (new_bits != TRACK_BIT_NONE) { + Trackdir trackdir = TrackEnterdirToTrackdir(TrackBitsToTrack(new_bits), dir); + if (HasPbsSignalOnTrackdir(tile, trackdir)) { + SetSignalStateByTrackdir(tile, trackdir, SIGNAL_STATE_GREEN); + MarkTileDirtyByTile(tile); + } + } + } + } } /** Reverse train. @@ -2570,6 +2608,104 @@ static Track DoTrainPathfind(Vehicle* v, TileIndex tile, DiagDirection enterdir, return best_track; } +struct TileTracks { + TileIndex tile; + TrackdirBits tracks; + Track track; + + TileTracks(const Vehicle *v, TileIndex _tile, Trackdir td) : tile(_tile), track(INVALID_TRACK) + { + DiagDirection enterdir = TrackdirToExitdir(td); + uint32 ts = GetTileTrackStatus(tile, TRANSPORT_RAIL, 0); + /* no tracks || not compatible || wrong owner || depot facing backwards || + * tunnel/bridge from wrong side --> no usable trackdirs */ + if (GB(ts, 0, 16) == 0 || !CheckCompatibleRail(v, tile) || GetTileOwner(tile) != v->owner || + (IsTileDepotType(tile, TRANSPORT_RAIL) && GetRailDepotDirection(tile) == enterdir) || + (IsTileType(tile, MP_TUNNELBRIDGE) && GetTunnelBridgeDirection(tile) != enterdir)) { + tracks = TRACKDIR_BIT_NONE; + } else { + tracks = (TrackdirBits)ts & DiagdirReachesTrackdirs(enterdir); + if ((_patches.new_pathfinding_all || _patches.yapf.rail_use_yapf) && _patches.forbid_90_deg) { + tracks &= ~TrackdirCrossesTrackdirs(td); + } + } + } +}; + +/** + * Try to reserve any path to a safe tile, ignoring the vehicle's destination. + * Safe tiles are tiles in front of a signal, depots and station tiles at end of line. + * + * @param v the vehicle + * @param tile the tile the vehicle is about to enter + * @param td the trackdir the vehicle currently is on + * @return true if a path to a safe stopping tile could be reserved. + */ +static bool TryReserveSafeTrack(const Vehicle* v, TileIndex tile, Trackdir td) +{ + std::stack visited; + + visited.push(TileTracks(v, tile, td)); + + while (!visited.empty()) { + TileTracks &top = visited.top(); + + /* Is this a safe stop tile? Junction tiles can't be safe stops. */ + if (top.tracks != TRACKDIR_BIT_NONE && KillFirstBit(top.tracks) == TRACKDIR_BIT_NONE) { + Trackdir track = FindFirstTrackdir(top.tracks); + + /* Front of a signal is safe. */ + if (IsTileType(top.tile, MP_RAILWAY) && HasSignalOnTrackdir(top.tile, track)) break; + /* A depot is safe. */ + if (IsTileDepotType(top.tile, TRANSPORT_RAIL) && !GetDepotReservation(top.tile)) { + SetDepotReservation(top.tile, true); + break; + } + + /* A station tile which is at the end of line is safe. */ + if (IsRailwayStationTile(top.tile)) { + TileTracks tt(v, TileAddByDiagDir(top.tile, TrackdirToExitdir(track)), track); + if (tt.tracks == TRACKDIR_BIT_NONE && !GetRailwayStationReservation(top.tile)) { + SetRailwayStationReservation(top.tile, true); + break; + } + } + } + + /* If we revisit a tile, free the old track reservation. */ + if (top.track != INVALID_TRACK) { + UnreserveRailTrack(top.tile, top.track); + top.track = INVALID_TRACK; + } + + /* No more possible tracks? Backtrack and try next tile. */ + if (top.tracks == TRACKDIR_BIT_NONE) { + visited.pop(); + continue; + } + + /* Grab a trackdir and try to reserve it. */ + Trackdir td = RemoveFirstTrackdir(&top.tracks); + if (!TryReserveRailTrack(top.tile, TrackdirToTrack(td))) continue; + top.track = TrackdirToTrack(td); + + /* Reservation successful, then add the tile reached by following the trackdir. */ + visited.push(TileTracks(v, TileAddByDiagDir(top.tile, TrackdirToExitdir(td)), td)); + } + + bool found = !visited.empty(); + + if (_debug_pbs_level >= 2) { + /* Mark path dirty */ + while (!visited.empty()) { + MarkTileDirtyByTile(visited.top().tile); + visited.pop(); + } + } + + return found; +} + /* choose a track */ static Track ChooseTrainTrack(Vehicle* v, TileIndex tile, DiagDirection enterdir, TrackBits tracks) { @@ -3255,6 +3391,10 @@ static void TrainController(Vehicle *v, bool update_image) if (VehicleFromPos(o_tile, &rdir, &CheckVehicleAtSignal) == NULL) return; } } + + /* Don't reverse in front of a PBS signal, it might cause crashes. */ + if (IsPbsSignal(GetSignalType(gp.new_tile, TrackdirToTrack(i)))) return; + goto reverse_train_direction; } } else { -- 1.5.3.5 From 0e4c26db74f557d68f6d7a0e8a7890172434ac1b Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Thu, 31 Jan 2008 23:44:21 +0100 Subject: Don't allow to remove reserved tracks from a tile. --- src/rail_cmd.cpp | 10 +++++++--- src/station_cmd.cpp | 3 +++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index ba3320c..f4c8b6a 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -41,6 +41,7 @@ #include "sound_func.h" #include "signal_func.h" #include "tunnelbridge.h" +#include "pbs.h" #include "table/sprites.h" #include "table/strings.h" @@ -431,7 +432,7 @@ CommandCost CmdBuildSingleRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p /** Remove a single piece of track * @param tile tile to remove track from * @param flags operation to perform - * @param p1 unused + * @param p1 force remove even if track is reserved * @param p2 rail orientation */ CommandCost CmdRemoveSingleRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) @@ -444,6 +445,8 @@ CommandCost CmdRemoveSingleRail(TileIndex tile, uint32 flags, uint32 p1, uint32 if (!ValParamTrackOrientation((Track)p2)) return CMD_ERROR; trackbit = TrackToTrackBits(track); + if (p1 == 0 && HasReservedTrack(tile, trackbit)) return CMD_ERROR; + /* Need to read tile owner now because it may change when the rail is removed * Also, in case of floods, _current_player != owner * There may be invalid tiletype even in exec run (when removing long track), @@ -666,7 +669,7 @@ static CommandCost CmdRailTrackHelper(TileIndex tile, uint32 flags, uint32 p1, u if (flags & DC_EXEC) SndPlayTileFx(SND_20_SPLAT_2, tile); for (;;) { - ret = DoCommand(tile, railtype, TrackdirToTrack(trackdir), flags, (mode == 0) ? CMD_BUILD_SINGLE_RAIL : CMD_REMOVE_SINGLE_RAIL); + ret = DoCommand(tile, (mode == 0) ? railtype : 0, TrackdirToTrack(trackdir), flags, (mode == 0) ? CMD_BUILD_SINGLE_RAIL : CMD_REMOVE_SINGLE_RAIL); if (CmdFailed(ret)) { if ((_error_message != STR_1007_ALREADY_BUILT) && (mode == 0)) break; @@ -1389,7 +1392,8 @@ static CommandCost ClearTile_Track(TileIndex tile, byte flags) TrackBits tracks = GetTrackBits(tile); while (tracks != TRACK_BIT_NONE) { Track track = RemoveFirstTrack(&tracks); - ret = DoCommand(tile, 0, track, flags, CMD_REMOVE_SINGLE_RAIL); + /* NOTE: Force removal of reserved tracks, maybe remove if no bugs found. */ + ret = DoCommand(tile, 1, track, flags, CMD_REMOVE_SINGLE_RAIL); if (CmdFailed(ret)) return CMD_ERROR; cost.AddCost(ret); } diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 38af7e0..16b4b64 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -1183,6 +1183,9 @@ CommandCost CmdRemoveFromRailroadStation(TileIndex tile, uint32 flags, uint32 p1 continue; } + /* Don't remove tile if it is reserved. */ + if (GetRailwayStationReservation(tile2)) continue; + /* If there is a vehicle on ground, do not allow to remove (flood) the tile */ if (!EnsureNoVehicleOnGround(tile2)) { continue; -- 1.5.3.5 From ee9727dcc6a0e84fbc081c4b5a2a2c8ad2e5fd97 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Wed, 30 Jan 2008 23:27:54 +0100 Subject: Tweak shorter platform penalty for YAPF. --- src/settings.cpp | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/src/settings.cpp b/src/settings.cpp index bde1497..f8b1c0a 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1576,7 +1576,7 @@ const SettingDesc _patch_settings[] = { /* penalties for too long or too short station platforms */ SDT_CONDVAR (Patches, yapf.rail_longer_platform_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 8 * YAPF_TILE_LENGTH, 0, 20000, 0, STR_NULL, NULL), SDT_CONDVAR (Patches, yapf.rail_longer_platform_per_tile_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 0 * YAPF_TILE_LENGTH, 0, 20000, 0, STR_NULL, NULL), - SDT_CONDVAR (Patches, yapf.rail_shorter_platform_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 40 * YAPF_TILE_LENGTH, 0, 20000, 0, STR_NULL, NULL), + SDT_CONDVAR (Patches, yapf.rail_shorter_platform_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 80 * YAPF_TILE_LENGTH, 0, 20000, 0, STR_NULL, NULL), SDT_CONDVAR (Patches, yapf.rail_shorter_platform_per_tile_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 0 * YAPF_TILE_LENGTH, 0, 20000, 0, STR_NULL, NULL), /* road vehicles - penalties */ SDT_CONDVAR (Patches, yapf.road_slope_penalty , SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 2 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), -- 1.5.3.5 From 5468d979558da059ddb6a13acce2884a1ab0b364 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sun, 20 Jan 2008 23:50:53 +0100 Subject: Comment typo fix. --- src/yapf/follow_track.hpp | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/src/yapf/follow_track.hpp b/src/yapf/follow_track.hpp index cf7d986..64e5c0b 100644 --- a/src/yapf/follow_track.hpp +++ b/src/yapf/follow_track.hpp @@ -9,7 +9,7 @@ /** Track follower helper template class (can serve pathfinders and vehicle * controllers). See 6 different typedefs below for 3 different transport - * types w/ of w/o 90-deg turns allowed */ + * types w/ or w/o 90-deg turns allowed */ template struct CFollowTrackT : public FollowTrack_t { -- 1.5.3.5