Loading

Paste #pnufelyg1

  1. static int CDECL StationRatingSorter(const Station * const *a, const Station * const *b)
  2. {
  3. //  GSortT(used_stations->Begin(), used_stations.Lenght(), );
  4.     const Station *sta = *a;
  5.     const Station *stb = *b;
  6.     return stb->goods[0].rating - sta->goods[0].rating;
  7. }
  8.  
  9. uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations)
  10. {
  11.     /* Return if nothing to do. Also the rounding below fails for 0. */
  12.     if (amount == 0) return 0;
  13.  
  14.     Station *st1 = NULL;   // Station with best rating
  15.     Station *st2 = NULL;   // Second best station
  16.     Station *st3 = NULL;   // Third best station
  17.     Station *st4 = NULL;   // Fourth best station
  18.     Station *st5 = NULL;   // Fifth best station
  19.     Station *st6 = NULL;   // Sixth best station
  20.     uint best_rating1 = 0; // rating of st1
  21.     uint best_rating2 = 0; // rating of st2
  22.     uint best_rating3 = 0; // rating of st3
  23.     uint best_rating4 = 0; // rating of st4
  24.     uint best_rating5 = 0; // rating of st5
  25.     uint best_rating6 = 0; // rating of st6
  26.  
  27.     StationList used_stations;
  28.  
  29.     for (Station * const *st_iter = all_stations->Begin(); st_iter != all_stations->End(); ++st_iter) {
  30.         Station *st = *st_iter;
  31.  
  32.         /* Is the station reserved exclusively for somebody else? */
  33.         if (st->town->exclusive_counter > 0 && st->town->exclusivity != st->owner) continue;
  34.  
  35.         if (st->goods[type].rating == 0) continue; // Lowest possible rating, better not to give cargo anymore
  36.  
  37.         if (_settings_game.order.selectgoods && !st->goods[type].HasVehicleEverTriedLoading()) continue; // Selectively servicing stations, and not this one
  38.  
  39.         if (IsCargoInClass(type, CC_PASSENGERS)) {
  40.             if (st->facilities == FACIL_TRUCK_STOP) continue; // passengers are never served by just a truck stop
  41.         } else {
  42.             if (st->facilities == FACIL_BUS_STOP) continue; // non-passengers are never served by just a bus stop
  43.         }
  44.  
  45.         /* This station can be used, add it to st1/st2/st3/st4/st5/st6 */
  46.         used_stations.Include(st);
  47.  
  48.         if (st1 == NULL || st->goods[type].rating >= best_rating1) {
  49.             st6 = st5; best_rating6 = best_rating5;
  50.             st5 = st4; best_rating5 = best_rating4;
  51.             st4 = st3; best_rating4 = best_rating3;
  52.             st3 = st2; best_rating3 = best_rating2;
  53.             st2 = st1; best_rating2 = best_rating1;
  54.             st1 = st; best_rating1 = st->goods[type].rating;
  55.         } else if (st2 == NULL || st->goods[type].rating >= best_rating2) {
  56.             st6 = st5; best_rating6 = best_rating5;
  57.             st5 = st4; best_rating5 = best_rating4;
  58.             st4 = st3; best_rating4 = best_rating3;
  59.             st3 = st2; best_rating3 = best_rating2;
  60.             st2 = st; best_rating2 = st->goods[type].rating;
  61.         } else if (st3 == NULL || st->goods[type].rating >= best_rating3) {
  62.             st6 = st5; best_rating6 = best_rating5;
  63.             st5 = st4; best_rating5 = best_rating4;
  64.             st4 = st3; best_rating4 = best_rating3;
  65.             st3 = st; best_rating3 = st->goods[type].rating;
  66.         } else if (st4 == NULL || st->goods[type].rating >= best_rating4) {
  67.             st6 = st5; best_rating6 = best_rating5;
  68.             st5 = st4; best_rating5 = best_rating4;
  69.             st4 = st; best_rating4 = st->goods[type].rating;
  70.         } else if (st5 == NULL || st->goods[type].rating >= best_rating5) {
  71.             st6 = st5; best_rating6 = best_rating5;
  72.             st5 = st; best_rating5 = st->goods[type].rating;
  73.         } else if (st6 == NULL || st->goods[type].rating >= best_rating6) {
  74.             st6 = st; best_rating6 = st->goods[type].rating;
  75.         }
  76.     }
  77.  
  78.     uint no_stations = used_stations.Length();
  79.  
  80.     GSortT(used_stations.Begin(), used_stations.Length(), &StationRatingSorter);
  81.    
  82.     if (no_stations > 1) {
  83.         Station *st1 = &used_stations.Begin();
  84.         Station *st2 = &st1++;
  85.         uint offset = 0;
  86.  
  87.         while (no_stations > 1) {
  88.             const int diff = st1->goods[type].rating - st2->goods[type].rating;
  89.             if (diff <= 0) {
  90.                 if (offset != 0) {
  91.                     st1 += offset;
  92.                     st2 += offset;
  93.                     offset = 0;
  94.                     continue;
  95.                 }
  96.  
  97.                 st1++;
  98.                 st2++;
  99.                 no_stations--;
  100.             } else {
  101.                 Swap(*st1, *st2);
  102.  
  103.                 if (st1 == *used_stations.Begin()) continue;
  104.  
  105.                 st1--;
  106.                 st2--;
  107.                 offset++;
  108.                 }
  109.         }
  110. //      for (Station **st_iter = used_stations.Begin(); st_iter != used_stations.End(); ++st_iter) {
  111. //          Station *st1 = *st_iter;
  112. //          Station *st2 = *st_iter + 1;
  113. //
  114. //          if (st1->goods[type].rating >= st2->goods[type].rating) {
  115. //              st2 = st1;
  116. //          }
  117. //
  118. //      }
  119.     }
  120.    
  121.     /* no stations around at all? */
  122.     if (st1 == NULL) return 0;
  123.  
  124.     /* From now we'll calculate with fractal cargo amounts.
  125.      * First determine how much cargo we really have. */
  126.     amount *= best_rating1 + 1;
  127.  
  128.     if (st2 == NULL) {
  129.         /* only one station around */
  130.         return UpdateStationWaiting(st1, type, amount, source_type, source_id);
  131.     }
  132.  
  133.     if (st3 == NULL) {
  134.         /* two stations around, the best two (highest rating) are in st1 and st2 */
  135.         assert(st1 != NULL);
  136.         assert(st2 != NULL);
  137.         assert(best_rating1 != 0 || best_rating2 != 0);
  138.  
  139.         /* Then determine the amount the worst station gets. We do it this way as the
  140.          * best should get a bonus, which in this case is the rounding difference from
  141.          * this calculation. In reality that will mean the bonus will be pretty low.
  142.          * Nevertheless, the best station should always get the most cargo regardless
  143.          * of rounding issues. */
  144.         uint worst_cargo = amount * best_rating2 / (best_rating1 + best_rating2);
  145.         assert(worst_cargo <= (amount - worst_cargo));
  146.  
  147.         /* And then send the cargo to the stations! */
  148.         uint moved = UpdateStationWaiting(st1, type, amount - worst_cargo, source_type, source_id);
  149.         /* These two UpdateStationWaiting's can't be in the statement as then the order
  150.          * of execution would be undefined and that could cause desyncs with callbacks. */
  151.         return moved + UpdateStationWaiting(st2, type, worst_cargo, source_type, source_id);
  152.     }
  153.  
  154.     if (st4 == NULL) {
  155.         /* three stations around, the best three (highest rating) are in st1, st2 and st3 */
  156.         assert(st1 != NULL);
  157.         assert(st2 != NULL);
  158.         assert(st3 != NULL);
  159.         assert(best_rating1 != 0 || best_rating2 != 0 || best_rating3 != 0);
  160.  
  161.         /* Then determine the amount the worst stations get. We do it this way as the
  162.          * best should get a bonus, which in this case is the rounding difference from
  163.          * this calculation. In reality that will mean the bonus will be pretty low.
  164.          * Nevertheless, the best station should always get the most cargo regardless
  165.          * of rounding issues. */
  166.         uint cargo_st3 = amount * best_rating3 / (best_rating1 + best_rating2 + best_rating3);
  167.         assert(cargo_st3 <= (amount - cargo_st3));
  168.  
  169.         uint remaining = amount - cargo_st3;
  170.         uint cargo_st2 = remaining * best_rating2 / (best_rating1 + best_rating2);
  171.         assert(cargo_st2 <= (remaining - cargo_st2));
  172.  
  173.         uint cargo_st1 = remaining - cargo_st2;
  174.         assert(amount == cargo_st1 + cargo_st2 + cargo_st3);
  175.  
  176.         /* And then send the cargo to the stations! */
  177.         uint moved = UpdateStationWaiting(st1, type, cargo_st1, source_type, source_id);
  178.         moved += UpdateStationWaiting(st2, type, cargo_st2, source_type, source_id);
  179.         return moved + UpdateStationWaiting(st3, type, cargo_st3, source_type, source_id);
  180.     }
  181.  
  182.     if (st5 == NULL) {
  183.         /* Four stations around, the best four (highest rating) are in st1, st2, st3 and st4 */
  184.         assert(st1 != NULL);
  185.         assert(st2 != NULL);
  186.         assert(st3 != NULL);
  187.         assert(st4 != NULL);
  188.         assert(best_rating1 != 0 || best_rating2 != 0 || best_rating3 != 0 || best_rating4 != 0);
  189.  
  190.         /* Then determine the amount the worst stations get. We do it this way as the
  191.          * best should get a bonus, which in this case is the rounding difference from
  192.          * this calculation. In reality that will mean the bonus will be pretty low.
  193.          * Nevertheless, the best station should always get the most cargo regardless
  194.          * of rounding issues. */
  195.         uint cargo_st4 = amount * best_rating4 / (best_rating1 + best_rating2 + best_rating3 + best_rating4);
  196.         assert(cargo_st4 <= (amount - cargo_st4));
  197.  
  198.         uint remaining = amount - cargo_st4;
  199.         uint cargo_st3 = remaining * best_rating3 / (best_rating1 + best_rating2 + best_rating3);
  200.         assert(cargo_st3 <= (remaining - cargo_st3));
  201.  
  202.         remaining -= cargo_st3;
  203.         uint cargo_st2 = remaining * best_rating2 / (best_rating1 + best_rating2);
  204.         assert(cargo_st2 <= (remaining - cargo_st2));
  205.  
  206.         uint cargo_st1 = remaining - cargo_st2;
  207.         assert(amount == cargo_st1 + cargo_st2 + cargo_st3 + cargo_st4);
  208.  
  209.         /* And then send the cargo to the stations! */
  210.         uint moved = UpdateStationWaiting(st1, type, cargo_st1, source_type, source_id);
  211.         moved += UpdateStationWaiting(st2, type, cargo_st2, source_type, source_id);
  212.         moved += UpdateStationWaiting(st3, type, cargo_st3, source_type, source_id);
  213.         return moved + UpdateStationWaiting(st4, type, cargo_st4, source_type, source_id);
  214.     }
  215.  
  216.     if (st6 == NULL) {
  217.         /* Five stations around, the best five (highest rating) are in st1, st2, st3, st4 and st5 */
  218.         assert(st1 != NULL);
  219.         assert(st2 != NULL);
  220.         assert(st3 != NULL);
  221.         assert(st4 != NULL);
  222.         assert(st5 != NULL);
  223.         assert(best_rating1 != 0 || best_rating2 != 0 || best_rating3 != 0 || best_rating4 != 0 || best_rating5 != 0);
  224.  
  225.         /* Then determine the amount the worst stations get. We do it this way as the
  226.          * best should get a bonus, which in this case is the rounding difference from
  227.          * this calculation. In reality that will mean the bonus will be pretty low.
  228.          * Nevertheless, the best station should always get the most cargo regardless
  229.          * of rounding issues. */
  230.         uint cargo_st5 = amount * best_rating5 / (best_rating1 + best_rating2 + best_rating3 + best_rating4 + best_rating5);
  231.         assert(cargo_st5 <= (amount - cargo_st5));
  232.  
  233.         uint remaining = amount - cargo_st5;
  234.         uint cargo_st4 = remaining * best_rating4 / (best_rating1 + best_rating2 + best_rating3 + best_rating4);
  235.         assert(cargo_st4 <= (remaining - cargo_st4));
  236.  
  237.         remaining -= cargo_st4;
  238.         uint cargo_st3 = remaining * best_rating3 / (best_rating1 + best_rating2 + best_rating3);
  239.         assert(cargo_st3 <= (remaining - cargo_st3));
  240.  
  241.         remaining -= cargo_st3;
  242.         uint cargo_st2 = remaining * best_rating2 / (best_rating1 + best_rating2);
  243.         assert(cargo_st2 <= (remaining - cargo_st2));
  244.  
  245.         uint cargo_st1 = remaining - cargo_st2;
  246.         assert(amount == cargo_st1 + cargo_st2 + cargo_st3 + cargo_st4 + cargo_st5);
  247.  
  248.         /* And then send the cargo to the stations! */
  249.         uint moved = UpdateStationWaiting(st1, type, cargo_st1, source_type, source_id);
  250.         moved += UpdateStationWaiting(st2, type, cargo_st2, source_type, source_id);
  251.         moved += UpdateStationWaiting(st3, type, cargo_st3, source_type, source_id);
  252.         moved += UpdateStationWaiting(st4, type, cargo_st4, source_type, source_id);
  253.         return moved + UpdateStationWaiting(st5, type, cargo_st5, source_type, source_id);
  254.     }
  255.  
  256.     /* Six stations around, the best six (highest rating) are in st1, st2, st3, st4, st5 and st6 */
  257.     assert(st1 != NULL);
  258.     assert(st2 != NULL);
  259.     assert(st3 != NULL);
  260.     assert(st4 != NULL);
  261.     assert(st5 != NULL);
  262.     assert(st6 != NULL);
  263.     assert(best_rating1 != 0 || best_rating2 != 0 || best_rating3 != 0 || best_rating4 != 0 || best_rating5 != 0 || best_rating6 != 0);
  264.  
  265.     /* Then determine the amount the worst stations get. We do it this way as the
  266.      * best should get a bonus, which in this case is the rounding difference from
  267.      * this calculation. In reality that will mean the bonus will be pretty low.
  268.      * Nevertheless, the best station should always get the most cargo regardless
  269.      * of rounding issues. */
  270.     uint cargo_st6 = amount * best_rating6 / (best_rating1 + best_rating2 + best_rating3 + best_rating4 + best_rating5 + best_rating6);
  271.     assert(cargo_st6 <= (amount - cargo_st6));
  272.  
  273.     uint remaining = amount - cargo_st6;
  274.     uint cargo_st5 = remaining * best_rating5 / (best_rating1 + best_rating2 + best_rating3 + best_rating4 + best_rating5);
  275.     assert(cargo_st5 <= (remaining - cargo_st5));
  276.  
  277.     remaining -= cargo_st5;
  278.     uint cargo_st4 = remaining * best_rating4 / (best_rating1 + best_rating2 + best_rating3 + best_rating4);
  279.     assert(cargo_st4 <= (remaining - cargo_st4));
  280.  
  281.     remaining -= cargo_st4;
  282.     uint cargo_st3 = remaining * best_rating3 / (best_rating1 + best_rating2 + best_rating3);
  283.     assert(cargo_st3 <= (remaining - cargo_st3));
  284.  
  285.     remaining -= cargo_st3;
  286.     uint cargo_st2 = remaining * best_rating2 / (best_rating1 + best_rating2);
  287.     assert(cargo_st2 <= (remaining - cargo_st2));
  288.  
  289.     uint cargo_st1 = remaining - cargo_st2;
  290.     assert(amount == cargo_st1 + cargo_st2 + cargo_st3 + cargo_st4 + cargo_st5 + cargo_st6);
  291.  
  292.     /* And then send the cargo to the stations! */
  293.     uint moved = UpdateStationWaiting(st1, type, cargo_st1, source_type, source_id);
  294.     moved += UpdateStationWaiting(st2, type, cargo_st2, source_type, source_id);
  295.     moved += UpdateStationWaiting(st3, type, cargo_st3, source_type, source_id);
  296.     moved += UpdateStationWaiting(st4, type, cargo_st4, source_type, source_id);
  297.     moved += UpdateStationWaiting(st5, type, cargo_st5, source_type, source_id);
  298.     return moved + UpdateStationWaiting(st6, type, cargo_st6, source_type, source_id);
  299. }

Version history

Revision # Author Created at
p2pn4keww Anonymous 25 Oct 2017, 12:36:08 UTC Diff
pfsmdufv4 Anonymous 24 Oct 2017, 18:35:28 UTC Diff

Comments