From 751f379cddab837964dd2c25a563d964bf3facd9 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sun, 17 Jun 2018 18:54:16 +0100 Subject: [PATCH 1/3] Trace restrict: Fix wrong position of safeguards header include --- src/tracerestrict.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tracerestrict.cpp b/src/tracerestrict.cpp index a2960006e7..8266c2b46f 100644 --- a/src/tracerestrict.cpp +++ b/src/tracerestrict.cpp @@ -22,11 +22,11 @@ #include "string_func.h" #include "pathfinder/yapf/yapf_cache.h" -#include "safeguards.h" - #include #include +#include "safeguards.h" + /** @file * * Trace Restrict Data Storage Model Notes: From 1b4db7d86c123084c097a4f5a5a6f98426037ef8 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sun, 17 Jun 2018 18:55:33 +0100 Subject: [PATCH 2/3] 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: From e9f5d804405aea611ae52bf56cdefd83d4b59aa5 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sun, 17 Jun 2018 21:13:53 +0100 Subject: [PATCH 3/3] Trace restrict slots: Add support for slot operations at PBS end signal --- src/lang/english.txt | 6 +++++ src/pathfinder/yapf/yapf_rail.cpp | 16 ++++++++++++- src/pbs.cpp | 12 +++++++--- src/pbs.h | 7 +++++- src/tracerestrict.cpp | 37 +++++++++++++++++++++++++++++++ src/tracerestrict.h | 8 +++++++ src/tracerestrict_gui.cpp | 18 +++++++++++++++ src/train_cmd.cpp | 12 +++++++++- 8 files changed, 110 insertions(+), 6 deletions(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index 53bebd56c3..084c08398a 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2473,10 +2473,16 @@ STR_TRACE_RESTRICT_SLOT_ACQUIRE_WAIT :Acquire or wait STR_TRACE_RESTRICT_SLOT_TRY_ACQUIRE :Try to acquire STR_TRACE_RESTRICT_SLOT_RELEASE_FRONT :Release (front) STR_TRACE_RESTRICT_SLOT_RELEASE_BACK :Release (back) +STR_TRACE_RESTRICT_SLOT_PBS_RES_END_ACQUIRE_WAIT :PBS end: Acquire or wait +STR_TRACE_RESTRICT_SLOT_PBS_RES_END_TRY_ACQUIRE :PBS end: Try to acquire +STR_TRACE_RESTRICT_SLOT_PBS_RES_END_RELEASE :PBS end: Release STR_TRACE_RESTRICT_SLOT_ACQUIRE_WAIT_ITEM :Acquire slot: {STRING1}{BLACK}{STRING}, or wait at PBS signal STR_TRACE_RESTRICT_SLOT_TRY_ACQUIRE_ITEM :Try to acquire slot: {STRING1}{BLACK}{STRING}, or continue anyway STR_TRACE_RESTRICT_SLOT_RELEASE_FRONT_ITEM :Release slot: {STRING1}{BLACK}{STRING} (front of train) STR_TRACE_RESTRICT_SLOT_RELEASE_BACK_ITEM :Release slot: {STRING1}{BLACK}{STRING} (back of train) +STR_TRACE_RESTRICT_SLOT_PBS_RES_END_ACQUIRE_WAIT_ITEM :PBS reservation ending here: Acquire slot: {STRING1}{BLACK}{STRING}, or wait at start +STR_TRACE_RESTRICT_SLOT_PBS_RES_END_TRY_ACQUIRE_ITEM :PBS reservation ending here: Acquire slot: {STRING1}{BLACK}{STRING}, or continue anyway +STR_TRACE_RESTRICT_SLOT_PBS_RES_END_RELEASE_ITEM :PBS reservation ending here: Release slot: {STRING1}{BLACK}{STRING} STR_TRACE_RESTRICT_SLOT_NAME :{TRSLOT} STR_TRACE_RESTRICT_SLOT_LIST_HEADER :{BLACK}Slot{CONSUME_ARG}{P "" s}: {LTBLUE} STR_TRACE_RESTRICT_SLOT_LIST_SEPARATOR :{BLACK}, {LTBLUE} diff --git a/src/pathfinder/yapf/yapf_rail.cpp b/src/pathfinder/yapf/yapf_rail.cpp index e3ae2c8a96..0d2d75cadd 100644 --- a/src/pathfinder/yapf/yapf_rail.cpp +++ b/src/pathfinder/yapf/yapf_rail.cpp @@ -18,6 +18,7 @@ #include "yapf_destrail.hpp" #include "../../viewport_func.h" #include "../../newgrf_station.h" +#include "../../tracerestrict.h" #include "../../safeguards.h" @@ -159,7 +160,8 @@ public: } /* Don't bother if the target is reserved. */ - if (!IsWaitingPositionFree(Yapf().GetVehicle(), m_res_dest, m_res_dest_td)) return false; + PBSWaitingPositionRestrictedSignalInfo restricted_signal_info; + if (!IsWaitingPositionFree(Yapf().GetVehicle(), m_res_dest, m_res_dest_td, false, &restricted_signal_info)) return false; for (Node *node = m_res_node; node->m_parent != NULL; node = node->m_parent) { node->IterateTiles(Yapf().GetVehicle(), Yapf(), *this, &CYapfReserveTrack::ReserveSingleTrack); @@ -177,6 +179,18 @@ public: } } + if (restricted_signal_info.tile != INVALID_TILE) { + const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(restricted_signal_info.tile, TrackdirToTrack(restricted_signal_info.trackdir)); + if (prog && prog->actions_used_flags & TRPAUF_PBS_RES_END_SLOT) { + extern TileIndex VehiclePosTraceRestrictPreviousSignalCallback(const Train *v, const void *); + + TraceRestrictProgramResult out; + TraceRestrictProgramInput input(restricted_signal_info.tile, restricted_signal_info.trackdir, &VehiclePosTraceRestrictPreviousSignalCallback, NULL); + input.permitted_slot_operations = TRPISP_PBS_RES_END_ACQUIRE | TRPISP_PBS_RES_END_RELEASE; + prog->Execute(Yapf().GetVehicle(), input, out); + } + } + if (target != NULL) target->okay = true; if (Yapf().CanUseGlobalCache(*m_res_node)) { diff --git a/src/pbs.cpp b/src/pbs.cpp index dc9e404145..737756e459 100644 --- a/src/pbs.cpp +++ b/src/pbs.cpp @@ -515,7 +515,7 @@ bool IsSafeWaitingPosition(const Train *v, TileIndex tile, Trackdir trackdir, bo * @param forbid_90deg Don't allow trains to make 90 degree turns * @return True if the position is free */ -bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bool forbid_90deg) +bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bool forbid_90deg, PBSWaitingPositionRestrictedSignalInfo *restricted_signal_info) { Track track = TrackdirToTrack(trackdir); TrackBits reserved = GetReservedTrackbits(tile); @@ -526,12 +526,18 @@ 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; - auto pbs_res_end_wait_test = [v](TileIndex t, Trackdir td) -> bool { + auto pbs_res_end_wait_test = [v, restricted_signal_info](TileIndex t, Trackdir td) -> bool { if (IsRestrictedSignal(t)) { const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(t, TrackdirToTrack(td)); + if (restricted_signal_info && prog) { + restricted_signal_info->tile = t; + restricted_signal_info->trackdir = td; + } if (prog && prog->actions_used_flags & TRPAUF_PBS_RES_END_WAIT) { + TraceRestrictProgramInput input(t, td, &VehiclePosTraceRestrictPreviousSignalCallback, NULL); + input.permitted_slot_operations = TRPISP_PBS_RES_END_ACQ_DRY; TraceRestrictProgramResult out; - prog->Execute(v, TraceRestrictProgramInput(t, td, &VehiclePosTraceRestrictPreviousSignalCallback, NULL), out); + prog->Execute(v, input, out); if (out.flags & TRPRF_PBS_RES_END_WAIT) { return false; } diff --git a/src/pbs.h b/src/pbs.h index 223aeccacf..38f386e7bb 100644 --- a/src/pbs.h +++ b/src/pbs.h @@ -46,9 +46,14 @@ struct PBSTileInfo { PBSTileInfo(TileIndex _t, Trackdir _td, bool _okay) : tile(_t), trackdir(_td), okay(_okay) {} }; +struct PBSWaitingPositionRestrictedSignalInfo { + TileIndex tile = INVALID_TILE; + Trackdir trackdir = INVALID_TRACKDIR; +}; + PBSTileInfo FollowTrainReservation(const Train *v, Vehicle **train_on_res = NULL); bool IsSafeWaitingPosition(const Train *v, TileIndex tile, Trackdir trackdir, bool include_line_end, bool forbid_90deg = false); -bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bool forbid_90deg = false); +bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bool forbid_90deg = false, PBSWaitingPositionRestrictedSignalInfo *restricted_signal_info = nullptr); Train *GetTrainForReservation(TileIndex tile, Track track); diff --git a/src/tracerestrict.cpp b/src/tracerestrict.cpp index e5f34f5b36..9056939e61 100644 --- a/src/tracerestrict.cpp +++ b/src/tracerestrict.cpp @@ -519,6 +519,22 @@ void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInp if (input.permitted_slot_operations & TRPISP_RELEASE_FRONT) slot->Vacate(v->index); break; + case TRSCOF_PBS_RES_END_ACQ_WAIT: + if (input.permitted_slot_operations & TRPISP_PBS_RES_END_ACQUIRE) { + if (!slot->Occupy(v->index)) out.flags |= TRPRF_PBS_RES_END_WAIT; + } else if (input.permitted_slot_operations & TRPISP_PBS_RES_END_ACQ_DRY) { + if (!slot->OccupyDryRun(v->index)) out.flags |= TRPRF_PBS_RES_END_WAIT; + } + break; + + case TRSCOF_PBS_RES_END_ACQ_TRY: + if (input.permitted_slot_operations & TRPISP_PBS_RES_END_ACQUIRE) slot->Occupy(v->index); + break; + + case TRSCOF_PBS_RES_END_RELEASE: + if (input.permitted_slot_operations & TRPISP_PBS_RES_END_RELEASE) slot->Vacate(v->index); + break; + default: NOT_REACHED(); break; @@ -673,6 +689,15 @@ CommandCost TraceRestrictProgram::Validate(const std::vector actions_used_flags |= TRPAUF_SLOT_RELEASE_FRONT; break; + case TRSCOF_PBS_RES_END_ACQ_WAIT: + actions_used_flags |= TRPAUF_PBS_RES_END_SLOT | TRPAUF_PBS_RES_END_WAIT; + break; + + case TRSCOF_PBS_RES_END_ACQ_TRY: + case TRSCOF_PBS_RES_END_RELEASE: + actions_used_flags |= TRPAUF_PBS_RES_END_SLOT; + break; + default: NOT_REACHED(); break; @@ -1467,6 +1492,18 @@ bool TraceRestrictSlot::Occupy(VehicleID id, bool force) return true; } +/** + * Dry-run adding vehicle ID to occupants if possible and not already an occupant + * @param id Vehicle ID + * @return whether vehicle IDwould be an occupant + */ +bool TraceRestrictSlot::OccupyDryRun(VehicleID id) +{ + if (this->IsOccupant(id)) return true; + if (this->occupants.size() >= this->max_occupancy) return false; + return true; +} + /** * Remove vehicle ID from occupants * @param id Vehicle ID diff --git a/src/tracerestrict.h b/src/tracerestrict.h index 3e7974f2e3..17fff7e509 100644 --- a/src/tracerestrict.h +++ b/src/tracerestrict.h @@ -240,6 +240,9 @@ enum TraceRestrictSlotCondOpField { TRSCOF_ACQUIRE_TRY = 1, ///< try to acquire a slot, or carry on otherwise TRSCOF_RELEASE_BACK = 2, ///< release a slot (back of train) TRSCOF_RELEASE_FRONT = 3, ///< release a slot (front of train) + TRSCOF_PBS_RES_END_ACQ_WAIT = 4, ///< PBS reservations ending at this signal: acquire a slot, or wait + TRSCOF_PBS_RES_END_ACQ_TRY = 5, ///< PBS reservations ending at this signal: acquire a slot, or carry on otherwise + TRSCOF_PBS_RES_END_RELEASE = 6, ///< PBS reservations ending at this signal: release a slot /* space up to 8 */ }; @@ -287,6 +290,7 @@ enum TraceRestrictProgramActionsUsedFlags { 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 + TRPAUF_PBS_RES_END_SLOT = 1 << 8, ///< PBS reservations ending at this signal slot action is present }; DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramActionsUsedFlags) @@ -297,6 +301,9 @@ enum TraceRestrictProgramInputSlotPermissions { TRPISP_ACQUIRE = 1 << 0, ///< Slot acquire is permitted TRPISP_RELEASE_BACK = 1 << 1, ///< Slot release (back) is permitted TRPISP_RELEASE_FRONT = 1 << 2, ///< Slot release (front) is permitted + TRPISP_PBS_RES_END_ACQUIRE = 1 << 3, ///< Slot acquire (PBS reservations ending at this signal) is permitted + TRPISP_PBS_RES_END_ACQ_DRY = 1 << 4, ///< Dry-run slot acquire (PBS reservations ending at this signal) is permitted + TRPISP_PBS_RES_END_RELEASE = 1 << 5, ///< Slot release (PBS reservations ending at this signal) is permitted }; DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramInputSlotPermissions) @@ -781,6 +788,7 @@ struct TraceRestrictSlot : TraceRestrictSlotPool::PoolItem<&_tracerestrictslot_p } bool Occupy(VehicleID id, bool force = false); + bool OccupyDryRun(VehicleID ids); void Vacate(VehicleID id); void Clear(); diff --git a/src/tracerestrict_gui.cpp b/src/tracerestrict_gui.cpp index cdbfeb43e5..4aa7bbbc67 100644 --- a/src/tracerestrict_gui.cpp +++ b/src/tracerestrict_gui.cpp @@ -506,6 +506,9 @@ static const StringID _slot_op_cond_ops_str[] = { STR_TRACE_RESTRICT_SLOT_TRY_ACQUIRE, STR_TRACE_RESTRICT_SLOT_RELEASE_FRONT, STR_TRACE_RESTRICT_SLOT_RELEASE_BACK, + STR_TRACE_RESTRICT_SLOT_PBS_RES_END_ACQUIRE_WAIT, + STR_TRACE_RESTRICT_SLOT_PBS_RES_END_TRY_ACQUIRE, + STR_TRACE_RESTRICT_SLOT_PBS_RES_END_RELEASE, INVALID_STRING_ID, }; static const uint _slot_op_cond_ops_val[] = { @@ -513,6 +516,9 @@ static const uint _slot_op_cond_ops_val[] = { TRSCOF_ACQUIRE_TRY, TRSCOF_RELEASE_FRONT, TRSCOF_RELEASE_BACK, + TRSCOF_PBS_RES_END_ACQ_WAIT, + TRSCOF_PBS_RES_END_ACQ_TRY, + TRSCOF_PBS_RES_END_RELEASE, }; /** cargo conditional operators dropdown list set */ static const TraceRestrictDropDownListSet _slot_op_cond_ops = { @@ -1079,6 +1085,18 @@ static void DrawInstructionString(const TraceRestrictProgram *prog, TraceRestric instruction_string = STR_TRACE_RESTRICT_SLOT_RELEASE_FRONT_ITEM; break; + case TRSCOF_PBS_RES_END_ACQ_WAIT: + instruction_string = STR_TRACE_RESTRICT_SLOT_PBS_RES_END_ACQUIRE_WAIT_ITEM; + break; + + case TRSCOF_PBS_RES_END_ACQ_TRY: + instruction_string = STR_TRACE_RESTRICT_SLOT_PBS_RES_END_TRY_ACQUIRE_ITEM; + break; + + case TRSCOF_PBS_RES_END_RELEASE: + instruction_string = STR_TRACE_RESTRICT_SLOT_PBS_RES_END_RELEASE_ITEM; + break; + default: NOT_REACHED(); break; diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 648c9fff4e..84face3c2b 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -2405,9 +2405,19 @@ static PBSTileInfo ExtendTrainReservation(const Train *v, const PBSTileInfo &ori cur_td = FindFirstTrackdir(ft.m_new_td_bits); if (IsSafeWaitingPosition(v, tile, cur_td, true, _settings_game.pf.forbid_90_deg)) { - bool wp_free = IsWaitingPositionFree(v, tile, cur_td, _settings_game.pf.forbid_90_deg); + PBSWaitingPositionRestrictedSignalInfo restricted_signal_info; + bool wp_free = IsWaitingPositionFree(v, tile, cur_td, _settings_game.pf.forbid_90_deg, &restricted_signal_info); if (!(wp_free && TryReserveRailTrack(tile, TrackdirToTrack(cur_td)))) break; /* Safe position is all good, path valid and okay. */ + if (restricted_signal_info.tile != INVALID_TILE) { + const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(restricted_signal_info.tile, TrackdirToTrack(restricted_signal_info.trackdir)); + if (prog && prog->actions_used_flags & TRPAUF_PBS_RES_END_SLOT) { + TraceRestrictProgramResult out; + TraceRestrictProgramInput input(restricted_signal_info.tile, restricted_signal_info.trackdir, &VehiclePosTraceRestrictPreviousSignalCallback, NULL); + input.permitted_slot_operations = TRPISP_PBS_RES_END_ACQUIRE | TRPISP_PBS_RES_END_RELEASE; + prog->Execute(v, input, out); + } + } return PBSTileInfo(tile, cur_td, true); }