4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
10 /** @file townname.cpp %Town name generators. */
13 #include "string_func.h"
14 #include "townname_type.h"
16 #include "strings_func.h"
17 #include "core/random_func.hpp"
19 #include "gfx_layout.h"
21 #include "table/townname.h"
23 #include "safeguards.h"
27 * Initializes this struct from town data
28 * @param t town for which we will be printing name later
30 TownNameParams::TownNameParams(const Town
*t
) :
31 grfid(t
->townnamegrfid
), // by default, use supplied data
34 if (t
->townnamegrfid
!= 0 && GetGRFTownName(t
->townnamegrfid
) == NULL
) {
35 /* Fallback to english original */
37 this->type
= SPECSTR_TOWNNAME_ENGLISH
;
44 * Fills buffer with specified town name
45 * @param buff buffer start
46 * @param par town name parameters
47 * @param townnameparts 'encoded' town name
48 * @param last end of buffer
49 * @return pointer to terminating '\0'
51 char *GetTownName(char *buff
, const TownNameParams
*par
, uint32 townnameparts
, const char *last
)
53 if (par
->grfid
== 0) {
54 int64 args_array
[1] = { townnameparts
};
55 StringParameters
tmp_params(args_array
);
56 return GetStringWithArgs(buff
, par
->type
, &tmp_params
, last
);
59 return GRFTownNameGenerate(buff
, par
->grfid
, par
->type
, townnameparts
, last
);
64 * Fills buffer with town's name
65 * @param buff buffer start
66 * @param t we want to get name of this town
67 * @param last end of buffer
68 * @return pointer to terminating '\0'
70 char *GetTownName(char *buff
, const Town
*t
, const char *last
)
72 TownNameParams
par(t
);
73 return GetTownName(buff
, &par
, t
->townnameparts
, last
);
78 * Verifies the town name is valid and unique.
79 * @param r random bits
80 * @param par town name parameters
81 * @param town_names if a name is generated, check its uniqueness with the set
82 * @return true iff name is valid and unique
84 bool VerifyTownName(uint32 r
, const TownNameParams
*par
, TownNames
*town_names
)
86 /* reserve space for extra unicode character and terminating '\0' */
87 char buf1
[(MAX_LENGTH_TOWN_NAME_CHARS
+ 1) * MAX_CHAR_LENGTH
];
88 char buf2
[(MAX_LENGTH_TOWN_NAME_CHARS
+ 1) * MAX_CHAR_LENGTH
];
90 GetTownName(buf1
, par
, r
, lastof(buf1
));
92 /* Check size and width */
93 if (Utf8StringLength(buf1
) >= MAX_LENGTH_TOWN_NAME_CHARS
) return false;
95 if (town_names
!= NULL
) {
96 if (town_names
->find(buf1
) != town_names
->end()) return false;
97 town_names
->insert(buf1
);
101 /* We can't just compare the numbers since
102 * several numbers may map to a single name. */
103 const char *buf
= t
->name
;
105 GetTownName(buf2
, t
, lastof(buf2
));
108 if (strcmp(buf1
, buf
) == 0) return false;
117 * Generates valid town name.
118 * @param townnameparts if a name is generated, it's stored there
119 * @param town_names if a name is generated, check its uniqueness with the set
120 * @return true iff a name was generated
122 bool GenerateTownName(uint32
*townnameparts
, TownNames
*town_names
)
124 /* Do not set too low tries, since when we run out of names, we loop
125 * for #tries only one time anyway - then we stop generating more
126 * towns. Do not show it too high neither, since looping through all
127 * the other towns may take considerable amount of time (10000 is
129 TownNameParams
par(_settings_game
.game_creation
.town_name
);
131 /* This function is called very often without entering the gameloop
132 * inbetween. So reset layout cache to prevent it from growing too big. */
133 Layouter::ReduceLineCache();
135 for (int i
= 1000; i
!= 0; i
--) {
136 uint32 r
= _generating_world
? Random() : InteractiveRandom();
137 if (!VerifyTownName(r
, &par
, town_names
)) continue;
149 * Generates a number from given seed.
150 * @param shift_by number of bits seed is shifted to the right
151 * @param max generated number is in interval 0...max-1
153 * @return seed transformed to a number from given range
155 static inline uint32
SeedChance(byte shift_by
, int max
, uint32 seed
)
157 return (GB(seed
, shift_by
, 16) * max
) >> 16;
162 * Generates a number from given seed. Uses different algorithm than SeedChance().
163 * @param shift_by number of bits seed is shifted to the right
164 * @param max generated number is in interval 0...max-1
166 * @return seed transformed to a number from given range
168 static inline uint32
SeedModChance(byte shift_by
, int max
, uint32 seed
)
170 /* This actually gives *MUCH* more even distribution of the values
171 * than SeedChance(), which is absolutely horrible in that. If
172 * you do not believe me, try with i.e. the Czech town names,
173 * compare the words (nicely visible on prefixes) generated by
174 * SeedChance() and SeedModChance(). Do not get discouraged by the
175 * never-use-modulo myths, which hold true only for the linear
176 * congruential generators (and Random() isn't such a generator).
178 * TODO: Perhaps we should use it for all the name generators? --pasky */
179 return (seed
>> shift_by
) % max
;
184 * Generates a number from given seed.
185 * @param shift_by number of bits seed is shifted to the right
186 * @param max generated number is in interval -bias...max-1
188 * @param bias minimum value that can be returned
189 * @return seed transformed to a number from given range
191 static inline int32
SeedChanceBias(byte shift_by
, int max
, uint32 seed
, int bias
)
193 return SeedChance(shift_by
, max
+ bias
, seed
) - bias
;
198 * Replaces a string beginning in 'org' with 'rep'.
199 * @param org string to replace, has to be 4 characters long
200 * @param rep string to be replaced with, has to be 4 characters long
201 * @param buf buffer with string
203 static void ReplaceWords(const char *org
, const char *rep
, char *buf
)
205 assert(strlen(org
) == 4 && strlen(rep
) == 4 && strlen(buf
) >= 4);
206 if (strncmp(buf
, org
, 4) == 0) memcpy(buf
, rep
, 4); // Safe as the string in buf is always more than 4 characters long.
211 * Replaces english curses and ugly letter combinations by nicer ones.
212 * @param buf buffer with town name
213 * @param original English (Original) generator was used
215 static void ReplaceEnglishWords(char *buf
, bool original
)
217 ReplaceWords("Cunt", "East", buf
);
218 ReplaceWords("Slag", "Pits", buf
);
219 ReplaceWords("Slut", "Edin", buf
);
220 if (!original
) ReplaceWords("Fart", "Boot", buf
); // never happens with 'English (Original)'
221 ReplaceWords("Drar", "Quar", buf
);
222 ReplaceWords("Dreh", "Bash", buf
);
223 ReplaceWords("Frar", "Shor", buf
);
224 ReplaceWords("Grar", "Aber", buf
);
225 ReplaceWords("Brar", "Over", buf
);
226 ReplaceWords("Wrar", original
? "Inve" : "Stan", buf
);
230 * Generates English (Original) town name from given seed.
231 * @param buf output buffer
232 * @param seed town name seed
233 * @param last end of buffer
235 static char *MakeEnglishOriginalTownName(char *buf
, const char *last
, uint32 seed
)
239 /* optional first segment */
240 int i
= SeedChanceBias(0, lengthof(_name_original_english_1
), seed
, 50);
241 if (i
>= 0) buf
= strecpy(buf
, _name_original_english_1
[i
], last
);
243 /* mandatory middle segments */
244 buf
= strecpy(buf
, _name_original_english_2
[SeedChance(4, lengthof(_name_original_english_2
), seed
)], last
);
245 buf
= strecpy(buf
, _name_original_english_3
[SeedChance(7, lengthof(_name_original_english_3
), seed
)], last
);
246 buf
= strecpy(buf
, _name_original_english_4
[SeedChance(10, lengthof(_name_original_english_4
), seed
)], last
);
247 buf
= strecpy(buf
, _name_original_english_5
[SeedChance(13, lengthof(_name_original_english_5
), seed
)], last
);
249 /* optional last segment */
250 i
= SeedChanceBias(15, lengthof(_name_original_english_6
), seed
, 60);
251 if (i
>= 0) buf
= strecpy(buf
, _name_original_english_6
[i
], last
);
253 /* Ce, Ci => Ke, Ki */
254 if (orig
[0] == 'C' && (orig
[1] == 'e' || orig
[1] == 'i')) {
258 assert(buf
- orig
>= 4);
259 ReplaceEnglishWords(orig
, true);
266 * Generates English (Additional) town name from given seed.
267 * @param buf output buffer
268 * @param seed town name seed
269 * @param last end of buffer
271 static char *MakeEnglishAdditionalTownName(char *buf
, const char *last
, uint32 seed
)
275 /* optional first segment */
276 int i
= SeedChanceBias(0, lengthof(_name_additional_english_prefix
), seed
, 50);
277 if (i
>= 0) buf
= strecpy(buf
, _name_additional_english_prefix
[i
], last
);
279 if (SeedChance(3, 20, seed
) >= 14) {
280 buf
= strecpy(buf
, _name_additional_english_1a
[SeedChance(6, lengthof(_name_additional_english_1a
), seed
)], last
);
282 buf
= strecpy(buf
, _name_additional_english_1b1
[SeedChance(6, lengthof(_name_additional_english_1b1
), seed
)], last
);
283 buf
= strecpy(buf
, _name_additional_english_1b2
[SeedChance(9, lengthof(_name_additional_english_1b2
), seed
)], last
);
284 if (SeedChance(11, 20, seed
) >= 4) {
285 buf
= strecpy(buf
, _name_additional_english_1b3a
[SeedChance(12, lengthof(_name_additional_english_1b3a
), seed
)], last
);
287 buf
= strecpy(buf
, _name_additional_english_1b3b
[SeedChance(12, lengthof(_name_additional_english_1b3b
), seed
)], last
);
291 buf
= strecpy(buf
, _name_additional_english_2
[SeedChance(14, lengthof(_name_additional_english_2
), seed
)], last
);
293 /* optional last segment */
294 i
= SeedChanceBias(15, lengthof(_name_additional_english_3
), seed
, 60);
295 if (i
>= 0) buf
= strecpy(buf
, _name_additional_english_3
[i
], last
);
297 assert(buf
- orig
>= 4);
298 ReplaceEnglishWords(orig
, false);
305 * Generates Austrian town name from given seed.
306 * @param buf output buffer
307 * @param seed town name seed
308 * @param last end of buffer
310 static char *MakeAustrianTownName(char *buf
, const char *last
, uint32 seed
)
312 /* Bad, Maria, Gross, ... */
313 int i
= SeedChanceBias(0, lengthof(_name_austrian_a1
), seed
, 15);
314 if (i
>= 0) buf
= strecpy(buf
, _name_austrian_a1
[i
], last
);
318 i
= SeedChance(4, 6, seed
);
320 /* Kaisers-kirchen */
321 buf
= strecpy(buf
, _name_austrian_a2
[SeedChance( 7, lengthof(_name_austrian_a2
), seed
)], last
);
322 buf
= strecpy(buf
, _name_austrian_a3
[SeedChance(13, lengthof(_name_austrian_a3
), seed
)], last
);
325 buf
= strecpy(buf
, _name_austrian_a5
[SeedChance( 7, lengthof(_name_austrian_a5
), seed
)], last
);
326 buf
= strecpy(buf
, _name_austrian_a6
[SeedChance( 9, lengthof(_name_austrian_a6
), seed
)], last
);
327 j
= 1; // More likely to have a " an der " or " am "
330 buf
= strecpy(buf
, _name_austrian_a4
[SeedChance( 7, lengthof(_name_austrian_a4
), seed
)], last
);
333 i
= SeedChance(1, 6, seed
);
335 /* an der Donau (rivers) */
336 buf
= strecpy(buf
, _name_austrian_f1
[SeedChance(4, lengthof(_name_austrian_f1
), seed
)], last
);
337 buf
= strecpy(buf
, _name_austrian_f2
[SeedChance(5, lengthof(_name_austrian_f2
), seed
)], last
);
338 } else if (i
>= 2 - j
) {
339 /* am Dachstein (mountains) */
340 buf
= strecpy(buf
, _name_austrian_b1
[SeedChance(4, lengthof(_name_austrian_b1
), seed
)], last
);
341 buf
= strecpy(buf
, _name_austrian_b2
[SeedChance(5, lengthof(_name_austrian_b2
), seed
)], last
);
349 * Generates German town name from given seed.
350 * @param buf output buffer
351 * @param seed town name seed
352 * @param last end of buffer
354 static char *MakeGermanTownName(char *buf
, const char *last
, uint32 seed
)
356 uint seed_derivative
= SeedChance(7, 28, seed
);
358 /* optional prefix */
359 if (seed_derivative
== 12 || seed_derivative
== 19) {
360 uint i
= SeedChance(2, lengthof(_name_german_pre
), seed
);
361 buf
= strecpy(buf
, _name_german_pre
[i
], last
);
364 /* mandatory middle segments including option of hardcoded name */
365 uint i
= SeedChance(3, lengthof(_name_german_real
) + lengthof(_name_german_1
), seed
);
366 if (i
< lengthof(_name_german_real
)) {
367 buf
= strecpy(buf
, _name_german_real
[i
], last
);
369 buf
= strecpy(buf
, _name_german_1
[i
- lengthof(_name_german_real
)], last
);
371 i
= SeedChance(5, lengthof(_name_german_2
), seed
);
372 buf
= strecpy(buf
, _name_german_2
[i
], last
);
375 /* optional suffix */
376 if (seed_derivative
== 24) {
377 i
= SeedChance(9, lengthof(_name_german_4_an_der
) + lengthof(_name_german_4_am
), seed
);
378 if (i
< lengthof(_name_german_4_an_der
)) {
379 buf
= strecpy(buf
, _name_german_3_an_der
[0], last
);
380 buf
= strecpy(buf
, _name_german_4_an_der
[i
], last
);
382 buf
= strecpy(buf
, _name_german_3_am
[0], last
);
383 buf
= strecpy(buf
, _name_german_4_am
[i
- lengthof(_name_german_4_an_der
)], last
);
392 * Generates Latin-American town name from given seed.
393 * @param buf output buffer
394 * @param seed town name seed
395 * @param last end of buffer
397 static char *MakeSpanishTownName(char *buf
, const char *last
, uint32 seed
)
399 return strecpy(buf
, _name_spanish_real
[SeedChance(0, lengthof(_name_spanish_real
), seed
)], last
);
404 * Generates French town name from given seed.
405 * @param buf output buffer
406 * @param seed town name seed
407 * @param last end of buffer
409 static char *MakeFrenchTownName(char *buf
, const char *last
, uint32 seed
)
411 return strecpy(buf
, _name_french_real
[SeedChance(0, lengthof(_name_french_real
), seed
)], last
);
416 * Generates Silly town name from given seed.
417 * @param buf output buffer
418 * @param seed town name seed
419 * @param last end of buffer
421 static char *MakeSillyTownName(char *buf
, const char *last
, uint32 seed
)
423 buf
= strecpy(buf
, _name_silly_1
[SeedChance( 0, lengthof(_name_silly_1
), seed
)], last
);
424 buf
= strecpy(buf
, _name_silly_2
[SeedChance(16, lengthof(_name_silly_2
), seed
)], last
);
431 * Generates Swedish town name from given seed.
432 * @param buf output buffer
433 * @param seed town name seed
434 * @param last end of buffer
436 static char *MakeSwedishTownName(char *buf
, const char *last
, uint32 seed
)
438 /* optional first segment */
439 int i
= SeedChanceBias(0, lengthof(_name_swedish_1
), seed
, 50);
440 if (i
>= 0) buf
= strecpy(buf
, _name_swedish_1
[i
], last
);
442 /* mandatory middle segments including option of hardcoded name */
443 if (SeedChance(4, 5, seed
) >= 3) {
444 buf
= strecpy(buf
, _name_swedish_2
[SeedChance( 7, lengthof(_name_swedish_2
), seed
)], last
);
446 buf
= strecpy(buf
, _name_swedish_2a
[SeedChance( 7, lengthof(_name_swedish_2a
), seed
)], last
);
447 buf
= strecpy(buf
, _name_swedish_2b
[SeedChance(10, lengthof(_name_swedish_2b
), seed
)], last
);
448 buf
= strecpy(buf
, _name_swedish_2c
[SeedChance(13, lengthof(_name_swedish_2c
), seed
)], last
);
451 buf
= strecpy(buf
, _name_swedish_3
[SeedChance(16, lengthof(_name_swedish_3
), seed
)], last
);
458 * Generates Dutch town name from given seed.
459 * @param buf output buffer
460 * @param seed town name seed
461 * @param last end of buffer
463 static char *MakeDutchTownName(char *buf
, const char *last
, uint32 seed
)
465 /* optional first segment */
466 int i
= SeedChanceBias(0, lengthof(_name_dutch_1
), seed
, 50);
467 if (i
>= 0) buf
= strecpy(buf
, _name_dutch_1
[i
], last
);
469 /* mandatory middle segments including option of hardcoded name */
470 if (SeedChance(6, 9, seed
) > 4) {
471 buf
= strecpy(buf
, _name_dutch_2
[SeedChance( 9, lengthof(_name_dutch_2
), seed
)], last
);
473 buf
= strecpy(buf
, _name_dutch_3
[SeedChance( 9, lengthof(_name_dutch_3
), seed
)], last
);
474 buf
= strecpy(buf
, _name_dutch_4
[SeedChance(12, lengthof(_name_dutch_4
), seed
)], last
);
477 buf
= strecpy(buf
, _name_dutch_5
[SeedChance(15, lengthof(_name_dutch_5
), seed
)], last
);
484 * Generates Finnish town name from given seed.
485 * @param buf output buffer
486 * @param seed town name seed
487 * @param last end of buffer
489 static char *MakeFinnishTownName(char *buf
, const char *last
, uint32 seed
)
493 /* Select randomly if town name should consists of one or two parts. */
494 if (SeedChance(0, 15, seed
) >= 10) {
495 return strecpy(buf
, _name_finnish_real
[SeedChance(2, lengthof(_name_finnish_real
), seed
)], last
);
498 if (SeedChance(0, 15, seed
) >= 5) {
499 /* A two-part name by combining one of _name_finnish_1 + "la"/"lä"
500 * The reason for not having the contents of _name_finnish_{1,2} in the same table is
501 * that the ones in _name_finnish_2 are not good for this purpose. */
502 uint sel
= SeedChance( 0, lengthof(_name_finnish_1
), seed
);
503 buf
= strecpy(buf
, _name_finnish_1
[sel
], last
);
506 if (*end
== 'i') *end
= 'e';
507 if (strstr(orig
, "a") != NULL
|| strstr(orig
, "o") != NULL
|| strstr(orig
, "u") != NULL
||
508 strstr(orig
, "A") != NULL
|| strstr(orig
, "O") != NULL
|| strstr(orig
, "U") != NULL
) {
509 buf
= strecpy(buf
, "la", last
);
511 buf
= strecpy(buf
, "l\xC3\xA4", last
);
516 /* A two-part name by combining one of _name_finnish_{1,2} + _name_finnish_3.
517 * Why aren't _name_finnish_{1,2} just one table? See above. */
518 uint sel
= SeedChance(2, lengthof(_name_finnish_1
) + lengthof(_name_finnish_2
), seed
);
519 if (sel
>= lengthof(_name_finnish_1
)) {
520 buf
= strecpy(buf
, _name_finnish_2
[sel
- lengthof(_name_finnish_1
)], last
);
522 buf
= strecpy(buf
, _name_finnish_1
[sel
], last
);
525 buf
= strecpy(buf
, _name_finnish_3
[SeedChance(10, lengthof(_name_finnish_3
), seed
)], last
);
532 * Generates Polish town name from given seed.
533 * @param buf output buffer
534 * @param seed town name seed
535 * @param last end of buffer
537 static char *MakePolishTownName(char *buf
, const char *last
, uint32 seed
)
539 /* optional first segment */
540 uint i
= SeedChance(0,
541 lengthof(_name_polish_2_o
) + lengthof(_name_polish_2_m
) +
542 lengthof(_name_polish_2_f
) + lengthof(_name_polish_2_n
),
544 uint j
= SeedChance(2, 20, seed
);
547 if (i
< lengthof(_name_polish_2_o
)) {
548 return strecpy(buf
, _name_polish_2_o
[SeedChance(3, lengthof(_name_polish_2_o
), seed
)], last
);
551 if (i
< lengthof(_name_polish_2_m
) + lengthof(_name_polish_2_o
)) {
553 buf
= strecpy(buf
, _name_polish_1_m
[SeedChance(5, lengthof(_name_polish_1_m
), seed
)], last
);
556 buf
= strecpy(buf
, _name_polish_2_m
[SeedChance(7, lengthof(_name_polish_2_m
), seed
)], last
);
558 if (j
>= 4 && j
< 16) {
559 buf
= strecpy(buf
, _name_polish_3_m
[SeedChance(10, lengthof(_name_polish_3_m
), seed
)], last
);
565 if (i
< lengthof(_name_polish_2_f
) + lengthof(_name_polish_2_m
) + lengthof(_name_polish_2_o
)) {
567 buf
= strecpy(buf
, _name_polish_1_f
[SeedChance(5, lengthof(_name_polish_1_f
), seed
)], last
);
570 buf
= strecpy(buf
, _name_polish_2_f
[SeedChance(7, lengthof(_name_polish_2_f
), seed
)], last
);
572 if (j
>= 4 && j
< 16) {
573 buf
= strecpy(buf
, _name_polish_3_f
[SeedChance(10, lengthof(_name_polish_3_f
), seed
)], last
);
580 buf
= strecpy(buf
, _name_polish_1_n
[SeedChance(5, lengthof(_name_polish_1_n
), seed
)], last
);
583 buf
= strecpy(buf
, _name_polish_2_n
[SeedChance(7, lengthof(_name_polish_2_n
), seed
)], last
);
585 if (j
>= 4 && j
< 16) {
586 buf
= strecpy(buf
, _name_polish_3_n
[SeedChance(10, lengthof(_name_polish_3_n
), seed
)], last
);
594 * Generates Czech town name from given seed.
595 * @param buf output buffer
596 * @param seed town name seed
597 * @param last end of buffer
599 static char *MakeCzechTownName(char *buf
, const char *last
, uint32 seed
)
601 /* 1:3 chance to use a real name. */
602 if (SeedModChance(0, 4, seed
) == 0) {
603 return strecpy(buf
, _name_czech_real
[SeedModChance(4, lengthof(_name_czech_real
), seed
)], last
);
606 const char *orig
= buf
;
608 /* Probability of prefixes/suffixes
609 * 0..11 prefix, 12..13 prefix+suffix, 14..17 suffix, 18..31 nothing */
610 int prob_tails
= SeedModChance(2, 32, seed
);
611 bool do_prefix
= prob_tails
< 12;
612 bool do_suffix
= prob_tails
> 11 && prob_tails
< 17;
615 /* IDs of the respective parts */
616 int prefix
= 0, ending
= 0, suffix
= 0;
620 /* The select criteria. */
625 if (do_prefix
) prefix
= SeedModChance(5, lengthof(_name_czech_adj
) * 12, seed
) / 12;
626 if (do_suffix
) suffix
= SeedModChance(7, lengthof(_name_czech_suffix
), seed
);
627 /* 3:1 chance 3:1 to use dynamic substantive */
628 stem
= SeedModChance(9,
629 lengthof(_name_czech_subst_full
) + 3 * lengthof(_name_czech_subst_stem
),
631 if (stem
< lengthof(_name_czech_subst_full
)) {
633 dynamic_subst
= false;
634 gender
= _name_czech_subst_full
[stem
].gender
;
635 choose
= _name_czech_subst_full
[stem
].choose
;
636 allow
= _name_czech_subst_full
[stem
].allow
;
638 uint map
[lengthof(_name_czech_subst_ending
)];
639 int ending_start
= -1, ending_stop
= -1;
641 /* Load the substantive */
642 dynamic_subst
= true;
643 stem
-= lengthof(_name_czech_subst_full
);
644 stem
%= lengthof(_name_czech_subst_stem
);
645 gender
= _name_czech_subst_stem
[stem
].gender
;
646 choose
= _name_czech_subst_stem
[stem
].choose
;
647 allow
= _name_czech_subst_stem
[stem
].allow
;
649 /* Load the postfix (1:1 chance that a postfix will be inserted) */
650 postfix
= SeedModChance(14, lengthof(_name_czech_subst_postfix
) * 2, seed
);
652 if (choose
& CZC_POSTFIX
) {
653 /* Always get a real postfix. */
654 postfix
%= lengthof(_name_czech_subst_postfix
);
656 if (choose
& CZC_NOPOSTFIX
) {
657 /* Always drop a postfix. */
658 postfix
+= lengthof(_name_czech_subst_postfix
);
660 if (postfix
< lengthof(_name_czech_subst_postfix
)) {
661 choose
|= CZC_POSTFIX
;
663 choose
|= CZC_NOPOSTFIX
;
666 /* Localize the array segment containing a good gender */
667 for (ending
= 0; ending
< (int)lengthof(_name_czech_subst_ending
); ending
++) {
668 const CzechNameSubst
*e
= &_name_czech_subst_ending
[ending
];
670 if (gender
== CZG_FREE
||
671 (gender
== CZG_NFREE
&& e
->gender
!= CZG_SNEUT
&& e
->gender
!= CZG_PNEUT
) ||
672 gender
== e
->gender
) {
673 if (ending_start
< 0) {
674 ending_start
= ending
;
676 } else if (ending_start
>= 0) {
677 ending_stop
= ending
- 1;
681 if (ending_stop
< 0) {
682 /* Whoa. All the endings matched. */
683 ending_stop
= ending
- 1;
686 /* Make a sequential map of the items with good mask */
688 for (ending
= ending_start
; ending
<= ending_stop
; ending
++) {
689 const CzechNameSubst
*e
= &_name_czech_subst_ending
[ending
];
691 if ((e
->choose
& choose
) == choose
&& (e
->allow
& allow
) != 0) {
697 /* Load the ending */
698 ending
= map
[SeedModChance(16, (int)i
, seed
)];
699 /* Override possible CZG_*FREE; this must be a real gender,
700 * otherwise we get overflow when modifying the adjectivum. */
701 gender
= _name_czech_subst_ending
[ending
].gender
;
702 assert(gender
!= CZG_FREE
&& gender
!= CZG_NFREE
);
705 if (do_prefix
&& (_name_czech_adj
[prefix
].choose
& choose
) != choose
) {
706 /* Throw away non-matching prefix. */
710 /* Now finally construct the name */
712 CzechPattern pattern
= _name_czech_adj
[prefix
].pattern
;
714 buf
= strecpy(buf
, _name_czech_adj
[prefix
].name
, last
);
716 char *endpos
= buf
- 1;
717 /* Find the first character in a UTF-8 sequence */
718 while (GB(*endpos
, 6, 2) == 2) endpos
--;
720 if (gender
== CZG_SMASC
&& pattern
== CZP_PRIVL
) {
721 assert(endpos
>= orig
+ 2);
724 assert(*(endpos
- 1) == 'v');
727 assert(endpos
>= orig
);
728 endpos
= strecpy(endpos
, _name_czech_patmod
[gender
][pattern
], last
);
731 buf
= strecpy(endpos
, " ", last
);
735 buf
= strecpy(buf
, _name_czech_subst_stem
[stem
].name
, last
);
736 if (postfix
< lengthof(_name_czech_subst_postfix
)) {
737 const char *poststr
= _name_czech_subst_postfix
[postfix
];
738 const char *endstr
= _name_czech_subst_ending
[ending
].name
;
740 size_t postlen
= strlen(poststr
);
741 size_t endlen
= strlen(endstr
);
742 assert(postlen
> 0 && endlen
> 0);
744 /* Kill the "avava" and "Jananna"-like cases */
745 if (postlen
< 2 || postlen
> endlen
||
746 ((poststr
[1] != 'v' || poststr
[1] != endstr
[1]) &&
747 poststr
[2] != endstr
[1])) {
748 buf
= strecpy(buf
, poststr
, last
);
750 /* k-i -> c-i, h-i -> z-i */
751 if (endstr
[0] == 'i') {
752 switch (*(buf
- 1)) {
753 case 'k': *(buf
- 1) = 'c'; break;
754 case 'h': *(buf
- 1) = 'z'; break;
760 buf
= strecpy(buf
, _name_czech_subst_ending
[ending
].name
, last
);
762 buf
= strecpy(buf
, _name_czech_subst_full
[stem
].name
, last
);
766 buf
= strecpy(buf
, " ", last
);
767 buf
= strecpy(buf
, _name_czech_suffix
[suffix
], last
);
775 * Generates Romanian town name from given seed.
776 * @param buf output buffer
777 * @param seed town name seed
778 * @param last end of buffer
780 static char *MakeRomanianTownName(char *buf
, const char *last
, uint32 seed
)
782 return strecpy(buf
, _name_romanian_real
[SeedChance(0, lengthof(_name_romanian_real
), seed
)], last
);
787 * Generates Slovak town name from given seed.
788 * @param buf output buffer
789 * @param seed town name seed
790 * @param last end of buffer
792 static char *MakeSlovakTownName(char *buf
, const char *last
, uint32 seed
)
794 return strecpy(buf
, _name_slovak_real
[SeedChance(0, lengthof(_name_slovak_real
), seed
)], last
);
799 * Generates Norwegian town name from given seed.
800 * @param buf output buffer
801 * @param seed town name seed
802 * @param last end of buffer
804 static char *MakeNorwegianTownName(char *buf
, const char *last
, uint32 seed
)
806 /* Use first 4 bit from seed to decide whether or not this town should
807 * have a real name 3/16 chance. Bit 0-3 */
808 if (SeedChance(0, 15, seed
) < 3) {
809 /* Use 7bit for the realname table index. Bit 4-10 */
810 return strecpy(buf
, _name_norwegian_real
[SeedChance(4, lengthof(_name_norwegian_real
), seed
)], last
);
813 /* Use 7bit for the first fake part. Bit 4-10 */
814 buf
= strecpy(buf
, _name_norwegian_1
[SeedChance(4, lengthof(_name_norwegian_1
), seed
)], last
);
815 /* Use 7bit for the last fake part. Bit 11-17 */
816 buf
= strecpy(buf
, _name_norwegian_2
[SeedChance(11, lengthof(_name_norwegian_2
), seed
)], last
);
823 * Generates Hungarian town name from given seed.
824 * @param buf output buffer
825 * @param seed town name seed
826 * @param last end of buffer
828 static char *MakeHungarianTownName(char *buf
, const char *last
, uint32 seed
)
830 if (SeedChance(12, 15, seed
) < 3) {
831 return strecpy(buf
, _name_hungarian_real
[SeedChance(0, lengthof(_name_hungarian_real
), seed
)], last
);
834 /* optional first segment */
835 uint i
= SeedChance(3, lengthof(_name_hungarian_1
) * 3, seed
);
836 if (i
< lengthof(_name_hungarian_1
)) buf
= strecpy(buf
, _name_hungarian_1
[i
], last
);
838 /* mandatory middle segments */
839 buf
= strecpy(buf
, _name_hungarian_2
[SeedChance(3, lengthof(_name_hungarian_2
), seed
)], last
);
840 buf
= strecpy(buf
, _name_hungarian_3
[SeedChance(6, lengthof(_name_hungarian_3
), seed
)], last
);
842 /* optional last segment */
843 i
= SeedChance(10, lengthof(_name_hungarian_4
) * 3, seed
);
844 if (i
< lengthof(_name_hungarian_4
)) {
845 buf
= strecpy(buf
, _name_hungarian_4
[i
], last
);
853 * Generates Swiss town name from given seed.
854 * @param buf output buffer
855 * @param seed town name seed
856 * @param last end of buffer
858 static char *MakeSwissTownName(char *buf
, const char *last
, uint32 seed
)
860 return strecpy(buf
, _name_swiss_real
[SeedChance(0, lengthof(_name_swiss_real
), seed
)], last
);
865 * Generates Danish town name from given seed.
866 * @param buf output buffer
867 * @param seed town name seed
868 * @param last end of buffer
870 static char *MakeDanishTownName(char *buf
, const char *last
, uint32 seed
)
872 /* optional first segment */
873 int i
= SeedChanceBias(0, lengthof(_name_danish_1
), seed
, 50);
874 if (i
>= 0) buf
= strecpy(buf
, _name_danish_1
[i
], last
);
876 /* middle segments removed as this algorithm seems to create much more realistic names */
877 buf
= strecpy(buf
, _name_danish_2
[SeedChance( 7, lengthof(_name_danish_2
), seed
)], last
);
878 buf
= strecpy(buf
, _name_danish_3
[SeedChance(16, lengthof(_name_danish_3
), seed
)], last
);
885 * Generates Turkish town name from given seed.
886 * @param buf output buffer
887 * @param seed town name seed
888 * @param last end of buffer
890 static char *MakeTurkishTownName(char *buf
, const char *last
, uint32 seed
)
892 uint i
= SeedModChance(0, 5, seed
);
896 buf
= strecpy(buf
, _name_turkish_prefix
[SeedModChance( 2, lengthof(_name_turkish_prefix
), seed
)], last
);
899 buf
= strecpy(buf
, _name_turkish_middle
[SeedModChance( 4, lengthof(_name_turkish_middle
), seed
)], last
);
901 /* optional suffix */
902 if (SeedModChance(0, 7, seed
) == 0) {
903 buf
= strecpy(buf
, _name_turkish_suffix
[SeedModChance( 10, lengthof(_name_turkish_suffix
), seed
)], last
);
908 buf
= strecpy(buf
, _name_turkish_prefix
[SeedModChance( 2, lengthof(_name_turkish_prefix
), seed
)], last
);
909 buf
= strecpy(buf
, _name_turkish_suffix
[SeedModChance( 4, lengthof(_name_turkish_suffix
), seed
)], last
);
913 buf
= strecpy(buf
, _name_turkish_real
[SeedModChance( 4, lengthof(_name_turkish_real
), seed
)], last
);
922 * Generates Italian town name from given seed.
923 * @param buf output buffer
924 * @param seed town name seed
925 * @param last end of buffer
927 static char *MakeItalianTownName(char *buf
, const char *last
, uint32 seed
)
929 if (SeedModChance(0, 6, seed
) == 0) { // real city names
930 return strecpy(buf
, _name_italian_real
[SeedModChance(4, lengthof(_name_italian_real
), seed
)], last
);
933 static const char * const mascul_femin_italian
[] = {
938 if (SeedModChance(0, 8, seed
) == 0) { // prefix
939 buf
= strecpy(buf
, _name_italian_pref
[SeedModChance(11, lengthof(_name_italian_pref
), seed
)], last
);
942 uint i
= SeedChance(0, 2, seed
);
943 if (i
== 0) { // masculine form
944 buf
= strecpy(buf
, _name_italian_1m
[SeedModChance(4, lengthof(_name_italian_1m
), seed
)], last
);
945 } else { // feminine form
946 buf
= strecpy(buf
, _name_italian_1f
[SeedModChance(4, lengthof(_name_italian_1f
), seed
)], last
);
949 if (SeedModChance(3, 3, seed
) == 0) {
950 buf
= strecpy(buf
, _name_italian_2
[SeedModChance(11, lengthof(_name_italian_2
), seed
)], last
);
951 buf
= strecpy(buf
, mascul_femin_italian
[i
], last
);
953 buf
= strecpy(buf
, _name_italian_2i
[SeedModChance(16, lengthof(_name_italian_2i
), seed
)], last
);
956 if (SeedModChance(15, 4, seed
) == 0) {
957 if (SeedModChance(5, 2, seed
) == 0) { // generic suffix
958 buf
= strecpy(buf
, _name_italian_3
[SeedModChance(4, lengthof(_name_italian_3
), seed
)], last
);
959 } else { // river name suffix
960 buf
= strecpy(buf
, _name_italian_river1
[SeedModChance(4, lengthof(_name_italian_river1
), seed
)], last
);
961 buf
= strecpy(buf
, _name_italian_river2
[SeedModChance(16, lengthof(_name_italian_river2
), seed
)], last
);
970 * Generates Catalan town name from given seed.
971 * @param buf output buffer
972 * @param seed town name seed
973 * @param last end of buffer
975 static char *MakeCatalanTownName(char *buf
, const char *last
, uint32 seed
)
977 if (SeedModChance(0, 3, seed
) == 0) { // real city names
978 return strecpy(buf
, _name_catalan_real
[SeedModChance(4, lengthof(_name_catalan_real
), seed
)], last
);
981 if (SeedModChance(0, 2, seed
) == 0) { // prefix
982 buf
= strecpy(buf
, _name_catalan_pref
[SeedModChance(11, lengthof(_name_catalan_pref
), seed
)], last
);
985 uint i
= SeedChance(0, 2, seed
);
986 if (i
== 0) { // masculine form
987 buf
= strecpy(buf
, _name_catalan_1m
[SeedModChance(4, lengthof(_name_catalan_1m
), seed
)], last
);
988 buf
= strecpy(buf
, _name_catalan_2m
[SeedModChance(11, lengthof(_name_catalan_2m
), seed
)], last
);
989 } else { // feminine form
990 buf
= strecpy(buf
, _name_catalan_1f
[SeedModChance(4, lengthof(_name_catalan_1f
), seed
)], last
);
991 buf
= strecpy(buf
, _name_catalan_2f
[SeedModChance(11, lengthof(_name_catalan_2f
), seed
)], last
);
994 if (SeedModChance(15, 5, seed
) == 0) {
995 if (SeedModChance(5, 2, seed
) == 0) { // generic suffix
996 buf
= strecpy(buf
, _name_catalan_3
[SeedModChance(4, lengthof(_name_catalan_3
), seed
)], last
);
997 } else { // river name suffix
998 buf
= strecpy(buf
, _name_catalan_river1
[SeedModChance(4, lengthof(_name_catalan_river1
), seed
)], last
);
1007 * Type for all town name generator functions.
1008 * @param buf The buffer to write the name to.
1009 * @param last The last element of the buffer.
1010 * @param seed The seed of the town name.
1011 * @return The end of the filled buffer.
1013 typedef char *TownNameGenerator(char *buf
, const char *last
, uint32 seed
);
1015 /** Contains pointer to generator and minimum buffer size (not incl. terminating '\0') */
1016 struct TownNameGeneratorParams
{
1017 byte min
; ///< minimum number of characters that need to be printed for generator to work correctly
1018 TownNameGenerator
*proc
; ///< generator itself
1021 /** Town name generators */
1022 static const TownNameGeneratorParams _town_name_generators
[] = {
1023 { 4, MakeEnglishOriginalTownName
}, // replaces first 4 characters of name
1024 { 0, MakeFrenchTownName
},
1025 { 0, MakeGermanTownName
},
1026 { 4, MakeEnglishAdditionalTownName
}, // replaces first 4 characters of name
1027 { 0, MakeSpanishTownName
},
1028 { 0, MakeSillyTownName
},
1029 { 0, MakeSwedishTownName
},
1030 { 0, MakeDutchTownName
},
1031 { 8, MakeFinnishTownName
}, // _name_finnish_1
1032 { 0, MakePolishTownName
},
1033 { 0, MakeSlovakTownName
},
1034 { 0, MakeNorwegianTownName
},
1035 { 0, MakeHungarianTownName
},
1036 { 0, MakeAustrianTownName
},
1037 { 0, MakeRomanianTownName
},
1038 { 28, MakeCzechTownName
}, // _name_czech_adj + _name_czech_patmod + 1 + _name_czech_subst_stem + _name_czech_subst_postfix
1039 { 0, MakeSwissTownName
},
1040 { 0, MakeDanishTownName
},
1041 { 0, MakeTurkishTownName
},
1042 { 0, MakeItalianTownName
},
1043 { 0, MakeCatalanTownName
},
1048 * Generates town name from given seed. a language.
1049 * @param buf output buffer
1050 * @param last end of buffer
1051 * @param lang town name language
1052 * @param seed generation seed
1053 * @return last character ('/0')
1055 char *GenerateTownNameString(char *buf
, const char *last
, size_t lang
, uint32 seed
)
1057 assert(lang
< lengthof(_town_name_generators
));
1059 /* Some generators need at least 9 bytes in buffer. English generators need 5 for
1060 * string replacing, others use constructions like strlen(buf)-3 and so on.
1061 * Finnish generator needs to fit all strings from _name_finnish_1.
1062 * Czech generator needs to fit almost whole town name...
1063 * These would break. Using another temporary buffer results in ~40% slower code,
1064 * so use it only when really needed. */
1065 const TownNameGeneratorParams
*par
= &_town_name_generators
[lang
];
1066 if (last
>= buf
+ par
->min
) return par
->proc(buf
, last
, seed
);
1068 char *buffer
= AllocaM(char, par
->min
+ 1);
1069 par
->proc(buffer
, buffer
+ par
->min
, seed
);
1071 return strecpy(buf
, buffer
, last
);