diff --git a/src/bindings/bind_attrib.c b/src/bindings/bind_attrib.c index 54821bfe9..04c02f305 100644 --- a/src/bindings/bind_attrib.c +++ b/src/bindings/bind_attrib.c @@ -15,6 +15,7 @@ without prior permission by the authors of Eressea. #include #include +#include #include #include #include diff --git a/src/bindings/bind_faction.c b/src/bindings/bind_faction.c index 045aeea05..75bafa275 100644 --- a/src/bindings/bind_faction.c +++ b/src/bindings/bind_faction.c @@ -471,19 +471,7 @@ tolua_faction_tostring(lua_State *L) static int tolua_faction_get_spells(lua_State* L) { faction* self = (faction*)tolua_tousertype(L, 1, 0); - spell_list * slist = self->spellbook; - if (slist) { - spell_list ** spell_ptr = (spell_list **)lua_newuserdata(L, sizeof(spell_list *)); - luaL_getmetatable(L, TOLUA_CAST "spell_list"); - lua_setmetatable(L, -2); - - *spell_ptr = slist; - lua_pushcclosure(L, tolua_spelllist_next, 1); - return 1; - } - - lua_pushnil(L); - return 1; + return tolua_quicklist_push(L, "spell_list", "spell", self->spellbook); } void diff --git a/src/bindings/bind_unit.c b/src/bindings/bind_unit.c index c7ff2a345..186950b9c 100644 --- a/src/bindings/bind_unit.c +++ b/src/bindings/bind_unit.c @@ -43,6 +43,7 @@ without prior permission by the authors of Eressea. #include #include #include +#include #include #include @@ -468,9 +469,11 @@ tolua_unit_addnotice(lua_State* L) static void unit_castspell(unit * u, const char * name) { - spell_list * slist = spells; - while (slist!=NULL) { - spell * sp = slist->data; + quicklist * ql = spells; + int qi; + + for (ql=spells,qi=0;ql;ql_advance(&ql, &qi, 1)) { + spell * sp = (spell *)ql_get(ql, qi); if (strcmp(name, sp->sname)==0) { castorder * co = (castorder*)malloc(sizeof(castorder)); co->distance = 0; @@ -490,7 +493,6 @@ unit_castspell(unit * u, const char * name) } free(co); } - slist=slist->next; } } @@ -506,23 +508,12 @@ tolua_unit_castspell(lua_State* L) static void unit_addspell(unit * u, const char * name) { - int add = 0; sc_mage * m = get_mage(u); - spell_list * slist = spells; - spell_list ** starget = NULL; - spell * spadd = NULL; - while (slist!=NULL) { - spell * sp = slist->data; - if (strcmp(name, sp->sname)==0) { - starget = get_spelllist(m, u->faction); - if (m->magietyp==sp->magietyp) spadd = sp; - else if (!spadd) spadd = sp; - add = 1; - } - slist=slist->next; - } + spell * spadd = find_spell(M_NONE, name); + if (!spadd) log_error(("spell %s could not be found\n", name)); else { + quicklist ** starget = get_spelllist(m, u->faction); add_spell(starget, spadd); } } @@ -537,19 +528,12 @@ tolua_unit_addspell(lua_State* L) } static void -unit_removespell(unit * u, const spell * sp) +unit_removespell(unit * u, spell * sp) { - spell_list ** isptr; - isptr = get_spelllist(get_mage(u), u->faction); + quicklist ** isptr; - while (*isptr && (*isptr)->data != sp) { - isptr = &(*isptr)->next; - } - if (*isptr) { - spell_list * sptr = *isptr; - *isptr = sptr->next; - free(sptr); - } + isptr = get_spelllist(get_mage(u), u->faction); + ql_set_remove(isptr, sp); } static int @@ -760,23 +744,16 @@ static int tolua_unit_get_spells(lua_State* L) { unit* self = (unit*)tolua_tousertype(L, 1, 0); sc_mage * mage = get_mage(self); + quicklist * slist = 0; if (mage) { - spell_list ** slist = get_spelllist(mage, self->faction); - assert(slist); - if (slist) { - spell_list ** spell_ptr = (spell_list **)lua_newuserdata(L, sizeof(spell_list *)); - luaL_getmetatable(L, TOLUA_CAST "spell_list"); - lua_setmetatable(L, -2); - - *spell_ptr = *slist; - lua_pushcclosure(L, tolua_spelllist_next, 1); - return 1; + quicklist ** slist_ptr = get_spelllist(mage, self->faction); + if (slist_ptr) { + slist = *slist_ptr; } } - lua_pushnil(L); - return 1; + return tolua_quicklist_push(L, "spell_list", "spell", slist); } static int tolua_unit_get_orders(lua_State* L) diff --git a/src/bindings/bindings.c b/src/bindings/bindings.c index 400df4a5c..f987c0173 100644 --- a/src/bindings/bindings.c +++ b/src/bindings/bindings.c @@ -92,7 +92,7 @@ int tolua_orderlist_next(lua_State *L) else return 0; /* no more values to return */ } -int tolua_quicklist_iter(lua_State *L) +static int tolua_quicklist_iter(lua_State *L) { quicklist** qlp = (quicklist **)lua_touserdata(L, lua_upvalueindex(1)); quicklist* ql = *qlp; @@ -110,16 +110,21 @@ int tolua_quicklist_iter(lua_State *L) else return 0; /* no more values to return */ } -int tolua_spelllist_next(lua_State *L) +int tolua_quicklist_push(struct lua_State *L, const char * list_type, const char * elem_type, struct quicklist * list) { - spell_list** spell_ptr = (spell_list **)lua_touserdata(L, lua_upvalueindex(1)); - spell_list* slist = *spell_ptr; - if (slist != NULL) { - tolua_pushusertype(L, slist->data, TOLUA_CAST "spell"); - *spell_ptr = slist->next; - return 1; + if (list) { + quicklist ** qlist_ptr = (quicklist**)lua_newuserdata(L, sizeof(quicklist *)); + *qlist_ptr = list; + + luaL_getmetatable(L, list_type); + lua_setmetatable(L, -2); + lua_pushnumber(L, 0); + lua_pushstring(L, elem_type); + lua_pushcclosure(L, tolua_quicklist_iter, 3); /* OBS: this closure has multiple upvalues (list, index, type_name) */ + } else { + lua_pushnil(L); } - else return 0; /* no more values to return */ + return 1; } int tolua_itemlist_next(lua_State *L) @@ -747,18 +752,7 @@ static int tolua_get_alliance_factions(lua_State* L) { alliance * self = (alliance *)tolua_tousertype(L, 1, 0); - quicklist ** faction_ptr = (quicklist**)lua_newuserdata(L, sizeof(quicklist *)); - - luaL_getmetatable(L, "faction_list"); - lua_setmetatable(L, -2); - - lua_pushnumber(L, 0); - - *faction_ptr = self->members; - - lua_pushstring(L, "faction"); - lua_pushcclosure(L, tolua_quicklist_iter, 3); /* OBS: this closure has multiple upvalues (list, index, type_name) */ - return 1; + return tolua_quicklist_push(L, "faction_list", "faction", self->members); } static int tolua_get_alliance_id(lua_State* L) @@ -794,10 +788,11 @@ tolua_write_spells(lua_State* L) const char * filename = "magic.xml"; xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0"); xmlNodePtr root = xmlNewNode(NULL, BAD_CAST "spells"); - spell_list * splist; + quicklist * ql; + int qi; - for (splist=spells; splist; splist=splist->next) { - spell * sp = splist->data; + for (ql=spells,qi=0;ql;ql_advance(&ql, &qi, 1)) { + spell * sp = (spell *)ql_get(ql, qi); if (sp->sp_function!=fun) { int combat = 0; xmlNodePtr node = xmlNewNode(NULL, BAD_CAST "spell"); @@ -904,19 +899,7 @@ tolua_get_spell_name(lua_State *L) static int tolua_get_spells(lua_State* L) { - spell_list * slist = spells; - if (slist) { - spell_list ** spell_ptr = (spell_list **)lua_newuserdata(L, sizeof(spell_list *)); - luaL_getmetatable(L, "spell_list"); - lua_setmetatable(L, -2); - - *spell_ptr = slist; - lua_pushcclosure(L, tolua_spelllist_next, 1); - return 1; - } - - lua_pushnil(L); - return 1; + return tolua_quicklist_push(L, "spell_list", "spell", spells); } int diff --git a/src/bindings/bindings.h b/src/bindings/bindings.h index 5ed8d6232..4cca8fee4 100644 --- a/src/bindings/bindings.h +++ b/src/bindings/bindings.h @@ -20,6 +20,7 @@ extern "C" { int tolua_spelllist_next(struct lua_State *L); int tolua_itemlist_next(struct lua_State *L); int tolua_orderlist_next(struct lua_State *L); + int tolua_quicklist_push(struct lua_State *L, const char * list_type, const char * elem_type, struct quicklist * list); int log_lua_error(struct lua_State * L); #ifdef __cplusplus diff --git a/src/gamecode.vcxproj b/src/gamecode.vcxproj index 8cfd4712a..78f231ff1 100644 --- a/src/gamecode.vcxproj +++ b/src/gamecode.vcxproj @@ -93,6 +93,7 @@ + @@ -119,6 +120,7 @@ + diff --git a/src/gamecode.vcxproj.filters b/src/gamecode.vcxproj.filters index 8cd90a6f3..9105225f2 100644 --- a/src/gamecode.vcxproj.filters +++ b/src/gamecode.vcxproj.filters @@ -65,6 +65,9 @@ Source Files + + Source Files + @@ -121,5 +124,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/src/gamecode/creport.c b/src/gamecode/creport.c index fbf0af602..a216b37e0 100644 --- a/src/gamecode/creport.c +++ b/src/gamecode/creport.c @@ -641,12 +641,15 @@ fwriteorder(FILE * F, const struct order * ord, const struct locale * lang, bool fputc('"', F); } -static void cr_output_spells(FILE * F, spell_list * slist, const faction * f, int maxlevel) +static void cr_output_spells(FILE * F, quicklist * slist, const faction * f, int maxlevel) { if (slist) { + quicklist * ql; + int qi; fprintf(F, "SPRUECHE\n"); - for (;slist; slist = slist->next) { - spell * sp = slist->data; + + for (ql=slist,qi=0;ql;ql_advance(&ql, &qi, 1)) { + spell * sp = (spell *)ql_get(ql, qi); if (sp->level <= maxlevel) { const char * name = add_translation(mkname("spell", sp->sname), spell_name(sp, f->locale)); fprintf(F, "\"%s\"\n", name); @@ -868,7 +871,7 @@ cr_output_unit(FILE * F, const region * r, /* spells */ if (is_mage(u)) { sc_mage * mage = get_mage(u); - spell_list ** slistp = get_spelllist(mage, u->faction); + quicklist ** slistp = get_spelllist(mage, u->faction); int i, maxlevel = effskill(u, SK_MAGIC); cr_output_spells(F, *slistp, f, maxlevel); diff --git a/src/gamecode/xmlreport.c b/src/gamecode/xmlreport.c index 2c7646895..eaa4873a5 100644 --- a/src/gamecode/xmlreport.c +++ b/src/gamecode/xmlreport.c @@ -58,6 +58,7 @@ without prior permission by the authors of Eressea. #include #include #include +#include #include #include @@ -173,13 +174,15 @@ xml_inventory(report_context * ctx, item * items, unit * u) } static xmlNodePtr -xml_spells(report_context * ctx, spell_list * slist, int maxlevel) +xml_spells(report_context * ctx, quicklist * slist, int maxlevel) { xml_context* xct = (xml_context*)ctx->userdata; xmlNodePtr child, node = xmlNewNode(xct->ns_atl, BAD_CAST "spells"); + quicklist * ql; + int qi; - for (;slist; slist = slist->next) { - spell * sp = slist->data; + for (ql=slist,qi=0;ql;ql_advance(&ql, &qi, 1)) { + spell * sp = (spell *)ql_get(ql, qi); if (sp->level <= maxlevel) { child = xmlAddChild(node, xmlNewNode(xct->ns_atl, BAD_CAST "spell")); @@ -338,7 +341,7 @@ xml_unit(report_context * ctx, unit * u, int mode) /* spells */ if (is_mage(u)) { sc_mage * mage = get_mage(u); - spell_list * slist = mage->spells; + quicklist * slist = mage->spells; if (slist) { xmlAddChild(node, xml_spells(ctx, slist, effskill(u, SK_MAGIC))); } diff --git a/src/kernel/faction.c b/src/kernel/faction.c index f5ac32f3c..7216e9338 100644 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -40,6 +40,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include +#include #include #include #include @@ -287,7 +288,7 @@ destroyfaction(faction * f) if (!f->alive) return; fset(f, FFL_QUIT); - freelist(f->spellbook); + ql_free(f->spellbook); f->spellbook = NULL; while (f->battles) { diff --git a/src/kernel/faction.h b/src/kernel/faction.h index 0e3617e34..fc0b71107 100644 --- a/src/kernel/faction.h +++ b/src/kernel/faction.h @@ -73,7 +73,7 @@ typedef struct faction { char *passw; char *override; int max_spelllevel; - struct spell_list * spellbook; + struct quicklist * spellbook; const struct locale * locale; int lastorders; int age; diff --git a/src/kernel/magic.c b/src/kernel/magic.c index a1e1251b6..db73632d6 100644 --- a/src/kernel/magic.c +++ b/src/kernel/magic.c @@ -53,6 +53,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include +#include #include #include #include @@ -208,7 +209,7 @@ int FactionSpells(void) return rules_factionspells; } -void read_spellist(struct spell_list ** slistp, magic_t mtype, struct storage * store) +void read_spells(struct quicklist ** slistp, magic_t mtype, struct storage * store) { for (;;) { spell * sp; @@ -269,16 +270,18 @@ read_mage(attrib * a, void * owner, struct storage * store) } } } - read_spellist(&mage->spells, mage->magietyp, store); + read_spells(&mage->spells, mage->magietyp, store); return AT_READ_OK; } -void write_spelllist(const spell_list * slist, struct storage * store) +void write_spells(struct quicklist * slist, struct storage * store) { - while (slist!=NULL) { - spell * sp = slist->data; + quicklist * ql; + int qi; + + for (ql=slist,qi=0;ql;ql_advance(&ql, &qi, 1)) { + spell * sp = (spell *)ql_get(ql, qi); store->w_tok(store, sp->sname); - slist = slist->next; } store->w_tok(store, "end"); } @@ -296,7 +299,7 @@ write_mage(const attrib * a, const void * owner, struct storage * store) store->w_tok(store, mage->combatspells[i].sp?mage->combatspells[i].sp->sname:"none"); store->w_int(store, mage->combatspells[i].level); } - write_spelllist(mage->spells, store); + write_spells(mage->spells, store); } attrib_type at_mage = { @@ -404,6 +407,13 @@ static boolean know_school(const faction * f, magic_t school) #define COMMONSPELLS 1 /* number of new common spells per level */ #define MAXSPELLS 256 +static boolean +has_spell(quicklist * ql, const spell * sp) +{ + int qi; + return ql_set_find(&ql, &qi, sp)!=0; +} + /** update the spellbook with a new level * Written for Eressea 1.1 */ @@ -411,18 +421,16 @@ void update_spellbook(faction * f, int level) { spell * commonspells[MAXSPELLS]; - int numspells = 0; - spell_list * slist; + int qi, numspells = 0; + quicklist * ql; - for (slist=spells;slist!=NULL;slist=slist->next) { - spell * sp = slist->data; + for (qi=0,ql=spells;ql;ql_advance(&ql, &qi, 1)) { + spell * sp = (spell *)ql_get(ql, qi); if (sp->magietyp == M_COMMON && level>f->max_spelllevel && sp->level<=level) { commonspells[numspells++] = sp; } else { if (know_school(f, sp->magietyp) && sp->level <= level) { - if (!has_spell(f->spellbook, sp)) { - add_spell(&f->spellbook, sp); - } + add_spell(&f->spellbook, sp); } } } @@ -442,7 +450,7 @@ update_spellbook(faction * f, int level) while (maxspell>0 && sp && sp->level<=f->max_spelllevel && !has_spell(f->spellbook, sp)); if (sp) { - add_spell(&f->spellbook, sp); + ql_set_insert(&f->spellbook, sp); commonspells[spellno] = 0; } } @@ -454,9 +462,11 @@ void updatespelllist(unit * u) { int sk = eff_skill(u, SK_MAGIC, u->region); - spell_list * slist = spells; + quicklist * ql = spells; + int qi; struct sc_mage * mage = get_mage(u); boolean ismonster = is_monsters(u->faction); + quicklist ** dst; if (mage->magietyp==M_GRAY) { /* Magier mit M_GRAY bekommen weder Sprüche angezeigt noch @@ -466,18 +476,19 @@ updatespelllist(unit * u) } if (FactionSpells()) { - slist = u->faction->spellbook; + ql = u->faction->spellbook; } + dst = get_spelllist(mage, u->faction); - for (;slist!=NULL;slist=slist->next) { - spell * sp = slist->data; + for (qi=0;ql;ql_advance(&ql, &qi, 1)) { + spell * sp = (spell *)ql_get(ql, qi); if (sp->level<=sk) { boolean know = u_hasspell(u, sp); if (know || sp->magietyp==M_COMMON || know_school(u->faction, sp->magietyp)) { faction * f = u->faction; - if (!know) add_spell(get_spelllist(mage, u->faction), sp); + if (!know) add_spell(dst, sp); if (!ismonster && !already_seen(u->faction, sp)) { a_add(&f->attribs, a_new(&at_reportspell))->data.v = sp; a_add(&f->attribs, a_new(&at_seenspell))->data.v = sp; @@ -511,39 +522,24 @@ create_mage(unit * u, magic_t mtyp) /* Funktionen für die Bearbeitung der List-of-known-spells */ void -add_spell(spell_list ** slistp, spell * sp) +add_spell(struct quicklist ** slistp, spell * sp) { - if (slistp==NULL) { - log_error(("add_spell: unit is not a mage.\n")); - } else { - spell_list ** slist = spelllist_find(slistp, sp); - if (*slist) { - spell * psp = (*slist)->data; - if (psp==sp) { - log_error(("add_spell: unit already has spell '%s'.\n", sp->sname)); - return; - } - } - spelllist_add(slist, sp); - } -} + quicklist * ql = *slistp; + int qi; -boolean -has_spell(spell_list * slist, const spell * sp) -{ - if (slist!=NULL) { - spell_list * sfind = *spelllist_find(&slist, sp); - return sfind!=NULL && sfind->data==sp; + if (ql_set_find(&ql, &qi, sp)) { + log_error(("add_spell: the list already contains the spell '%s'.\n", sp->sname)); + } else { + ql_set_insert(slistp, sp); } - return false; } boolean u_hasspell(const struct unit *u, const struct spell * sp) { sc_mage * mage = get_mage(u); - if (mage) return has_spell(mage->spells, sp); - return false; + + return (mage)?has_spell(mage->spells, sp):false; } /* ------------------------------------------------------------- */ @@ -2881,40 +2877,7 @@ curse_name(const curse_type * ctype, const struct locale * lang) return LOC(lang, mkname("spell", ctype->cname)); } -void -spelllist_add(spell_list ** lspells, spell * sp) -{ - spell_list * entry; - - while (*lspells) { - spell_list * slist = *lspells; - if (slist->data->id==sp->id) { - if (slist->data==sp) { - log_error(("trying to add spell '%s' to a list twice.\n", sp->sname)); - return; - } - } - if (slist->data->id>sp->id) break; - lspells = &slist->next; - } - entry = malloc(sizeof(spell_list)); - entry->data = sp; - entry->next = *lspells; - *lspells = entry; -} - -spell_list ** -spelllist_find(spell_list ** lspells, const spell * sp) -{ - while (*lspells) { - spell_list * slist = *lspells; - if (slist->data->id>=sp->id) break; - lspells = &slist->next; - } - return lspells; -} - -extern struct spell_list ** get_spelllist(struct sc_mage * mage, struct faction * f) +struct quicklist ** get_spelllist(struct sc_mage * mage, struct faction * f) { if (mage) { return &mage->spells; diff --git a/src/kernel/magic.h b/src/kernel/magic.h index 623c5f516..c3b65a038 100644 --- a/src/kernel/magic.h +++ b/src/kernel/magic.h @@ -25,6 +25,7 @@ extern "C" { #include "curse.h" struct fighter; struct building; +struct quicklist; /* ------------------------------------------------------------- */ @@ -123,7 +124,7 @@ typedef struct sc_mage { int spchange; int spellcount; combatspell combatspells[MAXCOMBATSPELLS]; - struct spell_list * spells; + struct quicklist * spells; } sc_mage; /* ------------------------------------------------------------- */ @@ -175,13 +176,6 @@ typedef struct spell { void (*patzer) (castorder*); } spell; -typedef struct spell_list { - struct spell_list * next; - spell * data; /* TODO: should be const */ -} spell_list; - -extern void spelllist_add(spell_list ** lspells, struct spell * sp); -extern spell_list ** spelllist_find(spell_list ** lspells, const struct spell * sp); /* ------------------------------------------------------------- */ /* besondere Spruchtypen */ @@ -282,10 +276,8 @@ void set_combatspell(struct unit *u, spell *sp, struct order * ord, int level); /* setzt Kampfzauber */ void unset_combatspell(struct unit *u, spell *sp); /* löscht Kampfzauber */ -void add_spell(spell_list ** slistp, spell *sp); +void add_spell(struct quicklist ** slistp, spell *sp); /* fügt den Spruch mit der Id spellid der Spruchliste der Einheit hinzu. */ -boolean has_spell(struct spell_list *slist, const struct spell * sp); - /* prüft, ob der Spruch in der Spruchliste der Einheit steht. */ boolean u_hasspell(const struct unit * u, const struct spell * sp); /* prüft, ob der Spruch in der Spruchliste der Einheit steht. */ void update_spellbook(struct faction * f, int level); @@ -383,10 +375,10 @@ extern const char * curse_name(const struct curse_type * ctype, const struct loc extern struct message * msg_unitnotfound(const struct unit * mage, struct order * ord, const struct spllprm * spobj); extern int FactionSpells(void); -extern struct spell_list ** get_spelllist(struct sc_mage * mage, struct faction * f); +extern struct quicklist ** get_spelllist(struct sc_mage * mage, struct faction * f); -extern void write_spelllist(const struct spell_list * slist, struct storage * store); -extern void read_spellist(struct spell_list ** slistp, magic_t mtype, struct storage * store); +extern void write_spells(struct quicklist * slist, struct storage * store); +extern void read_spells(struct quicklist ** slistp, magic_t mtype, struct storage * store); extern double MagicPower(void); #ifdef __cplusplus diff --git a/src/kernel/reports.c b/src/kernel/reports.c index 8ba41875b..c22c5f392 100644 --- a/src/kernel/reports.c +++ b/src/kernel/reports.c @@ -622,13 +622,13 @@ bufunit(const faction * f, const unit * u, int indent, int mode, char * buf, siz sc_mage * m = get_mage(u); if (m!=NULL) { - spell_list *slist = m->spells; - int t = effskill(u, SK_MAGIC); + quicklist * ql = m->spells; + int qi, t = effskill(u, SK_MAGIC); int bytes = snprintf(bufp, size, ". Aura %d/%d", get_spellpoints(u), max_spellpoints(u->region,u)); if (bytes<0 || wrptr(&bufp, &size, bytes)!=0) WARN_STATIC_BUFFER(); - for (dh=0; slist; slist=slist->next) { - spell * sp = slist->data; + for (dh=0,qi=0; ql; ql_advance(&ql, &qi, 1)) { + spell * sp = (spell *)ql_get(ql, qi); if (sp->level > t) continue; if (!dh) { bytes = snprintf(bufp, size, ", %s: ", LOC(f->locale, "nr_spells")); diff --git a/src/kernel/save.c b/src/kernel/save.c index 19db607ce..17a17b685 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -1288,7 +1288,7 @@ readfaction(struct storage * store) read_groups(store, f); f->spellbook = NULL; if (store->version>=REGIONOWNER_VERSION) { - read_spellist(&f->spellbook, f->magiegebiet, store); + read_spells(&f->spellbook, f->magiegebiet, store); } return f; } @@ -1352,7 +1352,7 @@ writefaction(struct storage * store, const faction * f) store->w_id(store, 0); store->w_brk(store); write_groups(store, f->groups); - write_spelllist(f->spellbook, store); + write_spells(f->spellbook, store); } int diff --git a/src/kernel/spell.c b/src/kernel/spell.c index 7bd05cf15..f48fdd0d5 100644 --- a/src/kernel/spell.c +++ b/src/kernel/spell.c @@ -33,12 +33,13 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include +#include /* Bitte die Sprüche nach Gebieten und Stufe ordnen, denn in derselben * Reihenfolge wie in Spelldaten tauchen sie auch im Report auf */ -spell_list * spells = NULL; +quicklist * spells = NULL; void register_spell(spell * sp) @@ -46,7 +47,7 @@ register_spell(spell * sp) if (sp->id==0) { sp->id = hashstring(sp->sname); } - spelllist_add(&spells, sp); + add_spell(&spells, sp); } /** versucht einen Spruch über gebiet + name zu identifizieren. @@ -54,15 +55,16 @@ register_spell(spell * sp) spell * find_spell(magic_t mtype, const char * name) { - spell_list * slist = spells; + quicklist * ql = spells; + int qi; spell * spx = NULL; - while (slist) { - spell * sp = slist->data; + + for (qi=0;ql;ql_advance(&ql, &qi, 1)) { + spell * sp = (spell *)ql_get(ql, qi); if (strcmp(name, sp->sname)==0) { if (mtype==M_NONE || sp->magietyp==mtype) return sp; spx = sp; } - slist = slist->next; } if (spx==NULL) { log_error(("cannot find spell by name: %s\n", name)); @@ -86,13 +88,14 @@ static spell_names * spellnames; static spell_names * init_spellnames(const struct locale * lang, magic_t mtype) { - spell_list * slist; - spell_names * sn = calloc(sizeof(spell_names), 1); + quicklist * ql; + int qi; + spell_names * sn = (spell_names *)calloc(sizeof(spell_names), 1); sn->next = spellnames; sn->lang = lang; sn->mtype = mtype; - for (slist=spells;slist!=NULL;slist=slist->next) { - spell * sp = slist->data; + for (qi=0,ql=spells;ql;ql_advance(&ql, &qi, 1)) { + spell * sp = (spell *)ql_get(ql, qi); if (sp->magietyp==mtype) { const char * n = spell_name(sp, lang); variant token; @@ -147,11 +150,11 @@ get_spellfromtoken(unit *u, const char *name, const struct locale * lang) if (m==NULL) return NULL; sp = get_spellfromtoken_i(name, lang, m->magietyp); if (sp!=NULL) { - spell_list * slist = m->spells; + quicklist * ql = m->spells; + int qi; - while (slist && slist->data->id<=sp->id) { - if (sp==slist->data) return sp; - slist = slist->next; + if (ql_set_find(&ql, &qi, sp)) { + return sp; } } return NULL; @@ -160,16 +163,19 @@ get_spellfromtoken(unit *u, const char *name, const struct locale * lang) spell * find_spellbyid(magic_t mtype, spellid_t id) { - spell_list * slist; + quicklist * ql; + int qi; assert(id>=0); if (id==0) return NULL; - for (slist=spells;slist!=NULL;slist=slist->next) { - spell* sp = slist->data; - if (sp->id == id) return sp; + for (qi=0, ql=spells; ql; ql_advance(&ql, &qi, 1)) { + spell * sp = (spell *)ql_get(ql, qi); + if (sp->id == id) { + return sp; + } } - for (slist=spells;slist!=NULL;slist=slist->next) { - spell* sp = slist->data; + for (qi=0, ql=spells; ql; ql_advance(&ql, &qi, 1)) { + spell * sp = (spell *)ql_get(ql, qi); unsigned int hashid = hashstring(sp->sname); if (hashid==id) { if (sp->magietyp==mtype || mtype==M_NONE) { diff --git a/src/kernel/spell.h b/src/kernel/spell.h index 9a250deb0..4565d2053 100644 --- a/src/kernel/spell.h +++ b/src/kernel/spell.h @@ -42,7 +42,7 @@ extern "C" { extern struct attrib_type at_unitdissolve; extern struct attrib_type at_wdwpyramid; - extern struct spell_list * spells; + extern struct quicklist * spells; extern void register_spell(struct spell * sp); extern struct spell * find_spell(magic_t mtype, const char * name); extern struct spell * find_spellbyid(magic_t mtype, spellid_t i); diff --git a/src/util/quicklist.c b/src/util/quicklist.c index e3986eb75..215bb0065 100644 --- a/src/util/quicklist.c +++ b/src/util/quicklist.c @@ -147,6 +147,22 @@ void ql_free(struct quicklist * ql) free(ql); } +int ql_set_remove(struct quicklist ** qlp, void * data) +{ + int qi; + quicklist * ql = *qlp; + + if (!ql) return 0; + + for (qi=0;qi!=ql->num_elements;++qi) { + void * qd = ql_get(ql, qi); + if (qd==data) { + return ql_delete(qlp, qi)==0; + } + } + return ql_set_remove(&ql->next, data); +} + int ql_set_insert(struct quicklist ** qlp, void * data) { if (*qlp) { @@ -174,4 +190,31 @@ int ql_set_insert(struct quicklist ** qlp, void * data) } ql_push(qlp, data); return 0; -} \ No newline at end of file +} + +int ql_set_find(struct quicklist ** qlp, int * qip, const void * data) +{ + quicklist * ql = *qlp; + int qi; + + while (ql && ql->elements[ql->num_elements-1]next; + } + + if (!ql) return 0; + + /* TODO: OPT | binary search */ + for (qi=0;qi!=ql->num_elements;++qi) { + if (ql->elements[qi]>data) { + return 0; + } + if (ql->elements[qi]==data) { + if (qip) { + *qip = qi; + *qlp = ql; + } + return 1; + } + } + return 0; +} diff --git a/src/util/quicklist.h b/src/util/quicklist.h index cc7186a31..f3068de48 100644 --- a/src/util/quicklist.h +++ b/src/util/quicklist.h @@ -34,6 +34,9 @@ void ql_free(struct quicklist * ql); /* you can use it as a set (sorted pointers)*/ int ql_set_insert(struct quicklist ** qlp, void * data); +int ql_set_find(struct quicklist ** qlp, int * qip, const void * data); +int ql_set_remove(struct quicklist ** qlp, void * data); + #ifdef __cplusplus } #endif diff --git a/src/util/quicklist_test.c b/src/util/quicklist_test.c index bb82afa12..8dd677405 100644 --- a/src/util/quicklist_test.c +++ b/src/util/quicklist_test.c @@ -26,7 +26,7 @@ static void test_insert_delete_gives_null(CuTest * tc) { static void test_set_insert(CuTest * tc) { struct quicklist * ql = NULL; - int a; + int a, qi; a = ql_set_insert(&ql, (void*)42); CuAssertIntEquals(tc, 1, ql_length(ql)); CuAssertIntEquals(tc, 0, a); @@ -42,6 +42,64 @@ static void test_set_insert(CuTest * tc) { CuAssertIntEquals(tc, 41, (int)ql_get(ql, 0)); CuAssertIntEquals(tc, 42, (int)ql_get(ql, 1)); CuAssertIntEquals(tc, 43, (int)ql_get(ql, 2)); + + a = ql_set_find(&ql, &qi, (void *)49); + CuAssertIntEquals(tc, 0, a); + a = ql_set_find(&ql, &qi, (void *)42); + CuAssertIntEquals(tc, 1, a); + CuAssertIntEquals(tc, 42, (int)ql_get(ql, qi)); +} + +static void test_set_remove(CuTest * tc) { + struct quicklist * ql = NULL, * q2; + int a; + + ql_set_insert(&ql, (void*)41); + ql_set_insert(&ql, (void*)42); + ql_set_insert(&ql, (void*)43); + + q2 = ql; + + a = ql_set_remove(&ql, (void*)42); + CuAssertPtrEquals(tc, q2, ql); + CuAssertIntEquals(tc, 1, a); + CuAssertIntEquals(tc, 41, (int)ql_get(ql, 0)); + CuAssertIntEquals(tc, 43, (int)ql_get(ql, 1)); + CuAssertIntEquals(tc, 2, ql_length(ql)); + + a = ql_set_remove(&ql, (void*)42); + CuAssertPtrEquals(tc, q2, ql); + CuAssertIntEquals(tc, 0, a); + + ql_set_remove(&ql, (void*)41); + ql_set_remove(&ql, (void*)43); + CuAssertPtrEquals(tc, 0, ql); +} + +static void test_set_find(CuTest * tc) { + struct quicklist * ql = NULL, * q2; + int a, qi; + + for (a=0;a!=32;++a) { + ql_set_insert(&ql, (void *)a); + } + + q2 = ql; + a = ql_set_find(&q2, 0, (void *)31); + CuAssertIntEquals(tc, 1, a); + CuAssertPtrEquals(tc, ql, q2); + + q2 = ql; + a = ql_set_find(&ql, &qi, (void *)0); + CuAssertIntEquals(tc, 1, a); + CuAssertIntEquals(tc, 0, qi); + CuAssertPtrEquals(tc, ql, q2); + + q2 = ql; + a = ql_set_find(&ql, &qi, (void *)31); + CuAssertIntEquals(tc, 1, a); + CuAssertIntEquals(tc, 31, (int)ql_get(ql, qi)); + CuAssertTrue(tc, ql!=q2); } static void test_advance(CuTest * tc) { @@ -111,6 +169,8 @@ CuSuite* get_quicklist_suite(void) SUITE_ADD_TEST(suite, test_advance); SUITE_ADD_TEST(suite, test_push); SUITE_ADD_TEST(suite, test_insert); + SUITE_ADD_TEST(suite, test_set_remove); + SUITE_ADD_TEST(suite, test_set_find); SUITE_ADD_TEST(suite, test_insert_delete_gives_null); SUITE_ADD_TEST(suite, test_insert_many); SUITE_ADD_TEST(suite, test_delete_rand);