# HG changeset patch # User pasky # Date 1110030583 0 # Node ID 0532cbf429f14464c008f55580631f7eaef3d5c9 # Parent 83e74e76f6001089ef79082be973ad2c8ca4b1ca (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. diff -r 83e74e76f600 -r 0532cbf429f1 town_cmd.c --- a/town_cmd.c Fri Mar 04 10:34:44 2005 +0000 +++ b/town_cmd.c Sat Mar 05 13:49:43 2005 +0000 @@ -864,21 +864,28 @@ } } -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 @@ 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 @@ 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 @@ 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 @@ uint tile = TILE_FROM_XY(x,y); TileInfo ti; Town *t; + uint32 townnameparts; SET_EXPENSES_TYPE(EXPENSES_OTHER); @@ -1013,6 +1026,10 @@ 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 @@ // 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 @@ uint tile; TileInfo ti; Town *t; + uint32 townnameparts; do { // Generate a tile index not too close from the edge @@ -1048,12 +1066,16 @@ 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;