diff --git a/src/lang/english.txt b/src/lang/english.txt index 49543dca3a..13b2daa5af 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2462,6 +2462,7 @@ STR_TRACE_RESTRICT_ERROR_VALIDATE_END_CONDSTACK :Validation fail STR_TRACE_RESTRICT_ERROR_VALIDATE_NO_IF :Validation failed: else/endif without opening if STR_TRACE_RESTRICT_ERROR_VALIDATE_DUP_ELSE :Validation failed: duplicate else STR_TRACE_RESTRICT_ERROR_VALIDATE_ELIF_NO_IF :Validation failed: else if without opening if +STR_TRACE_RESTRICT_ERROR_VALIDATE_UNKNOWN_INSTRUCTION :Validation failed: unknown instruction STR_TRACE_RESTRICT_ERROR_SOURCE_SAME_AS_TARGET :Source and target signals are the same STR_TRACE_RESTRICT_ERROR_CAN_T_RESET_SIGNAL :{WHITE}Can't reset signal STR_TRACE_RESTRICT_ERROR_CAN_T_COPY_PROGRAM :{WHITE}Can't copy program diff --git a/src/pathfinder/yapf/yapf_costrail.hpp b/src/pathfinder/yapf/yapf_costrail.hpp index f4ff174e43..b010fe4d8a 100644 --- a/src/pathfinder/yapf/yapf_costrail.hpp +++ b/src/pathfinder/yapf/yapf_costrail.hpp @@ -264,7 +264,7 @@ private: inline bool ExecuteTraceRestrict(Node& n, TileIndex tile, Trackdir trackdir, int& cost, TraceRestrictProgramResult &out) { const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(tile, TrackdirToTrack(trackdir)); - if (prog) { + if (prog && prog->actions_used_flags & TRPAUF_PF) { prog->Execute(Yapf().GetVehicle(), TraceRestrictProgramInput(tile, trackdir, &TraceRestrictPreviousSignalCallback, &n), out); if (out.flags & TRPRF_DENY) { n.m_segment->m_end_segment_reason |= ESRB_DEAD_END; diff --git a/src/pbs.cpp b/src/pbs.cpp index 16d0358b04..78a8337cb6 100644 --- a/src/pbs.cpp +++ b/src/pbs.cpp @@ -468,7 +468,7 @@ bool IsSafeWaitingPosition(const Train *v, TileIndex tile, Trackdir trackdir, bo if (HasPbsSignalOnTrackdir(ft.m_new_tile, td)) { if (IsRestrictedSignal(ft.m_new_tile)) { const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(ft.m_new_tile, TrackdirToTrack(td)); - if (prog) { + if (prog && prog->actions_used_flags & TRPAUF_RESERVE_THROUGH) { TraceRestrictProgramResult out; prog->Execute(v, TraceRestrictProgramInput(tile, trackdir, &IsSafeWaitingPositionTraceRestrictPreviousSignalCallback, nullptr), out); if (out.flags & TRPRF_RESERVE_THROUGH) { diff --git a/src/tracerestrict.cpp b/src/tracerestrict.cpp index 84710ce164..ff86f5c80a 100644 --- a/src/tracerestrict.cpp +++ b/src/tracerestrict.cpp @@ -413,12 +413,14 @@ void TraceRestrictProgram::DecrementRefCount() { /** * Validate a instruction list * Returns successful result if program seems OK - * This only validates that conditional nesting is correct, at present + * This only validates that conditional nesting is correct, + * and that all non-conditionals have a known type, at present */ -CommandCost TraceRestrictProgram::Validate(const std::vector &items) { +CommandCost TraceRestrictProgram::Validate(const std::vector &items, TraceRestrictProgramActionsUsedFlags &actions_used_flags) { // static to avoid needing to re-alloc/resize on each execution static std::vector condstack; condstack.clear(); + actions_used_flags = static_cast(0); size_t size = items.size(); for (size_t i = 0; i < size; i++) { @@ -462,6 +464,19 @@ CommandCost TraceRestrictProgram::Validate(const std::vector return_cmd_error(STR_TRACE_RESTRICT_ERROR_OFFSET_TOO_LARGE); // instruction ran off end } } + switch (GetTraceRestrictType(item)) { + case TRIT_PF_DENY: + case TRIT_PF_PENALTY: + actions_used_flags |= TRPAUF_PF; + break; + + case TRIT_RESERVE_THROUGH: + actions_used_flags |= TRPAUF_RESERVE_THROUGH; + break; + + default: + return_cmd_error(STR_TRACE_RESTRICT_ERROR_VALIDATE_UNKNOWN_INSTRUCTION); + } } } if(!condstack.empty()) { @@ -887,7 +902,8 @@ CommandCost CmdProgramSignalTraceRestrict(TileIndex tile, DoCommandFlag flags, u break; } - CommandCost validation_result = TraceRestrictProgram::Validate(items); + TraceRestrictProgramActionsUsedFlags actions_used_flags; + CommandCost validation_result = TraceRestrictProgram::Validate(items, actions_used_flags); if (validation_result.Failed()) { return validation_result; } @@ -897,6 +913,7 @@ CommandCost CmdProgramSignalTraceRestrict(TileIndex tile, DoCommandFlag flags, u // move in modified program prog->items.swap(items); + prog->actions_used_flags = actions_used_flags; if (prog->items.size() == 0 && prog->refcount == 1) { // program is empty, and this tile is the only reference to it diff --git a/src/tracerestrict.h b/src/tracerestrict.h index 63a80b9d21..1704dc4c79 100644 --- a/src/tracerestrict.h +++ b/src/tracerestrict.h @@ -197,6 +197,15 @@ enum TraceRestrictProgramResultFlags { }; DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramResultFlags) +/** + * Enumeration for TraceRestrictProgram::actions_used_flags + */ +enum TraceRestrictProgramActionsUsedFlags { + TRPAUF_PF = 1 << 0, ///< Pathfinder deny or penalty are present + TRPAUF_RESERVE_THROUGH = 1 << 1, ///< Reserve through action is present +}; +DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramActionsUsedFlags) + /** * Execution input of a TraceRestrictProgram */ @@ -230,9 +239,10 @@ struct TraceRestrictProgramResult { struct TraceRestrictProgram : TraceRestrictProgramPool::PoolItem<&_tracerestrictprogram_pool> { std::vector items; uint32 refcount; + TraceRestrictProgramActionsUsedFlags actions_used_flags; TraceRestrictProgram() - : refcount(0) { } + : refcount(0), actions_used_flags(static_cast(0)) { } void Execute(const Train *v, const TraceRestrictProgramInput &input, TraceRestrictProgramResult &out) const; @@ -243,7 +253,7 @@ struct TraceRestrictProgram : TraceRestrictProgramPool::PoolItem<&_tracerestrict void DecrementRefCount(); - static CommandCost Validate(const std::vector &items); + static CommandCost Validate(const std::vector &items, TraceRestrictProgramActionsUsedFlags &actions_used_flags); static size_t InstructionOffsetToArrayOffset(const std::vector &items, size_t offset); @@ -285,10 +295,11 @@ struct TraceRestrictProgram : TraceRestrictProgramPool::PoolItem<&_tracerestrict return items.begin() + TraceRestrictProgram::InstructionOffsetToArrayOffset(items, instruction_offset); } - /** - * Call validation function on current program instruction list - */ - CommandCost Validate() const { return TraceRestrictProgram::Validate(items); } + /** Call validation function on current program instruction list and set actions_used_flags */ + CommandCost Validate() + { + return TraceRestrictProgram::Validate(items, actions_used_flags); + } }; /** Get TraceRestrictItem type field */ diff --git a/src/tracerestrict_gui.cpp b/src/tracerestrict_gui.cpp index 0737f540a9..5125c053c3 100644 --- a/src/tracerestrict_gui.cpp +++ b/src/tracerestrict_gui.cpp @@ -1680,7 +1680,8 @@ private: items.insert(items.begin() + array_offset, item); } - return TraceRestrictProgram::Validate(items).Succeeded(); + TraceRestrictProgramActionsUsedFlags actions_used_flags; + return TraceRestrictProgram::Validate(items, actions_used_flags).Succeeded(); } /**