Route Line Rendering: Properly prevent endless loop due to conditional orders cycle.

(cherry picked from commit ac1c26f5fe942ef47c664ff71000053d874a6008)

See #39
This commit is contained in:
keldorkatarn
2018-04-19 01:43:33 +02:00
committed by Jonathan G Rennison
parent d154debb5e
commit 8df549284f

View File

@@ -1693,13 +1693,26 @@ static inline TileIndex GetLastValidOrderLocation(const Vehicle *veh)
static inline Order *GetFinalOrder(const Vehicle *veh, Order *order) 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)) { while (order->IsType(OT_CONDITIONAL)) {
order = veh->GetOrder(order->GetConditionSkipToOrder()); 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; return order;
} }