Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /** The type of cargo to be compared. */
- static CargoID _cargo_type_comparator;
- static int CDECL CompareCargoRatings(Station * const *a, Station * const *b)
- {
- return (*b)->goods[_cargo_type_comparator].rating - (*a)->goods[_cargo_type_comparator].rating;
- }
- uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations)
- {
- /* Return if nothing to do. Also the rounding below fails for 0. */
- if (amount == 0) return 0;
- // SmallVector<Station *, 1> used_stations;
- typedef std::vector<Station *> UsedStations;
- UsedStations used_stations;
- for (Station *st : *all_stations) {
- /* Is the station reserved exclusively for somebody else? */
- if (st->owner != OWNER_NONE && st->town->exclusive_counter > 0 && st->town->exclusivity != st->owner) continue;
- if (st->goods[type].rating == 0) continue; // Lowest possible rating, better not to give cargo anymore
- if (_settings_game.order.selectgoods && !st->goods[type].HasVehicleEverTriedLoading()) continue; // Selectively servicing stations, and not this one
- if (IsCargoInClass(type, CC_PASSENGERS)) {
- if (st->facilities == FACIL_TRUCK_STOP) continue; // passengers are never served by just a truck stop
- } else {
- if (st->facilities == FACIL_BUS_STOP) continue; // non-passengers are never served by just a bus stop
- }
- /* This station can be used, add it to the list */
- used_stations.emplace_back(st);
- }
- const uint num_stations = (uint)used_stations.size(); // total number of stations added
- /* no stations around at all? */
- if (num_stations == 0) return 0;
- /* Sort the stations by cargo rating in descending order. */
- _cargo_type_comparator = type;
- QSortT<Station *>(used_stations.begin(), used_stations.size(), CompareCargoRatings);
- Station *best_station = *used_stations.begin();
- /* From now we'll calculate with fractal cargo amounts.
- * First determine how much cargo we really have. */
- amount *= best_station->goods[type].rating + 1;
- /* several stations around */
- uint ratings_square_sum = 0;
- for (Station * const *st_iter = used_stations.begin(); st_iter != used_stations.end(); ++st_iter) {
- Station *st = *st_iter;
- ratings_square_sum += st->goods[type].rating * st->goods[type].rating;
- }
- uint moved = 0;
- for (Station * const *st_iter = used_stations.end(); st_iter != used_stations.begin(); --st_iter) {
- Station *st = *(st_iter - 1);
- if (st != best_station) {
- /* Determine the amount the worst station gets, which is the last one from the list.
- * Then determine the amount the next worst gets by iterating backwards, until the
- * best station remains. We do it this way as the best should get a bonus, which in
- * this case is the rounding difference from the last time this calculation is done.
- * In reality that will mean the bonus will be pretty low. Nevertheless, the best
- * station should always get the most cargo regardless of rounding issues. */
- uint cur_worst = amount * st->goods[type].rating * st->goods[type].rating / ratings_square_sum;
- /* And then send the cargo to the stations! */
- moved += UpdateStationWaiting(st, type, cur_worst, source_type, source_id);
- amount -= cur_worst;
- ratings_square_sum -= st->goods[type].rating * st->goods[type].rating;
- } else {
- /* These two UpdateStationWaiting's can't be in the statement as then the order
- * of execution would be undefined and that could cause desyncs with callbacks. */
- moved += UpdateStationWaiting(st, type, amount, source_type, source_id);
- }
- }
- return moved;
- }
Add Comment
Please, Sign In to add comment