summaryrefslogtreecommitdiff
path: root/src/cargopacket.cpp
diff options
context:
space:
mode:
authorfonsinchen <fonsinchen@openttd.org>2013-10-20 13:47:58 +0000
committerfonsinchen <fonsinchen@openttd.org>2013-10-20 13:47:58 +0000
commit54db96be43bbb94f3d5193647be2f787a192f358 (patch)
tree170110df7e7d1653f10bf55acb686495e019dc67 /src/cargopacket.cpp
parentdffc4d411e64269f5dd6678a8a5d599dd50bc82c (diff)
downloadopenttd-54db96be43bbb94f3d5193647be2f787a192f358.tar.xz
(svn r25891) -Feature: Use smallstack to allow for multiple next hops when loading and unloading.
Diffstat (limited to 'src/cargopacket.cpp')
-rw-r--r--src/cargopacket.cpp41
1 files changed, 30 insertions, 11 deletions
diff --git a/src/cargopacket.cpp b/src/cargopacket.cpp
index 6a37cb488..9a1ba8568 100644
--- a/src/cargopacket.cpp
+++ b/src/cargopacket.cpp
@@ -421,7 +421,7 @@ void VehicleCargoList::SetTransferLoadPlace(TileIndex xy)
* @param payment Payment object for registering transfers.
* return If any cargo will be unloaded.
*/
-bool VehicleCargoList::Stage(bool accepted, StationID current_station, StationID next_station, uint8 order_flags, const GoodsEntry *ge, CargoPayment *payment)
+bool VehicleCargoList::Stage(bool accepted, StationID current_station, StationIDStack next_station, uint8 order_flags, const GoodsEntry *ge, CargoPayment *payment)
{
this->AssertCountConsistency();
assert(this->action_counts[MTA_LOAD] == 0);
@@ -446,9 +446,24 @@ bool VehicleCargoList::Stage(bool accepted, StationID current_station, StationID
action = MTA_DELIVER;
} else if (force_transfer) {
action = MTA_TRANSFER;
- cargo_next = ge->GetVia(cp->source, current_station, next_station);
- assert((cargo_next != next_station || cargo_next == INVALID_STATION) &&
- cargo_next != current_station);
+ /* We cannot send the cargo to any of the possible next hops and
+ * also not to the current station. */
+ FlowStatMap::const_iterator flow_it(ge->flows.find(cp->source));
+ if (flow_it == ge->flows.end()) {
+ cargo_next = INVALID_STATION;
+ } else {
+ FlowStat new_shares = flow_it->second;
+ new_shares.ChangeShare(current_station, INT_MIN);
+ StationIDStack excluded = next_station;
+ while (!excluded.IsEmpty()) {
+ new_shares.ChangeShare(excluded.Pop(), INT_MIN);
+ }
+ if (new_shares.GetShares()->empty()) {
+ cargo_next = INVALID_STATION;
+ } else {
+ cargo_next = new_shares.GetVia();
+ }
+ }
} else {
/* Rewrite an invalid source station to some random other one to
* avoid keeping the cargo in the vehicle forever. */
@@ -460,7 +475,7 @@ bool VehicleCargoList::Stage(bool accepted, StationID current_station, StationID
action = (accepted && cp->source != current_station) ? MTA_DELIVER : MTA_KEEP;
} else if (cargo_next == current_station) {
action = MTA_DELIVER;
- } else if (cargo_next == next_station) {
+ } else if (next_station.Contains(cargo_next)) {
action = MTA_KEEP;
} else {
action = MTA_TRANSFER;
@@ -667,10 +682,14 @@ bool StationCargoList::ShiftCargo(Taction &action, StationID next)
* @return Amount of cargo actually moved.
*/
template <class Taction>
-uint StationCargoList::ShiftCargo(Taction action, StationID next, bool include_invalid)
+uint StationCargoList::ShiftCargo(Taction action, StationIDStack next, bool include_invalid)
{
uint max_move = action.MaxMove();
- if (this->ShiftCargo(action, next) && include_invalid && action.MaxMove() > 0) {
+ while (!next.IsEmpty()) {
+ this->ShiftCargo(action, next.Pop());
+ if (action.MaxMove() == 0) break;
+ }
+ if (include_invalid && action.MaxMove() > 0) {
this->ShiftCargo(action, INVALID_STATION);
}
return max_move - action.MaxMove();
@@ -735,10 +754,10 @@ uint StationCargoList::Truncate(uint max_move, StationCargoAmountMap *cargo_per_
* @param max_move Maximum amount of cargo to reserve.
* @param dest VehicleCargoList to reserve for.
* @param load_place Tile index of the current station.
- * @param next_station Next station the loading vehicle will visit.
+ * @param next_station Next station(s) the loading vehicle will visit.
* @return Amount of cargo actually reserved.
*/
-uint StationCargoList::Reserve(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationID next_station)
+uint StationCargoList::Reserve(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationIDStack next_station)
{
return this->ShiftCargo(CargoReservation(this, dest, max_move, load_place), next_station, true);
}
@@ -749,13 +768,13 @@ uint StationCargoList::Reserve(uint max_move, VehicleCargoList *dest, TileIndex
* @param max_move Amount of cargo to load.
* @param dest Vehicle cargo list where the cargo resides.
* @param load_place The new loaded_at_xy to be assigned to packets being moved.
- * @param next_station Next station the loading vehicle will visit.
+ * @param next_station Next station(s) the loading vehicle will visit.
* @return Amount of cargo actually loaded.
* @note Vehicles may or may not reserve, depending on their orders. The two
* modes of loading are exclusive, though. If cargo is reserved we don't
* need to load unreserved cargo.
*/
-uint StationCargoList::Load(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationID next_station)
+uint StationCargoList::Load(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationIDStack next_station)
{
uint move = min(dest->ActionCount(VehicleCargoList::MTA_LOAD), max_move);
if (move > 0) {