From 1b4db7d86c123084c097a4f5a5a6f98426037ef8 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sun, 17 Jun 2018 18:55:33 +0100 Subject: [PATCH] Trace restrict: Add wait at entrance PBS for reservation ending here --- src/lang/english.txt | 4 ++++ src/pbs.cpp | 31 +++++++++++++++++++++++-- src/saveload/extended_ver_sl.cpp | 2 +- src/tracerestrict.cpp | 40 ++++++++++++++++++++++++++++---- src/tracerestrict.h | 14 ++++++++++- src/tracerestrict_gui.cpp | 32 +++++++++++++++++++++---- 6 files changed, 110 insertions(+), 13 deletions(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index 659cde20ce..53bebd56c3 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2453,6 +2453,10 @@ STR_TRACE_RESTRICT_LONG_RESERVE :Long reserve STR_TRACE_RESTRICT_LONG_RESERVE_CANCEL :Cancel long reserve STR_TRACE_RESTRICT_WAIT_AT_PBS :Wait at PBS signal STR_TRACE_RESTRICT_WAIT_AT_PBS_CANCEL :Cancel wait at PBS signal +STR_TRACE_RESTRICT_PBS_RES_END_WAIT :Wait at start PBS signal for reservation ending here +STR_TRACE_RESTRICT_PBS_RES_END_WAIT_CANCEL :Cancel wait at start PBS signal for reservation ending here +STR_TRACE_RESTRICT_PBS_RES_END_WAIT_SHORT :Wait at start PBS... +STR_TRACE_RESTRICT_PBS_RES_END_WAIT_CANCEL_SHORT :Cancel wait at start PBS... STR_TRACE_RESTRICT_PF_PENALTY :Penalty STR_TRACE_RESTRICT_PF_VALUE_SMALL :small STR_TRACE_RESTRICT_PF_VALUE_MEDIUM :medium diff --git a/src/pbs.cpp b/src/pbs.cpp index a8bad4f069..dc9e404145 100644 --- a/src/pbs.cpp +++ b/src/pbs.cpp @@ -525,7 +525,24 @@ bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bo /* Not reserved and depot or not a pbs signal -> free. */ if (IsRailDepotTile(tile)) return true; - if (IsTileType(tile, MP_RAILWAY) && HasSignalOnTrackdir(tile, trackdir) && !IsPbsSignal(GetSignalType(tile, track))) return true; + + auto pbs_res_end_wait_test = [v](TileIndex t, Trackdir td) -> bool { + if (IsRestrictedSignal(t)) { + const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(t, TrackdirToTrack(td)); + if (prog && prog->actions_used_flags & TRPAUF_PBS_RES_END_WAIT) { + TraceRestrictProgramResult out; + prog->Execute(v, TraceRestrictProgramInput(t, td, &VehiclePosTraceRestrictPreviousSignalCallback, NULL), out); + if (out.flags & TRPRF_PBS_RES_END_WAIT) { + return false; + } + } + } + return true; + }; + + if (IsTileType(tile, MP_RAILWAY) && HasSignalOnTrackdir(tile, trackdir) && !IsPbsSignal(GetSignalType(tile, track))) { + return pbs_res_end_wait_test(tile, trackdir); + } /* Check the next tile, if it's a PBS signal, it has to be free as well. */ CFollowTrackRail ft(v, GetRailTypeInfo(v->railtype)->compatible_railtypes); @@ -536,5 +553,15 @@ bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bo ft.m_new_td_bits &= DiagdirReachesTrackdirs(ft.m_exitdir); if (forbid_90deg) ft.m_new_td_bits &= ~TrackdirCrossesTrackdirs(trackdir); - return !HasReservedTracks(ft.m_new_tile, TrackdirBitsToTrackBits(ft.m_new_td_bits)); + if (HasReservedTracks(ft.m_new_tile, TrackdirBitsToTrackBits(ft.m_new_td_bits))) return false; + + if (ft.m_new_td_bits != TRACKDIR_BIT_NONE && KillFirstBit(ft.m_new_td_bits) == TRACKDIR_BIT_NONE) { + Trackdir td = FindFirstTrackdir(ft.m_new_td_bits); + /* PBS signal on next trackdir? */ + if (HasPbsSignalOnTrackdir(ft.m_new_tile, td)) { + return pbs_res_end_wait_test(ft.m_new_tile, td); + } + } + + return true; } diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index 3e8ac50914..b8d6c91017 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -45,7 +45,7 @@ std::vector _sl_xv_discardable_chunk_ids; ///< list of chunks static const uint32 _sl_xv_slxi_chunk_version = 0; ///< current version os SLXI chunk const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { - { XSLFI_TRACE_RESTRICT, XSCF_NULL, 8, 8, "tracerestrict", NULL, NULL, "TRRM,TRRP,TRRS" }, + { XSLFI_TRACE_RESTRICT, XSCF_NULL, 9, 9, "tracerestrict", NULL, NULL, "TRRM,TRRP,TRRS" }, { XSLFI_NULL, XSCF_NULL, 0, 0, NULL, NULL, NULL, NULL },// This is the end marker }; diff --git a/src/tracerestrict.cpp b/src/tracerestrict.cpp index 8266c2b46f..e5f34f5b36 100644 --- a/src/tracerestrict.cpp +++ b/src/tracerestrict.cpp @@ -473,10 +473,26 @@ void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInp break; case TRIT_WAIT_AT_PBS: - if (GetTraceRestrictValue(item)) { - out.flags &= ~TRPRF_WAIT_AT_PBS; - } else { - out.flags |= TRPRF_WAIT_AT_PBS; + switch (static_cast(GetTraceRestrictValue(item))) { + case TRWAPVF_WAIT_AT_PBS: + out.flags |= TRPRF_WAIT_AT_PBS; + break; + + case TRWAPVF_CANCEL_WAIT_AT_PBS: + out.flags &= ~TRPRF_WAIT_AT_PBS; + break; + + case TRWAPVF_PBS_RES_END_WAIT: + out.flags |= TRPRF_PBS_RES_END_WAIT; + break; + + case TRWAPVF_CANCEL_PBS_RES_END_WAIT: + out.flags &= ~TRPRF_PBS_RES_END_WAIT; + break; + + default: + NOT_REACHED(); + break; } break; @@ -622,7 +638,21 @@ CommandCost TraceRestrictProgram::Validate(const std::vector break; case TRIT_WAIT_AT_PBS: - actions_used_flags |= TRPAUF_WAIT_AT_PBS; + switch (static_cast(GetTraceRestrictValue(item))) { + case TRWAPVF_WAIT_AT_PBS: + case TRWAPVF_CANCEL_WAIT_AT_PBS: + actions_used_flags |= TRPAUF_WAIT_AT_PBS; + break; + + case TRWAPVF_PBS_RES_END_WAIT: + case TRWAPVF_CANCEL_PBS_RES_END_WAIT: + actions_used_flags |= TRPAUF_PBS_RES_END_WAIT; + break; + + default: + NOT_REACHED(); + break; + } break; case TRIT_SLOT: diff --git a/src/tracerestrict.h b/src/tracerestrict.h index 16190e9d7b..3e7974f2e3 100644 --- a/src/tracerestrict.h +++ b/src/tracerestrict.h @@ -222,6 +222,16 @@ enum TraceRestrictPathfinderPenaltyAuxField { /* space up to 3 */ }; +/** + * TraceRestrictItem value field, for TRIT_WAIT_AT_PBS + */ +enum TraceRestrictWaitAtPbsValueField { + TRWAPVF_WAIT_AT_PBS = 0, ///< Wait at PBS + TRWAPVF_CANCEL_WAIT_AT_PBS = 1, ///< Cancel wait at PBS + TRWAPVF_PBS_RES_END_WAIT = 2, ///< PBS reservations ending at this signal wait + TRWAPVF_CANCEL_PBS_RES_END_WAIT = 3, ///< Cancel PBS reservations ending at this signal wait +}; + /** * TraceRestrictItem repurposed condition operator field, for slot operation type actions */ @@ -261,6 +271,7 @@ enum TraceRestrictProgramResultFlags { TRPRF_RESERVE_THROUGH = 1 << 1, ///< Reserve through is set TRPRF_LONG_RESERVE = 1 << 2, ///< Long reserve is set TRPRF_WAIT_AT_PBS = 1 << 3, ///< Wait at PBS signal is set + TRPRF_PBS_RES_END_WAIT = 1 << 4, ///< PBS reservations ending at this signal wait is set }; DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramResultFlags) @@ -275,6 +286,7 @@ enum TraceRestrictProgramActionsUsedFlags { TRPAUF_SLOT_ACQUIRE = 1 << 4, ///< Slot acquire action is present TRPAUF_SLOT_RELEASE_BACK = 1 << 5, ///< Slot release (back) action is present TRPAUF_SLOT_RELEASE_FRONT = 1 << 6, ///< Slot release (front) action is present + TRPAUF_PBS_RES_END_WAIT = 1 << 7, ///< PBS reservations ending at this signal wait action is present }; DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramActionsUsedFlags) @@ -498,7 +510,7 @@ enum TraceRestrictValueType { TRVT_FORCE = 15,///< takes a force TRVT_POWER_WEIGHT_RATIO = 16,///< takes a power / weight ratio, * 100 TRVT_FORCE_WEIGHT_RATIO = 17,///< takes a force / weight ratio, * 100 - TRVT_WAIT_AT_PBS = 18,///< takes a value 0 = wait at PBS signal, 1 = cancel wait at PBS signal + TRVT_WAIT_AT_PBS = 18,///< takes a TraceRestrictWaitAtPbsValueField value TRVT_SLOT_INDEX = 19,///< takes a TraceRestrictSlotID TRVT_SLOT_INDEX_INT = 20,///< takes a TraceRestrictSlotID, and an integer in the next item slot }; diff --git a/src/tracerestrict_gui.cpp b/src/tracerestrict_gui.cpp index 5dc1aecbc6..cdbfeb43e5 100644 --- a/src/tracerestrict_gui.cpp +++ b/src/tracerestrict_gui.cpp @@ -223,11 +223,15 @@ static const TraceRestrictDropDownListSet _long_reserve_value = { static const StringID _wait_at_pbs_value_str[] = { STR_TRACE_RESTRICT_WAIT_AT_PBS, STR_TRACE_RESTRICT_WAIT_AT_PBS_CANCEL, + STR_TRACE_RESTRICT_PBS_RES_END_WAIT_SHORT, + STR_TRACE_RESTRICT_PBS_RES_END_WAIT_CANCEL_SHORT, INVALID_STRING_ID }; static const uint _wait_at_pbs_value_val[] = { - 0, - 1, + TRWAPVF_WAIT_AT_PBS, + TRWAPVF_CANCEL_WAIT_AT_PBS, + TRWAPVF_PBS_RES_END_WAIT, + TRWAPVF_CANCEL_PBS_RES_END_WAIT, }; /** value drop down list for wait at PBS types strings and values */ @@ -1034,7 +1038,27 @@ static void DrawInstructionString(const TraceRestrictProgram *prog, TraceRestric break; case TRIT_WAIT_AT_PBS: - instruction_string = GetTraceRestrictValue(item) ? STR_TRACE_RESTRICT_WAIT_AT_PBS_CANCEL : STR_TRACE_RESTRICT_WAIT_AT_PBS; + switch (static_cast(GetTraceRestrictValue(item))) { + case TRWAPVF_WAIT_AT_PBS: + instruction_string = STR_TRACE_RESTRICT_WAIT_AT_PBS; + break; + + case TRWAPVF_CANCEL_WAIT_AT_PBS: + instruction_string = STR_TRACE_RESTRICT_WAIT_AT_PBS_CANCEL; + break; + + case TRWAPVF_PBS_RES_END_WAIT: + instruction_string = STR_TRACE_RESTRICT_PBS_RES_END_WAIT; + break; + + case TRWAPVF_CANCEL_PBS_RES_END_WAIT: + instruction_string = STR_TRACE_RESTRICT_PBS_RES_END_WAIT_CANCEL; + break; + + default: + NOT_REACHED(); + break; + } break; case TRIT_SLOT: @@ -2245,7 +2269,7 @@ private: right_sel->SetDisplayedPlane(DPR_VALUE_DROPDOWN); this->EnableWidget(TR_WIDGET_VALUE_DROPDOWN); this->GetWidget(TR_WIDGET_VALUE_DROPDOWN)->widget_data = - GetTraceRestrictValue(item) ? STR_TRACE_RESTRICT_WAIT_AT_PBS_CANCEL : STR_TRACE_RESTRICT_WAIT_AT_PBS; + GetDropDownStringByValue(&_wait_at_pbs_value, GetTraceRestrictValue(item)); break; case TRVT_GROUP_INDEX: