namegen.cpp

Go to the documentation of this file.
00001 /* $Id: namegen.cpp 11828 2008-01-13 01:21:35Z rubidium $ */
00002 
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "debug.h"
00008 #include "namegen.h"
00009 #include "string_func.h"
00010 
00011 #include "table/namegen.h"
00012 
00013 static inline uint32 SeedChance(int shift_by, int max, uint32 seed)
00014 {
00015   return (GB(seed, shift_by, 16) * max) >> 16;
00016 }
00017 
00018 static inline uint32 SeedModChance(int shift_by, int max, uint32 seed)
00019 {
00020   /* This actually gives *MUCH* more even distribution of the values
00021    * than SeedChance(), which is absolutely horrible in that. If
00022    * you do not believe me, try with i.e. the Czech town names,
00023    * compare the words (nicely visible on prefixes) generated by
00024    * SeedChance() and SeedModChance(). Do not get dicouraged by the
00025    * never-use-modulo myths, which hold true only for the linear
00026    * congruential generators (and Random() isn't such a generator).
00027    * --pasky */
00028   // TODO: Perhaps we should use it for all the name generators? --pasky
00029   return (seed >> shift_by) % max;
00030 }
00031 
00032 static inline int32 SeedChanceBias(int shift_by, int max, uint32 seed, int bias)
00033 {
00034   return SeedChance(shift_by, max + bias, seed) - bias;
00035 }
00036 
00037 static void ReplaceWords(const char *org, const char *rep, char *buf)
00038 {
00039   if (strncmp(buf, org, 4) == 0) strncpy(buf, rep, 4);
00040 }
00041 
00042 static byte MakeEnglishOriginalTownName(char *buf, uint32 seed, const char *last)
00043 {
00044   int i;
00045 
00046   /* null terminates the string for strcat */
00047   strecpy(buf, "", last);
00048 
00049   /* optional first segment */
00050   i = SeedChanceBias(0, lengthof(name_original_english_1), seed, 50);
00051   if (i >= 0)
00052     strecat(buf, name_original_english_1[i], last);
00053 
00054   /* mandatory middle segments */
00055   strecat(buf, name_original_english_2[SeedChance(4,  lengthof(name_original_english_2), seed)], last);
00056   strecat(buf, name_original_english_3[SeedChance(7,  lengthof(name_original_english_3), seed)], last);
00057   strecat(buf, name_original_english_4[SeedChance(10, lengthof(name_original_english_4), seed)], last);
00058   strecat(buf, name_original_english_5[SeedChance(13, lengthof(name_original_english_5), seed)], last);
00059 
00060   /* optional last segment */
00061   i = SeedChanceBias(15, lengthof(name_original_english_6), seed, 60);
00062   if (i >= 0)
00063     strecat(buf, name_original_english_6[i], last);
00064 
00065   if (buf[0] == 'C' && (buf[1] == 'e' || buf[1] == 'i'))
00066     buf[0] = 'K';
00067 
00068   ReplaceWords("Cunt", "East", buf);
00069   ReplaceWords("Slag", "Pits", buf);
00070   ReplaceWords("Slut", "Edin", buf);
00071   //ReplaceWords("Fart", "Boot", buf);
00072   ReplaceWords("Drar", "Quar", buf);
00073   ReplaceWords("Dreh", "Bash", buf);
00074   ReplaceWords("Frar", "Shor", buf);
00075   ReplaceWords("Grar", "Aber", buf);
00076   ReplaceWords("Brar", "Over", buf);
00077   ReplaceWords("Wrar", "Inve", buf);
00078 
00079   return 0;
00080 }
00081 
00082 
00083 static byte MakeEnglishAdditionalTownName(char *buf, uint32 seed, const char *last)
00084 {
00085   int i;
00086 
00087   /* null terminates the string for strcat */
00088   strecpy(buf, "", last);
00089 
00090   /* optional first segment */
00091   i = SeedChanceBias(0, lengthof(name_additional_english_prefix), seed, 50);
00092   if (i >= 0)
00093     strecat(buf, name_additional_english_prefix[i], last);
00094 
00095   if (SeedChance(3, 20, seed) >= 14) {
00096     strecat(buf, name_additional_english_1a[SeedChance(6, lengthof(name_additional_english_1a), seed)], last);
00097   } else {
00098     strecat(buf, name_additional_english_1b1[SeedChance(6, lengthof(name_additional_english_1b1), seed)], last);
00099     strecat(buf, name_additional_english_1b2[SeedChance(9, lengthof(name_additional_english_1b2), seed)], last);
00100     if (SeedChance(11, 20, seed) >= 4) {
00101       strecat(buf, name_additional_english_1b3a[SeedChance(12, lengthof(name_additional_english_1b3a), seed)], last);
00102     } else {
00103       strecat(buf, name_additional_english_1b3b[SeedChance(12, lengthof(name_additional_english_1b3b), seed)], last);
00104     }
00105   }
00106 
00107   strecat(buf, name_additional_english_2[SeedChance(14, lengthof(name_additional_english_2), seed)], last);
00108 
00109   /* optional last segment */
00110   i = SeedChanceBias(15, lengthof(name_additional_english_3), seed, 60);
00111   if (i >= 0)
00112     strecat(buf, name_additional_english_3[i], last);
00113 
00114   ReplaceWords("Cunt", "East", buf);
00115   ReplaceWords("Slag", "Pits", buf);
00116   ReplaceWords("Slut", "Edin", buf);
00117   ReplaceWords("Fart", "Boot", buf);
00118   ReplaceWords("Drar", "Quar", buf);
00119   ReplaceWords("Dreh", "Bash", buf);
00120   ReplaceWords("Frar", "Shor", buf);
00121   ReplaceWords("Grar", "Aber", buf);
00122   ReplaceWords("Brar", "Over", buf);
00123   ReplaceWords("Wrar", "Stan", buf);
00124 
00125   return 0;
00126 }
00127 
00128 static byte MakeAustrianTownName(char *buf, uint32 seed, const char *last)
00129 {
00130   int i, j = 0;
00131   strecpy(buf, "", last);
00132 
00133   /* Bad, Maria, Gross, ... */
00134   i = SeedChanceBias(0, lengthof(name_austrian_a1), seed, 15);
00135   if (i >= 0) strecat(buf, name_austrian_a1[i], last);
00136 
00137   i = SeedChance(4, 6, seed);
00138   if (i >= 4) {
00139     /* Kaisers-kirchen */
00140     strecat(buf, name_austrian_a2[SeedChance( 7, lengthof(name_austrian_a2), seed)], last);
00141     strecat(buf, name_austrian_a3[SeedChance(13, lengthof(name_austrian_a3), seed)], last);
00142   } else if (i >= 2) {
00143     /* St. Johann */
00144     strecat(buf, name_austrian_a5[SeedChance( 7, lengthof(name_austrian_a5), seed)], last);
00145     strecat(buf, name_austrian_a6[SeedChance( 9, lengthof(name_austrian_a6), seed)], last);
00146     j = 1; // More likely to have a " an der " or " am "
00147   } else {
00148     /* Zell */
00149     strecat(buf, name_austrian_a4[SeedChance( 7, lengthof(name_austrian_a4), seed)], last);
00150   }
00151 
00152   i = SeedChance(1, 6, seed);
00153   if (i >= 4 - j) {
00154     /* an der Donau (rivers) */
00155     strecat(buf, name_austrian_f1[SeedChance(4, lengthof(name_austrian_f1), seed)], last);
00156     strecat(buf, name_austrian_f2[SeedChance(5, lengthof(name_austrian_f2), seed)], last);
00157   } else if (i >= 2 - j) {
00158     /* am Dachstein (mountains) */
00159     strecat(buf, name_austrian_b1[SeedChance(4, lengthof(name_austrian_b1), seed)], last);
00160     strecat(buf, name_austrian_b2[SeedChance(5, lengthof(name_austrian_b2), seed)], last);
00161   }
00162 
00163   return 0;
00164 }
00165 
00166 static byte MakeGermanTownName(char *buf, uint32 seed, const char *last)
00167 {
00168   uint i;
00169   uint seed_derivative;
00170 
00171   /* null terminates the string for strcat */
00172   strecpy(buf, "", last);
00173 
00174   seed_derivative = SeedChance(7, 28, seed);
00175 
00176   /* optional prefix */
00177   if (seed_derivative == 12 || seed_derivative == 19) {
00178     i = SeedChance(2, lengthof(name_german_pre), seed);
00179     strecat(buf, name_german_pre[i], last);
00180   }
00181 
00182   /* mandatory middle segments including option of hardcoded name */
00183   i = SeedChance(3, lengthof(name_german_real) + lengthof(name_german_1), seed);
00184   if (i < lengthof(name_german_real)) {
00185     strecat(buf, name_german_real[i], last);
00186   } else {
00187     strecat(buf, name_german_1[i - lengthof(name_german_real)], last);
00188 
00189     i = SeedChance(5, lengthof(name_german_2), seed);
00190     strecat(buf, name_german_2[i], last);
00191   }
00192 
00193   /* optional suffix */
00194   if (seed_derivative == 24) {
00195     i = SeedChance(9,
00196       lengthof(name_german_4_an_der) + lengthof(name_german_4_am), seed);
00197     if (i < lengthof(name_german_4_an_der)) {
00198       strecat(buf, name_german_3_an_der[0], last);
00199       strecat(buf, name_german_4_an_der[i], last);
00200     } else {
00201       strecat(buf, name_german_3_am[0], last);
00202       strecat(buf, name_german_4_am[i - lengthof(name_german_4_an_der)], last);
00203     }
00204   }
00205   return 0;
00206 }
00207 
00208 static byte MakeSpanishTownName(char *buf, uint32 seed, const char *last)
00209 {
00210   strecpy(buf, name_spanish_real[SeedChance(0, lengthof(name_spanish_real), seed)], last);
00211   return 0;
00212 }
00213 
00214 static byte MakeFrenchTownName(char *buf, uint32 seed, const char *last)
00215 {
00216   strecpy(buf, name_french_real[SeedChance(0, lengthof(name_french_real), seed)], last);
00217   return 0;
00218 }
00219 
00220 static byte MakeSillyTownName(char *buf, uint32 seed, const char *last)
00221 {
00222   strecpy(buf, name_silly_1[SeedChance( 0, lengthof(name_silly_1), seed)], last);
00223   strecat(buf, name_silly_2[SeedChance(16, lengthof(name_silly_2), seed)], last);
00224   return 0;
00225 }
00226 
00227 static byte MakeSwedishTownName(char *buf, uint32 seed, const char *last)
00228 {
00229   int i;
00230 
00231   /* null terminates the string for strcat */
00232   strecpy(buf, "", last);
00233 
00234   /* optional first segment */
00235   i = SeedChanceBias(0, lengthof(name_swedish_1), seed, 50);
00236   if (i >= 0)
00237     strecat(buf, name_swedish_1[i], last);
00238 
00239   /* mandatory middle segments including option of hardcoded name */
00240   if (SeedChance(4, 5, seed) >= 3) {
00241     strecat(buf, name_swedish_2[SeedChance( 7, lengthof(name_swedish_2), seed)], last);
00242   } else {
00243     strecat(buf, name_swedish_2a[SeedChance( 7, lengthof(name_swedish_2a), seed)], last);
00244     strecat(buf, name_swedish_2b[SeedChance(10, lengthof(name_swedish_2b), seed)], last);
00245     strecat(buf, name_swedish_2c[SeedChance(13, lengthof(name_swedish_2c), seed)], last);
00246   }
00247 
00248   strecat(buf, name_swedish_3[SeedChance(16, lengthof(name_swedish_3), seed)], last);
00249 
00250   return 0;
00251 }
00252 
00253 static byte MakeDutchTownName(char *buf, uint32 seed, const char *last)
00254 {
00255   int i;
00256 
00257   /* null terminates the string for strcat */
00258   strecpy(buf, "", last);
00259 
00260   /* optional first segment */
00261   i = SeedChanceBias(0, lengthof(name_dutch_1), seed, 50);
00262   if (i >= 0)
00263     strecat(buf, name_dutch_1[i], last);
00264 
00265   /* mandatory middle segments including option of hardcoded name */
00266   if (SeedChance(6, 9, seed) > 4) {
00267     strecat(buf, name_dutch_2[SeedChance( 9, lengthof(name_dutch_2), seed)], last);
00268   } else {
00269     strecat(buf, name_dutch_3[SeedChance( 9, lengthof(name_dutch_3), seed)], last);
00270     strecat(buf, name_dutch_4[SeedChance(12, lengthof(name_dutch_4), seed)], last);
00271   }
00272   strecat(buf, name_dutch_5[SeedChance(15, lengthof(name_dutch_5), seed)], last);
00273 
00274   return 0;
00275 }
00276 
00277 static byte MakeFinnishTownName(char *buf, uint32 seed, const char *last)
00278 {
00279   /* null terminates the string for strcat */
00280   strecpy(buf, "", last);
00281 
00282   /* Select randomly if town name should consists of one or two parts. */
00283   if (SeedChance(0, 15, seed) >= 10) {
00284     strecat(buf, name_finnish_real[SeedChance(2, lengthof(name_finnish_real), seed)], last);
00285   } else if (SeedChance(0, 15, seed) >= 5) {
00286     /* A two-part name by combining one of name_finnish_1 + "la"/"lä"
00287      * The reason for not having the contents of name_finnish_{1,2} in the same table is
00288      * that the ones in name_finnish_2 are not good for this purpose. */
00289     uint sel = SeedChance( 0, lengthof(name_finnish_1), seed);
00290     char *end;
00291     strecat(buf, name_finnish_1[sel], last);
00292     end = &buf[strlen(buf)-1];
00293     if (*end == 'i')
00294       *end = 'e';
00295     if (strstr(buf, "a") || strstr(buf, "o") || strstr(buf, "u") ||
00296       strstr(buf, "A") || strstr(buf, "O") || strstr(buf, "U"))
00297     {
00298       strecat(buf, "la", last);
00299     } else {
00300       strecat(buf, "lä", last);
00301     }
00302   } else {
00303     /* A two-part name by combining one of name_finnish_{1,2} + name_finnish_3.
00304      * Why aren't name_finnish_{1,2} just one table? See above. */
00305     uint sel = SeedChance(2,
00306       lengthof(name_finnish_1) + lengthof(name_finnish_2), seed);
00307     if (sel >= lengthof(name_finnish_1)) {
00308       strecat(buf, name_finnish_2[sel-lengthof(name_finnish_1)], last);
00309     } else {
00310       strecat(buf, name_finnish_1[sel], last);
00311     }
00312     strecat(buf, name_finnish_3[SeedChance(10, lengthof(name_finnish_3), seed)], last);
00313   }
00314 
00315   return 0;
00316 }
00317 
00318 static byte MakePolishTownName(char *buf, uint32 seed, const char *last)
00319 {
00320   uint i;
00321   uint j;
00322 
00323   /* null terminates the string for strcat */
00324   strecpy(buf, "", last);
00325 
00326   /* optional first segment */
00327   i = SeedChance(0,
00328     lengthof(name_polish_2_o) + lengthof(name_polish_2_m) +
00329     lengthof(name_polish_2_f) + lengthof(name_polish_2_n),
00330     seed);
00331   j = SeedChance(2, 20, seed);
00332 
00333 
00334   if (i < lengthof(name_polish_2_o)) {
00335     strecat(buf, name_polish_2_o[SeedChance(3, lengthof(name_polish_2_o), seed)], last);
00336   } else if (i < lengthof(name_polish_2_m) + lengthof(name_polish_2_o)) {
00337     if (j < 4)
00338       strecat(buf, name_polish_1_m[SeedChance(5, lengthof(name_polish_1_m), seed)], last);
00339 
00340     strecat(buf, name_polish_2_m[SeedChance(7, lengthof(name_polish_2_m), seed)], last);
00341 
00342     if (j >= 4 && j < 16)
00343       strecat(buf, name_polish_3_m[SeedChance(10, lengthof(name_polish_3_m), seed)], last);
00344   } else if (i < lengthof(name_polish_2_f) + lengthof(name_polish_2_m) + lengthof(name_polish_2_o)) {
00345     if (j < 4)
00346       strecat(buf, name_polish_1_f[SeedChance(5, lengthof(name_polish_1_f), seed)], last);
00347 
00348     strecat(buf, name_polish_2_f[SeedChance(7, lengthof(name_polish_2_f), seed)], last);
00349 
00350     if (j >= 4 && j < 16)
00351       strecat(buf, name_polish_3_f[SeedChance(10, lengthof(name_polish_3_f), seed)], last);
00352   } else {
00353     if (j < 4)
00354       strecat(buf, name_polish_1_n[SeedChance(5, lengthof(name_polish_1_n), seed)], last);
00355 
00356     strecat(buf, name_polish_2_n[SeedChance(7, lengthof(name_polish_2_n), seed)], last);
00357 
00358     if (j >= 4 && j < 16)
00359       strecat(buf, name_polish_3_n[SeedChance(10, lengthof(name_polish_3_n), seed)], last);
00360   }
00361   return 0;
00362 }
00363 
00364 static byte MakeCzechTownName(char *buf, uint32 seed, const char *last)
00365 {
00366   /* Probability of prefixes/suffixes */
00367   /* 0..11 prefix, 12..13 prefix+suffix, 14..17 suffix, 18..31 nothing */
00368   int prob_tails;
00369   bool do_prefix, do_suffix, dynamic_subst;
00370   /* IDs of the respective parts */
00371   int prefix = 0, ending = 0, suffix = 0;
00372   uint postfix = 0;
00373   uint stem;
00374   /* The select criteria. */
00375   CzechGender gender;
00376   CzechChoose choose;
00377   CzechAllow allow;
00378 
00379   /* 1:3 chance to use a real name. */
00380   if (SeedModChance(0, 4, seed) == 0) {
00381     strecpy(buf, name_czech_real[SeedModChance(4, lengthof(name_czech_real), seed)], last);
00382     return 0;
00383   }
00384 
00385   /* NUL terminates the string for strcat() */
00386   strecpy(buf, "", last);
00387 
00388   prob_tails = SeedModChance(2, 32, seed);
00389   do_prefix = prob_tails < 12;
00390   do_suffix = prob_tails > 11 && prob_tails < 17;
00391 
00392   if (do_prefix) prefix = SeedModChance(5, lengthof(name_czech_adj) * 12, seed) / 12;
00393   if (do_suffix) suffix = SeedModChance(7, lengthof(name_czech_suffix), seed);
00394   /* 3:1 chance 3:1 to use dynamic substantive */
00395   stem = SeedModChance(9,
00396     lengthof(name_czech_subst_full) + 3 * lengthof(name_czech_subst_stem),
00397     seed);
00398   if (stem < lengthof(name_czech_subst_full)) {
00399     /* That was easy! */
00400     dynamic_subst = false;
00401     gender = name_czech_subst_full[stem].gender;
00402     choose = name_czech_subst_full[stem].choose;
00403     allow = name_czech_subst_full[stem].allow;
00404   } else {
00405     unsigned int map[lengthof(name_czech_subst_ending)];
00406     int ending_start = -1, ending_stop = -1;
00407     int i;
00408 
00409     /* Load the substantive */
00410     dynamic_subst = true;
00411     stem -= lengthof(name_czech_subst_full);
00412     stem %= lengthof(name_czech_subst_stem);
00413     gender = name_czech_subst_stem[stem].gender;
00414     choose = name_czech_subst_stem[stem].choose;
00415     allow = name_czech_subst_stem[stem].allow;
00416 
00417     /* Load the postfix (1:1 chance that a postfix will be inserted) */
00418     postfix = SeedModChance(14, lengthof(name_czech_subst_postfix) * 2, seed);
00419 
00420     if (choose & CZC_POSTFIX) {
00421       /* Always get a real postfix. */
00422       postfix %= lengthof(name_czech_subst_postfix);
00423     }
00424     if (choose & CZC_NOPOSTFIX) {
00425       /* Always drop a postfix. */
00426       postfix += lengthof(name_czech_subst_postfix);
00427     }
00428     if (postfix < lengthof(name_czech_subst_postfix)) {
00429       choose |= CZC_POSTFIX;
00430     } else {
00431       choose |= CZC_NOPOSTFIX;
00432     }
00433 
00434     /* Localize the array segment containing a good gender */
00435     for (ending = 0; ending < (int) lengthof(name_czech_subst_ending); ending++) {
00436       const CzechNameSubst *e = &name_czech_subst_ending[ending];
00437 
00438       if (gender == CZG_FREE ||
00439           (gender == CZG_NFREE && e->gender != CZG_SNEUT && e->gender != CZG_PNEUT) ||
00440           gender == e->gender) {
00441         if (ending_start < 0)
00442           ending_start = ending;
00443 
00444       } else if (ending_start >= 0) {
00445         ending_stop = ending - 1;
00446         break;
00447       }
00448     }
00449     if (ending_stop < 0) {
00450       /* Whoa. All the endings matched. */
00451       ending_stop = ending - 1;
00452     }
00453 
00454     /* Make a sequential map of the items with good mask */
00455     i = 0;
00456     for (ending = ending_start; ending <= ending_stop; ending++) {
00457       const CzechNameSubst *e = &name_czech_subst_ending[ending];
00458 
00459       if ((e->choose & choose) == choose && (e->allow & allow) != 0)
00460         map[i++] = ending;
00461     }
00462     assert(i > 0);
00463 
00464     /* Load the ending */
00465     ending = map[SeedModChance(16, i, seed)];
00466     /* Override possible CZG_*FREE; this must be a real gender,
00467      * otherwise we get overflow when modifying the adjectivum. */
00468     gender = name_czech_subst_ending[ending].gender;
00469     assert(gender != CZG_FREE && gender != CZG_NFREE);
00470   }
00471 
00472   if (do_prefix && (name_czech_adj[prefix].choose & choose) != choose) {
00473     /* Throw away non-matching prefix. */
00474     do_prefix = false;
00475   }
00476 
00477   /* Now finally construct the name */
00478 
00479   if (do_prefix) {
00480     CzechPattern pattern = name_czech_adj[prefix].pattern;
00481     size_t endpos;
00482 
00483     strecat(buf, name_czech_adj[prefix].name, last);
00484     endpos = strlen(buf) - 1;
00485     /* Find the first character in a UTF-8 sequence */
00486     while (GB(buf[endpos], 6, 2) == 2) endpos--;
00487     if (gender == CZG_SMASC && pattern == CZP_PRIVL) {
00488       /* -ovX -> -uv */
00489       buf[endpos - 2] = 'u';
00490       assert(buf[endpos - 1] == 'v');
00491       buf[endpos] = '\0';
00492     } else {
00493       strecpy(buf + endpos, name_czech_patmod[gender][pattern], last);
00494     }
00495 
00496     strecat(buf, " ", last);
00497   }
00498 
00499   if (dynamic_subst) {
00500     strecat(buf, name_czech_subst_stem[stem].name, last);
00501     if (postfix < lengthof(name_czech_subst_postfix)) {
00502       const char *poststr = name_czech_subst_postfix[postfix];
00503       const char *endstr = name_czech_subst_ending[ending].name;
00504       size_t postlen, endlen;
00505 
00506       postlen = strlen(poststr);
00507       endlen = strlen(endstr);
00508       assert(postlen > 0 && endlen > 0);
00509 
00510       /* Kill the "avava" and "Jananna"-like cases */
00511       if (postlen < 2 || postlen > endlen || (
00512             (poststr[1] != 'v' || poststr[1] != endstr[1]) &&
00513             poststr[2] != endstr[1])
00514           ) {
00515         size_t buflen;
00516         strecat(buf, poststr, last);
00517         buflen = strlen(buf);
00518 
00519         /* k-i -> c-i, h-i -> z-i */
00520         if (endstr[0] == 'i') {
00521           switch (buf[buflen - 1]) {
00522             case 'k': buf[buflen - 1] = 'c'; break;
00523             case 'h': buf[buflen - 1] = 'z'; break;
00524             default: break;
00525           }
00526         }
00527       }
00528     }
00529     strecat(buf, name_czech_subst_ending[ending].name, last);
00530   } else {
00531     strecat(buf, name_czech_subst_full[stem].name, last);
00532   }
00533 
00534   if (do_suffix) {
00535     strecat(buf, " ", last);
00536     strecat(buf, name_czech_suffix[suffix], last);
00537   }
00538 
00539   return 0;
00540 }
00541 
00542 static byte MakeRomanianTownName(char *buf, uint32 seed, const char *last)
00543 {
00544   strecpy(buf, name_romanian_real[SeedChance(0, lengthof(name_romanian_real), seed)], last);
00545   return 0;
00546 }
00547 
00548 static byte MakeSlovakTownName(char *buf, uint32 seed, const char *last)
00549 {
00550   strecpy(buf, name_slovak_real[SeedChance(0, lengthof(name_slovak_real), seed)], last);
00551   return 0;
00552 }
00553 
00554 static byte MakeNorwegianTownName(char *buf, uint32 seed, const char *last)
00555 {
00556   strecpy(buf, "", last);
00557 
00558   /* Use first 4 bit from seed to decide whether or not this town should
00559    * have a real name 3/16 chance.  Bit 0-3 */
00560   if (SeedChance(0, 15, seed) < 3) {
00561     /* Use 7bit for the realname table index.  Bit 4-10 */
00562     strecat(buf, name_norwegian_real[SeedChance(4, lengthof(name_norwegian_real), seed)], last);
00563   } else {
00564     /* Use 7bit for the first fake part.  Bit 4-10 */
00565     strecat(buf, name_norwegian_1[SeedChance(4, lengthof(name_norwegian_1), seed)], last);
00566     /* Use 7bit for the last fake part.  Bit 11-17 */
00567     strecat(buf, name_norwegian_2[SeedChance(11, lengthof(name_norwegian_2), seed)], last);
00568   }
00569 
00570   return 0;
00571 }
00572 
00573 static byte MakeHungarianTownName(char *buf, uint32 seed, const char *last)
00574 {
00575   uint i;
00576 
00577   /* null terminates the string for strcat */
00578   strecpy(buf, "", last);
00579 
00580   if (SeedChance(12, 15, seed) < 3) {
00581     strecat(buf, name_hungarian_real[SeedChance(0, lengthof(name_hungarian_real), seed)], last);
00582   } else {
00583     /* optional first segment */
00584     i = SeedChance(3, lengthof(name_hungarian_1) * 3, seed);
00585     if (i < lengthof(name_hungarian_1))
00586       strecat(buf, name_hungarian_1[i], last);
00587 
00588     /* mandatory middle segments */
00589     strecat(buf, name_hungarian_2[SeedChance(3, lengthof(name_hungarian_2), seed)], last);
00590     strecat(buf, name_hungarian_3[SeedChance(6, lengthof(name_hungarian_3), seed)], last);
00591 
00592     /* optional last segment */
00593     i = SeedChance(10, lengthof(name_hungarian_4) * 3, seed);
00594     if (i < lengthof(name_hungarian_4)) {
00595       strecat(buf, name_hungarian_4[i], last);
00596     }
00597   }
00598 
00599   return 0;
00600 }
00601 
00602 static byte MakeSwissTownName(char *buf, uint32 seed, const char *last)
00603 {
00604   strecpy(buf, name_swiss_real[SeedChance(0, lengthof(name_swiss_real), seed)], last);
00605   return 0;
00606 }
00607 
00608 static byte MakeDanishTownName(char *buf, uint32 seed, const char *last)
00609 {
00610   int i;
00611 
00612   /* null terminates the string for strcat */
00613   strecpy(buf, "", last);
00614 
00615   /* optional first segment */
00616   i = SeedChanceBias(0, lengthof(name_danish_1), seed, 50);
00617   if (i >= 0)
00618     strecat(buf, name_danish_1[i], last);
00619 
00620   /* middle segments removed as this algorithm seems to create much more realistic names */
00621   strecat(buf, name_danish_2[SeedChance( 7, lengthof(name_danish_2), seed)], last);
00622   strecat(buf, name_danish_3[SeedChance(16, lengthof(name_danish_3), seed)], last);
00623 
00624   return 0;
00625 }
00626 
00627 static byte MakeTurkishTownName(char *buf, uint32 seed, const char *last)
00628 {
00629   uint i;
00630 
00631   /* null terminates the string for strcat */
00632   strecpy(buf, "", last);
00633 
00634   if ((i = SeedModChance(0, 5, seed)) == 0) {
00635     strecat(buf, name_turkish_prefix[SeedModChance( 2, lengthof(name_turkish_prefix), seed)], last);
00636 
00637     /* middle segment */
00638     strecat(buf, name_turkish_middle[SeedModChance( 4, lengthof(name_turkish_middle), seed)], last);
00639 
00640     /* optional suffix */
00641     if (SeedModChance(0, 7, seed) == 0) {
00642       strecat(buf, name_turkish_suffix[SeedModChance( 10, lengthof(name_turkish_suffix), seed)], last);
00643     }
00644   } else {
00645     if (i == 1 || i == 2) {
00646       strecat(buf, name_turkish_prefix[SeedModChance( 2, lengthof(name_turkish_prefix), seed)], last);
00647       strecat(buf, name_turkish_suffix[SeedModChance( 4, lengthof(name_turkish_suffix), seed)], last);
00648     } else {
00649       strecat(buf, name_turkish_real[SeedModChance( 4, lengthof(name_turkish_real), seed)], last);
00650     }
00651   }
00652   return 0;
00653 }
00654 
00655 static const char *mascul_femin_italian[] = {
00656   "o",
00657   "a",
00658 };
00659 
00660 static byte MakeItalianTownName(char *buf, uint32 seed, const char *last)
00661 {
00662   strecpy(buf, "", last);
00663 
00664   if (SeedModChance(0, 6, seed) == 0) { // real city names
00665     strecat(buf, name_italian_real[SeedModChance(4, lengthof(name_italian_real), seed)], last);
00666   } else {
00667     uint i;
00668 
00669     if (SeedModChance(0, 8, seed) == 0) { // prefix
00670       strecat(buf, name_italian_pref[SeedModChance(11, lengthof(name_italian_pref), seed)], last);
00671     }
00672 
00673     i = SeedChance(0, 2, seed);
00674     if (i == 0) { // masculine form
00675       strecat(buf, name_italian_1m[SeedModChance(4, lengthof(name_italian_1m), seed)], last);
00676     } else { // feminine form
00677       strecat(buf, name_italian_1f[SeedModChance(4, lengthof(name_italian_1f), seed)], last);
00678     }
00679 
00680     if (SeedModChance(3, 3, seed) == 0) {
00681       strecat(buf, name_italian_2[SeedModChance(11, lengthof(name_italian_2), seed)], last);
00682       strecat(buf, mascul_femin_italian[i], last);
00683     } else {
00684       strecat(buf, name_italian_2i[SeedModChance(16, lengthof(name_italian_2i), seed)], last);
00685     }
00686 
00687     if (SeedModChance(15, 4, seed) == 0) {
00688       if (SeedModChance(5, 2, seed) == 0) { // generic suffix
00689         strecat(buf, name_italian_3[SeedModChance(4, lengthof(name_italian_3), seed)], last);
00690       } else { // river name suffix
00691         strecat(buf, name_italian_river1[SeedModChance(4, lengthof(name_italian_river1), seed)], last);
00692         strecat(buf, name_italian_river2[SeedModChance(16, lengthof(name_italian_river2), seed)], last);
00693       }
00694     }
00695   }
00696 
00697   return 0;
00698 }
00699 
00700 static byte MakeCatalanTownName(char *buf, uint32 seed, const char *last)
00701 {
00702   strecpy(buf, "", last);
00703 
00704   if (SeedModChance(0, 3, seed) == 0) { // real city names
00705     strecat(buf, name_catalan_real[SeedModChance(4, lengthof(name_catalan_real), seed)], last);
00706   } else {
00707     uint i;
00708 
00709     if (SeedModChance(0, 2, seed) == 0) { // prefix
00710       strecat(buf, name_catalan_pref[SeedModChance(11, lengthof(name_catalan_pref), seed)], last);
00711     }
00712 
00713     i = SeedChance(0, 2, seed);
00714     if (i == 0) { // masculine form
00715       strecat(buf, name_catalan_1m[SeedModChance(4, lengthof(name_catalan_1m), seed)], last);
00716       strecat(buf, name_catalan_2m[SeedModChance(11, lengthof(name_catalan_2m), seed)], last);
00717     } else { // feminine form
00718       strecat(buf, name_catalan_1f[SeedModChance(4, lengthof(name_catalan_1f), seed)], last);
00719       strecat(buf, name_catalan_2f[SeedModChance(11, lengthof(name_catalan_2f), seed)], last);
00720     }
00721 
00722 
00723     if (SeedModChance(15, 5, seed) == 0) {
00724       if (SeedModChance(5, 2, seed) == 0) { // generic suffix
00725         strecat(buf, name_catalan_3[SeedModChance(4, lengthof(name_catalan_3), seed)], last);
00726       } else { // river name suffix
00727         strecat(buf, name_catalan_river1[SeedModChance(4, lengthof(name_catalan_river1), seed)], last);
00728       }
00729     }
00730   }
00731 
00732   return 0;
00733 }
00734 
00735 
00736 
00737 TownNameGenerator * const _town_name_generators[] =
00738 {
00739   MakeEnglishOriginalTownName,
00740   MakeFrenchTownName,
00741   MakeGermanTownName,
00742   MakeEnglishAdditionalTownName,
00743   MakeSpanishTownName,
00744   MakeSillyTownName,
00745   MakeSwedishTownName,
00746   MakeDutchTownName,
00747   MakeFinnishTownName,
00748   MakePolishTownName,
00749   MakeSlovakTownName,
00750   MakeNorwegianTownName,
00751   MakeHungarianTownName,
00752   MakeAustrianTownName,
00753   MakeRomanianTownName,
00754   MakeCzechTownName,
00755   MakeSwissTownName,
00756   MakeDanishTownName,
00757   MakeTurkishTownName,
00758   MakeItalianTownName,
00759   MakeCatalanTownName,
00760 };
00761 
00762 /* DO WE NEED THIS ANY MORE? */
00763 #define FIXNUM(x, y, z) (((((x) << 16) / (y)) + 1) << z)
00764 
00765 uint32 GetOldTownName(uint32 townnameparts, byte old_town_name_type)
00766 {
00767   switch (old_town_name_type) {
00768     case 0: case 3: // English, American
00769       /* Already OK */
00770       return townnameparts;
00771 
00772     case 1: // French
00773       /* For some reason 86 needs to be subtracted from townnameparts
00774        * 0000 0000 0000 0000 0000 0000 1111 1111 */
00775       return FIXNUM(townnameparts - 86, lengthof(name_french_real), 0);
00776 
00777     case 2: // German
00778       DEBUG(misc, 0, "German Townnames are buggy (%d)", townnameparts);
00779       return townnameparts;
00780 
00781     case 4: // Latin-American
00782       /* 0000 0000 0000 0000 0000 0000 1111 1111 */
00783       return FIXNUM(townnameparts, lengthof(name_spanish_real), 0);
00784 
00785     case 5: // Silly
00786       /* NUM_SILLY_1 - lower 16 bits
00787        * NUM_SILLY_2 - upper 16 bits without leading 1 (first 8 bytes)
00788        * 1000 0000 2222 2222 0000 0000 1111 1111 */
00789       return FIXNUM(townnameparts, lengthof(name_silly_1), 0) | FIXNUM(GB(townnameparts, 16, 8), lengthof(name_silly_2), 16);
00790   }
00791   return 0;
00792 }

Generated on Mon Sep 22 20:34:16 2008 for openttd by  doxygen 1.5.6