From d5e989954479e4edcff208c8a0196d2b6f165409 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 5 Jul 2014 10:45:03 -0700 Subject: [PATCH 01/18] remove battle statistics, the flag is not set anywhere, and I have not used them in ages. --- src/kernel/battle.c | 67 --------------------------------------------- 1 file changed, 67 deletions(-) diff --git a/src/kernel/battle.c b/src/kernel/battle.c index d678dfa7c..ec04dba76 100644 --- a/src/kernel/battle.c +++ b/src/kernel/battle.c @@ -4057,70 +4057,6 @@ static bool start_battle(region * r, battle ** bp) return fighting; } -static void battle_stats(FILE * F, battle * b) -{ - typedef struct stat_info { - struct stat_info *next; - const weapon_type *wtype; - int level; - int number; - } stat_info; - side *s; - - for (s = b->sides; s != b->sides + b->nsides; ++s) { - fighter *df; - stat_info *stats = NULL, *stat; - - for (df = s->fighters; df; df = df->next) { - unit *du = df->unit; - troop dt; - stat_info *slast = NULL; - - dt.fighter = df; - for (dt.index = 0; dt.index != du->number; ++dt.index) { - weapon *wp = preferred_weapon(dt, true); - int level = wp ? wp->attackskill : 0; - const weapon_type *wtype = wp ? wp->type : NULL; - stat_info **slist = &stats; - - if (slast && slast->wtype == wtype && slast->level == level) { - ++slast->number; - continue; - } - while (*slist && (*slist)->wtype != wtype) { - slist = &(*slist)->next; - } - while (*slist && (*slist)->wtype == wtype && (*slist)->level > level) { - slist = &(*slist)->next; - } - stat = *slist; - if (stat == NULL || stat->wtype != wtype || stat->level != level) { - stat = (stat_info*)calloc(1, sizeof(stat_info)); - stat->wtype = wtype; - stat->level = level; - stat->next = *slist; - *slist = stat; - } - slast = stat; - ++slast->number; - } - } - - fprintf(F, "##STATS## Heer %u - %s:\n", army_index(s), - factionname(s->faction)); - for (stat = stats; stat != NULL; stat = stat->next) { - fprintf(F, "%s %u : %u\n", - stat->wtype ? stat->wtype->itype->rtype->_name[0] : "none", stat->level, - stat->number); - } - while (stats) { - stat_info *stat = stats; - stats = stat->next; - free(stat); - } - } -} - /** execute one round of attacks * fig->fighting is used to determine who attacks, not fig->alive, since * the latter may be influenced by attacks that already took place. @@ -4289,9 +4225,6 @@ void do_battle(region * r) b->has_tactics_turn = false; } - if (b->region->flags & RF_COMBATDEBUG) - battle_stats(bdebug, b); - /* PRECOMBATSPELLS */ do_combatmagic(b, DO_PRECOMBATSPELL); From d743d32215e6ced6f3800a397005e65ed3ff7e29 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 5 Jul 2014 10:46:00 -0700 Subject: [PATCH 02/18] bind "blocked" flag for Lua (bug 1922). remove unused region-flags. --- src/bind_region.c | 19 +++++++++++++++++++ src/kernel/region.h | 43 ++++++++++++++++++++----------------------- 2 files changed, 39 insertions(+), 23 deletions(-) diff --git a/src/bind_region.c b/src/bind_region.c index 7606a266d..5db39b6fc 100644 --- a/src/bind_region.c +++ b/src/bind_region.c @@ -62,6 +62,22 @@ static int tolua_region_get_id(lua_State * L) return 1; } +static int tolua_region_get_blocked(lua_State * L) +{ + region *self = (region *)tolua_tousertype(L, 1, 0); + lua_pushboolean(L, (self->flags&RF_BLOCKED)!=0); + return 1; +} + +static int tolua_region_set_blocked(lua_State * L) +{ + region *self = (region *)tolua_tousertype(L, 1, 0); + bool flag = !!tolua_toboolean(L, 2, 1); + if (flag) self->flags |= BLD_WORKING; + else self->flags &= ~BLD_WORKING; + return 0; +} + static int tolua_region_get_x(lua_State * L) { region *self = (region *) tolua_tousertype(L, 1, 0); @@ -652,6 +668,9 @@ void tolua_region_open(lua_State * L) tolua_function(L, TOLUA_CAST "destroy", tolua_region_destroy); tolua_function(L, TOLUA_CAST "__tostring", tolua_region_tostring); + /* flags */ + tolua_variable(L, TOLUA_CAST "blocked", tolua_region_get_blocked, tolua_region_set_blocked); + tolua_variable(L, TOLUA_CAST "id", tolua_region_get_id, NULL); tolua_variable(L, TOLUA_CAST "x", tolua_region_get_x, NULL); tolua_variable(L, TOLUA_CAST "y", tolua_region_get_y, NULL); diff --git a/src/kernel/region.h b/src/kernel/region.h index d427dd5f2..1e5493ad3 100644 --- a/src/kernel/region.h +++ b/src/kernel/region.h @@ -27,41 +27,38 @@ extern "C" { #include "direction.h" /* FAST_CONNECT: regions are directly connected to neighbours, saves doing - a hash-access each time a neighbour is needed */ + a hash-access each time a neighbour is needed, 6 extra pointers per hex */ #define FAST_CONNECT -#define RF_CHAOTIC (1<<0) -#define RF_MALLORN (1<<1) -#define RF_BLOCKED (1<<2) +#define RF_CHAOTIC (1<<0) /* persistent */ +#define RF_MALLORN (1<<1) /* persistent */ +#define RF_BLOCKED (1<<2) /* persistent */ -#define RF_BLOCK_NORTHWEST (1<<3) -#define RF_BLOCK_NORTHEAST (1<<4) -#define RF_BLOCK_EAST (1<<5) -#define RF_BLOCK_SOUTHEAST (1<<6) -#define RF_BLOCK_SOUTHWEST (1<<7) -#define RF_BLOCK_WEST (1<<8) +#define RF_UNUSED_3 (1<<3) +#define RF_UNUSED_4 (1<<4) +#define RF_UNUSED_5 (1<<5) +#define RF_UNUSED_6 (1<<6) +#define RF_UNUSED_7 (1<<7) +#define RF_UNUSED_8 (1<<8) -#define RF_ENCOUNTER (1<<9) -#define RF_MIGRATION (1<<10) -#define RF_UNUSED_1 (1<<11) -#define RF_ORCIFIED (1<<12) -#define RF_CURSED (1<<13) +#define RF_ENCOUNTER (1<<9) /* persistent */ +#define RF_MAPPER_HIGHLIGHT (1<<10) +#define RF_LIGHTHOUSE (1<<11) /* this region may contain a lighthouse */ +#define RF_ORCIFIED (1<<12) /* persistent */ +#define RF_MIGRATION (1<<13) - /* debug flags */ -#define RF_COMBATDEBUG (1<<14) -#define RF_MAPPER_HIGHLIGHT (1<<14) /* only used by mapper, not stored */ -#define RF_LIGHTHOUSE (1<<15) /* this region may contain a lighthouse */ +#define RF_UNUSED_14 (1<<14) +#define RF_UNUSED_15 (1<<15) +#define RF_UNUSED_16 (1<<16) #define RF_SELECT (1<<17) #define RF_MARK (1<<18) - -/* flags that speed up attribute access: */ #define RF_TRAVELUNIT (1<<19) -#define RF_GUARDED (1<<20) +#define RF_GUARDED (1<<20) /* persistent */ #define RF_ALL 0xFFFFFF -#define RF_SAVEMASK (RF_GUARDED|RF_CHAOTIC|RF_MALLORN|RF_BLOCKED|RF_BLOCK_NORTHWEST|RF_BLOCK_NORTHEAST|RF_BLOCK_EAST|RF_BLOCK_SOUTHEAST|RF_BLOCK_SOUTHWEST|RF_BLOCK_WEST|RF_ENCOUNTER|RF_ORCIFIED) +#define RF_SAVEMASK (RF_CHAOTIC|RF_MALLORN|RF_BLOCKED|RF_ENCOUNTER|RF_ORCIFIED|RF_GUARDED) struct message; struct message_list; struct rawmaterial; From 587df7fd12e70d9681a9a4089f7ef28952c883d7 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 5 Jul 2014 11:01:08 -0700 Subject: [PATCH 03/18] Migranten-Konversion gibt es nicht mehr. http://bugs.eressea.de/view.php?id=1502 --- core/res/messages.xml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/core/res/messages.xml b/core/res/messages.xml index e87c4900f..37b5acafa 100644 --- a/core/res/messages.xml +++ b/core/res/messages.xml @@ -8305,14 +8305,6 @@ "Meeoooooow..." - - - - - "Die Götter segnen $unit($unit) mit der richtigen Rasse." - "The gods are blessing $unit($unit) with the correct race." - - From 4a8707b06d003b82cfe5b98191e6167773b13a25 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 5 Jul 2014 18:21:20 -0700 Subject: [PATCH 04/18] fix a fall-through in jsonconf causing an error message. add tests for pool, not working because of missing GIVEITEM on JSON-configured races (TBD). --- se/eressea.vpj | 2 ++ se/tests.vpj | 1 + src/kernel/jsonconf.c | 3 ++- tests/init.lua | 1 + tests/pool.lua | 38 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 tests/pool.lua diff --git a/se/eressea.vpj b/se/eressea.vpj index 8f9b39b6c..78271d8af 100644 --- a/se/eressea.vpj +++ b/se/eressea.vpj @@ -246,6 +246,7 @@ + @@ -403,6 +404,7 @@ + diff --git a/se/tests.vpj b/se/tests.vpj index 9f4e1362e..f40c0151c 100644 --- a/se/tests.vpj +++ b/se/tests.vpj @@ -246,6 +246,7 @@ + diff --git a/src/kernel/jsonconf.c b/src/kernel/jsonconf.c index a73936afd..7ed042666 100644 --- a/src/kernel/jsonconf.c +++ b/src/kernel/jsonconf.c @@ -106,8 +106,9 @@ static void json_maintenance_i(cJSON *json, maintenance *mt) { mt->flags = json_flags(child, flags); } else { - log_error_n("maintenance contains unknown attribute %s", child->string); + log_error_n("maintenance contains unknown array %s", child->string); } + break; default: log_error_n("maintenance contains unknown attribute %s", child->string); } diff --git a/tests/init.lua b/tests/init.lua index 2d10882db..f286cbcf7 100644 --- a/tests/init.lua +++ b/tests/init.lua @@ -8,3 +8,4 @@ require "tests.castles" require "tests.spells" require "tests.movement" require "tests.ships" +require "tests.pool" diff --git a/tests/pool.lua b/tests/pool.lua new file mode 100644 index 000000000..01f62420f --- /dev/null +++ b/tests/pool.lua @@ -0,0 +1,38 @@ +require "lunit" + +module("tests.eressea.pool", package.seeall, lunit.testcase ) + +function setup() + eressea.free_game() + eressea.config.reset(); + eressea.settings.set("rules.economy.food", "0") + eressea.settings.set("nmr.removenewbie", "0") + eressea.settings.set("nmr.timeout", "0") + conf = [[{ + "races": { + "human" : {} + }, + "terrains" : { + "plain": { "flags" : [ "land" ] } + }, + "keywords" : { + "de" : { + "give" : "GIB" + } + } + }]] + + assert(eressea.config.parse(conf)==0) +end + +function test_give_nopool() + local r = region.create(1, 1, "plain") + local f = faction.create("test@example.com", "human", "de") + local u1 = unit.create(f, r, 1) + local u2 = unit.create(f, r, 1) + u1:add_item("money", 100) + u1:add_order("GIB " .. itoa36(u2.id) .. " 100 SILBER") + process_orders() + assert_equal(0, u1:get_item("money")) + assert_equal(100, u2:get_item("money")) +end From 5b437c5833cce545a489d1f14fdd1729c82bbe5f Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 5 Jul 2014 19:20:15 -0700 Subject: [PATCH 05/18] Replace RCF_PLAYERRACE with RCF_NPC, it's the less confusing default for tests. --- src/kernel/jsonconf.test.c | 6 +++--- src/kernel/race.h | 4 ++-- src/kernel/xmlreader.c | 4 ++-- src/tests.c | 1 - 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/kernel/jsonconf.test.c b/src/kernel/jsonconf.test.c index 932b88ac0..3d7ffbbeb 100644 --- a/src/kernel/jsonconf.test.c +++ b/src/kernel/jsonconf.test.c @@ -32,7 +32,7 @@ static void check_flag(CuTest *tc, const char *name, int flag) { } static void test_flags(CuTest *tc) { - check_flag(tc, "playerrace", RCF_PLAYERRACE); + check_flag(tc, "npc", RCF_NPC); check_flag(tc, "scarepeasants", RCF_SCAREPEASANTS); check_flag(tc, "cansteal", RCF_CANSTEAL); check_flag(tc, "noheal", RCF_NOHEAL); @@ -56,7 +56,7 @@ static void test_races(CuTest * tc) "\"capacity\" : 4," "\"hp\" : 5," "\"ac\" : 6," - "\"flags\" : [ \"playerrace\", \"walk\", \"undead\" ]" + "\"flags\" : [ \"npc\", \"walk\", \"undead\" ]" "}}}"; cJSON *json = cJSON_Parse(data); const struct race *rc; @@ -70,7 +70,7 @@ static void test_races(CuTest * tc) CuAssertPtrNotNull(tc, races); rc = rc_find("orc"); CuAssertPtrNotNull(tc, rc); - CuAssertIntEquals(tc, RCF_PLAYERRACE|RCF_WALK|RCF_UNDEAD, rc->flags); + CuAssertIntEquals(tc, RCF_NPC|RCF_WALK|RCF_UNDEAD, rc->flags); CuAssertStrEquals(tc, "1d4", rc->def_damage); CuAssertDblEquals(tc, 1.0, rc->magres, 0.0); CuAssertDblEquals(tc, 2.0, rc->maxaura, 0.0); diff --git a/src/kernel/race.h b/src/kernel/race.h index 3f83e6a53..3834dbfb7 100644 --- a/src/kernel/race.h +++ b/src/kernel/race.h @@ -184,7 +184,7 @@ extern "C" { void free_races(void); /* Flags */ -#define RCF_PLAYERRACE (1<<0) /* can be played by a player. */ +#define RCF_NPC (1<<0) /* can be played by a player. */ #define RCF_KILLPEASANTS (1<<1) /* Töten Bauern. Dämonen werden nicht über dieses Flag, sondern in randenc() behandelt. */ #define RCF_SCAREPEASANTS (1<<2) #define RCF_CANSTEAL (1<<3) @@ -238,7 +238,7 @@ extern "C" { #define omniscient(f) ((f)->race==get_race(RC_ILLUSION) || (f)->race==get_race(RC_TEMPLATE)) -#define playerrace(rc) (fval((rc), RCF_PLAYERRACE)) +#define playerrace(rc) (!fval((rc), RCF_NPC)) #define dragonrace(rc) ((rc) == get_race(RC_FIREDRAGON) || (rc) == get_race(RC_DRAGON) || (rc) == get_race(RC_WYRM) || (rc) == get_race(RC_BIRTHDAYDRAGON)) #define humanoidrace(rc) (fval((rc), RCF_UNDEAD) || (rc)==get_race(RC_DRACOID) || playerrace(rc)) #define illusionaryrace(rc) (fval(rc, RCF_ILLUSIONARY)) diff --git a/src/kernel/xmlreader.c b/src/kernel/xmlreader.c index 3d5c962eb..bc0bcd50e 100644 --- a/src/kernel/xmlreader.c +++ b/src/kernel/xmlreader.c @@ -1668,8 +1668,8 @@ static int parse_races(xmlDocPtr doc) rc->at_bonus = (char)xml_ivalue(node, "attackmodifier", 0); rc->df_bonus = (char)xml_ivalue(node, "defensemodifier", 0); - if (xml_bvalue(node, "playerrace", false)) - rc->flags |= RCF_PLAYERRACE; + if (!xml_bvalue(node, "playerrace", false)) + rc->flags |= RCF_NPC; if (xml_bvalue(node, "scarepeasants", false)) rc->flags |= RCF_SCAREPEASANTS; if (xml_bvalue(node, "cansteal", true)) diff --git a/src/tests.c b/src/tests.c index 00e8db540..abe9b085a 100644 --- a/src/tests.c +++ b/src/tests.c @@ -25,7 +25,6 @@ struct race *test_create_race(const char *name) { race *rc = rc_get_or_create(name); - rc->flags |= RCF_PLAYERRACE; rc->maintenance = 10; return rc; } From 072f927d5b46309b8675c014a1be8adf616b8e47 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 5 Jul 2014 19:29:12 -0700 Subject: [PATCH 06/18] replace RCF_CANSTEAL with RCF_NOSTEAL for less confusing default behavior. --- src/economy.c | 2 +- src/kernel/jsonconf.c | 4 ++-- src/kernel/jsonconf.test.c | 2 +- src/kernel/race.h | 10 +++++----- src/kernel/xmlreader.c | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/economy.c b/src/economy.c index 79ca4022c..1b6a4136b 100644 --- a/src/economy.c +++ b/src/economy.c @@ -2760,7 +2760,7 @@ static void steal_cmd(unit * u, struct order *ord, request ** stealorders) assert(skill_enabled(SK_PERCEPTION) && skill_enabled(SK_STEALTH)); - if (!fval(u_race(u), RCF_CANSTEAL)) { + if (fval(u_race(u), RCF_NOSTEAL)) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "race_nosteal", "race", u_race(u))); return; diff --git a/src/kernel/jsonconf.c b/src/kernel/jsonconf.c index 7ed042666..ef771f8ac 100644 --- a/src/kernel/jsonconf.c +++ b/src/kernel/jsonconf.c @@ -326,8 +326,8 @@ static void json_ship(cJSON *json, ship_type *st) { static void json_race(cJSON *json, race *rc) { cJSON *child; const char *flags[] = { - "playerrace", "killpeasants", "scarepeasants", - "cansteal", "moverandom", "cannotmove", + "npc", "killpeasants", "scarepeasants", + "nosteal", "moverandom", "cannotmove", "learn", "fly", "swim", "walk", "nolearn", "noteach", "horse", "desert", "illusionary", "absorbpeasants", "noheal", diff --git a/src/kernel/jsonconf.test.c b/src/kernel/jsonconf.test.c index 3d7ffbbeb..ad525ef33 100644 --- a/src/kernel/jsonconf.test.c +++ b/src/kernel/jsonconf.test.c @@ -34,7 +34,7 @@ static void check_flag(CuTest *tc, const char *name, int flag) { static void test_flags(CuTest *tc) { check_flag(tc, "npc", RCF_NPC); check_flag(tc, "scarepeasants", RCF_SCAREPEASANTS); - check_flag(tc, "cansteal", RCF_CANSTEAL); + check_flag(tc, "nosteal", RCF_NOSTEAL); check_flag(tc, "noheal", RCF_NOHEAL); check_flag(tc, "undead", RCF_UNDEAD); check_flag(tc, "dragon", RCF_DRAGON); diff --git a/src/kernel/race.h b/src/kernel/race.h index 3834dbfb7..62793bb12 100644 --- a/src/kernel/race.h +++ b/src/kernel/race.h @@ -183,11 +183,11 @@ extern "C" { const struct weapon_type *); void free_races(void); -/* Flags */ -#define RCF_NPC (1<<0) /* can be played by a player. */ -#define RCF_KILLPEASANTS (1<<1) /* Töten Bauern. Dämonen werden nicht über dieses Flag, sondern in randenc() behandelt. */ -#define RCF_SCAREPEASANTS (1<<2) -#define RCF_CANSTEAL (1<<3) +/* 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?) */ +#define RCF_KILLPEASANTS (1<<1) /* a monster that eats peasants */ +#define RCF_SCAREPEASANTS (1<<2) /* a monster that scares peasants out of the hex */ +#define RCF_NOSTEAL (1<<3) /* this race has high stealth, but is not allowed to steal */ #define RCF_MOVERANDOM (1<<4) #define RCF_CANNOTMOVE (1<<5) #define RCF_LEARN (1<<6) /* Lernt automatisch wenn struct faction == 0 */ diff --git a/src/kernel/xmlreader.c b/src/kernel/xmlreader.c index bc0bcd50e..3832c9bb1 100644 --- a/src/kernel/xmlreader.c +++ b/src/kernel/xmlreader.c @@ -1672,8 +1672,8 @@ static int parse_races(xmlDocPtr doc) rc->flags |= RCF_NPC; if (xml_bvalue(node, "scarepeasants", false)) rc->flags |= RCF_SCAREPEASANTS; - if (xml_bvalue(node, "cansteal", true)) - rc->flags |= RCF_CANSTEAL; + if (!xml_bvalue(node, "cansteal", true)) + rc->flags |= RCF_NOSTEAL; if (xml_bvalue(node, "cansail", true)) rc->flags |= RCF_CANSAIL; if (xml_bvalue(node, "cannotmove", false)) From f14264e3bb88278179e9964e71f2abd67341d6b6 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 5 Jul 2014 20:14:11 -0700 Subject: [PATCH 07/18] test coverage for can_steal. add a default message for when no messages are loaded, so that msg_feedback/msg_message doesn't return NULL when XML has not been laoded. initialize some core stuff before running tests (there probably needs to be more). --- src/economy.c | 40 +++++++------ src/economy.h | 2 + src/economy.test.c | 134 ++++++++++++++++++++++++++++++++------------ src/eressea.c | 3 +- src/kernel/config.c | 9 ++- src/test_eressea.c | 4 ++ 6 files changed, 135 insertions(+), 57 deletions(-) diff --git a/src/economy.c b/src/economy.c index 1b6a4136b..5bbeb4106 100644 --- a/src/economy.c +++ b/src/economy.c @@ -2747,6 +2747,24 @@ static int max_skill(region * r, faction * f, skill_t sk) return w; } +message * can_steal(const unit * u, struct order *ord) { + plane *pl; + + if (fval(u_race(u), RCF_NOSTEAL)) { + return msg_feedback(u, ord, "race_nosteal", "race", u_race(u)); + } + + if (fval(u->region->terrain, SEA_REGION) && u_race(u) != get_race(RC_AQUARIAN)) { + return msg_feedback(u, ord, "error_onlandonly", ""); + } + + pl = rplane(u->region); + if (pl && fval(pl, PFL_NOATTACK)) { + return msg_feedback(u, ord, "error270", ""); + } + return 0; +} + static void steal_cmd(unit * u, struct order *ord, request ** stealorders) { const resource_type *rring = get_resourcetype(R_RING_OF_NIMBLEFINGER); @@ -2756,27 +2774,15 @@ static void steal_cmd(unit * u, struct order *ord, request ** stealorders) unit *u2 = NULL; region *r = u->region; faction *f = NULL; - plane *pl; + message * msg; assert(skill_enabled(SK_PERCEPTION) && skill_enabled(SK_STEALTH)); - if (fval(u_race(u), RCF_NOSTEAL)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "race_nosteal", "race", - u_race(u))); - return; + msg = can_steal(u, ord); + if (msg) { + ADDMSG(&u->faction->msgs, msg); + return; } - - if (fval(r->terrain, SEA_REGION) && u_race(u) != get_race(RC_AQUARIAN)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_onlandonly", "")); - return; - } - - pl = rplane(r); - if (pl && fval(pl, PFL_NOATTACK)) { - cmistake(u, ord, 270, MSG_INCOME); - return; - } - init_tokens(ord); skip_token(); id = read_unitid(u->faction, r); diff --git a/src/economy.h b/src/economy.h index 8b44df380..63e5cbeaf 100644 --- a/src/economy.h +++ b/src/economy.h @@ -57,6 +57,8 @@ extern "C" { extern int give_control_cmd(struct unit *u, struct order *ord); extern void give_control(struct unit * u, struct unit * u2); + struct message * can_steal(const struct unit * u, struct order *ord); + #ifdef __cplusplus } #endif diff --git a/src/economy.test.c b/src/economy.test.c index 61294b1da..e0b9e16b0 100644 --- a/src/economy.test.c +++ b/src/economy.test.c @@ -2,60 +2,122 @@ #include #include "economy.h" +#include #include +#include #include #include #include +#include #include #include static void test_give_control_building(CuTest * tc) { - unit *u1, *u2; - building *b; - struct faction *f; - region *r; + unit *u1, *u2; + building *b; + struct faction *f; + region *r; - test_cleanup(); - test_create_world(); - f = test_create_faction(0); - r = findregion(0, 0); - b = test_create_building(r, 0); - u1 = test_create_unit(f, r); - u_set_building(u1, b); - u2 = test_create_unit(f, r); - u_set_building(u2, b); - CuAssertPtrEquals(tc, u1, building_owner(b)); - give_control(u1, u2); - CuAssertPtrEquals(tc, u2, building_owner(b)); + test_cleanup(); + test_create_world(); + f = test_create_faction(0); + r = findregion(0, 0); + b = test_create_building(r, 0); + u1 = test_create_unit(f, r); + u_set_building(u1, b); + u2 = test_create_unit(f, r); + u_set_building(u2, b); + CuAssertPtrEquals(tc, u1, building_owner(b)); + give_control(u1, u2); + CuAssertPtrEquals(tc, u2, building_owner(b)); + test_cleanup(); } static void test_give_control_ship(CuTest * tc) { - unit *u1, *u2; - ship *sh; - struct faction *f; - region *r; + unit *u1, *u2; + ship *sh; + struct faction *f; + region *r; - test_cleanup(); - test_create_world(); - f = test_create_faction(0); - r = findregion(0, 0); - sh = test_create_ship(r, 0); - u1 = test_create_unit(f, r); - u_set_ship(u1, sh); - u2 = test_create_unit(f, r); - u_set_ship(u2, sh); - CuAssertPtrEquals(tc, u1, ship_owner(sh)); - give_control(u1, u2); - CuAssertPtrEquals(tc, u2, ship_owner(sh)); + test_cleanup(); + test_create_world(); + f = test_create_faction(0); + r = findregion(0, 0); + sh = test_create_ship(r, 0); + u1 = test_create_unit(f, r); + u_set_ship(u1, sh); + u2 = test_create_unit(f, r); + u_set_ship(u2, sh); + CuAssertPtrEquals(tc, u1, ship_owner(sh)); + give_control(u1, u2); + CuAssertPtrEquals(tc, u2, ship_owner(sh)); + test_cleanup(); +} + +static struct { + struct unit *u; + struct region *r; + struct faction *f; +} steal; + +static void setup_steal(terrain_type *ter, race *rc) { + steal.r = test_create_region(0, 0, ter); + steal.f = test_create_faction(0); + steal.u = test_create_unit(steal.f, steal.r); +} + +static void test_steal_okay(CuTest * tc) { + race *rc; + terrain_type *ter; + + test_cleanup(); + ter = test_create_terrain("plain", LAND_REGION); + rc = test_create_race("human"); + rc->flags = 0; + setup_steal(ter, rc); + CuAssertPtrEquals(tc, 0, can_steal(steal.u, 0)); + test_cleanup(); +} + +static void test_steal_nosteal(CuTest * tc) { + race *rc; + terrain_type *ter; + message *msg; + + test_cleanup(); + ter = test_create_terrain("plain", LAND_REGION); + rc = test_create_race("human"); + rc->flags = RCF_NOSTEAL; + setup_steal(ter, rc); + CuAssertPtrNotNull(tc, msg=can_steal(steal.u, 0)); + msg_release(msg); + test_cleanup(); +} + +static void test_steal_ocean(CuTest * tc) { + race *rc; + terrain_type *ter; + message *msg; + + test_cleanup(); + ter = test_create_terrain("ocean", SEA_REGION); + rc = test_create_race("human"); + setup_steal(ter, rc); + CuAssertPtrNotNull(tc, msg = can_steal(steal.u, 0)); + msg_release(msg); + test_cleanup(); } CuSuite *get_economy_suite(void) { - CuSuite *suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, test_give_control_building); - SUITE_ADD_TEST(suite, test_give_control_ship); - return suite; + CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_give_control_building); + SUITE_ADD_TEST(suite, test_give_control_ship); + SUITE_ADD_TEST(suite, test_steal_okay); + SUITE_ADD_TEST(suite, test_steal_ocean); + SUITE_ADD_TEST(suite, test_steal_nosteal); + return suite; } diff --git a/src/eressea.c b/src/eressea.c index 16e9763f3..4900693a3 100755 --- a/src/eressea.c +++ b/src/eressea.c @@ -49,11 +49,10 @@ void game_done(void) void game_init(void) { - kernel_init(); + kernel_init(); register_triggers(); register_xmas(); - register_reports(); register_nr(); register_cr(); diff --git a/src/kernel/config.c b/src/kernel/config.c index 4d0fcacfa..61f02a211 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -46,6 +46,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "plane.h" #include "pool.h" #include "race.h" +#include "reports.h" #include "region.h" #include "save.h" #include "ship.h" @@ -2744,8 +2745,12 @@ void attrib_init(void) void kernel_init(void) { - attrib_init(); - translation_init(); + register_reports(); + if (!mt_find("missing_message")) { + mt_register(mt_new_va("missing_message", "name:string", 0)); + } + attrib_init(); + translation_init(); } static order * defaults[MAXLOCALES]; diff --git a/src/test_eressea.c b/src/test_eressea.c index 2b0fbee53..f93f88e48 100644 --- a/src/test_eressea.c +++ b/src/test_eressea.c @@ -1,7 +1,10 @@ +#include +#include #include #include #include + CuSuite *get_tests_suite(void); CuSuite *get_callback_suite(void); CuSuite *get_jsonconf_suite(void); @@ -39,6 +42,7 @@ int RunAllTests(void) int flags = log_flags; log_flags = LOG_FLUSH | LOG_CPERROR; + kernel_init(); /* self-test */ CuSuiteAddSuite(suite, get_tests_suite()); From b9b627a1713809045256016075eccf047709fc7d Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 5 Jul 2014 21:12:34 -0700 Subject: [PATCH 08/18] refactor setup for economy tests. rename can_steal->check_steal for consistent naming, check_give->can_give, too. --- src/economy.c | 31 +++++++++++++++++---------- src/economy.h | 3 ++- src/economy.test.c | 52 +++++++++++++++++++++++++++++++++++----------- 3 files changed, 62 insertions(+), 24 deletions(-) diff --git a/src/economy.c b/src/economy.c index 5bbeb4106..53f5ad4cd 100644 --- a/src/economy.c +++ b/src/economy.c @@ -390,8 +390,7 @@ static void feedback_give_not_allowed(unit * u, order * ord) "")); } -static bool check_give(unit * u, unit * u2, const item_type * itype, - int mask) +static bool can_give(const unit * u, const unit * u2, const item_type * itype, int mask) { if (u2) { if (u->faction != u2->faction) { @@ -700,6 +699,14 @@ int give_control_cmd(unit * u, order * ord) return 0; } +message *check_give(const unit *u, const unit *u2, order * ord) { + if (!can_give(u, u2, NULL, GIVE_ALLITEMS)) { + return msg_feedback(u, ord, "feedback_give_forbidden", ""); + } + + return 0; +} + static void give_cmd(unit * u, order * ord) { region *r = u->region; @@ -709,6 +716,7 @@ static void give_cmd(unit * u, order * ord) const item_type *itype; param_t p; plane *pl; + message *msg; init_tokens(ord); skip_token(); @@ -729,9 +737,10 @@ static void give_cmd(unit * u, order * ord) return; } - if (!check_give(u, u2, NULL, GIVE_ALLITEMS)) { - feedback_give_not_allowed(u, ord); - return; + msg = check_give(u, u2, ord); + if (msg) { + ADDMSG(&u->faction->msgs, msg); + return; } /* Damit Tarner nicht durch die Fehlermeldung enttarnt werden können */ @@ -773,7 +782,7 @@ static void give_cmd(unit * u, order * ord) msg_feedback(u, ord, "race_nogive", "race", u_race(u))); return; } - if (!check_give(u, u2, NULL, GIVE_HERBS)) { + if (!can_give(u, u2, NULL, GIVE_HERBS)) { feedback_give_not_allowed(u, ord); return; } @@ -831,7 +840,7 @@ static void give_cmd(unit * u, order * ord) else if (p == P_ANY) { const char *s; - if (!check_give(u, u2, NULL, GIVE_ALLITEMS)) { + if (!can_give(u, u2, NULL, GIVE_ALLITEMS)) { feedback_give_not_allowed(u, ord); return; } @@ -888,7 +897,7 @@ static void give_cmd(unit * u, order * ord) if (itype != NULL) { item *i = *i_find(&u->items, itype); if (i != NULL) { - if (check_give(u, u2, itype, 0)) { + if (can_give(u, u2, itype, 0)) { n = i->number - get_reservation(u, itype->rtype); give_item(n, itype, u, u2, ord); } else { @@ -941,7 +950,7 @@ static void give_cmd(unit * u, order * ord) itype = finditemtype(s, u->faction->locale); if (itype != NULL) { - if (check_give(u, u2, itype, 0)) { + if (can_give(u, u2, itype, 0)) { give_item(n, itype, u, u2, ord); } else { feedback_give_not_allowed(u, ord); @@ -2747,7 +2756,7 @@ static int max_skill(region * r, faction * f, skill_t sk) return w; } -message * can_steal(const unit * u, struct order *ord) { +message * check_steal(const unit * u, struct order *ord) { plane *pl; if (fval(u_race(u), RCF_NOSTEAL)) { @@ -2778,7 +2787,7 @@ static void steal_cmd(unit * u, struct order *ord, request ** stealorders) assert(skill_enabled(SK_PERCEPTION) && skill_enabled(SK_STEALTH)); - msg = can_steal(u, ord); + msg = check_steal(u, ord); if (msg) { ADDMSG(&u->faction->msgs, msg); return; diff --git a/src/economy.h b/src/economy.h index 63e5cbeaf..4ee69ea4b 100644 --- a/src/economy.h +++ b/src/economy.h @@ -57,7 +57,8 @@ extern "C" { extern int give_control_cmd(struct unit *u, struct order *ord); extern void give_control(struct unit * u, struct unit * u2); - struct message * can_steal(const struct unit * u, struct order *ord); + struct message * check_steal(const struct unit * u, struct order *ord); + struct message * check_give(const struct unit * u, const struct unit * u2, struct order *ord); #ifdef __cplusplus } diff --git a/src/economy.test.c b/src/economy.test.c index e0b9e16b0..54741e97a 100644 --- a/src/economy.test.c +++ b/src/economy.test.c @@ -57,19 +57,20 @@ static void test_give_control_ship(CuTest * tc) test_cleanup(); } -static struct { +struct steal { struct unit *u; struct region *r; struct faction *f; -} steal; +}; -static void setup_steal(terrain_type *ter, race *rc) { - steal.r = test_create_region(0, 0, ter); - steal.f = test_create_faction(0); - steal.u = test_create_unit(steal.f, steal.r); +static void setup_steal(struct steal *env, terrain_type *ter, race *rc) { + env->r = test_create_region(0, 0, ter); + env->f = test_create_faction(rc); + env->u = test_create_unit(env->f, env->r); } static void test_steal_okay(CuTest * tc) { + struct steal env; race *rc; terrain_type *ter; @@ -77,12 +78,13 @@ static void test_steal_okay(CuTest * tc) { ter = test_create_terrain("plain", LAND_REGION); rc = test_create_race("human"); rc->flags = 0; - setup_steal(ter, rc); - CuAssertPtrEquals(tc, 0, can_steal(steal.u, 0)); + setup_steal(&env, ter, rc); + CuAssertPtrEquals(tc, 0, check_steal(env.u, 0)); test_cleanup(); } static void test_steal_nosteal(CuTest * tc) { + struct steal env; race *rc; terrain_type *ter; message *msg; @@ -91,13 +93,14 @@ static void test_steal_nosteal(CuTest * tc) { ter = test_create_terrain("plain", LAND_REGION); rc = test_create_race("human"); rc->flags = RCF_NOSTEAL; - setup_steal(ter, rc); - CuAssertPtrNotNull(tc, msg=can_steal(steal.u, 0)); + setup_steal(&env, ter, rc); + CuAssertPtrNotNull(tc, msg = check_steal(env.u, 0)); msg_release(msg); test_cleanup(); } static void test_steal_ocean(CuTest * tc) { + struct steal env; race *rc; terrain_type *ter; message *msg; @@ -105,12 +108,36 @@ static void test_steal_ocean(CuTest * tc) { test_cleanup(); ter = test_create_terrain("ocean", SEA_REGION); rc = test_create_race("human"); - setup_steal(ter, rc); - CuAssertPtrNotNull(tc, msg = can_steal(steal.u, 0)); + setup_steal(&env, ter, rc); + CuAssertPtrNotNull(tc, msg = check_steal(env.u, 0)); msg_release(msg); test_cleanup(); } +struct give { + struct unit *src, *dst; + struct region *r; + struct faction *f; +}; + +static void setup_give(struct give *env) { + terrain_type *ter = test_create_terrain("plain", LAND_REGION); + struct race * rc = test_create_race("human"); + env->r = test_create_region(0, 0, ter); + env->f = test_create_faction(0); + env->src = test_create_unit(env->f, env->r); + env->dst = test_create_unit(env->f, env->r); +} + +static void test_give_okay(CuTest * tc) { + struct give env; + test_cleanup(); + setup_give(&env); + + CuAssertPtrEquals(tc, 0, check_give(env.src, env.dst, 0)); + test_cleanup(); +} + CuSuite *get_economy_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -119,5 +146,6 @@ CuSuite *get_economy_suite(void) SUITE_ADD_TEST(suite, test_steal_okay); SUITE_ADD_TEST(suite, test_steal_ocean); SUITE_ADD_TEST(suite, test_steal_nosteal); + SUITE_ADD_TEST(suite, test_give_okay); return suite; } From b21cb8f5c725f660c84e3fddfe1dd7afe3a6c99a Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 5 Jul 2014 23:06:51 -0700 Subject: [PATCH 09/18] Simple test for rules.give (there are many more, can_give deserves a test to itself). The more tests I write, the more I hate the infrastructure for them. --- src/economy.c | 1 - src/economy.test.c | 32 +++++++++++++++++++++++++++----- src/kernel/config.c | 1 + src/util/language.c | 3 +-- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/economy.c b/src/economy.c index 53f5ad4cd..0f1a7874e 100644 --- a/src/economy.c +++ b/src/economy.c @@ -703,7 +703,6 @@ message *check_give(const unit *u, const unit *u2, order * ord) { if (!can_give(u, u2, NULL, GIVE_ALLITEMS)) { return msg_feedback(u, ord, "feedback_give_forbidden", ""); } - return 0; } diff --git a/src/economy.test.c b/src/economy.test.c index 54741e97a..395f97a84 100644 --- a/src/economy.test.c +++ b/src/economy.test.c @@ -1,4 +1,5 @@ #include +#include #include #include "economy.h" @@ -117,27 +118,47 @@ static void test_steal_ocean(CuTest * tc) { struct give { struct unit *src, *dst; struct region *r; - struct faction *f; + struct faction *f1, *f2; }; static void setup_give(struct give *env) { terrain_type *ter = test_create_terrain("plain", LAND_REGION); - struct race * rc = test_create_race("human"); env->r = test_create_region(0, 0, ter); - env->f = test_create_faction(0); - env->src = test_create_unit(env->f, env->r); - env->dst = test_create_unit(env->f, env->r); + env->src = test_create_unit(env->f1, env->r); + env->dst = test_create_unit(env->f2, env->r); } static void test_give_okay(CuTest * tc) { struct give env; + struct race * rc; + test_cleanup(); + rc = test_create_race("human"); + env.f2 = env.f1 = test_create_faction(rc); setup_give(&env); + set_param(&global.parameters, "rules.give", "0"); CuAssertPtrEquals(tc, 0, check_give(env.src, env.dst, 0)); test_cleanup(); } +static void test_give_denied_by_rules(CuTest * tc) { + struct give env; + struct race * rc; + struct message *msg; + + test_cleanup(); + rc = test_create_race("human"); + env.f1 = test_create_faction(rc); + env.f2 = test_create_faction(rc); + setup_give(&env); + + set_param(&global.parameters, "rules.give", "0"); + CuAssertPtrNotNull(tc, msg=check_give(env.src, env.dst, 0)); + msg_release(msg); + test_cleanup(); +} + CuSuite *get_economy_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -147,5 +168,6 @@ CuSuite *get_economy_suite(void) SUITE_ADD_TEST(suite, test_steal_ocean); SUITE_ADD_TEST(suite, test_steal_nosteal); SUITE_ADD_TEST(suite, test_give_okay); + SUITE_ADD_TEST(suite, test_give_denied_by_rules); return suite; } diff --git a/src/kernel/config.c b/src/kernel/config.c index 61f02a211..01fb7a7ee 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -2748,6 +2748,7 @@ void kernel_init(void) register_reports(); if (!mt_find("missing_message")) { mt_register(mt_new_va("missing_message", "name:string", 0)); + mt_register(mt_new_va("missing_feedback", "unit:unit", "region:region", "command:order", "name:string", 0)); } attrib_init(); translation_init(); diff --git a/src/util/language.c b/src/util/language.c index 601be6245..f5e98797b 100644 --- a/src/util/language.c +++ b/src/util/language.c @@ -189,8 +189,7 @@ void locale_setstring(locale * lang, const char *key, const char *value) const char *locale_name(const locale * lang) { - assert(lang); - return lang->name; + return lang ? lang->name : "(null)"; } char *mkname_buf(const char *space, const char *name, char *buffer) From 5ec3f5b83aa5b599df8ecec0d8afea1612e173f1 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 5 Jul 2014 23:31:34 -0700 Subject: [PATCH 10/18] use race::flags|RCF_NOGIVE instead of race::ec_flags|GIVEITEM None of this has tests, it'd going to be years before a change like this can be made without fear D-: --- src/economy.c | 9 +++++---- src/kernel/battle.c | 4 ++-- src/kernel/jsonconf.c | 3 ++- src/kernel/jsonconf.test.c | 1 + src/kernel/pool.c | 4 ++-- src/kernel/race.h | 1 + src/kernel/unit.c | 22 ++++++++-------------- src/kernel/unit.h | 2 -- src/kernel/xmlreader.c | 5 +++-- src/laws.c | 10 ++++------ 10 files changed, 28 insertions(+), 33 deletions(-) diff --git a/src/economy.c b/src/economy.c index 0f1a7874e..e9c6f28fb 100644 --- a/src/economy.c +++ b/src/economy.c @@ -776,7 +776,7 @@ static void give_cmd(unit * u, order * ord) else if (p == P_HERBS) { bool given = false; - if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { + if (fval(u_race(u), RCF_NOGIVE) && u2 != NULL) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "race_nogive", "race", u_race(u))); return; @@ -847,7 +847,7 @@ static void give_cmd(unit * u, order * ord) if (*s == 0) { /* GIVE ALL items that you have */ /* do these checks once, not for each item we have: */ - if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { + if (fval(u_race(u), RCF_NOGIVE) && u2 != NULL) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "race_nogive", "race", u_race(u))); return; @@ -885,7 +885,8 @@ static void give_cmd(unit * u, order * ord) n = u->number; give_men(n, u, u2, ord); } - } else if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { + } + else if (fval(u_race(u), RCF_NOGIVE) && u2 != NULL) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "race_nogive", "race", u_race(u))); } else if (u2 && !(u_race(u2)->ec_flags & GETITEM)) { @@ -935,7 +936,7 @@ static void give_cmd(unit * u, order * ord) } if (u2 != NULL) { - if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { + if (fval(u_race(u), RCF_NOGIVE) && u2 != NULL) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "race_nogive", "race", u_race(u))); return; diff --git a/src/kernel/battle.c b/src/kernel/battle.c index ec04dba76..bd35ffbb5 100644 --- a/src/kernel/battle.c +++ b/src/kernel/battle.c @@ -214,7 +214,7 @@ int armedmen(const unit * u, bool siege_weapons) { item *itm; int n = 0; - if (!(urace(u)->flags & RCF_NOWEAPONS)) { + if (!fval(u_race(u), RCF_NOWEAPONS)) { if (effskill(u, SK_WEAPONLESS) >= 1) { /* kann ohne waffen bewachen: fuer drachen */ n = u->number; @@ -784,7 +784,7 @@ weapon_effskill(troop t, troop enemy, const weapon * w, bool attacking, skill += CavalryBonus(tu, enemy, BONUS_SKILL); if (wtype) skill = - skillmod(urace(tu)->attribs, tu, tu->region, wtype->skill, skill, + skillmod(u_race(tu)->attribs, tu, tu->region, wtype->skill, skill, SMF_RIDING); } diff --git a/src/kernel/jsonconf.c b/src/kernel/jsonconf.c index ef771f8ac..24494baed 100644 --- a/src/kernel/jsonconf.c +++ b/src/kernel/jsonconf.c @@ -332,7 +332,8 @@ static void json_race(cJSON *json, race *rc) { "noteach", "horse", "desert", "illusionary", "absorbpeasants", "noheal", "noweapons", "shapeshift", "", "undead", "dragon", - "coastal", "", "cansail", 0 + "coastal", "", "cansail", "invisible", "shipspeed", + "stonegolem", "irongolem", "nogive", 0 }; if (json->type!=cJSON_Object) { log_error_n("race %s is not a json object: %d", json->string, json->type); diff --git a/src/kernel/jsonconf.test.c b/src/kernel/jsonconf.test.c index ad525ef33..d9237cba2 100644 --- a/src/kernel/jsonconf.test.c +++ b/src/kernel/jsonconf.test.c @@ -39,6 +39,7 @@ static void test_flags(CuTest *tc) { check_flag(tc, "undead", RCF_UNDEAD); check_flag(tc, "dragon", RCF_DRAGON); check_flag(tc, "fly", RCF_FLY); + check_flag(tc, "nogive", RCF_NOGIVE); test_cleanup(); } diff --git a/src/kernel/pool.c b/src/kernel/pool.c index 49219127d..109fea2d3 100644 --- a/src/kernel/pool.c +++ b/src/kernel/pool.c @@ -182,7 +182,7 @@ get_pooled(const unit * u, const resource_type * rtype, unsigned int mode, if (v->items == NULL && rtype->uget == NULL) continue; - if ((urace(v)->ec_flags & GIVEITEM) == 0) + if (fval(u_race(v), RCF_NOGIVE)) continue; if (v->faction == f) { @@ -232,7 +232,7 @@ use_pooled(unit * u, const resource_type * rtype, unsigned int mode, int count) for (v = r->units; use > 0 && v != NULL; v = v->next) if (u != v) { int mask; - if ((urace(v)->ec_flags & GIVEITEM) == 0) + if (fval(u_race(v), RCF_NOGIVE)) continue; if (v->items == NULL && rtype->uget == NULL) continue; diff --git a/src/kernel/race.h b/src/kernel/race.h index 62793bb12..c1eab55c9 100644 --- a/src/kernel/race.h +++ b/src/kernel/race.h @@ -213,6 +213,7 @@ extern "C" { #define RCF_SHIPSPEED (1<<26) /* race gets +1 on shipspeed */ #define RCF_STONEGOLEM (1<<27) /* race gets stonegolem properties */ #define RCF_IRONGOLEM (1<<28) /* race gets irongolem properties */ +#define RCF_NOGIVE (1<<29) /* will not GIVE anything away */ /* Economic flags */ #define GIVEITEM (1<<1) /* gibt Gegenstände weg */ diff --git a/src/kernel/unit.c b/src/kernel/unit.c index ae2d9018c..266ec0cb1 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -196,10 +196,9 @@ static buddy *get_friends(const unit * u, int *numfriends) nf->unit = u2; nf->number = 0; *fr = nf; - } else if (nf->faction == u2->faction - && (u_race(u2)->ec_flags & GIVEITEM)) { + } else if (nf->faction == u2->faction && !fval(u_race(u2), RCF_NOGIVE)) { /* we don't like to gift it to units that won't give it back */ - if ((u_race(nf->unit)->ec_flags & GIVEITEM) == 0) { + if (fval(u_race(nf->unit), RCF_NOGIVE)) { nf->unit = u2; } } @@ -226,7 +225,7 @@ int gift_items(unit * u, int flags) item **itm_p = &u->items; int retval = 0; int rule = rule_give(); - + assert(u->region); assert(u->faction); @@ -239,20 +238,20 @@ int gift_items(unit * u, int flags) flags -= GIFT_SELF; } - if (u->items == NULL || fval(u_race(u), RCF_ILLUSIONARY)) - return 0; - if ((u_race(u)->ec_flags & GIVEITEM) == 0) + if (u->items == NULL || fval(u_race(u), RCF_ILLUSIONARY) || fval(u_race(u), RCF_NOGIVE)) { return 0; + } /* at first, I should try giving my crap to my own units in this region */ if (u->faction && (u->faction->flags & FFL_QUIT) == 0 && (flags & GIFT_SELF)) { unit *u2, *u3 = NULL; for (u2 = r->units; u2; u2 = u2->next) { if (u2 != u && u2->faction == u->faction && u2->number > 0) { + const race * rc = u_race(u2); /* some units won't take stuff: */ - if (u_race(u2)->ec_flags & GETITEM) { + if (rc->ec_flags & GETITEM) { /* we don't like to gift it to units that won't give it back */ - if (u_race(u2)->ec_flags & GIVEITEM) { + if (!fval(rc, RCF_NOGIVE)) { i_merge(&u2->items, &u->items); u->items = NULL; break; @@ -861,11 +860,6 @@ bool leave(unit * u, bool force) return true; } -const struct race *urace(const struct unit *u) -{ - return u->race_; -} - bool can_survive(const unit * u, const region * r) { if ((fval(r->terrain, WALK_INTO) && (u_race(u)->flags & RCF_WALK)) diff --git a/src/kernel/unit.h b/src/kernel/unit.h index 0826fb786..fc11a5d8f 100644 --- a/src/kernel/unit.h +++ b/src/kernel/unit.h @@ -141,8 +141,6 @@ extern "C" { struct unit *utarget(const struct unit *u); void usettarget(struct unit *u, const struct unit *b); - extern const struct race *urace(const struct unit *u); - const char *uprivate(const struct unit *u); void usetprivate(struct unit *u, const char *c); diff --git a/src/kernel/xmlreader.c b/src/kernel/xmlreader.c index 3832c9bb1..dbedc25b4 100644 --- a/src/kernel/xmlreader.c +++ b/src/kernel/xmlreader.c @@ -1721,8 +1721,9 @@ static int parse_races(xmlDocPtr doc) if (xml_bvalue(node, "irongolem", false)) rc->flags |= RCF_IRONGOLEM; - if (xml_bvalue(node, "giveitem", false)) - rc->ec_flags |= GIVEITEM; + if (xml_bvalue(node, "giveitem", false)) { + rc->flags |= RCF_NOGIVE; + } if (xml_bvalue(node, "giveperson", false)) rc->ec_flags |= GIVEPERSON; if (xml_bvalue(node, "giveunit", false)) diff --git a/src/laws.c b/src/laws.c index c02be826f..a2c829217 100755 --- a/src/laws.c +++ b/src/laws.c @@ -138,9 +138,7 @@ static void checkorders(void) static bool help_money(const unit * u) { - if (u_race(u)->ec_flags & GIVEITEM) - return true; - return false; + return !fval(u_race(u), RCF_NOGIVE); } static void help_feed(unit * donor, unit * u, int *need_p) @@ -3263,7 +3261,7 @@ static building *age_building(building * b) bt_blessed = bt_find("blessedstonecircle"); ct_astralblock = ct_find("astralblock"); - /* blesses stone circles create an astral protection in the astral region + /* blessed stone circles create an astral protection in the astral region * above the shield, which prevents chaos suction and other spells. * The shield is created when a magician enters the blessed stone circle, * and lasts for as long as his skill level / 2 is, at no mana cost. @@ -3279,7 +3277,7 @@ static building *age_building(building * b) * find out if there's a magician in there. */ for (u = r->units; u; u = u->next) { if (b == u->building && inside_building(u)) { - if (!(u_race(u)->ec_flags & GIVEITEM) == 0) { + if (!fval(u_race(u), RCF_NOGIVE)) { int n, unicorns = 0; for (n = 0; n != u->number; ++n) { if (chance(0.02)) { @@ -4041,7 +4039,7 @@ int pay_cmd(unit * u, struct order *ord) int reserve_cmd(unit * u, struct order *ord) { - if (u->number > 0 && (urace(u)->ec_flags & GETITEM)) { + if (u->number > 0 && (u_race(u)->ec_flags & GETITEM)) { int use, count; const resource_type *rtype; const char *s; From 88f9d247bddf218999eae75e87dfa1cd835f1866 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 6 Jul 2014 00:29:52 -0700 Subject: [PATCH 11/18] Revert "use race::flags|RCF_NOGIVE instead of race::ec_flags|GIVEITEM" E3 Tests (GIVE) did not pass. This reverts commit 5ec3f5b83aa5b599df8ecec0d8afea1612e173f1. --- scripts/tests/e3a.lua | 3 ++- src/economy.c | 9 ++++----- src/kernel/battle.c | 4 ++-- src/kernel/jsonconf.c | 3 +-- src/kernel/jsonconf.test.c | 1 - src/kernel/pool.c | 4 ++-- src/kernel/race.h | 1 - src/kernel/unit.c | 22 ++++++++++++++-------- src/kernel/unit.h | 2 ++ src/kernel/xmlreader.c | 5 ++--- src/laws.c | 10 ++++++---- 11 files changed, 35 insertions(+), 29 deletions(-) diff --git a/scripts/tests/e3a.lua b/scripts/tests/e3a.lua index d37cae476..08cdf4035 100644 --- a/scripts/tests/e3a.lua +++ b/scripts/tests/e3a.lua @@ -429,7 +429,8 @@ function test_canoe_passes_through_land() end function test_give_50_percent_of_money() - local r = region.create(0, 0, "plain") + local r = region.create(0, 0, "plain") + r.name = "50percent" local u1 = unit.create(faction.create("noreply@eressea.de", "human", "de"), r, 1) local u2 = unit.create(faction.create("noreply@eressea.de", "orc", "de"), r, 1) u1.faction.age = 10 diff --git a/src/economy.c b/src/economy.c index e9c6f28fb..0f1a7874e 100644 --- a/src/economy.c +++ b/src/economy.c @@ -776,7 +776,7 @@ static void give_cmd(unit * u, order * ord) else if (p == P_HERBS) { bool given = false; - if (fval(u_race(u), RCF_NOGIVE) && u2 != NULL) { + if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "race_nogive", "race", u_race(u))); return; @@ -847,7 +847,7 @@ static void give_cmd(unit * u, order * ord) if (*s == 0) { /* GIVE ALL items that you have */ /* do these checks once, not for each item we have: */ - if (fval(u_race(u), RCF_NOGIVE) && u2 != NULL) { + if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "race_nogive", "race", u_race(u))); return; @@ -885,8 +885,7 @@ static void give_cmd(unit * u, order * ord) n = u->number; give_men(n, u, u2, ord); } - } - else if (fval(u_race(u), RCF_NOGIVE) && u2 != NULL) { + } else if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "race_nogive", "race", u_race(u))); } else if (u2 && !(u_race(u2)->ec_flags & GETITEM)) { @@ -936,7 +935,7 @@ static void give_cmd(unit * u, order * ord) } if (u2 != NULL) { - if (fval(u_race(u), RCF_NOGIVE) && u2 != NULL) { + if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "race_nogive", "race", u_race(u))); return; diff --git a/src/kernel/battle.c b/src/kernel/battle.c index bd35ffbb5..ec04dba76 100644 --- a/src/kernel/battle.c +++ b/src/kernel/battle.c @@ -214,7 +214,7 @@ int armedmen(const unit * u, bool siege_weapons) { item *itm; int n = 0; - if (!fval(u_race(u), RCF_NOWEAPONS)) { + if (!(urace(u)->flags & RCF_NOWEAPONS)) { if (effskill(u, SK_WEAPONLESS) >= 1) { /* kann ohne waffen bewachen: fuer drachen */ n = u->number; @@ -784,7 +784,7 @@ weapon_effskill(troop t, troop enemy, const weapon * w, bool attacking, skill += CavalryBonus(tu, enemy, BONUS_SKILL); if (wtype) skill = - skillmod(u_race(tu)->attribs, tu, tu->region, wtype->skill, skill, + skillmod(urace(tu)->attribs, tu, tu->region, wtype->skill, skill, SMF_RIDING); } diff --git a/src/kernel/jsonconf.c b/src/kernel/jsonconf.c index 24494baed..ef771f8ac 100644 --- a/src/kernel/jsonconf.c +++ b/src/kernel/jsonconf.c @@ -332,8 +332,7 @@ static void json_race(cJSON *json, race *rc) { "noteach", "horse", "desert", "illusionary", "absorbpeasants", "noheal", "noweapons", "shapeshift", "", "undead", "dragon", - "coastal", "", "cansail", "invisible", "shipspeed", - "stonegolem", "irongolem", "nogive", 0 + "coastal", "", "cansail", 0 }; if (json->type!=cJSON_Object) { log_error_n("race %s is not a json object: %d", json->string, json->type); diff --git a/src/kernel/jsonconf.test.c b/src/kernel/jsonconf.test.c index d9237cba2..ad525ef33 100644 --- a/src/kernel/jsonconf.test.c +++ b/src/kernel/jsonconf.test.c @@ -39,7 +39,6 @@ static void test_flags(CuTest *tc) { check_flag(tc, "undead", RCF_UNDEAD); check_flag(tc, "dragon", RCF_DRAGON); check_flag(tc, "fly", RCF_FLY); - check_flag(tc, "nogive", RCF_NOGIVE); test_cleanup(); } diff --git a/src/kernel/pool.c b/src/kernel/pool.c index 109fea2d3..49219127d 100644 --- a/src/kernel/pool.c +++ b/src/kernel/pool.c @@ -182,7 +182,7 @@ get_pooled(const unit * u, const resource_type * rtype, unsigned int mode, if (v->items == NULL && rtype->uget == NULL) continue; - if (fval(u_race(v), RCF_NOGIVE)) + if ((urace(v)->ec_flags & GIVEITEM) == 0) continue; if (v->faction == f) { @@ -232,7 +232,7 @@ use_pooled(unit * u, const resource_type * rtype, unsigned int mode, int count) for (v = r->units; use > 0 && v != NULL; v = v->next) if (u != v) { int mask; - if (fval(u_race(v), RCF_NOGIVE)) + if ((urace(v)->ec_flags & GIVEITEM) == 0) continue; if (v->items == NULL && rtype->uget == NULL) continue; diff --git a/src/kernel/race.h b/src/kernel/race.h index c1eab55c9..62793bb12 100644 --- a/src/kernel/race.h +++ b/src/kernel/race.h @@ -213,7 +213,6 @@ extern "C" { #define RCF_SHIPSPEED (1<<26) /* race gets +1 on shipspeed */ #define RCF_STONEGOLEM (1<<27) /* race gets stonegolem properties */ #define RCF_IRONGOLEM (1<<28) /* race gets irongolem properties */ -#define RCF_NOGIVE (1<<29) /* will not GIVE anything away */ /* Economic flags */ #define GIVEITEM (1<<1) /* gibt Gegenstände weg */ diff --git a/src/kernel/unit.c b/src/kernel/unit.c index 266ec0cb1..ae2d9018c 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -196,9 +196,10 @@ static buddy *get_friends(const unit * u, int *numfriends) nf->unit = u2; nf->number = 0; *fr = nf; - } else if (nf->faction == u2->faction && !fval(u_race(u2), RCF_NOGIVE)) { + } else if (nf->faction == u2->faction + && (u_race(u2)->ec_flags & GIVEITEM)) { /* we don't like to gift it to units that won't give it back */ - if (fval(u_race(nf->unit), RCF_NOGIVE)) { + if ((u_race(nf->unit)->ec_flags & GIVEITEM) == 0) { nf->unit = u2; } } @@ -225,7 +226,7 @@ int gift_items(unit * u, int flags) item **itm_p = &u->items; int retval = 0; int rule = rule_give(); - + assert(u->region); assert(u->faction); @@ -238,20 +239,20 @@ int gift_items(unit * u, int flags) flags -= GIFT_SELF; } - if (u->items == NULL || fval(u_race(u), RCF_ILLUSIONARY) || fval(u_race(u), RCF_NOGIVE)) { + if (u->items == NULL || fval(u_race(u), RCF_ILLUSIONARY)) + return 0; + if ((u_race(u)->ec_flags & GIVEITEM) == 0) return 0; - } /* at first, I should try giving my crap to my own units in this region */ if (u->faction && (u->faction->flags & FFL_QUIT) == 0 && (flags & GIFT_SELF)) { unit *u2, *u3 = NULL; for (u2 = r->units; u2; u2 = u2->next) { if (u2 != u && u2->faction == u->faction && u2->number > 0) { - const race * rc = u_race(u2); /* some units won't take stuff: */ - if (rc->ec_flags & GETITEM) { + if (u_race(u2)->ec_flags & GETITEM) { /* we don't like to gift it to units that won't give it back */ - if (!fval(rc, RCF_NOGIVE)) { + if (u_race(u2)->ec_flags & GIVEITEM) { i_merge(&u2->items, &u->items); u->items = NULL; break; @@ -860,6 +861,11 @@ bool leave(unit * u, bool force) return true; } +const struct race *urace(const struct unit *u) +{ + return u->race_; +} + bool can_survive(const unit * u, const region * r) { if ((fval(r->terrain, WALK_INTO) && (u_race(u)->flags & RCF_WALK)) diff --git a/src/kernel/unit.h b/src/kernel/unit.h index fc11a5d8f..0826fb786 100644 --- a/src/kernel/unit.h +++ b/src/kernel/unit.h @@ -141,6 +141,8 @@ extern "C" { struct unit *utarget(const struct unit *u); void usettarget(struct unit *u, const struct unit *b); + extern const struct race *urace(const struct unit *u); + const char *uprivate(const struct unit *u); void usetprivate(struct unit *u, const char *c); diff --git a/src/kernel/xmlreader.c b/src/kernel/xmlreader.c index dbedc25b4..3832c9bb1 100644 --- a/src/kernel/xmlreader.c +++ b/src/kernel/xmlreader.c @@ -1721,9 +1721,8 @@ static int parse_races(xmlDocPtr doc) if (xml_bvalue(node, "irongolem", false)) rc->flags |= RCF_IRONGOLEM; - if (xml_bvalue(node, "giveitem", false)) { - rc->flags |= RCF_NOGIVE; - } + if (xml_bvalue(node, "giveitem", false)) + rc->ec_flags |= GIVEITEM; if (xml_bvalue(node, "giveperson", false)) rc->ec_flags |= GIVEPERSON; if (xml_bvalue(node, "giveunit", false)) diff --git a/src/laws.c b/src/laws.c index a2c829217..c02be826f 100755 --- a/src/laws.c +++ b/src/laws.c @@ -138,7 +138,9 @@ static void checkorders(void) static bool help_money(const unit * u) { - return !fval(u_race(u), RCF_NOGIVE); + if (u_race(u)->ec_flags & GIVEITEM) + return true; + return false; } static void help_feed(unit * donor, unit * u, int *need_p) @@ -3261,7 +3263,7 @@ static building *age_building(building * b) bt_blessed = bt_find("blessedstonecircle"); ct_astralblock = ct_find("astralblock"); - /* blessed stone circles create an astral protection in the astral region + /* blesses stone circles create an astral protection in the astral region * above the shield, which prevents chaos suction and other spells. * The shield is created when a magician enters the blessed stone circle, * and lasts for as long as his skill level / 2 is, at no mana cost. @@ -3277,7 +3279,7 @@ static building *age_building(building * b) * find out if there's a magician in there. */ for (u = r->units; u; u = u->next) { if (b == u->building && inside_building(u)) { - if (!fval(u_race(u), RCF_NOGIVE)) { + if (!(u_race(u)->ec_flags & GIVEITEM) == 0) { int n, unicorns = 0; for (n = 0; n != u->number; ++n) { if (chance(0.02)) { @@ -4039,7 +4041,7 @@ int pay_cmd(unit * u, struct order *ord) int reserve_cmd(unit * u, struct order *ord) { - if (u->number > 0 && (u_race(u)->ec_flags & GETITEM)) { + if (u->number > 0 && (urace(u)->ec_flags & GETITEM)) { int use, count; const resource_type *rtype; const char *s; From fdae518ef710701893d89f33e0742e210f503254 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 6 Jul 2014 00:53:15 -0700 Subject: [PATCH 12/18] also read the extended race::ec_flags from JSON configuration. --- src/kernel/jsonconf.c | 7 ++++++- src/kernel/jsonconf.test.c | 20 ++++++++++++++++---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/kernel/jsonconf.c b/src/kernel/jsonconf.c index ef771f8ac..829e93113 100644 --- a/src/kernel/jsonconf.c +++ b/src/kernel/jsonconf.c @@ -334,7 +334,11 @@ static void json_race(cJSON *json, race *rc) { "noweapons", "shapeshift", "", "undead", "dragon", "coastal", "", "cansail", 0 }; - if (json->type!=cJSON_Object) { + const char *ecflags[] = { + "", "giveitem", "giveperson", + "giveunit", "getitem", 0 + }; + if (json->type != cJSON_Object) { log_error_n("race %s is not a json object: %d", json->string, json->type); return; } @@ -381,6 +385,7 @@ static void json_race(cJSON *json, race *rc) { case cJSON_Array: if (strcmp(child->string, "flags")==0) { rc->flags = json_flags(child, flags); + rc->ec_flags = json_flags(child, ecflags); } break; } diff --git a/src/kernel/jsonconf.test.c b/src/kernel/jsonconf.test.c index ad525ef33..5083f8e73 100644 --- a/src/kernel/jsonconf.test.c +++ b/src/kernel/jsonconf.test.c @@ -16,19 +16,27 @@ #include #include -static void check_flag(CuTest *tc, const char *name, int flag) { +static const struct race * race_with_flag(const char * name) { char data[1024]; - const struct race *rc; cJSON *json; sprintf(data, "{\"races\" : { \"orc\": { \"speed\" : 1, \"flags\" : [ \"%s\"] }}}", name); json = cJSON_Parse(data); free_races(); json_config(json); - rc = rc_find("orc"); + return rc_find("orc"); +} + +static void check_ec_flag(CuTest *tc, const char *name, int flag) { + const struct race *rc = race_with_flag(name); + CuAssertPtrNotNull(tc, rc); + CuAssertIntEquals(tc, flag, rc->ec_flags); +} + +static void check_flag(CuTest *tc, const char *name, int flag) { + const struct race *rc = race_with_flag(name); CuAssertPtrNotNull(tc, rc); CuAssertIntEquals(tc, flag, rc->flags); - CuAssertDblEquals(tc, 1.0f, rc->speed, 0.0f); } static void test_flags(CuTest *tc) { @@ -39,6 +47,10 @@ static void test_flags(CuTest *tc) { check_flag(tc, "undead", RCF_UNDEAD); check_flag(tc, "dragon", RCF_DRAGON); check_flag(tc, "fly", RCF_FLY); + check_ec_flag(tc, "getitem", GETITEM); + check_ec_flag(tc, "giveitem", GIVEITEM); + check_ec_flag(tc, "giveperson", GIVEPERSON); + check_ec_flag(tc, "giveunit", GIVEUNIT); test_cleanup(); } From 9e2e7bfe972e19666c3757094e505141ec34c892 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 6 Jul 2014 01:13:09 -0700 Subject: [PATCH 13/18] test giving silver from the pool --- tests/init.lua | 1 + tests/pool.lua | 26 +++++++++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/tests/init.lua b/tests/init.lua index f286cbcf7..a5c198203 100644 --- a/tests/init.lua +++ b/tests/init.lua @@ -1,4 +1,5 @@ -- new tests 2014-06-11 +require "tests.pool" require "tests.settings" require "tests.config" require "tests.locale" diff --git a/tests/pool.lua b/tests/pool.lua index 01f62420f..20d2ea0bb 100644 --- a/tests/pool.lua +++ b/tests/pool.lua @@ -10,7 +10,7 @@ function setup() eressea.settings.set("nmr.timeout", "0") conf = [[{ "races": { - "human" : {} + "human" : { "flags" : [ "giveitem", "getitem" ] } }, "terrains" : { "plain": { "flags" : [ "land" ] } @@ -19,6 +19,11 @@ function setup() "de" : { "give" : "GIB" } + }, + "strings" : { + "de" : { + "money" : "Silber" + } } }]] @@ -31,8 +36,23 @@ function test_give_nopool() local u1 = unit.create(f, r, 1) local u2 = unit.create(f, r, 1) u1:add_item("money", 100) - u1:add_order("GIB " .. itoa36(u2.id) .. " 100 SILBER") + u1:add_order("GIB " .. itoa36(u2.id) .. " 50 SILBER") + process_orders() + assert_equal(50, u1:get_item("money")) + assert_equal(50, u2:get_item("money")) +end + +function test_give_from_faction() + local r = region.create(1, 1, "plain") + local f = faction.create("test@example.com", "human", "de") + local u1 = unit.create(f, r, 1) + local u2 = unit.create(f, r, 1) + local u3 = unit.create(f, r, 1) + u1:add_item("money", 50) + u2:add_item("money", 50) + u1:add_order("GIB " .. itoa36(u3.id) .. " 100 SILBER") process_orders() assert_equal(0, u1:get_item("money")) - assert_equal(100, u2:get_item("money")) + assert_equal(0, u2:get_item("money")) + assert_equal(100, u3:get_item("money")) end From 4d173cf7e2232304ab815600dd4ef08f98813353 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 6 Jul 2014 12:39:03 -0700 Subject: [PATCH 14/18] if a unit is empty, and not a TEMP, then it is dead and cannot recruit. This fixes http://bugs.eressea.de/view.php?id=2010 --- src/economy.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/economy.c b/src/economy.c index 0f1a7874e..2ac2a1e1c 100644 --- a/src/economy.c +++ b/src/economy.c @@ -372,13 +372,19 @@ static int do_recruiting(recruitment * recruits, int available) use_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, rc->recruitcost * number); } - add_recruits(u, number, req->qty); - dec = (int)(number * multi); - if ((rc->ec_flags & ECF_REC_ETHEREAL) == 0) { - recruited += dec; + if (u->number == 0 && !fval(u, UFL_ISNEW)) { + /* unit is empty, and not a TEMP => it is dead, and cannot recruit */ + number = 0; } + if (number > 0) { + add_recruits(u, number, req->qty); + dec = (int)(number * multi); + if ((rc->ec_flags & ECF_REC_ETHEREAL) == 0) { + recruited += dec; + } - get -= dec; + get -= dec; + } } } return recruited; From 68d96014b1abc0bfc31efc351be05a9dad0f2db1 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 6 Jul 2014 13:00:14 -0700 Subject: [PATCH 15/18] a new method for finding out that a unit died in battle. turns out, a unit can have 0 people without dying or being a TEMP (GIVE them all away, then RECRUIT more). --- src/economy.c | 4 ++-- src/kernel/battle.c | 10 ++++++++-- src/kernel/unit.h | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/economy.c b/src/economy.c index 2ac2a1e1c..fb70e4e13 100644 --- a/src/economy.c +++ b/src/economy.c @@ -372,8 +372,8 @@ static int do_recruiting(recruitment * recruits, int available) use_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, rc->recruitcost * number); } - if (u->number == 0 && !fval(u, UFL_ISNEW)) { - /* unit is empty, and not a TEMP => it is dead, and cannot recruit */ + if (u->number == 0 && fval(u, UFL_DEAD)) { + /* unit is empty, dead, and cannot recruit */ number = 0; } if (number > 0) { diff --git a/src/kernel/battle.c b/src/kernel/battle.c index ec04dba76..9b9319bb6 100644 --- a/src/kernel/battle.c +++ b/src/kernel/battle.c @@ -2661,6 +2661,7 @@ static void aftermath(battle * b) int dead = dead_fighters(df); int sum_hp = 0; int n; + int flags = 0; for (n = 0; n != df->alive; ++n) { if (df->person[n].hp > 0) { @@ -2669,11 +2670,16 @@ static void aftermath(battle * b) } snumber += du->number; if (relevant) { - int flags = UFL_LONGACTION | UFL_NOTMOVING; + flags = UFL_LONGACTION | UFL_NOTMOVING; if (du->status == ST_FLEE) { flags -= UFL_NOTMOVING; } - fset(du, flags); + } + if (df->alive == 0) { + flags |= UFL_DEAD; + } + if (flags) { + fset(du, flags); } if (sum_hp + df->run.hp < du->hp) { /* someone on the ship got damaged, damage the ship */ diff --git a/src/kernel/unit.h b/src/kernel/unit.h index 0826fb786..4c232da5e 100644 --- a/src/kernel/unit.h +++ b/src/kernel/unit.h @@ -30,7 +30,7 @@ extern "C" { struct item; struct sc_mage; -#define UFL_DEBUG (1<<0) +#define UFL_DEAD (1<<0) #define UFL_ISNEW (1<<1) /* 2 */ #define UFL_LONGACTION (1<<2) /* 4 */ #define UFL_OWNER (1<<3) /* 8 */ From 896681e189707605832700c9c9661713493b550e Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 6 Jul 2014 22:03:00 +0200 Subject: [PATCH 16/18] print log errors after runnign tests --- s/runtests | 1 + 1 file changed, 1 insertion(+) diff --git a/s/runtests b/s/runtests index 35934997b..bacceca0e 100755 --- a/s/runtests +++ b/s/runtests @@ -18,4 +18,5 @@ fi $ROOT/$BIN_DIR/eressea/test_eressea cd $ROOT $ROOT/$BIN_DIR/eressea/eressea -v0 scripts/runtests.lua +grep ERROR eressea.log cd $OLDWPD From b2b35fd9d0beae11c1f1e2a3537461582d3cf2ca Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 7 Jul 2014 03:40:58 +0200 Subject: [PATCH 17/18] add a test for the E3 reduced give quota. foreign units receive only 50% of silver given to them. Conflicts: tests/pool.lua --- scripts/tests/e3a.lua | 1 - src/give.c | 16 +++++++--------- src/kernel/unit.c | 4 ++-- tests/pool.lua | 18 +++++++++++++++++- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/scripts/tests/e3a.lua b/scripts/tests/e3a.lua index 08cdf4035..4ddeddc1c 100644 --- a/scripts/tests/e3a.lua +++ b/scripts/tests/e3a.lua @@ -430,7 +430,6 @@ end function test_give_50_percent_of_money() local r = region.create(0, 0, "plain") - r.name = "50percent" local u1 = unit.create(faction.create("noreply@eressea.de", "human", "de"), r, 1) local u2 = unit.create(faction.create("noreply@eressea.de", "orc", "de"), r, 1) u1.faction.age = 10 diff --git a/src/give.c b/src/give.c index bacae343f..3a47957dc 100644 --- a/src/give.c +++ b/src/give.c @@ -95,21 +95,19 @@ static bool limited_give(const item_type * type) int give_quota(const unit * src, const unit * dst, const item_type * type, int n) { - static float divisor = -1; + float divisor; - if (divisor == 0 || !limited_give(type)) { + if (!limited_give(type)) { return n; } if (dst && src && src->faction != dst->faction) { - if (divisor < 0) { divisor = get_param_flt(global.parameters, "rules.items.give_divisor", 1); assert(divisor == 0 || divisor >= 1); - } - if (divisor >= 1) { - /* predictable > correct: */ - int x = (int)(n / divisor); - return x; - } + if (divisor >= 1) { + /* predictable > correct: */ + int x = (int)(n / divisor); + return x; + } } return n; } diff --git a/src/kernel/unit.c b/src/kernel/unit.c index ae2d9018c..55e5e4a91 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -1214,8 +1214,8 @@ bool has_skill(const unit * u, skill_t sk) static int item_invis(const unit *u) { const struct resource_type *rring = get_resourcetype(R_RING_OF_INVISIBILITY); const struct resource_type *rsphere = get_resourcetype(R_SPHERE_OF_INVISIBILITY); - return i_get(u->items, rring->itype) - + i_get(u->items, rsphere->itype) * 100; + return (rring ? i_get(u->items, rring->itype) : 0) + + (rsphere ? i_get(u->items, rsphere->itype) * 100 : 0); } static int item_modification(const unit * u, skill_t sk, int val) diff --git a/tests/pool.lua b/tests/pool.lua index 20d2ea0bb..eb687363a 100644 --- a/tests/pool.lua +++ b/tests/pool.lua @@ -17,7 +17,8 @@ function setup() }, "keywords" : { "de" : { - "give" : "GIB" + "give" : "GIB", + "contact" : "KONTAKTIERE" } }, "strings" : { @@ -56,3 +57,18 @@ function test_give_from_faction() assert_equal(0, u2:get_item("money")) assert_equal(100, u3:get_item("money")) end + +function test_give_divisor() + eressea.settings.set("rules.items.give_divisor", 2) + local r = region.create(1, 1, "plain") + local f1 = faction.create("test@example.com", "human", "de") + local f2 = faction.create("test@example.com", "human", "de") + local u1 = unit.create(f1, r, 1) + local u2 = unit.create(f2, r, 1) + u2:add_order("KONTAKTIERE " .. itoa36(u1.id)) + u1:add_item("money", 100) + u1:add_order("GIB " .. itoa36(u2.id) .. " 100 SILBER") + process_orders() + assert_equal(0, u1:get_item("money")) + assert_equal(50, u2:get_item("money")) +end From acb0cd740411cb1921e67805d67f19e115c91351 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 7 Jul 2014 03:42:43 +0200 Subject: [PATCH 18/18] installed build 677 in production, increase build number to 678 --- src/build.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/build.h b/src/build.h index 768ebf8c4..252ef3b18 100644 --- a/src/build.h +++ b/src/build.h @@ -1,3 +1,3 @@ #define VERSION_MAJOR 3 #define VERSION_MINOR 0 -#define VERSION_BUILD 677 +#define VERSION_BUILD 678