replace spellid_t with unsigned int

fix finding spells by token
make magic_t an enum
This commit is contained in:
Enno Rehling 2012-05-09 03:14:54 -07:00
parent ae31948dc5
commit c22f49ec36
16 changed files with 193 additions and 172 deletions

View file

@ -32,9 +32,9 @@
<set name="songdragon_familiar">
<skill name="magic" level="1"/>
<!-- spells -->
<spell name="flee" school="gray"/>
<spell name="sleep" school="gray"/>
<spell name="frighten" school="gray"/>
<spell name="flee"/>
<spell name="sleep"/>
<spell name="frighten"/>
</set>
<set name="nymph_familiar">
@ -48,10 +48,10 @@
<skill name="entertainment" level="1"/>
<skill name="perception" level="1"/>
<!-- spells -->
<spell name="seduction" school="gray"/>
<spell name="calm_monster" school="gray"/>
<spell name="song_of_confusion" school="gray"/>
<spell name="appeasement" school="gray"/>
<spell name="seduction"/>
<spell name="calm_monster"/>
<spell name="song_of_confusion"/>
<spell name="appeasement"/>
</set>
<set name="unicorn_familiar">
@ -59,12 +59,12 @@
<skill name="stealth" level="1"/>
<skill name="perception" level="1"/>
<!-- spells -->
<spell name="resist_magic" school="gray"/>
<spell name="song_of_peace" school="gray"/>
<spell name="calm_monster" school="gray"/>
<spell name="heroic_song" school="gray"/>
<spell name="song_of_healing" school="gray"/>
<spell name="appeasement" school="gray"/>
<spell name="resist_magic"/>
<spell name="song_of_peace"/>
<spell name="calm_monster"/>
<spell name="heroic_song"/>
<spell name="song_of_healing"/>
<spell name="appeasement"/>
</set>
<set name="direwolf_familiar">
@ -75,9 +75,9 @@
<set name="ghost_familiar">
<skill name="magic" level="1"/>
<!-- spells -->
<spell name="steal_aura" school="gray"/>
<spell name="frighten" school="gray"/>
<spell name="summonundead" school="gray"/>
<spell name="steal_aura"/>
<spell name="frighten"/>
<spell name="summonundead"/>
</set>
<set name="imp_familiar">
@ -87,9 +87,9 @@
<skill name="perception" level="1"/>
<skill name="taxation" level="1"/>
<!-- spells -->
<spell name="steal_aura" school="gray"/>
<spell name="shapeshift" school="gray"/>
<spell name="seduction" school="gray"/>
<spell name="steal_aura"/>
<spell name="shapeshift"/>
<spell name="seduction"/>
</set>
<set name="dreamcat_familiar">
@ -99,16 +99,16 @@
<skill name="perception" level="1"/>
<skill name="taxation" level="1"/>
<!-- spells -->
<spell name="shapeshift" school="gray"/>
<spell name="transferauratraum" school="gray"/>
<spell name="shapeshift"/>
<spell name="transferauratraum"/>
</set>
<set name="fairy_familiar">
<skill name="magic" level="1"/>
<!-- spells -->
<spell name="appeasement" school="gray"/>
<spell name="calm_monster" school="gray"/>
<spell name="seduction" school="gray"/>
<spell name="appeasement"/>
<spell name="calm_monster"/>
<spell name="seduction"/>
</set>
<set name="owl_familiar">

View file

@ -493,7 +493,7 @@ static int tolua_unit_castspell(lua_State * L)
static int unit_addspell(unit * u, const char *name)
{
sc_mage *m = get_mage(u);
spell *spadd = find_spell(m->magietyp, name);
spell *spadd = find_spell(name);
if (!spadd) {
log_error(("spell %s could not be found\n", name));
@ -501,6 +501,7 @@ static int unit_addspell(unit * u, const char *name)
} else {
quicklist **starget = get_spelllist(m, u->faction);
add_spell(starget, spadd);
add_spellname(m, spadd);
}
return 0;
}

View file

