This commit is contained in:
Enno Rehling 2018-05-05 07:39:25 +02:00
commit 0e3170a0cb
17 changed files with 100 additions and 52 deletions

View file

@ -107,14 +107,14 @@ static int cmp_spell(const void *a, const void *b) {
return strcmp(spa->sname, spb->sname); return strcmp(spa->sname, spb->sname);
} }
static bool set_seen(attrib **alist, struct spell *sp) { static bool set_seen(attrib **alist, const struct spell *sp) {
attrib *a = a_find(*alist, &at_seenspells); attrib *a = a_find(*alist, &at_seenspells);
selist **sl; selist **sl;
if (!a) { if (!a) {
a = a_add(alist, a_new(&at_seenspells)); a = a_add(alist, a_new(&at_seenspells));
} }
sl = (selist **)&a->data.v; sl = (selist **)&a->data.v;
return selist_set_insert(sl, sp, cmp_spell); return selist_set_insert(sl, (void *)sp, cmp_spell);
} }
static void upgrade_seenspell(attrib **alist, attrib *abegin) { static void upgrade_seenspell(attrib **alist, attrib *abegin) {
@ -123,7 +123,7 @@ static void upgrade_seenspell(attrib **alist, attrib *abegin) {
ak = a_find(*alist, &at_seenspells); ak = a_find(*alist, &at_seenspells);
if (ak) alist = &ak; if (ak) alist = &ak;
for (a = abegin; a && a->type == abegin->type; a = a->next) { for (a = abegin; a && a->type == abegin->type; a = a->next) {
set_seen(alist, (struct spell *)a->data.v); set_seen(alist, (const struct spell *)a->data.v);
} }
} }
@ -156,11 +156,12 @@ attrib_type at_reportspell = {
"reportspell", NULL "reportspell", NULL
}; };
void show_spell(faction *f, const spellbook_entry *sbe) void show_spell(faction *f, spellbook_entry *sbe)
{ {
if (!already_seen(f, sbe->sp)) { const spell *sp = spellref_get(&sbe->spref);
if (!already_seen(f, sp)) {
/* mark the spell as seen by this faction: */ /* mark the spell as seen by this faction: */
if (set_seen(&f->attribs, sbe->sp)) { if (set_seen(&f->attribs, sp)) {
/* add the spell to the report: */ /* add the spell to the report: */
attrib * a = a_new(&at_reportspell); attrib * a = a_new(&at_reportspell);
a->data.v = (void *)sbe; a->data.v = (void *)sbe;

View file

@ -6,7 +6,7 @@ struct spellbook_entry;
struct faction; struct faction;
struct spell; struct spell;
void show_spell(struct faction * f, const struct spellbook_entry *sbe); void show_spell(struct faction * f, struct spellbook_entry *sbe);
void reset_seen_spells(struct faction * f, const struct spell *sp); void reset_seen_spells(struct faction * f, const struct spell *sp);
extern struct attrib_type at_reportspell; extern struct attrib_type at_reportspell;

View file

@ -1870,7 +1870,7 @@ static void do_extra_spell(troop at, const att * a)
const spell *sp = spellref_get(a->data.sp); const spell *sp = spellref_get(a->data.sp);
if (!sp) { if (!sp) {
log_error("no such spell: '%s'", a->data.sp->name); log_error("no such spell: '%s'", a->data.sp->_name);
} }
else { else {
assert(a->level > 0); assert(a->level > 0);

View file

@ -860,7 +860,7 @@ static int tolua_get_spell_name(lua_State * L)
static int tolua_get_spell_entry_name(lua_State * L) static int tolua_get_spell_entry_name(lua_State * L)
{ {
spellbook_entry *self = (spellbook_entry*)tolua_tousertype(L, 1, 0); spellbook_entry *self = (spellbook_entry*)tolua_tousertype(L, 1, 0);
lua_pushstring(L, self->sp->sname); lua_pushstring(L, spellref_name(&self->spref));
return 1; return 1;
} }

View file

@ -758,7 +758,7 @@ static void cr_output_spells(stream *out, const unit * u, int maxlevel)
for (ql = book->spells, qi = 0; ql; selist_advance(&ql, &qi, 1)) { for (ql = book->spells, qi = 0; ql; selist_advance(&ql, &qi, 1)) {
spellbook_entry * sbe = (spellbook_entry *)selist_get(ql, qi); spellbook_entry * sbe = (spellbook_entry *)selist_get(ql, qi);
if (sbe->level <= maxlevel) { if (sbe->level <= maxlevel) {
spell * sp = sbe->sp; const spell *sp = spellref_get(&sbe->spref);
const char *name = translate(mkname("spell", sp->sname), spell_name(sp, f->locale)); const char *name = translate(mkname("spell", sp->sname), spell_name(sp, f->locale));
if (!header) { if (!header) {
stream_printf(out, "SPRUECHE\n"); stream_printf(out, "SPRUECHE\n");
@ -1083,7 +1083,7 @@ static void cr_find_address(FILE * F, const faction * uf, selist * addresses)
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
static void cr_reportspell(FILE * F, spell * sp, int level, const struct locale *lang) static void cr_reportspell(FILE * F, const spell * sp, int level, const struct locale *lang)
{ {
int k; int k;
const char *name = const char *name =
@ -1673,7 +1673,8 @@ report_computer(const char *filename, report_context * ctx, const char *bom)
a = a_find(f->attribs, &at_reportspell); a = a_find(f->attribs, &at_reportspell);
while (a && a->type == &at_reportspell) { while (a && a->type == &at_reportspell) {
spellbook_entry *sbe = (spellbook_entry *)a->data.v; spellbook_entry *sbe = (spellbook_entry *)a->data.v;
cr_reportspell(F, sbe->sp, sbe->level, f->locale); const spell *sp = spellref_get(&sbe->spref);
cr_reportspell(F, sp, sbe->level, f->locale);
a = a->next; a = a->next;
} }
for (a = a_find(f->attribs, &at_showitem); a && a->type == &at_showitem; for (a = a_find(f->attribs, &at_showitem); a && a->type == &at_showitem;

View file

@ -180,19 +180,37 @@ struct spellref *spellref_create(spell *sp, const char *name)
if (sp) { if (sp) {
spref->sp = sp; spref->sp = sp;
spref->name = str_strdup(sp->sname); spref->_name = str_strdup(sp->sname);
} }
else if (name) { else if (name) {
spref->name = str_strdup(name); spref->_name = str_strdup(name);
spref->sp = NULL; spref->sp = NULL;
} }
return spref; return spref;
} }
void spellref_init(spellref *spref, spell *sp, const char *name)
{
if (sp) {
spref->sp = sp;
spref->_name = str_strdup(sp->sname);
}
else if (name) {
spref->_name = str_strdup(name);
spref->sp = NULL;
}
}
void spellref_done(spellref *spref) {
if (spref) {
free(spref->_name);
}
}
void spellref_free(spellref *spref) void spellref_free(spellref *spref)
{ {
if (spref) { if (spref) {
free(spref->name); spellref_done(spref);
free(spref); free(spref);
} }
} }
@ -200,12 +218,21 @@ void spellref_free(spellref *spref)
struct spell *spellref_get(struct spellref *spref) struct spell *spellref_get(struct spellref *spref)
{ {
if (!spref->sp) { if (!spref->sp) {
assert(spref->name); assert(spref->_name);
spref->sp = find_spell(spref->name); spref->sp = find_spell(spref->_name);
if (spref->sp) { if (spref->sp) {
free(spref->name); free(spref->_name);
spref->name = NULL; spref->_name = NULL;
} }
} }
return spref->sp; return spref->sp;
} }
const char *spellref_name(const struct spellref *spref)
{
if (spref->_name) {
return spref->_name;
}
assert(spref->sp);
return spref->sp->sname;
}

View file

@ -43,7 +43,7 @@ extern "C" {
} spell; } spell;
typedef struct spellref { typedef struct spellref {
char * name; char * _name;
struct spell *sp; struct spell *sp;
} spellref; } spellref;
@ -56,6 +56,10 @@ extern "C" {
struct spellref *spellref_create(struct spell *sp, const char *name); struct spellref *spellref_create(struct spell *sp, const char *name);
void spellref_free(struct spellref *spref); void spellref_free(struct spellref *spref);
struct spell *spellref_get(struct spellref *spref); struct spell *spellref_get(struct spellref *spref);
const char *spellref_name(const struct spellref *spref);
void spellref_init(struct spellref *spref, struct spell *sp, const char *name);
void spellref_done(struct spellref *spref);
int sp_antimagiczone(struct castorder *co); int sp_antimagiczone(struct castorder *co);

View file

@ -58,8 +58,9 @@ static void test_spellref(CuTest *tc)
ref = spellref_create(NULL, "hodor"); ref = spellref_create(NULL, "hodor");
CuAssertPtrNotNull(tc, ref); CuAssertPtrNotNull(tc, ref);
CuAssertPtrEquals(tc, NULL, ref->sp); CuAssertPtrEquals(tc, NULL, ref->sp);
CuAssertStrEquals(tc, "hodor", ref->name); CuAssertStrEquals(tc, "hodor", ref->_name);
CuAssertPtrEquals(tc, NULL, spellref_get(ref)); CuAssertPtrEquals(tc, NULL, spellref_get(ref));
CuAssertStrEquals(tc, "hodor", spellref_name(ref));
sp = create_spell("hodor"); sp = create_spell("hodor");
CuAssertPtrNotNull(tc, sp); CuAssertPtrNotNull(tc, sp);
CuAssertPtrEquals(tc, sp, spellref_get(ref)); CuAssertPtrEquals(tc, sp, spellref_get(ref));

View file

@ -67,13 +67,23 @@ void write_spellbook(const struct spellbook *book, struct storage *store)
if (book) { if (book) {
for (ql = book->spells, qi = 0; ql; selist_advance(&ql, &qi, 1)) { for (ql = book->spells, qi = 0; ql; selist_advance(&ql, &qi, 1)) {
spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi); spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi);
WRITE_TOK(store, sbe->sp->sname); WRITE_TOK(store, spellref_name(&sbe->spref));
WRITE_INT(store, sbe->level); WRITE_INT(store, sbe->level);
} }
} }
WRITE_TOK(store, "end"); WRITE_TOK(store, "end");
} }
void spellbook_addref(spellbook *sb, const char *name, int level) {
spellbook_entry * sbe;
assert(sb && name && level > 0);
sbe = (spellbook_entry *)malloc(sizeof(spellbook_entry));
spellref_init(&sbe->spref, NULL, name);
sbe->level = level;
selist_push(&sb->spells, sbe);
}
void spellbook_add(spellbook *sb, spell *sp, int level) void spellbook_add(spellbook *sb, spell *sp, int level)
{ {
spellbook_entry * sbe; spellbook_entry * sbe;
@ -85,7 +95,7 @@ void spellbook_add(spellbook *sb, spell *sp, int level)
} }
#endif #endif
sbe = (spellbook_entry *)malloc(sizeof(spellbook_entry)); sbe = (spellbook_entry *)malloc(sizeof(spellbook_entry));
sbe->sp = sp; spellref_init(&sbe->spref, sp, NULL);
sbe->level = level; sbe->level = level;
selist_push(&sb->spells, sbe); selist_push(&sb->spells, sbe);
} }
@ -98,6 +108,7 @@ void spellbook_clear(spellbook *sb)
assert(sb); assert(sb);
for (qi = 0, ql = sb->spells; ql; selist_advance(&ql, &qi, 1)) { for (qi = 0, ql = sb->spells; ql; selist_advance(&ql, &qi, 1)) {
spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi); spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi);
spellref_done(&sbe->spref);
free(sbe); free(sbe);
} }
selist_free(sb->spells); selist_free(sb->spells);
@ -127,7 +138,7 @@ spellbook_entry * spellbook_get(spellbook *sb, const struct spell *sp)
for (qi = 0, ql = sb->spells; ql; selist_advance(&ql, &qi, 1)) { for (qi = 0, ql = sb->spells; ql; selist_advance(&ql, &qi, 1)) {
spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi); spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi);
if (sbe->sp==sp) { if (spellref_get(&sbe->spref) == sp) {
return sbe; return sbe;
} }
} }

View file

@ -19,17 +19,18 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#ifndef H_KRNL_SPELLBOOK_H #ifndef H_KRNL_SPELLBOOK_H
#define H_KRNL_SPELLBOOK_H #define H_KRNL_SPELLBOOK_H
#include "spell.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
struct spell;
struct storage; struct storage;
struct gamedata; struct gamedata;
struct selist; struct selist;
typedef struct spellbook_entry { typedef struct spellbook_entry {
struct spell *sp; spellref spref;
int level; int level;
} spellbook_entry; } spellbook_entry;
@ -45,6 +46,7 @@ extern "C" {
void write_spellbook(const struct spellbook *book, struct storage *store); void write_spellbook(const struct spellbook *book, struct storage *store);
void spellbook_add(spellbook *sbp, struct spell *sp, int level); void spellbook_add(spellbook *sbp, struct spell *sp, int level);
void spellbook_addref(spellbook *sb, const char *name, int level);
int spellbook_foreach(spellbook *sb, int(*callback)(spellbook_entry *, void *), void * data); int spellbook_foreach(spellbook *sb, int(*callback)(spellbook_entry *, void *), void * data);
void spellbook_clear(spellbook *sb); void spellbook_clear(spellbook *sb);
spellbook_entry * spellbook_get(spellbook *sb, const struct spell *sp); spellbook_entry * spellbook_get(spellbook *sb, const struct spell *sp);

View file

@ -40,7 +40,7 @@ void test_named_spellbooks(CuTest * tc)
sbe = spellbook_get(sb, sp); sbe = spellbook_get(sb, sp);
CuAssertPtrNotNull(tc, sbe); CuAssertPtrNotNull(tc, sbe);
CuAssertIntEquals(tc, 1, sbe->level); CuAssertIntEquals(tc, 1, sbe->level);
CuAssertPtrEquals(tc, sp, sbe->sp); CuAssertPtrEquals(tc, sp, spellref_get(&sbe->spref));
spellbook_foreach(sb, count_spell_cb, &counter); spellbook_foreach(sb, count_spell_cb, &counter);
CuAssertIntEquals(tc, 1, counter); CuAssertIntEquals(tc, 1, counter);

View file

@ -3298,8 +3298,9 @@ static void copy_spells(const spellbook * src, spellbook * dst, int maxlevel)
for (qi = 0, ql = src->spells; ql; selist_advance(&ql, &qi, 1)) { for (qi = 0, ql = src->spells; ql; selist_advance(&ql, &qi, 1)) {
spellbook_entry * sbe = (spellbook_entry *)selist_get(ql, qi); spellbook_entry * sbe = (spellbook_entry *)selist_get(ql, qi);
if (sbe->level <= maxlevel) { if (sbe->level <= maxlevel) {
if (!spellbook_get(dst, sbe->sp)) { spell *sp = spellref_get(&sbe->spref);
spellbook_add(dst, sbe->sp, sbe->level); if (!spellbook_get(dst, sp)) {
spellbook_add(dst, sp, sbe->level);
} }
} }
} }

View file

@ -375,7 +375,9 @@ void pick_random_spells(faction * f, int level, spellbook * book, int num_spells
sbe = 0; sbe = 0;
} }
else { else {
if (f->spellbook && spellbook_get(f->spellbook, sbe->sp)) { if (f->spellbook) {
const spell *sp = spellref_get(&sbe->spref);
if (sp && spellbook_get(f->spellbook, sp)) {
/* already have this spell, remove it from the list of candidates */ /* already have this spell, remove it from the list of candidates */
commonspells[spellno] = commonspells[--numspells]; commonspells[spellno] = commonspells[--numspells];
if (maxspell > numspells) { if (maxspell > numspells) {
@ -385,12 +387,13 @@ void pick_random_spells(faction * f, int level, spellbook * book, int num_spells
} }
} }
} }
}
if (sbe && spellno < maxspell) { if (sbe && spellno < maxspell) {
if (!f->spellbook) { if (!f->spellbook) {
f->spellbook = create_spellbook(0); f->spellbook = create_spellbook(0);
} }
spellbook_add(f->spellbook, sbe->sp, sbe->level); spellbook_add(f->spellbook, spellref_get(&sbe->spref), sbe->level);
commonspells[spellno] = commonspells[--numspells]; commonspells[spellno] = commonspells[--numspells];
} }
} }
@ -2840,14 +2843,14 @@ static void select_spellbook(void **tokens, spellbook *sb, const struct locale *
for (qi = 0, ql = sb->spells; ql; selist_advance(&ql, &qi, 1)) { for (qi = 0, ql = sb->spells; ql; selist_advance(&ql, &qi, 1)) {
spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi); spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi);
const spell *sp = spellref_get(&sbe->spref);
const char *n = spell_name(sbe->sp, lang); const char *n = spell_name(sp, lang);
if (!n) { if (!n) {
log_error("no translation in locale %s for spell %s\n", locale_name(lang), sbe->sp->sname); log_error("no translation in locale %s for spell %s\n", locale_name(lang), sp->sname);
} }
else { else {
variant token; variant token;
token.v = sbe->sp; token.v = (void *)sp;
addtoken((struct tnode **)tokens, n, token); addtoken((struct tnode **)tokens, n, token);
} }
} }

View file

@ -86,7 +86,7 @@ static void test_spellbooks(CuTest * tc)
CuAssertPtrNotNull(tc, sp); CuAssertPtrNotNull(tc, sp);
entry = spellbook_get(herp, sp); entry = spellbook_get(herp, sp);
CuAssertPtrNotNull(tc, entry); CuAssertPtrNotNull(tc, entry);
CuAssertPtrEquals(tc, sp, entry->sp); CuAssertPtrEquals(tc, sp, spellref_get(&entry->spref));
test_teardown(); test_teardown();
test_setup(); test_setup();

View file

@ -249,7 +249,7 @@ void nr_spell_syntax(struct stream *out, spellbook_entry * sbe, const struct loc
char buf[4096]; char buf[4096];
char *bufp = buf; char *bufp = buf;
size_t size = sizeof(buf) - 1; size_t size = sizeof(buf) - 1;
const spell * sp = sbe->sp; const spell *sp = spellref_get(&sbe->spref);
const char *params = sp->parameter; const char *params = sp->parameter;
if (sp->sptyp & ISCOMBATSPELL) { if (sp->sptyp & ISCOMBATSPELL) {
@ -439,7 +439,7 @@ void nr_spell(struct stream *out, spellbook_entry * sbe, const struct locale *la
char buf[4096]; char buf[4096];
char *startp, *bufp = buf; char *startp, *bufp = buf;
size_t size = sizeof(buf) - 1; size_t size = sizeof(buf) - 1;
const spell * sp = sbe->sp; const spell *sp = spellref_get(&sbe->spref);
newline(out); newline(out);
centre(out, spell_name(sp, lang), true); centre(out, spell_name(sp, lang), true);

View file

@ -870,6 +870,7 @@ bufunit(const faction * f, const unit * u, seen_mode mode, char *buf,
for (header = 0, qi = 0; ql; selist_advance(&ql, &qi, 1)) { for (header = 0, qi = 0; ql; selist_advance(&ql, &qi, 1)) {
spellbook_entry * sbe = (spellbook_entry *)selist_get(ql, qi); spellbook_entry * sbe = (spellbook_entry *)selist_get(ql, qi);
const spell *sp = spellref_get(&sbe->spref);
if (sbe->level <= maxlevel) { if (sbe->level <= maxlevel) {
if (!header) { if (!header) {
n = snprintf(bufp, size, ", %s: ", LOC(lang, "nr_spells")); n = snprintf(bufp, size, ", %s: ", LOC(lang, "nr_spells"));
@ -882,7 +883,7 @@ bufunit(const faction * f, const unit * u, seen_mode mode, char *buf,
WARN_STATIC_BUFFER(); WARN_STATIC_BUFFER();
} }
/* TODO: no need to deref the spellref here (spref->name is good) */ /* TODO: no need to deref the spellref here (spref->name is good) */
bufp = STRLCPY(bufp, spell_name(sbe->sp, lang), size); bufp = STRLCPY(bufp, spell_name(sp, lang), size);
} }
} }

View file

@ -1113,17 +1113,12 @@ static int parse_spellbooks(xmlDocPtr doc)
if (result->nodesetval->nodeNr > 0) { if (result->nodesetval->nodeNr > 0) {
for (k = 0; k != result->nodesetval->nodeNr; ++k) { for (k = 0; k != result->nodesetval->nodeNr; ++k) {
xmlNodePtr node = result->nodesetval->nodeTab[k]; xmlNodePtr node = result->nodesetval->nodeTab[k];
spell * sp = 0;
int level = xml_ivalue(node, "level", -1); int level = xml_ivalue(node, "level", -1);
propValue = xmlGetProp(node, BAD_CAST "spell"); if (level > 0 && (propValue = xmlGetProp(node, BAD_CAST "spell")) != NULL) {
if (propValue) { spellbook_addref(sb, (const char *)propValue, level);
sp = find_spell((const char *)propValue);
xmlFree(propValue); xmlFree(propValue);
} }
if (sp && level > 0) {
spellbook_add(sb, sp, level);
}
else { else {
log_error("invalid entry at index '%d' in spellbook '%s'\n", k, sb->name); log_error("invalid entry at index '%d' in spellbook '%s'\n", k, sb->name);
} }
@ -1513,7 +1508,8 @@ static int parse_races(xmlDocPtr doc)
if (attack->data.sp) { if (attack->data.sp) {
attack->level = xml_ivalue(node, "level", 0); attack->level = xml_ivalue(node, "level", 0);
if (attack->level <= 0) { if (attack->level <= 0) {
log_error("magical attack '%s' for race '%s' needs a level: %d\n", attack->data.sp->name, rc->_name, attack->level); log_error("magical attack '%s' for race '%s' needs a level: %d\n",
spellref_name(attack->data.sp), rc->_name, attack->level);
} }
} }
} }