diff --git a/scripts/tests/e3/init.lua b/scripts/tests/e3/init.lua index 95df86c4c..28a2cf6e5 100644 --- a/scripts/tests/e3/init.lua +++ b/scripts/tests/e3/init.lua @@ -4,6 +4,7 @@ require 'tests.e3.spells' require 'tests.e3.rules' require 'tests.e3.parser' require 'tests.e3.morale' +require 'tests.e3.items' require 'tests.orders' require 'tests.common' require 'tests.items' diff --git a/scripts/tests/e3/items.lua b/scripts/tests/e3/items.lua new file mode 100644 index 000000000..9c6035bf7 --- /dev/null +++ b/scripts/tests/e3/items.lua @@ -0,0 +1,35 @@ +require "lunit" + +module("tests.e3.items", package.seeall, lunit.testcase ) + +function setup() + eressea.game.reset() + eressea.settings.set("rules.food.flags", "4") -- food is free + eressea.settings.set("NewbieImmunity", "0") +end + +function test_goblins() + local r = region.create(0, 0, "plain") + assert(r) + local f1 = faction.create("goblin@eressea.de", "goblin", "de") + local f2 = faction.create("dwarf@eressea.de", "dwarf", "de") + local f3 = faction.create("elf@eressea.de", "elf", "de") + local u1 = unit.create(f1, r, 1) + local u2 = unit.create(f2, r, 1) + local u3 = unit.create(f3, r, 1) + + local restricted = { + "towershield", "rep_crossbow", "plate", "lance", + "mllornlance", "greatbow", "greataxe", "axe", "scale", + "plate", "rustyhalberd", "halberd", "greatsword" + } + for k, v in ipairs(restricted) do + u1:add_item(v, 1) + u2:add_item(v, 1) + u2:add_item(v, 1) + end + + u1:add_order("ATTACKIERE " .. itoa36(u2.id)) + u1:add_order("ATTACKIERE " .. itoa36(u3.id)) + process_orders() +end diff --git a/src/battle.c b/src/battle.c index 9864adc41..9e2958242 100644 --- a/src/battle.c +++ b/src/battle.c @@ -576,10 +576,12 @@ static weapon *select_weapon(const troop t, bool attacking, static bool i_canuse(const unit * u, const item_type * itype) { + bool result = true; if (itype->canuse) { - return itype->canuse(u, itype); + result = itype->canuse(u, itype); } - return true; + assert(result==rc_can_use(u_race(u), itype)); + return result; } static int diff --git a/src/kernel/item.h b/src/kernel/item.h index 14196ab37..d38a21340 100644 --- a/src/kernel/item.h +++ b/src/kernel/item.h @@ -121,6 +121,8 @@ extern "C" { unsigned int flags; int weight; int capacity; + int mask_allow; + int mask_deny; struct construction *construction; char *_appearance[2]; /* wie es f�r andere aussieht */ /* --- functions --- */ diff --git a/src/kernel/race.c b/src/kernel/race.c index d159fd6d8..efe38dcfe 100644 --- a/src/kernel/race.c +++ b/src/kernel/race.c @@ -54,6 +54,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. /* libc includes */ #include #include +#include #include #include #include @@ -94,6 +95,7 @@ enum { RCO_TRADEHERB }; + static void rc_setoption(race *rc, int k, const char *value) { unsigned char key = (unsigned char)k; int i; @@ -323,6 +325,17 @@ bool rc_changed(int *cache) { return false; } +bool rc_can_use(const struct race *rc, const struct item_type *itype) +{ + if (itype->mask_allow) { + return (rc->mask_item==0 || (itype->mask_allow & rc->mask_item) != 0); + } + if (itype->mask_deny) { + return (itype->mask_deny & rc->mask_item) == 0; + } + return true; +} + race *rc_create(const char *zName) { race *rc; diff --git a/src/kernel/race.h b/src/kernel/race.h index f14b8e54f..fcd78ae19 100644 --- a/src/kernel/race.h +++ b/src/kernel/race.h @@ -48,6 +48,7 @@ extern "C" { struct spellref; struct locale; struct rcoption; + struct item_type; extern int num_races; @@ -140,6 +141,7 @@ extern "C" { int flags; int battle_flags; int ec_flags; + int mask_item; struct att attack[RACE_ATTACKS]; signed char bonus[MAXSKILLS]; @@ -174,6 +176,8 @@ extern "C" { const race *rc_find(const char *); void free_races(void); + bool rc_can_use(const struct race *rc, const struct item_type *itype); + typedef enum name_t { NAME_SINGULAR, NAME_PLURAL, NAME_DEFINITIVE, NAME_CATEGORY } name_t; const char * rc_name_s(const race *rc, name_t n); const char * rc_name(const race *rc, name_t n, char *name, size_t size); diff --git a/src/kernel/race.test.c b/src/kernel/race.test.c index 07ecbdd45..b292a825e 100644 --- a/src/kernel/race.test.c +++ b/src/kernel/race.test.c @@ -1,10 +1,13 @@ #include #include #include "race.h" -#include +#include "item.h" + #include +#include #include +#include #include static void test_rc_name(CuTest *tc) { @@ -100,6 +103,54 @@ static void test_rc_set_param(CuTest *tc) { test_cleanup(); } +static void test_rc_can_use(CuTest *tc) { + race *rc; + item_type *itype; + + test_setup(); + rc = test_create_race("goblin"); + itype = test_create_itemtype("plate"); + CuAssertTrue(tc, rc_can_use(rc, itype)); + + /* default case. all items and races in E2 */ + itype->mask_deny = 0; + rc->mask_item = 0; + CuAssertTrue(tc, rc_can_use(rc, itype)); + + /* some race is forbidden from using this item. */ + itype->mask_deny = 1; + + /* we are not that race. */ + rc->mask_item = 2; + CuAssertTrue(tc, rc_can_use(rc, itype)); + + /* we are that race */ + rc->mask_item = 1; + CuAssertTrue(tc, ! rc_can_use(rc, itype)); + + /* we are not a special race at all */ + rc->mask_item = 0; + CuAssertTrue(tc, rc_can_use(rc, itype)); + + /* only one race is allowed to use this item */ + itype->mask_deny = 0; + itype->mask_allow = 1; + + /* we are not that race */ + rc->mask_item = 2; + CuAssertTrue(tc, ! rc_can_use(rc, itype)); + + /* we are that race */ + rc->mask_item = 1; + CuAssertTrue(tc, rc_can_use(rc, itype)); + + /* we are not special */ + rc->mask_item = 0; + CuAssertTrue(tc, rc_can_use(rc, itype)); + + test_cleanup(); +} + CuSuite *get_race_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -109,6 +160,7 @@ CuSuite *get_race_suite(void) SUITE_ADD_TEST(suite, test_rc_defaults); SUITE_ADD_TEST(suite, test_rc_find); SUITE_ADD_TEST(suite, test_rc_set_param); + SUITE_ADD_TEST(suite, test_rc_can_use); return suite; }