(svn r9667) -Feature: Add the concept of cities. A (configurable) proportion of towns can

start off larger, and will grow twice as quickly as other towns. They can also
be placed specifically in the scenario editor. Thanks to TheJosh for the
initial patch and the idea.
This commit is contained in:
maedhros 2007-04-18 14:23:30 +00:00
parent 4b7c59fce1
commit 16a948a463
9 changed files with 95 additions and 32 deletions

View File

@ -751,6 +751,7 @@ STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}...ends
STR_02A1_SMALL :{BLACK}Small
STR_02A2_MEDIUM :{BLACK}Medium
STR_02A3_LARGE :{BLACK}Large
STR_SCENARIO_EDITOR_CITY :{BLACK}City
STR_02A4_SELECT_TOWN_SIZE :{BLACK}Select town size
STR_02A5_TOWN_SIZE :{YELLOW}Town size:
@ -1141,8 +1142,9 @@ STR_CONFIG_PATCHES_TOWN_GROWTH_SLOW :Slow
STR_CONFIG_PATCHES_TOWN_GROWTH_NORMAL :Normal
STR_CONFIG_PATCHES_TOWN_GROWTH_FAST :Fast
STR_CONFIG_PATCHES_TOWN_GROWTH_VERY_FAST :Very fast
STR_CONFIG_PATCHES_LARGER_TOWNS :{LTBLUE}Proportion of towns that will grow twice as fast: {ORANGE}1 in {STRING1}
STR_CONFIG_PATCHES_LARGER_TOWNS_DISABLED :{LTBLUE}Proportion of towns that will grow twice as fast: {ORANGE}None
STR_CONFIG_PATCHES_LARGER_TOWNS :{LTBLUE}Proportion of towns that will become cities: {ORANGE}1 in {STRING1}
STR_CONFIG_PATCHES_LARGER_TOWNS_DISABLED :{LTBLUE}Proportion of towns that will become cities: {ORANGE}None
STR_CONFIG_PATCHES_CITY_SIZE_MULTIPLIER :{LTBLUE}Initial city size multiplier: {ORANGE}{STRING1}
STR_CONFIG_PATCHES_GUI :{BLACK}Interface
STR_CONFIG_PATCHES_CONSTRUCTION :{BLACK}Construction

View File

@ -51,7 +51,7 @@ static int _rename_what = -1;
static byte _terraform_size = 1;
RailType _last_built_railtype;
static int _scengen_town_size = 2; // depress medium-sized towns per default
static int _scengen_town_size = 1; // depress medium-sized towns per default
extern void GenerateIndustries();
extern bool GenerateTowns();
@ -1406,7 +1406,9 @@ void CcBuildTown(bool success, TileIndex tile, uint32 p1, uint32 p2)
static void PlaceProc_Town(TileIndex tile)
{
DoCommandP(tile, _scengen_town_size, 0, CcBuildTown, CMD_BUILD_TOWN | CMD_MSG(STR_0236_CAN_T_BUILD_TOWN_HERE));
uint32 size = min(_scengen_town_size, (int)TSM_CITY);
uint32 mode = _scengen_town_size > TSM_CITY ? TSM_CITY : TSM_FIXED;
DoCommandP(tile, size, mode, CcBuildTown, CMD_BUILD_TOWN | CMD_MSG(STR_0236_CAN_T_BUILD_TOWN_HERE));
}
@ -1414,13 +1416,14 @@ static const Widget _scen_edit_town_gen_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 147, 0, 13, STR_0233_TOWN_GENERATION, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_STICKYBOX, RESIZE_NONE, 7, 148, 159, 0, 13, 0x0, STR_STICKY_BUTTON},
{ WWT_PANEL, RESIZE_NONE, 7, 0, 159, 14, 81, 0x0, STR_NULL},
{ WWT_PANEL, RESIZE_NONE, 7, 0, 159, 14, 94, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 157, 16, 27, STR_0234_NEW_TOWN, STR_0235_CONSTRUCT_NEW_TOWN},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 157, 29, 40, STR_023D_RANDOM_TOWN, STR_023E_BUILD_TOWN_IN_RANDOM_LOCATION},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 157, 42, 53, STR_MANY_RANDOM_TOWNS, STR_RANDOM_TOWNS_TIP},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 53, 68, 79, STR_02A1_SMALL, STR_02A4_SELECT_TOWN_SIZE},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 54, 105, 68, 79, STR_02A2_MEDIUM, STR_02A4_SELECT_TOWN_SIZE},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 106, 157, 68, 79, STR_02A3_LARGE, STR_02A4_SELECT_TOWN_SIZE},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 157, 81, 92, STR_SCENARIO_EDITOR_CITY, STR_02A4_SELECT_TOWN_SIZE},
{ WWT_LABEL, RESIZE_NONE, 7, 0, 147, 54, 67, STR_02A5_TOWN_SIZE, STR_NULL},
{ WIDGETS_END},
};
@ -1433,7 +1436,7 @@ static void ScenEditTownGenWndProc(Window *w, WindowEvent *e)
break;
case WE_CREATE:
LowerWindowWidget(w, (_scengen_town_size - 1)+ 7);
LowerWindowWidget(w, _scengen_town_size + 7);
break;
case WE_CLICK:
@ -1443,10 +1446,12 @@ static void ScenEditTownGenWndProc(Window *w, WindowEvent *e)
break;
case 5: {// random town
Town *t;
uint size = min(_scengen_town_size, (int)TSM_CITY);
TownSizeMode mode = _scengen_town_size > TSM_CITY ? TSM_CITY : TSM_FIXED;
HandleButtonClick(w, 5);
_generating_world = true;
t = CreateRandomTown(20, _scengen_town_size);
t = CreateRandomTown(20, mode, size);
_generating_world = false;
if (t == NULL) {
@ -1466,10 +1471,10 @@ static void ScenEditTownGenWndProc(Window *w, WindowEvent *e)
break;
}
case 7: case 8: case 9:
RaiseWindowWidget(w, (_scengen_town_size - 1) + 7);
_scengen_town_size = (e->we.click.widget - 7) + 1;
LowerWindowWidget(w, (_scengen_town_size - 1) + 7);
case 7: case 8: case 9: case 10:
RaiseWindowWidget(w, _scengen_town_size + 7);
_scengen_town_size = e->we.click.widget - 7;
LowerWindowWidget(w, _scengen_town_size + 7);
SetWindowDirty(w);
break;
}
@ -1485,14 +1490,14 @@ static void ScenEditTownGenWndProc(Window *w, WindowEvent *e)
break;
case WE_ABORT_PLACE_OBJ:
RaiseWindowButtons(w);
LowerWindowWidget(w, (_scengen_town_size - 1) + 7);
LowerWindowWidget(w, _scengen_town_size + 7);
SetWindowDirty(w);
break;
}
}
static const WindowDesc _scen_edit_town_gen_desc = {
WDP_AUTO, WDP_AUTO, 160, 82,
WDP_AUTO, WDP_AUTO, 160, 95,
WC_SCEN_TOWN_GEN, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
_scen_edit_town_gen_widgets,

View File

@ -1913,6 +1913,19 @@ bool AfterLoadGame()
}
}
/* A patch option containing the proportion of towns that grow twice as
* fast was added in version 54. From version 56 this is now saved in the
* town as cities can be built specifically in the scenario editor. */
if (CheckSavegameVersion(56)) {
Town *t;
FOR_ALL_TOWNS(t) {
if (_patches.larger_towns != 0 && (t->index % _patches.larger_towns) == 0) {
t->larger_town = true;
}
}
}
return true;
}

