Merge remote-tracking branch 'upstream/master'

This commit is contained in:
dP
2025-05-14 18:41:13 +05:00
994 changed files with 38759 additions and 34518 deletions

View File

@@ -2,6 +2,7 @@
#include "../stdafx.h"
#include "demands.h"
#include "../core/math_func.hpp"
#include <queue>
#include "../safeguards.h"
@@ -207,23 +208,26 @@ void DemandCalculator::CalcDemand(LinkGraphJob &job, Tscaler scaler)
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].base.xy, job[to_id].base.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].base.xy, job[to_id].base.xy);
/* Scale distance around base_distance by (mod_dist * (100 / 1024)).
* mod_dist may be > 1024, so clamp result to be non-negative */
scaled_distance = std::max(0, 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. */
@@ -256,7 +260,7 @@ void DemandCalculator::CalcDemand(LinkGraphJob &job, Tscaler scaler)
* @param job Job to calculate the demands for.
*/
DemandCalculator::DemandCalculator(LinkGraphJob &job) :
max_distance(DistanceMaxPlusManhattan(TileXY(0,0), TileXY(Map::MaxX(), Map::MaxY())))
base_distance(IntSqrt(DistanceMaxPlusManhattan(TileXY(0,0), TileXY(Map::MaxX(), Map::MaxY()))))
{
const LinkGraphSettings &settings = job.Settings();
CargoID cargo = job.Cargo();
@@ -264,9 +268,15 @@ DemandCalculator::DemandCalculator(LinkGraphJob &job) :
this->accuracy = settings.accuracy;
this->mod_dist = settings.demand_distance;
if (this->mod_dist > 100) {
/* Increase effect of mod_dist > 100 */
/* Increase effect of mod_dist > 100.
* Quadratic:
* 100 --> 100
* 150 --> 308
* 200 --> 933
* 255 --> 2102
*/
int over100 = this->mod_dist - 100;
this->mod_dist = 100 + over100 * over100;
this->mod_dist = 100 + ((over100 * over100) / 12);
}
switch (settings.GetDistributionType(cargo)) {

View File

@@ -14,9 +14,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<class Tscaler>
void CalcDemand(LinkGraphJob &job, Tscaler scaler);

View File

@@ -115,7 +115,7 @@ void LinkGraphOverlay::RebuildCache()
}
}
if (this->IsPointVisible(pta, &dpi)) {
this->cached_stations.push_back(std::make_pair(from, supply));
this->cached_stations.emplace_back(from, supply);
}
}
}
@@ -314,7 +314,7 @@ void LinkGraphOverlay::DrawContent(Point pta, Point ptb, const LinkProperties &c
GfxDrawLine(pta.x, pta.y + offset_y, ptb.x, ptb.y + offset_y, colour, width, dash);
}
GfxDrawLine(pta.x, pta.y, ptb.x, ptb.y, _colour_gradient[COLOUR_GREY][1], width);
GfxDrawLine(pta.x, pta.y, ptb.x, ptb.y, GetColourGradient(COLOUR_GREY, SHADE_DARKEST), width);
}
/**
@@ -333,9 +333,9 @@ void LinkGraphOverlay::DrawStationDots(const DrawPixelInfo *dpi) const
uint r = width * 2 + width * 2 * std::min(200U, i.second) / 200;
LinkGraphOverlay::DrawVertex(pt.x, pt.y, r,
_colour_gradient[st->owner != OWNER_NONE ?
Company::Get(st->owner)->colour : COLOUR_GREY][5],
_colour_gradient[COLOUR_GREY][1]);
GetColourGradient(st->owner != OWNER_NONE ?
Company::Get(st->owner)->colour : COLOUR_GREY, SHADE_LIGHT),
GetColourGradient(COLOUR_GREY, SHADE_DARKEST));
}
}
@@ -343,7 +343,7 @@ void LinkGraphOverlay::DrawStationDots(const DrawPixelInfo *dpi) const
* Draw a square symbolizing a producer of cargo.
* @param x X coordinate of the middle of the vertex.
* @param y Y coordinate of the middle of the vertex.
* @param size Y and y extend of the vertex.
* @param size x and y extent of the vertex.
* @param colour Colour with which the vertex will be filled.
* @param border_colour Colour for the border of the vertex.
*/
@@ -352,15 +352,10 @@ void LinkGraphOverlay::DrawStationDots(const DrawPixelInfo *dpi) const
size--;
int w1 = size / 2;
int w2 = size / 2 + size % 2;
int borderwidth = ScaleGUITrad(1);
GfxFillRect(x - w1 - borderwidth, y - w1 - borderwidth, x + w2 + borderwidth, y + w2 + borderwidth, border_colour);
GfxFillRect(x - w1, y - w1, x + w2, y + w2, colour);
w1++;
w2++;
GfxDrawLine(x - w1, y - w1, x + w2, y - w1, border_colour);
GfxDrawLine(x - w1, y + w2, x + w2, y + w2, border_colour);
GfxDrawLine(x - w1, y - w1, x - w1, y + w2, border_colour);
GfxDrawLine(x + w2, y - w1, x + w2, y + w2, border_colour);
}
bool LinkGraphOverlay::ShowTooltip(Point pt, TooltipCloseCondition close_cond)
@@ -401,7 +396,7 @@ bool LinkGraphOverlay::ShowTooltip(Point pt, TooltipCloseCondition close_cond)
const auto time = link.time ? back_time ? ((link.time + back_time) / 2) : link.time : back_time;
if (time > 0) {
SetDParam(0, time);
tooltip_extension += GetString(STR_LINKGRAPH_STATS_TOOLTIP_TIME_EXTENSION);
AppendStringInPlace(tooltip_extension, STR_LINKGRAPH_STATS_TOOLTIP_TIME_EXTENSION);
}
SetDParam(0, link.cargo);
SetDParam(1, link.Usage());
@@ -543,11 +538,11 @@ static constexpr NWidgetPart _nested_linkgraph_legend_widgets[] = {
static_assert(WID_LGL_SATURATION_LAST - WID_LGL_SATURATION_FIRST ==
lengthof(LinkGraphOverlay::LINK_COLOURS[0]) - 1);
static WindowDesc _linkgraph_legend_desc(__FILE__, __LINE__,
static WindowDesc _linkgraph_legend_desc(
WDP_AUTO, "toolbar_linkgraph", 0, 0,
WC_LINKGRAPH_LEGEND, WC_NONE,
0,
std::begin(_nested_linkgraph_legend_widgets), std::end(_nested_linkgraph_legend_widgets)
_nested_linkgraph_legend_widgets
);
/**
@@ -555,10 +550,10 @@ static WindowDesc _linkgraph_legend_desc(__FILE__, __LINE__,
*/
void ShowLinkGraphLegend()
{
AllocateWindowDescFront<LinkGraphLegendWindow>(&_linkgraph_legend_desc, 0);
AllocateWindowDescFront<LinkGraphLegendWindow>(_linkgraph_legend_desc, 0);
}
LinkGraphLegendWindow::LinkGraphLegendWindow(WindowDesc *desc, int window_number) : Window(desc)
LinkGraphLegendWindow::LinkGraphLegendWindow(WindowDesc &desc, int window_number) : Window(desc)
{
this->num_cargo = _sorted_cargo_specs.size();
@@ -586,7 +581,7 @@ void LinkGraphLegendWindow::SetOverlay(std::shared_ptr<LinkGraphOverlay> overlay
}
}
void LinkGraphLegendWindow::UpdateWidgetSize(WidgetID widget, Dimension *size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension *fill, [[maybe_unused]] Dimension *resize)
void LinkGraphLegendWindow::UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize)
{
if (IsInsideMM(widget, WID_LGL_SATURATION_FIRST, WID_LGL_SATURATION_LAST + 1)) {
StringID str = STR_NULL;
@@ -601,7 +596,7 @@ void LinkGraphLegendWindow::UpdateWidgetSize(WidgetID widget, Dimension *size, [
Dimension dim = GetStringBoundingBox(str, FS_SMALL);
dim.width += padding.width;
dim.height += padding.height;
*size = maxdim(*size, dim);
size = maxdim(size, dim);
}
}
if (IsInsideMM(widget, WID_LGL_CARGO_FIRST, WID_LGL_CARGO_LAST + 1)) {
@@ -609,7 +604,7 @@ void LinkGraphLegendWindow::UpdateWidgetSize(WidgetID widget, Dimension *size, [
Dimension dim = GetStringBoundingBox(cargo->abbrev, FS_SMALL);
dim.width += padding.width;
dim.height += padding.height;
*size = maxdim(*size, dim);
size = maxdim(size, dim);
}
}

View File

@@ -55,7 +55,7 @@ public:
* @param scale Desired thickness of lines and size of station dots.
*/
LinkGraphOverlay(Window *w, WidgetID wid, CargoTypes cargo_mask, CompanyMask company_mask, uint scale) :
window(w), widget_id(wid), cargo_mask(cargo_mask), company_mask(company_mask), scale(scale)
window(w), widget_id(wid), cargo_mask(cargo_mask), company_mask(company_mask), scale(scale), dirty(true)
{}
void Draw(const DrawPixelInfo *dpi);
@@ -105,10 +105,10 @@ void ShowLinkGraphLegend();
*/
struct LinkGraphLegendWindow : Window {
public:
LinkGraphLegendWindow(WindowDesc *desc, int window_number);
LinkGraphLegendWindow(WindowDesc &desc, int window_number);
void SetOverlay(std::shared_ptr<LinkGraphOverlay> overlay);
void UpdateWidgetSize(WidgetID widget, Dimension *size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension *fill, [[maybe_unused]] Dimension *resize) override;
void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override;
void DrawWidget(const Rect &r, WidgetID widget) const override;
bool OnTooltip([[maybe_unused]] Point pt, WidgetID widget, TooltipCloseCondition close_cond) override;
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override;

View File

@@ -19,7 +19,7 @@ static const LinkGraphJobID INVALID_LINK_GRAPH_JOB = UINT16_MAX;
typedef uint16_t NodeID;
static const NodeID INVALID_NODE = UINT16_MAX;
enum DistributionType : byte {
enum DistributionType : uint8_t {
DT_BEGIN = 0,
DT_MIN = 0,
DT_MANUAL = 0, ///< Manual distribution. No link graph calculations are run.

View File

@@ -101,7 +101,7 @@ public:
*/
EdgeAnnotation &operator[](NodeID to)
{
auto it = std::find_if(this->edges.begin(), this->edges.end(), [=] (const EdgeAnnotation &e) { return e.base.dest_node == to; });
auto it = std::ranges::find_if(this->edges, [=] (const EdgeAnnotation &e) { return e.base.dest_node == to; });
assert(it != this->edges.end());
return *it;
}
@@ -113,7 +113,7 @@ public:
*/
const EdgeAnnotation &operator[](NodeID to) const
{
auto it = std::find_if(this->edges.begin(), this->edges.end(), [=] (const EdgeAnnotation &e) { return e.base.dest_node == to; });
auto it = std::ranges::find_if(this->edges, [=] (const EdgeAnnotation &e) { return e.base.dest_node == to; });
assert(it != this->edges.end());
return *it;
}
@@ -346,14 +346,12 @@ public:
protected:
/**
/*
* Some boundaries to clamp against in order to avoid integer overflows.
*/
enum PathCapacityBoundaries {
PATH_CAP_MULTIPLIER = 16,
PATH_CAP_MIN_FREE = (INT_MIN + 1) / PATH_CAP_MULTIPLIER,
PATH_CAP_MAX_FREE = (INT_MAX - 1) / PATH_CAP_MULTIPLIER
};
static constexpr int PATH_CAP_MULTIPLIER = 16;
static constexpr int PATH_CAP_MIN_FREE = (INT_MIN + 1) / PATH_CAP_MULTIPLIER;
static constexpr int PATH_CAP_MAX_FREE = (INT_MAX - 1) / PATH_CAP_MULTIPLIER;
uint distance; ///< Sum(distance of all legs up to this one).
uint capacity; ///< This capacity is min(capacity) fom all edges.

View File

@@ -86,9 +86,9 @@ void LinkGraphSchedule::JoinNext()
*/
/* static */ void LinkGraphSchedule::Run(LinkGraphJob *job)
{
for (uint i = 0; i < lengthof(instance.handlers); ++i) {
for (const auto &handler : instance.handlers) {
if (job->IsJobAborted()) return;
instance.handlers[i]->Run(*job);
handler->Run(*job);
}
/*
@@ -143,12 +143,12 @@ void LinkGraphSchedule::ShiftDates(TimerGameEconomy::Date interval)
*/
LinkGraphSchedule::LinkGraphSchedule()
{
this->handlers[0] = new InitHandler;
this->handlers[1] = new DemandHandler;
this->handlers[2] = new MCFHandler<MCF1stPass>;
this->handlers[3] = new FlowMapper(false);
this->handlers[4] = new MCFHandler<MCF2ndPass>;
this->handlers[5] = new FlowMapper(true);
this->handlers[0] = std::make_unique<InitHandler>();
this->handlers[1] = std::make_unique<DemandHandler>();
this->handlers[2] = std::make_unique<MCFHandler<MCF1stPass>>();
this->handlers[3] = std::make_unique<FlowMapper>(false);
this->handlers[4] = std::make_unique<MCFHandler<MCF2ndPass>>();
this->handlers[5] = std::make_unique<FlowMapper>(true);
}
/**
@@ -157,9 +157,6 @@ LinkGraphSchedule::LinkGraphSchedule()
LinkGraphSchedule::~LinkGraphSchedule()
{
this->Clear();
for (uint i = 0; i < lengthof(this->handlers); ++i) {
delete this->handlers[i];
}
}
/**

View File

@@ -42,7 +42,7 @@ private:
friend SaveLoadTable GetLinkGraphScheduleDesc();
protected:
ComponentHandler *handlers[6]; ///< Handlers to be run for each job.
std::array<std::unique_ptr<ComponentHandler>, 6> handlers{}; ///< Handlers to be run for each job.
GraphList schedule; ///< Queue for new jobs.
JobList running; ///< Currently running jobs.

View File

@@ -70,8 +70,6 @@ LinkRefresher::LinkRefresher(Vehicle *vehicle, HopSet *seen_hops, bool allow_mer
vehicle(vehicle), seen_hops(seen_hops), cargo(INVALID_CARGO), allow_merge(allow_merge),
is_full_loading(is_full_loading)
{
memset(this->capacities, 0, sizeof(this->capacities));
/* Assemble list of capacities and set last loading stations to 0. */
for (Vehicle *v = this->vehicle; v != nullptr; v = v->Next()) {
this->refit_capacities.push_back(RefitDesc(v->cargo_type, v->cargo_cap, v->refit_cap));
@@ -102,7 +100,7 @@ bool LinkRefresher::HandleRefit(CargoID refit_cargo)
/* Back up the vehicle's cargo type */
CargoID temp_cid = v->cargo_type;
byte temp_subtype = v->cargo_subtype;
uint8_t temp_subtype = v->cargo_subtype;
v->cargo_type = this->cargo;
v->cargo_subtype = GetBestFittingSubType(v, v, this->cargo);

View File

@@ -78,7 +78,7 @@ protected:
typedef std::set<Hop> HopSet;
Vehicle *vehicle; ///< Vehicle for which the links should be refreshed.
uint capacities[NUM_CARGO]; ///< Current added capacities per cargo ID in the consist.
CargoArray capacities{}; ///< Current added capacities per cargo ID in the consist.
RefitList refit_capacities; ///< Current state of capacity remaining from previous refits versus overall capacity per vehicle in the consist.
HopSet *seen_hops; ///< Hops already seen. If the same hop is seen twice we stop the algorithm. This is shared between all Refreshers of the same run.
CargoID cargo; ///< Cargo given in last refit order.