summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/town.h1
-rw-r--r--src/town_cmd.cpp122
-rw-r--r--src/town_gui.cpp8
3 files changed, 84 insertions, 47 deletions
diff --git a/src/town.h b/src/town.h
index 0f544de22..b7ee39e5a 100644
--- a/src/town.h
+++ b/src/town.h
@@ -360,6 +360,7 @@ HouseZonesBits GetTownRadiusGroup(const Town *t, TileIndex tile);
void SetTownRatingTestMode(bool mode);
uint GetMaskOfTownActions(int *nump, CompanyID cid, const Town *t);
bool GenerateTowns(TownLayout layout);
+bool GenerateTownName(uint32 *townnameparts);
/**
* Calculate a hash value from a tile position
diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp
index c3d748331..6d043be4f 100644
--- a/src/town_cmd.cpp
+++ b/src/town_cmd.cpp
@@ -1364,49 +1364,83 @@ void UpdateTownRadius(Town *t)
}
}
-static bool CreateTownName(uint32 *townnameparts)
+extern int _nb_orig_names;
+
+/**
+ * Struct holding a parameters used to generate town name.
+ * Speeds things up a bit because these values are computed only once per name generation.
+ */
+struct TownNameParams {
+ bool grf; ///< true iff a newgrf is used to generate town name
+ uint32 grfid; ///< newgrf ID
+ uint16 townnametype; ///< town name style
+
+ TownNameParams(byte town_name) :
+ grf(town_name >= _nb_orig_names),
+ grfid(this->grf ? GetGRFTownNameId(town_name - _nb_orig_names) : 0),
+ townnametype(this->grf ? GetGRFTownNameType(town_name - _nb_orig_names) : SPECSTR_TOWNNAME_START + town_name)
+ { }
+};
+
+/**
+ * Verifies the town name is valid and unique.
+ * @param r random bits
+ * @param par town name parameters
+ * @return true iff name is valid and unique
+ */
+static bool VerifyTownName(uint32 r, const TownNameParams *par)
+{
+ /* reserve space for extra unicode character and terminating '\0' */
+ char buf1[MAX_LENGTH_TOWN_NAME_BYTES + 4 + 1];
+ char buf2[MAX_LENGTH_TOWN_NAME_BYTES + 4 + 1];
+
+ SetDParam(0, r);
+ if (par->grf && par->grfid != 0) {
+ GRFTownNameGenerate(buf1, par->grfid, par->townnametype, r, lastof(buf1));
+ } else {
+ GetString(buf1, par->townnametype, lastof(buf1));
+ }
+
+ /* Check size and width */
+ if (strlen(buf1) >= MAX_LENGTH_TOWN_NAME_BYTES) return false;
+
+ const Town *t;
+ FOR_ALL_TOWNS(t) {
+ /* We can't just compare the numbers since
+ * several numbers may map to a single name. */
+ SetDParam(0, t->index);
+ GetString(buf2, STR_TOWN, lastof(buf2));
+ if (strcmp(buf1, buf2) == 0) return false;
+ }
+
+ return true;
+}
+
+/**
+ * Generates valid town name.
+ * @param townnameparts if a name is generated, it's stored there
+ * @return true iff a name was generated
+ */
+bool GenerateTownName(uint32 *townnameparts)
{
- extern int _nb_orig_names;
- Town *t2;
- char buf1[64];
- char buf2[64];
- uint32 r;
/* Do not set too low tries, since when we run out of names, we loop
* for #tries only one time anyway - then we stop generating more
* towns. Do not show it too high neither, since looping through all
* the other towns may take considerable amount of time (10000 is
* too much). */
int tries = 1000;
- bool grf = (_settings_game.game_creation.town_name >= _nb_orig_names);
- uint32 grfid = grf ? GetGRFTownNameId(_settings_game.game_creation.town_name - _nb_orig_names) : 0;
- uint16 townnametype = grf ? GetGRFTownNameType(_settings_game.game_creation.town_name - _nb_orig_names) : SPECSTR_TOWNNAME_START + _settings_game.game_creation.town_name;
+ TownNameParams par(_settings_game.game_creation.town_name);
assert(townnameparts != NULL);
for (;;) {
-restart:
- r = Random();
+ uint32 r = InteractiveRandom();
- SetDParam(0, r);
- if (grf && grfid != 0) {
- GRFTownNameGenerate(buf1, grfid, townnametype, r, lastof(buf1));
- } else {
- GetString(buf1, townnametype, lastof(buf1));
+ if (!VerifyTownName(r, &par)) {
+ if (tries-- < 0) return false;
+ continue;
}
- /* Check size and width */
- if (strlen(buf1) >= MAX_LENGTH_TOWN_NAME_BYTES || GetStringBoundingBox(buf1).width > MAX_LENGTH_TOWN_NAME_PIXELS) continue;
-
- FOR_ALL_TOWNS(t2) {
- /* We can't just compare the numbers since
- * several numbers may map to a single name. */
- SetDParam(0, t2->index);
- GetString(buf2, STR_TOWN, lastof(buf2));
- if (strcmp(buf1, buf2) == 0) {
- if (tries-- < 0) return false;
- goto restart;
- }
- }
*townnameparts = r;
return true;
}
@@ -1429,8 +1463,6 @@ void UpdateTownMaxPass(Town *t)
*/
static void DoCreateTown(Town *t, TileIndex tile, uint32 townnameparts, TownSize size, bool city, TownLayout layout)
{
- extern int _nb_orig_names;
-
t->xy = tile;
t->num_houses = 0;
t->time_until_rebuild = 10;
@@ -1485,8 +1517,6 @@ static void DoCreateTown(Town *t, TileIndex tile, uint32 townnameparts, TownSize
if (size == TS_RANDOM) x = (Random() & 0xF) + 8;
if (city) x *= _settings_game.economy.initial_city_size;
- t->noise_reached = 0;
-
t->num_houses += x;
UpdateTownRadius(t);
@@ -1498,6 +1528,7 @@ static void DoCreateTown(Town *t, TileIndex tile, uint32 townnameparts, TownSize
t->num_houses -= x;
UpdateTownRadius(t);
UpdateTownMaxPass(t);
+ UpdateAirportsNoise();
}
/** Create a new town.
@@ -1508,7 +1539,7 @@ static void DoCreateTown(Town *t, TileIndex tile, uint32 townnameparts, TownSize
* @param p1 0..1 size of the town (@see TownSize)
* 2 true iff it should be a city
* 3..5 town road layout (@see TownLayout)
- * @param p2 unused
+ * @param p2 town name parts
*/
CommandCost CmdBuildTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
@@ -1518,28 +1549,27 @@ CommandCost CmdBuildTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
TownSize size = (TownSize)GB(p1, 0, 2);
bool city = HasBit(p1, 2);
TownLayout layout = (TownLayout)GB(p1, 3, 3);
+ TownNameParams par(_settings_game.game_creation.town_name);
+ uint32 townnameparts = p2;
if (size > TS_RANDOM) return CMD_ERROR;
if (layout > TL_RANDOM) return CMD_ERROR;
+ if (!VerifyTownName(townnameparts, &par)) return_cmd_error(STR_NAME_MUST_BE_UNIQUE);
/* Check if too close to the edge of map */
- if (DistanceFromEdge(tile) < 12)
+ if (DistanceFromEdge(tile) < 12) {
return_cmd_error(STR_0237_TOO_CLOSE_TO_EDGE_OF_MAP);
-
- /* Can only build on clear flat areas, possibly with trees. */
- if ((!IsTileType(tile, MP_CLEAR) && !IsTileType(tile, MP_TREES)) || GetTileSlope(tile, NULL) != SLOPE_FLAT) {
- return_cmd_error(STR_0239_SITE_UNSUITABLE);
}
/* Check distance to all other towns. */
- if (IsCloseToTown(tile, 20))
+ if (IsCloseToTown(tile, 20)) {
return_cmd_error(STR_0238_TOO_CLOSE_TO_ANOTHER_TOWN);
+ }
- uint32 townnameparts;
-
- /* Get a unique name for the town. */
- if (!CreateTownName(&townnameparts))
- return_cmd_error(STR_023A_TOO_MANY_TOWNS);
+ /* Can only build on clear flat areas, possibly with trees. */
+ if ((!IsTileType(tile, MP_CLEAR) && !IsTileType(tile, MP_TREES)) || GetTileSlope(tile, NULL) != SLOPE_FLAT) {
+ return_cmd_error(STR_0239_SITE_UNSUITABLE);
+ }
/* Allocate town struct */
if (!Town::CanAllocateItem()) return_cmd_error(STR_023A_TOO_MANY_TOWNS);
@@ -1583,7 +1613,7 @@ Town *CreateRandomTown(uint attempts, TownSize size, bool city, TownLayout layou
uint32 townnameparts;
/* Get a unique name for the town. */
- if (!CreateTownName(&townnameparts)) break;
+ if (!GenerateTownName(&townnameparts)) break;
/* Allocate a town struct */
Town *t = new Town(tile);
diff --git a/src/town_gui.cpp b/src/town_gui.cpp
index 0a5f24ad0..7a3aac6ad 100644
--- a/src/town_gui.cpp
+++ b/src/town_gui.cpp
@@ -752,7 +752,13 @@ public:
static void PlaceProc_Town(TileIndex tile)
{
- DoCommandP(tile, town_size | city << 2 | town_layout << 3, 0, CMD_BUILD_TOWN | CMD_MSG(STR_0236_CAN_T_BUILD_TOWN_HERE), CcBuildTown);
+ uint32 townnameparts;
+ if (!GenerateTownName(&townnameparts)) {
+ ShowErrorMessage(STR_023A_TOO_MANY_TOWNS, STR_0236_CAN_T_BUILD_TOWN_HERE, 0, 0);
+ return;
+ }
+
+ DoCommandP(tile, town_size | city << 2 | town_layout << 3, townnameparts, CMD_BUILD_TOWN | CMD_MSG(STR_0236_CAN_T_BUILD_TOWN_HERE), CcBuildTown);
}
};