View File

@ -28,7 +28,7 @@
#include "variables.h"
#include <setjmp.h>
extern const uint16 SAVEGAME_VERSION = 55;
extern const uint16 SAVEGAME_VERSION = 56;
uint16 _sl_version; ///< the major savegame version identifier
byte _sl_minor_version; ///< the minor savegame version, DO NOT USE!

View File

@ -1394,8 +1394,9 @@ const SettingDesc _patch_settings[] = {
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),
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),
SDT_CONDVAR(Patches, initial_city_size, SLE_UINT8, 56, SL_MAX_VERSION, 0, 0, 2, 1, 10, 1, STR_CONFIG_PATCHES_CITY_SIZE_MULTIPLIER, NULL),
/***************************************************************************/
/* AI section of the GUI-configure patches window */

View File

@ -635,6 +635,7 @@ static const char *_patches_economy[] = {
"allow_shares",
"town_growth_rate",
"larger_towns",
"initial_city_size",
};
static const char *_patches_ai[] = {

View File

@ -141,6 +141,9 @@ struct Town {
/* Index in town array */
TownID index;
/* If this is a larger town, and should grow more quickly. */
bool larger_town;
/* NOSAVE: UpdateTownRadius updates this given the house count. */
uint16 radius[5];
@ -181,6 +184,12 @@ struct HouseSpec {
const struct GRFFile *grffile; ///< grf file that introduced this house
};
enum TownSizeMode {
TSM_RANDOM,
TSM_FIXED,
TSM_CITY
};
VARDEF HouseSpec _house_specs[HOUSE_MAX];
uint32 GetWorldPopulation();
@ -189,7 +198,7 @@ void UpdateTownVirtCoord(Town *t);
void InitializeTown();
void ShowTownViewWindow(TownID town);
void ExpandTown(Town *t);
Town *CreateRandomTown(uint attempts, uint size_mode);
Town *CreateRandomTown(uint attempts, TownSizeMode mode, uint size);
enum {
ROAD_REMOVE = 0,

View File

@ -954,7 +954,16 @@ void UpdateTownMaxPass(Town *t)
t->max_mail = t->population >> 4;
}
static void DoCreateTown(Town *t, TileIndex tile, uint32 townnameparts, uint size_mode)
/**
* Does the actual town creation.
*
* @param t The town
* @param tile Where to put it
* @param townnameparts The town name
* @param size_mode How the size should be determined
* @param size Parameter for size determination
*/
static void DoCreateTown(Town *t, TileIndex tile, uint32 townnameparts, TownSizeMode size_mode, uint size)
{
int x, i;
@ -1003,10 +1012,25 @@ static void DoCreateTown(Town *t, TileIndex tile, uint32 townnameparts, uint siz
UpdateTownVirtCoord(t);
_town_sort_dirty = true;
if (size_mode == 0) {
x = (Random() & 0xF) + 8;
} else {
x = (size_mode - 1) * 16 + 3;
/* Random town size. */
x = (Random() & 0xF) + 8;
switch (size_mode) {
default: NOT_REACHED();
case TSM_RANDOM:
t->larger_town = false;
break;
case TSM_FIXED:
x = size * 16 + 3;
t->larger_town = false;
break;
case TSM_CITY:
x *= _patches.initial_city_size;
t->larger_town = true;
break;
}
t->num_houses += x;
@ -1051,8 +1075,8 @@ static Town *AllocateTown()
* as it might be possible in the future to fund your own town :)
* @param tile coordinates where town is built
* @param flags type of operation
* @param p1 size of the town (0 = random, 1 = small, 2 = medium, 3 = large)
* @param p2 unused
* @param p1 size of the town (0 = small, 1 = medium, 2 = large)
* @param p2 size mode (@see TownSizeMode)
*/
int32 CmdBuildTown(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{
@ -1061,6 +1085,7 @@ int32 CmdBuildTown(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
/* Only in the scenario editor */
if (_game_mode != GM_EDITOR) return CMD_ERROR;
if (p2 > TSM_CITY) return CMD_ERROR;
SET_EXPENSES_TYPE(EXPENSES_OTHER);
@ -1088,13 +1113,13 @@ int32 CmdBuildTown(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
/* Create the town */
if (flags & DC_EXEC) {
_generating_world = true;
DoCreateTown(t, tile, townnameparts, p1);
DoCreateTown(t, tile, townnameparts, (TownSizeMode)p2, p1);
_generating_world = false;
}
return 0;
}
Town *CreateRandomTown(uint attempts, uint size_mode)
Town *CreateRandomTown(uint attempts, TownSizeMode mode, uint size)
{
TileIndex tile;
Town *t;
@ -1118,7 +1143,7 @@ Town *CreateRandomTown(uint attempts, uint size_mode)
t = AllocateTown();
if (t == NULL) break;
DoCreateTown(t, tile, townnameparts, size_mode);
DoCreateTown(t, tile, townnameparts, mode, size);
return t;
} while (--attempts);
return NULL;
@ -1130,17 +1155,20 @@ bool GenerateTowns()
{
uint num = 0;
uint n = ScaleByMapSize(_num_initial_towns[_opt.diff.number_towns] + (Random() & 7));
uint num_cities = _patches.larger_towns == 0 ? 0 : n / _patches.larger_towns;
SetGeneratingWorldProgress(GWP_TOWN, n);
do {
IncreaseGeneratingWorldProgress(GWP_TOWN);
/* try 20 times to create a random-sized town for the first loop. */
if (CreateRandomTown(20, 0) != NULL) num++;
TownSizeMode mode = num_cities > 0 ? TSM_CITY : TSM_RANDOM;
if (CreateRandomTown(20, mode, _patches.initial_city_size) != NULL) num++;
if (num_cities > 0) num_cities--;
} while (--n);
/* give it a last try, but now more aggressive */
if (num == 0 && CreateRandomTown(10000, 0) == NULL) {
if (num == 0 && CreateRandomTown(10000, TSM_RANDOM, 0) == NULL) {
if (GetNumTowns() == 0) {
/* XXX - can we handle that more gracefully? */
if (_game_mode != GM_EDITOR) error("Could not generate any town");
@ -1718,7 +1746,7 @@ static void UpdateTownGrowRate(Town *t)
uint growth_multiplier = _patches.town_growth_rate != 0 ? _patches.town_growth_rate - 1 : 1;
m >>= growth_multiplier;
if (_patches.larger_towns != 0 && (t->index % _patches.larger_towns) == 0) m /= 2;
if (t->larger_town) m /= 2;
t->growth_rate = m / (t->num_houses / 50 + 1);
if (m <= t->grow_counter)
@ -1977,6 +2005,9 @@ static const SaveLoad _town_desc[] = {
SLE_VAR(Town, exclusivity, SLE_UINT8),
SLE_VAR(Town, exclusive_counter, SLE_UINT8),
SLE_CONDVAR(Town, larger_town, SLE_BOOL, 56, SL_MAX_VERSION),
/* reserve extra space in savegame here. (currently 30 bytes) */
SLE_CONDNULL(30, 2, SL_MAX_VERSION),

View File

@ -226,8 +226,9 @@ struct Patches {
uint8 scrollwheel_scrolling;
uint8 scrollwheel_multiplier;
uint8 town_growth_rate; ///< Town growth rate
uint8 larger_towns; ///< 1 in the specified number of towns will grow twice as fast
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
};
VARDEF Patches _patches;