From 0682dc3a0d97ecee26d807476071d5f552f86212 Mon Sep 17 00:00:00 2001 From: belugas Date: Mon, 15 Sep 2008 17:18:22 +0000 Subject: [PATCH] (svn r14332) -Fix[FS#1885]: Balance the monthly random industry changes, by introducing a daily random industry change. This will allow to perform more changes per month on big maps and less on smaller maps, while not overtaxing the IndustryMonthlyLoop process. Thanks to frosch, for nice code ideas and rewrites --- src/date.cpp | 3 ++- src/economy.cpp | 54 +++++++++++++++++++++++++++++++++++--------- src/economy_type.h | 14 +++++++----- src/industry.h | 2 ++ src/industry_cmd.cpp | 49 +++++++++++++++++++++++++++++++++------- src/saveload.cpp | 2 +- 6 files changed, 97 insertions(+), 27 deletions(-) diff --git a/src/date.cpp b/src/date.cpp index 0e99e314a2..180781ce56 100644 --- a/src/date.cpp +++ b/src/date.cpp @@ -159,7 +159,7 @@ Date ConvertYMDToDate(Year year, Month month, Day day) extern void WaypointsDailyLoop(); extern void EnginesDailyLoop(); extern void DisasterDailyLoop(); - +extern void IndustryDailyLoop(); extern void PlayersMonthlyLoop(); extern void EnginesMonthlyLoop(); extern void TownsMonthlyLoop(); @@ -229,6 +229,7 @@ void IncreaseDate() DisasterDailyLoop(); WaypointsDailyLoop(); + IndustryDailyLoop(); if (_game_mode != GM_MENU) { InvalidateWindowWidget(WC_STATUS_BAR, 0, 0); diff --git a/src/economy.cpp b/src/economy.cpp index ee9ada24b0..a80ea602d7 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -786,6 +786,27 @@ void SetPriceBaseMultiplier(uint price, byte factor) price_base_multiplier[price] = factor; } +/** + * Initialize the variables that will maintain the daily industry change system. + * @param init_counter specifies if the counter is required to be initialized + */ +static void StartupIndustryDailyChanges(bool init_counter) +{ + uint map_size = MapLogX() + MapLogY(); + /* After getting map size, it needs to be scaled appropriately and divided by 31, + * which stands for the days in a month. + * Using just 31 will make it so that a monthly reset (based on the real number of days of that month) + * would not be needed. + * Since it is based on "fractionnal parts", the leftover days will not make much of a difference + * on the overall total number of changes performed */ + _economy.industry_daily_increment = (1 << map_size) / 31; + + if (init_counter) { + /* A new game or a savegame from an older version will require the counter to be initialized */ + _economy.industry_daily_change_counter = 0; + } +} + void StartupEconomy() { int i; @@ -816,6 +837,9 @@ void StartupEconomy() _economy.infl_amount_pr = max(0, _settings_game.difficulty.initial_interest - 1); _economy.max_loan_unround = _economy.max_loan = _settings_game.difficulty.max_loan; _economy.fluct = GB(Random(), 0, 8) + 168; + + StartupIndustryDailyChanges(true); // As we are starting a new game, initialize the counter too + } void ResetEconomy() @@ -1924,27 +1948,35 @@ static void SaveLoad_CAPR() } static const SaveLoad _economy_desc[] = { - SLE_CONDVAR(Economy, max_loan, SLE_FILE_I32 | SLE_VAR_I64, 0, 64), - SLE_CONDVAR(Economy, max_loan, SLE_INT64, 65, SL_MAX_VERSION), - SLE_CONDVAR(Economy, max_loan_unround, SLE_FILE_I32 | SLE_VAR_I64, 0, 64), - SLE_CONDVAR(Economy, max_loan_unround, SLE_INT64, 65, SL_MAX_VERSION), - SLE_CONDVAR(Economy, max_loan_unround_fract, SLE_UINT16, 70, SL_MAX_VERSION), - SLE_VAR(Economy, fluct, SLE_INT16), - SLE_VAR(Economy, interest_rate, SLE_UINT8), - SLE_VAR(Economy, infl_amount, SLE_UINT8), - SLE_VAR(Economy, infl_amount_pr, SLE_UINT8), + SLE_CONDVAR(Economy, max_loan, SLE_FILE_I32 | SLE_VAR_I64, 0, 64), + SLE_CONDVAR(Economy, max_loan, SLE_INT64, 65, SL_MAX_VERSION), + SLE_CONDVAR(Economy, max_loan_unround, SLE_FILE_I32 | SLE_VAR_I64, 0, 64), + SLE_CONDVAR(Economy, max_loan_unround, SLE_INT64, 65, SL_MAX_VERSION), + SLE_CONDVAR(Economy, max_loan_unround_fract, SLE_UINT16, 70, SL_MAX_VERSION), + SLE_VAR(Economy, fluct, SLE_INT16), + SLE_VAR(Economy, interest_rate, SLE_UINT8), + SLE_VAR(Economy, infl_amount, SLE_UINT8), + SLE_VAR(Economy, infl_amount_pr, SLE_UINT8), + SLE_CONDVAR(Economy, industry_daily_change_counter, SLE_UINT32, 102, SL_MAX_VERSION), SLE_END() }; /** Economy variables */ -static void SaveLoad_ECMY() +static void Save_ECMY() { SlObject(&_economy, _economy_desc); } +/** Economy variables */ +static void Load_ECMY() +{ + SlObject(&_economy, _economy_desc); + StartupIndustryDailyChanges(CheckSavegameVersion(102)); // old savegames will need to be initialized +} + extern const ChunkHandler _economy_chunk_handlers[] = { { 'PRIC', SaveLoad_PRIC, SaveLoad_PRIC, CH_RIFF | CH_AUTO_LENGTH}, { 'CAPR', SaveLoad_CAPR, SaveLoad_CAPR, CH_RIFF | CH_AUTO_LENGTH}, { 'SUBS', Save_SUBS, Load_SUBS, CH_ARRAY}, - { 'ECMY', SaveLoad_ECMY, SaveLoad_ECMY, CH_RIFF | CH_LAST}, + { 'ECMY', Save_ECMY, Load_ECMY, CH_RIFF | CH_LAST}, }; diff --git a/src/economy_type.h b/src/economy_type.h index f516e57ef0..0b7b581d36 100644 --- a/src/economy_type.h +++ b/src/economy_type.h @@ -12,13 +12,15 @@ typedef OverflowSafeInt64 Money; struct Economy { - Money max_loan; ///< Maximum possible loan - Money max_loan_unround; ///< Economy fluctuation status - uint16 max_loan_unround_fract; ///< Fraction of the unrounded max loan + Money max_loan; ///< Maximum possible loan + Money max_loan_unround; ///< Economy fluctuation status + uint16 max_loan_unround_fract; ///< Fraction of the unrounded max loan int16 fluct; - byte interest_rate; ///< Interest - byte infl_amount; ///< inflation amount - byte infl_amount_pr; ///< inflation rate for payment rates + byte interest_rate; ///< Interest + byte infl_amount; ///< inflation amount + byte infl_amount_pr; ///< inflation rate for payment rates + uint32 industry_daily_change_counter; ///< Bits 31-16 are number of industry to be performed, 15-0 are fractional collected daily + uint32 industry_daily_increment; ///< The value which will increment industry_daily_change_counter. Computed value. NOSAVE }; struct Subsidy { diff --git a/src/industry.h b/src/industry.h index 59a1b932c4..f89cf04776 100644 --- a/src/industry.h +++ b/src/industry.h @@ -260,6 +260,8 @@ static inline IndustryGfx GetTranslatedIndustryTileID(IndustryGfx gfx) /* smallmap_gui.cpp */ void BuildIndustriesLegend(); +/* industry_cmd.cpp */ +void SetIndustryDailyChanges(); /** * Check if an Industry exists whithin the pool of industries diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index 41be3a9f2e..7c78762a17 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -2235,6 +2235,47 @@ static void ChangeIndustryProduction(Industry *i, bool monthly) } } +/** Daily handler for the industry changes + * Taking the original map size of 256*256, the number of random changes was always of just one unit. + * But it cannot be the same on smaller or bigger maps. That number has to be scaled up or down. + * For small maps, it implies that less than one change per month is required, while on bigger maps, + * it would be way more. The daily loop handles those changes. */ +void IndustryDailyLoop() +{ + _economy.industry_daily_change_counter += _economy.industry_daily_increment; + + /* Bits 16-31 of industry_construction_counter contain the number of industries to change/create today, + * the lower 16 bit are a fractional part that might accumulate over several days until it + * is sufficient for an industry. */ + uint16 change_loop = _economy.industry_daily_change_counter >> 16; + + /* Reset the active part of the counter, just keeping the "factional part" */ + _economy.industry_daily_change_counter &= 0xFFFF; + + if (change_loop == 0) { + return; // Nothing to do? get out + } + + PlayerID old_player = _current_player; + _current_player = OWNER_NONE; + + /* perform the required industry changes for the day */ + for (uint16 j = 0; j < change_loop; j++) { + /* 3% chance that we start a new industry */ + if (Chance16(3, 100)) { + MaybeNewIndustry(); + } else { + Industry *i = GetRandomIndustry(); + if (i != NULL) ChangeIndustryProduction(i, false); + } + } + + _current_player = old_player; + + /* production-change */ + InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 1); +} + void IndustryMonthlyLoop() { Industry *i; @@ -2250,14 +2291,6 @@ void IndustryMonthlyLoop() } } - /* 3% chance that we start a new industry */ - if (Chance16(3, 100)) { - MaybeNewIndustry(); - } else { - i = GetRandomIndustry(); - if (i != NULL) ChangeIndustryProduction(i, false); - } - _current_player = old_player; /* production-change */ diff --git a/src/saveload.cpp b/src/saveload.cpp index b4bc4b9194..01f6f6bf43 100644 --- a/src/saveload.cpp +++ b/src/saveload.cpp @@ -37,7 +37,7 @@ #include "table/strings.h" -extern const uint16 SAVEGAME_VERSION = 101; +extern const uint16 SAVEGAME_VERSION = 102; SavegameType _savegame_type; ///< type of savegame we are loading