From e3d49f16c7be138ae3f8c1cbf61b3e9a66bf390f Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 4 Oct 2024 22:36:36 +0200 Subject: [PATCH 1/4] replace custom hashing with stb hashmap --- src/kernel/attrib.c | 70 ++++++++++++++++++++++----------------------- src/kernel/attrib.h | 4 --- 2 files changed, 35 insertions(+), 39 deletions(-) diff --git a/src/kernel/attrib.c b/src/kernel/attrib.c index 2c50ed286..fc3947b42 100644 --- a/src/kernel/attrib.c +++ b/src/kernel/attrib.c @@ -8,6 +8,8 @@ #include #include +#include + #include #include #include @@ -112,8 +114,10 @@ void a_finalizestring(variant * var) free(var->v); } -#define MAXATHASH 61 -static attrib_type *at_hash[MAXATHASH]; +static struct at_hash_t { + unsigned int key; + attrib_type *value; +} *at_hash; static unsigned int __at_hashkey(const char *s) { @@ -128,46 +132,42 @@ static unsigned int __at_hashkey(const char *s) void at_register(attrib_type * at) { - attrib_type *find; - - if (at->read == NULL) { - log_warning("registering non-persistent attribute %s.\n", at->name); - } - at->hashkey = __at_hashkey(at->name); - find = at_hash[at->hashkey % MAXATHASH]; - while (find && at->hashkey != find->hashkey) { - find = find->nexthash; - } - if (find && find == at) { - log_warning("attribute '%s' was registered more than once\n", at->name); - return; + unsigned int hash = __at_hashkey(at->name); +#ifndef NDEBUG + ptrdiff_t i = hmgeti(at_hash, hash); + if (i >= 0) { + if (at == at_hash[i].value) { + log_error("attribute %s is already registered", at->name); + return; + } + else { + log_fatal("attributes %s and %s hash to the same key", at->name, at_hash[i].value->name); + } } - else { - assert(!find || !"hashkey is already in use"); +#endif + if (at->read == NULL) { + log_error("registering non-persistent attribute %s.\n", at->name); } - at->nexthash = at_hash[at->hashkey % MAXATHASH]; - at_hash[at->hashkey % MAXATHASH] = at; + hmput(at_hash, hash, at); } static attrib_type *at_find_key(unsigned int hk) { - attrib_type *find = at_hash[hk % MAXATHASH]; - while (find && hk != find->hashkey) - find = find->nexthash; - if (!find) { - const char *translate[3][2] = { - { "zielregion", "targetregion" }, /* remapping: from 'zielregion, heute targetregion */ - { "verzaubert", "curse" }, /* remapping: frueher verzaubert, jetzt curse */ + ptrdiff_t i = hmgeti(at_hash, hk); + if (i < 0) { + int k; + const char *aliases[3][2] = { + { "zielregion", "targetregion" }, /* remapping: from 'zielregion, heute targetregion */ + { "verzaubert", "curse" }, /* remapping: frueher verzaubert, jetzt curse */ { NULL, NULL } }; - int i = 0; - while (translate[i][0]) { - if (__at_hashkey(translate[i][0]) == hk) - return at_find_key(__at_hashkey(translate[i][1])); - ++i; + for (k = 0; aliases[k][0]; ++k) { + if (__at_hashkey(aliases[k][0]) == hk) + return at_find_key(__at_hashkey(aliases[k][1])); } + return NULL; } - return find; + return at_hash[i].value; } struct attrib_type *at_find(const char *name) { @@ -482,8 +482,8 @@ void a_write(struct storage *store, const attrib * attribs, const void *owner) { while (na) { if (na->type->write) { - assert(na->type->hashkey || !"attribute not registered"); - WRITE_INT(store, na->type->hashkey); + unsigned int hashkey = __at_hashkey(na->type->name); + WRITE_INT(store, hashkey); na->type->write(&na->data, owner, store); na = na->next; } @@ -496,5 +496,5 @@ void a_write(struct storage *store, const attrib * attribs, const void *owner) { void attrib_done(void) { cb_clear(&cb_deprecated); - memset(at_hash, 0, sizeof(at_hash[0]) * MAXATHASH); + hmfree(at_hash); } diff --git a/src/kernel/attrib.h b/src/kernel/attrib.h index f821867eb..9302b5412 100644 --- a/src/kernel/attrib.h +++ b/src/kernel/attrib.h @@ -34,9 +34,6 @@ extern "C" { int(*read) (union variant *, void *owner, struct gamedata *); /* return AT_READ_OK on success, AT_READ_FAIL if attrib needs removal */ void(*upgrade) (struct attrib **alist, struct attrib *a); unsigned int flags; - /* ---- internal data, do not modify: ---- */ - struct attrib_type *nexthash; - unsigned int hashkey; } attrib_type; void at_register(attrib_type * at); @@ -48,7 +45,6 @@ extern "C" { attrib *a_select(attrib * a, const void *data, bool(*compare) (const attrib *, const void *)); attrib *a_find(attrib * a, const attrib_type * at); - attrib** a_find_it(attrib** ap, const attrib_type* at); attrib *a_add(attrib ** pa, attrib * at); int a_remove(attrib ** pa, attrib * at); void a_removeall(attrib ** a, const attrib_type * at); From 516a8cbc463b6548b0ed4a29ce68f288f820d293 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 15 Oct 2024 20:50:06 +0200 Subject: [PATCH 2/4] use stb arrays for per-faction regional messages --- src/kernel/region.c | 61 ++++++++++++++++++++++++++------------------- src/kernel/region.h | 11 ++++---- src/tests.c | 21 ++++++++-------- 3 files changed, 53 insertions(+), 40 deletions(-) diff --git a/src/kernel/region.c b/src/kernel/region.c index 8fad3c1c3..d78d62cdd 100644 --- a/src/kernel/region.c +++ b/src/kernel/region.c @@ -936,14 +936,17 @@ void free_region(region * r) r->msgs = 0; } - while (r->individual_messages) { - struct individual_message *msg = r->individual_messages; - r->individual_messages = msg->next; - if (msg->msgs) { - free_messagelist(msg->msgs->begin); - free(msg->msgs); + if (r->individual_messages) { + ptrdiff_t i, l = arrlen(r->individual_messages); + for (i = 0; i != l; ++i) { + faction_messages *msg = r->individual_messages + i; + if (msg->msgs) { + free_messagelist(msg->msgs->begin); + free(msg->msgs); + } } - free(msg); + arrfree(r->individual_messages); + r->individual_messages = NULL; } a_removeall(&r->attribs, NULL); @@ -1307,32 +1310,40 @@ void write_region_reference(const region * r, struct storage *store) struct message_list *r_getmessages(const struct region *r, const struct faction *viewer) { - struct individual_message *imsg = r->individual_messages; - while (imsg && (imsg)->viewer != viewer) - imsg = imsg->next; - if (imsg) - return imsg->msgs; + if (r->individual_messages) { + ptrdiff_t i, l = arrlen(r->individual_messages); + for (i = 0; i != l; ++i) { + faction_messages *imsg = r->individual_messages + i; + if (imsg->viewer == viewer) { + return imsg->msgs; + } + } + } return NULL; } struct message *r_addmessage(struct region *r, const struct faction *viewer, -struct message *msg) + struct message *msg) { assert(r); if (viewer) { - struct individual_message *imsg; - imsg = r->individual_messages; - while (imsg && imsg->viewer != viewer) - imsg = imsg->next; - if (imsg == NULL) { - imsg = malloc(sizeof(struct individual_message)); - if (!imsg) abort(); - imsg->next = r->individual_messages; - imsg->msgs = NULL; - r->individual_messages = imsg; - imsg->viewer = viewer; + faction_messages *vmsg = NULL; + if (r->individual_messages) { + ptrdiff_t i, l = arrlen(r->individual_messages); + for (i = 0; i != l; ++i) { + faction_messages *imsg = r->individual_messages + i; + if (imsg->viewer == viewer) { + vmsg = imsg; + break; + } + } + } + if (!vmsg) { + vmsg = stbds_arraddnptr(r->individual_messages, 1); + vmsg->viewer = viewer; + vmsg->msgs = NULL; } - return add_message(&imsg->msgs, msg); + return add_message(&vmsg->msgs, msg); } return add_message(&r->msgs, msg); } diff --git a/src/kernel/region.h b/src/kernel/region.h index a952303a6..e7262fc36 100644 --- a/src/kernel/region.h +++ b/src/kernel/region.h @@ -89,6 +89,11 @@ typedef enum seen_mode { seen_battle } seen_mode; +typedef struct faction_messages { + const struct faction *viewer; + struct message_list *msgs; +} faction_messages; + typedef struct region { struct region *next; struct land_region *land; @@ -105,11 +110,7 @@ typedef struct region { int flags; unsigned short age; struct message_list *msgs; - struct individual_message { - struct individual_message *next; /* FIXME: stb_ds array, not list */ - const struct faction *viewer; - struct message_list *msgs; - } *individual_messages; + struct faction_messages *individual_messages; struct attrib *attribs; const struct terrain_type *terrain; struct rawmaterial *resources; diff --git a/src/tests.c b/src/tests.c index fb0046fe4..4220943f4 100644 --- a/src/tests.c +++ b/src/tests.c @@ -595,10 +595,13 @@ struct message *test_find_faction_message(const faction *f, const char *name) struct message *test_find_region_message(const region *r, const char *name, const faction *f) { if (f) { - const struct individual_message *imsg; - for (imsg = r->individual_messages; imsg; imsg = imsg->next) { - if (imsg->viewer == f) { - return test_find_messagetype(imsg->msgs, name); + if (r->individual_messages) { + ptrdiff_t i, l = arrlen(r->individual_messages); + for (i = 0; i != l; ++i) { + faction_messages *msg = r->individual_messages + i; + if (msg->viewer == f) { + return test_find_messagetype(msg->msgs, name); + } } } return NULL; @@ -639,14 +642,12 @@ void test_clear_region_messages(struct region *r) test_clear_messagelist(&r->msgs); } if (r->individual_messages) { - struct individual_message *imsg = r->individual_messages; - while (imsg) - { - struct individual_message *inext = imsg->next; + ptrdiff_t i, l = arrlen(r->individual_messages); + for (i = 0; i != l; ++i) { + faction_messages *imsg = r->individual_messages + i; test_clear_messagelist(&imsg->msgs); - free(imsg); - imsg = inext; } + arrfree(r->individual_messages); r->individual_messages = NULL; } } From 263937ebc779329443fcf89f1a81ef7460d44d39 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 15 Oct 2024 21:00:44 +0200 Subject: [PATCH 3/4] refactor: some cleanup of message_list code --- src/bindings.c | 3 +-- src/kernel/faction.c | 13 ++++--------- src/kernel/messages.c | 10 +++++++++- src/kernel/messages.h | 3 ++- src/kernel/messages.test.c | 8 +++----- src/kernel/region.c | 8 +++----- src/tests.c | 3 +-- 7 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/bindings.c b/src/bindings.c index 8923d5d3b..539bac6d9 100755 --- a/src/bindings.c +++ b/src/bindings.c @@ -405,8 +405,7 @@ static int tolua_turn_begin(lua_State * L) UNUSED_ARG(L); for (f = factions; f; f = f->next) { if (f->msgs) { - free_messagelist(f->msgs->begin); - free(f->msgs); + free_messagelist(f->msgs); f->msgs = NULL; } } diff --git a/src/kernel/faction.c b/src/kernel/faction.c index add9e152b..52c742a4b 100755 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -59,23 +59,19 @@ faction *factions; /** remove the faction from memory. - * this frees all memory that's only accessible through the faction, - * but you should still call funhash and remove the faction from the - * global list. + * this frees all memory that's only accessible through the faction. */ static void free_faction(faction * f) { funhash(f); if (f->msgs) { - free_messagelist(f->msgs->begin); - free(f->msgs); + free_messagelist(f->msgs); } while (f->battles) { struct bmsg *bm = f->battles; f->battles = bm->next; if (bm->msgs) { - free_messagelist(bm->msgs->begin); - free(bm->msgs); + free_messagelist(bm->msgs); } free(bm); } @@ -95,7 +91,6 @@ static void free_faction(faction * f) free(f->name); if (f->seen_factions) { selist_free(f->seen_factions); - f->seen_factions = 0; } while (f->attribs) { @@ -105,6 +100,7 @@ static void free_faction(faction * f) i_freeall(&f->items); freelist(f->origin); + free(f); } #define FMAXHASH 2039 @@ -335,7 +331,6 @@ void free_flist(faction **fp) { faction *f = flist; flist = f->next; free_faction(f); - free(f); } *fp = NULL; } diff --git a/src/kernel/messages.c b/src/kernel/messages.c index 61e6844ee..761389295 100644 --- a/src/kernel/messages.c +++ b/src/kernel/messages.c @@ -281,7 +281,7 @@ void syntax_error(const struct unit *u, struct order *ord) } } -void free_messagelist(mlist *msgs) +void free_mlist(mlist *msgs) { struct mlist **mlistptr; for (mlistptr = &msgs; *mlistptr;) { @@ -292,6 +292,14 @@ void free_messagelist(mlist *msgs) } } +void free_messagelist(message_list *msgs) +{ + free_mlist(msgs->begin); + msgs->begin = NULL; + msgs->end = NULL; + free(msgs); +} + message *add_message(message_list ** pm, message * m) { if (m != NULL) { diff --git a/src/kernel/messages.h b/src/kernel/messages.h index 75f59ad74..acb9de98d 100644 --- a/src/kernel/messages.h +++ b/src/kernel/messages.h @@ -46,7 +46,8 @@ struct message; enum msg_t; void message_handle_missing(int mode); -void free_messagelist(struct mlist *msgs); +void free_mlist(struct mlist *msgs); +void free_messagelist(struct message_list *msgs); struct message *msg_message(const char *name, const char *sig, ...); struct message *msg_feedback(const struct unit *, struct order *cmd, diff --git a/src/kernel/messages.test.c b/src/kernel/messages.test.c index 0eb87c79e..50e9f2b5c 100644 --- a/src/kernel/messages.test.c +++ b/src/kernel/messages.test.c @@ -92,11 +92,9 @@ static void test_merge_split(CuTest *tc) { CuAssertPtrEquals(tc, append->begin, mlist->begin->next); split_messages(mlist, split); CuAssertPtrEquals(tc, NULL, mlist->begin->next); - free_messagelist(*split); - free_messagelist(mlist->begin); - free(mlist); - free_messagelist(append->begin); - free(append); + free_mlist(*split); + free_messagelist(mlist); + free_messagelist(append); test_teardown(); } diff --git a/src/kernel/region.c b/src/kernel/region.c index d78d62cdd..b6b7118bd 100644 --- a/src/kernel/region.c +++ b/src/kernel/region.c @@ -931,9 +931,8 @@ void free_region(region * r) free_land(r->land); if (r->msgs) { - free_messagelist(r->msgs->begin); - free(r->msgs); - r->msgs = 0; + free_messagelist(r->msgs); + r->msgs = NULL; } if (r->individual_messages) { @@ -941,8 +940,7 @@ void free_region(region * r) for (i = 0; i != l; ++i) { faction_messages *msg = r->individual_messages + i; if (msg->msgs) { - free_messagelist(msg->msgs->begin); - free(msg->msgs); + free_messagelist(msg->msgs); } } arrfree(r->individual_messages); diff --git a/src/tests.c b/src/tests.c index 4220943f4..3667abfd4 100644 --- a/src/tests.c +++ b/src/tests.c @@ -624,8 +624,7 @@ int test_count_messagetype(struct message_list *msgs, const char *name) void test_clear_messagelist(message_list **msgs) { if (*msgs) { - free_messagelist((*msgs)->begin); - free(*msgs); + free_messagelist(*msgs); *msgs = NULL; } } From ffbe2579f376b80fa38fd8286dae949c8a60fbd1 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 2 Nov 2024 18:12:40 +0100 Subject: [PATCH 4/4] in spellbooks, use stb arrays, not selist --- scripts/tests/study.lua | 4 +--- src/bind_unit.c | 36 +++++++++++++++++++------------- src/creport.c | 8 +++---- src/kernel/spellbook.c | 46 ++++++++++++++++------------------------- src/kernel/spellbook.h | 2 +- src/laws.c | 15 +++++++------- src/magic.c | 16 +++++++------- src/magic.test.c | 3 ++- src/reports.c | 8 +++---- 9 files changed, 66 insertions(+), 72 deletions(-) diff --git a/scripts/tests/study.lua b/scripts/tests/study.lua index 8f4e17e17..073b41860 100644 --- a/scripts/tests/study.lua +++ b/scripts/tests/study.lua @@ -67,9 +67,7 @@ function test_unit_spells() u:add_spell("toast") assert_equal(nil, u.spells) u:add_spell("fireball", 2) - local sp = u.spells() - assert_equal("fireball", sp.name) - assert_equal(2, sp.level) + assert_equal(2, u:get_spell("fireball")) end local function make_teacher(student, f, skill) diff --git a/src/bind_unit.c b/src/bind_unit.c index c91710033..6cf0bb78d 100644 --- a/src/bind_unit.c +++ b/src/bind_unit.c @@ -507,6 +507,27 @@ static int tolua_unit_castspell(lua_State * L) return 0; } +static int tolua_unit_getspell(lua_State *L) +{ + unit *u = (unit *)tolua_tousertype(L, 1, NULL); + const char *str = tolua_tostring(L, 2, NULL); + spellbook *sb; + spellbook_entry *sbe = NULL; + + sb = unit_get_spellbook(u); + if (sb) { + spell *sp = find_spell(str); + if (!sp) { + log_warning("spell %s could not be found\n", str); + } + else { + sbe = spellbook_get(sb, sp); + } + } + lua_pushinteger(L, sbe->level); + return 1; +} + static int tolua_unit_addspell(lua_State * L) { unit *u = (unit *)tolua_tousertype(L, 1, NULL); @@ -800,19 +821,6 @@ static int tolua_unit_get_items(lua_State * L) return 1; } -static int tolua_unit_get_spells(lua_State * L) -{ - unit *u = (unit *) tolua_tousertype(L, 1, NULL); - struct sc_mage *mage = u ? get_mage(u) : NULL; - spellbook *sb = mage_get_spellbook(mage); - selist *slist = NULL; - if (sb) { - selist **slist_ptr = &sb->spells; - slist = *slist_ptr; - } - return tolua_selist_push(L, "spellbook", "spell_entry", slist); -} - static int tolua_unit_get_curse(lua_State *L) { unit *u = (unit *)tolua_tousertype(L, 1, NULL); const char *name = tolua_tostring(L, 2, NULL); @@ -1118,7 +1126,7 @@ void tolua_unit_open(lua_State * L) tolua_variable(L, "race_name", tolua_unit_get_racename, tolua_unit_set_racename); tolua_function(L, "add_spell", tolua_unit_addspell); - tolua_variable(L, "spells", tolua_unit_get_spells, 0); + tolua_function(L, "get_spell", tolua_unit_getspell); tolua_function(L, "cast_spell", tolua_unit_castspell); tolua_function(L, "effect", bind_unit_effect); diff --git a/src/creport.c b/src/creport.c index 457547186..287daf82c 100644 --- a/src/creport.c +++ b/src/creport.c @@ -727,11 +727,11 @@ static void cr_output_spells(stream *out, const unit * u, int maxlevel) if (book) { const faction * f = u->faction; - selist *ql; - int qi, header = 0; + int header = 0; + ptrdiff_t qi, ql = arrlen(book->spells); - for (ql = book->spells, qi = 0; ql; selist_advance(&ql, &qi, 1)) { - spellbook_entry * sbe = (spellbook_entry *)selist_get(ql, qi); + for (qi = 0; qi != ql; ++qi) { + spellbook_entry *sbe = (spellbook_entry *)book->spells + qi; if (sbe->level <= maxlevel) { const spell *sp = spellref_get(&sbe->spref); const char * spname = mkname("spell", sp->sname); diff --git a/src/kernel/spellbook.c b/src/kernel/spellbook.c index 9127459a0..09d0100e6 100644 --- a/src/kernel/spellbook.c +++ b/src/kernel/spellbook.c @@ -5,7 +5,7 @@ #include "spellbook.h" -#include +#include #include #include @@ -18,7 +18,7 @@ spellbook * create_spellbook(const char * name) spellbook *result = (spellbook *)malloc(sizeof(spellbook)); if (!result) abort(); result->name = name ? str_strdup(name) : 0; - result->spells = 0; + result->spells = NULL; return result; } @@ -59,12 +59,11 @@ void read_spellbook(spellbook **bookp, gamedata *data, int(*get_level)(const spe void write_spellbook(const struct spellbook *book, struct storage *store) { - selist *ql; - int qi; - if (book) { - for (ql = book->spells, qi = 0; ql; selist_advance(&ql, &qi, 1)) { - spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi); + ptrdiff_t qi, ql = arrlen(book->spells); + + for (qi = 0; qi != ql; ++qi) { + spellbook_entry *sbe = (spellbook_entry *)book->spells + qi; WRITE_TOK(store, spellref_name(&sbe->spref)); WRITE_INT(store, sbe->level); } @@ -76,11 +75,9 @@ 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)); - if (!sbe) abort(); + sbe = arraddnptr(sb->spells, 1); spellref_init(&sbe->spref, NULL, name); sbe->level = level; - selist_push(&sb->spells, sbe); } void spellbook_add(spellbook *sb, spell *sp, int level) @@ -93,35 +90,29 @@ void spellbook_add(spellbook *sb, spell *sp, int level) log_error("duplicate spell in spellbook '%s': '%s'\n", sb->name, sp->sname); } #endif - sbe = (spellbook_entry *)malloc(sizeof(spellbook_entry)); - if (!sbe) abort(); + sbe = arraddnptr(sb->spells, 1); spellref_init(&sbe->spref, sp, NULL); sbe->level = level; - selist_push(&sb->spells, sbe); } void spellbook_clear(spellbook *sb) { - selist *ql; - int qi; + ptrdiff_t qi, ql = arrlen(sb->spells); - assert(sb); - for (qi = 0, ql = sb->spells; ql; selist_advance(&ql, &qi, 1)) { - spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi); + for (qi = 0; qi != ql; ++qi) { + spellbook_entry *sbe = (spellbook_entry *)sb->spells + qi; spellref_done(&sbe->spref); - free(sbe); } - selist_free(sb->spells); + arrfree(sb->spells); free(sb->name); } int spellbook_foreach(spellbook *sb, int(*callback)(spellbook_entry *, void *), void * data) { - selist *ql; - int qi; + ptrdiff_t qi, ql = arrlen(sb->spells); - for (qi = 0, ql = sb->spells; ql; selist_advance(&ql, &qi, 1)) { - spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi); + for (qi = 0; qi != ql; ++qi) { + spellbook_entry *sbe = (spellbook_entry *)sb->spells + qi; int result = callback(sbe, data); if (result) { return result; @@ -133,11 +124,10 @@ int spellbook_foreach(spellbook *sb, int(*callback)(spellbook_entry *, void *), spellbook_entry * spellbook_get(spellbook *sb, const struct spell *sp) { if (sb) { - selist *ql; - int qi; + ptrdiff_t qi, ql = arrlen(sb->spells); - for (qi = 0, ql = sb->spells; ql; selist_advance(&ql, &qi, 1)) { - spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi); + for (qi = 0; qi != ql; ++qi) { + spellbook_entry *sbe = (spellbook_entry *)sb->spells + qi; if (spellref_get(&sbe->spref) == sp) { return sbe; } diff --git a/src/kernel/spellbook.h b/src/kernel/spellbook.h index f1e8340f6..0be7b801b 100644 --- a/src/kernel/spellbook.h +++ b/src/kernel/spellbook.h @@ -19,7 +19,7 @@ extern "C" { typedef struct spellbook { char * name; - struct selist * spells; /* FIXME: selist only ever adds with push, could use stb array */ + struct spellbook_entry * spells; /* FIXME: selist only ever adds with push, could use stb array */ } spellbook; spellbook * create_spellbook(const char * name); diff --git a/src/laws.c b/src/laws.c index 18fcc8e52..12f06ec0b 100644 --- a/src/laws.c +++ b/src/laws.c @@ -3137,10 +3137,10 @@ static void copy_spells(const spellbook * src, spellbook * dst, int maxlevel) { assert(dst); if (src && src->spells) { - selist *ql; - int qi; - for (qi = 0, ql = src->spells; ql; selist_advance(&ql, &qi, 1)) { - spellbook_entry * sbe = (spellbook_entry *)selist_get(ql, qi); + ptrdiff_t qi, ql = arrlen(src->spells); + + for (qi = 0; qi != ql; ++qi) { + spellbook_entry *sbe = (spellbook_entry *)src->spells + qi; if (sbe->level <= maxlevel) { spell *sp = spellref_get(&sbe->spref); if (!spellbook_get(dst, sp)) { @@ -3154,11 +3154,10 @@ static void copy_spells(const spellbook * src, spellbook * dst, int maxlevel) static void show_new_spells(faction * f, int level, const spellbook *book) { if (book) { - selist *ql = book->spells; - int qi; + ptrdiff_t qi, ql = arrlen(book->spells); - for (qi = 0; ql; selist_advance(&ql, &qi, 1)) { - spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi); + for (qi = 0; qi != ql; ++qi) { + spellbook_entry *sbe = (spellbook_entry *)book->spells + qi; if (sbe->level <= level) { show_spell(f, sbe); } diff --git a/src/magic.c b/src/magic.c index 9f8295580..85a0dd484 100644 --- a/src/magic.c +++ b/src/magic.c @@ -425,15 +425,15 @@ struct spellbook * unit_get_spellbook(const struct unit * u) void pick_random_spells(faction * f, int level, spellbook * book, int num_spells) { spellbook_entry *commonspells[MAXSPELLS]; - int qi, numspells = 0; - selist *ql; + int numspells = 0; + ptrdiff_t qi, ql = arrlen(book->spells); if (level <= f->max_spelllevel) { return; } - for (qi = 0, ql = book->spells; ql; selist_advance(&ql, &qi, 1)) { - spellbook_entry * sbe = (spellbook_entry *)selist_get(ql, qi); + for (qi = 0; qi != ql; ++qi) { + spellbook_entry *sbe = (spellbook_entry *)book->spells + qi; if (sbe && sbe->level <= level) { commonspells[numspells++] = sbe; } @@ -2878,14 +2878,12 @@ const char *curse_name(const curse_type * ctype, const struct locale *lang) } static void select_spellbook(void **tokens, spellbook *sb, const struct locale * lang) { - selist * ql; - int qi; + ptrdiff_t qi, ql; - assert(sb); assert(lang); - for (qi = 0, ql = sb->spells; ql; selist_advance(&ql, &qi, 1)) { - spellbook_entry *sbe = (spellbook_entry *)selist_get(ql, qi); + for (ql = arrlen(sb->spells), qi = 0; qi != ql; ++qi) { + spellbook_entry *sbe = (spellbook_entry *)sb->spells + qi; const spell *sp = spellref_get(&sbe->spref); const char *spname = mkname("spell", sp->sname); const char *n = spell_name(spname, lang); diff --git a/src/magic.test.c b/src/magic.test.c index 23f926941..64fb2037a 100644 --- a/src/magic.test.c +++ b/src/magic.test.c @@ -32,6 +32,7 @@ #include #include +#include #include @@ -60,7 +61,7 @@ void test_updatespells(CuTest * tc) CuAssertPtrEquals(tc, NULL, f->spellbook); pick_random_spells(f, 1, book, 1); CuAssertPtrNotNull(tc, f->spellbook); - CuAssertIntEquals(tc, 1, selist_length(f->spellbook->spells)); + CuAssertIntEquals(tc, 1, (int) arrlen(f->spellbook->spells)); CuAssertPtrNotNull(tc, spellbook_get(f->spellbook, sp)); free_spellbook(book); test_teardown(); diff --git a/src/reports.c b/src/reports.c index 6b357e344..f5312f7ff 100644 --- a/src/reports.c +++ b/src/reports.c @@ -806,12 +806,12 @@ static void bufunit_spells(const unit* u, struct sbstring* sbp) spellbook* book = unit_get_spellbook(u); if (book) { - selist* ql = book->spells; - int i, qi, header, maxlevel = effskill(u, SK_MAGIC, NULL); + int i, header = 0, maxlevel = effskill(u, SK_MAGIC, NULL); + ptrdiff_t qi, ql; sbs_printf(sbp, ". Aura %d/%d", get_spellpoints(u), max_spellpoints(u, NULL)); - for (header = 0, qi = 0; ql; selist_advance(&ql, &qi, 1)) { - spellbook_entry* sbe = (spellbook_entry*)selist_get(ql, qi); + for (ql = arrlen(book->spells), qi = 0; qi != ql; ++qi) { + spellbook_entry *sbe = (spellbook_entry *)book->spells + qi; const spell* sp = spellref_get(&sbe->spref); if (sbe->level <= maxlevel) { if (!header) {