De-duplicate cargo masking boilerplate using C++11.

pull/155/head
Jonathan G Rennison 8 years ago
parent 72a386abe5
commit e90b266af1

@ -38,22 +38,14 @@
for (const Order *o = v->orders.list->GetFirstOrder(); o != NULL; o = o->next) {
if (o->IsType(OT_GOTO_STATION) || o->IsType(OT_IMPLICIT)) {
if (o->GetUnloadType() == OUFB_CARGO_TYPE_UNLOAD) {
OrderUnloadFlags ouf = o->GetCargoUnloadType(first_cargo_id);
uint32 other_cargo_mask = cargo_mask;
ClrBit(other_cargo_mask, first_cargo_id);
CargoID cargo;
FOR_EACH_SET_BIT(cargo, other_cargo_mask) {
if (((ouf ^ o->GetCargoUnloadType(cargo)) & (OUFB_TRANSFER | OUFB_UNLOAD | OUFB_NO_UNLOAD)) != 0) ClrBit(cargo_mask, cargo);
}
CargoMaskValueFilter<uint>(cargo_mask, [&](CargoID cargo) -> uint {
return o->GetCargoUnloadType(cargo) & (OUFB_TRANSFER | OUFB_UNLOAD | OUFB_NO_UNLOAD);
});
}
if (o->GetLoadType() == OLFB_CARGO_TYPE_LOAD) {
OrderLoadFlags olf = o->GetCargoLoadType(first_cargo_id);
uint32 other_cargo_mask = cargo_mask;
ClrBit(other_cargo_mask, first_cargo_id);
CargoID cargo;
FOR_EACH_SET_BIT(cargo, other_cargo_mask) {
if (((olf ^ o->GetCargoLoadType(cargo)) & (OLFB_NO_LOAD)) != 0) ClrBit(cargo_mask, cargo);
}
CargoMaskValueFilter<uint>(cargo_mask, [&](CargoID cargo) -> uint {
return o->GetCargoLoadType(cargo) & (OLFB_NO_LOAD);
});
}
}
}

@ -388,6 +388,19 @@ public:
void FillNextStoppingStation(const Vehicle *v, const OrderList *o, const Order *first = NULL, uint hops = 0);
};
template <typename T, typename F> T CargoMaskValueFilter(uint32 &cargo_mask, F filter_func)
{
CargoID first_cargo_id = FindFirstBit(cargo_mask);
T value = filter_func(first_cargo_id);
uint32 other_cargo_mask = cargo_mask;
ClrBit(other_cargo_mask, first_cargo_id);
CargoID cargo;
FOR_EACH_SET_BIT(cargo, other_cargo_mask) {
if (value != filter_func(cargo)) ClrBit(cargo_mask, cargo);
}
return value;
}
/**
* Shared order list linking together the linked list of orders and the list
* of vehicles sharing this order list.

@ -439,16 +439,9 @@ const Order *OrderList::GetNextDecisionNode(const Order *next, uint hops, uint32
/* This is a cargo-specific load/unload order.
* If the first cargo is both a no-load and no-unload order, skip it.
* Drop cargoes which don't match the first one. */
CargoID first_cargo_id = FindFirstBit(cargo_mask);
can_load_or_unload = ((next->GetCargoLoadType(first_cargo_id) & OLFB_NO_LOAD) == 0 || (next->GetCargoUnloadType(first_cargo_id) & OUFB_NO_UNLOAD) == 0);
uint32 other_cargo_mask = cargo_mask;
ClrBit(other_cargo_mask, first_cargo_id);
CargoID cargo;
FOR_EACH_SET_BIT(cargo, other_cargo_mask) {
if (can_load_or_unload != ((next->GetCargoLoadType(cargo) & OLFB_NO_LOAD) == 0 || (next->GetCargoUnloadType(cargo) & OUFB_NO_UNLOAD) == 0)) {
ClrBit(cargo_mask, cargo);
}
}
can_load_or_unload = CargoMaskValueFilter<bool>(cargo_mask, [&](CargoID cargo) {
return ((next->GetCargoLoadType(cargo) & OLFB_NO_LOAD) == 0 || (next->GetCargoUnloadType(cargo) & OUFB_NO_UNLOAD) == 0);
});
} else if ((next->GetLoadType() & OLFB_NO_LOAD) == 0 || (next->GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
can_load_or_unload = true;
}
@ -520,21 +513,12 @@ CargoMaskedStationIDStack OrderList::GetNextStoppingStation(const Vehicle *v, ui
/* Don't return a next stop if the vehicle has to unload everything. */
if ((next->IsType(OT_GOTO_STATION) || next->IsType(OT_IMPLICIT)) &&
next->GetDestination() == v->last_station_visited) {
CargoID first_cargo_id = FindFirstBit(cargo_mask);
bool invalid = ((next->GetCargoUnloadType(first_cargo_id) & (OUFB_TRANSFER | OUFB_UNLOAD)) != 0);
if (next->GetUnloadType() == OUFB_CARGO_TYPE_UNLOAD) {
/* This is a cargo-specific load/unload order.
* Don't return a next stop if first cargo has transfer or unload set.
* Drop cargoes which don't match the first one. */
uint32 other_cargo_mask = cargo_mask;
ClrBit(other_cargo_mask, first_cargo_id);
CargoID cargo;
FOR_EACH_SET_BIT(cargo, other_cargo_mask) {
if (invalid != ((next->GetCargoUnloadType(cargo) & (OUFB_TRANSFER | OUFB_UNLOAD)) != 0)) {
ClrBit(cargo_mask, cargo);
}
}
}
/* This is a cargo-specific load/unload order.
* Don't return a next stop if first cargo has transfer or unload set.
* Drop cargoes which don't match the first one. */
bool invalid = CargoMaskValueFilter<bool>(cargo_mask, [&](CargoID cargo) {
return ((next->GetCargoUnloadType(cargo) & (OUFB_TRANSFER | OUFB_UNLOAD)) != 0);
});
if (invalid) return CargoMaskedStationIDStack(cargo_mask, INVALID_STATION);
}
} while (next->IsType(OT_GOTO_DEPOT) || next->GetDestination() == v->last_station_visited);

Loading…
Cancel
Save