Add setting to increase cost/distance of aircraft linkgraph links

pull/352/head
Jonathan G Rennison 2 years ago
parent ba97d0a827
commit 89181ea9fd

@ -2309,6 +2309,9 @@ STR_CONFIG_SETTING_DEMAND_SIZE_HELPTEXT :Setting this to
STR_CONFIG_SETTING_SHORT_PATH_SATURATION :Saturation of short paths before using high-capacity paths: {STRING2}
STR_CONFIG_SETTING_SHORT_PATH_SATURATION_HELPTEXT :Frequently there are multiple paths between two given stations. Cargodist will saturate the shortest path first, then use the second shortest path until that is saturated and so on. Saturation is determined by an estimation of capacity and planned usage. Once it has saturated all paths, if there is still demand left, it will overload all paths, prefering the ones with high capacity. Most of the time the algorithm will not estimate the capacity accurately, though. This setting allows you to specify up to which percentage a shorter path must be saturated in the first pass before choosing the next longer one. Set it to less than 100% to avoid overcrowded stations in case of overestimated capacity.
STR_CONFIG_SETTING_AIRCRAFT_PATH_COST :Scale distance of paths which use aircraft: {STRING2}
STR_CONFIG_SETTING_AIRCRAFT_PATH_COST_HELPTEXT :This scales the cost (distance metric) of paths which use aircraft, such that they appear longer/less direct than they actually are. The reduces the tendency for direct routes using aircraft to become heavily overloaded.
STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY :Speed units: {STRING2}
STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_HELPTEXT :Whenever a speed is shown in the user interface, show it in the selected units
###length 4

