summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpasky <pasky@openttd.org>2005-03-05 13:49:43 +0000
committerpasky <pasky@openttd.org>2005-03-05 13:49:43 +0000
commit7616f7c36297949e4758f47153feb32e0cf60be3 (patch)
tree50d8f7f31a9f74b035023001dc92b05e072b13da
parent4b7fd34129fc7f10ebe743370d4e611022e5283e (diff)
downloadopenttd-7616f7c36297949e4758f47153feb32e0cf60be3.tar.xz
(svn r1925) Fixed an infinite loop if the town generator runs out of town names. The number of generated towns is then limited by the number of available names.
-rw-r--r--town_cmd.c44
1 files changed, 33 insertions, 11 deletions
diff --git a/town_cmd.c b/town_cmd.c
index 104f2ca06..afdd0fb01 100644
--- a/town_cmd.c
+++ b/town_cmd.c
@@ -864,21 +864,28 @@ static void UpdateTownRadius(Town *t)
}
}
-static void CreateTownName(Town *t1)
+static bool CreateTownName(uint32 *townnameparts)
{
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;
+ uint16 townnametype = SPECSTR_TOWNNAME_START + _opt.town_name;
- t1->townnametype = SPECSTR_TOWNNAME_START + _opt.town_name;
+ assert(townnameparts);
for(;;) {
restart:
r = Random();
SetDParam(0, r);
- GetString(buf1, t1->townnametype);
+ GetString(buf1, townnametype);
// Check size and width
if (strlen(buf1) >= 31 || GetStringWidth(buf1) > 130)
@@ -886,15 +893,19 @@ restart:
FOR_ALL_TOWNS(t2) {
if (t2->xy != 0) {
+ // We can't just compare the numbers since
+ // several numbers may map to a single name.
SetDParam(0, t2->townnameparts);
GetString(buf2, t2->townnametype);
- if (strcmp(buf1, buf2) == 0)
+ if (strcmp(buf1, buf2) == 0) {
+ if (tries-- < 0)
+ return false;
goto restart;
+ }
}
}
- t1->townnameparts = r;
-
- return;
+ *townnameparts = r;
+ return true;
}
}
@@ -904,7 +915,7 @@ void UpdateTownMaxPass(Town *t)
t->max_mail = t->population >> 4;
}
-static void DoCreateTown(Town *t, TileIndex tile)
+static void DoCreateTown(Town *t, TileIndex tile, uint32 townnameparts)
{
int x, i;
@@ -946,7 +957,8 @@ static void DoCreateTown(Town *t, TileIndex tile)
t->exclusive_counter = 0;
t->statues = 0;
- CreateTownName(t);
+ t->townnametype = SPECSTR_TOWNNAME_START + _opt.town_name;
+ t->townnameparts = townnameparts;
UpdateTownVirtCoord(t);
_town_sort_dirty = true;
@@ -997,6 +1009,7 @@ int32 CmdBuildTown(int x, int y, uint32 flags, uint32 p1, uint32 p2)
uint tile = TILE_FROM_XY(x,y);
TileInfo ti;
Town *t;
+ uint32 townnameparts;
SET_EXPENSES_TYPE(EXPENSES_OTHER);
@@ -1013,6 +1026,10 @@ int32 CmdBuildTown(int x, int y, uint32 flags, uint32 p1, uint32 p2)
if (IsCloseToTown(tile, 20))
return_cmd_error(STR_0238_TOO_CLOSE_TO_ANOTHER_TOWN);
+ // Get a unique name for the town.
+ if (!CreateTownName(&townnameparts))
+ return_cmd_error(STR_023A_TOO_MANY_TOWNS);
+
// Allocate town struct
t = AllocateTown();
if (t == NULL)
@@ -1021,7 +1038,7 @@ int32 CmdBuildTown(int x, int y, uint32 flags, uint32 p1, uint32 p2)
// Create the town
if (flags & DC_EXEC) {
_generating_world = true;
- DoCreateTown(t, tile);
+ DoCreateTown(t, tile, townnameparts);
_generating_world = false;
}
return 0;
@@ -1032,6 +1049,7 @@ Town *CreateRandomTown(uint attempts)
uint tile;
TileInfo ti;
Town *t;
+ uint32 townnameparts;
do {
// Generate a tile index not too close from the edge
@@ -1048,12 +1066,16 @@ Town *CreateRandomTown(uint attempts)
if (IsCloseToTown(tile, 20))
continue;
+ // Get a unique name for the town.
+ if (!CreateTownName(&townnameparts))
+ break;
+
// Allocate a town struct
t = AllocateTown();
if (t == NULL)
break;
- DoCreateTown(t, tile);
+ DoCreateTown(t, tile, townnameparts);
return t;
} while (--attempts);
return NULL;