namegen.cpp

Go to the documentation of this file.
00001 /* $Id: namegen.cpp 15727 2009-03-15 16:31:16Z smatz $ */
00002 
00005 #include "stdafx.h"
00006 #include "namegen_func.h"
00007 #include "string_func.h"
00008 
00009 #include "table/namegen.h"
00010 
00011 static inline uint32 SeedChance(int shift_by, int max, uint32 seed)
00012 {
00013   return (GB(seed, shift_by, 16) * max) >> 16;
00014 }
00015 
00016 static inline uint32 SeedModChance(int shift_by, int max, uint32 seed)
00017 {
00018   /* This actually gives *MUCH* more even distribution of the values
00019    * than SeedChance(), which is absolutely horrible in that. If
00020    * you do not believe me, try with i.e. the Czech town names,
00021    * compare the words (nicely visible on prefixes) generated by
00022    * SeedChance() and SeedModChance(). Do not get dicouraged by the
00023    * never-use-modulo myths, which hold true only for the linear
00024    * congruential generators (and Random() isn't such a generator).
00025    * --pasky
00026    * TODO: Perhaps we should use it for all the name generators? --pasky */
00027   return (seed >> shift_by) % max;
00028 }
00029 
00030 static inline int32 SeedChanceBias(int shift_by, int max, uint32 seed, int bias)
00031 {
00032   return SeedChance(shift_by, max + bias, seed) - bias;
00033 }
00034 
00035 static void ReplaceWords(const char *org, const char *rep, char *buf)
00036 {
00037   if (strncmp(buf, org, 4) == 0) strncpy(buf, rep, 4); // Safe as the string in buf is always more than 4 characters long.
00038 }
00039 
00040 static byte MakeEnglishOriginalTownName(char *buf, uint32 seed, const char *last)
00041 {
00042   int i;
00043 
00044   /* null terminates the string for strcat */
00045   strecpy(buf, "", last);
00046 
00047   /* optional first segment */
00048   i = SeedChanceBias(0, lengthof(_name_original_english_1), seed, 50);
00049   if (i >= 0)
00050     strecat(buf, _name_original_english_1[i], last);
00051 
00052   /* mandatory middle segments */
00053   strecat(buf, _name_original_english_2[SeedChance(4,  lengthof(_name_original_english_2), seed)], last);
00054   strecat(buf, _name_original_english_3[SeedChance(7,  lengthof(_name_original_english_3), seed)], last);
00055   strecat(buf, _name_original_english_4[SeedChance(10, lengthof(_name_original_english_4), seed)], last);
00056   strecat(buf, _name_original_english_5[SeedChance(13, lengthof(_name_original_english_5), seed)], last);
00057 
00058   /* optional last segment */
00059   i = SeedChanceBias(15, lengthof(_name_original_english_6), seed, 60);
00060   if (i >= 0)
00061     strecat(buf, _name_original_english_6[i], last);
00062 
00063   if (buf[0] == 'C' && (buf[1] == 'e' || buf[1] == 'i'))
00064     buf[0] = 'K';
00065 
00066   ReplaceWords("Cunt", "East", buf);
00067   ReplaceWords("Slag", "Pits", buf);
00068   ReplaceWords("Slut", "Edin", buf);
00069   //ReplaceWords("Fart", "Boot", buf);
00070   ReplaceWords("Drar", "Quar", buf);
00071   ReplaceWords("Dreh", "Bash", buf);
00072   ReplaceWords("Frar", "Shor", buf);
00073   ReplaceWords("Grar", "Aber", buf);
00074   ReplaceWords("Brar", "Over", buf);
00075   ReplaceWords("Wrar", "Inve", buf);
00076 
00077   return 0;
00078 }
00079 
00080 
00081 static byte MakeEnglishAdditionalTownName(char *buf, uint32 seed, const char *last)
00082 {
00083   int i;
00084 
00085   /* null terminates the string for strcat */
00086   strecpy(buf, "", last);
00087 
00088   /* optional first segment */
00089   i = SeedChanceBias(0, lengthof(_name_additional_english_prefix), seed, 50);
00090   if (i >= 0)
00091     strecat(buf, _name_additional_english_prefix[i], last);
00092 
00093   if (SeedChance(3, 20, seed) >= 14) {
00094     strecat(buf, _name_additional_english_1a[SeedChance(6, lengthof(_name_additional_english_1a), seed)], last);
00095   } else {
00096     strecat(buf, _name_additional_english_1b1[SeedChance(6, lengthof(_name_additional_english_1b1), seed)], last);
00097     strecat(buf, _name_additional_english_1b2[SeedChance(9, lengthof(_name_additional_english_1b2), seed)], last);
00098     if (SeedChance(11, 20, seed) >= 4) {
00099       strecat(buf, _name_additional_english_1b3a[SeedChance(12, lengthof(_name_additional_english_1b3a), seed)], last);
00100     } else {
00101       strecat(buf, _name_additional_english_1b3b[SeedChance(12, lengthof(_name_additional_english_1b3b), seed)], last);
00102     }
00103   }
00104 
00105   strecat(buf, _name_additional_english_2[SeedChance(14, lengthof(_name_additional_english_2), seed)], last);
00106 
00107   /* optional last segment */
00108   i = SeedChanceBias(15, lengthof(_name_additional_english_3), seed, 60);
00109   if (i >= 0)
00110     strecat(buf, _name_additional_english_3[i], last);
00111 
00112   ReplaceWords("Cunt", "East", buf);
00113   ReplaceWords("Slag", "Pits", buf);
00114   ReplaceWords("Slut", "Edin", buf);
00115   ReplaceWords("Fart", "Boot", buf);
00116   ReplaceWords("Drar", "Quar", buf);
00117   ReplaceWords("Dreh", "Bash", buf);
00118   ReplaceWords("Frar", "Shor", buf);
00119   ReplaceWords("Grar", "Aber", buf);
00120   ReplaceWords("Brar", "Over", buf);
00121   ReplaceWords("Wrar", "Stan", buf);
00122 
00123   return 0;
00124 }
00125 
00126 static byte MakeAustrianTownName(char *buf, uint32 seed, const char *last)
00127 {
00128   int i, j = 0;
00129   strecpy(buf, "", last);
00130 
00131   /* Bad, Maria, Gross, ... */
00132   i = SeedChanceBias(0, lengthof(_name_austrian_a1), seed, 15);
00133   if (i >= 0) strecat(buf, _name_austrian_a1[i], last);
00134 
00135   i = SeedChance(4, 6, seed);
00136   if (i >= 4) {
00137     /* Kaisers-kirchen */
00138     strecat(buf, _name_austrian_a2[SeedChance( 7, lengthof(_name_austrian_a2), seed)], last);
00139     strecat(buf, _name_austrian_a3[SeedChance(13, lengthof(_name_austrian_a3), seed)], last);
00140   } else if (i >= 2) {
00141     /* St. Johann */
00142     strecat(buf, _name_austrian_a5[SeedChance( 7, lengthof(_name_austrian_a5), seed)], last);
00143     strecat(buf, _name_austrian_a6[SeedChance( 9, lengthof(_name_austrian_a6), seed)], last);
00144     j = 1; // More likely to have a " an der " or " am "
00145   } else {
00146     /* Zell */
00147     strecat(buf, _name_austrian_a4[SeedChance( 7, lengthof(_name_austrian_a4), seed)], last);
00148   }
00149 
00150   i = SeedChance(1, 6, seed);
00151   if (i >= 4 - j) {
00152     /* an der Donau (rivers) */
00153     strecat(buf, _name_austrian_f1[SeedChance(4, lengthof(_name_austrian_f1), seed)], last);
00154     strecat(buf, _name_austrian_f2[SeedChance(5, lengthof(_name_austrian_f2), seed)], last);
00155   } else if (i >= 2 - j) {
00156     /* am Dachstein (mountains) */
00157     strecat(buf, _name_austrian_b1[SeedChance(4, lengthof(_name_austrian_b1), seed)], last);
00158     strecat(buf, _name_austrian_b2[SeedChance(5, lengthof(_name_austrian_b2), seed)], last);
00159   }
00160 
00161   return 0;
00162 }
00163 
00164 static byte MakeGermanTownName(char *buf, uint32 seed, const char *last)
00165 {
00166   uint i;
00167   uint seed_derivative;
00168 
00169   /* null terminates the string for strcat */
00170   strecpy(buf, "", last);
00171 
00172   seed_derivative = SeedChance(7, 28, seed);
00173 
00174   /* optional prefix */
00175   if (seed_derivative == 12 || seed_derivative == 19) {
00176     i = SeedChance(2, lengthof(_name_german_pre), seed);
00177     strecat(buf, _name_german_pre[i], last);
00178   }
00179 
00180   /* mandatory middle segments including option of hardcoded name */
00181   i = SeedChance(3, lengthof(_name_german_real) + lengthof(_name_german_1), seed);
00182   if (i < lengthof(_name_german_real)) {
00183     strecat(buf, _name_german_real[i], last);
00184   } else {
00185     strecat(buf, _name_german_1[i - lengthof(_name_german_real)], last);
00186 
00187     i = SeedChance(5, lengthof(_name_german_2), seed);
00188     strecat(buf, _name_german_2[i], last);
00189   }
00190 
00191   /* optional suffix */
00192   if (seed_derivative == 24) {
00193     i = SeedChance(9,
00194       lengthof(_name_german_4_an_der) + lengthof(_name_german_4_am), seed);
00195     if (i < lengthof(_name_german_4_an_der)) {
00196       strecat(buf, _name_german_3_an_der[0], last);
00197       strecat(buf, _name_german_4_an_der[i], last);
00198     } else {
00199       strecat(buf, _name_german_3_am[0], last);
00200       strecat(buf, _name_german_4_am[i - lengthof(_name_german_4_an_der)], last);
00201     }
00202   }
00203   return 0;
00204 }
00205 
00206 static byte MakeSpanishTownName(char *buf, uint32 seed, const char *last)
00207 {
00208   strecpy(buf, _name_spanish_real[SeedChance(0, lengthof(_name_spanish_real), seed)], last);
00209   return 0;
00210 }
00211 
00212 static byte MakeFrenchTownName(char *buf, uint32 seed, const char *last)
00213 {
00214   strecpy(buf, _name_french_real[SeedChance(0, lengthof(_name_french_real), seed)], last);
00215   return 0;
00216 }
00217 
00218 static byte MakeSillyTownName(char *buf, uint32 seed, const char *last)
00219 {
00220   strecpy(buf, _name_silly_1[SeedChance( 0, lengthof(_name_silly_1), seed)], last);
00221   strecat(buf, _name_silly_2[SeedChance(16, lengthof(_name_silly_2), seed)], last);
00222   return 0;
00223 }
00224 
00225 static byte MakeSwedishTownName(char *buf, uint32 seed, const char *last)
00226 {
00227   int i;
00228 
00229   /* null terminates the string for strcat */
00230   strecpy(buf, "", last);
00231 
00232   /* optional first segment */
00233   i = SeedChanceBias(0, lengthof(_name_swedish_1), seed, 50);
00234   if (i >= 0)
00235     strecat(buf, _name_swedish_1[i], last);
00236 
00237   /* mandatory middle segments including option of hardcoded name */
00238   if (SeedChance(4, 5, seed) >= 3) {
00239     strecat(buf, _name_swedish_2[SeedChance( 7, lengthof(_name_swedish_2), seed)], last);
00240   } else {
00241     strecat(buf, _name_swedish_2a[SeedChance( 7, lengthof(_name_swedish_2a), seed)], last);
00242     strecat(buf, _name_swedish_2b[SeedChance(10, lengthof(_name_swedish_2b), seed)], last);
00243     strecat(buf, _name_swedish_2c[SeedChance(13, lengthof(_name_swedish_2c), seed)], last);
00244   }
00245 
00246   strecat(buf, _name_swedish_3[SeedChance(16, lengthof(_name_swedish_3), seed)], last);
00247 
00248   return 0;
00249 }
00250 
00251 static byte MakeDutchTownName(char *buf, uint32 seed, const char *last)
00252 {
00253   int i;
00254 
00255   /* null terminates the string for strcat */
00256   strecpy(buf, "", last);
00257 
00258   /* optional first segment */
00259   i = SeedChanceBias(0, lengthof(_name_dutch_1), seed, 50);
00260   if (i >= 0)
00261     strecat(buf, _name_dutch_1[i], last);
00262 
00263   /* mandatory middle segments including option of hardcoded name */
00264   if (SeedChance(6, 9, seed) > 4) {
00265     strecat(buf, _name_dutch_2[SeedChance( 9, lengthof(_name_dutch_2), seed)], last);
00266   } else {
00267     strecat(buf, _name_dutch_3[SeedChance( 9, lengthof(_name_dutch_3), seed)], last);
00268     strecat(buf, _name_dutch_4[SeedChance(12, lengthof(_name_dutch_4), seed)], last);
00269   }
00270   strecat(buf, _name_dutch_5[SeedChance(15, lengthof(_name_dutch_5), seed)], last);
00271 
00272   return 0;
00273 }
00274 
00275 static byte MakeFinnishTownName(char *buf, uint32 seed, const char *last)
00276 {
00277   /* null terminates the string for strcat */
00278   strecpy(buf, "", last);
00279 
00280   /* Select randomly if town name should consists of one or two parts. */
00281   if (SeedChance(0, 15, seed) >= 10) {
00282     strecat(buf, _name_finnish_real[SeedChance(2, lengthof(_name_finnish_real), seed)], last);
00283   } else if (SeedChance(0, 15, seed) >= 5) {
00284     /* A two-part name by combining one of _name_finnish_1 + "la"/"lä"
00285      * The reason for not having the contents of _name_finnish_{1,2} in the same table is
00286      * that the ones in _name_finnish_2 are not good for this purpose. */
00287     uint sel = SeedChance( 0, lengthof(_name_finnish_1), seed);
00288     char *end;
00289     strecat(buf, _name_finnish_1[sel], last);
00290     end = &buf[strlen(buf)-1];
00291     if (*end == 'i')
00292       *end = 'e';
00293     if (strstr(buf, "a") || strstr(buf, "o") || strstr(buf, "u") ||
00294       strstr(buf, "A") || strstr(buf, "O") || strstr(buf, "U"))
00295     {
00296       strecat(buf, "la", last);
00297     } else {
00298       strecat(buf, "lä", last);
00299     }
00300   } else {
00301     /* A two-part name by combining one of _name_finnish_{1,2} + _name_finnish_3.
00302      * Why aren't _name_finnish_{1,2} just one table? See above. */
00303     uint sel = SeedChance(2,
00304       lengthof(_name_finnish_1) + lengthof(_name_finnish_2), seed);
00305     if (sel >= lengthof(_name_finnish_1)) {
00306       strecat(buf, _name_finnish_2[sel - lengthof(_name_finnish_1)], last);
00307     } else {
00308       strecat(buf, _name_finnish_1[sel], last);
00309     }
00310     strecat(buf, _name_finnish_3[SeedChance(10, lengthof(_name_finnish_3), seed)], last);
00311   }
00312 
00313   return 0;
00314 }
00315 
00316 static byte MakePolishTownName(char *buf, uint32 seed, const char *last)
00317 {
00318   uint i;
00319   uint j;
00320 
00321   /* null terminates the string for strcat */
00322   strecpy(buf, "", last);
00323 
00324   /* optional first segment */
00325   i = SeedChance(0,
00326     lengthof(_name_polish_2_o) + lengthof(_name_polish_2_m) +
00327     lengthof(_name_polish_2_f) + lengthof(_name_polish_2_n),
00328     seed);
00329   j = SeedChance(2, 20, seed);
00330 
00331 
00332   if (i < lengthof(_name_polish_2_o)) {
00333     strecat(buf, _name_polish_2_o[SeedChance(3, lengthof(_name_polish_2_o), seed)], last);
00334   } else if (i < lengthof(_name_polish_2_m) + lengthof(_name_polish_2_o)) {
00335     if (j < 4)
00336       strecat(buf, _name_polish_1_m[SeedChance(5, lengthof(_name_polish_1_m), seed)], last);
00337 
00338     strecat(buf, _name_polish_2_m[SeedChance(7, lengthof(_name_polish_2_m), seed)], last);
00339 
00340     if (j >= 4 && j < 16)
00341       strecat(buf, _name_polish_3_m[SeedChance(10, lengthof(_name_polish_3_m), seed)], last);
00342   } else if (i < lengthof(_name_polish_2_f) + lengthof(_name_polish_2_m) + lengthof(_name_polish_2_o)) {
00343     if (j < 4)
00344       strecat(buf, _name_polish_1_f[SeedChance(5, lengthof(_name_polish_1_f), seed)], last);
00345 
00346     strecat(buf, _name_polish_2_f[SeedChance(7, lengthof(_name_polish_2_f), seed)], last);
00347 
00348     if (j >= 4 && j < 16)
00349       strecat(buf, _name_polish_3_f[SeedChance(10, lengthof(_name_polish_3_f), seed)], last);
00350   } else {
00351     if (j < 4)
00352       strecat(buf, _name_polish_1_n[SeedChance(5, lengthof(_name_polish_1_n), seed)], last);
00353 
00354     strecat(buf, _name_polish_2_n[SeedChance(7, lengthof(_name_polish_2_n), seed)], last);
00355 
00356     if (j >= 4 && j < 16)
00357       strecat(buf, _name_polish_3_n[SeedChance(10, lengthof(_name_polish_3_n), seed)], last);
00358   }
00359   return 0;
00360 }
00361 
00362 static byte MakeCzechTownName(char *buf, uint32 seed, const char *last)
00363 {
00364   /* Probability of prefixes/suffixes
00365    * 0..11 prefix, 12..13 prefix+suffix, 14..17 suffix, 18..31 nothing */
00366   int prob_tails;
00367   bool do_prefix, do_suffix, dynamic_subst;
00368   /* IDs of the respective parts */
00369   int prefix = 0, ending = 0, suffix = 0;
00370   uint postfix = 0;
00371   uint stem;
00372   /* The select criteria. */
00373   CzechGender gender;
00374   CzechChoose choose;
00375   CzechAllow allow;
00376 
00377   /* 1:3 chance to use a real name. */
00378   if (SeedModChance(0, 4, seed) == 0) {
00379     strecpy(buf, _name_czech_real[SeedModChance(4, lengthof(_name_czech_real), seed)], last);
00380     return 0;
00381   }
00382 
00383   /* NUL terminates the string for strcat() */
00384   strecpy(buf, "", last);
00385 
00386   prob_tails = SeedModChance(2, 32, seed);
00387   do_prefix = prob_tails < 12;
00388   do_suffix = prob_tails > 11 && prob_tails < 17;
00389 
00390   if (do_prefix) prefix = SeedModChance(5, lengthof(_name_czech_adj) * 12, seed) / 12;
00391   if (do_suffix) suffix = SeedModChance(7, lengthof(_name_czech_suffix), seed);
00392   /* 3:1 chance 3:1 to use dynamic substantive */
00393   stem = SeedModChance(9,
00394     lengthof(_name_czech_subst_full) + 3 * lengthof(_name_czech_subst_stem),
00395     seed);
00396   if (stem < lengthof(_name_czech_subst_full)) {
00397     /* That was easy! */
00398     dynamic_subst = false;
00399     gender = _name_czech_subst_full[stem].gender;
00400     choose = _name_czech_subst_full[stem].choose;
00401     allow = _name_czech_subst_full[stem].allow;
00402   } else {
00403     unsigned int map[lengthof(_name_czech_subst_ending)];
00404     int ending_start = -1, ending_stop = -1;
00405     int i;
00406 
00407     /* Load the substantive */
00408     dynamic_subst = true;
00409     stem -= lengthof(_name_czech_subst_full);
00410     stem %= lengthof(_name_czech_subst_stem);
00411     gender = _name_czech_subst_stem[stem].gender;
00412     choose = _name_czech_subst_stem[stem].choose;
00413     allow = _name_czech_subst_stem[stem].allow;
00414 
00415     /* Load the postfix (1:1 chance that a postfix will be inserted) */
00416     postfix = SeedModChance(14, lengthof(_name_czech_subst_postfix) * 2, seed);
00417 
00418     if (choose & CZC_POSTFIX) {
00419       /* Always get a real postfix. */
00420       postfix %= lengthof(_name_czech_subst_postfix);
00421     }
00422     if (choose & CZC_NOPOSTFIX) {
00423       /* Always drop a postfix. */
00424       postfix += lengthof(_name_czech_subst_postfix);
00425     }
00426     if (postfix < lengthof(_name_czech_subst_postfix)) {
00427       choose |= CZC_POSTFIX;
00428     } else {
00429       choose |= CZC_NOPOSTFIX;
00430     }
00431 
00432     /* Localize the array segment containing a good gender */
00433     for (ending = 0; ending < (int) lengthof(_name_czech_subst_ending); ending++) {
00434       const CzechNameSubst *e = &_name_czech_subst_ending[ending];
00435 
00436       if (gender == CZG_FREE ||
00437           (gender == CZG_NFREE && e->gender != CZG_SNEUT && e->gender != CZG_PNEUT) ||
00438           gender == e->gender) {
00439         if (ending_start < 0)
00440           ending_start = ending;
00441 
00442       } else if (ending_start >= 0) {
00443         ending_stop = ending - 1;
00444         break;
00445       }
00446     }
00447     if (ending_stop < 0) {
00448       /* Whoa. All the endings matched. */
00449       ending_stop = ending - 1;
00450     }
00451 
00452     /* Make a sequential map of the items with good mask */
00453     i = 0;
00454     for (ending = ending_start; ending <= ending_stop; ending++) {
00455       const CzechNameSubst *e = &_name_czech_subst_ending[ending];
00456 
00457       if ((e->choose & choose) == choose && (e->allow & allow) != 0)
00458         map[i++] = ending;
00459     }
00460     assert(i > 0);
00461 
00462     /* Load the ending */
00463     ending = map[SeedModChance(16, i, seed)];
00464     /* Override possible CZG_*FREE; this must be a real gender,
00465      * otherwise we get overflow when modifying the adjectivum. */
00466     gender = _name_czech_subst_ending[ending].gender;
00467     assert(gender != CZG_FREE && gender != CZG_NFREE);
00468   }
00469 
00470   if (do_prefix && (_name_czech_adj[prefix].choose & choose) != choose) {
00471     /* Throw away non-matching prefix. */
00472     do_prefix = false;
00473   }
00474 
00475   /* Now finally construct the name */
00476 
00477   if (do_prefix) {
00478     CzechPattern pattern = _name_czech_adj[prefix].pattern;
00479     size_t endpos;
00480 
00481     strecat(buf, _name_czech_adj[prefix].name, last);
00482     endpos = strlen(buf) - 1;
00483     /* Find the first character in a UTF-8 sequence */
00484     while (GB(buf[endpos], 6, 2) == 2) endpos--;
00485     if (gender == CZG_SMASC && pattern == CZP_PRIVL) {
00486       /* -ovX -> -uv */
00487       buf[endpos - 2] = 'u';
00488       assert(buf[endpos - 1] == 'v');
00489       buf[endpos] = '\0';
00490     } else {
00491       strecpy(buf + endpos, _name_czech_patmod[gender][pattern], last);
00492     }
00493 
00494     strecat(buf, " ", last);
00495   }
00496 
00497   if (dynamic_subst) {
00498     strecat(buf, _name_czech_subst_stem[stem].name, last);
00499     if (postfix < lengthof(_name_czech_subst_postfix)) {
00500       const char *poststr = _name_czech_subst_postfix[postfix];
00501       const char *endstr = _name_czech_subst_ending[ending].name;
00502       size_t postlen, endlen;
00503 
00504       postlen = strlen(poststr);
00505       endlen = strlen(endstr);
00506       assert(postlen > 0 && endlen > 0);
00507 
00508       /* Kill the "avava" and "Jananna"-like cases */
00509       if (postlen < 2 || postlen > endlen || (
00510             (poststr[1] != 'v' || poststr[1] != endstr[1]) &&
00511             poststr[2] != endstr[1])
00512           ) {
00513         size_t buflen;
00514         strecat(buf, poststr, last);
00515         buflen = strlen(buf);
00516 
00517         /* k-i -> c-i, h-i -> z-i */
00518         if (endstr[0] == 'i') {
00519           switch (buf[buflen - 1]) {
00520             case 'k': buf[buflen - 1] = 'c'; break;
00521             case 'h': buf[buflen - 1] = 'z'; break;
00522             default: break;
00523           }
00524         }
00525       }
00526     }
00527     strecat(buf, _name_czech_subst_ending[ending].name, last);
00528   } else {
00529     strecat(buf, _name_czech_subst_full[stem].name, last);
00530   }
00531 
00532   if (do_suffix) {
00533     strecat(buf, " ", last);
00534     strecat(buf, _name_czech_suffix[suffix], last);
00535   }
00536 
00537   return 0;
00538 }
00539 
00540 static byte MakeRomanianTownName(char *buf, uint32 seed, const char *last)
00541 {
00542   strecpy(buf, _name_romanian_real[SeedChance(0, lengthof(_name_romanian_real), seed)], last);
00543   return 0;
00544 }
00545 
00546 static byte MakeSlovakTownName(char *buf, uint32 seed, const char *last)
00547 {
00548   strecpy(buf, _name_slovak_real[SeedChance(0, lengthof(_name_slovak_real), seed)], last);
00549   return 0;
00550 }
00551 
00552 static byte MakeNorwegianTownName(char *buf, uint32 seed, const char *last)
00553 {
00554   strecpy(buf, "", last);
00555 
00556   /* Use first 4 bit from seed to decide whether or not this town should
00557    * have a real name 3/16 chance.  Bit 0-3 */
00558   if (SeedChance(0, 15, seed) < 3) {
00559     /* Use 7bit for the realname table index.  Bit 4-10 */
00560     strecat(buf, _name_norwegian_real[SeedChance(4, lengthof(_name_norwegian_real), seed)], last);
00561   } else {
00562     /* Use 7bit for the first fake part.  Bit 4-10 */
00563     strecat(buf, _name_norwegian_1[SeedChance(4, lengthof(_name_norwegian_1), seed)], last);
00564     /* Use 7bit for the last fake part.  Bit 11-17 */
00565     strecat(buf, _name_norwegian_2[SeedChance(11, lengthof(_name_norwegian_2), seed)], last);
00566   }
00567 
00568   return 0;
00569 }
00570 
00571 static byte MakeHungarianTownName(char *buf, uint32 seed, const char *last)
00572 {
00573   uint i;
00574 
00575   /* null terminates the string for strcat */
00576   strecpy(buf, "", last);
00577 
00578   if (SeedChance(12, 15, seed) < 3) {
00579     strecat(buf, _name_hungarian_real[SeedChance(0, lengthof(_name_hungarian_real), seed)], last);
00580   } else {
00581     /* optional first segment */
00582     i = SeedChance(3, lengthof(_name_hungarian_1) * 3, seed);
00583     if (i < lengthof(_name_hungarian_1))
00584       strecat(buf, _name_hungarian_1[i], last);
00585 
00586     /* mandatory middle segments */
00587     strecat(buf, _name_hungarian_2[SeedChance(3, lengthof(_name_hungarian_2), seed)], last);
00588     strecat(buf, _name_hungarian_3[SeedChance(6, lengthof(_name_hungarian_3), seed)], last);
00589 
00590     /* optional last segment */
00591     i = SeedChance(10, lengthof(_name_hungarian_4) * 3, seed);
00592     if (i < lengthof(_name_hungarian_4)) {
00593       strecat(buf, _name_hungarian_4[i], last);
00594     }
00595   }
00596 
00597   return 0;
00598 }
00599 
00600 static byte MakeSwissTownName(char *buf, uint32 seed, const char *last)
00601 {
00602   strecpy(buf, _name_swiss_real[SeedChance(0, lengthof(_name_swiss_real), seed)], last);
00603   return 0;
00604 }
00605 
00606 static byte MakeDanishTownName(char *buf, uint32 seed, const char *last)
00607 {
00608   int i;
00609 
00610   /* null terminates the string for strcat */
00611   strecpy(buf, "", last);
00612 
00613   /* optional first segment */
00614   i = SeedChanceBias(0, lengthof(_name_danish_1), seed, 50);
00615   if (i >= 0)
00616     strecat(buf, _name_danish_1[i], last);
00617 
00618   /* middle segments removed as this algorithm seems to create much more realistic names */
00619   strecat(buf, _name_danish_2[SeedChance( 7, lengthof(_name_danish_2), seed)], last);
00620   strecat(buf, _name_danish_3[SeedChance(16, lengthof(_name_danish_3), seed)], last);
00621 
00622   return 0;
00623 }
00624 
00625 static byte MakeTurkishTownName(char *buf, uint32 seed, const char *last)
00626 {
00627   uint i;
00628 
00629   /* null terminates the string for strcat */
00630   strecpy(buf, "", last);
00631 
00632   if ((i = SeedModChance(0, 5, seed)) == 0) {
00633     strecat(buf, _name_turkish_prefix[SeedModChance( 2, lengthof(_name_turkish_prefix), seed)], last);
00634 
00635     /* middle segment */
00636     strecat(buf, _name_turkish_middle[SeedModChance( 4, lengthof(_name_turkish_middle), seed)], last);
00637 
00638     /* optional suffix */
00639     if (SeedModChance(0, 7, seed) == 0) {
00640       strecat(buf, _name_turkish_suffix[SeedModChance( 10, lengthof(_name_turkish_suffix), seed)], last);
00641     }
00642   } else {
00643     if (i == 1 || i == 2) {
00644       strecat(buf, _name_turkish_prefix[SeedModChance( 2, lengthof(_name_turkish_prefix), seed)], last);
00645       strecat(buf, _name_turkish_suffix[SeedModChance( 4, lengthof(_name_turkish_suffix), seed)], last);
00646     } else {
00647       strecat(buf, _name_turkish_real[SeedModChance( 4, lengthof(_name_turkish_real), seed)], last);
00648     }
00649   }
00650   return 0;
00651 }
00652 
00653 static const char *mascul_femin_italian[] = {
00654   "o",
00655   "a",
00656 };
00657 
00658 static byte MakeItalianTownName(char *buf, uint32 seed, const char *last)
00659 {
00660   strecpy(buf, "", last);
00661 
00662   if (SeedModChance(0, 6, seed) == 0) { // real city names
00663     strecat(buf, _name_italian_real[SeedModChance(4, lengthof(_name_italian_real), seed)], last);
00664   } else {
00665     uint i;
00666 
00667     if (SeedModChance(0, 8, seed) == 0) { // prefix
00668       strecat(buf, _name_italian_pref[SeedModChance(11, lengthof(_name_italian_pref), seed)], last);
00669     }
00670 
00671     i = SeedChance(0, 2, seed);
00672     if (i == 0) { // masculine form
00673       strecat(buf, _name_italian_1m[SeedModChance(4, lengthof(_name_italian_1m), seed)], last);
00674     } else { // feminine form
00675       strecat(buf, _name_italian_1f[SeedModChance(4, lengthof(_name_italian_1f), seed)], last);
00676     }
00677 
00678     if (SeedModChance(3, 3, seed) == 0) {
00679       strecat(buf, _name_italian_2[SeedModChance(11, lengthof(_name_italian_2), seed)], last);
00680       strecat(buf, mascul_femin_italian[i], last);
00681     } else {
00682       strecat(buf, _name_italian_2i[SeedModChance(16, lengthof(_name_italian_2i), seed)], last);
00683     }
00684 
00685     if (SeedModChance(15, 4, seed) == 0) {
00686       if (SeedModChance(5, 2, seed) == 0) { // generic suffix
00687         strecat(buf, _name_italian_3[SeedModChance(4, lengthof(_name_italian_3), seed)], last);
00688       } else { // river name suffix
00689         strecat(buf, _name_italian_river1[SeedModChance(4, lengthof(_name_italian_river1), seed)], last);
00690         strecat(buf, _name_italian_river2[SeedModChance(16, lengthof(_name_italian_river2), seed)], last);
00691       }
00692     }
00693   }
00694 
00695   return 0;
00696 }
00697 
00698 static byte MakeCatalanTownName(char *buf, uint32 seed, const char *last)
00699 {
00700   strecpy(buf, "", last);
00701 
00702   if (SeedModChance(0, 3, seed) == 0) { // real city names
00703     strecat(buf, _name_catalan_real[SeedModChance(4, lengthof(_name_catalan_real), seed)], last);
00704   } else {
00705     uint i;
00706 
00707     if (SeedModChance(0, 2, seed) == 0) { // prefix
00708       strecat(buf, _name_catalan_pref[SeedModChance(11, lengthof(_name_catalan_pref), seed)], last);
00709     }
00710 
00711     i = SeedChance(0, 2, seed);
00712     if (i == 0) { // masculine form
00713       strecat(buf, _name_catalan_1m[SeedModChance(4, lengthof(_name_catalan_1m), seed)], last);
00714       strecat(buf, _name_catalan_2m[SeedModChance(11, lengthof(_name_catalan_2m), seed)], last);
00715     } else { // feminine form
00716       strecat(buf, _name_catalan_1f[SeedModChance(4, lengthof(_name_catalan_1f), seed)], last);
00717       strecat(buf, _name_catalan_2f[SeedModChance(11, lengthof(_name_catalan_2f), seed)], last);
00718     }
00719 
00720 
00721     if (SeedModChance(15, 5, seed) == 0) {
00722       if (SeedModChance(5, 2, seed) == 0) { // generic suffix
00723         strecat(buf, _name_catalan_3[SeedModChance(4, lengthof(_name_catalan_3), seed)], last);
00724       } else { // river name suffix
00725         strecat(buf, _name_catalan_river1[SeedModChance(4, lengthof(_name_catalan_river1), seed)], last);
00726       }
00727     }
00728   }
00729 
00730   return 0;
00731 }
00732 
00733 
00734 
00735 TownNameGenerator * const _town_name_generators[] =
00736 {
00737   MakeEnglishOriginalTownName,
00738   MakeFrenchTownName,
00739   MakeGermanTownName,
00740   MakeEnglishAdditionalTownName,
00741   MakeSpanishTownName,
00742   MakeSillyTownName,
00743   MakeSwedishTownName,
00744   MakeDutchTownName,
00745   MakeFinnishTownName,
00746   MakePolishTownName,
00747   MakeSlovakTownName,
00748   MakeNorwegianTownName,
00749   MakeHungarianTownName,
00750   MakeAustrianTownName,
00751   MakeRomanianTownName,
00752   MakeCzechTownName,
00753   MakeSwissTownName,
00754   MakeDanishTownName,
00755   MakeTurkishTownName,
00756   MakeItalianTownName,
00757   MakeCatalanTownName,
00758 };

Generated on Sun Mar 15 22:49:47 2009 for openttd by  doxygen 1.5.6