src/settings.cpp
branchgamebalance
changeset 9908 0fa543611bbe
parent 9907 3b068c3a1c74
child 9909 dce9a6923bb7
--- a/src/settings.cpp	Thu Apr 19 14:48:10 2007 +0000
+++ b/src/settings.cpp	Tue Jun 12 11:56:35 2007 +0000
@@ -1,6 +1,6 @@
 /* $Id$ */
 
-/** @file
+/** @file settings.cpp
  * All actions handling saving and loading of the settings/configuration goes on in this file.
  * The file consists of four parts:
  * <ol>
@@ -95,10 +95,10 @@
 
 	size = ALIGN(size, sizeof(void*));
 
-	// first check if there's memory in the next pool
+	/* first check if there's memory in the next pool */
 	if (p->next && p->next->pos + size <= p->next->size) {
 		p = p->next;
-	// then check if there's not memory in the cur pool
+	/* then check if there's not memory in the cur pool */
 	} else if (p->pos + size > p->size) {
 		SettingsMemoryPool *n = pool_new(size);
 		*pool = n;
@@ -130,7 +130,7 @@
 	}
 }
 
-// structs describing the ini format.
+/** structs describing the ini format. */
 struct IniItem {
 	char *name;
 	char *value;
@@ -139,21 +139,21 @@
 };
 
 struct IniGroup {
-	char *name; // name of group
-	char *comment; //comment for group
+	char *name;        ///< name of group
+	char *comment;     ///<comment for group
 	IniItem *item, **last_item;
 	IniGroup *next;
 	IniFile *ini;
-	IniGroupType type; // type of group
+	IniGroupType type; ///< type of group
 };
 
 struct IniFile {
 	SettingsMemoryPool *pool;
 	IniGroup *group, **last_group;
-	char *comment; // last comment in file
+	char *comment;     ///< last comment in file
 };
 
-// allocate an inifile object
+/** allocate an inifile object */
 static IniFile *ini_alloc()
 {
 	IniFile *ini;
@@ -167,7 +167,7 @@
 	return ini;
 }
 
-// allocate an ini group object
+/** allocate an ini group object */
 static IniGroup *ini_group_alloc(IniFile *ini, const char *grpt, int len)
 {
 	IniGroup *grp = (IniGroup*)pool_alloc(&ini->pool, sizeof(IniGroup));
@@ -199,7 +199,7 @@
 	return item;
 }
 