@ -118,7 +118,7 @@ use_antimagiccrystal(unit * u, const struct item_type *itype, int amount,
for (i = 0; i != amount; ++i) {
int effect, duration = 2;
double force;
spell *sp = find_spell(M_NONE, "antimagiczone");
spell *sp = find_spell("antimagiczone");
attrib **ap = &r->attribs;
unused(ord);
assert(sp);

View file

@ -121,6 +121,7 @@
<ClCompile Include="kernel\ship.c" />
<ClCompile Include="kernel\skill.c" />
<ClCompile Include="kernel\spell.c" />
<ClCompile Include="kernel\spell_test.c" />
<ClCompile Include="kernel\sqlite.c" />
<ClCompile Include="kernel\teleport.c" />
<ClCompile Include="kernel\terrain.c" />

View file

@ -298,6 +298,9 @@
<ClCompile Include="kernel\battle_test.c">
<Filter>kernel</Filter>
</ClCompile>
<ClCompile Include="kernel\spell_test.c">
<Filter>kernel</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="kernel\alchemy.h">

View file

@ -149,6 +149,7 @@ void equip_unit_mask(struct unit *u, const struct equipment *eq, int mask)
for (qi = 0; ql; ql_advance(&ql, &qi, 1)) {
spell *sp = (spell *) ql_get(ql, qi);
add_spell(&m->spells, sp);
add_spellname(m, sp);
}
}
}

View file

