mirror of https://github.com/OpenTTD/OpenTTD
Change: Deliver cargo to the closest industry first (#9536)
parent
e68bf58989
commit
36bee83864
|
@ -149,9 +149,9 @@ void AddCargoDelivery(CargoID cargo_type, CompanyID company, uint32 amount, Sour
|
||||||
if (iter != _cargo_deliveries.end()) iter->second += amount;
|
if (iter != _cargo_deliveries.end()) iter->second += amount;
|
||||||
|
|
||||||
/* Industry delivery. */
|
/* Industry delivery. */
|
||||||
for (Industry *ind : st->industries_near) {
|
for (const auto &i : st->industries_near) {
|
||||||
if (ind->index != dest) continue;
|
if (i.industry->index != dest) continue;
|
||||||
CargoMonitorID num = EncodeCargoIndustryMonitor(company, cargo_type, ind->index);
|
CargoMonitorID num = EncodeCargoIndustryMonitor(company, cargo_type, i.industry->index);
|
||||||
CargoMonitorMap::iterator iter = _cargo_deliveries.find(num);
|
CargoMonitorMap::iterator iter = _cargo_deliveries.find(num);
|
||||||
if (iter != _cargo_deliveries.end()) iter->second += amount;
|
if (iter != _cargo_deliveries.end()) iter->second += amount;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1040,9 +1040,10 @@ static uint DeliverGoodsToIndustry(const Station *st, CargoID cargo_type, uint n
|
||||||
|
|
||||||
uint accepted = 0;
|
uint accepted = 0;
|
||||||
|
|
||||||
for (Industry *ind : st->industries_near) {
|
for (const auto &i : st->industries_near) {
|
||||||
if (num_pieces == 0) break;
|
if (num_pieces == 0) break;
|
||||||
|
|
||||||
|
Industry *ind = i.industry;
|
||||||
if (ind->index == source) continue;
|
if (ind->index == source) continue;
|
||||||
|
|
||||||
uint cargo_index;
|
uint cargo_index;
|
||||||
|
|
|
@ -199,7 +199,7 @@ Industry::~Industry()
|
||||||
CargoPacket::InvalidateAllFrom(ST_INDUSTRY, this->index);
|
CargoPacket::InvalidateAllFrom(ST_INDUSTRY, this->index);
|
||||||
|
|
||||||
for (Station *st : this->stations_near) {
|
for (Station *st : this->stations_near) {
|
||||||
st->industries_near.erase(this);
|
st->RemoveIndustryToDeliver(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1701,15 +1701,14 @@ static void PopulateStationsNearby(Industry *ind)
|
||||||
/* Industry has a neutral station. Use it and ignore any other nearby stations. */
|
/* Industry has a neutral station. Use it and ignore any other nearby stations. */
|
||||||
ind->stations_near.insert(ind->neutral_station);
|
ind->stations_near.insert(ind->neutral_station);
|
||||||
ind->neutral_station->industries_near.clear();
|
ind->neutral_station->industries_near.clear();
|
||||||
ind->neutral_station->industries_near.insert(ind);
|
ind->neutral_station->industries_near.insert(IndustryListEntry{0, ind});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ForAllStationsAroundTiles(ind->location, [ind](Station *st, TileIndex tile) {
|
ForAllStationsAroundTiles(ind->location, [ind](Station *st, TileIndex tile) {
|
||||||
if (!IsTileType(tile, MP_INDUSTRY) || GetIndustryIndex(tile) != ind->index) return false;
|
if (!IsTileType(tile, MP_INDUSTRY) || GetIndustryIndex(tile) != ind->index) return false;
|
||||||
ind->stations_near.insert(st);
|
st->AddIndustryToDeliver(ind, tile);
|
||||||
st->AddIndustryToDeliver(ind);
|
return false;
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3069,7 +3068,8 @@ extern const TileTypeProcs _tile_type_industry_procs = {
|
||||||
TerraformTile_Industry, // terraform_tile_proc
|
TerraformTile_Industry, // terraform_tile_proc
|
||||||
};
|
};
|
||||||
|
|
||||||
bool IndustryCompare::operator() (const Industry *lhs, const Industry *rhs) const
|
bool IndustryCompare::operator() (const IndustryListEntry &lhs, const IndustryListEntry &rhs) const
|
||||||
{
|
{
|
||||||
return lhs->index < rhs->index;
|
/* Compare by distance first and use index as a tiebreaker. */
|
||||||
|
return std::tie(lhs.distance, lhs.industry->index) < std::tie(rhs.distance, rhs.industry->index);
|
||||||
}
|
}
|
||||||
|
|
|
@ -357,12 +357,25 @@ Rect Station::GetCatchmentRect() const
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add nearby industry to station's industries_near list if it accepts cargo.
|
* Add nearby industry to station's industries_near list if it accepts cargo.
|
||||||
* @param ind Industry
|
* For industries that are already on the list update distance if it's closer.
|
||||||
|
* @param ind Industry
|
||||||
|
* @param tile Tile of the industry to measure distance to.
|
||||||
*/
|
*/
|
||||||
void Station::AddIndustryToDeliver(Industry *ind)
|
void Station::AddIndustryToDeliver(Industry *ind, TileIndex tile)
|
||||||
{
|
{
|
||||||
/* Don't check further if this industry is already in the list */
|
/* Using DistanceMax to get about the same order as with previously used CircularTileSearch. */
|
||||||
if (this->industries_near.find(ind) != this->industries_near.end()) return;
|
uint distance = DistanceMax(this->xy, tile);
|
||||||
|
|
||||||
|
/* Don't check further if this industry is already in the list but update the distance if it's closer */
|
||||||
|
auto pos = std::find_if(this->industries_near.begin(), this->industries_near.end(), [&](const IndustryListEntry &e) { return e.industry->index == ind->index; });
|
||||||
|
if (pos != this->industries_near.end()) {
|
||||||
|
if (pos->distance > distance) {
|
||||||
|
auto node = this->industries_near.extract(pos);
|
||||||
|
node.value().distance = distance;
|
||||||
|
this->industries_near.insert(std::move(node));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Include only industries that can accept cargo */
|
/* Include only industries that can accept cargo */
|
||||||
uint cargo_index;
|
uint cargo_index;
|
||||||
|
@ -371,9 +384,21 @@ void Station::AddIndustryToDeliver(Industry *ind)
|
||||||
}
|
}
|
||||||
if (cargo_index >= lengthof(ind->accepts_cargo)) return;
|
if (cargo_index >= lengthof(ind->accepts_cargo)) return;
|
||||||
|
|
||||||
this->industries_near.insert(ind);
|
this->industries_near.insert(IndustryListEntry{distance, ind});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove nearby industry from station's industries_near list.
|
||||||
|
* @param ind Industry
|
||||||
|
*/
|
||||||
|
void Station::RemoveIndustryToDeliver(Industry *ind) {
|
||||||
|
auto pos = std::find_if(this->industries_near.begin(), this->industries_near.end(), [&](const IndustryListEntry &e) { return e.industry->index == ind->index; });
|
||||||
|
if (pos != this->industries_near.end()) {
|
||||||
|
this->industries_near.erase(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove this station from the nearby stations lists of all towns and industries.
|
* Remove this station from the nearby stations lists of all towns and industries.
|
||||||
*/
|
*/
|
||||||
|
@ -423,11 +448,11 @@ void Station::RecomputeCatchment()
|
||||||
}
|
}
|
||||||
/* The industry's stations_near may have been computed before its neutral station was built so clear and re-add here. */
|
/* The industry's stations_near may have been computed before its neutral station was built so clear and re-add here. */
|
||||||
for (Station *st : this->industry->stations_near) {
|
for (Station *st : this->industry->stations_near) {
|
||||||
st->industries_near.erase(this->industry);
|
st->RemoveIndustryToDeliver(this->industry);
|
||||||
}
|
}
|
||||||
this->industry->stations_near.clear();
|
this->industry->stations_near.clear();
|
||||||
this->industry->stations_near.insert(this);
|
this->industry->stations_near.insert(this);
|
||||||
this->industries_near.insert(this->industry);
|
this->industries_near.insert(IndustryListEntry{0, this->industry});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,7 +487,7 @@ void Station::RecomputeCatchment()
|
||||||
i->stations_near.insert(this);
|
i->stations_near.insert(this);
|
||||||
|
|
||||||
/* Add if we can deliver to this industry as well */
|
/* Add if we can deliver to this industry as well */
|
||||||
this->AddIndustryToDeliver(i);
|
this->AddIndustryToDeliver(i, tile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -437,11 +437,18 @@ private:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IndustryCompare {
|
struct IndustryListEntry {
|
||||||
bool operator() (const Industry *lhs, const Industry *rhs) const;
|
uint distance;
|
||||||
|
Industry *industry;
|
||||||
|
|
||||||
|
bool operator== (const IndustryListEntry &other) const { return this->distance == other.distance && this->industry == other.industry; };
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::set<Industry *, IndustryCompare> IndustryList;
|
struct IndustryCompare {
|
||||||
|
bool operator() (const IndustryListEntry &lhs, const IndustryListEntry &rhs) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::set<IndustryListEntry, IndustryCompare> IndustryList;
|
||||||
|
|
||||||
/** Station data structure */
|
/** Station data structure */
|
||||||
struct Station FINAL : SpecializedStation<Station, false> {
|
struct Station FINAL : SpecializedStation<Station, false> {
|
||||||
|
@ -500,7 +507,8 @@ public:
|
||||||
uint GetCatchmentRadius() const;
|
uint GetCatchmentRadius() const;
|
||||||
Rect GetCatchmentRect() const;
|
Rect GetCatchmentRect() const;
|
||||||
bool CatchmentCoversTown(TownID t) const;
|
bool CatchmentCoversTown(TownID t) const;
|
||||||
void AddIndustryToDeliver(Industry *ind);
|
void AddIndustryToDeliver(Industry *ind, TileIndex tile);
|
||||||
|
void RemoveIndustryToDeliver(Industry *ind);
|
||||||
void RemoveFromAllNearbyLists();
|
void RemoveFromAllNearbyLists();
|
||||||
|
|
||||||
inline bool TileIsInCatchment(TileIndex tile) const
|
inline bool TileIsInCatchment(TileIndex tile) const
|
||||||
|
|
|
@ -600,9 +600,9 @@ bool CheckSubsidised(CargoID cargo_type, CompanyID company, SourceType src_type,
|
||||||
if (s->cargo_type == cargo_type && s->src_type == src_type && s->src == src && (!s->IsAwarded() || s->awarded == company)) {
|
if (s->cargo_type == cargo_type && s->src_type == src_type && s->src == src && (!s->IsAwarded() || s->awarded == company)) {
|
||||||
switch (s->dst_type) {
|
switch (s->dst_type) {
|
||||||
case ST_INDUSTRY:
|
case ST_INDUSTRY:
|
||||||
for (Industry *ind : st->industries_near) {
|
for (const auto &i : st->industries_near) {
|
||||||
if (s->dst == ind->index) {
|
if (s->dst == i.industry->index) {
|
||||||
assert(ind->part_of_subsidy & POS_DST);
|
assert(i.industry->part_of_subsidy & POS_DST);
|
||||||
subsidised = true;
|
subsidised = true;
|
||||||
if (!s->IsAwarded()) s->AwardTo(company);
|
if (!s->IsAwarded()) s->AwardTo(company);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue