Add: Option for population-linear town cargo generation

Introduce a new default algorithm for town cargo generation (passengers and mail), and a game setting to choose between the new and original algorithm.

The original town cargo generation algorithm has the property of the generated amount relating to the square of each building's population, meaning large towns easily produce more cargo than can realistically be transported. The problem is excessive cargo is amplified if playing with cargodist.

The new algorithm introduced instead has a linear relation to the population. The result is that smaller towns will produce slightly more cargo, while the largest towns will produce about a fourth of what they would with the original algorithm.

Existing savegames will use the original algorithm, while new games will default to the new algorithm.
pull/82/head
Niels Martin Hansen 6 years ago
parent 7f00a420cb
commit 52572cafa6

@ -1583,6 +1583,10 @@ STR_CONFIG_SETTING_TOWN_FOUNDING_HELPTEXT :Enabling this s
STR_CONFIG_SETTING_TOWN_FOUNDING_FORBIDDEN :Forbidden
STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED :Allowed
STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED_CUSTOM_LAYOUT :Allowed, custom town layout
STR_CONFIG_SETTING_TOWN_CARGOGENMODE :Town cargo generation: {STRING2}
STR_CONFIG_SETTING_TOWN_CARGOGENMODE_HELPTEXT :How much cargo is produced by houses in towns, relative to the overall population of the town.{}Quadratic growth: A town twice the size generates four times as many passengers.{}Linear growth: A town twice the size generates twice the amount of passengers.
STR_CONFIG_SETTING_TOWN_CARGOGENMODE_ORIGINAL :Quadratic (original)
STR_CONFIG_SETTING_TOWN_CARGOGENMODE_BITCOUNT :Linear
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT :In game placement of trees: {STRING2}
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_HELPTEXT :Control random appearance of trees during the game. This might affect industries which rely on tree growth, for example lumber mills

@ -3080,6 +3080,11 @@ bool AfterLoadGame()
}
}
if (IsSavegameVersionBefore(SLV_TOWN_CARGOGEN)) {
/* Ensure the original cargo generation mode is used */
_settings_game.economy.town_cargogen_mode = TCGM_ORIGINAL;
}
/* Station acceptance is some kind of cache */
if (IsSavegameVersionBefore(SLV_127)) {
Station *st;

@ -291,6 +291,7 @@ enum SaveLoadVersion : uint16 {
SLV_GROUP_LIVERIES, ///< 205 PR#7108 Livery storage change and group liveries.
SLV_SHIPS_STOP_IN_LOCKS, ///< 206 PR#7150 Ship/lock movement changes.
SLV_FIX_CARGO_MONITOR, ///< 207 PR#7175 v1.9 Cargo monitor data packing fix to support 64 cargotypes.
SLV_TOWN_CARGOGEN, ///< 208 PR#6965 New algorithms for town building cargo generation.
SL_MAX_VERSION, ///< Highest possible saveload version
};

@ -1733,6 +1733,7 @@ static SettingsContainer &GetSettingsTree()
towns->Add(new SettingEntry("economy.allow_town_roads"));
towns->Add(new SettingEntry("economy.allow_town_level_crossings"));
towns->Add(new SettingEntry("economy.found_town"));
towns->Add(new SettingEntry("economy.town_cargogen_mode"));
}
SettingsPage *industries = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_INDUSTRIES));

