OpenTTD Source  20241108-master-g80f628063a
townname.cpp
Go to the documentation of this file.
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  */
7 
10 #include "stdafx.h"
11 #include "string_func.h"
12 #include "townname_type.h"
13 #include "town.h"
14 #include "strings_func.h"
15 #include "core/random_func.hpp"
16 #include "genworld.h"
17 #include "gfx_layout.h"
18 #include "strings_internal.h"
19 
20 #include "table/townname.h"
21 
22 #include "safeguards.h"
23 
24 
30  grfid(t->townnamegrfid), // by default, use supplied data
31  type(t->townnametype)
32 {
33  if (t->townnamegrfid != 0 && GetGRFTownName(t->townnamegrfid) == nullptr) {
34  /* Fallback to english original */
35  this->grfid = 0;
36  this->type = SPECSTR_TOWNNAME_ENGLISH;
37  return;
38  }
39 }
40 
41 
48 static void GetTownName(StringBuilder &builder, const TownNameParams *par, uint32_t townnameparts)
49 {
50  if (par->grfid == 0) {
51  auto tmp_params = MakeParameters(townnameparts);
52  GetStringWithArgs(builder, par->type, tmp_params);
53  return;
54  }
55 
56  GRFTownNameGenerate(builder, par->grfid, par->type, townnameparts);
57 }
58 
65 std::string GetTownName(const TownNameParams *par, uint32_t townnameparts)
66 {
67  std::string result;
68  StringBuilder builder(result);
69  GetTownName(builder, par, townnameparts);
70  return result;
71 }
72 
78 void GetTownName(StringBuilder &builder, const Town *t)
79 {
80  TownNameParams par(t);
81  GetTownName(builder, &par, t->townnameparts);
82 }
83 
89 std::string GetTownName(const Town *t)
90 {
91  TownNameParams par(t);
92  return GetTownName(&par, t->townnameparts);
93 }
94 
95 
103 bool VerifyTownName(uint32_t r, const TownNameParams *par, TownNames *town_names)
104 {
105  std::string name = GetTownName(par, r);
106 
107  /* Check size and width */
108  if (Utf8StringLength(name) >= MAX_LENGTH_TOWN_NAME_CHARS) return false;
109 
110  if (town_names != nullptr) {
111  if (town_names->find(name) != town_names->end()) return false;
112  town_names->insert(name);
113  } else {
114  for (const Town *t : Town::Iterate()) {
115  /* We can't just compare the numbers since
116  * several numbers may map to a single name. */
117  if (t->name.empty()) {
118  if (name == GetTownName(t)) return false;
119  } else {
120  if (name == t->name) return false;
121  }
122  }
123  }
124 
125  return true;
126 }
127 
128 
136 bool GenerateTownName(Randomizer &randomizer, uint32_t *townnameparts, TownNames *town_names)
137 {
139 
140  /* This function is called very often without entering the gameloop
141  * in between. So reset layout cache to prevent it from growing too big. */
143 
144  /* Do not set i too low, since when we run out of names, we loop
145  * for #tries only one time anyway - then we stop generating more
146  * towns. Do not set it too high either, since looping through all
147  * the other towns may take considerable amount of time (10000 is
148  * too much). */
149  for (int i = 1000; i != 0; i--) {
150  uint32_t r = randomizer.Next();
151  if (!VerifyTownName(r, &par, town_names)) continue;
152 
153  *townnameparts = r;
154  return true;
155  }
156 
157  return false;
158 }
159 
160 
161 
169 static inline uint32_t SeedChance(uint8_t shift_by, size_t max, uint32_t seed)
170 {
171  return (GB(seed, shift_by, 16) * ClampTo<uint16_t>(max)) >> 16;
172 }
173 
174 
182 static inline uint32_t SeedModChance(uint8_t shift_by, size_t max, uint32_t seed)
183 {
184  /* This actually gives *MUCH* more even distribution of the values
185  * than SeedChance(), which is absolutely horrible in that. If
186  * you do not believe me, try with i.e. the Czech town names,
187  * compare the words (nicely visible on prefixes) generated by
188  * SeedChance() and SeedModChance(). Do not get discouraged by the
189  * never-use-modulo myths, which hold true only for the linear
190  * congruential generators (and Random() isn't such a generator).
191  * --pasky
192  * TODO: Perhaps we should use it for all the name generators? --pasky */
193  return (seed >> shift_by) % max;
194 }
195 
196 
205 static inline int32_t SeedChanceBias(uint8_t shift_by, size_t max, uint32_t seed, int bias)
206 {
207  return SeedChance(shift_by, max + bias, seed) - bias;
208 }
209 
210 
218 static void ReplaceWords(const char *org, const char *rep, StringBuilder &builder, size_t start)
219 {
220  assert(strlen(org) == 4 && strlen(rep) == 4 && builder.CurrentIndex() - start >= 4);
221  if (strncmp(&builder[start], org, 4) == 0) memcpy(&builder[start], rep, 4); // Safe as the string in buf is always more than 4 characters long.
222 }
223 
224 
231 static void ReplaceEnglishWords(StringBuilder &builder, size_t start, bool original)
232 {
233  ReplaceWords("Cunt", "East", builder, start);
234  ReplaceWords("Slag", "Pits", builder, start);
235  ReplaceWords("Slut", "Edin", builder, start);
236  if (!original) ReplaceWords("Fart", "Boot", builder, start); // never happens with 'English (Original)'
237  ReplaceWords("Drar", "Quar", builder, start);
238  ReplaceWords("Dreh", "Bash", builder, start);
239  ReplaceWords("Frar", "Shor", builder, start);
240  ReplaceWords("Grar", "Aber", builder, start);
241  ReplaceWords("Brar", "Over", builder, start);
242  ReplaceWords("Wrar", original ? "Inve" : "Stan", builder, start);
243 }
244 
250 static void MakeEnglishOriginalTownName(StringBuilder &builder, uint32_t seed)
251 {
252  size_t start = builder.CurrentIndex();
253 
254  /* optional first segment */
255  int i = SeedChanceBias(0, std::size(_name_original_english_1), seed, 50);
256  if (i >= 0) builder += _name_original_english_1[i];
257 
258  /* mandatory middle segments */
259  builder += _name_original_english_2[SeedChance(4, std::size(_name_original_english_2), seed)];
260  builder += _name_original_english_3[SeedChance(7, std::size(_name_original_english_3), seed)];
261  builder += _name_original_english_4[SeedChance(10, std::size(_name_original_english_4), seed)];
262  builder += _name_original_english_5[SeedChance(13, std::size(_name_original_english_5), seed)];
263 
264  /* optional last segment */
265  i = SeedChanceBias(15, std::size(_name_original_english_6), seed, 60);
266  if (i >= 0) builder += _name_original_english_6[i];
267 
268  /* Ce, Ci => Ke, Ki */
269  if (builder[start] == 'C' && (builder[start + 1] == 'e' || builder[start + 1] == 'i')) {
270  builder[start] = 'K';
271  }
272 
273  assert(builder.CurrentIndex() - start >= 4);
274  ReplaceEnglishWords(builder, start, true);
275 }
276 
277 
283 static void MakeEnglishAdditionalTownName(StringBuilder &builder, uint32_t seed)
284 {
285  size_t start = builder.CurrentIndex();
286 
287  /* optional first segment */
288  int i = SeedChanceBias(0, std::size(_name_additional_english_prefix), seed, 50);
289  if (i >= 0) builder += _name_additional_english_prefix[i];
290 
291  if (SeedChance(3, 20, seed) >= 14) {
292  builder += _name_additional_english_1a[SeedChance(6, std::size(_name_additional_english_1a), seed)];
293  } else {
294  builder += _name_additional_english_1b1[SeedChance(6, std::size(_name_additional_english_1b1), seed)];
295  builder += _name_additional_english_1b2[SeedChance(9, std::size(_name_additional_english_1b2), seed)];
296  if (SeedChance(11, 20, seed) >= 4) {
297  builder += _name_additional_english_1b3a[SeedChance(12, std::size(_name_additional_english_1b3a), seed)];
298  } else {
299  builder += _name_additional_english_1b3b[SeedChance(12, std::size(_name_additional_english_1b3b), seed)];
300  }
301  }
302 
303  builder += _name_additional_english_2[SeedChance(14, std::size(_name_additional_english_2), seed)];
304 
305  /* optional last segment */
306  i = SeedChanceBias(15, std::size(_name_additional_english_3), seed, 60);
307  if (i >= 0) builder += _name_additional_english_3[i];
308 
309  assert(builder.CurrentIndex() - start >= 4);
310  ReplaceEnglishWords(builder, start, false);
311 }
312 
313 
319 static void MakeAustrianTownName(StringBuilder &builder, uint32_t seed)
320 {
321  /* Bad, Maria, Gross, ... */
322  int i = SeedChanceBias(0, std::size(_name_austrian_a1), seed, 15);
323  if (i >= 0) builder += _name_austrian_a1[i];
324 
325  int j = 0;
326 
327  i = SeedChance(4, 6, seed);
328  if (i >= 4) {
329  /* Kaisers-kirchen */
330  builder += _name_austrian_a2[SeedChance( 7, std::size(_name_austrian_a2), seed)];
331  builder += _name_austrian_a3[SeedChance(13, std::size(_name_austrian_a3), seed)];
332  } else if (i >= 2) {
333  /* St. Johann */
334  builder += _name_austrian_a5[SeedChance( 7, std::size(_name_austrian_a5), seed)];
335  builder += _name_austrian_a6[SeedChance( 9, std::size(_name_austrian_a6), seed)];
336  j = 1; // More likely to have a " an der " or " am "
337  } else {
338  /* Zell */
339  builder += _name_austrian_a4[SeedChance( 7, std::size(_name_austrian_a4), seed)];
340  }
341 
342  i = SeedChance(1, 6, seed);
343  if (i >= 4 - j) {
344  /* an der Donau (rivers) */
345  builder += _name_austrian_f1[SeedChance(4, std::size(_name_austrian_f1), seed)];
346  builder += _name_austrian_f2[SeedChance(5, std::size(_name_austrian_f2), seed)];
347  } else if (i >= 2 - j) {
348  /* am Dachstein (mountains) */
349  builder += _name_austrian_b1[SeedChance(4, std::size(_name_austrian_b1), seed)];
350  builder += _name_austrian_b2[SeedChance(5, std::size(_name_austrian_b2), seed)];
351  }
352 }
353 
354 
360 static void MakeGermanTownName(StringBuilder &builder, uint32_t seed)
361 {
362  uint seed_derivative = SeedChance(7, 28, seed);
363 
364  /* optional prefix */
365  if (seed_derivative == 12 || seed_derivative == 19) {
366  uint i = SeedChance(2, std::size(_name_german_pre), seed);
367  builder += _name_german_pre[i];
368  }
369 
370  /* mandatory middle segments including option of hardcoded name */
371  uint i = SeedChance(3, std::size(_name_german_real) + std::size(_name_german_1), seed);
372  if (i < std::size(_name_german_real)) {
373  builder += _name_german_real[i];
374  } else {
375  builder += _name_german_1[i - std::size(_name_german_real)];
376 
377  i = SeedChance(5, std::size(_name_german_2), seed);
378  builder += _name_german_2[i];
379  }
380 
381  /* optional suffix */
382  if (seed_derivative == 24) {
383  i = SeedChance(9, std::size(_name_german_4_an_der) + std::size(_name_german_4_am), seed);
384  if (i < std::size(_name_german_4_an_der)) {
385  builder += _name_german_3_an_der[0];
386  builder += _name_german_4_an_der[i];
387  } else {
388  builder += _name_german_3_am[0];
389  builder += _name_german_4_am[i - std::size(_name_german_4_an_der)];
390  }
391  }
392 }
393 
394 
400 static void MakeSpanishTownName(StringBuilder &builder, uint32_t seed)
401 {
402  builder += _name_spanish_real[SeedChance(0, std::size(_name_spanish_real), seed)];
403 }
404 
405 
411 static void MakeFrenchTownName(StringBuilder &builder, uint32_t seed)
412 {
413  builder += _name_french_real[SeedChance(0, std::size(_name_french_real), seed)];
414 }
415 
416 
422 static void MakeSillyTownName(StringBuilder &builder, uint32_t seed)
423 {
424  builder += _name_silly_1[SeedChance( 0, std::size(_name_silly_1), seed)];
425  builder += _name_silly_2[SeedChance(16, std::size(_name_silly_2), seed)];
426 }
427 
428 
434 static void MakeSwedishTownName(StringBuilder &builder, uint32_t seed)
435 {
436  /* optional first segment */
437  int i = SeedChanceBias(0, std::size(_name_swedish_1), seed, 50);
438  if (i >= 0) builder += _name_swedish_1[i];
439 
440  /* mandatory middle segments including option of hardcoded name */
441  if (SeedChance(4, 5, seed) >= 3) {
442  builder += _name_swedish_2[SeedChance( 7, std::size(_name_swedish_2), seed)];
443  } else {
444  builder += _name_swedish_2a[SeedChance( 7, std::size(_name_swedish_2a), seed)];
445  builder += _name_swedish_2b[SeedChance(10, std::size(_name_swedish_2b), seed)];
446  builder += _name_swedish_2c[SeedChance(13, std::size(_name_swedish_2c), seed)];
447  }
448 
449  builder += _name_swedish_3[SeedChance(16, std::size(_name_swedish_3), seed)];
450 }
451 
452 
458 static void MakeDutchTownName(StringBuilder &builder, uint32_t seed)
459 {
460  /* optional first segment */
461  int i = SeedChanceBias(0, std::size(_name_dutch_1), seed, 50);
462  if (i >= 0) builder += _name_dutch_1[i];
463 
464  /* mandatory middle segments including option of hardcoded name */
465  if (SeedChance(6, 9, seed) > 4) {
466  builder += _name_dutch_2[SeedChance( 9, std::size(_name_dutch_2), seed)];
467  } else {
468  builder += _name_dutch_3[SeedChance( 9, std::size(_name_dutch_3), seed)];
469  builder += _name_dutch_4[SeedChance(12, std::size(_name_dutch_4), seed)];
470  }
471 
472  builder += _name_dutch_5[SeedChance(15, std::size(_name_dutch_5), seed)];
473 }
474 
475 
481 static void MakeFinnishTownName(StringBuilder &builder, uint32_t seed)
482 {
483  size_t start = builder.CurrentIndex();
484 
485  /* Select randomly if town name should consists of one or two parts. */
486  if (SeedChance(0, 15, seed) >= 10) {
487  builder += _name_finnish_real[SeedChance(2, std::size(_name_finnish_real), seed)];
488  return;
489  }
490 
491  if (SeedChance(0, 15, seed) >= 5) {
492  /* A two-part name by combining one of _name_finnish_1 + "la"/"lä"
493  * The reason for not having the contents of _name_finnish_{1,2} in the same table is
494  * that the ones in _name_finnish_2 are not good for this purpose. */
495  uint sel = SeedChance( 0, std::size(_name_finnish_1), seed);
496  builder += _name_finnish_1[sel];
497  size_t last = builder.CurrentIndex() - 1;
498  if (builder[last] == 'i') builder[last] = 'e';
499 
500  std::string_view view(&builder[start], builder.CurrentIndex() - start);
501  if (view.find_first_of("aouAOU") != std::string_view::npos) {
502  builder += "la";
503  } else {
504  builder += "l\u00e4";
505  }
506  return;
507  }
508 
509  /* A two-part name by combining one of _name_finnish_{1,2} + _name_finnish_3.
510  * Why aren't _name_finnish_{1,2} just one table? See above. */
511  uint sel = SeedChance(2, std::size(_name_finnish_1) + std::size(_name_finnish_2), seed);
512  if (sel >= std::size(_name_finnish_1)) {
513  builder += _name_finnish_2[sel - std::size(_name_finnish_1)];
514  } else {
515  builder += _name_finnish_1[sel];
516  }
517 
518  builder += _name_finnish_3[SeedChance(10, std::size(_name_finnish_3), seed)];
519 }
520 
521 
527 static void MakePolishTownName(StringBuilder &builder, uint32_t seed)
528 {
529  /* optional first segment */
530  uint i = SeedChance(0,
531  std::size(_name_polish_2_o) + std::size(_name_polish_2_m) +
532  std::size(_name_polish_2_f) + std::size(_name_polish_2_n),
533  seed);
534  uint j = SeedChance(2, 20, seed);
535 
536 
537  if (i < std::size(_name_polish_2_o)) {
538  builder += _name_polish_2_o[SeedChance(3, std::size(_name_polish_2_o), seed)];
539  return;
540  }
541 
542  if (i < std::size(_name_polish_2_m) + std::size(_name_polish_2_o)) {
543  if (j < 4) {
544  builder += _name_polish_1_m[SeedChance(5, std::size(_name_polish_1_m), seed)];
545  }
546 
547  builder += _name_polish_2_m[SeedChance(7, std::size(_name_polish_2_m), seed)];
548 
549  if (j >= 4 && j < 16) {
550  builder += _name_polish_3_m[SeedChance(10, std::size(_name_polish_3_m), seed)];
551  }
552 
553  return;
554  }
555 
556  if (i < std::size(_name_polish_2_f) + std::size(_name_polish_2_m) + std::size(_name_polish_2_o)) {
557  if (j < 4) {
558  builder += _name_polish_1_f[SeedChance(5, std::size(_name_polish_1_f), seed)];
559  }
560 
561  builder += _name_polish_2_f[SeedChance(7, std::size(_name_polish_2_f), seed)];
562 
563  if (j >= 4 && j < 16) {
564  builder += _name_polish_3_f[SeedChance(10, std::size(_name_polish_3_f), seed)];
565  }
566 
567  return;
568  }
569 
570  if (j < 4) {
571  builder += _name_polish_1_n[SeedChance(5, std::size(_name_polish_1_n), seed)];
572  }
573 
574  builder += _name_polish_2_n[SeedChance(7, std::size(_name_polish_2_n), seed)];
575 
576  if (j >= 4 && j < 16) {
577  builder += _name_polish_3_n[SeedChance(10, std::size(_name_polish_3_n), seed)];
578  }
579 
580  return;
581 }
582 
583 
589 static void MakeCzechTownName(StringBuilder &builder, uint32_t seed)
590 {
591  /* 1:3 chance to use a real name. */
592  if (SeedModChance(0, 4, seed) == 0) {
593  builder += _name_czech_real[SeedModChance(4, std::size(_name_czech_real), seed)];
594  return;
595  }
596 
597  /* Probability of prefixes/suffixes
598  * 0..11 prefix, 12..13 prefix+suffix, 14..17 suffix, 18..31 nothing */
599  int prob_tails = SeedModChance(2, 32, seed);
600  bool do_prefix = prob_tails < 12;
601  bool do_suffix = prob_tails > 11 && prob_tails < 17;
602  bool dynamic_subst;
603 
604  /* IDs of the respective parts */
605  int prefix = 0, ending = 0, suffix = 0;
606  size_t postfix = 0;
607  size_t stem;
608 
609  /* The select criteria. */
610  CzechGender gender;
611  CzechChoose choose;
612  CzechAllow allow;
613 
614  if (do_prefix) prefix = SeedModChance(5, std::size(_name_czech_adj) * 12, seed) / 12;
615  if (do_suffix) suffix = SeedModChance(7, std::size(_name_czech_suffix), seed);
616  /* 3:1 chance 3:1 to use dynamic substantive */
617  stem = SeedModChance(9,
618  std::size(_name_czech_subst_full) + 3 * std::size(_name_czech_subst_stem),
619  seed);
620  if (stem < std::size(_name_czech_subst_full)) {
621  /* That was easy! */
622  dynamic_subst = false;
623  gender = _name_czech_subst_full[stem].gender;
624  choose = _name_czech_subst_full[stem].choose;
625  allow = _name_czech_subst_full[stem].allow;
626  } else {
627  uint map[std::size(_name_czech_subst_ending)];
628  int ending_start = -1, ending_stop = -1;
629 
630  /* Load the substantive */
631  dynamic_subst = true;
632  stem -= std::size(_name_czech_subst_full);
633  stem %= std::size(_name_czech_subst_stem);
634  gender = _name_czech_subst_stem[stem].gender;
635  choose = _name_czech_subst_stem[stem].choose;
636  allow = _name_czech_subst_stem[stem].allow;
637 
638  /* Load the postfix (1:1 chance that a postfix will be inserted) */
639  postfix = SeedModChance(14, std::size(_name_czech_subst_postfix) * 2, seed);
640 
641  if (choose & CZC_POSTFIX) {
642  /* Always get a real postfix. */
643  postfix %= std::size(_name_czech_subst_postfix);
644  }
645  if (choose & CZC_NOPOSTFIX) {
646  /* Always drop a postfix. */
647  postfix += std::size(_name_czech_subst_postfix);
648  }
649  if (postfix < std::size(_name_czech_subst_postfix)) {
650  choose |= CZC_POSTFIX;
651  } else {
652  choose |= CZC_NOPOSTFIX;
653  }
654 
655  /* Localize the array segment containing a good gender */
656  for (ending = 0; ending < (int)std::size(_name_czech_subst_ending); ending++) {
657  const CzechNameSubst *e = &_name_czech_subst_ending[ending];
658 
659  if (gender == CZG_FREE ||
660  (gender == CZG_NFREE && e->gender != CZG_SNEUT && e->gender != CZG_PNEUT) ||
661  gender == e->gender) {
662  if (ending_start < 0) {
663  ending_start = ending;
664  }
665  } else if (ending_start >= 0) {
666  ending_stop = ending - 1;
667  break;
668  }
669  }
670  if (ending_stop < 0) {
671  /* Whoa. All the endings matched. */
672  ending_stop = ending - 1;
673  }
674 
675  /* Make a sequential map of the items with good mask */
676  size_t i = 0;
677  for (ending = ending_start; ending <= ending_stop; ending++) {
678  const CzechNameSubst *e = &_name_czech_subst_ending[ending];
679 
680  if ((e->choose & choose) == choose && (e->allow & allow) != 0) {
681  map[i++] = ending;
682  }
683  }
684  assert(i > 0);
685 
686  /* Load the ending */
687  ending = map[SeedModChance(16, (int)i, seed)];
688  /* Override possible CZG_*FREE; this must be a real gender,
689  * otherwise we get overflow when modifying the adjectivum. */
690  gender = _name_czech_subst_ending[ending].gender;
691  assert(gender != CZG_FREE && gender != CZG_NFREE);
692  }
693 
694  if (do_prefix && (_name_czech_adj[prefix].choose & choose) != choose) {
695  /* Throw away non-matching prefix. */
696  do_prefix = false;
697  }
698 
699  /* Now finally construct the name */
700  if (do_prefix) {
701  CzechPattern pattern = _name_czech_adj[prefix].pattern;
702 
703  builder += _name_czech_adj[prefix].name;
704 
705  size_t endpos = builder.CurrentIndex() - 1;
706  /* Find the first character in a UTF-8 sequence */
707  while (GB(builder[endpos], 6, 2) == 2) endpos--;
708  builder.RemoveElementsFromBack(builder.CurrentIndex() - endpos);
709 
710  if (gender == CZG_SMASC && pattern == CZP_PRIVL) {
711  /* -ovX -> -uv */
712  builder[endpos - 2] = 'u';
713  } else {
714  builder += _name_czech_patmod[gender][pattern];
715  }
716 
717  builder += ' ';
718  }
719 
720  if (dynamic_subst) {
721  builder += _name_czech_subst_stem[stem].name;
722  if (postfix < std::size(_name_czech_subst_postfix)) {
723  const char *poststr = _name_czech_subst_postfix[postfix];
724  const char *endstr = _name_czech_subst_ending[ending].name;
725 
726  size_t postlen = strlen(poststr);
727  size_t endlen = strlen(endstr);
728  assert(postlen > 0 && endlen > 0);
729 
730  /* Kill the "avava" and "Jananna"-like cases */
731  if (postlen < 2 || postlen > endlen ||
732  ((poststr[1] != 'v' || poststr[1] != endstr[1]) &&
733  poststr[2] != endstr[1])) {
734  builder += poststr;
735 
736  /* k-i -> c-i, h-i -> z-i */
737  if (endstr[0] == 'i') {
738  size_t last = builder.CurrentIndex() - 1;
739  switch (builder[last]) {
740  case 'k': builder[last] = 'c'; break;
741  case 'h': builder[last] = 'z'; break;
742  default: break;
743  }
744  }
745  }
746  }
747  builder += _name_czech_subst_ending[ending].name;
748  } else {
749  builder += _name_czech_subst_full[stem].name;
750  }
751 
752  if (do_suffix) {
753  builder += " ";
754  builder += _name_czech_suffix[suffix];
755  }
756 }
757 
758 
764 static void MakeRomanianTownName(StringBuilder &builder, uint32_t seed)
765 {
766  builder += _name_romanian_real[SeedChance(0, std::size(_name_romanian_real), seed)];
767 }
768 
769 
775 static void MakeSlovakTownName(StringBuilder &builder, uint32_t seed)
776 {
777  builder += _name_slovak_real[SeedChance(0, std::size(_name_slovak_real), seed)];
778 }
779 
780 
786 static void MakeNorwegianTownName(StringBuilder &builder, uint32_t seed)
787 {
788  /* Use first 4 bit from seed to decide whether or not this town should
789  * have a real name 3/16 chance. Bit 0-3 */
790  if (SeedChance(0, 15, seed) < 3) {
791  /* Use 7bit for the realname table index. Bit 4-10 */
792  builder += _name_norwegian_real[SeedChance(4, std::size(_name_norwegian_real), seed)];
793  return;
794  }
795 
796  /* Use 7bit for the first fake part. Bit 4-10 */
797  builder += _name_norwegian_1[SeedChance(4, std::size(_name_norwegian_1), seed)];
798  /* Use 7bit for the last fake part. Bit 11-17 */
799  builder += _name_norwegian_2[SeedChance(11, std::size(_name_norwegian_2), seed)];
800 }
801 
802 
808 static void MakeHungarianTownName(StringBuilder &builder, uint32_t seed)
809 {
810  if (SeedChance(12, 15, seed) < 3) {
811  builder += _name_hungarian_real[SeedChance(0, std::size(_name_hungarian_real), seed)];
812  return;
813  }
814 
815  /* optional first segment */
816  uint i = SeedChance(3, std::size(_name_hungarian_1) * 3, seed);
817  if (i < std::size(_name_hungarian_1)) builder += _name_hungarian_1[i];
818 
819  /* mandatory middle segments */
820  builder += _name_hungarian_2[SeedChance(3, std::size(_name_hungarian_2), seed)];
821  builder += _name_hungarian_3[SeedChance(6, std::size(_name_hungarian_3), seed)];
822 
823  /* optional last segment */
824  i = SeedChance(10, std::size(_name_hungarian_4) * 3, seed);
825  if (i < std::size(_name_hungarian_4)) {
826  builder += _name_hungarian_4[i];
827  }
828 }
829 
830 
836 static void MakeSwissTownName(StringBuilder &builder, uint32_t seed)
837 {
838  builder += _name_swiss_real[SeedChance(0, std::size(_name_swiss_real), seed)];
839 }
840 
841 
847 static void MakeDanishTownName(StringBuilder &builder, uint32_t seed)
848 {
849  /* optional first segment */
850  int i = SeedChanceBias(0, std::size(_name_danish_1), seed, 50);
851  if (i >= 0) builder += _name_danish_1[i];
852 
853  /* middle segments removed as this algorithm seems to create much more realistic names */
854  builder += _name_danish_2[SeedChance( 7, std::size(_name_danish_2), seed)];
855  builder += _name_danish_3[SeedChance(16, std::size(_name_danish_3), seed)];
856 }
857 
858 
864 static void MakeTurkishTownName(StringBuilder &builder, uint32_t seed)
865 {
866  uint i = SeedModChance(0, 5, seed);
867 
868  switch (i) {
869  case 0:
870  builder += _name_turkish_prefix[SeedModChance( 2, std::size(_name_turkish_prefix), seed)];
871 
872  /* middle segment */
873  builder += _name_turkish_middle[SeedModChance( 4, std::size(_name_turkish_middle), seed)];
874 
875  /* optional suffix */
876  if (SeedModChance(0, 7, seed) == 0) {
877  builder += _name_turkish_suffix[SeedModChance( 10, std::size(_name_turkish_suffix), seed)];
878  }
879  break;
880 
881  case 1: case 2:
882  builder += _name_turkish_prefix[SeedModChance( 2, std::size(_name_turkish_prefix), seed)];
883  builder += _name_turkish_suffix[SeedModChance( 4, std::size(_name_turkish_suffix), seed)];
884  break;
885 
886  default:
887  builder += _name_turkish_real[SeedModChance( 4, std::size(_name_turkish_real), seed)];
888  break;
889  }
890 }
891 
892 
898 static void MakeItalianTownName(StringBuilder &builder, uint32_t seed)
899 {
900  if (SeedModChance(0, 6, seed) == 0) { // real city names
901  builder += _name_italian_real[SeedModChance(4, std::size(_name_italian_real), seed)];
902  return;
903  }
904 
905  static const char * const mascul_femin_italian[] = {
906  "o",
907  "a",
908  };
909 
910  if (SeedModChance(0, 8, seed) == 0) { // prefix
911  builder += _name_italian_pref[SeedModChance(11, std::size(_name_italian_pref), seed)];
912  }
913 
914  uint i = SeedChance(0, 2, seed);
915  if (i == 0) { // masculine form
916  builder += _name_italian_1m[SeedModChance(4, std::size(_name_italian_1m), seed)];
917  } else { // feminine form
918  builder += _name_italian_1f[SeedModChance(4, std::size(_name_italian_1f), seed)];
919  }
920 
921  if (SeedModChance(3, 3, seed) == 0) {
922  builder += _name_italian_2[SeedModChance(11, std::size(_name_italian_2), seed)];
923  builder += mascul_femin_italian[i];
924  } else {
925  builder += _name_italian_2i[SeedModChance(16, std::size(_name_italian_2i), seed)];
926  }
927 
928  if (SeedModChance(15, 4, seed) == 0) {
929  if (SeedModChance(5, 2, seed) == 0) { // generic suffix
930  builder += _name_italian_3[SeedModChance(4, std::size(_name_italian_3), seed)];
931  } else { // river name suffix
932  builder += _name_italian_river1[SeedModChance(4, std::size(_name_italian_river1), seed)];
933  builder += _name_italian_river2[SeedModChance(16, std::size(_name_italian_river2), seed)];
934  }
935  }
936 }
937 
938 
944 static void MakeCatalanTownName(StringBuilder &builder, uint32_t seed)
945 {
946  if (SeedModChance(0, 3, seed) == 0) { // real city names
947  builder += _name_catalan_real[SeedModChance(4, std::size(_name_catalan_real), seed)];
948  return;
949  }
950 
951  if (SeedModChance(0, 2, seed) == 0) { // prefix
952  builder += _name_catalan_pref[SeedModChance(11, std::size(_name_catalan_pref), seed)];
953  }
954 
955  uint i = SeedChance(0, 2, seed);
956  if (i == 0) { // masculine form
957  builder += _name_catalan_1m[SeedModChance(4, std::size(_name_catalan_1m), seed)];
958  builder += _name_catalan_2m[SeedModChance(11, std::size(_name_catalan_2m), seed)];
959  } else { // feminine form
960  builder += _name_catalan_1f[SeedModChance(4, std::size(_name_catalan_1f), seed)];
961  builder += _name_catalan_2f[SeedModChance(11, std::size(_name_catalan_2f), seed)];
962  }
963 
964  if (SeedModChance(15, 5, seed) == 0) {
965  if (SeedModChance(5, 2, seed) == 0) { // generic suffix
966  builder += _name_catalan_3[SeedModChance(4, std::size(_name_catalan_3), seed)];
967  } else { // river name suffix
968  builder += _name_catalan_river1[SeedModChance(4, std::size(_name_catalan_river1), seed)];
969  }
970  }
971 }
972 
973 
979 typedef void TownNameGenerator(StringBuilder &builder, uint32_t seed);
980 
983  MakeEnglishOriginalTownName, // replaces first 4 characters of name
986  MakeEnglishAdditionalTownName, // replaces first 4 characters of name
991  MakeFinnishTownName, // _name_finnish_1
998  MakeCzechTownName, // _name_czech_adj + _name_czech_patmod + 1 + _name_czech_subst_stem + _name_czech_subst_postfix
1004 };
1005 
1006 
1013 void GenerateTownNameString(StringBuilder &builder, size_t lang, uint32_t seed)
1014 {
1015  assert(lang < std::size(_town_name_generators));
1016  return _town_name_generators[lang](builder, seed);
1017 }
constexpr static debug_inline uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
static void ReduceLineCache()
Reduce the size of linecache if necessary to prevent infinite growth.
Definition: gfx_layout.cpp:405
Equivalent to the std::back_insert_iterator in function, with some convenience helpers for string con...
void RemoveElementsFromBack(size_t amount)
Remove the given amount of characters from the back of the string.
size_t CurrentIndex()
Get the current index in the string.
Functions related to world/map generation.
Functions related to laying out the texts.
Pseudo random number generator.
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:57
Definition of base types and functions in a cross-platform compatible way.
size_t Utf8StringLength(const char *s)
Get the length of an UTF-8 encoded string in number of characters and thus not the number of bytes th...
Definition: string.cpp:359
Functions related to low-level strings.
void GetStringWithArgs(StringBuilder &builder, StringID string, StringParameters &args, uint case_index, bool game_script)
Get a parsed string with most special stringcodes replaced by the string parameters.
Definition: strings.cpp:243
Functions related to OTTD's strings.
uint8_t town_name
the town name generator used for town names
GameCreationSettings game_creation
settings used during the creation of a game (map)
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:388
Structure to encapsulate the pseudo random number generators.
Definition: random_func.hpp:27
uint32_t Next()
Generate the next pseudo random number.
Definition: random_func.cpp:43
Struct holding parameters used to generate town name.
Definition: townname_type.h:28
TownNameParams(uint8_t town_name)
Initializes this struct from language ID.
Definition: townname_type.h:36
uint16_t type
town name style
Definition: townname_type.h:30
uint32_t grfid
newgrf ID (0 if not used)
Definition: townname_type.h:29
Town data structure.
Definition: town.h:54
Base of the town class.
static const uint MAX_LENGTH_TOWN_NAME_CHARS
The maximum length of a town name in characters including '\0'.
Definition: town_type.h:109
static void MakeHungarianTownName(StringBuilder &builder, uint32_t seed)
Generates Hungarian town name from given seed.
Definition: townname.cpp:808
static void MakeCatalanTownName(StringBuilder &builder, uint32_t seed)
Generates Catalan town name from given seed.
Definition: townname.cpp:944
static uint32_t SeedModChance(uint8_t shift_by, size_t max, uint32_t seed)
Generates a number from given seed.
Definition: townname.cpp:182
static void MakePolishTownName(StringBuilder &builder, uint32_t seed)
Generates Polish town name from given seed.
Definition: townname.cpp:527
static void MakeSlovakTownName(StringBuilder &builder, uint32_t seed)
Generates Slovak town name from given seed.
Definition: townname.cpp:775
static void MakeSwedishTownName(StringBuilder &builder, uint32_t seed)
Generates Swedish town name from given seed.
Definition: townname.cpp:434
static void MakeFrenchTownName(StringBuilder &builder, uint32_t seed)
Generates French town name from given seed.
Definition: townname.cpp:411
static void MakeItalianTownName(StringBuilder &builder, uint32_t seed)
Generates Italian town name from given seed.
Definition: townname.cpp:898
static void MakeNorwegianTownName(StringBuilder &builder, uint32_t seed)
Generates Norwegian town name from given seed.
Definition: townname.cpp:786
bool VerifyTownName(uint32_t r, const TownNameParams *par, TownNames *town_names)
Verifies the town name is valid and unique.
Definition: townname.cpp:103
static void MakeCzechTownName(StringBuilder &builder, uint32_t seed)
Generates Czech town name from given seed.
Definition: townname.cpp:589
static void MakeGermanTownName(StringBuilder &builder, uint32_t seed)
Generates German town name from given seed.
Definition: townname.cpp:360
static void MakeDanishTownName(StringBuilder &builder, uint32_t seed)
Generates Danish town name from given seed.
Definition: townname.cpp:847
static void MakeEnglishOriginalTownName(StringBuilder &builder, uint32_t seed)
Generates English (Original) town name from given seed.
Definition: townname.cpp:250
static void ReplaceWords(const char *org, const char *rep, StringBuilder &builder, size_t start)
Replaces a string beginning in 'org' with 'rep'.
Definition: townname.cpp:218
static void MakeEnglishAdditionalTownName(StringBuilder &builder, uint32_t seed)
Generates English (Additional) town name from given seed.
Definition: townname.cpp:283
static void MakeFinnishTownName(StringBuilder &builder, uint32_t seed)
Generates Finnish town name from given seed.
Definition: townname.cpp:481
static TownNameGenerator * _town_name_generators[]
Town name generators.
Definition: townname.cpp:982
void TownNameGenerator(StringBuilder &builder, uint32_t seed)
Type for all town name generator functions.
Definition: townname.cpp:979
static void MakeSpanishTownName(StringBuilder &builder, uint32_t seed)
Generates Latin-American town name from given seed.
Definition: townname.cpp:400
static void ReplaceEnglishWords(StringBuilder &builder, size_t start, bool original)
Replaces english curses and ugly letter combinations by nicer ones.
Definition: townname.cpp:231
bool GenerateTownName(Randomizer &randomizer, uint32_t *townnameparts, TownNames *town_names)
Generates valid town name.
Definition: townname.cpp:136
static void MakeRomanianTownName(StringBuilder &builder, uint32_t seed)
Generates Romanian town name from given seed.
Definition: townname.cpp:764
static void MakeSillyTownName(StringBuilder &builder, uint32_t seed)
Generates Silly town name from given seed.
Definition: townname.cpp:422
static void MakeTurkishTownName(StringBuilder &builder, uint32_t seed)
Generates Turkish town name from given seed.
Definition: townname.cpp:864
static void MakeDutchTownName(StringBuilder &builder, uint32_t seed)
Generates Dutch town name from given seed.
Definition: townname.cpp:458
static void MakeSwissTownName(StringBuilder &builder, uint32_t seed)
Generates Swiss town name from given seed.
Definition: townname.cpp:836
static int32_t SeedChanceBias(uint8_t shift_by, size_t max, uint32_t seed, int bias)
Generates a number from given seed.
Definition: townname.cpp:205
static uint32_t SeedChance(uint8_t shift_by, size_t max, uint32_t seed)
Generates a number from given seed.
Definition: townname.cpp:169
static void GetTownName(StringBuilder &builder, const TownNameParams *par, uint32_t townnameparts)
Fills builder with specified town name.
Definition: townname.cpp:48
void GenerateTownNameString(StringBuilder &builder, size_t lang, uint32_t seed)
Generates town name from given seed.
Definition: townname.cpp:1013
static void MakeAustrianTownName(StringBuilder &builder, uint32_t seed)
Generates Austrian town name from given seed.
Definition: townname.cpp:319
Namepart tables for the town name generator.
Definition of structures used for generating town names.