townname.cpp

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

Generated on Wed Dec 23 23:27:56 2009 for OpenTTD by  doxygen 1.5.6