diff --git a/src/pathfinder/yapf/yapf_costrail.hpp b/src/pathfinder/yapf/yapf_costrail.hpp index 1b541193a2..a0c127c1a5 100644 --- a/src/pathfinder/yapf/yapf_costrail.hpp +++ b/src/pathfinder/yapf/yapf_costrail.hpp @@ -261,11 +261,19 @@ private: } // returns true if dead end bit has been set - inline bool ExecuteTraceRestrict(Node& n, TileIndex tile, Trackdir trackdir, int& cost, TraceRestrictProgramResult &out) + inline bool ExecuteTraceRestrict(Node& n, TileIndex tile, Trackdir trackdir, int& cost, TraceRestrictProgramResult &out, bool *is_res_through) { const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(tile, TrackdirToTrack(trackdir)); - if (prog && prog->actions_used_flags & TRPAUF_PF) { + TraceRestrictProgramActionsUsedFlags flags_to_check = TRPAUF_PF; + if (is_res_through != NULL) { + *is_res_through = false; + flags_to_check |= TRPAUF_RESERVE_THROUGH; + } + if (prog && prog->actions_used_flags & flags_to_check) { prog->Execute(Yapf().GetVehicle(), TraceRestrictProgramInput(tile, trackdir, &TraceRestrictPreviousSignalCallback, &n), out); + if (out.flags & TRPRF_RESERVE_THROUGH && is_res_through != NULL) { + *is_res_through = true; + } if (out.flags & TRPRF_DENY) { n.m_segment->m_end_segment_reason |= ESRB_DEAD_END; return true; @@ -338,9 +346,11 @@ public: if (ShouldCheckTraceRestrict(n, tile)) { TraceRestrictProgramResult out; - if (ExecuteTraceRestrict(n, tile, trackdir, cost, out)) { + bool is_reserve_through = false; + if (ExecuteTraceRestrict(n, tile, trackdir, cost, out, &is_reserve_through)) { return -1; } + if (is_reserve_through) n.m_num_signals_res_through_passed++; } n.m_num_signals_passed++; @@ -353,7 +363,7 @@ public: if (ShouldCheckTraceRestrict(n, tile)) { TraceRestrictProgramResult out; - if (ExecuteTraceRestrict(n, tile, trackdir, cost, out)) { + if (ExecuteTraceRestrict(n, tile, trackdir, cost, out, NULL)) { return -1; } } diff --git a/src/pathfinder/yapf/yapf_node_rail.hpp b/src/pathfinder/yapf/yapf_node_rail.hpp index 180c894392..3584366961 100644 --- a/src/pathfinder/yapf/yapf_node_rail.hpp +++ b/src/pathfinder/yapf/yapf_node_rail.hpp @@ -128,6 +128,7 @@ struct CYapfRailNodeT CYapfRailSegment *m_segment; uint16 m_num_signals_passed; + uint16 m_num_signals_res_through_passed; union { uint32 m_inherited_flags; struct { @@ -145,6 +146,7 @@ struct CYapfRailNodeT m_segment = NULL; if (parent == NULL) { m_num_signals_passed = 0; + m_num_signals_res_through_passed = 0; flags_u.m_inherited_flags = 0; m_last_red_signal_type = SIGTYPE_NORMAL; /* We use PBS as initial signal type because if we are in @@ -160,6 +162,7 @@ struct CYapfRailNodeT m_last_signal_type = SIGTYPE_PBS; } else { m_num_signals_passed = parent->m_num_signals_passed; + m_num_signals_res_through_passed = parent->m_num_signals_res_through_passed; flags_u.m_inherited_flags = parent->flags_u.m_inherited_flags; m_last_red_signal_type = parent->m_last_red_signal_type; m_last_signal_type = parent->m_last_signal_type; @@ -210,6 +213,7 @@ struct CYapfRailNodeT base::Dump(dmp); dmp.WriteStructT("m_segment", m_segment); dmp.WriteLine("m_num_signals_passed = %d", m_num_signals_passed); + dmp.WriteLine("m_num_signals_res_through_passed = %d", m_num_signals_res_through_passed); dmp.WriteLine("m_targed_seen = %s", flags_u.flags_s.m_targed_seen ? "Yes" : "No"); dmp.WriteLine("m_choice_seen = %s", flags_u.flags_s.m_choice_seen ? "Yes" : "No"); dmp.WriteLine("m_last_signal_was_red = %s", flags_u.flags_s.m_last_signal_was_red ? "Yes" : "No"); diff --git a/src/pathfinder/yapf/yapf_rail.cpp b/src/pathfinder/yapf/yapf_rail.cpp index 5b334ddeec..861ca5ac29 100644 --- a/src/pathfinder/yapf/yapf_rail.cpp +++ b/src/pathfinder/yapf/yapf_rail.cpp @@ -168,8 +168,8 @@ public: { assert(node->m_parent != NULL); - /* We will never pass more than two signals, no need to check for a safe tile. */ - if (node->m_parent->m_num_signals_passed >= 2) return; + /* We will never pass more than two non-reserve-through signals, no need to check for a safe tile. */ + if (node->m_parent->m_num_signals_passed - node->m_parent->m_num_signals_res_through_passed >= 2) return; if (!node->IterateTiles(Yapf().GetVehicle(), Yapf(), *this, &CYapfReserveTrack::FindSafePositionProc)) { m_res_node = node;