richk@6720: /* $Id$ */ richk@6720: richk@6720: /** @file newgrf_townname.cpp richk@6720: * Implementation of Action 0F "universal holder" structure and functions. richk@6720: * This file implements a linked-lists of townname generators, richk@6720: * holding everything that the newgrf action 0F will send over to OpenTTD. richk@6720: */ richk@6720: richk@6720: #include "stdafx.h" richk@6720: #include "openttd.h" richk@6720: #include "table/strings.h" richk@6720: #include "newgrf_townname.h" richk@6720: #include "string.h" richk@6720: richk@6720: static GRFTownName *_grf_townnames = NULL; richk@6720: richk@6720: GRFTownName *GetGRFTownName(uint32 grfid) richk@6720: { richk@6720: GRFTownName *t = _grf_townnames; richk@6720: for (; t != NULL; t = t->next) { richk@6720: if (t->grfid == grfid) return t; richk@6720: } richk@6720: return NULL; richk@6720: } richk@6720: richk@6720: GRFTownName *AddGRFTownName(uint32 grfid) richk@6720: { richk@6720: GRFTownName *t = GetGRFTownName(grfid); richk@6720: if (t == NULL) { richk@6720: t = CallocT(1); richk@6720: t->grfid = grfid; richk@6720: t->next = _grf_townnames; richk@6720: _grf_townnames = t; richk@6720: } richk@6720: return t; richk@6720: } richk@6720: richk@6720: void DelGRFTownName(uint32 grfid) richk@6720: { richk@6720: GRFTownName *t = _grf_townnames; richk@6720: GRFTownName *p = NULL; richk@6720: for (;t != NULL; p = t, t = t->next) if (t->grfid == grfid) break; richk@6720: if (t != NULL) { richk@6720: for (int i = 0; i < 128; i++) { richk@6720: for (int j = 0; j < t->nbparts[i]; j++) { richk@6720: for (int k = 0; k < t->partlist[i][j].partcount; k++) { richk@6720: if (!HASBIT(t->partlist[i][j].parts[k].prob, 7)) free(t->partlist[i][j].parts[k].data.text); richk@6720: } richk@6720: free(t->partlist[i][j].parts); richk@6720: } richk@6720: free(t->partlist[i]); richk@6720: } richk@6720: if (p != NULL) { richk@6720: p->next = t->next; richk@6720: } else { richk@6720: _grf_townnames = t->next; richk@6720: } richk@6720: free(t); richk@6720: } richk@6720: } richk@6720: richk@6720: static char *RandomPart(char *buf, GRFTownName *t, uint32 seed, byte id, const char *last) richk@6720: { richk@6720: assert(t != NULL); richk@6720: for (int i = 0; i < t->nbparts[id]; i++) { richk@6720: byte count = t->partlist[id][i].bitcount; richk@6720: uint16 maxprob = t->partlist[id][i].maxprob; richk@6720: uint32 r = (GB(seed, t->partlist[id][i].bitstart, count) * maxprob) >> count; richk@6720: for (int j = 0; j < t->partlist[id][i].partcount; j++) { richk@6720: byte prob = t->partlist[id][i].parts[j].prob; richk@6720: maxprob -= GB(prob, 0, 7); richk@6720: if (maxprob > r) continue; richk@6720: if (HASBIT(prob, 7)) { richk@6720: buf = RandomPart(buf, t, seed, t->partlist[id][i].parts[j].data.id, last); richk@6720: } else { richk@6720: buf = strecat(buf, t->partlist[id][i].parts[j].data.text, last); richk@6720: } richk@6720: break; richk@6720: } richk@6720: } richk@6720: return buf; richk@6720: } richk@6720: richk@6720: char *GRFTownNameGenerate(char *buf, uint32 grfid, uint16 gen, uint32 seed, const char *last) richk@6720: { richk@6720: strecpy(buf, "", last); richk@6720: for (GRFTownName *t = _grf_townnames; t != NULL; t = t->next) { richk@6720: if (t->grfid == grfid) { richk@6720: assert(gen < t->nb_gen); richk@6720: buf = RandomPart(buf, t, seed, t->id[gen], last); richk@6720: break; richk@6720: } richk@6720: } richk@6720: return buf; richk@6720: } richk@6720: richk@6720: StringID *GetGRFTownNameList() richk@6720: { richk@6720: int nb_names = 0, n = 0; richk@6720: for (GRFTownName *t = _grf_townnames; t != NULL; t = t->next) nb_names += t->nb_gen; richk@6720: StringID *list = MallocT(nb_names + 1); richk@6720: for (GRFTownName *t = _grf_townnames; t != NULL; t = t->next) { richk@6720: for (int j = 0; j < t->nb_gen; j++) list[n++] = t->name[j]; richk@6720: } richk@6720: list[n] = INVALID_STRING_ID; richk@6720: return list; richk@6720: } richk@6720: richk@6720: void CleanUpGRFTownNames() richk@6720: { richk@6720: while (_grf_townnames != NULL) DelGRFTownName(_grf_townnames->grfid); richk@6720: } richk@6720: richk@6720: uint32 GetGRFTownNameId(int gen) richk@6720: { richk@6720: for (GRFTownName *t = _grf_townnames; t != NULL; t = t->next) { richk@6720: if (gen < t->nb_gen) return t->grfid; richk@6720: gen -= t->nb_gen; richk@6720: } richk@6720: /* Fallback to no NewGRF */ richk@6720: return 0; richk@6720: } richk@6720: richk@6720: uint16 GetGRFTownNameType(int gen) richk@6720: { richk@6720: for (GRFTownName *t = _grf_townnames; t != NULL; t = t->next) { richk@6720: if (gen < t->nb_gen) return gen; richk@6720: gen -= t->nb_gen; richk@6720: } richk@6720: /* Fallback to english original */ richk@6720: return SPECSTR_TOWNNAME_ENGLISH; richk@6720: }