From 3ea12be5642c130fd40a13c7e765e0c66927e14d Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 13 Feb 2017 18:48:38 +0100 Subject: [PATCH 1/7] BENUTZE Muschel repariert. at_keys hat jetzt auch zu jedem key ein value, und Funktionen zum Update altee Daten. --- scripts/eressea/embassy.lua | 16 +++++- src/attributes/dict.c | 98 +++++++++++-------------------------- src/attributes/dict.h | 10 ++-- src/attributes/key.c | 62 +++++++++++++---------- src/attributes/key.h | 6 +-- src/attributes/key.test.c | 47 ++++++++++++------ src/bind_faction.c | 6 +-- src/bind_region.c | 4 +- src/bind_unit.c | 2 +- src/bindings.c | 4 +- src/kernel/group.test.c | 4 +- src/kernel/item.c | 2 +- src/kernel/save.test.c | 8 +-- src/util/gamedata.h | 3 +- 14 files changed, 135 insertions(+), 137 deletions(-) diff --git a/scripts/eressea/embassy.lua b/scripts/eressea/embassy.lua index 704581c6f..93ff66d7c 100644 --- a/scripts/eressea/embassy.lua +++ b/scripts/eressea/embassy.lua @@ -5,6 +5,20 @@ if not config.embassy then return nil end local embassy = {} local home = nil +-- global exports (use item) +function use_seashell(u, amount) +-- Muschelplateau... + local visit = u.faction:get_key('mupL') + if visit and u.region~= home then + local turns = get_turn() - visit + local msg = message.create('msg_event') + msg:set_string("string", u.name .. "(" .. itoa36(u.id) .. ") erzählt den Bewohnern von " .. u.region.name .. " von Muschelplateau, das die Partei " .. u.faction.name .. " vor " .. turns .. " Wochen besucht hat." ) + msg:send_region(u.region) + return 0 + end + return -4 +end + function embassy.init() home = get_region(165,30) if home==nil then @@ -20,7 +34,7 @@ function embassy.update() eressea.log.debug("updating embassies in " .. tostring(home)) local u for u in home.units do - if not u.faction:get_key('mupL') then + if u.faction:get_key('mupL')==0 then if (u.faction:add_item('seashell', 1)>0) then eressea.log.debug("new seashell for " .. tostring(u.faction)) u.faction:set_key('mupL', get_turn()) diff --git a/src/attributes/dict.c b/src/attributes/dict.c index 6d4b3ed3c..ad66e3676 100644 --- a/src/attributes/dict.c +++ b/src/attributes/dict.c @@ -42,6 +42,10 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include +typedef enum { + TNONE = 0, TINTEGER = 1 +} dict_type; + typedef struct dict_data { dict_type type; char *name; @@ -62,94 +66,38 @@ static int dict_read(attrib * a, void *owner, gamedata *data) storage *store = data->store; char name[NAMESIZE]; dict_data *dd = (dict_data *)a->data.v; - int result, n; - float flt; + int n; READ_STR(store, name, sizeof(name)); dd->name = strdup(name); READ_INT(store, &n); dd->type = (dict_type)n; - switch (dd->type) { - case TINTEGER: - READ_INT(store, &dd->data.i); - break; - case TREAL: - READ_FLT(store, &flt); - if ((int)flt == flt) { - dd->type = TINTEGER; - dd->data.i = (int)flt; - } - else { - dd->data.real = flt; - } - break; - case TSTRING: - READ_STR(store, name, sizeof(name)); - dd->data.str = strdup(name); - break; - case TBUILDING: - result = - read_reference(&dd->data.b, data, read_building_reference, - resolve_building); - if (result == 0 && !dd->data.b) { - return AT_READ_FAIL; - } - break; - case TUNIT: - result = - read_reference(&dd->data.u, data, read_unit_reference, resolve_unit); - if (result == 0 && !dd->data.u) { - return AT_READ_FAIL; - } - break; - case TFACTION: - result = - read_reference(&dd->data.f, data, read_faction_reference, - resolve_faction); - if (result == 0 && !dd->data.f) { - return AT_READ_FAIL; - } - break; - case TREGION: - result = - read_reference(&dd->data.r, data, read_region_reference, - RESOLVE_REGION(data->version)); - if (result == 0 && !dd->data.r) { - return AT_READ_FAIL; - } - break; - case TSHIP: - /* return read_ship_reference(&data->data.sh, store); */ - assert(!"not implemented"); - break; - case TNONE: - break; - default: + if (dd->type != TINTEGER) { + log_error("read dict, invalid type %d", n); return AT_READ_FAIL; } + READ_INT(store, &dd->data.i); return AT_READ_DEPR; } static void dict_init(attrib * a) { - dict_data *data; + dict_data *dd; a->data.v = malloc(sizeof(dict_data)); - data = (dict_data *)a->data.v; - data->type = TNONE; + dd = (dict_data *)a->data.v; + dd->type = TNONE; } static void dict_done(attrib * a) { - dict_data *data = (dict_data *)a->data.v; - if (data->type == TSTRING) - free(data->data.str); - free(data->name); + dict_data *dd = (dict_data *)a->data.v; + free(dd->name); free(a->data.v); } static void dict_upgrade(attrib **alist, attrib *abegin) { int n = 0, *keys = 0; - int i = 0, val[4]; + int i = 0, val[8]; attrib *a, *ak = a_find(*alist, &at_keys); if (ak) { keys = (int *)ak->data.v; @@ -162,7 +110,9 @@ static void dict_upgrade(attrib **alist, attrib *abegin) { } else { if (strcmp(dd->name, "embassy_muschel")==0) { - val[i++] = atoi36("mupL"); + val[i * 2] = atoi36("mupL"); + val[i * 2 + 1] = dd->data.i; + ++i; } else { log_error("dict conversion, bad entry %s", dd->name); @@ -170,14 +120,14 @@ static void dict_upgrade(attrib **alist, attrib *abegin) { } if (i == 4) { keys = realloc(keys, sizeof(int) * (n + i + 1)); - memcpy(keys + n + 1, val, sizeof(int)*i); + memcpy(keys + n + 1, val, sizeof(val)); n += i; i = 0; } } if (i > 0) { - keys = realloc(keys, sizeof(int) * (n + i + 1)); - memcpy(keys + n + 1, val, sizeof(int)*i); + keys = realloc(keys, sizeof(int) * (2 * (n + i) + 1)); + memcpy(keys + n*2 + 1, val, sizeof(int)*i*2); if (!ak) { ak = a_add(alist, a_new(&at_keys)); } @@ -190,3 +140,11 @@ attrib_type at_dict = { "object", dict_init, dict_done, NULL, NULL, dict_read, dict_upgrade }; + +void dict_set(attrib * a, const char * name, int value) +{ + dict_data *dd = (dict_data *)a->data.v; + dd->name = strdup(name); + dd->type = TINTEGER; + dd->data.i = value; +} diff --git a/src/attributes/dict.h b/src/attributes/dict.h index 7b028fa00..cc700bb9f 100644 --- a/src/attributes/dict.h +++ b/src/attributes/dict.h @@ -13,18 +13,16 @@ #ifndef H_ATTRIBUTE_OBJECT #define H_ATTRIBUTE_OBJECT -#include +struct attrib_type; +struct attrib; #ifdef __cplusplus extern "C" { #endif - typedef enum { - TNONE = 0, TINTEGER = 1, TREAL = 2, TSTRING = 3, - TUNIT = 10, TFACTION = 11, TREGION = 12, TBUILDING = 13, TSHIP = 14 - } dict_type; + extern struct attrib_type at_dict; // DEPRECATED: at_dict has been replaced with at_keys - extern struct attrib_type at_dict; + void dict_set(struct attrib * a, const char * name, int value); #ifdef __cplusplus } diff --git a/src/attributes/key.c b/src/attributes/key.c index 84bbf7c04..904df32be 100644 --- a/src/attributes/key.c +++ b/src/attributes/key.c @@ -30,8 +30,10 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. static void a_writekeys(const attrib *a, const void *o, storage *store) { int i, *keys = (int *)a->data.v; - for (i = 0; i <= keys[0]; ++i) { - WRITE_INT(store, keys[i]); + WRITE_INT(store, keys[0]); + for (i = 0; i < keys[0]; ++i) { + WRITE_INT(store, keys[i * 2 + 1]); + WRITE_INT(store, keys[i * 2 + 2]); } } @@ -42,10 +44,16 @@ static int a_readkeys(attrib * a, void *owner, gamedata *data) { if (i == 0) { return AT_READ_FAIL; } - a->data.v = p = malloc(sizeof(int)*(i + 1)); + a->data.v = p = malloc(sizeof(int)*(i*2 + 1)); *p++ = i; while (i--) { READ_INT(data->store, p++); + if (data->version >= KEYVAL_VERSION) { + READ_INT(data->store, p++); + } + else { + *p++ = 1; + } } return AT_READ_OK; } @@ -71,24 +79,25 @@ attrib_type at_keys = { static void a_upgradekeys(attrib **alist, attrib *abegin) { int n = 0, *keys = 0; - int i = 0, val[4]; + int i = 0, val[8]; attrib *a, *ak = a_find(*alist, &at_keys); if (ak) { keys = (int *)ak->data.v; if (keys) n = keys[0]; } for (a = abegin; a && a->type == abegin->type; a = a->next) { - val[i++] = a->data.i; - if (i == 4) { - keys = realloc(keys, sizeof(int) * (n + i + 1)); - memcpy(keys + n + 1, val, sizeof(int)*i); + val[i * 2] = a->data.i; + val[i * 2 + 1] = 1; + if (++i == 4) { + keys = realloc(keys, sizeof(int) * (2 * (n + i) + 1)); + memcpy(keys + 2 * n + 1, val, sizeof(val)); n += i; i = 0; } } if (i > 0) { - keys = realloc(keys, sizeof(int) * (n + i + 1)); - memcpy(keys + n + 1, val, sizeof(int)*i); + keys = realloc(keys, sizeof(int) * (2 * (n + i) + 1)); + memcpy(keys + 2 * n + 1, val, sizeof(int)*i*2); if (!ak) { ak = a_add(alist, a_new(&at_keys)); } @@ -107,9 +116,9 @@ attrib_type at_key = { a_upgradekeys }; -void key_set(attrib ** alist, int key) +void key_set(attrib ** alist, int key, int val) { - int *keys, n = 1; + int *keys, n = 0; attrib *a; assert(key != 0); a = a_find(*alist, &at_keys); @@ -118,12 +127,13 @@ void key_set(attrib ** alist, int key) } keys = (int *)a->data.v; if (keys) { - n = keys[0] + 1; + n = keys[0]; } - keys = realloc(keys, sizeof(int) *(n + 1)); - // TODO: does insertion sort pay off here? - keys[0] = n; - keys[n] = key; + keys = realloc(keys, sizeof(int) *(2 * n + 3)); + // TODO: does insertion sort pay off here? prob. not. + keys[0] = n + 1; + keys[2 * n + 1] = key; + keys[2 * n + 2] = val; a->data.v = keys; } @@ -135,29 +145,31 @@ void key_unset(attrib ** alist, int key) if (a) { int i, *keys = (int *)a->data.v; if (keys) { - for (i = 1; i <= keys[0]; ++i) { - if (keys[i] == key) { - keys[i] = keys[keys[0]]; + int n = keys[0]; + for (i = 0; i != n; ++i) { + if (keys[2 * i + 1] == key) { + memmove(keys + 2 * i + 1, keys + 2 * n - 1, 2 * sizeof(int)); keys[0]--; + break; } } } } } -bool key_get(attrib *alist, int key) { +int key_get(attrib *alist, int key) { attrib *a; assert(key != 0); a = a_find(alist, &at_keys); if (a) { int i, *keys = (int *)a->data.v; if (keys) { - for (i = 1; i <= keys[0]; ++i) { - if (keys[i] == key) { - return true; + for (i = 0; i != keys[0]; ++i) { + if (keys[i*2+1] == key) { + return keys[i * 2 + 2]; } } } } - return false; + return 0; } diff --git a/src/attributes/key.h b/src/attributes/key.h index d2cea1ff0..81511d248 100644 --- a/src/attributes/key.h +++ b/src/attributes/key.h @@ -26,12 +26,12 @@ extern "C" { #endif struct attrib; struct attrib_type; - extern struct attrib_type at_key; + extern struct attrib_type at_key; // DEPRECATED: at_key has been replaced with at_keys extern struct attrib_type at_keys; - void key_set(struct attrib **alist, int key); + void key_set(struct attrib **alist, int key, int value); void key_unset(struct attrib **alist, int key); - bool key_get(struct attrib *alist, int key); + int key_get(struct attrib *alist, int key); #ifdef __cplusplus } diff --git a/src/attributes/key.test.c b/src/attributes/key.test.c index 2b7632917..b816e1d86 100644 --- a/src/attributes/key.test.c +++ b/src/attributes/key.test.c @@ -1,22 +1,24 @@ #include #include "key.h" +#include "dict.h" #include +#include #include #include static void test_get_set_keys(CuTest *tc) { attrib *a = 0; - key_set(&a, 42); - key_set(&a, 43); - key_set(&a, 44); - CuAssertTrue(tc, key_get(a, 42)); - CuAssertTrue(tc, key_get(a, 43)); - CuAssertTrue(tc, key_get(a, 44)); + key_set(&a, 42, 1); + key_set(&a, 43, 2); + key_set(&a, 44, 3); + CuAssertIntEquals(tc, 1, key_get(a, 42)); + CuAssertIntEquals(tc, 2, key_get(a, 43)); + CuAssertIntEquals(tc, 3, key_get(a, 44)); key_unset(&a, 42); - CuAssertTrue(tc, !key_get(a, 42)); - CuAssertTrue(tc, key_get(a, 43)); - CuAssertTrue(tc, key_get(a, 44)); + CuAssertIntEquals(tc, 0, key_get(a, 42)); + CuAssertIntEquals(tc, 2, key_get(a, 43)); + CuAssertIntEquals(tc, 3, key_get(a, 44)); a_removeall(&a, NULL); } @@ -26,7 +28,7 @@ static attrib *key_set_orig(attrib **alist, int key) { return a; } -static void test_upgrade(CuTest *tc) { +static void test_upgrade_key(CuTest *tc) { attrib *alist = 0; key_set_orig(&alist, 40); key_set_orig(&alist, 41); @@ -35,18 +37,31 @@ static void test_upgrade(CuTest *tc) { key_set_orig(&alist, 44); CuAssertPtrNotNull(tc, alist->type->upgrade); alist->type->upgrade(&alist, alist); - CuAssertTrue(tc, key_get(alist, 40)); - CuAssertTrue(tc, key_get(alist, 41)); - CuAssertTrue(tc, key_get(alist, 42)); - CuAssertTrue(tc, key_get(alist, 43)); - CuAssertTrue(tc, key_get(alist, 44)); + CuAssertIntEquals(tc, 1, key_get(alist, 40)); + CuAssertIntEquals(tc, 1, key_get(alist, 41)); + CuAssertIntEquals(tc, 1, key_get(alist, 42)); + CuAssertIntEquals(tc, 1, key_get(alist, 43)); + CuAssertIntEquals(tc, 1, key_get(alist, 44)); a_removeall(&alist, NULL); } +static void test_upgrade_dict(CuTest *tc) { + attrib *a; + + a = a_new(&at_dict); + + dict_set(a, "embassy_muschel", 42); + CuAssertPtrNotNull(tc, a->type->upgrade); + a->type->upgrade(&a, a); + CuAssertIntEquals(tc, 42, key_get(a, atoi36("mupL"))); + a_removeall(&a, NULL); +} + CuSuite *get_key_suite(void) { CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_get_set_keys); - SUITE_ADD_TEST(suite, test_upgrade); + SUITE_ADD_TEST(suite, test_upgrade_key); + SUITE_ADD_TEST(suite, test_upgrade_dict); return suite; } diff --git a/src/bind_faction.c b/src/bind_faction.c index 749bb65f6..371481fcb 100644 --- a/src/bind_faction.c +++ b/src/bind_faction.c @@ -248,7 +248,7 @@ static int tolua_faction_getkey(lua_State * L) const char *name = tolua_tostring(L, 2, 0); int flag = atoi36(name); - lua_pushboolean(L, key_get(self->attribs, flag)); + lua_pushinteger(L, key_get(self->attribs, flag)); return 1; } @@ -256,11 +256,11 @@ static int tolua_faction_setkey(lua_State * L) { faction *self = (faction *)tolua_tousertype(L, 1, 0); const char *name = tolua_tostring(L, 2, 0); - int value = tolua_toboolean(L, 3, 0); + int value = (int)tolua_tonumber(L, 3, 0); int flag = atoi36(name); if (value) { - key_set(&self->attribs, flag); + key_set(&self->attribs, flag, value); } else { key_unset(&self->attribs, flag); diff --git a/src/bind_region.c b/src/bind_region.c index d9956c8b6..51a5bedd4 100644 --- a/src/bind_region.c +++ b/src/bind_region.c @@ -544,11 +544,11 @@ static int tolua_region_setkey(lua_State * L) { region *self = (region *)tolua_tousertype(L, 1, 0); const char *name = tolua_tostring(L, 2, 0); - int value = tolua_toboolean(L, 3, 0); + int value = (int)tolua_tonumber(L, 3, 0); int flag = atoi36(name); if (value) { - key_set(&self->attribs, flag); + key_set(&self->attribs, flag, value); } else { key_unset(&self->attribs, flag); diff --git a/src/bind_unit.c b/src/bind_unit.c index c0939b5cf..a9d413bf0 100755 --- a/src/bind_unit.c +++ b/src/bind_unit.c @@ -786,7 +786,7 @@ static int tolua_unit_set_flag(lua_State * L) int value = (int)tolua_tonumber(L, 3, 0); int flag = atoi36(name); if (value) { - key_set(&self->attribs, flag); + key_set(&self->attribs, flag, value); } else { key_unset(&self->attribs, flag); diff --git a/src/bindings.c b/src/bindings.c index 21f2aad58..531b68618 100755 --- a/src/bindings.c +++ b/src/bindings.c @@ -206,10 +206,10 @@ static int tolua_translate(lua_State * L) static int tolua_setkey(lua_State * L) { const char *name = tolua_tostring(L, 1, 0); - int value = tolua_toboolean(L, 2, 0); + int value = (int)tolua_tonumber(L, 3, 0); int flag = atoi36(name); if (value) { - key_set(&global.attribs, flag); + key_set(&global.attribs, flag, value); } else { key_unset(&global.attribs, flag); diff --git a/src/kernel/group.test.c b/src/kernel/group.test.c index 78ee6b24f..e95458114 100644 --- a/src/kernel/group.test.c +++ b/src/kernel/group.test.c @@ -84,7 +84,7 @@ static void test_group_readwrite(CuTest * tc) f = test_create_faction(0); new_group(f, "NW", 42); g = new_group(f, "Egoisten", 43); - key_set(&g->attribs, 44); + key_set(&g->attribs, 44, 44); al = ally_add(&g->allies, f); al->status = HELP_GIVE; write_groups(&store, f); @@ -108,7 +108,7 @@ static void test_group_readwrite(CuTest * tc) CuAssertStrEquals(tc, "Egoisten", f->groups->next->name); CuAssertPtrEquals(tc, 0, f->groups->allies); g = f->groups->next; - CuAssertTrue(tc, key_get(g->attribs, 44)); + CuAssertIntEquals(tc, 44, key_get(g->attribs, 44)); CuAssertPtrNotNull(tc, g->allies); CuAssertPtrEquals(tc, 0, g->allies->next); CuAssertPtrEquals(tc, f, g->allies->faction); diff --git a/src/kernel/item.c b/src/kernel/item.c index 34a0e1875..9327700cd 100644 --- a/src/kernel/item.c +++ b/src/kernel/item.c @@ -939,7 +939,7 @@ struct order *ord) use_pooled(user, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, user->number); - key_set(&f->attribs, atoi36("mbst")); + key_set(&f->attribs, atoi36("mbst"), turn); set_level(user, SK_MAGIC, 3); ADDMSG(&user->faction->msgs, msg_message("use_item", diff --git a/src/kernel/save.test.c b/src/kernel/save.test.c index c05ce4455..70bcb2e65 100644 --- a/src/kernel/save.test.c +++ b/src/kernel/save.test.c @@ -211,8 +211,8 @@ static void test_readwrite_attrib(CuTest *tc) { attrib *a = NULL; test_setup(); - key_set(&a, 41); - key_set(&a, 42); + key_set(&a, 41, 42); + key_set(&a, 42, 43); mstream_init(&data.strm); gamedata_init(&data, &store, RELEASE_VERSION); write_attribs(data.store, a, NULL); @@ -223,8 +223,8 @@ static void test_readwrite_attrib(CuTest *tc) { read_attribs(&data, &a, NULL); mstream_done(&data.strm); gamedata_done(&data); - CuAssertTrue(tc, key_get(a, 41)); - CuAssertTrue(tc, key_get(a, 42)); + CuAssertIntEquals(tc, 42, key_get(a, 41)); + CuAssertIntEquals(tc, 43, key_get(a, 42)); a_removeall(&a, NULL); test_cleanup(); diff --git a/src/util/gamedata.h b/src/util/gamedata.h index bb1632838..75a750452 100644 --- a/src/util/gamedata.h +++ b/src/util/gamedata.h @@ -32,10 +32,11 @@ #define NOCRYPT_VERSION 352 /* passwords are plaintext again */ #define ATHASH_VERSION 353 /* attribute-type hash, not name */ #define NOWATCH_VERSION 354 /* plane->watchers is gone */ +#define KEYVAL_VERSION 355 /* at_keys has values */ /* unfinished: */ #define CRYPT_VERSION 400 /* passwords are encrypted */ -#define RELEASE_VERSION NOWATCH_VERSION /* current datafile */ +#define RELEASE_VERSION KEYVAL_VERSION /* current datafile */ #define MIN_VERSION INTPAK_VERSION /* minimal datafile we support */ #define MAX_VERSION RELEASE_VERSION /* change this if we can need to read the future datafile, and we can do so */ From aa230cc191b85dbcf40051bb0093e09046b5b6f4 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 14 Feb 2017 12:15:36 +0100 Subject: [PATCH 2/7] fix coverity warnings --- src/attributes/key.c | 8 ++++++-- src/kernel/version.c | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/attributes/key.c b/src/attributes/key.c index 904df32be..8b09fdd1c 100644 --- a/src/attributes/key.c +++ b/src/attributes/key.c @@ -102,8 +102,12 @@ static void a_upgradekeys(attrib **alist, attrib *abegin) { ak = a_add(alist, a_new(&at_keys)); } } - ak->data.v = keys; - keys[0] = n + i; + if (ak) { + ak->data.v = keys; + if (keys) { + keys[0] = n + i; + } + } } attrib_type at_key = { diff --git a/src/kernel/version.c b/src/kernel/version.c index 7e8ed01d7..8cf6a372e 100644 --- a/src/kernel/version.c +++ b/src/kernel/version.c @@ -11,8 +11,9 @@ const char *eressea_version(void) { #ifdef ERESSEA_BUILDNO return ERESSEA_VERSION "-" ERESSEA_BUILDNO; -#endif +#else return ERESSEA_VERSION; +#endif } int version_no(const char *str) { From 08e14f3095c6feb62821dd3101d4b13bf6f503c9 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 14 Feb 2017 16:23:40 +0100 Subject: [PATCH 3/7] coverity warnings --- src/attributes/dict.c | 8 ++++++-- src/economy.c | 8 ++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/attributes/dict.c b/src/attributes/dict.c index ad66e3676..36d017b2c 100644 --- a/src/attributes/dict.c +++ b/src/attributes/dict.c @@ -132,8 +132,12 @@ static void dict_upgrade(attrib **alist, attrib *abegin) { ak = a_add(alist, a_new(&at_keys)); } } - ak->data.v = keys; - keys[0] = n + i; + if (ak) { + ak->data.v = keys; + if (keys) { + keys[0] = n + i; + } + } } attrib_type at_dict = { diff --git a/src/economy.c b/src/economy.c index dcbc7431e..dec4517a4 100644 --- a/src/economy.c +++ b/src/economy.c @@ -2707,7 +2707,7 @@ static void expandloot(region * r, request * lootorders) { unit *u; unsigned int i; - int looted = 0; + int m, looted = 0; int startmoney = rmoney(r); expandorders(r, lootorders); @@ -2724,9 +2724,9 @@ static void expandloot(region * r, request * lootorders) free(g_requests); /* Lowering morale by 1 depending on the looted money (+20%) */ - if (rng_int() % 100 < 20 + (looted * 80) / startmoney) { - int m = region_get_morale(r); - if (m) { + m = region_get_morale(r); + if (m && startmoney>0) { + if (rng_int() % 100 < 20 + (looted * 80) / startmoney) { /*Nur Moral -1, turns is not changed, so the first time nothing happens if the morale is good*/ region_set_morale(r, m - 1, -1); } From 623137e872f3bec0f824ff40cdb51914681074bd Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 14 Feb 2017 19:57:31 +0100 Subject: [PATCH 4/7] test guardhouse level limits. --- scripts/tests/e3/castles.lua | 52 +++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/scripts/tests/e3/castles.lua b/scripts/tests/e3/castles.lua index df395ed3d..eafc58b51 100644 --- a/scripts/tests/e3/castles.lua +++ b/scripts/tests/e3/castles.lua @@ -11,30 +11,40 @@ function teardown() eressea.settings.set("rules.food.flags", "0") end +function test_watch() + local r = region.create(0, 0, "plain") + local b = building.create(r, "watch") + + assert_equal("scaffolding", b:get_typename(1)) + assert_equal("scaffolding", b:get_typename(4)) + assert_equal("guardhouse", b:get_typename(5)) + assert_equal("guardhouse", b:get_typename(9)) + assert_equal("guardtower", b:get_typename(10)) +end + function test_small_castles() - local r = region.create(0, 0, "plain") - local f1 = faction.create("noreply@eressea.de", "human", "de") - local u1 = unit.create(f1, r, 1) - local f2 = faction.create("noreply@eressea.de", "halfling", "de") - local u2 = unit.create(f2, r, 1) - u1:add_item("money", 10000) + local r = region.create(0, 0, "plain") + local f1 = faction.create("noreply@eressea.de", "human", "de") + local u1 = unit.create(f1, r, 1) + local f2 = faction.create("noreply@eressea.de", "halfling", "de") + local u2 = unit.create(f2, r, 1) - local b = building.create(r, "castle") - u2.building = b - u1.building = b + local b = building.create(r, "castle") + u2.building = b + u1.building = b - b.owner = u2 - assert_equal("site", b:get_typename(7)) - assert_equal("fortification", b:get_typename(8)) - b.owner = u1 - assert_equal("site", b:get_typename(9)) - assert_equal("fortification", b:get_typename(10)) + b.owner = u2 + assert_equal("site", b:get_typename(7)) + assert_equal("fortification", b:get_typename(8)) + b.owner = u1 + assert_equal("site", b:get_typename(9)) + assert_equal("fortification", b:get_typename(10)) end function test_build_normal() - local r = region.create(0, 0, "plain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, r, 1) + local r = region.create(0, 0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u = unit.create(f, r, 1) u:clear_orders() u:add_item("stone", 10) u:set_skill("building", 10) @@ -45,9 +55,9 @@ function test_build_normal() end function test_build_packice() - local r = region.create(0, 0, "packice") - local f = faction.create("packice@eressea.de", "human", "de") - local u = unit.create(f, r, 1) + local r = region.create(0, 0, "packice") + local f = faction.create("packice@eressea.de", "human", "de") + local u = unit.create(f, r, 1) u:clear_orders() u:add_item("stone", 10) u:set_skill("building", 10) From 1dcb21b08cffe1be5170c0ac4fa77747dfaa686e Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 14 Feb 2017 20:30:24 +0100 Subject: [PATCH 5/7] bug 2281: add a failing test https://bugs.eressea.de/view.php?id=2281 --- scripts/tests/e3/castles.lua | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/scripts/tests/e3/castles.lua b/scripts/tests/e3/castles.lua index eafc58b51..b16019159 100644 --- a/scripts/tests/e3/castles.lua +++ b/scripts/tests/e3/castles.lua @@ -11,6 +11,28 @@ function teardown() eressea.settings.set("rules.food.flags", "0") end +function test_build_watch() + local r = region.create(0, 0, "plain") + local f = faction.create("e3build@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + + u.number = 20 + u:add_item("log", 20) + u.id = 42 + + u:set_skill("building", 1) + u:add_order("MACHE Wache") + process_orders() + assert_not_nil(u.building) + assert_equal(5, u.building.size) + + u:set_skill("building", 2) + u:add_order("MACHE Wache " .. itoa36(u.building.id)) + process_orders() + assert_not_nil(u.building) + assert_equal(10, u.building.size) +end + function test_watch() local r = region.create(0, 0, "plain") local b = building.create(r, "watch") From 4ce415be5099ef93f20c9634d1c396a7effa8e5e Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 14 Feb 2017 20:51:03 +0100 Subject: [PATCH 6/7] BUG 2281: fix maxsize of guard towers. --- res/e3a/buildings.xml | 2 +- src/kernel/build.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/res/e3a/buildings.xml b/res/e3a/buildings.xml index c1edbcc0b..f65654e2f 100644 --- a/res/e3a/buildings.xml +++ b/res/e3a/buildings.xml @@ -3,7 +3,7 @@ - + diff --git a/src/kernel/build.c b/src/kernel/build.c index dff51cf6c..6b23723e8 100644 --- a/src/kernel/build.c +++ b/src/kernel/build.c @@ -595,7 +595,7 @@ int build(unit * u, const construction * ctype, int completed, int want) else break; } - if (type->materials) + if (type->materials) { for (c = 0; type->materials[c].number; c++) { const struct resource_type *rtype = type->materials[c].rtype; int prebuilt = @@ -620,6 +620,7 @@ int build(unit * u, const construction * ctype, int completed, int want) use_pooled(u, rtype, GET_DEFAULT, (need - prebuilt + multi - 1) / multi); } + } made += n; skills -= n * type->minskill; want -= n; From 794710189940fec22b1a02ccef5a36681f56cdfd Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 14 Feb 2017 21:01:22 +0100 Subject: [PATCH 7/7] factor out some function to make future debugging easier. --- src/kernel/build.c | 131 ++++++++++++++++++++++++++------------------- 1 file changed, 75 insertions(+), 56 deletions(-) diff --git a/src/kernel/build.c b/src/kernel/build.c index 6b23723e8..78bcd6b8f 100644 --- a/src/kernel/build.c +++ b/src/kernel/build.c @@ -428,6 +428,76 @@ int roqf_factor(void) return value; } +static int use_materials(unit *u, const construction *type, int n, int completed) { + if (type->materials) { + int c; + for (c = 0; type->materials[c].number; c++) { + const struct resource_type *rtype = type->materials[c].rtype; + int prebuilt = + required(completed, type->reqsize, type->materials[c].number); + int need = + required(completed + n, type->reqsize, type->materials[c].number); + int multi = 1; + int canuse = 100; /* normalization */ + if (building_is_active(u->building) && inside_building(u)) { + canuse = matmod(u->building->type->attribs, u, rtype, canuse); + } + if (canuse < 0) { + return canuse; /* pass errors to caller */ + } + canuse = matmod(type->attribs, u, rtype, canuse); + + assert(canuse % 100 == 0 + || !"only constant multipliers are implemented in build()"); + multi = canuse / 100; + if (canuse < 0) { + return canuse; /* pass errors to caller */ + } + use_pooled(u, rtype, GET_DEFAULT, + (need - prebuilt + multi - 1) / multi); + } + } + return 0; +} + +static int count_materials(unit *u, const construction *type, int n, int completed) +{ + if (type->materials) { + int c; + for (c = 0; n > 0 && type->materials[c].number; c++) { + const struct resource_type *rtype = type->materials[c].rtype; + int need, prebuilt; + int canuse = get_pooled(u, rtype, GET_DEFAULT, INT_MAX); + + if (building_is_active(u->building) && inside_building(u)) { + canuse = matmod(u->building->type->attribs, u, rtype, canuse); + } + + if (canuse < 0) + return canuse; /* pass errors to caller */ + canuse = matmod(type->attribs, u, rtype, canuse); + if (type->reqsize > 1) { + prebuilt = + required(completed, type->reqsize, type->materials[c].number); + for (; n;) { + need = + required(completed + n, type->reqsize, type->materials[c].number); + if (need - prebuilt <= canuse) + break; + --n; /* TODO: optimieren? */ + } + } + else { + int maxn = canuse / type->materials[c].number; + if (maxn < n) { + n = maxn; + } + } + } + } + return n; +} + /** Use up resources for building an object. * Build up to 'size' points of 'type', where 'completed' * of the first object have already been finished. return the @@ -492,7 +562,7 @@ int build(unit * u, const construction * ctype, int completed, int want) } } for (; want > 0 && skills > 0;) { - int c, n; + int err, n; /* skip over everything that's already been done: * type->improvement==NULL means no more improvements, but no size limits @@ -559,67 +629,16 @@ int build(unit * u, const construction * ctype, int completed, int want) } } - if (type->materials) - for (c = 0; n > 0 && type->materials[c].number; c++) { - const struct resource_type *rtype = type->materials[c].rtype; - int need, prebuilt; - int canuse = get_pooled(u, rtype, GET_DEFAULT, INT_MAX); - - if (building_is_active(u->building) && inside_building(u)) { - canuse = matmod(u->building->type->attribs, u, rtype, canuse); - } - - if (canuse < 0) - return canuse; /* pass errors to caller */ - canuse = matmod(type->attribs, u, rtype, canuse); - if (type->reqsize > 1) { - prebuilt = - required(completed, type->reqsize, type->materials[c].number); - for (; n;) { - need = - required(completed + n, type->reqsize, type->materials[c].number); - if (need - prebuilt <= canuse) - break; - --n; /* TODO: optimieren? */ - } - } - else { - int maxn = canuse / type->materials[c].number; - if (maxn < n) - n = maxn; - } - } + n = count_materials(u, type, n, completed); if (n <= 0) { if (made == 0) return ENOMATERIALS; else break; } - if (type->materials) { - for (c = 0; type->materials[c].number; c++) { - const struct resource_type *rtype = type->materials[c].rtype; - int prebuilt = - required(completed, type->reqsize, type->materials[c].number); - int need = - required(completed + n, type->reqsize, type->materials[c].number); - int multi = 1; - int canuse = 100; /* normalization */ - if (building_is_active(u->building) && inside_building(u)) { - canuse = matmod(u->building->type->attribs, u, rtype, canuse); - } - if (canuse < 0) - return canuse; /* pass errors to caller */ - canuse = matmod(type->attribs, u, rtype, canuse); - - assert(canuse % 100 == 0 - || !"only constant multipliers are implemented in build()"); - multi = canuse / 100; - if (canuse < 0) - return canuse; /* pass errors to caller */ - - use_pooled(u, rtype, GET_DEFAULT, - (need - prebuilt + multi - 1) / multi); - } + err = use_materials(u, type, n, completed); + if (err < 0) { + return err; } made += n; skills -= n * type->minskill;