Change: Towns generate cargo based on town production effect.

This replaces the fixed handling of passengers and mail.
This commit is contained in:
Peter Nelson 2024-01-07 19:32:41 +00:00 committed by Peter Nelson
parent 8d69d0549d
commit 6d93fa649c
2 changed files with 72 additions and 40 deletions

View File

@ -541,9 +541,52 @@ static void TownGenerateCargo(Town *t, CargoID ct, uint amount, StationFinder &s
amount = ScaleByCargoScale(amount, true); amount = ScaleByCargoScale(amount, true);
/* Actually generate cargo and update town statistics. */ /* Actually generate cargo and update town statistics. */
uint moved = MoveGoodsToStation(ct, amount, SourceType::Town, t->index, stations.GetStations());
t->supplied[ct].new_max += amount; t->supplied[ct].new_max += amount;
t->supplied[ct].new_act += moved; t->supplied[ct].new_act += MoveGoodsToStation(ct, amount, SourceType::Town, t->index, stations.GetStations());;
}
/**
* Generate cargo for a house using the original algorithm.
* @param t The current town.
* @param tpe The town production effect.
* @param rate The town's product rate for this production.
* @param stations Available stations for this house.
*/
static void TownGenerateCargoOriginal(Town *t, TownProductionEffect tpe, uint8_t rate, StationFinder &stations)
{
for (const CargoSpec *cs : CargoSpec::town_production_cargoes[tpe]) {
uint32_t r = Random();
if (GB(r, 0, 8) < rate) {
CargoID cid = cs->Index();
uint amt = GB(r, 0, 8) / 8 + 1;
TownGenerateCargo(t, cid, amt, stations, true);
}
}
}
/**
* Generate cargo for a house using the binominal algorithm.
* @param t The current town.
* @param tpe The town production effect.
* @param rate The town's product rate for this production.
* @param stations Available stations for this house.
*/
static void TownGenerateCargoBinominal(Town *t, TownProductionEffect tpe, uint8_t rate, StationFinder &stations)
{
for (const CargoSpec *cs : CargoSpec::town_production_cargoes[tpe]) {
CargoID cid = cs->Index();
uint32_t r = Random();
/* Make a bitmask with up to 32 bits set, one for each potential pax. */
int genmax = (rate + 7) / 8;
uint32_t genmask = (genmax >= 32) ? 0xFFFFFFFF : ((1 << genmax) - 1);
/* Mask random value by potential pax and count number of actual pax. */
uint amt = CountBits(r & genmask);
TownGenerateCargo(t, cid, amt, stations, true);
}
} }
/** /**
@ -600,15 +643,8 @@ static void TileLoop_Town(TileIndex tile)
switch (_settings_game.economy.town_cargogen_mode) { switch (_settings_game.economy.town_cargogen_mode) {
case TCGM_ORIGINAL: case TCGM_ORIGINAL:
/* Original (quadratic) cargo generation algorithm */ /* Original (quadratic) cargo generation algorithm */
if (GB(r, 0, 8) < hs->population) { TownGenerateCargoOriginal(t, TPE_PASSENGERS, hs->population, stations);
uint amt = GB(r, 0, 8) / 8 + 1; TownGenerateCargoOriginal(t, TPE_MAIL, hs->mail_generation, stations);
TownGenerateCargo(t, CT_PASSENGERS, amt, stations, true);
}
if (GB(r, 8, 8) < hs->mail_generation) {
uint amt = GB(r, 8, 8) / 8 + 1;
TownGenerateCargo(t, CT_MAIL, amt, stations, true);
}
break; break;
case TCGM_BITCOUNT: case TCGM_BITCOUNT:
@ -616,20 +652,8 @@ static void TileLoop_Town(TileIndex tile)
/* Reduce generation rate to a 1/4, using tile bits to spread out distribution. /* Reduce generation rate to a 1/4, using tile bits to spread out distribution.
* As tick counter is incremented by 256 between each call, we ignore the lower 8 bits. */ * As tick counter is incremented by 256 between each call, we ignore the lower 8 bits. */
if (GB(TimerGameTick::counter, 8, 2) == GB(tile.base(), 0, 2)) { if (GB(TimerGameTick::counter, 8, 2) == GB(tile.base(), 0, 2)) {
/* Make a bitmask with up to 32 bits set, one for each potential pax */ TownGenerateCargoBinominal(t, TPE_PASSENGERS, hs->population, stations);
int genmax = (hs->population + 7) / 8; TownGenerateCargoBinominal(t, TPE_MAIL, hs->mail_generation, stations);
uint32_t genmask = (genmax >= 32) ? 0xFFFFFFFF : ((1 << genmax) - 1);
/* Mask random value by potential pax and count number of actual pax */
uint amt = CountBits(r & genmask);
/* Adjust and apply */
TownGenerateCargo(t, CT_PASSENGERS, amt, stations, true);
/* Do the same for mail, with a fresh random */
r = Random();
genmax = (hs->mail_generation + 7) / 8;
genmask = (genmax >= 32) ? 0xFFFFFFFF : ((1 << genmax) - 1);
amt = CountBits(r & genmask);
TownGenerateCargo(t, CT_MAIL, amt, stations, true);
} }
break; break;
@ -731,10 +755,14 @@ static void AddProducedCargo_Town(TileIndex tile, CargoArray &produced)
} }
} else { } else {
if (hs->population > 0) { if (hs->population > 0) {
produced[CT_PASSENGERS]++; for (const CargoSpec *cs : CargoSpec::town_production_cargoes[TPE_PASSENGERS]) {
produced[cs->Index()]++;
}
} }
if (hs->mail_generation > 0) { if (hs->mail_generation > 0) {
produced[CT_MAIL]++; for (const CargoSpec *cs : CargoSpec::town_production_cargoes[TPE_MAIL]) {
produced[cs->Index()]++;
}
} }
} }
} }
@ -1883,8 +1911,12 @@ void UpdateTownRadius(Town *t)
*/ */
void UpdateTownMaxPass(Town *t) void UpdateTownMaxPass(Town *t)
{ {
t->supplied[CT_PASSENGERS].old_max = ScaleByCargoScale(t->cache.population >> 3, true); for (const CargoSpec *cs : CargoSpec::town_production_cargoes[TPE_PASSENGERS]) {
t->supplied[CT_MAIL].old_max = ScaleByCargoScale(t->cache.population >> 4, true); t->supplied[cs->Index()].old_max = ScaleByCargoScale(t->cache.population >> 3, true);
}
for (const CargoSpec *cs : CargoSpec::town_production_cargoes[TPE_MAIL]) {
t->supplied[cs->Index()].old_max = ScaleByCargoScale(t->cache.population >> 4, true);
}
} }
static void UpdateTownGrowthRate(Town *t); static void UpdateTownGrowthRate(Town *t);

