(svn r13941) -Codechange [YAPP]: Added YAPP-related penalties to YAPF. (michi_cc)
authorrubidium
Sat, 02 Aug 2008 22:51:07 +0000
changeset 9799 c91afc4512fe
parent 9798 4b8cdc1adf4b
child 9800 a8cbb9206502
(svn r13941) -Codechange [YAPP]: Added YAPP-related penalties to YAPF. (michi_cc)
src/settings.cpp
src/settings_type.h
src/track_func.h
src/yapf/yapf_costrail.hpp
--- a/src/settings.cpp	Sat Aug 02 22:50:52 2008 +0000
+++ b/src/settings.cpp	Sat Aug 02 22:51:07 2008 +0000
@@ -1725,6 +1725,8 @@
 	 SDT_CONDVAR(GameSettings, pf.yapf.rail_look_ahead_signal_p0,               SLE_INT, 28, SL_MAX_VERSION, 0, 0,   500,              -1000000, 1000000, 0, STR_NULL,         NULL),
 	 SDT_CONDVAR(GameSettings, pf.yapf.rail_look_ahead_signal_p1,               SLE_INT, 28, SL_MAX_VERSION, 0, 0,  -100,              -1000000, 1000000, 0, STR_NULL,         NULL),
 	 SDT_CONDVAR(GameSettings, pf.yapf.rail_look_ahead_signal_p2,               SLE_INT, 28, SL_MAX_VERSION, 0, 0,     5,              -1000000, 1000000, 0, STR_NULL,         NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.rail_pbs_cross_penalty,                 SLE_UINT,100, SL_MAX_VERSION, 0, 0,     3 * YAPF_TILE_LENGTH,  0, 1000000, 0, STR_NULL,         NULL),
+	 SDT_CONDVAR(GameSettings, pf.yapf.rail_pbs_signal_back_penalty,           SLE_UINT,100, SL_MAX_VERSION, 0, 0,    15 * YAPF_TILE_LENGTH,  0, 1000000, 0, STR_NULL,         NULL),
 	 SDT_CONDVAR(GameSettings, pf.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(GameSettings, pf.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(GameSettings, pf.yapf.rail_shorter_platform_penalty,          SLE_UINT, 33, SL_MAX_VERSION, 0, 0,    40 * YAPF_TILE_LENGTH,  0,   20000, 0, STR_NULL,         NULL),
--- a/src/settings_type.h	Sat Aug 02 22:50:52 2008 +0000
+++ b/src/settings_type.h	Sat Aug 02 22:51:07 2008 +0000
@@ -218,6 +218,8 @@
 	int32  rail_look_ahead_signal_p0;        ///< constant in polynomial penalty function
 	int32  rail_look_ahead_signal_p1;        ///< constant in polynomial penalty function
 	int32  rail_look_ahead_signal_p2;        ///< constant in polynomial penalty function
+	uint32 rail_pbs_cross_penalty;           ///< penalty for crossing a reserved tile
+	uint32 rail_pbs_signal_back_penalty;     ///< penalty for passing a pbs signal from the backside
 
 	uint32 rail_longer_platform_penalty;           ///< penalty for longer  station platform than train
 	uint32 rail_longer_platform_per_tile_penalty;  ///< penalty for longer  station platform than train (per tile)
--- a/src/track_func.h	Sat Aug 02 22:50:52 2008 +0000
+++ b/src/track_func.h	Sat Aug 02 22:51:07 2008 +0000
@@ -590,6 +590,19 @@
 }
 
 /**
+ * Check if a given track is contained within or overlaps some other tracks.
+ *
+ * @param tracks Tracks to be testet against
+ * @param track The track to test
+ * @return true if the track is already in the tracks or overlaps the tracks.
+ */
+static inline bool TrackOverlapsTracks(TrackBits tracks, Track track)
+{
+	if (HasBit(tracks, track)) return true;
+	return TracksOverlap(tracks | TrackToTrackBits(track));
+}
+
+/**
  * Checks whether the trackdir means that we are reversing.
  * @param dir the trackdir to check
  * @return true if it is a reversing road trackdir
--- a/src/yapf/yapf_costrail.hpp	Sat Aug 02 22:50:52 2008 +0000
+++ b/src/yapf/yapf_costrail.hpp	Sat Aug 02 22:51:07 2008 +0000
@@ -5,6 +5,7 @@
 #ifndef  YAPF_COSTRAIL_HPP
 #define  YAPF_COSTRAIL_HPP
 
+#include "../pbs.h"
 
 template <class Types>
 class CYapfCostRailT
@@ -128,6 +129,19 @@
 		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() / 2) return 0;
+
+		if (TrackOverlapsTracks(GetReservedTrackbits(tile), TrackdirToTrack(trackdir))) {
+			int cost = Yapf().PfGetSettings().rail_pbs_cross_penalty;
+			if (!IsDiagonalTrackdir(trackdir)) cost = (cost * YAPF_TILE_CORNER_LENGTH) / YAPF_TILE_LENGTH;
+			return cost * (skipped + 1);
+		}
+		return 0;
+	}
+
 	int SignalCost(Node& n, TileIndex tile, Trackdir trackdir)
 	{
 		int cost = 0;
@@ -139,50 +153,58 @@
 			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;
+			} 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 {
+						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) {
+							// 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;
+						}
+						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;
+						// 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;
+								default: 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;
 				}
-				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;
+				}
 			}
 		}
 		return cost;
@@ -327,6 +349,9 @@
 			/* 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;