forked from github/server
spellbooks fully operational (and could be loaded from XML definitions if I had them)
fixed the cleanup between tests to properly free locales
This commit is contained in:
parent
f45a494277
commit
92e96689bb
|
@ -38,6 +38,7 @@ without prior permission by the authors of Eressea.
|
|||
#include <kernel/teleport.h>
|
||||
#include <kernel/faction.h>
|
||||
#include <kernel/save.h>
|
||||
#include <kernel/spell.h>
|
||||
|
||||
#include <gamecode/creport.h>
|
||||
#include <gamecode/economy.h>
|
||||
|
@ -684,6 +685,7 @@ static int tolua_set_alliance_name(lua_State * L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef WRITE_SPELLS
|
||||
#include <libxml/tree.h>
|
||||
#include <util/functions.h>
|
||||
#include <util/xml.h>
|
||||
|
@ -755,6 +757,7 @@ static int tolua_write_spells(lua_State * L)
|
|||
xmlFreeDoc(doc);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int config_get_ships(lua_State * L)
|
||||
{
|
||||
|
@ -975,6 +978,7 @@ static int tolua_get_spell_text(lua_State * L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
#ifdef TODO
|
||||
static int tolua_get_spell_school(lua_State * L)
|
||||
{
|
||||
spell *self = (spell *) tolua_tousertype(L, 1, 0);
|
||||
|
@ -988,6 +992,7 @@ static int tolua_get_spell_level(lua_State * L)
|
|||
lua_pushnumber(L, self->level);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int tolua_get_spell_name(lua_State * L)
|
||||
{
|
||||
|
@ -1177,8 +1182,10 @@ int tolua_eressea_open(lua_State * L)
|
|||
{
|
||||
tolua_function(L, TOLUA_CAST "__tostring", tolua_get_spell_name);
|
||||
tolua_variable(L, TOLUA_CAST "name", tolua_get_spell_name, 0);
|
||||
#ifdef TODO
|
||||
tolua_variable(L, TOLUA_CAST "school", tolua_get_spell_school, 0);
|
||||
tolua_variable(L, TOLUA_CAST "level", tolua_get_spell_level, 0);
|
||||
#endif
|
||||
tolua_variable(L, TOLUA_CAST "text", tolua_get_spell_text, 0);
|
||||
} tolua_endmodule(L);
|
||||
tolua_module(L, TOLUA_CAST "eventbus", 1);
|
||||
|
@ -1263,7 +1270,9 @@ int tolua_eressea_open(lua_State * L)
|
|||
tolua_function(L, TOLUA_CAST "translate", &tolua_translate);
|
||||
tolua_function(L, TOLUA_CAST "rng_int", tolua_rng_int);
|
||||
tolua_function(L, TOLUA_CAST "spells", tolua_get_spells);
|
||||
#ifdef WRITE_SPELLS
|
||||
tolua_function(L, TOLUA_CAST "write_spells", tolua_write_spells);
|
||||
#endif
|
||||
tolua_function(L, TOLUA_CAST "read_xml", tolua_read_xml);
|
||||
} tolua_endmodule(L);
|
||||
return 1;
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <kernel/ship.c>
|
||||
#include <kernel/skill.c>
|
||||
#include <kernel/spell.c>
|
||||
#include <kernel/spellbook.c>
|
||||
#include <kernel/teleport.c>
|
||||
#include <kernel/terrain.c>
|
||||
#include <kernel/textstore.c>
|
||||
|
|
|
@ -18,6 +18,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
|
||||
#include <platform.h>
|
||||
#include <kernel/config.h>
|
||||
#include <kernel/types.h>
|
||||
#include "magic.h"
|
||||
|
||||
#include "building.h"
|
||||
|
@ -35,6 +36,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include "ship.h"
|
||||
#include "skill.h"
|
||||
#include "spell.h"
|
||||
#include "spellbook.h"
|
||||
#include "teleport.h"
|
||||
#include "terrain.h"
|
||||
#include "unit.h"
|
||||
|
@ -49,6 +51,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
|
||||
/* util includes */
|
||||
#include <util/attrib.h>
|
||||
#include <util/critbit.h>
|
||||
#include <util/language.h>
|
||||
#include <util/lists.h>
|
||||
#include <util/log.h>
|
||||
|
@ -2924,3 +2927,28 @@ struct quicklist **get_spelllist(struct sc_mage *mage, struct faction *f)
|
|||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static critbit_tree cb_spellbooks;
|
||||
|
||||
spellbook * get_spellbook(const char * name)
|
||||
{
|
||||
char buffer[64];
|
||||
spellbook * result;
|
||||
const void * match;
|
||||
|
||||
if (cb_find_prefix(&cb_spellbooks, name, strlen(name), &match, 1, 0)) {
|
||||
cb_get_kv(match, &result, sizeof(result));
|
||||
} else {
|
||||
size_t len = strlen(name);
|
||||
result = create_spellbook(name);
|
||||
assert(strlen(name)+sizeof(result)<sizeof(buffer));
|
||||
len = cb_new_kv(name, len, &result, sizeof(result), buffer);
|
||||
cb_insert(&cb_spellbooks, buffer, len);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void free_spellbooks(void)
|
||||
{
|
||||
cb_clear(&cb_spellbooks);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ extern "C" {
|
|||
#include "curse.h"
|
||||
struct fighter;
|
||||
struct building;
|
||||
struct quicklist;
|
||||
struct spellbook;
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
||||
|
@ -385,6 +385,8 @@ typedef struct sc_mage {
|
|||
struct storage *store);
|
||||
extern double MagicPower(void);
|
||||
|
||||
extern struct spellbook * get_spellbook(const char * name);
|
||||
extern void free_spellbooks(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -14,21 +14,55 @@ void test_updatespells(CuTest * tc)
|
|||
{
|
||||
struct faction * f;
|
||||
spell * sp;
|
||||
spellbook * book = 0;
|
||||
spellbook *book = 0;
|
||||
|
||||
test_cleanup();
|
||||
|
||||
f = test_create_faction(0);
|
||||
sp = create_spell("testspell", 0);
|
||||
CuAssertPtrNotNull(tc, sp);
|
||||
spellbook_add(&book, sp, 1);
|
||||
|
||||
book = create_spellbook("spells");
|
||||
CuAssertPtrNotNull(tc, book);
|
||||
spellbook_add(book, sp, 1);
|
||||
|
||||
update_spellbook(f, 1);
|
||||
}
|
||||
|
||||
void test_spellbooks(CuTest * tc)
|
||||
{
|
||||
spell *sp;
|
||||
spellbook *herp, *derp;
|
||||
spellbook_entry *entry;
|
||||
const char * sname = "herpderp";
|
||||
test_cleanup();
|
||||
|
||||
herp = get_spellbook("herp");
|
||||
derp = get_spellbook("derp");
|
||||
CuAssertPtrNotNull(tc, herp);
|
||||
CuAssertPtrNotNull(tc, derp);
|
||||
CuAssertTrue(tc, derp!=herp);
|
||||
CuAssertStrEquals(tc, "herp", herp->name);
|
||||
CuAssertStrEquals(tc, "derp", derp->name);
|
||||
|
||||
sp = create_spell(sname, 0);
|
||||
spellbook_add(herp, sp, 1);
|
||||
CuAssertPtrNotNull(tc, sp);
|
||||
entry = spellbook_get(herp, sname);
|
||||
CuAssertPtrNotNull(tc, entry);
|
||||
CuAssertPtrEquals(tc, sp, entry->sp);
|
||||
CuAssertPtrEquals(tc, 0, spellbook_get(derp, sname));
|
||||
|
||||
test_cleanup();
|
||||
herp = get_spellbook("herp");
|
||||
CuAssertPtrNotNull(tc, herp);
|
||||
CuAssertPtrEquals(tc, 0, spellbook_get(herp, sname));
|
||||
}
|
||||
|
||||
CuSuite *get_magic_suite(void)
|
||||
{
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
SUITE_ADD_TEST(suite, test_updatespells);
|
||||
SUITE_ADD_TEST(suite, test_spellbooks);
|
||||
return suite;
|
||||
}
|
||||
|
|
|
@ -1,15 +1,27 @@
|
|||
#include <platform.h>
|
||||
#include <kernel/config.h>
|
||||
#include <kernel/spell.h>
|
||||
#include <kernel/magic.h>
|
||||
#include <util/quicklist.h>
|
||||
|
||||
#include "spellbook.h"
|
||||
|
||||
void spellbook_add(spellbook **sbp, struct spell * sp, int level)
|
||||
spellbook * create_spellbook(const char * name)
|
||||
{
|
||||
spellbook *result = (spellbook *)malloc(sizeof(spellbook));
|
||||
result->name = strdup(name);
|
||||
result->spells = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
void spellbook_add(spellbook *sb, struct spell * sp, int level)
|
||||
{
|
||||
spellbook_entry * sbe = (spellbook_entry *)malloc(sizeof(spellbook_entry));
|
||||
|
||||
assert(sb);
|
||||
sbe->sp = sp;
|
||||
sbe->level = level;
|
||||
ql_push(sbp, sbe);
|
||||
ql_push(&sb->spells, sbe);
|
||||
}
|
||||
|
||||
void spellbook_free(spellbook *sb)
|
||||
|
@ -17,11 +29,12 @@ void spellbook_free(spellbook *sb)
|
|||
quicklist *ql;
|
||||
int qi;
|
||||
|
||||
for (qi = 0, ql = sb; ql; ql_advance(&ql, &qi, 1)) {
|
||||
assert(sb);
|
||||
for (qi = 0, ql = sb->spells; ql; ql_advance(&ql, &qi, 1)) {
|
||||
spellbook_entry *sbe = (spellbook_entry *) ql_get(ql, qi);
|
||||
free(sbe);
|
||||
}
|
||||
ql_free(sb);
|
||||
ql_free(sb->spells);
|
||||
}
|
||||
|
||||
int spellbook_foreach(spellbook *sb, int (*callback)(spellbook_entry *, void *), void * data)
|
||||
|
@ -29,7 +42,7 @@ int spellbook_foreach(spellbook *sb, int (*callback)(spellbook_entry *, void *),
|
|||
quicklist *ql;
|
||||
int qi;
|
||||
|
||||
for (qi = 0, ql = sb; ql; ql_advance(&ql, &qi, 1)) {
|
||||
for (qi = 0, ql = sb->spells; ql; ql_advance(&ql, &qi, 1)) {
|
||||
spellbook_entry *sbe = (spellbook_entry *) ql_get(ql, qi);
|
||||
int result = callback(sbe, data);
|
||||
if (result) {
|
||||
|
@ -38,3 +51,18 @@ int spellbook_foreach(spellbook *sb, int (*callback)(spellbook_entry *, void *),
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
spellbook_entry * spellbook_get(spellbook *sb, const char * name)
|
||||
{
|
||||
quicklist *ql;
|
||||
int qi;
|
||||
|
||||
for (qi = 0, ql = sb->spells; ql; ql_advance(&ql, &qi, 1)) {
|
||||
spellbook_entry *sbe = (spellbook_entry *) ql_get(ql, qi);
|
||||
if (strcmp(name, sbe->sp->sname)==0) {
|
||||
return sbe;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,19 +24,25 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
struct spell;
|
||||
struct quicklist;
|
||||
|
||||
typedef struct spellbook_entry {
|
||||
struct spell * sp;
|
||||
int level;
|
||||
} spellbook_entry;
|
||||
|
||||
typedef struct quicklist spellbook;
|
||||
typedef struct spellbook
|
||||
{
|
||||
char * name;
|
||||
struct quicklist * spells;
|
||||
} spellbook;
|
||||
|
||||
spellbook * school_books[MAXMAGIETYP];
|
||||
spellbook * create_spellbook(const char * name);
|
||||
|
||||
void spellbook_add(spellbook **sbp, struct spell * sp, int level);
|
||||
void spellbook_add(spellbook *sbp, struct spell * sp, int level);
|
||||
int spellbook_foreach(spellbook *sb, int (*callback)(spellbook_entry *, void *), void * data);
|
||||
void spellbook_free(spellbook *sb);
|
||||
spellbook_entry * spellbook_get(spellbook *sb, const char * name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -18,23 +18,35 @@ int count_spell_cb(spellbook_entry * sbe, void * ptr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void test_spellbook(CuTest * tc)
|
||||
void test_named_spellbooks(CuTest * tc)
|
||||
{
|
||||
spell * sp;
|
||||
spellbook * sb = 0;
|
||||
spellbook * sb;
|
||||
int counter = 0;
|
||||
|
||||
sp = create_spell("testspell", 0);
|
||||
spellbook_add(&sb, sp, 1);
|
||||
sb = create_spellbook("spells");
|
||||
CuAssertPtrNotNull(tc, sb);
|
||||
CuAssertStrEquals(tc, "spells", sb->name);
|
||||
|
||||
sp = create_spell("testspell", 0);
|
||||
spellbook_add(sb, sp, 1);
|
||||
CuAssertPtrNotNull(tc, sb->spells);
|
||||
|
||||
spellbook_foreach(sb, count_spell_cb, &counter);
|
||||
CuAssertIntEquals(tc, 1, counter);
|
||||
|
||||
#ifdef TODO
|
||||
/* try adding the same spell twice. that should fail */
|
||||
spellbook_add(sb, sp, 1);
|
||||
spellbook_foreach(sb, count_spell_cb, &counter);
|
||||
CuAssertIntEquals(tc, 1, counter);
|
||||
#endif
|
||||
spellbook_free(sb);
|
||||
}
|
||||
|
||||
CuSuite *get_spellbook_suite(void)
|
||||
{
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
SUITE_ADD_TEST(suite, test_spellbook);
|
||||
SUITE_ADD_TEST(suite, test_named_spellbooks);
|
||||
return suite;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ without prior permission by the authors of Eressea.
|
|||
#include "terrain.h"
|
||||
#include "skill.h"
|
||||
#include "spell.h"
|
||||
#include "spellbook.h"
|
||||
#include "calendar.h"
|
||||
|
||||
/* util includes */
|
||||
|
@ -1461,6 +1462,58 @@ static int parse_equipment(xmlDocPtr doc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int parse_spellbooks(xmlDocPtr doc)
|
||||
{
|
||||
xmlXPathContextPtr xpath = xmlXPathNewContext(doc);
|
||||
xmlXPathObjectPtr spellbooks;
|
||||
|
||||
/* reading eressea/spells/spell */
|
||||
spellbooks = xmlXPathEvalExpression(BAD_CAST "/eressea/spells/spellbook", xpath);
|
||||
|
||||
if (spellbooks->nodesetval != NULL) {
|
||||
xmlNodeSetPtr nodes = spellbooks->nodesetval;
|
||||
int i, k;
|
||||
|
||||
for (i = 0; i != nodes->nodeNr; ++i) {
|
||||
xmlXPathObjectPtr result;
|
||||
xmlNodePtr node = nodes->nodeTab[i];
|
||||
xmlChar *propValue;
|
||||
spellbook * sb;
|
||||
|
||||
propValue = xmlGetProp(node, BAD_CAST "name");
|
||||
assert(propValue != NULL);
|
||||
sb = get_spellbook((const char *)propValue);
|
||||
xmlFree(propValue);
|
||||
|
||||
xpath->node = node;
|
||||
result = xmlXPathEvalExpression(BAD_CAST "entry", xpath);
|
||||
|
||||
if (result->nodesetval->nodeNr > 0) {
|
||||
for (k = 0; k != result->nodesetval->nodeNr; ++k) {
|
||||
xmlNodePtr node = result->nodesetval->nodeTab[k];
|
||||
spell * sp = 0;
|
||||
int level = xml_ivalue(node, "level", -1);
|
||||
|
||||
propValue = xmlGetProp(node, BAD_CAST "name");
|
||||
if (propValue) {
|
||||
sp = find_spell((const char *)propValue);
|
||||
xmlFree(propValue);
|
||||
}
|
||||
if (sp && level>0) {
|
||||
spellbook_add(sb, sp, level);
|
||||
} else {
|
||||
log_error("invalid entry at index '%d' in spellbook '%s'\n", k, sb->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
xmlXPathFreeObject(result);
|
||||
}
|
||||
}
|
||||
xmlXPathFreeObject(spellbooks);
|
||||
xmlXPathFreeContext(xpath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_spells(xmlDocPtr doc)
|
||||
{
|
||||
xmlXPathContextPtr xpath = xmlXPathNewContext(doc);
|
||||
|
@ -1505,7 +1558,7 @@ static int parse_spells(xmlDocPtr doc)
|
|||
sp->syntax = strdup((const char *)propValue);
|
||||
xmlFree(propValue);
|
||||
}
|
||||
|
||||
#ifdef TODO /* no longer need it, spellbooks! */
|
||||
/* magic type */
|
||||
propValue = xmlGetProp(node, BAD_CAST "type");
|
||||
assert(propValue != NULL);
|
||||
|
@ -1515,7 +1568,7 @@ static int parse_spells(xmlDocPtr doc)
|
|||
}
|
||||
assert(sp->magietyp != MAXMAGIETYP);
|
||||
xmlFree(propValue);
|
||||
|
||||
#endif
|
||||
/* level, rank and flags */
|
||||
sp->level = xml_ivalue(node, "level", -1);
|
||||
sp->rank = (char)xml_ivalue(node, "rank", -1);
|
||||
|
@ -2332,6 +2385,7 @@ void register_xmlreader(void)
|
|||
xml_register_callback(parse_buildings); /* requires resources */
|
||||
xml_register_callback(parse_ships); /* requires terrains */
|
||||
xml_register_callback(parse_spells); /* requires resources */
|
||||
xml_register_callback(parse_spellbooks); /* requires spells */
|
||||
xml_register_callback(parse_equipment); /* requires spells */
|
||||
xml_register_callback(parse_races); /* requires spells */
|
||||
xml_register_callback(parse_calendar);
|
||||
|
|
|
@ -112,8 +112,9 @@ void test_cleanup(void)
|
|||
global.functions.maintenance = NULL;
|
||||
global.functions.wage = NULL;
|
||||
default_locale = 0;
|
||||
locales = 0; /* TODO: this is evil and leaky */
|
||||
free_spells(); /* TODO: this is just as bad! */
|
||||
free_locales(); /* TODO: this is evil and leaky */
|
||||
free_spells();
|
||||
free_spellbooks();
|
||||
free_gamedata();
|
||||
}
|
||||
|
||||
|
|
|
@ -234,3 +234,23 @@ void ** get_translations(const struct locale *lang, int index)
|
|||
}
|
||||
return lstrs[0].tokens + index;
|
||||
}
|
||||
|
||||
void free_locales(void)
|
||||
{
|
||||
while (locales) {
|
||||
int i;
|
||||
locale * next = locales->next;
|
||||
|
||||
for (i=0; i!=SMAXHASH; ++i) {
|
||||
while (locales->strings[i]) {
|
||||
struct locale_str * strings = locales->strings[i];
|
||||
free(strings->key);
|
||||
free(strings->str);
|
||||
locales->strings[i] = strings->nexthash;
|
||||
free(strings);
|
||||
}
|
||||
}
|
||||
free(locales);
|
||||
locales = next;
|
||||
}
|
||||
}
|
|
@ -29,8 +29,9 @@ extern "C" {
|
|||
/** managing multiple locales: **/
|
||||
extern struct locale *find_locale(const char *name);
|
||||
extern struct locale *make_locale(const char *key);
|
||||
extern void free_locales(void);
|
||||
|
||||
/** operations on locales: **/
|
||||
/** operations on locales: **/
|
||||
extern void locale_setstring(struct locale *lang, const char *key,
|
||||
const char *value);
|
||||
extern const char *locale_getstring(const struct locale *lang,
|
||||
|
|
Loading…
Reference in New Issue