Add setting to increase cost/distance of aircraft linkgraph links
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user