changeset 13993:d6215232b503 draft

(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
author rubidium <rubidium@openttd.org>
date Sat, 19 Dec 2009 15:30:24 +0000
parents 6edb85a3b23e
children 486560a72171
files src/pathfinder/npf/npf.cpp src/pathfinder/yapf/yapf_costrail.hpp src/pathfinder/yapf/yapf_node_rail.hpp
diffstat 3 files changed, 25 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/pathfinder/npf/npf.cpp
+++ b/src/pathfinder/npf/npf.cpp
@@ -66,6 +66,7 @@
 	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 @@
 	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 @@
 	/* 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 @@
 					 * 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 @@
 			} 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)) {
--- a/src/pathfinder/yapf/yapf_costrail.hpp
+++ b/src/pathfinder/yapf/yapf_costrail.hpp
@@ -169,6 +169,7 @@
 	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 @@
 			} 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 @@
 							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 @@
 			/* 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. */
--- a/src/pathfinder/yapf/yapf_node_rail.hpp
+++ b/src/pathfinder/yapf/yapf_node_rail.hpp
@@ -206,6 +206,7 @@
 		} 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 @@
 			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;
 	}