summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfonsinchen <fonsinchen@openttd.org>2014-01-19 09:27:44 +0000
committerfonsinchen <fonsinchen@openttd.org>2014-01-19 09:27:44 +0000
commit7e91f96b92da84b7152e22d50bd5324e65cfccb3 (patch)
treed05494ec3940ec21ef1c18e6e04ff8b59cd73795
parentb158c7d0fa0bec2ccf885d06a9f1855ca8b3c698 (diff)
downloadopenttd-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.h2
-rw-r--r--src/order_cmd.cpp46
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. */