View File

@ -408,17 +408,17 @@ public:
tr.top += GetCharacterHeight(FS_NORMAL); tr.top += GetCharacterHeight(FS_NORMAL);
StringID str_last_period = TimerGameEconomy::UsingWallclockUnits() ? STR_TOWN_VIEW_CARGO_LAST_MINUTE_MAX : STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX; StringID str_last_period = TimerGameEconomy::UsingWallclockUnits() ? STR_TOWN_VIEW_CARGO_LAST_MINUTE_MAX : STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX;
SetDParam(0, 1 << CT_PASSENGERS);
SetDParam(1, this->town->supplied[CT_PASSENGERS].old_act);
SetDParam(2, this->town->supplied[CT_PASSENGERS].old_max);
DrawString(tr, str_last_period);
tr.top += GetCharacterHeight(FS_NORMAL);
SetDParam(0, 1 << CT_MAIL); for (auto tpe : {TPE_PASSENGERS, TPE_MAIL}) {
SetDParam(1, this->town->supplied[CT_MAIL].old_act); for (const CargoSpec *cs : CargoSpec::town_production_cargoes[tpe]) {
SetDParam(2, this->town->supplied[CT_MAIL].old_max); CargoID cid = cs->Index();
DrawString(tr, str_last_period); SetDParam(0, 1ULL << cid);
tr.top += GetCharacterHeight(FS_NORMAL); SetDParam(1, this->town->supplied[cid].old_act);
SetDParam(2, this->town->supplied[cid].old_max);
DrawString(tr, str_last_period);
tr.top += GetCharacterHeight(FS_NORMAL);
}
}
bool first = true; bool first = true;
for (int i = TAE_BEGIN; i < TAE_END; i++) { for (int i = TAE_BEGIN; i < TAE_END; i++) {
@ -539,7 +539,7 @@ public:
*/ */
uint GetDesiredInfoHeight(int width) const uint GetDesiredInfoHeight(int width) const
{ {
uint aimed_height = 3 * GetCharacterHeight(FS_NORMAL); uint aimed_height = static_cast<uint>(1 + CargoSpec::town_production_cargoes[TPE_PASSENGERS].size() + CargoSpec::town_production_cargoes[TPE_MAIL].size()) * GetCharacterHeight(FS_NORMAL);
bool first = true; bool first = true;
for (int i = TAE_BEGIN; i < TAE_END; i++) { for (int i = TAE_BEGIN; i < TAE_END; i++) {