-// load an ini file into the "abstract" format
+/** load an ini file into the "abstract" format */
 static IniFile *ini_load(const char *filename)
 {
 	char buffer[1024], c, *s, *t, *e;
@@ -217,23 +217,23 @@
 	in = fopen(filename, "r");
 	if (in == NULL) return ini;
 
-	// for each line in the file
+	/* for each line in the file */
 	while (fgets(buffer, sizeof(buffer), in)) {
 
-		// trim whitespace from the left side
+		/* trim whitespace from the left side */
 		for (s = buffer; *s == ' ' || *s == '\t'; s++);
 
-		// trim whitespace from right side.
+		/* trim whitespace from right side. */
 		e = s + strlen(s);
 		while (e > s && ((c=e[-1]) == '\n' || c == '\r' || c == ' ' || c == '\t')) e--;
 		*e = '\0';
 
-		// skip comments and empty lines
+		/* skip comments and empty lines */
 		if (*s == '#' || *s == ';' || *s == '\0') {
 			uint ns = comment_size + (e - s + 1);
 			uint a = comment_alloc;
 			uint pos;
-			// add to comment
+			/* add to comment */
 			if (ns > a) {
 				a = max(a, 128U);
 				do a*=2; while (a < ns);
@@ -246,7 +246,7 @@
 			continue;
 		}
 
-		// it's a group?
+		/* it's a group? */
 		if (s[0] == '[') {
 			if (e[-1] != ']') {
 				ShowInfoF("ini: invalid group name '%s'", buffer);
@@ -260,30 +260,36 @@
 				comment_size = 0;
 			}
 		} else if (group) {
-			// find end of keyname
-			for (t = s; *t != '\0' && *t != '=' && *t != '\t' && *t != ' '; t++);
+			/* find end of keyname */
+			if (*s == '\"') {
+				s++;
+				for (t = s; *t != '\0' && *t != '\"'; t++);
+				if (*t == '\"') *t = ' ';
+			} else {
+				for (t = s; *t != '\0' && *t != '=' && *t != '\t' && *t != ' '; t++);
+			}
 
-			// it's an item in an existing group
+			/* it's an item in an existing group */
 			item = ini_item_alloc(group, s, t-s);
 			if (comment_size) {
 				item->comment = (char*)pool_strdup(&ini->pool, comment, comment_size);
 				comment_size = 0;
 			}
 
-			// find start of parameter
+			/* find start of parameter */
 			while (*t == '=' || *t == ' ' || *t == '\t') t++;
 
 
-			// remove starting quotation marks
+			/* remove starting quotation marks */
 			if (*t == '\"') t++;
-			// remove ending quotation marks
+			/* remove ending quotation marks */
 			e = t + strlen(t);
 			if (e > t && e[-1] == '\"') e--;
 			*e = '\0';
 
 			item->value = (char*)pool_strdup(&ini->pool, t, e - t);
 		} else {
-			// it's an orphan item
+			/* it's an orphan item */
 			ShowInfoF("ini: '%s' outside of group", buffer);
 		}
 	}
@@ -299,25 +305,25 @@
 	return ini;
 }
 
-// lookup a group or make a new one
+/** lookup a group or make a new one */
 static IniGroup *ini_getgroup(IniFile *ini, const char *name, int len)
 {
 	IniGroup *group;
 
 	if (len == -1) len = strlen(name);
 
-	// does it exist already?
+	/* does it exist already? */
 	for (group = ini->group; group; group = group->next)
 		if (!memcmp(group->name, name, len) && group->name[len] == 0)
 			return group;
 
-	// otherwise make a new one
+	/* otherwise make a new one */
 	group = ini_group_alloc(ini, name, len);
 	group->comment = (char*)pool_strdup(&ini->pool, "\n", 1);
 	return group;
 }
 
-// lookup an item or make a new one
+/** lookup an item or make a new one */
 static IniItem *ini_getitem(IniGroup *group, const char *name, bool create)
 {
 	IniItem *item;
@@ -328,11 +334,11 @@
 
 	if (!create) return NULL;
 
-	// otherwise make a new one
+	/* otherwise make a new one */
 	return ini_item_alloc(group, name, len);
 }
 
-// save ini file from the "abstract" format.
+/** save ini file from the "abstract" format. */
 static bool ini_save(const char *filename, IniFile *ini)
 {
 	FILE *f;
@@ -349,11 +355,18 @@
 			assert(item->value != NULL);
 			if (item->comment != NULL) fputs(item->comment, f);
 
+			/* protect item->name with quotes if needed */
+			if (strchr(item->name, ' ') != NULL) {
+				fprintf(f, "\"%s\"", item->name);
+			} else {
+				fprintf(f, "%s", item->name);
+			}
+
 			/* Don't give an equal sign to list items that don't have a parameter */
 			if (group->type == IGT_LIST && *item->value == '\0') {
-				fprintf(f, "%s\n", item->name);
+				fprintf(f, "\n");
 			} else {
-				fprintf(f, "%s = %s\n", item->name, item->value);
+				fprintf(f, " = %s\n", item->value);
 			}
 		}
 	}
@@ -380,13 +393,13 @@
 
 	if (onelen == -1) onelen = strlen(one);
 
