diff options
author | fonsinchen <fonsinchen@openttd.org> | 2014-01-19 09:27:44 +0000 |
---|---|---|
committer | fonsinchen <fonsinchen@openttd.org> | 2014-01-19 09:27:44 +0000 |
commit | 7e91f96b92da84b7152e22d50bd5324e65cfccb3 (patch) | |
tree | d05494ec3940ec21ef1c18e6e04ff8b59cd73795 | |
parent | b158c7d0fa0bec2ccf885d06a9f1855ca8b3c698 (diff) | |
download | openttd-7e91f96b92da84b7152e22d50bd5324e65cfccb3.tar.xz |
(svn r26267) -Fix [FS#5865]: Really fix the infinite recursion problem and always consider all branches of conditional orders as possible next stopping stations.
-rw-r--r-- | src/order_base.h | 2 | ||||
-rw-r--r-- | src/order_cmd.cpp | 46 |
2 files changed, 17 insertions, 31 deletions
diff --git a/src/order_base.h b/src/order_base.h index 85d8a05a7..ff0813613 100644 --- a/src/order_base.h +++ b/src/order_base.h @@ -263,7 +263,7 @@ public: */ inline VehicleOrderID GetNumManualOrders() const { return this->num_manual_orders; } - StationIDStack GetNextStoppingStation(const Vehicle *v, const Order *first = NULL) const; + StationIDStack GetNextStoppingStation(const Vehicle *v, const Order *first = NULL, uint hops = 0) const; const Order *GetNextDecisionNode(const Order *next, uint hops) const; void InsertOrderAt(Order *new_order, int index); diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index eefa249e7..484fff4b2 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -391,11 +391,12 @@ const Order *OrderList::GetNextDecisionNode(const Order *next, uint hops) const * Recursively determine the next deterministic station to stop at. * @param v The vehicle we're looking at. * @param first Order to start searching at or NULL to start at cur_implicit_order_index + 1. + * @param hops Number of orders we have already looked at. * @return Next stoppping station or INVALID_STATION. * @pre The vehicle is currently loading and v->last_station_visited is meaningful. * @note This function may draw a random number. Don't use it from the GUI. */ -StationIDStack OrderList::GetNextStoppingStation(const Vehicle *v, const Order *first) const +StationIDStack OrderList::GetNextStoppingStation(const Vehicle *v, const Order *first, uint hops) const { const Order *next = first; @@ -413,42 +414,27 @@ StationIDStack OrderList::GetNextStoppingStation(const Vehicle *v, const Order * } } - uint hops = 0; do { next = this->GetNextDecisionNode(next, ++hops); /* Resolve possibly nested conditionals by estimation. */ while (next != NULL && next->IsType(OT_CONDITIONAL)) { - ++hops; - if (next->GetConditionVariable() == OCV_LOAD_PERCENTAGE) { - /* If the condition is based on load percentage we can't - * tell what it will do. So we choose randomly. */ - const Order *skip_to = this->GetNextDecisionNode( - this->GetOrderAt(next->GetConditionSkipToOrder()), - hops); - const Order *advance = this->GetNextDecisionNode( - this->GetNext(next), hops); - if (advance == NULL || advance == first) { - next = (skip_to == first) ? NULL : skip_to; - } else if (skip_to == NULL || skip_to == first) { - next = (advance == first) ? NULL : advance; - } else { - StationIDStack st1 = this->GetNextStoppingStation(v, skip_to); - StationIDStack st2 = this->GetNextStoppingStation(v, advance); - while (!st2.IsEmpty()) st1.Push(st2.Pop()); - return st1; - } + /* We return both options of conditional orders. */ + const Order *skip_to = this->GetNextDecisionNode( + this->GetOrderAt(next->GetConditionSkipToOrder()), hops); + const Order *advance = this->GetNextDecisionNode( + this->GetNext(next), hops); + if (advance == NULL || advance == first || skip_to == advance) { + next = (skip_to == first) ? NULL : skip_to; + } else if (skip_to == NULL || skip_to == first) { + next = (advance == first) ? NULL : advance; } else { - /* Otherwise we're optimistic and expect that the - * condition value won't change until it's evaluated. */ - VehicleOrderID skip_to = ProcessConditionalOrder(next, v); - if (skip_to != INVALID_VEH_ORDER_ID) { - next = this->GetNextDecisionNode(this->GetOrderAt(skip_to), - hops); - } else { - next = this->GetNextDecisionNode(this->GetNext(next), hops); - } + StationIDStack st1 = this->GetNextStoppingStation(v, skip_to, hops); + StationIDStack st2 = this->GetNextStoppingStation(v, advance, hops); + while (!st2.IsEmpty()) st1.Push(st2.Pop()); + return st1; } + ++hops; } /* Don't return a next stop if the vehicle has to unload everything. */ |