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 }