diff options
-rw-r--r-- | src/settings.cpp | 2 | ||||
-rw-r--r-- | src/settings_type.h | 2 | ||||
-rw-r--r-- | src/track_func.h | 13 | ||||
-rw-r--r-- | src/yapf/yapf_costrail.hpp | 107 |
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; |