1. spell_list was pretty much used everywhere in the code, and is now also a quicklist.

2. Cleaned up the bindings for quicklist to Lua.
This commit is contained in:
Enno Rehling 2011-02-26 00:26:14 -08:00
parent b28fa19d01
commit b2d6203cec
20 changed files with 254 additions and 222 deletions

View file

@ -15,6 +15,7 @@ without prior permission by the authors of Eressea.
#include <kernel/config.h>
#include <kernel/unit.h>
#include <kernel/faction.h>
#include <kernel/ship.h>
#include <kernel/building.h>
#include <kernel/region.h>

View file

@ -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

View file

@ -43,6 +43,7 @@ without prior permission by the authors of Eressea.
#include <util/event.h>
#include <util/lists.h>
#include <util/log.h>
#include <util/quicklist.h>
#include <lua.h>
#include <tolua.h>
@ -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)

View file

@ -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

View file

@ -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

View file

@ -93,6 +93,7 @@
<ClCompile Include="gamecode\economy.c" />
<ClCompile Include="eressea.c" />
<ClCompile Include="gamecode\give.c" />
<ClCompile Include="gamecode\xmlreport.c" />
<ClCompile Include="gmtool.c" />
<ClCompile Include="gamecode\items.c" />
<ClCompile Include="gamecode\laws.c" />
@ -119,6 +120,7 @@
<ClInclude Include="gamecode\economy.h" />
<ClInclude Include="eressea.h" />
<ClInclude Include="gamecode\give.h" />
<ClInclude Include="gamecode\xmlreport.h" />
<ClInclude Include="gmtool.h" />
<ClInclude Include="gmtool_structs.h" />
<ClInclude Include="gamecode\items.h" />

View file

@ -65,6 +65,9 @@
<ClCompile Include="gamecode\summary.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="gamecode\xmlreport.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="gamecode\archetype.h">
@ -121,5 +124,8 @@
<ClInclude Include="gamecode\summary.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="gamecode\xmlreport.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View file

@ -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);

View file

@ -58,6 +58,7 @@ without prior permission by the authors of Eressea.
#include <util/goodies.h>
#include <util/language.h>
#include <util/message.h>
#include <util/quicklist.h>
#include <util/unicode.h>
#include <util/xml.h>
@ -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)));
}

View file

@ -40,6 +40,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <util/lists.h>
#include <util/language.h>
#include <util/log.h>
#include <util/quicklist.h>
#include <util/resolve.h>
#include <util/rng.h>
#include <util/storage.h>
@ -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) {

View file

@ -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;

View file

@ -53,6 +53,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <util/lists.h>
#include <util/log.h>
#include <util/parser.h>
#include <util/quicklist.h>
#include <util/resolve.h>
#include <util/rand.h>
#include <util/rng.h>
@ -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;

View file

@ -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

View file

@ -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"));

View file

@ -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

View file

@ -33,12 +33,13 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <util/language.h>
#include <util/log.h>
#include <util/umlaut.h>
#include <util/quicklist.h>
/* 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) {

View file

@ -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);

View file

@ -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;
}
}
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]<data) {
ql=ql->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;
}

View file

@ -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

View file

@ -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);