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 }

Generated on Wed Jan 20 23:38:41 2010 for OpenTTD by  doxygen 1.5.6