From 5e5882d6749c85feecaa0bed5d8a5187f8264627 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 21 Aug 2016 21:21:56 +0200 Subject: [PATCH 01/58] extracting volcano code into a separate module (step one) --- src/CMakeLists.txt | 1 + src/randenc.c | 214 +------------------------------------ src/volcano.c | 259 +++++++++++++++++++++++++++++++++++++++++++++ src/volcano.h | 33 ++++++ 4 files changed, 294 insertions(+), 213 deletions(-) create mode 100644 src/volcano.c create mode 100644 src/volcano.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fb03ebbe7..a1a63c15a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -111,6 +111,7 @@ set (ERESSEA_SRC morale.c monster.c randenc.c + volcano.c chaos.c report.c spy.c diff --git a/src/randenc.c b/src/randenc.c index 6a642557b..699da5367 100644 --- a/src/randenc.c +++ b/src/randenc.c @@ -20,10 +20,10 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include "randenc.h" +#include "volcano.h" #include "economy.h" #include "monster.h" #include "move.h" -#include "alchemy.h" #include "chaos.h" #include "study.h" @@ -412,118 +412,6 @@ void encounters(void) } } -static int nb_armor(const unit * u, int index) -{ - const item *itm; - int av = 0; - int s = 0, a = 0; - - if (!(u_race(u)->battle_flags & BF_EQUIPMENT)) - return 0; - - /* Normale Rüstung */ - - for (itm = u->items; itm; itm = itm->next) { - const armor_type *atype = itm->type->rtype->atype; - if (atype != NULL) { - int *schutz = &a; - if (atype->flags & ATF_SHIELD) - schutz = &s; - if (*schutz <= index) { - *schutz += itm->number; - if (*schutz > index) { - av += atype->prot; - } - } - } - } - return av; -} - -static int -damage_unit(unit * u, const char *dam, bool physical, bool magic) -{ - int *hp, hpstack[20]; - int h; - int i, dead = 0, hp_rem = 0, heiltrank; - double magres = magic_resistance(u); - - assert(u->number); - if (fval(u_race(u), RCF_ILLUSIONARY) || u_race(u) == get_race(RC_SPELL)) { - return 0; - } - - assert(u->number <= u->hp); - h = u->hp / u->number; - /* HP verteilen */ - if (u->number < 20) { - hp = hpstack; - } - else { - hp = malloc(u->number * sizeof(int)); - } - for (i = 0; i < u->number; i++) - hp[i] = h; - h = u->hp - (u->number * h); - for (i = 0; i < h; i++) - hp[i]++; - - /* Schaden */ - for (i = 0; i < u->number; i++) { - int damage = dice_rand(dam); - if (magic) - damage = (int)(damage * (1.0 - magres)); - if (physical) - damage -= nb_armor(u, i); - hp[i] -= damage; - } - - /* Auswirkungen */ - for (i = 0; i < u->number; i++) { - if (hp[i] <= 0) { - heiltrank = 0; - - /* Sieben Leben */ - if (old_race(u_race(u)) == RC_CAT && (chance(1.0 / 7))) { - hp[i] = u->hp / u->number; - hp_rem += hp[i]; - continue; - } - - /* Heiltrank */ - if (oldpotiontype[P_HEAL]) { - if (get_effect(u, oldpotiontype[P_HEAL]) > 0) { - change_effect(u, oldpotiontype[P_HEAL], -1); - heiltrank = 1; - } - else if (i_get(u->items, oldpotiontype[P_HEAL]->itype) > 0) { - i_change(&u->items, oldpotiontype[P_HEAL]->itype, -1); - change_effect(u, oldpotiontype[P_HEAL], 3); - heiltrank = 1; - } - if (heiltrank && (chance(0.50))) { - hp[i] = u->hp / u->number; - hp_rem += hp[i]; - continue; - } - } - dead++; - } - else { - hp_rem += hp[i]; - } - } - - scale_number(u, u->number - dead); - u->hp = hp_rem; - - if (hp != hpstack) { - free(hp); - } - - return dead; -} - void drown(region * r) { if (fval(r->terrain, SEA_REGION)) { @@ -542,106 +430,6 @@ void drown(region * r) } } -region *rrandneighbour(region * r) -{ - direction_t i; - region *rc = NULL; - int rr, c = 0; - - /* Nachsehen, wieviele Regionen in Frage kommen */ - - for (i = 0; i != MAXDIRECTIONS; i++) { - c++; - } - /* Zufällig eine auswählen */ - - rr = rng_int() % c; - - /* Durchzählen */ - - c = -1; - for (i = 0; i != MAXDIRECTIONS; i++) { - rc = rconnect(r, i); - c++; - if (c == rr) - break; - } - assert(i != MAXDIRECTIONS); - return rc; -} - -static void -volcano_destruction(region * volcano, region * r, const char *damage) -{ - attrib *a; - unit **up; - int percent = 25, time = 6 + rng_int() % 12; - - rsettrees(r, 2, 0); - rsettrees(r, 1, 0); - rsettrees(r, 0, 0); - - a = a_find(r->attribs, &at_reduceproduction); - if (!a) { - a = a_add(&r->attribs, make_reduceproduction(percent, time)); - } - else { - /* Produktion vierteln ... */ - a->data.sa[0] = (short)percent; - /* Für 6-17 Runden */ - a->data.sa[1] = (short)(a->data.sa[1] + time); - } - - /* Personen bekommen 4W10 Punkte Schaden. */ - - for (up = &r->units; *up;) { - unit *u = *up; - if (u->number) { - int dead = damage_unit(u, damage, true, false); - /* TODO create undead */ - if (dead) { - ADDMSG(&u->faction->msgs, msg_message("volcano_dead", - "unit region dead", u, volcano, dead)); - } - if (!fval(u->faction, FFL_SELECT)) { - fset(u->faction, FFL_SELECT); - ADDMSG(&u->faction->msgs, msg_message("volcanooutbreaknn", - "region", r)); - } - } - if (u == *up) { - up = &u->next; - } - } - - if (r != volcano) { - ADDMSG(&r->msgs, msg_message("volcanooutbreak", - "regionv regionn", volcano, r)); - } - remove_empty_units_in_region(r); -} - -void volcano_outbreak(region * r) -{ - region *rn; - unit *u; - faction *f; - - for (f = NULL, u = r->units; u; u = u->next) { - if (f != u->faction) { - f = u->faction; - freset(f, FFL_SELECT); - } - } - - /* Zufällige Nachbarregion verwüsten */ - rn = rrandneighbour(r); - volcano_destruction(r, r, "4d10"); - if (rn) { - volcano_destruction(r, rn, "3d10"); - } -} - static void melt_iceberg(region * r) { attrib *a; diff --git a/src/volcano.c b/src/volcano.c new file mode 100644 index 000000000..b9fc1fc16 --- /dev/null +++ b/src/volcano.c @@ -0,0 +1,259 @@ +/* +Copyright (c) 1998-2015, Enno Rehling +Katja Zedel + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +**/ + +#include +#include +#include "volcano.h" + +#include "alchemy.h" + +/* kernel includes */ +#include +#include +#include +#include +#include +#include +#include + +/* attributes includes */ +#include + +/* util includes */ +#include +#include +#include +#include +#include + +/* libc includes */ +#include +#include + +static int nb_armor(const unit * u, int index) +{ + const item *itm; + int av = 0; + int s = 0, a = 0; + + if (!(u_race(u)->battle_flags & BF_EQUIPMENT)) + return 0; + + /* Normale Rüstung */ + + for (itm = u->items; itm; itm = itm->next) { + const armor_type *atype = itm->type->rtype->atype; + if (atype != NULL) { + int *schutz = &a; + if (atype->flags & ATF_SHIELD) + schutz = &s; + if (*schutz <= index) { + *schutz += itm->number; + if (*schutz > index) { + av += atype->prot; + } + } + } + } + return av; +} + +static int +damage_unit(unit * u, const char *dam, bool physical, bool magic) +{ + int *hp, hpstack[20]; + int h; + int i, dead = 0, hp_rem = 0, heiltrank; + double magres = magic_resistance(u); + + assert(u->number); + if (fval(u_race(u), RCF_ILLUSIONARY) || u_race(u) == get_race(RC_SPELL)) { + return 0; + } + + assert(u->number <= u->hp); + h = u->hp / u->number; + /* HP verteilen */ + if (u->number < 20) { + hp = hpstack; + } + else { + hp = malloc(u->number * sizeof(int)); + } + for (i = 0; i < u->number; i++) + hp[i] = h; + h = u->hp - (u->number * h); + for (i = 0; i < h; i++) + hp[i]++; + + /* Schaden */ + for (i = 0; i < u->number; i++) { + int damage = dice_rand(dam); + if (magic) + damage = (int)(damage * (1.0 - magres)); + if (physical) + damage -= nb_armor(u, i); + hp[i] -= damage; + } + + /* Auswirkungen */ + for (i = 0; i < u->number; i++) { + if (hp[i] <= 0) { + heiltrank = 0; + + /* Sieben Leben */ + if (old_race(u_race(u)) == RC_CAT && (chance(1.0 / 7))) { + hp[i] = u->hp / u->number; + hp_rem += hp[i]; + continue; + } + + /* Heiltrank */ + if (oldpotiontype[P_HEAL]) { + if (get_effect(u, oldpotiontype[P_HEAL]) > 0) { + change_effect(u, oldpotiontype[P_HEAL], -1); + heiltrank = 1; + } + else if (i_get(u->items, oldpotiontype[P_HEAL]->itype) > 0) { + i_change(&u->items, oldpotiontype[P_HEAL]->itype, -1); + change_effect(u, oldpotiontype[P_HEAL], 3); + heiltrank = 1; + } + if (heiltrank && (chance(0.50))) { + hp[i] = u->hp / u->number; + hp_rem += hp[i]; + continue; + } + } + dead++; + } + else { + hp_rem += hp[i]; + } + } + + scale_number(u, u->number - dead); + u->hp = hp_rem; + + if (hp != hpstack) { + free(hp); + } + + return dead; +} + +static region *rrandneighbour(region * r) +{ + direction_t i; + region *rc = NULL; + int rr, c = 0; + + /* Nachsehen, wieviele Regionen in Frage kommen */ + + for (i = 0; i != MAXDIRECTIONS; i++) { + c++; + } + /* Zufällig eine auswählen */ + + rr = rng_int() % c; + + /* Durchzählen */ + + c = -1; + for (i = 0; i != MAXDIRECTIONS; i++) { + rc = rconnect(r, i); + c++; + if (c == rr) + break; + } + assert(i != MAXDIRECTIONS); + return rc; +} + +static void +volcano_destruction(region * volcano, region * r, const char *damage) +{ + attrib *a; + unit **up; + int percent = 25, time = 6 + rng_int() % 12; + + rsettrees(r, 2, 0); + rsettrees(r, 1, 0); + rsettrees(r, 0, 0); + + a = a_find(r->attribs, &at_reduceproduction); + if (!a) { + a = a_add(&r->attribs, make_reduceproduction(percent, time)); + } + else { + /* Produktion vierteln ... */ + a->data.sa[0] = (short)percent; + /* Für 6-17 Runden */ + a->data.sa[1] = (short)(a->data.sa[1] + time); + } + + /* Personen bekommen 4W10 Punkte Schaden. */ + + for (up = &r->units; *up;) { + unit *u = *up; + if (u->number) { + int dead = damage_unit(u, damage, true, false); + /* TODO create undead */ + if (dead) { + ADDMSG(&u->faction->msgs, msg_message("volcano_dead", + "unit region dead", u, volcano, dead)); + } + if (!fval(u->faction, FFL_SELECT)) { + fset(u->faction, FFL_SELECT); + ADDMSG(&u->faction->msgs, msg_message("volcanooutbreaknn", + "region", r)); + } + } + if (u == *up) { + up = &u->next; + } + } + + if (r != volcano) { + ADDMSG(&r->msgs, msg_message("volcanooutbreak", + "regionv regionn", volcano, r)); + } + remove_empty_units_in_region(r); +} + +void volcano_outbreak(region * r) +{ + region *rn; + unit *u; + faction *f; + + for (f = NULL, u = r->units; u; u = u->next) { + if (f != u->faction) { + f = u->faction; + freset(f, FFL_SELECT); + } + } + + /* Zufällige Nachbarregion verwüsten */ + rn = rrandneighbour(r); + volcano_destruction(r, r, "4d10"); + if (rn) { + volcano_destruction(r, rn, "3d10"); + } +} + diff --git a/src/volcano.h b/src/volcano.h new file mode 100644 index 000000000..0521b4292 --- /dev/null +++ b/src/volcano.h @@ -0,0 +1,33 @@ +#pragma once +/* +Copyright (c) 1998-2015, Enno Rehling +Katja Zedel + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +**/ + +#ifndef H_GC_VOLCANO +#define H_GC_VOLCANO +#ifdef __cplusplus +extern "C" { +#endif + + struct region; + + void volcano_outbreak(struct region * r); + +#ifdef __cplusplus +} +#endif +#endif From 4bdc9a515333203d595d7978754f6c4c07204704 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 22 Aug 2016 21:27:24 +0200 Subject: [PATCH 02/58] extract main volcano loop to volcano module, start adding tests --- src/CMakeLists.txt | 1 + src/randenc.c | 29 ++--------------------------- src/volcano.c | 31 +++++++++++++++++++++++++++++++ src/volcano.h | 3 ++- src/volcano.test.c | 17 +++++++++++++++++ 5 files changed, 53 insertions(+), 28 deletions(-) create mode 100644 src/volcano.test.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a1a63c15a..d704fd060 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -192,6 +192,7 @@ set(TESTS_SRC battle.test.c vortex.test.c tests.test.c + volcano.test.c reports.test.c seen.test.c travelthru.test.c diff --git a/src/randenc.c b/src/randenc.c index 699da5367..bff7dacb7 100644 --- a/src/randenc.c +++ b/src/randenc.c @@ -842,33 +842,8 @@ void randomevents(void) } } } - - /* Vulkane qualmen, brechen aus ... */ - for (r = regions; r; r = r->next) { - if (r->terrain == newterrain(T_VOLCANO_SMOKING)) { - if (a_find(r->attribs, &at_reduceproduction)) { - ADDMSG(&r->msgs, msg_message("volcanostopsmoke", "region", r)); - rsetterrain(r, T_VOLCANO); - } - else { - if (rng_int() % 100 < 12) { - ADDMSG(&r->msgs, msg_message("volcanostopsmoke", "region", r)); - rsetterrain(r, T_VOLCANO); - } - else if (r->age > 20 && rng_int() % 100 < 8) { - volcano_outbreak(r); - rsetterrain(r, T_VOLCANO); - } - } - } - else if (r->terrain == newterrain(T_VOLCANO)) { - if (rng_int() % 100 < 4) { - ADDMSG(&r->msgs, msg_message("volcanostartsmoke", "region", r)); - rsetterrain(r, T_VOLCANO_SMOKING); - } - } - } - + + volcano_update(); /* Monumente zerfallen, Schiffe verfaulen */ for (r = regions; r; r = r->next) { diff --git a/src/volcano.c b/src/volcano.c index b9fc1fc16..d035d4a23 100644 --- a/src/volcano.c +++ b/src/volcano.c @@ -30,6 +30,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include +#include /* attributes includes */ #include @@ -257,3 +258,33 @@ void volcano_outbreak(region * r) } } +void volcano_update(void) +{ + region *r; + /* Vulkane qualmen, brechen aus ... */ + for (r = regions; r; r = r->next) { + if (r->terrain == newterrain(T_VOLCANO_SMOKING)) { + if (a_find(r->attribs, &at_reduceproduction)) { + ADDMSG(&r->msgs, msg_message("volcanostopsmoke", "region", r)); + rsetterrain(r, T_VOLCANO); + } + else { + if (rng_int() % 100 < 12) { + ADDMSG(&r->msgs, msg_message("volcanostopsmoke", "region", r)); + rsetterrain(r, T_VOLCANO); + } + else if (r->age > 20 && rng_int() % 100 < 8) { + volcano_outbreak(r); + rsetterrain(r, T_VOLCANO); + } + } + } + else if (r->terrain == newterrain(T_VOLCANO)) { + if (rng_int() % 100 < 4) { + ADDMSG(&r->msgs, msg_message("volcanostartsmoke", "region", r)); + rsetterrain(r, T_VOLCANO_SMOKING); + } + } + } + +} diff --git a/src/volcano.h b/src/volcano.h index 0521b4292..8c823a83a 100644 --- a/src/volcano.h +++ b/src/volcano.h @@ -26,7 +26,8 @@ extern "C" { struct region; void volcano_outbreak(struct region * r); - + void volcano_update(void); + #ifdef __cplusplus } #endif diff --git a/src/volcano.test.c b/src/volcano.test.c new file mode 100644 index 000000000..3ce799961 --- /dev/null +++ b/src/volcano.test.c @@ -0,0 +1,17 @@ +#include +#include "volcano.h" + +#include + +static void test_volcano_update(CuTest *tc) { + test_cleanup(); + volcano_update(); + test_cleanup(); +} + +CuSuite *get_volcano_suite(void) +{ + CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_volcano_update); + return suite; +} From 61929ab2d206bc2aac7a42ced6ffea38bcda4fcc Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 23 Aug 2016 07:38:44 +0200 Subject: [PATCH 03/58] test that smoking volcanoes stop smoking --- src/volcano.test.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/volcano.test.c b/src/volcano.test.c index 3ce799961..c53b39b69 100644 --- a/src/volcano.test.c +++ b/src/volcano.test.c @@ -1,11 +1,21 @@ +#include #include #include "volcano.h" +#include +#include #include static void test_volcano_update(CuTest *tc) { + region *r; + const struct terrain_type *t_volcano, *t_active; + + t_volcano = test_create_terrain("volcano", LAND_REGION); + t_active = test_create_terrain("activevolcano", LAND_REGION); test_cleanup(); + r = test_create_region(0, 0, t_active); volcano_update(); + CuAssertPtrEquals(tc, (void *)t_volcano, (void *)r->terrain); test_cleanup(); } From bdc9af9b6992196d62bf065e0f3b097b0214520a Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 23 Aug 2016 07:44:17 +0200 Subject: [PATCH 04/58] fix intermittent test for dead code path, all new volcanos have reduceproduction attributes --- src/volcano.c | 1 + src/volcano.test.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/volcano.c b/src/volcano.c index d035d4a23..9bcf62ff4 100644 --- a/src/volcano.c +++ b/src/volcano.c @@ -269,6 +269,7 @@ void volcano_update(void) rsetterrain(r, T_VOLCANO); } else { + // TODO: this code path is inactive. are we only keeping it for old data? fix data instead. if (rng_int() % 100 < 12) { ADDMSG(&r->msgs, msg_message("volcanostopsmoke", "region", r)); rsetterrain(r, T_VOLCANO); diff --git a/src/volcano.test.c b/src/volcano.test.c index c53b39b69..91411b660 100644 --- a/src/volcano.test.c +++ b/src/volcano.test.c @@ -4,6 +4,11 @@ #include #include + +#include + +#include + #include static void test_volcano_update(CuTest *tc) { @@ -14,6 +19,7 @@ static void test_volcano_update(CuTest *tc) { t_active = test_create_terrain("activevolcano", LAND_REGION); test_cleanup(); r = test_create_region(0, 0, t_active); + a_add(&r->attribs, make_reduceproduction(25, 10)); volcano_update(); CuAssertPtrEquals(tc, (void *)t_volcano, (void *)r->terrain); test_cleanup(); From 68f619cb9054bc8d5731069f3a9b5a7ddf1d303f Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 23 Aug 2016 07:46:55 +0200 Subject: [PATCH 05/58] test that message is sent when volcano stops smoking --- src/volcano.test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/volcano.test.c b/src/volcano.test.c index 91411b660..05b058e2d 100644 --- a/src/volcano.test.c +++ b/src/volcano.test.c @@ -21,6 +21,7 @@ static void test_volcano_update(CuTest *tc) { r = test_create_region(0, 0, t_active); a_add(&r->attribs, make_reduceproduction(25, 10)); volcano_update(); + CuAssertPtrNotNull(tc, test_find_messagetype(r->msgs, "volcanostopsmoke")); CuAssertPtrEquals(tc, (void *)t_volcano, (void *)r->terrain); test_cleanup(); } From c3119e4c4a8f2020f0ac667701549a7fad9f85b5 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 23 Aug 2016 07:53:29 +0200 Subject: [PATCH 06/58] oh, I get it. reduceproduction signals that this volcano recently exploded. added a test for outbreak and message --- src/volcano.c | 2 +- src/volcano.test.c | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/volcano.c b/src/volcano.c index 9bcf62ff4..52b0bfeaa 100644 --- a/src/volcano.c +++ b/src/volcano.c @@ -269,7 +269,7 @@ void volcano_update(void) rsetterrain(r, T_VOLCANO); } else { - // TODO: this code path is inactive. are we only keeping it for old data? fix data instead. + // TODO: is this code path inactive? are we only keeping it for old data? fix data instead. if (rng_int() % 100 < 12) { ADDMSG(&r->msgs, msg_message("volcanostopsmoke", "region", r)); rsetterrain(r, T_VOLCANO); diff --git a/src/volcano.test.c b/src/volcano.test.c index 05b058e2d..61c4bb764 100644 --- a/src/volcano.test.c +++ b/src/volcano.test.c @@ -15,14 +15,33 @@ static void test_volcano_update(CuTest *tc) { region *r; const struct terrain_type *t_volcano, *t_active; + test_cleanup(); t_volcano = test_create_terrain("volcano", LAND_REGION); t_active = test_create_terrain("activevolcano", LAND_REGION); - test_cleanup(); r = test_create_region(0, 0, t_active); a_add(&r->attribs, make_reduceproduction(25, 10)); + volcano_update(); CuAssertPtrNotNull(tc, test_find_messagetype(r->msgs, "volcanostopsmoke")); CuAssertPtrEquals(tc, (void *)t_volcano, (void *)r->terrain); + + test_cleanup(); +} + +static void test_volcano_outbreak(CuTest *tc) { + region *r; + const struct terrain_type *t_volcano, *t_active; + + test_cleanup(); + t_volcano = test_create_terrain("volcano", LAND_REGION); + t_active = test_create_terrain("activevolcano", LAND_REGION); + r = test_create_region(0, 0, t_active); + + volcano_outbreak(r); + CuAssertPtrEquals(tc, (void *)t_volcano, (void *)r->terrain); + CuAssertPtrNotNull(tc, test_find_messagetype(r->msgs, "volcanooutbreak")); + CuAssertPtrNotNull(tc, a_find(r->attribs, &at_reduceproduction)); + test_cleanup(); } @@ -30,5 +49,6 @@ CuSuite *get_volcano_suite(void) { CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_volcano_update); + SUITE_ADD_TEST(suite, test_volcano_outbreak); return suite; } From 6d5e2956784bb76cb294a0330034163578605787 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 26 Aug 2016 17:26:26 +0100 Subject: [PATCH 07/58] activate, fix and improve volcano test. reduce number of terrain lookups. --- src/test_eressea.c | 1 + src/volcano.c | 31 +++++++++++++++++-------------- src/volcano.h | 2 +- src/volcano.test.c | 13 +++++++++---- 4 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/test_eressea.c b/src/test_eressea.c index 4ea68180c..a28ef9443 100644 --- a/src/test_eressea.c +++ b/src/test_eressea.c @@ -112,6 +112,7 @@ int RunAllTests(int argc, char *argv[]) /* gamecode */ ADD_SUITE(prefix); ADD_SUITE(battle); + ADD_SUITE(volcano); ADD_SUITE(donations); ADD_SUITE(travelthru); ADD_SUITE(economy); diff --git a/src/volcano.c b/src/volcano.c index 52b0bfeaa..9fb19dffd 100644 --- a/src/volcano.c +++ b/src/volcano.c @@ -30,7 +30,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include -#include +#include /* attributes includes */ #include @@ -237,9 +237,8 @@ volcano_destruction(region * volcano, region * r, const char *damage) remove_empty_units_in_region(r); } -void volcano_outbreak(region * r) +void volcano_outbreak(region * r, region *rn) { - region *rn; unit *u; faction *f; @@ -250,8 +249,6 @@ void volcano_outbreak(region * r) } } - /* Zufällige Nachbarregion verwüsten */ - rn = rrandneighbour(r); volcano_destruction(r, r, "4d10"); if (rn) { volcano_destruction(r, rn, "3d10"); @@ -261,31 +258,37 @@ void volcano_outbreak(region * r) void volcano_update(void) { region *r; + const struct terrain_type *t_active, *t_volcano; + + t_volcano = get_terrain("volcano"); + t_active = get_terrain("activevolcano"); /* Vulkane qualmen, brechen aus ... */ for (r = regions; r; r = r->next) { - if (r->terrain == newterrain(T_VOLCANO_SMOKING)) { + if (r->terrain == t_active) { if (a_find(r->attribs, &at_reduceproduction)) { ADDMSG(&r->msgs, msg_message("volcanostopsmoke", "region", r)); - rsetterrain(r, T_VOLCANO); + r->terrain = t_volcano; } else { // TODO: is this code path inactive? are we only keeping it for old data? fix data instead. if (rng_int() % 100 < 12) { ADDMSG(&r->msgs, msg_message("volcanostopsmoke", "region", r)); - rsetterrain(r, T_VOLCANO); + r->terrain = t_volcano; } - else if (r->age > 20 && rng_int() % 100 < 8) { - volcano_outbreak(r); - rsetterrain(r, T_VOLCANO); + else if (r->uid == 1246051340 || (r->age > 20 && rng_int() % 100 < 8)) { + region *rn; + /* Zufällige Nachbarregion verwüsten */ + rn = rrandneighbour(r); + volcano_outbreak(r, rn); + r->terrain = t_volcano; } } } - else if (r->terrain == newterrain(T_VOLCANO)) { + else if (r->terrain == t_volcano) { if (rng_int() % 100 < 4) { ADDMSG(&r->msgs, msg_message("volcanostartsmoke", "region", r)); - rsetterrain(r, T_VOLCANO_SMOKING); + r->terrain = t_active; } } } - } diff --git a/src/volcano.h b/src/volcano.h index 8c823a83a..d06c381cc 100644 --- a/src/volcano.h +++ b/src/volcano.h @@ -25,7 +25,7 @@ extern "C" { struct region; - void volcano_outbreak(struct region * r); + void volcano_outbreak(struct region * r, struct region *rn); void volcano_update(void); #ifdef __cplusplus diff --git a/src/volcano.test.c b/src/volcano.test.c index 61c4bb764..dd644cd22 100644 --- a/src/volcano.test.c +++ b/src/volcano.test.c @@ -29,18 +29,23 @@ static void test_volcano_update(CuTest *tc) { } static void test_volcano_outbreak(CuTest *tc) { - region *r; + region *r, *rn; const struct terrain_type *t_volcano, *t_active; test_cleanup(); t_volcano = test_create_terrain("volcano", LAND_REGION); t_active = test_create_terrain("activevolcano", LAND_REGION); r = test_create_region(0, 0, t_active); + rn = test_create_region(1, 0, t_volcano); - volcano_outbreak(r); - CuAssertPtrEquals(tc, (void *)t_volcano, (void *)r->terrain); - CuAssertPtrNotNull(tc, test_find_messagetype(r->msgs, "volcanooutbreak")); + volcano_outbreak(r, rn); +// CuAssertPtrEquals(tc, (void *)t_volcano, (void *)r->terrain); + CuAssertIntEquals(tc, 0, rtrees(r, 0)); + CuAssertIntEquals(tc, 0, rtrees(r, 1)); + CuAssertIntEquals(tc, 0, rtrees(r, 2)); + CuAssertPtrNotNull(tc, test_find_messagetype(rn->msgs, "volcanooutbreak")); CuAssertPtrNotNull(tc, a_find(r->attribs, &at_reduceproduction)); + CuAssertPtrNotNull(tc, a_find(rn->attribs, &at_reduceproduction)); test_cleanup(); } From b56c48d95c05bf3bc088a49ebca6873273c45fd8 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 27 Aug 2016 08:29:01 +0100 Subject: [PATCH 08/58] verify arguments for volcanooutbreak message. --- src/volcano.c | 1 - src/volcano.test.c | 9 +++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/volcano.c b/src/volcano.c index 9fb19dffd..910bd8775 100644 --- a/src/volcano.c +++ b/src/volcano.c @@ -270,7 +270,6 @@ void volcano_update(void) r->terrain = t_volcano; } else { - // TODO: is this code path inactive? are we only keeping it for old data? fix data instead. if (rng_int() % 100 < 12) { ADDMSG(&r->msgs, msg_message("volcanostopsmoke", "region", r)); r->terrain = t_volcano; diff --git a/src/volcano.test.c b/src/volcano.test.c index dd644cd22..091628cb7 100644 --- a/src/volcano.test.c +++ b/src/volcano.test.c @@ -4,6 +4,7 @@ #include #include +#include #include @@ -30,20 +31,24 @@ static void test_volcano_update(CuTest *tc) { static void test_volcano_outbreak(CuTest *tc) { region *r, *rn; + message *m; const struct terrain_type *t_volcano, *t_active; test_cleanup(); + mt_register(mt_new_va("volcanooutbreak", "regionv:region", "regionn:region", 0)); t_volcano = test_create_terrain("volcano", LAND_REGION); t_active = test_create_terrain("activevolcano", LAND_REGION); r = test_create_region(0, 0, t_active); rn = test_create_region(1, 0, t_volcano); volcano_outbreak(r, rn); -// CuAssertPtrEquals(tc, (void *)t_volcano, (void *)r->terrain); + CuAssertPtrEquals(tc, (void *)t_active, (void *)r->terrain); CuAssertIntEquals(tc, 0, rtrees(r, 0)); CuAssertIntEquals(tc, 0, rtrees(r, 1)); CuAssertIntEquals(tc, 0, rtrees(r, 2)); - CuAssertPtrNotNull(tc, test_find_messagetype(rn->msgs, "volcanooutbreak")); + CuAssertPtrNotNull(tc, m = test_find_messagetype(rn->msgs, "volcanooutbreak")); + CuAssertPtrEquals(tc, r, m->parameters[0].v); + CuAssertPtrEquals(tc, rn, m->parameters[1].v); CuAssertPtrNotNull(tc, a_find(r->attribs, &at_reduceproduction)); CuAssertPtrNotNull(tc, a_find(rn->attribs, &at_reduceproduction)); From 9400a05a87b741261afd8489dc29341b923449e1 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 28 Aug 2016 10:05:34 +0100 Subject: [PATCH 09/58] test that two different volcano_dead messages are sent for units in different regions. new test_find_messagetype_ex helper. --- src/tests.c | 17 +++++++++++++++-- src/tests.h | 1 + src/volcano.test.c | 18 +++++++++++++++--- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/tests.c b/src/tests.c index 120d62e12..be62fdde8 100644 --- a/src/tests.c +++ b/src/tests.c @@ -377,17 +377,30 @@ const char * test_get_messagetype(const message *msg) { return name; } -struct message * test_find_messagetype(struct message_list *msgs, const char *name) { +struct message * test_find_messagetype_ex(struct message_list *msgs, const char *name, struct message *prev) +{ struct mlist *ml; if (!msgs) return 0; for (ml = msgs->begin; ml; ml = ml->next) { if (strcmp(name, test_get_messagetype(ml->msg)) == 0) { - return ml->msg; + if (prev) { + if (ml->msg == prev) { + prev = NULL; + } + } + else { + return ml->msg; + } } } return 0; } +struct message * test_find_messagetype(struct message_list *msgs, const char *name) +{ + return test_find_messagetype_ex(msgs, name, NULL); +} + void test_clear_messages(faction *f) { if (f->msgs) { free_messagelist(f->msgs->begin); diff --git a/src/tests.h b/src/tests.h index d18ff6456..e31578beb 100644 --- a/src/tests.h +++ b/src/tests.h @@ -51,6 +51,7 @@ extern "C" { int RunAllTests(void); void test_translate_param(const struct locale *lang, param_t param, const char *text); const char * test_get_messagetype(const struct message *msg); + struct message * test_find_messagetype_ex(struct message_list *msgs, const char *name, struct message *prev); struct message * test_find_messagetype(struct message_list *msgs, const char *name); struct message * test_get_last_message(struct message_list *mlist); void test_clear_messages(struct faction *f); diff --git a/src/volcano.test.c b/src/volcano.test.c index 091628cb7..a79d08829 100644 --- a/src/volcano.test.c +++ b/src/volcano.test.c @@ -2,8 +2,10 @@ #include #include "volcano.h" +#include #include #include +#include #include #include @@ -31,6 +33,8 @@ static void test_volcano_update(CuTest *tc) { static void test_volcano_outbreak(CuTest *tc) { region *r, *rn; + unit *u1, *u2; + faction *f; message *m; const struct terrain_type *t_volcano, *t_active; @@ -40,18 +44,26 @@ static void test_volcano_outbreak(CuTest *tc) { t_active = test_create_terrain("activevolcano", LAND_REGION); r = test_create_region(0, 0, t_active); rn = test_create_region(1, 0, t_volcano); + f = test_create_faction(0); + u1 = test_create_unit(f, r); + u1->hp = u1->number; + u2 = test_create_unit(f, rn); + u2->hp = u2->number; volcano_outbreak(r, rn); CuAssertPtrEquals(tc, (void *)t_active, (void *)r->terrain); CuAssertIntEquals(tc, 0, rtrees(r, 0)); CuAssertIntEquals(tc, 0, rtrees(r, 1)); CuAssertIntEquals(tc, 0, rtrees(r, 2)); - CuAssertPtrNotNull(tc, m = test_find_messagetype(rn->msgs, "volcanooutbreak")); - CuAssertPtrEquals(tc, r, m->parameters[0].v); - CuAssertPtrEquals(tc, rn, m->parameters[1].v); CuAssertPtrNotNull(tc, a_find(r->attribs, &at_reduceproduction)); CuAssertPtrNotNull(tc, a_find(rn->attribs, &at_reduceproduction)); + CuAssertPtrNotNull(tc, m = test_find_messagetype(rn->msgs, "volcanooutbreak")); + CuAssertPtrEquals(tc, r, m->parameters[0].v); + CuAssertPtrEquals(tc, rn, m->parameters[1].v); + + CuAssertPtrNotNull(tc, m = test_find_messagetype_ex(f->msgs, "volcano_dead", NULL)); + CuAssertPtrNotNull(tc, m = test_find_messagetype_ex(f->msgs, "volcano_dead", m)); test_cleanup(); } From 3bc2221bfe10910dfb5645ab0e54e7c9540f69f0 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 28 Aug 2016 10:08:41 +0100 Subject: [PATCH 10/58] finish testing the (current) volcano_dead message. --- src/volcano.test.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/volcano.test.c b/src/volcano.test.c index a79d08829..25fded763 100644 --- a/src/volcano.test.c +++ b/src/volcano.test.c @@ -40,6 +40,7 @@ static void test_volcano_outbreak(CuTest *tc) { test_cleanup(); mt_register(mt_new_va("volcanooutbreak", "regionv:region", "regionn:region", 0)); + mt_register(mt_new_va("volcano_dead", "unit:unit", "region:region", "dead:int", 0)); t_volcano = test_create_terrain("volcano", LAND_REGION); t_active = test_create_terrain("activevolcano", LAND_REGION); r = test_create_region(0, 0, t_active); @@ -63,7 +64,13 @@ static void test_volcano_outbreak(CuTest *tc) { CuAssertPtrEquals(tc, rn, m->parameters[1].v); CuAssertPtrNotNull(tc, m = test_find_messagetype_ex(f->msgs, "volcano_dead", NULL)); + CuAssertPtrEquals(tc, u1, m->parameters[0].v); + CuAssertPtrEquals(tc, r, m->parameters[1].v); + CuAssertIntEquals(tc, 1, m->parameters[2].i); CuAssertPtrNotNull(tc, m = test_find_messagetype_ex(f->msgs, "volcano_dead", m)); + CuAssertPtrEquals(tc, u2, m->parameters[0].v); + CuAssertPtrEquals(tc, r, m->parameters[1].v); + CuAssertIntEquals(tc, 1, m->parameters[2].i); test_cleanup(); } From cf96013e0b642ebc7b6177f91c9675d0fbfd328d Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 28 Aug 2016 14:06:57 +0100 Subject: [PATCH 11/58] better volcano message testing. --- src/volcano.test.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/volcano.test.c b/src/volcano.test.c index 25fded763..091615fed 100644 --- a/src/volcano.test.c +++ b/src/volcano.test.c @@ -16,16 +16,19 @@ static void test_volcano_update(CuTest *tc) { region *r; + message *m; const struct terrain_type *t_volcano, *t_active; test_cleanup(); + mt_register(mt_new_va("volcanostopsmoke", "region:region", 0)); t_volcano = test_create_terrain("volcano", LAND_REGION); t_active = test_create_terrain("activevolcano", LAND_REGION); r = test_create_region(0, 0, t_active); a_add(&r->attribs, make_reduceproduction(25, 10)); volcano_update(); - CuAssertPtrNotNull(tc, test_find_messagetype(r->msgs, "volcanostopsmoke")); + CuAssertPtrNotNull(tc, m = test_find_messagetype(r->msgs, "volcanostopsmoke")); + CuAssertPtrEquals(tc, r, m->parameters[0].v); CuAssertPtrEquals(tc, (void *)t_volcano, (void *)r->terrain); test_cleanup(); From 1e04e20671596941e10821572e892f7d2a770882 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 28 Aug 2016 14:31:25 +0100 Subject: [PATCH 12/58] testing destroy_road by way of destroy_cmd. two simple cases only. --- src/kernel/build.c | 2 +- src/kernel/build.test.c | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/kernel/build.c b/src/kernel/build.c index f9e10b09e..ff3993d79 100644 --- a/src/kernel/build.c +++ b/src/kernel/build.c @@ -130,7 +130,7 @@ static void destroy_road(unit * u, int nmax, struct order *ord) if (willdo == 0) { /* TODO: error message */ } - if (willdo > SHRT_MAX) + else if (willdo > SHRT_MAX) road = 0; else road = (short)(road - willdo); diff --git a/src/kernel/build.test.c b/src/kernel/build.test.c index 41dcdb1a5..c6b087304 100644 --- a/src/kernel/build.test.c +++ b/src/kernel/build.test.c @@ -265,6 +265,30 @@ static void test_build_building_success(CuTest *tc) { teardown_build(&bf); } +static void test_build_destroy_road(CuTest *tc) +{ + region *r; + faction *f; + unit *u; + order *ord; + + test_cleanup(); + test_create_region(1, 0, 0); + r = test_create_region(0, 0, 0); + rsetroad(r, D_EAST, 100); + u = test_create_unit(f = test_create_faction(0), r); + ord = create_order(K_DESTROY, f->locale, "%s %s", LOC(f->locale, parameters[P_ROAD]), LOC(f->locale, directions[D_EAST])); + + CuAssertIntEquals(tc, 0, destroy_cmd(u, ord)); + CuAssertIntEquals(tc, 100, rroad(r, D_EAST)); + + set_level(u, SK_ROAD_BUILDING, 1); + CuAssertIntEquals(tc, 0, destroy_cmd(u, ord)); + CuAssertIntEquals(tc, 99, rroad(r, D_EAST)); + + test_cleanup(); +} + CuSuite *get_build_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -279,6 +303,7 @@ CuSuite *get_build_suite(void) SUITE_ADD_TEST(suite, test_build_building_success); 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_road); return suite; } From 1cdeab5e066a5734da330350515483f3d59561f8 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 28 Aug 2016 16:13:26 +0100 Subject: [PATCH 13/58] test destroy_road skill scaling and person scaling. --- src/kernel/build.test.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/kernel/build.test.c b/src/kernel/build.test.c index c6b087304..5ae8e299e 100644 --- a/src/kernel/build.test.c +++ b/src/kernel/build.test.c @@ -286,6 +286,14 @@ static void test_build_destroy_road(CuTest *tc) CuAssertIntEquals(tc, 0, destroy_cmd(u, ord)); CuAssertIntEquals(tc, 99, rroad(r, D_EAST)); + set_level(u, SK_ROAD_BUILDING, 4); + CuAssertIntEquals(tc, 0, destroy_cmd(u, ord)); + CuAssertIntEquals(tc, 95, rroad(r, D_EAST)); + + scale_number(u, 4); + set_level(u, SK_ROAD_BUILDING, 2); + CuAssertIntEquals(tc, 0, destroy_cmd(u, ord)); + CuAssertIntEquals(tc, 87, rroad(r, D_EAST)); test_cleanup(); } From b0400a797d34f1b52d83b12fda98c80a5531b00f Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 28 Aug 2016 16:31:29 +0100 Subject: [PATCH 14/58] when not skilled enough to destroy a road, don't get a destroy_road message. test destroy_road message. --- src/kernel/build.c | 6 +++-- src/kernel/build.test.c | 52 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/src/kernel/build.c b/src/kernel/build.c index ff3993d79..871ccfc89 100644 --- a/src/kernel/build.c +++ b/src/kernel/build.c @@ -135,8 +135,10 @@ static void destroy_road(unit * u, int nmax, struct order *ord) else road = (short)(road - willdo); rsetroad(r, d, road); - ADDMSG(&u->faction->msgs, msg_message("destroy_road", - "unit from to", u, r, r2)); + if (willdo > 0) { + ADDMSG(&u->faction->msgs, msg_message("destroy_road", + "unit from to", u, r, r2)); + } } } } diff --git a/src/kernel/build.test.c b/src/kernel/build.test.c index 5ae8e299e..87cd359e0 100644 --- a/src/kernel/build.test.c +++ b/src/kernel/build.test.c @@ -3,6 +3,7 @@ #include "alchemy.h" #include "types.h" #include "build.h" +#include "guard.h" #include "order.h" #include "unit.h" #include "building.h" @@ -281,10 +282,12 @@ static void test_build_destroy_road(CuTest *tc) CuAssertIntEquals(tc, 0, destroy_cmd(u, ord)); CuAssertIntEquals(tc, 100, rroad(r, D_EAST)); + CuAssertPtrEquals(tc, 0, test_find_messagetype(f->msgs, "destroy_road")); set_level(u, SK_ROAD_BUILDING, 1); CuAssertIntEquals(tc, 0, destroy_cmd(u, ord)); CuAssertIntEquals(tc, 99, rroad(r, D_EAST)); + CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "destroy_road")); set_level(u, SK_ROAD_BUILDING, 4); CuAssertIntEquals(tc, 0, destroy_cmd(u, ord)); @@ -297,6 +300,54 @@ static void test_build_destroy_road(CuTest *tc) test_cleanup(); } +unit *test_create_guard(region *r, faction *f, race *rc) { + unit *ug; + + if (!rc) { + rc = test_create_race("guardian"); + rc->flags |= RCF_UNARMEDGUARD; + } + if (!f) { + f = test_create_faction(rc); + } + ug = test_create_unit(f, r); + guard(ug, GUARD_TAX); + + return ug; +} + +static void test_build_destroy_road_guard(CuTest *tc) +{ + region *r; + faction *f; + unit *u, *ug; + order *ord; + + test_cleanup(); + test_create_region(1, 0, 0); + r = test_create_region(0, 0, 0); + rsetroad(r, D_EAST, 100); + ug = test_create_guard(r, 0, 0); + u = test_create_unit(f = test_create_faction(0), r); + ord = create_order(K_DESTROY, f->locale, "%s %s", LOC(f->locale, parameters[P_ROAD]), LOC(f->locale, directions[D_EAST])); + + set_level(u, SK_ROAD_BUILDING, 1); + CuAssertIntEquals(tc, 0, destroy_cmd(u, ord)); + CuAssertIntEquals(tc, 100, rroad(r, D_EAST)); + CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "error70")); + CuAssertPtrEquals(tc, 0, test_find_messagetype(f->msgs, "destroy_road")); + + test_clear_messages(f); + guard(ug, GUARD_NONE); + + CuAssertIntEquals(tc, 0, destroy_cmd(u, ord)); + CuAssertIntEquals(tc, 99, rroad(r, D_EAST)); + CuAssertPtrEquals(tc, NULL, test_find_messagetype(f->msgs, "error70")); + CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "destroy_road")); + + test_cleanup(); +} + CuSuite *get_build_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -312,6 +363,7 @@ CuSuite *get_build_suite(void) 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_road); + SUITE_ADD_TEST(suite, test_build_destroy_road_guard); return suite; } From 808d51429e16a3148dbd00ba5eba8148ffc4a006 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 28 Aug 2016 16:44:14 +0100 Subject: [PATCH 15/58] test destroy_road message arguments. --- src/kernel/build.test.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/kernel/build.test.c b/src/kernel/build.test.c index 87cd359e0..f7da1edb3 100644 --- a/src/kernel/build.test.c +++ b/src/kernel/build.test.c @@ -1,5 +1,7 @@ #include #include + +#include #include "alchemy.h" #include "types.h" #include "build.h" @@ -268,13 +270,15 @@ static void test_build_building_success(CuTest *tc) { static void test_build_destroy_road(CuTest *tc) { - region *r; + region *r, *r2; faction *f; unit *u; order *ord; + message *m; test_cleanup(); - test_create_region(1, 0, 0); + mt_register(mt_new_va("destroy_road", "unit:unit", "from:region", "to:region", 0)); + r2 = test_create_region(1, 0, 0); r = test_create_region(0, 0, 0); rsetroad(r, D_EAST, 100); u = test_create_unit(f = test_create_faction(0), r); @@ -287,7 +291,10 @@ static void test_build_destroy_road(CuTest *tc) set_level(u, SK_ROAD_BUILDING, 1); CuAssertIntEquals(tc, 0, destroy_cmd(u, ord)); CuAssertIntEquals(tc, 99, rroad(r, D_EAST)); - CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "destroy_road")); + CuAssertPtrNotNull(tc, m = test_find_messagetype(f->msgs, "destroy_road")); + CuAssertPtrEquals(tc, u, m->parameters[0].v); + CuAssertPtrEquals(tc, r, m->parameters[1].v); + CuAssertPtrEquals(tc, r2, m->parameters[2].v); set_level(u, SK_ROAD_BUILDING, 4); CuAssertIntEquals(tc, 0, destroy_cmd(u, ord)); From a451d61f2309b1acbf1823484e80515665a0c5e2 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 28 Aug 2016 16:48:06 +0100 Subject: [PATCH 16/58] simplify destroy_cmd parsing. --- src/kernel/build.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/kernel/build.c b/src/kernel/build.c index 871ccfc89..5d8f955c5 100644 --- a/src/kernel/build.c +++ b/src/kernel/build.c @@ -165,19 +165,17 @@ int destroy_cmd(unit * u, struct order *ord) init_order(ord); s = gettoken(token, sizeof(token)); - if (findparam(s, u->faction->locale) == P_ROAD) { - destroy_road(u, INT_MAX, ord); - return 0; - } - if (s && *s) { n = atoi((const char *)s); if (n <= 0) { n = INT_MAX; } + else { + s = gettoken(token, sizeof(token)); + } } - if (getparam(u->faction->locale) == P_ROAD) { + if (isparam(s, u->faction->locale, P_ROAD)) { destroy_road(u, n, ord); return 0; } From 534708d83e50026695d7080871a7b03960fe317c Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 28 Aug 2016 16:51:16 +0100 Subject: [PATCH 17/58] add a test for DESTROY ROAD --- src/kernel/build.test.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/kernel/build.test.c b/src/kernel/build.test.c index f7da1edb3..b59a09d73 100644 --- a/src/kernel/build.test.c +++ b/src/kernel/build.test.c @@ -355,6 +355,33 @@ static void test_build_destroy_road_guard(CuTest *tc) test_cleanup(); } +static void test_build_destroy_road_limit(CuTest *tc) +{ + region *r; + faction *f; + unit *u; + order *ord; + + test_cleanup(); + test_create_region(1, 0, 0); + r = test_create_region(0, 0, 0); + rsetroad(r, D_EAST, 100); + u = test_create_unit(f = test_create_faction(0), r); + ord = create_order(K_DESTROY, f->locale, "1 %s %s", LOC(f->locale, parameters[P_ROAD]), LOC(f->locale, directions[D_EAST])); + + set_level(u, SK_ROAD_BUILDING, 1); + CuAssertIntEquals(tc, 0, destroy_cmd(u, ord)); + CuAssertIntEquals(tc, 99, rroad(r, D_EAST)); + CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "destroy_road")); + + set_level(u, SK_ROAD_BUILDING, 4); + CuAssertIntEquals(tc, 0, destroy_cmd(u, ord)); + CuAssertIntEquals(tc, 98, rroad(r, D_EAST)); + CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "destroy_road")); + + test_cleanup(); +} + CuSuite *get_build_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -370,6 +397,7 @@ CuSuite *get_build_suite(void) 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_road); + SUITE_ADD_TEST(suite, test_build_destroy_road_limit); SUITE_ADD_TEST(suite, test_build_destroy_road_guard); return suite; } From 020ab942ec56a58b286cd9452af661f81c1edc9c Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 28 Aug 2016 17:37:08 +0100 Subject: [PATCH 18/58] add tests for monster naming functions (existence only). --- src/CMakeLists.txt | 1 + src/names.test.c | 30 ++++++++++++++++++++++++++++++ src/test_eressea.c | 1 + 3 files changed, 32 insertions(+) create mode 100644 src/names.test.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d704fd060..8776c1e5d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -184,6 +184,7 @@ target_link_libraries(eressea set(TESTS_SRC monsters.test.c + names.test.c donations.test.c wormhole.test.c alchemy.test.c diff --git a/src/names.test.c b/src/names.test.c new file mode 100644 index 000000000..234346172 --- /dev/null +++ b/src/names.test.c @@ -0,0 +1,30 @@ +#include + +#include "names.h" + +#include + +#include +#include "tests.h" + +static void test_names(CuTest * tc) +{ + test_cleanup(); + register_names(); + CuAssertPtrNotNull(tc, get_function("nameundead")); + CuAssertPtrNotNull(tc, get_function("nameskeleton")); + CuAssertPtrNotNull(tc, get_function("namezombie")); + CuAssertPtrNotNull(tc, get_function("nameghoul")); + CuAssertPtrNotNull(tc, get_function("namedragon")); + CuAssertPtrNotNull(tc, get_function("namedracoid")); + CuAssertPtrNotNull(tc, get_function("namegeneric")); + CuAssertPtrNotNull(tc, get_function("describe_braineater")); + test_cleanup(); +} + +CuSuite *get_names_suite(void) +{ + CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_names); + return suite; +} diff --git a/src/test_eressea.c b/src/test_eressea.c index a28ef9443..8236465cf 100644 --- a/src/test_eressea.c +++ b/src/test_eressea.c @@ -111,6 +111,7 @@ int RunAllTests(int argc, char *argv[]) ADD_SUITE(messages); /* gamecode */ ADD_SUITE(prefix); + ADD_SUITE(names); ADD_SUITE(battle); ADD_SUITE(volcano); ADD_SUITE(donations); From eb8db3bfb94fa4ce7bd060c4a4211636134d1653 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 28 Aug 2016 18:08:52 +0100 Subject: [PATCH 19/58] test undead name generation. --- src/names.h | 5 ++++- src/names.test.c | 9 ++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/names.h b/src/names.h index 17bb9a0e9..76e7c9497 100644 --- a/src/names.h +++ b/src/names.h @@ -21,7 +21,10 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #ifdef __cplusplus extern "C" { #endif - extern void register_names(void); + + struct unit; + typedef const char *(*name_func)(const struct unit *); + void register_names(void); const char *abkz(const char *s, char *buf, size_t size, size_t maxchars); #ifdef __cplusplus diff --git a/src/names.test.c b/src/names.test.c index 234346172..99c1663ed 100644 --- a/src/names.test.c +++ b/src/names.test.c @@ -2,6 +2,7 @@ #include "names.h" +#include #include #include @@ -9,9 +10,15 @@ static void test_names(CuTest * tc) { + name_func foo; test_cleanup(); register_names(); - CuAssertPtrNotNull(tc, get_function("nameundead")); + default_locale = test_create_locale(); + locale_setstring(default_locale, "undead_prefix_0", "Kleine"); + locale_setstring(default_locale, "undead_name_0", "Graue"); + locale_setstring(default_locale, "undead_postfix_0", "Kobolde"); + CuAssertPtrNotNull(tc, foo = (name_func)get_function("nameundead")); + CuAssertStrEquals(tc, "Kleine Graue Kobolde", foo(NULL)); CuAssertPtrNotNull(tc, get_function("nameskeleton")); CuAssertPtrNotNull(tc, get_function("namezombie")); CuAssertPtrNotNull(tc, get_function("nameghoul")); From 0ac30c65a1b7830f3ba553ef89d82ee9bbfaa67a Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 28 Aug 2016 18:15:00 +0100 Subject: [PATCH 20/58] refactoring prior to removing static variable --- src/kernel/race.h | 2 ++ src/kernel/unit.c | 3 ++- src/kernel/xmlreader.c | 2 +- src/names.h | 1 - src/names.test.c | 5 +++-- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/kernel/race.h b/src/kernel/race.h index a106249f8..775ac55a5 100644 --- a/src/kernel/race.h +++ b/src/kernel/race.h @@ -119,6 +119,8 @@ extern "C" { extern int num_races; + typedef const char *(*race_name_func)(const struct unit *); + typedef struct race { char *_name; float magres; diff --git a/src/kernel/unit.c b/src/kernel/unit.c index 47e4a63b4..98d635d87 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -1416,7 +1416,8 @@ void name_unit(unit * u) if (u_race(u)->generate_name) { const char *gen_name = u_race(u)->generate_name(u); if (gen_name) { - unit_setname(u, gen_name); + free(u->_name); + u->_name = _strdup(gen_name); } else { unit_setname(u, racename(u->faction->locale, u, u_race(u))); diff --git a/src/kernel/xmlreader.c b/src/kernel/xmlreader.c index da8014d67..e944471f8 100644 --- a/src/kernel/xmlreader.c +++ b/src/kernel/xmlreader.c @@ -1797,7 +1797,7 @@ static int parse_races(xmlDocPtr doc) } assert(propValue != NULL); if (strcmp((const char *)propValue, "name") == 0) { - rc->generate_name = (const char *(*)(const struct unit *))fun; + rc->generate_name = (race_name_func)fun; } else if (strcmp((const char *)propValue, "describe") == 0) { rc->describe = diff --git a/src/names.h b/src/names.h index 76e7c9497..63e9c8628 100644 --- a/src/names.h +++ b/src/names.h @@ -23,7 +23,6 @@ extern "C" { #endif struct unit; - typedef const char *(*name_func)(const struct unit *); void register_names(void); const char *abkz(const char *s, char *buf, size_t size, size_t maxchars); diff --git a/src/names.test.c b/src/names.test.c index 99c1663ed..7c3c24506 100644 --- a/src/names.test.c +++ b/src/names.test.c @@ -2,6 +2,7 @@ #include "names.h" +#include #include #include @@ -10,14 +11,14 @@ static void test_names(CuTest * tc) { - name_func foo; + race_name_func foo; test_cleanup(); register_names(); default_locale = test_create_locale(); locale_setstring(default_locale, "undead_prefix_0", "Kleine"); locale_setstring(default_locale, "undead_name_0", "Graue"); locale_setstring(default_locale, "undead_postfix_0", "Kobolde"); - CuAssertPtrNotNull(tc, foo = (name_func)get_function("nameundead")); + CuAssertPtrNotNull(tc, foo = (race_name_func)get_function("nameundead")); CuAssertStrEquals(tc, "Kleine Graue Kobolde", foo(NULL)); CuAssertPtrNotNull(tc, get_function("nameskeleton")); CuAssertPtrNotNull(tc, get_function("namezombie")); From d1b6629281a3f0079a6a140f5c09847890f0cae9 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 28 Aug 2016 19:00:04 +0100 Subject: [PATCH 21/58] extract counting name particles. --- src/names.c | 77 +++++++++++++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 35 deletions(-) diff --git a/src/names.c b/src/names.c index f608764d8..20eaf99ad 100644 --- a/src/names.c +++ b/src/names.c @@ -49,14 +49,10 @@ static const char *describe_braineater(unit * u, const struct locale *lang) return LOC(lang, "describe_braineater"); } -static const char *make_names(const char *monster, int *num_postfix, - int pprefix, int *num_name, int *num_prefix, int ppostfix) +static void count_particles(const char *monster, int *num_prefix, int *num_name, int *num_postfix) { - int uv, uu, un; - static char name[NAMESIZE + 1]; // FIXME: static return value - char zText[32]; const char *str; - + char zText[32]; if (*num_prefix == 0) { for (*num_prefix = 0;; ++*num_prefix) { @@ -80,48 +76,59 @@ static const char *make_names(const char *monster, int *num_postfix, break; } } +} +static const char *make_names(const char *monster, int *num_postfix, + int pprefix, int *num_name, int *num_prefix, int ppostfix) +{ if (*num_name == 0) { - return NULL; + count_particles(monster, num_prefix, num_name, num_postfix); } + if (*num_name > 0) { + static char name[NAMESIZE + 1]; // FIXME: static return value + char zText[32]; + int uv, uu, un; + const char *str; - /* nur 50% aller Namen haben "Vor-Teil" */ - uv = rng_int() % (*num_prefix * pprefix); + /* nur 50% aller Namen haben "Vor-Teil" */ + uv = rng_int() % (*num_prefix * pprefix); - uu = rng_int() % *num_name; + uu = rng_int() % *num_name; - /* nur 50% aller Namen haben "Nach-Teil", wenn kein Vor-Teil */ - if (*num_postfix > 0 && uv >= *num_prefix) { - un = rng_int() % *num_postfix; - } - else { - un = rng_int() % (*num_postfix * ppostfix); - } - - name[0] = 0; - if (uv < *num_prefix) { - sprintf(zText, "%s_prefix_%d", monster, uv); - str = locale_getstring(default_locale, zText); - if (str) { - size_t sz = strlcpy(name, (const char *)str, sizeof(name)); - strlcpy(name + sz, " ", sizeof(name) - sz); + /* nur 50% aller Namen haben "Nach-Teil", wenn kein Vor-Teil */ + if (*num_postfix > 0 && uv >= *num_prefix) { + un = rng_int() % *num_postfix; + } + else { + un = rng_int() % (*num_postfix * ppostfix); } - } - sprintf(zText, "%s_name_%d", monster, uu); - str = locale_getstring(default_locale, zText); - if (str) - strlcat(name, (const char *)str, sizeof(name)); + name[0] = 0; + if (uv < *num_prefix) { + sprintf(zText, "%s_prefix_%d", monster, uv); + str = locale_getstring(default_locale, zText); + if (str) { + size_t sz = strlcpy(name, (const char *)str, sizeof(name)); + strlcpy(name + sz, " ", sizeof(name) - sz); + } + } - if (un < *num_postfix) { - sprintf(zText, "%s_postfix_%d", monster, un); + sprintf(zText, "%s_name_%d", monster, uu); str = locale_getstring(default_locale, zText); - if (str) { - strlcat(name, " ", sizeof(name)); + if (str) strlcat(name, (const char *)str, sizeof(name)); + + if (un < *num_postfix) { + sprintf(zText, "%s_postfix_%d", monster, un); + str = locale_getstring(default_locale, zText); + if (str) { + strlcat(name, " ", sizeof(name)); + strlcat(name, (const char *)str, sizeof(name)); + } } + return name; } - return name; + return NULL; } static const char *undead_name(const unit * u) From 0f3de70ced1afd9c66b6df4a92045de142dd74a1 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 28 Aug 2016 19:06:14 +0100 Subject: [PATCH 22/58] refactor to push back the const-ness of generated names. --- src/kernel/race.c | 9 +++++++++ src/kernel/race.h | 1 + src/kernel/unit.c | 4 ++-- src/names.c | 38 ++++++++++++++++++-------------------- 4 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/kernel/race.c b/src/kernel/race.c index be9f2ab68..905464baa 100644 --- a/src/kernel/race.c +++ b/src/kernel/race.c @@ -319,3 +319,12 @@ const char *dbrace(const struct race *rc) return zText; } +char * race_namegen(const struct race *rc, const struct unit *u) { + if (rc->generate_name) { + const char * str = rc->generate_name(u); + if (str) { + return _strdup(str); + } + } + return NULL; +} diff --git a/src/kernel/race.h b/src/kernel/race.h index 775ac55a5..bd7607d31 100644 --- a/src/kernel/race.h +++ b/src/kernel/race.h @@ -261,6 +261,7 @@ extern "C" { void give_starting_equipment(const struct equipment *eq, struct unit *u); const char *dbrace(const struct race *rc); + char * race_namegen(const struct race *rc, const struct unit *u); #ifdef __cplusplus } diff --git a/src/kernel/unit.c b/src/kernel/unit.c index 98d635d87..1db0d7761 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -1414,10 +1414,10 @@ void default_name(const unit *u, char name[], int len) { void name_unit(unit * u) { if (u_race(u)->generate_name) { - const char *gen_name = u_race(u)->generate_name(u); + char *gen_name = race_namegen(u_race(u), u); if (gen_name) { free(u->_name); - u->_name = _strdup(gen_name); + u->_name = gen_name; } else { unit_setname(u, racename(u->faction->locale, u, u_race(u))); diff --git a/src/names.c b/src/names.c index 20eaf99ad..18fad3d34 100644 --- a/src/names.c +++ b/src/names.c @@ -51,30 +51,28 @@ static const char *describe_braineater(unit * u, const struct locale *lang) static void count_particles(const char *monster, int *num_prefix, int *num_name, int *num_postfix) { - const char *str; char zText[32]; - if (*num_prefix == 0) { + const char *str; - for (*num_prefix = 0;; ++*num_prefix) { - sprintf(zText, "%s_prefix_%d", monster, *num_prefix); - str = locale_getstring(default_locale, zText); - if (str == NULL) - break; - } + for (*num_prefix = 0;; ++*num_prefix) { + sprintf(zText, "%s_prefix_%d", monster, *num_prefix); + str = locale_getstring(default_locale, zText); + if (str == NULL) + break; + } - for (*num_name = 0;; ++*num_name) { - sprintf(zText, "%s_name_%d", monster, *num_name); - str = locale_getstring(default_locale, zText); - if (str == NULL) - break; - } + for (*num_name = 0;; ++*num_name) { + sprintf(zText, "%s_name_%d", monster, *num_name); + str = locale_getstring(default_locale, zText); + if (str == NULL) + break; + } - for (*num_postfix = 0;; ++*num_postfix) { - sprintf(zText, "%s_postfix_%d", monster, *num_postfix); - str = locale_getstring(default_locale, zText); - if (str == NULL) - break; - } + for (*num_postfix = 0;; ++*num_postfix) { + sprintf(zText, "%s_postfix_%d", monster, *num_postfix); + str = locale_getstring(default_locale, zText); + if (str == NULL) + break; } } From 514565d66bba0ec0a7dc0fb5f9b55bda5ecbcd95 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 28 Aug 2016 20:02:45 +0100 Subject: [PATCH 23/58] move race_name_func registrations into race.c --- src/kernel/race.c | 4 ++++ src/kernel/race.h | 3 ++- src/names.c | 17 +++++++++-------- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/kernel/race.c b/src/kernel/race.c index 905464baa..8b842eecd 100644 --- a/src/kernel/race.c +++ b/src/kernel/race.c @@ -319,6 +319,10 @@ const char *dbrace(const struct race *rc) return zText; } +void register_race_name_function(race_name_func func, const char *name) { + register_function((pf_generic)func, name); +} + char * race_namegen(const struct race *rc, const struct unit *u) { if (rc->generate_name) { const char * str = rc->generate_name(u); diff --git a/src/kernel/race.h b/src/kernel/race.h index bd7607d31..b25b4764e 100644 --- a/src/kernel/race.h +++ b/src/kernel/race.h @@ -151,7 +151,7 @@ extern "C" { struct att attack[RACE_ATTACKS]; signed char bonus[MAXSKILLS]; - const char *(*generate_name) (const struct unit *); + race_name_func generate_name; const char *(*describe) (const struct unit *, const struct locale *); void(*age) (struct unit * u); bool(*move_allowed) (const struct region *, const struct region *); @@ -261,6 +261,7 @@ extern "C" { void give_starting_equipment(const struct equipment *eq, struct unit *u); const char *dbrace(const struct race *rc); + void register_race_name_function(race_name_func, const char *); char * race_namegen(const struct race *rc, const struct unit *u); #ifdef __cplusplus diff --git a/src/names.c b/src/names.c index 18fad3d34..faf7d72fd 100644 --- a/src/names.c +++ b/src/names.c @@ -22,6 +22,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. /* kernel includes */ #include +#include #include #include #include @@ -31,8 +32,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. /* util includes */ #include #include -#include #include +#include #include #include @@ -482,11 +483,11 @@ void register_names(void) /* function name * generate a name for a nonplayerunit * race->generate_name() */ - register_function((pf_generic)undead_name, "nameundead"); - register_function((pf_generic)skeleton_name, "nameskeleton"); - register_function((pf_generic)zombie_name, "namezombie"); - register_function((pf_generic)ghoul_name, "nameghoul"); - register_function((pf_generic)dragon_name, "namedragon"); - register_function((pf_generic)dracoid_name, "namedracoid"); - register_function((pf_generic)generic_name, "namegeneric"); + register_race_name_function(undead_name, "nameundead"); + register_race_name_function(skeleton_name, "nameskeleton"); + register_race_name_function(zombie_name, "namezombie"); + register_race_name_function(ghoul_name, "nameghoul"); + register_race_name_function(dragon_name, "namedragon"); + register_race_name_function(dracoid_name, "namedracoid"); + register_race_name_function(generic_name, "namegeneric"); } From e3b0dfedc90c670fe2a36ac16ee13d22c058fae6 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 28 Aug 2016 20:27:40 +0100 Subject: [PATCH 24/58] race naming functions do more work than before. --- src/kernel/race.c | 7 ++----- src/kernel/race.h | 4 ++-- src/names.c | 50 ++++++++++++++++++++++++++--------------------- src/names.test.c | 10 ++++++++-- 4 files changed, 40 insertions(+), 31 deletions(-) diff --git a/src/kernel/race.c b/src/kernel/race.c index 8b842eecd..6eea8651b 100644 --- a/src/kernel/race.c +++ b/src/kernel/race.c @@ -323,12 +323,9 @@ void register_race_name_function(race_name_func func, const char *name) { register_function((pf_generic)func, name); } -char * race_namegen(const struct race *rc, const struct unit *u) { +char * race_namegen(const struct race *rc, struct unit *u) { if (rc->generate_name) { - const char * str = rc->generate_name(u); - if (str) { - return _strdup(str); - } + rc->generate_name(u); } return NULL; } diff --git a/src/kernel/race.h b/src/kernel/race.h index b25b4764e..45e769648 100644 --- a/src/kernel/race.h +++ b/src/kernel/race.h @@ -119,7 +119,7 @@ extern "C" { extern int num_races; - typedef const char *(*race_name_func)(const struct unit *); + typedef void (*race_name_func)(struct unit *); typedef struct race { char *_name; @@ -262,7 +262,7 @@ extern "C" { struct unit *u); const char *dbrace(const struct race *rc); void register_race_name_function(race_name_func, const char *); - char * race_namegen(const struct race *rc, const struct unit *u); + char * race_namegen(const struct race *rc, struct unit *u); #ifdef __cplusplus } diff --git a/src/names.c b/src/names.c index faf7d72fd..a90a90f94 100644 --- a/src/names.c +++ b/src/names.c @@ -86,15 +86,14 @@ static const char *make_names(const char *monster, int *num_postfix, if (*num_name > 0) { static char name[NAMESIZE + 1]; // FIXME: static return value char zText[32]; - int uv, uu, un; + int uv = 0, uu = 0, un = 0; const char *str; - /* nur 50% aller Namen haben "Vor-Teil" */ - uv = rng_int() % (*num_prefix * pprefix); - + if (*num_prefix > 0) { + uv = rng_int() % (*num_prefix * pprefix); + } uu = rng_int() % *num_name; - /* nur 50% aller Namen haben "Nach-Teil", wenn kein Vor-Teil */ if (*num_postfix > 0 && uv >= *num_prefix) { un = rng_int() % *num_postfix; } @@ -130,28 +129,32 @@ static const char *make_names(const char *monster, int *num_postfix, return NULL; } -static const char *undead_name(const unit * u) +static void undead_name(unit * u) { static int num_postfix, num_name, num_prefix; - return make_names("undead", &num_postfix, 2, &num_name, &num_prefix, 2); + const char *str = make_names("undead", &num_postfix, 2, &num_name, &num_prefix, 2); + unit_setname(u, str); } -static const char *skeleton_name(const unit * u) +static void skeleton_name(unit * u) { static int num_postfix, num_name, num_prefix; - return make_names("skeleton", &num_postfix, 5, &num_name, &num_prefix, 2); + const char *str = make_names("skeleton", &num_postfix, 5, &num_name, &num_prefix, 2); + unit_setname(u, str); } -static const char *zombie_name(const unit * u) +static void zombie_name(unit * u) { static int num_postfix, num_name, num_prefix; - return make_names("zombie", &num_postfix, 5, &num_name, &num_prefix, 2); + const char *str = make_names("zombie", &num_postfix, 5, &num_name, &num_prefix, 2); + unit_setname(u, str); } -static const char *ghoul_name(const unit * u) +static void ghoul_name(unit * u) { static int num_postfix, num_name, num_prefix; - return make_names("ghoul", &num_postfix, 5, &num_name, &num_prefix, 4); + const char *str = make_names("ghoul", &num_postfix, 5, &num_name, &num_prefix, 4); + unit_setname(u, str); } /* Drachen */ @@ -219,15 +222,18 @@ const char *silbe3[SIL3] = { "bus", }; -static const char *generic_name(const unit * u) +static void generic_name(unit * u) { const char * name = rc_name_s(u_race(u), (u->number == 1) ? NAME_SINGULAR : NAME_PLURAL); - return LOC(u->faction->locale, name); + name = LOC(u->faction->locale, name); + if (name) { + unit_setname(u, name); + } } -static const char *dragon_name(const unit * u) +static void dragon_name(unit * u) { - static char name[NAMESIZE + 1]; // FIXME: static return value + char name[NAMESIZE + 1]; int rnd, ter = 0; int anzahl = 1; static int num_postfix; @@ -268,7 +274,7 @@ static const char *dragon_name(const unit * u) } if (num_postfix <=0) { - return NULL; + return; } else if (num_postfix < 6) { rnd = rng_int() % num_postfix; @@ -311,7 +317,7 @@ static const char *dragon_name(const unit * u) } } - return name; + unit_setname(u, name); } /* Dracoide */ @@ -363,7 +369,7 @@ static const char *drac_suf[DRAC_SUF] = { "k" }; -static const char *dracoid_name(const unit * u) +static void dracoid_name(unit * u) { static char name[NAMESIZE + 1]; // FIXME: static return value int mid_syllabels; @@ -383,7 +389,7 @@ static const char *dracoid_name(const unit * u) sz += strlcat(name, drac_mid[rng_int() % DRAC_MID], sizeof(name)); } sz += strlcat(name, drac_suf[rng_int() % DRAC_SUF], sizeof(name)); - return name; + unit_setname(u, name); } /** returns an abbreviation of a string. @@ -487,7 +493,7 @@ void register_names(void) register_race_name_function(skeleton_name, "nameskeleton"); register_race_name_function(zombie_name, "namezombie"); register_race_name_function(ghoul_name, "nameghoul"); - register_race_name_function(dragon_name, "namedragon"); register_race_name_function(dracoid_name, "namedracoid"); + register_race_name_function(dragon_name, "namedragon"); register_race_name_function(generic_name, "namegeneric"); } diff --git a/src/names.test.c b/src/names.test.c index 7c3c24506..a6dd6bb11 100644 --- a/src/names.test.c +++ b/src/names.test.c @@ -3,6 +3,7 @@ #include "names.h" #include +#include #include #include @@ -12,14 +13,19 @@ static void test_names(CuTest * tc) { race_name_func foo; + unit *u; + race *rc; test_cleanup(); register_names(); default_locale = test_create_locale(); - locale_setstring(default_locale, "undead_prefix_0", "Kleine"); + u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); + rc = test_create_race("undead"); locale_setstring(default_locale, "undead_name_0", "Graue"); locale_setstring(default_locale, "undead_postfix_0", "Kobolde"); CuAssertPtrNotNull(tc, foo = (race_name_func)get_function("nameundead")); - CuAssertStrEquals(tc, "Kleine Graue Kobolde", foo(NULL)); + rc->generate_name = foo; + race_namegen(rc, u); + CuAssertStrEquals(tc, "Graue Kobolde", u->_name); CuAssertPtrNotNull(tc, get_function("nameskeleton")); CuAssertPtrNotNull(tc, get_function("namezombie")); CuAssertPtrNotNull(tc, get_function("nameghoul")); From c18d75207e8e96bfa74b93749a2103f1792e51b2 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 28 Aug 2016 20:31:25 +0100 Subject: [PATCH 25/58] remove a TODO: static return variable from make_names. --- src/names.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/names.c b/src/names.c index a90a90f94..1d39df792 100644 --- a/src/names.c +++ b/src/names.c @@ -77,14 +77,14 @@ static void count_particles(const char *monster, int *num_prefix, int *num_name, } } -static const char *make_names(const char *monster, int *num_postfix, +static void make_name(unit *u, const char *monster, int *num_postfix, int pprefix, int *num_name, int *num_prefix, int ppostfix) { if (*num_name == 0) { count_particles(monster, num_prefix, num_name, num_postfix); } if (*num_name > 0) { - static char name[NAMESIZE + 1]; // FIXME: static return value + char name[NAMESIZE + 1]; // FIXME: static return value char zText[32]; int uv = 0, uu = 0, un = 0; const char *str; @@ -124,37 +124,32 @@ static const char *make_names(const char *monster, int *num_postfix, strlcat(name, (const char *)str, sizeof(name)); } } - return name; + unit_setname(u, name); } - return NULL; } static void undead_name(unit * u) { static int num_postfix, num_name, num_prefix; - const char *str = make_names("undead", &num_postfix, 2, &num_name, &num_prefix, 2); - unit_setname(u, str); + make_name(u, "undead", &num_postfix, 2, &num_name, &num_prefix, 2); } static void skeleton_name(unit * u) { static int num_postfix, num_name, num_prefix; - const char *str = make_names("skeleton", &num_postfix, 5, &num_name, &num_prefix, 2); - unit_setname(u, str); + make_name(u, "skeleton", &num_postfix, 5, &num_name, &num_prefix, 2); } static void zombie_name(unit * u) { static int num_postfix, num_name, num_prefix; - const char *str = make_names("zombie", &num_postfix, 5, &num_name, &num_prefix, 2); - unit_setname(u, str); + make_name(u, "zombie", &num_postfix, 5, &num_name, &num_prefix, 2); } static void ghoul_name(unit * u) { static int num_postfix, num_name, num_prefix; - const char *str = make_names("ghoul", &num_postfix, 5, &num_name, &num_prefix, 4); - unit_setname(u, str); + make_name(u, "ghoul", &num_postfix, 5, &num_name, &num_prefix, 4); } /* Drachen */ From 33701ab891c256a8ccecddcb4d489736bbf72879 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 28 Aug 2016 20:44:09 +0100 Subject: [PATCH 26/58] make describe_braineater more generic (describe_race). --- res/core/de/strings.xml | 2 +- res/e3a/races.xml | 2 +- res/eressea/races.xml | 2 +- src/kernel/race.c | 4 ++++ src/kernel/race.h | 20 +++++++++----------- src/kernel/save.c | 9 ++++++--- src/kernel/unit.c | 2 +- src/kernel/xmlreader.c | 3 +-- src/names.c | 8 +++++--- src/names.test.c | 2 +- 10 files changed, 30 insertions(+), 24 deletions(-) diff --git a/res/core/de/strings.xml b/res/core/de/strings.xml index 0b09a972b..ee8a409d8 100644 --- a/res/core/de/strings.xml +++ b/res/core/de/strings.xml @@ -34,7 +34,7 @@ Singdrachen sind von der Größe eines ausgewachsenden Tigers. Ihre Färbung reicht von schillerndem Rot, über dunkles Grün bis hin zu tiefem Schwarz. Alle bekannten Drachen dieser Art weisen eine hohe Intelligenz und ein hohes Maß an magischen Fähigkeiten auf. Wie Ihre großen Verwandten verfügen sie über einen Feuerodem. Sie lieben den Gesang und das üppige Mahl. Von Zeit zu Zeit gehen sie eine engen magisches Bund zu einem Magier ein. Wenn dies geschieht, so steht dem Magier ein äußerst loyaler und lohnender Vertrauter zur Seite. - + Song Dragons are roughly the size of a fully grown tiger. Their coloring ranges from bright red, through a dark green shade to a deep black. All known dragons of this species display a high level of intelligence and highly developed magical skills. Like their larger cousins, Song Dragons posess a firegland. They love singing and a good meal. From time to time one of these magnificent creatures will bond with a mage. When this happens, the mage is assured of a most loyal and useful familiar at his side. diff --git a/res/e3a/races.xml b/res/e3a/races.xml index aeafc4218..99c3420af 100644 --- a/res/e3a/races.xml +++ b/res/e3a/races.xml @@ -619,7 +619,7 @@ - + diff --git a/res/eressea/races.xml b/res/eressea/races.xml index e91d2f6f6..201a6a797 100644 --- a/res/eressea/races.xml +++ b/res/eressea/races.xml @@ -602,7 +602,7 @@ regaura="1.000000" recruitcost="50000" weight="100" capacity="540" speed="1.000000" hp="20" damage="0d0" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="10" scarepeasants="yes" fly="yes" walk="yes" teach="no" invinciblenonmagic="yes"> - + diff --git a/src/kernel/race.c b/src/kernel/race.c index 6eea8651b..4a6546f46 100644 --- a/src/kernel/race.c +++ b/src/kernel/race.c @@ -319,6 +319,10 @@ const char *dbrace(const struct race *rc) return zText; } +void register_race_description_function(race_desc_func func, const char *name) { + register_function((pf_generic)func, name); +} + void register_race_name_function(race_name_func func, const char *name) { register_function((pf_generic)func, name); } diff --git a/src/kernel/race.h b/src/kernel/race.h index 45e769648..2d1648b7d 100644 --- a/src/kernel/race.h +++ b/src/kernel/race.h @@ -45,6 +45,8 @@ extern "C" { struct param; struct spell; + extern int num_races; + typedef enum { RC_DWARF, /* 0 - Zwerg */ RC_ELF, @@ -117,8 +119,7 @@ extern "C" { int level; } att; - extern int num_races; - + typedef const char *(*race_desc_func)(const struct race *rc, const struct locale *lang); typedef void (*race_name_func)(struct unit *); typedef struct race { @@ -152,7 +153,7 @@ extern "C" { signed char bonus[MAXSKILLS]; race_name_func generate_name; - const char *(*describe) (const struct unit *, const struct locale *); + race_desc_func describe; void(*age) (struct unit * u); bool(*move_allowed) (const struct region *, const struct region *); struct item *(*itemdrop) (const struct race *, int size); @@ -168,8 +169,8 @@ extern "C" { const struct race *data; } race_list; - extern void racelist_clear(struct race_list **rl); - extern void racelist_insert(struct race_list **rl, const struct race *r); + void racelist_clear(struct race_list **rl); + void racelist_insert(struct race_list **rl, const struct race *r); struct race_list *get_familiarraces(void); @@ -178,8 +179,8 @@ extern "C" { /** TODO: compatibility hacks: **/ race_t old_race(const struct race *); - extern race *rc_get_or_create(const char *name); - extern const race *rc_find(const char *); + race *rc_get_or_create(const char *name); + const race *rc_find(const char *); void free_races(void); typedef enum name_t { NAME_SINGULAR, NAME_PLURAL, NAME_DEFINITIVE, NAME_CATEGORY } name_t; @@ -236,7 +237,6 @@ extern "C" { #define BF_INV_NONMAGIC (1<<5) /* Immun gegen nichtmagischen Schaden */ #define BF_NO_ATTACK (1<<6) /* Kann keine ATTACKIERE Befehle ausfuehren */ - int unit_old_max_hp(struct unit *u); const char *racename(const struct locale *lang, const struct unit *u, const race * rc); @@ -257,11 +257,9 @@ extern "C" { variant read_race_reference(struct storage *store); const char *raceprefix(const struct unit *u); - - void give_starting_equipment(const struct equipment *eq, - struct unit *u); const char *dbrace(const struct race *rc); void register_race_name_function(race_name_func, const char *); + void register_race_description_function(race_desc_func, const char *); char * race_namegen(const struct race *rc, struct unit *u); #ifdef __cplusplus diff --git a/src/kernel/save.c b/src/kernel/save.c index b3bdd2c17..9cfcc0f57 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -699,6 +699,7 @@ void write_attribs(storage *store, attrib *alist, const void *owner) unit *read_unit(struct gamedata *data) { unit *u; + const race *rc; int number, n, p; order **orderp; char obuf[DISPLAYSIZE]; @@ -760,7 +761,9 @@ unit *read_unit(struct gamedata *data) u->age = (short)n; READ_TOK(data->store, rname, sizeof(rname)); - u_setrace(u, rc_find(rname)); + rc = rc_find(rname); + assert(rc); + u_setrace(u, rc); READ_TOK(data->store, rname, sizeof(rname)); if (rname[0] && skill_enabled(SK_STEALTH)) @@ -768,8 +771,8 @@ unit *read_unit(struct gamedata *data) else u->irace = NULL; - if (u_race(u)->describe) { - const char *rcdisp = u_race(u)->describe(u, u->faction->locale); + if (rc->describe) { + const char *rcdisp = rc->describe(rc, u->faction->locale); if (u->display && rcdisp) { /* see if the data file contains old descriptions */ if (strcmp(rcdisp, u->display) == 0) { diff --git a/src/kernel/unit.c b/src/kernel/unit.c index 1db0d7761..c2ae688f4 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -470,7 +470,7 @@ const char *u_description(const unit * u, const struct locale *lang) return u->display; } else if (u_race(u)->describe) { - return u_race(u)->describe(u, lang); + return u_race(u)->describe(u->_race, lang); } return NULL; } diff --git a/src/kernel/xmlreader.c b/src/kernel/xmlreader.c index e944471f8..5075e26be 100644 --- a/src/kernel/xmlreader.c +++ b/src/kernel/xmlreader.c @@ -1800,8 +1800,7 @@ static int parse_races(xmlDocPtr doc) rc->generate_name = (race_name_func)fun; } else if (strcmp((const char *)propValue, "describe") == 0) { - rc->describe = - (const char *(*)(const struct unit *, const struct locale *))fun; + rc->describe = (race_desc_func)fun; } else if (strcmp((const char *)propValue, "age") == 0) { rc->age = (void(*)(struct unit *))fun; diff --git a/src/names.c b/src/names.c index 1d39df792..a9386ac07 100644 --- a/src/names.c +++ b/src/names.c @@ -45,9 +45,11 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include -static const char *describe_braineater(unit * u, const struct locale *lang) +static const char *describe_race(const race * rc, const struct locale *lang) { - return LOC(lang, "describe_braineater"); + char zText[32]; + sprintf(zText, "describe_%s", rc->_name); + return LOC(lang, zText); } static void count_particles(const char *monster, int *num_prefix, int *num_name, int *num_postfix) @@ -480,7 +482,7 @@ const char *abkz(const char *s, char *buf, size_t buflen, size_t maxchars) void register_names(void) { - register_function((pf_generic)describe_braineater, "describe_braineater"); + register_race_description_function(describe_race, "describe_race"); /* function name * generate a name for a nonplayerunit * race->generate_name() */ diff --git a/src/names.test.c b/src/names.test.c index a6dd6bb11..f50937f17 100644 --- a/src/names.test.c +++ b/src/names.test.c @@ -32,7 +32,7 @@ static void test_names(CuTest * tc) CuAssertPtrNotNull(tc, get_function("namedragon")); CuAssertPtrNotNull(tc, get_function("namedracoid")); CuAssertPtrNotNull(tc, get_function("namegeneric")); - CuAssertPtrNotNull(tc, get_function("describe_braineater")); + CuAssertPtrNotNull(tc, get_function("describe_race")); test_cleanup(); } From 5bc5dbdca1fbe54461cce88e85f092e7d2fd125a Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 28 Aug 2016 20:54:02 +0100 Subject: [PATCH 27/58] check for out-of-memory situations. --- src/tests.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tests.c b/src/tests.c index be62fdde8..6954c03d3 100644 --- a/src/tests.c +++ b/src/tests.c @@ -191,6 +191,7 @@ ship_type * test_create_shiptype(const char * name) stype->damage = 1; if (!stype->construction) { stype->construction = calloc(1, sizeof(construction)); + assert(stype->construction || !"out of memory"); stype->construction->maxsize = 5; stype->construction->minskill = 1; stype->construction->reqsize = 1; @@ -259,6 +260,7 @@ spell * test_create_spell(void) sp = create_spell("testspell", 0); sp->components = (spell_component *)calloc(4, sizeof(spell_component)); + assert(sp->components || !"out of memory"); sp->components[0].amount = 1; sp->components[0].type = get_resourcetype(R_SILVER); sp->components[0].cost = SPC_FIX; From 194f96c50f7203f89c18a1ff34db6235c4c3259e Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 28 Aug 2016 21:03:23 +0100 Subject: [PATCH 28/58] eliminate some possible null-pointer exceptions --- src/battle.c | 12 ++++++++---- src/move.c | 16 +++++++++++----- src/spells.c | 1 + 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/battle.c b/src/battle.c index 9d6448be4..762a37e7a 100644 --- a/src/battle.c +++ b/src/battle.c @@ -218,6 +218,7 @@ static void message_faction(battle * b, faction * f, struct message *m) assert(f); if (f->battles == NULL || f->battles->r != r) { struct bmsg *bm = (struct bmsg *)calloc(1, sizeof(struct bmsg)); + assert(bm || !"out of memory"); bm->next = f->battles; f->battles = bm; bm->r = r; @@ -251,6 +252,7 @@ static void fbattlerecord(battle * b, faction * f, const char *s) static bool set_enemy(side * as, side * ds, bool attacking) { int i; + assert(as && ds); for (i = 0; i != MAXSIDES; ++i) { if (ds->enemies[i] == NULL) ds->enemies[i] = as; @@ -1942,10 +1944,12 @@ int skilldiff(troop at, troop dt, int dist) is_protected = 2; } } - if (magicwalls_ct - && curse_active(get_curse(df->building->attribs, magicwalls_ct))) { - /* Verdoppelt Burgenbonus */ - skdiff -= df->building->type->protection(df->building, du, DEFENSE_BONUS); + if (df->building->type->protection) { + if (magicwalls_ct + && curse_active(get_curse(df->building->attribs, magicwalls_ct))) { + /* Verdoppelt Burgenbonus */ + skdiff -= df->building->type->protection(df->building, du, DEFENSE_BONUS); + } } } /* Goblin-Verteidigung diff --git a/src/move.c b/src/move.c index 09f3c2b3f..6d398d2f9 100644 --- a/src/move.c +++ b/src/move.c @@ -127,6 +127,7 @@ get_followers(unit * target, region * r, const region_list * route_end, const attrib *a = a_find(uf->attribs, &at_follow); if (a && a->data.v == target) { follower *fnew = (follower *)malloc(sizeof(follower)); + assert(fnew || !"out of memory"); fnew->uf = uf; fnew->ut = target; fnew->route_end = route_end; @@ -585,18 +586,21 @@ static void leave_trail(ship * sh, region * from, region_list * route) while (a != NULL && a->type == &at_shiptrail) { td = (traveldir *)a->data.v; - if (td->no == sh->no) + if (td->no == sh->no) { + td->dir = dir; + td->age = 2; break; + } a = a->next; } - if (a == NULL || a->type != &at_shiptrail) { + if (a == NULL) { a = a_add(&(r->attribs), a_new(&at_shiptrail)); td = (traveldir *)a->data.v; td->no = sh->no; + td->dir = dir; + td->age = 2; } - td->dir = dir; - td->age = 2; } route = route->next; r = rn; @@ -769,8 +773,9 @@ static void msg_to_ship_inmates(ship *sh, unit **firstu, unit **lastu, message * *lastu = u->next; } } - if (shipfirst) + if (shipfirst) { *firstu = shipfirst; + } for (u = *firstu; u != *lastu; u = u->next) { freset(u->faction, FFL_MARK); } @@ -1540,6 +1545,7 @@ static arg_regions *var_copy_regions(const region_list * begin, int size) assert(size > 0); arg_regions *dst = (arg_regions *)malloc(sizeof(arg_regions) + sizeof(region *) * (size_t)size); + assert(dst || !"out of memory"); dst->nregions = size; dst->regions = (region **)(dst + 1); for (rsrc = begin; i != size; rsrc = rsrc->next) { diff --git a/src/spells.c b/src/spells.c index 1da440df2..9dd7ef5bf 100644 --- a/src/spells.c +++ b/src/spells.c @@ -1263,6 +1263,7 @@ add_ironweapon(const struct item_type *type, const struct item_type *rusty, float chance) { iron_weapon *iweapon = malloc(sizeof(iron_weapon)); + assert(iweapon || !"out of memory"); iweapon->type = type; iweapon->rusty = rusty; iweapon->chance = chance; From 23a91be9c1815899a39e8c55f66dfe6f04f48861 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 29 Aug 2016 08:04:43 +0100 Subject: [PATCH 29/58] basic test for skilldiff. --- src/battle.test.c | 48 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/src/battle.test.c b/src/battle.test.c index f5c4979d7..0d7d73e19 100644 --- a/src/battle.test.c +++ b/src/battle.test.c @@ -203,10 +203,14 @@ static void test_building_defence_bonus(CuTest * tc) } static fighter *setup_fighter(battle **bp, unit *u) { - battle *b; + battle *b = *bp; + side *s; - *bp = b = make_battle(u->region); - return make_fighter(b, u, make_side(b, u->faction, 0, 0, 0), false); + if (!b) { + *bp = b = make_battle(u->region); + } + s = make_side(b, u->faction, 0, 0, 0); + return make_fighter(b, u, s, false); } static void test_natural_armor(CuTest * tc) @@ -229,7 +233,7 @@ static void test_natural_armor(CuTest * tc) static void test_calculate_armor(CuTest * tc) { troop dt; - battle *b; + battle *b = NULL; region *r; unit *du; weapon_type *wtype; @@ -255,6 +259,7 @@ static void test_calculate_armor(CuTest * tc) CuAssertDblEquals_Msg(tc, "magres unmodified", 1.0, magres, 0.01); free_battle(b); + b = NULL; i_change(&du->items, ibelt, 1); dt.fighter = setup_fighter(&b, du); CuAssertIntEquals_Msg(tc, "magical armor", 1, calculate_armor(dt, 0, 0, 0)); @@ -263,6 +268,7 @@ static void test_calculate_armor(CuTest * tc) rc->armor = 0; free_battle(b); + b = NULL; i_change(&du->items, ishield, 1); i_change(&du->items, ichain, 1); dt.fighter = setup_fighter(&b, du); @@ -270,6 +276,7 @@ static void test_calculate_armor(CuTest * tc) CuAssertIntEquals_Msg(tc, "require BF_EQUIPMENT", 1, calculate_armor(dt, 0, 0, 0)); free_battle(b); + b = NULL; rc->battle_flags |= BF_EQUIPMENT; dt.fighter = setup_fighter(&b, du); CuAssertIntEquals_Msg(tc, "stack equipment rc", 5, calculate_armor(dt, 0, 0, 0)); @@ -296,7 +303,7 @@ static void test_calculate_armor(CuTest * tc) static void test_magic_resistance(CuTest *tc) { troop dt; - battle *b; + battle *b = NULL; region *r; unit *du; armor_type *ashield, *achain; @@ -324,6 +331,7 @@ static void test_magic_resistance(CuTest *tc) calculate_armor(dt, 0, 0, &magres); free_battle(b); + b = NULL; i_change(&du->items, ishield, 1); i_change(&du->items, ichain, 1); achain->flags |= ATF_LAEN; @@ -335,6 +343,7 @@ static void test_magic_resistance(CuTest *tc) CuAssertDblEquals_Msg(tc, "laen reduction", 0.81, magres, 0.01); free_battle(b); + b = NULL; i_change(&du->items, ishield, -1); i_change(&du->items, ichain, -1); set_level(du, SK_MAGIC, 2); @@ -359,7 +368,7 @@ static void test_magic_resistance(CuTest *tc) static void test_projectile_armor(CuTest * tc) { troop dt; - battle *b; + battle *b = NULL; region *r; unit *du; weapon_type *wtype; @@ -394,10 +403,37 @@ static void test_projectile_armor(CuTest * tc) test_cleanup(); } +static void test_battle_skilldiff(CuTest *tc) +{ + troop ta, td; + region *r; + unit *ua, *ud; + battle *b = NULL; + + test_cleanup(); + r = test_create_region(0, 0, 0); + ud = test_create_unit(test_create_faction(0), r); + ua = test_create_unit(test_create_faction(0), r); + td.fighter = setup_fighter(&b, ud); + td.index = 0; + ta.fighter = setup_fighter(&b, ua); + ta.index = 0; + ua = test_create_unit(test_create_faction(0), r); + CuAssertIntEquals(tc, 0, skilldiff(ta, td, 0)); + + ta.fighter->person[0].attack = 2; + td.fighter->person[0].defence = 1; + CuAssertIntEquals(tc, 1, skilldiff(ta, td, 0)); + + free_battle(b); + test_cleanup(); +} + CuSuite *get_battle_suite(void) { CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_make_fighter); + SUITE_ADD_TEST(suite, test_battle_skilldiff); SUITE_ADD_TEST(suite, test_defenders_get_building_bonus); SUITE_ADD_TEST(suite, test_attackers_get_no_building_bonus); SUITE_ADD_TEST(suite, test_building_bonus_respects_size); From 0d609f2115cb0f416d5a3cce1eb272c31e48a81e Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 29 Aug 2016 08:53:09 +0100 Subject: [PATCH 30/58] test magicwalls and strongwalls effects on buildings. --- src/battle.c | 32 +++++++++++------------- src/battle.test.c | 57 +++++++++++++++++++++++++++++++++++++++--- src/kernel/building.c | 10 +------- src/kernel/building.h | 2 +- src/kernel/unit.c | 10 +++----- src/kernel/xmlreader.c | 2 +- 6 files changed, 74 insertions(+), 39 deletions(-) diff --git a/src/battle.c b/src/battle.c index 762a37e7a..9af7a23d4 100644 --- a/src/battle.c +++ b/src/battle.c @@ -1922,20 +1922,8 @@ int skilldiff(troop at, troop dt, int dist) } if (df->building) { - bool init = false; - static const curse_type *strongwall_ct, *magicwalls_ct; - if (!init) { - strongwall_ct = ct_find("strongwall"); - magicwalls_ct = ct_find("magicwalls"); - init = true; - } - if (df->building->type->protection) { - int beff = df->building->type->protection(df->building, du, DEFENSE_BONUS); - if (beff) { - skdiff -= beff; - is_protected = 2; - } - } + static const curse_type *strongwall_ct; + strongwall_ct = ct_find("strongwall"); if (strongwall_ct) { curse *c = get_curse(df->building->attribs, strongwall_ct); if (curse_active(c)) { @@ -1944,11 +1932,19 @@ int skilldiff(troop at, troop dt, int dist) is_protected = 2; } } + if (df->building->type->protection) { - if (magicwalls_ct - && curse_active(get_curse(df->building->attribs, magicwalls_ct))) { - /* Verdoppelt Burgenbonus */ - skdiff -= df->building->type->protection(df->building, du, DEFENSE_BONUS); + int beff = df->building->type->protection(df->building, du, DEFENSE_BONUS); + if (beff) { + static const curse_type *magicwalls_ct; + skdiff -= beff; + is_protected = 2; + magicwalls_ct = ct_find("magicwalls"); + if (magicwalls_ct + && curse_active(get_curse(df->building->attribs, magicwalls_ct))) { + /* Verdoppelt Burgenbonus */ + skdiff -= beff; + } } } } diff --git a/src/battle.test.c b/src/battle.test.c index 0d7d73e19..2ba68bbc9 100644 --- a/src/battle.test.c +++ b/src/battle.test.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -59,7 +60,7 @@ static void test_make_fighter(CuTest * tc) test_cleanup(); } -static int add_two(building * b, unit * u, building_bonus bonus) { +static int add_two(const building * b, const unit * u, building_bonus bonus) { return 2; } @@ -187,7 +188,7 @@ static void test_building_defence_bonus(CuTest * tc) test_cleanup(); r = test_create_region(0, 0, 0); btype = test_create_buildingtype("castle"); - btype->protection = (int(*)(struct building *, struct unit *, building_bonus))get_function("building_protection"); + btype->protection = (int(*)(const struct building *, const struct unit *, building_bonus))get_function("building_protection"); btype->construction->defense_bonus = 3; bld = test_create_building(r, btype); bld->size = 1; @@ -403,7 +404,7 @@ static void test_projectile_armor(CuTest * tc) test_cleanup(); } -static void test_battle_skilldiff(CuTest *tc) +static void test_battle_skilldiff(CuTest *tc) { troop ta, td; region *r; @@ -411,6 +412,7 @@ static void test_battle_skilldiff(CuTest *tc) battle *b = NULL; test_cleanup(); + r = test_create_region(0, 0, 0); ud = test_create_unit(test_create_faction(0), r); ua = test_create_unit(test_create_faction(0), r); @@ -425,6 +427,54 @@ static void test_battle_skilldiff(CuTest *tc) td.fighter->person[0].defence = 1; CuAssertIntEquals(tc, 1, skilldiff(ta, td, 0)); + td.fighter->person[0].flags |= FL_SLEEPING; + CuAssertIntEquals(tc, 3, skilldiff(ta, td, 0)); + + // TODO: unarmed halfling vs. dragon: +5 + // TODO: rule_goblin_bonus + + free_battle(b); + test_cleanup(); +} + +static int protect(const building *b, const unit *u, building_bonus bonus) { + return (bonus == DEFENSE_BONUS) ? 4 : 0; +} + +static void test_battle_skilldiff_building(CuTest *tc) +{ + troop ta, td; + region *r; + unit *ua, *ud; + battle *b = NULL; + building_type *btype; + static const curse_type *strongwall_ct, *magicwalls_ct; + + test_cleanup(); + btype = test_create_buildingtype("castle"); + strongwall_ct = ct_find("strongwall"); + magicwalls_ct = ct_find("magicwalls"); + + r = test_create_region(0, 0, 0); + ud = test_create_unit(test_create_faction(0), r); + ud->building = test_create_building(ud->region, btype); + ua = test_create_unit(test_create_faction(0), r); + td.fighter = setup_fighter(&b, ud); + td.index = 0; + ta.fighter = setup_fighter(&b, ua); + ta.index = 0; + ua = test_create_unit(test_create_faction(0), r); + CuAssertIntEquals(tc, 0, skilldiff(ta, td, 0)); + + btype->protection = protect; + CuAssertIntEquals(tc, -4, skilldiff(ta, td, 0)); + + create_curse(NULL, &ud->building->attribs, magicwalls_ct, 1, 1, 1, 1); + CuAssertIntEquals(tc, -8, skilldiff(ta, td, 0)); + + create_curse(NULL, &ud->building->attribs, strongwall_ct, 1, 1, 2, 1); + CuAssertIntEquals(tc, -10, skilldiff(ta, td, 0)); + free_battle(b); test_cleanup(); } @@ -434,6 +484,7 @@ CuSuite *get_battle_suite(void) CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_make_fighter); SUITE_ADD_TEST(suite, test_battle_skilldiff); + SUITE_ADD_TEST(suite, test_battle_skilldiff_building); SUITE_ADD_TEST(suite, test_defenders_get_building_bonus); SUITE_ADD_TEST(suite, test_attackers_get_no_building_bonus); SUITE_ADD_TEST(suite, test_building_bonus_respects_size); diff --git a/src/kernel/building.c b/src/kernel/building.c index cf40c0ea3..7e537c70d 100644 --- a/src/kernel/building.c +++ b/src/kernel/building.c @@ -322,9 +322,8 @@ const building_type *findbuildingtype(const char *name, return (const building_type *)type.v; } -static int building_protection(building * b, unit * u, building_bonus bonus) +static int building_protection(const building * b, const unit * u, building_bonus bonus) { - int i = 0; int bsize = buildingeffsize(b, false); const construction *cons = b->type->construction; @@ -350,17 +349,10 @@ static int building_protection(building * b, unit * u, building_bonus bonus) } } -static int meropis_building_protection(building * b, unit * u) -{ - return 2; -} - void register_buildings(void) { register_function((pf_generic)building_protection, "building_protection"); - register_function((pf_generic)meropis_building_protection, - "meropis_building_protection"); register_function((pf_generic)init_smithy, "init_smithy"); register_function((pf_generic)castle_name, "castle_name"); register_function((pf_generic)castle_name_2, "castle_name_2"); diff --git a/src/kernel/building.h b/src/kernel/building.h index fda4a4676..c2dcb6dea 100644 --- a/src/kernel/building.h +++ b/src/kernel/building.h @@ -75,7 +75,7 @@ extern "C" { const struct building * b, int size); void(*init) (struct building_type *); void(*age) (struct building *); - int(*protection) (struct building *, struct unit *, building_bonus); + int(*protection) (const struct building *, const struct unit *, building_bonus bonus); double(*taxes) (const struct building *, int size); struct attrib *attribs; } building_type; diff --git a/src/kernel/unit.c b/src/kernel/unit.c index c2ae688f4..d039560f6 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -1217,16 +1217,12 @@ static int item_modification(const unit * u, skill_t sk, int val) static int att_modification(const unit * u, skill_t sk) { double result = 0; - static bool init = false; // TODO: static variables are bad global state static const curse_type *skillmod_ct, *gbdream_ct, *worse_ct; curse *c; - if (!init) { - init = true; - skillmod_ct = ct_find("skillmod"); - gbdream_ct = ct_find("gbdream"); - worse_ct = ct_find("worse"); - } + skillmod_ct = ct_find("skillmod"); + gbdream_ct = ct_find("gbdream"); + worse_ct = ct_find("worse"); c = get_curse(u->attribs, worse_ct); if (c != NULL) diff --git a/src/kernel/xmlreader.c b/src/kernel/xmlreader.c index 5075e26be..19d661cc6 100644 --- a/src/kernel/xmlreader.c +++ b/src/kernel/xmlreader.c @@ -305,7 +305,7 @@ static int parse_buildings(xmlDocPtr doc) btype->age = (void(*)(struct building *))fun; } else if (strcmp((const char *)propValue, "protection") == 0) { - btype->protection = (int(*)(struct building *, struct unit *, building_bonus))fun; + btype->protection = (int(*)(const struct building *, const struct unit *, building_bonus))fun; } else if (strcmp((const char *)propValue, "taxes") == 0) { btype->taxes = (double(*)(const struct building *, int))fun; From 1f3413a9b47ee26f31769b9f74ce51f161bc1db7 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 29 Aug 2016 08:55:59 +0100 Subject: [PATCH 31/58] annotations --- src/battle.c | 4 ---- src/battle.test.c | 1 + src/kernel/building.h | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/battle.c b/src/battle.c index 9af7a23d4..c061f1ca5 100644 --- a/src/battle.c +++ b/src/battle.c @@ -1948,10 +1948,6 @@ int skilldiff(troop at, troop dt, int dist) } } } - /* Goblin-Verteidigung - * ist direkt in der Rassentabelle als df_default - */ - /* Effekte der Waffen */ skdiff += weapon_effskill(at, dt, awp, true, dist > 1); if (awp && fval(awp->type, WTF_MISSILE)) { diff --git a/src/battle.test.c b/src/battle.test.c index 2ba68bbc9..f44d3985c 100644 --- a/src/battle.test.c +++ b/src/battle.test.c @@ -432,6 +432,7 @@ static void test_battle_skilldiff(CuTest *tc) // TODO: unarmed halfling vs. dragon: +5 // TODO: rule_goblin_bonus + // TODO: weapon modifiers, missiles, skill_formula free_battle(b); test_cleanup(); diff --git a/src/kernel/building.h b/src/kernel/building.h index c2dcb6dea..020de077b 100644 --- a/src/kernel/building.h +++ b/src/kernel/building.h @@ -53,7 +53,7 @@ extern "C" { typedef enum { DEFENSE_BONUS, - CLOSE_COMBAT_ATTACK_BONUS, + CLOSE_COMBAT_ATTACK_BONUS, // TODO: only DEFENSE_BONUS is in use? RANGED_ATTACK_BONUS, } building_bonus; From fd273848ae87d8538bf5c637255b5aad01812ffc Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 29 Aug 2016 09:20:08 +0100 Subject: [PATCH 32/58] add an assert_alloc macro for allocations that cannot fail. --- src/battle.c | 4 ++-- src/move.c | 6 +++--- src/spells.c | 4 ++-- src/tests.c | 6 +++--- src/util/assert.h | 7 +++++++ src/util/strings.c | 6 +++++- src/util/translation.c | 12 +++++------- src/util/umlaut.c | 2 ++ src/util/xml.c | 3 ++- 9 files changed, 31 insertions(+), 19 deletions(-) create mode 100644 src/util/assert.h diff --git a/src/battle.c b/src/battle.c index c061f1ca5..a35026983 100644 --- a/src/battle.c +++ b/src/battle.c @@ -56,6 +56,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include /* util includes */ +#include #include #include #include @@ -67,7 +68,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include /* libc includes */ -#include #include #include #include @@ -218,7 +218,7 @@ static void message_faction(battle * b, faction * f, struct message *m) assert(f); if (f->battles == NULL || f->battles->r != r) { struct bmsg *bm = (struct bmsg *)calloc(1, sizeof(struct bmsg)); - assert(bm || !"out of memory"); + assert_alloc(bm); bm->next = f->battles; f->battles = bm; bm->r = r; diff --git a/src/move.c b/src/move.c index 6d398d2f9..156c3c5d2 100644 --- a/src/move.c +++ b/src/move.c @@ -57,6 +57,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "skill.h" /* util includes */ +#include #include #include #include @@ -77,7 +78,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include /* libc includes */ -#include #include #include #include @@ -127,7 +127,7 @@ get_followers(unit * target, region * r, const region_list * route_end, const attrib *a = a_find(uf->attribs, &at_follow); if (a && a->data.v == target) { follower *fnew = (follower *)malloc(sizeof(follower)); - assert(fnew || !"out of memory"); + assert_alloc(fnew); fnew->uf = uf; fnew->ut = target; fnew->route_end = route_end; @@ -1545,7 +1545,7 @@ static arg_regions *var_copy_regions(const region_list * begin, int size) assert(size > 0); arg_regions *dst = (arg_regions *)malloc(sizeof(arg_regions) + sizeof(region *) * (size_t)size); - assert(dst || !"out of memory"); + assert_alloc(dst); dst->nregions = size; dst->regions = (region **)(dst + 1); for (rsrc = begin; i != size; rsrc = rsrc->next) { diff --git a/src/spells.c b/src/spells.c index 9dd7ef5bf..5329e85d3 100644 --- a/src/spells.c +++ b/src/spells.c @@ -58,6 +58,7 @@ #include /* util includes */ +#include #include #include #include @@ -80,7 +81,6 @@ #include /* libc includes */ -#include #include #include #include @@ -1263,7 +1263,7 @@ add_ironweapon(const struct item_type *type, const struct item_type *rusty, float chance) { iron_weapon *iweapon = malloc(sizeof(iron_weapon)); - assert(iweapon || !"out of memory"); + assert_alloc(iweapon); iweapon->type = type; iweapon->rusty = rusty; iweapon->chance = chance; diff --git a/src/tests.c b/src/tests.c index 6954c03d3..53ebe8a28 100644 --- a/src/tests.c +++ b/src/tests.c @@ -27,10 +27,10 @@ #include #include #include +#include #include -#include #include #include #include @@ -191,7 +191,7 @@ ship_type * test_create_shiptype(const char * name) stype->damage = 1; if (!stype->construction) { stype->construction = calloc(1, sizeof(construction)); - assert(stype->construction || !"out of memory"); + assert_alloc(stype->construction); stype->construction->maxsize = 5; stype->construction->minskill = 1; stype->construction->reqsize = 1; @@ -260,7 +260,7 @@ spell * test_create_spell(void) sp = create_spell("testspell", 0); sp->components = (spell_component *)calloc(4, sizeof(spell_component)); - assert(sp->components || !"out of memory"); + assert_alloc(sp->components); sp->components[0].amount = 1; sp->components[0].type = get_resourcetype(R_SILVER); sp->components[0].cost = SPC_FIX; diff --git a/src/util/assert.h b/src/util/assert.h new file mode 100644 index 000000000..79abce73e --- /dev/null +++ b/src/util/assert.h @@ -0,0 +1,7 @@ +#ifndef UTIL_ASSERT_H +#define UTIL_ASSERT_H + +#include + +#define assert_alloc(expr) assert((expr) || !"out of memory") +#endif diff --git a/src/util/strings.c b/src/util/strings.c index b3801d52f..5c8a7ba71 100644 --- a/src/util/strings.c +++ b/src/util/strings.c @@ -18,6 +18,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include +#include "assert.h" + /* libc includes */ #include #include @@ -34,7 +36,9 @@ char *set_string(char **s, const char *neu) strcpy(*s, neu); } else { - *s = realloc(*s, strlen(neu) + 1); + char *rs = realloc(*s, strlen(neu) + 1); + assert_alloc(rs); + *s = rs; strcpy(*s, neu); } return *s; diff --git a/src/util/translation.c b/src/util/translation.c index 16d3e684f..829a1fe05 100644 --- a/src/util/translation.c +++ b/src/util/translation.c @@ -1,4 +1,4 @@ -/* +/* +-------------------+ Christian Schlittchen | | Enno Rehling | Eressea PBEM host | Katja Zedel @@ -16,9 +16,9 @@ #include "bsdstring.h" #include "critbit.h" #include "log.h" +#include "assert.h" -/* libc includes */ -#include + /* libc includes */ #include #include #include @@ -48,6 +48,7 @@ void opstack_push(opstack ** stackp, variant data) opstack *stack = *stackp; if (stack == NULL) { stack = (opstack *)malloc(sizeof(opstack)); + assert_alloc(stack); stack->size = 2; stack->begin = malloc(sizeof(variant) * stack->size); stack->top = stack->begin; @@ -58,10 +59,7 @@ void opstack_push(opstack ** stackp, variant data) void *tmp; stack->size += stack->size; tmp = realloc(stack->begin, sizeof(variant) * stack->size); - if (!tmp) { - log_error("realloc out of memory"); - abort(); - } + assert_alloc(tmp); stack->begin = (variant *)tmp; stack->top = stack->begin + pos; } diff --git a/src/util/umlaut.c b/src/util/umlaut.c index abbd59372..616596a01 100644 --- a/src/util/umlaut.c +++ b/src/util/umlaut.c @@ -19,6 +19,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include "umlaut.h" +#include "assert.h" #include "log.h" #include "unicode.h" @@ -183,6 +184,7 @@ void addtoken(void ** root, const char *str, variant id) index = lcs % NODEHASHSIZE; #endif ref = (tref *)malloc(sizeof(tref)); + assert_alloc(ref); ref->ucs = lcs; ref->node = node; ref->nexthash = tk->next[index]; diff --git a/src/util/xml.c b/src/util/xml.c index 80cec1092..2d49f2a7d 100644 --- a/src/util/xml.c +++ b/src/util/xml.c @@ -14,6 +14,7 @@ /* util includes */ #include "log.h" +#include "assert.h" #ifdef USE_LIBXML2 #include @@ -21,7 +22,6 @@ #endif /* libc includes */ -#include #include #include #include @@ -93,6 +93,7 @@ void xml_register_callback(xml_callback callback) { xml_reader *reader = (xml_reader *)malloc(sizeof(xml_reader)); xml_reader **insert = &xmlReaders; + assert_alloc(reader); reader->callback = callback; reader->next = NULL; From 2eb9b5c5ea919e082e595772e0b30cd9b7d1de60 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 29 Aug 2016 13:49:39 +0100 Subject: [PATCH 33/58] delete dead code (dbrace) --- src/kernel/race.c | 16 ---------------- src/kernel/race.h | 1 - src/util/language.c | 3 ++- src/util/log.c | 1 + 4 files changed, 3 insertions(+), 18 deletions(-) diff --git a/src/kernel/race.c b/src/kernel/race.c index 4a6546f46..fdc720e2e 100644 --- a/src/kernel/race.c +++ b/src/kernel/race.c @@ -303,22 +303,6 @@ variant read_race_reference(struct storage *store) return result; } -/** Returns the English name of the race, which is what the database uses. -*/ -const char *dbrace(const struct race *rc) -{ - static char zText[32]; // FIXME: static return value - char *zPtr = zText; - - /* the english names are all in ASCII, so we don't need to worry about UTF8 */ - strlcpy(zText, (const char *)LOC(get_locale("en"), rc_name_s(rc, NAME_SINGULAR)), sizeof(zText)); - while (*zPtr) { - *zPtr = (char)(toupper(*zPtr)); - ++zPtr; - } - return zText; -} - void register_race_description_function(race_desc_func func, const char *name) { register_function((pf_generic)func, name); } diff --git a/src/kernel/race.h b/src/kernel/race.h index 2d1648b7d..b1632f62d 100644 --- a/src/kernel/race.h +++ b/src/kernel/race.h @@ -257,7 +257,6 @@ extern "C" { variant read_race_reference(struct storage *store); const char *raceprefix(const struct unit *u); - const char *dbrace(const struct race *rc); void register_race_name_function(race_name_func, const char *); void register_race_description_function(race_desc_func, const char *); char * race_namegen(const struct race *rc, struct unit *u); diff --git a/src/util/language.c b/src/util/language.c index 03d65c164..d8b899742 100644 --- a/src/util/language.c +++ b/src/util/language.c @@ -22,11 +22,11 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "log.h" #include "strings.h" #include "umlaut.h" +#include "assert.h" #include #include #include -#include #include #define SMAXHASH 2048 @@ -84,6 +84,7 @@ locale *get_or_create_locale(const char *name) } } *lp = l = (locale *)calloc(sizeof(locale), 1); + assert_alloc(l); l->hashkey = hkey; l->name = _strdup(name); l->index = nextlocaleindex++; diff --git a/src/util/log.c b/src/util/log.c index cb358519c..a0985ea46 100644 --- a/src/util/log.c +++ b/src/util/log.c @@ -138,6 +138,7 @@ static int check_dupe(const char *format, int level) static char last_message[32]; /* STATIC_XCALL: used across calls */ static int dupes = 0; /* STATIC_XCALL: used across calls */ if (strncmp(last_message, format, sizeof(last_message)) == 0) { + // TODO: C6054: String 'last_message' might not be zero - terminated. ++dupes; return 1; } From 1c5fcded9f9262042ce258ff4908f21d6c9818b7 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 29 Aug 2016 14:09:47 +0100 Subject: [PATCH 34/58] allow control over stderr logging from tests. separate test_cleanup from test_setup. --- src/kernel/spell.test.c | 9 ++++++--- src/test_eressea.c | 1 - src/tests.c | 31 ++++++++++++++++++++++++++++--- src/tests.h | 2 ++ 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/kernel/spell.test.c b/src/kernel/spell.test.c index 0c0beb6ce..60665a591 100644 --- a/src/kernel/spell.test.c +++ b/src/kernel/spell.test.c @@ -13,13 +13,14 @@ static void test_create_a_spell(CuTest * tc) { spell * sp; - test_cleanup(); + test_setup(); CuAssertPtrEquals(tc, 0, spells); CuAssertPtrEquals(tc, 0, find_spell("testspell")); sp = create_spell("testspell", 0); CuAssertPtrEquals(tc, sp, find_spell("testspell")); CuAssertPtrNotNull(tc, spells); + test_cleanup(); } static void test_create_duplicate_spell(CuTest * tc) @@ -27,12 +28,13 @@ static void test_create_duplicate_spell(CuTest * tc) spell *sp; /* FIXME: this test emits ERROR messages (duplicate spells), inject a logger to verify that */ - test_cleanup(); + test_setup(); CuAssertPtrEquals(tc, 0, find_spell("testspell")); sp = create_spell("testspell", 0); CuAssertPtrEquals(tc, 0, create_spell("testspell", 0)); CuAssertPtrEquals(tc, sp, find_spell("testspell")); + test_cleanup(); } static void test_create_spell_with_id(CuTest * tc) @@ -40,12 +42,13 @@ static void test_create_spell_with_id(CuTest * tc) spell *sp; /* FIXME: this test emits ERROR messages (duplicate spells), inject a logger to verify that */ - test_cleanup(); + test_setup(); CuAssertPtrEquals(tc, 0, find_spellbyid(42)); sp = create_spell("testspell", 42); CuAssertPtrEquals(tc, sp, find_spellbyid(42)); CuAssertPtrEquals(tc, 0, create_spell("testspell", 47)); CuAssertPtrEquals(tc, 0, find_spellbyid(47)); + test_cleanup(); } CuSuite *get_spell_suite(void) diff --git a/src/test_eressea.c b/src/test_eressea.c index 8236465cf..3001ee2b8 100644 --- a/src/test_eressea.c +++ b/src/test_eressea.c @@ -158,7 +158,6 @@ int RunAllTests(int argc, char *argv[]) } int main(int argc, char ** argv) { - log_to_file(LOG_CPERROR, stderr); ++argv; --argc; if (argc > 0 && strcmp("--list", argv[0]) == 0) { diff --git a/src/tests.c b/src/tests.c index 53ebe8a28..5d359813d 100644 --- a/src/tests.c +++ b/src/tests.c @@ -123,10 +123,24 @@ struct unit *test_create_unit(struct faction *f, struct region *r) return create_unit(r, f, 1, rc ? rc : rc_get_or_create("human"), 0, 0, 0); } -void test_cleanup(void) -{ - int i; +void test_log_stderr(int flags) { + static struct log_t *stderrlog; + if (flags) { + if (stderrlog) { + log_error("stderr logging is still active. did you call test_cleanup?"); + log_destroy(stderrlog); + } + stderrlog = log_to_file(flags, stderr); + } + else { + log_destroy(stderrlog); + stderrlog = 0; + } +} + +static void test_reset(void) { + int i; default_locale = 0; free_gamedata(); free_terrains(); @@ -158,6 +172,17 @@ void test_cleanup(void) random_source_reset(); } +void test_setup(void) { + test_log_stderr(LOG_CPERROR); + test_reset(); +} + +void test_cleanup(void) +{ + test_reset(); + test_log_stderr(0); +} + terrain_type * test_create_terrain(const char * name, unsigned int flags) { diff --git a/src/tests.h b/src/tests.h index e31578beb..a025c92c1 100644 --- a/src/tests.h +++ b/src/tests.h @@ -29,7 +29,9 @@ extern "C" { struct CuTest; + void test_setup(void); void test_cleanup(void); + void test_log_stderr(int on); struct locale * test_create_locale(void); struct terrain_type * test_create_terrain(const char * name, unsigned int flags); From c032091b393dae805e5dd99a7e29d525dff801b4 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 29 Aug 2016 14:21:28 +0100 Subject: [PATCH 35/58] new rule: call test_setup to begin test, test_cleanup at end. --- src/alchemy.test.c | 2 +- src/attributes/otherfaction.test.c | 4 ++-- src/kernel/alliance.test.c | 16 ++++++++-------- src/kernel/spell.test.c | 2 ++ src/prefix.test.c | 4 ++-- src/spy.test.c | 4 ++-- src/study.test.c | 30 +++++++++++++++--------------- src/tests.c | 7 ++++++- src/triggers/shock.test.c | 4 ++-- src/upkeep.test.c | 10 +++++----- src/vortex.test.c | 2 +- src/wormhole.test.c | 4 ++-- 12 files changed, 48 insertions(+), 41 deletions(-) diff --git a/src/alchemy.test.c b/src/alchemy.test.c index 7e2e5b399..7fd2da8e1 100644 --- a/src/alchemy.test.c +++ b/src/alchemy.test.c @@ -25,7 +25,7 @@ static void test_herbsearch(CuTest * tc) region *r; const item_type *itype; - test_cleanup(); + test_setup(); r = test_create_region(0, 0, 0); rc = rc_get_or_create("dragon"); rc->flags |= RCF_UNARMEDGUARD; diff --git a/src/attributes/otherfaction.test.c b/src/attributes/otherfaction.test.c index 8e3d09b0a..a28d9f470 100644 --- a/src/attributes/otherfaction.test.c +++ b/src/attributes/otherfaction.test.c @@ -16,7 +16,7 @@ #include static void test_rules(CuTest *tc) { - test_cleanup(); + test_setup(); config_set("stealth.faction.other", NULL); CuAssertIntEquals(tc, true, rule_stealth_other()); config_set("stealth.faction.other", "0"); @@ -37,7 +37,7 @@ static void test_otherfaction(CuTest *tc) { unit *u; faction *f; - test_cleanup(); + test_setup(); u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); f = test_create_faction(0); config_set("stealth.faction.other", "1"); diff --git a/src/kernel/alliance.test.c b/src/kernel/alliance.test.c index 8432f1692..72a31a42c 100644 --- a/src/kernel/alliance.test.c +++ b/src/kernel/alliance.test.c @@ -17,7 +17,6 @@ typedef struct alliance_fixture { } alliance_fixture; static void setup_alliance(alliance_fixture *fix) { - test_cleanup(); test_create_world(); fix->rc = test_create_race("human"); fix->f1 = test_create_faction(fix->rc); @@ -28,7 +27,7 @@ static void setup_alliance(alliance_fixture *fix) { static void test_alliance_make(CuTest *tc) { alliance * al; - test_cleanup(); + test_setup(); assert(!alliances); al = makealliance(1, "Hodor"); CuAssertPtrNotNull(tc, al); @@ -50,6 +49,7 @@ static void test_alliance_join(CuTest *tc) { alliance_fixture fix; alliance * al; + test_setup(); setup_alliance(&fix); CuAssertPtrEquals(tc, 0, fix.f1->alliance); CuAssertPtrEquals(tc, 0, fix.f2->alliance); @@ -69,7 +69,7 @@ static void test_alliance_dead_faction(CuTest *tc) { faction *f, *f2; alliance *al; - test_cleanup(); + test_setup(); f = test_create_faction(0); f2 = test_create_faction(0); al = makealliance(42, "Hodor"); @@ -91,7 +91,7 @@ static void test_alliance_cmd(CuTest *tc) { struct region *r; struct alliance *al; - test_cleanup(); + test_setup(); r = test_create_region(0, 0, 0); u1 = test_create_unit(test_create_faction(0), r); u2 = test_create_unit(test_create_faction(0), r); @@ -118,7 +118,7 @@ static void test_alliance_cmd_kick(CuTest *tc) { struct region *r; struct alliance *al; - test_cleanup(); + test_setup(); al = makealliance(42, "Hodor"); r = test_create_region(0, 0, 0); u1 = test_create_unit(test_create_faction(0), r); @@ -138,7 +138,7 @@ static void test_alliance_cmd_no_invite(CuTest *tc) { unit *u1, *u2; struct region *r; - test_cleanup(); + test_setup(); r = test_create_region(0, 0, 0); u1 = test_create_unit(test_create_faction(0), r); u2 = test_create_unit(test_create_faction(0), r); @@ -159,7 +159,7 @@ static void test_alliance_cmd_leave(CuTest *tc) { struct region *r; struct alliance *al; - test_cleanup(); + test_setup(); al = makealliance(42, "Hodor"); r = test_create_region(0, 0, 0); u1 = test_create_unit(test_create_faction(0), r); @@ -180,7 +180,7 @@ static void test_alliance_cmd_transfer(CuTest *tc) { struct region *r; struct alliance *al; - test_cleanup(); + test_setup(); al = makealliance(42, "Hodor"); r = test_create_region(0, 0, 0); u1 = test_create_unit(test_create_faction(0), r); diff --git a/src/kernel/spell.test.c b/src/kernel/spell.test.c index 60665a591..db167adce 100644 --- a/src/kernel/spell.test.c +++ b/src/kernel/spell.test.c @@ -29,6 +29,7 @@ static void test_create_duplicate_spell(CuTest * tc) /* FIXME: this test emits ERROR messages (duplicate spells), inject a logger to verify that */ test_setup(); + test_log_stderr(0); CuAssertPtrEquals(tc, 0, find_spell("testspell")); sp = create_spell("testspell", 0); @@ -43,6 +44,7 @@ static void test_create_spell_with_id(CuTest * tc) /* FIXME: this test emits ERROR messages (duplicate spells), inject a logger to verify that */ test_setup(); + test_log_stderr(0); CuAssertPtrEquals(tc, 0, find_spellbyid(42)); sp = create_spell("testspell", 42); CuAssertPtrEquals(tc, sp, find_spellbyid(42)); diff --git a/src/prefix.test.c b/src/prefix.test.c index 44c0d845d..222c19f85 100644 --- a/src/prefix.test.c +++ b/src/prefix.test.c @@ -6,7 +6,7 @@ #include static void test_add_prefix(CuTest *tc) { - test_cleanup(); + test_setup(); CuAssertPtrEquals(tc, 0, race_prefixes); add_raceprefix("sea"); CuAssertPtrNotNull(tc, race_prefixes); @@ -26,4 +26,4 @@ CuSuite *get_prefix_suite(void) CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_add_prefix); return suite; -} \ No newline at end of file +} diff --git a/src/spy.test.c b/src/spy.test.c index b843306f1..299e4b3a6 100644 --- a/src/spy.test.c +++ b/src/spy.test.c @@ -32,7 +32,7 @@ typedef struct { } spy_fixture; static void setup_spy(spy_fixture *fix) { - test_cleanup(); + test_setup(); fix->r = test_create_region(0, 0, NULL); fix->spy = test_create_unit(test_create_faction(NULL), fix->r); fix->victim = test_create_unit(test_create_faction(NULL), fix->r); @@ -88,7 +88,7 @@ static void test_all_spy_message(CuTest *tc) { static void setup_sabotage(void) { struct locale *lang; - test_cleanup(); + test_setup(); lang = get_or_create_locale("de"); locale_setstring(lang, parameters[P_SHIP], "SCHIFF"); locale_setstring(lang, parameters[P_ANY], "ALLE"); diff --git a/src/study.test.c b/src/study.test.c index 7e0eb8744..f12fc25df 100644 --- a/src/study.test.c +++ b/src/study.test.c @@ -70,7 +70,7 @@ static void setup_study(study_fixture *fix, skill_t sk) { struct locale *lang; assert(fix); - test_cleanup(); + test_setup(); config_set("study.random_progress", "0"); test_create_world(); r = findregion(0, 0); @@ -138,7 +138,7 @@ static void test_study_bug_2194(CuTest *tc) { struct locale * loc; building * b; - test_cleanup(); + test_setup(); random_source_inject_constant(0.0); init_resources(); loc = get_or_create_locale("de"); @@ -195,7 +195,7 @@ static void test_produceexp(CuTest *tc) { unit *u; g_tc = tc; - test_cleanup(); + test_setup(); u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); scale_number(u, 2); config_set("study.produceexp", "20"); @@ -210,7 +210,7 @@ static void test_academy_building(CuTest *tc) { building * b; message * msg; - test_cleanup(); + test_setup(); mt_register(mt_new_va("teach_asgood", "unit:unit", "region:region", "command:order", "student:unit", 0)); random_source_inject_constant(0.0); @@ -253,7 +253,7 @@ static void test_academy_building(CuTest *tc) { void test_learn_skill_single(CuTest *tc) { unit *u; skill *sv; - test_cleanup(); + test_setup(); config_set("study.random_progress", "0"); u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); learn_skill(u, SK_ALCHEMY, STUDYDAYS); @@ -272,7 +272,7 @@ void test_learn_skill_single(CuTest *tc) { void test_learn_skill_multi(CuTest *tc) { unit *u; skill *sv; - test_cleanup(); + test_setup(); config_set("study.random_progress", "0"); u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); scale_number(u, 10); @@ -292,7 +292,7 @@ void test_learn_skill_multi(CuTest *tc) { static void test_demon_skillchanges(CuTest *tc) { unit * u; race * rc; - test_cleanup(); + test_setup(); rc = test_create_race("demon"); CuAssertPtrEquals(tc, rc, get_race(RC_DAEMON)); u = test_create_unit(test_create_faction(rc), 0); @@ -305,7 +305,7 @@ static void test_demon_skillchanges(CuTest *tc) { static void test_study_cmd(CuTest *tc) { unit *u; - test_cleanup(); + test_setup(); init_resources(); u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); u->thisorder = create_order(K_STUDY, u->faction->locale, "CROSSBOW"); @@ -321,7 +321,7 @@ static void test_study_cmd(CuTest *tc) { static void test_study_cost(CuTest *tc) { unit *u; const struct item_type *itype; - test_cleanup(); + test_setup(); init_resources(); itype = get_resourcetype(R_SILVER)->itype; u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); @@ -340,7 +340,7 @@ static void test_study_cost(CuTest *tc) { static void test_teach_cmd(CuTest *tc) { unit *u, *ut; - test_cleanup(); + test_setup(); init_resources(); u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); scale_number(u, 10); @@ -360,7 +360,7 @@ static void test_teach_cmd(CuTest *tc) { static void test_teach_two(CuTest *tc) { unit *u1, *u2, *ut; - test_cleanup(); + test_setup(); init_resources(); u1 = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); scale_number(u1, 5); @@ -390,7 +390,7 @@ static void test_teach_two_skills(CuTest *tc) { faction *f; region *r; - test_cleanup(); + test_setup(); init_resources(); f = test_create_faction(0); r = test_create_region(0, 0, 0); @@ -420,7 +420,7 @@ static void test_teach_two_skills(CuTest *tc) { static void test_teach_one_to_many(CuTest *tc) { unit *u, *ut; - test_cleanup(); + test_setup(); init_resources(); u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); scale_number(u, 20); @@ -440,7 +440,7 @@ static void test_teach_one_to_many(CuTest *tc) { static void test_teach_many_to_one(CuTest *tc) { unit *u, *u1, *u2; - test_cleanup(); + test_setup(); init_resources(); u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); scale_number(u, 20); @@ -467,7 +467,7 @@ static void test_teach_many_to_many(CuTest *tc) { region *r; faction *f; - test_cleanup(); + test_setup(); init_resources(); f = test_create_faction(0); r = test_create_region(0, 0, 0); diff --git a/src/tests.c b/src/tests.c index 5d359813d..54779c450 100644 --- a/src/tests.c +++ b/src/tests.c @@ -133,7 +133,12 @@ void test_log_stderr(int flags) { stderrlog = log_to_file(flags, stderr); } else { - log_destroy(stderrlog); + if (stderrlog) { + log_destroy(stderrlog); + } + else { + log_warning("stderr logging is inactive. did you call test_cleanup twice?"); + } stderrlog = 0; } diff --git a/src/triggers/shock.test.c b/src/triggers/shock.test.c index 77bc192dc..058dfaae3 100644 --- a/src/triggers/shock.test.c +++ b/src/triggers/shock.test.c @@ -12,8 +12,8 @@ static void test_shock(CuTest *tc) { unit *u; trigger *tt; - test_cleanup(); + test_setup(); u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); create_mage(u, M_GRAY); set_level(u, SK_MAGIC, 5); @@ -32,8 +32,8 @@ static void test_shock(CuTest *tc) { static void test_shock_low(CuTest *tc) { unit *u; trigger *tt; - test_cleanup(); + test_setup(); u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); create_mage(u, M_GRAY); set_level(u, SK_MAGIC, 5); diff --git a/src/upkeep.test.c b/src/upkeep.test.c index bba43a95f..1013314aa 100644 --- a/src/upkeep.test.c +++ b/src/upkeep.test.c @@ -19,7 +19,7 @@ void test_upkeep_default(CuTest * tc) faction *f1, *f2; const item_type *i_silver; - test_cleanup(); + test_setup(); test_create_world(); i_silver = it_find("money"); @@ -50,7 +50,7 @@ void test_upkeep_hunger_damage(CuTest * tc) faction *f1; const item_type *i_silver; - test_cleanup(); + test_setup(); test_create_world(); i_silver = it_find("money"); @@ -75,7 +75,7 @@ void test_upkeep_from_pool(CuTest * tc) unit *u1, *u2; const item_type *i_silver; - test_cleanup(); + test_setup(); test_create_world(); i_silver = it_find("money"); @@ -108,7 +108,7 @@ void test_upkeep_from_friend(CuTest * tc) faction *f1, *f2; const item_type *i_silver; - test_cleanup(); + test_setup(); test_create_world(); i_silver = it_find("money"); @@ -142,7 +142,7 @@ void test_upkeep_free(CuTest * tc) unit *u; const item_type *i_silver; - test_cleanup(); + test_setup(); test_create_world(); i_silver = it_find("money"); diff --git a/src/vortex.test.c b/src/vortex.test.c index 78a04535f..21ea6596c 100644 --- a/src/vortex.test.c +++ b/src/vortex.test.c @@ -22,7 +22,7 @@ static void test_move_to_vortex(CuTest *tc) { unit *u; struct locale *lang; - test_cleanup(); + test_setup(); lang = get_or_create_locale("en"); locale_setstring(lang, "vortex", "wirbel"); init_locale(lang); diff --git a/src/wormhole.test.c b/src/wormhole.test.c index 03bf14ab9..ec93c5b4c 100644 --- a/src/wormhole.test.c +++ b/src/wormhole.test.c @@ -22,7 +22,7 @@ static void test_make_wormholes(CuTest *tc) { terrain_type *t_plain; building_type *btype; - test_cleanup(); + test_setup(); t_plain = test_create_terrain("plain", LAND_REGION); btype = test_create_buildingtype("wormhole"); match[0] = r1 = test_create_region(0, 0, t_plain); @@ -44,7 +44,7 @@ static void test_sort_wormhole_regions(CuTest *tc) { terrain_type *t_plain; quicklist *rlist = 0; - test_cleanup(); + test_setup(); t_plain = test_create_terrain("plain", LAND_REGION); r1 = test_create_region(0, 0, t_plain); r2 = test_create_region(1, 0, t_plain); From 2c5063095df02b6918cb0d67bfe5ff8685ab1362 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 29 Aug 2016 14:49:31 +0100 Subject: [PATCH 36/58] fixed: tests that try to create duplicate spells do not spam stderr. --- src/battle.c | 1 + src/kernel/spell.c | 2 +- src/kernel/spell.test.c | 31 +++++++++++++++++++++++++++---- src/reports.c | 20 -------------------- src/reports.h | 9 +-------- src/reports.test.c | 1 + src/util/lists.c | 19 +++++++++++++++++++ src/util/lists.h | 7 +++++++ src/util/strings.c | 1 + 9 files changed, 58 insertions(+), 33 deletions(-) diff --git a/src/battle.c b/src/battle.c index a35026983..0d893cbc9 100644 --- a/src/battle.c +++ b/src/battle.c @@ -61,6 +61,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include +#include #include #include #include diff --git a/src/kernel/spell.c b/src/kernel/spell.c index ec651bd79..8e14ec2c0 100644 --- a/src/kernel/spell.c +++ b/src/kernel/spell.c @@ -71,7 +71,7 @@ spell * create_spell(const char * name, unsigned int id) assert(len + sizeof(sp) < sizeof(buffer)); if (cb_find_str(&cb_spells, name)) { - log_error("create_spell: duplicate name '%s'\n", name); + log_error("create_spell: duplicate name '%s'", name); return 0; } sp = (spell *)calloc(1, sizeof(spell)); diff --git a/src/kernel/spell.test.c b/src/kernel/spell.test.c index db167adce..64ab5c0cb 100644 --- a/src/kernel/spell.test.c +++ b/src/kernel/spell.test.c @@ -1,9 +1,11 @@ #include -#include #include -#include +#include +#include + +#include #include #include @@ -23,17 +25,30 @@ static void test_create_a_spell(CuTest * tc) test_cleanup(); } +static void log_list(void *udata, int flags, const char *module, const char *format, va_list args) { + strlist **slp = (strlist **)udata; + addstrlist(slp, format); +} + static void test_create_duplicate_spell(CuTest * tc) { spell *sp; - /* FIXME: this test emits ERROR messages (duplicate spells), inject a logger to verify that */ + struct log_t *log; + strlist *sl = 0; test_setup(); test_log_stderr(0); + log = log_create(LOG_CPERROR, &sl, log_list); + CuAssertPtrEquals(tc, 0, find_spell("testspell")); sp = create_spell("testspell", 0); CuAssertPtrEquals(tc, 0, create_spell("testspell", 0)); + CuAssertPtrNotNull(tc, sl); + CuAssertStrEquals(tc, "create_spell: duplicate name '%s'", sl->s); + CuAssertPtrEquals(tc, 0, sl->next); + freestrlist(sl); + log_destroy(log); CuAssertPtrEquals(tc, sp, find_spell("testspell")); test_cleanup(); } @@ -41,14 +56,22 @@ static void test_create_duplicate_spell(CuTest * tc) static void test_create_spell_with_id(CuTest * tc) { spell *sp; - /* FIXME: this test emits ERROR messages (duplicate spells), inject a logger to verify that */ + struct log_t *log; + strlist *sl = 0; test_setup(); test_log_stderr(0); + log = log_create(LOG_CPERROR, &sl, log_list); + CuAssertPtrEquals(tc, 0, find_spellbyid(42)); sp = create_spell("testspell", 42); CuAssertPtrEquals(tc, sp, find_spellbyid(42)); CuAssertPtrEquals(tc, 0, create_spell("testspell", 47)); + CuAssertPtrNotNull(tc, sl); + CuAssertStrEquals(tc, "create_spell: duplicate name '%s'", sl->s); + CuAssertPtrEquals(tc, 0, sl->next); + freestrlist(sl); + log_destroy(log); CuAssertPtrEquals(tc, 0, find_spellbyid(47)); test_cleanup(); } diff --git a/src/reports.c b/src/reports.c index 8dfd055c4..ce17b9ad2 100644 --- a/src/reports.c +++ b/src/reports.c @@ -2176,26 +2176,6 @@ static void eval_int36(struct opstack **stack, const void *userdata) /*** END MESSAGE RENDERING ***/ -/* - String Listen --------------------------------------------- */ -void addstrlist(strlist ** SP, const char *s) -{ - strlist *slist = malloc(sizeof(strlist)); - slist->next = NULL; - slist->s = _strdup(s); - addlist(SP, slist); -} - -void freestrlist(strlist * s) -{ - strlist *q, *p = s; - while (p) { - q = p->next; - free(p->s); - free(p); - p = q; - } -} - #include static void log_orders(const struct message *msg) diff --git a/src/reports.h b/src/reports.h index 2c71803c3..044e65042 100644 --- a/src/reports.h +++ b/src/reports.h @@ -121,14 +121,7 @@ extern "C" { size_t f_regionid(const struct region *r, const struct faction *f, char *buffer, size_t size); - typedef struct strlist { - struct strlist *next; - char *s; - } strlist; - - void addstrlist(strlist ** SP, const char *s); - void freestrlist(strlist * s); - void split_paragraph(strlist ** SP, const char *s, unsigned int indent, unsigned int width, char mark); + void split_paragraph(struct strlist ** SP, const char *s, unsigned int indent, unsigned int width, char mark); int stream_printf(struct stream * out, const char *format, ...); diff --git a/src/reports.test.c b/src/reports.test.c index ebfe794cb..6e636b542 100644 --- a/src/reports.test.c +++ b/src/reports.test.c @@ -18,6 +18,7 @@ #include #include +#include #include #include diff --git a/src/util/lists.c b/src/util/lists.c index 36cd0f066..0f92eceb7 100644 --- a/src/util/lists.c +++ b/src/util/lists.c @@ -121,3 +121,22 @@ unsigned int listlen(void *l) for (p = (void_list *)l, i = 0; p; p = p->next, i++); return i; } +/* - String Listen --------------------------------------------- */ +void addstrlist(strlist ** SP, const char *s) +{ + strlist *slist = malloc(sizeof(strlist)); + slist->next = NULL; + slist->s = _strdup(s); + addlist(SP, slist); +} + +void freestrlist(strlist * s) +{ + strlist *q, *p = s; + while (p) { + q = p->next; + free(p->s); + free(p); + p = q; + } +} diff --git a/src/util/lists.h b/src/util/lists.h index a9efab218..8b9b093df 100644 --- a/src/util/lists.h +++ b/src/util/lists.h @@ -24,6 +24,13 @@ extern "C" { #include + typedef struct strlist { + struct strlist *next; + char *s; + } strlist; + + void addstrlist(strlist ** SP, const char *s); + void freestrlist(strlist * s); void addlist(void *l1, void *p1); void translist(void *l1, void *l2, void *p); #ifndef MALLOCDBG diff --git a/src/util/strings.c b/src/util/strings.c index 5c8a7ba71..4e7e17aa4 100644 --- a/src/util/strings.c +++ b/src/util/strings.c @@ -18,6 +18,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include +#include "strings.h" #include "assert.h" /* libc includes */ From fb2b6495e59e8c055893d93643769861e31f8b24 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 29 Aug 2016 15:19:17 +0100 Subject: [PATCH 37/58] promote spell.test error logging to a tests.c API, use it for item.test --- src/kernel/item.c | 2 +- src/kernel/item.test.c | 24 ++++++++++++++++++------ src/kernel/spell.test.c | 17 +++++------------ src/tests.c | 15 +++++++++++++++ src/tests.h | 4 ++++ 5 files changed, 43 insertions(+), 19 deletions(-) diff --git a/src/kernel/item.c b/src/kernel/item.c index 182e71fbe..9816258c2 100644 --- a/src/kernel/item.c +++ b/src/kernel/item.c @@ -491,7 +491,7 @@ item *i_change(item ** pi, const item_type * itype, int delta) item *i = *pi; i->number += delta; if (i->number < 0) { - log_error("serious accounting error. number of items is %d.\n", i->number); + log_error("serious accounting error. number of items is %d.", i->number); i->number = 0; } if (i->number == 0) { diff --git a/src/kernel/item.test.c b/src/kernel/item.test.c index 1c133b74f..47b32b537 100644 --- a/src/kernel/item.test.c +++ b/src/kernel/item.test.c @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include #include @@ -45,8 +47,11 @@ static void test_resourcename_with_appearance(CuTest *tc) { static void test_uchange(CuTest * tc, unit * u, const resource_type * rtype) { int n; + struct log_t *log; + strlist *sl = 0; assert(rtype); + log = test_log_start(LOG_CPERROR, &sl); change_resource(u, rtype, 4); n = get_resource(u, rtype); CuAssertPtrNotNull(tc, rtype->uchange); @@ -54,25 +59,31 @@ static void test_uchange(CuTest * tc, unit * u, const resource_type * rtype) { CuAssertIntEquals(tc, n - 3, rtype->uchange(u, rtype, -3)); CuAssertIntEquals(tc, n - 3, get_resource(u, rtype)); CuAssertIntEquals(tc, 0, rtype->uchange(u, rtype, -n)); + CuAssertPtrNotNull(tc, sl); + CuAssertStrEquals(tc, "serious accounting error. number of items is %d.", sl->s); + CuAssertPtrEquals(tc, 0, sl->next); + test_log_stop(log, sl); } void test_change_item(CuTest * tc) { unit * u; - test_cleanup(); + test_setup(); + test_log_stderr(0); test_create_itemtype("iron"); init_resources(); u = test_create_unit(test_create_faction(0), 0); test_uchange(tc, u, get_resourcetype(R_IRON)); + test_cleanup(); } void test_resource_type(CuTest * tc) { struct item_type *itype; - test_cleanup(); + test_setup(); CuAssertPtrEquals(tc, 0, rt_find("herpderp")); @@ -89,7 +100,7 @@ void test_finditemtype(CuTest * tc) const item_type *itype; struct locale * lang; - test_cleanup(); + test_setup(); lang = get_or_create_locale("de"); locale_setstring(lang, "horse", "Pferd"); @@ -103,7 +114,7 @@ void test_findresourcetype(CuTest * tc) const item_type *itype; struct locale * lang; - test_cleanup(); + test_setup(); lang = get_or_create_locale("de"); locale_setstring(lang, "horse", "Pferd"); @@ -124,7 +135,7 @@ static void test_fix_demand(CuTest *tc) { terrain_type *tplain; item_type *ltype; - test_cleanup(); + test_setup(); ltype = test_create_itemtype("balm"); ltype->rtype->flags |= (RTF_ITEM | RTF_POOLED); new_luxurytype(ltype, 0); @@ -145,7 +156,8 @@ static void test_fix_demand(CuTest *tc) { static void test_core_resources(CuTest *tc) { resource_type * rtype; - test_cleanup(); + + test_setup(); init_resources(); CuAssertPtrNotNull(tc, rtype = rt_find("money")); CuAssertPtrNotNull(tc, rtype->itype); diff --git a/src/kernel/spell.test.c b/src/kernel/spell.test.c index 64ab5c0cb..fa5e9527c 100644 --- a/src/kernel/spell.test.c +++ b/src/kernel/spell.test.c @@ -25,11 +25,6 @@ static void test_create_a_spell(CuTest * tc) test_cleanup(); } -static void log_list(void *udata, int flags, const char *module, const char *format, va_list args) { - strlist **slp = (strlist **)udata; - addstrlist(slp, format); -} - static void test_create_duplicate_spell(CuTest * tc) { spell *sp; @@ -38,7 +33,7 @@ static void test_create_duplicate_spell(CuTest * tc) test_setup(); test_log_stderr(0); - log = log_create(LOG_CPERROR, &sl, log_list); + log = test_log_start(LOG_CPERROR, &sl); CuAssertPtrEquals(tc, 0, find_spell("testspell")); @@ -47,9 +42,8 @@ static void test_create_duplicate_spell(CuTest * tc) CuAssertPtrNotNull(tc, sl); CuAssertStrEquals(tc, "create_spell: duplicate name '%s'", sl->s); CuAssertPtrEquals(tc, 0, sl->next); - freestrlist(sl); - log_destroy(log); CuAssertPtrEquals(tc, sp, find_spell("testspell")); + test_log_stop(log, sl); test_cleanup(); } @@ -61,18 +55,17 @@ static void test_create_spell_with_id(CuTest * tc) test_setup(); test_log_stderr(0); - log = log_create(LOG_CPERROR, &sl, log_list); + log = test_log_start(LOG_CPERROR, &sl); CuAssertPtrEquals(tc, 0, find_spellbyid(42)); sp = create_spell("testspell", 42); CuAssertPtrEquals(tc, sp, find_spellbyid(42)); CuAssertPtrEquals(tc, 0, create_spell("testspell", 47)); + CuAssertPtrEquals(tc, 0, find_spellbyid(47)); CuAssertPtrNotNull(tc, sl); CuAssertStrEquals(tc, "create_spell: duplicate name '%s'", sl->s); CuAssertPtrEquals(tc, 0, sl->next); - freestrlist(sl); - log_destroy(log); - CuAssertPtrEquals(tc, 0, find_spellbyid(47)); + test_log_stop(log, sl); test_cleanup(); } diff --git a/src/tests.c b/src/tests.c index 54779c450..13400ebd4 100644 --- a/src/tests.c +++ b/src/tests.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -123,6 +124,20 @@ struct unit *test_create_unit(struct faction *f, struct region *r) return create_unit(r, f, 1, rc ? rc : rc_get_or_create("human"), 0, 0, 0); } +static void log_list(void *udata, int flags, const char *module, const char *format, va_list args) { + strlist **slp = (strlist **)udata; + addstrlist(slp, format); +} + +struct log_t * test_log_start(int flags, strlist **slist) { + return log_create(flags, slist, log_list); +} + +void test_log_stop(struct log_t *log, struct strlist *slist) { + freestrlist(slist); + log_destroy(log); +} + void test_log_stderr(int flags) { static struct log_t *stderrlog; if (flags) { diff --git a/src/tests.h b/src/tests.h index a025c92c1..10934c3d7 100644 --- a/src/tests.h +++ b/src/tests.h @@ -26,12 +26,16 @@ extern "C" { struct spellparameter; struct spell; struct locale; + struct strlist; + struct log_t; struct CuTest; void test_setup(void); void test_cleanup(void); void test_log_stderr(int on); + struct log_t * test_log_start(int flags, struct strlist **slist); + void test_log_stop(struct log_t *log, struct strlist *slist); struct locale * test_create_locale(void); struct terrain_type * test_create_terrain(const char * name, unsigned int flags); From ef44a4534e730721ea45567e5c15c5513aa3eaea Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 29 Aug 2016 17:31:09 +0100 Subject: [PATCH 38/58] add a test for copying resources message arguments. my plan is to add a new argument type for arrays of resources with fewer allocations. --- res/core/messages.xml | 4 ++-- src/kernel/save.c | 4 ++-- src/magic.c | 1 + src/reports.c | 9 +++++---- src/reports.test.c | 36 ++++++++++++++++++++++++++++++++++++ src/util/message.c | 5 +++-- src/util/message.h | 15 ++++++++------- tests/drmemory.bat | 4 ++-- 8 files changed, 59 insertions(+), 19 deletions(-) diff --git a/res/core/messages.xml b/res/core/messages.xml index 4669ab8b1..d0df6343b 100644 --- a/res/core/messages.xml +++ b/res/core/messages.xml @@ -776,7 +776,7 @@ - + "$unit($unit) in $region($region): '$order($command)' - Dafür braucht die Einheit $resources($required)." "$unit($unit) in $region($region): '$order($command)' - For this, the unit needs $resources($required)." @@ -2374,7 +2374,7 @@ - + "$unit($unit) in $region($region): '$order($command)' - Für diesen Zauber fehlen noch $resources($list)." "$unit($unit) in $region($region): '$order($command)' - Casting this spell requires an additional $resources($list)." diff --git a/src/kernel/save.c b/src/kernel/save.c index 9cfcc0f57..fb0c0eba4 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -172,9 +172,9 @@ static unit *unitorders(FILE * F, int enc, struct faction *f) if (s[0]) { if (s[0] != '@') { - char token[128]; + char token[64]; const char *stok = s; - stok = parse_token(&stok, token, 64); // FIXME: use sizeof, but parse_token overwrites the buffer + stok = parse_token(&stok, token, sizeof(token)); if (stok) { bool quit = false; diff --git a/src/magic.c b/src/magic.c index d24612e06..9960f2cb2 100644 --- a/src/magic.c +++ b/src/magic.c @@ -993,6 +993,7 @@ cancast(unit * u, const spell * sp, int level, int range, struct order * ord) itemhave = get_pooled(u, rtype, GET_DEFAULT, itemanz); if (itemhave < itemanz) { + // TODO: lots of alloc/dealloc calls here (make var_copy_resources take an array) resource *res = malloc(sizeof(resource)); res->number = itemanz - itemhave; res->type = rtype; diff --git a/src/reports.c b/src/reports.c index ce17b9ad2..a7a9f7ac0 100644 --- a/src/reports.c +++ b/src/reports.c @@ -1688,7 +1688,7 @@ static variant var_copy_items(variant x) return x; } -static variant var_copy_resources(variant x) +static variant var_copy_resource_list(variant x) { resource *rsrc; resource *rdst = NULL, **rptr = &rdst; @@ -1705,7 +1705,7 @@ static variant var_copy_resources(variant x) return x; } -static void var_free_resources(variant x) +static void var_free_resource_list(variant x) { resource *rsrc = (resource *)x.v; while (rsrc) { @@ -2250,8 +2250,9 @@ void register_reports(void) register_argtype("int", NULL, NULL, VAR_INT); register_argtype("string", var_free_string, var_copy_string, VAR_VOIDPTR); register_argtype("order", var_free_order, var_copy_order, VAR_VOIDPTR); - register_argtype("resources", var_free_resources, var_copy_resources, VAR_VOIDPTR); - register_argtype("items", var_free_resources, var_copy_items, VAR_VOIDPTR); + register_argtype("resource_list", var_free_resource_list, var_copy_resource_list, VAR_VOIDPTR); + //register_argtype("resources", var_free_resources, var_copy_resources, VAR_VOIDPTR); + register_argtype("items", var_free_resource_list, var_copy_items, VAR_VOIDPTR); register_argtype("regions", var_free_regions, NULL, VAR_VOIDPTR); msg_log_create = &log_orders; diff --git a/src/reports.test.c b/src/reports.test.c index 6e636b542..8cf8f402c 100644 --- a/src/reports.test.c +++ b/src/reports.test.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -19,6 +20,7 @@ #include #include +#include #include #include @@ -415,6 +417,39 @@ static void test_write_spell_syntax(CuTest *tc) { cleanup_spell_fixture(&spell); } +static void test_arg_resources(CuTest *tc) { + variant v1, v2; + arg_type *atype; + resource *res; + item_type *itype; + + test_setup(); + itype = test_create_itemtype("stone"); + v1.v = res = malloc(sizeof(resource)*2); + res[0].number = 10; + res[0].type = itype->rtype; + res[0].next = &res[1]; + res[1].number = 5; + res[1].type = itype->rtype; + res[1].next = NULL; + + register_reports(); + atype = find_argtype("resource_list"); + CuAssertPtrNotNull(tc, atype); + v2 = atype->copy(v1); + free(v1.v); + CuAssertPtrNotNull(tc, v2.v); + res = (resource *)v2.v; + CuAssertPtrEquals(tc, itype->rtype, (void *)res->type); + CuAssertIntEquals(tc, 10, res->number); + CuAssertPtrNotNull(tc, res = res->next); + CuAssertPtrEquals(tc, itype->rtype, (void *)res->type); + CuAssertIntEquals(tc, 5, res->number); + CuAssertPtrEquals(tc, 0, res->next); + atype->release(v2); + test_cleanup(); +} + CuSuite *get_reports_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -428,5 +463,6 @@ CuSuite *get_reports_suite(void) SUITE_ADD_TEST(suite, test_write_travelthru); SUITE_ADD_TEST(suite, test_write_unit); SUITE_ADD_TEST(suite, test_write_spell_syntax); + SUITE_ADD_TEST(suite, test_arg_resources); return suite; } diff --git a/src/util/message.c b/src/util/message.c index 073371b54..92a5b43e6 100644 --- a/src/util/message.c +++ b/src/util/message.c @@ -47,7 +47,7 @@ variant(*copy_arg) (variant), variant_type type) argtypes = atype; } -static arg_type *find_argtype(const char *name) +arg_type *find_argtype(const char *name) { arg_type *atype = argtypes; while (atype != NULL) { @@ -83,7 +83,7 @@ message_type *mt_new(const char *name, const char *args[]) mtype->pnames = NULL; mtype->types = NULL; } - if (args != NULL) + if (args != NULL) { for (i = 0; args[i]; ++i) { const char *x = args[i]; const char *spos = strchr(x, ':'); @@ -102,6 +102,7 @@ message_type *mt_new(const char *name, const char *args[]) assert(mtype->types[i]); } } + } return mtype; } diff --git a/src/util/message.h b/src/util/message.h index b76f281a8..687413605 100644 --- a/src/util/message.h +++ b/src/util/message.h @@ -46,22 +46,23 @@ extern "C" { /* mt_new("simple_sentence", "subject:string", "predicate:string", * "object:string", "lang:locale", NULL); */ - extern struct message *msg_create(const struct message_type *type, + struct message *msg_create(const struct message_type *type, variant args[]); /* msg_create(&mt_simplesentence, "enno", "eats", "chocolate", &locale_de); * parameters must be in the same order as they were for mt_new! */ - extern void msg_release(struct message *msg); - extern struct message *msg_addref(struct message *msg); + void msg_release(struct message *msg); + struct message *msg_addref(struct message *msg); - extern const char *mt_name(const struct message_type *mtype); + const char *mt_name(const struct message_type *mtype); /** message_type registry (optional): **/ - extern const struct message_type *mt_register(struct message_type *); - extern const struct message_type *mt_find(const char *); + const struct message_type *mt_register(struct message_type *); + const struct message_type *mt_find(const char *); - extern void register_argtype(const char *name, void(*free_arg) (variant), + void register_argtype(const char *name, void(*free_arg) (variant), variant(*copy_arg) (variant), variant_type); + arg_type *find_argtype(const char *name); void(*msg_log_create) (const struct message * msg); diff --git a/tests/drmemory.bat b/tests/drmemory.bat index 1d07081aa..66ca98c38 100644 --- a/tests/drmemory.bat +++ b/tests/drmemory.bat @@ -2,6 +2,6 @@ cd c:\users\enno\documents\eressea\git\tests "C:\Program Files (x86)\Dr. Memory\bin64\drmemory.exe" ..\build-vs14\eressea\Debug\eressea.exe -t184 test-turn.lua -del reports -del datum htpasswd parteien parteien.full passwd score turn +del /q reports +del /q datum htpasswd parteien parteien.full passwd score turn pause From 4bc881705659098ba1c4fb1a622038fdea469a81 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 29 Aug 2016 18:15:20 +0100 Subject: [PATCH 39/58] remove a TODO that was ill-advised. The reason that "resources" is a list is that it's built incrementally. --- res/core/messages.xml | 4 ++-- src/kernel/build.c | 1 - src/magic.c | 1 - src/reports.c | 9 ++++----- src/reports.test.c | 2 +- 5 files changed, 7 insertions(+), 10 deletions(-) diff --git a/res/core/messages.xml b/res/core/messages.xml index d0df6343b..4669ab8b1 100644 --- a/res/core/messages.xml +++ b/res/core/messages.xml @@ -776,7 +776,7 @@ - + "$unit($unit) in $region($region): '$order($command)' - Dafür braucht die Einheit $resources($required)." "$unit($unit) in $region($region): '$order($command)' - For this, the unit needs $resources($required)." @@ -2374,7 +2374,7 @@ - + "$unit($unit) in $region($region): '$order($command)' - Für diesen Zauber fehlen noch $resources($list)." "$unit($unit) in $region($region): '$order($command)' - Casting this spell requires an additional $resources($list)." diff --git a/src/kernel/build.c b/src/kernel/build.c index 5d8f955c5..a6e8ff3dc 100644 --- a/src/kernel/build.c +++ b/src/kernel/build.c @@ -640,7 +640,6 @@ message *msg_materials_required(unit * u, order * ord, if (multi <= 0 || multi == INT_MAX) multi = 1; for (c = 0; ctype && ctype->materials[c].number; ++c) { - // TODO: lots of alloc/dealloc calls here (make var_copy_resources take an array) resource *res = malloc(sizeof(resource)); res->number = multi * ctype->materials[c].number / ctype->reqsize; res->type = ctype->materials[c].rtype; diff --git a/src/magic.c b/src/magic.c index 9960f2cb2..d24612e06 100644 --- a/src/magic.c +++ b/src/magic.c @@ -993,7 +993,6 @@ cancast(unit * u, const spell * sp, int level, int range, struct order * ord) itemhave = get_pooled(u, rtype, GET_DEFAULT, itemanz); if (itemhave < itemanz) { - // TODO: lots of alloc/dealloc calls here (make var_copy_resources take an array) resource *res = malloc(sizeof(resource)); res->number = itemanz - itemhave; res->type = rtype; diff --git a/src/reports.c b/src/reports.c index a7a9f7ac0..ce17b9ad2 100644 --- a/src/reports.c +++ b/src/reports.c @@ -1688,7 +1688,7 @@ static variant var_copy_items(variant x) return x; } -static variant var_copy_resource_list(variant x) +static variant var_copy_resources(variant x) { resource *rsrc; resource *rdst = NULL, **rptr = &rdst; @@ -1705,7 +1705,7 @@ static variant var_copy_resource_list(variant x) return x; } -static void var_free_resource_list(variant x) +static void var_free_resources(variant x) { resource *rsrc = (resource *)x.v; while (rsrc) { @@ -2250,9 +2250,8 @@ void register_reports(void) register_argtype("int", NULL, NULL, VAR_INT); register_argtype("string", var_free_string, var_copy_string, VAR_VOIDPTR); register_argtype("order", var_free_order, var_copy_order, VAR_VOIDPTR); - register_argtype("resource_list", var_free_resource_list, var_copy_resource_list, VAR_VOIDPTR); - //register_argtype("resources", var_free_resources, var_copy_resources, VAR_VOIDPTR); - register_argtype("items", var_free_resource_list, var_copy_items, VAR_VOIDPTR); + register_argtype("resources", var_free_resources, var_copy_resources, VAR_VOIDPTR); + register_argtype("items", var_free_resources, var_copy_items, VAR_VOIDPTR); register_argtype("regions", var_free_regions, NULL, VAR_VOIDPTR); msg_log_create = &log_orders; diff --git a/src/reports.test.c b/src/reports.test.c index 8cf8f402c..f368e63e1 100644 --- a/src/reports.test.c +++ b/src/reports.test.c @@ -434,7 +434,7 @@ static void test_arg_resources(CuTest *tc) { res[1].next = NULL; register_reports(); - atype = find_argtype("resource_list"); + atype = find_argtype("resources"); CuAssertPtrNotNull(tc, atype); v2 = atype->copy(v1); free(v1.v); From 5a73fc80d8992f04c48fb7b53ad1084faac57595 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 29 Aug 2016 18:20:36 +0100 Subject: [PATCH 40/58] telepath_see is a planned, but never realized, feature. delete it. --- src/reports.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/reports.c b/src/reports.c index ce17b9ad2..d27f2ad70 100644 --- a/src/reports.c +++ b/src/reports.c @@ -455,7 +455,6 @@ size_t size) const char *pzTmp, *str; building *b; bool isbattle = (bool)(mode == see_battle); - int telepath_see = 0; item *itm; item *show; faction *fv = visible_faction(f, u); @@ -553,7 +552,7 @@ size_t size) } /* status */ - if (u->number && (u->faction == f || telepath_see || isbattle)) { + if (u->number && (u->faction == f || isbattle)) { const char *c = hp_status(u); c = c ? LOC(f->locale, c) : 0; bufp = STRLCPY(bufp, ", ", size); @@ -586,7 +585,7 @@ size_t size) } dh = 0; - if (u->faction == f || telepath_see) { + if (u->faction == f) { skill *sv; for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) { size_t bytes = spskill(bufp, size, f->locale, u, sv, &dh, 1); @@ -597,7 +596,7 @@ size_t size) } dh = 0; - if (f == u->faction || telepath_see || omniscient(f)) { + if (f == u->faction || omniscient(f)) { show = u->items; } else if (!itemcloak && mode >= see_unit) { @@ -634,7 +633,7 @@ size_t size) } } - if (u->faction == f || telepath_see) { + if (u->faction == f) { spellbook *book = unit_get_spellbook(u); if (book) { @@ -761,11 +760,6 @@ size_t size) return dh; } -/* TODO: telepath_see wird nicht berücksichtigt: Parteien mit - * telepath_see sollten immer einzelne Einheiten zu sehen - * bekommen, alles andere ist darstellungsteschnisch kompliziert. - */ - size_t spskill(char *buffer, size_t size, const struct locale * lang, const struct unit * u, struct skill * sv, int *dh, int days) From 40d9ebfa943b59981db007e06fb8abcfe4f1b1e3 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 29 Aug 2016 19:37:47 +0100 Subject: [PATCH 41/58] reduce code duplication: itemcloak code was copied between NR and CR. --- src/creport.c | 30 ++++++++--------------------- src/kernel/config.c | 17 +++++------------ src/reports.c | 40 ++++++++++++++++++--------------------- src/reports.h | 2 +- src/spells/combatspells.c | 8 +------- 5 files changed, 33 insertions(+), 64 deletions(-) diff --git a/src/creport.c b/src/creport.c index 6ba9f5e39..39ecd9c2b 100644 --- a/src/creport.c +++ b/src/creport.c @@ -742,13 +742,10 @@ void cr_output_unit(stream *out, const region * r, const faction * f, const char *str; const item_type *lasttype; int pr; - item *itm, *show; + item *itm, *show = NULL; building *b; const char *pzTmp; skill *sv; - bool itemcloak = false; - static const curse_type *itemcloak_ct = 0; - static bool init = false; item result[MAX_INVENTORY]; const faction *sf; const char *prefix; @@ -758,15 +755,6 @@ void cr_output_unit(stream *out, const region * r, const faction * f, if (fval(u_race(u), RCF_INVISIBLE)) return; - if (!init) { - init = true; - itemcloak_ct = ct_find("itemcloak"); - } - if (itemcloak_ct != NULL) { - curse * cu = get_curse(u->attribs, itemcloak_ct); - itemcloak = cu && curse_active(cu); - } - stream_printf(out, "EINHEIT %d\n", u->no); stream_printf(out, "\"%s\";Name\n", unit_getname(u)); str = u_description(u, f->locale); @@ -970,16 +958,14 @@ void cr_output_unit(stream *out, const region * r, const faction * f, if (f == u->faction || omniscient(f)) { show = u->items; } - else if (!itemcloak && mode >= see_unit) { - int n = report_items(u->items, result, MAX_INVENTORY, u, f); - assert(n >= 0); - if (n > 0) - show = result; - else - show = NULL; - } else { - show = NULL; + if (mode >= see_unit) { + int n = report_items(u, result, MAX_INVENTORY, u, f); + assert(n >= 0); + if (n > 0) { + show = result; + } + } } lasttype = NULL; for (itm = show; itm; itm = itm->next) { diff --git a/src/kernel/config.c b/src/kernel/config.c index cda449a23..feaf76aa8 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -897,18 +897,10 @@ default_wage(const region * r, const faction * f, const race * rc, int in_turn) { building *b = largestbuilding(r, &cmp_wage, false); int esize = 0; - curse *c; double wage; attrib *a; const building_type *artsculpture_type = bt_find("artsculpture"); - static const curse_type *drought_ct, *blessedharvest_ct; - static bool init; - - if (!init) { - init = true; - drought_ct = ct_find("drought"); - blessedharvest_ct = ct_find("blessedharvest"); - } + const struct curse_type *ctype; if (b != NULL) { /* TODO: this reveals imaginary castles */ @@ -937,7 +929,7 @@ default_wage(const region * r, const faction * f, const race * rc, int in_turn) } if (rule_blessed_harvest() == HARVEST_WORK) { /* E1 rules */ - wage += curse_geteffect(get_curse(r->attribs, blessedharvest_ct)); + wage += curse_geteffect(get_curse(r->attribs, ct_find("blessedharvest"))); } } @@ -954,8 +946,9 @@ default_wage(const region * r, const faction * f, const race * rc, int in_turn) } /* Bei einer Dürre verdient man nur noch ein Viertel */ - if (drought_ct) { - c = get_curse(r->attribs, drought_ct); + ctype = ct_find("drought"); + if (ctype) { + curse *c = get_curse(r->attribs, ctype); if (curse_active(c)) wage /= curse_geteffect(c); } diff --git a/src/reports.c b/src/reports.c index d27f2ad70..7173bcf3f 100644 --- a/src/reports.c +++ b/src/reports.c @@ -265,16 +265,24 @@ static size_t buforder(char *buffer, size_t size, const order * ord, int mode) * \param viewer: the faction looking at the items */ int -report_items(const item * items, item * result, int size, const unit * owner, -const faction * viewer) +report_items(const unit *u, item * result, int size, const unit * owner, + const faction * viewer) { - const item *itm; + const item *itm, *items = u->items; int n = 0; /* number of results */ + bool itemcloak = false; + const curse_type *itemcloak_ct = ct_find("itemcloak"); - assert(owner == NULL || viewer != owner->faction - || !"not required for owner=viewer!"); + assert(owner == NULL || viewer != owner->faction); assert(size); + if (itemcloak_ct) { + curse * cu = get_curse(u->attribs, itemcloak_ct); + itemcloak = cu && curse_active(cu); + } + if (itemcloak) { + return 0; + } for (itm = items; itm; itm = itm->next) { item *ishow; const char *ic; @@ -455,20 +463,12 @@ size_t size) const char *pzTmp, *str; building *b; bool isbattle = (bool)(mode == see_battle); - item *itm; - item *show; + item *itm, *show = NULL; faction *fv = visible_faction(f, u); char *bufp = buf; - bool itemcloak = false; - const curse_type *itemcloak_ct = 0; int result = 0; item results[MAX_INVENTORY]; - itemcloak_ct = ct_find("itemcloak"); - if (itemcloak_ct) { - itemcloak = curse_active(get_curse(u->attribs, itemcloak_ct)); - } - bufp = STRLCPY(bufp, unitname(u), size); if (!isbattle) { @@ -599,16 +599,12 @@ size_t size) if (f == u->faction || omniscient(f)) { show = u->items; } - else if (!itemcloak && mode >= see_unit) { - int n = report_items(u->items, results, MAX_INVENTORY, u, f); + else if (mode >= see_unit) { + int n = report_items(u, results, MAX_INVENTORY, u, f); assert(n >= 0); - if (n > 0) + if (n > 0) { show = results; - else - show = NULL; - } - else { - show = NULL; + } } for (itm = show; itm; itm = itm->next) { const char *ic; diff --git a/src/reports.h b/src/reports.h index 044e65042..be99fbba7 100644 --- a/src/reports.h +++ b/src/reports.h @@ -107,7 +107,7 @@ extern "C" { void view_neighbours(struct seen_region **seen, struct region * r, struct faction * f); int report_resources(const struct seen_region *sr, struct resource_report *result, int size, const struct faction *viewer); - int report_items(const struct item *items, struct item *result, int size, + int report_items(const struct unit *u, struct item *result, int size, const struct unit *owner, const struct faction *viewer); void report_item(const struct unit *owner, const struct item *i, const struct faction *viewer, const char **name, const char **basename, diff --git a/src/spells/combatspells.c b/src/spells/combatspells.c index 0ee3755b3..bcbbb1b52 100644 --- a/src/spells/combatspells.c +++ b/src/spells/combatspells.c @@ -959,13 +959,7 @@ int sp_strong_wall(struct castorder * co) unit *mage = fi->unit; building *burg; double effect; - static bool init = false; message *msg; - static const curse_type *strongwall_ct; - if (!init) { - init = true; - strongwall_ct = ct_find("strongwall"); - } if (!mage->building) { return 0; @@ -973,7 +967,7 @@ int sp_strong_wall(struct castorder * co) burg = mage->building; effect = power / 4; - create_curse(mage, &burg->attribs, strongwall_ct, power, 1, effect, 0); + create_curse(mage, &burg->attribs, ct_find("strongwall"), power, 1, effect, 0); msg = msg_message("sp_strongwalls_effect", "mage building", mage, mage->building); From 8ff26eb0e4ba755a2033625a2f879608eac47d85 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 29 Aug 2016 19:41:21 +0100 Subject: [PATCH 42/58] optimization: no need to look for a curse if unit has no attribs. --- src/move.c | 19 ++++++++----------- src/reports.c | 16 ++++++++-------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/move.c b/src/move.c index 156c3c5d2..3cc93855d 100644 --- a/src/move.c +++ b/src/move.c @@ -1463,8 +1463,6 @@ static void make_route(unit * u, order * ord, region_list ** routep) static int movement_speed(unit * u) { int mp = BP_WALKING; - static const curse_type *speed_ct; - static bool init = false; double dk = u_race(u)->speed; assert(u->number); @@ -1482,15 +1480,14 @@ static int movement_speed(unit * u) break; } - if (!init) { - init = true; - speed_ct = ct_find("speed"); - } - if (speed_ct) { - curse *c = get_curse(u->attribs, speed_ct); - if (c != NULL) { - int men = get_cursedmen(u, c); - dk *= 1.0 + (double)men / (double)u->number; + if (u->attribs) { + const curse_type *speed_ct = ct_find("speed"); + if (speed_ct) { + curse *c = get_curse(u->attribs, speed_ct); + if (c != NULL) { + int men = get_cursedmen(u, c); + dk *= 1.0 + (double)men / (double)u->number; + } } } diff --git a/src/reports.c b/src/reports.c index 7173bcf3f..679b1be42 100644 --- a/src/reports.c +++ b/src/reports.c @@ -270,18 +270,18 @@ report_items(const unit *u, item * result, int size, const unit * owner, { const item *itm, *items = u->items; int n = 0; /* number of results */ - bool itemcloak = false; - const curse_type *itemcloak_ct = ct_find("itemcloak"); assert(owner == NULL || viewer != owner->faction); assert(size); - if (itemcloak_ct) { - curse * cu = get_curse(u->attribs, itemcloak_ct); - itemcloak = cu && curse_active(cu); - } - if (itemcloak) { - return 0; + if (u->attribs) { + const curse_type *itemcloak_ct = ct_find("itemcloak"); + if (itemcloak_ct) { + curse * cu = get_curse(u->attribs, itemcloak_ct); + if (cu && curse_active(cu)) { + return 0; + } + } } for (itm = items; itm; itm = itm->next) { item *ishow; From aa998166e4bb8e782df8fe9a4d2ea603e5f474a9 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 29 Aug 2016 19:44:43 +0100 Subject: [PATCH 43/58] optimization: the orcish curse is pretty rare, and we are spending a lot of time on processing it. remove static variables. --- src/randenc.c | 57 ++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/src/randenc.c b/src/randenc.c index bff7dacb7..85c3dd8d3 100644 --- a/src/randenc.c +++ b/src/randenc.c @@ -682,7 +682,7 @@ static void godcurse(void) } /** handles the "orcish" curse that makes units grow like old orks - * This would probably be better handled in an age-function for the curse, + * TODO: This would probably be better handled in an age-function for the curse, * but it's now being called by randomevents() */ static void orc_growth(void) @@ -691,39 +691,36 @@ static void orc_growth(void) for (r = regions; r; r = r->next) { unit *u; for (u = r->units; u; u = u->next) { - static bool init = false; - static const curse_type *ct_orcish = 0; - curse *c = 0; - if (!init) { - init = true; - ct_orcish = ct_find("orcish"); - } - if (ct_orcish) - c = get_curse(u->attribs, ct_orcish); - - if (c && !has_skill(u, SK_MAGIC) && !has_skill(u, SK_ALCHEMY) + if (u->attribs && !has_skill(u, SK_MAGIC) && !has_skill(u, SK_ALCHEMY) && !fval(u, UFL_HERO)) { - int n; - int increase = 0; - int num = get_cursedmen(u, c); - double prob = curse_geteffect(c); - const item_type * it_chastity = it_find("ao_chastity"); + const curse_type *ct_orcish = ct_find("orcish"); - if (it_chastity) { - num -= i_get(u->items, it_chastity); - } - for (n = num; n > 0; n--) { - if (chance(prob)) { - ++increase; + if (ct_orcish) { + curse *c = get_curse(u->attribs, ct_orcish); + if (c) { + int n; + int increase = 0; + int num = get_cursedmen(u, c); + double prob = curse_geteffect(c); + const item_type * it_chastity = it_find("ao_chastity"); + + if (it_chastity) { + num -= i_get(u->items, it_chastity); + } + for (n = num; n > 0; n--) { + if (chance(prob)) { + ++increase; + } + } + if (increase) { + unit *u2 = create_unit(r, u->faction, increase, u_race(u), 0, NULL, u); + transfermen(u2, u, u2->number); + + ADDMSG(&u->faction->msgs, msg_message("orcgrowth", + "unit amount race", u, increase, u_race(u))); + } } } - if (increase) { - unit *u2 = create_unit(r, u->faction, increase, u_race(u), 0, NULL, u); - transfermen(u2, u, u2->number); - - ADDMSG(&u->faction->msgs, msg_message("orcgrowth", - "unit amount race", u, increase, u_race(u))); - } } } } From b43ac6ab27cc7813814726af23e7ae67e069f65c Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 29 Aug 2016 19:46:19 +0100 Subject: [PATCH 44/58] remove static initialization code --- src/battle.c | 31 ++++++++++++++++--------------- src/kernel/ship.c | 24 ++++++++++-------------- 2 files changed, 26 insertions(+), 29 deletions(-) diff --git a/src/battle.c b/src/battle.c index 0d893cbc9..c4b5e8052 100644 --- a/src/battle.c +++ b/src/battle.c @@ -1923,28 +1923,29 @@ int skilldiff(troop at, troop dt, int dist) } if (df->building) { - static const curse_type *strongwall_ct; - strongwall_ct = ct_find("strongwall"); - if (strongwall_ct) { - curse *c = get_curse(df->building->attribs, strongwall_ct); - if (curse_active(c)) { - /* wirkt auf alle Gebäude */ - skdiff -= curse_geteffect_int(c); - is_protected = 2; + if (df->building->attribs) { + const curse_type *strongwall_ct = ct_find("strongwall"); + if (strongwall_ct) { + curse *c = get_curse(df->building->attribs, strongwall_ct); + if (curse_active(c)) { + /* wirkt auf alle Gebäude */ + skdiff -= curse_geteffect_int(c); + is_protected = 2; + } } } - if (df->building->type->protection) { int beff = df->building->type->protection(df->building, du, DEFENSE_BONUS); if (beff) { - static const curse_type *magicwalls_ct; skdiff -= beff; is_protected = 2; - magicwalls_ct = ct_find("magicwalls"); - if (magicwalls_ct - && curse_active(get_curse(df->building->attribs, magicwalls_ct))) { - /* Verdoppelt Burgenbonus */ - skdiff -= beff; + if (df->building->attribs) { + const curse_type *magicwalls_ct = ct_find("magicwalls"); + if (magicwalls_ct + && curse_active(get_curse(df->building->attribs, magicwalls_ct))) { + /* Verdoppelt Burgenbonus */ + skdiff -= beff; + } } } } diff --git a/src/kernel/ship.c b/src/kernel/ship.c index b10af5aeb..fb2fb3906 100644 --- a/src/kernel/ship.c +++ b/src/kernel/ship.c @@ -298,8 +298,6 @@ int crew_skill(const ship *sh) { int shipspeed(const ship * sh, const unit * u) { int k = sh->type->range; - static const struct curse_type *stormwind_ct, *nodrift_ct; - static bool init; attrib *a; struct curse *c; int bonus; @@ -312,19 +310,17 @@ int shipspeed(const ship * sh, const unit * u) assert(sh->type->construction); assert(sh->type->construction->improvement == NULL); /* sonst ist construction::size nicht ship_type::maxsize */ - if (!init) { - init = true; - stormwind_ct = ct_find("stormwind"); - nodrift_ct = ct_find("nodrift"); - } if (sh->size != sh->type->construction->maxsize) return 0; - if (curse_active(get_curse(sh->attribs, stormwind_ct))) - k *= 2; - if (curse_active(get_curse(sh->attribs, nodrift_ct))) - k += 1; - + if (sh->attribs) { + if (curse_active(get_curse(sh->attribs, ct_find("stormwind")))) { + k *= 2; + } + if (curse_active(get_curse(sh->attribs, ct_find("nodrift")))) { + k += 1; + } + } if (u->faction->race == u_race(u)) { /* race bonus for this faction? */ if (fval(u_race(u), RCF_SHIPSPEED)) { @@ -333,7 +329,7 @@ int shipspeed(const ship * sh, const unit * u) } bonus = ShipSpeedBonus(u); - if (bonus > 0 && sh->type->range_max>sh->type->range) { + if (bonus > 0 && sh->type->range_max > sh->type->range) { int crew = crew_skill(sh); int crew_bonus = (crew / sh->type->sumskill / 2) - 1; if (crew_bonus > 0) { @@ -358,7 +354,7 @@ int shipspeed(const ship * sh, const unit * u) c = c->nexthash; } - if (sh->damage>0) { + if (sh->damage > 0) { int size = sh->size * DAMAGE_SCALE; k *= (size - sh->damage); k = (k + size - 1) / size; From 1a1ec3f36362b013d17d5d72bbdc594247f0e4f0 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 29 Aug 2016 20:02:39 +0100 Subject: [PATCH 45/58] cleanup: remove static curse_type variables. --- src/economy.c | 9 +++------ src/laws.c | 6 ++---- src/monsters.c | 12 ++++++------ src/move.c | 42 +++++++++++++++++++++-------------------- src/spells/flyingship.c | 39 ++++++++++++++++++-------------------- 5 files changed, 51 insertions(+), 57 deletions(-) diff --git a/src/economy.c b/src/economy.c index 155a46b7e..d063e9cf4 100644 --- a/src/economy.c +++ b/src/economy.c @@ -2756,13 +2756,10 @@ expandwork(region * r, request * work_begin, request * work_end, int maxwork) jobs = rpeasants(r); } earnings = jobs * p_wage; - if (rule_blessed_harvest() == HARVEST_TAXES) { + if (r->attribs && rule_blessed_harvest() == HARVEST_TAXES) { /* E3 rules */ - static const curse_type *blessedharvest_ct; - if (!blessedharvest_ct) { - blessedharvest_ct = ct_find("blessedharvest"); - } - if (blessedharvest_ct && r->attribs) { + const curse_type *blessedharvest_ct = ct_find("blessedharvest"); + if (blessedharvest_ct) { int happy = (int)curse_geteffect(get_curse(r->attribs, blessedharvest_ct)); happy = _min(happy, jobs); diff --git a/src/laws.c b/src/laws.c index 3129bd16b..5e277176a 100755 --- a/src/laws.c +++ b/src/laws.c @@ -3487,15 +3487,13 @@ static double heal_factor(const unit * u) void monthly_healing(void) { region *r; - static const curse_type *heal_ct = NULL; - if (heal_ct == NULL) - heal_ct = ct_find("healingzone"); + const curse_type *heal_ct = ct_find("healingzone"); for (r = regions; r; r = r->next) { unit *u; double healingcurse = 0; - if (heal_ct != NULL) { + if (r->attribs && heal_ct) { /* bonus zurücksetzen */ curse *c = get_curse(r->attribs, heal_ct); if (c != NULL) { diff --git a/src/monsters.c b/src/monsters.c index 2fc2fcde3..19777364e 100644 --- a/src/monsters.c +++ b/src/monsters.c @@ -929,16 +929,16 @@ void spawn_undead(void) { region *r; faction *monsters = get_monsters(); + const curse_type *ctype = ct_find("holyground"); for (r = regions; r; r = r->next) { int unburied = deathcount(r); - static const curse_type *ctype = NULL; - - if (!ctype) - ctype = ct_find("holyground"); - if (ctype && curse_active(get_curse(r->attribs, ctype))) - continue; + if (r->attribs && ctype) { + if (curse_active(get_curse(r->attribs, ctype))) { + continue; + } + } /* Chance 0.1% * chaosfactor */ if (r->land && unburied > rpeasants(r) / 20 && rng_int() % 10000 < (100 + 100 * chaosfactor(r))) { diff --git a/src/move.c b/src/move.c index 3cc93855d..f3cc68ba1 100644 --- a/src/move.c +++ b/src/move.c @@ -496,7 +496,8 @@ static double overload(const region * r, ship * sh) if (sh->type->construction && sh->size != sh->type->construction->maxsize) { return DBL_MAX; - } else { + } + else { int n = 0, p = 0; int mcabins = sh->type->cabins; @@ -828,7 +829,7 @@ static void drifting_ships(region * r) /* Kapitän bestimmen */ captain = ship_owner(sh); if (captain && effskill(captain, SK_SAILING, r) < sh->type->cptskill) - captain = NULL; + captain = NULL; /* Kapitän da? Beschädigt? Genügend Matrosen? * Genügend leicht? Dann ist alles OK. */ @@ -843,7 +844,8 @@ static void drifting_ships(region * r) ovl = overload(r, sh); if (ovl >= overload_start()) { rnext = NULL; - } else { + } + else { /* Auswahl einer Richtung: Zuerst auf Land, dann * zufällig. Falls unmögliches Resultat: vergiß es. */ rnext = drift_target(sh); @@ -870,7 +872,8 @@ static void drifting_ships(region * r) if (ovl >= overload_start()) { damage_ship(sh, damage_overload(ovl)); msg_to_ship_inmates(sh, &firstu, &lastu, msg_message("massive_overload", "ship", sh)); - } else + } + else damage_ship(sh, damage_drift); if (sh->damage >= sh->size * DAMAGE_SCALE) { msg_to_ship_inmates(sh, &firstu, &lastu, msg_message("shipsink", "ship", sh)); @@ -1053,23 +1056,22 @@ unit *is_guarded(region * r, unit * u, unsigned int mask) bool move_blocked(const unit * u, const region * r, const region * r2) { connection *b; - curse *c; - static const curse_type *fogtrap_ct = NULL; if (r2 == NULL) return true; b = get_borders(r, r2); while (b) { - if (b->type->block && b->type->block(b, u, r)) + if (b->type->block && b->type->block(b, u, r)) { return true; + } b = b->next; } - if (fogtrap_ct == NULL) - fogtrap_ct = ct_find("fogtrap"); - c = get_curse(r->attribs, fogtrap_ct); - if (curse_active(c)) - return true; + if (r->attribs) { + const curse_type *fogtrap_ct = ct_find("fogtrap"); + curse *c = get_curse(r->attribs, fogtrap_ct); + return curse_active(c); + } return false; } @@ -1308,7 +1310,6 @@ static bool roadto(const region * r, direction_t dir) /* wenn es hier genug strassen gibt, und verbunden ist, und es dort * genug strassen gibt, dann existiert eine strasse in diese richtung */ region *r2; - static const curse_type *roads_ct = NULL; assert(r); assert(dir < MAXDIRECTIONS); @@ -1318,13 +1319,14 @@ static bool roadto(const region * r, direction_t dir) if (r == NULL || r2 == NULL) return false; - if (roads_ct == NULL) - roads_ct = ct_find("magicstreet"); - if (roads_ct != NULL) { - if (get_curse(r->attribs, roads_ct) != NULL) - return true; - if (get_curse(r2->attribs, roads_ct) != NULL) - return true; + if (r->attribs || r2->attribs) { + const curse_type *roads_ct = ct_find("magicstreet"); + if (roads_ct != NULL) { + if (get_curse(r->attribs, roads_ct) != NULL) + return true; + if (get_curse(r2->attribs, roads_ct) != NULL) + return true; + } } if (r->terrain->max_road <= 0) diff --git a/src/spells/flyingship.c b/src/spells/flyingship.c index c58ec270c..1b6b56d26 100644 --- a/src/spells/flyingship.c +++ b/src/spells/flyingship.c @@ -148,29 +148,26 @@ bool flying_ship(const ship * sh) static curse *shipcurse_flyingship(ship * sh, unit * mage, double power, int duration) { - static const curse_type *ct_flyingship = NULL; - if (!ct_flyingship) { - ct_flyingship = ct_find("flyingship"); - assert(ct_flyingship); - } - if (curse_active(get_curse(sh->attribs, ct_flyingship))) { - return NULL; - } - else if (is_cursed(sh->attribs, C_SHIP_SPEEDUP, 0)) { - return NULL; - } - else { - /* mit C_SHIP_NODRIFT haben wir kein Problem */ - curse *c = - create_curse(mage, &sh->attribs, ct_flyingship, power, duration, 0.0, 0); - if (c) { - c->data.v = sh; - if (c->duration > 0) { - sh->flags |= SF_FLYING; - } + curse *c; + const curse_type *ct_flyingship = ct_find("flyingship"); + assert(ct_flyingship); + if (sh->attribs) { + if (curse_active(get_curse(sh->attribs, ct_flyingship))) { + return NULL; + } + if (is_cursed(sh->attribs, C_SHIP_SPEEDUP, 0)) { + return NULL; } - return c; } + /* mit C_SHIP_NODRIFT haben wir kein Problem */ + c = create_curse(mage, &sh->attribs, ct_flyingship, power, duration, 0.0, 0); + if (c) { + c->data.v = sh; + if (c->duration > 0) { + sh->flags |= SF_FLYING; + } + } + return c; } int levitate_ship(ship * sh, unit * mage, double power, int duration) From f47113e9bd356850663ee66489400a78fdce219c Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 29 Aug 2016 20:31:18 +0100 Subject: [PATCH 46/58] eliminate static curse variables (gbdream & more) --- src/kernel/curse.h | 2 +- src/kernel/region.c | 21 ++++++------ src/kernel/unit.c | 78 ++++++++++++++++++++++----------------------- src/spells.c | 21 ++++++------ src/study.c | 15 ++++----- 5 files changed, 67 insertions(+), 70 deletions(-) diff --git a/src/kernel/curse.h b/src/kernel/curse.h index c78e43405..9013a1df5 100644 --- a/src/kernel/curse.h +++ b/src/kernel/curse.h @@ -304,7 +304,7 @@ extern "C" { const struct curse *c, int self); int curse_cansee(const struct curse *c, const struct faction *viewer, objtype_t typ, const void *obj, int self); #define is_cursed(a, id, id2) \ - curse_active(get_curse(a, ct_find(oldcursename(id)))) + (a && curse_active(get_curse(a, ct_find(oldcursename(id))))) #define get_curseeffect(a, id, id2) \ curse_geteffect(get_curse(a, ct_find(oldcursename(id)))) diff --git a/src/kernel/region.c b/src/kernel/region.c index 54e78ec06..b04dc6709 100644 --- a/src/kernel/region.c +++ b/src/kernel/region.c @@ -146,23 +146,24 @@ int deathcount(const region * r) void deathcounts(region * r, int fallen) { - attrib *a; - static const curse_type *ctype = NULL; + attrib *a = NULL; if (fallen == 0) return; - if (!ctype) - ctype = ct_find("holyground"); - if (ctype && curse_active(get_curse(r->attribs, ctype))) - return; - - a = a_find(r->attribs, &at_deathcount); - if (!a) + if (r->attribs) { + const curse_type *ctype = ct_find("holyground"); + if (ctype && curse_active(get_curse(r->attribs, ctype))) + return; + a = a_find(r->attribs, &at_deathcount); + } + if (!a) { a = a_add(&r->attribs, a_new(&at_deathcount)); + } a->data.i += fallen; - if (a->data.i <= 0) + if (a->data.i <= 0) { a_remove(&r->attribs, a); + } } /* Moveblock wird zur Zeit nicht über Attribute, sondern ein Bitfeld diff --git a/src/kernel/unit.c b/src/kernel/unit.c index d039560f6..349d2b260 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -863,16 +863,15 @@ bool can_survive(const unit * u, const region * r) if ((fval(r->terrain, WALK_INTO) && (u_race(u)->flags & RCF_WALK)) || (fval(r->terrain, SWIM_INTO) && (u_race(u)->flags & RCF_SWIM)) || (fval(r->terrain, FLY_INTO) && (u_race(u)->flags & RCF_FLY))) { - static const curse_type *ctype = NULL; if (has_horses(u) && !fval(r->terrain, WALK_INTO)) return false; - if (!ctype) - ctype = ct_find("holyground"); - if (fval(u_race(u), RCF_UNDEAD) && curse_active(get_curse(r->attribs, ctype))) - return false; - + if (r->attribs) { + const curse_type *ctype = ct_find("holyground"); + if (fval(u_race(u), RCF_UNDEAD) && curse_active(get_curse(r->attribs, ctype))) + return false; + } return true; } return false; @@ -1217,50 +1216,51 @@ static int item_modification(const unit * u, skill_t sk, int val) static int att_modification(const unit * u, skill_t sk) { double result = 0; - static const curse_type *skillmod_ct, *gbdream_ct, *worse_ct; - curse *c; - skillmod_ct = ct_find("skillmod"); - gbdream_ct = ct_find("gbdream"); - worse_ct = ct_find("worse"); - - c = get_curse(u->attribs, worse_ct); - if (c != NULL) - result += curse_geteffect(c); - if (skillmod_ct) { - attrib *a = a_find(u->attribs, &at_curse); - while (a && a->type == &at_curse) { - curse *c = (curse *)a->data.v; - if (c->type == skillmod_ct && c->data.i == sk) { - result += curse_geteffect(c); - break; + if (u->attribs) { + curse *c; + const curse_type *skillmod_ct = ct_find("skillmod"); + const curse_type *worse_ct = ct_find("worse"); + c = get_curse(u->attribs, worse_ct); + if (c != NULL) + result += curse_geteffect(c); + if (skillmod_ct) { + attrib *a = a_find(u->attribs, &at_curse); + while (a && a->type == &at_curse) { + curse *c = (curse *)a->data.v; + if (c->type == skillmod_ct && c->data.i == sk) { + result += curse_geteffect(c); + break; + } + a = a->next; } - a = a->next; } } - /* TODO hier kann nicht mit get/iscursed gearbeitet werden, da nur der * jeweils erste vom Typ C_GBDREAM zurueckgegen wird, wir aber alle * durchsuchen und aufaddieren muessen */ - if (gbdream_ct && u->region) { - int bonus = 0, malus = 0; - attrib *a = a_find(u->region->attribs, &at_curse); - while (a && a->type == &at_curse) { - curse *c = (curse *)a->data.v; + if (u->region && u->region->attribs) { + const curse_type *gbdream_ct = ct_find("gbdream"); + if (gbdream_ct) { + int bonus = 0, malus = 0; + attrib *a = a_find(u->region->attribs, &at_curse); + while (a && a->type == &at_curse) { + curse *c = (curse *)a->data.v; - if (curse_active(c) && c->type == gbdream_ct) { - int effect = curse_geteffect_int(c); - bool allied = alliedunit(c->magician, u->faction, HELP_GUARD); - if (allied) { - if (effect > bonus) bonus = effect; - } - else { - if (effect < malus) malus = effect; + if (curse_active(c) && c->type == gbdream_ct) { + int effect = curse_geteffect_int(c); + bool allied = alliedunit(c->magician, u->faction, HELP_GUARD); + if (allied) { + if (effect > bonus) bonus = effect; + } + else { + if (effect < malus) malus = effect; + } } + a = a->next; } - a = a->next; + result = result + bonus + malus; } - result = result + bonus + malus; } return (int)result; diff --git a/src/spells.c b/src/spells.c index 5329e85d3..88919a847 100644 --- a/src/spells.c +++ b/src/spells.c @@ -2012,7 +2012,7 @@ static int sp_treewalkexit(castorder * co) */ static int sp_holyground(castorder * co) { - static const curse_type *ctype = NULL; + const curse_type *ctype = NULL; region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; @@ -2021,9 +2021,7 @@ static int sp_holyground(castorder * co) report_spell(mage, r, msg); msg_release(msg); - if (!ctype) { - ctype = ct_find("holyground"); - } + ctype = ct_find("holyground"); create_curse(mage, &r->attribs, ctype, power * power, 1, zero_effect, 0); a_removeall(&r->attribs, &at_deathcount); @@ -3206,15 +3204,14 @@ static int sp_magicboost(castorder * co) double power = co->force; double effect; trigger *tsummon; - static const curse_type *ct_auraboost; - static const curse_type *ct_magicboost; + const curse_type *ct_auraboost; + const curse_type *ct_magicboost; + + ct_auraboost = ct_find("auraboost"); + ct_magicboost = ct_find("magicboost"); + assert(ct_auraboost != NULL); + assert(ct_magicboost != NULL); - if (!ct_auraboost) { - ct_auraboost = ct_find("auraboost"); - ct_magicboost = ct_find("magicboost"); - assert(ct_auraboost != NULL); - assert(ct_magicboost != NULL); - } /* fehler, wenn schon ein boost */ if (is_cursed(mage->attribs, C_MBOOST, 0)) { report_failure(mage, co->order); diff --git a/src/study.c b/src/study.c index f0a27606c..58cbde94a 100644 --- a/src/study.c +++ b/src/study.c @@ -277,21 +277,20 @@ teach_unit(unit * teacher, unit * student, int nteaching, skill_t sk, int teach_cmd(unit * u, struct order *ord) { - static const curse_type *gbdream_ct = NULL; plane *pl; region *r = u->region; skill_t sk_academy = NOSKILL; int teaching, i, j, count, academy = 0; - if (gbdream_ct == 0) - gbdream_ct = ct_find("gbdream"); - if (gbdream_ct) { - if (get_curse(u->region->attribs, gbdream_ct)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "gbdream_noteach", "")); - return 0; + if (u->region->attribs) { + const curse_type *gbdream_ct = ct_find("gbdream"); + if (gbdream_ct) { + if (get_curse(u->region->attribs, gbdream_ct)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "gbdream_noteach", "")); + return 0; + } } } - if ((u_race(u)->flags & RCF_NOTEACH) || fval(u, UFL_WERE)) { cmistake(u, ord, 274, MSG_EVENT); return 0; From 873e6f8086f42edfbb4fe3116d3bf7ef2b80040f Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 29 Aug 2016 20:34:30 +0100 Subject: [PATCH 47/58] remove more static curse_type variables --- src/battle.test.c | 2 +- src/kernel/unit.c | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/battle.test.c b/src/battle.test.c index f44d3985c..7228ef90e 100644 --- a/src/battle.test.c +++ b/src/battle.test.c @@ -449,7 +449,7 @@ static void test_battle_skilldiff_building(CuTest *tc) unit *ua, *ud; battle *b = NULL; building_type *btype; - static const curse_type *strongwall_ct, *magicwalls_ct; + const curse_type *strongwall_ct, *magicwalls_ct; test_cleanup(); btype = test_create_buildingtype("castle"); diff --git a/src/kernel/unit.c b/src/kernel/unit.c index 349d2b260..bb519e898 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -1662,7 +1662,6 @@ int unit_max_hp(const unit * u) { int h; double p; - static const curse_type *heal_ct = NULL; int rule_stamina = config_get_int("rules.stamina", STAMINA_AFFECTS_HP); h = u_race(u)->hitpoints; @@ -1672,9 +1671,8 @@ int unit_max_hp(const unit * u) } /* der healing curse veraendert die maximalen hp */ - if (u->region) { - if (heal_ct == NULL) - heal_ct = ct_find("healingzone"); + if (u->region && u->region->attribs) { + const curse_type *heal_ct = ct_find("healingzone"); if (heal_ct) { curse *c = get_curse(u->region->attribs, heal_ct); if (c) { From d0c1b2daa48eb0625f195b3588924999baf935e2 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 29 Aug 2016 20:36:26 +0100 Subject: [PATCH 48/58] that's all folks. no more static curse_type caches. --- src/battle.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/battle.c b/src/battle.c index c4b5e8052..3ab117c2a 100644 --- a/src/battle.c +++ b/src/battle.c @@ -3260,8 +3260,8 @@ fighter *make_fighter(battle * b, unit * u, side * s1, bool attack) /* Effekte von Sprüchen */ - { - static const curse_type *speed_ct; + if (u->attribs) { + const curse_type *speed_ct; speed_ct = ct_find("speed"); if (speed_ct) { curse *c = get_curse(u->attribs, speed_ct); From eee4fa9e919989821b8efa6307e35a699da4bbf5 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 29 Aug 2016 20:53:53 +0100 Subject: [PATCH 49/58] I am pretty sure the phoenix doesn't work. --- src/items/phoenixcompass.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/items/phoenixcompass.c b/src/items/phoenixcompass.c index 86a4f50d9..571bfa6fd 100644 --- a/src/items/phoenixcompass.c +++ b/src/items/phoenixcompass.c @@ -49,13 +49,10 @@ int amount, struct order *ord) direction_t direction; unit *u2; direction_t closest_neighbour_direction = 0; - static const race *rc_phoenix = NULL; + const race *rc_phoenix = rc_find("phoenix"); - if (rc_phoenix == NULL) { - rc_phoenix = rc_find("phoenix"); - if (rc_phoenix == NULL) - return 0; - } + if (rc_phoenix == NULL) + return 0; /* find the closest phoenix. */ From ce7eb9663a4c84cc6f5e6e1f21a14c2f3991ce9d Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 29 Aug 2016 20:56:00 +0100 Subject: [PATCH 50/58] remove dead phoenix feature. --- res/core/de/strings.xml | 25 -------- res/core/messages.xml | 21 ------ src/items/CMakeLists.txt | 1 - src/items/itemtypes.c | 2 - src/items/phoenixcompass.c | 128 ------------------------------------- src/items/phoenixcompass.h | 30 --------- 6 files changed, 207 deletions(-) delete mode 100644 src/items/phoenixcompass.c delete mode 100644 src/items/phoenixcompass.h diff --git a/res/core/de/strings.xml b/res/core/de/strings.xml index ee8a409d8..f00b14763 100644 --- a/res/core/de/strings.xml +++ b/res/core/de/strings.xml @@ -1118,14 +1118,6 @@ Trollhörner troll horns - - Feder des Phönix - feather of the phoenix - - - Federn des Phönix - feathers of the phoenix - @@ -3195,23 +3187,6 @@ young dragon - - Phönix - phoenix - - - Phönixe - phoenixes - - - Phönixen - phoenixes - - - Phönix - phoenix - - Illusion illusion diff --git a/res/core/messages.xml b/res/core/messages.xml index 4669ab8b1..c07393609 100644 --- a/res/core/messages.xml +++ b/res/core/messages.xml @@ -8090,27 +8090,6 @@ "The plank of $ship($ship) are inscribed with strange runes. ($int36($id))" - - - - - - - "$unit($unit) in $region($region): '$order($command)' - Die Kompassnadel springt wild hin und her und es lässt sich keine Richtung erkennen." - "$unit($unit) in $region($region): '$order($command)' - The needle jumps wildly and there is no specific direction recognizable." - - - - - - - - - - "$unit($unit) in $region($region): '$order($command)' - Die Kompassnadel zeigt nach $direction($dir)." - "$unit($unit) in $region($region): '$order($command)' - The needle points $direction($dir)." - - diff --git a/src/items/CMakeLists.txt b/src/items/CMakeLists.txt index 9ab324e77..0a2c581b4 100644 --- a/src/items/CMakeLists.txt +++ b/src/items/CMakeLists.txt @@ -8,7 +8,6 @@ SET(_FILES artrewards.c demonseye.c itemtypes.c -phoenixcompass.c seed.c speedsail.c weapons.c diff --git a/src/items/itemtypes.c b/src/items/itemtypes.c index 4c154efdb..ca56b1273 100644 --- a/src/items/itemtypes.c +++ b/src/items/itemtypes.c @@ -16,7 +16,6 @@ #include "xerewards.h" #include "artrewards.h" -#include "phoenixcompass.h" #include "weapons.h" #include "seed.h" @@ -26,7 +25,6 @@ void register_itemtypes(void) register_weapons(); register_xerewards(); register_artrewards(); - register_phoenixcompass(); } void init_itemtypes(void) diff --git a/src/items/phoenixcompass.c b/src/items/phoenixcompass.c deleted file mode 100644 index 571bfa6fd..000000000 --- a/src/items/phoenixcompass.c +++ /dev/null @@ -1,128 +0,0 @@ -/* -Copyright (c) 1998-2015, Enno Rehling -Katja Zedel - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -**/ - -#include -#include -#include "phoenixcompass.h" - -/* kernel includes */ -#include -#include -#include -#include -#include -#include - -/* util includes */ -#include -#include -#include - -/* libc includes */ -#include -#include -#include - -static int -use_phoenixcompass(struct unit *u, const struct item_type *itype, -int amount, struct order *ord) -{ - region *r; - unit *closest_phoenix = NULL; - int closest_phoenix_distance = INT_MAX; - bool confusion = false; - direction_t direction; - unit *u2; - direction_t closest_neighbour_direction = 0; - const race *rc_phoenix = rc_find("phoenix"); - - if (rc_phoenix == NULL) - return 0; - - /* find the closest phoenix. */ - - for (r = regions; r; r = r->next) { - for (u2 = r->units; u2; u2 = u2->next) { - if (u_race(u2) == rc_phoenix) { - if (closest_phoenix == NULL) { - closest_phoenix = u2; - closest_phoenix_distance = - distance(u->region, closest_phoenix->region); - } - else { - int dist = distance(u->region, r); - if (dist < closest_phoenix_distance) { - closest_phoenix = u2; - closest_phoenix_distance = dist; - confusion = false; - } - else if (dist == closest_phoenix_distance) { - confusion = true; - } - } - } - } - } - - /* no phoenix found at all.* if confusion == true more than one phoenix - * at the same distance was found and the device is confused */ - - if (closest_phoenix == NULL - || closest_phoenix->region == u->region || confusion) { - add_message(&u->faction->msgs, msg_message("phoenixcompass_confusion", - "unit region command", u, u->region, ord)); - return 0; - } - - /* else calculate the direction. this is tricky. we calculate the - * neighbouring region which is closest to the phoenix found. hardcoded - * for readability. */ - - for (direction = 0; direction < MAXDIRECTIONS; ++direction) { - region *neighbour; - int closest_neighbour_distance = INT_MAX; - - neighbour = r_connect(u->region, direction); - if (neighbour != NULL) { - int dist = distance(neighbour, closest_phoenix->region); - if (dist < closest_neighbour_distance) { - closest_neighbour_direction = direction; - closest_neighbour_distance = dist; - } - else if (dist == closest_neighbour_distance && rng_int() % 100 < 50) { - /* there can never be more than two neighbours with the same - * distance (except when you are standing in the same region - * as the phoenix, but that case has already been handled). - * therefore this simple solution is correct */ - closest_neighbour_direction = direction; - closest_neighbour_distance = dist; - } - } - } - - add_message(&u->faction->msgs, msg_message("phoenixcompass_success", - "unit region command dir", - u, u->region, ord, closest_neighbour_direction)); - - return 0; -} - -void register_phoenixcompass(void) -{ - register_item_use(use_phoenixcompass, "use_phoenixcompass"); -} diff --git a/src/items/phoenixcompass.h b/src/items/phoenixcompass.h deleted file mode 100644 index bc194959d..000000000 --- a/src/items/phoenixcompass.h +++ /dev/null @@ -1,30 +0,0 @@ -/* -Copyright (c) 1998-2015, Enno Rehling -Katja Zedel - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -**/ - -#ifndef H_ITM_PHOENIXCOMPASS -#define H_ITM_PHOENIXCOMPASS -#ifdef __cplusplus -extern "C" { -#endif - - extern void register_phoenixcompass(void); - -#ifdef __cplusplus -} -#endif -#endif From 257d5c18bbd891e1149c629dac3c98750d0b7b53 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 30 Aug 2016 07:39:57 +0100 Subject: [PATCH 51/58] remove unused FASTER_SKILLMOD optimization --- src/kernel/skills.c | 39 --------------------------------------- 1 file changed, 39 deletions(-) diff --git a/src/kernel/skills.c b/src/kernel/skills.c index 171d42dd0..caae7b836 100644 --- a/src/kernel/skills.c +++ b/src/kernel/skills.c @@ -123,33 +123,6 @@ int skill_mod(const race * rc, skill_t sk, const struct terrain_type *terrain) return result; } -#define RCMODMAXHASH 31 -#ifdef FASTER_SKILLMOD -static struct skillmods { - struct skillmods *next; - const struct race *race; - struct modifiers { - int value[MAXSKILLS]; - } mod[MAXTERRAINS]; -} *modhash[RCMODMAXHASH]; - -static struct skillmods *init_skills(const race * rc) -{ - terrain_t t; - struct skillmods *mods = - (struct skillmods *)calloc(1, sizeof(struct skillmods)); - mods->race = rc; - - for (t = 0; t != MAXTERRAINS; ++t) { - skill_t sk; - for (sk = 0; sk != MAXSKILLS; ++sk) { - mods->mod[t].value[sk] = skill_mod(rc, sk, newterrain(t)); - } - } - return mods; -} -#endif - int rc_skillmod(const struct race *rc, const region * r, skill_t sk) { int mods = 0; @@ -157,21 +130,9 @@ int rc_skillmod(const struct race *rc, const region * r, skill_t sk) if (!skill_enabled(sk)) { return 0; } -#ifdef FASTER_SKILLMOD - unsigned int index = hashstring(rc->_name) % RCMODMAXHASH; - struct skillmods **imods = &modhash[index]; - while (*imods && (*imods)->race != rc) { - imods = &(*imods)->next; - } - if (*imods == NULL) { - *imods = init_skills(rc); - } - mods = (*imods)->mod[rterrain(r)].value[sk]; -#else if (r) { mods = skill_mod(rc, sk, r->terrain); } -#endif if (rc == get_race(RC_ELF) && r && r_isforest(r)) { if (sk == SK_PERCEPTION || sk == SK_STEALTH) { ++mods; From 2d1a13a8115fa20805d1c68af9c7413c59066525 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 30 Aug 2016 07:51:05 +0100 Subject: [PATCH 52/58] death to static caches! --- src/kernel/item.c | 6 ++---- src/kernel/unit.c | 13 +++++-------- src/upkeep.c | 27 ++++++++++++++------------- src/util/rand.c | 2 +- src/util/umlaut.c | 2 +- 5 files changed, 23 insertions(+), 27 deletions(-) diff --git a/src/kernel/item.c b/src/kernel/item.c index 9816258c2..95d7461aa 100644 --- a/src/kernel/item.c +++ b/src/kernel/item.c @@ -862,11 +862,9 @@ struct order *ord) else { const race *irace = u_irace(u); if (irace == u_race(u)) { - static const race *rcfailure; + const race *rcfailure = rc_find("smurf"); if (!rcfailure) { - rcfailure = rc_find("smurf"); - if (!rcfailure) - rcfailure = rc_find("toad"); + rcfailure = rc_find("toad"); } if (rcfailure) { trigger *trestore = trigger_changerace(u, u_race(u), irace); diff --git a/src/kernel/unit.c b/src/kernel/unit.c index bb519e898..ba58849e6 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -1389,15 +1389,12 @@ void default_name(const unit *u, char name[], int len) { const char * result; const struct locale * lang = u->faction ? u->faction->locale : default_locale; if (lang) { - static const char * prefix[MAXLOCALES]; - int i = locale_index(lang); - /*if (!prefix[i]) {*/ - prefix[i] = LOC(lang, "unitdefault"); - if (!prefix[i]) { - prefix[i] = parameters[P_UNIT]; + const char * prefix; + prefix = LOC(lang, "unitdefault"); + if (!prefix) { + prefix= parameters[P_UNIT]; } - /*}*/ - result = prefix[i]; + result = prefix; } else { result = parameters[P_UNIT]; diff --git a/src/upkeep.c b/src/upkeep.c index 5d114c74e..a9feca37a 100644 --- a/src/upkeep.c +++ b/src/upkeep.c @@ -58,27 +58,28 @@ static void help_feed(unit * donor, unit * u, int *need_p) *need_p = need; } +static const char *hunger_damage(const race *rc) { + const char * damage = get_param(rc->parameters, "hunger.damage"); + if (!damage) { + damage = config_get("hunger.damage"); + } + if (!damage) { + damage = "1d12+12"; + } + return damage; +} + static bool hunger(int number, unit * u) { region *r = u->region; int dead = 0, hpsub = 0; int hp = u->hp / u->number; - static const char *damage = 0; - static const char *rcdamage = 0; - static const race *rc = 0; + const char *damage = 0; - if (!damage) { - damage = config_get("hunger.damage"); - if (damage == NULL) - damage = "1d12+12"; - } - if (rc != u_race(u)) { - rcdamage = get_param(u_race(u)->parameters, "hunger.damage"); - rc = u_race(u); - } + damage = hunger_damage(u_race(u)); while (number--) { - int dam = dice_rand(rcdamage ? rcdamage : damage); + int dam = dice_rand(damage); if (dam >= hp) { ++dead; } diff --git a/src/util/rand.c b/src/util/rand.c index 1825340fe..73879656c 100644 --- a/src/util/rand.c +++ b/src/util/rand.c @@ -33,7 +33,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ double normalvariate(double mu, double sigma) { - static const double NV_MAGICCONST = 1.7155277699214135; /* STATIC_CONST: a constant */ + static const double NV_MAGICCONST = 1.7155277699214135; double z; for (;;) { double u1 = rng_double(); diff --git a/src/util/umlaut.c b/src/util/umlaut.c index 616596a01..9c37b852c 100644 --- a/src/util/umlaut.c +++ b/src/util/umlaut.c @@ -117,7 +117,7 @@ char * transliterate(char * out, size_t size, const char * in) void addtoken(void ** root, const char *str, variant id) { tnode * tk; - static const struct replace { /* STATIC_CONST: constant value */ + static const struct replace { ucs4_t ucs; const char str[3]; } replace[] = { From fdc91c01a00da0a9b31ec682e1844ab48fcf15bd Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 30 Aug 2016 07:56:40 +0100 Subject: [PATCH 53/58] remove some FIXME comments --- src/names.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/names.c b/src/names.c index a9386ac07..e972c8d05 100644 --- a/src/names.c +++ b/src/names.c @@ -86,7 +86,7 @@ static void make_name(unit *u, const char *monster, int *num_postfix, count_particles(monster, num_prefix, num_name, num_postfix); } if (*num_name > 0) { - char name[NAMESIZE + 1]; // FIXME: static return value + char name[NAMESIZE + 1]; char zText[32]; int uv = 0, uu = 0, un = 0; const char *str; @@ -368,7 +368,7 @@ static const char *drac_suf[DRAC_SUF] = { static void dracoid_name(unit * u) { - static char name[NAMESIZE + 1]; // FIXME: static return value + static char name[NAMESIZE + 1]; int mid_syllabels; size_t sz; From 5bb9a10a46c84635af1baea57ac804a17bca0c01 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 30 Aug 2016 09:13:59 +0100 Subject: [PATCH 54/58] is_building_type should be a quicker way to test for a building type than bt_find. --- src/kernel/building.c | 20 +++++++------------- src/kernel/building.h | 1 + src/kernel/building.test.c | 11 +++++++++++ src/kernel/config.c | 3 +-- src/lighthouse.c | 3 +-- src/reports.c | 6 ++---- 6 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/kernel/building.c b/src/kernel/building.c index 7e537c70d..ca9fbe9ce 100644 --- a/src/kernel/building.c +++ b/src/kernel/building.c @@ -158,9 +158,7 @@ const char *buildingtype(const building_type * btype, const building * b, int bs s = btype->name(btype, b, bsize); } if (b && b->attribs) { - const struct building_type *bt_generic = bt_find("generic"); - - if (btype == bt_generic) { + if (is_building_type(btype, "generic")) { const attrib *a = a_find(b->attribs, &at_building_generic_type); if (a) { s = (const char *)a->data.v; @@ -390,16 +388,9 @@ building *new_building(const struct building_type * btype, region * r, { building **bptr = &r->buildings; building *b = (building *)calloc(1, sizeof(building)); - static bool init_lighthouse = false; - static const struct building_type *bt_lighthouse = 0; const char *bname = 0; char buffer[32]; - if (!init_lighthouse) { - bt_lighthouse = bt_find("lighthouse"); - init_lighthouse = true; - } - b->no = newcontainerid(); bhash(b); @@ -409,9 +400,7 @@ building *new_building(const struct building_type * btype, region * r, bptr = &(*bptr)->next; *bptr = b; - if (b->type == bt_lighthouse) { - r->flags |= RF_LIGHTHOUSE; - } + update_lighthouse(b); if (b->type->name) { bname = LOC(lang, buildingtype(btype, b, 0)); } @@ -695,3 +684,8 @@ bool in_safe_building(unit *u1, unit *u2) { } return false; } + +bool is_building_type(const struct building_type *btype, const char *name) { + assert(btype); + return name && strcmp(btype->_name, name)==0; +} diff --git a/src/kernel/building.h b/src/kernel/building.h index 020de077b..587197276 100644 --- a/src/kernel/building.h +++ b/src/kernel/building.h @@ -163,6 +163,7 @@ extern "C" { bool buildingtype_exists(const struct region *r, const struct building_type *bt, bool working); bool building_is_active(const struct building *b); + bool is_building_type(const struct building_type *btype, const char *name); struct building *active_building(const struct unit *u, const struct building_type *btype); extern const char *buildingname(const struct building *b); diff --git a/src/kernel/building.test.c b/src/kernel/building.test.c index 1c5ff1fe2..bda3e7e90 100644 --- a/src/kernel/building.test.c +++ b/src/kernel/building.test.c @@ -480,6 +480,16 @@ static void test_safe_building(CuTest *tc) { test_cleanup(); } +static void test_building_type(CuTest *tc) { + building_type *btype; + test_setup(); + btype = test_create_buildingtype("house"); + CuAssertIntEquals(tc, true, is_building_type(btype, "house")); + CuAssertIntEquals(tc, false, is_building_type(btype, "castle")); + CuAssertIntEquals(tc, false, is_building_type(NULL, "house")); + test_cleanup(); +} + CuSuite *get_building_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -494,6 +504,7 @@ CuSuite *get_building_suite(void) SUITE_ADD_TEST(suite, test_buildingowner_goes_to_other_after_leave); SUITE_ADD_TEST(suite, test_buildingowner_goes_to_same_faction_after_leave); SUITE_ADD_TEST(suite, test_buildingowner_goes_to_empty_unit_after_leave); + SUITE_ADD_TEST(suite, test_building_type); SUITE_ADD_TEST(suite, test_active_building); SUITE_ADD_TEST(suite, test_buildingtype_exists); SUITE_ADD_TEST(suite, test_safe_building); diff --git a/src/kernel/config.c b/src/kernel/config.c index feaf76aa8..12e16719c 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -899,7 +899,6 @@ default_wage(const region * r, const faction * f, const race * rc, int in_turn) int esize = 0; double wage; attrib *a; - const building_type *artsculpture_type = bt_find("artsculpture"); const struct curse_type *ctype; if (b != NULL) { @@ -935,7 +934,7 @@ default_wage(const region * r, const faction * f, const race * rc, int in_turn) /* Artsculpture: Income +5 */ for (b = r->buildings; b; b = b->next) { - if (b->type == artsculpture_type) { + if (is_building_type(b->type, "artsculpture")) { wage += 5; } } diff --git a/src/lighthouse.c b/src/lighthouse.c index 6192db142..4230268d5 100644 --- a/src/lighthouse.c +++ b/src/lighthouse.c @@ -25,8 +25,7 @@ static attrib_type at_lighthouse = { */ void update_lighthouse(building * lh) { - const struct building_type *bt_lighthouse = bt_find("lighthouse"); - if (bt_lighthouse && lh->type == bt_lighthouse) { + if (is_building_type(lh->type, "lighthouse")) { region *r = lh->region; int d = (int)log10(lh->size) + 1; int x; diff --git a/src/reports.c b/src/reports.c index 679b1be42..e498d0f23 100644 --- a/src/reports.c +++ b/src/reports.c @@ -1754,11 +1754,9 @@ f_regionid(const region * r, const faction * f, char *buffer, size_t size) static char *f_regionid_s(const region * r, const faction * f) { - static int i = 0; - static char bufs[4][NAMESIZE + 20]; // FIXME: static return value - char *buf = bufs[(++i) % 4]; + static char buf[NAMESIZE + 20]; // FIXME: static return value - f_regionid(r, f, buf, NAMESIZE + 20); + f_regionid(r, f, buf, sizeof(buf)); return buf; } From d9e541843bc18354b5c9fa9d4b1d74223f5f7333 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 30 Aug 2016 09:19:19 +0100 Subject: [PATCH 55/58] further reduce number of bt_find calls. --- src/economy.c | 13 ++++--------- src/kernel/building.c | 1 + src/kernel/building.test.c | 1 - src/kernel/config.c | 3 +-- src/laws.c | 5 +---- src/lighthouse.c | 2 +- src/move.c | 6 +++--- src/reports.c | 5 +---- src/spells.c | 8 ++++---- 9 files changed, 16 insertions(+), 28 deletions(-) diff --git a/src/economy.c b/src/economy.c index d063e9cf4..c9d218038 100644 --- a/src/economy.c +++ b/src/economy.c @@ -1795,6 +1795,7 @@ static void expandselling(region * r, request * sellorders, int limit) unit *hafenowner; static int counter[MAXLUXURIES]; static int ncounter = 0; + const struct building_type *castle_bt; if (ncounter == 0) { const luxury_type *ltype; @@ -1810,15 +1811,15 @@ static void expandselling(region * r, request * sellorders, int limit) } /* Stelle Eigentümer der größten Burg fest. Bekommt Steuern aus jedem * Verkauf. Wenn zwei Burgen gleicher Größe bekommt gar keiner etwas. */ - + castle_bt = bt_find("castle"); for (b = rbuildings(r); b; b = b->next) { if (b->size > maxsize && building_owner(b) != NULL - && b->type == bt_find("castle")) { + && b->type == castle_bt) { maxb = b; maxsize = b->size; maxowner = building_owner(b); } - else if (b->size == maxsize && b->type == bt_find("castle")) { + else if (b->size == maxsize && b->type == castle_bt) { maxb = (building *)NULL; maxowner = (unit *)NULL; } @@ -1923,13 +1924,7 @@ static void expandselling(region * r, request * sellorders, int limit) } } if (use > 0) { -#ifdef NDEBUG use_pooled(oa[j].unit, ltype->itype->rtype, GET_DEFAULT, use); -#else - /* int i = */ use_pooled(oa[j].unit, ltype->itype->rtype, GET_DEFAULT, - use); - /* assert(i==use); */ -#endif } } free(oa); diff --git a/src/kernel/building.c b/src/kernel/building.c index ca9fbe9ce..11ab70bb1 100644 --- a/src/kernel/building.c +++ b/src/kernel/building.c @@ -446,6 +446,7 @@ void remove_building(building ** blist, building * b) /* Falls Karawanserei, Damm oder Tunnel einstürzen, wird die schon * gebaute Straße zur Hälfte vernichtet */ + // TODO: caravan, tunnel, dam modularization ? is_building_type ? if (b->type == bt_caravan || b->type == bt_dam || b->type == bt_tunnel) { region *r = b->region; int d; diff --git a/src/kernel/building.test.c b/src/kernel/building.test.c index bda3e7e90..2f6fa6e34 100644 --- a/src/kernel/building.test.c +++ b/src/kernel/building.test.c @@ -486,7 +486,6 @@ static void test_building_type(CuTest *tc) { btype = test_create_buildingtype("house"); CuAssertIntEquals(tc, true, is_building_type(btype, "house")); CuAssertIntEquals(tc, false, is_building_type(btype, "castle")); - CuAssertIntEquals(tc, false, is_building_type(NULL, "house")); test_cleanup(); } diff --git a/src/kernel/config.c b/src/kernel/config.c index 12e16719c..e3918557e 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -764,8 +764,7 @@ static const int wagetable[7][4] = { int cmp_wage(const struct building *b, const building * a) { - const struct building_type *bt_castle = bt_find("castle"); - if (b->type == bt_castle) { + if (is_building_type(b->type, "castle")) { if (!a) return 1; if (b->size > a->size) diff --git a/src/laws.c b/src/laws.c index 5e277176a..e41bafbec 100755 --- a/src/laws.c +++ b/src/laws.c @@ -3082,10 +3082,7 @@ static void age_stonecircle(building *b) { static building *age_building(building * b) { - const struct building_type *bt_blessed; - - bt_blessed = bt_find("blessedstonecircle"); - if (bt_blessed && b->type == bt_blessed) { + if (is_building_type(b->type, "blessedstonecircle")) { age_stonecircle(b); } a_age(&b->attribs, b); diff --git a/src/lighthouse.c b/src/lighthouse.c index 4230268d5..52ebc5aeb 100644 --- a/src/lighthouse.c +++ b/src/lighthouse.c @@ -110,7 +110,7 @@ bool check_leuchtturm(region * r, faction * f) a = a->next) { building *b = (building *)a->data.v; - assert(b->type == bt_find("lighthouse")); + assert(is_building_type(b->type, "lighthouse")); if (fval(b, BLD_MAINTAINED) && b->size >= 10) { int maxd = (int)log10(b->size) + 1; diff --git a/src/move.c b/src/move.c index f3cc68ba1..190589186 100644 --- a/src/move.c +++ b/src/move.c @@ -669,8 +669,7 @@ static bool is_freezing(const unit * u) int check_ship_allowed(struct ship *sh, const region * r) { int c = 0; - const building_type *bt_harbour = NULL; - bt_harbour = bt_find("harbour"); + const building_type *bt_harbour = bt_find("harbour"); if (sh->region && r_insectstalled(r)) { /* insekten dürfen nicht hier rein. haben wir welche? */ @@ -923,6 +922,7 @@ static unit *bewegung_blockiert_von(unit * reisender, region * r) int guard_count = 0; int stealth = eff_stealth(reisender, r); const struct resource_type *ramulet = get_resourcetype(R_AMULET_OF_TRUE_SEEING); + const struct building_type *castle_bt = bt_find("castle"); double base_prob = config_get_flt("rules.guard.base_stop_prob", .3); double skill_prob = config_get_flt("rules.guard.skill_stop_prob", .1); @@ -947,7 +947,7 @@ static unit *bewegung_blockiert_von(unit * reisender, region * r) double prob_u = (sk - stealth) * skill_prob; /* amulet counts at most once */ prob_u += _min(1, _min(u->number, i_get(u->items, ramulet->itype))) * amulet_prob; - if (u->building && (u->building->type == bt_find("castle")) && u == building_owner(u->building)) + if (u->building && (u->building->type == castle_bt) && u == building_owner(u->building)) prob_u += castle_prob*buildingeffsize(u->building, 0); if (prob_u >= prob) { prob = prob_u; diff --git a/src/reports.c b/src/reports.c index e498d0f23..74ba8656a 100644 --- a/src/reports.c +++ b/src/reports.c @@ -352,16 +352,13 @@ void report_building(const struct building *b, const char **name, const char **illusion) { - const struct building_type *bt_illusion; - if (name) { *name = buildingtype(b->type, b, b->size); } if (illusion) { *illusion = NULL; - bt_illusion = bt_find("illusioncastle"); - if (bt_illusion && b->type == bt_illusion) { + if (is_building_type(b->type, "illusioncastle")) { const attrib *a = a_find(b->attribs, &at_icastle); if (a != NULL) { *illusion = buildingtype(icastle_type(a), b, b->size); diff --git a/src/spells.c b/src/spells.c index 88919a847..d304dffd8 100644 --- a/src/spells.c +++ b/src/spells.c @@ -969,7 +969,7 @@ static int sp_blessstonecircle(castorder * co) b = p->param[0]->data.b; - if (b->type != bt_find("stonecircle")) { + if (!is_building_type(b->type, "stonecircle")) { ADDMSG(&mage->faction->msgs, msg_feedback(mage, co->order, "error_notstonecircle", "building", b)); return 0; @@ -2052,7 +2052,7 @@ static int sp_homestone(castorder * co) double force = co->force; double effect; message *msg; - if (!mage->building || mage->building->type != bt_find("castle")) { + if (!mage->building || !is_building_type(mage->building->type, "castle")) { cmistake(mage, co->order, 197, MSG_MAGIC); return 0; } @@ -5971,8 +5971,8 @@ int sp_movecastle(castorder * co) u = unext; } - if ((b->type == bt_find("caravan") || b->type == bt_find("dam") - || b->type == bt_find("tunnel"))) { + if ((is_building_type(b->type, "caravan") || is_building_type(b->type, "dam") + || is_building_type(b->type, "tunnel"))) { direction_t d; for (d = 0; d != MAXDIRECTIONS; ++d) { if (rroad(r, d)) { From a1d56acfe6b345a39abdcdbe65cb2b5c21407fc6 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 30 Aug 2016 20:15:28 +0100 Subject: [PATCH 56/58] missing include, I believe --- src/util/lists.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/lists.c b/src/util/lists.c index 0f92eceb7..c7a6094b2 100644 --- a/src/util/lists.c +++ b/src/util/lists.c @@ -17,6 +17,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. **/ #include +#include #include #include From afeea58999e7ccff4acc8fd08d9f164f6d454183 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 30 Aug 2016 21:22:32 +0200 Subject: [PATCH 57/58] fix include order --- src/util/lists.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/util/lists.c b/src/util/lists.c index c7a6094b2..d61327fa0 100644 --- a/src/util/lists.c +++ b/src/util/lists.c @@ -16,13 +16,13 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. **/ +#include +#include "lists.h" + #include #include #include -#include -#include "lists.h" - typedef struct void_list { struct void_list *next; void *data; From 298b3893f2c3f316ba5717843b891d5e5fe5bfe7 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 31 Aug 2016 18:18:51 +0200 Subject: [PATCH 58/58] update development version --- src/buildno.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/buildno.h b/src/buildno.h index f9749c33c..72049c497 100644 --- a/src/buildno.h +++ b/src/buildno.h @@ -1,3 +1,3 @@ #define VERSION_MAJOR 3 -#define VERSION_MINOR 9 +#define VERSION_MINOR 10 #define VERSION_BUILD 0