@ -58,6 +58,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <util/rand.h>
#include <util/rng.h>
#include <util/storage.h>
#include <util/umlaut.h>
#include <util/base36.h>
#include <util/event.h>
@ -213,14 +214,17 @@ void read_spells(struct quicklist **slistp, magic_t mtype,
int i = store->r_int(store);
if (i < 0)
break;
sp = find_spellbyid(M_NONE, (spellid_t) i);
sp = find_spellbyid((unsigned int) i);
} else {
store->r_tok_buf(store, spname, sizeof(spname));
if (strcmp(spname, "end") == 0)
break;
sp = find_spell(mtype, spname);
sp = find_spell(spname);
if (!sp) {
log_error(("read_spells: could not find spell '%s' in school '%s'\n", spname, magic_school[mtype]));
}
}
if (sp != NULL) {
if (sp) {
add_spell(slistp, sp);
}
}
@ -244,14 +248,17 @@ static int read_mage(attrib * a, void *owner, struct storage *store)
spid = store->r_int(store);
level = store->r_int(store);
if (spid >= 0) {
sp = find_spellbyid(mage->magietyp, (spellid_t) spid);
sp = find_spellbyid((unsigned int) spid);
}
} else {
store->r_tok_buf(store, spname, sizeof(spname));
level = store->r_int(store);
if (strcmp("none", spname) != 0) {
sp = find_spell(mage->magietyp, spname);
sp = find_spell(spname);
if (!sp) {
log_error(("read_mage: could not find combat spell '%s' in school '%s'\n", spname, magic_school[mage->magietyp]));
}
}
}
if (sp && level >= 0) {
@ -343,14 +350,16 @@ static int read_seenspell(attrib * a, void *owner, struct storage *store)
store->r_tok_buf(store, token, sizeof(token));
i = atoi(token);
if (i != 0) {
sp = find_spellbyid(M_NONE, (spellid_t) i);
sp = find_spellbyid((unsigned int) i);
} else {
int mtype;
mtype = store->r_int(store);
sp = find_spell((magic_t) mtype, token);
sp = find_spell(token);
if (!sp) {
log_error(("read_seenspell: could not find spell '%s' in school '%s'\n", token, magic_school[mtype]));
}
}
if (sp == NULL) {
/* log_error(("could not find seenspell '%s'\n", buf)); */
if (!sp) {
return AT_READ_FAIL;
}
a->data.v = sp;
@ -488,8 +497,10 @@ void updatespelllist(unit * u)
|| know_school(u->faction, sp->magietyp)) {
faction *f = u->faction;
if (!know)
if (!know) {
add_spell(dst, sp);
add_spellname(mage, 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;
@ -521,6 +532,18 @@ sc_mage *create_mage(unit * u, magic_t mtyp)
/* ------------------------------------------------------------- */
/* Funktionen für die Bearbeitung der List-of-known-spells */
void add_spellname(sc_mage * mage, const spell * sp)
{
spell_names * names = mage->spellnames;
while (names) {
variant token;
const char *n = spell_name(sp, names->lang);
token.v = (void *)sp;
addtoken(names->tokens, n, token);
names = names->next;
}
}
void add_spell(struct quicklist **slistp, spell * sp)
{
if (ql_set_insert(slistp, sp) != 0) {
@ -2568,14 +2591,14 @@ static castorder *cast_cmd(unit * u, order * ord)
/* Vertraute können auch Zauber sprechen, die sie selbst nicht
* können. get_spellfromtoken findet aber nur jene Sprüche, die
* die Einheit beherrscht. */
if (sp == NULL && is_familiar(u)) {
if (!sp && is_familiar(u)) {
familiar = u;
mage = get_familiar_mage(u);
if (mage != NULL)
sp = get_spellfromtoken(mage, s, mage->faction->locale);
}
if (sp == NULL) {
if (!sp) {
/* Fehler 'Spell not found' */
cmistake(u, ord, 173, MSG_MAGIC);
return 0;

View file

@ -86,19 +86,6 @@ extern "C" {
/* ------------------------------------------------------------- */
/* Magierichtungen */
/* typedef unsigned char magic_t; */
enum {
M_GRAY = 0, /* Gray */
M_ILLAUN = 1, /* Illaun */
M_TYBIED = 2, /* Tybied */
M_CERDDOR = 3, /* Cerddor */
M_GWYRRD = 4, /* Gwyrrd */
M_DRAIG = 5, /* Draig */
M_COMMON = 6, /* common spells */
MAXMAGIETYP,
/* this enum is stored in the datafile, so do not change the numbers around */
M_NONE = (magic_t) - 1
};
extern const char *magic_school[MAXMAGIETYP];
/* ------------------------------------------------------------- */
@ -113,19 +100,26 @@ extern "C" {
* - Spruchliste
*/
typedef struct combatspell {
int level;
const struct spell *sp;
} combatspell;
typedef struct combatspell {
int level;
const struct spell *sp;
} combatspell;
typedef struct sc_mage {
magic_t magietyp;
int spellpoints;
int spchange;
int spellcount;
combatspell combatspells[MAXCOMBATSPELLS];
struct quicklist *spells;
} sc_mage;
typedef struct spell_names {
struct spell_names *next;
const struct locale *lang;
struct tnode * tokens;
} spell_names;
typedef struct sc_mage {
magic_t magietyp;
int spellpoints;
int spchange;
int spellcount;
combatspell combatspells[MAXCOMBATSPELLS];
struct quicklist *spells;
struct spell_names * spellnames;
} sc_mage;
/* ------------------------------------------------------------- */
/* Zauberliste */
@ -164,7 +158,7 @@ extern "C" {
} spell_component;
typedef struct spell {
spellid_t id;
unsigned int id;
char *sname;
char *syntax;
char *parameter;
@ -278,6 +272,7 @@ extern "C" {
void unset_combatspell(struct unit *u, spell * sp);
/* löscht Kampfzauber */
void add_spell(struct quicklist **slistp, spell * sp);
void add_spellname(sc_mage * mage, const spell * sp);
/* fügt den Spruch mit der Id spellid der Spruchliste der Einheit hinzu. */
boolean u_hasspell(const struct unit *u, const struct spell *sp);
/* prüft, ob der Spruch in der Spruchliste der Einheit steht. */

View file

@ -35,12 +35,15 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#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
*/
quicklist *spells = NULL;
spell * create_spell(const char * name)
{
spell * sp = (spell *) calloc(1, sizeof(spell));
sp->sname = strdup(name);
return sp;
}
void register_spell(spell * sp)
{
if (sp->id == 0) {
@ -49,120 +52,56 @@ void register_spell(spell * sp)
add_spell(&spells, sp);
}
/** versucht einen Spruch über gebiet + name zu identifizieren.
* gibt ansonsten NULL zurück */
spell *find_spell(magic_t mtype, const char *name)
spell *find_spell(const char *name)
{
quicklist *ql = spells;
int qi;
spell *spx = NULL;
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;
return sp;
}
}
if (spx == NULL) {
log_error(("cannot find spell by name: %s\n", name));
}
return spx;
log_warning(("find_spell: could not find spell '%s'\n", name));
return 0;
}
/* ------------------------------------------------------------- */
/* Spruch identifizieren */
typedef struct spell_names {
struct spell_names *next;
const struct locale *lang;
magic_t mtype;
struct tnode names;
} spell_names;
static spell_names *spellnames;
static spell_names *init_spellnames(const struct locale *lang, magic_t mtype)
{
quicklist *ql;
int qi;
spell_names *sn = (spell_names *) calloc(sizeof(spell_names), 1);
sn->next = spellnames;
sn->lang = lang;
sn->mtype = mtype;
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;
token.v = sp;
addtoken(&sn->names, n, token);
}
}
return spellnames = sn;
}
static spell_names *get_spellnames(const struct locale *lang, magic_t mtype)
{
spell_names *sn = spellnames;
while (sn) {
if (sn->mtype == mtype && sn->lang == lang)
break;
sn = sn->next;
}
if (!sn)
return init_spellnames(lang, mtype);
return sn;
}
static spell *get_spellfromtoken_i(const char *name, const struct locale *lang,
magic_t mtype)
{
variant token = { 0 };
spell_names *sn;
sn = get_spellnames(lang, mtype);
if (findtoken(&sn->names, name, &token) == E_TOK_NOMATCH) {
magic_t mt;
/* if we could not find it in the main magic type, we look through all the others */
for (mt = 0; mt != MAXMAGIETYP; ++mt) {
if (mt != mtype) {
sn = get_spellnames(lang, mt);
if (findtoken(&sn->names, name, &token) != E_TOK_NOMATCH)
break;
}
}
}
if (token.v != NULL)
return (spell *) token.v;
if (lang == default_locale)
return NULL;
return get_spellfromtoken_i(name, default_locale, mtype);
}
spell *get_spellfromtoken(unit * u, const char *name,
const struct locale * lang)
{
variant token;
sc_mage *m = get_mage(u);
spell *sp;
if (m == NULL)
return NULL;
sp = get_spellfromtoken_i(name, lang, m->magietyp);
if (sp != NULL) {
struct spell_names * names = m->spellnames;
for (;names;names=names->next) {
if (names->lang==lang) break;
}
if (!names) {
quicklist *ql = m->spells;
int qi;
if (ql_set_find(&ql, &qi, sp)) {
return sp;
names = (spell_names *)calloc(1, sizeof(spell_names));
names->next = m->spellnames;
names->lang = lang;
names->tokens = (tnode *)calloc(1, sizeof(tnode));
for (qi = 0, ql = m->spells; ql; ql_advance(&ql, &qi, 1)) {
spell *sp = (spell *) ql_get(ql, qi);
const char *n = spell_name(sp, lang);
token.v = sp;
addtoken(names->tokens, n, token);
}
m->spellnames = names;
}
return NULL;
if (findtoken(names->tokens, name, &token) != E_TOK_NOMATCH) {
return (spell *) token.v;
}
return 0;
}
spell *find_spellbyid(magic_t mtype, spellid_t id)
spell *find_spellbyid(unsigned int id)
{
quicklist *ql;
int qi;
@ -180,9 +119,7 @@ spell *find_spellbyid(magic_t mtype, spellid_t id)
spell *sp = (spell *) ql_get(ql, qi);
unsigned int hashid = hashstring(sp->sname);
if (hashid == id) {
if (sp->magietyp == mtype || mtype == M_NONE) {
return sp;
}
return sp;
}
}

View file

@ -29,6 +29,8 @@ extern "C" {
struct curse_type;
struct castorder;
struct curse;
struct region;
struct unit;
/* Prototypen */
@ -43,9 +45,11 @@ extern "C" {
extern struct attrib_type at_wdwpyramid;
extern struct quicklist *spells;
extern struct spell * create_spell(const char * name);
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);
extern struct spell *find_spell(const char *name);
extern struct spell *find_spellbyid(unsigned int i);
extern struct spell *get_spellfromtoken(struct unit *u, const char *s,
const struct locale *lang);

29
src/kernel/spell_test.c Normal file
View file

@ -0,0 +1,29 @@
#include <util/quicklist.h>
#include <kernel/spell.h>
#include <kernel/magic.h>
#include <cutest/CuTest.h>
#include <tests.h>
#include <stdlib.h>
static void test_register_spell(CuTest * tc)
{
spell * sp;
CuAssertPtrEquals(tc, 0, find_spell("testspell"));
CuAssertPtrEquals(tc, spells, 0);
sp = create_spell("testspell");
sp->magietyp = 5;
register_spell(sp);
CuAssertIntEquals(tc, 1, ql_length(spells));
CuAssertPtrEquals(tc, sp, find_spell("testspell"));
}
CuSuite *get_spell_suite(void)
{
CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_register_spell);
return suite;
}

View file

@ -31,10 +31,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <util/variant.h>
typedef short terrain_t;
typedef short magic_t;
typedef short typ_t;
typedef short item_t;
typedef unsigned int spellid_t;
struct attrib;
struct attrib_type;
@ -375,6 +373,19 @@ typedef enum {
NODIRECTION = -1
} direction_t;
typedef enum {
M_GRAY = 0, /* Gray */
M_ILLAUN = 1, /* Illaun */
M_TYBIED = 2, /* Tybied */
M_CERDDOR = 3, /* Cerddor */
M_GWYRRD = 4, /* Gwyrrd */
M_DRAIG = 5, /* Draig */
M_COMMON = 6, /* common spells */
MAXMAGIETYP,
/* this enum is stored in the datafile, so do not change the numbers around */
M_NONE = -1
} magic_t;
#define DONT_HELP 0
#define HELP_MONEY 1 /* Mitversorgen von Einheiten */
#define HELP_FIGHT 2 /* Bei Verteidigung mithelfen */

View file

@ -90,7 +90,7 @@ static const spell *xml_spell(xmlNode * node, const char *name)
const spell *sp = NULL;
xmlChar *propValue = xmlGetProp(node, BAD_CAST name);
if (propValue != NULL) {
sp = find_spell(M_NONE, (const char *)propValue);
sp = find_spell((const char *)propValue);
assert(sp);
xmlFree(propValue);
}
@ -1322,12 +1322,14 @@ static void add_spells(equipment * eq, xmlNodeSetPtr nsetItems)
propValue = xmlGetProp(node, BAD_CAST "name");
assert(propValue != NULL);
sp = find_spell(mtype, (const char *)propValue);
assert(sp);
xmlFree(propValue);
if (sp != NULL) {
sp = find_spell((const char *)propValue);
if (!sp) {
log_error(("no spell '%s' in school '%s' for equipment-set '%s'\n",
(const char *)propValue, magic_school[mtype], eq->name));
} else {
equipment_addspell(eq, sp);
}
xmlFree(propValue);
}
}
}
@ -1492,13 +1494,13 @@ static int parse_spells(xmlDocPtr doc)
xmlChar *propValue;
int k;
spell_component *component;
spell *sp = (spell *) calloc(1, sizeof(spell));
spell *sp;
static int modes[] = { 0, PRECOMBATSPELL, COMBATSPELL, POSTCOMBATSPELL };
/* spellname */
propValue = xmlGetProp(node, BAD_CAST "name");
assert(propValue != NULL);
sp->sname = strdup((const char *)propValue);
sp = create_spell((const char *)propValue);
xmlFree(propValue);
propValue = xmlGetProp(node, BAD_CAST "parameters");

View file

@ -7,6 +7,7 @@
#include <util/base36_test.c>
#include <util/quicklist_test.c>
#include <kernel/move_test.c>
#include <kernel/spell_test.c>
#include <kernel/curse_test.c>
#include <kernel/battle_test.c>
#include <gamecode/laws_test.c>
@ -38,6 +39,7 @@ int RunAllTests(void)
CuSuiteAddSuite(suite, get_curse_suite());
CuSuiteAddSuite(suite, get_market_suite());
CuSuiteAddSuite(suite, get_move_suite());
CuSuiteAddSuite(suite, get_spell_suite());
CuSuiteAddSuite(suite, get_laws_suite());
CuSuiteAddSuite(suite, get_battle_suite());

View file

@ -61,6 +61,7 @@ void addtoken(tnode * root, const char *str, variant id)
0, ""}
};
assert(root);
if (!*str) {
root->id = id;
root->flags |= LEAF;
@ -135,8 +136,18 @@ void addtoken(tnode * root, const char *str, variant id)
}
}
void freetokens(struct tnode *root)
{
int i;
for (i=0;root && i!=NODEHASHSIZE;++i) {
freetokens(root->next[i]->node);
free(root->next[i]);
}
}
int findtoken(const tnode * tk, const char *str, variant * result)
{
assert(tk);
if (!str || *str == 0)
return E_TOK_NOMATCH;

View file

@ -38,6 +38,7 @@ extern "C" {
int findtoken(const struct tnode *tk, const char *str, variant * result);
void addtoken(struct tnode *root, const char *str, variant id);
void freetokens(struct tnode *root);
typedef struct local_names {
struct local_names *next;