From 3d0498950778ff88ef8cd5816aa2c60ddb4bef4a Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Tue, 9 Apr 2024 23:35:21 +0100 Subject: [PATCH] Link graph: Change distance scaling algorithm in demand scaler Fix erratic scaling and increase effect at large setting values --- src/linkgraph/demands.cpp | 28 +++++++++++++++------------- src/linkgraph/demands.h | 6 +++--- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/linkgraph/demands.cpp b/src/linkgraph/demands.cpp index 1ea8a547ad..7728a9edd7 100644 --- a/src/linkgraph/demands.cpp +++ b/src/linkgraph/demands.cpp @@ -308,23 +308,26 @@ void DemandCalculator::CalcDemand(LinkGraphJob &job, const std::vector &re int32_t supply = scaler.EffectiveSupply(job[from_id], job[to_id]); assert(supply > 0); - /* Scale the distance by mod_dist around max_distance */ - int32_t distance = this->max_distance - (this->max_distance - - (int32_t)DistanceMaxPlusManhattan(job[from_id].XY(), job[to_id].XY())) * - this->mod_dist / 100; + constexpr int32_t divisor_scale = 16; + + int32_t scaled_distance = this->base_distance; + if (this->mod_dist > 0) { + const int32_t distance = DistanceMaxPlusManhattan(job[from_id].XY(), job[to_id].XY()); + /* Scale distance around base_distance by (mod_dist * (100 / 1024)). + * Note that this means that the distance range is always compressed because mod_dist <= 1024. */ + scaled_distance = this->base_distance + (((distance - this->base_distance) * this->mod_dist) / 1024); + } /* Scale the accuracy by distance around accuracy / 2 */ - int32_t divisor = this->accuracy * (this->mod_dist - 50) / 100 + - this->accuracy * distance / this->max_distance + 1; - - assert(divisor > 0); + const int32_t divisor = divisor_scale + ((this->accuracy * scaled_distance * divisor_scale) / (this->base_distance * 2)); + assert(divisor >= divisor_scale); uint demand_forw = 0; - if (divisor <= supply) { + if (divisor <= (supply * divisor_scale)) { /* At first only distribute demand if * effective supply / accuracy divisor >= 1 * Others are too small or too far away to be considered. */ - demand_forw = supply / divisor; + demand_forw = (supply * divisor_scale) / divisor; } else if (++chance > this->accuracy * num_demands * num_supplies) { /* After some trying, if there is still supply left, distribute * demand also to other nodes. */ @@ -410,7 +413,7 @@ void DemandCalculator::CalcMinimisedDistanceDemand(LinkGraphJob &job, const std: * @param job Job to calculate the demands for. */ DemandCalculator::DemandCalculator(LinkGraphJob &job) : - max_distance(DistanceMaxPlusManhattan(TileXY(0,0), TileXY(MapMaxX(), MapMaxY()))) + base_distance(IntSqrt(DistanceMaxPlusManhattan(TileXY(0,0), TileXY(MapMaxX(), MapMaxY())))) { const LinkGraphSettings &settings = job.Settings(); CargoID cargo = job.Cargo(); @@ -419,8 +422,7 @@ DemandCalculator::DemandCalculator(LinkGraphJob &job) : this->mod_dist = settings.demand_distance; if (this->mod_dist > 100) { /* Increase effect of mod_dist > 100 */ - int over100 = this->mod_dist - 100; - this->mod_dist = 100 + over100 * over100; + this->mod_dist = 100 + ((this->mod_dist - 100) * 4); } if (settings.GetDistributionType(cargo) == DT_MANUAL) return; diff --git a/src/linkgraph/demands.h b/src/linkgraph/demands.h index 1a3798972a..b1879b7b4d 100644 --- a/src/linkgraph/demands.h +++ b/src/linkgraph/demands.h @@ -15,9 +15,9 @@ public: DemandCalculator(LinkGraphJob &job); private: - int32_t max_distance; ///< Maximum distance possible on the map. - int32_t mod_dist; ///< Distance modifier, determines how much demands decrease with distance. - int32_t accuracy; ///< Accuracy of the calculation. + int32_t base_distance; ///< Base distance for scaling purposes. + int32_t mod_dist; ///< Distance modifier, determines how much demands decrease with distance. + int32_t accuracy; ///< Accuracy of the calculation. template void CalcDemand(LinkGraphJob &job, const std::vector &reachable_nodes, Tscaler scaler);