From c5159055e3e8bad4e5daa302bb3132ff92f09b47 Mon Sep 17 00:00:00 2001 From: rubidium Date: Sat, 19 Dec 2009 15:30:24 +0000 Subject: (svn r18535) -Fix [FS#2722]: don't account for path reservation costs when entering a signal block via a 'block' signal. This way you won't get double penalties, both red signals and reservation costs, for the block signalled tracks --- src/pathfinder/npf/npf.cpp | 6 ++++-- src/pathfinder/yapf/yapf_costrail.hpp | 11 ++++++++--- src/pathfinder/yapf/yapf_node_rail.hpp | 13 +++++++++++++ 3 files changed, 25 insertions(+), 5 deletions(-) (limited to 'src/pathfinder') diff --git a/src/pathfinder/npf/npf.cpp b/src/pathfinder/npf/npf.cpp index 0432ba6ff..4a5979542 100644 --- a/src/pathfinder/npf/npf.cpp +++ b/src/pathfinder/npf/npf.cpp @@ -66,6 +66,7 @@ enum NPFNodeFlag { NPF_FLAG_3RD_SIGNAL, ///< Used to mark that three signals were seen, 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_LAST_SIGNAL_BLOCK, ///< Used to mark that the last signal on this path was a block signal NPF_FLAG_IGNORE_START_TILE, ///< Used to mark that the start tile is invalid, and searching should start from the second tile on NPF_FLAG_TARGET_RESERVED, ///< Used to mark that the possible reservation target is already reserved NPF_FLAG_IGNORE_RESERVED, ///< Used to mark that reserved tiles should be considered impassable @@ -272,7 +273,7 @@ static uint NPFReservedTrackCost(AyStarNode *current) TrackBits track = TrackToTrackBits(TrackdirToTrack(current->direction)); TrackBits res = GetReservedTrackbits(tile); - if (NPFGetFlag(current, NPF_FLAG_3RD_SIGNAL) || ((res & track) == TRACK_BIT_NONE && !TracksOverlap(res | track))) return 0; + if (NPFGetFlag(current, NPF_FLAG_3RD_SIGNAL) || NPFGetFlag(current, NPF_FLAG_LAST_SIGNAL_BLOCK) || ((res & track) == TRACK_BIT_NONE && !TracksOverlap(res | track))) return 0; if (IsTileType(tile, MP_TUNNELBRIDGE)) { DiagDirection exitdir = TrackdirToExitdir(current->direction); @@ -463,6 +464,7 @@ static int32 NPFRailPathCost(AyStar *as, AyStarNode *current, OpenListNode *pare /* Check for signals */ if (IsTileType(tile, MP_RAILWAY)) { if (HasSignalOnTrackdir(tile, trackdir)) { + SignalType sigtype = GetSignalType(tile, TrackdirToTrack(trackdir)); /* Ordinary track with signals */ if (GetSignalStateByTrackdir(tile, trackdir) == SIGNAL_STATE_RED) { /* Signal facing us is red */ @@ -471,7 +473,6 @@ static int32 NPFRailPathCost(AyStar *as, AyStarNode *current, OpenListNode *pare * 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) */ @@ -496,6 +497,7 @@ static int32 NPFRailPathCost(AyStar *as, AyStarNode *current, OpenListNode *pare } else { NPFSetFlag(current, NPF_FLAG_SEEN_SIGNAL, true); } + NPFSetFlag(current, NPF_FLAG_LAST_SIGNAL_BLOCK, !IsPbsSignal(sigtype)); } if (HasPbsSignalOnTrackdir(tile, ReverseTrackdir(trackdir)) && !NPFGetFlag(current, NPF_FLAG_3RD_SIGNAL)) { diff --git a/src/pathfinder/yapf/yapf_costrail.hpp b/src/pathfinder/yapf/yapf_costrail.hpp index cfc1bba82..57820af1e 100644 --- a/src/pathfinder/yapf/yapf_costrail.hpp +++ b/src/pathfinder/yapf/yapf_costrail.hpp @@ -169,6 +169,7 @@ public: FORCEINLINE int ReservationCost(Node& n, TileIndex tile, Trackdir trackdir, int skipped) { if (n.m_num_signals_passed >= m_sig_look_ahead_costs.Size() / 2) return 0; + if (!IsPbsSignal(n.m_last_signal_type)) return 0; if (IsRailStationTile(tile) && IsAnyStationTileReserved(tile, trackdir, skipped)) { return Yapf().PfGetSettings().rail_pbs_station_penalty * (skipped + 1); @@ -194,6 +195,10 @@ public: } else { if (has_signal_along) { SignalState sig_state = GetSignalStateByTrackdir(tile, trackdir); + SignalType sig_type = GetSignalType(tile, TrackdirToTrack(trackdir)); + + n.m_last_signal_type = sig_type; + /* 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) { @@ -205,7 +210,6 @@ public: cost -= look_ahead_cost; } } else { - SignalType sig_type = GetSignalType(tile, TrackdirToTrack(trackdir)); /* we have a red signal in our direction * was it first signal which is two-way? */ if (!IsPbsSignal(sig_type) && Yapf().TreatFirstRedTwoWaySignalAsEOL() && n.flags_u.flags_s.m_choice_seen && has_signal_against && n.m_num_signals_passed == 0) { @@ -389,11 +393,12 @@ 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); + /* Signal cost (routine can modify segment data). */ + segment_cost += Yapf().SignalCost(n, 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; /* Tests for 'potential target' reasons to close the segment. */ diff --git a/src/pathfinder/yapf/yapf_node_rail.hpp b/src/pathfinder/yapf/yapf_node_rail.hpp index 64eb8ed65..41ad8f8ff 100644 --- a/src/pathfinder/yapf/yapf_node_rail.hpp +++ b/src/pathfinder/yapf/yapf_node_rail.hpp @@ -206,6 +206,7 @@ struct CYapfRailNodeT } flags_s; } flags_u; SignalType m_last_red_signal_type; + SignalType m_last_signal_type; FORCEINLINE void Set(CYapfRailNodeT *parent, TileIndex tile, Trackdir td, bool is_choice) { @@ -215,10 +216,22 @@ struct CYapfRailNodeT m_num_signals_passed = 0; flags_u.m_inherited_flags = 0; m_last_red_signal_type = SIGTYPE_NORMAL; + /* We use PBS as initial signal type because if we are in + * a PBS section and need to route, i.e. we're at a safe + * waiting point of a station, we need to account for the + * reservation costs. If we are in a normal block then we + * should be alone in there and as such the reservation + * costs should be 0 anyway. If there would be another + * train in the block, i.e. passing signals at danger + * then avoiding that train with help of the reservation + * costs is not a bad thing, actually it would probably + * be a good thing to do. */ + m_last_signal_type = SIGTYPE_PBS; } else { m_num_signals_passed = parent->m_num_signals_passed; flags_u.m_inherited_flags = parent->flags_u.m_inherited_flags; m_last_red_signal_type = parent->m_last_red_signal_type; + m_last_signal_type = parent->m_last_signal_type; } flags_u.flags_s.m_choice_seen |= is_choice; } -- cgit v1.2.3-54-g00ecf