|
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 } |