(svn r14332) -Fix[FS#1885]: Balance the monthly random industry changes, by introducing a daily random industry change.
authorbelugas
Mon, 15 Sep 2008 17:18:22 +0000
changeset 10146 cfea97f96067
parent 10145 849ba8b8626b
child 10147 f0215b6c526e
(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
src/economy.cpp
src/economy_type.h
src/industry.h
src/industry_cmd.cpp
src/saveload.cpp
--- a/src/date.cpp	Mon Sep 15 16:29:40 2008 +0000
+++ b/src/date.cpp	Mon Sep 15 17:18:22 2008 +0000
@@ -159,7 +159,7 @@
 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 @@
 
 	DisasterDailyLoop();
 	WaypointsDailyLoop();
+	IndustryDailyLoop();
 
 	if (_game_mode != GM_MENU) {
 		InvalidateWindowWidget(WC_STATUS_BAR, 0, 0);
--- a/src/economy.cpp	Mon Sep 15 16:29:40 2008 +0000
+++ b/src/economy.cpp	Mon Sep 15 17:18:22 2008 +0000
@@ -786,6 +786,27 @@
 	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 @@
 	_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 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},
 };
--- a/src/economy_type.h	Mon Sep 15 16:29:40 2008 +0000
+++ b/src/economy_type.h	Mon Sep 15 17:18:22 2008 +0000
@@ -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 {
--- a/src/industry.h	Mon Sep 15 16:29:40 2008 +0000
+++ b/src/industry.h	Mon Sep 15 17:18:22 2008 +0000
@@ -260,6 +260,8 @@
 
 /* smallmap_gui.cpp */
 void BuildIndustriesLegend();
+/* industry_cmd.cpp */
+void SetIndustryDailyChanges();
 
 /**
  * Check if an Industry exists whithin the pool of industries
--- a/src/industry_cmd.cpp	Mon Sep 15 16:29:40 2008 +0000
+++ b/src/industry_cmd.cpp	Mon Sep 15 17:18:22 2008 +0000
@@ -2235,6 +2235,47 @@
 	}
 }
 
+/** 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 @@
 		}
 	}
 
-	/* 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 */
--- a/src/saveload.cpp	Mon Sep 15 16:29:40 2008 +0000
+++ b/src/saveload.cpp	Mon Sep 15 17:18:22 2008 +0000
@@ -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