Codechange: Use std:: features for NewGRF town names (#10631)

This removes manual memory (de-)allocation and list counting.
This commit is contained in:
PeterN 2023-04-16 21:24:54 +01:00 committed by GitHub
parent 4491e45f3c
commit d949cfab24
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 80 additions and 107 deletions

View File

@ -7725,8 +7725,8 @@ static void FeatureTownName(ByteReader *buf)
bool new_scheme = _cur.grffile->grf_version >= 7;
byte lang = buf->ReadByte();
StringID style = STR_UNDEFINED;
byte nb_gen = townname->nb_gen;
do {
ClrBit(lang, 7);
@ -7735,53 +7735,48 @@ static void FeatureTownName(ByteReader *buf)
std::string lang_name = TranslateTTDPatchCodes(grfid, lang, false, name);
grfmsg(6, "FeatureTownName: lang 0x%X -> '%s'", lang, lang_name.c_str());
townname->name[nb_gen] = AddGRFString(grfid, id, lang, new_scheme, false, name, STR_UNDEFINED);
style = AddGRFString(grfid, id, lang, new_scheme, false, name, STR_UNDEFINED);
lang = buf->ReadByte();
} while (lang != 0);
townname->id[nb_gen] = id;
townname->nb_gen++;
townname->styles.emplace_back(style, id);
}
byte nb = buf->ReadByte();
grfmsg(6, "FeatureTownName: %u parts", nb);
uint8 parts = buf->ReadByte();
grfmsg(6, "FeatureTownName: %u parts", parts);
townname->nbparts[id] = nb;
townname->partlist[id] = CallocT<NamePartList>(nb);
townname->partlists[id].reserve(parts);
for (uint partnum = 0; partnum < parts; partnum++) {
NamePartList &partlist = townname->partlists[id].emplace_back();
uint8 texts = buf->ReadByte();
partlist.bitstart = buf->ReadByte();
partlist.bitcount = buf->ReadByte();
partlist.maxprob = 0;
grfmsg(6, "FeatureTownName: part %u contains %u texts and will use GB(seed, %u, %u)", partnum, texts, partlist.bitstart, partlist.bitcount);
for (int i = 0; i < nb; i++) {
byte nbtext = buf->ReadByte();
townname->partlist[id][i].bitstart = buf->ReadByte();
townname->partlist[id][i].bitcount = buf->ReadByte();
townname->partlist[id][i].maxprob = 0;
townname->partlist[id][i].partcount = nbtext;
townname->partlist[id][i].parts = CallocT<NamePart>(nbtext);
grfmsg(6, "FeatureTownName: part %d contains %d texts and will use GB(seed, %d, %d)", i, nbtext, townname->partlist[id][i].bitstart, townname->partlist[id][i].bitcount);
partlist.parts.reserve(texts);
for (uint textnum = 0; textnum < texts; textnum++) {
NamePart &part = partlist.parts.emplace_back();
part.prob = buf->ReadByte();
for (int j = 0; j < nbtext; j++) {
byte prob = buf->ReadByte();
if (HasBit(prob, 7)) {
if (HasBit(part.prob, 7)) {
byte ref_id = buf->ReadByte();
if (townname->nbparts[ref_id] == 0) {
if (ref_id >= GRFTownName::MAX_LISTS || townname->partlists[ref_id].empty()) {
grfmsg(0, "FeatureTownName: definition 0x%02X doesn't exist, deactivating", ref_id);
DelGRFTownName(grfid);
DisableGrf(STR_NEWGRF_ERROR_INVALID_ID);
return;
}
grfmsg(6, "FeatureTownName: part %d, text %d, uses intermediate definition 0x%02X (with probability %d)", i, j, ref_id, prob & 0x7F);
townname->partlist[id][i].parts[j].data.id = ref_id;
part.id = ref_id;
grfmsg(6, "FeatureTownName: part %u, text %u, uses intermediate definition 0x%02X (with probability %u)", partnum, textnum, ref_id, part.prob & 0x7F);
} else {
const char *text = buf->ReadString();
townname->partlist[id][i].parts[j].data.text = stredup(TranslateTTDPatchCodes(grfid, 0, false, text).c_str());
grfmsg(6, "FeatureTownName: part %d, text %d, '%s' (with probability %d)", i, j, townname->partlist[id][i].parts[j].data.text, prob);
part.text = TranslateTTDPatchCodes(grfid, 0, false, text);
grfmsg(6, "FeatureTownName: part %u, text %u, '%s' (with probability %u)", partnum, textnum, part.text.c_str(), part.prob);
}
townname->partlist[id][i].parts[j].prob = prob;
townname->partlist[id][i].maxprob += GB(prob, 0, 7);
partlist.maxprob += GB(part.prob, 0, 7);
}
grfmsg(6, "FeatureTownName: part %d, total probability %d", i, townname->partlist[id][i].maxprob);
grfmsg(6, "FeatureTownName: part %u, total probability %u", partnum, partlist.maxprob);
}
}

View File

@ -21,15 +21,13 @@
#include "safeguards.h"
static GRFTownName *_grf_townnames = nullptr;
static std::vector<GRFTownName> _grf_townnames;
static std::vector<StringID> _grf_townname_names;
GRFTownName *GetGRFTownName(uint32 grfid)
{
GRFTownName *t = _grf_townnames;
for (; t != nullptr; t = t->next) {
if (t->grfid == grfid) return t;
}
auto found = std::find_if(std::begin(_grf_townnames), std::end(_grf_townnames), [&grfid](const GRFTownName &t){ return t.grfid == grfid; });
if (found != std::end(_grf_townnames)) return &*found;
return nullptr;
}
@ -37,53 +35,31 @@ GRFTownName *AddGRFTownName(uint32 grfid)
{
GRFTownName *t = GetGRFTownName(grfid);
if (t == nullptr) {
t = CallocT<GRFTownName>(1);
t = &_grf_townnames.emplace_back();
t->grfid = grfid;
t->next = _grf_townnames;
_grf_townnames = t;
}
return t;
}
void DelGRFTownName(uint32 grfid)
{
GRFTownName *t = _grf_townnames;
GRFTownName *p = nullptr;
for (;t != nullptr; p = t, t = t->next) if (t->grfid == grfid) break;
if (t != nullptr) {
for (int i = 0; i < 128; i++) {
for (int j = 0; j < t->nbparts[i]; j++) {
for (int k = 0; k < t->partlist[i][j].partcount; k++) {
if (!HasBit(t->partlist[i][j].parts[k].prob, 7)) free(t->partlist[i][j].parts[k].data.text);
}
free(t->partlist[i][j].parts);
}
free(t->partlist[i]);
}
if (p != nullptr) {
p->next = t->next;
} else {
_grf_townnames = t->next;
}
free(t);
}
_grf_townnames.erase(std::find_if(std::begin(_grf_townnames), std::end(_grf_townnames), [&grfid](const GRFTownName &t){ return t.grfid == grfid; }));
}
static char *RandomPart(char *buf, GRFTownName *t, uint32 seed, byte id, const char *last)
static char *RandomPart(char *buf, const GRFTownName *t, uint32 seed, byte id, const char *last)
{
assert(t != nullptr);
for (int i = 0; i < t->nbparts[id]; i++) {
byte count = t->partlist[id][i].bitcount;
uint16 maxprob = t->partlist[id][i].maxprob;
uint32 r = (GB(seed, t->partlist[id][i].bitstart, count) * maxprob) >> count;
for (int j = 0; j < t->partlist[id][i].partcount; j++) {
byte prob = t->partlist[id][i].parts[j].prob;
maxprob -= GB(prob, 0, 7);
for (const auto &partlist : t->partlists[id]) {
byte count = partlist.bitcount;
uint16 maxprob = partlist.maxprob;
uint32 r = (GB(seed, partlist.bitstart, count) * maxprob) >> count;
for (const auto &part : partlist.parts) {
maxprob -= GB(part.prob, 0, 7);
if (maxprob > r) continue;
if (HasBit(prob, 7)) {
buf = RandomPart(buf, t, seed, t->partlist[id][i].parts[j].data.id, last);
if (HasBit(part.prob, 7)) {
buf = RandomPart(buf, t, seed, part.id, last);
} else {
buf = strecat(buf, t->partlist[id][i].parts[j].data.text, last);
buf = strecat(buf, part.text.c_str(), last);
}
break;
}
@ -94,12 +70,10 @@ static char *RandomPart(char *buf, GRFTownName *t, uint32 seed, byte id, const c
char *GRFTownNameGenerate(char *buf, uint32 grfid, uint16 gen, uint32 seed, const char *last)
{
strecpy(buf, "", last);
for (GRFTownName *t = _grf_townnames; t != nullptr; t = t->next) {
if (t->grfid == grfid) {
assert(gen < t->nb_gen);
buf = RandomPart(buf, t, seed, t->id[gen], last);
break;
}
const GRFTownName *t = GetGRFTownName(grfid);
if (t != nullptr) {
assert(gen < t->styles.size());
buf = RandomPart(buf, t, seed, t->styles[gen].id, last);
}
return buf;
}
@ -109,8 +83,10 @@ char *GRFTownNameGenerate(char *buf, uint32 grfid, uint16 gen, uint32 seed, cons
void InitGRFTownGeneratorNames()
{
_grf_townname_names.clear();
for (GRFTownName *t = _grf_townnames; t != nullptr; t = t->next) {
for (int j = 0; j < t->nb_gen; j++) _grf_townname_names.push_back(t->name[j]);
for (const auto &t : _grf_townnames) {
for (const auto &style : t.styles) {
_grf_townname_names.push_back(style.name);
}
}
}
@ -119,31 +95,31 @@ const std::vector<StringID>& GetGRFTownNameList()
return _grf_townname_names;
}
StringID GetGRFTownNameName(uint gen)
StringID GetGRFTownNameName(uint16 gen)
{
return gen < _grf_townname_names.size() ? _grf_townname_names[gen] : STR_UNDEFINED;
}
void CleanUpGRFTownNames()
{
while (_grf_townnames != nullptr) DelGRFTownName(_grf_townnames->grfid);
_grf_townnames.clear();
}
uint32 GetGRFTownNameId(int gen)
uint32 GetGRFTownNameId(uint16 gen)
{
for (GRFTownName *t = _grf_townnames; t != nullptr; t = t->next) {
if (gen < t->nb_gen) return t->grfid;
gen -= t->nb_gen;
for (const auto &t : _grf_townnames) {
if (gen < t.styles.size()) return t.grfid;
gen -= static_cast<uint16>(t.styles.size());
}
/* Fallback to no NewGRF */
return 0;
}
uint16 GetGRFTownNameType(int gen)
uint16 GetGRFTownNameType(uint16 gen)
{
for (GRFTownName *t = _grf_townnames; t != nullptr; t = t->next) {
if (gen < t->nb_gen) return gen;
gen -= t->nb_gen;
for (const auto &t : _grf_townnames) {
if (gen < t.styles.size()) return gen;
gen -= static_cast<uint16>(t.styles.size());
}
/* Fallback to english original */
return SPECSTR_TOWNNAME_ENGLISH;

View File

@ -17,29 +17,31 @@
#include "strings_type.h"
struct NamePart {
byte prob; ///< The relative probability of the following name to appear in the bottom 7 bits.
union {
char *text; ///< If probability bit 7 is clear
byte id; ///< If probability bit 7 is set
} data;
std::string text; ///< If probability bit 7 is clear
byte id; ///< If probability bit 7 is set
byte prob; ///< The relative probability of the following name to appear in the bottom 7 bits.
};
struct NamePartList {
byte partcount;
byte bitstart;
byte bitcount;
uint16 maxprob;
NamePart *parts;
byte bitstart; ///< Start of random seed bits to use.
byte bitcount; ///< Number of bits of random seed to use.
uint16 maxprob; ///< Total probability of all parts.
std::vector<NamePart> parts; ///< List of parts to choose from.
};
struct TownNameStyle {
StringID name; ///< String ID of this town name style.
byte id; ///< Index within partlist for this town name style.
TownNameStyle(StringID name, byte id) : name(name), id(id) { }
};
struct GRFTownName {
uint32 grfid;
byte nb_gen;
byte id[128];
StringID name[128];
byte nbparts[128];
NamePartList *partlist[128];
GRFTownName *next;
static const uint MAX_LISTS = 128; ///< Maximum number of town name lists that can be defined per GRF.
uint32 grfid; ///< GRF ID of NewGRF.
std::vector<TownNameStyle> styles; ///< Style names defined by the Town Name NewGRF.
std::vector<NamePartList> partlists[MAX_LISTS]; ///< Lists of town name parts.
};
GRFTownName *AddGRFTownName(uint32 grfid);
@ -47,9 +49,9 @@ GRFTownName *GetGRFTownName(uint32 grfid);
void DelGRFTownName(uint32 grfid);
void CleanUpGRFTownNames();
char *GRFTownNameGenerate(char *buf, uint32 grfid, uint16 gen, uint32 seed, const char *last);
uint32 GetGRFTownNameId(int gen);
uint16 GetGRFTownNameType(int gen);
StringID GetGRFTownNameName(uint gen);
uint32 GetGRFTownNameId(uint16 gen);
uint16 GetGRFTownNameType(uint16 gen);
StringID GetGRFTownNameName(uint16 gen);
const std::vector<StringID>& GetGRFTownNameList();