summaryrefslogtreecommitdiff
path: root/src/order_cmd.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/order_cmd.cpp')
-rw-r--r--src/order_cmd.cpp52
1 files changed, 48 insertions, 4 deletions
diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp
index 833d23ff3..71edbb406 100644
--- a/src/order_cmd.cpp
+++ b/src/order_cmd.cpp
@@ -351,19 +351,61 @@ Order *OrderList::GetOrderAt(int index) const
}
/**
+ * Choose between the two possible next orders so that the given consist can
+ * load most cargo.
+ * @param v Head of the consist.
+ * @param o1 First order to choose from.
+ * @param o2 Second order to choose from.
+ * @return Either o1 or o2, depending on the amounts of cargo waiting at the
+ * vehicle's current station for each.
+ */
+const Order *OrderList::GetBestLoadableNext(const Vehicle *v, const Order *o2, const Order *o1) const
+{
+ SmallMap<CargoID, uint> capacities;
+ v->GetConsistFreeCapacities(capacities);
+ uint loadable1 = 0;
+ uint loadable2 = 0;
+ StationID st1 = o1->GetDestination();
+ StationID st2 = o2->GetDestination();
+ const Station *cur_station = Station::Get(v->last_station_visited);
+ for (SmallPair<CargoID, uint> *i = capacities.Begin(); i != capacities.End(); ++i) {
+ const StationCargoPacketMap *loadable_packets = cur_station->goods[i->first].cargo.Packets();
+ uint loadable_cargo = 0;
+ std::pair<StationCargoPacketMap::const_iterator, StationCargoPacketMap::const_iterator> p =
+ loadable_packets->equal_range(st1);
+ for (StationCargoPacketMap::const_iterator j = p.first; j != p.second; ++j) {
+ loadable_cargo = (*j)->Count();
+ }
+ loadable1 += min(i->second, loadable_cargo);
+
+ loadable_cargo = 0;
+ p = loadable_packets->equal_range(st2);
+ for (StationCargoPacketMap::const_iterator j = p.first; j != p.second; ++j) {
+ loadable_cargo = (*j)->Count();
+ }
+ loadable2 += min(i->second, loadable_cargo);
+ }
+ if (loadable1 == loadable2) return RandomRange(2) == 0 ? o1 : o2;
+ return loadable1 > loadable2 ? o1 : o2;
+}
+
+/**
* Get the next order which will make the given vehicle stop at a station
* or refit at a depot if its state doesn't change.
* @param v The vehicle in question.
* @param next The order to start looking at.
* @param hops The number of orders we have already looked at.
+ * @param is_loading If the vehicle is loading. This triggers a different
+ * behaviour on conditional orders based on load percentage.
* @return Either an order or NULL if the vehicle won't stop anymore.
+ * @see OrderList::GetBestLoadableNext
*/
-const Order *OrderList::GetNextStoppingOrder(const Vehicle *v, const Order *next, uint hops) const
+const Order *OrderList::GetNextStoppingOrder(const Vehicle *v, const Order *next, uint hops, bool is_loading) const
{
if (hops > this->GetNumOrders() || next == NULL) return NULL;
if (next->IsType(OT_CONDITIONAL)) {
- if (next->GetConditionVariable() == OCV_LOAD_PERCENTAGE) {
+ if (is_loading && 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->GetNextStoppingOrder(v,
@@ -373,7 +415,7 @@ const Order *OrderList::GetNextStoppingOrder(const Vehicle *v, const Order *next
this->GetNext(next), hops + 1);
if (advance == NULL) return skip_to;
if (skip_to == NULL) return advance;
- return RandomRange(2) == 0 ? skip_to : advance;
+ return this->GetBestLoadableNext(v, skip_to, advance);
}
/* Otherwise we're optimistic and expect that the
* condition value won't change until it's evaluated. */
@@ -401,6 +443,8 @@ const Order *OrderList::GetNextStoppingOrder(const Vehicle *v, const Order *next
* Recursively determine the next deterministic station to stop at.
* @param v The vehicle we're looking 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.
*/
StationID OrderList::GetNextStoppingStation(const Vehicle *v) const
{
@@ -420,7 +464,7 @@ StationID OrderList::GetNextStoppingStation(const Vehicle *v) const
uint hops = 0;
do {
- next = this->GetNextStoppingOrder(v, next, ++hops);
+ next = this->GetNextStoppingOrder(v, next, ++hops, true);
/* Don't return a next stop if the vehicle has to unload everything. */
if (next == NULL || (next->GetDestination() == v->last_station_visited &&
(next->GetUnloadType() & (OUFB_TRANSFER | OUFB_UNLOAD)) == 0)) {