# townname.cpp

Go to the documentation of this file.

    00001 /* $Id: townname.cpp 18809 2010-01-15 16:41:15Z rubidium $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * 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.
    00006  * 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.
    00007  * 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/>.
    00008  */
    00009
    00012 #include "stdafx.h"
    00013 #include "string_func.h"
    00014 #include "townname_type.h"
    00015 #include "town.h"
    00016 #include "core/alloc_func.hpp"
    00017 #include "strings_func.h"
    00018 #include "core/random_func.hpp"
    00019
    00020 #include "table/townname.h"
    00021
    00022
    00027 TownNameParams::TownNameParams(const Town *t) :
    00028     grfid(t->townnamegrfid), // by default, use supplied data
    00029     type(t->townnametype)
    00030 {
    00031   if (t->townnamegrfid != 0 && GetGRFTownName(t->townnamegrfid) == NULL) {
    00032     /* Fallback to english original */
    00033     this->grfid = 0;
    00034     this->type = SPECSTR_TOWNNAME_ENGLISH;
    00035     return;
    00036   }
    00037 }
    00038
    00039
    00048 char *GetTownName(char *buff, const TownNameParams *par, uint32 townnameparts, const char *last)
    00049 {
    00050   if (par->grfid == 0) {
    00051     int64 temp[1] = { townnameparts };
    00052     return GetStringWithArgs(buff, par->type, temp, last);
    00053   }
    00054
    00055   return GRFTownNameGenerate(buff, par->grfid, par->type, townnameparts, last);
    00056 }
    00057
    00058
    00066 char *GetTownName(char *buff, const Town *t, const char *last)
    00067 {
    00068   TownNameParams par(t);
    00069   return GetTownName(buff, &par, t->townnameparts, last);
    00070 }
    00071
    00072
    00079 bool VerifyTownName(uint32 r, const TownNameParams *par)
    00080 {
    00081   /* reserve space for extra unicode character and terminating '\0' */
    00082   char buf1[MAX_LENGTH_TOWN_NAME_BYTES + MAX_CHAR_LENGTH];
    00083   char buf2[MAX_LENGTH_TOWN_NAME_BYTES + MAX_CHAR_LENGTH];
    00084
    00085   GetTownName(buf1, par, r, lastof(buf1));
    00086
    00087   /* Check size and width */
    00088   if (strlen(buf1) >= MAX_LENGTH_TOWN_NAME_BYTES) return false;
    00089
    00090   const Town *t;
    00091   FOR_ALL_TOWNS(t) {
    00092     /* We can't just compare the numbers since
    00093      * several numbers may map to a single name. */
    00094     const char *buf = t->name;
    00095     if (buf == NULL) {
    00096       GetTownName(buf2, t, lastof(buf2));
    00097       buf = buf2;
    00098     }
    00099     if (strcmp(buf1, buf2) == 0) return false;
    00100   }
    00101
    00102   return true;
    00103 }
    00104
    00105
    00111 bool GenerateTownName(uint32 *townnameparts)
    00112 {
    00113   /* Do not set too low tries, since when we run out of names, we loop
    00114    * for #tries only one time anyway - then we stop generating more
    00115    * towns. Do not show it too high neither, since looping through all
    00116    * the other towns may take considerable amount of time (10000 is
    00117    * too much). */
    00118   TownNameParams par(_settings_game.game_creation.town_name);
    00119
    00120   for (int i = 1000; i != 0; i--) {
    00121     uint32 r = InteractiveRandom();
    00122     if (!VerifyTownName(r, &par)) continue;
    00123
    00124     *townnameparts = r;
    00125     return true;
    00126   }
    00127
    00128   return false;
    00129 }
    00130
    00131
    00132
    00140 static inline uint32 SeedChance(byte shift_by, int max, uint32 seed)
    00141 {
    00142   return (GB(seed, shift_by, 16) * max) >> 16;
    00143 }
    00144
    00145
    00153 static inline uint32 SeedModChance(byte shift_by, int max, uint32 seed)
    00154 {
    00155   /* This actually gives *MUCH* more even distribution of the values
    00156    * than SeedChance(), which is absolutely horrible in that. If
    00157    * you do not believe me, try with i.e. the Czech town names,
    00158    * compare the words (nicely visible on prefixes) generated by
    00159    * SeedChance() and SeedModChance(). Do not get dicouraged by the
    00160    * never-use-modulo myths, which hold true only for the linear
    00161    * congruential generators (and Random() isn't such a generator).
    00162    * --pasky
    00163    * TODO: Perhaps we should use it for all the name generators? --pasky */
    00164   return (seed >> shift_by) % max;
    00165 }
    00166
    00167
    00176 static inline int32 SeedChanceBias(byte shift_by, int max, uint32 seed, int bias)
    00177 {
    00178   return SeedChance(shift_by, max + bias, seed) - bias;
    00179 }
    00180
    00181
    00188 static void ReplaceWords(const char *org, const char *rep, char *buf)
    00189 {
    00190   if (strncmp(buf, org, 4) == 0) strncpy(buf, rep, 4); // Safe as the string in buf is always more than 4 characters long.
    00191 }
    00192
    00193
    00199 static void ReplaceEnglishWords(char *buf, bool original)
    00200 {
    00201   ReplaceWords("Cunt", "East", buf);
    00202   ReplaceWords("Slag", "Pits", buf);
    00203   ReplaceWords("Slut", "Edin", buf);
    00204   if (!original) ReplaceWords("Fart", "Boot", buf); // never happens with 'English (Original)'
    00205   ReplaceWords("Drar", "Quar", buf);
    00206   ReplaceWords("Dreh", "Bash", buf);
    00207   ReplaceWords("Frar", "Shor", buf);
    00208   ReplaceWords("Grar", "Aber", buf);
    00209   ReplaceWords("Brar", "Over", buf);
    00210   ReplaceWords("Wrar", original ? "Inve" : "Stan", buf);
    00211 }
    00212
    00219 static char *MakeEnglishOriginalTownName(char *buf, const char *last, uint32 seed)
    00220 {
    00221   char *orig = buf;
    00222
    00223   /* optional first segment */
    00224   int i = SeedChanceBias(0, lengthof(_name_original_english_1), seed, 50);
    00225   if (i >= 0) buf = strecpy(buf, _name_original_english_1[i], last);
    00226
    00227   /* mandatory middle segments */
    00228   buf = strecpy(buf, _name_original_english_2[SeedChance(4,  lengthof(_name_original_english_2), seed)], last);
    00229   buf = strecpy(buf, _name_original_english_3[SeedChance(7,  lengthof(_name_original_english_3), seed)], last);
    00230   buf = strecpy(buf, _name_original_english_4[SeedChance(10, lengthof(_name_original_english_4), seed)], last);
    00231   buf = strecpy(buf, _name_original_english_5[SeedChance(13, lengthof(_name_original_english_5), seed)], last);
    00232
    00233   /* optional last segment */
    00234   i = SeedChanceBias(15, lengthof(_name_original_english_6), seed, 60);
    00235   if (i >= 0) buf = strecpy(buf, _name_original_english_6[i], last);
    00236
    00237   /* Ce, Ci => Ke, Ki */
    00238   if (orig[0] == 'C' && (orig[1] == 'e' || orig[1] == 'i')) {
    00239     orig[0] = 'K';
    00240   }
    00241
    00242   assert(buf - orig >= 4);
    00243   ReplaceEnglishWords(orig, true);
    00244
    00245   return buf;
    00246 }
    00247
    00248
    00255 static char *MakeEnglishAdditionalTownName(char *buf, const char *last, uint32 seed)
    00256 {
    00257   char *orig = buf;
    00258
    00259   /* optional first segment */
    00260   int i = SeedChanceBias(0, lengthof(_name_additional_english_prefix), seed, 50);
    00261   if (i >= 0) buf = strecpy(buf, _name_additional_english_prefix[i], last);
    00262
    00263   if (SeedChance(3, 20, seed) >= 14) {
    00264     buf = strecpy(buf, _name_additional_english_1a[SeedChance(6, lengthof(_name_additional_english_1a), seed)], last);
    00265   } else {
    00266     buf = strecpy(buf, _name_additional_english_1b1[SeedChance(6, lengthof(_name_additional_english_1b1), seed)], last);
    00267     buf = strecpy(buf, _name_additional_english_1b2[SeedChance(9, lengthof(_name_additional_english_1b2), seed)], last);
    00268     if (SeedChance(11, 20, seed) >= 4) {
    00269       buf = strecpy(buf, _name_additional_english_1b3a[SeedChance(12, lengthof(_name_additional_english_1b3a), seed)], last);
    00270     } else {
    00271       buf = strecpy(buf, _name_additional_english_1b3b[SeedChance(12, lengthof(_name_additional_english_1b3b), seed)], last);
    00272     }
    00273   }
    00274
    00275   buf = strecpy(buf, _name_additional_english_2[SeedChance(14, lengthof(_name_additional_english_2), seed)], last);
    00276
    00277   /* optional last segment */
    00278   i = SeedChanceBias(15, lengthof(_name_additional_english_3), seed, 60);
    00279   if (i >= 0) buf = strecpy(buf, _name_additional_english_3[i], last);
    00280
    00281   assert(buf - orig >= 4);
    00282   ReplaceEnglishWords(orig, false);
    00283
    00284   return buf;
    00285 }
    00286
    00287
    00294 static char *MakeAustrianTownName(char *buf, const char *last, uint32 seed)
    00295 {
    00296   /* Bad, Maria, Gross, ... */
    00297   int i = SeedChanceBias(0, lengthof(_name_austrian_a1), seed, 15);
    00298   if (i >= 0) buf = strecpy(buf, _name_austrian_a1[i], last);
    00299
    00300   int j = 0;
    00301
    00302   i = SeedChance(4, 6, seed);
    00303   if (i >= 4) {
    00304     /* Kaisers-kirchen */
    00305     buf = strecpy(buf, _name_austrian_a2[SeedChance( 7, lengthof(_name_austrian_a2), seed)], last);
    00306     buf = strecpy(buf, _name_austrian_a3[SeedChance(13, lengthof(_name_austrian_a3), seed)], last);
    00307   } else if (i >= 2) {
    00308     /* St. Johann */
    00309     buf = strecpy(buf, _name_austrian_a5[SeedChance( 7, lengthof(_name_austrian_a5), seed)], last);
    00310     buf = strecpy(buf, _name_austrian_a6[SeedChance( 9, lengthof(_name_austrian_a6), seed)], last);
    00311     j = 1; // More likely to have a " an der " or " am "
    00312   } else {
    00313     /* Zell */
    00314     buf = strecpy(buf, _name_austrian_a4[SeedChance( 7, lengthof(_name_austrian_a4), seed)], last);
    00315   }
    00316
    00317   i = SeedChance(1, 6, seed);
    00318   if (i >= 4 - j) {
    00319     /* an der Donau (rivers) */
    00320     buf = strecpy(buf, _name_austrian_f1[SeedChance(4, lengthof(_name_austrian_f1), seed)], last);
    00321     buf = strecpy(buf, _name_austrian_f2[SeedChance(5, lengthof(_name_austrian_f2), seed)], last);
    00322   } else if (i >= 2 - j) {
    00323     /* am Dachstein (mountains) */
    00324     buf = strecpy(buf, _name_austrian_b1[SeedChance(4, lengthof(_name_austrian_b1), seed)], last);
    00325     buf = strecpy(buf, _name_austrian_b2[SeedChance(5, lengthof(_name_austrian_b2), seed)], last);
    00326   }
    00327
    00328   return buf;
    00329 }
    00330
    00331
    00338 static char *MakeGermanTownName(char *buf, const char *last, uint32 seed)
    00339 {
    00340   uint seed_derivative = SeedChance(7, 28, seed);
    00341
    00342   /* optional prefix */
    00343   if (seed_derivative == 12 || seed_derivative == 19) {
    00344     uint i = SeedChance(2, lengthof(_name_german_pre), seed);
    00345     buf = strecpy(buf, _name_german_pre[i], last);
    00346   }
    00347
    00348   /* mandatory middle segments including option of hardcoded name */
    00349   uint i = SeedChance(3, lengthof(_name_german_real) + lengthof(_name_german_1), seed);
    00350   if (i < lengthof(_name_german_real)) {
    00351     buf = strecpy(buf, _name_german_real[i], last);
    00352   } else {
    00353     buf = strecpy(buf, _name_german_1[i - lengthof(_name_german_real)], last);
    00354
    00355     i = SeedChance(5, lengthof(_name_german_2), seed);
    00356     buf = strecpy(buf, _name_german_2[i], last);
    00357   }
    00358
    00359   /* optional suffix */
    00360   if (seed_derivative == 24) {
    00361     i = SeedChance(9, lengthof(_name_german_4_an_der) + lengthof(_name_german_4_am), seed);
    00362     if (i < lengthof(_name_german_4_an_der)) {
    00363       buf = strecpy(buf, _name_german_3_an_der[0], last);
    00364       buf = strecpy(buf, _name_german_4_an_der[i], last);
    00365     } else {
    00366       buf = strecpy(buf, _name_german_3_am[0], last);
    00367       buf = strecpy(buf, _name_german_4_am[i - lengthof(_name_german_4_an_der)], last);
    00368     }
    00369   }
    00370
    00371   return buf;
    00372 }
    00373
    00374
    00381 static char *MakeSpanishTownName(char *buf, const char *last, uint32 seed)
    00382 {
    00383   return strecpy(buf, _name_spanish_real[SeedChance(0, lengthof(_name_spanish_real), seed)], last);
    00384 }
    00385
    00386
    00393 static char *MakeFrenchTownName(char *buf, const char *last, uint32 seed)
    00394 {
    00395   return strecpy(buf, _name_french_real[SeedChance(0, lengthof(_name_french_real), seed)], last);
    00396 }
    00397
    00398
    00405 static char *MakeSillyTownName(char *buf, const char *last, uint32 seed)
    00406 {
    00407   buf = strecpy(buf, _name_silly_1[SeedChance( 0, lengthof(_name_silly_1), seed)], last);
    00408   buf = strecpy(buf, _name_silly_2[SeedChance(16, lengthof(_name_silly_2), seed)], last);
    00409
    00410   return buf;
    00411 }
    00412
    00413
    00420 static char *MakeSwedishTownName(char *buf, const char *last, uint32 seed)
    00421 {
    00422   /* optional first segment */
    00423   int i = SeedChanceBias(0, lengthof(_name_swedish_1), seed, 50);
    00424   if (i >= 0) buf = strecpy(buf, _name_swedish_1[i], last);
    00425
    00426   /* mandatory middle segments including option of hardcoded name */
    00427   if (SeedChance(4, 5, seed) >= 3) {
    00428     buf = strecpy(buf, _name_swedish_2[SeedChance( 7, lengthof(_name_swedish_2), seed)], last);
    00429   } else {
    00430     buf = strecpy(buf, _name_swedish_2a[SeedChance( 7, lengthof(_name_swedish_2a), seed)], last);
    00431     buf = strecpy(buf, _name_swedish_2b[SeedChance(10, lengthof(_name_swedish_2b), seed)], last);
    00432     buf = strecpy(buf, _name_swedish_2c[SeedChance(13, lengthof(_name_swedish_2c), seed)], last);
    00433   }
    00434
    00435   buf = strecpy(buf, _name_swedish_3[SeedChance(16, lengthof(_name_swedish_3), seed)], last);
    00436
    00437   return buf;
    00438 }
    00439
    00440
    00447 static char *MakeDutchTownName(char *buf, const char *last, uint32 seed)
    00448 {
    00449   /* optional first segment */
    00450   int i = SeedChanceBias(0, lengthof(_name_dutch_1), seed, 50);
    00451   if (i >= 0) buf = strecpy(buf, _name_dutch_1[i], last);
    00452
    00453   /* mandatory middle segments including option of hardcoded name */
    00454   if (SeedChance(6, 9, seed) > 4) {
    00455     buf = strecpy(buf, _name_dutch_2[SeedChance( 9, lengthof(_name_dutch_2), seed)], last);
    00456   } else {
    00457     buf = strecpy(buf, _name_dutch_3[SeedChance( 9, lengthof(_name_dutch_3), seed)], last);
    00458     buf = strecpy(buf, _name_dutch_4[SeedChance(12, lengthof(_name_dutch_4), seed)], last);
    00459   }
    00460
    00461   buf = strecpy(buf, _name_dutch_5[SeedChance(15, lengthof(_name_dutch_5), seed)], last);
    00462
    00463   return buf;
    00464 }
    00465
    00466
    00473 static char *MakeFinnishTownName(char *buf, const char *last, uint32 seed)
    00474 {
    00475   char *orig = buf;
    00476
    00477   /* Select randomly if town name should consists of one or two parts. */
    00478   if (SeedChance(0, 15, seed) >= 10) {
    00479     return strecpy(buf, _name_finnish_real[SeedChance(2, lengthof(_name_finnish_real), seed)], last);
    00480   }
    00481
    00482   if (SeedChance(0, 15, seed) >= 5) {
    00483     /* A two-part name by combining one of _name_finnish_1 + "la"/"lä"
    00484      * The reason for not having the contents of _name_finnish_{1,2} in the same table is
    00485      * that the ones in _name_finnish_2 are not good for this purpose. */
    00486     uint sel = SeedChance( 0, lengthof(_name_finnish_1), seed);
    00487     buf = strecpy(buf, _name_finnish_1[sel], last);
    00488     char *end = buf - 1;
    00489     assert(end >= orig);
    00490     if (*end == 'i') *end = 'e';
    00491     if (strstr(orig, "a") != NULL || strstr(orig, "o") != NULL || strstr(orig, "u") != NULL ||
    00492         strstr(orig, "A") != NULL || strstr(orig, "O") != NULL || strstr(orig, "U")  != NULL) {
    00493       buf = strecpy(buf, "la", last);
    00494     } else {
    00495       buf = strecpy(buf, "l\xC3\xA4", last);
    00496     }
    00497     return buf;
    00498   }
    00499
    00500   /* A two-part name by combining one of _name_finnish_{1,2} + _name_finnish_3.
    00501    * Why aren't _name_finnish_{1,2} just one table? See above. */
    00502   uint sel = SeedChance(2, lengthof(_name_finnish_1) + lengthof(_name_finnish_2), seed);
    00503   if (sel >= lengthof(_name_finnish_1)) {
    00504     buf = strecpy(buf, _name_finnish_2[sel - lengthof(_name_finnish_1)], last);
    00505   } else {
    00506     buf = strecpy(buf, _name_finnish_1[sel], last);
    00507   }
    00508
    00509   buf = strecpy(buf, _name_finnish_3[SeedChance(10, lengthof(_name_finnish_3), seed)], last);
    00510
    00511   return buf;
    00512 }
    00513
    00514
    00521 static char *MakePolishTownName(char *buf, const char *last, uint32 seed)
    00522 {
    00523   /* optional first segment */
    00524   uint i = SeedChance(0,
    00525       lengthof(_name_polish_2_o) + lengthof(_name_polish_2_m) +
    00526       lengthof(_name_polish_2_f) + lengthof(_name_polish_2_n),
    00527       seed);
    00528   uint j = SeedChance(2, 20, seed);
    00529
    00530
    00531   if (i < lengthof(_name_polish_2_o)) {
    00532     return strecpy(buf, _name_polish_2_o[SeedChance(3, lengthof(_name_polish_2_o), seed)], last);
    00533   }
    00534
    00535   if (i < lengthof(_name_polish_2_m) + lengthof(_name_polish_2_o)) {
    00536     if (j < 4) {
    00537       buf = strecpy(buf, _name_polish_1_m[SeedChance(5, lengthof(_name_polish_1_m), seed)], last);
    00538     }
    00539
    00540     buf = strecpy(buf, _name_polish_2_m[SeedChance(7, lengthof(_name_polish_2_m), seed)], last);
    00541
    00542     if (j >= 4 && j < 16) {
    00543       buf = strecpy(buf, _name_polish_3_m[SeedChance(10, lengthof(_name_polish_3_m), seed)], last);
    00544     }
    00545
    00546     return buf;
    00547   }
    00548
    00549   if (i < lengthof(_name_polish_2_f) + lengthof(_name_polish_2_m) + lengthof(_name_polish_2_o)) {
    00550     if (j < 4) {
    00551       buf = strecpy(buf, _name_polish_1_f[SeedChance(5, lengthof(_name_polish_1_f), seed)], last);
    00552     }
    00553
    00554     buf = strecpy(buf, _name_polish_2_f[SeedChance(7, lengthof(_name_polish_2_f), seed)], last);
    00555
    00556     if (j >= 4 && j < 16) {
    00557       buf = strecpy(buf, _name_polish_3_f[SeedChance(10, lengthof(_name_polish_3_f), seed)], last);
    00558     }
    00559
    00560     return buf;
    00561   }
    00562
    00563   if (j < 4) {
    00564     buf = strecpy(buf, _name_polish_1_n[SeedChance(5, lengthof(_name_polish_1_n), seed)], last);
    00565   }
    00566
    00567   buf = strecpy(buf, _name_polish_2_n[SeedChance(7, lengthof(_name_polish_2_n), seed)], last);
    00568
    00569   if (j >= 4 && j < 16) {
    00570     buf = strecpy(buf, _name_polish_3_n[SeedChance(10, lengthof(_name_polish_3_n), seed)], last);
    00571   }
    00572
    00573   return buf;
    00574 }
    00575
    00576
    00583 static char *MakeCzechTownName(char *buf, const char *last, uint32 seed)
    00584 {
    00585   /* 1:3 chance to use a real name. */
    00586   if (SeedModChance(0, 4, seed) == 0) {
    00587     return strecpy(buf, _name_czech_real[SeedModChance(4, lengthof(_name_czech_real), seed)], last);
    00588   }
    00589
    00590   const char *orig = buf;
    00591
    00592   /* Probability of prefixes/suffixes
    00593    * 0..11 prefix, 12..13 prefix+suffix, 14..17 suffix, 18..31 nothing */
    00594   int prob_tails = SeedModChance(2, 32, seed);
    00595   bool do_prefix = prob_tails < 12;
    00596   bool do_suffix = prob_tails > 11 && prob_tails < 17;
    00597   bool dynamic_subst;
    00598
    00599   /* IDs of the respective parts */
    00600   int prefix = 0, ending = 0, suffix = 0;
    00601   uint postfix = 0;
    00602   uint stem;
    00603
    00604   /* The select criteria. */
    00605   CzechGender gender;
    00606   CzechChoose choose;
    00607   CzechAllow allow;
    00608
    00609   if (do_prefix) prefix = SeedModChance(5, lengthof(_name_czech_adj) * 12, seed) / 12;
    00610   if (do_suffix) suffix = SeedModChance(7, lengthof(_name_czech_suffix), seed);
    00611   /* 3:1 chance 3:1 to use dynamic substantive */
    00612   stem = SeedModChance(9,
    00613       lengthof(_name_czech_subst_full) + 3 * lengthof(_name_czech_subst_stem),
    00614       seed);
    00615   if (stem < lengthof(_name_czech_subst_full)) {
    00616     /* That was easy! */
    00617     dynamic_subst = false;
    00618     gender = _name_czech_subst_full[stem].gender;
    00619     choose = _name_czech_subst_full[stem].choose;
    00620     allow = _name_czech_subst_full[stem].allow;
    00621   } else {
    00622     unsigned int map[lengthof(_name_czech_subst_ending)];
    00623     int ending_start = -1, ending_stop = -1;
    00624
    00625     /* Load the substantive */
    00626     dynamic_subst = true;
    00627     stem -= lengthof(_name_czech_subst_full);
    00628     stem %= lengthof(_name_czech_subst_stem);
    00629     gender = _name_czech_subst_stem[stem].gender;
    00630     choose = _name_czech_subst_stem[stem].choose;
    00631     allow = _name_czech_subst_stem[stem].allow;
    00632
    00633     /* Load the postfix (1:1 chance that a postfix will be inserted) */
    00634     postfix = SeedModChance(14, lengthof(_name_czech_subst_postfix) * 2, seed);
    00635
    00636     if (choose & CZC_POSTFIX) {
    00637       /* Always get a real postfix. */
    00638       postfix %= lengthof(_name_czech_subst_postfix);
    00639     }
    00640     if (choose & CZC_NOPOSTFIX) {
    00641       /* Always drop a postfix. */
    00642       postfix += lengthof(_name_czech_subst_postfix);
    00643     }
    00644     if (postfix < lengthof(_name_czech_subst_postfix)) {
    00645       choose |= CZC_POSTFIX;
    00646     } else {
    00647       choose |= CZC_NOPOSTFIX;
    00648     }
    00649
    00650     /* Localize the array segment containing a good gender */
    00651     for (ending = 0; ending < (int)lengthof(_name_czech_subst_ending); ending++) {
    00652       const CzechNameSubst *e = &_name_czech_subst_ending[ending];
    00653
    00654       if (gender == CZG_FREE ||
    00655           (gender == CZG_NFREE && e->gender != CZG_SNEUT && e->gender != CZG_PNEUT) ||
    00656            gender == e->gender) {
    00657         if (ending_start < 0) {
    00658           ending_start = ending;
    00659         }
    00660       } else if (ending_start >= 0) {
    00661         ending_stop = ending - 1;
    00662         break;
    00663       }
    00664     }
    00665     if (ending_stop < 0) {
    00666       /* Whoa. All the endings matched. */
    00667       ending_stop = ending - 1;
    00668     }
    00669
    00670     /* Make a sequential map of the items with good mask */
    00671     size_t i = 0;
    00672     for (ending = ending_start; ending <= ending_stop; ending++) {
    00673       const CzechNameSubst *e = &_name_czech_subst_ending[ending];
    00674
    00675       if ((e->choose & choose) == choose && (e->allow & allow) != 0) {
    00676         map[i++] = ending;
    00677       }
    00678     }
    00679     assert(i > 0);
    00680
    00681     /* Load the ending */
    00682     ending = map[SeedModChance(16, (int)i, seed)];
    00683     /* Override possible CZG_*FREE; this must be a real gender,
    00684      * otherwise we get overflow when modifying the adjectivum. */
    00685     gender = _name_czech_subst_ending[ending].gender;
    00686     assert(gender != CZG_FREE && gender != CZG_NFREE);
    00687   }
    00688
    00689   if (do_prefix && (_name_czech_adj[prefix].choose & choose) != choose) {
    00690     /* Throw away non-matching prefix. */
    00691     do_prefix = false;
    00692   }
    00693
    00694   /* Now finally construct the name */
    00695   if (do_prefix) {
    00696     CzechPattern pattern = _name_czech_adj[prefix].pattern;
    00697
    00698     buf = strecpy(buf, _name_czech_adj[prefix].name, last);
    00699
    00700     char *endpos = buf - 1;
    00701     /* Find the first character in a UTF-8 sequence */
    00702     while (GB(*endpos, 6, 2) == 2) endpos--;
    00703
    00704     if (gender == CZG_SMASC && pattern == CZP_PRIVL) {
    00705       assert(endpos >= orig + 2);
    00706       /* -ovX -> -uv */
    00707       *(endpos - 2) = 'u';
    00708       assert(*(endpos - 1) == 'v');
    00709       *endpos = '\0';
    00710     } else {
    00711       assert(endpos >= orig);
    00712       endpos = strecpy(endpos, _name_czech_patmod[gender][pattern], last);
    00713     }
    00714
    00715     buf = strecpy(endpos, " ", last);
    00716   }
    00717
    00718   if (dynamic_subst) {
    00719     buf = strecpy(buf, _name_czech_subst_stem[stem].name, last);
    00720     if (postfix < lengthof(_name_czech_subst_postfix)) {
    00721       const char *poststr = _name_czech_subst_postfix[postfix];
    00722       const char *endstr = _name_czech_subst_ending[ending].name;
    00723
    00724       size_t postlen = strlen(poststr);
    00725       size_t endlen = strlen(endstr);
    00726       assert(postlen > 0 && endlen > 0);
    00727
    00728       /* Kill the "avava" and "Jananna"-like cases */
    00729       if (postlen < 2 || postlen > endlen ||
    00730           ((poststr[1] != 'v' || poststr[1] != endstr[1]) &&
    00731           poststr[2] != endstr[1])) {
    00732         buf = strecpy(buf, poststr, last);
    00733
    00734         /* k-i -> c-i, h-i -> z-i */
    00735         if (endstr[0] == 'i') {
    00736           switch (*(buf - 1)) {
    00737             case 'k': *(buf - 1) = 'c'; break;
    00738             case 'h': *(buf - 1) = 'z'; break;
    00739             default: break;
    00740           }
    00741         }
    00742       }
    00743     }
    00744     buf = strecpy(buf, _name_czech_subst_ending[ending].name, last);
    00745   } else {
    00746     buf = strecpy(buf, _name_czech_subst_full[stem].name, last);
    00747   }
    00748
    00749   if (do_suffix) {
    00750     buf = strecpy(buf, " ", last);
    00751     buf = strecpy(buf, _name_czech_suffix[suffix], last);
    00752   }
    00753
    00754   return buf;
    00755 }
    00756
    00757
    00764 static char *MakeRomanianTownName(char *buf, const char *last, uint32 seed)
    00765 {
    00766   return strecpy(buf, _name_romanian_real[SeedChance(0, lengthof(_name_romanian_real), seed)], last);
    00767 }
    00768
    00769
    00776 static char *MakeSlovakTownName(char *buf, const char *last, uint32 seed)
    00777 {
    00778   return strecpy(buf, _name_slovak_real[SeedChance(0, lengthof(_name_slovak_real), seed)], last);
    00779 }
    00780
    00781
    00788 static char *MakeNorwegianTownName(char *buf, const char *last, uint32 seed)
    00789 {
    00790   /* Use first 4 bit from seed to decide whether or not this town should
    00791    * have a real name 3/16 chance.  Bit 0-3 */
    00792   if (SeedChance(0, 15, seed) < 3) {
    00793     /* Use 7bit for the realname table index.  Bit 4-10 */
    00794     return strecpy(buf, _name_norwegian_real[SeedChance(4, lengthof(_name_norwegian_real), seed)], last);
    00795   }
    00796
    00797   /* Use 7bit for the first fake part.  Bit 4-10 */
    00798   buf = strecpy(buf, _name_norwegian_1[SeedChance(4, lengthof(_name_norwegian_1), seed)], last);
    00799   /* Use 7bit for the last fake part.  Bit 11-17 */
    00800   buf = strecpy(buf, _name_norwegian_2[SeedChance(11, lengthof(_name_norwegian_2), seed)], last);
    00801
    00802   return buf;
    00803 }
    00804
    00805
    00812 static char *MakeHungarianTownName(char *buf, const char *last, uint32 seed)
    00813 {
    00814   if (SeedChance(12, 15, seed) < 3) {
    00815     return strecpy(buf, _name_hungarian_real[SeedChance(0, lengthof(_name_hungarian_real), seed)], last);
    00816   }
    00817
    00818   /* optional first segment */
    00819   uint i = SeedChance(3, lengthof(_name_hungarian_1) * 3, seed);
    00820   if (i < lengthof(_name_hungarian_1)) buf = strecpy(buf, _name_hungarian_1[i], last);
    00821
    00822   /* mandatory middle segments */
    00823   buf = strecpy(buf, _name_hungarian_2[SeedChance(3, lengthof(_name_hungarian_2), seed)], last);
    00824   buf = strecpy(buf, _name_hungarian_3[SeedChance(6, lengthof(_name_hungarian_3), seed)], last);
    00825
    00826   /* optional last segment */
    00827   i = SeedChance(10, lengthof(_name_hungarian_4) * 3, seed);
    00828   if (i < lengthof(_name_hungarian_4)) {
    00829     buf = strecpy(buf, _name_hungarian_4[i], last);
    00830   }
    00831
    00832   return buf;
    00833 }
    00834
    00835
    00842 static char *MakeSwissTownName(char *buf, const char *last, uint32 seed)
    00843 {
    00844   return strecpy(buf, _name_swiss_real[SeedChance(0, lengthof(_name_swiss_real), seed)], last);
    00845 }
    00846
    00847
    00854 static char *MakeDanishTownName(char *buf, const char *last, uint32 seed)
    00855 {
    00856   /* optional first segment */
    00857   int i = SeedChanceBias(0, lengthof(_name_danish_1), seed, 50);
    00858   if (i >= 0) buf = strecpy(buf, _name_danish_1[i], last);
    00859
    00860   /* middle segments removed as this algorithm seems to create much more realistic names */
    00861   buf = strecpy(buf, _name_danish_2[SeedChance( 7, lengthof(_name_danish_2), seed)], last);
    00862   buf = strecpy(buf, _name_danish_3[SeedChance(16, lengthof(_name_danish_3), seed)], last);
    00863
    00864   return buf;
    00865 }
    00866
    00867
    00874 static char *MakeTurkishTownName(char *buf, const char *last, uint32 seed)
    00875 {
    00876   uint i = SeedModChance(0, 5, seed);
    00877
    00878   switch (i) {
    00879     case 0:
    00880       buf = strecpy(buf, _name_turkish_prefix[SeedModChance( 2, lengthof(_name_turkish_prefix), seed)], last);
    00881
    00882       /* middle segment */
    00883       buf = strecpy(buf, _name_turkish_middle[SeedModChance( 4, lengthof(_name_turkish_middle), seed)], last);
    00884
    00885       /* optional suffix */
    00886       if (SeedModChance(0, 7, seed) == 0) {
    00887         buf = strecpy(buf, _name_turkish_suffix[SeedModChance( 10, lengthof(_name_turkish_suffix), seed)], last);
    00888       }
    00889       break;
    00890
    00891     case 1: case 2:
    00892       buf = strecpy(buf, _name_turkish_prefix[SeedModChance( 2, lengthof(_name_turkish_prefix), seed)], last);
    00893       buf = strecpy(buf, _name_turkish_suffix[SeedModChance( 4, lengthof(_name_turkish_suffix), seed)], last);
    00894       break;
    00895
    00896     default:
    00897       buf = strecpy(buf, _name_turkish_real[SeedModChance( 4, lengthof(_name_turkish_real), seed)], last);
    00898       break;
    00899   }
    00900
    00901   return buf;
    00902 }
    00903
    00904
    00911 static char *MakeItalianTownName(char *buf, const char *last, uint32 seed)
    00912 {
    00913   if (SeedModChance(0, 6, seed) == 0) { // real city names
    00914     return strecpy(buf, _name_italian_real[SeedModChance(4, lengthof(_name_italian_real), seed)], last);
    00915   }
    00916
    00917   static const char * const mascul_femin_italian[] = {
    00918     "o",
    00919     "a",
    00920   };
    00921
    00922   if (SeedModChance(0, 8, seed) == 0) { // prefix
    00923     buf = strecpy(buf, _name_italian_pref[SeedModChance(11, lengthof(_name_italian_pref), seed)], last);
    00924   }
    00925
    00926   uint i = SeedChance(0, 2, seed);
    00927   if (i == 0) { // masculine form
    00928     buf = strecpy(buf, _name_italian_1m[SeedModChance(4, lengthof(_name_italian_1m), seed)], last);
    00929   } else { // feminine form
    00930     buf = strecpy(buf, _name_italian_1f[SeedModChance(4, lengthof(_name_italian_1f), seed)], last);
    00931   }
    00932
    00933   if (SeedModChance(3, 3, seed) == 0) {
    00934     buf = strecpy(buf, _name_italian_2[SeedModChance(11, lengthof(_name_italian_2), seed)], last);
    00935     buf = strecpy(buf, mascul_femin_italian[i], last);
    00936   } else {
    00937     buf = strecpy(buf, _name_italian_2i[SeedModChance(16, lengthof(_name_italian_2i), seed)], last);
    00938   }
    00939
    00940   if (SeedModChance(15, 4, seed) == 0) {
    00941     if (SeedModChance(5, 2, seed) == 0) { // generic suffix
    00942       buf = strecpy(buf, _name_italian_3[SeedModChance(4, lengthof(_name_italian_3), seed)], last);
    00943     } else { // river name suffix
    00944       buf = strecpy(buf, _name_italian_river1[SeedModChance(4, lengthof(_name_italian_river1), seed)], last);
    00945       buf = strecpy(buf, _name_italian_river2[SeedModChance(16, lengthof(_name_italian_river2), seed)], last);
    00946     }
    00947   }
    00948
    00949   return buf;
    00950 }
    00951
    00952
    00959 static char *MakeCatalanTownName(char *buf, const char *last, uint32 seed)
    00960 {
    00961   if (SeedModChance(0, 3, seed) == 0) { // real city names
    00962     return strecpy(buf, _name_catalan_real[SeedModChance(4, lengthof(_name_catalan_real), seed)], last);
    00963   }
    00964
    00965   if (SeedModChance(0, 2, seed) == 0) { // prefix
    00966     buf = strecpy(buf, _name_catalan_pref[SeedModChance(11, lengthof(_name_catalan_pref), seed)], last);
    00967   }
    00968
    00969   uint i = SeedChance(0, 2, seed);
    00970   if (i == 0) { // masculine form
    00971     buf = strecpy(buf, _name_catalan_1m[SeedModChance(4, lengthof(_name_catalan_1m), seed)], last);
    00972     buf = strecpy(buf, _name_catalan_2m[SeedModChance(11, lengthof(_name_catalan_2m), seed)], last);
    00973   } else { // feminine form
    00974     buf = strecpy(buf, _name_catalan_1f[SeedModChance(4, lengthof(_name_catalan_1f), seed)], last);
    00975     buf = strecpy(buf, _name_catalan_2f[SeedModChance(11, lengthof(_name_catalan_2f), seed)], last);
    00976   }
    00977
    00978   if (SeedModChance(15, 5, seed) == 0) {
    00979     if (SeedModChance(5, 2, seed) == 0) { // generic suffix
    00980       buf = strecpy(buf, _name_catalan_3[SeedModChance(4, lengthof(_name_catalan_3), seed)], last);
    00981     } else { // river name suffix
    00982       buf = strecpy(buf, _name_catalan_river1[SeedModChance(4, lengthof(_name_catalan_river1), seed)], last);
    00983     }
    00984   }
    00985
    00986   return buf;
    00987 }
    00988
    00989
    00990 typedef char *TownNameGenerator(char *buf, const char *last, uint32 seed);
    00991
    00993 struct TownNameGeneratorParams {
    00994   byte min;
    00995   TownNameGenerator *proc;
    00996 };
    00997
    00999 static const TownNameGeneratorParams _town_name_generators[] = {
    01000   {  4, MakeEnglishOriginalTownName},  // replaces first 4 characters of name
    01001   {  0, MakeFrenchTownName},
    01002   {  0, MakeGermanTownName},
    01003   {  4, MakeEnglishAdditionalTownName}, // replaces first 4 characters of name
    01004   {  0, MakeSpanishTownName},
    01005   {  0, MakeSillyTownName},
    01006   {  0, MakeSwedishTownName},
    01007   {  0, MakeDutchTownName},
    01008   {  8, MakeFinnishTownName}, // _name_finnish_1
    01009   {  0, MakePolishTownName},
    01010   {  0, MakeSlovakTownName},
    01011   {  0, MakeNorwegianTownName},
    01012   {  0, MakeHungarianTownName},
    01013   {  0, MakeAustrianTownName},
    01014   {  0, MakeRomanianTownName},
    01015   { 28, MakeCzechTownName}, // _name_czech_adj + _name_czech_patmod + 1 + _name_czech_subst_stem + _name_czech_subst_postfix
    01016   {  0, MakeSwissTownName},
    01017   {  0, MakeDanishTownName},
    01018   {  0, MakeTurkishTownName},
    01019   {  0, MakeItalianTownName},
    01020   {  0, MakeCatalanTownName},
    01021 };
    01022
    01023
    01032 char *GenerateTownNameString(char *buf, const char *last, size_t lang, uint32 seed)
    01033 {
    01034   assert(lang < lengthof(_town_name_generators));
    01035
    01036   /* Some generators need at least 9 bytes in buffer.  English generators need 5 for
    01037    * string replacing, others use constructions like strlen(buf)-3 and so on.
    01038    * Finnish generator needs to fit all strings from _name_finnish_1.
    01039    * Czech generator needs to fit almost whole town name...
    01040    * These would break. Using another temporary buffer results in ~40% slower code,
    01041    * so use it only when really needed. */
    01042   const TownNameGeneratorParams *par = &_town_name_generators[lang];
    01043   if (last >= buf + par->min) return par->proc(buf, last, seed);
    01044
    01045   char *buffer = AllocaM(char, par->min + 1);
    01046   par->proc(buffer, buffer + par->min, seed);
    01047
    01048   return strecpy(buf, buffer, last);
    01049 }