mirror of https://github.com/OpenTTD/OpenTTD.git
(svn r25362) -Feature: consider cargo waiting at other stations for rating at the origin station
This commit is contained in:
parent
04e3eb6fab
commit
741c431caa
|
@ -659,33 +659,53 @@ uint StationCargoList::ShiftCargo(Taction action, StationID next, bool include_i
|
||||||
/**
|
/**
|
||||||
* Truncates where each destination loses roughly the same percentage of its
|
* Truncates where each destination loses roughly the same percentage of its
|
||||||
* cargo. This is done by randomizing the selection of packets to be removed.
|
* cargo. This is done by randomizing the selection of packets to be removed.
|
||||||
|
* Optionally count the cargo by origin station.
|
||||||
* @param max_move Maximum amount of cargo to remove.
|
* @param max_move Maximum amount of cargo to remove.
|
||||||
|
* @param cargo_per_source Container for counting the cargo by origin.
|
||||||
* @return Amount of cargo actually moved.
|
* @return Amount of cargo actually moved.
|
||||||
*/
|
*/
|
||||||
uint StationCargoList::Truncate(uint max_move)
|
uint StationCargoList::Truncate(uint max_move, StationCargoAmountMap *cargo_per_source)
|
||||||
{
|
{
|
||||||
max_move = min(max_move, this->count);
|
max_move = min(max_move, this->count);
|
||||||
uint prev_count = this->count;
|
uint prev_count = this->count;
|
||||||
uint moved = 0;
|
uint moved = 0;
|
||||||
|
uint loop = 0;
|
||||||
|
bool do_count = cargo_per_source != NULL;
|
||||||
while (max_move > moved) {
|
while (max_move > moved) {
|
||||||
for (Iterator it(this->packets.begin()); it != this->packets.end();) {
|
for (Iterator it(this->packets.begin()); it != this->packets.end();) {
|
||||||
|
CargoPacket *cp = *it;
|
||||||
if (prev_count > max_move && RandomRange(prev_count) < prev_count - max_move) {
|
if (prev_count > max_move && RandomRange(prev_count) < prev_count - max_move) {
|
||||||
|
if (do_count && loop == 0) {
|
||||||
|
(*cargo_per_source)[cp->source] += cp->count;
|
||||||
|
}
|
||||||
++it;
|
++it;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
CargoPacket *cp = *it;
|
|
||||||
uint diff = max_move - moved;
|
uint diff = max_move - moved;
|
||||||
if (cp->count > diff) {
|
if (cp->count > diff) {
|
||||||
this->RemoveFromCache(cp, diff);
|
if (diff > 0) {
|
||||||
cp->Reduce(diff);
|
this->RemoveFromCache(cp, diff);
|
||||||
return moved + diff;
|
cp->Reduce(diff);
|
||||||
|
moved += diff;
|
||||||
|
}
|
||||||
|
if (loop > 0) {
|
||||||
|
if (do_count) (*cargo_per_source)[cp->source] -= diff;
|
||||||
|
return moved;
|
||||||
|
} else {
|
||||||
|
if (do_count) (*cargo_per_source)[cp->source] += cp->count;
|
||||||
|
++it;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
it = this->packets.erase(it);
|
it = this->packets.erase(it);
|
||||||
|
if (do_count && loop > 0) {
|
||||||
|
(*cargo_per_source)[cp->source] -= cp->count;
|
||||||
|
}
|
||||||
moved += cp->count;
|
moved += cp->count;
|
||||||
this->RemoveFromCache(cp, cp->count);
|
this->RemoveFromCache(cp, cp->count);
|
||||||
delete cp;
|
delete cp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
loop++;
|
||||||
}
|
}
|
||||||
return moved;
|
return moved;
|
||||||
}
|
}
|
||||||
|
|
|
@ -443,6 +443,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef MultiMap<StationID, CargoPacket *> StationCargoPacketMap;
|
typedef MultiMap<StationID, CargoPacket *> StationCargoPacketMap;
|
||||||
|
typedef std::map<StationID, uint> StationCargoAmountMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CargoList that is used for stations.
|
* CargoList that is used for stations.
|
||||||
|
@ -532,7 +533,7 @@ public:
|
||||||
|
|
||||||
uint Reserve(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationID next);
|
uint Reserve(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationID next);
|
||||||
uint Load(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationID next);
|
uint Load(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationID next);
|
||||||
uint Truncate(uint max_move = UINT_MAX);
|
uint Truncate(uint max_move = UINT_MAX, StationCargoAmountMap *cargo_per_source = NULL);
|
||||||
uint Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge);
|
uint Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -282,6 +282,7 @@ const SaveLoad *GetGoodsDesc()
|
||||||
SLE_CONDVAR(GoodsEntry, link_graph, SLE_UINT16, 183, SL_MAX_VERSION),
|
SLE_CONDVAR(GoodsEntry, link_graph, SLE_UINT16, 183, SL_MAX_VERSION),
|
||||||
SLE_CONDVAR(GoodsEntry, node, SLE_UINT16, 183, SL_MAX_VERSION),
|
SLE_CONDVAR(GoodsEntry, node, SLE_UINT16, 183, SL_MAX_VERSION),
|
||||||
SLEG_CONDVAR( _num_flows, SLE_UINT32, 183, SL_MAX_VERSION),
|
SLEG_CONDVAR( _num_flows, SLE_UINT32, 183, SL_MAX_VERSION),
|
||||||
|
SLE_CONDVAR(GoodsEntry, max_waiting_cargo, SLE_UINT32, 183, SL_MAX_VERSION),
|
||||||
SLE_END()
|
SLE_END()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -160,7 +160,8 @@ struct GoodsEntry {
|
||||||
last_speed(0),
|
last_speed(0),
|
||||||
last_age(255),
|
last_age(255),
|
||||||
link_graph(INVALID_LINK_GRAPH),
|
link_graph(INVALID_LINK_GRAPH),
|
||||||
node(INVALID_NODE)
|
node(INVALID_NODE),
|
||||||
|
max_waiting_cargo(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
byte acceptance_pickup; ///< Status of this cargo, see #GoodsEntryStatus.
|
byte acceptance_pickup; ///< Status of this cargo, see #GoodsEntryStatus.
|
||||||
|
@ -197,6 +198,7 @@ struct GoodsEntry {
|
||||||
LinkGraphID link_graph; ///< Link graph this station belongs to.
|
LinkGraphID link_graph; ///< Link graph this station belongs to.
|
||||||
NodeID node; ///< ID of node in link graph referring to this goods entry.
|
NodeID node; ///< ID of node in link graph referring to this goods entry.
|
||||||
FlowStatMap flows; ///< Planned flows through this station.
|
FlowStatMap flows; ///< Planned flows through this station.
|
||||||
|
uint max_waiting_cargo; ///< Max cargo from this station waiting at any station.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reports whether a vehicle has ever tried to load the cargo at this station.
|
* Reports whether a vehicle has ever tried to load the cargo at this station.
|
||||||
|
|
|
@ -3241,6 +3241,19 @@ static void UpdateStationRating(Station *st)
|
||||||
int rating = 0;
|
int rating = 0;
|
||||||
uint waiting = ge->cargo.TotalCount();
|
uint waiting = ge->cargo.TotalCount();
|
||||||
|
|
||||||
|
/* num_dests is at least 1 if there is any cargo as
|
||||||
|
* INVALID_STATION is also a destination.
|
||||||
|
*/
|
||||||
|
uint num_dests = (uint)ge->cargo.Packets()->MapSize();
|
||||||
|
|
||||||
|
/* Average amount of cargo per next hop, but prefer solitary stations
|
||||||
|
* with only one or two next hops. They are allowed to have more
|
||||||
|
* cargo waiting per next hop.
|
||||||
|
* With manual cargo distribution waiting_avg = waiting / 2 as then
|
||||||
|
* INVALID_STATION is the only destination.
|
||||||
|
*/
|
||||||
|
uint waiting_avg = waiting / (num_dests + 1);
|
||||||
|
|
||||||
if (HasBit(cs->callback_mask, CBM_CARGO_STATION_RATING_CALC)) {
|
if (HasBit(cs->callback_mask, CBM_CARGO_STATION_RATING_CALC)) {
|
||||||
/* Perform custom station rating. If it succeeds the speed, days in transit and
|
/* Perform custom station rating. If it succeeds the speed, days in transit and
|
||||||
* waiting cargo ratings must not be executed. */
|
* waiting cargo ratings must not be executed. */
|
||||||
|
@ -3248,7 +3261,7 @@ static void UpdateStationRating(Station *st)
|
||||||
/* NewGRFs expect last speed to be 0xFF when no vehicle has arrived yet. */
|
/* NewGRFs expect last speed to be 0xFF when no vehicle has arrived yet. */
|
||||||
uint last_speed = ge->HasVehicleEverTriedLoading() ? ge->last_speed : 0xFF;
|
uint last_speed = ge->HasVehicleEverTriedLoading() ? ge->last_speed : 0xFF;
|
||||||
|
|
||||||
uint32 var18 = min(ge->time_since_pickup, 0xFF) | (min(waiting, 0xFFFF) << 8) | (min(last_speed, 0xFF) << 24);
|
uint32 var18 = min(ge->time_since_pickup, 0xFF) | (min(ge->max_waiting_cargo, 0xFFFF) << 8) | (min(last_speed, 0xFF) << 24);
|
||||||
/* Convert to the 'old' vehicle types */
|
/* Convert to the 'old' vehicle types */
|
||||||
uint32 var10 = (st->last_vehicle_type == VEH_INVALID) ? 0x0 : (st->last_vehicle_type + 0x10);
|
uint32 var10 = (st->last_vehicle_type == VEH_INVALID) ? 0x0 : (st->last_vehicle_type + 0x10);
|
||||||
uint16 callback = GetCargoCallback(CBID_CARGO_STATION_RATING_CALC, var10, var18, cs);
|
uint16 callback = GetCargoCallback(CBID_CARGO_STATION_RATING_CALC, var10, var18, cs);
|
||||||
|
@ -3273,11 +3286,11 @@ static void UpdateStationRating(Station *st)
|
||||||
(rating += 45, waittime > 3) ||
|
(rating += 45, waittime > 3) ||
|
||||||
(rating += 35, true);
|
(rating += 35, true);
|
||||||
|
|
||||||
(rating -= 90, waiting > 1500) ||
|
(rating -= 90, ge->max_waiting_cargo > 1500) ||
|
||||||
(rating += 55, waiting > 1000) ||
|
(rating += 55, ge->max_waiting_cargo > 1000) ||
|
||||||
(rating += 35, waiting > 600) ||
|
(rating += 35, ge->max_waiting_cargo > 600) ||
|
||||||
(rating += 10, waiting > 300) ||
|
(rating += 10, ge->max_waiting_cargo > 300) ||
|
||||||
(rating += 20, waiting > 100) ||
|
(rating += 20, ge->max_waiting_cargo > 100) ||
|
||||||
(rating += 10, true);
|
(rating += 10, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3295,12 +3308,12 @@ static void UpdateStationRating(Station *st)
|
||||||
/* only modify rating in steps of -2, -1, 0, 1 or 2 */
|
/* only modify rating in steps of -2, -1, 0, 1 or 2 */
|
||||||
ge->rating = rating = or_ + Clamp(Clamp(rating, 0, 255) - or_, -2, 2);
|
ge->rating = rating = or_ + Clamp(Clamp(rating, 0, 255) - or_, -2, 2);
|
||||||
|
|
||||||
/* if rating is <= 64 and more than 200 items waiting,
|
/* if rating is <= 64 and more than 100 items waiting on average per destination,
|
||||||
* remove some random amount of goods from the station */
|
* remove some random amount of goods from the station */
|
||||||
if (rating <= 64 && waiting >= 200) {
|
if (rating <= 64 && waiting_avg >= 100) {
|
||||||
int dec = Random() & 0x1F;
|
int dec = Random() & 0x1F;
|
||||||
if (waiting < 400) dec &= 7;
|
if (waiting_avg < 200) dec &= 7;
|
||||||
waiting -= dec + 1;
|
waiting -= (dec + 1) * num_dests;
|
||||||
waiting_changed = true;
|
waiting_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3309,7 +3322,7 @@ static void UpdateStationRating(Station *st)
|
||||||
uint32 r = Random();
|
uint32 r = Random();
|
||||||
if (rating <= (int)GB(r, 0, 7)) {
|
if (rating <= (int)GB(r, 0, 7)) {
|
||||||
/* Need to have int, otherwise it will just overflow etc. */
|
/* Need to have int, otherwise it will just overflow etc. */
|
||||||
waiting = max((int)waiting - (int)GB(r, 8, 2) - 1, 0);
|
waiting = max((int)waiting - (int)((GB(r, 8, 2) - 1) * num_dests), 0);
|
||||||
waiting_changed = true;
|
waiting_changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3332,7 +3345,25 @@ static void UpdateStationRating(Station *st)
|
||||||
/* We can't truncate cargo that's already reserved for loading.
|
/* We can't truncate cargo that's already reserved for loading.
|
||||||
* Thus StoredCount() here. */
|
* Thus StoredCount() here. */
|
||||||
if (waiting_changed && waiting < ge->cargo.AvailableCount()) {
|
if (waiting_changed && waiting < ge->cargo.AvailableCount()) {
|
||||||
ge->cargo.Truncate(ge->cargo.AvailableCount() - waiting);
|
/* Feed back the exact own waiting cargo at this station for the
|
||||||
|
* next rating calculation. */
|
||||||
|
ge->max_waiting_cargo = 0;
|
||||||
|
|
||||||
|
/* If truncating also punish the source stations' ratings to
|
||||||
|
* decrease the flow of incoming cargo. */
|
||||||
|
|
||||||
|
StationCargoAmountMap waiting_per_source;
|
||||||
|
ge->cargo.Truncate(ge->cargo.AvailableCount() - waiting, &waiting_per_source);
|
||||||
|
for (StationCargoAmountMap::iterator i(waiting_per_source.begin()); i != waiting_per_source.end(); ++i) {
|
||||||
|
Station *source_station = Station::GetIfValid(i->first);
|
||||||
|
if (source_station == NULL) continue;
|
||||||
|
|
||||||
|
GoodsEntry &source_ge = source_station->goods[cs->Index()];
|
||||||
|
source_ge.max_waiting_cargo = max(source_ge.max_waiting_cargo, i->second);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* If the average number per next hop is low, be more forgiving. */
|
||||||
|
ge->max_waiting_cargo = waiting_avg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue