From ea618453f70f85aed68868b7335298023f4064c4 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 24 Jul 2012 00:16:25 -0700 Subject: [PATCH 01/15] bind more processing functions to Lua (almost done) --- scripts/tests/bindings.lua | 8 +++++++ scripts/tests/orders.lua | 28 +++++++++++++++++++++++ src/bindings/bind_process.c | 45 +++++++++++++++++++++++++++++++++++++ src/bindings/bind_process.h | 8 +++++++ src/bindings/process.pkg | 8 +++++++ src/gamecode/laws.c | 42 ++++++++++++++++++++++++++++++---- src/gamecode/laws.h | 8 ++++++- src/kernel/pool.c | 43 +++++------------------------------ src/kernel/pool.h | 6 +---- src/kernel/unit.h | 12 +++++----- 10 files changed, 156 insertions(+), 52 deletions(-) diff --git a/scripts/tests/bindings.lua b/scripts/tests/bindings.lua index b37606530..189d34769 100755 --- a/scripts/tests/bindings.lua +++ b/scripts/tests/bindings.lua @@ -45,6 +45,14 @@ function test_process() assert_equal("function", _G.type(eressea.process.regeneration)) assert_equal("function", _G.type(eressea.process.guard_on)) assert_equal("function", _G.type(eressea.process.guard_off)) + assert_equal("function", _G.type(eressea.process.explain)) + assert_equal("function", _G.type(eressea.process.messages)) + assert_equal("function", _G.type(eressea.process.reserve)) + assert_equal("function", _G.type(eressea.process.claim)) + assert_equal("function", _G.type(eressea.process.follow)) + assert_equal("function", _G.type(eressea.process.alliance)) + assert_equal("function", _G.type(eressea.process.idle)) + assert_equal("function", _G.type(eressea.process.set_default)) end function test_settings() diff --git a/scripts/tests/orders.lua b/scripts/tests/orders.lua index b46e0c1c7..e3d30cdfa 100755 --- a/scripts/tests/orders.lua +++ b/scripts/tests/orders.lua @@ -236,3 +236,31 @@ end function test_process_guard_off() eressea.process.guard_off() end + +function test_process_explain() + eressea.process.explain() +end + +function test_process_messages() + eressea.process.messages() +end + +function test_process_reserve() + eressea.process.reserve() +end + +function test_process_claim() + eressea.process.claim() +end + +function test_process_follow() + eressea.process.follow() +end + +function test_process_idle() + eressea.process.idle() +end + +function test_process_set_default() + eressea.process.set_default() +end diff --git a/src/bindings/bind_process.c b/src/bindings/bind_process.c index 926655e66..83420578b 100755 --- a/src/bindings/bind_process.c +++ b/src/bindings/bind_process.c @@ -2,6 +2,8 @@ #include #include +#include +#include #include #include #include @@ -215,6 +217,32 @@ void process_guard_on(void) { process_cmd(K_GUARD, guard_on_cmd, PROC_LAND_REGION); } +void process_explain(void) { + process_cmd(K_RESHOW, reshow_cmd, 0); +} + +void process_reserve(void) { + process_cmd(K_RESERVE, reserve_cmd, 0); +} + +void process_claim(void) { + process_cmd(K_CLAIM, claim_cmd, 0); +} + +void process_follow(void) { + struct region *r; + for (r = regions; r; r = r->next) { + unit * u; + for (u=r->units; u; u=u->next) { + follow_unit(u); + } + } +} + +void process_messages(void) { + process_cmd(K_MAIL, mail_cmd, 0); +} + void process_guard_off(void) { process_cmd(K_GUARD, guard_off_cmd, PROC_LAND_REGION); } @@ -247,3 +275,20 @@ void process_maintenance(void) { maintain_buildings(r, 0); } } + +void process_alliance(void) { + alliance_cmd(); +} + +void process_idle(void) { + region * r; + for (r=regions; r; r=r->next) { + auto_work(r); + } +} + +void process_set_default(void) { + if (!global.disabled[K_DEFAULT]) { + defaultorders(); + } +} diff --git a/src/bindings/bind_process.h b/src/bindings/bind_process.h index 4a9ebc147..767c7eb77 100755 --- a/src/bindings/bind_process.h +++ b/src/bindings/bind_process.h @@ -37,6 +37,14 @@ void process_give_control(void); void process_regeneration(void); void process_guard_on(void); void process_guard_off(void); +void process_explain(void); +void process_messages(void); +void process_reserve(void); +void process_claim(void); +void process_follow(void); +void process_alliance(void); +void process_idle(void); +void process_set_default(void); #ifdef __cplusplus } diff --git a/src/bindings/process.pkg b/src/bindings/process.pkg index bf6f4a83c..fb68e3a42 100755 --- a/src/bindings/process.pkg +++ b/src/bindings/process.pkg @@ -34,5 +34,13 @@ module eressea { void process_regeneration @ regeneration(void); /* regen health & aura */ void process_guard_on @ guard_on(void); /* GUARD */ void process_guard_off @ guard_off(void); /* GUARD NOT */ + void process_explain @ explain(void); /* SHOW */ + void process_messages @ messages(void); /* MESSAGE */ + void process_reserve @ reserve(void); /* RESERVE */ + void process_claim @ claim(void); /* CLAIM */ + void process_follow @ follow(void); /* FOLLOW */ + void process_alliance @ alliance(void); /* FOLLOW */ + void process_idle @ idle(void); /* work.auto */ + void process_set_default @ set_default(void); /* work.auto */ } } diff --git a/src/gamecode/laws.c b/src/gamecode/laws.c index 82ebc4034..0229b9e45 100755 --- a/src/gamecode/laws.c +++ b/src/gamecode/laws.c @@ -2166,7 +2166,7 @@ static void mailfaction(unit * u, int n, struct order *ord, const char *s) cmistake(u, ord, 66, MSG_MESSAGE); } -static int mail_cmd(unit * u, struct order *ord) +int mail_cmd(unit * u, struct order *ord) { region *r = u->region; unit *u2; @@ -2781,7 +2781,7 @@ int guard_off_cmd(unit * u, struct order *ord) return 0; } -static int reshow_cmd(unit * u, struct order *ord) +int reshow_cmd(unit * u, struct order *ord) { const char *s; param_t p = NOPARAM; @@ -3867,9 +3867,11 @@ static void remove_exclusive(order ** ordp) } } -static void defaultorders(void) +void defaultorders(void) { region *r; + + assert(!global.disabled[K_DEFAULT]); for (r = regions; r; r = r->next) { unit *u; for (u = r->units; u; u = u->next) { @@ -4054,7 +4056,39 @@ int pay_cmd(unit * u, struct order *ord) return 0; } -static int claim_cmd(unit * u, struct order *ord) + +int reserve_cmd(unit * u, struct order *ord) +{ + if (u->number > 0 && (urace(u)->ec_flags & GETITEM)) { + int use, count; + const resource_type *rtype; + const char *s; + + init_tokens(ord); + skip_token(); + s = getstrtoken(); + count = atoip((const char *)s); + + if (count == 0 && findparam(s, u->faction->locale) == P_EACH) { + count = getint() * u->number; + } + + rtype = findresourcetype(getstrtoken(), u->faction->locale); + if (rtype == NULL) + return 0; + + set_resvalue(u, rtype, 0); /* make sure the pool is empty */ + use = use_pooled(u, rtype, GET_DEFAULT, count); + if (use) { + set_resvalue(u, rtype, use); + change_resource(u, rtype, use); + return use; + } + } + return 0; +} + +int claim_cmd(unit * u, struct order *ord) { const char *t; int n; diff --git a/src/gamecode/laws.h b/src/gamecode/laws.h index 0d4cbd614..e0faf47f8 100755 --- a/src/gamecode/laws.h +++ b/src/gamecode/laws.h @@ -50,6 +50,7 @@ extern "C" { extern int enter_ship(struct unit *u, struct order *ord, int id, int report); extern void new_units(void); + extern void defaultorders(void); extern void quit(void); extern void monthly_healing(void); extern void renumber_factions(void); @@ -81,7 +82,12 @@ extern "C" { extern int contact_cmd(struct unit *u, struct order *ord); extern int guard_on_cmd(struct unit *u, struct order *ord); extern int guard_off_cmd(struct unit *u, struct order *ord); - + extern int reshow_cmd(struct unit *u, struct order *ord); + extern int mail_cmd(struct unit *u, struct order *ord); + extern int reserve_cmd(struct unit *u, struct order *ord); + extern int claim_cmd(struct unit *u, struct order *ord); + extern int follow_cmd(struct unit *u, struct order *ord); + #ifdef __cplusplus } #endif diff --git a/src/kernel/pool.c b/src/kernel/pool.c index b150f9f9f..f738bc0d6 100644 --- a/src/kernel/pool.c +++ b/src/kernel/pool.c @@ -96,7 +96,7 @@ int change_resource(unit * u, const resource_type * rtype, int change) int get_reservation(const unit * u, const resource_type * rtype) { - struct reservation *res = u->reservations; + reservation *res = u->reservations; if (rtype == oldresourcetype[R_STONE] && (u->race->flags & RCF_STONEGOLEM)) return (u->number * GOLEM_STONE); @@ -111,7 +111,7 @@ int get_reservation(const unit * u, const resource_type * rtype) int change_reservation(unit * u, const resource_type * rtype, int value) { - struct reservation *res, **rp = &u->reservations; + reservation *res, **rp = &u->reservations; if (!value) return 0; @@ -120,7 +120,7 @@ int change_reservation(unit * u, const resource_type * rtype, int value) rp = &(*rp)->next; res = *rp; if (!res) { - *rp = res = calloc(sizeof(struct reservation), 1); + *rp = res = calloc(sizeof(reservation), 1); res->type = rtype; res->value = value; } else if (res && res->value + value <= 0) { @@ -133,9 +133,9 @@ int change_reservation(unit * u, const resource_type * rtype, int value) return res->value; } -static int new_set_resvalue(unit * u, const resource_type * rtype, int value) +int set_resvalue(unit * u, const resource_type * rtype, int value) { - struct reservation *res, **rp = &u->reservations; + reservation *res, **rp = &u->reservations; while (*rp && (*rp)->type != rtype) rp = &(*rp)->next; @@ -143,7 +143,7 @@ static int new_set_resvalue(unit * u, const resource_type * rtype, int value) if (!res) { if (!value) return 0; - *rp = res = calloc(sizeof(struct reservation), 1); + *rp = res = calloc(sizeof(reservation), 1); res->type = rtype; res->value = value; } else if (res && value <= 0) { @@ -253,34 +253,3 @@ use_pooled(unit * u, const resource_type * rtype, unsigned int mode, int count) } return count - use; } - -int reserve_cmd(unit * u, struct order *ord) -{ - if (u->number > 0 && (urace(u)->ec_flags & GETITEM)) { - int use, count; - const resource_type *rtype; - const char *s; - - init_tokens(ord); - skip_token(); - s = getstrtoken(); - count = atoip((const char *)s); - - if (count == 0 && findparam(s, u->faction->locale) == P_EACH) { - count = getint() * u->number; - } - - rtype = findresourcetype(getstrtoken(), u->faction->locale); - if (rtype == NULL) - return 0; - - new_set_resvalue(u, rtype, 0); /* make sure the pool is empty */ - use = use_pooled(u, rtype, GET_DEFAULT, count); - if (use) { - new_set_resvalue(u, rtype, use); - change_resource(u, rtype, use); - return use; - } - } - return 0; -} diff --git a/src/kernel/pool.h b/src/kernel/pool.h index b6a5e6833..6de15bf3c 100644 --- a/src/kernel/pool.h +++ b/src/kernel/pool.h @@ -54,11 +54,7 @@ extern "C" { int change_reservation(struct unit *u, const struct resource_type *res, int value); - int reserve_cmd(struct unit *u, struct order *ord); - -/** init_pool - * initialisiert den regionalen Pool. - */ + int set_resvalue(struct unit * u, const struct resource_type * rtype, int value); #ifdef __cplusplus } diff --git a/src/kernel/unit.h b/src/kernel/unit.h index 7c9e3d8d3..f94a1d4ee 100644 --- a/src/kernel/unit.h +++ b/src/kernel/unit.h @@ -71,6 +71,12 @@ extern "C" { extern int maxheroes(const struct faction *f); extern int countheroes(const struct faction *f); + typedef struct reservation { + struct reservation *next; + const struct resource_type *type; + int value; + } reservation; + typedef struct unit { struct unit *next; /* needs to be first entry, for region's unitlist */ struct unit *nextF; /* nächste Einheit der Partei */ @@ -90,11 +96,7 @@ extern "C" { short skill_size; struct skill *skills; struct item *items; - struct reservation { - struct reservation *next; - const struct resource_type *type; - int value; - } *reservations; + reservation *reservations; /* orders */ struct order *orders; From b02f275582e460ef026441ac1b90af32b69cfd64 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Wed, 25 Jul 2012 22:35:30 +0200 Subject: [PATCH 02/15] fixed bug #1879: CAST should not prevent FOLLOW UNIT --- scripts/tests/common.lua | 18 ++++++++++++++++++ src/gamecode/laws.c | 2 +- src/kernel/magic.c | 16 +++++++++------- src/kernel/move.c | 3 ++- 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/scripts/tests/common.lua b/scripts/tests/common.lua index 3a7193ed0..df7fd97ca 100755 --- a/scripts/tests/common.lua +++ b/scripts/tests/common.lua @@ -1171,3 +1171,21 @@ function test_bug_1875_use_own_first() assert_equal(99, u:get_potion("peasantblood")) -- unit uses one peasantblood effect assert_equal(99, u2:get_potion("peasantblood")) -- u2 uses its own effect before u's end + + +function test_bug_1879_follow_unit() + local r = region.create(0, 0, "plain") + local r1 = region.create(1, 0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u1, u2 = two_units(r, f, f) + u1:clear_orders() + u1:set_skill("magic", 10) + u1:add_order("ZAUBERE STUFE 1 Kleine Flüche") + u1:add_order("FOLGEN EINHEIT " .. itoa36(u2.id)) + u2:clear_orders() + u2:add_order("NACH o") + process_orders() + assert_equal(u1.region.id, r1.id) + assert_equal(u2.region.id, r1.id) +end + diff --git a/src/gamecode/laws.c b/src/gamecode/laws.c index b79a59233..ac77a3c97 100755 --- a/src/gamecode/laws.c +++ b/src/gamecode/laws.c @@ -3711,7 +3711,7 @@ void update_long_order(unit * u) case K_CAST: /* dient dazu, das neben Zaubern kein weiterer Befehl * ausgeführt werden kann, Zaubern ist ein kurzer Befehl */ - set_order(&u->thisorder, NULL); + set_order(&u->thisorder, copy_order(ord)); break; default: diff --git a/src/kernel/magic.c b/src/kernel/magic.c index 3f388450b..f062549bf 100644 --- a/src/kernel/magic.c +++ b/src/kernel/magic.c @@ -2743,13 +2743,15 @@ void magic(void) continue; } - for (ord = u->orders; ord; ord = ord->next) { - if (get_keyword(ord) == K_CAST) { - castorder *co = cast_cmd(u, ord); - fset(u, UFL_LONGACTION | UFL_NOTMOVING); - if (co) { - const spell *sp = co->sp; - add_castorder(&spellranks[sp->rank], co); + if (u->thisorder != NULL) { + for (ord = u->orders; ord; ord = ord->next) { + if (get_keyword(ord) == K_CAST) { + castorder *co = cast_cmd(u, ord); + fset(u, UFL_LONGACTION | UFL_NOTMOVING); + if (co) { + const spell *sp = co->sp; + add_castorder(&spellranks[sp->rank], co); + } } } } diff --git a/src/kernel/move.c b/src/kernel/move.c index 46a1cadfd..9821e92b5 100644 --- a/src/kernel/move.c +++ b/src/kernel/move.c @@ -2697,12 +2697,13 @@ void follow_unit(unit * u) attrib *a2 = a_find(u2->attribs, &at_follow); if (a2 != NULL) { unit *u3 = a2->data.v; - follow = (u3 && u2->region == u2->region); + follow = (u3 && u2->region == u3->region); } } if (follow) { fset(u, UFL_FOLLOWING); fset(u2, UFL_FOLLOWED); + /* FOLLOW unit on a (potentially) moving unit prevents long orders */ set_order(&u->thisorder, NULL); } } From f286c5186224ae8e08448812be971b9eb1a85ea0 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Wed, 25 Jul 2012 22:45:15 +0200 Subject: [PATCH 03/15] test effect of mine (hunting bug #1926) test that laen is processed correctly --- scripts/tests/common.lua | 68 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/scripts/tests/common.lua b/scripts/tests/common.lua index df7fd97ca..a069c7f0a 100755 --- a/scripts/tests/common.lua +++ b/scripts/tests/common.lua @@ -568,6 +568,73 @@ function test_config() assert_not_equal(nil, config.locales) end +local function _test_create_laen() + local r = region.create(0,0, "mountain") + local f1 = faction.create("noreply@eressea.de", "human", "de") + local u1 = unit.create(f1, r, 1) + + -- TODO this is a stupid way to create a laen region + for i = 1, 10000 do + r = region.create(i,0, "mountain") + if r:get_resource("laen") > 2 then + break + end + end + assert(r:get_resource("laen")>2, "could not run test properly, please try again") + + return r, u1 +end + +function test_laen1() + local r, u1 = _test_create_laen() + + u1:add_item("money", 1000) + u1:set_skill("mining", 14) + u1:clear_orders() + u1:add_order("MACHEN Laen") + + process_orders() + assert_equal(0, u1:get_item("laen")) +end + +function test_laen2() + local r, u1 = _test_create_laen() + + u1:add_item("money", 1000) + u1:set_skill("mining", 15) + u1:clear_orders() + u1:add_order("MACHEN Laen") + + local b = building.create(r, "mine") + b.size = 10 + u1.building = b + local laen = r:get_resource("laen") + + process_orders() + assert_equal(2, u1:get_item("laen")) + assert_equal(laen - 2, r:get_resource("laen")) +end + +function test_mine() + local r = region.create(0,0, "mountain") + local f1 = faction.create("noreply@eressea.de", "human", "de") + local u1 = unit.create(f1, r, 1) + + u1:add_item("money", 1000) + u1:set_skill("mining", 1) + u1:clear_orders() + u1:add_order("MACHEN Eisen") + + local b = building.create(r, "mine") + b.size = 10 + u1.building = b + local iron = r:get_resource("iron") + + process_orders() + assert_equal(2, u1:get_item("iron")) -- skill +1 + assert_equal(iron - 1, r:get_resource("iron")) -- only 1/2 is taken away +end + function test_guard_resources() -- this is not quite http://bugs.eressea.de/view.php?id=1756 local r = region.create(0,0, "mountain") @@ -590,6 +657,7 @@ function test_guard_resources() process_orders() local iron = u2:get_item("iron") + assert_true(iron > 0) process_orders() assert_equal(iron, u2:get_item("iron")) end From 69a51c4b2cb6b875b67d322e4dac4069a6e834c7 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Wed, 25 Jul 2012 23:07:30 +0200 Subject: [PATCH 04/15] add message if implicit leave of building owner fails (see bug #1870) --- scripts/tests/common.lua | 42 ++++++++++++++++++++++++++++++++++++++++ src/gamecode/laws.c | 6 +++++- src/kernel/unit.c | 6 +++++- 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/scripts/tests/common.lua b/scripts/tests/common.lua index a069c7f0a..8e6d66c9f 100755 --- a/scripts/tests/common.lua +++ b/scripts/tests/common.lua @@ -955,6 +955,7 @@ function setup() eressea.write_game("free.dat") eressea.settings.set("rules.economy.food", "4") -- FOOD_IS_FREE eressea.settings.set("rules.encounters", "0") + eressea.settings.set("rules.move.owner_leave", "0") end function test_parser() @@ -1257,3 +1258,44 @@ function test_bug_1879_follow_unit() assert_equal(u2.region.id, r1.id) end +function test_bug_1870_leave_enter_e2() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u1, u2 = two_units(r, f, f) + local mine = building.create(r, "mine") + mine.size = 10 + u1.building = mine + + local b = building.create(r, "castle") + b.size = 10 + u2.building = b + + u1:clear_orders() + u1:add_order("LERNEN Burgenbau ") + u1:add_order("BETRETEN BURG " .. itoa36(b.id)) + + eressea.settings.set("rules.move.owner_leave", "0") + process_orders() + assert_equal(u1.building.id, b.id) +end + +function test_bug_1870_leave_enter_e3() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u1, u2 = two_units(r, f, f) + local mine = building.create(r, "mine") + mine.size = 10 + u1.building = mine + + local b = building.create(r, "castle") + b.size = 10 + u2.building = b + + u1:clear_orders() + u1:add_order("LERNEN Burgenbau ") + u1:add_order("BETRETEN BURG " .. itoa36(b.id)) + + eressea.settings.set("rules.move.owner_leave", "1") + process_orders() + assert_equal(u1.building.id, mine.id) +end diff --git a/src/gamecode/laws.c b/src/gamecode/laws.c index ac77a3c97..cf43535d8 100755 --- a/src/gamecode/laws.c +++ b/src/gamecode/laws.c @@ -1261,9 +1261,11 @@ int enter_ship(unit * u, struct order *ord, int id, int report) } } - if (leave(u, 0)) { + if (leave(u, false)) { u_set_ship(u, sh); fset(u, UFL_ENTER); + } else if (report) { + cmistake(u, ord, 150, MSG_MOVE); } return 1; } @@ -1310,6 +1312,8 @@ int enter_building(unit * u, order * ord, int id, int report) fset(u, UFL_ENTER); u_set_building(u, b); return 1; + } else if (report) { + cmistake(u, ord, 150, MSG_MOVE); } return 0; } diff --git a/src/kernel/unit.c b/src/kernel/unit.c index 5aee29ab7..16901d34b 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -822,14 +822,18 @@ void leave_building(unit * u) bool can_leave(unit * u) { + static int gamecookie = -1; static int rule_leave = -1; if (!u->building) { return true; } - if (rule_leave < 0) { + + if (rule_leave < 0 || gamecookie != global.cookie) { + gamecookie = global.cookie; rule_leave = get_param_int(global.parameters, "rules.move.owner_leave", 0); } + if (rule_leave && u->building && u == building_owner(u->building)) { return false; } From 379e1a8f3f853299b64ae25a0b13c3ddf8151f84 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Thu, 26 Jul 2012 10:35:09 +0200 Subject: [PATCH 05/15] fix bug #1795: demon recruitment limit --- scripts/tests/common.lua | 35 +++++++++++++++++++++++++++++++++++ src/gamecode/economy.c | 24 +++++++++++++++++------- 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/scripts/tests/common.lua b/scripts/tests/common.lua index 8e6d66c9f..e6b3b8f4a 100755 --- a/scripts/tests/common.lua +++ b/scripts/tests/common.lua @@ -1299,3 +1299,38 @@ function test_bug_1870_leave_enter_e3() process_orders() assert_equal(u1.building.id, mine.id) end + +function test_bug_1795_limit() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u1 = one_unit(r,f) + u1:add_item("money", 100000000) + u1:add_order("REKRUTIEREN 9999") + r:set_resource("peasant", 2000) -- no fractional growth! + local peasants = r:get_resource("peasant") + local limit,frac = math.modf(peasants/40) -- one day this should be a parameter + local growth = peasants * 0.001 + + process_orders() + + assert_equal(limit+1, u1.number, u1.number .. "!=" .. (limit+1)) + assert_equal(peasants+growth-limit, r:get_resource("peasant")) +end + +function test_bug_1795_demons() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply@eressea.de", "demon", "de") + local u1 = one_unit(r,f) + r:set_resource("peasant", 2000) + local peasants = r:get_resource("peasant") + local limit,frac = math.modf(peasants/40) + local growth = peasants * 0.001 + + u1:add_item("money", 100000000) + u1:add_order("REKRUTIEREN 9999") + + process_orders() + + assert_equal(limit+1, u1.number, u1.number .. "!=" .. (limit+1)) + assert_equal(peasants+growth, r:get_resource("peasant")) +end diff --git a/src/gamecode/economy.c b/src/gamecode/economy.c index 859cdd079..10de6365d 100644 --- a/src/gamecode/economy.c +++ b/src/gamecode/economy.c @@ -215,6 +215,9 @@ typedef struct recruitment { int total, assigned; } recruitment; +/** Creates a list of recruitment structs, one for each faction. Adds every quantifyable request + * to the faction's struct and to total. + */ static recruitment *select_recruitment(request ** rop, int (*quantify) (const struct race *, int), int *total) { @@ -292,14 +295,14 @@ static int any_recruiters(const struct race *rc, int qty) return (int)(qty * 2 * rc->recruit_multi); } -static int peasant_recruiters(const struct race *rc, int qty) +/*static int peasant_recruiters(const struct race *rc, int qty) { if (rc->ec_flags & ECF_REC_ETHEREAL) return -1; if (rc->ec_flags & ECF_REC_HORSES) return -1; return (int)(qty * 2 * rc->recruit_multi); -} +}*/ static int horse_recruiters(const struct race *rc, int qty) { @@ -315,10 +318,12 @@ static int do_recruiting(recruitment * recruits, int available) recruitment *rec; int recruited = 0; + /* try to assign recruits to factions fairly */ while (available > 0) { int n = 0; int rest, mintotal = INT_MAX; + /* find smallest request */ for (rec = recruits; rec != NULL; rec = rec->next) { int want = rec->total - rec->assigned; if (want > 0) { @@ -334,6 +339,8 @@ static int do_recruiting(recruitment * recruits, int available) } rest = available - mintotal * n; + /* assign size of smallest request for everyone if possible; in the end roll dice to assign + * small rest */ for (rec = recruits; rec != NULL; rec = rec->next) { int want = rec->total - rec->assigned; @@ -350,6 +357,7 @@ static int do_recruiting(recruitment * recruits, int available) } } + /* do actual recruiting */ for (rec = recruits; rec != NULL; rec = rec->next) { request *req; int get = rec->assigned; @@ -365,8 +373,6 @@ static int do_recruiting(recruitment * recruits, int available) int afford = get_pooled(u, oldresourcetype[R_SILVER], GET_DEFAULT, number * rc->recruitcost) / rc->recruitcost; number = MIN(number, afford); - use_pooled(u, oldresourcetype[R_SILVER], GET_DEFAULT, - rc->recruitcost * number); } if (u->number + number > UNIT_MAXSIZE) { ADDMSG(&u->faction->msgs, msg_feedback(u, req->ord, "error_unit_size", @@ -374,6 +380,10 @@ static int do_recruiting(recruitment * recruits, int available) number = UNIT_MAXSIZE - u->number; assert(number >= 0); } + if (rc->recruitcost) { + use_pooled(u, oldresourcetype[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) { @@ -449,7 +459,7 @@ static void expandrecruit(region * r, request * recruitorders) } /* peasant limited: */ - recruits = select_recruitment(&recruitorders, peasant_recruiters, &orc_total); + recruits = select_recruitment(&recruitorders, any_recruiters, &orc_total); if (recruits) { int orc_recruited, orc_peasants = rpeasants(r) * 2; int orc_frac = orc_peasants / RECRUITFRACTION; /* anzahl orks. 2 ork = 1 bauer */ @@ -464,10 +474,10 @@ static void expandrecruit(region * r, request * recruitorders) /* no limit: */ recruits = select_recruitment(&recruitorders, any_recruiters, &orc_total); if (recruits) { - int recruited, peasants = rpeasants(r); + int recruited, peasants = rpeasants(r) * 2; recruited = do_recruiting(recruits, INT_MAX); if (recruited > 0) { - rsetpeasants(r, peasants - recruited / 2); + rsetpeasants(r, (peasants - recruited) / 2); } free_recruitments(recruits); } From dbc09d35ace029569c33413397cb6c180dad9bd7 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 29 Jul 2012 00:35:17 +0200 Subject: [PATCH 06/15] fix a crash caused by an old curse --- src/kernel/curse.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/kernel/curse.c b/src/kernel/curse.c index 4a7403e69..3b0d7c3e2 100644 --- a/src/kernel/curse.c +++ b/src/kernel/curse.c @@ -438,7 +438,10 @@ double curse_geteffect(const curse * c) int curse_geteffect_int(const curse * c) { double effect = curse_geteffect(c); - assert(effect - (int)effect == 0); + if (effect - (int)effect != 0) { + log_error("curse has an integer attribute with float value: '%s' = %lf", + c->type->cname, effect); + } return (int)effect; } From d056f6049e95a1ce459f748e1e22aea7a59edf08 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 2 Aug 2012 08:08:39 +0200 Subject: [PATCH 07/15] fix an intermittently segfaulting test --- src/kernel/region.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kernel/region.c b/src/kernel/region.c index c2d5e6587..491efa290 100644 --- a/src/kernel/region.c +++ b/src/kernel/region.c @@ -1604,7 +1604,7 @@ int owner_change(const region * r) if (r->land && r->land->ownership) { return r->land->ownership->since_turn; } - return -1; + return INT_MIN; } bool is_mourning(const region * r, int in_turn) From 65e5a8250466f1792468006d87aedfd474b19560 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 1 Aug 2012 23:12:23 -0700 Subject: [PATCH 08/15] we can now compare regions, do not need to compare ids --- scripts/tests/common.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/tests/common.lua b/scripts/tests/common.lua index e6b3b8f4a..84d614b1b 100755 --- a/scripts/tests/common.lua +++ b/scripts/tests/common.lua @@ -329,7 +329,7 @@ function test_guard() u2:add_item("money", 100) u3:add_item("money", 100) process_orders() - assert_equal(r.id, u1.region.id, "unit may not move after combat") + assert_equal(r, u1.region, "unit may not move after combat") end function test_recruit() From 166d4ccc2cc187b15bcd40f7449fbfc98162f7af Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 1 Aug 2012 23:20:59 -0700 Subject: [PATCH 09/15] make the fighter in this test not die --- scripts/tests/common.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/tests/common.lua b/scripts/tests/common.lua index 84d614b1b..287736c66 100755 --- a/scripts/tests/common.lua +++ b/scripts/tests/common.lua @@ -309,12 +309,13 @@ function test_guard() local r = region.create(0, 0, "plain") local f1 = faction.create("noreply@eressea.de", "human", "de") f1.age = 20 - local u1 = unit.create(f1, r, 1) + local u1 = unit.create(f1, r, 10) u1:add_item("sword", 10) u1:add_item("money", 10) u1:set_skill("melee", 10) u1:clear_orders() u1:add_order("NACH O") + u1.name="Kalle Pimp" local f2 = faction.create("noreply@eressea.de", "human", "de") f2.age = 20 From 1fe075e82d4f84c4e198389b4e85304e10557570 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 2 Aug 2012 00:06:03 -0700 Subject: [PATCH 10/15] laen test does not work. trying to make setresource add the raw material to fix it --- scripts/tests/common.lua | 21 ++++++--------------- src/kernel/region.c | 10 ++++++++++ 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/scripts/tests/common.lua b/scripts/tests/common.lua index 287736c66..f8f546e05 100755 --- a/scripts/tests/common.lua +++ b/scripts/tests/common.lua @@ -570,20 +570,11 @@ function test_config() end local function _test_create_laen() - local r = region.create(0,0, "mountain") - local f1 = faction.create("noreply@eressea.de", "human", "de") - local u1 = unit.create(f1, r, 1) - - -- TODO this is a stupid way to create a laen region - for i = 1, 10000 do - r = region.create(i,0, "mountain") - if r:get_resource("laen") > 2 then - break - end - end - assert(r:get_resource("laen")>2, "could not run test properly, please try again") - - return r, u1 + local r = region.create(0,0, "mountain") + local f1 = faction.create("noreply@eressea.de", "human", "de") + local u1 = unit.create(f1, r, 1) + r:set_resource("laen", 3) + return r, u1 end function test_laen1() @@ -611,7 +602,7 @@ function test_laen2() u1.building = b local laen = r:get_resource("laen") - process_orders() + process_orders() assert_equal(2, u1:get_item("laen")) assert_equal(laen - 2, r:get_resource("laen")) end diff --git a/src/kernel/region.c b/src/kernel/region.c index 491efa290..e22e5ef62 100644 --- a/src/kernel/region.c +++ b/src/kernel/region.c @@ -1016,6 +1016,16 @@ void region_setresource(region * r, const resource_type * rtype, int value) rsetpeasants(r, value); else if (rtype == rt_find("horse")) rsethorses(r, value); + else { + int i; + for (i = 0; r->terrain->production[i].type; ++i) { + const terrain_production *production = r->terrain->production + i; + if (production->type==rtype) { + add_resource(r, 1, value, dice_rand(production->divisor), rtype); + break; + } + } + } } } From cde0ce07424e19db30c2d61ce6356cf58fa12ba8 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 3 Aug 2012 00:41:17 -0700 Subject: [PATCH 11/15] fix broken laen tests by hacking in another config setting --- scripts/tests/common.lua | 12 ++++++++---- src/kernel/resources.c | 11 ++++++++--- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/scripts/tests/common.lua b/scripts/tests/common.lua index f8f546e05..0521e66e4 100755 --- a/scripts/tests/common.lua +++ b/scripts/tests/common.lua @@ -570,10 +570,11 @@ function test_config() end local function _test_create_laen() + eressea.settings.set("rules.terraform.all", "1") local r = region.create(0,0, "mountain") local f1 = faction.create("noreply@eressea.de", "human", "de") local u1 = unit.create(f1, r, 1) - r:set_resource("laen", 3) + r:set_resource("laen", 50) return r, u1 end @@ -596,15 +597,18 @@ function test_laen2() u1:set_skill("mining", 15) u1:clear_orders() u1:add_order("MACHEN Laen") - + u1.name = "Laenmeister" + local b = building.create(r, "mine") b.size = 10 u1.building = b local laen = r:get_resource("laen") - process_orders() - assert_equal(2, u1:get_item("laen")) + process_orders() + init_reports() + write_report(u1.faction) assert_equal(laen - 2, r:get_resource("laen")) + assert_equal(2, u1:get_item("laen")) end function test_mine() diff --git a/src/kernel/resources.c b/src/kernel/resources.c index 4a3607d7b..5f3c14757 100644 --- a/src/kernel/resources.c +++ b/src/kernel/resources.c @@ -82,6 +82,10 @@ void terraform_resources(region * r) { int i; const terrain_type *terrain = r->terrain; + static int terraform_all = -1; + if (terraform_all<0) { + terraform_all = get_param_int(global.parameters, "rules.terraform.all", 0); + } if (terrain->production == NULL) return; @@ -94,10 +98,11 @@ void terraform_resources(region * r) if (rm->type->rtype == rtype) break; } - if (rm) + if (rm) { continue; - - if (chance(production->chance)) { + } + + if (terraform_all || chance(production->chance)) { add_resource(r, dice_rand(production->startlevel), dice_rand(production->base), dice_rand(production->divisor), production->type); From 5e58f3a881737f625c45e2cf0979ae4db431d752 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 21 Oct 2012 18:37:51 -0700 Subject: [PATCH 12/15] start adding test coverage for res_changeitem --- src/kernel/item.c | 4 ++++ src/kernel/item_test.c | 25 +++++++++++++++++++++++++ src/tests.c | 8 ++++---- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/kernel/item.c b/src/kernel/item.c index fd35f0776..2fd76ded3 100644 --- a/src/kernel/item.c +++ b/src/kernel/item.c @@ -1226,6 +1226,10 @@ void test_clear_resources(void) void register_resources(void) { + static bool registered = false; + if (registered) return; + 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"); diff --git a/src/kernel/item_test.c b/src/kernel/item_test.c index c59e47d33..6279bc0af 100644 --- a/src/kernel/item_test.c +++ b/src/kernel/item_test.c @@ -2,11 +2,35 @@ #include #include +#include #include +#include #include #include +void test_change_item(CuTest * tc) +{ + rtype_uchange res_changeitem; + const resource_type * rtype; + unit * u; + + register_resources(); + res_changeitem = (rtype_uchange)get_function("changeitem"); + CuAssertPtrNotNull(tc, res_changeitem); + + test_cleanup(); + test_create_world(); + rtype = olditemtype[I_IRON]->rtype; + + u = test_create_unit(0, 0); + CuAssertIntEquals(tc, 0, res_changeitem(u, rtype, 0)); + i_change(&u->items, rtype->itype, 4); + CuAssertIntEquals(tc, 4, res_changeitem(u, rtype, 0)); + CuAssertIntEquals(tc, 1, res_changeitem(u, rtype, -3)); + CuAssertIntEquals(tc, 1, i_get(u->items, rtype->itype)); +} + void test_resource_type(CuTest * tc) { struct item_type *itype; @@ -68,6 +92,7 @@ void test_findresourcetype(CuTest * tc) CuSuite *get_item_suite(void) { CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_change_item); SUITE_ADD_TEST(suite, test_resource_type); SUITE_ADD_TEST(suite, test_finditemtype); SUITE_ADD_TEST(suite, test_findresourcetype); diff --git a/src/tests.c b/src/tests.c index dd05c7d93..568e65ac4 100644 --- a/src/tests.c +++ b/src/tests.c @@ -180,15 +180,15 @@ void test_create_world(void) terrain_type *t_plain, *t_ocean; region *island[2]; int i; - item_type * itype; - const char * names[] = { "horse", "horse_p", "boat", "boat_p" }; + const char * names[] = { "horse", "horse_p", "boat", "boat_p", "iron", "iron_p", "stone", "stone_p" }; make_locale("de"); init_resources(); assert(!olditemtype[I_HORSE]); - itype = test_create_itemtype(names); - olditemtype[I_HORSE] = itype; + olditemtype[I_HORSE] = test_create_itemtype(names+0); + olditemtype[I_IRON] = test_create_itemtype(names+4); + olditemtype[I_STONE] = test_create_itemtype(names+6); t_plain = test_create_terrain("plain", LAND_REGION | FOREST_REGION | WALK_INTO | CAVALRY_REGION); t_plain->size = 1000; From 79feb5723c075a45a1a94ed286c87993314ce8da Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 21 Oct 2012 19:42:59 -0700 Subject: [PATCH 13/15] also test changing persons --- src/kernel/item.c | 6 +++++- src/kernel/item_test.c | 42 ++++++++++++++++++++++++++++++------------ 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/kernel/item.c b/src/kernel/item.c index 2fd76ded3..db1da94ad 100644 --- a/src/kernel/item.c +++ b/src/kernel/item.c @@ -73,7 +73,11 @@ static int res_changeaura(unit * u, const resource_type * rtype, int delta) static int res_changeperson(unit * u, const resource_type * rtype, int delta) { assert(rtype != NULL || !"not implemented"); - scale_number(u, u->number + delta); + if (u->number + delta >=0) { + scale_number(u, u->number + delta); + } else { + scale_number(u, 0); + } return u->number; } diff --git a/src/kernel/item_test.c b/src/kernel/item_test.c index 6279bc0af..c9a144ede 100644 --- a/src/kernel/item_test.c +++ b/src/kernel/item_test.c @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -9,26 +10,42 @@ #include #include +static void test_uchange(CuTest * tc, unit * u, const resource_type * rtype) { + int n; + change_resource(u, rtype, 4); + n = get_resource(u, rtype); + CuAssertPtrNotNull(tc, rtype->uchange); + CuAssertIntEquals(tc, n, rtype->uchange(u, rtype, 0)); + CuAssertIntEquals(tc, n-3, rtype->uchange(u, rtype, -3)); + CuAssertIntEquals(tc, n-3, get_resource(u, rtype)); + CuAssertIntEquals(tc, 0, rtype->uchange(u, rtype, -n)); +} + void test_change_item(CuTest * tc) { - rtype_uchange res_changeitem; - const resource_type * rtype; unit * u; - register_resources(); - res_changeitem = (rtype_uchange)get_function("changeitem"); - CuAssertPtrNotNull(tc, res_changeitem); - test_cleanup(); + register_resources(); + init_resources(); test_create_world(); - rtype = olditemtype[I_IRON]->rtype; u = test_create_unit(0, 0); - CuAssertIntEquals(tc, 0, res_changeitem(u, rtype, 0)); - i_change(&u->items, rtype->itype, 4); - CuAssertIntEquals(tc, 4, res_changeitem(u, rtype, 0)); - CuAssertIntEquals(tc, 1, res_changeitem(u, rtype, -3)); - CuAssertIntEquals(tc, 1, i_get(u->items, rtype->itype)); + test_uchange(tc, u, olditemtype[I_IRON]->rtype); +} + +void test_change_person(CuTest * tc) +{ + unit * u; + + test_cleanup(); + + register_resources(); + init_resources(); + test_create_world(); + + u = test_create_unit(0, 0); + test_uchange(tc, u, r_unit); } void test_resource_type(CuTest * tc) @@ -93,6 +110,7 @@ CuSuite *get_item_suite(void) { CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_change_item); + SUITE_ADD_TEST(suite, test_change_person); SUITE_ADD_TEST(suite, test_resource_type); SUITE_ADD_TEST(suite, test_finditemtype); SUITE_ADD_TEST(suite, test_findresourcetype); From 841876e3359e49d059704ee7b5aa7a138447f871 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 23 Feb 2013 17:23:47 -0800 Subject: [PATCH 14/15] bind faction.flags to Lua --- scripts/tests/common.lua | 7 +++++++ src/bindings/bind_faction.c | 10 +++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/scripts/tests/common.lua b/scripts/tests/common.lua index 0521e66e4..88dae3080 100755 --- a/scripts/tests/common.lua +++ b/scripts/tests/common.lua @@ -1330,3 +1330,10 @@ function test_bug_1795_demons() assert_equal(limit+1, u1.number, u1.number .. "!=" .. (limit+1)) assert_equal(peasants+growth, r:get_resource("peasant")) end + +function test_faction_flags() + f = faction.create("noreply@eressea.de", "human", "de") + assert_equal(0, f.flags) + f.flags = 42 + assert_equal(42, f.flags) +end diff --git a/src/bindings/bind_faction.c b/src/bindings/bind_faction.c index d5efd226c..775cb5ab8 100644 --- a/src/bindings/bind_faction.c +++ b/src/bindings/bind_faction.c @@ -160,6 +160,14 @@ static int tolua_faction_get_flags(lua_State * L) return 1; } +static int tolua_faction_set_flags(lua_State * L) +{ + faction *self = (faction *) tolua_tousertype(L, 1, 0); + int flags = (int)tolua_tonumber(L, 2, self->flags); + self->flags = flags; + return 1; +} + static int tolua_faction_get_options(lua_State * L) { faction *self = (faction *) tolua_tousertype(L, 1, 0); @@ -525,7 +533,7 @@ void tolua_faction_open(lua_State * L) tolua_faction_set_age); tolua_variable(L, TOLUA_CAST "options", tolua_faction_get_options, tolua_faction_set_options); - tolua_variable(L, TOLUA_CAST "flags", tolua_faction_get_flags, NULL); + tolua_variable(L, TOLUA_CAST "flags", tolua_faction_get_flags, tolua_faction_set_flags); tolua_variable(L, TOLUA_CAST "lastturn", tolua_faction_get_lastturn, tolua_faction_set_lastturn); From ed4c4aa3633f3587deb14c781405a48c7599d62b Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 28 Apr 2013 03:13:40 +0200 Subject: [PATCH 15/15] Some crashes and other minor stuff. Just things that Eressea has changed in the past 2 months --- res/de/strings.xml | 1 + src/items/weapons.c | 5 +++-- src/kernel/reports.c | 2 +- src/util/translation.c | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/res/de/strings.xml b/res/de/strings.xml index 3b7b88f43..bb16c92fe 100644 --- a/res/de/strings.xml +++ b/res/de/strings.xml @@ -7290,6 +7290,7 @@ Es ist Spätherbst, und diese Woche ist die letzte vor dem Winter, in der Insekten rekrutieren können. + It is the last week before winter in which insects can still recruit. diff --git a/src/items/weapons.c b/src/items/weapons.c index 7b817510a..9eb3d8d72 100644 --- a/src/items/weapons.c +++ b/src/items/weapons.c @@ -72,9 +72,10 @@ attack_firesword(const troop * at, const struct weapon_type *wtype, do { dt = select_enemy(fi, 0, 1, SELECT_ADVANCE | SELECT_DISTANCE); - assert(dt.fighter); --force; - killed += terminate(dt, *at, AT_SPELL, damage, 1); + if (dt.fighter) { + killed += terminate(dt, *at, AT_SPELL, damage, 1); + } } while (force && killed < enemies); if (casualties) *casualties = killed; diff --git a/src/kernel/reports.c b/src/kernel/reports.c index 54cdbb011..78292451e 100644 --- a/src/kernel/reports.c +++ b/src/kernel/reports.c @@ -1788,7 +1788,7 @@ int reports(void) static variant var_copy_string(variant x) { - x.v = strdup((const char *)x.v); + x.v = x.v?strdup((const char *)x.v):0; return x; } diff --git a/src/util/translation.c b/src/util/translation.c index e3493f434..a96f0914f 100644 --- a/src/util/translation.c +++ b/src/util/translation.c @@ -283,7 +283,7 @@ static const char *parse_string(opstack ** stack, const char *in, if (ic == NULL) return NULL; c = (char *)opop_v(stack); - bytes = (int)strlcpy(oc, c, size); + bytes = (int)c?strlcpy(oc, c, size):0; if (bytes < (int)size) oc += bytes; else