From acb1de2eefa9b3a0ff1c89a51a74373bfa2d6a94 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 28 Feb 2019 10:32:08 +0100 Subject: [PATCH 01/56] do not fail on malformed passwords --- process/epasswd.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/process/epasswd.py b/process/epasswd.py index 20109b9ba..496eb8331 100755 --- a/process/epasswd.py +++ b/process/epasswd.py @@ -69,7 +69,12 @@ class EPasswd: def check(self, id, passwd): pw = self.get_passwd(id) if pw[0:4]=='$2a$' or pw[0:4]=='$2y$': - return bcrypt.checkpw(passwd.encode('utf8'), pw.encode('utf8')) + try: + h1 = pw.encode('utf8') + h2 = passwd.encode('utf8') + return bcrypt.checkpw(h1, h2) + except: + return False return pw == passwd def get_passwd(self, id): From 5dd12df1007d75b5cd196dd7770ddf2bbe7378f2 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 2 Mar 2019 05:03:43 +0100 Subject: [PATCH 02/56] BUG 2564: show new spells. --- src/laws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/laws.c b/src/laws.c index 521ff92ab..f7eba8c97 100644 --- a/src/laws.c +++ b/src/laws.c @@ -3205,7 +3205,7 @@ static int faction_getmages(faction * f, unit ** results, int numresults) for (u = f->units; u; u = u->nextF) { if (u->number > 0) { struct sc_mage * mage = get_mage(u); - if (mage && mage_get_spellbook(mage)) { + if (mage) { int level = effskill(u, SK_MAGIC, NULL); if (level > maxlevel) { maxlevel = level; From 8253d8f8335c62575fb306bcfca8d8d422ee8663 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 3 Mar 2019 09:23:07 +0100 Subject: [PATCH 03/56] new players should have lastorders = 0, get password. --- src/kernel/faction.c | 2 +- src/reports.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/kernel/faction.c b/src/kernel/faction.c index b595bd902..fc1de186a 100755 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -299,7 +299,7 @@ unit *addplayer(region * r, faction * f) } while (rc == NULL || urc == RC_DAEMON || !playerrace(rc)); u->irace = rc; } - + f->lastorders = 0; return u; } diff --git a/src/reports.c b/src/reports.c index 6827e7897..056ee8dd0 100644 --- a/src/reports.c +++ b/src/reports.c @@ -1603,7 +1603,9 @@ int write_reports(faction * f) if (noreports) { return false; } - if (f->lastorders == 0) { + if (f->lastorders == 0 || f->age <= 1) { + /* neue Parteien, oder solche die noch NIE einen Zug gemacht haben, + * kriegen ein neues Passwort: */ password = faction_genpassword(f, buffer); } prepare_report(&ctx, f, password); From 9f3f9d7c569265a3ffa41a78a5314631323ec361 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 3 Mar 2019 09:37:00 +0100 Subject: [PATCH 04/56] fix the new password test --- src/reports.test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/reports.test.c b/src/reports.test.c index aeeb0ff58..7bea6c73c 100644 --- a/src/reports.test.c +++ b/src/reports.test.c @@ -963,6 +963,7 @@ static void test_reports_genpassword(CuTest *tc) { CuAssertTrue(tc, f->password_id != 0); test_clear_messagelist(&f->msgs); f->lastorders = 1; + f->age = 2; pwid = f->password_id; write_reports(f); CuAssertIntEquals(tc, pwid, f->password_id); From 2a0688d1b483d836e841b11a4cec302b24cc0191 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 3 Mar 2019 13:12:37 +0100 Subject: [PATCH 05/56] re-enable undead check, I think it is fixed. --- scripts/tests/e2/undead.lua | 1 - src/reports.c | 2 -- 2 files changed, 3 deletions(-) diff --git a/scripts/tests/e2/undead.lua b/scripts/tests/e2/undead.lua index 28d2c20c1..ee487cea2 100644 --- a/scripts/tests/e2/undead.lua +++ b/scripts/tests/e2/undead.lua @@ -31,7 +31,6 @@ function test_undead_reserve_other() u1.name = 'Xolgrim' process_orders() - -- Intermittent Failure: expected 0 but was 2 assert_equal(0, u1:get_item("log")) assert_equal(2, u2:get_item("log")) diff --git a/src/reports.c b/src/reports.c index 056ee8dd0..4b950b73b 100644 --- a/src/reports.c +++ b/src/reports.c @@ -144,8 +144,6 @@ bool omniscient(const faction *f) return (f->race == rc_template); } - - static char *groupid(const struct group *g, const struct faction *f) { typedef char name[OBJECTIDSIZE + 1]; From 8cc38420f0ec93fc63145c9529f855e7af6dfc5b Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 17 Feb 2019 15:34:14 +0100 Subject: [PATCH 06/56] missing nul-termination triggers valgrind. --- src/json.test.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/json.test.c b/src/json.test.c index 30d4e072e..ec814eec6 100644 --- a/src/json.test.c +++ b/src/json.test.c @@ -58,6 +58,7 @@ static cJSON *export_a_region(CuTest * tc, const struct terrain_type *terrain, r int err; region *r; cJSON *json, *attr, *result, *regs; + size_t sz; r = test_create_region(0, 0, terrain); @@ -65,7 +66,8 @@ static cJSON *export_a_region(CuTest * tc, const struct terrain_type *terrain, r err = json_export(&out, EXPORT_REGIONS); CuAssertIntEquals(tc, 0, err); out.api->rewind(out.handle); - out.api->read(out.handle, buf, sizeof(buf)); + sz = out.api->read(out.handle, buf, sizeof(buf)); + buf[sz] = '\0'; mstream_done(&out); json = cJSON_Parse(buf); From 6a286db0f08f75188c02445b4788c33ed07a7ac2 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 17 Feb 2019 15:16:07 +0100 Subject: [PATCH 07/56] upgrade to cJSON 1.7.10 --- cJSON | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cJSON b/cJSON index 22a4fc9be..26e64b820 160000 --- a/cJSON +++ b/cJSON @@ -1 +1 @@ -Subproject commit 22a4fc9be31f0426e622f5bc9ebd7a1550845001 +Subproject commit 26e64b8207b30bf9f8389b33f68d46d9dea6f9d8 From ef81a20c6e783a59ab7841ed8781b4f55bed12b5 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 11 Mar 2019 21:32:59 +0100 Subject: [PATCH 08/56] 2565 Leerzeile nach Helfe-Status. Helfestatus an das Ende des Reports. --- cJSON | 2 +- src/report.c | 35 ++++++++++++++++------------------- src/report.test.c | 4 ++-- 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/cJSON b/cJSON index 22a4fc9be..8df81fb49 160000 --- a/cJSON +++ b/cJSON @@ -1 +1 @@ -Subproject commit 22a4fc9be31f0426e622f5bc9ebd7a1550845001 +Subproject commit 8df81fb497cc48b089a57fcdc3a9933540ebc7c9 diff --git a/src/report.c b/src/report.c index 7ea25c8d6..65c13492f 100644 --- a/src/report.c +++ b/src/report.c @@ -1545,7 +1545,7 @@ static int show_allies_cb(struct allies *all, faction *af, int status, void *uda } } if (show->num_allies == show->num_listed) { - sbs_strcat(sbp, ")."); + sbs_strcat(sbp, ").\n"); pump_paragraph(sbp, show->out, show->maxlen, true); } else { @@ -1577,11 +1577,24 @@ void report_allies(struct stream *out, size_t maxlen, const struct faction * f, } } +static void rpline(struct stream *out) +{ + static char line[REPORTWIDTH + 1]; + if (line[0] != '-') { + memset(line, '-', sizeof(line)); + line[REPORTWIDTH] = '\n'; + } + swrite(line, sizeof(line), 1, out); +} + static void allies(struct stream *out, const faction * f) { const group *g = f->groups; char prefix[64]; + centre(out, LOC(f->locale, "nr_alliances"), false); + newline(out); + if (f->allies) { snprintf(prefix, sizeof(prefix), "%s ", LOC(f->locale, "faction_help")); report_allies(out, REPORTWIDTH, f, f->allies, prefix); @@ -1594,6 +1607,7 @@ static void allies(struct stream *out, const faction * f) } g = g->next; } + rpline(out); } static void guards(struct stream *out, const region * r, const faction * see) @@ -1660,16 +1674,6 @@ static void guards(struct stream *out, const region * r, const faction * see) } } -static void rpline(struct stream *out) -{ - static char line[REPORTWIDTH + 1]; - if (line[0] != '-') { - memset(line, '-', sizeof(line)); - line[REPORTWIDTH] = '\n'; - } - swrite(line, sizeof(line), 1, out); -} - static void list_address(struct stream *out, const faction * uf, selist * seenfactions) { int qi = 0; @@ -2114,14 +2118,6 @@ report_plaintext(const char *filename, report_context * ctx, } } newline(out); - ERRNO_CHECK(); - centre(out, LOC(f->locale, "nr_alliances"), false); - newline(out); - - allies(out, f); - - rpline(out); - ERRNO_CHECK(); anyunits = 0; @@ -2249,6 +2245,7 @@ report_plaintext(const char *filename, report_context * ctx, paragraph(out, LOC(f->locale, "nr_youaredead"), 0, 2, 0); } else { + allies(out, f); list_address(out, f, ctx->addresses); } } diff --git a/src/report.test.c b/src/report.test.c index 59148d3a2..b6696ea1b 100644 --- a/src/report.test.c +++ b/src/report.test.c @@ -192,7 +192,7 @@ static void test_report_allies(CuTest *tc) { f1 = test_create_faction(NULL); f2 = test_create_faction(NULL); f3 = test_create_faction(NULL); - snprintf(exp, sizeof(exp), "Wir helfen %s (%s).\n", + snprintf(exp, sizeof(exp), "Wir helfen %s (%s).\n\n", factionname(f1), LOC(lang, parameters[P_GUARD])); ally_set(&f->allies, f1, HELP_GUARD); @@ -211,7 +211,7 @@ static void test_report_allies(CuTest *tc) { factionname(f2), LOC(lang, parameters[P_GIVE])); linebreak = strlen(exp); - snprintf(exp, sizeof(exp), "Wir helfen %s (%s), %s (%s)\nund %s (%s).\n", + snprintf(exp, sizeof(exp), "Wir helfen %s (%s), %s (%s)\nund %s (%s).\n\n", factionname(f1), LOC(lang, parameters[P_GUARD]), factionname(f2), From d1fbd924e0ce06120105b80a617e3cd0334b9249 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 18 Mar 2019 10:36:33 +0100 Subject: [PATCH 09/56] increase version number --- src/kernel/version.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kernel/version.c b/src/kernel/version.c index 1f8f7e0a7..adbb78e18 100644 --- a/src/kernel/version.c +++ b/src/kernel/version.c @@ -8,7 +8,7 @@ #ifndef ERESSEA_VERSION /* the version number, if it was not passed to make with -D */ -#define ERESSEA_VERSION "3.19.0" +#define ERESSEA_VERSION "3.20.0" #endif const char *eressea_version(void) { From 7c64ec5612e643d9a3b7fc9e2f3897d91362f1d8 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 24 Mar 2019 18:05:40 +0100 Subject: [PATCH 10/56] test debugging --- scripts/tests/e2/undead.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/tests/e2/undead.lua b/scripts/tests/e2/undead.lua index c6122657f..b836b17f8 100644 --- a/scripts/tests/e2/undead.lua +++ b/scripts/tests/e2/undead.lua @@ -32,6 +32,10 @@ function test_undead_reserve_other() process_orders() assert_equal(0, u1:get_item("log")) + if 2 ~= u2:get_item("log") then + -- try to catch that intermittent bug: + print(u2:show()) + end assert_equal(2, u2:get_item("log")) end From 53662878aa0988fc2dc1c370886c125369a968cf Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 31 Mar 2019 10:19:02 +0200 Subject: [PATCH 11/56] minor cleanup --- src/kernel/gamedata.h | 2 -- src/kernel/save.c | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/kernel/gamedata.h b/src/kernel/gamedata.h index e14c0a551..b4c3e4a5f 100644 --- a/src/kernel/gamedata.h +++ b/src/kernel/gamedata.h @@ -63,6 +63,4 @@ void gamedata_close(gamedata *data); gamedata *gamedata_open(const char *filename, const char *mode, int version); int gamedata_openfile(gamedata *data, const char *filename, const char *mode, int version); -#define STREAM_VERSION 2 /* internal encoding of binary files */ - #endif diff --git a/src/kernel/save.c b/src/kernel/save.c index 45da22a7c..b1e518c9f 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -613,6 +613,26 @@ static void read_regioninfo(gamedata *data, const region *r, char *info, size_t } } +static void fix_baselevel(region *r) { + struct terrain_production *p; + for (p = r->terrain->production; p->type; ++p) { + char *end; + long start = (int)strtol(p->startlevel, &end, 10); + if (*end == '\0') { + rawmaterial *res; + for (res = r->resources; res; res = res->next) { + if (p->type == res->rtype) { + if (start != res->startlevel) { + log_debug("setting resource start level for %s in %s to %d", + res->rtype->_name, regionname(r, NULL), start); + res->startlevel = start; + } + } + } + } + } +} + static region *readregion(gamedata *data, int x, int y) { region *r; From b48b69bc943c42ab5b96b2a0d4ae14709a2ac190 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 3 Apr 2019 18:27:29 +0200 Subject: [PATCH 12/56] Let's apply the relaxed E3 hunger rules to E2. --- conf/e2/config.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/conf/e2/config.json b/conf/e2/config.json index 4da247263..cc480b2e2 100644 --- a/conf/e2/config.json +++ b/conf/e2/config.json @@ -41,7 +41,8 @@ "nmr.timeout": 5, "nmr.removenewbie": false, "GiveRestriction": 3, - "hunger.long": true, + "hunger.long": false, + "hunger.damage": "1d9+9", "init_spells": 0, "game.era": 2, "game.start": 184, From df746dd342904e7c1db693803b66cf663d5a53c1 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 5 Apr 2019 17:14:28 +0200 Subject: [PATCH 13/56] Newbie islands should not have volcano terrain. --- src/bind_gmtool.c | 2 +- src/gmtool.c | 2 +- src/modules/autoseed.c | 36 +++++++++++++++++------------------- src/modules/autoseed.h | 4 +--- 4 files changed, 20 insertions(+), 24 deletions(-) diff --git a/src/bind_gmtool.c b/src/bind_gmtool.c index d0a023a5b..5901ccf1d 100644 --- a/src/bind_gmtool.c +++ b/src/bind_gmtool.c @@ -160,7 +160,7 @@ static int tolua_make_island(lua_State * L) int y = (int)tolua_tonumber(L, 2, 0); int s = (int)tolua_tonumber(L, 3, 0); - s = build_island_e3(x, y, s, NULL, 0); + s = build_island(x, y, s, NULL, 0); lua_pushinteger(L, s); return 1; } diff --git a/src/gmtool.c b/src/gmtool.c index 0ab31854e..3ec464a3f 100644 --- a/src/gmtool.c +++ b/src/gmtool.c @@ -1143,7 +1143,7 @@ static void handlekey(state * st, int c) else { n = minpop; } - build_island_e3(nx, ny, n, NULL, 0); + build_island(nx, ny, n, NULL, 0); st->modified = 1; st->wnd_info->update |= 1; st->wnd_status->update |= 1; diff --git a/src/modules/autoseed.c b/src/modules/autoseed.c index 65d4b1dfc..a59567dd4 100644 --- a/src/modules/autoseed.c +++ b/src/modules/autoseed.c @@ -49,7 +49,7 @@ #include #include -const terrain_type *random_terrain(const terrain_type * terrains[], +static const terrain_type *random_terrain_select(const terrain_type * terrains[], int distribution[], int size) { int ndistribution = size; @@ -583,7 +583,7 @@ int autoseed(newfaction ** players, int nsize, int max_agediff) break; } else { - terraform_region(r, random_terrain(terrainarr, distribution, nterrains)); + terraform_region(r, random_terrain_select(terrainarr, distribution, nterrains)); --isize; } } @@ -619,7 +619,7 @@ int autoseed(newfaction ** players, int nsize, int max_agediff) pnormalize(&x, &y, pl); rn = new_region(x, y, pl, 0); if (rng_int() % SPECIALCHANCE < special) { - terrain = random_terrain(terrainarr, distribution, nterrains); + terrain = random_terrain_select(terrainarr, distribution, nterrains); special = SPECIALCHANCE / 3; /* 33% chance auf noch eines */ } else { @@ -698,23 +698,21 @@ region *regionqueue_pop(region_list ** rlist) return 0; } -#define GEOMAX 8 +#define GEOMAX 7 static struct geo { int distribution; terrain_t type; } geography_e3[GEOMAX] = { - { - 8, T_OCEAN }, { - 3, T_SWAMP }, { - 1, T_VOLCANO }, { - 3, T_DESERT }, { - 4, T_HIGHLAND }, { - 3, T_MOUNTAIN }, { - 2, T_GLACIER }, { - 1, T_PLAIN } + { 8, T_OCEAN }, + { 3, T_SWAMP }, + { 3, T_DESERT }, + { 4, T_HIGHLAND }, + { 3, T_MOUNTAIN }, + { 2, T_GLACIER }, + { 1, T_PLAIN } }; -const terrain_type *random_terrain_e3(direction_t dir) +const terrain_type *random_terrain(direction_t dir) { static const terrain_type **terrainarr = 0; static int *distribution = 0; @@ -731,7 +729,7 @@ const terrain_type *random_terrain_e3(direction_t dir) distribution[n] = geography_e3[n].distribution; } } - return random_terrain(terrainarr, distribution, GEOMAX); + return random_terrain_select(terrainarr, distribution, GEOMAX); } static int @@ -864,8 +862,8 @@ static void starting_region(newfaction ** players, region * r, region * rn[]) } } -/* E3A island generation */ -int build_island_e3(int x, int y, int minsize, newfaction ** players, int numfactions) +/* island generator */ +int build_island(int x, int y, int minsize, newfaction ** players, int numfactions) { #define MIN_QUALITY 1000 int nfactions = 0; @@ -881,14 +879,14 @@ int build_island_e3(int x, int y, int minsize, newfaction ** players, int numfac r = new_region(x, y, pl, 0); } do { - terraform_region(r, random_terrain_e3(NODIRECTION)); + terraform_region(r, random_terrain(NODIRECTION)); } while (!r->land); while (r) { fset(r, RF_MARK); if (r->land) { if (nsize < minsize) { - nsize += random_neighbours(r, &rlist, &random_terrain_e3, minsize - nsize); + nsize += random_neighbours(r, &rlist, &random_terrain, minsize - nsize); } else { nsize += random_neighbours(r, &rlist, &get_ocean, minsize - nsize); diff --git a/src/modules/autoseed.h b/src/modules/autoseed.h index b78a2df55..cec42ba4a 100644 --- a/src/modules/autoseed.h +++ b/src/modules/autoseed.h @@ -33,10 +33,8 @@ extern "C" { extern int autoseed(newfaction ** players, int nsize, int max_agediff); extern newfaction *read_newfactions(const char *filename); - extern const struct terrain_type *random_terrain(const struct terrain_type - *terrains[], int distribution[], int size); - extern int build_island_e3(int x, int y, int minsize, newfaction **players, int numfactions); + extern int build_island(int x, int y, int minsize, newfaction **players, int numfactions); #ifdef __cplusplus } From 65dee13592a38915c3fa329ee6241ed80eb68fcb Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 6 Apr 2019 11:29:19 +0200 Subject: [PATCH 14/56] I am moving my library dependency folder to c:\libraries build.bat needed to know that. --- CMakeLists.txt | 7 ++----- cmake/Modules/FindToLua.cmake | 4 +++- vs2017-build.bat | 11 +++++++---- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b91565da..aa4e746c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,9 +31,6 @@ ELSE (HAVE_LIBBSD) CHECK_FUNCTION_EXISTS(strlcat HAVE_STRLCAT) ENDIF(HAVE_LIBBSD) -endif (MSVC) - -if (MSVC) find_package (PDCurses) SET(CURSES_FOUND ${PDCURSES_FOUND}) SET(CURSES_LIBRARIES ${PDCURSES_LIBRARY}) @@ -42,7 +39,8 @@ else (MSVC) find_package (Curses) endif (MSVC) -find_package (Readline) +# find_package (Readline) +find_package (EXPAT REQUIRED) if (ERESSEA_DB STREQUAL "db") find_package (BerkeleyDB REQUIRED QUIET) @@ -50,7 +48,6 @@ else() find_package (SQLite3 REQUIRED QUIET) endif() -find_package(EXPAT REQUIRED) find_package (ToLua REQUIRED) if (TOLUA_FOUND) if (${TOLUA_VERSION_STRING} VERSION_EQUAL "5.2") diff --git a/cmake/Modules/FindToLua.cmake b/cmake/Modules/FindToLua.cmake index 52c721112..92732981b 100644 --- a/cmake/Modules/FindToLua.cmake +++ b/cmake/Modules/FindToLua.cmake @@ -58,7 +58,9 @@ elseif(TOLUA_INCLUDE_DIR AND EXISTS "${TOLUA_INCLUDE_DIR}/tolua.h") string(REGEX REPLACE "^#define[\t ]+TOLUA_VERSION[\t ]+\"tolua ([^\"]*)\".*" "\\1" TOLUA_VERSION_STRING "${tolua_version_str}") unset(tolua_version_str) -endif() +else(PC_TOLUA_VERSION) +message(ERROR "TOLUA_VERSION_STRING cannot be determined") +endif(PC_TOLUA_VERSION) # handle the QUIETLY and REQUIRED arguments and set TOLUA_FOUND to TRUE if # all listed variables are TRUE diff --git a/vs2017-build.bat b/vs2017-build.bat index 7503153fe..22e153874 100644 --- a/vs2017-build.bat +++ b/vs2017-build.bat @@ -1,13 +1,16 @@ @ECHO OFF +IF "%WIN32_DEV%" == "" SET WIN32_DEV="C:\Libraries" +SET CMAKE_ROOT=%ProgramFiles%\CMake +IF "%LUA_DEV%" == "" SET LUA_DEV="%ProgramFiles(x86)%/Lua/5.1" SET VSVERSION=15 SET SRCDIR=%CD% -CD .. -SET ERESSEA=%CD% +REM CD .. +REM SET ERESSEA=%CD% +REM CD %SRCDIR% -CD %SRCDIR% IF exist build-vs%VSVERSION% goto HAVEDIR mkdir build-vs%VSVERSION% :HAVEDIR cd build-vs%VSVERSION% -"%ProgramFiles%\CMake\bin\cmake.exe" -G "Visual Studio %VSVERSION%" -DCMAKE_PREFIX_PATH="%ProgramFiles(x86)%/Lua/5.1;%ERESSEA%/dependencies-win32" -DCMAKE_MODULE_PATH="%SRCDIR%/cmake/Modules" -DCMAKE_SUPPRESS_REGENERATION=TRUE .. +"%CMAKE_ROOT%\bin\cmake.exe" -G "Visual Studio %VSVERSION%" -DCMAKE_PREFIX_PATH="%LUA_DEV%;%WIN32_DEV%" -DCMAKE_MODULE_PATH="%SRCDIR%/cmake/Modules" -DCMAKE_SUPPRESS_REGENERATION=TRUE .. PAUSE From 102a0e0e27463d1b222a23a6be36993a4de6eb8b Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 6 Apr 2019 11:41:56 +0200 Subject: [PATCH 15/56] fix cmake syntax. --- CMakeLists.txt | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index aa4e746c0..2d2635f05 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,41 +6,38 @@ FILE(TO_CMAKE_PATH "${CMAKE_PREFIX_PATH}" CMAKE_PREFIX_PATH ) endif(WIN32) project (eressea-server C) -set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules/" ${CMAKE_MODULE_PATH}) +set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") if (MSVC) -include(MSVC) +find_package (PDCurses) +set (CURSES_FOUND ${PDCURSES_FOUND}) +set (CURSES_LIBRARIES ${PDCURSES_LIBRARY}) +set (CURSES_INCLUDE_DIR ${PDCURSES_INCLUDE_DIR}) set (HAVE_STRDUP 0) set (HAVE_STRLCAT 0) set (HAVE_LIBBSD 0) set (HAVE_SIGNAL_H 0) set (HAVE_EXECINFO_H 0) +include (MSVC) else (MSVC) -INCLUDE (CheckIncludeFile) +find_package (Curses) +include (CheckIncludeFile) CHECK_INCLUDE_FILE(signal.h HAVE_SIGNAL_H) CHECK_INCLUDE_FILE(execinfo.h HAVE_EXECINFO_H) CHECK_INCLUDE_FILE(bsd/string.h HAVE_LIBBSD) -INCLUDE (CheckFunctionExists) +include (CheckFunctionExists) CHECK_FUNCTION_EXISTS(strdup HAVE_STRDUP) -IF (HAVE_LIBBSD) -INCLUDE (CheckLibraryExists) +if (HAVE_LIBBSD) +include (CheckLibraryExists) CHECK_LIBRARY_EXISTS(bsd strlcat "bsd/string.h" HAVE_STRLCAT) -ELSE (HAVE_LIBBSD) +else (HAVE_LIBBSD) CHECK_FUNCTION_EXISTS(strlcat HAVE_STRLCAT) -ENDIF(HAVE_LIBBSD) - -find_package (PDCurses) -SET(CURSES_FOUND ${PDCURSES_FOUND}) -SET(CURSES_LIBRARIES ${PDCURSES_LIBRARY}) -SET(CURSES_INCLUDE_DIR ${PDCURSES_INCLUDE_DIR}) -else (MSVC) -find_package (Curses) +endif (HAVE_LIBBSD) endif (MSVC) -# find_package (Readline) -find_package (EXPAT REQUIRED) +find_package (Readline) if (ERESSEA_DB STREQUAL "db") find_package (BerkeleyDB REQUIRED QUIET) @@ -48,6 +45,7 @@ else() find_package (SQLite3 REQUIRED QUIET) endif() +find_package(EXPAT REQUIRED) find_package (ToLua REQUIRED) if (TOLUA_FOUND) if (${TOLUA_VERSION_STRING} VERSION_EQUAL "5.2") From 510b6c2628541495a1af8c12cbd6d0dc269d2366 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 6 Apr 2019 19:00:59 +0200 Subject: [PATCH 16/56] =?UTF-8?q?Zeige=20keine=20Luxusg=C3=BCter-Statistik?= =?UTF-8?q?=20im=20Ozean.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/report.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/report.c b/src/report.c index ae9607736..961f5227e 100644 --- a/src/report.c +++ b/src/report.c @@ -1216,14 +1216,14 @@ static void statistics(struct stream *out, const region * r, const faction * f) if (!markets_module()) { if (buildingtype_exists(r, bt_find("caravan"), true)) { - m = msg_message("nr_stat_luxuries", "max", (p * 2) / TRADE_FRACTION); + p *= 2; } - else { + if (p >= TRADE_FRACTION) { m = msg_message("nr_stat_luxuries", "max", p / TRADE_FRACTION); + nr_render(m, f->locale, buf, sizeof(buf), f); + paragraph(out, buf, 2, 2, 0); + msg_release(m); } - nr_render(m, f->locale, buf, sizeof(buf), f); - paragraph(out, buf, 2, 2, 0); - msg_release(m); } /* count */ From bcca812ecc1c50220d1588ae8b69c5962ad35e65 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 7 Apr 2019 13:11:02 +0200 Subject: [PATCH 17/56] Bug 2576: additional logging. increase log verbosity, decrease some log levels. --- scripts/eressea/tunnels.lua | 16 +++++++++++++--- src/creport.c | 9 ++++----- src/magic.c | 2 +- src/main.c | 4 ++-- src/reports.c | 2 +- 5 files changed, 21 insertions(+), 12 deletions(-) diff --git a/scripts/eressea/tunnels.lua b/scripts/eressea/tunnels.lua index 4a787a373..6b7a8e8d1 100644 --- a/scripts/eressea/tunnels.lua +++ b/scripts/eressea/tunnels.lua @@ -27,11 +27,21 @@ end local function tunnel_action(b, param) local units = tunnel_travelers(b) local rto = get_target(param) + eressea.log.info("Tunnel from " .. tostring(b) .. " [" .. param .. "]") if rto and units then - eressea.log.debug("Tunnel from " .. tostring(b) .. " [" .. param .. "]") - for key, u in pairs(units) do + for _, u in pairs(units) do u.region = rto - eressea.log.debug("teleported " .. tostring(u) .. " to " .. tostring(rto)) + eressea.log.info("teleported " .. tostring(u) .. " to " .. tostring(rto)) + end + elseif not units then + eressea.log.info("No units in tunnel " .. tostring(b) .. " [" .. param .. "]") + elseif not rto then + eressea.log.error("No target for tunnel " .. tostring(b) .. " [" .. param .. "]") + end + -- debug code to find bugs: + for u in b.region.units do + if u.building == b then + eressea.log.error("Did not teleport " .. tostring(u) .. " from tunnel " .. tostring(b)) end end end diff --git a/src/creport.c b/src/creport.c index 45400f241..0458f7271 100644 --- a/src/creport.c +++ b/src/creport.c @@ -848,13 +848,12 @@ void cr_output_unit(stream *out, const faction * f, pzTmp = get_racename(u->attribs); if (pzTmp) { - const char *pzRace = LOC(lang, mkname("race", pzTmp)); - pzTmp = pzRace ? pzRace : pzTmp; - stream_printf(out, "\"%s\";Typ\n", translate(pzTmp, LOC(lang, pzTmp))); + const char *pzRace = locale_string(lang, mkname("race", pzTmp), false); + pzTmp = pzRace ? translate(pzRace, LOC(lang, pzRace)) : pzTmp; + stream_printf(out, "\"%s\";Typ\n", pzTmp); if (u->faction == f && fval(u_race(u), RCF_SHAPESHIFTANY)) { pzRace = rc_name_s(u_race(u), NAME_PLURAL); - stream_printf(out, "\"%s\";wahrerTyp\n", - translate(pzRace, LOC(lang, pzRace))); + stream_printf(out, "\"%s\";wahrerTyp\n", pzTmp); } } else { diff --git a/src/magic.c b/src/magic.c index d7b57f24d..fdd74d55e 100644 --- a/src/magic.c +++ b/src/magic.c @@ -2237,7 +2237,7 @@ static void equip_familiar(unit *fam) { snprintf(eqname, sizeof(eqname), "fam_%s", rc->_name); if (!equip_unit(fam, eqname)) { - log_info("could not perform initialization for familiar %s.\n", rc->_name); + log_debug("could not perform initialization for familiar %s.\n", rc->_name); } } diff --git a/src/main.c b/src/main.c index 6b80c0cb0..4216d3046 100644 --- a/src/main.c +++ b/src/main.c @@ -53,7 +53,7 @@ static const char *logfile = "eressea.log"; static const char *luafile = 0; static const char *inifile = "eressea.ini"; static int memdebug = 0; -static int verbosity = 1; +static int verbosity = 2; static void load_inifile(void) { @@ -183,7 +183,7 @@ static int verbosity_to_flags(int verbosity) { static int parse_args(int argc, char **argv) { int i; - int log_stderr, log_flags = 2; + int log_stderr, log_flags = 3; for (i = 1; i != argc; ++i) { char *argi = argv[i]; diff --git a/src/reports.c b/src/reports.c index 4b950b73b..306fe0e10 100644 --- a/src/reports.c +++ b/src/reports.c @@ -713,7 +713,7 @@ void bufunit(const faction * f, const unit * u, const faction *fv, pzTmp = get_racename(u->attribs); if (pzTmp) { - const char *name = LOC(lang, mkname("race", pzTmp)); + const char *name = locale_string(lang, mkname("race", pzTmp), false); sbs_strcat(sbp, name ? name : pzTmp); if (u->faction == f && fval(u_race(u), RCF_SHAPESHIFTANY)) { sbs_strcat(sbp, " ("); From ca5e7b82ae3c20e2e2087175f67fafcdc621c9a5 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 7 Apr 2019 15:27:11 +0200 Subject: [PATCH 18/56] =?UTF-8?q?Bug=202570:=20Linie=20vor=20jeder=20Regio?= =?UTF-8?q?n,=20Leerzeilen=20aufger=C3=A4umt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/report.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/report.c b/src/report.c index 961f5227e..61cb915b8 100644 --- a/src/report.c +++ b/src/report.c @@ -1607,7 +1607,6 @@ static void allies(struct stream *out, const faction * f) } g = g->next; } - rpline(out); } static void guards(struct stream *out, const region * r, const faction * see) @@ -1703,8 +1702,6 @@ static void list_address(struct stream *out, const faction * uf, selist * seenfa } selist_advance(&flist, &qi, 1); } - newline(out); - rpline(out); } static void @@ -2130,9 +2127,10 @@ report_plaintext(const char *filename, report_context * ctx, continue; /* Beschreibung */ + rpline(out); + newline(out); if (r->seen.mode >= seen_unit) { anyunits = 1; - newline(out); report_region(out, r, f); if (markets_module() && r->land) { const item_type *lux = r_luxury(r); @@ -2169,20 +2167,21 @@ report_plaintext(const char *filename, report_context * ctx, newline(out); report_travelthru(out, r, f); } - newline(out); if (wants_stats && r->seen.mode >= seen_travel) { if (r->land || r->seen.mode >= seen_unit) { - statistics(out, r, f); newline(out); + statistics(out, r, f); } } /* Nachrichten an REGION in der Region */ if (r->seen.mode >= seen_travel) { message_list *mlist = r_getmessages(r, f); + newline(out); if (mlist) { struct mlist **split = merge_messages(mlist, r->msgs); + newline(out); rp_messages(out, mlist, f, 0, false); split_messages(mlist, split); } @@ -2236,7 +2235,6 @@ report_plaintext(const char *filename, report_context * ctx, assert(!u); newline(out); - rpline(out); ERRNO_CHECK(); } if (!is_monsters(f)) { From 21e226b0682554cf1cc0856fcbcc4c58510f1cef Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 7 Apr 2019 16:05:00 +0200 Subject: [PATCH 19/56] Bug 2576: fix indexing of portals. --- scripts/eressea/tunnels.lua | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/scripts/eressea/tunnels.lua b/scripts/eressea/tunnels.lua index 6b7a8e8d1..96d482abd 100644 --- a/scripts/eressea/tunnels.lua +++ b/scripts/eressea/tunnels.lua @@ -16,12 +16,17 @@ local function tunnel_travelers(b) end local function get_target(param) - local ntargets = table.maxn(targets) - if ntargets==0 then + local ntargets = #targets + if ntargets == 0 then + eressea.log.error("Zero tunnel targets for [" .. param .. "]") return nil end local rn = math.fmod(rng_int(), ntargets) - return targets[rn] + local t = targets[rn + 1] + if not t then + eressea.log.error("NULL target for [" .. param .. "]" .. " at index " .. rn) + end + return t end local function tunnel_action(b, param) @@ -50,7 +55,7 @@ function tunnels.init() local r, b for r in regions() do if r:get_key('tnnL') then - targets[table.maxn(targets)+1] = r + table.insert(targets, r) if (r:get_flag(0)) then -- target region is chaotic? nope. r:set_flag(0, false) @@ -62,10 +67,11 @@ function tunnels.init() end for b in r.buildings do if b.type == 'portal' then - buildings[table.maxn(buildings)+1] = b + table.insert(buildings, b) end end end + eressea.log.info("Found " .. #targets .. " tunnel targets") end function tunnels.update() From 3f021b21cd0976d677128356046ef0e64420ebae Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 7 Apr 2019 17:55:04 +0200 Subject: [PATCH 20/56] Bug 1982: disable the clone spell. --- res/e3a/spellbooks/gray.xml | 2 +- res/e3a/spellbooks/illaun.xml | 2 +- res/e3a/spells.xml | 4 ++-- res/eressea/spellbooks/gray.xml | 2 +- res/eressea/spellbooks/illaun.xml | 2 +- res/eressea/spells.xml | 5 +++-- src/attributes/seenspell.c | 11 ++++++----- src/creport.c | 16 +++++++++++----- vs2017-build.bat | 3 +++ 9 files changed, 29 insertions(+), 18 deletions(-) diff --git a/res/e3a/spellbooks/gray.xml b/res/e3a/spellbooks/gray.xml index 998405b03..f3f4e496d 100644 --- a/res/e3a/spellbooks/gray.xml +++ b/res/e3a/spellbooks/gray.xml @@ -25,7 +25,7 @@ - + diff --git a/res/e3a/spellbooks/illaun.xml b/res/e3a/spellbooks/illaun.xml index 0392842c2..8d820bf71 100644 --- a/res/e3a/spellbooks/illaun.xml +++ b/res/e3a/spellbooks/illaun.xml @@ -27,7 +27,7 @@ - + diff --git a/res/e3a/spells.xml b/res/e3a/spells.xml index 94d7cbc08..d72386803 100644 --- a/res/e3a/spells.xml +++ b/res/e3a/spells.xml @@ -79,13 +79,13 @@ + - + --> diff --git a/res/eressea/spellbooks/gray.xml b/res/eressea/spellbooks/gray.xml index 942b50237..74486f004 100644 --- a/res/eressea/spellbooks/gray.xml +++ b/res/eressea/spellbooks/gray.xml @@ -30,7 +30,7 @@ - + diff --git a/res/eressea/spellbooks/illaun.xml b/res/eressea/spellbooks/illaun.xml index 83ffcfc27..6552a4bd8 100644 --- a/res/eressea/spellbooks/illaun.xml +++ b/res/eressea/spellbooks/illaun.xml @@ -20,7 +20,7 @@ - + diff --git a/res/eressea/spells.xml b/res/eressea/spells.xml index 1931a4c74..5725b8768 100644 --- a/res/eressea/spells.xml +++ b/res/eressea/spells.xml @@ -446,12 +446,13 @@ - + diff --git a/src/attributes/seenspell.c b/src/attributes/seenspell.c index e20976015..698a83076 100644 --- a/src/attributes/seenspell.c +++ b/src/attributes/seenspell.c @@ -54,11 +54,12 @@ static int read_seenspells(variant *var, void *owner, struct gamedata *data) READ_TOK(store, token, sizeof(token)); while (token[0]) { spell *sp = find_spell(token); - if (!sp) { - log_info("read_seenspells: could not find spell '%s'\n", token); - return AT_READ_FAIL; + if (sp) { + selist_push(&ql, sp); + } + else { + log_info("read_seenspells: could not find spell '%s'\n", token); } - selist_push(&ql, sp); READ_TOK(store, token, sizeof(token)); } var->v = ql; @@ -70,8 +71,8 @@ static bool cb_write_spell(void *data, void *more) { storage *store = (storage *)more; WRITE_TOK(store, sp->sname); return true; - } + static void write_seenspells(const variant *var, const void *owner, struct storage *store) { diff --git a/src/creport.c b/src/creport.c index 0458f7271..23e0f7c8a 100644 --- a/src/creport.c +++ b/src/creport.c @@ -108,8 +108,8 @@ struct locale *crtag_locale(void) { static const char *crtag(const char *key) { const char *result; - result = LOC(crtag_locale(), key); - return result; + result = locale_string(crtag_locale(), key, false); + return result ? result : key; } /* * translation table @@ -849,11 +849,17 @@ void cr_output_unit(stream *out, const faction * f, pzTmp = get_racename(u->attribs); if (pzTmp) { const char *pzRace = locale_string(lang, mkname("race", pzTmp), false); - pzTmp = pzRace ? translate(pzRace, LOC(lang, pzRace)) : pzTmp; - stream_printf(out, "\"%s\";Typ\n", pzTmp); + if (pzRace) { + pzTmp = pzRace; + } + pzRace = translate(pzTmp, locale_string(lang, pzTmp, false)); + if (!pzRace) { + pzRace = pzTmp; + } + stream_printf(out, "\"%s\";Typ\n", pzRace); if (u->faction == f && fval(u_race(u), RCF_SHAPESHIFTANY)) { pzRace = rc_name_s(u_race(u), NAME_PLURAL); - stream_printf(out, "\"%s\";wahrerTyp\n", pzTmp); + stream_printf(out, "\"%s\";wahrerTyp\n", pzRace); } } else { diff --git a/vs2017-build.bat b/vs2017-build.bat index 22e153874..b79a81e85 100644 --- a/vs2017-build.bat +++ b/vs2017-build.bat @@ -12,5 +12,8 @@ IF exist build-vs%VSVERSION% goto HAVEDIR mkdir build-vs%VSVERSION% :HAVEDIR cd build-vs%VSVERSION% +IF NOT EXIST CMakeCache.txt GOTO NOCACHE +DEL CMakeCache.txt +:NOCACHE "%CMAKE_ROOT%\bin\cmake.exe" -G "Visual Studio %VSVERSION%" -DCMAKE_PREFIX_PATH="%LUA_DEV%;%WIN32_DEV%" -DCMAKE_MODULE_PATH="%SRCDIR%/cmake/Modules" -DCMAKE_SUPPRESS_REGENERATION=TRUE .. PAUSE From 91e40b706138e0175e311942a7dccbc48e3b3ebc Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 7 Apr 2019 21:37:06 +0200 Subject: [PATCH 21/56] =?UTF-8?q?Bug=201982:=20Klone=20aufl=C3=B6sen,=20un?= =?UTF-8?q?d=20Magiern=20ihre=20permanete=20Aura=20und=20Trank=20zur=C3=BC?= =?UTF-8?q?ck=20geben.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/kernel/gamedata.h | 3 +- src/kernel/save.c | 70 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/src/kernel/gamedata.h b/src/kernel/gamedata.h index 587ee0a40..d4293d461 100644 --- a/src/kernel/gamedata.h +++ b/src/kernel/gamedata.h @@ -42,8 +42,9 @@ #define FAMILIAR_FIXMAGE_VERSION 364 /* familiar links are fixed */ #define FAMILIAR_FIXSPELLBOOK_VERSION 365 /* familiar spells are fixed */ #define FIX_STARTLEVEL_VERSION 366 /* fixing resource startlevels */ +#define FIX_CLONES_VERSION 367 /* dissolve clones */ -#define RELEASE_VERSION FIX_STARTLEVEL_VERSION /* current datafile */ +#define RELEASE_VERSION FIX_CLONES_VERSION /* current datafile */ #define MIN_VERSION UIDHASH_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 */ diff --git a/src/kernel/save.c b/src/kernel/save.c index 0b3ade593..70c75f62a 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -1368,6 +1368,72 @@ static void fix_fam_triggers(unit *u) { } } +static void fix_clone(unit *uc) { + attrib * a; + assert(uc); + assert(uc->number > 0); + ADDMSG(&uc->faction->msgs, msg_message("dissolve_units_5", + "unit region number race", uc, uc->region, uc->number, u_race(uc))); + a_removeall(&uc->attribs, &at_clonemage); + a = a_new(&at_unitdissolve); + a->data.ca[0] = 0; + a->data.ca[1] = 100; + a_add(&uc->attribs, a); +} + +static void fix_clone_mage(unit *um, const item_type *itype) { + i_change(&um->items, itype, 1); + change_maxspellpoints(um, 20); + a_removeall(&um->attribs, &at_clone); +} + +static void fix_clones(void) { + const race *rc_clone = rc_find("clone"); + const item_type *it_potion = it_find("lifepotion"); + + if (rc_clone && it_potion) { + region *r; + for (r = regions; r; r = r->next) { + unit * u; + for (u = r->units; u; u = u->next) { + if (!fval(u, UFL_MARK)) { + if (u_race(u) == rc_clone) { + attrib *a = a_find(u->attribs, &at_clonemage); + unit * um = NULL; + fset(u, UFL_MARK); + if (a) { + um = (unit *)a->data.v; + fset(um, UFL_MARK); + } + } + else { + attrib *a = a_find(u->attribs, &at_clone); + if (a) { + unit *uc = (unit *)a->data.v; + fset(u, UFL_MARK); + fset(uc, UFL_MARK); + } + } + } + } + } + for (r = regions; r; r = r->next) { + unit * u; + for (u = r->units; u; u = u->next) { + if (fval(u, UFL_MARK)) { + if (u_race(u) == rc_clone) { + fix_clone(u); + } + else { + fix_clone_mage(u, it_potion); + } + freset(u, UFL_MARK); + } + } + } + } +} + static void fix_familiars(void (*callback)(unit *)) { region *r; for (r = regions; r; r = r->next) { @@ -1559,7 +1625,9 @@ int read_game(gamedata *data) } } } - + if (data->version < FIX_CLONES_VERSION) { + fix_clones(); + } if (data->version < FAMILIAR_FIX_VERSION) { fix_familiars(fix_fam_triggers); } From bb3ce32be6451cf547280e928ef3a7e8fb1fbd01 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 8 Apr 2019 14:56:44 +0200 Subject: [PATCH 22/56] fix default crtag locale --- src/creport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/creport.c b/src/creport.c index 23e0f7c8a..fce3b8bff 100644 --- a/src/creport.c +++ b/src/creport.c @@ -100,7 +100,7 @@ struct locale *crtag_locale(void) { static int config; if (config_changed(&config)) { const char *lname = config_get("creport.tags"); - lang = get_locale(lname ? lname : "de"); + lang = lname ? get_locale(lname) : default_locale; } return lang; } From aab234a3f4c30c1b16ca24ae1059a2c4a38e4a2f Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 23 Apr 2019 13:18:51 +0200 Subject: [PATCH 23/56] update to schema version 1 - factions table is now faction - no turn column - new update logic --- process/epasswd.py | 4 +- src/creport.c | 2 +- src/gamedb.c | 29 +++++--- src/kernel/database.test.c | 17 +++-- src/kernel/db/driver.h | 14 +++- src/kernel/db/sqlite.c | 132 +++++++++++++++++++++++++------------ tests/runtests.bat | 6 +- 7 files changed, 139 insertions(+), 65 deletions(-) diff --git a/process/epasswd.py b/process/epasswd.py index bdb3c4a6d..c5e1712b9 100755 --- a/process/epasswd.py +++ b/process/epasswd.py @@ -45,9 +45,7 @@ class EPasswd: def load_database(self, file): conn = sqlite3.connect(file) c = conn.cursor() - c.execute('SELECT MAX(turn) FROM factions') - args = c.fetchone() - for row in c.execute('SELECT no, email, password FROM factions WHERE turn=?', args): + for row in c.execute('SELECT `no`, `email`, `password` FROM `faction`'): (no, email, passwd) = row self.set_data(baseconvert(no, 36), email, passwd) conn.close() diff --git a/src/creport.c b/src/creport.c index 23e0f7c8a..fce3b8bff 100644 --- a/src/creport.c +++ b/src/creport.c @@ -100,7 +100,7 @@ struct locale *crtag_locale(void) { static int config; if (config_changed(&config)) { const char *lname = config_get("creport.tags"); - lang = get_locale(lname ? lname : "de"); + lang = lname ? get_locale(lname) : default_locale; } return lang; } diff --git a/src/gamedb.c b/src/gamedb.c index 5f53d9120..9af580a9f 100644 --- a/src/gamedb.c +++ b/src/gamedb.c @@ -9,9 +9,25 @@ #include "kernel/faction.h" #include "kernel/db/driver.h" +#include "util/strings.h" + +static int generate_factions(void *data, db_faction *results, int nresults) +{ + int i; + faction **iter = (faction **)data; + for (i = 0; *iter && i != nresults; ++i) { + faction *f = *iter; + results[i].p_uid = &f->uid; + results[i].no = f->no; + results[i].email = faction_getemail(f); + str_strlcpy(results[i].pwhash, faction_getpassword(f), sizeof(results[i].pwhash)); + *iter = f->next; + } + return i; +} + int gamedb_update(void) { - faction *f; int err; const char *dbname; @@ -19,14 +35,9 @@ int gamedb_update(void) err = db_driver_open(DB_GAME, dbname); if (err == 0) { - for (f = factions; f; f = f->next) { - int uid = db_driver_faction_save(f->uid, f->no, turn, - faction_getemail(f), - faction_getpassword(f)); - if (uid > 0) { - f->uid = uid; - } - } + faction *list = factions; + db_driver_update_factions(generate_factions, &list); + db_driver_compact(turn); db_driver_close(DB_GAME); } return err; diff --git a/src/kernel/database.test.c b/src/kernel/database.test.c index c5aae1af6..a84a4b286 100644 --- a/src/kernel/database.test.c +++ b/src/kernel/database.test.c @@ -47,19 +47,26 @@ static void test_save_load_order(CuTest *tc) { static void test_update_faction(CuTest *tc) { faction *f; - int uid; + int err; + dbrow_id id; test_setup(); db_driver_open(DB_GAME, NULL); f = test_create_faction(NULL); - uid = db_driver_faction_save(f->uid, f->no, 0, + CuAssertIntEquals(tc, 0, f->uid); + id = 0; + err = db_driver_faction_save(&id, f->no, faction_getemail(f), faction_getpassword(f)); - f->uid = uid; - uid = db_driver_faction_save(f->uid, f->no, 0, + CuAssertTrue(tc, 0 != id); + f->uid = (int)id; + db_driver_close(DB_GAME); + + db_driver_open(DB_GAME, NULL); + db_driver_faction_save(&id, f->no, faction_getemail(f), faction_getpassword(f)); - CuAssertIntEquals(tc, f->uid, uid); + CuAssertIntEquals(tc, f->uid, id); db_driver_close(DB_GAME); test_teardown(); } diff --git a/src/kernel/db/driver.h b/src/kernel/db/driver.h index 341653991..91fcfbb27 100644 --- a/src/kernel/db/driver.h +++ b/src/kernel/db/driver.h @@ -1,6 +1,7 @@ #pragma once #include +#include struct order_data; @@ -17,6 +18,17 @@ int db_driver_open(database_t db, const char *dbname); void db_driver_close(database_t db); dbrow_id db_driver_order_save(const char *str); struct order_data *db_driver_order_load(dbrow_id id); -dbrow_id db_driver_faction_save(dbrow_id id, int no, int turn, const char *email, const char *password); dbrow_id db_driver_string_save(const char *s); const char *db_driver_string_load(dbrow_id id, size_t *size); +void db_driver_compact(int turn); + +typedef struct db_faction { + int *p_uid; + int no; + const char *email; + char pwhash[128]; +} db_faction; + +typedef int (*db_faction_generator)(void *, db_faction *, int); +int db_driver_update_factions(db_faction_generator gen, void *data); +int db_driver_faction_save(dbrow_id * p_id, int no, const char *email, const char *password); diff --git a/src/kernel/db/sqlite.c b/src/kernel/db/sqlite.c index 29638d900..676dc5028 100644 --- a/src/kernel/db/sqlite.c +++ b/src/kernel/db/sqlite.c @@ -95,68 +95,104 @@ dbrow_id db_driver_order_save(const char *str) { return (dbrow_id)id; } - -dbrow_id db_driver_faction_save(dbrow_id id, int no, int turn, const char *email, const char *password) +int db_driver_faction_save(dbrow_id * p_id, int no, const char *email, const char *password) { - sqlite3_int64 row_id; + dbrow_id id = *p_id; int err; + sqlite3_stmt *stmt = (id > 0) ? g_stmt_update_faction : g_stmt_insert_faction; assert(g_game_db); - if (id != 0) { - int rows; - err = sqlite3_reset(g_stmt_update_faction); - assert(err == SQLITE_OK); - err = sqlite3_bind_int(g_stmt_update_faction, 1, no); - assert(err == SQLITE_OK); - err = sqlite3_bind_int(g_stmt_update_faction, 2, turn); - assert(err == SQLITE_OK); - err = sqlite3_bind_text(g_stmt_update_faction, 3, email, -1, SQLITE_STATIC); - assert(err == SQLITE_OK); - err = sqlite3_bind_text(g_stmt_update_faction, 4, password, -1, SQLITE_STATIC); - assert(err == SQLITE_OK); - err = sqlite3_bind_int(g_stmt_update_faction, 5, id); - assert(err == SQLITE_OK); - err = sqlite3_step(g_stmt_update_faction); - assert(err == SQLITE_DONE); - rows = sqlite3_changes(g_game_db); - if (rows != 0) { - return id; - } + err = sqlite3_reset(stmt); + if (err != SQLITE_OK) return err; + err = sqlite3_bind_int(stmt, 1, no); + if (err != SQLITE_OK) return err; + err = sqlite3_bind_text(stmt, 2, email, -1, SQLITE_STATIC); + if (err != SQLITE_OK) return err; + err = sqlite3_bind_text(stmt, 3, password, -1, SQLITE_STATIC); + if (err != SQLITE_OK) return err; + + if (id > 0) { + err = sqlite3_bind_int(stmt, 4, id); + if (err != SQLITE_OK) return err; } - err = sqlite3_reset(g_stmt_insert_faction); - assert(err == SQLITE_OK); - err = sqlite3_bind_int(g_stmt_insert_faction, 1, no); - assert(err == SQLITE_OK); - err = sqlite3_bind_int(g_stmt_insert_faction, 2, turn); - assert(err == SQLITE_OK); - err = sqlite3_bind_text(g_stmt_insert_faction, 3, email, -1, SQLITE_STATIC); - assert(err == SQLITE_OK); - err = sqlite3_bind_text(g_stmt_insert_faction, 4, password, -1, SQLITE_STATIC); - assert(err == SQLITE_OK); - err = sqlite3_step(g_stmt_insert_faction); - assert(err == SQLITE_DONE); + err = sqlite3_step(stmt); + if (err != SQLITE_DONE) return err; ERRNO_CHECK(); - row_id = sqlite3_last_insert_rowid(g_game_db); - assert(row_id>0 && row_id <= UINT_MAX); - return (dbrow_id)row_id; + if (id <= 0) { + sqlite3_int64 row_id; + row_id = sqlite3_last_insert_rowid(g_game_db); + assert(row_id > 0 && row_id <= UINT_MAX); + *p_id = (dbrow_id)row_id; + } + return SQLITE_OK; +} + +int db_driver_update_factions(db_faction_generator gen, void *data) +{ + db_faction results[32]; + int num, err; + + err = sqlite3_exec(g_game_db, "BEGIN TRANSACTION", NULL, NULL, NULL); + assert(err == SQLITE_OK); + err = sqlite3_exec(g_game_db, "DELETE FROM `faction`", NULL, NULL, NULL); + if (err != SQLITE_OK) { + sqlite3_exec(g_game_db, "ROLLBACK", NULL, NULL, NULL); + return err; + } + num = gen(data, results, 32); + while (num > 0) { + int i; + for (i = 0; i != num; ++i) { + db_faction *dbf = results + i; + dbrow_id id = (dbrow_id)*dbf->p_uid; + err = db_driver_faction_save(&id, dbf->no, dbf->email, dbf->pwhash); + if (err != SQLITE_OK) { + sqlite3_exec(g_game_db, "ROLLBACK", NULL, NULL, NULL); + return err; + } + assert(id > 0 && id <= INT_MAX); + *dbf->p_uid = (int)id; + } + num = gen(data, results, 32); + } + err = sqlite3_exec(g_game_db, "COMMIT", NULL, NULL, NULL); + return err; +} + +static int cb_int_col(void *data, int ncols, char **text, char **name) { + int *p_int = (int *)data; + *p_int = atoi(text[0]); + return SQLITE_OK; } static int db_open_game(const char *dbname) { - int err; + int err, version = 0; err = sqlite3_open(dbname, &g_game_db); assert(err == SQLITE_OK); - err = sqlite3_exec(g_game_db, "CREATE TABLE IF NOT EXISTS factions (id INTEGER PRIMARY KEY, no INTEGER NOT NULL, email VARCHAR(128), password VARCHAR(128), turn INTEGER NOT NULL)", NULL, NULL, NULL); + + err = sqlite3_exec(g_game_db, "PRAGMA user_version", cb_int_col, &version, NULL); assert(err == SQLITE_OK); - err = sqlite3_prepare_v2(g_game_db, "UPDATE factions SET no=?, turn=?, email=?, password=? WHERE id=?", -1, &g_stmt_update_faction, NULL); + if (version < 1) { + /* drop deprecated table */ + err = sqlite3_exec(g_game_db, "DROP TABLE IF EXISTS `factions`", NULL, NULL, NULL); + assert(err == SQLITE_OK); + /* install schema version 1: */ + err = sqlite3_exec(g_game_db, "CREATE TABLE IF NOT EXISTS `faction` (`id` INTEGER PRIMARY KEY, `no` INTEGER NOT NULL UNIQUE, `email` VARCHAR(128), `password` VARCHAR(128))", NULL, NULL, NULL); + assert(err == SQLITE_OK); + err = sqlite3_exec(g_game_db, "PRAGMA user_version = 1", NULL, NULL, NULL); + assert(err == SQLITE_OK); + } + /* create prepared statments: */ + err = sqlite3_prepare_v2(g_game_db, "INSERT INTO `faction` (`no`, `email`, `password`, `id`) VALUES (?,?,?,?)", -1, &g_stmt_update_faction, NULL); assert(err == SQLITE_OK); - err = sqlite3_prepare_v2(g_game_db, "INSERT INTO factions (no, turn, email, password) VALUES (?,?,?,?)", -1, &g_stmt_insert_faction, NULL); + err = sqlite3_prepare_v2(g_game_db, "INSERT INTO `faction` (`no`, `email`, `password`) VALUES (?,?,?)", -1, &g_stmt_insert_faction, NULL); assert(err == SQLITE_OK); ERRNO_CHECK(); - return 0; + return err; } static int db_open_swap(const char *dbname) { @@ -303,3 +339,13 @@ const char *db_driver_string_load(dbrow_id id, size_t *size) { ERRNO_CHECK(); return NULL; } + +void db_driver_compact(int turn) +{ + int err; + + /* repack database: */ + err = sqlite3_exec(g_game_db, "VACUUM", 0, 0, 0); + assert(err == SQLITE_OK); +} + diff --git a/tests/runtests.bat b/tests/runtests.bat index 88afc8d31..e73580851 100644 --- a/tests/runtests.bat +++ b/tests/runtests.bat @@ -7,9 +7,9 @@ IF EXIST ..\build-vs15 SET BUILD=..\build-vs15\eressea\Debug SET SERVER=%BUILD%\eressea.exe %BUILD%\test_eressea.exe -%SERVER% ..\scripts\run-tests.lua -%SERVER% -re2 ..\scripts\run-tests-e2.lua -%SERVER% -re3 ..\scripts\run-tests-e3.lua +%SERVER% -v1 ..\scripts\run-tests.lua +%SERVER% -v1 -re2 ..\scripts\run-tests-e2.lua +%SERVER% -v1 -re3 ..\scripts\run-tests-e3.lua %SERVER% --version PAUSE RMDIR /s /q reports From 7298968921a638c0c5bdce3ac06a8b759043174d Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 24 Apr 2019 08:08:50 +0200 Subject: [PATCH 24/56] schema version 2 faction no is a char(4), not an int. --- src/kernel/db/sqlite.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/kernel/db/sqlite.c b/src/kernel/db/sqlite.c index 676dc5028..e92f8cd57 100644 --- a/src/kernel/db/sqlite.c +++ b/src/kernel/db/sqlite.c @@ -3,6 +3,7 @@ #include #include +#include #include "driver.h" @@ -105,7 +106,7 @@ int db_driver_faction_save(dbrow_id * p_id, int no, const char *email, const cha err = sqlite3_reset(stmt); if (err != SQLITE_OK) return err; - err = sqlite3_bind_int(stmt, 1, no); + err = sqlite3_bind_text(stmt, 1, itoa36(no), -1, SQLITE_STATIC); if (err != SQLITE_OK) return err; err = sqlite3_bind_text(stmt, 2, email, -1, SQLITE_STATIC); if (err != SQLITE_OK) return err; @@ -179,10 +180,12 @@ static int db_open_game(const char *dbname) { /* drop deprecated table */ err = sqlite3_exec(g_game_db, "DROP TABLE IF EXISTS `factions`", NULL, NULL, NULL); assert(err == SQLITE_OK); - /* install schema version 1: */ - err = sqlite3_exec(g_game_db, "CREATE TABLE IF NOT EXISTS `faction` (`id` INTEGER PRIMARY KEY, `no` INTEGER NOT NULL UNIQUE, `email` VARCHAR(128), `password` VARCHAR(128))", NULL, NULL, NULL); + } + if (version < 2) { + /* install schema version 2: */ + err = sqlite3_exec(g_game_db, "CREATE TABLE IF NOT EXISTS `faction` (`id` INTEGER PRIMARY KEY, `no` CHAR(4) NOT NULL UNIQUE, `email` VARCHAR(128), `password` VARCHAR(128))", NULL, NULL, NULL); assert(err == SQLITE_OK); - err = sqlite3_exec(g_game_db, "PRAGMA user_version = 1", NULL, NULL, NULL); + err = sqlite3_exec(g_game_db, "PRAGMA user_version = 2", NULL, NULL, NULL); assert(err == SQLITE_OK); } /* create prepared statments: */ From 75dfed808211d483dae56206a17278af16c74108 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 24 Apr 2019 12:55:41 +0200 Subject: [PATCH 25/56] Leerzeichen aus Beschreibungen trimmen. --- res/eressea/spells.xml | 2 +- src/laws.c | 16 +++++++++---- src/laws.test.c | 53 +++++++++++++++++++++++++++++++++--------- src/util/parser.c | 4 ++-- src/util/parser.h | 4 ++-- src/util/unicode.c | 2 ++ 6 files changed, 61 insertions(+), 20 deletions(-) diff --git a/res/eressea/spells.xml b/res/eressea/spells.xml index 5725b8768..a56b147ef 100644 --- a/res/eressea/spells.xml +++ b/res/eressea/spells.xml @@ -314,7 +314,7 @@ - + diff --git a/src/laws.c b/src/laws.c index f7eba8c97..fda3f434f 100644 --- a/src/laws.c +++ b/src/laws.c @@ -1488,7 +1488,7 @@ int display_cmd(unit * u, struct order *ord) { char token[128]; char **s = NULL; - const char *str; + char *str; region *r = u->region; init_order_depr(ord); @@ -1525,11 +1525,19 @@ int display_cmd(unit * u, struct order *ord) break; case P_UNIT: - unit_setinfo(u, getstrtoken()); + str = getstrtoken(); + if (str) { + unicode_utf8_trim(str); + } + unit_setinfo(u, str); break; case P_PRIVAT: - usetprivate(u, getstrtoken()); + str = getstrtoken(); + if (str) { + unicode_utf8_trim(str); + } + usetprivate(u, str); break; case P_REGION: @@ -1664,7 +1672,7 @@ int name_cmd(struct unit *u, struct order *ord) bool foreign = false; const char *str; - init_order_depr(ord); + init_order(ord, u->faction->locale); str = gettoken(token, sizeof(token)); p = findparam_ex(str, u->faction->locale); diff --git a/src/laws.test.c b/src/laws.test.c index 0896b54f3..cead8605a 100644 --- a/src/laws.test.c +++ b/src/laws.test.c @@ -221,6 +221,21 @@ static void test_display_cmd(CuTest *tc) { CuAssertStrEquals(tc, "Hodor", unit_getinfo(u)); free_order(ord); + ord = create_order(K_DISPLAY, f->locale, "%s ' Klabautermann '", LOC(f->locale, parameters[P_UNIT])); + CuAssertIntEquals(tc, 0, display_cmd(u, ord)); + CuAssertStrEquals(tc, "Klabautermann", unit_getinfo(u)); + free_order(ord); + + ord = create_order(K_DISPLAY, f->locale, "%s Hodor", LOC(f->locale, parameters[P_PRIVAT])); + CuAssertIntEquals(tc, 0, display_cmd(u, ord)); + CuAssertStrEquals(tc, "Hodor", uprivate(u)); + free_order(ord); + + ord = create_order(K_DISPLAY, f->locale, "%s ' Klabautermann '", LOC(f->locale, parameters[P_PRIVAT])); + CuAssertIntEquals(tc, 0, display_cmd(u, ord)); + CuAssertStrEquals(tc, "Klabautermann", uprivate(u)); + free_order(ord); + ord = create_order(K_DISPLAY, f->locale, LOC(f->locale, parameters[P_UNIT])); CuAssertIntEquals(tc, 0, display_cmd(u, ord)); CuAssertPtrEquals(tc, NULL, (void *)unit_getinfo(u)); @@ -940,6 +955,12 @@ static void test_name_unit(CuTest *tc) { u = setup_name_cmd(); f = u->faction; + + ord = create_order(K_NAME, f->locale, "%s ' Klabauterfrau '", LOC(f->locale, parameters[P_UNIT])); + name_cmd(u, ord); + CuAssertStrEquals(tc, "Klabauterfrau", u->_name); + free_order(ord); + ord = create_order(K_NAME, f->locale, "%s Hodor", LOC(f->locale, parameters[P_UNIT])); name_cmd(u, ord); CuAssertStrEquals(tc, "Hodor", u->_name); @@ -960,10 +981,15 @@ static void test_name_region(CuTest *tc) { order *ord; u = setup_name_cmd(); + u_set_building(u, test_create_building(u->region, NULL)); f = u->faction; + ord = create_order(K_NAME, f->locale, "%s ' Hodor Hodor '", LOC(f->locale, parameters[P_REGION])); + name_cmd(u, ord); + CuAssertStrEquals(tc, "Hodor Hodor", u->region->land->name); + free_order(ord); + ord = create_order(K_NAME, f->locale, "%s Hodor", LOC(f->locale, parameters[P_REGION])); - u_set_building(u, test_create_building(u->region, NULL)); name_cmd(u, ord); CuAssertStrEquals(tc, "Hodor", u->region->land->name); free_order(ord); @@ -980,6 +1006,7 @@ static void test_name_region(CuTest *tc) { static void test_name_building(CuTest *tc) { unit *uo, *u, *ux; faction *f; + order *ord; u = setup_name_cmd(); u->building = test_create_building(u->region, NULL); @@ -989,29 +1016,33 @@ static void test_name_building(CuTest *tc) { ux = test_create_unit(f, test_create_region(0, 0, NULL)); u_set_building(ux, u->building); - u->thisorder = create_order(K_NAME, f->locale, "%s Hodor", LOC(f->locale, parameters[P_BUILDING])); - + ord = create_order(K_NAME, f->locale, "%s ' Hodor Hodor '", LOC(f->locale, parameters[P_BUILDING])); building_set_owner(uo); - name_cmd(u, u->thisorder); + name_cmd(u, ord); CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "error148")); test_clear_messages(f); - building_set_owner(u); - name_cmd(u, u->thisorder); + name_cmd(u, ord); + CuAssertStrEquals(tc, "Hodor Hodor", u->building->name); + free_order(ord); + + ord = create_order(K_NAME, f->locale, "%s Hodor", LOC(f->locale, parameters[P_BUILDING])); + name_cmd(u, ord); CuAssertStrEquals(tc, "Hodor", u->building->name); building_setname(u->building, "Home"); building_set_owner(ux); - name_cmd(u, u->thisorder); + name_cmd(u, ord); CuAssertPtrEquals(tc, NULL, test_find_messagetype(f->msgs, "error148")); CuAssertStrEquals(tc, "Hodor", u->building->name); - test_clear_messages(f); - free_order(u->thisorder); - u->thisorder = create_order(K_NAME, f->locale, LOC(f->locale, parameters[P_BUILDING])); - name_cmd(u, u->thisorder); + free_order(ord); + + ord = create_order(K_NAME, f->locale, LOC(f->locale, parameters[P_BUILDING])); + name_cmd(u, ord); CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "error84")); CuAssertStrEquals(tc, "Hodor", u->building->name); + free_order(ord); /* TODO: test BTF_NAMECHANGE: btype->flags |= BTF_NAMECHANGE; diff --git a/src/util/parser.c b/src/util/parser.c index 3d1ba250d..bd187b5f8 100644 --- a/src/util/parser.c +++ b/src/util/parser.c @@ -233,12 +233,12 @@ const char *parse_token_depr(const char **str) return parse_token(str, pbuf, MAXTOKENSIZE); } -const char *getstrtoken(void) +char *getstrtoken(void) { return parse_token((const char **)&states->current_token, pbuf, MAXTOKENSIZE); } -const char *gettoken(char *lbuf, size_t bufsize) +char *gettoken(char *lbuf, size_t bufsize) { return parse_token((const char **)&states->current_token, lbuf, bufsize); } diff --git a/src/util/parser.h b/src/util/parser.h index a540aa2ac..329d6f654 100644 --- a/src/util/parser.h +++ b/src/util/parser.h @@ -26,8 +26,8 @@ extern "C" { void parser_pushstate(void); void parser_popstate(void); bool parser_end(void); - const char *getstrtoken(void); - const char *gettoken(char *lbuf, size_t bufsize); + char *getstrtoken(void); + char *gettoken(char *lbuf, size_t bufsize); int getuint(void); int getint(void); int getid(void); diff --git a/src/util/unicode.c b/src/util/unicode.c index 90b63205d..b4bb803dd 100644 --- a/src/util/unicode.c +++ b/src/util/unicode.c @@ -11,6 +11,7 @@ #include #include "unicode.h" +#include #include #include #include @@ -36,6 +37,7 @@ int unicode_utf8_trim(utf8_t *buf) { int result = 0, ts = 0; utf8_t *op = buf, *ip = buf, *lc = buf; + assert(buf); while (*ip) { size_t size = 1; wint_t wc = *ip; From 5acfdf5cd04f6927d5f73af900c2fa251648268f Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 24 Apr 2019 15:13:27 +0200 Subject: [PATCH 26/56] fix unused variable warning. --- src/kernel/database.test.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/kernel/database.test.c b/src/kernel/database.test.c index a84a4b286..975d98f7d 100644 --- a/src/kernel/database.test.c +++ b/src/kernel/database.test.c @@ -58,14 +58,16 @@ static void test_update_faction(CuTest *tc) { err = db_driver_faction_save(&id, f->no, faction_getemail(f), faction_getpassword(f)); + CuAssertIntEquals(tc, 0, err); CuAssertTrue(tc, 0 != id); f->uid = (int)id; db_driver_close(DB_GAME); db_driver_open(DB_GAME, NULL); - db_driver_faction_save(&id, f->no, + err = db_driver_faction_save(&id, f->no, faction_getemail(f), faction_getpassword(f)); + CuAssertIntEquals(tc, 0, err); CuAssertIntEquals(tc, f->uid, id); db_driver_close(DB_GAME); test_teardown(); From 692cdcea13cd82a5fed64f12e7c681fb863338b5 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 25 Apr 2019 08:44:48 +0200 Subject: [PATCH 27/56] Rechtschreibung Dragon Evolution: hitpoint tweaking. --- src/races/dragons.c | 2 +- src/spells/combatspells.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/races/dragons.c b/src/races/dragons.c index 5ab877c40..872893b64 100644 --- a/src/races/dragons.c +++ b/src/races/dragons.c @@ -32,9 +32,9 @@ static int age_chance(int a, int b, int p) { static void evolve_dragon(unit * u, const struct race *rc) { scale_number(u, 1); + u->hp = unit_max_hp(u); u_setrace(u, rc); u->irace = NULL; - u->hp = unit_max_hp(u); } void age_firedragon(unit * u) diff --git a/src/spells/combatspells.c b/src/spells/combatspells.c index 2eae5dc6a..e8a1be274 100644 --- a/src/spells/combatspells.c +++ b/src/spells/combatspells.c @@ -62,7 +62,7 @@ static const char *spell_damage(int sp) { switch (sp) { case 0: - /* meist toetlich 20-65 HP */ + /* meist toedlich 20-65 HP */ return "5d10+15"; case 1: /* sehr variabel 4-48 HP */ @@ -71,7 +71,7 @@ static const char *spell_damage(int sp) /* leicht verwundet 4-18 HP */ return "2d8+2"; case 3: - /* fast immer toetlich 30-50 HP */ + /* fast immer toedlich 30-50 HP */ return "5d5+25"; case 4: /* verwundet 11-26 HP */ From 2442aed1dbdce908f331bb24d9888bdcbaa74473 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 25 Apr 2019 16:31:35 +0200 Subject: [PATCH 28/56] null pointer handling for strlcpy --- src/gamedb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/gamedb.c b/src/gamedb.c index 9af580a9f..abd738ffc 100644 --- a/src/gamedb.c +++ b/src/gamedb.c @@ -17,10 +17,12 @@ static int generate_factions(void *data, db_faction *results, int nresults) faction **iter = (faction **)data; for (i = 0; *iter && i != nresults; ++i) { faction *f = *iter; + const char *pwhash; results[i].p_uid = &f->uid; results[i].no = f->no; results[i].email = faction_getemail(f); - str_strlcpy(results[i].pwhash, faction_getpassword(f), sizeof(results[i].pwhash)); + pwhash = faction_getpassword(f); + str_strlcpy(results[i].pwhash, pwhash ? pwhash : "", sizeof(results[i].pwhash)); *iter = f->next; } return i; From cffcac8af7c8904ee1f9ede68ff934ba752ed3a6 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 26 Apr 2019 23:54:22 +0200 Subject: [PATCH 29/56] fix binding faction.no to sqlite statement. --- src/kernel/db/sqlite.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/kernel/db/sqlite.c b/src/kernel/db/sqlite.c index e92f8cd57..6b88ad6c5 100644 --- a/src/kernel/db/sqlite.c +++ b/src/kernel/db/sqlite.c @@ -100,13 +100,20 @@ int db_driver_faction_save(dbrow_id * p_id, int no, const char *email, const cha { dbrow_id id = *p_id; int err; + char dbno[4]; + size_t len; + const char *str; sqlite3_stmt *stmt = (id > 0) ? g_stmt_update_faction : g_stmt_insert_faction; assert(g_game_db); err = sqlite3_reset(stmt); if (err != SQLITE_OK) return err; - err = sqlite3_bind_text(stmt, 1, itoa36(no), -1, SQLITE_STATIC); + str = itoa36(no); + len = strlen(str); + assert(len <= 4); + memcpy(dbno, str, len); + err = sqlite3_bind_text(stmt, 1, dbno, len, SQLITE_STATIC); if (err != SQLITE_OK) return err; err = sqlite3_bind_text(stmt, 2, email, -1, SQLITE_STATIC); if (err != SQLITE_OK) return err; From 968f67a567c249cac1616bd58a247559dcd6e198 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 27 Apr 2019 18:30:30 +0200 Subject: [PATCH 30/56] delete intermittent test: ents have no special guarding powers. --- scripts/eressea/wedding.lua | 2 +- scripts/tests/e2/init.lua | 6 ------ scripts/tests/economy.lua | 18 ------------------ src/bind_unit.c | 28 ++++++++++++++++++++++++++-- src/monsters.c | 2 +- 5 files changed, 28 insertions(+), 28 deletions(-) diff --git a/scripts/eressea/wedding.lua b/scripts/eressea/wedding.lua index 71664eec9..1732392fb 100644 --- a/scripts/eressea/wedding.lua +++ b/scripts/eressea/wedding.lua @@ -15,7 +15,7 @@ local function wedding_travellers(b) local units = {} for u in b.units do - if u:get_flag('wdgt') then + if u:get_key('wdgt') then units[u] = u end end diff --git a/scripts/tests/e2/init.lua b/scripts/tests/e2/init.lua index 55feab5bf..fde840f98 100644 --- a/scripts/tests/e2/init.lua +++ b/scripts/tests/e2/init.lua @@ -1,9 +1,3 @@ -function dump_messages(f) - for k, v in ipairs(f.messages) do - print(v) - end -end - require 'tests.e2.movement' require 'tests.e2.astral' require 'tests.e2.spells' diff --git a/scripts/tests/economy.lua b/scripts/tests/economy.lua index 3379b2ab7..9c72e7e70 100644 --- a/scripts/tests/economy.lua +++ b/scripts/tests/economy.lua @@ -216,21 +216,3 @@ function test_sawmill() assert_equal(6, u:get_item("log")) assert_equal(97, r:get_resource("tree")) end - -function test_ent_guards_trees() - local r = region.create(0, 0, "plain") - r:set_resource("tree", 100) - local u = unit.create(faction.create("human"), r) - u:set_skill("mining", 1) - local guard = unit.create(get_monsters(), r, 1, "ent") - u:set_skill("forestry", 1) - guard:clear_orders() - u:clear_orders() - - guard:add_order("BEWACHEN") - u:add_order("MACHE HOLZ") - process_orders() - assert_equal(1, u:get_item("log")) - process_orders() - assert_equal(1, u:get_item("log")) -end diff --git a/src/bind_unit.c b/src/bind_unit.c index d75323f0b..c5954082b 100644 --- a/src/bind_unit.c +++ b/src/bind_unit.c @@ -760,7 +760,7 @@ static int tolua_unit_has_attrib(lua_State *L) { return 1; } -static int tolua_unit_get_flag(lua_State * L) +static int tolua_unit_get_key(lua_State * L) { unit *self = (unit *)tolua_tousertype(L, 1, 0); const char *name = tolua_tostring(L, 2, 0); @@ -769,7 +769,7 @@ static int tolua_unit_get_flag(lua_State * L) return 1; } -static int tolua_unit_set_flag(lua_State * L) +static int tolua_unit_set_key(lua_State * L) { unit *self = (unit *)tolua_tousertype(L, 1, 0); const char *name = tolua_tostring(L, 2, 0); @@ -784,6 +784,28 @@ static int tolua_unit_set_flag(lua_State * L) return 0; } +static int tolua_unit_get_flag(lua_State * L) +{ + unit *self = (unit *)tolua_tousertype(L, 1, NULL); + int bit = (int)tolua_tonumber(L, 2, 0); + + lua_pushboolean(L, (self->flags & (1 << bit))); + return 1; +} + +static int tolua_unit_set_flag(lua_State * L) +{ + unit *self = (unit *)tolua_tousertype(L, 1, NULL); + int bit = (int)tolua_tonumber(L, 2, 0); + int set = tolua_toboolean(L, 3, 1); + + if (set) + self->flags |= (1 << bit); + else + self->flags &= ~(1 << bit); + return 0; +} + static int tolua_unit_get_weight(lua_State * L) { unit *self = (unit *)tolua_tousertype(L, 1, 0); @@ -959,6 +981,8 @@ void tolua_unit_open(lua_State * L) tolua_function(L, TOLUA_CAST "has_attrib", tolua_unit_has_attrib); /* key-attributes for named flags: */ + tolua_function(L, TOLUA_CAST "set_key", tolua_unit_set_key); + tolua_function(L, TOLUA_CAST "get_key", tolua_unit_get_key); tolua_function(L, TOLUA_CAST "set_flag", tolua_unit_set_flag); tolua_function(L, TOLUA_CAST "get_flag", tolua_unit_get_flag); tolua_variable(L, TOLUA_CAST "guard", tolua_unit_get_guard, diff --git a/src/monsters.c b/src/monsters.c index 290cbdb87..535e03166 100644 --- a/src/monsters.c +++ b/src/monsters.c @@ -442,7 +442,7 @@ static order *monster_move(region * r, unit * u) if (fval(u_race(u), RCF_DRAGON)) { d = richest_neighbour(r, u->faction, 1); } - else if (get_race(RC_TREEMAN)==u_race(u)) { + else if (get_race(RC_TREEMAN) == u_race(u)) { d = treeman_neighbour(r); } else { From bbcb2113d79380916aaff8a9ddd89e5db4165eb0 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 30 Apr 2019 18:40:24 +0200 Subject: [PATCH 31/56] WIP feature: STIRB [PARTEI ] --- res/core/messages.xml | 14 ------------- res/translations/messages.de.po | 8 +------ res/translations/messages.en.po | 8 +------ src/laws.c | 37 ++++++++++++++++++++++++++++++--- src/randenc.c | 3 +-- src/spells.c | 4 ++-- 6 files changed, 39 insertions(+), 35 deletions(-) diff --git a/res/core/messages.xml b/res/core/messages.xml index 7028ab6b9..4de8b0299 100644 --- a/res/core/messages.xml +++ b/res/core/messages.xml @@ -2937,13 +2937,6 @@ - - - - - - - @@ -3244,13 +3237,6 @@ - - - - - - - diff --git a/res/translations/messages.de.po b/res/translations/messages.de.po index 57b4426ef..c24966d6a 100644 --- a/res/translations/messages.de.po +++ b/res/translations/messages.de.po @@ -587,9 +587,6 @@ msgstr "\"$unit($unit) in $region($region): '$order($command)' - Unbekannte Opti msgid "error131" msgstr "\"$unit($unit) in $region($region): '$order($command)' - Um in Gletschern StraĂŸen bauen zu können, muĂŸ zuerst ein Tunnel errichtet werden.\"" -msgid "error241" -msgstr "\"$unit($unit) in $region($region): '$order($command)' - Die Partei muĂŸ mindestens 81 Wochen alt sein, um einen Neustart mit einer anderen Rasse zu versuchen.\"" - msgid "feedback_unit_not_found" msgstr "\"$unit($unit) in $region($region): '$order($command)' - Die Einheit wurde nicht gefunden.\"" @@ -1119,7 +1116,7 @@ msgid "dissolve_units_4" msgstr "\"$unit($unit) in $region($region): $int($number) $race($race,$number) $if($eq($number,1),\"zerfiel\", \"zerfielen\") zu Staub.\"" msgid "error281" -msgstr "\"$unit($unit) in $region($region): '$order($command)' - Gegen welche Rasse soll der Jihad ausgerufen werden?\"" +msgstr "\"$unit($unit) in $region($region): '$order($command)' - Die Zielpartei muss die selbe Rasse haben.\"" msgid "error171" msgstr "\"$unit($unit) in $region($region): '$order($command)' - Diesen Kampfzauber gibt es nicht.\"" @@ -1784,9 +1781,6 @@ msgstr "\"$unit($unit) in $region($region): '$order($command)' - Es konnte kein msgid "error50" msgstr "\"$unit($unit) in $region($region): '$order($command)' - Die Einheit ist nicht erfahren genug dafĂ¼r.\"" -msgid "error282" -msgstr "\"$unit($unit) in $region($region): '$order($command)' - Gegen diese Rasse kann kein Jihad ausgerufen werden.\"" - msgid "nmr_warning_final" msgstr "\"Bitte sende die Befehle nächste Runde ein, wenn du weiterspielen möchtest.\"" diff --git a/res/translations/messages.en.po b/res/translations/messages.en.po index 060fe09c2..1f1db551c 100644 --- a/res/translations/messages.en.po +++ b/res/translations/messages.en.po @@ -587,9 +587,6 @@ msgstr "\"$unit($unit) in $region($region): '$order($command)' - Unknown option. msgid "error131" msgstr "\"$unit($unit) in $region($region): '$order($command)' - You must build a tunnel before building roads through glaciers.\"" -msgid "error241" -msgstr "\"$unit($unit) in $region($region): '$order($command)' - The faction must be at least 81 weeks old to restart with a new race.\"" - msgid "feedback_unit_not_found" msgstr "\"$unit($unit) in $region($region): '$order($command)' - The unit could not be found.\"" @@ -1119,7 +1116,7 @@ msgid "dissolve_units_4" msgstr "\"$unit($unit) in $region($region): $int($number) $race($race,$number) turned to dust.\"" msgid "error281" -msgstr "\"$unit($unit) in $region($region): '$order($command)' - What race did you want the jihad to be against?\"" +msgstr "\"$unit($unit) in $region($region): '$order($command)' - The target faction must have the same race as yours.\"" msgid "error171" msgstr "\"$unit($unit) in $region($region): '$order($command)' - This combat spell does not exist.\"" @@ -1784,9 +1781,6 @@ msgstr "\"$unit($unit) in $region($region): '$order($command)' - No peasant coul msgid "error50" msgstr "\"$unit($unit) in $region($region): '$order($command)' - The unit is not experienced enough to do this.\"" -msgid "error282" -msgstr "\"$unit($unit) in $region($region): '$order($command)' - You cannot start a jihad against this race.\"" - msgid "nmr_warning_final" msgstr "\"Please send in orders for the next turn if you want to continue playing.\"" diff --git a/src/laws.c b/src/laws.c index fda3f434f..d6c754f08 100644 --- a/src/laws.c +++ b/src/laws.c @@ -395,8 +395,7 @@ static void peasants(region * r, int rule) dead += (int)(0.5 + n * PEASANT_STARVATION_CHANCE); if (dead > 0) { - message *msg = add_message(&r->msgs, msg_message("phunger", "dead", dead)); - msg_release(msg); + ADDMSG(&r->msgs, msg_message("phunger", "dead", dead)); peasants -= dead; } @@ -941,6 +940,10 @@ int leave_cmd(unit * u, struct order *ord) return 0; } +int transfer_faction(faction *fsrc, faction *fdst) { + return 0; +} + int quit_cmd(unit * u, struct order *ord) { char token[128]; @@ -952,6 +955,34 @@ int quit_cmd(unit * u, struct order *ord) assert(kwd == K_QUIT); passwd = gettoken(token, sizeof(token)); if (checkpasswd(f, (const char *)passwd)) { + param_t p; + p = getparam(f->locale); + if (p == P_FACTION) { + faction *f2 = getfaction(); + if (f2 == NULL) { + cmistake(u, ord, 66, MSG_EVENT); + } + else if (f->race != f2->race) { + cmistake(u, ord, 281, MSG_EVENT); + } + else { + unit *u2; + for (u2 = u->region->units; u2; u2 = u2->next) { + if (u2->faction == f2 && ucontact(u2, u)) { + int err = transfer_faction(u->faction, u2->faction); + if (err != 0) { + /* something went wrong */ + cmistake(u, ord, err, MSG_EVENT); + } + break; + } + } + if (u2 == NULL) { + /* no target unit found */ + cmistake(u, ord, 0, MSG_EVENT); + } + } + } fset(f, FFL_QUIT); } else { @@ -2077,7 +2108,7 @@ int banner_cmd(unit * u, struct order *ord) init_order_depr(ord); s = getstrtoken(); faction_setbanner(u->faction, s); - add_message(&u->faction->msgs, msg_message("changebanner", "value", s)); + ADDMSG(&u->faction->msgs, msg_message("changebanner", "value", s)); return 0; } diff --git a/src/randenc.c b/src/randenc.c index b0e5dd13a..9c3fd4739 100644 --- a/src/randenc.c +++ b/src/randenc.c @@ -603,8 +603,7 @@ void plagues(region * r) } if (dead > 0) { - message *msg = add_message(&r->msgs, msg_message("pest", "dead", dead)); - msg_release(msg); + ADDMSG(&r->msgs, msg_message("pest", "dead", dead)); deathcounts(r, dead); rsetpeasants(r, peasants - dead); } diff --git a/src/spells.c b/src/spells.c index 5e2474861..83b7f2050 100644 --- a/src/spells.c +++ b/src/spells.c @@ -3110,8 +3110,8 @@ static int sp_chaossuction(castorder * co) create_special_direction(rt, r, 2, "vortex_desc", "vortex", false); new_border(&bt_chaosgate, r, rt); - add_message(&r->msgs, msg_message("chaosgate_effect_1", "mage", caster)); - add_message(&rt->msgs, msg_message("chaosgate_effect_2", "")); + ADDMSG(&r->msgs, msg_message("chaosgate_effect_1", "mage", caster)); + ADDMSG(&rt->msgs, msg_message("chaosgate_effect_2", "")); return cast_level; } From b13deb2b046528181ff5b5e497f689c536234abf Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 30 Apr 2019 22:06:08 +0200 Subject: [PATCH 32/56] test maximum shipspeed with all modifiers --- src/kernel/ship.test.c | 43 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/src/kernel/ship.test.c b/src/kernel/ship.test.c index 180b558a2..71282cbd8 100644 --- a/src/kernel/ship.test.c +++ b/src/kernel/ship.test.c @@ -470,7 +470,7 @@ static void test_shipspeed_stormwind(CuTest *tc) { test_setup(); sh = setup_ship(); - setup_crew(sh, 0, &cap, &crew); + setup_crew(sh, NULL, &cap, &crew); register_shipcurse(); assert(sh && cap && crew); @@ -488,7 +488,7 @@ static void test_shipspeed_nodrift(CuTest *tc) { test_setup(); sh = setup_ship(); - setup_crew(sh, 0, &cap, &crew); + setup_crew(sh, NULL, &cap, &crew); register_shipcurse(); assert(sh && cap && crew); @@ -503,7 +503,7 @@ static void test_shipspeed_shipspeedup(CuTest *tc) { test_setup(); sh = setup_ship(); - setup_crew(sh, 0, &cap, &crew); + setup_crew(sh, NULL, &cap, &crew); register_shipcurse(); assert(sh && cap && crew); @@ -519,7 +519,7 @@ static void test_shipspeed_at_speedup(CuTest *tc) { test_setup(); sh = setup_ship(); - setup_crew(sh, 0, &cap, &crew); + setup_crew(sh, NULL, &cap, &crew); assert(sh && cap && crew); a = a_new(&at_speedup); @@ -536,7 +536,7 @@ static void test_shipspeed_race_bonus(CuTest *tc) { test_setup(); sh = setup_ship(); - setup_crew(sh, 0, &cap, &crew); + setup_crew(sh, NULL, &cap, &crew); assert(sh && cap && crew); rc = rc_get_or_create(cap->_race->_name); @@ -551,7 +551,7 @@ static void test_shipspeed_damage(CuTest *tc) { test_setup(); sh = setup_ship(); - setup_crew(sh, 0, &cap, &crew); + setup_crew(sh, NULL, &cap, &crew); assert(sh && cap && crew); sh->damage = 1; @@ -563,6 +563,32 @@ static void test_shipspeed_damage(CuTest *tc) { test_teardown(); } +static void test_maximum_shipspeed(CuTest *tc) { + ship *sh; + unit *cap, *crew; + race *rc; + struct faction *f; + attrib *a; + + test_setup(); + sh = setup_ship(); + rc = test_create_race("aquarian"); + rc->flags |= RCF_SHIPSPEED; + f = test_create_faction(rc); + setup_crew(sh, f, &cap, &crew); + CuAssertIntEquals(tc, sh->type->range + 1, shipspeed(sh, cap)); + create_curse(0, &sh->attribs, &ct_stormwind, 1, 1, 1, 0); + CuAssertIntEquals(tc, 2 * sh->type->range + 1, shipspeed(sh, cap)); + create_curse(0, &sh->attribs, &ct_nodrift, 1, 1, 1, 0); + CuAssertIntEquals(tc, 2 * sh->type->range + 2, shipspeed(sh, cap)); + a = a_new(&at_speedup); + a->data.i = 3; + a_add(&sh->attribs, a); + CuAssertIntEquals(tc, 2 * sh->type->range + 5, shipspeed(sh, cap)); + create_curse(0, &sh->attribs, &ct_shipspeedup, 1, 1, 4, 0); + CuAssertIntEquals(tc, 2 * sh->type->range + 9, shipspeed(sh, cap)); +} + static void test_shipspeed(CuTest *tc) { ship *sh; const ship_type *stype; @@ -574,7 +600,7 @@ static void test_shipspeed(CuTest *tc) { CuAssertIntEquals_Msg(tc, "ship without a captain cannot move", 0, shipspeed(sh, NULL)); - setup_crew(sh, 0, &cap, &crew); + setup_crew(sh, NULL, &cap, &crew); CuAssertPtrEquals(tc, cap, ship_owner(sh)); CuAssertIntEquals_Msg(tc, "ship with fully skilled crew can sail at max speed", 2, shipspeed(sh, cap)); @@ -603,7 +629,7 @@ static void test_shipspeed_max_range(CuTest *tc) { test_setup(); sh = setup_ship(); - setup_crew(sh, 0, &cap, &crew); + setup_crew(sh, NULL, &cap, &crew); config_set("movement.shipspeed.skillbonus", "5"); r = sh->region; f = test_create_faction(NULL); @@ -649,5 +675,6 @@ CuSuite *get_ship_suite(void) SUITE_ADD_TEST(suite, test_shipspeed_race_bonus); SUITE_ADD_TEST(suite, test_shipspeed_damage); SUITE_ADD_TEST(suite, test_shipspeed_max_range); + SUITE_ADD_TEST(suite, test_maximum_shipspeed); return suite; } From 7b3b792d01028fe88d05a034fe3eaab63ac351f7 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 1 May 2019 20:08:14 +0200 Subject: [PATCH 33/56] Nicht Sonnensegel verhindert Sturmelementar, sondern Sturmelementar verhindert Sturmelementar. --- src/spells.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/spells.c b/src/spells.c index 5e2474861..c9fe2fb4b 100644 --- a/src/spells.c +++ b/src/spells.c @@ -2242,13 +2242,12 @@ static int sp_stormwinds(castorder * co) sh = pa->param[n]->data.sh; - /* mit C_SHIP_NODRIFT haben wir kein Problem */ if (is_cursed(sh->attribs, &ct_flyingship)) { ADDMSG(&caster->faction->msgs, msg_feedback(caster, co->order, "error_spell_on_flying_ship", "ship", sh)) continue; } - if (is_cursed(sh->attribs, &ct_shipspeedup)) { + if (is_cursed(sh->attribs, &ct_stormwind)) { ADDMSG(&caster->faction->msgs, msg_feedback(caster, co->order, "error_spell_on_ship_already", "ship", sh)) continue; From 0daa0ec04eb90b21f47852a8110c17ff13e7305a Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 1 May 2019 20:10:20 +0200 Subject: [PATCH 34/56] Rechtschreibung --- res/translations/messages.de.po | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/translations/messages.de.po b/res/translations/messages.de.po index 57b4426ef..c6daf3f4e 100644 --- a/res/translations/messages.de.po +++ b/res/translations/messages.de.po @@ -105,7 +105,7 @@ msgid "massive_overload" msgstr "\"Die $ship($ship) ist zu stark Ă¼berladen und wird stark beschädigt.\"" msgid "curseinfo::shipspeedup" -msgstr "\"Die Winde scheinen dieses Schiff besonders zu beguenstigen. ($int36($id))\"" +msgstr "\"Die Winde scheinen dieses Schiff besonders zu begĂ¼nstigen. ($int36($id))\"" msgid "error152" msgstr "\"$unit($unit) in $region($region): '$order($command)' - Die Einheit springt Ă¼ber Bord und ertrinkt.\"" @@ -1002,7 +1002,7 @@ msgid "battle_critical" msgstr "\"$int36($unit.id($unit))/$int($index) erzielt einen kritischen Treffer.\"" msgid "error_spell_on_ship_already" -msgstr "\"$unit($unit) in $region($region): '$order($command)' - Auf $ship($ship) liegt beeits ein Zauber.\"" +msgstr "\"$unit($unit) in $region($region): '$order($command)' - Auf $ship($ship) liegt bereits ein Zauber.\"" msgid "error228" msgstr "\"$unit($unit) in $region($region): '$order($command)' - Nur normale Personen können Steuern eintreiben.\"" From 6637c9485298c63fcb456eef2160bca4e953dcc3 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 1 May 2019 20:46:26 +0200 Subject: [PATCH 35/56] do not allow transfer of heros and limited units. --- src/give.c | 32 ++++++++++++++----------- src/give.h | 2 ++ src/laws.c | 62 ++++++++++++++++++++++++++++--------------------- src/laws.test.c | 46 ++++++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 40 deletions(-) diff --git a/src/give.c b/src/give.c index c6e77aa68..5f9127b23 100644 --- a/src/give.c +++ b/src/give.c @@ -299,7 +299,7 @@ static bool can_give_men(const unit *u, const unit *dst, order *ord, message **m return false; } -static bool rule_transfermen(void) +bool rule_transfermen(void) { int rule = config_get_int("rules.transfermen", 1); return rule != 0; @@ -472,9 +472,23 @@ message * disband_men(int n, unit * u, struct order *ord) { return msg_message("give_person_peasants", "unit amount", u, n); } +int give_unit_allowed(const unit * u) +{ + if (unit_has_cursed_item(u)) { + return 78; + } + if (fval(u, UFL_HERO)) { + return 75; + } + if (fval(u, UFL_LOCKED) || fval(u, UFL_HUNGER)) { + return 74; + } + return 0; +} + void give_unit(unit * u, unit * u2, order * ord) { - int maxt = max_transfers(); + int err, maxt = max_transfers(); assert(u); if (!rule_transfermen() && u2 && u->faction != u2->faction) { @@ -482,17 +496,9 @@ void give_unit(unit * u, unit * u2, order * ord) return; } - if (unit_has_cursed_item(u)) { - cmistake(u, ord, 78, MSG_COMMERCE); - return; - } - - if (fval(u, UFL_HERO)) { - cmistake(u, ord, 75, MSG_COMMERCE); - return; - } - if (fval(u, UFL_LOCKED) || fval(u, UFL_HUNGER)) { - cmistake(u, ord, 74, MSG_COMMERCE); + err = give_unit_allowed(u); + if (err != 0) { + cmistake(u, ord, err, MSG_COMMERCE); return; } diff --git a/src/give.h b/src/give.h index 94eee729c..4d44790a7 100644 --- a/src/give.h +++ b/src/give.h @@ -29,10 +29,12 @@ extern "C" { struct message * disband_men(int n, struct unit * u, struct order *ord); struct message * give_men(int n, struct unit *u, struct unit *u2, struct order *ord); + int give_unit_allowed(const struct unit * u); void give_unit(struct unit *u, struct unit *u2, struct order *ord); void give_cmd(struct unit * u, struct order * ord); struct message * check_give(const struct unit * u, const struct unit * u2, struct order *ord); bool can_give_to(struct unit *u, struct unit *u2); + bool rule_transfermen(void); #ifdef __cplusplus } diff --git a/src/laws.c b/src/laws.c index d6c754f08..9e9e337b1 100644 --- a/src/laws.c +++ b/src/laws.c @@ -30,6 +30,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "battle.h" #include "contact.h" #include "economy.h" +#include "give.h" #include "market.h" #include "morale.h" #include "monsters.h" @@ -940,8 +941,13 @@ int leave_cmd(unit * u, struct order *ord) return 0; } -int transfer_faction(faction *fsrc, faction *fdst) { - return 0; +void transfer_faction(faction *fsrc, faction *fdst) { + unit *u; + for (u = fsrc->units; u != NULL; u = u->nextF) { + if (give_unit_allowed(u) == 0) { + u_setfaction(u, fdst); + } + } } int quit_cmd(unit * u, struct order *ord) @@ -955,35 +961,37 @@ int quit_cmd(unit * u, struct order *ord) assert(kwd == K_QUIT); passwd = gettoken(token, sizeof(token)); if (checkpasswd(f, (const char *)passwd)) { - param_t p; - p = getparam(f->locale); - if (p == P_FACTION) { - faction *f2 = getfaction(); - if (f2 == NULL) { - cmistake(u, ord, 66, MSG_EVENT); - } - else if (f->race != f2->race) { - cmistake(u, ord, 281, MSG_EVENT); - } - else { - unit *u2; - for (u2 = u->region->units; u2; u2 = u2->next) { - if (u2->faction == f2 && ucontact(u2, u)) { - int err = transfer_faction(u->faction, u2->faction); - if (err != 0) { - /* something went wrong */ - cmistake(u, ord, err, MSG_EVENT); - } - break; - } + int flags = FFL_QUIT; + if (rule_transfermen()) { + param_t p; + p = getparam(f->locale); + if (p == P_FACTION) { + faction *f2 = getfaction(); + if (f2 == NULL) { + cmistake(u, ord, 66, MSG_EVENT); + flags = 0; } - if (u2 == NULL) { - /* no target unit found */ - cmistake(u, ord, 0, MSG_EVENT); + else if (f->race != f2->race) { + cmistake(u, ord, 281, MSG_EVENT); + flags = 0; + } + else { + unit *u2; + for (u2 = u->region->units; u2; u2 = u2->next) { + if (u2->faction == f2 && ucontact(u2, u)) { + transfer_faction(u->faction, u2->faction); + break; + } + } + if (u2 == NULL) { + /* no target unit found */ + cmistake(u, ord, 0, MSG_EVENT); + flags = 0; + } } } } - fset(f, FFL_QUIT); + f->flags |= flags; } else { char buffer[64]; diff --git a/src/laws.test.c b/src/laws.test.c index cead8605a..573e1a486 100644 --- a/src/laws.test.c +++ b/src/laws.test.c @@ -1,6 +1,7 @@ #include #include "laws.h" #include "battle.h" +#include "contact.h" #include "guard.h" #include "monsters.h" @@ -1868,6 +1869,49 @@ static void test_long_order_on_ocean(CuTest *tc) { test_teardown(); } +static void test_quit(CuTest *tc) { + faction *f; + unit *u; + region *r; + + test_setup(); + r = test_create_plain(0, 0); + f = test_create_faction(NULL); + u = test_create_unit(f, r); + u->thisorder = create_order(K_QUIT, f->locale, "password"); + + faction_setpassword(f, "passwort"); + quit_cmd(u, u->thisorder); + CuAssertIntEquals(tc, 0, f->flags & FFL_QUIT); + + faction_setpassword(f, "password"); + quit_cmd(u, u->thisorder); + CuAssertIntEquals(tc, FFL_QUIT, f->flags & FFL_QUIT); + + test_teardown(); +} + +static void test_quit_transfer(CuTest *tc) { + faction *f1, *f2; + unit *u1, *u2; + region *r; + + test_setup(); + r = test_create_plain(0, 0); + f1 = test_create_faction(NULL); + faction_setpassword(f1, "password"); + u1 = test_create_unit(f1, r); + f2 = test_create_faction(NULL); + u2 = test_create_unit(f2, r); + contact_unit(u2, u1); + u1->thisorder = create_order(K_QUIT, f1->locale, "password %s %s", + LOC(f1->locale, parameters[P_FACTION]), itoa36(f2->no)); + quit_cmd(u1, u1->thisorder); + CuAssertIntEquals(tc, FFL_QUIT, f1->flags & FFL_QUIT); + CuAssertPtrEquals(tc, f2, u1->faction); + test_teardown(); +} + CuSuite *get_laws_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -1943,6 +1987,8 @@ CuSuite *get_laws_suite(void) SUITE_ADD_TEST(suite, test_nmr_timeout); SUITE_ADD_TEST(suite, test_long_orders); SUITE_ADD_TEST(suite, test_long_order_on_ocean); + SUITE_ADD_TEST(suite, test_quit); + SUITE_ADD_TEST(suite, test_quit_transfer); return suite; } From 8605409ed38db73be777b9c6185b75a8ce0f99c5 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 4 May 2019 10:45:51 +0200 Subject: [PATCH 36/56] limited-skill units are only transferred up to the limit. --- src/economy.c | 2 +- src/give.c | 12 ++++++------ src/kernel/build.c | 2 +- src/kernel/faction.c | 6 +++--- src/kernel/faction.h | 4 ++-- src/kernel/faction.test.c | 22 ++++++++++++++++++++++ src/kernel/unit.c | 22 ++++++++++++++++------ src/kernel/unit.h | 1 + src/laws.c | 34 ++++++++++++++++++++++++++++++++++ src/laws.test.c | 35 +++++++++++++++++++++++++++++++++++ src/spells.c | 2 +- src/study.c | 8 ++++---- 12 files changed, 126 insertions(+), 24 deletions(-) diff --git a/src/economy.c b/src/economy.c index ec6986dd6..efca9ce5c 100644 --- a/src/economy.c +++ b/src/economy.c @@ -548,7 +548,7 @@ static void recruit(unit * u, struct order *ord, econ_request ** recruitorders) return; } if (has_skill(u, SK_ALCHEMY)) { - if (count_skill(u->faction, SK_ALCHEMY) + n > skill_limit(u->faction, SK_ALCHEMY)) { + if (faction_count_skill(u->faction, SK_ALCHEMY) + n > faction_skill_limit(u->faction, SK_ALCHEMY)) { cmistake(u, ord, 156, MSG_EVENT); return; } diff --git a/src/give.c b/src/give.c index 5f9127b23..64fa39504 100644 --- a/src/give.c +++ b/src/give.c @@ -391,7 +391,7 @@ message * give_men(int n, unit * u, unit * u2, struct order *ord) } if (has_skill(u, SK_ALCHEMY) || has_skill(u2, SK_ALCHEMY)) { - int k = count_skill(u2->faction, SK_ALCHEMY); + int k = faction_count_skill(u2->faction, SK_ALCHEMY); /* Falls die Zieleinheit keine Alchemisten sind, werden sie nun * welche. */ @@ -408,7 +408,7 @@ message * give_men(int n, unit * u, unit * u2, struct order *ord) /* wird das Alchemistenmaximum ueberschritten ? */ - if (k > skill_limit(u2->faction, SK_ALCHEMY)) { + if (k > faction_skill_limit(u2->faction, SK_ALCHEMY)) { error = 156; } } @@ -592,8 +592,8 @@ void give_unit(unit * u, unit * u2, order * ord) } } if (has_skill(u, SK_MAGIC)) { - if (count_skill(u2->faction, SK_MAGIC) + u->number > - skill_limit(u2->faction, SK_MAGIC)) { + if (faction_count_skill(u2->faction, SK_MAGIC) + u->number > + faction_skill_limit(u2->faction, SK_MAGIC)) { cmistake(u, ord, 155, MSG_COMMERCE); return; } @@ -603,8 +603,8 @@ void give_unit(unit * u, unit * u2, order * ord) } } if (has_skill(u, SK_ALCHEMY) - && count_skill(u2->faction, SK_ALCHEMY) + u->number > - skill_limit(u2->faction, SK_ALCHEMY)) { + && faction_count_skill(u2->faction, SK_ALCHEMY) + u->number > + faction_skill_limit(u2->faction, SK_ALCHEMY)) { cmistake(u, ord, 156, MSG_COMMERCE); return; } diff --git a/src/kernel/build.c b/src/kernel/build.c index 0475c607e..a5eb0a6db 100644 --- a/src/kernel/build.c +++ b/src/kernel/build.c @@ -572,7 +572,7 @@ static int build_limited(unit * u, const construction * con, int completed, int } /* Flinkfingerring wirkt nicht auf Mengenbegrenzte (magische) * Talente */ - if (skill_limit(u->faction, con->skill) == INT_MAX) { + if (faction_skill_limit(u->faction, con->skill) == INT_MAX) { const resource_type *ring = get_resourcetype(R_RING_OF_NIMBLEFINGER); item *itm = ring ? *i_find(&u->items, ring->itype) : 0; int i = itm ? itm->number : 0; diff --git a/src/kernel/faction.c b/src/kernel/faction.c index 238ba834b..beec40e0a 100755 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -609,7 +609,7 @@ static int allied_skillcount(const faction * f, skill_t sk) for (qi = 0; members; selist_advance(&members, &qi, 1)) { faction *m = (faction *)selist_get(members, qi); - num += count_skill(m, sk); + num += faction_count_skill(m, sk); } return num; } @@ -623,7 +623,7 @@ static int allied_skilllimit(const faction * f, skill_t sk) return value; } -int count_skill(faction * f, skill_t sk) +int faction_count_skill(faction * f, skill_t sk) { int n = 0; unit *u; @@ -638,7 +638,7 @@ int count_skill(faction * f, skill_t sk) return n; } -int skill_limit(faction * f, skill_t sk) +int faction_skill_limit(const faction * f, skill_t sk) { int m = INT_MAX; int al = allied_skilllimit(f, sk); diff --git a/src/kernel/faction.h b/src/kernel/faction.h index cbe4c7008..d22e9ee22 100644 --- a/src/kernel/faction.h +++ b/src/kernel/faction.h @@ -161,8 +161,8 @@ extern "C" { struct spellbook * faction_get_spellbook(struct faction *f); /* skills */ - int skill_limit(struct faction *f, skill_t sk); - int count_skill(struct faction *f, skill_t sk); + int faction_skill_limit(const struct faction *f, skill_t sk); + int faction_count_skill(struct faction *f, skill_t sk); bool faction_id_is_unused(int); #define COUNT_MONSTERS 0x01 diff --git a/src/kernel/faction.test.c b/src/kernel/faction.test.c index 65310ee3a..e572cf312 100644 --- a/src/kernel/faction.test.c +++ b/src/kernel/faction.test.c @@ -25,6 +25,7 @@ #include #include +#include static void test_destroyfaction_allies(CuTest *tc) { faction *f1, *f2; @@ -211,6 +212,26 @@ static void test_max_migrants(CuTest *tc) { test_teardown(); } +static void test_skill_limit(CuTest *tc) { + faction *f; + + test_setup(); + f = test_create_faction(NULL); + CuAssertIntEquals(tc, INT_MAX, faction_skill_limit(f, SK_ENTERTAINMENT)); + CuAssertIntEquals(tc, 3, faction_skill_limit(f, SK_ALCHEMY)); + config_set_int("rules.maxskills.alchemy", 4); + CuAssertIntEquals(tc, 4, faction_skill_limit(f, SK_ALCHEMY)); + CuAssertIntEquals(tc, 3, faction_skill_limit(f, SK_MAGIC)); + CuAssertIntEquals(tc, 3, max_magicians(f)); + config_set_int("rules.maxskills.magic", 4); + CuAssertIntEquals(tc, 4, faction_skill_limit(f, SK_MAGIC)); + CuAssertIntEquals(tc, 4, max_magicians(f)); + f->race = test_create_race(racenames[RC_ELF]); + CuAssertIntEquals(tc, 5, faction_skill_limit(f, SK_MAGIC)); + CuAssertIntEquals(tc, 5, max_magicians(f)); + test_teardown(); +} + static void test_valid_race(CuTest *tc) { race * rc1, *rc2; faction *f; @@ -334,6 +355,7 @@ CuSuite *get_faction_suite(void) CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_addplayer); SUITE_ADD_TEST(suite, test_max_migrants); + SUITE_ADD_TEST(suite, test_skill_limit); SUITE_ADD_TEST(suite, test_addfaction); SUITE_ADD_TEST(suite, test_remove_empty_factions); SUITE_ADD_TEST(suite, test_destroyfaction_allies); diff --git a/src/kernel/unit.c b/src/kernel/unit.c index c1e9264b9..23bcc9982 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -1812,17 +1812,27 @@ int maintenance_cost(const struct unit *u) return u_race(u)->maintenance * u->number; } -static skill_t limited_skills[] = { SK_MAGIC, SK_ALCHEMY, SK_TACTICS, SK_SPY, SK_HERBALISM, NOSKILL }; +static skill_t limited_skills[] = { SK_ALCHEMY, SK_HERBALISM, SK_MAGIC, SK_SPY, SK_TACTICS, NOSKILL }; + +bool is_limited_skill(skill_t sk) +{ + int i; + for (i = 0; limited_skills[i] != NOSKILL; ++i) { + if (sk == limited_skills[i]) { + return true; + } + } + return false; +} + bool has_limited_skills(const struct unit * u) { - int i, j; + int i; for (i = 0; i != u->skill_size; ++i) { skill *sv = u->skills + i; - for (j = 0; limited_skills[j] != NOSKILL; ++j) { - if (sv->id == limited_skills[j]) { - return true; - } + if (is_limited_skill(sv->id)) { + return true; } } return false; diff --git a/src/kernel/unit.h b/src/kernel/unit.h index 46746e3a1..fc5602694 100644 --- a/src/kernel/unit.h +++ b/src/kernel/unit.h @@ -251,6 +251,7 @@ extern "C" { bool has_horses(const struct unit *u); int maintenance_cost(const struct unit *u); bool has_limited_skills(const struct unit *u); + bool is_limited_skill(skill_t sk); #ifdef __cplusplus } diff --git a/src/laws.c b/src/laws.c index 9e9e337b1..f1e69b231 100644 --- a/src/laws.c +++ b/src/laws.c @@ -943,8 +943,42 @@ int leave_cmd(unit * u, struct order *ord) void transfer_faction(faction *fsrc, faction *fdst) { unit *u; + skill_t sk; + int skill_count[MAXSKILLS]; + int skill_limit[MAXSKILLS]; + + for (sk = 0; sk != MAXSKILLS; ++sk) { + skill_limit[sk] = faction_skill_limit(fdst, sk); + } + memset(skill_count, 0, sizeof(skill_count)); + + for (u = fdst->units; u != NULL; u = u->nextF) { + if (u->skills) { + int i; + for (i = 0; i != u->skill_size; ++i) { + const skill *sv = u->skills + i; + skill_t sk = (skill_t)sv->id; + skill_count[sk] += u->number; + } + } + } + for (u = fsrc->units; u != NULL; u = u->nextF) { if (give_unit_allowed(u) == 0) { + if (u->skills) { + int i; + + for (i = 0; i != u->skill_size; ++i) { + const skill *sv = u->skills + i; + skill_t sk = (skill_t)sv->id; + if (skill_count[sk] + u->number > skill_limit[sk]) { + break; + } + } + if (i != u->skill_size) { + continue; + } + } u_setfaction(u, fdst); } } diff --git a/src/laws.test.c b/src/laws.test.c index 573e1a486..f82ec52e5 100644 --- a/src/laws.test.c +++ b/src/laws.test.c @@ -1912,6 +1912,40 @@ static void test_quit_transfer(CuTest *tc) { test_teardown(); } +static void test_quit_transfer_limited(CuTest *tc) { + faction *f1, *f2; + unit *u1, *u2; + region *r; + + test_setup(); + r = test_create_plain(0, 0); + f1 = test_create_faction(NULL); + faction_setpassword(f1, "password"); + u1 = test_create_unit(f1, r); + f2 = test_create_faction(NULL); + u2 = test_create_unit(f2, r); + contact_unit(u2, u1); + u1->thisorder = create_order(K_QUIT, f1->locale, "password %s %s", + LOC(f1->locale, parameters[P_FACTION]), itoa36(f2->no)); + + set_level(u1, SK_MAGIC, 1); + set_level(u2, SK_MAGIC, 1); + CuAssertIntEquals(tc, true, has_limited_skills(u1)); + + config_set_int("rules.maxskills.magic", 1); + quit_cmd(u1, u1->thisorder); + CuAssertIntEquals(tc, FFL_QUIT, f1->flags & FFL_QUIT); + CuAssertPtrEquals(tc, f1, u1->faction); + + f1->flags -= FFL_QUIT; + config_set_int("rules.maxskills.magic", 2); + quit_cmd(u1, u1->thisorder); + CuAssertIntEquals(tc, FFL_QUIT, f1->flags & FFL_QUIT); + CuAssertPtrEquals(tc, f2, u1->faction); + + test_teardown(); +} + CuSuite *get_laws_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -1989,6 +2023,7 @@ CuSuite *get_laws_suite(void) SUITE_ADD_TEST(suite, test_long_order_on_ocean); SUITE_ADD_TEST(suite, test_quit); SUITE_ADD_TEST(suite, test_quit_transfer); + SUITE_ADD_TEST(suite, test_quit_transfer_limited); return suite; } diff --git a/src/spells.c b/src/spells.c index 83b7f2050..335bcef3c 100644 --- a/src/spells.c +++ b/src/spells.c @@ -3451,7 +3451,7 @@ static bool can_charm(const unit * u, int maxlevel) while (l < h) { int m = (l + h) / 2; if (sk == expskills[m]) { - if (skill_limit(u->faction, sk) != INT_MAX) { + if (faction_skill_limit(u->faction, sk) != INT_MAX) { return false; } else if ((int)sv->level > maxlevel) { diff --git a/src/study.c b/src/study.c index 7e5ca9812..8d39e5d5f 100644 --- a/src/study.c +++ b/src/study.c @@ -635,9 +635,9 @@ int study_cmd(unit * u, order * ord) mtype = M_GRAY; } else if (!has_skill(u, SK_MAGIC)) { - int mmax = skill_limit(u->faction, SK_MAGIC); + int mmax = faction_skill_limit(u->faction, SK_MAGIC); /* Die Einheit ist noch kein Magier */ - if (count_skill(u->faction, SK_MAGIC) + u->number > mmax) { + if (faction_count_skill(u->faction, SK_MAGIC) + u->number > mmax) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_max_magicians", "amount", mmax)); return -1; @@ -694,8 +694,8 @@ int study_cmd(unit * u, order * ord) if (sk == SK_ALCHEMY) { maxalchemy = effskill(u, SK_ALCHEMY, NULL); if (!has_skill(u, SK_ALCHEMY)) { - int amax = skill_limit(u->faction, SK_ALCHEMY); - if (count_skill(u->faction, SK_ALCHEMY) + u->number > amax) { + int amax = faction_skill_limit(u->faction, SK_ALCHEMY); + if (faction_count_skill(u->faction, SK_ALCHEMY) + u->number > amax) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_max_alchemists", "amount", amax)); return -1; From 2cb42872685b4812ccb34ae2b5f51af227e5c9f8 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 4 May 2019 10:55:13 +0200 Subject: [PATCH 37/56] do not transfer migrants. comments are good. --- src/laws.c | 26 ++++++++++--------- src/laws.test.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 12 deletions(-) diff --git a/src/laws.c b/src/laws.c index f1e69b231..2f86e79a6 100644 --- a/src/laws.c +++ b/src/laws.c @@ -964,22 +964,24 @@ void transfer_faction(faction *fsrc, faction *fdst) { } for (u = fsrc->units; u != NULL; u = u->nextF) { - if (give_unit_allowed(u) == 0) { - if (u->skills) { - int i; + if (u_race(u) == fdst->race) { + if (give_unit_allowed(u) == 0) { + if (u->skills) { + int i; - for (i = 0; i != u->skill_size; ++i) { - const skill *sv = u->skills + i; - skill_t sk = (skill_t)sv->id; - if (skill_count[sk] + u->number > skill_limit[sk]) { - break; + for (i = 0; i != u->skill_size; ++i) { + const skill *sv = u->skills + i; + skill_t sk = (skill_t)sv->id; + if (skill_count[sk] + u->number > skill_limit[sk]) { + break; + } + } + if (i != u->skill_size) { + continue; } } - if (i != u->skill_size) { - continue; - } + u_setfaction(u, fdst); } - u_setfaction(u, fdst); } } } diff --git a/src/laws.test.c b/src/laws.test.c index f82ec52e5..c5dafd851 100644 --- a/src/laws.test.c +++ b/src/laws.test.c @@ -1891,6 +1891,9 @@ static void test_quit(CuTest *tc) { test_teardown(); } +/** + * Gifting units to another faction upon voluntary death (QUIT). + */ static void test_quit_transfer(CuTest *tc) { faction *f1, *f2; unit *u1, *u2; @@ -1912,6 +1915,12 @@ static void test_quit_transfer(CuTest *tc) { test_teardown(); } +/** + * Gifting units with limited skills to another faction. + * + * This is allowed only up to the limit of the target faction. + * Units that would break the limit are not transferred. + */ static void test_quit_transfer_limited(CuTest *tc) { faction *f1, *f2; unit *u1, *u2; @@ -1946,6 +1955,62 @@ static void test_quit_transfer_limited(CuTest *tc) { test_teardown(); } +/** + * Only units of the same race can be gifted to another faction. + */ +static void test_quit_transfer_migrants(CuTest *tc) { + faction *f1, *f2; + unit *u1, *u2; + region *r; + + test_setup(); + r = test_create_plain(0, 0); + f1 = test_create_faction(NULL); + faction_setpassword(f1, "password"); + u1 = test_create_unit(f1, r); + f2 = test_create_faction(NULL); + u2 = test_create_unit(f2, r); + contact_unit(u2, u1); + u1->thisorder = create_order(K_QUIT, f1->locale, "password %s %s", + LOC(f1->locale, parameters[P_FACTION]), itoa36(f2->no)); + + u_setrace(u1, test_create_race("smurf")); + + quit_cmd(u1, u1->thisorder); + CuAssertIntEquals(tc, FFL_QUIT, f1->flags & FFL_QUIT); + CuAssertPtrEquals(tc, f1, u1->faction); + + test_teardown(); +} + +/** + * Heroes cannot be gifted to another faction. + */ +static void test_quit_transfer_hero(CuTest *tc) { + faction *f1, *f2; + unit *u1, *u2; + region *r; + + test_setup(); + r = test_create_plain(0, 0); + f1 = test_create_faction(NULL); + faction_setpassword(f1, "password"); + u1 = test_create_unit(f1, r); + f2 = test_create_faction(NULL); + u2 = test_create_unit(f2, r); + contact_unit(u2, u1); + u1->thisorder = create_order(K_QUIT, f1->locale, "password %s %s", + LOC(f1->locale, parameters[P_FACTION]), itoa36(f2->no)); + + u1->flags |= UFL_HERO; + + quit_cmd(u1, u1->thisorder); + CuAssertIntEquals(tc, FFL_QUIT, f1->flags & FFL_QUIT); + CuAssertPtrEquals(tc, f1, u1->faction); + + test_teardown(); +} + CuSuite *get_laws_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -2024,6 +2089,8 @@ CuSuite *get_laws_suite(void) SUITE_ADD_TEST(suite, test_quit); SUITE_ADD_TEST(suite, test_quit_transfer); SUITE_ADD_TEST(suite, test_quit_transfer_limited); + SUITE_ADD_TEST(suite, test_quit_transfer_migrants); + SUITE_ADD_TEST(suite, test_quit_transfer_hero); return suite; } From cd28f3aee44f9630fe213dfa7723790c99c0ff46 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 4 May 2019 11:11:30 +0200 Subject: [PATCH 38/56] heroes lose their status when gifted. --- src/laws.c | 1 + src/laws.test.c | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/laws.c b/src/laws.c index 2f86e79a6..e8200c262 100644 --- a/src/laws.c +++ b/src/laws.c @@ -965,6 +965,7 @@ void transfer_faction(faction *fsrc, faction *fdst) { for (u = fsrc->units; u != NULL; u = u->nextF) { if (u_race(u) == fdst->race) { + u->flags &= ~UFL_HERO; if (give_unit_allowed(u) == 0) { if (u->skills) { int i; diff --git a/src/laws.test.c b/src/laws.test.c index c5dafd851..33742f427 100644 --- a/src/laws.test.c +++ b/src/laws.test.c @@ -1984,7 +1984,7 @@ static void test_quit_transfer_migrants(CuTest *tc) { } /** - * Heroes cannot be gifted to another faction. + * A hero that is gifted to another faction loses their status. */ static void test_quit_transfer_hero(CuTest *tc) { faction *f1, *f2; @@ -2006,7 +2006,8 @@ static void test_quit_transfer_hero(CuTest *tc) { quit_cmd(u1, u1->thisorder); CuAssertIntEquals(tc, FFL_QUIT, f1->flags & FFL_QUIT); - CuAssertPtrEquals(tc, f1, u1->faction); + CuAssertPtrEquals(tc, f2, u1->faction); + CuAssertIntEquals(tc, 0, u1->flags & UFL_HERO); test_teardown(); } From 32da0028c1b6721029b7186b5d51a5ad97548616 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 7 May 2019 21:45:10 +0200 Subject: [PATCH 39/56] write to database after the file is created and dated --- process/accept-orders.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/process/accept-orders.py b/process/accept-orders.py index b0acbe0e1..8dd088c40 100755 --- a/process/accept-orders.py +++ b/process/accept-orders.py @@ -235,13 +235,6 @@ def copy_orders(message, filename, sender, mtime): outfile.write(name + ": " + value + "\n") outfile.close() - if writedb: - dirname, basename = os.path.split(filename) - cli = os.path.join(tooldir, 'cli.php'); - dbname = os.path.join(dirname, 'orders.db') - datestr = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(mtime)) - subprocess.call(['php', cli, '-d', dbname, 'insert', basename, sender, datestr]) - found = False outfile = open(filename, "w") if message.is_multipart(): @@ -262,6 +255,7 @@ def copy_orders(message, filename, sender, mtime): charset = message.get_content_charset() logger.error("could not write text/plain message (charset=%s) for %s" % (charset, sender)) outfile.close() + return found # create a file, containing: @@ -312,6 +306,12 @@ def accept(game, locale, stream, extend=None): warning = " (" + messages["warning-" + locale] + ")" msg = msg + formatpar(messages["nodate-" + locale], 76, 2) + "\n" + if writedb: + dirname, basename = os.path.split(filename) + cli = os.path.join(tooldir, 'cli.php'); + dbname = os.path.join(dirname, 'orders.db') + subprocess.call(['php', cli, '-d', dbname, 'insert', basename, email]) + if not text_ok: warning = " (" + messages["error-" + locale] + ")" msg = msg + formatpar(messages["multipart-" + locale], 76, 2) + "\n" From 85a7066ecc7a250931c4cfc784742f9ba55a1c74 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 8 May 2019 18:23:19 +0200 Subject: [PATCH 40/56] move php calls from python to shell script --- process/accept-orders.py | 10 ++-------- process/orders-accept | 27 ++++++++++++++++++++++----- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/process/accept-orders.py b/process/accept-orders.py index 8dd088c40..5a7124d43 100755 --- a/process/accept-orders.py +++ b/process/accept-orders.py @@ -55,9 +55,6 @@ sendmail = True maxfiles = 30 # write headers to file? writeheaders = True -# write received files to database? -tooldir = os.path.join(rootdir, 'orders-php') -writedb = os.path.exists(tooldir) # reject all html email? rejecthtml = True @@ -306,11 +303,8 @@ def accept(game, locale, stream, extend=None): warning = " (" + messages["warning-" + locale] + ")" msg = msg + formatpar(messages["nodate-" + locale], 76, 2) + "\n" - if writedb: - dirname, basename = os.path.split(filename) - cli = os.path.join(tooldir, 'cli.php'); - dbname = os.path.join(dirname, 'orders.db') - subprocess.call(['php', cli, '-d', dbname, 'insert', basename, email]) + print('ACCEPT_MAIL=' + email) + print('ACCEPT_FILE="' + filename + '"') if not text_ok: warning = " (" + messages["error-" + locale] + ")" diff --git a/process/orders-accept b/process/orders-accept index 33b3d5ecc..0873352e0 100755 --- a/process/orders-accept +++ b/process/orders-accept @@ -1,8 +1,25 @@ #!/bin/sh -SCRIPT=$(readlink -f $0) -cd $(dirname $SCRIPT) +# example: orders-accept 2 de < mail.txt -lockfile -r3 -l120 orders.queue.lock -python accept-orders.py "$@" -rm -f orders.queue.lock +game="$1" +[ -z "$ERESSEA" ] && ERESSEA="$HOME/eressea" +SCRIPT=$(readlink -f "$0") +BIN=$(dirname "$SCRIPT") + +LOCKFILE="$ERESSEA/game-$game/orders.queue.lock" +set -e +trap 'rm -f "$LOCKFILE"' EXIT + +cd "$ERESSEA/game-$game" +mkdir -p orders.dir +cd orders.dir +lockfile -r3 -l120 "$LOCKFILE" +eval "$(python "$BIN/accept-orders.py" "$@")" +filename=$(basename "$ACCEPT_FILE") +email="$ACCEPT_MAIL" +if [ -d "$ERESSEA/orders-php" ] +then + php "$ERESSEA/orders-php/cli.php" insert "$filename" "$email" +fi +rm -f "$LOCKFILE" From ef90806ca0060c930b0167d45c9d5d28fca477be Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 8 May 2019 21:08:14 +0200 Subject: [PATCH 41/56] hold lockfile only during python script --- process/orders-accept | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/process/orders-accept b/process/orders-accept index 0873352e0..99398e64f 100755 --- a/process/orders-accept +++ b/process/orders-accept @@ -16,10 +16,10 @@ mkdir -p orders.dir cd orders.dir lockfile -r3 -l120 "$LOCKFILE" eval "$(python "$BIN/accept-orders.py" "$@")" +rm -f "$LOCKFILE" filename=$(basename "$ACCEPT_FILE") email="$ACCEPT_MAIL" if [ -d "$ERESSEA/orders-php" ] then php "$ERESSEA/orders-php/cli.php" insert "$filename" "$email" fi -rm -f "$LOCKFILE" From 182d7df4804638ac2209adcea385e92d3471c11e Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 9 May 2019 21:55:45 +0200 Subject: [PATCH 42/56] do not include the database when creating order file the old way --- process/create-orders | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/process/create-orders b/process/create-orders index ef7a8bf15..5d4088fe5 100755 --- a/process/create-orders +++ b/process/create-orders @@ -17,7 +17,7 @@ else mkdir -p orders.dir fi rm -f "orders.$TURN" -find "orders.dir.$TURN" -maxdepth 1 -type f -printf "%T+\t%p\n" | sort | cut -f2 | while read -r +find "orders.dir.$TURN" -maxdepth 1 -name "turn-*" -type f -printf "%T+\t%p\n" | sort | cut -f2 | while read -r do tr -d '\r' < "$REPLY" >> "orders.$TURN" done From 7dbb417b93759bc6ba2c0e6a5b8e78fc409b06f7 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 11 May 2019 20:51:42 +0200 Subject: [PATCH 43/56] Bug 2575 --- src/kernel/build.c | 3 ++- src/kernel/build.test.c | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/kernel/build.c b/src/kernel/build.c index a5eb0a6db..14d07bb55 100644 --- a/src/kernel/build.c +++ b/src/kernel/build.c @@ -729,8 +729,9 @@ static int build_stages(unit *u, const building_type *btype, int built, int n, i } else { /* err is the amount we built of this stage */ + built += err; made += err; - if (err != con->maxsize && con->maxsize > 0) { + if (con->maxsize > 0 && built < con->maxsize) { /* we did not finish the stage, can quit here */ break; } diff --git a/src/kernel/build.test.c b/src/kernel/build.test.c index a123b5db0..4eba0baaf 100644 --- a/src/kernel/build.test.c +++ b/src/kernel/build.test.c @@ -96,6 +96,28 @@ static void test_build_building_stages(CuTest *tc) { item_type *it_stone; unit *u; + test_setup(); + init_resources(); + it_stone = test_create_itemtype("stone"); + btype = setup_castle(it_stone); + u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); + u->building = test_create_building(u->region, btype); + u->building->size = 1; + set_level(u, SK_BUILDING, 2); + i_change(&u->items, it_stone, 4); + build_building(u, btype, -1, INT_MAX, NULL); + CuAssertPtrNotNull(tc, u->building); + CuAssertIntEquals(tc, 3, u->building->size); + CuAssertIntEquals(tc, 2, i_get(u->items, it_stone)); + + test_teardown(); +} + +static void test_build_building_stage_continue(CuTest *tc) { + building_type *btype; + item_type *it_stone; + unit *u; + test_setup(); init_resources(); it_stone = test_create_itemtype("stone"); @@ -450,6 +472,7 @@ CuSuite *get_build_suite(void) SUITE_ADD_TEST(suite, test_build_with_potion); SUITE_ADD_TEST(suite, test_build_building_success); SUITE_ADD_TEST(suite, test_build_building_stages); + SUITE_ADD_TEST(suite, test_build_building_stage_continue); SUITE_ADD_TEST(suite, test_build_building_with_golem); SUITE_ADD_TEST(suite, test_build_building_no_materials); SUITE_ADD_TEST(suite, test_build_destroy_cmd); From d2ee91bc88c7e97fb077f71017f2fa3d43cfb6fc Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 18 May 2019 12:56:40 +0200 Subject: [PATCH 44/56] Bug 2584: failing test for aura regeneration. --- src/magic.h | 4 +-- src/magic.test.c | 75 +++++++++++++++++++++++++++++++----------------- 2 files changed, 51 insertions(+), 28 deletions(-) diff --git a/src/magic.h b/src/magic.h index 8d2b2b534..0e618a56e 100644 --- a/src/magic.h +++ b/src/magic.h @@ -259,7 +259,7 @@ extern "C" { /* veraendert die maximalen Magiepunkte einer Einheit */ /* Zaubern */ - extern double spellpower(struct region *r, struct unit *u, const struct spell * sp, + double spellpower(struct region *r, struct unit *u, const struct spell * sp, int cast_level, struct order *ord); /* ermittelt die Staerke eines Spruchs */ bool fumble(struct region *r, struct unit *u, const struct spell * sp, @@ -315,7 +315,7 @@ extern "C" { int resist_bonus); /* gibt false zurueck, wenn der Zauber gelingt, true, wenn das Ziel * widersteht */ - extern struct spell * unit_getspell(struct unit *u, const char *s, + struct spell * unit_getspell(struct unit *u, const char *s, const struct locale *lang); const char *magic_name(magic_t mtype, const struct locale *lang); diff --git a/src/magic.test.c b/src/magic.test.c index 577e88a37..160662c15 100644 --- a/src/magic.test.c +++ b/src/magic.test.c @@ -108,7 +108,7 @@ void test_pay_spell(CuTest * tc) test_setup(); init_resources(); - r = test_create_region(0, 0, NULL); + r = test_create_plain(0, 0); f = test_create_faction(NULL); u = test_create_unit(f, r); CuAssertPtrNotNull(tc, u); @@ -142,7 +142,7 @@ void test_pay_spell_failure(CuTest * tc) test_setup(); init_resources(); - r = test_create_region(0, 0, NULL); + r = test_create_plain(0, 0); f = test_create_faction(NULL); u = test_create_unit(f, r); CuAssertPtrNotNull(tc, u); @@ -179,7 +179,7 @@ void test_getspell_unit(CuTest * tc) struct locale * lang; test_setup(); - r = test_create_region(0, 0, NULL); + r = test_create_plain(0, 0); f = test_create_faction(NULL); u = test_create_unit(f, r); create_mage(u, M_GWYRRD); @@ -207,7 +207,7 @@ void test_getspell_faction(CuTest * tc) struct locale * lang; test_setup(); - r = test_create_region(0, 0, NULL); + r = test_create_plain(0, 0); f = test_create_faction(NULL); f->magiegebiet = M_TYBIED; u = test_create_unit(f, r); @@ -238,7 +238,7 @@ void test_getspell_school(CuTest * tc) struct spellbook * book; test_setup(); - r = test_create_region(0, 0, NULL); + r = test_create_plain(0, 0); f = test_create_faction(NULL); f->magiegebiet = M_TYBIED; u = test_create_unit(f, r); @@ -268,7 +268,7 @@ void test_set_pre_combatspell(CuTest * tc) const int index = 0; test_setup(); - r = test_create_region(0, 0, NULL); + r = test_create_plain(0, 0); f = test_create_faction(NULL); f->magiegebiet = M_TYBIED; u = test_create_unit(f, r); @@ -300,7 +300,7 @@ void test_set_main_combatspell(CuTest * tc) const int index = 1; test_setup(); - r = test_create_region(0, 0, NULL); + r = test_create_plain(0, 0); f = test_create_faction(NULL); f->magiegebiet = M_TYBIED; u = test_create_unit(f, r); @@ -332,7 +332,7 @@ void test_set_post_combatspell(CuTest * tc) const int index = 2; test_setup(); - r = test_create_region(0, 0, NULL); + r = test_create_plain(0, 0); f = test_create_faction(NULL); f->magiegebiet = M_TYBIED; u = test_create_unit(f, r); @@ -363,7 +363,7 @@ void test_hasspell(CuTest * tc) struct region * r; test_setup(); - r = test_create_region(0, 0, NULL); + r = test_create_plain(0, 0); f = test_create_faction(NULL); f->magiegebiet = M_TYBIED; u = test_create_unit(f, r); @@ -405,7 +405,7 @@ void test_multi_cast(CuTest *tc) { locale_setstring(lang, mkname("spell", sp->sname), "Feuerball"); CuAssertStrEquals(tc, "Feuerball", spell_name(sp, lang)); - u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL)); + u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); set_level(u, SK_MAGIC, 10); unit_add_spell(u, sp, 1); CuAssertPtrEquals(tc, sp, unit_getspell(u, "Feuerball", lang)); @@ -426,7 +426,7 @@ static void test_magic_resistance(CuTest *tc) { test_setup(); rc = test_create_race("human"); - u = test_create_unit(test_create_faction(rc), test_create_region(0, 0, NULL)); + u = test_create_unit(test_create_faction(rc), test_create_plain(0, 0)); CuAssertTrue(tc, frac_equal(rc->magres, magic_resistance(u))); rc->magres = frac_one; CuAssert(tc, "magic resistance is capped at 0.9", frac_equal(magic_resistance(u), frac_make(9, 10))); @@ -445,23 +445,45 @@ static void test_max_spellpoints(CuTest *tc) { test_setup(); rc = test_create_race("human"); - u = test_create_unit(test_create_faction(rc), test_create_region(0, 0, NULL)); + u = test_create_unit(test_create_faction(rc), test_create_plain(0, 0)); CuAssertIntEquals(tc, 1, max_spellpoints_depr(u->region, u)); + CuAssertIntEquals(tc, 1, max_spellpoints(u, u->region)); + CuAssertIntEquals(tc, 1, max_spellpoints(u, NULL)); rc->maxaura = 100; - CuAssertIntEquals(tc, 1, max_spellpoints_depr(u->region, u)); + CuAssertIntEquals(tc, 1, max_spellpoints(u, u->region)); rc->maxaura = 200; - CuAssertIntEquals(tc, 2, max_spellpoints_depr(u->region, u)); + CuAssertIntEquals(tc, 2, max_spellpoints(u, u->region)); create_mage(u, M_GWYRRD); set_level(u, SK_MAGIC, 1); - CuAssertIntEquals(tc, 3, max_spellpoints_depr(u->region, u)); + CuAssertIntEquals(tc, 3, max_spellpoints(u, u->region)); set_level(u, SK_MAGIC, 2); - CuAssertIntEquals(tc, 9, max_spellpoints_depr(u->region, u)); + CuAssertIntEquals(tc, 9, max_spellpoints(u, u->region)); /* permanent aura loss: */ CuAssertIntEquals(tc, 7, change_maxspellpoints(u, -2)); - CuAssertIntEquals(tc, 7, max_spellpoints_depr(u->region, u)); + CuAssertIntEquals(tc, 7, max_spellpoints(u, u->region)); test_teardown(); } +static void test_regenerate_aura(CuTest *tc) { + unit *u; + + test_setup(); + test_teardown(); + u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); + create_mage(u, M_GWYRRD); + CuAssertIntEquals(tc, 0, get_spellpoints(u)); + CuAssertIntEquals(tc, 1, max_spellpoints(u, NULL)); + regenerate_aura(); + CuAssertIntEquals(tc, 1, get_spellpoints(u)); + + u = test_create_unit(u->faction, u->region); + create_mage(u, M_GRAY); + CuAssertIntEquals(tc, 0, get_spellpoints(u)); + CuAssertIntEquals(tc, 1, max_spellpoints(u, NULL)); + regenerate_aura(); + CuAssertIntEquals(tc, 1, get_spellpoints(u)); +} + static void test_illusioncastle(CuTest *tc) { building *b; @@ -470,7 +492,7 @@ static void test_illusioncastle(CuTest *tc) test_setup(); btype = test_create_buildingtype("castle"); bt_icastle = test_create_buildingtype("illusioncastle"); - b = test_create_building(test_create_region(0, 0, NULL), bt_icastle); + b = test_create_building(test_create_plain(0, 0), bt_icastle); b->size = 1; make_icastle(b, btype, 10); a = a_find(b->attribs, &at_icastle); @@ -488,7 +510,7 @@ static void test_is_mage(CuTest *tc) { struct sc_mage *mage; test_setup(); - u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL)); + u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); CuAssertPtrEquals(tc, NULL, get_mage(u)); CuAssertTrue(tc, !is_mage(u)); set_level(u, SK_MAGIC, 1); @@ -505,7 +527,7 @@ static void test_get_mage(CuTest *tc) { struct sc_mage *mage; test_setup(); - u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL)); + u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); CuAssertPtrEquals(tc, NULL, get_mage(u)); CuAssertPtrNotNull(tc, mage = create_mage(u, M_CERDDOR)); CuAssertPtrEquals(tc, mage, get_mage(u)); @@ -517,8 +539,8 @@ static void test_familiar_set(CuTest *tc) { test_setup(); - mag = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL)); - fam = test_create_unit(mag->faction, test_create_region(0, 0, NULL)); + mag = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); + fam = test_create_unit(mag->faction, test_create_plain(0, 0)); CuAssertPtrEquals(tc, NULL, get_familiar(mag)); CuAssertPtrEquals(tc, NULL, get_familiar_mage(fam)); CuAssertPtrEquals(tc, NULL, a_find(mag->attribs, &at_skillmod)); @@ -537,8 +559,8 @@ static void test_familiar_age(CuTest *tc) { test_setup(); - mag = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL)); - fam = test_create_unit(mag->faction, test_create_region(0, 0, NULL)); + mag = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); + fam = test_create_unit(mag->faction, test_create_plain(0, 0)); set_familiar(mag, fam); CuAssertPtrEquals(tc, fam, get_familiar(mag)); CuAssertPtrEquals(tc, mag, get_familiar_mage(fam)); @@ -568,8 +590,8 @@ static void test_familiar_equip(CuTest *tc) { test_setup(); callbacks.equip_unit = equip_callback; - mag = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL)); - u = test_create_unit(mag->faction, test_create_region(0, 0, NULL)); + mag = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); + u = test_create_unit(mag->faction, test_create_plain(0, 0)); CuAssertStrEquals(tc, "human", u->_race->_name); set_familiar(mag, u); create_newfamiliar(mag, u); @@ -612,5 +634,6 @@ CuSuite *get_magic_suite(void) SUITE_ADD_TEST(suite, test_magic_resistance); SUITE_ADD_TEST(suite, test_max_spellpoints); SUITE_ADD_TEST(suite, test_illusioncastle); + SUITE_ADD_TEST(suite, test_regenerate_aura); return suite; } From 20182382637339bea5d6c5c75f095ebf115d7e39 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 18 May 2019 13:16:13 +0200 Subject: [PATCH 45/56] Bug 2584: gray mages can regenerate aura. --- src/magic.c | 95 ++++++++++++++++++++++++++--------------------------- src/magic.h | 1 + 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/magic.c b/src/magic.c index fdd74d55e..7b15bb71d 100644 --- a/src/magic.c +++ b/src/magic.c @@ -117,6 +117,11 @@ typedef struct sc_mage { struct spellbook *spellbook; } sc_mage; +void mage_set_spellpoints(sc_mage *m, int aura) +{ + m->spellpoints = aura; +} + int mage_get_spellpoints(const sc_mage *m) { return m ? m->spellpoints : 0; @@ -603,7 +608,7 @@ void set_spellpoints(unit * u, int sp) { sc_mage *m = get_mage(u); if (m) { - m->spellpoints = sp; + mage_set_spellpoints(m, sp); } } @@ -615,18 +620,6 @@ int change_spellpoints(unit * u, int mp) return mage_change_spellpoints(get_mage(u), mp); } -/** - * Bietet die Moeglichkeit, die maximale Anzahl der Magiepunkte mit - * Regionszaubern oder Attributen zu beinflussen - */ -static int get_spchange(const unit * u) -{ - sc_mage *m; - - m = get_mage(u); - return m ? m->spchange : 0; -} - /* ein Magier kann normalerweise maximal Stufe^2.1/1.2+1 Magiepunkte * haben. * Manche Rassen haben einen zusaetzlichen Multiplikator @@ -655,12 +648,15 @@ int max_spellpoints(const struct unit *u, const region * r) double potenz = 2.1; double divisor = 1.2; const struct resource_type *rtype; + const sc_mage *m; assert(u); if (!r) r = u->region; sk = effskill(u, SK_MAGIC, r); - msp = rc_maxaura(u_race(u)) * (pow(sk, potenz) / divisor + 1) + get_spchange(u); + msp = rc_maxaura(u_race(u)) * (pow(sk, potenz) / divisor + 1); + m = get_mage(u); + if (m) msp += m->spchange; rtype = rt_find("aurafocus"); if (rtype && i_get(u->items, rtype->itype) > 0) { @@ -1464,44 +1460,47 @@ void regenerate_aura(void) for (r = regions; r; r = r->next) { for (u = r->units; u; u = u->next) { - if (u->number && is_mage(u)) { - aura = get_spellpoints(u); - auramax = max_spellpoints_depr(r, u); - if (aura < auramax) { - struct building *b = inside_building(u); - const struct building_type *btype = building_is_active(b) ? b->type : NULL; - reg_aura = regeneration(u); + if (u->number && u->attribs) { + sc_mage *m = get_mage(u); + if (m) { + aura = mage_get_spellpoints(m); + auramax = max_spellpoints(u, r); + if (aura < auramax) { + struct building *b = inside_building(u); + const struct building_type *btype = building_is_active(b) ? b->type : NULL; + reg_aura = regeneration(u); - /* Magierturm erhoeht die Regeneration um 75% */ - /* Steinkreis erhoeht die Regeneration um 50% */ - if (btype) - reg_aura *= btype->auraregen; + /* Magierturm erhoeht die Regeneration um 75% */ + /* Steinkreis erhoeht die Regeneration um 50% */ + if (btype) + reg_aura *= btype->auraregen; - /* Bonus/Malus durch Zauber */ - mod = get_curseeffect(u->attribs, &ct_auraboost); - if (mod > 0) { - reg_aura = (reg_aura * mod) / 100.0; + /* Bonus/Malus durch Zauber */ + mod = get_curseeffect(u->attribs, &ct_auraboost); + if (mod > 0) { + reg_aura = (reg_aura * mod) / 100.0; + } + + /* Einfluss von Artefakten */ + /* TODO (noch gibs keine) */ + + /* maximal Differenz bis Maximale-Aura regenerieren + * mindestens 1 Aura pro Monat */ + regen = (int)reg_aura; + reg_aura -= regen; + if (chance(reg_aura)) { + ++regen; + } + if (regen < 1) regen = 1; + if (regen > auramax - aura) regen = auramax - aura; + + aura += regen; + ADDMSG(&u->faction->msgs, msg_message("regenaura", + "unit region amount", u, r, regen)); } - - /* Einfluss von Artefakten */ - /* TODO (noch gibs keine) */ - - /* maximal Differenz bis Maximale-Aura regenerieren - * mindestens 1 Aura pro Monat */ - regen = (int)reg_aura; - reg_aura -= regen; - if (chance(reg_aura)) { - ++regen; - } - if (regen < 1) regen = 1; - if (regen > auramax - aura) regen = auramax - aura; - - aura += regen; - ADDMSG(&u->faction->msgs, msg_message("regenaura", - "unit region amount", u, r, regen)); + if (aura > auramax) aura = auramax; + mage_set_spellpoints(m, aura); } - if (aura > auramax) aura = auramax; - set_spellpoints(u, aura); } } } diff --git a/src/magic.h b/src/magic.h index 0e618a56e..5269e3259 100644 --- a/src/magic.h +++ b/src/magic.h @@ -210,6 +210,7 @@ extern "C" { const struct spell *mage_get_combatspell(const struct sc_mage *mage, int nr, int *level); struct spellbook * mage_get_spellbook(const struct sc_mage * mage); int mage_get_spellpoints(const struct sc_mage *m); + void mage_set_spellpoints(struct sc_mage *m, int aura); int mage_change_spellpoints(struct sc_mage *m, int delta); enum magic_t unit_get_magic(const struct unit *u); From 3434bbe67d0e69dc9d17975d2f131fe5a551f4c3 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 18 May 2019 12:56:40 +0200 Subject: [PATCH 46/56] Bug 2584: failing test for aura regeneration. --- src/magic.h | 4 +-- src/magic.test.c | 75 +++++++++++++++++++++++++++++++----------------- 2 files changed, 51 insertions(+), 28 deletions(-) diff --git a/src/magic.h b/src/magic.h index 8d2b2b534..0e618a56e 100644 --- a/src/magic.h +++ b/src/magic.h @@ -259,7 +259,7 @@ extern "C" { /* veraendert die maximalen Magiepunkte einer Einheit */ /* Zaubern */ - extern double spellpower(struct region *r, struct unit *u, const struct spell * sp, + double spellpower(struct region *r, struct unit *u, const struct spell * sp, int cast_level, struct order *ord); /* ermittelt die Staerke eines Spruchs */ bool fumble(struct region *r, struct unit *u, const struct spell * sp, @@ -315,7 +315,7 @@ extern "C" { int resist_bonus); /* gibt false zurueck, wenn der Zauber gelingt, true, wenn das Ziel * widersteht */ - extern struct spell * unit_getspell(struct unit *u, const char *s, + struct spell * unit_getspell(struct unit *u, const char *s, const struct locale *lang); const char *magic_name(magic_t mtype, const struct locale *lang); diff --git a/src/magic.test.c b/src/magic.test.c index 577e88a37..160662c15 100644 --- a/src/magic.test.c +++ b/src/magic.test.c @@ -108,7 +108,7 @@ void test_pay_spell(CuTest * tc) test_setup(); init_resources(); - r = test_create_region(0, 0, NULL); + r = test_create_plain(0, 0); f = test_create_faction(NULL); u = test_create_unit(f, r); CuAssertPtrNotNull(tc, u); @@ -142,7 +142,7 @@ void test_pay_spell_failure(CuTest * tc) test_setup(); init_resources(); - r = test_create_region(0, 0, NULL); + r = test_create_plain(0, 0); f = test_create_faction(NULL); u = test_create_unit(f, r); CuAssertPtrNotNull(tc, u); @@ -179,7 +179,7 @@ void test_getspell_unit(CuTest * tc) struct locale * lang; test_setup(); - r = test_create_region(0, 0, NULL); + r = test_create_plain(0, 0); f = test_create_faction(NULL); u = test_create_unit(f, r); create_mage(u, M_GWYRRD); @@ -207,7 +207,7 @@ void test_getspell_faction(CuTest * tc) struct locale * lang; test_setup(); - r = test_create_region(0, 0, NULL); + r = test_create_plain(0, 0); f = test_create_faction(NULL); f->magiegebiet = M_TYBIED; u = test_create_unit(f, r); @@ -238,7 +238,7 @@ void test_getspell_school(CuTest * tc) struct spellbook * book; test_setup(); - r = test_create_region(0, 0, NULL); + r = test_create_plain(0, 0); f = test_create_faction(NULL); f->magiegebiet = M_TYBIED; u = test_create_unit(f, r); @@ -268,7 +268,7 @@ void test_set_pre_combatspell(CuTest * tc) const int index = 0; test_setup(); - r = test_create_region(0, 0, NULL); + r = test_create_plain(0, 0); f = test_create_faction(NULL); f->magiegebiet = M_TYBIED; u = test_create_unit(f, r); @@ -300,7 +300,7 @@ void test_set_main_combatspell(CuTest * tc) const int index = 1; test_setup(); - r = test_create_region(0, 0, NULL); + r = test_create_plain(0, 0); f = test_create_faction(NULL); f->magiegebiet = M_TYBIED; u = test_create_unit(f, r); @@ -332,7 +332,7 @@ void test_set_post_combatspell(CuTest * tc) const int index = 2; test_setup(); - r = test_create_region(0, 0, NULL); + r = test_create_plain(0, 0); f = test_create_faction(NULL); f->magiegebiet = M_TYBIED; u = test_create_unit(f, r); @@ -363,7 +363,7 @@ void test_hasspell(CuTest * tc) struct region * r; test_setup(); - r = test_create_region(0, 0, NULL); + r = test_create_plain(0, 0); f = test_create_faction(NULL); f->magiegebiet = M_TYBIED; u = test_create_unit(f, r); @@ -405,7 +405,7 @@ void test_multi_cast(CuTest *tc) { locale_setstring(lang, mkname("spell", sp->sname), "Feuerball"); CuAssertStrEquals(tc, "Feuerball", spell_name(sp, lang)); - u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL)); + u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); set_level(u, SK_MAGIC, 10); unit_add_spell(u, sp, 1); CuAssertPtrEquals(tc, sp, unit_getspell(u, "Feuerball", lang)); @@ -426,7 +426,7 @@ static void test_magic_resistance(CuTest *tc) { test_setup(); rc = test_create_race("human"); - u = test_create_unit(test_create_faction(rc), test_create_region(0, 0, NULL)); + u = test_create_unit(test_create_faction(rc), test_create_plain(0, 0)); CuAssertTrue(tc, frac_equal(rc->magres, magic_resistance(u))); rc->magres = frac_one; CuAssert(tc, "magic resistance is capped at 0.9", frac_equal(magic_resistance(u), frac_make(9, 10))); @@ -445,23 +445,45 @@ static void test_max_spellpoints(CuTest *tc) { test_setup(); rc = test_create_race("human"); - u = test_create_unit(test_create_faction(rc), test_create_region(0, 0, NULL)); + u = test_create_unit(test_create_faction(rc), test_create_plain(0, 0)); CuAssertIntEquals(tc, 1, max_spellpoints_depr(u->region, u)); + CuAssertIntEquals(tc, 1, max_spellpoints(u, u->region)); + CuAssertIntEquals(tc, 1, max_spellpoints(u, NULL)); rc->maxaura = 100; - CuAssertIntEquals(tc, 1, max_spellpoints_depr(u->region, u)); + CuAssertIntEquals(tc, 1, max_spellpoints(u, u->region)); rc->maxaura = 200; - CuAssertIntEquals(tc, 2, max_spellpoints_depr(u->region, u)); + CuAssertIntEquals(tc, 2, max_spellpoints(u, u->region)); create_mage(u, M_GWYRRD); set_level(u, SK_MAGIC, 1); - CuAssertIntEquals(tc, 3, max_spellpoints_depr(u->region, u)); + CuAssertIntEquals(tc, 3, max_spellpoints(u, u->region)); set_level(u, SK_MAGIC, 2); - CuAssertIntEquals(tc, 9, max_spellpoints_depr(u->region, u)); + CuAssertIntEquals(tc, 9, max_spellpoints(u, u->region)); /* permanent aura loss: */ CuAssertIntEquals(tc, 7, change_maxspellpoints(u, -2)); - CuAssertIntEquals(tc, 7, max_spellpoints_depr(u->region, u)); + CuAssertIntEquals(tc, 7, max_spellpoints(u, u->region)); test_teardown(); } +static void test_regenerate_aura(CuTest *tc) { + unit *u; + + test_setup(); + test_teardown(); + u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); + create_mage(u, M_GWYRRD); + CuAssertIntEquals(tc, 0, get_spellpoints(u)); + CuAssertIntEquals(tc, 1, max_spellpoints(u, NULL)); + regenerate_aura(); + CuAssertIntEquals(tc, 1, get_spellpoints(u)); + + u = test_create_unit(u->faction, u->region); + create_mage(u, M_GRAY); + CuAssertIntEquals(tc, 0, get_spellpoints(u)); + CuAssertIntEquals(tc, 1, max_spellpoints(u, NULL)); + regenerate_aura(); + CuAssertIntEquals(tc, 1, get_spellpoints(u)); +} + static void test_illusioncastle(CuTest *tc) { building *b; @@ -470,7 +492,7 @@ static void test_illusioncastle(CuTest *tc) test_setup(); btype = test_create_buildingtype("castle"); bt_icastle = test_create_buildingtype("illusioncastle"); - b = test_create_building(test_create_region(0, 0, NULL), bt_icastle); + b = test_create_building(test_create_plain(0, 0), bt_icastle); b->size = 1; make_icastle(b, btype, 10); a = a_find(b->attribs, &at_icastle); @@ -488,7 +510,7 @@ static void test_is_mage(CuTest *tc) { struct sc_mage *mage; test_setup(); - u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL)); + u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); CuAssertPtrEquals(tc, NULL, get_mage(u)); CuAssertTrue(tc, !is_mage(u)); set_level(u, SK_MAGIC, 1); @@ -505,7 +527,7 @@ static void test_get_mage(CuTest *tc) { struct sc_mage *mage; test_setup(); - u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL)); + u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); CuAssertPtrEquals(tc, NULL, get_mage(u)); CuAssertPtrNotNull(tc, mage = create_mage(u, M_CERDDOR)); CuAssertPtrEquals(tc, mage, get_mage(u)); @@ -517,8 +539,8 @@ static void test_familiar_set(CuTest *tc) { test_setup(); - mag = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL)); - fam = test_create_unit(mag->faction, test_create_region(0, 0, NULL)); + mag = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); + fam = test_create_unit(mag->faction, test_create_plain(0, 0)); CuAssertPtrEquals(tc, NULL, get_familiar(mag)); CuAssertPtrEquals(tc, NULL, get_familiar_mage(fam)); CuAssertPtrEquals(tc, NULL, a_find(mag->attribs, &at_skillmod)); @@ -537,8 +559,8 @@ static void test_familiar_age(CuTest *tc) { test_setup(); - mag = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL)); - fam = test_create_unit(mag->faction, test_create_region(0, 0, NULL)); + mag = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); + fam = test_create_unit(mag->faction, test_create_plain(0, 0)); set_familiar(mag, fam); CuAssertPtrEquals(tc, fam, get_familiar(mag)); CuAssertPtrEquals(tc, mag, get_familiar_mage(fam)); @@ -568,8 +590,8 @@ static void test_familiar_equip(CuTest *tc) { test_setup(); callbacks.equip_unit = equip_callback; - mag = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL)); - u = test_create_unit(mag->faction, test_create_region(0, 0, NULL)); + mag = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); + u = test_create_unit(mag->faction, test_create_plain(0, 0)); CuAssertStrEquals(tc, "human", u->_race->_name); set_familiar(mag, u); create_newfamiliar(mag, u); @@ -612,5 +634,6 @@ CuSuite *get_magic_suite(void) SUITE_ADD_TEST(suite, test_magic_resistance); SUITE_ADD_TEST(suite, test_max_spellpoints); SUITE_ADD_TEST(suite, test_illusioncastle); + SUITE_ADD_TEST(suite, test_regenerate_aura); return suite; } From a461bff6f01282c5dc74c611ad1ced2b5975dbd6 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 18 May 2019 13:16:13 +0200 Subject: [PATCH 47/56] Bug 2584: gray mages can regenerate aura. --- src/magic.c | 95 ++++++++++++++++++++++++++--------------------------- src/magic.h | 1 + 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/magic.c b/src/magic.c index fdd74d55e..7b15bb71d 100644 --- a/src/magic.c +++ b/src/magic.c @@ -117,6 +117,11 @@ typedef struct sc_mage { struct spellbook *spellbook; } sc_mage; +void mage_set_spellpoints(sc_mage *m, int aura) +{ + m->spellpoints = aura; +} + int mage_get_spellpoints(const sc_mage *m) { return m ? m->spellpoints : 0; @@ -603,7 +608,7 @@ void set_spellpoints(unit * u, int sp) { sc_mage *m = get_mage(u); if (m) { - m->spellpoints = sp; + mage_set_spellpoints(m, sp); } } @@ -615,18 +620,6 @@ int change_spellpoints(unit * u, int mp) return mage_change_spellpoints(get_mage(u), mp); } -/** - * Bietet die Moeglichkeit, die maximale Anzahl der Magiepunkte mit - * Regionszaubern oder Attributen zu beinflussen - */ -static int get_spchange(const unit * u) -{ - sc_mage *m; - - m = get_mage(u); - return m ? m->spchange : 0; -} - /* ein Magier kann normalerweise maximal Stufe^2.1/1.2+1 Magiepunkte * haben. * Manche Rassen haben einen zusaetzlichen Multiplikator @@ -655,12 +648,15 @@ int max_spellpoints(const struct unit *u, const region * r) double potenz = 2.1; double divisor = 1.2; const struct resource_type *rtype; + const sc_mage *m; assert(u); if (!r) r = u->region; sk = effskill(u, SK_MAGIC, r); - msp = rc_maxaura(u_race(u)) * (pow(sk, potenz) / divisor + 1) + get_spchange(u); + msp = rc_maxaura(u_race(u)) * (pow(sk, potenz) / divisor + 1); + m = get_mage(u); + if (m) msp += m->spchange; rtype = rt_find("aurafocus"); if (rtype && i_get(u->items, rtype->itype) > 0) { @@ -1464,44 +1460,47 @@ void regenerate_aura(void) for (r = regions; r; r = r->next) { for (u = r->units; u; u = u->next) { - if (u->number && is_mage(u)) { - aura = get_spellpoints(u); - auramax = max_spellpoints_depr(r, u); - if (aura < auramax) { - struct building *b = inside_building(u); - const struct building_type *btype = building_is_active(b) ? b->type : NULL; - reg_aura = regeneration(u); + if (u->number && u->attribs) { + sc_mage *m = get_mage(u); + if (m) { + aura = mage_get_spellpoints(m); + auramax = max_spellpoints(u, r); + if (aura < auramax) { + struct building *b = inside_building(u); + const struct building_type *btype = building_is_active(b) ? b->type : NULL; + reg_aura = regeneration(u); - /* Magierturm erhoeht die Regeneration um 75% */ - /* Steinkreis erhoeht die Regeneration um 50% */ - if (btype) - reg_aura *= btype->auraregen; + /* Magierturm erhoeht die Regeneration um 75% */ + /* Steinkreis erhoeht die Regeneration um 50% */ + if (btype) + reg_aura *= btype->auraregen; - /* Bonus/Malus durch Zauber */ - mod = get_curseeffect(u->attribs, &ct_auraboost); - if (mod > 0) { - reg_aura = (reg_aura * mod) / 100.0; + /* Bonus/Malus durch Zauber */ + mod = get_curseeffect(u->attribs, &ct_auraboost); + if (mod > 0) { + reg_aura = (reg_aura * mod) / 100.0; + } + + /* Einfluss von Artefakten */ + /* TODO (noch gibs keine) */ + + /* maximal Differenz bis Maximale-Aura regenerieren + * mindestens 1 Aura pro Monat */ + regen = (int)reg_aura; + reg_aura -= regen; + if (chance(reg_aura)) { + ++regen; + } + if (regen < 1) regen = 1; + if (regen > auramax - aura) regen = auramax - aura; + + aura += regen; + ADDMSG(&u->faction->msgs, msg_message("regenaura", + "unit region amount", u, r, regen)); } - - /* Einfluss von Artefakten */ - /* TODO (noch gibs keine) */ - - /* maximal Differenz bis Maximale-Aura regenerieren - * mindestens 1 Aura pro Monat */ - regen = (int)reg_aura; - reg_aura -= regen; - if (chance(reg_aura)) { - ++regen; - } - if (regen < 1) regen = 1; - if (regen > auramax - aura) regen = auramax - aura; - - aura += regen; - ADDMSG(&u->faction->msgs, msg_message("regenaura", - "unit region amount", u, r, regen)); + if (aura > auramax) aura = auramax; + mage_set_spellpoints(m, aura); } - if (aura > auramax) aura = auramax; - set_spellpoints(u, aura); } } } diff --git a/src/magic.h b/src/magic.h index 0e618a56e..5269e3259 100644 --- a/src/magic.h +++ b/src/magic.h @@ -210,6 +210,7 @@ extern "C" { const struct spell *mage_get_combatspell(const struct sc_mage *mage, int nr, int *level); struct spellbook * mage_get_spellbook(const struct sc_mage * mage); int mage_get_spellpoints(const struct sc_mage *m); + void mage_set_spellpoints(struct sc_mage *m, int aura); int mage_change_spellpoints(struct sc_mage *m, int delta); enum magic_t unit_get_magic(const struct unit *u); From 4391ab95fa019ada194018d93df7f38985698e4c Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 18 May 2019 16:16:30 +0200 Subject: [PATCH 48/56] =?UTF-8?q?Bug=202483:=20FLIEHE=20als=20Default=20f?= =?UTF-8?q?=C3=BCr=20neue=20Parteien,=20nicht=20AGGRESSIV.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/kernel/faction.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/kernel/faction.c b/src/kernel/faction.c index beec40e0a..86f74dc03 100755 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -281,6 +281,7 @@ unit *addplayer(region * r, faction * f) assert(f->units == NULL); faction_setorigin(f, 0, r->x, r->y); u = create_unit(r, f, 1, f->race, 0, NULL, NULL); + u->status = ST_FLEE; u->thisorder = default_order(f->locale); unit_addorder(u, copy_order(u->thisorder)); name = config_get("rules.equip_first"); From bc6f38d9bcb3a79e9564a18bdc6ac903d39ac1c1 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 18 May 2019 19:49:06 +0200 Subject: [PATCH 49/56] remove superfluous race definitions that are not used anywhere. --- conf/e3/races.json | 10 +++--- res/{ => e3a}/races/dragon.xml | 0 .../goblin-3.xml => e3a/races/goblin.xml} | 0 res/{ => e3a}/races/wyrm.xml | 0 res/{ => e3a}/races/youngdragon.xml | 0 res/races/aquarian.xml | 19 ---------- res/races/cat.xml | 26 -------------- res/races/demon.xml | 36 ------------------- res/races/dwarf.xml | 32 ----------------- res/races/elf.xml | 28 --------------- res/races/goblin.xml | 30 ---------------- res/races/halfling.xml | 33 ----------------- res/races/human.xml | 16 --------- res/races/insect.xml | 29 --------------- res/races/orc.xml | 31 ---------------- res/races/troll.xml | 36 ------------------- res/races/zombie.xml | 12 ------- 17 files changed, 5 insertions(+), 333 deletions(-) rename res/{ => e3a}/races/dragon.xml (100%) rename res/{races/goblin-3.xml => e3a/races/goblin.xml} (100%) rename res/{ => e3a}/races/wyrm.xml (100%) rename res/{ => e3a}/races/youngdragon.xml (100%) delete mode 100644 res/races/aquarian.xml delete mode 100644 res/races/cat.xml delete mode 100644 res/races/demon.xml delete mode 100644 res/races/dwarf.xml delete mode 100644 res/races/elf.xml delete mode 100644 res/races/goblin.xml delete mode 100644 res/races/halfling.xml delete mode 100644 res/races/human.xml delete mode 100644 res/races/insect.xml delete mode 100644 res/races/orc.xml delete mode 100644 res/races/troll.xml delete mode 100644 res/races/zombie.xml diff --git a/conf/e3/races.json b/conf/e3/races.json index 1ac473f49..a7cd06857 100644 --- a/conf/e3/races.json +++ b/conf/e3/races.json @@ -1,9 +1,9 @@ { "include": [ - "config://res/races/goblin-3.xml", - "config://res/races/wyrm.xml", - "config://res/races/dragon.xml", - "config://res/races/youngdragon.xml", - "config://res/e3a/races.xml" + "config://res/e3a/races.xml", + "config://res/e3a/races/goblin.xml", + "config://res/e3a/races/wyrm.xml", + "config://res/e3a/races/dragon.xml", + "config://res/e3a/races/youngdragon.xml" ] } diff --git a/res/races/dragon.xml b/res/e3a/races/dragon.xml similarity index 100% rename from res/races/dragon.xml rename to res/e3a/races/dragon.xml diff --git a/res/races/goblin-3.xml b/res/e3a/races/goblin.xml similarity index 100% rename from res/races/goblin-3.xml rename to res/e3a/races/goblin.xml diff --git a/res/races/wyrm.xml b/res/e3a/races/wyrm.xml similarity index 100% rename from res/races/wyrm.xml rename to res/e3a/races/wyrm.xml diff --git a/res/races/youngdragon.xml b/res/e3a/races/youngdragon.xml similarity index 100% rename from res/races/youngdragon.xml rename to res/e3a/races/youngdragon.xml diff --git a/res/races/aquarian.xml b/res/races/aquarian.xml deleted file mode 100644 index 4950d60d1..000000000 --- a/res/races/aquarian.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/res/races/cat.xml b/res/races/cat.xml deleted file mode 100644 index 2e0f73dcf..000000000 --- a/res/races/cat.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/races/demon.xml b/res/races/demon.xml deleted file mode 100644 index 21a1f289d..000000000 --- a/res/races/demon.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/races/dwarf.xml b/res/races/dwarf.xml deleted file mode 100644 index 4f2719649..000000000 --- a/res/races/dwarf.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/races/elf.xml b/res/races/elf.xml deleted file mode 100644 index 968ad22f2..000000000 --- a/res/races/elf.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/races/goblin.xml b/res/races/goblin.xml deleted file mode 100644 index ec224a0c7..000000000 --- a/res/races/goblin.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/races/halfling.xml b/res/races/halfling.xml deleted file mode 100644 index 22001df7d..000000000 --- a/res/races/halfling.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/races/human.xml b/res/races/human.xml deleted file mode 100644 index 00c11f8a6..000000000 --- a/res/races/human.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/res/races/insect.xml b/res/races/insect.xml deleted file mode 100644 index b783f047a..000000000 --- a/res/races/insect.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/races/orc.xml b/res/races/orc.xml deleted file mode 100644 index 47754152a..000000000 --- a/res/races/orc.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/races/troll.xml b/res/races/troll.xml deleted file mode 100644 index 7d3f18551..000000000 --- a/res/races/troll.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/races/zombie.xml b/res/races/zombie.xml deleted file mode 100644 index 01407b29a..000000000 --- a/res/races/zombie.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - From a35a0ca516ff8820997228987ad62c2adffa98ee Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 19 May 2019 10:46:10 +0200 Subject: [PATCH 50/56] 2582 WIP: failing test for regenerate_aura --- src/magic.c | 5 +++-- src/magic.test.c | 30 ++++++++++++++++++++++++++---- src/randenc.c | 2 ++ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/magic.c b/src/magic.c index 7b15bb71d..553927ec6 100644 --- a/src/magic.c +++ b/src/magic.c @@ -651,12 +651,13 @@ int max_spellpoints(const struct unit *u, const region * r) const sc_mage *m; assert(u); + m = get_mage(u); + if (!m) return 0; if (!r) r = u->region; sk = effskill(u, SK_MAGIC, r); msp = rc_maxaura(u_race(u)) * (pow(sk, potenz) / divisor + 1); - m = get_mage(u); - if (m) msp += m->spchange; + msp += m->spchange; rtype = rt_find("aurafocus"); if (rtype && i_get(u->items, rtype->itype) > 0) { diff --git a/src/magic.test.c b/src/magic.test.c index 160662c15..83d5610f6 100644 --- a/src/magic.test.c +++ b/src/magic.test.c @@ -446,14 +446,14 @@ static void test_max_spellpoints(CuTest *tc) { test_setup(); rc = test_create_race("human"); u = test_create_unit(test_create_faction(rc), test_create_plain(0, 0)); - CuAssertIntEquals(tc, 1, max_spellpoints_depr(u->region, u)); - CuAssertIntEquals(tc, 1, max_spellpoints(u, u->region)); - CuAssertIntEquals(tc, 1, max_spellpoints(u, NULL)); + CuAssertIntEquals(tc, 0, max_spellpoints_depr(u->region, u)); + CuAssertIntEquals(tc, 0, max_spellpoints(u, u->region)); + CuAssertIntEquals(tc, 0, max_spellpoints(u, NULL)); + create_mage(u, M_GWYRRD); rc->maxaura = 100; CuAssertIntEquals(tc, 1, max_spellpoints(u, u->region)); rc->maxaura = 200; CuAssertIntEquals(tc, 2, max_spellpoints(u, u->region)); - create_mage(u, M_GWYRRD); set_level(u, SK_MAGIC, 1); CuAssertIntEquals(tc, 3, max_spellpoints(u, u->region)); set_level(u, SK_MAGIC, 2); @@ -484,6 +484,27 @@ static void test_regenerate_aura(CuTest *tc) { CuAssertIntEquals(tc, 1, get_spellpoints(u)); } +/** + * Test for Bug 2582. + * + * Migrant units that are not familiars, but whose race has a maxaura + * must not regenerate aura. + */ +static void test_regenerate_aura_migrants(CuTest *tc) { + unit *u; + race *rc; + + test_setup(); + test_teardown(); + rc = test_create_race("demon"); + rc->maxaura = 100; + u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); + u_setrace(u, rc); + CuAssertIntEquals(tc, 0, get_spellpoints(u)); + regenerate_aura(); + CuAssertIntEquals(tc, 0, get_spellpoints(u)); +} + static void test_illusioncastle(CuTest *tc) { building *b; @@ -635,5 +656,6 @@ CuSuite *get_magic_suite(void) SUITE_ADD_TEST(suite, test_max_spellpoints); SUITE_ADD_TEST(suite, test_illusioncastle); SUITE_ADD_TEST(suite, test_regenerate_aura); + SUITE_ADD_TEST(suite, test_regenerate_aura_migrants); return suite; } diff --git a/src/randenc.c b/src/randenc.c index 9c3fd4739..e6ebf549b 100644 --- a/src/randenc.c +++ b/src/randenc.c @@ -239,6 +239,7 @@ static void move_iceberg(region * r) "region dir", r, dir)); } + stats_count("iceberg.drift", 1); x = r->x; y = r->y; @@ -379,6 +380,7 @@ static void create_icebergs(void) continue; r->terrain = t_iceberg; + stats_count("iceberg.terraform", 1); fset(r, RF_SELECT); move_iceberg(r); From cab3f4309fe21bb5235780b756846ba9927fad8d Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 19 May 2019 12:38:54 +0200 Subject: [PATCH 51/56] simple test for aurafocus effect on max spellpoints. --- src/magic.test.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/magic.test.c b/src/magic.test.c index 83d5610f6..7923fb6d8 100644 --- a/src/magic.test.c +++ b/src/magic.test.c @@ -442,6 +442,7 @@ static void test_magic_resistance(CuTest *tc) { static void test_max_spellpoints(CuTest *tc) { unit *u; race *rc; + item_type *it_aura; test_setup(); rc = test_create_race("human"); @@ -451,16 +452,20 @@ static void test_max_spellpoints(CuTest *tc) { CuAssertIntEquals(tc, 0, max_spellpoints(u, NULL)); create_mage(u, M_GWYRRD); rc->maxaura = 100; - CuAssertIntEquals(tc, 1, max_spellpoints(u, u->region)); + CuAssertIntEquals(tc, 1, max_spellpoints(u, NULL)); rc->maxaura = 200; - CuAssertIntEquals(tc, 2, max_spellpoints(u, u->region)); + CuAssertIntEquals(tc, 2, max_spellpoints(u, NULL)); set_level(u, SK_MAGIC, 1); - CuAssertIntEquals(tc, 3, max_spellpoints(u, u->region)); + CuAssertIntEquals(tc, 3, max_spellpoints(u, NULL)); set_level(u, SK_MAGIC, 2); - CuAssertIntEquals(tc, 9, max_spellpoints(u, u->region)); + CuAssertIntEquals(tc, 9, max_spellpoints(u, NULL)); /* permanent aura loss: */ CuAssertIntEquals(tc, 7, change_maxspellpoints(u, -2)); - CuAssertIntEquals(tc, 7, max_spellpoints(u, u->region)); + CuAssertIntEquals(tc, 7, max_spellpoints(u, NULL)); + /* aurafocus: */ + it_aura = test_create_itemtype("aurafocus"); + i_change(&u->items, it_aura, 1); + CuAssertIntEquals(tc, 9, max_spellpoints(u, NULL)); test_teardown(); } From 670aa56d4ec6ab94844e6ba751e591ad6c382c64 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 19 May 2019 15:14:01 +0200 Subject: [PATCH 52/56] fix_fam_spells happy case test (is familiar) --- src/kernel/save.c | 2 +- src/magic.c | 14 ++++++++++++-- src/magic.h | 3 ++- src/magic.test.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 57 insertions(+), 6 deletions(-) diff --git a/src/kernel/save.c b/src/kernel/save.c index f43c21f20..1d51ee433 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -1659,7 +1659,7 @@ int read_game(gamedata *data) fix_familiars(fix_fam_triggers); } if (data->version < FAMILIAR_FIXSPELLBOOK_VERSION) { - fix_familiars(fix_fam_mage); + fix_familiars(fix_fam_spells); } log_debug("Done loading turn %d.", turn); diff --git a/src/magic.c b/src/magic.c index 553927ec6..8b8cf9c3d 100644 --- a/src/magic.c +++ b/src/magic.c @@ -2251,9 +2251,20 @@ static int copy_spell_cb(spellbook_entry *sbe, void *udata) { } /** + * Entferne Magie-Attribut von Migranten, die keine Vertrauten sind. + * + * Einmalige Reparatur von Vertrauten (Bug 2585). + */ +void fix_fam_migrant(unit *u) { + +} + +/** + * Einheiten, die Vertraute sind, bekommen ihre fehlenden Zauber. + * * Einmalige Reparatur von Vertrauten (Bugs 2451, 2517). */ -void fix_fam_mage(unit *u) { +void fix_fam_spells(unit *u) { sc_mage *dmage; unit *du = unit_create(0); @@ -2286,7 +2297,6 @@ void fix_fam_mage(unit *u) { void create_newfamiliar(unit * mage, unit * fam) { - create_mage(fam, M_GRAY); set_familiar(mage, fam); equip_familiar(fam); diff --git a/src/magic.h b/src/magic.h index 5269e3259..15870e90c 100644 --- a/src/magic.h +++ b/src/magic.h @@ -330,7 +330,8 @@ extern "C" { void create_newfamiliar(struct unit *mage, struct unit *familiar); void create_newclone(struct unit *mage, struct unit *familiar); - void fix_fam_mage(struct unit *u); + void fix_fam_spells(struct unit *u); + void fix_fam_migrant(struct unit *u); const char *spell_info(const struct spell *sp, const struct locale *lang); diff --git a/src/magic.test.c b/src/magic.test.c index 7923fb6d8..e70e026ca 100644 --- a/src/magic.test.c +++ b/src/magic.test.c @@ -473,7 +473,6 @@ static void test_regenerate_aura(CuTest *tc) { unit *u; test_setup(); - test_teardown(); u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); create_mage(u, M_GWYRRD); CuAssertIntEquals(tc, 0, get_spellpoints(u)); @@ -487,6 +486,7 @@ static void test_regenerate_aura(CuTest *tc) { CuAssertIntEquals(tc, 1, max_spellpoints(u, NULL)); regenerate_aura(); CuAssertIntEquals(tc, 1, get_spellpoints(u)); + test_teardown(); } /** @@ -500,14 +500,53 @@ static void test_regenerate_aura_migrants(CuTest *tc) { race *rc; test_setup(); - test_teardown(); rc = test_create_race("demon"); rc->maxaura = 100; + rc->flags |= RCF_FAMILIAR; + u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); u_setrace(u, rc); CuAssertIntEquals(tc, 0, get_spellpoints(u)); regenerate_aura(); CuAssertIntEquals(tc, 0, get_spellpoints(u)); + test_teardown(); +} + +static bool equip_spell(unit *u, const char *eqname, int mask) { + spell * sp = find_spell("test"); + unit_add_spell(u, sp, 1); + return true; +} + +static void test_fix_fam_spells(CuTest *tc) { + unit *u, *mage; + race *rc; + spell * sp; + + test_setup(); + sp = create_spell("test"); + rc = test_create_race("demon"); + rc->maxaura = 100; + rc->flags |= RCF_FAMILIAR; + + /* u is a familiar, and gets equipped: */ + mage = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); + u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); + u_setrace(u, rc); + /* reproduce the bug, create a broken familiar: */ + callbacks.equip_unit = NULL; + create_newfamiliar(mage, u); + set_level(u, SK_MAGIC, 1); + CuAssertPtrEquals(tc, NULL, unit_get_spellbook(u)); + CuAssertTrue(tc, !u_hasspell(u, sp)); + callbacks.equip_unit = equip_spell; + fix_fam_spells(u); + CuAssertPtrNotNull(tc, unit_get_spellbook(u)); + CuAssertTrue(tc, u_hasspell(u, sp)); + + /* u is a migrant, and does not get equipped: */ + + test_teardown(); } static void test_illusioncastle(CuTest *tc) @@ -662,5 +701,6 @@ CuSuite *get_magic_suite(void) SUITE_ADD_TEST(suite, test_illusioncastle); SUITE_ADD_TEST(suite, test_regenerate_aura); SUITE_ADD_TEST(suite, test_regenerate_aura_migrants); + SUITE_ADD_TEST(suite, test_fix_fam_spells); return suite; } From 1c01f4d0834e3d86b79806faf7b872046920053f Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 19 May 2019 15:28:16 +0200 Subject: [PATCH 53/56] fix the fix_fam_spells function (2585 WIP) --- src/magic.c | 4 ++++ src/magic.test.c | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/src/magic.c b/src/magic.c index 8b8cf9c3d..517921212 100644 --- a/src/magic.c +++ b/src/magic.c @@ -2268,6 +2268,10 @@ void fix_fam_spells(unit *u) { sc_mage *dmage; unit *du = unit_create(0); + if (!is_familiar(u)) { + return; + } + u_setrace(du, u_race(u)); dmage = create_mage(du, M_GRAY); equip_familiar(du); diff --git a/src/magic.test.c b/src/magic.test.c index e70e026ca..ead8a6a8a 100644 --- a/src/magic.test.c +++ b/src/magic.test.c @@ -540,11 +540,19 @@ static void test_fix_fam_spells(CuTest *tc) { CuAssertPtrEquals(tc, NULL, unit_get_spellbook(u)); CuAssertTrue(tc, !u_hasspell(u, sp)); callbacks.equip_unit = equip_spell; + CuAssertTrue(tc, is_familiar(u)); fix_fam_spells(u); + CuAssertTrue(tc, is_familiar(u)); CuAssertPtrNotNull(tc, unit_get_spellbook(u)); CuAssertTrue(tc, u_hasspell(u, sp)); /* u is a migrant, and does not get equipped: */ + u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); + u_setrace(u, rc); + CuAssertTrue(tc, !is_familiar(u)); + fix_fam_spells(u); + CuAssertTrue(tc, !is_familiar(u)); + CuAssertPtrEquals(tc, NULL, unit_get_spellbook(u)); test_teardown(); } From 9f2741f3dcff8f0a4f0f2b33dd247b4cbe8c7947 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 19 May 2019 15:47:13 +0200 Subject: [PATCH 54/56] fix any migrants that have received aura. --- src/kernel/equipment.test.c | 2 +- src/kernel/gamedata.h | 3 ++- src/kernel/save.c | 3 +++ src/magic.c | 4 +++- src/magic.test.c | 36 ++++++++++++++++++++++++++++++++++++ src/tests.c | 7 ++++--- 6 files changed, 49 insertions(+), 6 deletions(-) diff --git a/src/kernel/equipment.test.c b/src/kernel/equipment.test.c index 331625c14..ff6b5621f 100644 --- a/src/kernel/equipment.test.c +++ b/src/kernel/equipment.test.c @@ -24,10 +24,10 @@ static bool equip_callback(unit *u, const char *eqname, int mask) { static void test_equipment(CuTest * tc) { - callbacks.equip_unit = equip_callback; unit * u; test_setup(); + callbacks.equip_unit = equip_callback; u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL)); CuAssertIntEquals(tc, true, equip_unit_mask(u, "hodor", EQUIP_ALL)); diff --git a/src/kernel/gamedata.h b/src/kernel/gamedata.h index 527d2c5e7..bc1701173 100644 --- a/src/kernel/gamedata.h +++ b/src/kernel/gamedata.h @@ -44,8 +44,9 @@ #define FIX_STARTLEVEL_VERSION 366 /* fixing resource startlevels */ #define FIX_RES_BASE_VERSION 367 /* fixing resource base */ #define FIX_CLONES_VERSION 368 /* dissolve clones */ +#define FIX_MIGRANT_AURA_VERSION 369 /* bug 2585, migrants with aura */ -#define RELEASE_VERSION FIX_CLONES_VERSION /* current datafile */ +#define RELEASE_VERSION FIX_MIGRANT_AURA_VERSION /* current datafile */ #define MIN_VERSION UIDHASH_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 */ diff --git a/src/kernel/save.c b/src/kernel/save.c index 1d51ee433..2b66c7f18 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -1661,6 +1661,9 @@ int read_game(gamedata *data) if (data->version < FAMILIAR_FIXSPELLBOOK_VERSION) { fix_familiars(fix_fam_spells); } + if (data->version < FIX_MIGRANT_AURA_VERSION) { + fix_familiars(fix_fam_migrant); + } log_debug("Done loading turn %d.", turn); diff --git a/src/magic.c b/src/magic.c index 517921212..5b64b1459 100644 --- a/src/magic.c +++ b/src/magic.c @@ -2256,7 +2256,9 @@ static int copy_spell_cb(spellbook_entry *sbe, void *udata) { * Einmalige Reparatur von Vertrauten (Bug 2585). */ void fix_fam_migrant(unit *u) { - + if (!is_familiar(u)) { + a_removeall(&u->attribs, &at_mage); + } } /** diff --git a/src/magic.test.c b/src/magic.test.c index ead8a6a8a..068efdfa4 100644 --- a/src/magic.test.c +++ b/src/magic.test.c @@ -512,6 +512,41 @@ static void test_regenerate_aura_migrants(CuTest *tc) { test_teardown(); } +static void test_fix_fam_migrants(CuTest *tc) { + unit *u, *mage; + race *rc; + + test_setup(); + rc = test_create_race("demon"); + rc->maxaura = 100; + rc->flags |= RCF_FAMILIAR; + + /* u is a migrant with at_mage attribute, but not a familiar */ + u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); + u_setrace(u, rc); + create_mage(u, M_GRAY); + CuAssertTrue(tc, !is_familiar(u)); + CuAssertPtrNotNull(tc, get_mage(u)); + fix_fam_migrant(u); + CuAssertTrue(tc, !is_familiar(u)); + CuAssertPtrEquals(tc, NULL, get_mage(u)); + + /* u is a familiar, and stays unchanged: */ + mage = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); + u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); + u_setrace(u, rc); + /* reproduce the bug, create a broken familiar: */ + create_newfamiliar(mage, u); + set_level(u, SK_MAGIC, 1); + CuAssertTrue(tc, is_familiar(u)); + CuAssertPtrNotNull(tc, get_mage(u)); + fix_fam_migrant(u); + CuAssertTrue(tc, is_familiar(u)); + CuAssertPtrNotNull(tc, get_mage(u)); + + test_teardown(); +} + static bool equip_spell(unit *u, const char *eqname, int mask) { spell * sp = find_spell("test"); unit_add_spell(u, sp, 1); @@ -710,5 +745,6 @@ CuSuite *get_magic_suite(void) SUITE_ADD_TEST(suite, test_regenerate_aura); SUITE_ADD_TEST(suite, test_regenerate_aura_migrants); SUITE_ADD_TEST(suite, test_fix_fam_spells); + SUITE_ADD_TEST(suite, test_fix_fam_migrants); return suite; } diff --git a/src/tests.c b/src/tests.c index 26e57d23a..a34e6c743 100644 --- a/src/tests.c +++ b/src/tests.c @@ -7,8 +7,9 @@ #include "vortex.h" #include "kernel/calendar.h" -#include -#include +#include "kernel/callbacks.h" +#include "kernel/config.h" +#include "kernel/alliance.h" #include #include #include @@ -228,7 +229,7 @@ static void test_reset(void) { errno = 0; log_error("errno: %d (%s)", error, strerror(error)); } - + memset(&callbacks, 0, sizeof(callbacks)); free_gamedata(); free_terrains(); free_resources(); From 0e888c264fab20f0fe7a46ca1c57d29107dcf681 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 26 May 2019 19:51:32 +0200 Subject: [PATCH 55/56] halflings take more hunger damage. nobody can die after one week of hunger . --- conf/e2/config.json | 2 +- res/eressea/races.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/conf/e2/config.json b/conf/e2/config.json index cc480b2e2..114fffe52 100644 --- a/conf/e2/config.json +++ b/conf/e2/config.json @@ -42,7 +42,7 @@ "nmr.removenewbie": false, "GiveRestriction": 3, "hunger.long": false, - "hunger.damage": "1d9+9", + "hunger.damage": "1d8+6", "init_spells": 0, "game.era": 2, "game.start": 184, diff --git a/res/eressea/races.xml b/res/eressea/races.xml index bf9eeb18c..c858aceb1 100644 --- a/res/eressea/races.xml +++ b/res/eressea/races.xml @@ -782,7 +782,7 @@ - + From 873086b75c84377df6c66425387979e1a1e66526 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 26 May 2019 20:01:28 +0200 Subject: [PATCH 56/56] use cadaver for box backups --- process/backup-eressea | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/process/backup-eressea b/process/backup-eressea index 12ced938c..3944a9221 100755 --- a/process/backup-eressea +++ b/process/backup-eressea @@ -4,6 +4,13 @@ if [ -z $ERESSEA ] ; then echo "The ERESSEA environment variable is not set. Assuming $ERESSEA." fi GAME=$1 + +upload() { + SRC="$1" + DST=$(basename "$SRC") + echo put "$SRC" "$DST" | cadaver "https://dav.box.com/dav/Eressea/game-$GAME/" +} + if [ ! -d $ERESSEA/game-$GAME ]; then echo "No such game: game-$GAME." exit 1 @@ -26,7 +33,7 @@ fi if [ -e reports/reports.txt ] ; then echo "backup reports $TURN, game $GAME" tar cjf backup/$TURN-reports.tar.bz2 reports - curl -s -n -T backup/$TURN-reports.tar.bz2 https://dav.box.com/dav/Eressea/game-$GAME/$TURN-reports.tar.bz2 + upload backup/$TURN-reports.tar.bz2 fi files="data/$TURN.dat parteien.full parteien" if [ -e orders.$TURN ]; then @@ -34,5 +41,5 @@ files="$files orders.$TURN" fi echo "backup turn $TURN, game $GAME, files: $files" tar cjf backup/$TURN.tar.bz2 $files -curl -s -n -T backup/$TURN.tar.bz2 https://dav.box.com/dav/Eressea/game-$GAME/$TURN.tar.bz2 -#curl -s -n -T eressea.db https://dav.box.com/dav/Eressea/eressea.db +upload backup/$TURN.tar.bz2 +