From d154debb5e8040165c61bc3cc0d8924672c19c28 Mon Sep 17 00:00:00 2001 From: keldorkatarn Date: Wed, 11 Apr 2018 20:45:21 +0200 Subject: [PATCH 1/2] FIX: Endless look in vehicle route drawing if conditional orders form a cycle (in the simplest form, a conditional order skipping to itself) (cherry picked from commit 680ddba875208b09160908ad03064b542193df4e) See: #39 --- src/viewport.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/viewport.cpp b/src/viewport.cpp index 429148b175..1ca6fa2032 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -1693,8 +1693,13 @@ static inline TileIndex GetLastValidOrderLocation(const Vehicle *veh) static inline Order *GetFinalOrder(const Vehicle *veh, Order *order) { - while (order->IsType(OT_CONDITIONAL)) + auto original_order = order; + + while (order->IsType(OT_CONDITIONAL)) { order = veh->GetOrder(order->GetConditionSkipToOrder()); + + if (original_order == order) return nullptr; + } return order; } @@ -1709,6 +1714,7 @@ static bool ViewportMapPrepareVehicleRoute(const Vehicle * const veh) Order *order; FOR_VEHICLE_ORDERS(veh, order) { Order *final_order = GetFinalOrder(veh, order); + if (final_order == nullptr) continue; const TileIndex to_tile = final_order->GetLocation(veh, veh->type == VEH_AIRCRAFT); if (to_tile == INVALID_TILE) continue; From 8df549284f6923d3edbb43c87aa0100c30ac202c Mon Sep 17 00:00:00 2001 From: keldorkatarn Date: Thu, 19 Apr 2018 01:43:33 +0200 Subject: [PATCH 2/2] Route Line Rendering: Properly prevent endless loop due to conditional orders cycle. (cherry picked from commit ac1c26f5fe942ef47c664ff71000053d874a6008) See #39 --- src/viewport.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/viewport.cpp b/src/viewport.cpp index 1ca6fa2032..6c61793dae 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -1693,13 +1693,26 @@ static inline TileIndex GetLastValidOrderLocation(const Vehicle *veh) static inline Order *GetFinalOrder(const Vehicle *veh, Order *order) { - auto original_order = order; + // Use Floyd's cycle-finding algorithm to prevent endless loop + // due to a cycle formed by confitional orders. + auto cycle_check = order; while (order->IsType(OT_CONDITIONAL)) { order = veh->GetOrder(order->GetConditionSkipToOrder()); - if (original_order == order) return nullptr; + if (cycle_check->IsType(OT_CONDITIONAL)) { + cycle_check = veh->GetOrder(cycle_check->GetConditionSkipToOrder()); + + if (cycle_check->IsType(OT_CONDITIONAL)) { + cycle_check = veh->GetOrder(cycle_check->GetConditionSkipToOrder()); + } + } + + bool cycle_detected = (order->IsType(OT_CONDITIONAL) && (order == cycle_check)); + + if (cycle_detected) return nullptr; } + return order; }