-	// check if it's an integer
+	/* check if it's an integer */
 	if (*one >= '0' && *one <= '9')
 		return strtoul(one, NULL, 0);
 
 	idx = 0;
 	for (;;) {
-		// find end of item
+		/* find end of item */
 		s = many;
 		while (*s != '|' && *s != 0) s++;
 		if (s - many == onelen && !memcmp(one, many, onelen)) return idx;
@@ -408,7 +421,7 @@
 	uint32 res = 0;
 
 	for (;;) {
-		// skip "whitespace"
+		/* skip "whitespace" */
 		while (*str == ' ' || *str == '\t' || *str == '|') str++;
 		if (*str == 0) break;
 
@@ -522,7 +535,7 @@
 {
 	int orig_id = id;
 
-	// Look for the id'th element
+	/* Look for the id'th element */
 	while (--id >= 0) {
 		for (; *many != '|'; many++) {
 			if (*many == '\0') { // not found
@@ -533,7 +546,7 @@
 		many++; // pass the |-character
 	}
 
-	// copy string until next item (|) or the end of the list if this is the last one
+	/* copy string until next item (|) or the end of the list if this is the last one */
 	while (*many != '\0' && *many != '|') *buf++ = *many++;
 	*buf = '\0';
 }
@@ -685,7 +698,7 @@
 
 		if (!SlIsObjectCurrentlyValid(sld->version_from, sld->version_to)) continue;
 
-		// XXX - wtf is this?? (group override?)
+		/* XXX - wtf is this?? (group override?) */
 		s = strchr(sdb->name, '.');
 		if (s != NULL) {
 			group = ini_getgroup(ini, sdb->name, s - sdb->name);
@@ -761,7 +774,7 @@
 		if (!SlIsObjectCurrentlyValid(sld->version_from, sld->version_to)) continue;
 		if (sld->conv & SLF_CONFIG_NO) continue;
 
-		// XXX - wtf is this?? (group override?)
+		/* XXX - wtf is this?? (group override?) */
 		s = strchr(sdb->name, '.');
 		if (s != NULL) {
 			group = ini_getgroup(ini, sdb->name, s - sdb->name);
@@ -776,7 +789,7 @@
 		ptr = GetVariableAddress(object, sld);
 
 		if (item->value != NULL) {
-			// check if the value is the same as the old value
+			/* check if the value is the same as the old value */
 			const void *p = string_to_val(sdb, item->value);
 
 			/* The main type of a variable/setting is in bytes 8-15
@@ -929,7 +942,8 @@
  * 2. SDT_something
  * The 'G' stands for global, so this is the one you will use for a
  * SettingDescGlobVarList section meaning global variables. The other uses a
- * Base/Offset and runtime variable selection mechanism, known from the saveload * convention (it also has global so it should not be hard).
+ * Base/Offset and runtime variable selection mechanism, known from the saveload
+ * convention (it also has global so it should not be hard).
  * Of each type there are again two versions, the normal one and one prefixed
  * with 'COND'.
  * COND means that the setting is only valid in certain savegame versions
@@ -1052,7 +1066,6 @@
 /* Shortcuts for macros below. Logically if we don't save the value
  * we also don't sync it in a network game */
 #define S SLF_SAVE_NO | SLF_NETWORK_NO
-#define NS SLF_SAVE_NO
 #define C SLF_CONFIG_NO
 #define N SLF_NETWORK_NO
 
@@ -1069,7 +1082,7 @@
 #include "gui.h"
 #include "town.h"
 #include "gfx.h"
-// virtual PositionMainToolbar function, calls the right one.
+/* virtual PositionMainToolbar function, calls the right one.*/
 static int32 v_PositionMainToolbar(int32 p1)
 {
 	if (_game_mode != GM_MENU) PositionMainToolbar(NULL);
@@ -1205,7 +1218,7 @@
 #endif /* WIN32 */
 
 static const SettingDescGlobVarList _misc_settings[] = {
-	SDTG_MMANY("display_opt",     SLE_UINT8, S, 0, _display_opt,       (DO_SHOW_TOWN_NAMES|DO_SHOW_STATION_NAMES|DO_SHOW_SIGNS|DO_FULL_ANIMATION|DO_FULL_DETAIL|DO_TRANS_BUILDINGS|DO_WAYPOINTS), "SHOW_TOWN_NAMES|SHOW_STATION_NAMES|SHOW_SIGNS|FULL_ANIMATION|TRANS_BUILDINGS|FULL_DETAIL|WAYPOINTS", STR_NULL, NULL),
+	SDTG_MMANY("display_opt",     SLE_UINT8, S, 0, _display_opt,       (DO_SHOW_TOWN_NAMES|DO_SHOW_STATION_NAMES|DO_SHOW_SIGNS|DO_FULL_ANIMATION|DO_FULL_DETAIL|DO_WAYPOINTS), "SHOW_TOWN_NAMES|SHOW_STATION_NAMES|SHOW_SIGNS|FULL_ANIMATION|FULL_DETAIL|WAYPOINTS", STR_NULL, NULL),
 	 SDTG_BOOL("news_ticker_sound",          S, 0, _news_ticker_sound,     true,    STR_NULL, NULL),
 	 SDTG_BOOL("fullscreen",                 S, 0, _fullscreen,           false,    STR_NULL, NULL),
 	  SDTG_STR("videodriver",      SLE_STRB,C|S,0, _ini_videodriver,       NULL,    STR_NULL, NULL),
@@ -1380,6 +1393,8 @@
 	 SDT_VAR(Patches, ending_year,      SLE_INT32,0,NC|NO,2051, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_ENDING_YEAR,  NULL),
 	SDT_BOOL(Patches, smooth_economy,             0, 0,  true,            STR_CONFIG_PATCHES_SMOOTH_ECONOMY,   NULL),
 	SDT_BOOL(Patches, allow_shares,               0, 0, false,            STR_CONFIG_PATCHES_ALLOW_SHARES,     NULL),
+	SDT_CONDVAR(Patches, town_growth_rate, SLE_UINT8, 54, SL_MAX_VERSION, 0, MS, 2, 0,   4, 0, STR_CONFIG_PATCHES_TOWN_GROWTH,  NULL),
+	SDT_CONDVAR(Patches, larger_towns,     SLE_UINT8, 54, SL_MAX_VERSION, 0, D0, 4, 0, 255, 1, STR_CONFIG_PATCHES_LARGER_TOWNS, NULL),
 
 	/***************************************************************************/
 	/* AI section of the GUI-configure patches window */
@@ -1461,7 +1476,7 @@
 	SDT_CONDVAR (Patches, npf_road_drive_through_penalty, SLE_UINT, 47, SL_MAX_VERSION, 0, 0,  8 * NPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL),
 
 
-	// The maximum number of nodes to search
+	/* The maximum number of nodes to search */
 	SDT_CONDBOOL(Patches, yapf.disable_node_optimization  ,           28, SL_MAX_VERSION, 0, 0, false                   ,                       STR_NULL, NULL),
 	SDT_CONDVAR (Patches, yapf.max_search_nodes           , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 10000                   ,      500, 1000000, 0, STR_NULL, NULL),
 	SDT_CONDBOOL(Patches, yapf.rail_firstred_twoway_eol   ,           28, SL_MAX_VERSION, 0, 0,  true                   ,                       STR_NULL, NULL),
@@ -1473,22 +1488,22 @@
 	SDT_CONDVAR (Patches, yapf.rail_slope_penalty         , SLE_UINT, 28, SL_MAX_VERSION, 0, 0,     2 * YAPF_TILE_LENGTH,        0, 1000000, 0, STR_NULL, NULL),
 	SDT_CONDVAR (Patches, yapf.rail_curve45_penalty       , SLE_UINT, 28, SL_MAX_VERSION, 0, 0,     1 * YAPF_TILE_LENGTH,        0, 1000000, 0, STR_NULL, NULL),
 	SDT_CONDVAR (Patches, yapf.rail_curve90_penalty       , SLE_UINT, 28, SL_MAX_VERSION, 0, 0,     6 * YAPF_TILE_LENGTH,        0, 1000000, 0, STR_NULL, NULL),
-	// This penalty is applied when a train reverses inside a depot
+	/* This penalty is applied when a train reverses inside a depot */
 	SDT_CONDVAR (Patches, yapf.rail_depot_reverse_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0,    50 * YAPF_TILE_LENGTH,        0, 1000000, 0, STR_NULL, NULL),
-	// This is the penalty for level crossings (for trains only)
+	/* This is the penalty for level crossings (for trains only) */
 	SDT_CONDVAR (Patches, yapf.rail_crossing_penalty      , SLE_UINT, 28, SL_MAX_VERSION, 0, 0,     3 * YAPF_TILE_LENGTH,        0, 1000000, 0, STR_NULL, NULL),
-	// look-ahead how many signals are checked
+	/* look-ahead how many signals are checked */
 	SDT_CONDVAR (Patches, yapf.rail_look_ahead_max_signals, SLE_UINT, 28, SL_MAX_VERSION, 0, 0,    10                   ,        1,     100, 0, STR_NULL, NULL),
-	// look-ahead n-th red signal penalty polynomial: penalty = p2 * n^2 + p1 * n + p0
+	/* look-ahead n-th red signal penalty polynomial: penalty = p2 * n^2 + p1 * n + p0 */
 	SDT_CONDVAR (Patches, yapf.rail_look_ahead_signal_p0  , SLE_INT , 28, SL_MAX_VERSION, 0, 0,   500                   , -1000000, 1000000, 0, STR_NULL, NULL),
 	SDT_CONDVAR (Patches, yapf.rail_look_ahead_signal_p1  , SLE_INT , 28, SL_MAX_VERSION, 0, 0,  -100                   , -1000000, 1000000, 0, STR_NULL, NULL),
 	SDT_CONDVAR (Patches, yapf.rail_look_ahead_signal_p2  , SLE_INT , 28, SL_MAX_VERSION, 0, 0,     5                   , -1000000, 1000000, 0, STR_NULL, NULL),
-	// penalties for too long or too short station platforms
+	/* penalties for too long or too short station platforms */
 	SDT_CONDVAR (Patches, yapf.rail_longer_platform_penalty,           SLE_UINT, 33, SL_MAX_VERSION, 0, 0,  8 * YAPF_TILE_LENGTH, 0,   20000, 0, STR_NULL, NULL),
 	SDT_CONDVAR (Patches, yapf.rail_longer_platform_per_tile_penalty,  SLE_UINT, 33, SL_MAX_VERSION, 0, 0,  0 * YAPF_TILE_LENGTH, 0,   20000, 0, STR_NULL, NULL),
 	SDT_CONDVAR (Patches, yapf.rail_shorter_platform_penalty,          SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 40 * YAPF_TILE_LENGTH, 0,   20000, 0, STR_NULL, NULL),
 	SDT_CONDVAR (Patches, yapf.rail_shorter_platform_per_tile_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0,  0 * YAPF_TILE_LENGTH, 0,   20000, 0, STR_NULL, NULL),
-	// road vehicles - penalties
+	/* road vehicles - penalties */
 	SDT_CONDVAR (Patches, yapf.road_slope_penalty                    , SLE_UINT, 33, SL_MAX_VERSION, 0, 0,  2 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL),
 	SDT_CONDVAR (Patches, yapf.road_curve_penalty                    , SLE_UINT, 33, SL_MAX_VERSION, 0, 0,  1 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL),
 	SDT_CONDVAR (Patches, yapf.road_crossing_penalty                 , SLE_UINT, 33, SL_MAX_VERSION, 0, 0,  3 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL),
@@ -1577,7 +1592,7 @@
 
 	for (item = group->item; item != NULL; item = item->next) {
 		GRFConfig *c = CallocT<GRFConfig>(1);
-		c->filename = strdup(item->name);
+		c->full_path = strdup(item->name);
 
 		/* Parse parameters */
 		if (*item->value != '\0') {
@@ -1654,7 +1669,7 @@
 		char params[512];
 		GRFBuildParamList(params, c, lastof(params));
 
-		*item = ini_item_alloc(group, c->filename, strlen(c->filename));
+		*item = ini_item_alloc(group, c->full_path, strlen(c->full_path));
 		(*item)->value = (char*)pool_strdup(&ini->pool, params, strlen(params));
 		item = &(*item)->next;
 	}
@@ -1830,6 +1845,25 @@
 		name, value, (sd->desc.flags & SGF_0ISDISABLED) ? "(0) " : "", sd->desc.min, sd->desc.max);
 }
 
+void IConsoleListPatches()
+{
+	IConsolePrintF(_icolour_warn, "All patches with their current value:");
+
+	for (const SettingDesc *sd = _patch_settings; sd->save.cmd != SL_END; sd++) {
+		char value[80];
+		const void *ptr = GetVariableAddress((_game_mode == GM_MENU) ? &_patches_newgame : &_patches, &sd->save);
+
+		if (sd->desc.cmd == SDT_BOOLX) {
+			snprintf(value, lengthof(value), (*(bool*)ptr == 1) ? "on" : "off");
+		} else {
+			snprintf(value, lengthof(value), "%d", (uint32)ReadValue(ptr, sd->save.conv));
+		}
+		IConsolePrintF(_icolour_def, "%s = %s", sd->desc.name, value);
+	}
+
+	IConsolePrintF(_icolour_warn, "Use 'patch' command to change a value");
+}
+
 /** Save and load handler for patches/settings
  * @param osd SettingDesc struct containing all information
  * @param object can be either NULL in which case we load global variables or