(svn r25891) -Feature: Use smallstack to allow for multiple next hops when loading and unloading.
This commit is contained in:
@@ -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) {
|
||||
|
Reference in New Issue
Block a user