@ -493,6 +493,7 @@ struct EconomySettings {
uint8 larger_towns; ///< the number of cities to build. These start off larger and grow twice as fast
uint8 initial_city_size; ///< multiplier for the initial size of the cities compared to towns
TownLayoutByte town_layout; ///< select town layout, @see TownLayout
TownCargoGenMode town_cargogen_mode; ///< algorithm for generating cargo from houses, @see TownCargoGenMode
bool allow_town_roads; ///< towns are allowed to build roads (always allowed when generating world / in SE)
TownFoundingByte found_town; ///< town founding, @see TownFounding
bool station_noise_level; ///< build new airports when the town noise level is still within accepted limits

@ -618,6 +618,21 @@ def = true
str = STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS
strhelp = STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS_HELPTEXT
[SDT_VAR]
base = GameSettings
var = economy.town_cargogen_mode
type = SLE_UINT8
from = SLV_TOWN_CARGOGEN
guiflags = SGF_MULTISTRING
def = TCGM_BITCOUNT
min = TCGM_BEGIN
max = TCGM_END - 1
interval = 1
str = STR_CONFIG_SETTING_TOWN_CARGOGENMODE
strhelp = STR_CONFIG_SETTING_TOWN_CARGOGENMODE_HELPTEXT
strval = STR_CONFIG_SETTING_TOWN_CARGOGENMODE_ORIGINAL
cat = SC_ADVANCED
; link graph
[SDT_VAR]

@ -536,20 +536,54 @@ static void TileLoop_Town(TileIndex tile)
t->supplied[cs->Index()].new_act += moved;
}
} else {
if (GB(r, 0, 8) < hs->population) {
uint amt = GB(r, 0, 8) / 8 + 1;
switch (_settings_game.economy.town_cargogen_mode) {
case TCGM_ORIGINAL:
/* Original (quadratic) cargo generation algorithm */
if (GB(r, 0, 8) < hs->population) {
uint amt = GB(r, 0, 8) / 8 + 1;
if (EconomyIsInRecession()) amt = (amt + 1) >> 1;
t->supplied[CT_PASSENGERS].new_max += amt;
t->supplied[CT_PASSENGERS].new_act += MoveGoodsToStation(CT_PASSENGERS, amt, ST_TOWN, t->index, stations.GetStations());
}
if (EconomyIsInRecession()) amt = (amt + 1) >> 1;
t->supplied[CT_PASSENGERS].new_max += amt;
t->supplied[CT_PASSENGERS].new_act += MoveGoodsToStation(CT_PASSENGERS, amt, ST_TOWN, t->index, stations.GetStations());
}
if (GB(r, 8, 8) < hs->mail_generation) {
uint amt = GB(r, 8, 8) / 8 + 1;
if (EconomyIsInRecession()) amt = (amt + 1) >> 1;
t->supplied[CT_MAIL].new_max += amt;
t->supplied[CT_MAIL].new_act += MoveGoodsToStation(CT_MAIL, amt, ST_TOWN, t->index, stations.GetStations());
}
break;
if (GB(r, 8, 8) < hs->mail_generation) {
uint amt = GB(r, 8, 8) / 8 + 1;
case TCGM_BITCOUNT:
/* Binomial distribution per tick, by a series of coin flips */
/* 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. */
if (GB(_tick_counter, 8, 2) == GB(tile, 0, 2)) {
/* Make a bitmask with up to 32 bits set, one for each potential pax */
int genmax = (hs->population + 7) / 8;
uint32 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 */
if (EconomyIsInRecession()) amt = (amt + 1) >> 1;
t->supplied[CT_PASSENGERS].new_max += amt;
t->supplied[CT_PASSENGERS].new_act += MoveGoodsToStation(CT_PASSENGERS, amt, ST_TOWN, t->index, stations.GetStations());
/* 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);
if (EconomyIsInRecession()) amt = (amt + 1) >> 1;
t->supplied[CT_MAIL].new_max += amt;
t->supplied[CT_MAIL].new_act += MoveGoodsToStation(CT_MAIL, amt, ST_TOWN, t->index, stations.GetStations());
}
break;
if (EconomyIsInRecession()) amt = (amt + 1) >> 1;
t->supplied[CT_MAIL].new_max += amt;
t->supplied[CT_MAIL].new_act += MoveGoodsToStation(CT_MAIL, amt, ST_TOWN, t->index, stations.GetStations());
default:
NOT_REACHED();
}
}

@ -105,6 +105,14 @@ enum TownFounding {
/** It needs to be 8bits, because we save and load it as such */
typedef SimpleTinyEnumT<TownFounding, byte> TownFoundingByte;
/** Town cargo generation modes */
enum TownCargoGenMode : byte {
TCGM_BEGIN = 0,
TCGM_ORIGINAL = 0, ///< Original algorithm (quadratic cargo by population)
TCGM_BITCOUNT, ///< Bit-counted algorithm (normal distribution from individual house population)
TCGM_END,
};
static const uint MAX_LENGTH_TOWN_NAME_CHARS = 32; ///< The maximum length of a town name in characters including '\0'
/** Store the maximum and actually transported cargo amount for the current and the last month. */

Loading…
Cancel
Save