Loading

Paste #pfsmdufv4

  1. uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations)
  2. {
  3.     /* Return if nothing to do. Also the rounding below fails for 0. */
  4.     if (amount == 0) return 0;
  5.  
  6.     Station *st1 = NULL;   // Station with best rating
  7.     Station *st2 = NULL;   // Second best station
  8.     Station *st3 = NULL;   // Third best station
  9.     uint best_rating1 = 0; // rating of st1
  10.     uint best_rating2 = 0; // rating of st2
  11.     uint best_rating3 = 0; // rating of st3
  12.  
  13.     for (Station * const *st_iter = all_stations->Begin(); st_iter != all_stations->End(); ++st_iter) {
  14.         Station *st = *st_iter;
  15.  
  16.         /* Is the station reserved exclusively for somebody else? */
  17.         if (st->town->exclusive_counter > 0 && st->town->exclusivity != st->owner) continue;
  18.  
  19.         if (st->goods[type].rating == 0) continue; // Lowest possible rating, better not to give cargo anymore
  20.  
  21.         if (_settings_game.order.selectgoods && !st->goods[type].HasVehicleEverTriedLoading()) continue; // Selectively servicing stations, and not this one
  22.  
  23.         if (IsCargoInClass(type, CC_PASSENGERS)) {
  24.             if (st->facilities == FACIL_TRUCK_STOP) continue; // passengers are never served by just a truck stop
  25.         } else {
  26.             if (st->facilities == FACIL_BUS_STOP) continue; // non-passengers are never served by just a bus stop
  27.         }
  28.  
  29.         /* This station can be used, add it to st1/st2/st3 */
  30.         if (st1 == NULL || st->goods[type].rating >= best_rating1) {
  31.             st3 = st2;
  32.             best_rating3 = best_rating2;
  33.             st2 = st1;
  34.             best_rating2 = best_rating1;
  35.             st1 = st;
  36.             best_rating1 = st->goods[type].rating;
  37.         } else if (st2 == NULL || st->goods[type].rating >= best_rating2) {
  38.             st3 = st2;
  39.             best_rating3 = best_rating2;
  40.             st2 = st;
  41.             best_rating2 = st->goods[type].rating;
  42.         } else if (st3 == NULL || st->goods[type].rating >= best_rating3) {
  43.             st3 = st;
  44.             best_rating3 = st->goods[type].rating;
  45.         }
  46.     }
  47.  
  48.     /* no stations around at all? */
  49.     if (st1 == NULL) return 0;
  50.  
  51.     /* From now we'll calculate with fractal cargo amounts.
  52.      * First determine how much cargo we really have. */
  53.     amount *= best_rating1 + 1;
  54.  
  55.     if (st2 == NULL) {
  56.         /* only one station around */
  57.         return UpdateStationWaiting(st1, type, amount, source_type, source_id);
  58.     }
  59.  
  60.     if (st3 == NULL) {
  61.         /* two stations around, the best two (highest rating) are in st1 and st2 */
  62.         assert(st1 != NULL);
  63.         assert(st2 != NULL);
  64.         assert(best_rating1 != 0 || best_rating2 != 0);
  65.  
  66.         /* Then determine the amount the worst station gets. We do it this way as the
  67.          * best should get a bonus, which in this case is the rounding difference from
  68.          * this calculation. In reality that will mean the bonus will be pretty low.
  69.          * Nevertheless, the best station should always get the most cargo regardless
  70.          * of rounding issues. */
  71.         uint worst_cargo = amount * best_rating2 / (best_rating1 + best_rating2);
  72.         assert(worst_cargo <= (amount - worst_cargo));
  73.  
  74.         /* And then send the cargo to the stations! */
  75.         uint moved = UpdateStationWaiting(st1, type, amount - worst_cargo, source_type, source_id);
  76.         /* These two UpdateStationWaiting's can't be in the statement as then the order
  77.          * of execution would be undefined and that could cause desyncs with callbacks. */
  78.         return moved + UpdateStationWaiting(st2, type, worst_cargo, source_type, source_id);
  79.     }
  80.  
  81.     /* three stations around, the best three (highest rating) are in st1, st2 and st3 */
  82.     assert(st1 != NULL);
  83.     assert(st2 != NULL);
  84.     assert(st3 != NULL);
  85.     assert(best_rating1 != 0 || best_rating2 != 0 || best_rating3 !=0);
  86.  
  87.     /* Then determine the amount the worst station gets. We do it this way as the
  88.      * best should get a bonus, which in this case is the rounding difference from
  89.      * this calculation. In reality that will mean the bonus will be pretty low.
  90.      * Nevertheless, the best station should always get the most cargo regardless
  91.      * of rounding issues. */
  92.     uint worst_cargo_st3 = amount * best_rating3 / (best_rating1 + best_rating2 + best_rating3);
  93.     assert(worst_cargo_st3 <= (amount - worst_cargo_st3));
  94.  
  95.     uint remaining_amount = amount - worst_cargo_st3;
  96.     uint worst_cargo_st2 = remaining_amount * best_rating2 / (best_rating1 + best_rating2);
  97.     assert(worst_cargo_st2 <= (remaining_amount - worst_cargo_st2));
  98.  
  99.     /* And then send the cargo to the stations! */
  100.     uint moved = UpdateStationWaiting(st1, type, remaining_amount - worst_cargo_st2, source_type, source_id);
  101.     /* HALP - I GOT 3 UpdateStationWaitings now! */
  102.     moved += UpdateStationWaiting(st2, type, worst_cargo_st2, source_type, source_id);
  103.     return moved + UpdateStationWaiting(st3, type, worst_cargo_st3, source_type, source_id);
  104. }

Comments