# namegen.cpp

Go to the documentation of this file.

    00001 /* $Id: namegen.cpp 14426 2008-10-01 11:48:57Z 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); // Safe as the string in buf is always more than 4 characters long.
    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 }