From 3cb1d1a071b99203fc4908e8550baa9b1a4e714f Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 29 Apr 2018 13:13:10 +0200 Subject: [PATCH 1/3] simplify race masking for weapon modifiers. --- res/core/weapons/greatbow.xml | 4 +--- res/core/weapons/mallornbow.xml | 4 +--- res/e3a/armor.xml | 4 +--- res/e3a/weapons.xml | 4 +--- res/eressea/items.xml | 4 +--- src/battle.c | 30 +++++++++--------------------- src/kernel/item.c | 11 ----------- src/kernel/item.h | 4 ++-- src/xmlreader.c | 24 ++++++------------------ 9 files changed, 22 insertions(+), 67 deletions(-) diff --git a/res/core/weapons/greatbow.xml b/res/core/weapons/greatbow.xml index b30cae8c6..a63761535 100644 --- a/res/core/weapons/greatbow.xml +++ b/res/core/weapons/greatbow.xml @@ -11,9 +11,7 @@ - - - + diff --git a/res/core/weapons/mallornbow.xml b/res/core/weapons/mallornbow.xml index 9164d2c4b..b50104e36 100644 --- a/res/core/weapons/mallornbow.xml +++ b/res/core/weapons/mallornbow.xml @@ -10,9 +10,7 @@ - - - + diff --git a/res/e3a/armor.xml b/res/e3a/armor.xml index d0d5138ef..160e527d9 100644 --- a/res/e3a/armor.xml +++ b/res/e3a/armor.xml @@ -8,9 +8,7 @@ - - - + diff --git a/res/e3a/weapons.xml b/res/e3a/weapons.xml index 3a75fe350..6f9b5fa5e 100644 --- a/res/e3a/weapons.xml +++ b/res/e3a/weapons.xml @@ -136,9 +136,7 @@ - - - + diff --git a/res/eressea/items.xml b/res/eressea/items.xml index 2cfa9e653..ea6ab047d 100644 --- a/res/eressea/items.xml +++ b/res/eressea/items.xml @@ -10,9 +10,7 @@ - - - + diff --git a/src/battle.c b/src/battle.c index f6a1314ea..fb91a1998 100644 --- a/src/battle.c +++ b/src/battle.c @@ -723,6 +723,7 @@ bool missile) } if (wtype->modifiers != NULL) { /* Pferdebonus, Lanzenbonus, usw. */ + const race *rc = u_race(tu); int m; unsigned int flags = WMF_SKILL | (attacking ? WMF_OFFENSIVE : WMF_DEFENSIVE); @@ -738,17 +739,10 @@ bool missile) for (m = 0; wtype->modifiers[m].value; ++m) { if ((wtype->modifiers[m].flags & flags) == flags) { - race_list *rlist = wtype->modifiers[m].races; - if (rlist != NULL) { - while (rlist) { - if (rlist->data == u_race(tu)) - break; - rlist = rlist->next; - } - if (rlist == NULL) - continue; + int mask = wtype->modifiers[m].race_mask; + if ((mask == 0) || (mask & rc->mask_item)) { + skill += wtype->modifiers[m].value; } - skill += wtype->modifiers[m].value; } } } @@ -1029,17 +1023,10 @@ static int rc_specialdamage(const unit *au, const unit *du, const struct weapon_ for (m = 0; wtype->modifiers[m].value; ++m) { /* weapon damage for this weapon, possibly by race */ if (wtype->modifiers[m].flags & WMF_DAMAGE) { - race_list *rlist = wtype->modifiers[m].races; - if (rlist != NULL) { - while (rlist) { - if (rlist->data == ar) - break; - rlist = rlist->next; - } - if (rlist == NULL) - continue; + int mask = wtype->modifiers[m].race_mask; + if ((mask == 0) || (mask & ar->mask_item)) { + modifier += wtype->modifiers[m].value; } - modifier += wtype->modifiers[m].value; } } } @@ -3272,8 +3259,9 @@ fighter *make_fighter(battle * b, unit * u, side * s1, bool attack) adata->atype = itm->type->rtype->atype; adata->count = itm->number; for (aptr = &fig->armors; *aptr; aptr = &(*aptr)->next) { - if (adata->atype->prot > (*aptr)->atype->prot) + if (adata->atype->prot > (*aptr)->atype->prot) { break; + } } adata->next = *aptr; *aptr = adata; diff --git a/src/kernel/item.c b/src/kernel/item.c index ab6ad8c8d..ad811fefd 100644 --- a/src/kernel/item.c +++ b/src/kernel/item.c @@ -609,16 +609,6 @@ mod_elves_only(const unit * u, const region * r, skill_t sk, int value) return -118; } -static int -mod_dwarves_only(const unit * u, const region * r, skill_t sk, int value) -{ - UNUSED_ARG(r); - if (u_race(u) == get_race(RC_DWARF) || (u_race(u)->ec_flags & ECF_IRONGOLEM)) { - return value; - } - return -118; -} - void register_item_give(int(*foo) (struct unit *, struct unit *, const struct item_type *, int, struct order *), const char *name) @@ -973,7 +963,6 @@ void register_resources(void) registered = true; register_function((pf_generic)mod_elves_only, "mod_elves_only"); - register_function((pf_generic)mod_dwarves_only, "mod_dwarves_only"); register_function((pf_generic)res_changeitem, "changeitem"); register_function((pf_generic)res_changeperson, "changeperson"); register_function((pf_generic)res_changepeasants, "changepeasants"); diff --git a/src/kernel/item.h b/src/kernel/item.h index e7bfef7cc..e08c95e57 100644 --- a/src/kernel/item.h +++ b/src/kernel/item.h @@ -147,8 +147,8 @@ extern "C" { struct race_list; typedef struct weapon_mod { int value; - unsigned int flags; - struct race_list *races; + int flags; + int race_mask; } weapon_mod; #define ATF_NONE 0x00 diff --git a/src/xmlreader.c b/src/xmlreader.c index 333e891df..fa81ea11d 100644 --- a/src/xmlreader.c +++ b/src/xmlreader.c @@ -520,6 +520,8 @@ static armor_type *xml_readarmor(xmlXPathContextPtr xpath, item_type * itype) return atype; } +static void mask_races(xmlNodePtr node, const char *key, int *maskp); + static weapon_type *xml_readweapon(xmlXPathContextPtr xpath, item_type * itype) { xmlNodePtr node = xpath->node; @@ -591,8 +593,7 @@ static weapon_type *xml_readweapon(xmlXPathContextPtr xpath, item_type * itype) wtype->modifiers = calloc(result->nodesetval->nodeNr + 1, sizeof(weapon_mod)); for (k = 0; k != result->nodesetval->nodeNr; ++k) { xmlNodePtr node = result->nodesetval->nodeTab[k]; - xmlXPathObjectPtr races; - int r, flags = 0; + int flags = 0; if (xml_bvalue(node, "walking", false)) flags |= WMF_WALKING; @@ -619,21 +620,8 @@ static weapon_type *xml_readweapon(xmlXPathContextPtr xpath, item_type * itype) wtype->modifiers[k].flags = flags; wtype->modifiers[k].value = xml_ivalue(node, "value", 0); - xpath->node = node; - races = xmlXPathEvalExpression(BAD_CAST "race", xpath); - for (r = 0; r != races->nodesetval->nodeNr; ++r) { - xmlNodePtr node = races->nodesetval->nodeTab[r]; - - propValue = xmlGetProp(node, BAD_CAST "name"); - if (propValue != NULL) { - const race *rc = rc_find((const char *)propValue); - if (rc == NULL) - rc = rc_get_or_create((const char *)propValue); - racelist_insert(&wtype->modifiers[k].races, rc); - xmlFree(propValue); - } - } - xmlXPathFreeObject(races); + mask_races(node, "races", &wtype->modifiers[k].race_mask); + wtype->modifiers[k].race_mask = 0; } xmlXPathFreeObject(result); @@ -1311,7 +1299,7 @@ static void parse_ai(race * rc, xmlNodePtr node) rc->flags |= RCF_ATTACK_MOVED; } -static void set_study_speed(race *rc, skill_t sk, int modifier){ +static void set_study_speed(race *rc, skill_t sk, int modifier) { if (!rc->study_speed) rc->study_speed = calloc(1, MAXSKILLS); rc->study_speed[sk] = (char)modifier; From ac786e034ca4a8ac38c56fe17b644bac8dbf9e60 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 28 Apr 2018 16:14:32 +0200 Subject: [PATCH 2/3] extract rc_mask, add it to exparse code. --- src/kernel/race.c | 17 +++++++++++++++++ src/kernel/race.h | 2 ++ src/kernel/race.test.c | 15 +++++++++++++++ src/xmlreader.c | 13 +------------ 4 files changed, 35 insertions(+), 12 deletions(-) diff --git a/src/kernel/race.c b/src/kernel/race.c index edf415223..c9299d5bd 100644 --- a/src/kernel/race.c +++ b/src/kernel/race.c @@ -574,3 +574,20 @@ struct race * read_race_reference(struct storage *store) void register_race_function(race_func func, const char *name) { register_function((pf_generic)func, name); } + +static int race_mask = 1; + +int rc_mask(char *list) { + int mask = 0; + char * tok = strtok(list, " ,"); + while (tok) { + race * rc = rc_get_or_create(tok); + if (!rc->mask_item) { + rc->mask_item = race_mask; + race_mask = race_mask << 1; + } + mask |= rc->mask_item; + tok = strtok(NULL, " ,"); + } + return mask; +} diff --git a/src/kernel/race.h b/src/kernel/race.h index 1203eaed2..042cb5e78 100644 --- a/src/kernel/race.h +++ b/src/kernel/race.h @@ -197,6 +197,8 @@ extern "C" { #define MIGRANTS_NONE 0 #define MIGRANTS_LOG10 1 int rc_migrants_formula(const race *rc); + + int rc_mask(char *list); /* Flags. Do not reorder these without changing json_race() in jsonconf.c */ #define RCF_NPC (1<<0) /* cannot be the race for a player faction (and other limits?) */ diff --git a/src/kernel/race.test.c b/src/kernel/race.test.c index dcb4ce6f7..2f34c127e 100644 --- a/src/kernel/race.test.c +++ b/src/kernel/race.test.c @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -172,6 +173,19 @@ static void test_racename(CuTest *tc) { test_teardown(); } +static void test_rc_mask(CuTest *tc) { + int mask; + char list[64]; + test_setup(); + strcpy(list, "goblin dwarf"); + mask = rc_mask(list); + CuAssertIntEquals(tc, 3, mask); + CuAssertStrEquals(tc, "goblin", list); + mask = rc_mask(list); + CuAssertIntEquals(tc, 1, mask); + test_teardown(); +} + CuSuite *get_race_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -180,6 +194,7 @@ CuSuite *get_race_suite(void) SUITE_ADD_TEST(suite, test_rc_name); SUITE_ADD_TEST(suite, test_rc_defaults); SUITE_ADD_TEST(suite, test_rc_find); + SUITE_ADD_TEST(suite, test_rc_mask); SUITE_ADD_TEST(suite, test_rc_set_param); SUITE_ADD_TEST(suite, test_rc_can_use); SUITE_ADD_TEST(suite, test_racename); diff --git a/src/xmlreader.c b/src/xmlreader.c index fa81ea11d..edbf677ef 100644 --- a/src/xmlreader.c +++ b/src/xmlreader.c @@ -656,23 +656,12 @@ static weapon_type *xml_readweapon(xmlXPathContextPtr xpath, item_type * itype) return wtype; } -static int race_mask = 1; - static void mask_races(xmlNodePtr node, const char *key, int *maskp) { xmlChar *propValue = xmlGetProp(node, BAD_CAST key); int mask = 0; assert(maskp); if (propValue) { - char * tok = strtok((char *)propValue, " ,"); - while (tok) { - race * rc = rc_get_or_create(tok); - if (!rc->mask_item) { - rc->mask_item = race_mask; - race_mask = race_mask << 1; - } - mask |= rc->mask_item; - tok = strtok(NULL, " ,"); - } + mask = rc_mask((char *)propValue); xmlFree(propValue); } *maskp = mask; From 837ab325f9aca9aee0b40479c62bb8880cf4a0b3 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 29 Apr 2018 13:46:17 +0200 Subject: [PATCH 3/3] XML simplificatio: unified system for masking races on modifiers. --- res/core/resources/iron.xml | 2 +- res/core/resources/stone.xml | 2 +- res/core/weapons/greatbow.xml | 2 +- res/e3a/armor.xml | 6 ++---- res/e3a/weapons.xml | 4 ++-- src/economy.c | 7 ++++--- src/economy.test.c | 12 ++++++------ src/kernel/build.c | 2 +- src/kernel/race.c | 20 +++++++++++++------- src/kernel/race.h | 3 ++- src/kernel/race.test.c | 4 ++-- src/kernel/resources.h | 2 +- src/xmlreader.c | 34 ++++++++++++---------------------- 13 files changed, 48 insertions(+), 52 deletions(-) diff --git a/res/core/resources/iron.xml b/res/core/resources/iron.xml index 38ddb33c8..ae4829dd7 100644 --- a/res/core/resources/iron.xml +++ b/res/core/resources/iron.xml @@ -8,7 +8,7 @@ - + diff --git a/res/core/resources/stone.xml b/res/core/resources/stone.xml index b8f91eadc..459e66074 100644 --- a/res/core/resources/stone.xml +++ b/res/core/resources/stone.xml @@ -7,7 +7,7 @@ - + diff --git a/res/core/weapons/greatbow.xml b/res/core/weapons/greatbow.xml index a63761535..ad6a4e018 100644 --- a/res/core/weapons/greatbow.xml +++ b/res/core/weapons/greatbow.xml @@ -2,7 +2,7 @@ - + diff --git a/res/e3a/armor.xml b/res/e3a/armor.xml index 160e527d9..207f873b2 100644 --- a/res/e3a/armor.xml +++ b/res/e3a/armor.xml @@ -2,8 +2,7 @@ - - + @@ -20,8 +19,7 @@ - - + diff --git a/res/e3a/weapons.xml b/res/e3a/weapons.xml index 6f9b5fa5e..3eea6dc44 100644 --- a/res/e3a/weapons.xml +++ b/res/e3a/weapons.xml @@ -31,7 +31,7 @@ - + @@ -127,7 +127,7 @@ * has a lua canuse function * has lower damage --> - + diff --git a/src/economy.c b/src/economy.c index 18ca23b8e..4cabb4ab5 100644 --- a/src/economy.c +++ b/src/economy.c @@ -833,7 +833,8 @@ static struct message * get_modifiers(unit *u, skill_t sk, const resource_type * for (mod = rtype->modifiers; mod && mod->type != RMT_END; ++mod) { if (mod->btype == NULL || mod->btype == btype) { - if (mod->race == NULL || mod->race == u_race(u)) { + const race * rc = u_race(u); + if (mod->race_mask == 0 || (mod->race_mask & rc->mask_item)) { switch (mod->type) { case RMT_PROD_SAVE: if (savep) { @@ -845,7 +846,7 @@ static struct message * get_modifiers(unit *u, skill_t sk, const resource_type * mod_skill(mod, sk, &skill); break; case RMT_PROD_REQUIRE: - if (mod->race) need_race |= 1; + if (mod->race_mask) need_race |= 1; if (mod->btype) { need_bldg |= 1; } @@ -857,7 +858,7 @@ static struct message * get_modifiers(unit *u, skill_t sk, const resource_type * } } if (mod->type == RMT_PROD_REQUIRE) { - if (mod->race) need_race |= 2; + if (mod->race_mask) need_race |= 2; if (mod->btype) { btype_needed = mod->btype; need_bldg |= 2; diff --git a/src/economy.test.c b/src/economy.test.c index 282318191..3e5d39007 100644 --- a/src/economy.test.c +++ b/src/economy.test.c @@ -509,7 +509,7 @@ static void test_modify_material(CuTest *tc) { mod = rtype->modifiers = calloc(2, sizeof(resource_mod)); mod[0].type = RMT_USE_SAVE; mod[0].value = frac_make(2, 1); - mod[0].race = u_race(u); + mod[0].race_mask = rc_mask(u_race(u)); itype = test_create_itemtype("sword"); make_item(u, itype, 1); @@ -574,7 +574,7 @@ static void test_modify_skill(CuTest *tc) { mod[0].type = RMT_PROD_SKILL; mod[0].value.sa[0] = SK_WEAPONSMITH; mod[0].value.sa[1] = 1; - mod[0].race = u_race(u); + mod[0].race_mask = rc_mask(u_race(u)); set_item(u, rtype->itype, 2); /* 2 iron should get us 2 swords */ make_item(u, itype, 2); @@ -647,7 +647,7 @@ static void test_modify_production(CuTest *tc) { rtype->modifiers = calloc(3, sizeof(resource_mod)); rtype->modifiers[0].type = RMT_PROD_SAVE; - rtype->modifiers[0].race = u->_race; + rtype->modifiers[0].race_mask = rc_mask(u->_race); rtype->modifiers[0].value.sa[0] = (short)(0.5+100*d); rtype->modifiers[0].value.sa[1] = 100; rtype->modifiers[1].type = RMT_END; @@ -668,7 +668,7 @@ static void test_modify_production(CuTest *tc) { CuAssertIntEquals(tc, 280, region_getresource(u->region, rtype)); /* 50% saving = 3 stones make 6 stones */ rtype->modifiers[0].type = RMT_PROD_REQUIRE; - rtype->modifiers[0].race = NULL; + rtype->modifiers[0].race_mask = 0; rtype->modifiers[0].btype = bt_get_or_create("mine"); test_clear_messages(u->faction); @@ -677,7 +677,7 @@ static void test_modify_production(CuTest *tc) { CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "building_needed")); rtype->modifiers[0].type = RMT_PROD_REQUIRE; - rtype->modifiers[0].race = test_create_race("smurf"); + rtype->modifiers[0].race_mask = rc_mask(test_create_race("smurf")); rtype->modifiers[0].btype = NULL; test_clear_messages(u->faction); @@ -686,7 +686,7 @@ static void test_modify_production(CuTest *tc) { CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "error117")); rtype->modifiers[1].type = RMT_PROD_REQUIRE; - rtype->modifiers[1].race = u_race(u); + rtype->modifiers[1].race_mask = rc_mask(u_race(u)); rtype->modifiers[1].btype = NULL; rtype->modifiers[2].type = RMT_END; diff --git a/src/kernel/build.c b/src/kernel/build.c index b2774fbd7..96aee5662 100644 --- a/src/kernel/build.c +++ b/src/kernel/build.c @@ -419,7 +419,7 @@ static int matmod(const unit * u, const resource_type * rtype, int value) for (mod = rtype->modifiers; mod->type != RMT_END; ++mod) { if (mod->type == RMT_USE_SAVE) { if (!mod->btype || mod->btype == btype) { - if (!mod->race || mod->race == rc) { + if (!mod->race_mask || (mod->race_mask & rc->mask_item)) { save = frac_mul(save, mod->value); } } diff --git a/src/kernel/race.c b/src/kernel/race.c index c9299d5bd..ac81f7f78 100644 --- a/src/kernel/race.c +++ b/src/kernel/race.c @@ -259,7 +259,10 @@ void racelist_insert(struct race_list **rl, const struct race *r) *rl = rl2; } +static int race_mask = 0; + void free_races(void) { + race_mask = 0; while (races) { int i; race * rc = races->next; @@ -347,6 +350,10 @@ race *rc_create(const char *zName) assert(zName); rc = (race *)calloc(sizeof(race), 1); + + rc->mask_item = 1 << race_mask; + ++race_mask; + rc->magres.sa[1] = 1; rc->hitpoints = 1; rc->weight = PERSON_WEIGHT; @@ -575,18 +582,17 @@ void register_race_function(race_func func, const char *name) { register_function((pf_generic)func, name); } -static int race_mask = 1; +int rc_mask(const race * rc) { + assert(rc->mask_item); + return rc->mask_item; +} -int rc_mask(char *list) { +int rc_get_mask(char *list) { int mask = 0; char * tok = strtok(list, " ,"); while (tok) { race * rc = rc_get_or_create(tok); - if (!rc->mask_item) { - rc->mask_item = race_mask; - race_mask = race_mask << 1; - } - mask |= rc->mask_item; + mask |= rc_mask(rc); tok = strtok(NULL, " ,"); } return mask; diff --git a/src/kernel/race.h b/src/kernel/race.h index 042cb5e78..7c38eec57 100644 --- a/src/kernel/race.h +++ b/src/kernel/race.h @@ -198,7 +198,8 @@ extern "C" { #define MIGRANTS_LOG10 1 int rc_migrants_formula(const race *rc); - int rc_mask(char *list); + int rc_mask(const race *rc); + int rc_get_mask(char *list); /* Flags. Do not reorder these without changing json_race() in jsonconf.c */ #define RCF_NPC (1<<0) /* cannot be the race for a player faction (and other limits?) */ diff --git a/src/kernel/race.test.c b/src/kernel/race.test.c index 2f34c127e..d695969b7 100644 --- a/src/kernel/race.test.c +++ b/src/kernel/race.test.c @@ -178,10 +178,10 @@ static void test_rc_mask(CuTest *tc) { char list[64]; test_setup(); strcpy(list, "goblin dwarf"); - mask = rc_mask(list); + mask = rc_get_mask(list); CuAssertIntEquals(tc, 3, mask); CuAssertStrEquals(tc, "goblin", list); - mask = rc_mask(list); + mask = rc_get_mask(list); CuAssertIntEquals(tc, 1, mask); test_teardown(); } diff --git a/src/kernel/resources.h b/src/kernel/resources.h index 2daa44dd8..8f291c305 100644 --- a/src/kernel/resources.h +++ b/src/kernel/resources.h @@ -50,7 +50,7 @@ extern "C" { resource_modifier_type type; variant value; const struct building_type *btype; - const struct race *race; + int race_mask; } resource_mod; typedef struct rawmaterial_type { diff --git a/src/xmlreader.c b/src/xmlreader.c index edbf677ef..adddb808e 100644 --- a/src/xmlreader.c +++ b/src/xmlreader.c @@ -61,6 +61,17 @@ without prior permission by the authors of Eressea. #include +static void mask_races(xmlNodePtr node, const char *key, int *maskp) { + xmlChar *propValue = xmlGetProp(node, BAD_CAST key); + int mask = 0; + assert(maskp); + if (propValue) { + mask = rc_get_mask((char *)propValue); + xmlFree(propValue); + } + *maskp = mask; +} + static variant xml_fraction(xmlNodePtr node, const char *name) { xmlChar *propValue = xmlGetProp(node, BAD_CAST name); if (propValue != NULL) { @@ -129,16 +140,8 @@ static resource_mod * xml_readmodifiers(xmlXPathObjectPtr result, xmlNodePtr nod xmlNodePtr node = result->nodesetval->nodeTab[k]; xmlChar *propValue; building_type *btype = NULL; - const race *rc = NULL; - propValue = xmlGetProp(node, BAD_CAST "race"); - if (propValue != NULL) { - rc = rc_find((const char *)propValue); - if (rc == NULL) - rc = rc_get_or_create((const char *)propValue); - xmlFree(propValue); - } - modifiers[k].race = rc; + mask_races(node, "races", &modifiers[k].race_mask); propValue = xmlGetProp(node, BAD_CAST "building"); if (propValue != NULL) { @@ -520,8 +523,6 @@ static armor_type *xml_readarmor(xmlXPathContextPtr xpath, item_type * itype) return atype; } -static void mask_races(xmlNodePtr node, const char *key, int *maskp); - static weapon_type *xml_readweapon(xmlXPathContextPtr xpath, item_type * itype) { xmlNodePtr node = xpath->node; @@ -656,17 +657,6 @@ static weapon_type *xml_readweapon(xmlXPathContextPtr xpath, item_type * itype) return wtype; } -static void mask_races(xmlNodePtr node, const char *key, int *maskp) { - xmlChar *propValue = xmlGetProp(node, BAD_CAST key); - int mask = 0; - assert(maskp); - if (propValue) { - mask = rc_mask((char *)propValue); - xmlFree(propValue); - } - *maskp = mask; -} - static item_type *xml_readitem(xmlXPathContextPtr xpath, resource_type * rtype) { xmlNodePtr node = xpath->node;