@ -41,6 +41,7 @@ inline void LinkGraph::BaseEdge::Init()
this->usage = 0;
this->last_unrestricted_update = INVALID_DATE;
this->last_restricted_update = INVALID_DATE;
this->last_aircraft_update = INVALID_DATE;
this->next_edge = INVALID_NODE;
}
@ -59,6 +60,7 @@ void LinkGraph::ShiftDates(int interval)
BaseEdge &edge = this->edges[node1][node2];
if (edge.last_unrestricted_update != INVALID_DATE) edge.last_unrestricted_update += interval;
if (edge.last_restricted_update != INVALID_DATE) edge.last_restricted_update += interval;
if (edge.last_aircraft_update != INVALID_DATE) edge.last_aircraft_update += interval;
}
}
}
@ -199,6 +201,7 @@ void LinkGraph::Node::AddEdge(NodeID to, uint capacity, uint usage, EdgeUpdateMo
first.next_edge = to;
if (mode & EUM_UNRESTRICTED) edge.last_unrestricted_update = _date;
if (mode & EUM_RESTRICTED) edge.last_restricted_update = _date;
if (mode & EUM_AIRCRAFT) edge.last_aircraft_update = _date;
}
/**
@ -230,6 +233,7 @@ void LinkGraph::Node::RemoveEdge(NodeID to)
edge.capacity = 0;
edge.last_unrestricted_update = INVALID_DATE;
edge.last_restricted_update = INVALID_DATE;
edge.last_aircraft_update = INVALID_DATE;
edge.usage = 0;
NodeID prev = this->index;
@ -270,6 +274,7 @@ void LinkGraph::Edge::Update(uint capacity, uint usage, EdgeUpdateMode mode)
}
if (mode & EUM_UNRESTRICTED) this->edge.last_unrestricted_update = _date;
if (mode & EUM_RESTRICTED) this->edge.last_restricted_update = _date;
if (mode & EUM_AIRCRAFT) this->edge.last_aircraft_update = _date;
}
/**

@ -72,6 +72,7 @@ public:
uint usage; ///< Usage of the link.
Date last_unrestricted_update; ///< When the unrestricted part of the link was last updated.
Date last_restricted_update; ///< When the restricted part of the link was last updated.
Date last_aircraft_update; ///< When aircraft capacity of the link was last updated.
NodeID next_edge; ///< Destination of next valid edge starting at the same source node.
void Init();
};
@ -117,6 +118,12 @@ public:
*/
Date LastRestrictedUpdate() const { return this->edge.last_restricted_update; }
/**
* Get the date of the last update to the edge's aircraft capacity.
* @return Last update.
*/
Date LastAircraftUpdate() const { return this->edge.last_aircraft_update; }
/**
* Get the date of the last update to any part of the edge's capacity.
* @return Last update.
@ -307,6 +314,7 @@ public:
void Update(uint capacity, uint usage, EdgeUpdateMode mode);
void Restrict() { this->edge.last_unrestricted_update = INVALID_DATE; }
void Release() { this->edge.last_restricted_update = INVALID_DATE; }
void ClearAircraft() { this->edge.last_aircraft_update = INVALID_DATE; }
};
/**

@ -48,6 +48,7 @@ enum EdgeUpdateMode {
EUM_REFRESH = 1 << 1, ///< Refresh capacity.
EUM_RESTRICTED = 1 << 2, ///< Use restricted link.
EUM_UNRESTRICTED = 1 << 3, ///< Use unrestricted link.
EUM_AIRCRAFT = 1 << 4, ///< Capacity is an aircraft link.
};
DECLARE_ENUM_AS_BIT_SET(EdgeUpdateMode)

@ -284,6 +284,8 @@ void MultiCommodityFlow::Dijkstra(NodeID source_node, PathVector &paths)
this->job.path_allocator.SetParameters(sizeof(Tannotation), (8192 - 32) / sizeof(Tannotation));
const uint16 aircraft_link_scale = this->job.Settings().aircraft_link_scale;
for (NodeID node = 0; node < size; ++node) {
Tannotation *anno = new (this->job.path_allocator.Allocate()) Tannotation(node, node == source_node);
anno->UpdateAnnotation();
@ -310,6 +312,10 @@ void MultiCommodityFlow::Dijkstra(NodeID source_node, PathVector &paths)
}
/* punish in-between stops a little */
uint distance = DistanceMaxPlusManhattan(this->job[from].XY(), this->job[to].XY()) + 1;
if (edge.LastAircraftUpdate() != INVALID_DATE && aircraft_link_scale != 100) {
distance *= aircraft_link_scale;
distance /= 100;
}
Tannotation *dest = static_cast<Tannotation *>(paths[to]);
if (dest->IsBetter(source, capacity, capacity - edge.Flow(), distance)) {
if (dest->GetAnnosSetFlag()) annos.erase(AnnoSetItem<Tannotation>(dest));

@ -55,7 +55,10 @@
HopSet seen_hops;
LinkRefresher refresher(v, &seen_hops, allow_merge, is_full_loading, iter_cargo_mask);
refresher.RefreshLinks(first, first, (iter_cargo_mask & have_cargo_mask) ? 1 << HAS_CARGO : 0);
uint8 flags = 0;
if (iter_cargo_mask & have_cargo_mask) flags |= 1 << HAS_CARGO;
if (v->type == VEH_AIRCRAFT) flags |= 1 << AIRCRAFT;
refresher.RefreshLinks(first, first, flags);
}
cargo_mask &= ~iter_cargo_mask;
@ -234,7 +237,7 @@ const Order *LinkRefresher::PredictNextOrder(const Order *cur, const Order *next
* @param cur Last stop where the consist could interact with cargo.
* @param next Next order to be processed.
*/
void LinkRefresher::RefreshStats(const Order *cur, const Order *next)
void LinkRefresher::RefreshStats(const Order *cur, const Order *next, uint8 flags)
{
StationID next_station = next->GetDestination();
Station *st = Station::GetIfValid(cur->GetDestination());
@ -257,6 +260,8 @@ void LinkRefresher::RefreshStats(const Order *cur, const Order *next)
EdgeUpdateMode restricted_mode = (cur->GetCargoLoadType(c) & OLFB_NO_LOAD) == 0 ?
EUM_UNRESTRICTED : EUM_RESTRICTED;
if (HasBit(flags, AIRCRAFT)) restricted_mode |= EUM_AIRCRAFT;
/* If the vehicle is currently full loading, increase the capacities at the station
* where it is loading by an estimate of what it would have transported if it wasn't
* loading. Don't do that if the vehicle has been waiting for longer than the entire
@ -347,7 +352,7 @@ void LinkRefresher::RefreshLinks(const Order *cur, const Order *next, uint8 flag
if (cur->IsType(OT_GOTO_STATION) || cur->IsType(OT_IMPLICIT)) {
if (cur->CanLeaveWithCargo(HasBit(flags, HAS_CARGO), FindFirstBit(this->cargo_mask))) {
SetBit(flags, HAS_CARGO);
this->RefreshStats(cur, next);
this->RefreshStats(cur, next, flags);
} else {
ClrBit(flags, HAS_CARGO);
}

@ -34,6 +34,7 @@ protected:
WAS_REFIT, ///< Consist was refit since the last stop where it could interact with cargo.
RESET_REFIT, ///< Consist had a chance to load since the last refit and the refit capacities can be reset.
IN_AUTOREFIT, ///< Currently doing an autorefit loop. Ignore the first autorefit order.
AIRCRAFT, ///< Vehicle is an aircraft.
};
/**
@ -93,7 +94,7 @@ protected:
bool HandleRefit(CargoID refit_cargo);
void ResetRefit();
void RefreshStats(const Order *cur, const Order *next);
void RefreshStats(const Order *cur, const Order *next, uint8 flags);
const Order *PredictNextOrder(const Order *cur, const Order *next, uint8 flags, uint num_hops = 0);
void RefreshLinks(const Order *cur, const Order *next, uint8 flags, uint num_hops = 0);

@ -160,6 +160,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_EXTRA_SIGNAL_TYPES, XSCF_NULL, 1, 1, "extra_signal_types", nullptr, nullptr, nullptr },
{ XSLFI_BANKRUPTCY_EXTRA, XSCF_NULL, 1, 1, "bankruptcy_extra", nullptr, nullptr, nullptr },
{ XSLFI_OBJECT_GROUND_TYPES, XSCF_NULL, 1, 1, "object_ground_types", nullptr, nullptr, nullptr },
{ XSLFI_LINKGRAPH_AIRCRAFT, XSCF_NULL, 1, 1, "linkgraph_aircraft", nullptr, nullptr, nullptr },
{ XSLFI_SCRIPT_INT64, XSCF_NULL, 1, 1, "script_int64", nullptr, nullptr, nullptr },
{ XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker
};

@ -114,6 +114,7 @@ enum SlXvFeatureIndex {
XSLFI_EXTRA_SIGNAL_TYPES, ///< Extra signal types
XSLFI_BANKRUPTCY_EXTRA, ///< Extra company bankruptcy fields
XSLFI_OBJECT_GROUND_TYPES, ///< Object ground types
XSLFI_LINKGRAPH_AIRCRAFT, ///< Link graph last aircraft update field and aircraft link scaling setting
XSLFI_SCRIPT_INT64, ///< See: SLV_SCRIPT_INT64

@ -128,6 +128,7 @@ static const SaveLoad _edge_desc[] = {
SLE_VAR(Edge, usage, SLE_UINT32),
SLE_VAR(Edge, last_unrestricted_update, SLE_INT32),
SLE_CONDVAR(Edge, last_restricted_update, SLE_INT32, SLV_187, SL_MAX_VERSION),
SLE_CONDVAR_X(Edge, last_aircraft_update, SLE_INT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_AIRCRAFT)),
SLE_VAR(Edge, next_edge, SLE_UINT16),
};

@ -2204,6 +2204,7 @@ static SettingsContainer &GetSettingsTree()
cdist->Add(new SettingEntry("linkgraph.demand_size"));
cdist->Add(new SettingEntry("linkgraph.short_path_saturation"));
cdist->Add(new SettingEntry("linkgraph.recalc_not_scaled_by_daylength"));
cdist->Add(new SettingEntry("linkgraph.aircraft_link_scale"));
}
SettingsPage *treedist = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TREES));
{

@ -691,6 +691,7 @@ struct LinkGraphSettings {
uint8 demand_size; ///< influence of supply ("station size") on the demand function
uint8 demand_distance; ///< influence of distance between stations on the demand function
uint8 short_path_saturation; ///< percentage up to which short paths are saturated before saturating most capacious paths
uint16 aircraft_link_scale; ///< scale effective distance of aircraft links
inline DistributionType GetDistributionType(CargoID cargo) const {
if (this->distribution_per_cargo[cargo] != DT_PER_CARGO_DEFAULT) return this->distribution_per_cargo[cargo];

@ -4124,6 +4124,9 @@ void DeleteStaleLinks(Station *from)
++it; // Do that before removing the edge. Anything else may crash.
assert(_date >= edge.LastUpdate());
uint timeout = std::max<uint>((LinkGraph::MIN_TIMEOUT_DISTANCE + (DistanceManhattan(from->xy, to->xy) >> 3)) / _settings_game.economy.day_length_factor, 1);
if (edge.LastAircraftUpdate() != INVALID_DATE && (uint)(_date - edge.LastAircraftUpdate()) > timeout) {
edge.ClearAircraft();
}
if ((uint)(_date - edge.LastUpdate()) > timeout) {
bool updated = false;

@ -1226,6 +1226,18 @@ str = STR_CONFIG_SETTING_SHORT_PATH_SATURATION
strval = STR_CONFIG_SETTING_PERCENTAGE
strhelp = STR_CONFIG_SETTING_SHORT_PATH_SATURATION_HELPTEXT
[SDT_VAR]
var = linkgraph.aircraft_link_scale
type = SLE_UINT16
def = 100
min = 100
max = 1000
interval = 50
str = STR_CONFIG_SETTING_AIRCRAFT_PATH_COST
strval = STR_CONFIG_SETTING_PERCENTAGE
strhelp = STR_CONFIG_SETTING_AIRCRAFT_PATH_COST_HELPTEXT
extver = SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_AIRCRAFT, 1, 1)
[SDT_VAR]
var = economy.old_town_cargo_factor
type = SLE_INT8

@ -3148,8 +3148,10 @@ static void VehicleIncreaseStats(const Vehicle *front)
* among the wagons in that case.
* As usage is not such an important figure anyway we just
* ignore the additional cargo then.*/
EdgeUpdateMode restricted_mode = EUM_INCREASE;
if (v->type == VEH_AIRCRAFT) restricted_mode |= EUM_AIRCRAFT;
IncreaseStats(Station::Get(last_loading_station), v->cargo_type, front->last_station_visited, v->refit_cap,
std::min<uint>(v->refit_cap, v->cargo.StoredCount()), EUM_INCREASE);
std::min<uint>(v->refit_cap, v->cargo.StoredCount()), restricted_mode);
}
}
}

Loading…
Cancel
Save