From 131840054cb3c3b997e778aea716d2db75a2c8eb Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 27 May 2012 08:38:17 -0700 Subject: [PATCH 1/9] giving ownerships over buildings was broken by a recent refactoring --- src/gamecode.vcxproj | 1 + src/gamecode.vcxproj.filters | 3 ++ src/gamecode/economy.c | 20 ++++++------ src/gamecode/economy.h | 1 + src/gamecode/economy_test.c | 60 ++++++++++++++++++++++++++++++++++++ src/tests.c | 10 +++--- 6 files changed, 82 insertions(+), 13 deletions(-) create mode 100644 src/gamecode/economy_test.c diff --git a/src/gamecode.vcxproj b/src/gamecode.vcxproj index 17572c776..e9cd8c4be 100644 --- a/src/gamecode.vcxproj +++ b/src/gamecode.vcxproj @@ -92,6 +92,7 @@ + diff --git a/src/gamecode.vcxproj.filters b/src/gamecode.vcxproj.filters index 9105225f2..176c488c8 100644 --- a/src/gamecode.vcxproj.filters +++ b/src/gamecode.vcxproj.filters @@ -68,6 +68,9 @@ Source Files + + Source Files + diff --git a/src/gamecode/economy.c b/src/gamecode/economy.c index 2d0af734c..dcf4bdcc7 100644 --- a/src/gamecode/economy.c +++ b/src/gamecode/economy.c @@ -626,17 +626,19 @@ static void friendly_takeover(region * r, faction * f) } } -static void give_control(unit * u, unit * u2) +void give_control(unit * u, unit * u2) { - if (u->building && u->faction != u2->faction && rule_region_owners()) { - region *r = u->region; - faction *f = region_get_owner(r); + if (u->building) { + if (u->faction != u2->faction && rule_region_owners()) { + region *r = u->region; + faction *f = region_get_owner(r); - assert(u->building==u2->building); - if (f == u->faction) { - building *b = largestbuilding(r, &cmp_current_owner, false); - if (b == u->building) { - friendly_takeover(r, u2->faction); + assert(u->building==u2->building); + if (f == u->faction) { + building *b = largestbuilding(r, &cmp_current_owner, false); + if (b == u->building) { + friendly_takeover(r, u2->faction); + } } } building_set_owner(u2); diff --git a/src/gamecode/economy.h b/src/gamecode/economy.h index 9d931e433..b5ccac86d 100644 --- a/src/gamecode/economy.h +++ b/src/gamecode/economy.h @@ -55,6 +55,7 @@ extern "C" { extern void split_allocations(struct region *r); extern int recruit_archetypes(void); extern int give_control_cmd(struct unit *u, struct order *ord); + extern void give_control(struct unit * u, struct unit * u2); #ifdef __cplusplus } diff --git a/src/gamecode/economy_test.c b/src/gamecode/economy_test.c new file mode 100644 index 000000000..0d44c2dc1 --- /dev/null +++ b/src/gamecode/economy_test.c @@ -0,0 +1,60 @@ +#include "platform.h" +#include "economy.h" + +#include +#include +#include +#include + +#include +#include + +static void test_give_control_building(CuTest * tc) +{ + 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)); +} + +static void test_give_control_ship(CuTest * tc) +{ + 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)); +} + +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; +} diff --git a/src/tests.c b/src/tests.c index 4dcdaa1b3..1f6d4df38 100644 --- a/src/tests.c +++ b/src/tests.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -67,6 +68,7 @@ int RunAllTests(void) /* gamecode */ CuSuiteAddSuite(suite, get_market_suite()); CuSuiteAddSuite(suite, get_laws_suite()); + CuSuiteAddSuite(suite, get_economy_suite()); CuSuiteRun(suite); CuSuiteSummary(suite, output); @@ -137,15 +139,15 @@ test_create_terrain(const char * name, unsigned int flags) building * test_create_building(region * r, const building_type * btype) { - building * b = new_building(btype, r, default_locale); - b->size = btype->maxsize>0?btype->maxsize:1; + building * b = new_building(btype?btype:bt_find("castle"), r, default_locale); + b->size = b->type->maxsize>0?b->type->maxsize:1; return b; } ship * test_create_ship(region * r, const ship_type * stype) { - ship * s = new_ship(stype, r, default_locale); - s->size = stype->construction?stype->construction->maxsize:1; + ship * s = new_ship(stype?stype:st_find("boat"), r, default_locale); + s->size = s->type->construction?s->type->construction->maxsize:1; return s; } From 7152ffd40f39e2ff3882a0aa7743e5f0944ef5d8 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 27 May 2012 09:52:44 -0700 Subject: [PATCH 2/9] this spell school was misnamed. that's trouble. --- res/spellbooks/tybied.xml | 2 +- src/kernel/spellbook.c | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/res/spellbooks/tybied.xml b/res/spellbooks/tybied.xml index 2965ec782..f6db0bfd5 100644 --- a/res/spellbooks/tybied.xml +++ b/res/spellbooks/tybied.xml @@ -1,5 +1,5 @@ - + diff --git a/src/kernel/spellbook.c b/src/kernel/spellbook.c index ab73bdd09..7093fca84 100644 --- a/src/kernel/spellbook.c +++ b/src/kernel/spellbook.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "spellbook.h" @@ -21,8 +22,11 @@ void spellbook_add(spellbook *sb, struct spell * sp, int level) spellbook_entry * sbe; assert(sb && sp && level>0); - assert(!spellbook_get(sb, sp)); - +#ifndef NDEBUG + if (spellbook_get(sb, sp)) { + log_error("duplicate spell in spellbook '%s': '%s'\n", sb->name, sp->sname); + } +#endif sbe = (spellbook_entry *)malloc(sizeof(spellbook_entry)); sbe->sp = sp; sbe->level = level; From 131efac393bf8c9cd0713dcdd3b3a98c36c6d7a1 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 28 May 2012 23:31:46 -0700 Subject: [PATCH 3/9] add a test for f_regionid, catch missing zero-termination --- src/kernel/reports.c | 13 +++++++------ src/kernel/reports_test.c | 23 +++++++++++++++++++++++ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/kernel/reports.c b/src/kernel/reports.c index a7244d213..8fb83abd7 100644 --- a/src/kernel/reports.c +++ b/src/kernel/reports.c @@ -1858,8 +1858,9 @@ const char *trailinto(const region * r, const struct locale *lang) size_t f_regionid(const region * r, const faction * f, char *buffer, size_t size) { + size_t len; if (!r) { - strncpy(buffer, "(Chaos)", size); + len = strlcpy(buffer, "(Chaos)", size); } else { plane *pl = rplane(r); const char *name = pl ? pl->name : 0; @@ -1867,12 +1868,12 @@ f_regionid(const region * r, const faction * f, char *buffer, size_t size) int named = (name && name[0]); pnormalize(&nx, &ny, pl); adjust_coordinates(f, &nx, &ny, pl, r); - strncpy(buffer, rname(r, f->locale), size); - buffer[size - 1] = 0; - sprintf(buffer + strlen(buffer), " (%d,%d%s%s)", nx, ny, named ? "," : "", - (named) ? name : ""); + len = strlcpy(buffer, rname(r, f?f->locale:0), size); + snprintf(buffer + len, size-len, " (%d,%d%s%s)", nx, ny, named ? "," : "", (named) ? name : ""); + buffer[size-1] = 0; + len=strlen(buffer); } - return strlen(buffer); + return len; } static char *f_regionid_s(const region * r, const faction * f) diff --git a/src/kernel/reports_test.c b/src/kernel/reports_test.c index 29bc9f5d2..d07217ece 100644 --- a/src/kernel/reports_test.c +++ b/src/kernel/reports_test.c @@ -52,9 +52,32 @@ static void test_reorder_units(CuTest * tc) CuAssertPtrEquals(tc, 0, u0->next); } +static void test_regionid(CuTest * tc) { + size_t len; + const struct terrain_type * plain; + struct region * r; + char buffer[64]; + + test_cleanup(); + plain = test_create_terrain("plain", 0); + r = test_create_region(0, 0, plain); + + memset(buffer, 0xff, sizeof(buffer)); + len = f_regionid(r, 0, buffer, sizeof(buffer)); + CuAssertIntEquals(tc, 11, len); + CuAssertStrEquals(tc, "plain (0,0)", buffer); + + memset(buffer, -1, sizeof(buffer)); + len = f_regionid(r, 0, buffer, 11); + CuAssertIntEquals(tc, 10, len); + CuAssertStrEquals(tc, "plain (0,0", buffer); + CuAssertIntEquals(tc, -1, buffer[11]); +} + CuSuite *get_reports_suite(void) { CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_reorder_units); + SUITE_ADD_TEST(suite, test_regionid); return suite; } From 330bc9c13b5e028679bcf241277f0af3a18b6598 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 29 May 2012 10:45:46 -0700 Subject: [PATCH 4/9] added slprintf and tests for the bsdstring functions --- src/build/util.c | 7 ++-- src/tests.c | 2 ++ src/util.vcxproj | 1 + src/util.vcxproj.filters | 3 ++ src/util/bsdstring.c | 35 ++++++++++++++++---- src/util/bsdstring.h | 21 ++++++------ src/util/bsdstring_test.c | 68 +++++++++++++++++++++++++++++++++++++++ src/util/strncpy.c | 23 ------------- 8 files changed, 116 insertions(+), 44 deletions(-) create mode 100644 src/util/bsdstring_test.c delete mode 100644 src/util/strncpy.c diff --git a/src/build/util.c b/src/build/util.c index daddfbcdd..7de1d97e9 100644 --- a/src/build/util.c +++ b/src/build/util.c @@ -5,6 +5,8 @@ #include #include +#include + #include #include #include @@ -33,10 +35,5 @@ #include #ifndef HAVE_INLINE -#include #include #endif - -#ifdef __GNUC__ -#include -#endif diff --git a/src/tests.c b/src/tests.c index 1f6d4df38..6e4bf6c4e 100644 --- a/src/tests.c +++ b/src/tests.c @@ -6,6 +6,7 @@ #include "tests_test.c" #include +#include #include #include #include @@ -49,6 +50,7 @@ int RunAllTests(void) CuSuiteAddSuite(suite, get_tests_suite()); /* util */ CuSuiteAddSuite(suite, get_base36_suite()); + CuSuiteAddSuite(suite, get_bsdstring_suite()); CuSuiteAddSuite(suite, get_quicklist_suite()); CuSuiteAddSuite(suite, get_functions_suite()); CuSuiteAddSuite(suite, get_umlaut_suite()); diff --git a/src/util.vcxproj b/src/util.vcxproj index d1695aeac..a0967f595 100644 --- a/src/util.vcxproj +++ b/src/util.vcxproj @@ -125,6 +125,7 @@ + diff --git a/src/util.vcxproj.filters b/src/util.vcxproj.filters index e47bd8168..43fb1d700 100644 --- a/src/util.vcxproj.filters +++ b/src/util.vcxproj.filters @@ -208,5 +208,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/src/util/bsdstring.c b/src/util/bsdstring.c index a2467229f..0b677525e 100644 --- a/src/util/bsdstring.c +++ b/src/util/bsdstring.c @@ -2,12 +2,11 @@ #include #include #include +#include -#ifndef HAVE_INLINE #include "bsdstring.h" -#endif -INLINE_FUNCTION int wrptr(char **ptr, size_t * size, int bytes) +int wrptr(char **ptr, size_t * size, int bytes) { assert(bytes >= 0 || !"you're not using snprintf right, maybe?"); @@ -29,8 +28,9 @@ INLINE_FUNCTION int wrptr(char **ptr, size_t * size, int bytes) return ENAMETOOLONG; } -#if !defined(HAVE_STRLCPY) -INLINE_FUNCTION size_t strlcpy(char *dst, const char *src, size_t siz) +#ifndef HAVE_STRLCPY +#define HAVE_STRLCPY +size_t strlcpy(char *dst, const char *src, size_t siz) { /* copied from OpenBSD source code */ register char *d = dst; register const char *s = src; @@ -53,8 +53,11 @@ INLINE_FUNCTION size_t strlcpy(char *dst, const char *src, size_t siz) return (s - src - 1); /* count does not include NUL */ } +#endif -INLINE_FUNCTION size_t strlcat(char *dst, const char *src, size_t siz) +#ifndef HAVE_STRLCAT +#define HAVE_STRLCAT +size_t strlcat(char *dst, const char *src, size_t siz) { register char *d = dst; register const char *s = src; @@ -81,3 +84,23 @@ INLINE_FUNCTION size_t strlcat(char *dst, const char *src, size_t siz) return (dlen + (s - src)); /* count does not include NUL */ } #endif + +#ifndef HAVE_SLPRINTF +#define HAVE_SLPRINTF +size_t slprintf(char * dst, size_t size, const char * format, ...) +{ + va_list args; + int result; + + va_start(args, format); + result = vsnprintf(dst, size, format, args); + if (result<0 || result>=(int)size) { + dst[size-1]='\0'; + return size; + } + va_start(args, format); + va_end(args); + + return (size_t)result; +} +#endif diff --git a/src/util/bsdstring.h b/src/util/bsdstring.h index dc9e2919b..b917baafa 100644 --- a/src/util/bsdstring.h +++ b/src/util/bsdstring.h @@ -1,19 +1,20 @@ #ifndef UTIL_BSDSTRING_H #define UTIL_BSDSTRING_H -#ifdef HAVE_INLINE -# include "bsdstring.c" -#else -extern size_t strlcpy(char *dst, const char *src, size_t siz); -extern size_t strlcat(char *dst, const char *src, size_t siz); extern int wrptr(char **ptr, size_t * size, int bytes); + +#ifndef HAVE_STRLCPY +extern size_t strlcpy(char *dst, const char *src, size_t siz); +#endif + +#ifndef HAVE_STRLCAT +extern size_t strlcat(char *dst, const char *src, size_t siz); +#endif + +#ifndef HAVE_SLPRINTF +extern size_t slprintf(char * dst, size_t size, const char * format, ...); #endif #define WARN_STATIC_BUFFER() log_warning("static buffer too small in %s:%d\n", __FILE__, __LINE__) -#if !defined(HAVE_STRLPRINTF) -# define HAVE_STRLPRINTF -# define slprintf snprintf -#endif - #endif diff --git a/src/util/bsdstring_test.c b/src/util/bsdstring_test.c new file mode 100644 index 000000000..b084e5c31 --- /dev/null +++ b/src/util/bsdstring_test.c @@ -0,0 +1,68 @@ +#include +#include "bsdstring.h" +#include + +static void test_strlcat(CuTest * tc) +{ + char buffer[32]; + + memset(buffer, -2, sizeof(buffer)); + + buffer[0] = '\0'; + CuAssertIntEquals(tc, 4, strlcat(buffer, "herp", 4)); + CuAssertStrEquals(tc, "her", buffer); + + buffer[0] = '\0'; + CuAssertIntEquals(tc, 4, strlcat(buffer, "herp", 8)); + CuAssertStrEquals(tc, "herp", buffer); + CuAssertIntEquals(tc, -2, buffer[5]); + + CuAssertIntEquals(tc, 8, strlcat(buffer, "derp", 8)); + CuAssertStrEquals(tc, "herpder", buffer); + CuAssertIntEquals(tc, -2, buffer[8]); +} + +static void test_strlcpy(CuTest * tc) +{ + char buffer[32]; + + memset(buffer, -2, sizeof(buffer)); + + CuAssertIntEquals(tc, 4, strlcpy(buffer, "herp", 4)); + CuAssertStrEquals(tc, "her", buffer); + + CuAssertIntEquals(tc, 4, strlcpy(buffer, "herp", 8)); + CuAssertStrEquals(tc, "herp", buffer); + CuAssertIntEquals(tc, -2, buffer[5]); + + CuAssertIntEquals(tc, 8, strlcpy(buffer, "herpderp", 8)); + CuAssertStrEquals(tc, "herpder", buffer); + CuAssertIntEquals(tc, -2, buffer[8]); +} + +static void test_slprintf(CuTest * tc) +{ + char buffer[32]; + + memset(buffer, -2, sizeof(buffer)); + + CuAssertTrue(tc, slprintf(buffer, 4, "%s", "herpderp")>3); + CuAssertStrEquals(tc, "her", buffer); + + CuAssertIntEquals(tc, 4, slprintf(buffer, 8, "%s", "herp")); + CuAssertStrEquals(tc, "herp", buffer); + CuAssertIntEquals(tc, -2, buffer[5]); + + CuAssertIntEquals(tc, 8, slprintf(buffer, 8, "%s", "herpderp")); + CuAssertStrEquals(tc, "herpder", buffer); + CuAssertIntEquals(tc, -2, buffer[8]); +} + +CuSuite *get_bsdstring_suite(void) +{ + CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_strlcat); + SUITE_ADD_TEST(suite, test_strlcpy); + SUITE_ADD_TEST(suite, test_slprintf); + return suite; +} diff --git a/src/util/strncpy.c b/src/util/strncpy.c deleted file mode 100644 index 954da8811..000000000 --- a/src/util/strncpy.c +++ /dev/null @@ -1,23 +0,0 @@ - -/* - * Faster replacement for ISO-C strncpy, does not pad with zeros - */ - -#include - -char *strncpy(char *to, const char *from, size_t size) -{ - char *t = to, *f = (char *)from; - int copied = 0; - - while (copied < size) { - *t = *f; - if (*f == '\0') - break; - t++; - f++; - copied++; - } - - return to; -} From 347ff0dd776259cef87b30ada6a499b56392f47e Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 29 May 2012 12:17:25 -0700 Subject: [PATCH 5/9] snprintf is evil and dangerous. --- src/bindings/helpers.c | 40 +++++++++++++++++++++++++++++----------- src/gamecode/economy.c | 5 ++++- src/gamecode/laws.c | 8 ++++---- src/gamecode/randenc.c | 4 ++-- src/kernel/alliance.c | 4 ++-- src/kernel/battle.c | 11 ++--------- src/kernel/building.c | 3 +-- src/kernel/config.c | 3 +-- src/kernel/connection.c | 2 +- src/kernel/faction.c | 5 ++--- src/kernel/move.c | 4 +--- src/kernel/region.c | 6 +++--- src/kernel/save.c | 3 ++- src/kernel/ship.c | 3 +-- src/kernel/unit.c | 5 ++++- 15 files changed, 59 insertions(+), 47 deletions(-) diff --git a/src/bindings/helpers.c b/src/bindings/helpers.c index cb586cf9f..28ee984da 100644 --- a/src/bindings/helpers.c +++ b/src/bindings/helpers.c @@ -15,13 +15,14 @@ without prior permission by the authors of Eressea. #include #include +#include #include #include #include #include #include -#include +#include #include #include #include @@ -77,7 +78,8 @@ static int limit_resource(const region * r, const resource_type * rtype) int result = -1; lua_State *L = (lua_State *) global.vm_state; - snprintf(fname, sizeof(fname), "%s_limit", rtype->_name[0]); + strlcpy(fname, rtype->_name[0], sizeof(fname)); + strlcat(fname, "_limit", sizeof(fname)); lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); @@ -105,7 +107,9 @@ produce_resource(region * r, const resource_type * rtype, int norders) { lua_State *L = (lua_State *) global.vm_state; char fname[64]; - snprintf(fname, sizeof(fname), "%s_produce", rtype->_name[0]); + + strlcpy(fname, rtype->_name[0], sizeof(fname)); + strlcat(fname, "_produce", sizeof(fname)); lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); @@ -245,7 +249,9 @@ static int lua_initfamiliar(unit * u) lua_State *L = (lua_State *) global.vm_state; char fname[64]; int result = -1; - snprintf(fname, sizeof(fname), "initfamiliar_%s", u->race->_name[0]); + + strlcpy(fname, "initfamiliar_", sizeof(fname)); + strlcat(fname, u->race->_name[0], sizeof(fname)); lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); @@ -267,7 +273,8 @@ static int lua_initfamiliar(unit * u) create_mage(u, M_GRAY); - snprintf(fname, sizeof(fname), "%s_familiar", u->race->_name[0]); + strlcpy(fname, u->race->_name[0], sizeof(fname)); + strlcat(fname, "_familiar", sizeof(fname)); equip_unit(u, get_equipment(fname)); return result; } @@ -278,7 +285,9 @@ lua_changeresource(unit * u, const struct resource_type *rtype, int delta) lua_State *L = (lua_State *) global.vm_state; int result = -1; char fname[64]; - snprintf(fname, sizeof(fname), "%s_changeresource", rtype->_name[0]); + + strlcpy(fname, rtype->_name[0], sizeof(fname)); + strlcat(fname, "_changeresource", sizeof(fname)); lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); @@ -307,7 +316,9 @@ static int lua_getresource(unit * u, const struct resource_type *rtype) lua_State *L = (lua_State *) global.vm_state; int result = -1; char fname[64]; - snprintf(fname, sizeof(fname), "%s_getresource", rtype->_name[0]); + + strlcpy(fname, rtype->_name[0], sizeof(fname)); + strlcat(fname, "_getresource", sizeof(fname)); lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); @@ -398,7 +409,8 @@ static void lua_agebuilding(building * b) lua_State *L = (lua_State *) global.vm_state; char fname[64]; - snprintf(fname, sizeof(fname), "age_%s", b->type->_name); + strlcpy(fname, "age_", sizeof(fname)); + strlcat(fname, b->type->_name, sizeof(fname)); lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); @@ -502,7 +514,9 @@ static int lua_equipmentcallback(const struct equipment *eq, unit * u) lua_State *L = (lua_State *) global.vm_state; char fname[64]; int result = -1; - snprintf(fname, sizeof(fname), "equip_%s", eq->name); + + strlcpy(fname, "equip_", sizeof(fname)); + strlcat(fname, eq->name, sizeof(fname)); lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); @@ -532,7 +546,9 @@ lua_useitem(struct unit *u, const struct item_type *itype, int amount, lua_State *L = (lua_State *) global.vm_state; int result = 0; char fname[64]; - snprintf(fname, sizeof(fname), "use_%s", itype->rtype->_name[0]); + + strlcpy(fname, "use_", sizeof(fname)); + strlcat(fname, itype->rtype->_name[0], sizeof(fname)); lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); @@ -561,7 +577,9 @@ static int lua_recruit(struct unit *u, const struct archetype *arch, int amount) lua_State *L = (lua_State *) global.vm_state; int result = 0; char fname[64]; - snprintf(fname, sizeof(fname), "recruit_%s", arch->name[0]); + + strlcpy(fname, "recruit_", sizeof(fname)); + strlcat(fname, arch->name[0], sizeof(fname)); lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); diff --git a/src/gamecode/economy.c b/src/gamecode/economy.c index dcf4bdcc7..cc516d784 100644 --- a/src/gamecode/economy.c +++ b/src/gamecode/economy.c @@ -55,6 +55,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. /* util includes */ #include #include +#include #include #include #include @@ -264,7 +265,9 @@ static void add_recruits(unit * u, int number, int wanted) unew = create_unit(r, u->faction, number, u->race, 0, NULL, u); } - snprintf(equipment, sizeof(equipment), "new_%s_unit", u->race->_name[0]); + strlcpy(equipment, "new_", sizeof(equipment)); + strlcat(equipment, u->race->_name[0], sizeof(equipment)); + strlcat(equipment, "_unit", sizeof(equipment)); equip_unit(unew, get_equipment(equipment)); if (unew->race->ec_flags & ECF_REC_HORSES) { diff --git a/src/gamecode/laws.c b/src/gamecode/laws.c index 27f069345..ab79b4122 100644 --- a/src/gamecode/laws.c +++ b/src/gamecode/laws.c @@ -2302,21 +2302,21 @@ static boolean display_race(faction * f, unit * u, const race * rc) /* hp_p : Trefferpunkte */ bytes = - snprintf(bufp, size, " %d %s", rc->hitpoints, LOC(f->locale, + slprintf(bufp, size, " %d %s", rc->hitpoints, LOC(f->locale, "stat_hitpoints")); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); /* b_attacke : Angriff */ bytes = - snprintf(bufp, size, ", %s: %d", LOC(f->locale, "stat_attack"), + slprintf(bufp, size, ", %s: %d", LOC(f->locale, "stat_attack"), (rc->at_default + rc->at_bonus)); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); /* b_defense : Verteidigung */ bytes = - snprintf(bufp, size, ", %s: %d", LOC(f->locale, "stat_defense"), + slprintf(bufp, size, ", %s: %d", LOC(f->locale, "stat_defense"), (rc->df_default + rc->df_bonus)); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); @@ -2324,7 +2324,7 @@ static boolean display_race(faction * f, unit * u, const race * rc) /* b_armor : Rüstung */ if (rc->armor > 0) { bytes = - snprintf(bufp, size, ", %s: %d", LOC(f->locale, "stat_armor"), rc->armor); + slprintf(bufp, size, ", %s: %d", LOC(f->locale, "stat_armor"), rc->armor); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } diff --git a/src/gamecode/randenc.c b/src/gamecode/randenc.c index b0f422f0b..a2d84f154 100644 --- a/src/gamecode/randenc.c +++ b/src/gamecode/randenc.c @@ -235,9 +235,9 @@ void find_manual(region * r, unit * u) break; } - snprintf(zLocation, sizeof(zLocation), "manual_location_%d", + slprintf(zLocation, sizeof(zLocation), "manual_location_%d", (int)(rng_int() % 4)); - snprintf(zBook, sizeof(zLocation), "manual_title_%s", skillnames[skill]); + slprintf(zBook, sizeof(zLocation), "manual_title_%s", skillnames[skill]); msg = msg_message("find_manual", "unit location book", u, zLocation, zBook); r_addmessage(r, u->faction, msg); diff --git a/src/kernel/alliance.c b/src/kernel/alliance.c index 15d4c7f6d..ddb92fcf4 100644 --- a/src/kernel/alliance.c +++ b/src/kernel/alliance.c @@ -31,6 +31,7 @@ without prior permission by the authors of Eressea. /* util includes */ #include #include +#include #include #include #include @@ -394,8 +395,7 @@ const char *alliancename(const alliance * al) char *ibuf = idbuf[(++nextbuf) % 8]; if (al && al->name) { - snprintf(ibuf, sizeof(name), "%s (%s)", al->name, itoa36(al->id)); - ibuf[sizeof(name) - 1] = 0; + slprintf(ibuf, sizeof(name), "%s (%s)", al->name, itoa36(al->id)); } else { return NULL; } diff --git a/src/kernel/battle.c b/src/kernel/battle.c index 6c51ce01b..36abba1b9 100644 --- a/src/kernel/battle.c +++ b/src/kernel/battle.c @@ -211,13 +211,7 @@ static char *sidename(side * s) static char sidename_buf[4][SIDENAMEBUFLEN]; /* STATIC_RESULT: used for return, not across calls */ bufno = bufno % 4; - if (s->stealthfaction) { - snprintf(sidename_buf[bufno], SIDENAMEBUFLEN, - "%s", factionname(s->stealthfaction)); - } else { - snprintf(sidename_buf[bufno], SIDENAMEBUFLEN, - "%s", factionname(s->faction)); - } + strlcpy(sidename_buf[bufno], factionname(s->stealthfaction?s->stealthfaction:s->faction), SIDENAMEBUFLEN); return sidename_buf[bufno++]; } @@ -3850,9 +3844,8 @@ static int battle_report(battle * b) if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } - snprintf(buffer, sizeof(buffer), "%s %2d(%s): ", + slprintf(buffer, sizeof(buffer), "%s %2d(%s): ", loc_army, army_index(s), abbrev); - buffer[sizeof(buffer) - 1] = 0; bytes = (int)strlcpy(bufp, buffer, size); if (wrptr(&bufp, &size, bytes) != 0) diff --git a/src/kernel/building.c b/src/kernel/building.c index a5178a17d..0edb9a6bc 100644 --- a/src/kernel/building.c +++ b/src/kernel/building.c @@ -613,8 +613,7 @@ int bt_effsize(const building_type * btype, const building * b, int bsize) const char *write_buildingname(const building * b, char *ibuf, size_t size) { - snprintf((char *)ibuf, size, "%s (%s)", b->name, itoa36(b->no)); - ibuf[size - 1] = 0; + slprintf(ibuf, size, "%s (%s)", b->name, itoa36(b->no)); return ibuf; } diff --git a/src/kernel/config.c b/src/kernel/config.c index 114e5cafb..d2eb422d6 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -1653,8 +1653,7 @@ building *largestbuilding(const region * r, cmp_building_cb cmp_gt, char *write_unitname(const unit * u, char *buffer, size_t size) { - snprintf((char *)buffer, size, "%s (%s)", (const char *)u->name, - itoa36(u->no)); + slprintf(buffer, size, "%s (%s)", (const char *)u->name, itoa36(u->no)); buffer[size - 1] = 0; return buffer; } diff --git a/src/kernel/connection.c b/src/kernel/connection.c index 32eb73a6b..98ac0234b 100644 --- a/src/kernel/connection.c +++ b/src/kernel/connection.c @@ -532,7 +532,7 @@ static const char *b_nameroad(const connection * b, const region * r, } else { int percent = MAX(1, 100 * local / r->terrain->max_road); if (local) { - snprintf(buffer, sizeof(buffer), LOC(f->locale, mkname("border", + slprintf(buffer, sizeof(buffer), LOC(f->locale, mkname("border", "a_road_percent")), percent); } else { return LOC(f->locale, mkname("border", "a_road_connection")); diff --git a/src/kernel/faction.c b/src/kernel/faction.c index dcfa7b59a..6c33d9dd7 100644 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -153,8 +153,7 @@ const char *factionname(const faction * f) char *ibuf = idbuf[(++nextbuf) % 8]; if (f && f->name) { - snprintf(ibuf, sizeof(name), "%s (%s)", f->name, itoa36(f->no)); - ibuf[sizeof(name) - 1] = 0; + slprintf(ibuf, sizeof(name), "%s (%s)", f->name, itoa36(f->no)); } else { strcpy(ibuf, "Unbekannte Partei (?)"); } @@ -226,7 +225,7 @@ faction *addfaction(const char *email, const char *password, addlist(&factions, f); fhash(f); - snprintf(buf, sizeof(buf), "%s %s", LOC(loc, "factiondefault"), factionid(f)); + slprintf(buf, sizeof(buf), "%s %s", LOC(loc, "factiondefault"), factionid(f)); f->name = strdup(buf); return f; diff --git a/src/kernel/move.c b/src/kernel/move.c index c7a669d9a..5c1f7b9fc 100644 --- a/src/kernel/move.c +++ b/src/kernel/move.c @@ -2398,9 +2398,7 @@ static int hunt(unit * u, order * ord) } bufp = command; - bytes = - snprintf(bufp, size, "%s %s", LOC(u->faction->locale, keywords[K_MOVE]), - LOC(u->faction->locale, directions[dir])); + bytes = slprintf(bufp, size, "%s %s", LOC(u->faction->locale, keywords[K_MOVE]), LOC(u->faction->locale, directions[dir])); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); diff --git a/src/kernel/region.c b/src/kernel/region.c index fdcc2f39b..6996d959f 100644 --- a/src/kernel/region.c +++ b/src/kernel/region.c @@ -41,6 +41,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. /* util includes */ #include +#include #include #include #include @@ -114,15 +115,14 @@ const char *write_regionname(const region * r, const faction * f, char *buffer, char *buf = (char *)buffer; const struct locale *lang = f ? f->locale : 0; if (r == NULL) { - strcpy(buf, "(null)"); + strlcpy(buf, "(null)", size); } else { plane *pl = rplane(r); int nx = r->x, ny = r->y; pnormalize(&nx, &ny, pl); adjust_coordinates(f, &nx, &ny, pl, r); - snprintf(buf, size, "%s (%d,%d)", rname(r, lang), nx, ny); + slprintf(buf, size, "%s (%d,%d)", rname(r, lang), nx, ny); } - buf[size - 1] = 0; return buffer; } diff --git a/src/kernel/save.c b/src/kernel/save.c index 20f1eb39d..ccc28c895 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -1552,7 +1552,8 @@ int readgame(const char *filename, int mode, int backup) store->r_str_buf(store, basefile, sizeof(basefile)); if (strcmp(game_name, basefile) != 0) { char buffer[64]; - snprintf(buffer, sizeof(buffer), "%s.xml", game_name); + strlcpy(buffer, game_name, sizeof(buffer)); + strlcat(buffer, ".xml", sizeof(buffer)); if (strcmp(basefile, buffer) != 0) { log_warning("game mismatch: datafile contains %s, game is %s\n", basefile, game_name); printf("WARNING: any key to continue, Ctrl-C to stop\n"); diff --git a/src/kernel/ship.c b/src/kernel/ship.c index 63787a3ab..6c008dfd6 100644 --- a/src/kernel/ship.c +++ b/src/kernel/ship.c @@ -233,8 +233,7 @@ void free_ships(void) const char *write_shipname(const ship * sh, char *ibuf, size_t size) { - snprintf(ibuf, size, "%s (%s)", sh->name, itoa36(sh->no)); - ibuf[size - 1] = 0; + slprintf(ibuf, size, "%s (%s)", sh->name, itoa36(sh->no)); return ibuf; } diff --git a/src/kernel/unit.c b/src/kernel/unit.c index a1c4bc50e..585696e3f 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -44,6 +44,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. /* util includes */ #include #include +#include #include #include #include @@ -1424,7 +1425,9 @@ void name_unit(unit * u) } else { result = parameters[P_UNIT]; } - snprintf(name, sizeof(name), "%s %s", result, itoa36(u->no)); + strlcpy(name, result, sizeof(name)); + strlcat(name, " ", sizeof(name)); + strlcat(name, itoa36(u->no), sizeof(name)); unit_setname(u, name); } } From cb0e406733f600a01b8555b793e3c3615a7851b4 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 29 May 2012 18:08:56 -0700 Subject: [PATCH 6/9] repair lua spells (bad stack index) add a whole bunch more spell tests allow spell tests to disable fumbles --- scripts/tests/spells.lua | 122 ++++++++++++++++++++++++++++++++++----- src/bindings/bindings.c | 8 +-- src/bindings/helpers.c | 5 +- src/kernel/magic.c | 3 + 4 files changed, 116 insertions(+), 22 deletions(-) diff --git a/scripts/tests/spells.lua b/scripts/tests/spells.lua index 0101c2518..1538b4249 100644 --- a/scripts/tests/spells.lua +++ b/scripts/tests/spells.lua @@ -5,25 +5,117 @@ module("tests.spells", package.seeall, lunit.testcase) function setup() free_game() settings.set("magic.fumble.enable", "0") + settings.set("magic.regeneration.enable", "0") + settings.set("rules.economy.food", "0") end -function test_roi() +function test_create_firesword() local r = region.create(0,0, "plain") - local f = faction.create("noreply@eressea.de", "human", "de") + local f = faction.create("create_firesword@eressea.de", "human", "de") local u = unit.create(f, r, 1) - u.race = "elf" - u:set_skill("magic", 10) - u:add_item("money", 3010) - f.magic = "gwyrrd" - u.magic = "gwyrrd" - u.aura = 200 - u.ship = s1 + u:set_skill("magic", 12) + u:add_spell("create_firesword") --- local err = u:add_spell("create_roi") --- assert_equal(0, err) - u:clear_orders() - u:add_order("ZAUBERE 'Erschaffe einen Ring der Unsichtbarkeit' ") - process_orders() - write_reports() + u:cast_spell('create_firesword', 1) + assert_equal(1, u:get_item("firesword")) +end + +function test_create_roi() + local r = region.create(0,0, "plain") + local f = faction.create("create_roi@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + u:set_skill("magic", 10) + + u:cast_spell('create_roi') assert_equal(1, u:get_item("roi")) end + +function test_create_roqf() + local r = region.create(0,0, "plain") + local f = faction.create("create_roqf@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + u:set_skill("magic", 10) + + u:cast_spell('create_roqf') + assert_equal(1, u:get_item("roqf")) +end + +function test_create_aots() + local r = region.create(0,0, "plain") + local f = faction.create("create_aots@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + u:set_skill("magic", 10) + + u:cast_spell('create_aots') + assert_equal(1, u:get_item("aots")) +end + +function test_create_ror() + local r = region.create(0,0, "plain") + local f = faction.create("create_ror@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + u:set_skill("magic", 10) + + u:cast_spell('create_ror') + assert_equal(1, u:get_item("ror")) +end + +function test_create_magicherbbag() + local r = region.create(0,0, "plain") + local f = faction.create("create_magicherbbag@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + u:set_skill("magic", 10) + + u:cast_spell('create_magicherbbag') + assert_equal(1, u:get_item("magicherbbag")) +end + +function test_create_trollbelt() + local r = region.create(0,0, "plain") + local f = faction.create("create_trollbelt@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + u:set_skill("magic", 10) + + u:cast_spell('create_trollbelt') + assert_equal(1, u:get_item("trollbelt")) +end + +function test_create_dreameye() + local r = region.create(0,0, "plain") + local f = faction.create("create_dreameye@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + u:set_skill("magic", 10) + + u:cast_spell('create_dreameye') + assert_equal(1, u:get_item("dreameye")) +end + +function test_create_antimagic() + local r = region.create(0,0, "plain") + local f = faction.create("create_antimagic@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + u:set_skill("magic", 10) + + u:cast_spell('create_antimagic') + assert_equal(1, u:get_item("antimagic")) +end + +function test_create_runesword() + local r = region.create(0,0, "plain") + local f = faction.create("create_runesword@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + u:set_skill("magic", 10) + + u:cast_spell('create_runesword') + assert_equal(1, u:get_item("runesword")) +end + +function test_create_rop() + local r = region.create(0,0, "plain") + local f = faction.create("create_rop@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + u:set_skill("magic", 10) + + u:cast_spell('create_rop') + assert_equal(1, u:get_item("rop")) +end diff --git a/src/bindings/bindings.c b/src/bindings/bindings.c index f633f7716..228b94ada 100644 --- a/src/bindings/bindings.c +++ b/src/bindings/bindings.c @@ -1070,7 +1070,7 @@ static int tolua_eventbus_register(lua_State * L) { void *sender = tolua_tousertype(L, 1, 0); const char *event = tolua_tostring(L, 2, 0); - event_args *args = malloc(sizeof(event_args)); + event_args *args = (event_args *)malloc(sizeof(event_args)); args->sendertype = sender ? tolua_typename(L, 1) : NULL; lua_pushvalue(L, 3); args->hfunction = luaL_ref(L, LUA_REGISTRYINDEX); @@ -1259,10 +1259,8 @@ int tolua_eressea_open(lua_State * L) tolua_function(L, TOLUA_CAST "itoa36", tolua_itoa36); tolua_function(L, TOLUA_CAST "dice_roll", tolua_dice_rand); tolua_function(L, TOLUA_CAST "get_nmrs", tolua_get_nmrs); - tolua_function(L, TOLUA_CAST "remove_empty_units", - tolua_remove_empty_units); - tolua_function(L, TOLUA_CAST "update_subscriptions", - tolua_update_subscriptions); + tolua_function(L, TOLUA_CAST "remove_empty_units", tolua_remove_empty_units); + tolua_function(L, TOLUA_CAST "update_subscriptions", tolua_update_subscriptions); tolua_function(L, TOLUA_CAST "update_scores", tolua_update_scores); tolua_function(L, TOLUA_CAST "update_owners", tolua_update_owners); tolua_function(L, TOLUA_CAST "learn_skill", tolua_learn_skill); diff --git a/src/bindings/helpers.c b/src/bindings/helpers.c index 28ee984da..dec73f5f8 100644 --- a/src/bindings/helpers.c +++ b/src/bindings/helpers.c @@ -203,7 +203,7 @@ static int lua_callspell(castorder * co) lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); - if (lua_isfunction(L, 1)) { + if (lua_isfunction(L, -1)) { int nparam = 4; tolua_pushusertype(L, r, TOLUA_CAST "region"); tolua_pushusertype(L, caster, TOLUA_CAST "unit"); @@ -236,7 +236,8 @@ static int lua_callspell(castorder * co) lua_pop(L, 1); } } else { - log_error("spell(%s) calling '%s': not a function.\n", unitname(caster), fname); + int ltype = lua_type(L, -1); + log_error("spell(%s) calling '%s': not a function, has type %d.\n", unitname(caster), fname, ltype); lua_pop(L, 1); } diff --git a/src/kernel/magic.c b/src/kernel/magic.c index 783ef5cad..581ef4988 100644 --- a/src/kernel/magic.c +++ b/src/kernel/magic.c @@ -1452,6 +1452,9 @@ void regeneration_magiepunkte(void) double reg_aura; int regen; double mod; + int regen_enabled = get_param_int(global.parameters, "magic.regeneration.enable", 1); + + if (!regen_enabled) return; for (r = regions; r; r = r->next) { for (u = r->units; u; u = u->next) { From 5e26d246a29797a330a8da29cd1d5f6712b407d6 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 29 May 2012 20:13:54 -0700 Subject: [PATCH 7/9] more Lua functions using the wrong stack index. --- src/bindings/helpers.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/bindings/helpers.c b/src/bindings/helpers.c index dec73f5f8..f2fbae090 100644 --- a/src/bindings/helpers.c +++ b/src/bindings/helpers.c @@ -37,8 +37,7 @@ without prior permission by the authors of Eressea. #include static int -lua_giveitem(unit * s, unit * d, const item_type * itype, int n, - struct order *ord) +lua_giveitem(unit * s, unit * d, const item_type * itype, int n, struct order *ord) { lua_State *L = (lua_State *) global.vm_state; char fname[64]; @@ -46,11 +45,12 @@ lua_giveitem(unit * s, unit * d, const item_type * itype, int n, const char *iname = itype->rtype->_name[0]; assert(s != NULL); - strcat(strcpy(fname, iname), "_give"); + strlcpy(fname, iname, sizeof(fname)); + strlcat(fname, "_give", sizeof(fname)); lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); - if (lua_isfunction(L, 1)) { + if (lua_isfunction(L, -1)) { tolua_pushusertype(L, s, TOLUA_CAST "unit"); tolua_pushusertype(L, d, TOLUA_CAST "unit"); tolua_pushstring(L, iname); @@ -83,7 +83,7 @@ static int limit_resource(const region * r, const resource_type * rtype) lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); - if (lua_isfunction(L, 1)) { + if (lua_isfunction(L, -1)) { tolua_pushusertype(L, (void *)r, TOLUA_CAST "region"); if (lua_pcall(L, 1, 1, 0) != 0) { @@ -113,7 +113,7 @@ produce_resource(region * r, const resource_type * rtype, int norders) lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); - if (lua_isfunction(L, 1)) { + if (lua_isfunction(L, -1)) { tolua_pushusertype(L, (void *)r, TOLUA_CAST "region"); tolua_pushnumber(L, (lua_Number) norders); @@ -142,7 +142,7 @@ static int lc_age(struct attrib *a) lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); - if (lua_isfunction(L, 1)) { + if (lua_isfunction(L, -1)) { tolua_pushusertype(L, (void *)b, TOLUA_CAST "building"); if (fparam) { tolua_pushstring(L, fparam); @@ -256,7 +256,7 @@ static int lua_initfamiliar(unit * u) lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); - if (lua_isfunction(L, 1)) { + if (lua_isfunction(L, -1)) { tolua_pushusertype(L, u, TOLUA_CAST "unit"); if (lua_pcall(L, 1, 1, 0) != 0) { @@ -292,7 +292,7 @@ lua_changeresource(unit * u, const struct resource_type *rtype, int delta) lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); - if (lua_isfunction(L, 1)) { + if (lua_isfunction(L, -1)) { tolua_pushusertype(L, u, TOLUA_CAST "unit"); tolua_pushnumber(L, (lua_Number) delta); @@ -323,7 +323,7 @@ static int lua_getresource(unit * u, const struct resource_type *rtype) lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); - if (lua_isfunction(L, 1)) { + if (lua_isfunction(L, -1)) { tolua_pushusertype(L, u, TOLUA_CAST "unit"); if (lua_pcall(L, 1, 1, 0) != 0) { @@ -353,7 +353,7 @@ static boolean lua_canuse_item(const unit * u, const struct item_type *itype) lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); - if (lua_isfunction(L, 1)) { + if (lua_isfunction(L, -1)) { tolua_pushusertype(L, (void *)u, TOLUA_CAST "unit"); tolua_pushstring(L, itype->rtype->_name[0]); @@ -383,7 +383,7 @@ lua_wage(const region * r, const faction * f, const race * rc, int in_turn) lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); - if (lua_isfunction(L, 1)) { + if (lua_isfunction(L, -1)) { tolua_pushusertype(L, (void *)r, TOLUA_CAST "region"); tolua_pushusertype(L, (void *)f, TOLUA_CAST "faction"); tolua_pushstring(L, rc ? rc->_name[0] : 0); @@ -415,7 +415,7 @@ static void lua_agebuilding(building * b) lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); - if (lua_isfunction(L, 1)) { + if (lua_isfunction(L, -1)) { tolua_pushusertype(L, (void *)b, TOLUA_CAST "building"); if (lua_pcall(L, 1, 0, 0) != 0) { @@ -437,7 +437,7 @@ static int lua_building_protection(building * b, unit * u) lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); - if (lua_isfunction(L, 1)) { + if (lua_isfunction(L, -1)) { tolua_pushusertype(L, (void *)b, TOLUA_CAST "building"); tolua_pushusertype(L, (void *)u, TOLUA_CAST "unit"); @@ -464,7 +464,7 @@ static double lua_building_taxes(building * b, int level) lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); - if (lua_isfunction(L, 1)) { + if (lua_isfunction(L, -1)) { tolua_pushusertype(L, (void *)b, TOLUA_CAST "building"); tolua_pushnumber(L, level); @@ -491,7 +491,7 @@ static int lua_maintenance(const unit * u) lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); - if (lua_isfunction(L, 1)) { + if (lua_isfunction(L, -1)) { tolua_pushusertype(L, (void *)u, TOLUA_CAST "unit"); if (lua_pcall(L, 1, 1, 0) != 0) { @@ -521,7 +521,7 @@ static int lua_equipmentcallback(const struct equipment *eq, unit * u) lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); - if (lua_isfunction(L, 1)) { + if (lua_isfunction(L, -1)) { tolua_pushusertype(L, (void *)u, TOLUA_CAST "unit"); if (lua_pcall(L, 1, 1, 0) != 0) { @@ -553,7 +553,7 @@ lua_useitem(struct unit *u, const struct item_type *itype, int amount, lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); - if (lua_isfunction(L, 1)) { + if (lua_isfunction(L, -1)) { tolua_pushusertype(L, (void *)u, TOLUA_CAST "unit"); tolua_pushnumber(L, (lua_Number) amount); @@ -584,7 +584,7 @@ static int lua_recruit(struct unit *u, const struct archetype *arch, int amount) lua_pushstring(L, fname); lua_rawget(L, LUA_GLOBALSINDEX); - if (lua_isfunction(L, 1)) { + if (lua_isfunction(L, -1)) { tolua_pushusertype(L, (void *)u, TOLUA_CAST "unit"); tolua_pushnumber(L, (lua_Number) amount); From 44e5c60c96b13df30e37c6b4f72e6b31a6b2f54f Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 29 May 2012 20:44:25 -0700 Subject: [PATCH 8/9] test added: when a spell is not found, we do not have to pay for it --- scripts/tests/spells.lua | 44 +++++++++++++++++++++++++++++++++++++++- src/kernel/magic.c | 12 +++++++---- 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/scripts/tests/spells.lua b/scripts/tests/spells.lua index 1538b4249..2d23d2efe 100644 --- a/scripts/tests/spells.lua +++ b/scripts/tests/spells.lua @@ -6,7 +6,49 @@ function setup() free_game() settings.set("magic.fumble.enable", "0") settings.set("magic.regeneration.enable", "0") - settings.set("rules.economy.food", "0") + settings.set("rules.economy.food", "4") +end + +function test_spell_payment() + local r = region.create(0,0, "plain") + local f = faction.create("spell_payment@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + u:set_skill("magic", 12) + u.magic = "gwyrrd" -- calls create_mage + u:add_spell("create_roi") + + local permaura = u:get_pooled("permaura") + u:add_item("money", 3000) + u.aura = 50 + u:clear_orders() + u:add_order("ZAUBERE 'Erschaffe einen Ring der Unsichtbarkeit' ") + process_orders() + + assert_equal(1, u:get_item("roi")) + assert_equal(0, u:get_item("money")) + assert_equal(0, u.aura) + assert_equal(permaura-1, u:get_pooled("permaura")) +end + +function test_spell_not_found_no_payment() + local r = region.create(0,0, "plain") + local f = faction.create("spell_fails_no_payment@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + u:set_skill("magic", 12) + u.magic = "gwyrrd" -- calls create_mage + + local permaura = u:get_pooled("permaura") + u:add_item("money", 3000) + u.aura = 50 + + u:clear_orders() + u:add_order("ZAUBERE 'Erschaffe einen Ring der Unsichtbarkeit' ") + process_orders() + + assert_equal(0, u:get_item("roi")) + assert_equal(3000, u:get_item("money")) + assert_equal(50, u.aura) + assert_equal(permaura, u:get_pooled("permaura")) end function test_create_firesword() diff --git a/src/kernel/magic.c b/src/kernel/magic.c index 581ef4988..f6b8360b9 100644 --- a/src/kernel/magic.c +++ b/src/kernel/magic.c @@ -889,6 +889,7 @@ void pay_spell(unit * u, const spell * sp, int cast_level, int range) int k; int resuse; + assert(cast_level>0); for (k = 0; sp->components[k].type; k++) { if (sp->components[k].type == r_aura) { resuse = spellcost(u, sp) * range; @@ -1394,7 +1395,7 @@ static void do_fumble(castorder * co) case 5: case 6: /* Spruch gelingt, aber alle Magiepunkte weg */ - sp->cast(co); + co->level = sp->cast(co); set_spellpoints(u, 0); ADDMSG(&u->faction->msgs, msg_message("patzer4", "unit region spell", u, r, sp)); @@ -1405,7 +1406,7 @@ static void do_fumble(castorder * co) case 9: default: /* Spruch gelingt, alle nachfolgenden Sprüche werden 2^4 so teuer */ - sp->cast(co); + co->level = sp->cast(co); ADDMSG(&u->faction->msgs, msg_message("patzer5", "unit region spell", u, r, sp)); countspells(u, 3); @@ -2839,10 +2840,13 @@ void magic(void) } } } - pay_spell(u, sp, co->level, co->distance); /* erst bezahlen, dann Kostenzähler erhöhen */ - if (fumbled) + if (fumbled) { do_fumble(co); + } + if (co->level>0) { + pay_spell(u, sp, co->level, co->distance); + } countspells(u, 1); } } From 3e67e7fb4e1d0e6c1036cf4a6b2644e0c8c49790 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 29 May 2012 20:50:20 -0700 Subject: [PATCH 9/9] Lua unit:cast_spell should only cast spells the unit knows. do not allow payment for spells cast at level <= 0 --- scripts/tests/spells.lua | 22 +++++++++++++++++++++- src/bindings/bind_unit.c | 10 +++++----- src/kernel/magic_test.c | 16 +++------------- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/scripts/tests/spells.lua b/scripts/tests/spells.lua index 2d23d2efe..d8b446ace 100644 --- a/scripts/tests/spells.lua +++ b/scripts/tests/spells.lua @@ -34,8 +34,8 @@ function test_spell_not_found_no_payment() local r = region.create(0,0, "plain") local f = faction.create("spell_fails_no_payment@eressea.de", "human", "de") local u = unit.create(f, r, 1) - u:set_skill("magic", 12) u.magic = "gwyrrd" -- calls create_mage + u:set_skill("magic", 12) local permaura = u:get_pooled("permaura") u:add_item("money", 3000) @@ -55,6 +55,7 @@ function test_create_firesword() local r = region.create(0,0, "plain") local f = faction.create("create_firesword@eressea.de", "human", "de") local u = unit.create(f, r, 1) + u.magic = "gwyrrd" -- calls create_mage u:set_skill("magic", 12) u:add_spell("create_firesword") @@ -66,8 +67,10 @@ function test_create_roi() local r = region.create(0,0, "plain") local f = faction.create("create_roi@eressea.de", "human", "de") local u = unit.create(f, r, 1) + u.magic = "gwyrrd" -- calls create_mage u:set_skill("magic", 10) + u:add_spell('create_roi') u:cast_spell('create_roi') assert_equal(1, u:get_item("roi")) end @@ -76,8 +79,10 @@ function test_create_roqf() local r = region.create(0,0, "plain") local f = faction.create("create_roqf@eressea.de", "human", "de") local u = unit.create(f, r, 1) + u.magic = "gwyrrd" -- calls create_mage u:set_skill("magic", 10) + u:add_spell('create_roqf') u:cast_spell('create_roqf') assert_equal(1, u:get_item("roqf")) end @@ -86,8 +91,10 @@ function test_create_aots() local r = region.create(0,0, "plain") local f = faction.create("create_aots@eressea.de", "human", "de") local u = unit.create(f, r, 1) + u.magic = "gwyrrd" -- calls create_mage u:set_skill("magic", 10) + u:add_spell('create_aots') u:cast_spell('create_aots') assert_equal(1, u:get_item("aots")) end @@ -96,8 +103,10 @@ function test_create_ror() local r = region.create(0,0, "plain") local f = faction.create("create_ror@eressea.de", "human", "de") local u = unit.create(f, r, 1) + u.magic = "gwyrrd" -- calls create_mage u:set_skill("magic", 10) + u:add_spell('create_ror') u:cast_spell('create_ror') assert_equal(1, u:get_item("ror")) end @@ -106,8 +115,10 @@ function test_create_magicherbbag() local r = region.create(0,0, "plain") local f = faction.create("create_magicherbbag@eressea.de", "human", "de") local u = unit.create(f, r, 1) + u.magic = "gwyrrd" -- calls create_mage u:set_skill("magic", 10) + u:add_spell('create_magicherbbag') u:cast_spell('create_magicherbbag') assert_equal(1, u:get_item("magicherbbag")) end @@ -116,8 +127,10 @@ function test_create_trollbelt() local r = region.create(0,0, "plain") local f = faction.create("create_trollbelt@eressea.de", "human", "de") local u = unit.create(f, r, 1) + u.magic = "gwyrrd" -- calls create_mage u:set_skill("magic", 10) + u:add_spell('create_trollbelt') u:cast_spell('create_trollbelt') assert_equal(1, u:get_item("trollbelt")) end @@ -126,8 +139,10 @@ function test_create_dreameye() local r = region.create(0,0, "plain") local f = faction.create("create_dreameye@eressea.de", "human", "de") local u = unit.create(f, r, 1) + u.magic = "gwyrrd" -- calls create_mage u:set_skill("magic", 10) + u:add_spell('create_dreameye') u:cast_spell('create_dreameye') assert_equal(1, u:get_item("dreameye")) end @@ -136,8 +151,10 @@ function test_create_antimagic() local r = region.create(0,0, "plain") local f = faction.create("create_antimagic@eressea.de", "human", "de") local u = unit.create(f, r, 1) + u.magic = "gwyrrd" -- calls create_mage u:set_skill("magic", 10) + u:add_spell('create_antimagic') u:cast_spell('create_antimagic') assert_equal(1, u:get_item("antimagic")) end @@ -146,8 +163,10 @@ function test_create_runesword() local r = region.create(0,0, "plain") local f = faction.create("create_runesword@eressea.de", "human", "de") local u = unit.create(f, r, 1) + u.magic = "gwyrrd" -- calls create_mage u:set_skill("magic", 10) + u:add_spell('create_runesword') u:cast_spell('create_runesword') assert_equal(1, u:get_item("runesword")) end @@ -158,6 +177,7 @@ function test_create_rop() local u = unit.create(f, r, 1) u:set_skill("magic", 10) + u:add_spell('create_rop') u:cast_spell('create_rop') assert_equal(1, u:get_item("rop")) end diff --git a/src/bindings/bind_unit.c b/src/bindings/bind_unit.c index 1b4547932..50c588e78 100644 --- a/src/bindings/bind_unit.c +++ b/src/bindings/bind_unit.c @@ -32,6 +32,7 @@ without prior permission by the authors of Eressea. #include #include #include +#include #include #include #include @@ -455,12 +456,11 @@ static int tolua_unit_addnotice(lua_State * L) static void unit_castspell(unit * u, const char *name, int level) { - quicklist *ql = spells; - int qi; + spell *sp = find_spell(name); - for (ql = spells, qi = 0; ql; ql_advance(&ql, &qi, 1)) { - spell *sp = (spell *) ql_get(ql, qi); - if (strcmp(name, sp->sname) == 0) { + if (sp) { + spellbook *book = unit_get_spellbook(u); + if (spellbook_get(book, sp)) { if (!sp->cast) { log_error("spell '%s' has no function.\n", sp->sname); } else { diff --git a/src/kernel/magic_test.c b/src/kernel/magic_test.c index 9bcc1d117..20899e32d 100644 --- a/src/kernel/magic_test.c +++ b/src/kernel/magic_test.c @@ -152,19 +152,9 @@ void test_pay_spell_failure(CuTest * tc) CuAssertIntEquals(tc, 3, change_resource(u, rt_find("aura"), 3)); CuAssertIntEquals(tc, 2, change_resource(u, rt_find("horse"), 1)); - level = eff_spelllevel(u, sp, 3, 1); - CuAssertIntEquals(tc, 0, level); - pay_spell(u, sp, level, 1); - CuAssertIntEquals(tc, 0, get_resource(u, rt_find("money"))); /* seems we even pay this at level 0 */ - CuAssertIntEquals(tc, 3, get_resource(u, rt_find("aura"))); - CuAssertIntEquals(tc, 2, get_resource(u, rt_find("horse"))); - - level = eff_spelllevel(u, sp, 2, 1); - CuAssertIntEquals(tc, 0, level); - pay_spell(u, sp, level, 1); - CuAssertIntEquals(tc, 0, get_resource(u, rt_find("money"))); - CuAssertIntEquals(tc, 3, get_resource(u, rt_find("aura"))); - CuAssertIntEquals(tc, 2, get_resource(u, rt_find("horse"))); + CuAssertIntEquals(tc, 0, eff_spelllevel(u, sp, 3, 1)); + CuAssertIntEquals(tc, 0, change_resource(u, rt_find("money"), -1)); + CuAssertIntEquals(tc, 0, eff_spelllevel(u, sp, 2, 1)); } void test_getspell_unit(CuTest * tc)