2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8 /** @file townname.cpp %Town name generators. */
11 #include "string_func.h"
12 #include "townname_type.h"
14 #include "strings_func.h"
15 #include "core/random_func.hpp"
17 #include "gfx_layout.h"
19 #include "table/townname.h"
21 #include "safeguards.h"
25 * Initializes this struct from town data
26 * @param t town for which we will be printing name later
28 TownNameParams::TownNameParams(const Town
*t
) :
29 grfid(t
->townnamegrfid
), // by default, use supplied data
32 if (t
->townnamegrfid
!= 0 && GetGRFTownName(t
->townnamegrfid
) == nullptr) {
33 /* Fallback to english original */
35 this->type
= SPECSTR_TOWNNAME_ENGLISH
;
42 * Fills buffer with specified town name
43 * @param buff buffer start
44 * @param par town name parameters
45 * @param townnameparts 'encoded' town name
46 * @param last end of buffer
47 * @return pointer to terminating '\0'
49 char *GetTownName(char *buff
, const TownNameParams
*par
, uint32 townnameparts
, const char *last
)
51 if (par
->grfid
== 0) {
52 int64 args_array
[1] = { townnameparts
};
53 StringParameters
tmp_params(args_array
);
54 return GetStringWithArgs(buff
, par
->type
, &tmp_params
, last
);
57 return GRFTownNameGenerate(buff
, par
->grfid
, par
->type
, townnameparts
, last
);
62 * Fills buffer with town's name
63 * @param buff buffer start
64 * @param t we want to get name of this town
65 * @param last end of buffer
66 * @return pointer to terminating '\0'
68 char *GetTownName(char *buff
, const Town
*t
, const char *last
)
70 TownNameParams
par(t
);
71 return GetTownName(buff
, &par
, t
->townnameparts
, last
);
76 * Verifies the town name is valid and unique.
77 * @param r random bits
78 * @param par town name parameters
79 * @param town_names if a name is generated, check its uniqueness with the set
80 * @return true iff name is valid and unique
82 bool VerifyTownName(uint32 r
, const TownNameParams
*par
, TownNames
*town_names
)
84 /* reserve space for extra unicode character and terminating '\0' */
85 char buf1
[(MAX_LENGTH_TOWN_NAME_CHARS
+ 1) * MAX_CHAR_LENGTH
];
86 char buf2
[(MAX_LENGTH_TOWN_NAME_CHARS
+ 1) * MAX_CHAR_LENGTH
];
88 GetTownName(buf1
, par
, r
, lastof(buf1
));
90 /* Check size and width */
91 if (Utf8StringLength(buf1
) >= MAX_LENGTH_TOWN_NAME_CHARS
) return false;
93 if (town_names
!= nullptr) {
94 if (town_names
->find(buf1
) != town_names
->end()) return false;
95 town_names
->insert(buf1
);
97 for (const Town
*t
: Town::Iterate()) {
98 /* We can't just compare the numbers since
99 * several numbers may map to a single name. */
100 const char *buf
= t
->name
.empty() ? nullptr : t
->name
.c_str();
101 if (buf
== nullptr) {
102 GetTownName(buf2
, t
, lastof(buf2
));
105 if (strcmp(buf1
, buf
) == 0) return false;
114 * Generates valid town name.
115 * @param townnameparts if a name is generated, it's stored there
116 * @param town_names if a name is generated, check its uniqueness with the set
117 * @return true iff a name was generated
119 bool GenerateTownName(uint32
*townnameparts
, TownNames
*town_names
)
121 TownNameParams
par(_settings_game
.game_creation
.town_name
);
123 /* This function is called very often without entering the gameloop
124 * in between. So reset layout cache to prevent it from growing too big. */
125 Layouter::ReduceLineCache();
127 /* Do not set i too low, since when we run out of names, we loop
128 * for #tries only one time anyway - then we stop generating more
129 * towns. Do not set it too high either, since looping through all
130 * the other towns may take considerable amount of time (10000 is
132 for (int i
= 1000; i
!= 0; i
--) {
133 uint32 r
= _generating_world
? Random() : InteractiveRandom();
134 if (!VerifyTownName(r
, &par
, town_names
)) continue;
146 * Generates a number from given seed.
147 * @param shift_by number of bits seed is shifted to the right
148 * @param max generated number is in interval 0...max-1
150 * @return seed transformed to a number from given range
152 static inline uint32
SeedChance(byte shift_by
, int max
, uint32 seed
)
154 return (GB(seed
, shift_by
, 16) * max
) >> 16;
159 * Generates a number from given seed. Uses different algorithm than SeedChance().
160 * @param shift_by number of bits seed is shifted to the right
161 * @param max generated number is in interval 0...max-1
163 * @return seed transformed to a number from given range
165 static inline uint32
SeedModChance(byte shift_by
, int max
, uint32 seed
)
167 /* This actually gives *MUCH* more even distribution of the values
168 * than SeedChance(), which is absolutely horrible in that. If
169 * you do not believe me, try with i.e. the Czech town names,
170 * compare the words (nicely visible on prefixes) generated by
171 * SeedChance() and SeedModChance(). Do not get discouraged by the
172 * never-use-modulo myths, which hold true only for the linear
173 * congruential generators (and Random() isn't such a generator).
175 * TODO: Perhaps we should use it for all the name generators? --pasky */
176 return (seed
>> shift_by
) % max
;
181 * Generates a number from given seed.
182 * @param shift_by number of bits seed is shifted to the right
183 * @param max generated number is in interval -bias...max-1
185 * @param bias minimum value that can be returned
186 * @return seed transformed to a number from given range
188 static inline int32
SeedChanceBias(byte shift_by
, int max
, uint32 seed
, int bias
)
190 return SeedChance(shift_by
, max
+ bias
, seed
) - bias
;
195 * Replaces a string beginning in 'org' with 'rep'.
196 * @param org string to replace, has to be 4 characters long
197 * @param rep string to be replaced with, has to be 4 characters long
198 * @param buf buffer with string
200 static void ReplaceWords(const char *org
, const char *rep
, char *buf
)
202 assert(strlen(org
) == 4 && strlen(rep
) == 4 && strlen(buf
) >= 4);
203 if (strncmp(buf
, org
, 4) == 0) memcpy(buf
, rep
, 4); // Safe as the string in buf is always more than 4 characters long.
208 * Replaces english curses and ugly letter combinations by nicer ones.
209 * @param buf buffer with town name
210 * @param original English (Original) generator was used
212 static void ReplaceEnglishWords(char *buf
, bool original
)
214 ReplaceWords("Cunt", "East", buf
);
215 ReplaceWords("Slag", "Pits", buf
);
216 ReplaceWords("Slut", "Edin", buf
);
217 if (!original
) ReplaceWords("Fart", "Boot", buf
); // never happens with 'English (Original)'
218 ReplaceWords("Drar", "Quar", buf
);
219 ReplaceWords("Dreh", "Bash", buf
);
220 ReplaceWords("Frar", "Shor", buf
);
221 ReplaceWords("Grar", "Aber", buf
);
222 ReplaceWords("Brar", "Over", buf
);
223 ReplaceWords("Wrar", original
? "Inve" : "Stan", buf
);
227 * Generates English (Original) town name from given seed.
228 * @param buf output buffer
229 * @param seed town name seed
230 * @param last end of buffer
232 static char *MakeEnglishOriginalTownName(char *buf
, const char *last
, uint32 seed
)
236 /* optional first segment */
237 int i
= SeedChanceBias(0, lengthof(_name_original_english_1
), seed
, 50);
238 if (i
>= 0) buf
= strecpy(buf
, _name_original_english_1
[i
], last
);
240 /* mandatory middle segments */
241 buf
= strecpy(buf
, _name_original_english_2
[SeedChance(4, lengthof(_name_original_english_2
), seed
)], last
);
242 buf
= strecpy(buf
, _name_original_english_3
[SeedChance(7, lengthof(_name_original_english_3
), seed
)], last
);
243 buf
= strecpy(buf
, _name_original_english_4
[SeedChance(10, lengthof(_name_original_english_4
), seed
)], last
);
244 buf
= strecpy(buf
, _name_original_english_5
[SeedChance(13, lengthof(_name_original_english_5
), seed
)], last
);
246 /* optional last segment */
247 i
= SeedChanceBias(15, lengthof(_name_original_english_6
), seed
, 60);
248 if (i
>= 0) buf
= strecpy(buf
, _name_original_english_6
[i
], last
);
250 /* Ce, Ci => Ke, Ki */
251 if (orig
[0] == 'C' && (orig
[1] == 'e' || orig
[1] == 'i')) {
255 assert(buf
- orig
>= 4);
256 ReplaceEnglishWords(orig
, true);
263 * Generates English (Additional) town name from given seed.
264 * @param buf output buffer
265 * @param seed town name seed
266 * @param last end of buffer
268 static char *MakeEnglishAdditionalTownName(char *buf
, const char *last
, uint32 seed
)
272 /* optional first segment */
273 int i
= SeedChanceBias(0, lengthof(_name_additional_english_prefix
), seed
, 50);
274 if (i
>= 0) buf
= strecpy(buf
, _name_additional_english_prefix
[i
], last
);
276 if (SeedChance(3, 20, seed
) >= 14) {
277 buf
= strecpy(buf
, _name_additional_english_1a
[SeedChance(6, lengthof(_name_additional_english_1a
), seed
)], last
);
279 buf
= strecpy(buf
, _name_additional_english_1b1
[SeedChance(6, lengthof(_name_additional_english_1b1
), seed
)], last
);
280 buf
= strecpy(buf
, _name_additional_english_1b2
[SeedChance(9, lengthof(_name_additional_english_1b2
), seed
)], last
);
281 if (SeedChance(11, 20, seed
) >= 4) {
282 buf
= strecpy(buf
, _name_additional_english_1b3a
[SeedChance(12, lengthof(_name_additional_english_1b3a
), seed
)], last
);
284 buf
= strecpy(buf
, _name_additional_english_1b3b
[SeedChance(12, lengthof(_name_additional_english_1b3b
), seed
)], last
);
288 buf
= strecpy(buf
, _name_additional_english_2
[SeedChance(14, lengthof(_name_additional_english_2
), seed
)], last
);
290 /* optional last segment */
291 i
= SeedChanceBias(15, lengthof(_name_additional_english_3
), seed
, 60);
292 if (i
>= 0) buf
= strecpy(buf
, _name_additional_english_3
[i
], last
);
294 assert(buf
- orig
>= 4);
295 ReplaceEnglishWords(orig
, false);
302 * Generates Austrian town name from given seed.
303 * @param buf output buffer
304 * @param seed town name seed
305 * @param last end of buffer
307 static char *MakeAustrianTownName(char *buf
, const char *last
, uint32 seed
)
309 /* Bad, Maria, Gross, ... */
310 int i
= SeedChanceBias(0, lengthof(_name_austrian_a1
), seed
, 15);
311 if (i
>= 0) buf
= strecpy(buf
, _name_austrian_a1
[i
], last
);
315 i
= SeedChance(4, 6, seed
);
317 /* Kaisers-kirchen */
318 buf
= strecpy(buf
, _name_austrian_a2
[SeedChance( 7, lengthof(_name_austrian_a2
), seed
)], last
);
319 buf
= strecpy(buf
, _name_austrian_a3
[SeedChance(13, lengthof(_name_austrian_a3
), seed
)], last
);
322 buf
= strecpy(buf
, _name_austrian_a5
[SeedChance( 7, lengthof(_name_austrian_a5
), seed
)], last
);
323 buf
= strecpy(buf
, _name_austrian_a6
[SeedChance( 9, lengthof(_name_austrian_a6
), seed
)], last
);
324 j
= 1; // More likely to have a " an der " or " am "
327 buf
= strecpy(buf
, _name_austrian_a4
[SeedChance( 7, lengthof(_name_austrian_a4
), seed
)], last
);
330 i
= SeedChance(1, 6, seed
);
332 /* an der Donau (rivers) */
333 buf
= strecpy(buf
, _name_austrian_f1
[SeedChance(4, lengthof(_name_austrian_f1
), seed
)], last
);
334 buf
= strecpy(buf
, _name_austrian_f2
[SeedChance(5, lengthof(_name_austrian_f2
), seed
)], last
);
335 } else if (i
>= 2 - j
) {
336 /* am Dachstein (mountains) */
337 buf
= strecpy(buf
, _name_austrian_b1
[SeedChance(4, lengthof(_name_austrian_b1
), seed
)], last
);
338 buf
= strecpy(buf
, _name_austrian_b2
[SeedChance(5, lengthof(_name_austrian_b2
), seed
)], last
);
346 * Generates German town name from given seed.
347 * @param buf output buffer
348 * @param seed town name seed
349 * @param last end of buffer
351 static char *MakeGermanTownName(char *buf
, const char *last
, uint32 seed
)
353 uint seed_derivative
= SeedChance(7, 28, seed
);
355 /* optional prefix */
356 if (seed_derivative
== 12 || seed_derivative
== 19) {
357 uint i
= SeedChance(2, lengthof(_name_german_pre
), seed
);
358 buf
= strecpy(buf
, _name_german_pre
[i
], last
);
361 /* mandatory middle segments including option of hardcoded name */
362 uint i
= SeedChance(3, lengthof(_name_german_real
) + lengthof(_name_german_1
), seed
);
363 if (i
< lengthof(_name_german_real
)) {
364 buf
= strecpy(buf
, _name_german_real
[i
], last
);
366 buf
= strecpy(buf
, _name_german_1
[i
- lengthof(_name_german_real
)], last
);
368 i
= SeedChance(5, lengthof(_name_german_2
), seed
);
369 buf
= strecpy(buf
, _name_german_2
[i
], last
);
372 /* optional suffix */
373 if (seed_derivative
== 24) {
374 i
= SeedChance(9, lengthof(_name_german_4_an_der
) + lengthof(_name_german_4_am
), seed
);
375 if (i
< lengthof(_name_german_4_an_der
)) {
376 buf
= strecpy(buf
, _name_german_3_an_der
[0], last
);
377 buf
= strecpy(buf
, _name_german_4_an_der
[i
], last
);
379 buf
= strecpy(buf
, _name_german_3_am
[0], last
);
380 buf
= strecpy(buf
, _name_german_4_am
[i
- lengthof(_name_german_4_an_der
)], last
);
389 * Generates Latin-American town name from given seed.
390 * @param buf output buffer
391 * @param seed town name seed
392 * @param last end of buffer
394 static char *MakeSpanishTownName(char *buf
, const char *last
, uint32 seed
)
396 return strecpy(buf
, _name_spanish_real
[SeedChance(0, lengthof(_name_spanish_real
), seed
)], last
);
401 * Generates French town name from given seed.
402 * @param buf output buffer
403 * @param seed town name seed
404 * @param last end of buffer
406 static char *MakeFrenchTownName(char *buf
, const char *last
, uint32 seed
)
408 return strecpy(buf
, _name_french_real
[SeedChance(0, lengthof(_name_french_real
), seed
)], last
);
413 * Generates Silly town name from given seed.
414 * @param buf output buffer
415 * @param seed town name seed
416 * @param last end of buffer
418 static char *MakeSillyTownName(char *buf
, const char *last
, uint32 seed
)
420 buf
= strecpy(buf
, _name_silly_1
[SeedChance( 0, lengthof(_name_silly_1
), seed
)], last
);
421 buf
= strecpy(buf
, _name_silly_2
[SeedChance(16, lengthof(_name_silly_2
), seed
)], last
);
428 * Generates Swedish town name from given seed.
429 * @param buf output buffer
430 * @param seed town name seed
431 * @param last end of buffer
433 static char *MakeSwedishTownName(char *buf
, const char *last
, uint32 seed
)
435 /* optional first segment */
436 int i
= SeedChanceBias(0, lengthof(_name_swedish_1
), seed
, 50);
437 if (i
>= 0) buf
= strecpy(buf
, _name_swedish_1
[i
], last
);
439 /* mandatory middle segments including option of hardcoded name */
440 if (SeedChance(4, 5, seed
) >= 3) {
441 buf
= strecpy(buf
, _name_swedish_2
[SeedChance( 7, lengthof(_name_swedish_2
), seed
)], last
);
443 buf
= strecpy(buf
, _name_swedish_2a
[SeedChance( 7, lengthof(_name_swedish_2a
), seed
)], last
);
444 buf
= strecpy(buf
, _name_swedish_2b
[SeedChance(10, lengthof(_name_swedish_2b
), seed
)], last
);
445 buf
= strecpy(buf
, _name_swedish_2c
[SeedChance(13, lengthof(_name_swedish_2c
), seed
)], last
);
448 buf
= strecpy(buf
, _name_swedish_3
[SeedChance(16, lengthof(_name_swedish_3
), seed
)], last
);
455 * Generates Dutch town name from given seed.
456 * @param buf output buffer
457 * @param seed town name seed
458 * @param last end of buffer
460 static char *MakeDutchTownName(char *buf
, const char *last
, uint32 seed
)
462 /* optional first segment */
463 int i
= SeedChanceBias(0, lengthof(_name_dutch_1
), seed
, 50);
464 if (i
>= 0) buf
= strecpy(buf
, _name_dutch_1
[i
], last
);
466 /* mandatory middle segments including option of hardcoded name */
467 if (SeedChance(6, 9, seed
) > 4) {
468 buf
= strecpy(buf
, _name_dutch_2
[SeedChance( 9, lengthof(_name_dutch_2
), seed
)], last
);
470 buf
= strecpy(buf
, _name_dutch_3
[SeedChance( 9, lengthof(_name_dutch_3
), seed
)], last
);
471 buf
= strecpy(buf
, _name_dutch_4
[SeedChance(12, lengthof(_name_dutch_4
), seed
)], last
);
474 buf
= strecpy(buf
, _name_dutch_5
[SeedChance(15, lengthof(_name_dutch_5
), seed
)], last
);
481 * Generates Finnish town name from given seed.
482 * @param buf output buffer
483 * @param seed town name seed
484 * @param last end of buffer
486 static char *MakeFinnishTownName(char *buf
, const char *last
, uint32 seed
)
490 /* Select randomly if town name should consists of one or two parts. */
491 if (SeedChance(0, 15, seed
) >= 10) {
492 return strecpy(buf
, _name_finnish_real
[SeedChance(2, lengthof(_name_finnish_real
), seed
)], last
);
495 if (SeedChance(0, 15, seed
) >= 5) {
496 /* A two-part name by combining one of _name_finnish_1 + "la"/"lä"
497 * The reason for not having the contents of _name_finnish_{1,2} in the same table is
498 * that the ones in _name_finnish_2 are not good for this purpose. */
499 uint sel
= SeedChance( 0, lengthof(_name_finnish_1
), seed
);
500 buf
= strecpy(buf
, _name_finnish_1
[sel
], last
);
503 if (*end
== 'i') *end
= 'e';
504 if (strstr(orig
, "a") != nullptr || strstr(orig
, "o") != nullptr || strstr(orig
, "u") != nullptr ||
505 strstr(orig
, "A") != nullptr || strstr(orig
, "O") != nullptr || strstr(orig
, "U") != nullptr) {
506 buf
= strecpy(buf
, "la", last
);
508 buf
= strecpy(buf
, u8
"l\u00e4", last
);
513 /* A two-part name by combining one of _name_finnish_{1,2} + _name_finnish_3.
514 * Why aren't _name_finnish_{1,2} just one table? See above. */
515 uint sel
= SeedChance(2, lengthof(_name_finnish_1
) + lengthof(_name_finnish_2
), seed
);
516 if (sel
>= lengthof(_name_finnish_1
)) {
517 buf
= strecpy(buf
, _name_finnish_2
[sel
- lengthof(_name_finnish_1
)], last
);
519 buf
= strecpy(buf
, _name_finnish_1
[sel
], last
);
522 buf
= strecpy(buf
, _name_finnish_3
[SeedChance(10, lengthof(_name_finnish_3
), seed
)], last
);
529 * Generates Polish town name from given seed.
530 * @param buf output buffer
531 * @param seed town name seed
532 * @param last end of buffer
534 static char *MakePolishTownName(char *buf
, const char *last
, uint32 seed
)
536 /* optional first segment */
537 uint i
= SeedChance(0,
538 lengthof(_name_polish_2_o
) + lengthof(_name_polish_2_m
) +
539 lengthof(_name_polish_2_f
) + lengthof(_name_polish_2_n
),
541 uint j
= SeedChance(2, 20, seed
);
544 if (i
< lengthof(_name_polish_2_o
)) {
545 return strecpy(buf
, _name_polish_2_o
[SeedChance(3, lengthof(_name_polish_2_o
), seed
)], last
);
548 if (i
< lengthof(_name_polish_2_m
) + lengthof(_name_polish_2_o
)) {
550 buf
= strecpy(buf
, _name_polish_1_m
[SeedChance(5, lengthof(_name_polish_1_m
), seed
)], last
);
553 buf
= strecpy(buf
, _name_polish_2_m
[SeedChance(7, lengthof(_name_polish_2_m
), seed
)], last
);
555 if (j
>= 4 && j
< 16) {
556 buf
= strecpy(buf
, _name_polish_3_m
[SeedChance(10, lengthof(_name_polish_3_m
), seed
)], last
);
562 if (i
< lengthof(_name_polish_2_f
) + lengthof(_name_polish_2_m
) + lengthof(_name_polish_2_o
)) {
564 buf
= strecpy(buf
, _name_polish_1_f
[SeedChance(5, lengthof(_name_polish_1_f
), seed
)], last
);
567 buf
= strecpy(buf
, _name_polish_2_f
[SeedChance(7, lengthof(_name_polish_2_f
), seed
)], last
);
569 if (j
>= 4 && j
< 16) {
570 buf
= strecpy(buf
, _name_polish_3_f
[SeedChance(10, lengthof(_name_polish_3_f
), seed
)], last
);
577 buf
= strecpy(buf
, _name_polish_1_n
[SeedChance(5, lengthof(_name_polish_1_n
), seed
)], last
);
580 buf
= strecpy(buf
, _name_polish_2_n
[SeedChance(7, lengthof(_name_polish_2_n
), seed
)], last
);
582 if (j
>= 4 && j
< 16) {
583 buf
= strecpy(buf
, _name_polish_3_n
[SeedChance(10, lengthof(_name_polish_3_n
), seed
)], last
);
591 * Generates Czech town name from given seed.
592 * @param buf output buffer
593 * @param seed town name seed
594 * @param last end of buffer
596 static char *MakeCzechTownName(char *buf
, const char *last
, uint32 seed
)
598 /* 1:3 chance to use a real name. */
599 if (SeedModChance(0, 4, seed
) == 0) {
600 return strecpy(buf
, _name_czech_real
[SeedModChance(4, lengthof(_name_czech_real
), seed
)], last
);
603 [[maybe_unused
]] const char *orig
= buf
;
605 /* Probability of prefixes/suffixes
606 * 0..11 prefix, 12..13 prefix+suffix, 14..17 suffix, 18..31 nothing */
607 int prob_tails
= SeedModChance(2, 32, seed
);
608 bool do_prefix
= prob_tails
< 12;
609 bool do_suffix
= prob_tails
> 11 && prob_tails
< 17;
612 /* IDs of the respective parts */
613 int prefix
= 0, ending
= 0, suffix
= 0;
617 /* The select criteria. */
622 if (do_prefix
) prefix
= SeedModChance(5, lengthof(_name_czech_adj
) * 12, seed
) / 12;
623 if (do_suffix
) suffix
= SeedModChance(7, lengthof(_name_czech_suffix
), seed
);
624 /* 3:1 chance 3:1 to use dynamic substantive */
625 stem
= SeedModChance(9,
626 lengthof(_name_czech_subst_full
) + 3 * lengthof(_name_czech_subst_stem
),
628 if (stem
< lengthof(_name_czech_subst_full
)) {
630 dynamic_subst
= false;
631 gender
= _name_czech_subst_full
[stem
].gender
;
632 choose
= _name_czech_subst_full
[stem
].choose
;
633 allow
= _name_czech_subst_full
[stem
].allow
;
635 uint map
[lengthof(_name_czech_subst_ending
)];
636 int ending_start
= -1, ending_stop
= -1;
638 /* Load the substantive */
639 dynamic_subst
= true;
640 stem
-= lengthof(_name_czech_subst_full
);
641 stem
%= lengthof(_name_czech_subst_stem
);
642 gender
= _name_czech_subst_stem
[stem
].gender
;
643 choose
= _name_czech_subst_stem
[stem
].choose
;
644 allow
= _name_czech_subst_stem
[stem
].allow
;
646 /* Load the postfix (1:1 chance that a postfix will be inserted) */
647 postfix
= SeedModChance(14, lengthof(_name_czech_subst_postfix
) * 2, seed
);
649 if (choose
& CZC_POSTFIX
) {
650 /* Always get a real postfix. */
651 postfix
%= lengthof(_name_czech_subst_postfix
);
653 if (choose
& CZC_NOPOSTFIX
) {
654 /* Always drop a postfix. */
655 postfix
+= lengthof(_name_czech_subst_postfix
);
657 if (postfix
< lengthof(_name_czech_subst_postfix
)) {
658 choose
|= CZC_POSTFIX
;
660 choose
|= CZC_NOPOSTFIX
;
663 /* Localize the array segment containing a good gender */
664 for (ending
= 0; ending
< (int)lengthof(_name_czech_subst_ending
); ending
++) {
665 const CzechNameSubst
*e
= &_name_czech_subst_ending
[ending
];
667 if (gender
== CZG_FREE
||
668 (gender
== CZG_NFREE
&& e
->gender
!= CZG_SNEUT
&& e
->gender
!= CZG_PNEUT
) ||
669 gender
== e
->gender
) {
670 if (ending_start
< 0) {
671 ending_start
= ending
;
673 } else if (ending_start
>= 0) {
674 ending_stop
= ending
- 1;
678 if (ending_stop
< 0) {
679 /* Whoa. All the endings matched. */
680 ending_stop
= ending
- 1;
683 /* Make a sequential map of the items with good mask */
685 for (ending
= ending_start
; ending
<= ending_stop
; ending
++) {
686 const CzechNameSubst
*e
= &_name_czech_subst_ending
[ending
];
688 if ((e
->choose
& choose
) == choose
&& (e
->allow
& allow
) != 0) {
694 /* Load the ending */
695 ending
= map
[SeedModChance(16, (int)i
, seed
)];
696 /* Override possible CZG_*FREE; this must be a real gender,
697 * otherwise we get overflow when modifying the adjectivum. */
698 gender
= _name_czech_subst_ending
[ending
].gender
;
699 assert(gender
!= CZG_FREE
&& gender
!= CZG_NFREE
);
702 if (do_prefix
&& (_name_czech_adj
[prefix
].choose
& choose
) != choose
) {
703 /* Throw away non-matching prefix. */
707 /* Now finally construct the name */
709 CzechPattern pattern
= _name_czech_adj
[prefix
].pattern
;
711 buf
= strecpy(buf
, _name_czech_adj
[prefix
].name
, last
);
713 char *endpos
= buf
- 1;
714 /* Find the first character in a UTF-8 sequence */
715 while (GB(*endpos
, 6, 2) == 2) endpos
--;
717 if (gender
== CZG_SMASC
&& pattern
== CZP_PRIVL
) {
718 assert(endpos
>= orig
+ 2);
721 assert(*(endpos
- 1) == 'v');
724 assert(endpos
>= orig
);
725 endpos
= strecpy(endpos
, _name_czech_patmod
[gender
][pattern
], last
);
728 buf
= strecpy(endpos
, " ", last
);
732 buf
= strecpy(buf
, _name_czech_subst_stem
[stem
].name
, last
);
733 if (postfix
< lengthof(_name_czech_subst_postfix
)) {
734 const char *poststr
= _name_czech_subst_postfix
[postfix
];
735 const char *endstr
= _name_czech_subst_ending
[ending
].name
;
737 size_t postlen
= strlen(poststr
);
738 size_t endlen
= strlen(endstr
);
739 assert(postlen
> 0 && endlen
> 0);
741 /* Kill the "avava" and "Jananna"-like cases */
742 if (postlen
< 2 || postlen
> endlen
||
743 ((poststr
[1] != 'v' || poststr
[1] != endstr
[1]) &&
744 poststr
[2] != endstr
[1])) {
745 buf
= strecpy(buf
, poststr
, last
);
747 /* k-i -> c-i, h-i -> z-i */
748 if (endstr
[0] == 'i') {
749 switch (*(buf
- 1)) {
750 case 'k': *(buf
- 1) = 'c'; break;
751 case 'h': *(buf
- 1) = 'z'; break;
757 buf
= strecpy(buf
, _name_czech_subst_ending
[ending
].name
, last
);
759 buf
= strecpy(buf
, _name_czech_subst_full
[stem
].name
, last
);
763 buf
= strecpy(buf
, " ", last
);
764 buf
= strecpy(buf
, _name_czech_suffix
[suffix
], last
);
772 * Generates Romanian town name from given seed.
773 * @param buf output buffer
774 * @param seed town name seed
775 * @param last end of buffer
777 static char *MakeRomanianTownName(char *buf
, const char *last
, uint32 seed
)
779 return strecpy(buf
, _name_romanian_real
[SeedChance(0, lengthof(_name_romanian_real
), seed
)], last
);
784 * Generates Slovak town name from given seed.
785 * @param buf output buffer
786 * @param seed town name seed
787 * @param last end of buffer
789 static char *MakeSlovakTownName(char *buf
, const char *last
, uint32 seed
)
791 return strecpy(buf
, _name_slovak_real
[SeedChance(0, lengthof(_name_slovak_real
), seed
)], last
);
796 * Generates Norwegian town name from given seed.
797 * @param buf output buffer
798 * @param seed town name seed
799 * @param last end of buffer
801 static char *MakeNorwegianTownName(char *buf
, const char *last
, uint32 seed
)
803 /* Use first 4 bit from seed to decide whether or not this town should
804 * have a real name 3/16 chance. Bit 0-3 */
805 if (SeedChance(0, 15, seed
) < 3) {
806 /* Use 7bit for the realname table index. Bit 4-10 */
807 return strecpy(buf
, _name_norwegian_real
[SeedChance(4, lengthof(_name_norwegian_real
), seed
)], last
);
810 /* Use 7bit for the first fake part. Bit 4-10 */
811 buf
= strecpy(buf
, _name_norwegian_1
[SeedChance(4, lengthof(_name_norwegian_1
), seed
)], last
);
812 /* Use 7bit for the last fake part. Bit 11-17 */
813 buf
= strecpy(buf
, _name_norwegian_2
[SeedChance(11, lengthof(_name_norwegian_2
), seed
)], last
);
820 * Generates Hungarian town name from given seed.
821 * @param buf output buffer
822 * @param seed town name seed
823 * @param last end of buffer
825 static char *MakeHungarianTownName(char *buf
, const char *last
, uint32 seed
)
827 if (SeedChance(12, 15, seed
) < 3) {
828 return strecpy(buf
, _name_hungarian_real
[SeedChance(0, lengthof(_name_hungarian_real
), seed
)], last
);
831 /* optional first segment */
832 uint i
= SeedChance(3, lengthof(_name_hungarian_1
) * 3, seed
);
833 if (i
< lengthof(_name_hungarian_1
)) buf
= strecpy(buf
, _name_hungarian_1
[i
], last
);
835 /* mandatory middle segments */
836 buf
= strecpy(buf
, _name_hungarian_2
[SeedChance(3, lengthof(_name_hungarian_2
), seed
)], last
);
837 buf
= strecpy(buf
, _name_hungarian_3
[SeedChance(6, lengthof(_name_hungarian_3
), seed
)], last
);
839 /* optional last segment */
840 i
= SeedChance(10, lengthof(_name_hungarian_4
) * 3, seed
);
841 if (i
< lengthof(_name_hungarian_4
)) {
842 buf
= strecpy(buf
, _name_hungarian_4
[i
], last
);
850 * Generates Swiss town name from given seed.
851 * @param buf output buffer
852 * @param seed town name seed
853 * @param last end of buffer
855 static char *MakeSwissTownName(char *buf
, const char *last
, uint32 seed
)
857 return strecpy(buf
, _name_swiss_real
[SeedChance(0, lengthof(_name_swiss_real
), seed
)], last
);
862 * Generates Danish town name from given seed.
863 * @param buf output buffer
864 * @param seed town name seed
865 * @param last end of buffer
867 static char *MakeDanishTownName(char *buf
, const char *last
, uint32 seed
)
869 /* optional first segment */
870 int i
= SeedChanceBias(0, lengthof(_name_danish_1
), seed
, 50);
871 if (i
>= 0) buf
= strecpy(buf
, _name_danish_1
[i
], last
);
873 /* middle segments removed as this algorithm seems to create much more realistic names */
874 buf
= strecpy(buf
, _name_danish_2
[SeedChance( 7, lengthof(_name_danish_2
), seed
)], last
);
875 buf
= strecpy(buf
, _name_danish_3
[SeedChance(16, lengthof(_name_danish_3
), seed
)], last
);
882 * Generates Turkish town name from given seed.
883 * @param buf output buffer
884 * @param seed town name seed
885 * @param last end of buffer
887 static char *MakeTurkishTownName(char *buf
, const char *last
, uint32 seed
)
889 uint i
= SeedModChance(0, 5, seed
);
893 buf
= strecpy(buf
, _name_turkish_prefix
[SeedModChance( 2, lengthof(_name_turkish_prefix
), seed
)], last
);
896 buf
= strecpy(buf
, _name_turkish_middle
[SeedModChance( 4, lengthof(_name_turkish_middle
), seed
)], last
);
898 /* optional suffix */
899 if (SeedModChance(0, 7, seed
) == 0) {
900 buf
= strecpy(buf
, _name_turkish_suffix
[SeedModChance( 10, lengthof(_name_turkish_suffix
), seed
)], last
);
905 buf
= strecpy(buf
, _name_turkish_prefix
[SeedModChance( 2, lengthof(_name_turkish_prefix
), seed
)], last
);
906 buf
= strecpy(buf
, _name_turkish_suffix
[SeedModChance( 4, lengthof(_name_turkish_suffix
), seed
)], last
);
910 buf
= strecpy(buf
, _name_turkish_real
[SeedModChance( 4, lengthof(_name_turkish_real
), seed
)], last
);
919 * Generates Italian town name from given seed.
920 * @param buf output buffer
921 * @param seed town name seed
922 * @param last end of buffer
924 static char *MakeItalianTownName(char *buf
, const char *last
, uint32 seed
)
926 if (SeedModChance(0, 6, seed
) == 0) { // real city names
927 return strecpy(buf
, _name_italian_real
[SeedModChance(4, lengthof(_name_italian_real
), seed
)], last
);
930 static const char * const mascul_femin_italian
[] = {
935 if (SeedModChance(0, 8, seed
) == 0) { // prefix
936 buf
= strecpy(buf
, _name_italian_pref
[SeedModChance(11, lengthof(_name_italian_pref
), seed
)], last
);
939 uint i
= SeedChance(0, 2, seed
);
940 if (i
== 0) { // masculine form
941 buf
= strecpy(buf
, _name_italian_1m
[SeedModChance(4, lengthof(_name_italian_1m
), seed
)], last
);
942 } else { // feminine form
943 buf
= strecpy(buf
, _name_italian_1f
[SeedModChance(4, lengthof(_name_italian_1f
), seed
)], last
);
946 if (SeedModChance(3, 3, seed
) == 0) {
947 buf
= strecpy(buf
, _name_italian_2
[SeedModChance(11, lengthof(_name_italian_2
), seed
)], last
);
948 buf
= strecpy(buf
, mascul_femin_italian
[i
], last
);
950 buf
= strecpy(buf
, _name_italian_2i
[SeedModChance(16, lengthof(_name_italian_2i
), seed
)], last
);
953 if (SeedModChance(15, 4, seed
) == 0) {
954 if (SeedModChance(5, 2, seed
) == 0) { // generic suffix
955 buf
= strecpy(buf
, _name_italian_3
[SeedModChance(4, lengthof(_name_italian_3
), seed
)], last
);
956 } else { // river name suffix
957 buf
= strecpy(buf
, _name_italian_river1
[SeedModChance(4, lengthof(_name_italian_river1
), seed
)], last
);
958 buf
= strecpy(buf
, _name_italian_river2
[SeedModChance(16, lengthof(_name_italian_river2
), seed
)], last
);
967 * Generates Catalan town name from given seed.
968 * @param buf output buffer
969 * @param seed town name seed
970 * @param last end of buffer
972 static char *MakeCatalanTownName(char *buf
, const char *last
, uint32 seed
)
974 if (SeedModChance(0, 3, seed
) == 0) { // real city names
975 return strecpy(buf
, _name_catalan_real
[SeedModChance(4, lengthof(_name_catalan_real
), seed
)], last
);
978 if (SeedModChance(0, 2, seed
) == 0) { // prefix
979 buf
= strecpy(buf
, _name_catalan_pref
[SeedModChance(11, lengthof(_name_catalan_pref
), seed
)], last
);
982 uint i
= SeedChance(0, 2, seed
);
983 if (i
== 0) { // masculine form
984 buf
= strecpy(buf
, _name_catalan_1m
[SeedModChance(4, lengthof(_name_catalan_1m
), seed
)], last
);
985 buf
= strecpy(buf
, _name_catalan_2m
[SeedModChance(11, lengthof(_name_catalan_2m
), seed
)], last
);
986 } else { // feminine form
987 buf
= strecpy(buf
, _name_catalan_1f
[SeedModChance(4, lengthof(_name_catalan_1f
), seed
)], last
);
988 buf
= strecpy(buf
, _name_catalan_2f
[SeedModChance(11, lengthof(_name_catalan_2f
), seed
)], last
);
991 if (SeedModChance(15, 5, seed
) == 0) {
992 if (SeedModChance(5, 2, seed
) == 0) { // generic suffix
993 buf
= strecpy(buf
, _name_catalan_3
[SeedModChance(4, lengthof(_name_catalan_3
), seed
)], last
);
994 } else { // river name suffix
995 buf
= strecpy(buf
, _name_catalan_river1
[SeedModChance(4, lengthof(_name_catalan_river1
), seed
)], last
);
1004 * Type for all town name generator functions.
1005 * @param buf The buffer to write the name to.
1006 * @param last The last element of the buffer.
1007 * @param seed The seed of the town name.
1008 * @return The end of the filled buffer.
1010 typedef char *TownNameGenerator(char *buf
, const char *last
, uint32 seed
);
1012 /** Contains pointer to generator and minimum buffer size (not incl. terminating '\0') */
1013 struct TownNameGeneratorParams
{
1014 byte min
; ///< minimum number of characters that need to be printed for generator to work correctly
1015 TownNameGenerator
*proc
; ///< generator itself
1018 /** Town name generators */
1019 static const TownNameGeneratorParams _town_name_generators
[] = {
1020 { 4, MakeEnglishOriginalTownName
}, // replaces first 4 characters of name
1021 { 0, MakeFrenchTownName
},
1022 { 0, MakeGermanTownName
},
1023 { 4, MakeEnglishAdditionalTownName
}, // replaces first 4 characters of name
1024 { 0, MakeSpanishTownName
},
1025 { 0, MakeSillyTownName
},
1026 { 0, MakeSwedishTownName
},
1027 { 0, MakeDutchTownName
},
1028 { 8, MakeFinnishTownName
}, // _name_finnish_1
1029 { 0, MakePolishTownName
},
1030 { 0, MakeSlovakTownName
},
1031 { 0, MakeNorwegianTownName
},
1032 { 0, MakeHungarianTownName
},
1033 { 0, MakeAustrianTownName
},
1034 { 0, MakeRomanianTownName
},
1035 { 28, MakeCzechTownName
}, // _name_czech_adj + _name_czech_patmod + 1 + _name_czech_subst_stem + _name_czech_subst_postfix
1036 { 0, MakeSwissTownName
},
1037 { 0, MakeDanishTownName
},
1038 { 0, MakeTurkishTownName
},
1039 { 0, MakeItalianTownName
},
1040 { 0, MakeCatalanTownName
},
1045 * Generates town name from given seed.
1046 * @param buf output buffer
1047 * @param last end of buffer
1048 * @param lang town name language
1049 * @param seed generation seed
1050 * @return last character ('/0')
1052 char *GenerateTownNameString(char *buf
, const char *last
, size_t lang
, uint32 seed
)
1054 assert(lang
< lengthof(_town_name_generators
));
1056 /* Some generators need at least 9 bytes in buffer. English generators need 5 for
1057 * string replacing, others use constructions like strlen(buf)-3 and so on.
1058 * Finnish generator needs to fit all strings from _name_finnish_1.
1059 * Czech generator needs to fit almost whole town name...
1060 * These would break. Using another temporary buffer results in ~40% slower code,
1061 * so use it only when really needed. */
1062 const TownNameGeneratorParams
*par
= &_town_name_generators
[lang
];
1063 if (last
>= buf
+ par
->min
) return par
->proc(buf
, last
, seed
);
1065 char *buffer
= AllocaM(char, par
->min
+ 1);
1066 par
->proc(buffer
, buffer
+ par
->min
, seed
);
1068 return strecpy(buf
, buffer
, last
);