mirror of https://github.com/OpenTTD/OpenTTD
(svn r15741) -Fix (r15740): czech town name generator needs very long buffer, use different min size for each generator
parent
38056dabdf
commit
cabf57b221
|
@ -5,6 +5,7 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "namegen_func.h"
|
#include "namegen_func.h"
|
||||||
#include "string_func.h"
|
#include "string_func.h"
|
||||||
|
#include "core/alloc_func.hpp"
|
||||||
|
|
||||||
#include "table/namegen.h"
|
#include "table/namegen.h"
|
||||||
|
|
||||||
|
@ -157,7 +158,6 @@ static char *MakeEnglishAdditionalTownName(char *buf, const char *last, uint32 s
|
||||||
i = SeedChanceBias(15, lengthof(_name_additional_english_3), seed, 60);
|
i = SeedChanceBias(15, lengthof(_name_additional_english_3), seed, 60);
|
||||||
if (i >= 0) buf = strecpy(buf, _name_additional_english_3[i], last);
|
if (i >= 0) buf = strecpy(buf, _name_additional_english_3[i], last);
|
||||||
|
|
||||||
|
|
||||||
assert(buf - orig >= 4);
|
assert(buf - orig >= 4);
|
||||||
ReplaceEnglishWords(orig, false);
|
ReplaceEnglishWords(orig, false);
|
||||||
|
|
||||||
|
@ -462,29 +462,29 @@ static char *MakePolishTownName(char *buf, const char *last, uint32 seed)
|
||||||
*/
|
*/
|
||||||
static char *MakeCzechTownName(char *buf, const char *last, uint32 seed)
|
static char *MakeCzechTownName(char *buf, const char *last, uint32 seed)
|
||||||
{
|
{
|
||||||
const char *orig = buf;
|
|
||||||
|
|
||||||
/* Probability of prefixes/suffixes
|
|
||||||
* 0..11 prefix, 12..13 prefix+suffix, 14..17 suffix, 18..31 nothing */
|
|
||||||
int prob_tails;
|
|
||||||
bool do_prefix, do_suffix, dynamic_subst;
|
|
||||||
/* IDs of the respective parts */
|
|
||||||
int prefix = 0, ending = 0, suffix = 0;
|
|
||||||
uint postfix = 0;
|
|
||||||
uint stem;
|
|
||||||
/* The select criteria. */
|
|
||||||
CzechGender gender;
|
|
||||||
CzechChoose choose;
|
|
||||||
CzechAllow allow;
|
|
||||||
|
|
||||||
/* 1:3 chance to use a real name. */
|
/* 1:3 chance to use a real name. */
|
||||||
if (SeedModChance(0, 4, seed) == 0) {
|
if (SeedModChance(0, 4, seed) == 0) {
|
||||||
return strecpy(buf, _name_czech_real[SeedModChance(4, lengthof(_name_czech_real), seed)], last);
|
return strecpy(buf, _name_czech_real[SeedModChance(4, lengthof(_name_czech_real), seed)], last);
|
||||||
}
|
}
|
||||||
|
|
||||||
prob_tails = SeedModChance(2, 32, seed);
|
const char *orig = buf;
|
||||||
do_prefix = prob_tails < 12;
|
|
||||||
do_suffix = prob_tails > 11 && prob_tails < 17;
|
/* Probability of prefixes/suffixes
|
||||||
|
* 0..11 prefix, 12..13 prefix+suffix, 14..17 suffix, 18..31 nothing */
|
||||||
|
int prob_tails = SeedModChance(2, 32, seed);
|
||||||
|
bool do_prefix = prob_tails < 12;
|
||||||
|
bool do_suffix = prob_tails > 11 && prob_tails < 17;
|
||||||
|
bool dynamic_subst;
|
||||||
|
|
||||||
|
/* IDs of the respective parts */
|
||||||
|
int prefix = 0, ending = 0, suffix = 0;
|
||||||
|
uint postfix = 0;
|
||||||
|
uint stem;
|
||||||
|
|
||||||
|
/* The select criteria. */
|
||||||
|
CzechGender gender;
|
||||||
|
CzechChoose choose;
|
||||||
|
CzechAllow allow;
|
||||||
|
|
||||||
if (do_prefix) prefix = SeedModChance(5, lengthof(_name_czech_adj) * 12, seed) / 12;
|
if (do_prefix) prefix = SeedModChance(5, lengthof(_name_czech_adj) * 12, seed) / 12;
|
||||||
if (do_suffix) suffix = SeedModChance(7, lengthof(_name_czech_suffix), seed);
|
if (do_suffix) suffix = SeedModChance(7, lengthof(_name_czech_suffix), seed);
|
||||||
|
@ -869,29 +869,35 @@ static char *MakeCatalanTownName(char *buf, const char *last, uint32 seed)
|
||||||
|
|
||||||
typedef char *TownNameGenerator(char *buf, const char *last, uint32 seed);
|
typedef char *TownNameGenerator(char *buf, const char *last, uint32 seed);
|
||||||
|
|
||||||
|
/** Contains pointer to generator and minimum buffer size (not incl. terminating '\0') */
|
||||||
|
struct TownNameGeneratorParams {
|
||||||
|
byte min; ///< minimum number of characters that need to be printed for generator to work correctly
|
||||||
|
TownNameGenerator *proc; ///< generator itself
|
||||||
|
};
|
||||||
|
|
||||||
/** Town name generators */
|
/** Town name generators */
|
||||||
static TownNameGenerator * const _town_name_generators[] = {
|
static const TownNameGeneratorParams _town_name_generators[] = {
|
||||||
MakeEnglishOriginalTownName,
|
{ 4, MakeEnglishOriginalTownName}, // replaces first 4 characters of name
|
||||||
MakeFrenchTownName,
|
{ 0, MakeFrenchTownName},
|
||||||
MakeGermanTownName,
|
{ 0, MakeGermanTownName},
|
||||||
MakeEnglishAdditionalTownName,
|
{ 4, MakeEnglishAdditionalTownName}, // replaces first 4 characters of name
|
||||||
MakeSpanishTownName,
|
{ 0, MakeSpanishTownName},
|
||||||
MakeSillyTownName,
|
{ 0, MakeSillyTownName},
|
||||||
MakeSwedishTownName,
|
{ 0, MakeSwedishTownName},
|
||||||
MakeDutchTownName,
|
{ 0, MakeDutchTownName},
|
||||||
MakeFinnishTownName,
|
{ 8, MakeFinnishTownName}, // _name_finnish_1
|
||||||
MakePolishTownName,
|
{ 0, MakePolishTownName},
|
||||||
MakeSlovakTownName,
|
{ 0, MakeSlovakTownName},
|
||||||
MakeNorwegianTownName,
|
{ 0, MakeNorwegianTownName},
|
||||||
MakeHungarianTownName,
|
{ 0, MakeHungarianTownName},
|
||||||
MakeAustrianTownName,
|
{ 0, MakeAustrianTownName},
|
||||||
MakeRomanianTownName,
|
{ 0, MakeRomanianTownName},
|
||||||
MakeCzechTownName,
|
{ 28, MakeCzechTownName}, // _name_czech_adj + _name_czech_patmod + 1 + _name_czech_subst_stem + _name_czech_subst_postfix
|
||||||
MakeSwissTownName,
|
{ 0, MakeSwissTownName},
|
||||||
MakeDanishTownName,
|
{ 0, MakeDanishTownName},
|
||||||
MakeTurkishTownName,
|
{ 0, MakeTurkishTownName},
|
||||||
MakeItalianTownName,
|
{ 0, MakeItalianTownName},
|
||||||
MakeCatalanTownName,
|
{ 0, MakeCatalanTownName},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -910,12 +916,14 @@ char *GenerateTownNameString(char *buf, const char *last, size_t lang, uint32 se
|
||||||
/* Some generators need at least 9 bytes in buffer. English generators need 5 for
|
/* Some generators need at least 9 bytes in buffer. English generators need 5 for
|
||||||
* string replacing, others use constructions like strlen(buf)-3 and so on.
|
* string replacing, others use constructions like strlen(buf)-3 and so on.
|
||||||
* Finnish generator needs to fit all strings from _name_finnish_1.
|
* Finnish generator needs to fit all strings from _name_finnish_1.
|
||||||
|
* Czech generator needs to fit almost whole town name...
|
||||||
* These would break. Using another temporary buffer results in ~40% slower code,
|
* These would break. Using another temporary buffer results in ~40% slower code,
|
||||||
* so use it only when really needed. */
|
* so use it only when really needed. */
|
||||||
if (last - buf >= 9) return _town_name_generators[lang](buf, last, seed);
|
const TownNameGeneratorParams *par = &_town_name_generators[lang];
|
||||||
|
if (last >= buf + par->min) return par->proc(buf, last, seed);
|
||||||
|
|
||||||
char buffer[10]; // only at most 9 bytes will be needed anyway
|
char *buffer = AllocaM(char, par->min + 1);
|
||||||
_town_name_generators[lang](buffer, lastof(buffer), seed);
|
par->proc(buffer, buffer + par->min, seed);
|
||||||
|
|
||||||
return strecpy(buf, buffer, last);
|
return strecpy(buf, buffer, last);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue