src/namegen.cpp
changeset 5835 e0ff603ae0b7
parent 5726 8f399788f6c9
child 6303 84c215fc8eb8
equal deleted inserted replaced
5834:7bf92d5a5a0f 5835:e0ff603ae0b7
       
     1 /* $Id$ */
       
     2 
       
     3 #include "stdafx.h"
       
     4 #include "openttd.h"
       
     5 #include "debug.h"
       
     6 #include "macros.h"
       
     7 #include "namegen.h"
       
     8 #include "table/namegen.h"
       
     9 #include "string.h"
       
    10 
       
    11 static inline uint32 SeedChance(int shift_by, int max, uint32 seed)
       
    12 {
       
    13 	return (GB(seed, shift_by, 16) * max) >> 16;
       
    14 }
       
    15 
       
    16 static inline uint32 SeedModChance(int shift_by, int max, uint32 seed)
       
    17 {
       
    18 	/* This actually gives *MUCH* more even distribution of the values
       
    19 	 * than SeedChance(), which is absolutely horrible in that. If
       
    20 	 * you do not believe me, try with i.e. the Czech town names,
       
    21 	 * compare the words (nicely visible on prefixes) generated by
       
    22 	 * SeedChance() and SeedModChance(). Do not get dicouraged by the
       
    23 	 * never-use-modulo myths, which hold true only for the linear
       
    24 	 * congruential generators (and Random() isn't such a generator).
       
    25 	 * --pasky */
       
    26 	// TODO: Perhaps we should use it for all the name generators? --pasky
       
    27 	return (seed >> shift_by) % max;
       
    28 }
       
    29 
       
    30 static inline int32 SeedChanceBias(int shift_by, int max, uint32 seed, int bias)
       
    31 {
       
    32 	return SeedChance(shift_by, max + bias, seed) - bias;
       
    33 }
       
    34 
       
    35 static void ReplaceWords(const char *org, const char *rep, char *buf)
       
    36 {
       
    37 	if (strncmp(buf, org, 4) == 0) strncpy(buf, rep, 4);
       
    38 }
       
    39 
       
    40 static byte MakeEnglishOriginalTownName(char *buf, uint32 seed, const char *last)
       
    41 {
       
    42 	int i;
       
    43 
       
    44 	//null terminates the string for strcat
       
    45 	strecpy(buf, "", last);
       
    46 
       
    47 	// optional first segment
       
    48 	i = SeedChanceBias(0, lengthof(name_original_english_1), seed, 50);
       
    49 	if (i >= 0)
       
    50 		strecat(buf, name_original_english_1[i], last);
       
    51 
       
    52 	//mandatory middle segments
       
    53 	strecat(buf, name_original_english_2[SeedChance(4,  lengthof(name_original_english_2), seed)], last);
       
    54 	strecat(buf, name_original_english_3[SeedChance(7,  lengthof(name_original_english_3), seed)], last);
       
    55 	strecat(buf, name_original_english_4[SeedChance(10, lengthof(name_original_english_4), seed)], last);
       
    56 	strecat(buf, name_original_english_5[SeedChance(13, lengthof(name_original_english_5), seed)], last);
       
    57 
       
    58 	//optional last segment
       
    59 	i = SeedChanceBias(15, lengthof(name_original_english_6), seed, 60);
       
    60 	if (i >= 0)
       
    61 		strecat(buf, name_original_english_6[i], last);
       
    62 
       
    63 	if (buf[0] == 'C' && (buf[1] == 'e' || buf[1] == 'i'))
       
    64 		buf[0] = 'K';
       
    65 
       
    66 	ReplaceWords("Cunt", "East", buf);
       
    67 	ReplaceWords("Slag", "Pits", buf);
       
    68 	ReplaceWords("Slut", "Edin", buf);
       
    69 	//ReplaceWords("Fart", "Boot", buf);
       
    70 	ReplaceWords("Drar", "Quar", buf);
       
    71 	ReplaceWords("Dreh", "Bash", buf);
       
    72 	ReplaceWords("Frar", "Shor", buf);
       
    73 	ReplaceWords("Grar", "Aber", buf);
       
    74 	ReplaceWords("Brar", "Over", buf);
       
    75 	ReplaceWords("Wrar", "Inve", buf);
       
    76 
       
    77 	return 0;
       
    78 }
       
    79 
       
    80 
       
    81 static byte MakeEnglishAdditionalTownName(char *buf, uint32 seed, const char *last)
       
    82 {
       
    83 	int i;
       
    84 
       
    85 	//null terminates the string for strcat
       
    86 	strecpy(buf, "", last);
       
    87 
       
    88 	// optional first segment
       
    89 	i = SeedChanceBias(0, lengthof(name_additional_english_prefix), seed, 50);
       
    90 	if (i >= 0)
       
    91 		strecat(buf,name_additional_english_prefix[i], last);
       
    92 
       
    93 	if (SeedChance(3, 20, seed) >= 14) {
       
    94 		strecat(buf, name_additional_english_1a[SeedChance(6, lengthof(name_additional_english_1a), seed)], last);
       
    95 	} else {
       
    96 		strecat(buf, name_additional_english_1b1[SeedChance(6, lengthof(name_additional_english_1b1), seed)], last);
       
    97 		strecat(buf, name_additional_english_1b2[SeedChance(9, lengthof(name_additional_english_1b2), seed)], last);
       
    98 		if (SeedChance(11, 20, seed) >= 4) {
       
    99 			strecat(buf, name_additional_english_1b3a[SeedChance(12, lengthof(name_additional_english_1b3a), seed)], last);
       
   100 		} else {
       
   101 			strecat(buf, name_additional_english_1b3b[SeedChance(12, lengthof(name_additional_english_1b3b), seed)], last);
       
   102 		}
       
   103 	}
       
   104 
       
   105 	strecat(buf, name_additional_english_2[SeedChance(14, lengthof(name_additional_english_2), seed)], last);
       
   106 
       
   107 	//optional last segment
       
   108 	i = SeedChanceBias(15, lengthof(name_additional_english_3), seed, 60);
       
   109 	if (i >= 0)
       
   110 		strecat(buf, name_additional_english_3[i], last);
       
   111 
       
   112 	ReplaceWords("Cunt", "East", buf);
       
   113 	ReplaceWords("Slag", "Pits", buf);
       
   114 	ReplaceWords("Slut", "Edin", buf);
       
   115 	ReplaceWords("Fart", "Boot", buf);
       
   116 	ReplaceWords("Drar", "Quar", buf);
       
   117 	ReplaceWords("Dreh", "Bash", buf);
       
   118 	ReplaceWords("Frar", "Shor", buf);
       
   119 	ReplaceWords("Grar", "Aber", buf);
       
   120 	ReplaceWords("Brar", "Over", buf);
       
   121 	ReplaceWords("Wrar", "Stan", buf);
       
   122 
       
   123 	return 0;
       
   124 }
       
   125 
       
   126 static byte MakeAustrianTownName(char *buf, uint32 seed, const char *last)
       
   127 {
       
   128 	int i, j = 0;
       
   129 	strecpy(buf, "", last);
       
   130 
       
   131 	// Bad, Maria, Gross, ...
       
   132 	i = SeedChanceBias(0, lengthof(name_austrian_a1), seed, 15);
       
   133 	if (i >= 0) strecat(buf, name_austrian_a1[i], last);
       
   134 
       
   135 	i = SeedChance(4, 6, seed);
       
   136 	if (i >= 4) {
       
   137 		// Kaisers-kirchen
       
   138 		strecat(buf, name_austrian_a2[SeedChance( 7, lengthof(name_austrian_a2), seed)], last);
       
   139 		strecat(buf, name_austrian_a3[SeedChance(13, lengthof(name_austrian_a3), seed)], last);
       
   140 	} else if (i >= 2) {
       
   141 		// St. Johann
       
   142 		strecat(buf, name_austrian_a5[SeedChance( 7, lengthof(name_austrian_a5), seed)], last);
       
   143 		strecat(buf, name_austrian_a6[SeedChance( 9, lengthof(name_austrian_a6), seed)], last);
       
   144 		j = 1; // More likely to have a " an der " or " am "
       
   145 	} else {
       
   146 		// Zell
       
   147 		strecat(buf, name_austrian_a4[SeedChance( 7, lengthof(name_austrian_a4), seed)], last);
       
   148 	}
       
   149 
       
   150 	i = SeedChance(1, 6, seed);
       
   151 	if (i >= 4 - j) {
       
   152 		// an der Donau (rivers)
       
   153 		strecat(buf, name_austrian_f1[SeedChance(4, lengthof(name_austrian_f1), seed)], last);
       
   154 		strecat(buf, name_austrian_f2[SeedChance(5, lengthof(name_austrian_f2), seed)], last);
       
   155 	} else if (i >= 2 - j) {
       
   156 		// am Dachstein (mountains)
       
   157 		strecat(buf, name_austrian_b1[SeedChance(4, lengthof(name_austrian_b1), seed)], last);
       
   158 		strecat(buf, name_austrian_b2[SeedChance(5, lengthof(name_austrian_b2), seed)], last);
       
   159 	}
       
   160 
       
   161 	return 0;
       
   162 }
       
   163 
       
   164 static byte MakeGermanTownName(char *buf, uint32 seed, const char *last)
       
   165 {
       
   166 	uint i;
       
   167 	uint seed_derivative;
       
   168 
       
   169 	//null terminates the string for strcat
       
   170 	strecpy(buf, "", last);
       
   171 
       
   172 	seed_derivative = SeedChance(7, 28, seed);
       
   173 
       
   174 	//optional prefix
       
   175 	if (seed_derivative == 12 || seed_derivative == 19) {
       
   176 		i = SeedChance(2, lengthof(name_german_pre), seed);
       
   177 		strecat(buf,name_german_pre[i], last);
       
   178 	}
       
   179 
       
   180 	// mandatory middle segments including option of hardcoded name
       
   181 	i = SeedChance(3, lengthof(name_german_real) + lengthof(name_german_1), seed);
       
   182 	if (i < lengthof(name_german_real)) {
       
   183 		strecat(buf,name_german_real[i], last);
       
   184 	} else {
       
   185 		strecat(buf, name_german_1[i - lengthof(name_german_real)], last);
       
   186 
       
   187 		i = SeedChance(5, lengthof(name_german_2), seed);
       
   188 		strecat(buf, name_german_2[i], last);
       
   189 	}
       
   190 
       
   191 	// optional suffix
       
   192 	if (seed_derivative == 24) {
       
   193 		i = SeedChance(9,
       
   194 			lengthof(name_german_4_an_der) + lengthof(name_german_4_am), seed);
       
   195 		if (i < lengthof(name_german_4_an_der)) {
       
   196 			strecat(buf, name_german_3_an_der[0], last);
       
   197 			strecat(buf, name_german_4_an_der[i], last);
       
   198 		} else {
       
   199 			strecat(buf, name_german_3_am[0], last);
       
   200 			strecat(buf, name_german_4_am[i - lengthof(name_german_4_an_der)], last);
       
   201 		}
       
   202 	}
       
   203 	return 0;
       
   204 }
       
   205 
       
   206 static byte MakeSpanishTownName(char *buf, uint32 seed, const char *last)
       
   207 {
       
   208 	strecpy(buf, name_spanish_real[SeedChance(0, lengthof(name_spanish_real), seed)], last);
       
   209 	return 0;
       
   210 }
       
   211 
       
   212 static byte MakeFrenchTownName(char *buf, uint32 seed, const char *last)
       
   213 {
       
   214 	strecpy(buf, name_french_real[SeedChance(0, lengthof(name_french_real), seed)], last);
       
   215 	return 0;
       
   216 }
       
   217 
       
   218 static byte MakeSillyTownName(char *buf, uint32 seed, const char *last)
       
   219 {
       
   220 	strecpy(buf, name_silly_1[SeedChance( 0, lengthof(name_silly_1), seed)], last);
       
   221 	strecat(buf, name_silly_2[SeedChance(16, lengthof(name_silly_2), seed)], last);
       
   222 	return 0;
       
   223 }
       
   224 
       
   225 static byte MakeSwedishTownName(char *buf, uint32 seed, const char *last)
       
   226 {
       
   227 	int i;
       
   228 
       
   229 	//null terminates the string for strcat
       
   230 	strecpy(buf, "", last);
       
   231 
       
   232 	// optional first segment
       
   233 	i = SeedChanceBias(0, lengthof(name_swedish_1), seed, 50);
       
   234 	if (i >= 0)
       
   235 		strecat(buf, name_swedish_1[i], last);
       
   236 
       
   237 	// mandatory middle segments including option of hardcoded name
       
   238 	if (SeedChance(4, 5, seed) >= 3) {
       
   239 		strecat(buf, name_swedish_2[SeedChance( 7, lengthof(name_swedish_2), seed)], last);
       
   240 	} else {
       
   241 		strecat(buf, name_swedish_2a[SeedChance( 7, lengthof(name_swedish_2a), seed)], last);
       
   242 		strecat(buf, name_swedish_2b[SeedChance(10, lengthof(name_swedish_2b), seed)], last);
       
   243 		strecat(buf, name_swedish_2c[SeedChance(13, lengthof(name_swedish_2c), seed)], last);
       
   244 	}
       
   245 
       
   246 	strecat(buf, name_swedish_3[SeedChance(16, lengthof(name_swedish_3), seed)], last);
       
   247 
       
   248 	return 0;
       
   249 }
       
   250 
       
   251 static byte MakeDutchTownName(char *buf, uint32 seed, const char *last)
       
   252 {
       
   253 	int i;
       
   254 
       
   255 	//null terminates the string for strcat
       
   256 	strecpy(buf, "", last);
       
   257 
       
   258 	// optional first segment
       
   259 	i = SeedChanceBias(0, lengthof(name_dutch_1), seed, 50);
       
   260 	if (i >= 0)
       
   261 		strecat(buf, name_dutch_1[i], last);
       
   262 
       
   263 	// mandatory middle segments including option of hardcoded name
       
   264 	if (SeedChance(6, 9, seed) > 4) {
       
   265 		strecat(buf, name_dutch_2[SeedChance( 9, lengthof(name_dutch_2), seed)], last);
       
   266 	} else {
       
   267 		strecat(buf, name_dutch_3[SeedChance( 9, lengthof(name_dutch_3), seed)], last);
       
   268 		strecat(buf, name_dutch_4[SeedChance(12, lengthof(name_dutch_4), seed)], last);
       
   269 	}
       
   270 	strecat(buf, name_dutch_5[SeedChance(15, lengthof(name_dutch_5), seed)], last);
       
   271 
       
   272 	return 0;
       
   273 }
       
   274 
       
   275 static byte MakeFinnishTownName(char *buf, uint32 seed, const char *last)
       
   276 {
       
   277 	//null terminates the string for strcat
       
   278 	strecpy(buf, "", last);
       
   279 
       
   280 	// Select randomly if town name should consists of one or two parts.
       
   281 	if (SeedChance(0, 15, seed) >= 10) {
       
   282 		strecat(buf, name_finnish_real[SeedChance(2, lengthof(name_finnish_real), seed)], last);
       
   283 	} else if (SeedChance(0, 15, seed) >= 5) {
       
   284 		// A two-part name by combining one of name_finnish_1 + "la"/"lä"
       
   285 		// The reason for not having the contents of name_finnish_{1,2} in the same table is
       
   286 		// that the ones in name_finnish_2 are not good for this purpose.
       
   287 		uint sel = SeedChance( 0, lengthof(name_finnish_1), seed);
       
   288 		char *end;
       
   289 		strecat(buf, name_finnish_1[sel], last);
       
   290 		end = &buf[strlen(buf)-1];
       
   291 		if (*end == 'i')
       
   292 			*end = 'e';
       
   293 		if (strstr(buf, "a") || strstr(buf, "o") || strstr(buf, "u") ||
       
   294 			strstr(buf, "A") || strstr(buf, "O") || strstr(buf, "U"))
       
   295 		{
       
   296 			strecat(buf, "la", last);
       
   297 		} else {
       
   298 			strecat(buf, "lä", last);
       
   299 		}
       
   300 	} else {
       
   301 		// A two-part name by combining one of name_finnish_{1,2} + name_finnish_3.
       
   302 		// Why aren't name_finnish_{1,2} just one table? See above.
       
   303 		uint sel = SeedChance(2,
       
   304 			lengthof(name_finnish_1) + lengthof(name_finnish_2), seed);
       
   305 		if (sel >= lengthof(name_finnish_1)) {
       
   306 			strecat(buf, name_finnish_2[sel-lengthof(name_finnish_1)], last);
       
   307 		} else {
       
   308 			strecat(buf, name_finnish_1[sel], last);
       
   309 		}
       
   310 		strecat(buf, name_finnish_3[SeedChance(10, lengthof(name_finnish_3), seed)], last);
       
   311 	}
       
   312 
       
   313 	return 0;
       
   314 }
       
   315 
       
   316 static byte MakePolishTownName(char *buf, uint32 seed, const char *last)
       
   317 {
       
   318 	uint i;
       
   319 	uint j;
       
   320 
       
   321 	//null terminates the string for strcat
       
   322 	strecpy(buf, "", last);
       
   323 
       
   324 	// optional first segment
       
   325 	i = SeedChance(0,
       
   326 		lengthof(name_polish_2_o) + lengthof(name_polish_2_m) +
       
   327 		lengthof(name_polish_2_f) + lengthof(name_polish_2_n),
       
   328 		seed);
       
   329 	j = SeedChance(2, 20, seed);
       
   330 
       
   331 
       
   332 	if (i < lengthof(name_polish_2_o)) {
       
   333 		strecat(buf, name_polish_2_o[SeedChance(3, lengthof(name_polish_2_o), seed)], last);
       
   334 	} else if (i < lengthof(name_polish_2_m) + lengthof(name_polish_2_o)) {
       
   335 		if (j < 4)
       
   336 			strecat(buf, name_polish_1_m[SeedChance(5, lengthof(name_polish_1_m), seed)], last);
       
   337 
       
   338 		strecat(buf, name_polish_2_m[SeedChance(7, lengthof(name_polish_2_m), seed)], last);
       
   339 
       
   340 		if (j >= 4 && j < 16)
       
   341 			strecat(buf, name_polish_3_m[SeedChance(10, lengthof(name_polish_3_m), seed)], last);
       
   342 	} else if (i < lengthof(name_polish_2_f) + lengthof(name_polish_2_m) + lengthof(name_polish_2_o)) {
       
   343 		if (j < 4)
       
   344 			strecat(buf, name_polish_1_f[SeedChance(5, lengthof(name_polish_1_f), seed)], last);
       
   345 
       
   346 		strecat(buf, name_polish_2_f[SeedChance(7, lengthof(name_polish_2_f), seed)], last);
       
   347 
       
   348 		if (j >= 4 && j < 16)
       
   349 			strecat(buf, name_polish_3_f[SeedChance(10, lengthof(name_polish_3_f), seed)], last);
       
   350 	} else {
       
   351 		if (j < 4)
       
   352 			strecat(buf, name_polish_1_n[SeedChance(5, lengthof(name_polish_1_n), seed)], last);
       
   353 
       
   354 		strecat(buf, name_polish_2_n[SeedChance(7, lengthof(name_polish_2_n), seed)], last);
       
   355 
       
   356 		if (j >= 4 && j < 16)
       
   357 			strecat(buf, name_polish_3_n[SeedChance(10, lengthof(name_polish_3_n), seed)], last);
       
   358 	}
       
   359 	return 0;
       
   360 }
       
   361 
       
   362 static byte MakeCzechTownName(char *buf, uint32 seed, const char *last)
       
   363 {
       
   364 	/* Probability of prefixes/suffixes */
       
   365 	/* 0..11 prefix, 12..13 prefix+suffix, 14..17 suffix, 18..31 nothing */
       
   366 	int prob_tails;
       
   367 	bool do_prefix, do_suffix, dynamic_subst;
       
   368 	/* IDs of the respective parts */
       
   369 	int prefix = 0, ending = 0, suffix = 0;
       
   370 	uint postfix = 0;
       
   371 	uint stem;
       
   372 	/* The select criteria. */
       
   373 	CzechGender gender;
       
   374 	CzechChoose choose;
       
   375 	CzechAllow allow;
       
   376 
       
   377 	// 1:3 chance to use a real name.
       
   378 	if (SeedModChance(0, 4, seed) == 0) {
       
   379 		strecpy(buf, name_czech_real[SeedModChance(4, lengthof(name_czech_real), seed)], last);
       
   380 		return 0;
       
   381 	}
       
   382 
       
   383 	// NUL terminates the string for strcat()
       
   384 	strecpy(buf, "", last);
       
   385 
       
   386 	prob_tails = SeedModChance(2, 32, seed);
       
   387 	do_prefix = prob_tails < 12;
       
   388 	do_suffix = prob_tails > 11 && prob_tails < 17;
       
   389 
       
   390 	if (do_prefix) prefix = SeedModChance(5, lengthof(name_czech_adj) * 12, seed) / 12;
       
   391 	if (do_suffix) suffix = SeedModChance(7, lengthof(name_czech_suffix), seed);
       
   392 	// 3:1 chance 3:1 to use dynamic substantive
       
   393 	stem = SeedModChance(9,
       
   394 		lengthof(name_czech_subst_full) + 3 * lengthof(name_czech_subst_stem),
       
   395 		seed);
       
   396 	if (stem < lengthof(name_czech_subst_full)) {
       
   397 		// That was easy!
       
   398 		dynamic_subst = false;
       
   399 		gender = name_czech_subst_full[stem].gender;
       
   400 		choose = name_czech_subst_full[stem].choose;
       
   401 		allow = name_czech_subst_full[stem].allow;
       
   402 	} else {
       
   403 		unsigned int map[lengthof(name_czech_subst_ending)];
       
   404 		int ending_start = -1, ending_stop = -1;
       
   405 		int i;
       
   406 
       
   407 		// Load the substantive
       
   408 		dynamic_subst = true;
       
   409 		stem -= lengthof(name_czech_subst_full);
       
   410 		stem %= lengthof(name_czech_subst_stem);
       
   411 		gender = name_czech_subst_stem[stem].gender;
       
   412 		choose = name_czech_subst_stem[stem].choose;
       
   413 		allow = name_czech_subst_stem[stem].allow;
       
   414 
       
   415 		// Load the postfix (1:1 chance that a postfix will be inserted)
       
   416 		postfix = SeedModChance(14, lengthof(name_czech_subst_postfix) * 2, seed);
       
   417 
       
   418 		if (choose & CZC_POSTFIX) {
       
   419 			// Always get a real postfix.
       
   420 			postfix %= lengthof(name_czech_subst_postfix);
       
   421 		}
       
   422 		if (choose & CZC_NOPOSTFIX) {
       
   423 			// Always drop a postfix.
       
   424 			postfix += lengthof(name_czech_subst_postfix);
       
   425 		}
       
   426 		if (postfix < lengthof(name_czech_subst_postfix)) {
       
   427 			choose |= CZC_POSTFIX;
       
   428 		} else {
       
   429 			choose |= CZC_NOPOSTFIX;
       
   430 		}
       
   431 
       
   432 		// Localize the array segment containing a good gender
       
   433 		for (ending = 0; ending < (int) lengthof(name_czech_subst_ending); ending++) {
       
   434 			const CzechNameSubst *e = &name_czech_subst_ending[ending];
       
   435 
       
   436 			if (gender == CZG_FREE ||
       
   437 					(gender == CZG_NFREE && e->gender != CZG_SNEUT && e->gender != CZG_PNEUT) ||
       
   438 					gender == e->gender) {
       
   439 				if (ending_start < 0)
       
   440 					ending_start = ending;
       
   441 
       
   442 			} else if (ending_start >= 0) {
       
   443 				ending_stop = ending - 1;
       
   444 				break;
       
   445 			}
       
   446 		}
       
   447 		if (ending_stop < 0) {
       
   448 			// Whoa. All the endings matched.
       
   449 			ending_stop = ending - 1;
       
   450 		}
       
   451 
       
   452 		// Make a sequential map of the items with good mask
       
   453 		i = 0;
       
   454 		for (ending = ending_start; ending <= ending_stop; ending++) {
       
   455 			const CzechNameSubst *e = &name_czech_subst_ending[ending];
       
   456 
       
   457 			if ((e->choose & choose) == choose && (e->allow & allow) != 0)
       
   458 				map[i++] = ending;
       
   459 		}
       
   460 		assert(i > 0);
       
   461 
       
   462 		// Load the ending
       
   463 		ending = map[SeedModChance(16, i, seed)];
       
   464 		// Override possible CZG_*FREE; this must be a real gender,
       
   465 		// otherwise we get overflow when modifying the adjectivum.
       
   466 		gender = name_czech_subst_ending[ending].gender;
       
   467 		assert(gender != CZG_FREE && gender != CZG_NFREE);
       
   468 	}
       
   469 
       
   470 	if (do_prefix && (name_czech_adj[prefix].choose & choose) != choose) {
       
   471 		// Throw away non-matching prefix.
       
   472 		do_prefix = false;
       
   473 	}
       
   474 
       
   475 	// Now finally construct the name
       
   476 
       
   477 	if (do_prefix) {
       
   478 		CzechPattern pattern = name_czech_adj[prefix].pattern;
       
   479 		size_t endpos;
       
   480 
       
   481 		strecat(buf, name_czech_adj[prefix].name, last);
       
   482 		endpos = strlen(buf) - 1;
       
   483 		/* Find the first character in a UTF-8 sequence */
       
   484 		while (GB(buf[endpos], 6, 2) == 2) endpos--;
       
   485 		if (gender == CZG_SMASC && pattern == CZP_PRIVL) {
       
   486 			/* -ovX -> -uv */
       
   487 			buf[endpos - 2] = 'u';
       
   488 			assert(buf[endpos - 1] == 'v');
       
   489 			buf[endpos] = '\0';
       
   490 		} else {
       
   491 			strecpy(buf + endpos, name_czech_patmod[gender][pattern], last);
       
   492 		}
       
   493 
       
   494 		strecat(buf, " ", last);
       
   495 	}
       
   496 
       
   497 	if (dynamic_subst) {
       
   498 		strecat(buf, name_czech_subst_stem[stem].name, last);
       
   499 		if (postfix < lengthof(name_czech_subst_postfix)) {
       
   500 			const char *poststr = name_czech_subst_postfix[postfix];
       
   501 			const char *endstr = name_czech_subst_ending[ending].name;
       
   502 			size_t postlen, endlen;
       
   503 
       
   504 			postlen = strlen(poststr);
       
   505 			endlen = strlen(endstr);
       
   506 			assert(postlen > 0 && endlen > 0);
       
   507 
       
   508 			// Kill the "avava" and "Jananna"-like cases
       
   509 			if (postlen < 2 || postlen > endlen || (
       
   510 						(poststr[1] != 'v' || poststr[1] != endstr[1]) &&
       
   511 						poststr[2] != endstr[1])
       
   512 					) {
       
   513 				size_t buflen;
       
   514 				strecat(buf, poststr, last);
       
   515 				buflen = strlen(buf);
       
   516 
       
   517 				// k-i -> c-i, h-i -> z-i
       
   518 				if (endstr[0] == 'i') {
       
   519 					switch (buf[buflen - 1]) {
       
   520 						case 'k': buf[buflen - 1] = 'c'; break;
       
   521 						case 'h': buf[buflen - 1] = 'z'; break;
       
   522 						default: break;
       
   523 					}
       
   524 				}
       
   525 			}
       
   526 		}
       
   527 		strecat(buf, name_czech_subst_ending[ending].name, last);
       
   528 	} else {
       
   529 		strecat(buf, name_czech_subst_full[stem].name, last);
       
   530 	}
       
   531 
       
   532 	if (do_suffix) {
       
   533 		strecat(buf, " ", last);
       
   534 		strecat(buf, name_czech_suffix[suffix], last);
       
   535 	}
       
   536 
       
   537 	return 0;
       
   538 }
       
   539 
       
   540 static byte MakeRomanianTownName(char *buf, uint32 seed, const char *last)
       
   541 {
       
   542 	strecpy(buf, name_romanian_real[SeedChance(0, lengthof(name_romanian_real), seed)], last);
       
   543 	return 0;
       
   544 }
       
   545 
       
   546 static byte MakeSlovakTownName(char *buf, uint32 seed, const char *last)
       
   547 {
       
   548 	strecpy(buf, name_slovak_real[SeedChance(0, lengthof(name_slovak_real), seed)], last);
       
   549 	return 0;
       
   550 }
       
   551 
       
   552 static byte MakeNorwegianTownName(char *buf, uint32 seed, const char *last)
       
   553 {
       
   554 	strecpy(buf, "", last);
       
   555 
       
   556 	// Use first 4 bit from seed to decide whether or not this town should
       
   557 	// have a real name 3/16 chance.  Bit 0-3
       
   558 	if (SeedChance(0, 15, seed) < 3) {
       
   559 		// Use 7bit for the realname table index.  Bit 4-10
       
   560 		strecat(buf, name_norwegian_real[SeedChance(4, lengthof(name_norwegian_real), seed)], last);
       
   561 	} else {
       
   562 		// Use 7bit for the first fake part.  Bit 4-10
       
   563 		strecat(buf, name_norwegian_1[SeedChance(4, lengthof(name_norwegian_1), seed)], last);
       
   564 		// Use 7bit for the last fake part.  Bit 11-17
       
   565 		strecat(buf, name_norwegian_2[SeedChance(11, lengthof(name_norwegian_2), seed)], last);
       
   566 	}
       
   567 
       
   568 	return 0;
       
   569 }
       
   570 
       
   571 static byte MakeHungarianTownName(char *buf, uint32 seed, const char *last)
       
   572 {
       
   573 	uint i;
       
   574 
       
   575 	//null terminates the string for strcat
       
   576 	strecpy(buf, "", last);
       
   577 
       
   578 	if (SeedChance(12, 15, seed) < 3) {
       
   579 		strecat(buf, name_hungarian_real[SeedChance(0, lengthof(name_hungarian_real), seed)], last);
       
   580 	} else {
       
   581 		// optional first segment
       
   582 		i = SeedChance(3, lengthof(name_hungarian_1) * 3, seed);
       
   583 		if (i < lengthof(name_hungarian_1))
       
   584 			strecat(buf, name_hungarian_1[i], last);
       
   585 
       
   586 		// mandatory middle segments
       
   587 		strecat(buf, name_hungarian_2[SeedChance(3, lengthof(name_hungarian_2), seed)], last);
       
   588 		strecat(buf, name_hungarian_3[SeedChance(6, lengthof(name_hungarian_3), seed)], last);
       
   589 
       
   590 		// optional last segment
       
   591 		i = SeedChance(10, lengthof(name_hungarian_4) * 3, seed);
       
   592 		if (i < lengthof(name_hungarian_4)) {
       
   593 			strecat(buf, name_hungarian_4[i], last);
       
   594 		}
       
   595 	}
       
   596 
       
   597 	return 0;
       
   598 }
       
   599 
       
   600 static byte MakeSwissTownName(char *buf, uint32 seed, const char *last)
       
   601 {
       
   602 	strecpy(buf, name_swiss_real[SeedChance(0, lengthof(name_swiss_real), seed)], last);
       
   603 	return 0;
       
   604 }
       
   605 
       
   606 static byte MakeDanishTownName(char *buf, uint32 seed, const char *last)
       
   607 {
       
   608 	int i;
       
   609 
       
   610 	// null terminates the string for strcat
       
   611 	strecpy(buf, "", last);
       
   612 
       
   613 	// optional first segment
       
   614 	i = SeedChanceBias(0, lengthof(name_danish_1), seed, 50);
       
   615 	if (i >= 0)
       
   616 		strecat(buf, name_danish_1[i], last);
       
   617 
       
   618 	// middle segments removed as this algorithm seems to create much more realistic names
       
   619 	strecat(buf, name_danish_2[SeedChance( 7, lengthof(name_danish_2), seed)], last);
       
   620 	strecat(buf, name_danish_3[SeedChance(16, lengthof(name_danish_3), seed)], last);
       
   621 
       
   622 	return 0;
       
   623 }
       
   624 
       
   625 static byte MakeTurkishTownName(char *buf, uint32 seed, const char *last)
       
   626 {
       
   627 	uint i;
       
   628 
       
   629 	// null terminates the string for strcat
       
   630 	strecpy(buf, "", last);
       
   631 
       
   632 	if ((i = SeedModChance(0, 5, seed)) == 0) {
       
   633 		strecat(buf, name_turkish_prefix[SeedModChance( 2, lengthof(name_turkish_prefix), seed)], last);
       
   634 
       
   635 		// middle segment
       
   636 		strecat(buf, name_turkish_middle[SeedModChance( 4, lengthof(name_turkish_middle), seed)], last);
       
   637 
       
   638 		// optional suffix
       
   639 		if (SeedModChance(0, 7, seed) == 0) {
       
   640 			strecat(buf, name_turkish_suffix[SeedModChance( 10, lengthof(name_turkish_suffix), seed)], last);
       
   641 		}
       
   642 	} else {
       
   643 		if (i == 1 || i == 2) {
       
   644 			strecat(buf, name_turkish_prefix[SeedModChance( 2, lengthof(name_turkish_prefix), seed)], last);
       
   645 			strecat(buf, name_turkish_suffix[SeedModChance( 4, lengthof(name_turkish_suffix), seed)], last);
       
   646 		} else {
       
   647 			strecat(buf, name_turkish_real[SeedModChance( 4, lengthof(name_turkish_real), seed)], last);
       
   648 		}
       
   649 	}
       
   650 	return 0;
       
   651 }
       
   652 
       
   653 static const char *mascul_femin_italian[] = {
       
   654 	"o",
       
   655 	"a",
       
   656 };
       
   657 
       
   658 static byte MakeItalianTownName(char *buf, uint32 seed, const char *last)
       
   659 {
       
   660 	strecpy(buf, "", last);
       
   661 
       
   662 	if (SeedModChance(0, 6, seed) == 0) { // real city names
       
   663 		strecat(buf, name_italian_real[SeedModChance(4, lengthof(name_italian_real), seed)], last);
       
   664 	} else {
       
   665 		uint i;
       
   666 
       
   667 		if (SeedModChance(0, 8, seed) == 0) { // prefix
       
   668 			strecat(buf, name_italian_pref[SeedModChance(11, lengthof(name_italian_pref), seed)], last);
       
   669 		}
       
   670 
       
   671 		i = SeedChance(0, 2, seed);
       
   672 		if (i == 0) { // masculine form
       
   673 			strecat(buf, name_italian_1m[SeedModChance(4, lengthof(name_italian_1m), seed)], last);
       
   674 		} else { // feminine form
       
   675 			strecat(buf, name_italian_1f[SeedModChance(4, lengthof(name_italian_1f), seed)], last);
       
   676 		}
       
   677 
       
   678 		if (SeedModChance(3, 3, seed) == 0) {
       
   679 			strecat(buf, name_italian_2[SeedModChance(11, lengthof(name_italian_2), seed)], last);
       
   680 			strecat(buf,mascul_femin_italian[i], last);
       
   681 		} else {
       
   682 			strecat(buf, name_italian_2i[SeedModChance(16, lengthof(name_italian_2i), seed)], last);
       
   683 		}
       
   684 
       
   685 		if (SeedModChance(15, 4, seed) == 0) {
       
   686 			if (SeedModChance(5, 2, seed) == 0) { // generic suffix
       
   687 				strecat(buf, name_italian_3[SeedModChance(4, lengthof(name_italian_3), seed)], last);
       
   688 			} else { // river name suffix
       
   689 				strecat(buf, name_italian_river1[SeedModChance(4, lengthof(name_italian_river1), seed)], last);
       
   690 				strecat(buf, name_italian_river2[SeedModChance(16, lengthof(name_italian_river2), seed)], last);
       
   691 			}
       
   692 		}
       
   693 	}
       
   694 
       
   695 	return 0;
       
   696 }
       
   697 
       
   698 static byte MakeCatalanTownName(char *buf, uint32 seed, const char *last)
       
   699 {
       
   700 	strecpy(buf, "", last);
       
   701 
       
   702 	if (SeedModChance(0, 3, seed) == 0) { // real city names
       
   703 		strecat(buf, name_catalan_real[SeedModChance(4, lengthof(name_catalan_real), seed)], last);
       
   704 	} else {
       
   705 		uint i;
       
   706 
       
   707 		if (SeedModChance(0, 2, seed) == 0) { // prefix
       
   708 			strecat(buf, name_catalan_pref[SeedModChance(11, lengthof(name_catalan_pref), seed)], last);
       
   709 		}
       
   710 
       
   711 		i = SeedChance(0, 2, seed);
       
   712 		if (i == 0) { // masculine form
       
   713 			strecat(buf, name_catalan_1m[SeedModChance(4, lengthof(name_catalan_1m), seed)], last);
       
   714 			strecat(buf, name_catalan_2m[SeedModChance(11, lengthof(name_catalan_2m), seed)], last);
       
   715 		} else { // feminine form
       
   716 			strecat(buf, name_catalan_1f[SeedModChance(4, lengthof(name_catalan_1f), seed)], last);
       
   717 			strecat(buf, name_catalan_2f[SeedModChance(11, lengthof(name_catalan_2f), seed)], last);
       
   718 		}
       
   719 
       
   720 
       
   721 		if (SeedModChance(15, 5, seed) == 0) {
       
   722 			if (SeedModChance(5, 2, seed) == 0) { // generic suffix
       
   723 				strecat(buf, name_catalan_3[SeedModChance(4, lengthof(name_catalan_3), seed)], last);
       
   724 			} else { // river name suffix
       
   725 				strecat(buf, name_catalan_river1[SeedModChance(4, lengthof(name_catalan_river1), seed)], last);
       
   726 			}
       
   727 		}
       
   728 	}
       
   729 
       
   730 	return 0;
       
   731 }
       
   732 
       
   733 
       
   734 
       
   735 TownNameGenerator * const _town_name_generators[] =
       
   736 {
       
   737 	MakeEnglishOriginalTownName,
       
   738 	MakeFrenchTownName,
       
   739 	MakeGermanTownName,
       
   740 	MakeEnglishAdditionalTownName,
       
   741 	MakeSpanishTownName,
       
   742 	MakeSillyTownName,
       
   743 	MakeSwedishTownName,
       
   744 	MakeDutchTownName,
       
   745 	MakeFinnishTownName,
       
   746 	MakePolishTownName,
       
   747 	MakeSlovakTownName,
       
   748 	MakeNorwegianTownName,
       
   749 	MakeHungarianTownName,
       
   750 	MakeAustrianTownName,
       
   751 	MakeRomanianTownName,
       
   752 	MakeCzechTownName,
       
   753 	MakeSwissTownName,
       
   754 	MakeDanishTownName,
       
   755 	MakeTurkishTownName,
       
   756 	MakeItalianTownName,
       
   757 	MakeCatalanTownName,
       
   758 };
       
   759 
       
   760 // DO WE NEED THIS ANY MORE?
       
   761 #define FIXNUM(x, y, z) (((((x) << 16) / (y)) + 1) << z)
       
   762 
       
   763 uint32 GetOldTownName(uint32 townnameparts, byte old_town_name_type)
       
   764 {
       
   765 	switch (old_town_name_type) {
       
   766 		case 0: case 3: /* English, American */
       
   767 			/* Already OK */
       
   768 			return townnameparts;
       
   769 
       
   770 		case 1: /* French */
       
   771 			/* For some reason 86 needs to be subtracted from townnameparts
       
   772 			 * 0000 0000 0000 0000 0000 0000 1111 1111 */
       
   773 			return FIXNUM(townnameparts - 86, lengthof(name_french_real), 0);
       
   774 
       
   775 		case 2: /* German */
       
   776 			DEBUG(misc, 0, "German Townnames are buggy (%d)", townnameparts);
       
   777 			return townnameparts;
       
   778 
       
   779 		case 4: /* Latin-American */
       
   780 			/* 0000 0000 0000 0000 0000 0000 1111 1111 */
       
   781 			return FIXNUM(townnameparts, lengthof(name_spanish_real), 0);
       
   782 
       
   783 		case 5: /* Silly */
       
   784 			/* NUM_SILLY_1 - lower 16 bits
       
   785 			 * NUM_SILLY_2 - upper 16 bits without leading 1 (first 8 bytes)
       
   786 			 * 1000 0000 2222 2222 0000 0000 1111 1111 */
       
   787 			return FIXNUM(townnameparts, lengthof(name_silly_1), 0) | FIXNUM(GB(townnameparts, 16, 8), lengthof(name_silly_2), 16);
       
   788 	}
       
   789 	return 0;
       
   790 }