summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/settings.cpp2
-rw-r--r--src/settings_type.h2
-rw-r--r--src/track_func.h13
-rw-r--r--src/yapf/yapf_costrail.hpp107
4 files changed, 83 insertions, 41 deletions
diff --git a/src/settings.cpp b/src/settings.cpp
index 5ef857258..032435faa 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -1725,6 +1725,8 @@ const SettingDesc _patch_settings[] = {
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),
diff --git a/src/settings_type.h b/src/settings_type.h
index 098d56f60..80e5960d6 100644
--- a/src/settings_type.h
+++ b/src/settings_type.h
@@ -218,6 +218,8 @@ struct YAPFSettings {
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)
diff --git a/src/track_func.h b/src/track_func.h
index 144ea03e8..706de2067 100644
--- a/src/track_func.h
+++ b/src/track_func.h
@@ -590,6 +590,19 @@ static inline bool TracksOverlap(TrackBits bits)
}
/**
+ * 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
diff --git a/src/yapf/yapf_costrail.hpp b/src/yapf/yapf_costrail.hpp
index 509cba5d7..7ff99bb60 100644
--- a/src/yapf/yapf_costrail.hpp
+++ b/src/yapf/yapf_costrail.hpp
@@ -5,6 +5,7 @@
#ifndef YAPF_COSTRAIL_HPP
#define YAPF_COSTRAIL_HPP
+#include "../pbs.h"
template <class Types>
class CYapfCostRailT
@@ -128,6 +129,19 @@ 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() / 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 @@ public:
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 {
+ 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;
- // 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;
- };
+ // 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;
+ };
+ }
}
+
+ 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;
@@ -327,6 +349,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;