Translations update
[openttd/fttd.git] / src / townnamegen.cpp
blob4ca3864dd390c494f903f876d5ea245a91981217
1 /*
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/>.
6 */
8 /** @file townnamegen.cpp Original town name generators. */
10 #include "stdafx.h"
11 #include "townnamegen.h"
12 #include "core/random_func.hpp"
15 /**
16 * Generates a number from given seed.
17 * @param shift_by number of bits seed is shifted to the right
18 * @param max generated number is in interval 0...max-1
19 * @param seed seed
20 * @return seed transformed to a number from given range
22 static inline uint32 SeedChance(byte shift_by, int max, uint32 seed)
24 return (GB(seed, shift_by, 16) * max) >> 16;
27 /**
28 * Generates a number from given seed. Uses different algorithm than SeedChance().
29 * @param shift_by number of bits seed is shifted to the right
30 * @param max generated number is in interval 0...max-1
31 * @param seed seed
32 * @return seed transformed to a number from given range
34 static inline uint32 SeedModChance(byte shift_by, int max, uint32 seed)
36 /* This actually gives *MUCH* more even distribution of the values
37 * than SeedChance(), which is absolutely horrible in that. If
38 * you do not believe me, try with i.e. the Czech town names,
39 * compare the words (nicely visible on prefixes) generated by
40 * SeedChance() and SeedModChance(). Do not get discouraged by the
41 * never-use-modulo myths, which hold true only for the linear
42 * congruential generators (and Random() isn't such a generator).
43 * --pasky
44 * TODO: Perhaps we should use it for all the name generators? --pasky */
45 return (seed >> shift_by) % max;
49 /**
50 * Choose a string from a string array.
51 * @param strs The string array to choose from.
52 * @param seed The random seed.
53 * @param shift_by The number of bits that the seed is shifted to the right.
54 * @return A random string from the array.
56 template <uint N>
57 static inline const char *choose_str (const char * const (&strs) [N],
58 uint32 seed, uint shift_by)
60 return strs [SeedChance (shift_by, N, seed)];
63 /**
64 * Choose a string from a string array.
65 * @param strs The string array to choose from.
66 * @param seed The random seed.
67 * @param shift_by The number of bits that the seed is shifted to the right.
68 * @return A random string from the array.
70 template <uint N>
71 static inline const char *choose_str_mod (const char * const (&strs) [N],
72 uint32 seed, uint shift_by)
74 return strs [SeedModChance (shift_by, N, seed)];
77 /**
78 * Optionally choose a string from an array.
79 * @param strs The string array to choose from.
80 * @param seed The random seed.
81 * @param shift_by The number of bits that the seed is shifted to the right.
82 * @param threshold The threshold value to actually choose a string.
83 * @return A random string from the array or the null string.
85 template <uint N>
86 static inline const char *choose_str_opt (const char * const (&strs) [N],
87 uint32 seed, uint shift_by, uint threshold)
89 uint i = SeedChance (shift_by, N + threshold, seed);
90 return (i >= threshold) ? strs [i - threshold] : "";
94 /**
95 * Replaces english curses and ugly letter combinations by nicer ones.
96 * @param buf buffer with town name
97 * @param original English (Original) generator was used
99 static void ReplaceEnglishWords(char *buf, bool original)
101 static const uint N = 9;
102 static const char org[N + 1][4] = {
103 {'C','u','n','t'}, {'S','l','a','g'}, {'S','l','u','t'},
104 {'F','a','r','t'}, {'D','r','a','r'}, {'D','r','e','h'},
105 {'F','r','a','r'}, {'G','r','a','r'}, {'B','r','a','r'},
106 {'W','r','a','r'}
108 static const char rep[N + 2][4] = {
109 {'E','a','s','t'}, {'P','i','t','s'}, {'E','d','i','n'},
110 {'B','o','o','t'}, {'Q','u','a','r'}, {'B','a','s','h'},
111 {'S','h','o','r'}, {'A','b','e','r'}, {'O','v','e','r'},
112 {'I','n','v','e'}, {'S','t','a','n'}
115 assert (strlen(buf) >= 4);
117 for (uint i = 0; i < N; i++) {
118 if (memcmp (buf, org[i], 4) == 0) {
119 memcpy (buf, rep[i], 4);
120 return;
124 if (memcmp (buf, org[N], 4) == 0) {
125 memcpy (buf, rep[original ? N : N + 1], 4);
130 * Generates English (Original) town name from given seed.
131 * @param buf output buffer
132 * @param seed town name seed
134 static void MakeEnglishOriginalTownName (stringb *buf, uint32 seed)
136 static const char * const names_1[] = {
137 "Great ", "Little ", "New ", "Fort ",
140 static const char * const names_2[] = {
141 "Wr", "B", "C", "Ch", "Br", "D", "Dr", "F", "Fr",
142 "Fl", "G", "Gr", "H", "L", "M", "N", "P", "Pr",
143 "Pl", "R", "S", "S", "Sl", "T", "Tr", "W",
146 static const char * const names_3[] = {
147 "ar", "a", "e", "in", "on", "u", "un", "en",
150 static const char * const names_4[] = {
151 "n", "ning", "ding", "d", "", "t", "fing",
154 static const char * const names_5[] = {
155 "ville", "ham", "field", "ton", "town", "bridge",
156 "bury", "wood", "ford", "hall", "ston", "way",
157 "stone", "borough", "ley", "head", "bourne", "pool",
158 "worth", "hill", "well", "hattan", "burg",
161 static const char * const names_6[] = {
162 "-on-sea", " Bay", " Market", " Cross", " Bridge",
163 " Falls", " City", " Ridge", " Springs",
166 size_t orig_length = buf->length();
168 buf->append_fmt ("%s%s%s%s%s%s",
169 /* optional first segment */
170 choose_str_opt (names_1, seed, 0, 50),
171 /* mandatory middle segments */
172 choose_str (names_2, seed, 4),
173 choose_str (names_3, seed, 7),
174 choose_str (names_4, seed, 10),
175 choose_str (names_5, seed, 13),
176 /* optional last segment */
177 choose_str_opt (names_6, seed, 15, 60));
179 /* Ce, Ci => Ke, Ki */
180 if (buf->buffer[orig_length] == 'C' && (buf->buffer[orig_length + 1] == 'e' || buf->buffer[orig_length + 1] == 'i')) {
181 buf->buffer[orig_length] = 'K';
184 assert (buf->length() - orig_length >= 4);
185 ReplaceEnglishWords (&buf->buffer[orig_length], true);
189 * Generates English (Additional) town name from given seed.
190 * @param buf output buffer
191 * @param seed town name seed
193 static void MakeEnglishAdditionalTownName (stringb *buf, uint32 seed)
195 static const char * const names_prefix[] = {
196 "Great ", "Little ", "New ", "Fort ", "St. ", "Old ",
199 static const char * const names_1a[] = {
200 "Pen", "Lough", "Stam", "Aber", "Acc", "Ex", "Ax", "Bre",
201 "Cum", "Dun", "Fin", "Inver", "Kin", "Mon", "Nan", "Nant",
202 "Pit", "Pol", "Pont", "Strath", "Tre", "Tilly", "Beck",
203 "Canter", "Bath", "Liver", "Mal", "Ox", "Bletch", "Maccles",
204 "Grim", "Wind", "Sher", "Gates", "Orp", "Brom", "Lewis",
205 "Whit", "White", "Worm", "Tyne", "Avon", "Stan",
208 static const char * const names_1b1[] = {
209 "Wr", "B", "C", "Ch", "Br", "D", "Dr", "F", "Fr",
210 "Fl", "G", "Gr", "H", "L", "M", "N", "P", "Pr",
211 "Pl", "R", "S", "S", "Sl", "T", "Tr", "W",
214 static const char * const names_1b2[] = {
215 "ar", "a", "e", "in", "on", "u",
216 "o", "ee", "es", "ea", "un", "en",
219 static const char * const names_1b3a[] = {
220 "n", "d", "", "t", "", "",
223 static const char * const names_1b3b[] = {
224 "ning", "ding", "fing",
227 static const char * const names_2[] = {
228 "ville", "ham", "field", "ton", "town", "borough", "bridge",
229 "bury", "wood", "ditch", "ford", "hall", "dean", "leigh",
230 "dore", "ston", "stow", "church", "wich", "low", "way",
231 "stone", "minster", "ley", "head", "bourne", "pool", "worth",
232 "hill", "well", "hattan", "burg", "berg", "burgh", "port",
233 "stoke", "haven", "stable", "stock", "side", "brook", "don",
234 "den", "down", "nor", "grove", "combe", "by", "say", "ney",
235 "chester", "dale", "ness", "shaw", "thwaite",
238 static const char * const names_3[] = {
239 "-on-sea", " Bay", " Market", " Beeches", " Common", " Park",
240 " Heath", " Marsh", " Green", " Castle", " End", " Rivers",
241 " Cross", " Bridge", " Falls", " City", " Ridge", " Springs",
244 size_t orig_length = buf->length();
246 /* optional first segment */
247 const char *prefix = choose_str_opt (names_prefix, seed, 0, 50);
249 const char *s11, *s12, *s13;
250 if (SeedChance(3, 20, seed) >= 14) {
251 s11 = choose_str (names_1a, seed, 6);
252 s12 = s13 = "";
253 } else {
254 s11 = choose_str (names_1b1, seed, 6);
255 s12 = choose_str (names_1b2, seed, 9);
256 s13 = (SeedChance (11, 20, seed) >= 4) ?
257 choose_str (names_1b3a, seed, 12) :
258 choose_str (names_1b3b, seed, 12);
261 const char *s2 = choose_str (names_2, seed, 14);
263 /* optional last segment */
264 const char *s3 = choose_str_opt (names_3, seed, 15, 60);
266 buf->append_fmt ("%s%s%s%s%s%s", prefix, s11, s12, s13, s2, s3);
268 assert (buf->length() - orig_length >= 4);
269 ReplaceEnglishWords (&buf->buffer[orig_length], false);
274 * Generates Austrian town name from given seed.
275 * @param buf output buffer
276 * @param seed town name seed
278 static void MakeAustrianTownName (stringb *buf, uint32 seed)
280 static const char * const names_a1[] = {
281 "Bad ", "Deutsch ", "Gross ", "Klein ", "Markt ", "Maria ",
284 static const char * const names_a2[] = {
285 "Aus", "Alten", "Braun", "V\xC3\xB6sl", "Mittern", "Nuss",
286 "Neu", "Walters", "Breiten", "Eisen", "Feld", "Mittern",
287 "Gall", "Obern", "Grat", "Heiligen", "Hof", "Holla", "Stein",
288 "Eber", "Eggen", "Enzers", "Frauen", "Herren", "Hof",
289 "H\xC3\xBCtt", "Kaisers", "K\xC3\xB6nigs", "Knittel", "Lang",
290 "Ober", "Ollers", "Pfaffen", "Potten", "Salz", "Schwarz",
291 "Stocker", "Unter", "Utten", "V\xC3\xB6sen", "Vill", "Weissen",
294 static const char * const names_a3[] = {
295 "see", "bach", "dorf", "ach", "stein", "hofen", "au", "ach",
296 "kirch", "kirchen", "kreuz", "brunn", "siedl", "markt",
297 "wang", "haag",
300 static const char * const names_a4[] = {
301 "Bruck", "Brunn", "Gams", "Grein", "Ried", "Faak", "Zell",
302 "Spital", "Kirchberg", "Saal", "Taferl", "Wald",
305 static const char * const names_a5[] = {
306 "St. ", "Sankt ",
309 static const char * const names_a6[] = {
310 "Aegyd", "Andr\xC3\xA4", "Georgen", "Jakob", "Johann",
311 "Leonhard", "Marein", "Lorenzen", "Margarethen", "Martin",
312 "Michael", "Nikolai", "Oswald", "Peter", "P\xC3\xB6lten",
313 "Stefan", "Stephan", "Thomas", "Veit", "Wolfgang",
316 static const char * const names_f1[] = {
317 " an der ", " ob der ",
320 static const char * const names_f2[] = {
321 "Donau", "Steyr", "Lafnitz", "Leitha", "Thaya", "Gail",
322 "Drau", "Salzach", "Ybbs", "Traisen", "Enns", "Mur", "Ill",
325 static const char * const names_b1[] = {
326 " am ",
329 static const char * const names_b2[] = {
330 "Brenner", "Dachstein", "Gebirge", "Grossglockner", "Hausruck",
331 "Semmering", "Wagram", "Wechsel", "Wilden Kaiser", "Ziller",
334 /* Bad, Maria, Gross, ... */
335 const char *s1 = choose_str_opt (names_a1, seed, 0, 15);
337 uint j = 0;
339 uint i = SeedChance (4, 6, seed);
340 const char *s2, *s3;
341 if (i >= 4) {
342 /* Kaisers-kirchen */
343 s2 = choose_str (names_a2, seed, 7);
344 s3 = choose_str (names_a3, seed, 13);
345 } else if (i >= 2) {
346 /* St. Johann */
347 s2 = choose_str (names_a5, seed, 7);
348 s3 = choose_str (names_a6, seed, 9);
349 j = 1; // More likely to have a " an der " or " am "
350 } else {
351 /* Zell */
352 s2 = choose_str (names_a4, seed, 7);
353 s3 = "";
356 j += SeedChance (1, 6, seed);
357 const char *s4, *s5;
358 if (j >= 4) {
359 /* an der Donau (rivers) */
360 s4 = choose_str (names_f1, seed, 4);
361 s5 = choose_str (names_f2, seed, 5);
362 } else if (j >= 2) {
363 /* am Dachstein (mountains) */
364 s4 = choose_str (names_b1, seed, 4);
365 s5 = choose_str (names_b2, seed, 5);
366 } else {
367 s4 = s5 = "";
370 buf->append_fmt ("%s%s%s%s%s", s1, s2, s3, s4, s5);
375 * Generates German town name from given seed.
376 * @param buf output buffer
377 * @param seed town name seed
379 static void MakeGermanTownName (stringb *buf, uint32 seed)
381 static const char * const names_real[] = {
382 "Berlin", "Bonn", "Bremen", "Cottbus", "Chemnitz", "Dortmund",
383 "Dresden", "Erfurt", "Erlangen", "Essen", "Fulda", "Gera",
384 "Kassel", "Kiel", "K\xC3\xB6ln", "L\xC3\xBC""beck",
385 "Magdeburg", "M\xC3\xBCnchen", "Potsdam", "Stuttgart",
386 "Wiesbaden",
389 static const char * const names_pre[] = {
390 "Bad ", "Klein ", "Neu ",
393 static const char * const names_1[] = {
394 "Alb", "Als", "Ander", "Arns", "Bruns", "Bam", "Biele",
395 "Cloppen", "Co", "Duis", "D\xC3\xBCssel", "Dannen", "Elb",
396 "Els", "Elster", "Eichen", "Ems", "Fahr", "Falken", "Flens",
397 "Frank", "Frei", "Freuden", "Fried", "F\xC3\xBCrsten", "Hahn",
398 "Ham", "Harz", "Heidel", "Hers", "Herz", "Holz", "Hildes",
399 "Inns", "Ilsen", "Ingols", "Kel", "Kies", "Korn", "Kor",
400 "Kreuz", "Kulm", "Langen", "Lim", "Lohr", "L\xC3\xBCne",
401 "Mel", "Michels", "M\xC3\xBChl", "Naum", "Nest", "Nord",
402 "Nort", "Nien", "Nidda", "Nieder", "N\xC3\xBCrn", "Ober",
403 "Offen", "Osna", "Olden", "Ols", "Oranien", "Pader",
404 "Quedlin", "Quer", "Ravens", "Regens", "Rott", "Ros",
405 "R\xC3\xBCssels", "Saal", "Saar", "Salz", "Sch\xC3\xB6ne",
406 "Schwein", "Sonder", "Sonnen", "Stein", "Strals", "Straus",
407 "S\xC3\xBC""d", "Ton", "Unter", "Ur", "Vor", "Wald", "War",
408 "Wert", "Wester", "Witten", "Wolfs", "W\xC3\xBCrz",
411 static const char * const names_2[] = {
412 "bach", "berg", "br\xC3\xBC""ck", "br\xC3\xBC""cken", "burg",
413 "dorf", "feld", "furt", "hausen", "haven", "heim", "horst",
414 "mund", "m\xC3\xBCnster", "stadt", "wald",
417 static const char * const names_4_an_der[] = {
418 "Oder", "Spree", "Donau", "Saale", "Elbe",
421 uint seed_derivative = SeedChance(7, 28, seed);
423 /* optional prefix */
424 const char *pre = (seed_derivative == 12 || seed_derivative == 19) ?
425 choose_str (names_pre, seed, 2) : "";
427 /* mandatory middle segments including option of hardcoded name */
428 uint i = SeedChance (3, lengthof(names_real) + lengthof(names_1), seed);
429 const char *s1, *s2;
430 if (i < lengthof(names_real)) {
431 s1 = names_real[i];
432 s2 = "";
433 } else {
434 s1 = names_1 [i - lengthof(names_real)];
435 s2 = choose_str (names_2, seed, 5);
438 /* optional suffix */
439 const char *s3, *s4;
440 if (seed_derivative == 24) {
441 i = SeedChance (9, lengthof(names_4_an_der) + 1, seed);
442 if (i < lengthof(names_4_an_der)) {
443 s3 = " an der ";
444 s4 = names_4_an_der[i];
445 } else {
446 s3 = " am Main";
447 s4 = "";
449 } else {
450 s3 = s4 = "";
453 buf->append_fmt ("%s%s%s%s%s", pre, s1, s2, s3, s4);
458 * Generates Latin-American town name from given seed.
459 * @param buf output buffer
460 * @param seed town name seed
462 static void MakeSpanishTownName (stringb *buf, uint32 seed)
464 static const char * const names_real[] = {
465 "Caracas", "Maracay", "Maracaibo", "Valencia", "El Dorado",
466 "Morrocoy", "Cata", "Cataito", "Ciudad Bol\xC3\xADvar",
467 "Barquisimeto", "M\xC3\xA9rida", "Puerto Ordaz",
468 "Santa Elena", "San Juan", "San Luis", "San Rafael",
469 "Santiago", "Barcelona", "Barinas", "San Crist\xC3\xB3""bal",
470 "San Fransisco", "San Mart\xC3\xADn", "Guayana", "San Carlos",
471 "El Lim\xC3\xB3n", "Coro", "Corocoro", "Puerto Ayacucho",
472 "Elorza", "Arismendi", "Trujillo", "Carupano", "Anaco",
473 "Lima", "Cuzco", "Iquitos", "Callao", "Huacho", "Camana",
474 "Puerto Chala", "Santa Cruz", "Quito", "Cuenca", "Huacho",
475 "Tulc\xC3\xA1n", "Esmeraldas", "Ibarra", "San Lorenzo",
476 "Macas", "Morana", "Machala", "Zamora", "Latacunga", "Tena",
477 "Cochabamba", "Ascensi\xC3\xB3n", "Magdalena", "Santa Ana",
478 "Manoa", "Sucre", "Oruro", "Uyuni", "Potos\xC3\xAD", "Tupiza",
479 "La Quiaca", "Yacuiba", "San Borja", "Fuerte Olimpio",
480 "Fort\xC3\xADn Esteros", "Campo Grande", "Bogota", "El Banco",
481 "Zaragoza", "Neiva", "Mariano", "Cali", "La Palma", "Andoas",
482 "Barranca", "Montevideo", "Valdivia", "Arica", "Temuco",
483 "Tocopilla", "Mendoza", "Santa Rosa",
486 buf->append (choose_str (names_real, seed, 0));
491 * Generates French town name from given seed.
492 * @param buf output buffer
493 * @param seed town name seed
495 static void MakeFrenchTownName (stringb *buf, uint32 seed)
497 static const char * const names_real[] = {
498 "Agincourt", "Lille", "Dinan", "Aubusson", "Rodez",
499 "Bergerac", "Bordeaux", "Bayonne", "Montpellier",
500 "Mont\xC3\xA9limar", "Valence", "Digne", "Nice", "Cannes",
501 "St. Tropez", "Marseille", "Narbonne", "S\xC3\xA8te",
502 "Aurillac", "Gu\xC3\xA9ret", "Le Creusot", "Nevers",
503 "Auxerre", "Versailles", "Meaux", "Ch\xC3\xA2lons",
504 "Compi\xC3\xA8gne", "Metz", "Chaumont", "Langres", "Bourg",
505 "Lyon", "Vienne", "Grenoble", "Toulon", "Rennes", "Le Mans",
506 "Angers", "Nantes", "Ch\xC3\xA2teauroux", "Orl\xC3\xA9""ans",
507 "Lisieux", "Cherbourg", "Morlaix", "Cognac", "Agen", "Tulle",
508 "Blois", "Troyes", "Charolles", "Grenoble", "Chamb\xC3\xA9ry",
509 "Tours", "St. Brieuc", "St. Malo", "La Rochelle", "St. Flour",
510 "Le Puy", "Vichy", "St. Valery", "Beaujolais", "Narbonne",
511 "Albi", "Paris", "Biarritz", "B\xC3\xA9ziers", "N\xC3\xAEmes",
512 "Chamonix", "Angoul\xC3\xA8me", "Alen\xC3\xA7on",
515 buf->append (choose_str (names_real, seed, 0));
520 * Generates Silly town name from given seed.
521 * @param buf output buffer
522 * @param seed town name seed
524 static void MakeSillyTownName (stringb *buf, uint32 seed)
526 static const char * const names_1[] = {
527 "Binky", "Blubber", "Bumble", "Crinkle", "Crusty", "Dangle",
528 "Dribble", "Flippety", "Google", "Muffin", "Nosey", "Pinker",
529 "Quack", "Rumble", "Sleepy", "Sliggles", "Snooze", "Teddy",
530 "Tinkle", "Twister", "Pinker", "Hippo", "Itchy", "Jelly",
531 "Jingle", "Jolly", "Kipper", "Lazy", "Frogs", "Mouse",
532 "Quack", "Cheeky", "Lumpy", "Grumpy", "Mangle", "Fiddle",
533 "Slugs", "Noodles", "Poodles", "Shiver", "Rumble", "Pixie",
534 "Puddle", "Riddle", "Rattle", "Rickety", "Waffle", "Sagging",
535 "Sausage", "Egg", "Sleepy", "Scatter", "Scramble", "Silly",
536 "Simple", "Trickle", "Slippery", "Slimey", "Slumber", "Soggy",
537 "Sliggles", "Splutter", "Sulky", "Swindle", "Swivel", "Tasty",
538 "Tangle", "Toggle", "Trotting", "Tumble", "Snooze", "Water",
539 "Windy", "Amble", "Bubble", "Cheery", "Cheese", "Cockle",
540 "Cracker", "Crumple", "Teddy", "Evil", "Fairy", "Falling",
541 "Fishy", "Fizzle", "Frosty", "Griddle",
544 static const char * const names_2[] = {
545 "ton", "bury", "bottom", "ville", "well", "weed", "worth",
546 "wig", "wick", "wood", "pool", "head", "burg", "gate",
547 "bridge",
550 buf->append_fmt ("%s%s", choose_str (names_1, seed, 0),
551 choose_str (names_2, seed, 16));
556 * Generates Swedish town name from given seed.
557 * @param buf output buffer
558 * @param seed town name seed
560 static void MakeSwedishTownName (stringb *buf, uint32 seed)
562 static const char * const names_1[] = {
563 "Gamla ", "Lilla ", "Nya ", "Stora ",
566 static const char * const names_2[] = {
567 "Boll", "Bor", "Ed", "En", "Erik", "Es", "Fin", "Fisk",
568 "Gr\xC3\xB6n", "Hag", "Halm", "Karl", "Kram", "Kung", "Land",
569 "Lid", "Lin", "Mal", "Malm", "Marie", "Ner", "Norr", "Oskar",
570 "Sand", "Skog", "Stock", "Stor", "Str\xC3\xB6m", "Sund",
571 "S\xC3\xB6""der", "Tall", "Tratt", "Troll", "Upp", "Var",
572 "V\xC3\xA4ster", "\xC3\x84ngel", "\xC3\x96ster",
575 static const char * const names_2a[] = {
576 "B", "Br", "D", "Dr", "Dv", "F", "Fj", "Fl", "Fr", "G", "Gl",
577 "Gn", "Gr", "H", "J", "K", "Kl", "Kn", "Kr", "Kv", "L", "M",
578 "N", "P", "Pl", "Pr", "R", "S", "Sk", "Skr", "Sl", "Sn", "Sp",
579 "Spr", "St", "Str", "Sv", "T", "Tr", "Tv", "V", "Vr",
582 static const char * const names_2b[] = {
583 "a", "e", "i", "o", "u", "y",
584 "\xC3\xA5", "\xC3\xA4", "\xC3\xB6",
587 static const char * const names_2c[] = {
588 "ck", "d", "dd", "g", "gg", "l", "ld", "m", "n",
589 "nd", "ng", "nn", "p", "pp", "r", "rd", "rk", "rp",
590 "rr", "rt", "s", "sk", "st", "t", "tt", "v",
593 static const char * const names_3[] = {
594 "arp", "berg", "boda", "borg", "bro", "bukten", "by", "byn",
595 "fors", "hammar", "hamn", "holm", "hus", "h\xC3\xA4ttan",
596 "kulle", "k\xC3\xB6ping", "lund", "l\xC3\xB6v", "sala",
597 "skrona", "sl\xC3\xA4tt", "sp\xC3\xA5ng", "stad", "sund",
598 "svall", "svik", "s\xC3\xA5ker", "udde", "valla", "viken",
599 "\xC3\xA4lv", "\xC3\xA5s",
602 /* optional first segment */
603 const char *s1 = choose_str_opt (names_1, seed, 0, 50);
605 /* mandatory middle segments including option of hardcoded name */
606 const char *s2a, *s2b, *s2c;
607 if (SeedChance(4, 5, seed) >= 3) {
608 s2a = choose_str (names_2, seed, 7);
609 s2b = s2c = "";
610 } else {
611 s2a = choose_str (names_2a, seed, 7);
612 s2b = choose_str (names_2b, seed, 10);
613 s2c = choose_str (names_2c, seed, 13);
616 const char *s3 = choose_str (names_3, seed, 16);
618 buf->append_fmt ("%s%s%s%s%s", s1, s2a, s2b, s2c, s3);
623 * Generates Dutch town name from given seed.
624 * @param buf output buffer
625 * @param seed town name seed
627 static void MakeDutchTownName (stringb *buf, uint32 seed)
629 static const char * const names_1[] = {
630 "Nieuw ", "Oud ", "Groot ", "Zuid ",
631 "Noord ", "Oost ", "West ", "Klein ",
634 static const char * const names_2[] = {
635 "Hoog", "Laag", "Zuider", "Zuid", "Ooster", "Oost", "Wester",
636 "West", "Hoofd", "Midden", "Eind", "Amster", "Amstel", "Dord",
637 "Rotter", "Haar", "Til", "Enk", "Dok", "Veen", "Leidsch",
638 "Lely", "En", "Kaats", "U", "Maas", "Mar", "Bla", "Al", "Alk",
639 "Eer", "Drie", "Ter", "Groes", "Goes", "Soest", "Coe", "Uit",
640 "Zwaag", "Hellen", "Slie", "IJ", "Grubben", "Groen", "Lek",
641 "Ridder", "Schie", "Olde", "Roose", "Haar", "Til", "Loos",
642 "Hil",
645 static const char * const names_3[] = {
646 "Drog", "Nat", "Valk", "Bob", "Dedem", "Kollum", "Best",
647 "Hoend", "Leeuw", "Graaf", "Uithuis", "Purm", "Hard", "Hell",
648 "Werk", "Spijk", "Vink", "Wams", "Heerhug", "Koning",
651 static const char * const names_4[] = {
652 "e", "er", "el", "en", "o", "s",
655 static const char * const names_5[] = {
656 "stad", "vorst", "dorp", "dam", "beek", "doorn", "zijl",
657 "zijlen", "lo", "muiden", "meden", "vliet", "nisse", "daal",
658 "vorden", "vaart", "mond", "zaal", "water", "duinen", "heuvel",
659 "geest", "kerk", "meer", "maar", "hoorn", "rade", "wijk",
660 "berg", "heim", "sum", "richt", "burg", "recht", "drecht",
661 "trecht", "tricht", "dricht", "lum", "rum", "halen", "oever",
662 "wolde", "veen", "hoven", "gast", "kum", "hage", "dijk",
663 "zwaag", "pomp", "huizen", "bergen", "schede", "mere", "end",
666 /* optional first segment */
667 const char *s1 = choose_str_opt (names_1, seed, 0, 50);
669 /* mandatory middle segments including option of hardcoded name */
670 const char *s3, *s4;
671 if (SeedChance(6, 9, seed) > 4) {
672 s3 = choose_str (names_2, seed, 9);
673 s4 = "";
674 } else {
675 s3 = choose_str (names_3, seed, 9);
676 s4 = choose_str (names_4, seed, 12);
679 const char *s5 = choose_str (names_5, seed, 15);
681 buf->append_fmt ("%s%s%s%s", s1, s3, s4, s5);
686 * Generates Finnish town name from given seed.
687 * @param buf output buffer
688 * @param seed town name seed
690 static void MakeFinnishTownName (stringb *buf, uint32 seed)
692 static const char * const names_real[] = {
693 "Aijala", "Kisko", "Espoo", "Helsinki", "Tapiola",
694 "J\xC3\xA4rvel\xC3\xA4", "Lahti", "Kotka", "Hamina",
695 "Loviisa", "Kouvola", "Tampere", "Oulu", "Salo", "Malmi",
696 "Pelto", "Koski", "Iisalmi", "Raisio", "Taavetti", "Joensuu",
697 "Imatra", "Tapanila", "Pasila", "Turku", "Kupittaa", "Vaasa",
698 "Pori", "Rauma", "Kolari", "Lieksa",
701 static const char * const names_1[] = {
702 "Hiekka", "Haapa", "Mylly", "Sauna", "Uusi", "Vanha",
703 "Kes\xC3\xA4", "Kuusi", "Pelto", "Tuomi", "Terva", "Olki",
704 "Hein\xC3\xA4", "Sein\xC3\xA4", "Rova", "Koivu", "Kokko",
705 "M\xC3\xA4nty", "Pihlaja", "Pet\xC3\xA4j\xC3\xA4", "Kielo",
706 "Kauha", "Viita", "Kivi", "Riihi", "\xC3\x84\xC3\xA4ne",
707 "Niini",
708 "Lappeen", "Lohjan", "Savon", "Lapin", "Pit\xC3\xA4j\xC3\xA4n",
709 "Martin", "Kuusan", "Kemi", "Keri", "H\xC3\xA4meen", "Kangas",
712 static const char * const names_3[] = {
713 "harju", "linna", "j\xC3\xA4rvi", "kallio", "m\xC3\xA4ki",
714 "nummi", "joki", "kyl\xC3\xA4", "lampi", "lahti",
715 "mets\xC3\xA4", "suo", "laakso", "niitty", "luoto", "hovi",
716 "ranta", "koski", "salo",
719 /* Select randomly if town name should consists of one or two parts. */
720 uint i = SeedChance (0, 15, seed);
721 if (i >= 10) {
722 buf->append (choose_str (names_real, seed, 2));
723 } else if (i >= 5) {
724 assert (!buf->full());
725 /* A two-part name by combining one of names_1 + "la"/"lä".
726 * Only the first strings are good for this purpose. */
727 assert_compile (lengthof(names_1) >= 27);
728 const char *orig = names_1 [SeedChance (0, 27, seed)];
729 bool fit = buf->append (orig);
730 assert (fit);
731 assert (!buf->empty());
732 char *end = &buf->buffer[buf->length() - 1];
733 if (*end == 'i') *end = 'e';
734 buf->append ((strpbrk (orig, "aouAOU") != NULL) ?
735 "la" : "l\xC3\xA4");
736 } else {
737 /* A two-part name by combining one of names_1 + names_3. */
738 buf->append_fmt ("%s%s", choose_str (names_1, seed, 2),
739 choose_str (names_3, seed, 10));
745 * Generates Polish town name from given seed.
746 * @param buf output buffer
747 * @param seed town name seed
749 static void MakePolishTownName (stringb *buf, uint32 seed)
751 struct StringTriple {
752 const char *m, *f, *n;
755 static const StringTriple names_1[] = {
756 { "Wielki ", "Wielka ", "Wielkie " },
757 { "Ma\xC5\x82y ", "Ma\xC5\x82""a ", "Ma\xC5\x82""e " },
758 { "Z\xC5\x82y ", "Z\xC5\x82""a ", "Z\xC5\x82""e " },
759 { "Dobry ", "Dobra ", "Dobre " },
760 { "Nowy ", "Nowa ", "Nowe " },
761 { "Stary ", "Stara ", "Stare " },
762 { "Z\xC5\x82oty ", "Z\xC5\x82ota ", "Z\xC5\x82ote " },
763 { "Zielony ", "Zielona ", "Zielone " },
764 { "Bia\xC5\x82y ", "Bia\xC5\x82""a ", "Bia\xC5\x82""e " },
765 { "Modry ", "Modra ", "Modre " },
766 { "D\xC4\x99""bowy ", "D\xC4\x99""bowa ", "D\xC4\x99""bowe " },
769 static const char * const names_2_o[] = {
770 "Frombork", "Gniezno", "Olsztyn", "Toru\xC5\x84",
771 "Bydgoszcz", "Terespol", "Krak\xC3\xB3w", "Pozna\xC5\x84",
772 "Wroc\xC5\x82""aw", "Katowice", "Cieszyn", "Bytom",
773 "Frombork", "Hel", "Konin", "Lublin", "Malbork", "Sopot",
774 "Sosnowiec", "Gda\xC5\x84sk", "Gdynia", "Sieradz",
775 "Sandomierz", "Szczyrk", "Szczytno", "Szczecin", "Zakopane",
776 "Szklarska Por\xC4\x99""ba", "Bochnia", "Golub-Dobrzyn",
777 "Chojnice", "Ostrowiec", "Otwock", "Wolsztyn",
780 static const char * const names_2_m[] = {
781 "Jarocin", "Gogolin", "Tomasz\xC3\xB3w", "Piotrk\xC3\xB3w",
782 "Lidzbark", "Rypin", "Radzymin", "Wo\xC5\x82omin",
783 "Pruszk\xC3\xB3w", "Olsztynek", "Rypin", "Cisek",
784 "Krotoszyn", "Stoczek", "Lubin", "Lubicz", "Milicz", "Targ",
785 "Ostr\xC3\xB3w", "Ozimek", "Puck", "Rzepin", "Siewierz",
786 "Stargard", "Starogard", "Turek", "Tymbark", "Wolsztyn",
787 "Strzepcz", "Strzebielin", "Sochaczew", "Gr\xC4\x99""bocin",
788 "Gniew", "Lubliniec", "Lubasz", "Lutomiersk", "Niemodlin",
789 "Przeworsk", "Ursus", "Tyczyn", "Sztum", "Szczebrzeszyn",
790 "Wolin", "Wrzeszcz", "Zgierz", "Zieleniec", "Drobin",
791 "Garwolin",
794 static const char * const names_2_f[] = {
795 "Szprotawa", "Pogorzelica", "Mot\xC5\x82""awa", "Lubawa",
796 "Nidzica", "Kruszwica", "Bierawa", "Brodnica", "Chojna",
797 "Krzepica", "Ruda", "Rumia", "Tuchola", "Trzebinia", "Ustka",
798 "Warszawa", "Bobowa", "Dukla", "Krynica", "Murowana",
799 "Niemcza", "Zaspa", "Zawoja", "Wola", "Limanowa", "Rabka",
800 "Skawina", "Pilawa",
803 static const char * const names_2_n[] = {
804 "Lipsko", "Pilzno", "Przodkowo", "Strzelno", "Susz",
805 "Jaworzno", "Choszczno", "Mogilno", "Luzino", "Miasto",
806 "Dziadowo", "Kowalewo", "Legionowo", "Miastko", "Zabrze",
807 "Zawiercie", "Kochanowo", "Miechucino", "Mirachowo",
808 "Robakowo", "Kosakowo", "Borne", "Braniewo", "Sulinowo",
809 "Chmielno", "Jastrz\xC4\x99""bie", "Gryfino", "Koronowo",
810 "Lubichowo", "Opoczno",
813 static const StringTriple names_3[] = {
814 { " Wybudowanie", " Wybudowanie", " Wybudowanie" },
815 { " \xC5\x9Awi\xC4\x99tokrzyski", " \xC5\x9Awi\xC4\x99tokrzyska", " \xC5\x9Awietokrzyskie" },
816 { " G\xC3\xB3rski", " G\xC3\xB3rska", " G\xC3\xB3rskie" },
817 { " Morski", " Morska", " Morskie" },
818 { " Zdr\xC3\xB3j", " Zdr\xC3\xB3j", " Zdr\xC3\xB3j" },
819 { " Wody", " Woda", " Wody" },
820 { " Bajoro", " Bajoro", " Bajoro" },
821 { " Kraje\xC5\x84ski", " Kraje\xC5\x84ska", " Kraje\xC5\x84skie" },
822 { " \xC5\x9Al\xC4\x85ski", " \xC5\x9Al\xC4\x85ska", " \xC5\x9Al\xC4\x85skie" },
823 { " Mazowiecki", " Mazowiecka", " Mazowieckie" },
824 { " Pomorski", " Pomorska", " Pomorskie" },
825 { " Wielki", " Wielka", " Wielkie" },
826 { " Maly", " Ma\xC5\x82""a", " Ma\xC5\x82""e" },
827 { " Warmi\xC5\x84ski", " Warmi\xC5\x84ska", " Warmi\xC5\x84skie " },
828 { " Mazurski", " Mazurska", " Mazurskie " },
829 { " Mniejszy", " Mniejsza", " Mniejsze" },
830 { " Wi\xC4\x99kszy", " Wi\xC4\x99ksza", " Wi\xC4\x99ksze" },
831 { " G\xC3\xB3rny", " G\xC3\xB3rna", " G\xC3\xB3rne" },
832 { " Dolny", " Dolna", " Dolne" },
833 { " Wielki", " Wielka", " Wielkie" },
834 { " Stary", " Stara", " Stare" },
835 { " Nowy", " Nowa", " Nowe" },
836 { " Wielkopolski", " Wielkopolska", " Wielkopolskie" },
837 { " Wzg\xC3\xB3rze", " Wzg\xC3\xB3rza", " Wzg\xC3\xB3rze" },
838 { " Mosty", " Mosty", " Mosty" },
839 { " Kujawski", " Kujawska", " Kujawskie" },
840 { " Ma\xC5\x82opolski", " Malopolska", " Ma\xC5\x82opolskie" },
841 { " Podlaski", " Podlaska", " Podlaskie" },
842 { " Lesny", " Le\xC5\x9Bna", " Le\xC5\x9Bne" },
845 /* optional first segment */
846 uint i = SeedChance(0,
847 lengthof(names_2_o) + lengthof(names_2_m) +
848 lengthof(names_2_f) + lengthof(names_2_n),
849 seed);
851 if (i < lengthof(names_2_o)) {
852 buf->append (choose_str (names_2_o, seed, 3));
853 return;
856 uint j = SeedChance(2, 20, seed);
857 const StringTriple *pre = NULL, *post = NULL;
858 if (j < 4) {
859 pre = &names_1 [SeedChance ( 5, lengthof(names_1), seed)];
860 } else if (j < 16) {
861 post = &names_3 [SeedChance (10, lengthof(names_3), seed)];
864 const char *s;
865 const char * StringTriple::* g;
867 if (i < lengthof(names_2_m) + lengthof(names_2_o)) {
868 s = choose_str (names_2_m, seed, 7);
869 g = &StringTriple::m;
870 } else if (i < lengthof(names_2_f) + lengthof(names_2_m) + lengthof(names_2_o)) {
871 s = choose_str (names_2_f, seed, 7);
872 g = &StringTriple::f;
873 } else {
874 s = choose_str (names_2_n, seed, 7);
875 g = &StringTriple::n;
878 buf->append_fmt ("%s%s%s", (pre != NULL) ? pre->*g : "", s,
879 (post != NULL) ? post->*g : "");
883 /* The advanced hyperintelligent Czech town names generator!
884 * The tables and MakeCzechTownName() is (c) Petr Baudis 2005 (GPL'd)
885 * Feel free to ask me about anything unclear or if you need help
886 * with cloning this for your own language. */
888 /* Sing., pl. */
889 enum CzechGender {
890 CZG_SMASC,
891 CZG_SFEM,
892 CZG_SNEUT,
893 CZG_PMASC,
894 CZG_PFEM,
895 CZG_PNEUT,
896 /* Special for substantive stems - the ending chooses the gender. */
897 CZG_FREE,
898 /* Like CZG_FREE, but disallow CZG_SNEUT. */
899 CZG_NFREE
902 enum CzechPattern {
903 CZP_JARNI,
904 CZP_MLADY,
905 CZP_PRIVL
908 /* This way the substantive can choose only some adjectives/endings:
909 * At least one of these flags must be satisfied: */
910 enum CzechAllow {
911 CZA_SHORT = 1,
912 CZA_MIDDLE = 2,
913 CZA_LONG = 4,
914 CZA_ALL = ~0
917 DECLARE_ENUM_AS_BIT_SET(CzechAllow)
919 /* All these flags must be satisfied (in the stem->others direction): */
920 enum CzechChoose {
921 CZC_NONE = 0, // No requirements.
922 CZC_COLOR = 1,
923 CZC_POSTFIX = 2, // Matched if postfix was inserted.
924 CZC_NOPOSTFIX = 4, // Matched if no postfix was inserted.
925 CZC_ANY = ~0
928 DECLARE_ENUM_AS_BIT_SET(CzechChoose)
930 struct CzechNameSubst {
931 CzechGender gender;
932 CzechAllow allow;
933 CzechChoose choose;
934 const char *name;
937 struct CzechNameAdj {
938 CzechPattern pattern;
939 CzechChoose choose;
940 const char *name;
944 * Generates Czech town name from given seed.
945 * @param buf output buffer
946 * @param seed town name seed
948 static void MakeCzechTownName (stringb *buf, uint32 seed)
950 static const char * const names_real[] = {
951 "A\xC5\xA1", "Bene\xC5\xA1ov", "Beroun", "Bezdru\xC5\xBEice",
952 "Blansko", "B\xC5\x99""eclav", "Brno", "Brunt\xC3\xA1l",
953 "\xC4\x8C""esk\xC3\xA1 L\xC3\xADpa",
954 "\xC4\x8C""esk\xC3\xA9 Bud\xC4\x9Bjovice",
955 "\xC4\x8C""esk\xC3\xBD Krumlov", "D\xC4\x9B\xC4\x8D\xC3\xADn",
956 "Doma\xC5\xBElice", "Dub\xC3\xAD",
957 "Fr\xC3\xBD""dek-M\xC3\xADstek",
958 "Havl\xC3\xAD\xC4\x8Dk\xC5\xAFv Brod", "Hodon\xC3\xADn",
959 "Hradec Kr\xC3\xA1lov\xC3\xA9", "Humpolec", "Cheb",
960 "Chomutov", "Chrudim", "Jablonec nad Nisou",
961 "Jesen\xC3\xADk", "Ji\xC4\x8D\xC3\xADn", "Jihlava",
962 "Jind\xC5\x99ich\xC5\xAFv Hradec", "Karlovy Vary",
963 "Karvin\xC3\xA1", "Kladno", "Klatovy", "Kol\xC3\xADn",
964 "Kosmonosy", "Krom\xC4\x9B\xC5\x99\xC3\xAD\xC5\xBE",
965 "Kutn\xC3\xA1 Hora", "Liberec", "Litom\xC4\x9B\xC5\x99ice",
966 "Louny", "Man\xC4\x9Bt\xC3\xADn", "M\xC4\x9Bln\xC3\xADk",
967 "Mlad\xC3\xA1 Boleslav", "Most", "N\xC3\xA1""chod",
968 "Nov\xC3\xBD Ji\xC4\x8D\xC3\xADn", "Nymburk", "Olomouc",
969 "Opava", "Or\xC3\xA1\xC4\x8Dov", "Ostrava", "Pardubice",
970 "Pelh\xC5\x99imov", "Pol\xC5\xBEice", "P\xC3\xADsek",
971 "Plze\xC5\x88", "Praha", "Prachatice", "P\xC5\x99""erov",
972 "P\xC5\x99\xC3\xAD""bram", "Prost\xC4\x9Bjov",
973 "Rakovn\xC3\xADk", "Rokycany", "Rudn\xC3\xA1",
974 "Rychnov nad Kn\xC4\x9B\xC5\xBEnou", "Semily", "Sokolov",
975 "Strakonice", "St\xC5\x99""edokluky", "\xC5\xA0umperk",
976 "Svitavy", "T\xC3\xA1""bor", "Tachov", "Teplice",
977 "T\xC5\x99""eb\xC3\xAD\xC4\x8D", "Trutnov",
978 "Uhersk\xC3\xA9 Hradi\xC5\xA1t\xC4\x9B",
979 "\xC3\x9Ast\xC3\xAD nad Labem",
980 "\xC3\x9Ast\xC3\xAD nad Orlic\xC3\xAD",
981 "Vset\xC3\xADn", "Vy\xC5\xA1kov",
982 "\xC5\xBD\xC4\x8F\xC3\xA1r nad S\xC3\xA1zavou",
983 "Zl\xC3\xADn", "Znojmo",
986 /* [CzechGender][CzechPattern] - replaces the last character of the adjective
987 * by this.
988 * XXX: [CZG_SMASC][CZP_PRIVL] needs special handling: -ovX -> -uv. */
989 static const char * const names_patmod[][3] = {
990 /* CZG_SMASC */ { "\xC3\xAD", "\xC3\xBD", "X" },
991 /* CZG_SFEM */ { "\xC3\xAD", "\xC3\xA1", "a" },
992 /* CZG_SNEUT */ { "\xC3\xAD", "\xC3\xA9", "o" },
993 /* CZG_PMASC */ { "\xC3\xAD", "\xC3\xA9", "y" },
994 /* CZG_PFEM */ { "\xC3\xAD", "\xC3\xA9", "y" },
995 /* CZG_PNEUT */ { "\xC3\xAD", "\xC3\xA1", "a" }
998 /* Some of items which should be common are doubled. */
999 static const CzechNameAdj names_adj[] = {
1000 { CZP_JARNI, CZC_ANY, "Horn\xC3\xAD" },
1001 { CZP_JARNI, CZC_ANY, "Horn\xC3\xAD" },
1002 { CZP_JARNI, CZC_ANY, "Doln\xC3\xAD" },
1003 { CZP_JARNI, CZC_ANY, "Doln\xC3\xAD" },
1004 { CZP_JARNI, CZC_ANY, "P\xC5\x99""edn\xC3\xAD" },
1005 { CZP_JARNI, CZC_ANY, "Zadn\xC3\xAD" },
1006 { CZP_JARNI, CZC_ANY, "Kosteln\xC3\xAD" },
1007 { CZP_JARNI, CZC_ANY, "Havran\xC3\xAD" },
1008 { CZP_JARNI, CZC_ANY, "\xC5\x98\xC3\xAD\xC4\x8Dn\xC3\xAD" },
1009 { CZP_JARNI, CZC_ANY, "Jezern\xC3\xAD" },
1010 { CZP_MLADY, CZC_ANY, "Velk\xC3\xBD" },
1011 { CZP_MLADY, CZC_ANY, "Velk\xC3\xBD" },
1012 { CZP_MLADY, CZC_ANY, "Mal\xC3\xBD" },
1013 { CZP_MLADY, CZC_ANY, "Mal\xC3\xBD" },
1014 { CZP_MLADY, CZC_ANY, "Vysok\xC3\xBD" },
1015 { CZP_MLADY, CZC_ANY, "\xC4\x8C""esk\xC3\xBD" },
1016 { CZP_MLADY, CZC_ANY, "Moravsk\xC3\xBD" },
1017 { CZP_MLADY, CZC_ANY, "Slov\xC3\xA1""ck\xC3\xBD" },
1018 { CZP_MLADY, CZC_ANY, "Slezsk\xC3\xBD" },
1019 { CZP_MLADY, CZC_ANY, "Uhersk\xC3\xBD" },
1020 { CZP_MLADY, CZC_ANY, "Star\xC3\xBD" },
1021 { CZP_MLADY, CZC_ANY, "Star\xC3\xBD" },
1022 { CZP_MLADY, CZC_ANY, "Nov\xC3\xBD" },
1023 { CZP_MLADY, CZC_ANY, "Nov\xC3\xBD" },
1024 { CZP_MLADY, CZC_ANY, "Mlad\xC3\xBD" },
1025 { CZP_MLADY, CZC_ANY, "Kr\xC3\xA1lovsk\xC3\xBD" },
1026 { CZP_MLADY, CZC_ANY, "Kamenn\xC3\xBD" },
1027 { CZP_MLADY, CZC_ANY, "Cihlov\xC3\xBD" },
1028 { CZP_MLADY, CZC_ANY, "Divn\xC3\xBD" },
1029 { CZP_MLADY, CZC_COLOR, "\xC4\x8C""erven\xC3\xA1" },
1030 { CZP_MLADY, CZC_COLOR, "\xC4\x8C""erven\xC3\xA1" },
1031 { CZP_MLADY, CZC_COLOR, "\xC4\x8C""erven\xC3\xA1" },
1032 { CZP_MLADY, CZC_COLOR, "Zelen\xC3\xA1" },
1033 { CZP_MLADY, CZC_COLOR, "\xC5\xBDlut\xC3\xA1" },
1034 { CZP_MLADY, CZC_COLOR, "Siv\xC3\xA1" },
1035 { CZP_MLADY, CZC_COLOR, "\xC5\xA0""ed\xC3\xA1" },
1036 { CZP_MLADY, CZC_COLOR, "B\xC3\xADl\xC3\xA1" },
1037 { CZP_MLADY, CZC_COLOR, "B\xC3\xADl\xC3\xA1" },
1038 { CZP_MLADY, CZC_COLOR, "Modr\xC3\xA1" },
1039 { CZP_MLADY, CZC_COLOR, "R\xC5\xAF\xC5\xBEov\xC3\xA1" },
1040 { CZP_MLADY, CZC_COLOR, "\xC4\x8C""ern\xC3\xA1" },
1041 { CZP_PRIVL, CZC_ANY, "Kr\xC3\xA1lova" },
1042 { CZP_PRIVL, CZC_ANY, "Janova" },
1043 { CZP_PRIVL, CZC_ANY, "Karlova" },
1044 { CZP_PRIVL, CZC_ANY, "Kry\xC5\xA1tofova" },
1045 { CZP_PRIVL, CZC_ANY, "Ji\xC5\x99\xC3\xADkova" },
1046 { CZP_PRIVL, CZC_ANY, "Petrova" },
1047 { CZP_PRIVL, CZC_ANY, "Sudovo" },
1050 /* Considered a stem for choose/allow matching purposes. */
1051 static const CzechNameSubst names_subst_full[] = {
1052 { CZG_SMASC, CZA_ALL, CZC_COLOR, "Sedlec" },
1053 { CZG_SMASC, CZA_ALL, CZC_COLOR, "Brod" },
1054 { CZG_SMASC, CZA_ALL, CZC_COLOR, "Brod" },
1055 { CZG_SMASC, CZA_ALL, CZC_NONE, "\xC3\x9Aval" },
1056 { CZG_SMASC, CZA_ALL, CZC_COLOR, "\xC5\xBD\xC4\x8F\xC3\xA1r" },
1057 { CZG_SMASC, CZA_ALL, CZC_COLOR, "Smrk" },
1058 { CZG_SFEM, CZA_ALL, CZC_COLOR, "Hora" },
1059 { CZG_SFEM, CZA_ALL, CZC_COLOR, "Lhota" },
1060 { CZG_SFEM, CZA_ALL, CZC_COLOR, "Lhota" },
1061 { CZG_SFEM, CZA_ALL, CZC_COLOR, "Hlava" },
1062 { CZG_SFEM, CZA_ALL, CZC_COLOR, "L\xC3\xADpa" },
1063 { CZG_SNEUT, CZA_ALL, CZC_COLOR, "Pole" },
1064 { CZG_SNEUT, CZA_ALL, CZC_COLOR, "\xC3\x9A""dol\xC3\xAD" },
1065 { CZG_PMASC, CZA_ALL, CZC_NONE, "\xC3\x9Avaly" },
1066 { CZG_PFEM, CZA_ALL, CZC_COLOR, "Luka" },
1067 { CZG_PNEUT, CZA_ALL, CZC_COLOR, "Pole" },
1070 /* TODO: More stems needed. --pasky */
1071 static const CzechNameSubst names_subst_stem[] = {
1072 { CZG_SMASC, CZA_MIDDLE, CZC_COLOR, "Kostel" },
1073 { CZG_SMASC, CZA_MIDDLE, CZC_COLOR, "Kl\xC3\xA1\xC5\xA1ter" },
1074 { CZG_SMASC, CZA_SHORT, CZC_COLOR, "Lhot" },
1075 { CZG_SFEM, CZA_SHORT, CZC_COLOR, "Lhot" },
1076 { CZG_SFEM, CZA_SHORT, CZC_COLOR, "Hur" },
1077 { CZG_FREE, CZA_MIDDLE | CZA_LONG, CZC_NONE, "Sedl" },
1078 { CZG_FREE, CZA_SHORT | CZA_MIDDLE | CZA_LONG, CZC_COLOR, "Hrad" },
1079 { CZG_NFREE, CZA_MIDDLE, CZC_NONE, "Pras" },
1080 { CZG_NFREE, CZA_MIDDLE, CZC_NONE, "Ba\xC5\xBE" },
1081 { CZG_NFREE, CZA_MIDDLE, CZC_NONE, "Tes" },
1082 { CZG_NFREE, CZA_MIDDLE, CZC_NONE, "U\xC5\xBE" },
1083 { CZG_NFREE, CZA_MIDDLE | CZA_LONG, CZC_POSTFIX, "B\xC5\x99" },
1084 { CZG_NFREE, CZA_MIDDLE | CZA_LONG, CZC_NONE, "Vod" },
1085 { CZG_NFREE, CZA_MIDDLE | CZA_LONG, CZC_NONE, "Jan" },
1086 { CZG_NFREE, CZA_LONG, CZC_NONE, "Prach" },
1087 { CZG_NFREE, CZA_LONG, CZC_NONE, "Kunr" },
1088 { CZG_NFREE, CZA_LONG, CZC_NONE, "Strak" },
1089 { CZG_NFREE, CZA_LONG, CZC_NONE, "V\xC3\xADt" },
1090 { CZG_NFREE, CZA_LONG, CZC_NONE, "Vy\xC5\xA1" },
1091 { CZG_NFREE, CZA_LONG, CZC_NONE, "\xC5\xBD""at" },
1092 { CZG_NFREE, CZA_LONG, CZC_NONE, "\xC5\xBD""er" },
1093 { CZG_NFREE, CZA_LONG, CZC_NONE, "St\xC5\x99""ed" },
1094 { CZG_NFREE, CZA_LONG, CZC_NONE, "Harv" },
1095 { CZG_NFREE, CZA_LONG, CZC_NONE, "Pruh" },
1096 { CZG_NFREE, CZA_LONG, CZC_NONE, "Tach" },
1097 { CZG_NFREE, CZA_LONG, CZC_NONE, "P\xC3\xADsn" },
1098 { CZG_NFREE, CZA_LONG, CZC_NONE, "Jin" },
1099 { CZG_NFREE, CZA_LONG, CZC_NONE, "Jes" },
1100 { CZG_NFREE, CZA_LONG, CZC_NONE, "Jar" },
1101 { CZG_NFREE, CZA_LONG, CZC_NONE, "Sok" },
1102 { CZG_NFREE, CZA_LONG, CZC_NONE, "Hod" },
1103 { CZG_NFREE, CZA_LONG, CZC_NONE, "Net" },
1104 { CZG_FREE, CZA_LONG, CZC_NONE, "Pra\xC5\xBE" },
1105 { CZG_FREE, CZA_LONG, CZC_NONE, "Nerat" },
1106 { CZG_FREE, CZA_LONG, CZC_NONE, "Kral" },
1107 { CZG_FREE, CZA_LONG, CZC_NONE, "Hut" },
1108 { CZG_FREE, CZA_LONG, CZC_NOPOSTFIX, "Pan" },
1109 { CZG_FREE, CZA_SHORT | CZA_MIDDLE | CZA_LONG, CZC_NOPOSTFIX, "Odst\xC5\x99""ed" },
1110 { CZG_FREE, CZA_SHORT | CZA_MIDDLE | CZA_LONG, CZC_COLOR, "Mrat" },
1111 { CZG_FREE, CZA_LONG, CZC_COLOR, "Hlav" },
1112 { CZG_FREE, CZA_SHORT | CZA_MIDDLE, CZC_NONE, "M\xC4\x9B\xC5\x99" },
1113 { CZG_FREE, CZA_MIDDLE | CZA_LONG, CZC_NONE, "Lip" },
1116 /* Optional postfix inserted between stem and ending. */
1117 static const char * const names_subst_postfix[] = {
1118 "av", "an", "at",
1119 "ov", "on", "ot",
1120 "ev", "en", "et",
1123 /* This array must have the both neutral genders at the end! */
1124 static const CzechNameSubst names_subst_ending[] = {
1125 { CZG_SMASC, CZA_SHORT | CZA_MIDDLE, CZC_ANY, "ec" },
1126 { CZG_SMASC, CZA_SHORT | CZA_MIDDLE, CZC_ANY, "\xC3\xADn" },
1127 { CZG_SMASC, CZA_SHORT | CZA_MIDDLE | CZA_LONG, CZC_ANY, "ov" },
1128 { CZG_SMASC, CZA_SHORT | CZA_LONG, CZC_ANY, "kov" },
1129 { CZG_SMASC, CZA_LONG, CZC_POSTFIX, "\xC3\xADn" },
1130 { CZG_SMASC, CZA_LONG, CZC_POSTFIX, "n\xC3\xADk" },
1131 { CZG_SMASC, CZA_LONG, CZC_ANY, "burk" },
1132 { CZG_SFEM, CZA_SHORT, CZC_ANY, "ka" },
1133 { CZG_SFEM, CZA_MIDDLE, CZC_ANY, "inka" },
1134 { CZG_SFEM, CZA_MIDDLE, CZC_ANY, "n\xC3\xA1" },
1135 { CZG_SFEM, CZA_LONG, CZC_ANY, "ava" },
1136 { CZG_PMASC, CZA_LONG, CZC_POSTFIX, "\xC3\xADky" },
1137 { CZG_PMASC, CZA_LONG, CZC_ANY, "upy" },
1138 { CZG_PMASC, CZA_LONG, CZC_ANY, "olupy" },
1139 { CZG_PFEM, CZA_LONG, CZC_ANY, "avy" },
1140 { CZG_PFEM, CZA_SHORT | CZA_MIDDLE | CZA_LONG, CZC_ANY, "ice" },
1141 { CZG_PFEM, CZA_SHORT | CZA_MIDDLE | CZA_LONG, CZC_ANY, "i\xC4\x8Dky" },
1142 { CZG_PNEUT, CZA_SHORT | CZA_MIDDLE, CZC_ANY, "na" },
1143 { CZG_SNEUT, CZA_SHORT | CZA_MIDDLE, CZC_ANY, "no" },
1144 { CZG_SNEUT, CZA_LONG, CZC_ANY, "i\xC5\xA1t\xC4\x9B" },
1147 static const char * const names_suffix[] = {
1148 "nad Cidlinou", "nad Dyj\xC3\xAD", "nad Jihlavou",
1149 "nad Labem", "nad Lesy", "nad Moravou", "nad Nisou",
1150 "nad Odrou", "nad Ostravic\xC3\xAD", "nad S\xC3\xA1zavou",
1151 "nad Vltavou", "pod Prad\xC4\x9B""dem",
1152 "pod Radho\xC5\xA1t\xC4\x9Bm", "pod \xC5\x98\xC3\xADpem",
1153 "pod Sn\xC4\x9B\xC5\xBEkou",
1154 "pod \xC5\xA0pi\xC4\x8D\xC3\xA1kem", "pod Sedlem",
1155 "v \xC4\x8C""ech\xC3\xA1""ch", "na Morav\xC4\x9B",
1158 /* 1:3 chance to use a real name. */
1159 if (SeedModChance(0, 4, seed) == 0) {
1160 buf->append (choose_str_mod (names_real, seed, 4));
1161 return;
1164 /* Probability of prefixes/suffixes
1165 * 0..11 prefix, 12..13 prefix+suffix, 14..17 suffix, 18..31 nothing */
1166 int prob_tails = SeedModChance(2, 32, seed);
1167 bool do_prefix = prob_tails < 12;
1168 bool do_suffix = prob_tails > 11 && prob_tails < 17;
1169 bool dynamic_subst;
1171 /* IDs of the respective parts */
1172 int prefix = 0, ending = 0;
1173 uint postfix = 0;
1174 uint stem;
1176 /* The select criteria. */
1177 CzechGender gender;
1178 CzechChoose choose;
1179 CzechAllow allow;
1181 if (do_prefix) prefix = SeedModChance(5, lengthof(names_adj) * 12, seed) / 12;
1182 const char *suffix = do_suffix ? choose_str_mod (names_suffix, seed, 7) : NULL;
1184 /* 3:1 chance 3:1 to use dynamic substantive */
1185 stem = SeedModChance(9,
1186 lengthof(names_subst_full) + 3 * lengthof(names_subst_stem),
1187 seed);
1188 if (stem < lengthof(names_subst_full)) {
1189 /* That was easy! */
1190 dynamic_subst = false;
1191 gender = names_subst_full[stem].gender;
1192 choose = names_subst_full[stem].choose;
1193 allow = names_subst_full[stem].allow;
1194 } else {
1195 unsigned int map[lengthof(names_subst_ending)];
1196 int ending_start = -1, ending_stop = -1;
1198 /* Load the substantive */
1199 dynamic_subst = true;
1200 stem -= lengthof(names_subst_full);
1201 stem %= lengthof(names_subst_stem);
1202 gender = names_subst_stem[stem].gender;
1203 choose = names_subst_stem[stem].choose;
1204 allow = names_subst_stem[stem].allow;
1206 /* Load the postfix (1:1 chance that a postfix will be inserted) */
1207 postfix = SeedModChance(14, lengthof(names_subst_postfix) * 2, seed);
1209 if (choose & CZC_POSTFIX) {
1210 /* Always get a real postfix. */
1211 postfix %= lengthof(names_subst_postfix);
1213 if (choose & CZC_NOPOSTFIX) {
1214 /* Always drop a postfix. */
1215 postfix += lengthof(names_subst_postfix);
1217 if (postfix < lengthof(names_subst_postfix)) {
1218 choose |= CZC_POSTFIX;
1219 } else {
1220 choose |= CZC_NOPOSTFIX;
1223 /* Localize the array segment containing a good gender */
1224 for (ending = 0; ending < (int)lengthof(names_subst_ending); ending++) {
1225 const CzechNameSubst *e = &names_subst_ending[ending];
1227 if (gender == CZG_FREE ||
1228 (gender == CZG_NFREE && e->gender != CZG_SNEUT && e->gender != CZG_PNEUT) ||
1229 gender == e->gender) {
1230 if (ending_start < 0) {
1231 ending_start = ending;
1233 } else if (ending_start >= 0) {
1234 ending_stop = ending - 1;
1235 break;
1238 if (ending_stop < 0) {
1239 /* Whoa. All the endings matched. */
1240 ending_stop = ending - 1;
1243 /* Make a sequential map of the items with good mask */
1244 size_t i = 0;
1245 for (ending = ending_start; ending <= ending_stop; ending++) {
1246 const CzechNameSubst *e = &names_subst_ending[ending];
1248 if ((e->choose & choose) == choose && (e->allow & allow) != 0) {
1249 map[i++] = ending;
1252 assert(i > 0);
1254 /* Load the ending */
1255 ending = map[SeedModChance(16, (int)i, seed)];
1256 /* Override possible CZG_*FREE; this must be a real gender,
1257 * otherwise we get overflow when modifying the adjectivum. */
1258 gender = names_subst_ending[ending].gender;
1259 assert(gender != CZG_FREE && gender != CZG_NFREE);
1262 if (do_prefix && (names_adj[prefix].choose & choose) != choose) {
1263 /* Throw away non-matching prefix. */
1264 do_prefix = false;
1267 /* Now finally construct the name */
1268 if (do_prefix) {
1269 size_t orig_length = buf->length();
1271 CzechPattern pattern = names_adj[prefix].pattern;
1273 buf->append (names_adj[prefix].name);
1275 assert (!buf->empty());
1276 size_t end_length = buf->length() - 1;
1277 /* Find the first character in a UTF-8 sequence */
1278 while (GB(buf->buffer[end_length], 6, 2) == 2) end_length--;
1280 if (gender == CZG_SMASC && pattern == CZP_PRIVL) {
1281 assert (end_length >= orig_length + 2);
1282 /* -ovX -> -uv */
1283 buf->buffer[end_length - 2] = 'u';
1284 assert(buf->buffer[end_length - 1] == 'v');
1285 assert (end_length < buf->length());
1286 buf->buffer[end_length] = ' ';
1287 buf->truncate (end_length + 1);
1288 } else {
1289 assert (end_length >= orig_length);
1290 buf->append_fmt ("%s ", names_patmod[gender][pattern]);
1294 if (dynamic_subst) {
1295 buf->append (names_subst_stem[stem].name);
1296 if (postfix < lengthof(names_subst_postfix)) {
1297 const char *poststr = names_subst_postfix[postfix];
1298 const char *endstr = names_subst_ending[ending].name;
1300 size_t postlen = strlen(poststr);
1301 size_t endlen = strlen(endstr);
1302 assert(postlen > 0 && endlen > 0);
1304 /* Kill the "avava" and "Jananna"-like cases */
1305 if (postlen < 2 || postlen > endlen ||
1306 ((poststr[1] != 'v' || poststr[1] != endstr[1]) &&
1307 poststr[2] != endstr[1])) {
1308 buf->append (poststr);
1310 /* k-i -> c-i, h-i -> z-i */
1311 if (endstr[0] == 'i') {
1312 assert (!buf->empty());
1313 char *last = &buf->buffer[buf->length() - 1];
1314 switch (*last) {
1315 case 'k': *last = 'c'; break;
1316 case 'h': *last = 'z'; break;
1317 default: break;
1322 buf->append (names_subst_ending[ending].name);
1323 } else {
1324 buf->append (names_subst_full[stem].name);
1327 if (suffix != NULL) buf->append_fmt (" %s", suffix);
1332 * Generates Romanian town name from given seed.
1333 * @param buf output buffer
1334 * @param seed town name seed
1336 static void MakeRomanianTownName (stringb *buf, uint32 seed)
1338 static const char * const names_real[] = {
1339 "Adjud", "Alba Iulia", "Alexandria", "Babadag", "Bac\xC3\xA3u",
1340 "Baia Mare", "B\xC3\xA3ile Herculane", "B\xC3\xA3ilesti",
1341 "B\xC3\xA2rlad", "Bicaz", "Bistrita", "Blaj", "Borsec",
1342 "Botosani", "Br\xC3\xA3ila", "Brasov", "Bucuresti", "Buftea",
1343 "Buz\xC3\xA3u", "C\xC3\xA3l\xC3\xA3rasi", "Caransebes",
1344 "Cernavod\xC3\xA3", "Cluj-Napoca", "Constanta", "Covasna",
1345 "Craiova", "Dej", "Deva", "Dorohoi", "Dr.-Tr. Severin",
1346 "Dr\xC3\xA3g\xC3\xA3sani", "F\xC3\xA3g\xC3\xA3ras",
1347 "F\xC3\xA3lticeni", "Fetesti", "Focsani", "Galati",
1348 "Gheorgheni", "Giurgiu", "H\xC3\xA2rsova", "Hunedoara",
1349 "Husi", "Iasi", "Isaccea", "Lugoj", "M\xC3\xA3""cin",
1350 "Mangalia", "Medgidia", "Medias", "Miercurea Ciuc", "Mizil",
1351 "Motru", "N\xC3\xA3s\xC3\xA3ud", "N\xC3\xA3vodari",
1352 "Odobesti", "Oltenita", "Onesti", "Oradea", "Orsova",
1353 "Petrosani", "Piatra Neamt", "Pitesti", "Ploiesti", "Predeal",
1354 "R\xC3\xA2mnicu V\xC3\xA2lcea", "Reghin", "Resita", "Roman",
1355 "Rosiorii de Vede", "Satu Mare", "Sebes",
1356 "Sf\xC3\xA2ntu Gheorghe", "Sibiu", "Sighisoara", "Sinaia",
1357 "Slatina", "Slobozia", "Sovata", "Suceava", "Sulina",
1358 "T\xC3\xA3nd\xC3\xA3rei", "T\xC3\xA2rgoviste",
1359 "T\xC3\xA2rgu Jiu", "T\xC3\xA2rgu Mures", "Tecuci",
1360 "Timisoara", "Tulcea", "Turda", "Turnu M\xC3\xA3gurele",
1361 "Urziceni", "Vaslui", "Vatra Dornei", "Victoria", "Videle",
1362 "Zal\xC3\xA3u",
1365 buf->append (choose_str (names_real, seed, 0));
1370 * Generates Slovak town name from given seed.
1371 * @param buf output buffer
1372 * @param seed town name seed
1374 static void MakeSlovakTownName (stringb *buf, uint32 seed)
1376 static const char * const names_real[] = {
1377 "Bratislava", "Banovce nad Bebravou", "Banska Bystrica",
1378 "Banska Stiavnica", "Bardejov", "Brezno",
1379 "Brezova pod Bradlom", "Bytca", "Cadca", "Cierna nad Tisou",
1380 "Detva", "Detva", "Dolny Kubin", "Dolny Kubin",
1381 "Dunajska Streda", "Gabcikovo", "Galanta", "Gbely", "Gelnica",
1382 "Handlova", "Hlohovec", "Holic", "Humenne", "Hurbanovo",
1383 "Kezmarok", "Komarno", "Kosice", "Kremnica", "Krompachy",
1384 "Kuty", "Leopoldov", "Levoca", "Liptovsky Mikulas",
1385 "Lucenec", "Malacky", "Martin", "Medzilaborce", "Michalovce",
1386 "Modra", "Myjava", "Namestovo", "Nitra", "Nova Bana",
1387 "Nove Mesto nad Vahom", "Nove Zamky", "Partizanske",
1388 "Pezinok", "Piestany", "Poltar", "Poprad", "Povazska Bystrica",
1389 "Prievidza", "Puchov", "Revuca", "Rimavska Sobota", "Roznava",
1390 "Ruzomberok", "Sabinov", "Sala", "Senec", "Senica", "Sered",
1391 "Skalica", "Sladkovicovo", "Smolenice", "Snina",
1392 "Stara Lubovna", "Stara Tura", "Strazske", "Stropkov",
1393 "Stupava", "Sturovo", "Sulekovo", "Topolcany", "Trebisov",
1394 "Trencin", "Trnava", "Turcianske Teplice", "Tvrdosin",
1395 "Vrable", "Vranov nad Toplou", "Zahorska Bystrica", "Zdiar",
1396 "Ziar nad Hronom", "Zilina", "Zlate Moravce", "Zvolen",
1399 buf->append (choose_str (names_real, seed, 0));
1404 * Generates Norwegian town name from given seed.
1405 * @param buf output buffer
1406 * @param seed town name seed
1408 static void MakeNorwegianTownName (stringb *buf, uint32 seed)
1410 static const char * const names_1[] = {
1411 "Arna", "Aust", "Bj\xC3\xB8rk", "Bj\xC3\xB8rn", "Brand",
1412 "B\xC3\xB8ver", "Drag", "Dr\xC3\xB8", "Eids", "Egge", "Fager",
1413 "Finns", "Flat", "Foll", "Foss", "Fugle", "Furu", "Gaus",
1414 "Galte", "Geir", "Gl\xC3\xB8s", "Gran", "Grind", "Grims",
1415 "Gr\xC3\xB8n", "Gr\xC3\xB8t", "Gulle", "Haka", "Hammer",
1416 "Haug", "Hol", "Hon", "Hop", "Hov", "Jess", "Kabel", "Kjerns",
1417 "Kjerring", "Knatte", "Krok", "K\xC3\xB8y", "Lang", "Lauv",
1418 "Leir", "Lund", "Logn", "Lo", "Lyng", "L\xC3\xB8n", "Mesna",
1419 "Mel", "Mo", "Nar", "Nitte", "Nord", "Odd", "Ola", "Otte",
1420 "Ran", "Rev", "Rog", "Roms", "Rosen", "Sand", "Sau", "Sel",
1421 "Sol", "Sjur", "Sk\xC3\xA5r", "Sl\xC3\xA5tt", "Stj\xC3\xB8r",
1422 "Stor", "Svart", "Svens", "Svin", "Sylte", "Syn", "Tran",
1423 "Vass", "Ved", "Vest", "Vesle", "Vik", "V\xC3\xA5g",
1426 static const char * const names_2[] = {
1427 "aker", "anger", "bakken", "bekk", "berg", "botn", "breen",
1428 "bu", "bugen", "by", "bygd", "b\xC3\xB8", "dal", "egga",
1429 "eid", "elv", "enga", "foss", "fjell", "fjord", "foten",
1430 "gard", "grend", "hammer", "haug", "havn", "heim", "hella",
1431 "hovda", "h\xC3\xB8""a", "h\xC3\xB8gda", "kampen",
1432 "kj\xC3\xB8len", "kollen", "kroken", "land", "lia", "mark",
1433 "moen", "myr", "nes", "nuten", "osen", "rike", "rud", "sand",
1434 "set", "sj\xC3\xB8""en", "skogen", "slette", "snipa", "stad",
1435 "stua", "stulen", "sund", "svingen", "s\xC3\xA6tra", "tinden",
1436 "tun", "vang", "vatn", "veid", "vik", "voll", "v\xC3\xA5g",
1437 "um", "\xC3\xA5sen",
1440 static const char * const names_real[] = {
1441 "Alta", "Arendal", "Askim", "Bergen", "Bod\xC3\xB8",
1442 "Brevik", "Bryne", "Br\xC3\xB8nn\xC3\xB8ysund", "Drammen",
1443 "Dr\xC3\xB8""bak", "Egersund", "Elverum", "Farsund", "Fauske",
1444 "Finnsnes", "Flekkefjord", "Flora", "Fosnav\xC3\xA5g",
1445 "Fredrikstad", "F\xC3\xB8rde", "Gj\xC3\xB8vik", "Grimstad",
1446 "Halden", "Hamar", "Hammerfest", "Harstad", "Haugesund",
1447 "Holmestrand", "Horten", "J\xC3\xB8rpeland", "Kirkenes",
1448 "Kolvereid", "Kongsberg", "Kongsvinger", "Kopervik",
1449 "Krager\xC3\xB8", "Kristiansand", "Kristiansund", "Langesund",
1450 "Larvik", "Leirvik", "Leknes", "Levanger", "Lillehammer",
1451 "Lillesand", "Lillestr\xC3\xB8m", "Lyngdal",
1452 "L\xC3\xB8renskog", "Mandal", "Mo i Rana", "Molde",
1453 "Mosj\xC3\xB8""en", "Moss", "Mysen", "M\xC3\xA5l\xC3\xB8y",
1454 "Namsos", "Narvik", "Notodden", "Odda", "Oslo", "Otta",
1455 "Porsgrunn", "Ringerike", "Ris\xC3\xB8r", "Rjukan",
1456 "Sandefjord", "Sandnes", "Sandnessj\xC3\xB8""en",
1457 "Sandvika", "Sarpsborg", "Sauda", "Ski", "Skien",
1458 "Skudeneshavn", "Sortland", "Stathelle", "Stavanger",
1459 "Steinkjer", "Stj\xC3\xB8rdal", "Stokmarknes", "Stord",
1460 "Svelvik", "Svolv\xC3\xA6r", "Troms\xC3\xB8", "Trondheim",
1461 "Tvedestrand", "T\xC3\xB8nsberg", "Ulsteinvik",
1462 "Vads\xC3\xB8", "Vard\xC3\xB8", "Verdals\xC3\xB8ra",
1463 "\xC3\x85krehamn", "\xC3\x85lesund", "\xC3\x85ndalsnes",
1466 /* Use first 4 bit from seed to decide whether or not this town should
1467 * have a real name 3/16 chance. Bit 0-3 */
1468 if (SeedChance(0, 15, seed) < 3) {
1469 /* Use 7bit for the realname table index. Bit 4-10 */
1470 buf->append (choose_str (names_real, seed, 4));
1471 return;
1474 buf->append_fmt ("%s%s",
1475 /* Use 7bit for the first fake part. Bit 4-10 */
1476 choose_str (names_1, seed, 4),
1477 /* Use 7bit for the last fake part. Bit 11-17 */
1478 choose_str (names_2, seed, 11));
1483 * Generates Hungarian town name from given seed.
1484 * @param buf output buffer
1485 * @param seed town name seed
1487 static void MakeHungarianTownName (stringb *buf, uint32 seed)
1489 static const char * const names_1[] = {
1490 "Nagy-", "Kis-", "Fels\xC5\x91-", "Als\xC3\xB3-", "\xC3\x9Aj-",
1493 static const char * const names_2[] = {
1494 "Bodrog", "Dr\xC3\xA1va", "Duna", "Hej\xC5\x91",
1495 "Hern\xC3\xA1""d", "R\xC3\xA1""ba", "Saj\xC3\xB3", "Szamos",
1496 "Tisza", "Zala", "Balaton", "Fert\xC5\x91", "Bakony",
1497 "Cserh\xC3\xA1t", "Bihar", "Hajd\xC3\xBA", "J\xC3\xA1sz",
1498 "Kun", "Magyar", "N\xC3\xB3gr\xC3\xA1""d", "Ny\xC3\xADr",
1499 "Somogy", "Sz\xC3\xA9kely", "Buda", "Gy\xC5\x91r", "Pest",
1500 "Feh\xC3\xA9r", "Cser\xC3\xA9p", "Erd\xC5\x91", "Hegy",
1501 "Homok", "Mez\xC5\x91", "Puszta", "S\xC3\xA1r",
1502 "Cs\xC3\xA1sz\xC3\xA1r", "Herceg", "Kir\xC3\xA1ly", "Nemes",
1503 "P\xC3\xBCsp\xC3\xB6k", "Szent", "Alm\xC3\xA1s",
1504 "Szilv\xC3\xA1s", "Agg", "Aranyos", "B\xC3\xA9k\xC3\xA9s",
1505 "Egyh\xC3\xA1zas", "Gagy", "Heves", "Kapos",
1506 "T\xC3\xA1pi\xC3\xB3", "Torna", "Vas", "V\xC3\xA1mos",
1507 "V\xC3\xA1s\xC3\xA1ros",
1510 static const char * const names_3[] = {
1511 "ap\xC3\xA1ti", "b\xC3\xA1""ba", "bikk", "dob", "fa",
1512 "f\xC3\xB6ld", "hegyes", "kak", "kereszt", "k\xC3\xBCrt",
1513 "lad\xC3\xA1ny", "m\xC3\xA9rges", "szalonta", "telek",
1514 "vas", "v\xC3\xB6lgy",
1517 static const char * const names_4[] = {
1518 "alja", "egyh\xC3\xA1za", "h\xC3\xA1za",
1519 "\xC3\xBAr", "v\xC3\xA1r",
1522 static const char * const names_real[] = {
1523 "Ajka", "Asz\xC3\xB3""d", "Badacsony", "Baja",
1524 "Budapest", "Debrecen", "Eger", "Fony\xC3\xB3""d",
1525 "G\xC3\xB6""d\xC3\xB6ll\xC5\x91", "Gy\xC5\x91r", "Gyula",
1526 "Karcag", "Kecskem\xC3\xA9t", "Keszthely", "Kisk\xC3\xB6re",
1527 "Kocsord", "Kom\xC3\xA1rom", "K\xC5\x91szeg", "Mak\xC3\xB3",
1528 "Moh\xC3\xA1""cs", "Miskolc", "\xC3\x93zd", "Paks",
1529 "P\xC3\xA1pa", "P\xC3\xA9""cs", "Polg\xC3\xA1r", "Sarkad",
1530 "Si\xC3\xB3""fok", "Szeged", "Szentes", "Szolnok", "Tihany",
1531 "Tokaj", "V\xC3\xA1""c", "Z\xC3\xA1hony", "Zirc",
1534 if (SeedChance(12, 15, seed) < 3) {
1535 buf->append (choose_str (names_real, seed, 0));
1536 return;
1539 /* optional first segment */
1540 uint i = SeedChance(3, lengthof(names_1) * 3, seed);
1541 const char *s1 = (i < lengthof(names_1)) ? names_1[i] : "";
1543 /* mandatory middle segments */
1544 const char *s2 = choose_str (names_2, seed, 3);
1545 const char *s3 = choose_str (names_3, seed, 6);
1547 /* optional last segment */
1548 i = SeedChance(10, lengthof(names_4) * 3, seed);
1549 const char *s4 = (i < lengthof(names_4)) ? names_4[i] : "";
1551 buf->append_fmt ("%s%s%s%s", s1, s2, s3, s4);
1556 * Generates Swiss town name from given seed.
1557 * @param buf output buffer
1558 * @param seed town name seed
1560 static void MakeSwissTownName (stringb *buf, uint32 seed)
1562 static const char * const names_real[] = {
1563 "Aarau", "Aesch", "Altdorf", "Arosa", "Appenzell", "Arbon",
1564 "Altst\xC3\xA4tten", "Baar", "Baden", "Bellinzona",
1565 "Brig-Glis", "Bienne", "Bulle", "Binningen", "Burgdorf",
1566 "Bern", "Basel", "B\xC3\xBClach", "Carouge", "Cham",
1567 "Chiasso", "Chur", "Davos", "Del\xC3\xA9mont", "Dietikon",
1568 "D\xC3\xBC""bendorf", "Emmen", "Freienbach-Pf\xC3\xA4""ffikon",
1569 "Fribourg", "Frauenfeld", "Gen\xC3\xA8ve", "Glarus", "Gossau",
1570 "Grenchen", "Herisau", "Horgen", "Horw", "Illnau-Effretikon",
1571 "Ittigen", "Jona", "Kriens", "Kloten", "K\xC3\xB6niz",
1572 "Kreuzlingen", "K\xC3\xBCsnacht", "Agen", "Lancy",
1573 "La Chaux-de-Fonds", "Lenzburg", "Lugano", "Langenthal",
1574 "Littau", "Le Locle", "La Neuveville", "Locarno", "Liestal",
1575 "La Tour-de-Peilz", "Lausanne", "Lyss", "Luzern", "Martigny",
1576 "M\xC3\xBCnchenstein", "Meyrin", "Montreux", "Monthey",
1577 "Morges", "Murten", "Moutier", "Muttenz", "Neuch\xC3\xA2tel",
1578 "Neuhausen am Rheinfall", "Nyon", "Olten", "Onex", "Opfikon",
1579 "Ostermundigen", "Payerne", "Peseux", "Prilly", "Pully",
1580 "Rapperswil", "Richterswil", "Regensdorf", "Rheinfelden",
1581 "Riehen", "Renens", "Romanshorn", "Rorschach", "Stans",
1582 "Schaffhausen", "Steffisburg", "St. Gallen", "Schlieren",
1583 "Sierre", "Solothurn", "St. Moritz", "Sion", "Spiez",
1584 "St\xC3\xA4""fa", "Sursee", "Schwyz", "Thalwil",
1585 "Th\xC3\xB4nex", "Thun", "Uster", "Uzwil", "Vernier",
1586 "Volketswil", "Versoix", "Vevey", "W\xC3\xA4""denswil",
1587 "Wettingen", "Wil", "Wallisellen", "Winterthur", "Wohlen",
1588 "Worb", "Wetzikon", "Yverdon-les-Bains", "Zollikon",
1589 "Zofingen", "Z\xC3\xBCrich", "Zug",
1592 buf->append (choose_str (names_real, seed, 0));
1597 * Generates Danish town name from given seed.
1598 * @param buf output buffer
1599 * @param seed town name seed
1601 static void MakeDanishTownName (stringb *buf, uint32 seed)
1603 static const char * const names_1[] = {
1604 "Gamle ", "Lille ", "Nye ", "Store ", "Kirke ",
1605 "N\xC3\xB8rre ", "Vester ", "S\xC3\xB8nder ",
1606 "\xC3\x98ster ", "Hvide ", "H\xC3\xB8je ", "Kongens ",
1609 static const char * const names_2[] = {
1610 "Ager", "Alle", "Aske", "Balle", "Bede", "Birke", "Bjerring",
1611 "Bj\xC3\xA6ver", "Blommens", "Blok", "Bolder", "Bred",
1612 "Charlotten", "Christians", "Danne", "Diana", "Es", "Fredens",
1613 "Frederiks", "Fugle", "F\xC3\xA5re", "Gille", "Gis", "Givs",
1614 "Glams", "Glo", "Guld", "Had", "Haralds", "Hassel", "Hede",
1615 "Helle", "Hessel", "Hjorts", "Hol", "Horn", "Humle",
1616 "H\xC3\xB8j", "H\xC3\xB8r", "Is", "Jyde", "J\xC3\xA6gers",
1617 "Karls", "Klov", "Kokke", "Kvist", "Lang", "Lange", "Mari",
1618 "Nord", "Ny", "Oks", "Ring", "R\xC3\xB8""de", "Rung",
1619 "R\xC3\xB8r", "Rud", "Saks", "Salt", "Skam", "Silke", "Skod",
1620 "Sk\xC3\xA6l", "Sk\xC3\xA6r", "Sol", "Svend", "Svine",
1621 "Strand", "Stubbe", "Ting", "Tj\xC3\xA6re", "Tore", "Uger",
1622 "Ulf", "Val", "Vand", "Vej", "Vor", "V\xC3\xA6r", "\xC3\x98r",
1623 "\xC3\x85l",
1626 static const char * const names_3[] = {
1627 "basse", "borg", "berg", "bro", "by", "havn", "strup",
1628 "holm", "hus", "k\xC3\xB8""bing", "lund", "lunde", "sund",
1629 "ovre", "h\xC3\xB8j", "dal", "sted", "sten", "l\xC3\xB8se",
1630 "r\xC3\xB8""d", "magle", "s\xC3\xB8", "bjerg", "b\xC3\xA6k",
1631 "drup", "lev", "bo", "lyst", "feld", "skov",
1634 buf->append_fmt ("%s%s%s",
1635 /* optional first segment */
1636 choose_str_opt (names_1, seed, 0, 50),
1637 /* middle segments removed as this algorithm seems
1638 * to create much more realistic names */
1639 choose_str (names_2, seed, 7),
1640 choose_str (names_3, seed, 16));
1645 * Generates Turkish town name from given seed.
1646 * @param buf output buffer
1647 * @param seed town name seed
1649 static void MakeTurkishTownName (stringb *buf, uint32 seed)
1651 static const char * const names_prefix[] = {
1652 "Ak\xC3\xA7""a", "Alt\xC4\xB1n", "Bah\xC3\xA7""e", "Boz",
1653 "B\xC3\xBCy\xC3\xBCk", "\xC3\x87""ay", "Do\xC4\x9Fu",
1654 "Eski", "G\xC3\xBCzel", "K\xC4\xB1z\xC4\xB1l",
1655 "K\xC3\xBC\xC3\xA7\xC3\xBCk", "Orta", "Sar\xC4\xB1",
1656 "Sultan", "Ulu", "Yeni",
1659 static const char * const names_middle[] = {
1660 "aga\xC3\xA7", "ayva", "\xC3\xA7""am", "elma", "kurt",
1661 "pazar", "yal\xC4\xB1",
1664 static const char * const names_suffix[] = {
1665 "dere", "hisar", "kale", "kaya", "kent", "k\xC3\xB6y",
1666 "ova", "\xC3\xB6z\xC3\xBC", "\xC3\xB6ren", "pazar",
1667 "saray", "tepe", "yer", "yurt",
1670 static const char * const names_real[] = {
1671 "Adana", "Ad\xC4\xB1yaman", "Afyon", "A\xC4\x9Fr\xC4\xB1",
1672 "Amasya", "Antalya", "Artvin", "Bal\xC4\xB1kesir",
1673 "Bilecik", "Bitlis", "Bolu", "Burdur", "Bursa",
1674 "\xC3\x87""anakkale", "\xC3\x87""ank\xC4\xB1r\xC4\xB1",
1675 "Denizli", "Diyarbak\xC4\xB1r", "Edirne",
1676 "Elaz\xC4\xB1\xC4\x9F", "Erzurum", "Eskisehir", "Giresun",
1677 "G\xC3\xBCm\xC3\xBC\xC5\x9Fhane", "Hatay", "Isparta",
1678 "\xC4\xB0\xC3\xA7""el", "\xC4\xB0stanbul", "\xC4\xB0zmir",
1679 "Kars", "Kastamonu", "Kayseri", "Kirklareli", "Kocaeli",
1680 "Konya", "K\xC3\xBCtahya", "Malatya", "Manisa",
1681 "Kahramanmara\xC5\x9F", "Mardin", "Mu\xC4\x9Fla",
1682 "Mu\xC5\x9F", "Nev\xC5\x9F""ehir", "Ni\xC4\x9F""de", "Rize",
1683 "Sakarya", "Samsun", "Siirt", "Sinop", "Sivas", "Trabzon",
1684 "\xC5\x9E""anl\xC4\xB1urfa", "Van", "Yozgat", "Zonguldak",
1685 "Aksaray", "Bayburt", "Karaman", "\xC5\x9E\xC4\xB1rnak",
1686 "Bart\xC4\xB1n", "Ardahan", "I\xC4\x9F""d\xC4\xB1r",
1687 "Yalova", "Karab\xC3\xBCk", "Osmaniye", "D\xC3\xBCzce",
1690 uint i = SeedModChance(0, 5, seed);
1692 switch (i) {
1693 case 0:
1694 buf->append_fmt ("%s%s%s",
1695 choose_str_mod (names_prefix, seed, 2),
1696 /* middle segment */
1697 choose_str_mod (names_middle, seed, 4),
1698 /* optional suffix */
1699 (SeedModChance (0, 7, seed) == 0) ?
1700 choose_str_mod (names_suffix, seed, 10) : "");
1701 break;
1703 case 1: case 2:
1704 buf->append_fmt ("%s%s",
1705 choose_str_mod (names_prefix, seed, 2),
1706 choose_str_mod (names_suffix, seed, 4));
1707 break;
1709 default:
1710 buf->append (choose_str_mod (names_real, seed, 4));
1711 break;
1717 * Generates Italian town name from given seed.
1718 * @param buf output buffer
1719 * @param seed town name seed
1721 static void MakeItalianTownName (stringb *buf, uint32 seed)
1723 static const char * const names_real[] = {
1724 "Roma", "Milano", "Napoli", "Torino", "Venezia", "Firenze",
1725 "Palermo", "Genova", "Parma", "Bologna", "Bari", "Cagliari",
1726 "Sassari", "Pisa", "Aosta", "Brescia", "Verona", "Bolzano",
1727 "Padova", "Udine", "Trieste", "Livorno", "Ancona", "Perugia",
1728 "Pescara", "L'Aquila", "Campobasso", "Potenza", "Cosenza",
1729 "Reggio Calabria", "Catania", "Caltanisetta", "Agrigento",
1730 "La Spezia", "Modena", "Vicenza", "Mantova", "Cremona",
1731 "Piacenza", "Reggio Emilia", "Foggia", "Benevento", "Salerno",
1732 "Catanzaro", "Lecce", "Como", "Lecco", "Sondrio", "Trento",
1733 "Desenzano", "Cuneo", "Asti", "Lodi", "Novara", "Biella",
1734 "Vercelli", "Rieti", "Nuoro", "Oristano", "Matera", "Taranto",
1735 "Varese", "Bergamo", "Pavia", "Caserta", "Frosinone",
1736 "Latina", "Enna", "Ragusa", "Siracusa", "Pordenone",
1737 "Imperia", "Verbania", "Alessandria", "Messina", "Siena",
1738 "Arezzo", "Grosseto",
1741 static const char * const names_pref[] = {
1742 "Alpe ", "Borgo ", "Cascina ", "Castel ", "Fonte ", "Forte ",
1743 "Malga ", "Pieve ", "Poggio ", "Rocca ", "Villa ", "Villar ",
1746 static const char * const names_1m[] = {
1747 "Bel", "Borgo", "Bosco", "Campo", "Capo", "Casal", "Castel",
1748 "Colle", "Fiume", "Fonte", "Lago", "Mezzo", "Monte", "Mon",
1749 "Orto", "Passo", "Prato", "Poggio", "Ponte", "Pozzo", "Sasso",
1750 "Tra", "Tre", "Ver", "Vico",
1753 static const char * const names_1f[] = {
1754 "Acqua", "Bra", "Cala", "Casa", "Chiesa", "Citta", "Civita",
1755 "Corte", "Costa", "Croce", "Fontana", "Grotta", "Guardia",
1756 "Mezza", "Palma", "Pietra", "Ripa", "Rocca", "Serra", "Torre",
1757 "Val", "Valle", "Villa",
1760 static const char * const names_2[] = {
1761 "bell", "bianc", "cald", "chiar", "cort", "ferrat", "fier",
1762 "fredd", "gioios", "grec", "guzz", "lung", "long", "migli",
1763 "negr", "ner", "nov", "nuov", "ross", "rotond", "scur",
1764 "secc", "sett", "vecchi", "ventos", "vers", "viv",
1767 static const char * const names_2i[] = {
1768 "", "breve", "brevi", "chiari", "ferro", "fieschi", "fiore",
1769 "fonte", "forte", "gate", "leone", "maggiore", "minore",
1770 "mole", "monte", "poli", "scuri", "terra", "te", "torrione",
1771 "vento", "verde", "versiere",
1775 static const char * const names_3[] = {
1776 " Marittimo", " Marittima", " del Capo", " del Monte",
1777 " di Sopra", " di Sotto", " sui Monti", " dei Marmi",
1778 " dei Sassi", " delle Fonti", " sui Prati", " a Mare",
1779 " Superiore", " Inferiore", " Terme", " Alta", " Bassa",
1780 " Brianza", " Vesuviano", " Scrivia", " Ticino",
1783 static const char * const names_river1[] = {
1784 " del", " sul", " al", " nel",
1787 static const char * const names_river2[] = {
1788 "l'Adda", "l'Adige", "le Alpi", "l'Arno", " Bormida",
1789 " Brenta", "la Dora Baltea", " Lambro", " Mincio",
1790 " Naviglio", "l'Oglio", "l'Olona", "l'Ombrone", " Panaro",
1791 " Piave", " Po", " Reno", " Scrivia", " Secchia", " Serio",
1792 " Tagliamento", " Tanaro", " Taro", " Ticino", " Tevere",
1795 if (SeedModChance(0, 6, seed) == 0) { // real city names
1796 buf->append (choose_str_mod (names_real, seed, 4));
1797 return;
1800 static const char * const mascul_femin_italian[2] = { "o", "a" };
1802 const char *prefix = (SeedModChance (0, 8, seed) == 0) ? // prefix
1803 choose_str_mod (names_pref, seed, 11) : "";
1805 uint i = SeedChance(0, 2, seed);
1806 const char *s1 = (i == 0) ?
1807 choose_str_mod (names_1m, seed, 4) : // masculine form
1808 choose_str_mod (names_1f, seed, 4); // feminine form
1810 const char *s2a, *s2b;
1811 if (SeedModChance(3, 3, seed) == 0) {
1812 s2a = choose_str_mod (names_2, seed, 11);
1813 s2b = mascul_femin_italian[i];
1814 } else {
1815 s2a = choose_str_mod (names_2i, seed, 16);
1816 s2b = "";
1819 const char *s3a, *s3b;
1820 if (SeedModChance(15, 4, seed) == 0) {
1821 if (SeedModChance(5, 2, seed) == 0) { // generic suffix
1822 s3a = choose_str_mod (names_3, seed, 4);
1823 s3b = "";
1824 } else { // river name suffix
1825 s3a = choose_str_mod (names_river1, seed, 4);
1826 s3b = choose_str_mod (names_river2, seed, 16);
1828 } else {
1829 s3a = s3b = "";
1832 buf->append_fmt ("%s%s%s%s%s%s", prefix, s1, s2a, s2b, s3a, s3b);
1837 * Generates Catalan town name from given seed.
1838 * @param buf output buffer
1839 * @param seed town name seed
1841 static void MakeCatalanTownName (stringb *buf, uint32 seed)
1843 static const char * const names_real[] = {
1844 "Barcelona", "L'Hospitalet de Llobregat", "Cerdanyola",
1845 "Martorell", "Badalona", "Tarragona", "Lleida", "Girona",
1846 "Sabadell", "Terrassa", "Reus", "Valls", "Vic",
1847 "Vielha e Mijaran", "Amposta", "Tortosa", "Berga", "Olot",
1848 "Mollerussa", "Banyoles", "Figueres", "Balaguer",
1849 "Vilafranca del Pened\xC3\xA8s", "La Seu d'Urgell",
1850 "El Pont de Suert", "Igualada", "Manresa", "Solsona",
1851 "Les Borges Blanques", "Tremp", "Sort", "Colera", "Portbou",
1852 "El Vendrell", "Falset", "Ripoll", "Cervera", "Gandesa",
1853 "Matar\xC3\xB3", "Montblanc", "Vilanova i la Geltr\xC3\xBA",
1854 "T\xC3\xA0rrega", "Camprodon", "Campdev\xC3\xA0nol",
1855 "Cambrils", "Begur", "Setcases", "Palafrugell", "Begues",
1856 "El Bruc", "Cadaqu\xC3\xA9s", "Collbat\xC3\xB3",
1857 "Cervell\xC3\xB3", "Esparreguera", "Abrera", "Alp", "Das",
1858 "Cercs", "Manlleu", "El Masnou", "Molins de Rei", "Monistrol",
1859 "Rocallaura", "Rub\xC3\xAD", "Ripollet", "Sitges", "Roses",
1862 static const char * const names_pref[] = {
1863 "El Pont de ", "Parets de ", "Canet de ", "Castellar de ",
1864 "Corbera de ", "Arenys de ", "Calella de ", "La Seu de ",
1865 "La Bisbal de ", "Torroella de ", "Port de ", "Vilafranca de ",
1866 "Vilanova de ", "Caldes de ", "La Conca de ", "Olesa de ",
1867 "La Roca de ", "Sant Esteve de ", "Sant Andreu de ",
1868 "Sant Jordi de ", "Sant Joan de ", "Sant Feliu de ",
1869 "Sant Quirze de ", "Sant Sadurn\xC3\xAD de ",
1870 "Santa Coloma de ", "Santa Margarida de ", "Santa Maria de ",
1871 "Sant Mart\xC3\xAD de ", "Sant Pere de ",
1872 "Sant Juli\xC3\xA0 de ", "Sant Vicen\xC3\xA7 de ",
1875 static const char * const names_1m[] = {
1876 "Torrent", "Cami", "Mont", "Bell", "Puig", "Riu",
1879 static const char * const names_1f[] = {
1880 "Pala", "Selva", "Vall", "Serra",
1881 "Torre", "Riba", "Cova", "Terra",
1884 static const char * const names_2m[] = {
1885 "alt", "baix", "fosc", "pelat", "vent\xC3\xB3s",
1886 "negre", "roig", "gr\xC3\xADs",
1889 static const char * const names_2f[] = {
1890 "baixa", "alta", "fosca", "clara",
1891 "negra", "roja", "grisa", "freda",
1894 static const char * const names_3[] = {
1895 " Desp\xC3\xAD", " Desvern", " del Cam\xC3\xAD", " de Mar",
1896 " de Dalt", " de Baix", " del Vall\xC3\xA8s",
1897 " de Bergued\xC3\xA0", " de Conflent", " de la Plana",
1900 static const char * const names_river1[] = {
1901 " d'Anoia", " de Ter", " de Llobregat", " d'Ebre",
1902 " de Segre", " de Francol\xC3\xAD",
1905 if (SeedModChance(0, 3, seed) == 0) { // real city names
1906 buf->append (choose_str_mod (names_real, seed, 4));
1907 return;
1910 const char *prefix = (SeedModChance (0, 2, seed) == 0) ? // prefix
1911 choose_str_mod (names_pref, seed, 11) : "";
1913 uint i = SeedChance(0, 2, seed);
1914 const char *s1, *s2;
1915 if (i == 0) { // masculine form
1916 s1 = choose_str_mod (names_1m, seed, 4);
1917 s2 = choose_str_mod (names_2m, seed, 11);
1918 } else { // feminine form
1919 s1 = choose_str_mod (names_1f, seed, 4);
1920 s2 = choose_str_mod (names_2f, seed, 11);
1923 const char *s3;
1924 if (SeedModChance(15, 5, seed) == 0) {
1925 s3 = (SeedModChance (5, 2, seed) == 0) ?
1926 choose_str_mod (names_3, seed, 4) : // generic suffix
1927 choose_str_mod (names_river1, seed, 4); // river name suffix
1928 } else {
1929 s3 = "";
1932 buf->append_fmt ("%s%s%s%s", prefix, s1, s2, s3);
1937 * Type for all town name generator functions.
1938 * @param buf The buffer to write the name to.
1939 * @param seed The seed of the town name.
1941 typedef void TownNameGenerator (stringb *buf, uint32 seed);
1943 /** Contains pointer to generator and minimum buffer size (not incl. terminating '\0') */
1944 struct TownNameGeneratorParams {
1945 byte min; ///< minimum number of characters that need to be printed for generator to work correctly
1946 TownNameGenerator *proc; ///< generator itself
1949 /** Town name generators */
1950 static const TownNameGeneratorParams _town_name_generators[] = {
1951 { 4, MakeEnglishOriginalTownName}, // replaces first 4 characters of name
1952 { 0, MakeFrenchTownName},
1953 { 0, MakeGermanTownName},
1954 { 4, MakeEnglishAdditionalTownName}, // replaces first 4 characters of name
1955 { 0, MakeSpanishTownName},
1956 { 0, MakeSillyTownName},
1957 { 0, MakeSwedishTownName},
1958 { 0, MakeDutchTownName},
1959 { 8, MakeFinnishTownName}, // names_1
1960 { 0, MakePolishTownName},
1961 { 0, MakeSlovakTownName},
1962 { 0, MakeNorwegianTownName},
1963 { 0, MakeHungarianTownName},
1964 { 0, MakeAustrianTownName},
1965 { 0, MakeRomanianTownName},
1966 { 28, MakeCzechTownName}, // names_adj + names_patmod + 1 + names_subst_stem + names_subst_postfix
1967 { 0, MakeSwissTownName},
1968 { 0, MakeDanishTownName},
1969 { 0, MakeTurkishTownName},
1970 { 0, MakeItalianTownName},
1971 { 0, MakeCatalanTownName},
1974 assert_compile (lengthof(_town_name_generators) == N_ORIG_TOWN_NAME_GEN);
1978 * Generates town name from given seed. a language.
1979 * @param buf output buffer
1980 * @param lang town name language
1981 * @param seed generation seed
1983 void GenerateTownNameString (stringb *buf, uint lang, uint32 seed)
1985 assert(lang < lengthof(_town_name_generators));
1987 /* Some generators need at least 9 bytes in buffer. English generators need 5 for
1988 * string replacing, others use constructions like strlen(buf)-3 and so on.
1989 * Finnish generator needs to fit most strings from names_1.
1990 * Czech generator needs to fit almost whole town name...
1991 * These would break. Using another temporary buffer results in ~40% slower code,
1992 * so use it only when really needed. */
1993 const TownNameGeneratorParams *par = &_town_name_generators[lang];
1994 if (buf->capacity > par->min) {
1995 par->proc (buf, seed);
1996 return;
1999 char *buffer = AllocaM(char, par->min + 1);
2000 stringb tmp (par->min + 1, buffer);
2001 par->proc (&tmp, seed);
2003 buf->append (buffer);