diff options
author | fonsinchen <fonsinchen@openttd.org> | 2013-10-19 13:17:06 +0000 |
---|---|---|
committer | fonsinchen <fonsinchen@openttd.org> | 2013-10-19 13:17:06 +0000 |
commit | 338d9861bc7800744f47e72de1b6a659540ed3b1 (patch) | |
tree | c1f6433a8011ffa605d55fd1902fc95edfe8ef1c /src | |
parent | 8fff781ca06dfdd4e60509d525fcb5c840e0e431 (diff) | |
download | openttd-338d9861bc7800744f47e72de1b6a659540ed3b1.tar.xz |
(svn r25883) -Fix: Limit recursion and branching in RefreshNextHopsStats more aggressively.
Diffstat (limited to 'src')
-rw-r--r-- | src/vehicle.cpp | 30 | ||||
-rw-r--r-- | src/vehicle_base.h | 2 |
2 files changed, 20 insertions, 12 deletions
diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 78aedbf8f..3d9da8447 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -2141,8 +2141,9 @@ void Vehicle::ResetRefitCaps() * @param has_cargo If the consist could leave the last stop where it could * interact with cargo carrying cargo * (i.e. not an "unload all" + "no loading" order). + * @return Total number of hops used. */ -void Vehicle::RefreshNextHopsStats(CapacitiesMap &capacities, +uint Vehicle::RefreshNextHopsStats(CapacitiesMap &capacities, RefitList &refit_capacities, const Order *first, const Order *cur, const Order *next, uint hops, bool was_refit, bool has_cargo) { @@ -2211,20 +2212,13 @@ void Vehicle::RefreshNextHopsStats(CapacitiesMap &capacities, /* Resolve conditionals by recursion. */ do { + const Order *skip_to = NULL; if (next->IsType(OT_CONDITIONAL)) { - const Order *skip_to = this->orders.list->GetNextDecisionNode( + skip_to = this->orders.list->GetNextDecisionNode( this->orders.list->GetOrderAt(next->GetConditionSkipToOrder()), hops / 2); - - if (skip_to != NULL) { - /* Make copies of capacity tracking lists. */ - CapacitiesMap skip_capacities = capacities; - RefitList skip_refit_capacities = refit_capacities; - this->RefreshNextHopsStats(skip_capacities, - skip_refit_capacities, first, cur, skip_to, hops + 1, - was_refit, has_cargo); - } } + if (skip_first_inc) { /* First incrementation has to be skipped if a "real" next hop, * different from cur, was given. */ @@ -2237,6 +2231,19 @@ void Vehicle::RefreshNextHopsStats(CapacitiesMap &capacities, next = this->orders.list->GetNextDecisionNode( this->orders.list->GetNext(next), hops / 2); } + + if (skip_to != NULL) { + /* Process the linear succession first. Skip_to is likely to + * point back to already seen orders. */ + + /* Make copies of capacity tracking lists. */ + CapacitiesMap next_capacities = capacities; + RefitList next_refit_capacities = refit_capacities; + hops = this->RefreshNextHopsStats(next_capacities, + next_refit_capacities, first, cur, next, hops + 1, + was_refit, has_cargo); + next = skip_to; + } } while (next != NULL && next->IsType(OT_CONDITIONAL)); if (next == NULL) break; @@ -2278,6 +2285,7 @@ void Vehicle::RefreshNextHopsStats(CapacitiesMap &capacities, } } } + return hops; } /** diff --git a/src/vehicle_base.h b/src/vehicle_base.h index 4eecda6cc..ef5afa568 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -150,7 +150,7 @@ private: Vehicle *next_shared; ///< pointer to the next vehicle that shares the order Vehicle *previous_shared; ///< NOSAVE: pointer to the previous vehicle in the shared order chain - void RefreshNextHopsStats(CapacitiesMap &capacities, + uint RefreshNextHopsStats(CapacitiesMap &capacities, RefitList &refit_capacities, const Order *first, const Order *cur, const Order *next, uint hops, bool was_refit, bool has_cargo); public: |