From 54db96be43bbb94f3d5193647be2f787a192f358 Mon Sep 17 00:00:00 2001 From: fonsinchen Date: Sun, 20 Oct 2013 13:47:58 +0000 Subject: (svn r25891) -Feature: Use smallstack to allow for multiple next hops when loading and unloading. --- src/cargopacket.cpp | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) (limited to 'src/cargopacket.cpp') 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 -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) { -- cgit v1.2.3-70-g09d2