Changeset - r23403:d1046b8440da
[Not reviewed]
master
0 8 0
Niels Martin Hansen - 6 years ago 2018-11-07 18:06:39
nielsm@indvikleren.dk
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.
8 files changed with 83 insertions and 14 deletions:
0 comments (0 inline, 0 general)
src/lang/english.txt
Show inline comments
 
@@ -1580,12 +1580,16 @@ STR_CONFIG_SETTING_NOISE_LEVEL          
 
STR_CONFIG_SETTING_NOISE_LEVEL_HELPTEXT                         :With this setting disabled, there can be two airports in each town. With this setting enabled, the number of airports in a town is limited by the noise acceptance of the town, which depends on population and airport size and distance
 
STR_CONFIG_SETTING_TOWN_FOUNDING                                :Founding towns in game: {STRING2}
 
STR_CONFIG_SETTING_TOWN_FOUNDING_HELPTEXT                       :Enabling this setting allows players to found new towns in the game
 
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
 
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NONE                    :None {RED}(breaks lumber mill)
 
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_RAINFOREST              :Only in rain forests
 
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_ALL                     :Everywhere
src/saveload/afterload.cpp
Show inline comments
 
@@ -3077,12 +3077,17 @@ bool AfterLoadGame()
 
				/* On lower half of lock */
 
				s->z_pos = GetTileZ(s->tile) * (int)TILE_HEIGHT;
 
			}
 
		}
 
	}
 

	
 
	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;
 
		FOR_ALL_STATIONS(st) UpdateStationAcceptance(st, false);
 
	}
 

	
src/saveload/saveload.h
Show inline comments
 
@@ -288,12 +288,13 @@ enum SaveLoadVersion : uint16 {
 
	SLV_SHIP_PATH_CACHE,                    ///< 203  PR#7072 Add path cache for ships
 
	SLV_SHIP_ROTATION,                      ///< 204  PR#7065 Add extra rotation stages for ships.
 

	
 
	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
 
};
 

	
 
/** Save or load result codes. */
 
enum SaveOrLoadResult {
src/settings_gui.cpp
Show inline comments
 
@@ -1730,12 +1730,13 @@ static SettingsContainer &GetSettingsTre
 
			SettingsPage *towns = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TOWNS));
 
			{
 
				towns->Add(new SettingEntry("economy.town_growth_rate"));
 
				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));
 
			{
 
				industries->Add(new SettingEntry("construction.raw_industry_construction"));
 
				industries->Add(new SettingEntry("construction.industry_platform"));
src/settings_type.h
Show inline comments
 
@@ -490,12 +490,13 @@ struct EconomySettings {
 
	bool   mod_road_rebuild;                 ///< roadworks remove unnecessary RoadBits
 
	bool   multiple_industry_per_town;       ///< allow many industries of the same type per town
 
	uint8  town_growth_rate;                 ///< town growth rate
 
	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
 
	uint16 town_noise_population[3];         ///< population to base decision on noise evaluation (@see town_council_tolerance)
 
	bool   allow_town_level_crossings;       ///< towns are allowed to build level crossings
 
	bool   infrastructure_maintenance;       ///< enable monthly maintenance fee for owner infrastructure
src/table/settings.ini
Show inline comments
 
@@ -615,12 +615,27 @@ var      = economy.allow_town_level_cros
 
from     = SLV_143
 
guiflags = SGF_NO_NETWORK
 
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]
 
base     = GameSettings
 
var      = linkgraph.recalc_interval
 
type     = SLE_UINT16
src/town_cmd.cpp
Show inline comments
 
@@ -533,26 +533,60 @@ static void TileLoop_Town(TileIndex tile
 

	
 
			const CargoSpec *cs = CargoSpec::Get(cargo);
 
			t->supplied[cs->Index()].new_max += amt;
 
			t->supplied[cs->Index()].new_act += moved;
 
		}
 
	} else {
 
		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 (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());
 
		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 (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;
 

	
 
			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;
 

	
 
			default:
 
				NOT_REACHED();
 
		}
 
	}
 

	
 
	Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
 

	
 
	if ((hs->building_flags & BUILDING_HAS_1_TILE) &&
src/town_type.h
Show inline comments
 
@@ -102,12 +102,20 @@ enum TownFounding {
 
	TF_CUSTOM_LAYOUT, ///< Allowed, with custom town layout
 
	TF_END,           ///< Used for iterations and limit testing
 
};
 
/** 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. */
 
template <typename Tstorage>
 
struct TransportedCargoStat {
 
	Tstorage old_max;  ///< Maximum amount last month
0 comments (0 inline, 0 general)