# townname.cpp

Go to the documentation of this file.

    00001 /* $Id: townname.cpp 26346 2014-02-16 17:45:24Z frosch $ */
    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 "strings_func.h"
    00017 #include "core/random_func.hpp"
    00018 #include "genworld.h"
    00019 #include "gfx_layout.h"
    00020
    00021 #include "table/townname.h"
    00022
    00023
    00028 TownNameParams::TownNameParams(const Town *t) :
    00029     grfid(t->townnamegrfid), // by default, use supplied data
    00030     type(t->townnametype)
    00031 {
    00032   if (t->townnamegrfid != 0 && GetGRFTownName(t->townnamegrfid) == NULL) {
    00033     /* Fallback to english original */
    00034     this->grfid = 0;
    00035     this->type = SPECSTR_TOWNNAME_ENGLISH;
    00036     return;
    00037   }
    00038 }
    00039
    00040
    00049 char *GetTownName(char *buff, const TownNameParams *par, uint32 townnameparts, const char *last)
    00050 {
    00051   if (par->grfid == 0) {
    00052     int64 args_array[1] = { townnameparts };
    00053     StringParameters tmp_params(args_array);
    00054     return GetStringWithArgs(buff, par->type, &tmp_params, last);
    00055   }
    00056
    00057   return GRFTownNameGenerate(buff, par->grfid, par->type, townnameparts, last);
    00058 }
    00059
    00060
    00068 char *GetTownName(char *buff, const Town *t, const char *last)
    00069 {
    00070   TownNameParams par(t);
    00071   return GetTownName(buff, &par, t->townnameparts, last);
    00072 }
    00073
    00074
    00082 bool VerifyTownName(uint32 r, const TownNameParams *par, TownNames *town_names)
    00083 {
    00084   /* reserve space for extra unicode character and terminating '\0' */
    00085   char buf1[(MAX_LENGTH_TOWN_NAME_CHARS + 1) * MAX_CHAR_LENGTH];
    00086   char buf2[(MAX_LENGTH_TOWN_NAME_CHARS + 1) * MAX_CHAR_LENGTH];
    00087
    00088   GetTownName(buf1, par, r, lastof(buf1));
    00089
    00090   /* Check size and width */
    00091   if (Utf8StringLength(buf1) >= MAX_LENGTH_TOWN_NAME_CHARS) return false;
    00092
    00093   if (town_names != NULL) {
    00094     if (town_names->find(buf1) != town_names->end()) return false;
    00095     town_names->insert(buf1);
    00096   } else {
    00097     const Town *t;
    00098     FOR_ALL_TOWNS(t) {
    00099       /* We can't just compare the numbers since
    00100        * several numbers may map to a single name. */
    00101       const char *buf = t->name;
    00102       if (buf == NULL) {
    00103         GetTownName(buf2, t, lastof(buf2));
    00104         buf = buf2;
    00105       }
    00106       if (strcmp(buf1, buf) == 0) return false;
    00107     }
    00108   }
    00109
    00110   return true;
    00111 }
    00112
    00113
    00120 bool GenerateTownName(uint32 *townnameparts, TownNames *town_names)
    00121 {
    00122   /* Do not set too low tries, since when we run out of names, we loop
    00123    * for #tries only one time anyway - then we stop generating more
    00124    * towns. Do not show it too high neither, since looping through all
    00125    * the other towns may take considerable amount of time (10000 is
    00126    * too much). */
    00127   TownNameParams par(_settings_game.game_creation.town_name);
    00128
    00129   /* This function is called very often without entering the gameloop
    00130    * inbetween. So reset layout cache to prevent it from growing too big. */
    00131   Layouter::ReduceLineCache();
    00132
    00133   for (int i = 1000; i != 0; i--) {
    00134     uint32 r = _generating_world ? Random() : InteractiveRandom();
    00135     if (!VerifyTownName(r, &par, town_names)) continue;
    00136
    00137     *townnameparts = r;
    00138     return true;
    00139   }
    00140
    00141   return false;
    00142 }
    00143
    00144
    00145
    00153 static inline uint32 SeedChance(byte shift_by, int max, uint32 seed)
    00154 {
    00155   return (GB(seed, shift_by, 16) * max) >> 16;
    00156 }
    00157
    00158
    00166 static inline uint32 SeedModChance(byte shift_by, int max, uint32 seed)
    00167 {
    00168   /* This actually gives *MUCH* more even distribution of the values
    00169    * than SeedChance(), which is absolutely horrible in that. If
    00170    * you do not believe me, try with i.e. the Czech town names,
    00171    * compare the words (nicely visible on prefixes) generated by
    00172    * SeedChance() and SeedModChance(). Do not get discouraged by the
    00173    * never-use-modulo myths, which hold true only for the linear
    00174    * congruential generators (and Random() isn't such a generator).
    00175    * --pasky
    00176    * TODO: Perhaps we should use it for all the name generators? --pasky */
    00177   return (seed >> shift_by) % max;
    00178 }
    00179
    00180
    00189 static inline int32 SeedChanceBias(byte shift_by, int max, uint32 seed, int bias)
    00190 {
    00191   return SeedChance(shift_by, max + bias, seed) - bias;
    00192 }
    00193
    00194
    00201 static void ReplaceWords(const char *org, const char *rep, char *buf)
    00202 {
    00203   if (strncmp(buf, org, 4) == 0) strncpy(buf, rep, 4); // Safe as the string in buf is always more than 4 characters long.
    00204 }
    00205
    00206
    00212 static void ReplaceEnglishWords(char *buf, bool original)
    00213 {
    00214   ReplaceWords("Cunt", "East", buf);
    00215   ReplaceWords("Slag", "Pits", buf);
    00216   ReplaceWords("Slut", "Edin", buf);
    00217   if (!original) ReplaceWords("Fart", "Boot", buf); // never happens with 'English (Original)'
    00218   ReplaceWords("Drar", "Quar", buf);
    00219   ReplaceWords("Dreh", "Bash", buf);
    00220   ReplaceWords("Frar", "Shor", buf);
    00221   ReplaceWords("Grar", "Aber", buf);
    00222   ReplaceWords("Brar", "Over", buf);
    00223   ReplaceWords("Wrar", original ? "Inve" : "Stan", buf);
    00224 }
    00225
    00232 static char *MakeEnglishOriginalTownName(char *buf, const char *last, uint32 seed)
    00233 {
    00234   char *orig = buf;
    00235
    00236   /* optional first segment */
    00237   int i = SeedChanceBias(0, lengthof(_name_original_english_1), seed, 50);
    00238   if (i >= 0) buf = strecpy(buf, _name_original_english_1[i], last);
    00239
    00240   /* mandatory middle segments */
    00241   buf = strecpy(buf, _name_original_english_2[SeedChance(4,  lengthof(_name_original_english_2), seed)], last);
    00242   buf = strecpy(buf, _name_original_english_3[SeedChance(7,  lengthof(_name_original_english_3), seed)], last);
    00243   buf = strecpy(buf, _name_original_english_4[SeedChance(10, lengthof(_name_original_english_4), seed)], last);
    00244   buf = strecpy(buf, _name_original_english_5[SeedChance(13, lengthof(_name_original_english_5), seed)], last);
    00245
    00246   /* optional last segment */
    00247   i = SeedChanceBias(15, lengthof(_name_original_english_6), seed, 60);
    00248   if (i >= 0) buf = strecpy(buf, _name_original_english_6[i], last);
    00249
    00250   /* Ce, Ci => Ke, Ki */
    00251   if (orig[0] == 'C' && (orig[1] == 'e' || orig[1] == 'i')) {
    00252     orig[0] = 'K';
    00253   }
    00254
    00255   assert(buf - orig >= 4);
    00256   ReplaceEnglishWords(orig, true);
    00257
    00258   return buf;
    00259 }
    00260
    00261
    00268 static char *MakeEnglishAdditionalTownName(char *buf, const char *last, uint32 seed)
    00269 {
    00270   char *orig = buf;
    00271
    00272   /* optional first segment */
    00273   int i = SeedChanceBias(0, lengthof(_name_additional_english_prefix), seed, 50);
    00274   if (i >= 0) buf = strecpy(buf, _name_additional_english_prefix[i], last);
    00275
    00276   if (SeedChance(3, 20, seed) >= 14) {
    00277     buf = strecpy(buf, _name_additional_english_1a[SeedChance(6, lengthof(_name_additional_english_1a), seed)], last);
    00278   } else {
    00279     buf = strecpy(buf, _name_additional_english_1b1[SeedChance(6, lengthof(_name_additional_english_1b1), seed)], last);
    00280     buf = strecpy(buf, _name_additional_english_1b2[SeedChance(9, lengthof(_name_additional_english_1b2), seed)], last);
    00281     if (SeedChance(11, 20, seed) >= 4) {
    00282       buf = strecpy(buf, _name_additional_english_1b3a[SeedChance(12, lengthof(_name_additional_english_1b3a), seed)], last);
    00283     } else {
    00284       buf = strecpy(buf, _name_additional_english_1b3b[SeedChance(12, lengthof(_name_additional_english_1b3b), seed)], last);
    00285     }
    00286   }
    00287
    00288   buf = strecpy(buf, _name_additional_english_2[SeedChance(14, lengthof(_name_additional_english_2), seed)], last);
    00289
    00290   /* optional last segment */
    00291   i = SeedChanceBias(15, lengthof(_name_additional_english_3), seed, 60);
    00292   if (i >= 0) buf = strecpy(buf, _name_additional_english_3[i], last);
    00293
    00294   assert(buf - orig >= 4);
    00295   ReplaceEnglishWords(orig, false);
    00296
    00297   return buf;
    00298 }
    00299
    00300
    00307 static char *MakeAustrianTownName(char *buf, const char *last, uint32 seed)
    00308 {
    00309   /* Bad, Maria, Gross, ... */
    00310   int i = SeedChanceBias(0, lengthof(_name_austrian_a1), seed, 15);
    00311   if (i >= 0) buf = strecpy(buf, _name_austrian_a1[i], last);
    00312
    00313   int j = 0;
    00314
    00315   i = SeedChance(4, 6, seed);
    00316   if (i >= 4) {
    00317     /* Kaisers-kirchen */
    00318     buf = strecpy(buf, _name_austrian_a2[SeedChance( 7, lengthof(_name_austrian_a2), seed)], last);
    00319     buf = strecpy(buf, _name_austrian_a3[SeedChance(13, lengthof(_name_austrian_a3), seed)], last);
    00320   } else if (i >= 2) {
    00321     /* St. Johann */
    00322     buf = strecpy(buf, _name_austrian_a5[SeedChance( 7, lengthof(_name_austrian_a5), seed)], last);
    00323     buf = strecpy(buf, _name_austrian_a6[SeedChance( 9, lengthof(_name_austrian_a6), seed)], last);
    00324     j = 1; // More likely to have a " an der " or " am "
    00325   } else {
    00326     /* Zell */
    00327     buf = strecpy(buf, _name_austrian_a4[SeedChance( 7, lengthof(_name_austrian_a4), seed)], last);
    00328   }
    00329
    00330   i = SeedChance(1, 6, seed);
    00331   if (i >= 4 - j) {
    00332     /* an der Donau (rivers) */
    00333     buf = strecpy(buf, _name_austrian_f1[SeedChance(4, lengthof(_name_austrian_f1), seed)], last);
    00334     buf = strecpy(buf, _name_austrian_f2[SeedChance(5, lengthof(_name_austrian_f2), seed)], last);
    00335   } else if (i >= 2 - j) {
    00336     /* am Dachstein (mountains) */
    00337     buf = strecpy(buf, _name_austrian_b1[SeedChance(4, lengthof(_name_austrian_b1), seed)], last);
    00338     buf = strecpy(buf, _name_austrian_b2[SeedChance(5, lengthof(_name_austrian_b2), seed)], last);
    00339   }
    00340
    00341   return buf;
    00342 }
    00343
    00344
    00351 static char *MakeGermanTownName(char *buf, const char *last, uint32 seed)
    00352 {
    00353   uint seed_derivative = SeedChance(7, 28, seed);
    00354
    00355   /* optional prefix */
    00356   if (seed_derivative == 12 || seed_derivative == 19) {
    00357     uint i = SeedChance(2, lengthof(_name_german_pre), seed);
    00358     buf = strecpy(buf, _name_german_pre[i], last);
    00359   }
    00360
    00361   /* mandatory middle segments including option of hardcoded name */
    00362   uint i = SeedChance(3, lengthof(_name_german_real) + lengthof(_name_german_1), seed);
    00363   if (i < lengthof(_name_german_real)) {
    00364     buf = strecpy(buf, _name_german_real[i], last);
    00365   } else {
    00366     buf = strecpy(buf, _name_german_1[i - lengthof(_name_german_real)], last);
    00367
    00368     i = SeedChance(5, lengthof(_name_german_2), seed);
    00369     buf = strecpy(buf, _name_german_2[i], last);
    00370   }
    00371
    00372   /* optional suffix */
    00373   if (seed_derivative == 24) {
    00374     i = SeedChance(9, lengthof(_name_german_4_an_der) + lengthof(_name_german_4_am), seed);
    00375     if (i < lengthof(_name_german_4_an_der)) {
    00376       buf = strecpy(buf, _name_german_3_an_der[0], last);
    00377       buf = strecpy(buf, _name_german_4_an_der[i], last);
    00378     } else {
    00379       buf = strecpy(buf, _name_german_3_am[0], last);
    00380       buf = strecpy(buf, _name_german_4_am[i - lengthof(_name_german_4_an_der)], last);
    00381     }
    00382   }
    00383
    00384   return buf;
    00385 }
    00386
    00387
    00394 static char *MakeSpanishTownName(char *buf, const char *last, uint32 seed)
    00395 {
    00396   return strecpy(buf, _name_spanish_real[SeedChance(0, lengthof(_name_spanish_real), seed)], last);
    00397 }
    00398
    00399
    00406 static char *MakeFrenchTownName(char *buf, const char *last, uint32 seed)
    00407 {
    00408   return strecpy(buf, _name_french_real[SeedChance(0, lengthof(_name_french_real), seed)], last);
    00409 }
    00410
    00411
    00418 static char *MakeSillyTownName(char *buf, const char *last, uint32 seed)
    00419 {
    00420   buf = strecpy(buf, _name_silly_1[SeedChance( 0, lengthof(_name_silly_1), seed)], last);
    00421   buf = strecpy(buf, _name_silly_2[SeedChance(16, lengthof(_name_silly_2), seed)], last);
    00422
    00423   return buf;
    00424 }
    00425
    00426
    00433 static char *MakeSwedishTownName(char *buf, const char *last, uint32 seed)
    00434 {
    00435   /* optional first segment */
    00436   int i = SeedChanceBias(0, lengthof(_name_swedish_1), seed, 50);
    00437   if (i >= 0) buf = strecpy(buf, _name_swedish_1[i], last);
    00438
    00439   /* mandatory middle segments including option of hardcoded name */
    00440   if (SeedChance(4, 5, seed) >= 3) {
    00441     buf = strecpy(buf, _name_swedish_2[SeedChance( 7, lengthof(_name_swedish_2), seed)], last);
    00442   } else {
    00443     buf = strecpy(buf, _name_swedish_2a[SeedChance( 7, lengthof(_name_swedish_2a), seed)], last);
    00444     buf = strecpy(buf, _name_swedish_2b[SeedChance(10, lengthof(_name_swedish_2b), seed)], last);
    00445     buf = strecpy(buf, _name_swedish_2c[SeedChance(13, lengthof(_name_swedish_2c), seed)], last);
    00446   }
    00447
    00448   buf = strecpy(buf, _name_swedish_3[SeedChance(16, lengthof(_name_swedish_3), seed)], last);
    00449
    00450   return buf;
    00451 }
    00452
    00453
    00460 static char *MakeDutchTownName(char *buf, const char *last, uint32 seed)
    00461 {
    00462   /* optional first segment */
    00463   int i = SeedChanceBias(0, lengthof(_name_dutch_1), seed, 50);
    00464   if (i >= 0) buf = strecpy(buf, _name_dutch_1[i], last);
    00465
    00466   /* mandatory middle segments including option of hardcoded name */
    00467   if (SeedChance(6, 9, seed) > 4) {
    00468     buf = strecpy(buf, _name_dutch_2[SeedChance( 9, lengthof(_name_dutch_2), seed)], last);
    00469   } else {
    00470     buf = strecpy(buf, _name_dutch_3[SeedChance( 9, lengthof(_name_dutch_3), seed)], last);
    00471     buf = strecpy(buf, _name_dutch_4[SeedChance(12, lengthof(_name_dutch_4), seed)], last);
    00472   }
    00473
    00474   buf = strecpy(buf, _name_dutch_5[SeedChance(15, lengthof(_name_dutch_5), seed)], last);
    00475
    00476   return buf;
    00477 }
    00478
    00479
    00486 static char *MakeFinnishTownName(char *buf, const char *last, uint32 seed)
    00487 {
    00488   char *orig = buf;
    00489
    00490   /* Select randomly if town name should consists of one or two parts. */
    00491   if (SeedChance(0, 15, seed) >= 10) {
    00492     return strecpy(buf, _name_finnish_real[SeedChance(2, lengthof(_name_finnish_real), seed)], last);
    00493   }
    00494
    00495   if (SeedChance(0, 15, seed) >= 5) {
    00496     /* A two-part name by combining one of _name_finnish_1 + "la"/"lä"
    00497      * The reason for not having the contents of _name_finnish_{1,2} in the same table is
    00498      * that the ones in _name_finnish_2 are not good for this purpose. */
    00499     uint sel = SeedChance( 0, lengthof(_name_finnish_1), seed);
    00500     buf = strecpy(buf, _name_finnish_1[sel], last);
    00501     char *end = buf - 1;
    00502     assert(end >= orig);
    00503     if (*end == 'i') *end = 'e';
    00504     if (strstr(orig, "a") != NULL || strstr(orig, "o") != NULL || strstr(orig, "u") != NULL ||
    00505         strstr(orig, "A") != NULL || strstr(orig, "O") != NULL || strstr(orig, "U")  != NULL) {
    00506       buf = strecpy(buf, "la", last);
    00507     } else {
    00508       buf = strecpy(buf, "l\xC3\xA4", last);
    00509     }
    00510     return buf;
    00511   }
    00512
    00513   /* A two-part name by combining one of _name_finnish_{1,2} + _name_finnish_3.
    00514    * Why aren't _name_finnish_{1,2} just one table? See above. */
    00515   uint sel = SeedChance(2, lengthof(_name_finnish_1) + lengthof(_name_finnish_2), seed);
    00516   if (sel >= lengthof(_name_finnish_1)) {
    00517     buf = strecpy(buf, _name_finnish_2[sel - lengthof(_name_finnish_1)], last);
    00518   } else {
    00519     buf = strecpy(buf, _name_finnish_1[sel], last);
    00520   }
    00521
    00522   buf = strecpy(buf, _name_finnish_3[SeedChance(10, lengthof(_name_finnish_3), seed)], last);
    00523
    00524   return buf;
    00525 }
    00526
    00527
    00534 static char *MakePolishTownName(char *buf, const char *last, uint32 seed)
    00535 {
    00536   /* optional first segment */
    00537   uint i = SeedChance(0,
    00538       lengthof(_name_polish_2_o) + lengthof(_name_polish_2_m) +
    00539       lengthof(_name_polish_2_f) + lengthof(_name_polish_2_n),
    00540       seed);
    00541   uint j = SeedChance(2, 20, seed);
    00542
    00543
    00544   if (i < lengthof(_name_polish_2_o)) {
    00545     return strecpy(buf, _name_polish_2_o[SeedChance(3, lengthof(_name_polish_2_o), seed)], last);
    00546   }
    00547
    00548   if (i < lengthof(_name_polish_2_m) + lengthof(_name_polish_2_o)) {
    00549     if (j < 4) {
    00550       buf = strecpy(buf, _name_polish_1_m[SeedChance(5, lengthof(_name_polish_1_m), seed)], last);
    00551     }
    00552
    00553     buf = strecpy(buf, _name_polish_2_m[SeedChance(7, lengthof(_name_polish_2_m), seed)], last);
    00554
    00555     if (j >= 4 && j < 16) {
    00556       buf = strecpy(buf, _name_polish_3_m[SeedChance(10, lengthof(_name_polish_3_m), seed)], last);
    00557     }
    00558
    00559     return buf;
    00560   }
    00561
    00562   if (i < lengthof(_name_polish_2_f) + lengthof(_name_polish_2_m) + lengthof(_name_polish_2_o)) {
    00563     if (j < 4) {
    00564       buf = strecpy(buf, _name_polish_1_f[SeedChance(5, lengthof(_name_polish_1_f), seed)], last);
    00565     }
    00566
    00567     buf = strecpy(buf, _name_polish_2_f[SeedChance(7, lengthof(_name_polish_2_f), seed)], last);
    00568
    00569     if (j >= 4 && j < 16) {
    00570       buf = strecpy(buf, _name_polish_3_f[SeedChance(10, lengthof(_name_polish_3_f), seed)], last);
    00571     }
    00572
    00573     return buf;
    00574   }
    00575
    00576   if (j < 4) {
    00577     buf = strecpy(buf, _name_polish_1_n[SeedChance(5, lengthof(_name_polish_1_n), seed)], last);
    00578   }
    00579
    00580   buf = strecpy(buf, _name_polish_2_n[SeedChance(7, lengthof(_name_polish_2_n), seed)], last);
    00581
    00582   if (j >= 4 && j < 16) {
    00583     buf = strecpy(buf, _name_polish_3_n[SeedChance(10, lengthof(_name_polish_3_n), seed)], last);
    00584   }
    00585
    00586   return buf;
    00587 }
    00588
    00589
    00596 static char *MakeCzechTownName(char *buf, const char *last, uint32 seed)
    00597 {
    00598   /* 1:3 chance to use a real name. */
    00599   if (SeedModChance(0, 4, seed) == 0) {
    00600     return strecpy(buf, _name_czech_real[SeedModChance(4, lengthof(_name_czech_real), seed)], last);
    00601   }
    00602
    00603   const char *orig = buf;
    00604
    00605   /* Probability of prefixes/suffixes
    00606    * 0..11 prefix, 12..13 prefix+suffix, 14..17 suffix, 18..31 nothing */
    00607   int prob_tails = SeedModChance(2, 32, seed);
    00608   bool do_prefix = prob_tails < 12;
    00609   bool do_suffix = prob_tails > 11 && prob_tails < 17;
    00610   bool dynamic_subst;
    00611
    00612   /* IDs of the respective parts */
    00613   int prefix = 0, ending = 0, suffix = 0;
    00614   uint postfix = 0;
    00615   uint stem;
    00616
    00617   /* The select criteria. */
    00618   CzechGender gender;
    00619   CzechChoose choose;
    00620   CzechAllow allow;
    00621
    00622   if (do_prefix) prefix = SeedModChance(5, lengthof(_name_czech_adj) * 12, seed) / 12;
    00623   if (do_suffix) suffix = SeedModChance(7, lengthof(_name_czech_suffix), seed);
    00624   /* 3:1 chance 3:1 to use dynamic substantive */
    00625   stem = SeedModChance(9,
    00626       lengthof(_name_czech_subst_full) + 3 * lengthof(_name_czech_subst_stem),
    00627       seed);
    00628   if (stem < lengthof(_name_czech_subst_full)) {
    00629     /* That was easy! */
    00630     dynamic_subst = false;
    00631     gender = _name_czech_subst_full[stem].gender;
    00632     choose = _name_czech_subst_full[stem].choose;
    00633     allow = _name_czech_subst_full[stem].allow;
    00634   } else {
    00635     unsigned int map[lengthof(_name_czech_subst_ending)];
    00636     int ending_start = -1, ending_stop = -1;
    00637
    00638     /* Load the substantive */
    00639     dynamic_subst = true;
    00640     stem -= lengthof(_name_czech_subst_full);
    00641     stem %= lengthof(_name_czech_subst_stem);
    00642     gender = _name_czech_subst_stem[stem].gender;
    00643     choose = _name_czech_subst_stem[stem].choose;
    00644     allow = _name_czech_subst_stem[stem].allow;
    00645
    00646     /* Load the postfix (1:1 chance that a postfix will be inserted) */
    00647     postfix = SeedModChance(14, lengthof(_name_czech_subst_postfix) * 2, seed);
    00648
    00649     if (choose & CZC_POSTFIX) {
    00650       /* Always get a real postfix. */
    00651       postfix %= lengthof(_name_czech_subst_postfix);
    00652     }
    00653     if (choose & CZC_NOPOSTFIX) {
    00654       /* Always drop a postfix. */
    00655       postfix += lengthof(_name_czech_subst_postfix);
    00656     }
    00657     if (postfix < lengthof(_name_czech_subst_postfix)) {
    00658       choose |= CZC_POSTFIX;
    00659     } else {
    00660       choose |= CZC_NOPOSTFIX;
    00661     }
    00662
    00663     /* Localize the array segment containing a good gender */
    00664     for (ending = 0; ending < (int)lengthof(_name_czech_subst_ending); ending++) {
    00665       const CzechNameSubst *e = &_name_czech_subst_ending[ending];
    00666
    00667       if (gender == CZG_FREE ||
    00668           (gender == CZG_NFREE && e->gender != CZG_SNEUT && e->gender != CZG_PNEUT) ||
    00669            gender == e->gender) {
    00670         if (ending_start < 0) {
    00671           ending_start = ending;
    00672         }
    00673       } else if (ending_start >= 0) {
    00674         ending_stop = ending - 1;
    00675         break;
    00676       }
    00677     }
    00678     if (ending_stop < 0) {
    00679       /* Whoa. All the endings matched. */
    00680       ending_stop = ending - 1;
    00681     }
    00682
    00683     /* Make a sequential map of the items with good mask */
    00684     size_t i = 0;
    00685     for (ending = ending_start; ending <= ending_stop; ending++) {
    00686       const CzechNameSubst *e = &_name_czech_subst_ending[ending];
    00687
    00688       if ((e->choose & choose) == choose && (e->allow & allow) != 0) {
    00689         map[i++] = ending;
    00690       }
    00691     }
    00692     assert(i > 0);
    00693
    00694     /* Load the ending */
    00695     ending = map[SeedModChance(16, (int)i, seed)];
    00696     /* Override possible CZG_*FREE; this must be a real gender,
    00697      * otherwise we get overflow when modifying the adjectivum. */
    00698     gender = _name_czech_subst_ending[ending].gender;
    00699     assert(gender != CZG_FREE && gender != CZG_NFREE);
    00700   }
    00701
    00702   if (do_prefix && (_name_czech_adj[prefix].choose & choose) != choose) {
    00703     /* Throw away non-matching prefix. */
    00704     do_prefix = false;
    00705   }
    00706
    00707   /* Now finally construct the name */
    00708   if (do_prefix) {
    00709     CzechPattern pattern = _name_czech_adj[prefix].pattern;
    00710
    00711     buf = strecpy(buf, _name_czech_adj[prefix].name, last);
    00712
    00713     char *endpos = buf - 1;
    00714     /* Find the first character in a UTF-8 sequence */
    00715     while (GB(*endpos, 6, 2) == 2) endpos--;
    00716
    00717     if (gender == CZG_SMASC && pattern == CZP_PRIVL) {
    00718       assert(endpos >= orig + 2);
    00719       /* -ovX -> -uv */
    00720       *(endpos - 2) = 'u';
    00721       assert(*(endpos - 1) == 'v');
    00722       *endpos = '\0';
    00723     } else {
    00724       assert(endpos >= orig);
    00725       endpos = strecpy(endpos, _name_czech_patmod[gender][pattern], last);
    00726     }
    00727
    00728     buf = strecpy(endpos, " ", last);
    00729   }
    00730
    00731   if (dynamic_subst) {
    00732     buf = strecpy(buf, _name_czech_subst_stem[stem].name, last);
    00733     if (postfix < lengthof(_name_czech_subst_postfix)) {
    00734       const char *poststr = _name_czech_subst_postfix[postfix];
    00735       const char *endstr = _name_czech_subst_ending[ending].name;
    00736
    00737       size_t postlen = strlen(poststr);
    00738       size_t endlen = strlen(endstr);
    00739       assert(postlen > 0 && endlen > 0);
    00740
    00741       /* Kill the "avava" and "Jananna"-like cases */
    00742       if (postlen < 2 || postlen > endlen ||
    00743           ((poststr[1] != 'v' || poststr[1] != endstr[1]) &&
    00744           poststr[2] != endstr[1])) {
    00745         buf = strecpy(buf, poststr, last);
    00746
    00747         /* k-i -> c-i, h-i -> z-i */
    00748         if (endstr[0] == 'i') {
    00749           switch (*(buf - 1)) {
    00750             case 'k': *(buf - 1) = 'c'; break;
    00751             case 'h': *(buf - 1) = 'z'; break;
    00752             default: break;
    00753           }
    00754         }
    00755       }
    00756     }
    00757     buf = strecpy(buf, _name_czech_subst_ending[ending].name, last);
    00758   } else {
    00759     buf = strecpy(buf, _name_czech_subst_full[stem].name, last);
    00760   }
    00761
    00762   if (do_suffix) {
    00763     buf = strecpy(buf, " ", last);
    00764     buf = strecpy(buf, _name_czech_suffix[suffix], last);
    00765   }
    00766
    00767   return buf;
    00768 }
    00769
    00770
    00777 static char *MakeRomanianTownName(char *buf, const char *last, uint32 seed)
    00778 {
    00779   return strecpy(buf, _name_romanian_real[SeedChance(0, lengthof(_name_romanian_real), seed)], last);
    00780 }
    00781
    00782
    00789 static char *MakeSlovakTownName(char *buf, const char *last, uint32 seed)
    00790 {
    00791   return strecpy(buf, _name_slovak_real[SeedChance(0, lengthof(_name_slovak_real), seed)], last);
    00792 }
    00793
    00794
    00801 static char *MakeNorwegianTownName(char *buf, const char *last, uint32 seed)
    00802 {
    00803   /* Use first 4 bit from seed to decide whether or not this town should
    00804    * have a real name 3/16 chance.  Bit 0-3 */
    00805   if (SeedChance(0, 15, seed) < 3) {
    00806     /* Use 7bit for the realname table index.  Bit 4-10 */
    00807     return strecpy(buf, _name_norwegian_real[SeedChance(4, lengthof(_name_norwegian_real), seed)], last);
    00808   }
    00809
    00810   /* Use 7bit for the first fake part.  Bit 4-10 */
    00811   buf = strecpy(buf, _name_norwegian_1[SeedChance(4, lengthof(_name_norwegian_1), seed)], last);
    00812   /* Use 7bit for the last fake part.  Bit 11-17 */
    00813   buf = strecpy(buf, _name_norwegian_2[SeedChance(11, lengthof(_name_norwegian_2), seed)], last);
    00814
    00815   return buf;
    00816 }
    00817
    00818
    00825 static char *MakeHungarianTownName(char *buf, const char *last, uint32 seed)
    00826 {
    00827   if (SeedChance(12, 15, seed) < 3) {
    00828     return strecpy(buf, _name_hungarian_real[SeedChance(0, lengthof(_name_hungarian_real), seed)], last);
    00829   }
    00830
    00831   /* optional first segment */
    00832   uint i = SeedChance(3, lengthof(_name_hungarian_1) * 3, seed);
    00833   if (i < lengthof(_name_hungarian_1)) buf = strecpy(buf, _name_hungarian_1[i], last);
    00834
    00835   /* mandatory middle segments */
    00836   buf = strecpy(buf, _name_hungarian_2[SeedChance(3, lengthof(_name_hungarian_2), seed)], last);
    00837   buf = strecpy(buf, _name_hungarian_3[SeedChance(6, lengthof(_name_hungarian_3), seed)], last);
    00838
    00839   /* optional last segment */
    00840   i = SeedChance(10, lengthof(_name_hungarian_4) * 3, seed);
    00841   if (i < lengthof(_name_hungarian_4)) {
    00842     buf = strecpy(buf, _name_hungarian_4[i], last);
    00843   }
    00844
    00845   return buf;
    00846 }
    00847
    00848
    00855 static char *MakeSwissTownName(char *buf, const char *last, uint32 seed)
    00856 {
    00857   return strecpy(buf, _name_swiss_real[SeedChance(0, lengthof(_name_swiss_real), seed)], last);
    00858 }
    00859
    00860
    00867 static char *MakeDanishTownName(char *buf, const char *last, uint32 seed)
    00868 {
    00869   /* optional first segment */
    00870   int i = SeedChanceBias(0, lengthof(_name_danish_1), seed, 50);
    00871   if (i >= 0) buf = strecpy(buf, _name_danish_1[i], last);
    00872
    00873   /* middle segments removed as this algorithm seems to create much more realistic names */
    00874   buf = strecpy(buf, _name_danish_2[SeedChance( 7, lengthof(_name_danish_2), seed)], last);
    00875   buf = strecpy(buf, _name_danish_3[SeedChance(16, lengthof(_name_danish_3), seed)], last);
    00876
    00877   return buf;
    00878 }
    00879
    00880
    00887 static char *MakeTurkishTownName(char *buf, const char *last, uint32 seed)
    00888 {
    00889   uint i = SeedModChance(0, 5, seed);
    00890
    00891   switch (i) {
    00892     case 0:
    00893       buf = strecpy(buf, _name_turkish_prefix[SeedModChance( 2, lengthof(_name_turkish_prefix), seed)], last);
    00894
    00895       /* middle segment */
    00896       buf = strecpy(buf, _name_turkish_middle[SeedModChance( 4, lengthof(_name_turkish_middle), seed)], last);
    00897
    00898       /* optional suffix */
    00899       if (SeedModChance(0, 7, seed) == 0) {
    00900         buf = strecpy(buf, _name_turkish_suffix[SeedModChance( 10, lengthof(_name_turkish_suffix), seed)], last);
    00901       }
    00902       break;
    00903
    00904     case 1: case 2:
    00905       buf = strecpy(buf, _name_turkish_prefix[SeedModChance( 2, lengthof(_name_turkish_prefix), seed)], last);
    00906       buf = strecpy(buf, _name_turkish_suffix[SeedModChance( 4, lengthof(_name_turkish_suffix), seed)], last);
    00907       break;
    00908
    00909     default:
    00910       buf = strecpy(buf, _name_turkish_real[SeedModChance( 4, lengthof(_name_turkish_real), seed)], last);
    00911       break;
    00912   }
    00913
    00914   return buf;
    00915 }
    00916
    00917
    00924 static char *MakeItalianTownName(char *buf, const char *last, uint32 seed)
    00925 {
    00926   if (SeedModChance(0, 6, seed) == 0) { // real city names
    00927     return strecpy(buf, _name_italian_real[SeedModChance(4, lengthof(_name_italian_real), seed)], last);
    00928   }
    00929
    00930   static const char * const mascul_femin_italian[] = {
    00931     "o",
    00932     "a",
    00933   };
    00934
    00935   if (SeedModChance(0, 8, seed) == 0) { // prefix
    00936     buf = strecpy(buf, _name_italian_pref[SeedModChance(11, lengthof(_name_italian_pref), seed)], last);
    00937   }
    00938
    00939   uint i = SeedChance(0, 2, seed);
    00940   if (i == 0) { // masculine form
    00941     buf = strecpy(buf, _name_italian_1m[SeedModChance(4, lengthof(_name_italian_1m), seed)], last);
    00942   } else { // feminine form
    00943     buf = strecpy(buf, _name_italian_1f[SeedModChance(4, lengthof(_name_italian_1f), seed)], last);
    00944   }
    00945
    00946   if (SeedModChance(3, 3, seed) == 0) {
    00947     buf = strecpy(buf, _name_italian_2[SeedModChance(11, lengthof(_name_italian_2), seed)], last);
    00948     buf = strecpy(buf, mascul_femin_italian[i], last);
    00949   } else {
    00950     buf = strecpy(buf, _name_italian_2i[SeedModChance(16, lengthof(_name_italian_2i), seed)], last);
    00951   }
    00952
    00953   if (SeedModChance(15, 4, seed) == 0) {
    00954     if (SeedModChance(5, 2, seed) == 0) { // generic suffix
    00955       buf = strecpy(buf, _name_italian_3[SeedModChance(4, lengthof(_name_italian_3), seed)], last);
    00956     } else { // river name suffix
    00957       buf = strecpy(buf, _name_italian_river1[SeedModChance(4, lengthof(_name_italian_river1), seed)], last);
    00958       buf = strecpy(buf, _name_italian_river2[SeedModChance(16, lengthof(_name_italian_river2), seed)], last);
    00959     }
    00960   }
    00961
    00962   return buf;
    00963 }
    00964
    00965
    00972 static char *MakeCatalanTownName(char *buf, const char *last, uint32 seed)
    00973 {
    00974   if (SeedModChance(0, 3, seed) == 0) { // real city names
    00975     return strecpy(buf, _name_catalan_real[SeedModChance(4, lengthof(_name_catalan_real), seed)], last);
    00976   }
    00977
    00978   if (SeedModChance(0, 2, seed) == 0) { // prefix
    00979     buf = strecpy(buf, _name_catalan_pref[SeedModChance(11, lengthof(_name_catalan_pref), seed)], last);
    00980   }
    00981
    00982   uint i = SeedChance(0, 2, seed);
    00983   if (i == 0) { // masculine form
    00984     buf = strecpy(buf, _name_catalan_1m[SeedModChance(4, lengthof(_name_catalan_1m), seed)], last);
    00985     buf = strecpy(buf, _name_catalan_2m[SeedModChance(11, lengthof(_name_catalan_2m), seed)], last);
    00986   } else { // feminine form
    00987     buf = strecpy(buf, _name_catalan_1f[SeedModChance(4, lengthof(_name_catalan_1f), seed)], last);
    00988     buf = strecpy(buf, _name_catalan_2f[SeedModChance(11, lengthof(_name_catalan_2f), seed)], last);
    00989   }
    00990
    00991   if (SeedModChance(15, 5, seed) == 0) {
    00992     if (SeedModChance(5, 2, seed) == 0) { // generic suffix
    00993       buf = strecpy(buf, _name_catalan_3[SeedModChance(4, lengthof(_name_catalan_3), seed)], last);
    00994     } else { // river name suffix
    00995       buf = strecpy(buf, _name_catalan_river1[SeedModChance(4, lengthof(_name_catalan_river1), seed)], last);
    00996     }
    00997   }
    00998
    00999   return buf;
    01000 }
    01001
    01002
    01010 typedef char *TownNameGenerator(char *buf, const char *last, uint32 seed);
    01011
    01013 struct TownNameGeneratorParams {
    01014   byte min;
    01015   TownNameGenerator *proc;
    01016 };
    01017
    01019 static const TownNameGeneratorParams _town_name_generators[] = {
    01020   {  4, MakeEnglishOriginalTownName},  // replaces first 4 characters of name
    01021   {  0, MakeFrenchTownName},
    01022   {  0, MakeGermanTownName},
    01023   {  4, MakeEnglishAdditionalTownName}, // replaces first 4 characters of name
    01024   {  0, MakeSpanishTownName},
    01025   {  0, MakeSillyTownName},
    01026   {  0, MakeSwedishTownName},
    01027   {  0, MakeDutchTownName},
    01028   {  8, MakeFinnishTownName}, // _name_finnish_1
    01029   {  0, MakePolishTownName},
    01030   {  0, MakeSlovakTownName},
    01031   {  0, MakeNorwegianTownName},
    01032   {  0, MakeHungarianTownName},
    01033   {  0, MakeAustrianTownName},
    01034   {  0, MakeRomanianTownName},
    01035   { 28, MakeCzechTownName}, // _name_czech_adj + _name_czech_patmod + 1 + _name_czech_subst_stem + _name_czech_subst_postfix
    01036   {  0, MakeSwissTownName},
    01037   {  0, MakeDanishTownName},
    01038   {  0, MakeTurkishTownName},
    01039   {  0, MakeItalianTownName},
    01040   {  0, MakeCatalanTownName},
    01041 };
    01042
    01043
    01052 char *GenerateTownNameString(char *buf, const char *last, size_t lang, uint32 seed)
    01053 {
    01054   assert(lang < lengthof(_town_name_generators));
    01055
    01056   /* Some generators need at least 9 bytes in buffer.  English generators need 5 for
    01057    * string replacing, others use constructions like strlen(buf)-3 and so on.
    01058    * Finnish generator needs to fit all strings from _name_finnish_1.
    01059    * Czech generator needs to fit almost whole town name...
    01060    * These would break. Using another temporary buffer results in ~40% slower code,
    01061    * so use it only when really needed. */
    01062   const TownNameGeneratorParams *par = &_town_name_generators[lang];
    01063   if (last >= buf + par->min) return par->proc(buf, last, seed);
    01064
    01065   char *buffer = AllocaM(char, par->min + 1);
    01066   par->proc(buffer, buffer + par->min, seed);
    01067
    01068   return strecpy(buf, buffer, last);
    01069 }