(svn r15505) -Codechange: pass name of new town as parameter to CMD_BUILD_TOWN

This commit is contained in:
smatz 2009-02-16 23:23:33 +00:00
parent db0cd46a3f
commit 0878541cf2
3 changed files with 84 additions and 47 deletions

View File

@ -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

View File

@ -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,29 +1549,28 @@ 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);
}
/* Check distance to all other towns. */
if (IsCloseToTown(tile, 20)) {
return_cmd_error(STR_0238_TOO_CLOSE_TO_ANOTHER_TOWN);
}
/* 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))
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);
/* 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);

View File

@ -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);
}
};