From 293cb78de8a84cf087a425d4045f0d6b12e25a17 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 18 Aug 2017 19:36:17 +0200 Subject: [PATCH 1/4] BUG 2356: add a failing test. --- src/kernel/curse.test.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/kernel/curse.test.c b/src/kernel/curse.test.c index 56c3288f8..a9271f897 100644 --- a/src/kernel/curse.test.c +++ b/src/kernel/curse.test.c @@ -106,7 +106,7 @@ static void test_memstream(CuTest *tc) { storage store; stream out = { 0 }; char buf[1024]; - int val=0; + int val = 0; mstream_init(&out); binstore_init(&store, &out); @@ -137,11 +137,13 @@ static void test_write_flag(CuTest *tc) { mstream_init(&data.strm); gamedata_init(&data, &store, RELEASE_VERSION); - setup_curse(&fix, "gbdream"); + setup_curse(&fix, "magicwalls"); c = fix.c; r = fix.r; uid = r->uid; - c->flags = CURSE_ISNEW; + c_setflag(c, CURSE_ISNEW); + c_setflag(c, CURSE_IMMUNE); + CuAssertIntEquals(tc, c->type->flags | CURSE_IMMUNE | CURSE_ISNEW, c_flags(c)); write_game(&data); free_gamedata(); data.strm.api->rewind(data.strm.handle); @@ -150,7 +152,7 @@ static void test_write_flag(CuTest *tc) { CuAssertPtrNotNull(tc, r); CuAssertPtrNotNull(tc, r->attribs); c = (curse *)r->attribs->data.v; - CuAssertIntEquals(tc, CURSE_ISNEW, c->flags); + CuAssertIntEquals(tc, c->type->flags | CURSE_IMMUNE | CURSE_ISNEW, c_flags(c)); mstream_done(&data.strm); gamedata_done(&data); @@ -160,7 +162,7 @@ static void test_write_flag(CuTest *tc) { static void test_curse_cache(CuTest *tc) { int cache = 0; - const curse_type ct_dummy = { "dummy", CURSETYP_NORM, 0, M_SUMEFFECT, NULL }; + const curse_type ct_dummy = { "dummy", CURSETYP_NORM, 0, M_SUMEFFECT, NULL }; test_setup(); CuAssertIntEquals(tc, true, ct_changed(&cache)); CuAssertIntEquals(tc, false, ct_changed(&cache)); From c8b2ce79002fb7a662438eaaf460e2a6685f8ea2 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 18 Aug 2017 18:42:59 +0200 Subject: [PATCH 2/4] BUG 2356: fix curse read/write rename curse::flags to curse::mask, use c_flags. fix some curse_type having CURSE_ISNEW fixed. --- src/battle.c | 5 ++--- src/battle.test.c | 8 +++++--- src/items.c | 4 ++-- src/kernel/curse.c | 25 ++++++++----------------- src/kernel/curse.h | 4 ++-- src/kernel/ship.c | 3 ++- src/kernel/ship.test.c | 2 +- src/laws.c | 5 ++--- src/spells.c | 2 +- src/spells/buildingcurse.c | 2 +- src/spells/buildingcurse.h | 3 +++ src/spells/regioncurse.c | 8 ++++---- src/spells/shipcurse.c | 4 ++-- src/spells/shipcurse.h | 2 ++ src/spells/unitcurse.c | 2 +- 15 files changed, 38 insertions(+), 41 deletions(-) diff --git a/src/battle.c b/src/battle.c index 19f30e59c..a9130f2ef 100644 --- a/src/battle.c +++ b/src/battle.c @@ -54,6 +54,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include +#include /* util includes */ #include @@ -1905,9 +1906,7 @@ int skilldiff(troop at, troop dt, int dist) skdiff -= beff; is_protected = 2; if (b->attribs) { - const curse_type *magicwalls_ct = ct_find("magicwalls"); - if (magicwalls_ct - && curse_active(get_curse(b->attribs, magicwalls_ct))) { + if (curse_active(get_curse(b->attribs, &ct_magicwalls))) { /* Verdoppelt Burgenbonus */ skdiff -= beff; } diff --git a/src/battle.test.c b/src/battle.test.c index b00d06a98..290ef6d74 100644 --- a/src/battle.test.c +++ b/src/battle.test.c @@ -11,6 +11,9 @@ #include #include #include + +#include + #include #include @@ -463,12 +466,11 @@ static void test_battle_skilldiff_building(CuTest *tc) unit *ua, *ud; battle *b = NULL; building_type *btype; - const curse_type *strongwall_ct, *magicwalls_ct; + const curse_type *strongwall_ct; test_setup(); btype = setup_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); @@ -484,7 +486,7 @@ static void test_battle_skilldiff_building(CuTest *tc) ud->building->size = 10; CuAssertIntEquals(tc, -1, skilldiff(ta, td, 0)); - create_curse(NULL, &ud->building->attribs, magicwalls_ct, 1, 1, 1, 1); + create_curse(NULL, &ud->building->attribs, &ct_magicwalls, 1, 1, 1, 1); CuAssertIntEquals(tc, -2, skilldiff(ta, td, 0)); create_curse(NULL, &ud->building->attribs, strongwall_ct, 1, 1, 2, 1); diff --git a/src/items.c b/src/items.c index 0f97ea675..37299563f 100644 --- a/src/items.c +++ b/src/items.c @@ -22,6 +22,7 @@ #include #include +#include /* triggers includes */ #include @@ -97,9 +98,8 @@ struct order *ord) } effect = SPEEDSAIL_EFFECT; - c = create_curse(u, &sh->attribs, ct_find("shipspeedup"), 20, INT_MAX, + c = create_curse(u, &sh->attribs, &ct_shipspeedup, 20, INT_MAX, effect, 0); - c_setflag(c, CURSE_NOAGE); ADDMSG(&u->faction->msgs, msg_message("use_speedsail", "unit speed", u, SPEEDSAIL_EFFECT)); diff --git a/src/kernel/curse.c b/src/kernel/curse.c index 01e77eace..5b881eb82 100644 --- a/src/kernel/curse.c +++ b/src/kernel/curse.c @@ -61,14 +61,14 @@ static curse *cursehash[MAXENTITYHASH]; void c_setflag(curse * c, unsigned int flags) { assert(c); - c->flags = (c->flags & ~flags) | (flags & (c->type->flags ^ flags)); + c->mask = (c->mask & ~flags) | (flags & (c->type->flags ^ flags)); } /* -------------------------------------------------------------------------- */ void c_clearflag(curse * c, unsigned int flags) { assert(c); - c->flags = (c->flags & ~flags) | (c->type->flags & flags); + c->mask = (c->mask & ~flags) | (c->type->flags & flags); } void chash(curse * c) @@ -180,14 +180,13 @@ int curse_read(attrib * a, void *owner, gamedata *data) int ur; char cursename[64]; int n; - int flags; float flt; assert(!c->no); READ_INT(store, &c->no); chash(c); READ_TOK(store, cursename, sizeof(cursename)); - READ_INT(store, &flags); + READ_INT(store, &c->mask); READ_INT(store, &c->duration); READ_FLT(store, &flt); c->vigour = flt; @@ -214,7 +213,6 @@ int curse_read(attrib * a, void *owner, gamedata *data) assert(result == 0); return AT_READ_FAIL; } - c->flags = flags; if (data->version < EXPLICIT_CURSE_ISNEW_VERSION) { c_clearflag(c, CURSE_ISNEW); } @@ -239,21 +237,13 @@ int curse_read(attrib * a, void *owner, gamedata *data) void curse_write(const attrib * a, const void *owner, struct storage *store) { - unsigned int flags; curse *c = (curse *)a->data.v; const curse_type *ct = c->type; unit *mage = (c->magician && c->magician->number) ? c->magician : NULL; - /* copied from c_clearflag */ -#if RELEASE_VERSION < EXPLICIT_CURSE_ISNEW_VERSION - flags = (c->flags & ~CURSE_ISNEW) | (c->type->flags & CURSE_ISNEW); -#else - flags = c->flags | c->type->flags; -#endif - WRITE_INT(store, c->no); WRITE_TOK(store, ct->cname); - WRITE_INT(store, flags); + WRITE_INT(store, c->mask); WRITE_INT(store, c->duration); WRITE_FLT(store, (float)c->vigour); write_unit_reference(mage, store); @@ -306,6 +296,7 @@ void ct_register(const curse_type * ct) selist **ctlp = cursetypes + hash; assert(ct->age==NULL || (ct->flags&CURSE_NOAGE) == 0); + assert((ct->flags&CURSE_ISNEW) == 0); selist_set_insert(ctlp, (void *)ct, NULL); ++ct_changes; } @@ -553,7 +544,7 @@ static curse *make_curse(unit * mage, attrib ** ap, const curse_type * ct, c = (curse *)a->data.v; c->type = ct; - c->flags = 0; + c->mask = 0; c->vigour = vigour; c->duration = duration; c->effect = effect; @@ -638,7 +629,7 @@ static void do_transfer_curse(curse * c, unit * u, unit * u2, int n) bool dogive = false; const curse_type *ct = c->type; - switch ((ct->flags | c->flags) & CURSE_SPREADMASK) { + switch (c_flags(c) & CURSE_SPREADMASK) { case CURSE_SPREADALWAYS: dogive = true; men = u2->number + n; @@ -671,7 +662,7 @@ static void do_transfer_curse(curse * c, unit * u, unit * u2, int n) if (dogive) { curse *cnew = make_curse(c->magician, &u2->attribs, c->type, c->vigour, c->duration, c->effect, men); - cnew->flags = c->flags; + cnew->mask = c->mask; if (ct->typ == CURSETYP_UNIT) set_cursedmen(cnew, men); diff --git a/src/kernel/curse.h b/src/kernel/curse.h index 543755c2b..b28427fcd 100644 --- a/src/kernel/curse.h +++ b/src/kernel/curse.h @@ -187,7 +187,7 @@ extern "C" { /* ------------------------------------------------------------- */ /* Allgemeine Zauberwirkungen */ -#define c_flags(c) ((c)->type->flags ^ (c)->flags) +#define c_flags(c) ((c)->type->flags ^ (c)->mask) /* ------------------------------------------------------------- */ @@ -215,7 +215,7 @@ extern "C" { double vigour; /* Stärke der Verzauberung, Widerstand gegen Antimagie */ double effect; int no; /* 'Einheitennummer' dieses Curse */ - int flags; /* WARNING: these are XORed with type->flags! */ + int mask; /* This is XORed with type->flags, see c_flags()! */ int duration; /* Dauer der Verzauberung. Wird jede Runde vermindert */ } curse; diff --git a/src/kernel/ship.c b/src/kernel/ship.c index 220c16619..234a91631 100644 --- a/src/kernel/ship.c +++ b/src/kernel/ship.c @@ -42,6 +42,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include +#include #include #include @@ -365,7 +366,7 @@ int shipspeed(const ship * sh, const unit * u) a = a->next; } - c = get_curse(sh->attribs, ct_find("shipspeedup")); + c = get_curse(sh->attribs, &ct_shipspeedup); while (c) { k += curse_geteffect_int(c); c = c->nexthash; diff --git a/src/kernel/ship.test.c b/src/kernel/ship.test.c index b003f74b9..541ddee9a 100644 --- a/src/kernel/ship.test.c +++ b/src/kernel/ship.test.c @@ -462,7 +462,7 @@ static void test_shipspeed_shipspeedup(CuTest *tc) { register_shipcurse(); assert(sh && cap && crew); - create_curse(0, &sh->attribs, ct_find("shipspeedup"), 1, 1, 3, 0); + create_curse(0, &sh->attribs, &ct_shipspeedup, 1, 1, 3, 0); CuAssertIntEquals_Msg(tc, "shipspeedup adds effect to range", sh->type->range + 3, shipspeed(sh, cap)); test_cleanup(); } diff --git a/src/laws.c b/src/laws.c index e16cbd583..5c7d36b51 100644 --- a/src/laws.c +++ b/src/laws.c @@ -70,6 +70,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include +#include /* util includes */ #include @@ -3885,7 +3886,6 @@ int siege_cmd(unit * u, order * ord) building *b; int d, pooled; int bewaffnete, katapultiere = 0; - const curse_type *magicwalls_ct; resource_type *rt_catapultammo = NULL; resource_type *rt_catapult = NULL; @@ -3904,7 +3904,6 @@ int siege_cmd(unit * u, order * ord) } /* schaden durch katapulte */ - magicwalls_ct = ct_find("magicwalls"); rt_catapultammo = rt_find("catapultammo"); rt_catapult = rt_find("catapult"); @@ -3945,7 +3944,7 @@ int siege_cmd(unit * u, order * ord) d = MIN(d, b->size - 1); /* meldung, schaden anrichten */ - if (d && !curse_active(get_curse(b->attribs, magicwalls_ct))) { + if (d && !curse_active(get_curse(b->attribs, &ct_magicwalls))) { b->size -= d; use_pooled(u, rt_catapultammo, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, d); diff --git a/src/spells.c b/src/spells.c index 0c6bb2722..7931be8b8 100644 --- a/src/spells.c +++ b/src/spells.c @@ -2072,7 +2072,7 @@ static int sp_homestone(castorder * co) return 0; } - c = create_curse(mage, &mage->building->attribs, ct_find("magicwalls"), + c = create_curse(mage, &mage->building->attribs, &ct_magicwalls, force * force, 1, zero_effect, 0); if (c == NULL) { diff --git a/src/spells/buildingcurse.c b/src/spells/buildingcurse.c index 9c87aaba4..f1a3b3773 100644 --- a/src/spells/buildingcurse.c +++ b/src/spells/buildingcurse.c @@ -75,7 +75,7 @@ CURSETYP_NORM, 0, M_SUMEFFECT, cinfo_magicrunes }; /* Heimstein-Zauber */ -static struct curse_type ct_magicwalls = { "magicwalls", +const struct curse_type ct_magicwalls = { "magicwalls", CURSETYP_NORM, CURSE_ONLYONE|CURSE_NOAGE, NO_MERGE, cinfo_building }; diff --git a/src/spells/buildingcurse.h b/src/spells/buildingcurse.h index 46989829a..2150dc3b6 100644 --- a/src/spells/buildingcurse.h +++ b/src/spells/buildingcurse.h @@ -21,6 +21,9 @@ extern "C" { struct locale; struct curse; struct message; + struct curse_type; + + extern const struct curse_type ct_magicwalls; extern void register_buildingcurse(void); struct message *cinfo_building(const void *obj, objtype_t typ, const struct curse * c, int self); diff --git a/src/spells/regioncurse.c b/src/spells/regioncurse.c index b10f3046f..1d69574df 100644 --- a/src/spells/regioncurse.c +++ b/src/spells/regioncurse.c @@ -57,7 +57,7 @@ static message *cinfo_cursed_by_the_gods(const void *obj, objtype_t typ, static struct curse_type ct_godcursezone = { "godcursezone", - CURSETYP_NORM, CURSE_IMMUNE | CURSE_ISNEW, (NO_MERGE), + CURSETYP_NORM, CURSE_IMMUNE, (NO_MERGE), cinfo_cursed_by_the_gods, }; @@ -83,7 +83,7 @@ static message *cinfo_dreamcurse(const void *obj, objtype_t typ, const curse * c static struct curse_type ct_gbdream = { "gbdream", - CURSETYP_NORM, CURSE_ISNEW, (NO_MERGE), cinfo_dreamcurse + CURSETYP_NORM, 0, (NO_MERGE), cinfo_dreamcurse }; /* --------------------------------------------------------------------- */ @@ -196,7 +196,7 @@ static struct curse_type ct_fogtrap = { static struct curse_type ct_maelstrom = { "maelstrom", - CURSETYP_NORM, CURSE_ISNEW, (M_DURATION | M_VIGOUR), + CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR), cinfo_simple }; @@ -214,7 +214,7 @@ static struct curse_type ct_drought = { static struct curse_type ct_badlearn = { "badlearn", - CURSETYP_NORM, CURSE_ISNEW, (M_DURATION | M_VIGOUR), + CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR), cinfo_simple }; diff --git a/src/spells/shipcurse.c b/src/spells/shipcurse.c index b6a722ad3..0295695a1 100644 --- a/src/spells/shipcurse.c +++ b/src/spells/shipcurse.c @@ -73,14 +73,14 @@ static message *cinfo_shipnodrift(const void *obj, objtype_t typ, const curse * } static struct curse_type ct_stormwind = { "stormwind", -CURSETYP_NORM, 0, NO_MERGE, cinfo_ship +CURSETYP_NORM, CURSE_NOAGE, NO_MERGE, cinfo_ship }; static struct curse_type ct_nodrift = { "nodrift", CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR), cinfo_shipnodrift }; -static struct curse_type ct_shipspeedup = { "shipspeedup", +const struct curse_type ct_shipspeedup = { "shipspeedup", CURSETYP_NORM, 0, 0, cinfo_ship }; diff --git a/src/spells/shipcurse.h b/src/spells/shipcurse.h index 9ac57b142..a41f9edee 100644 --- a/src/spells/shipcurse.h +++ b/src/spells/shipcurse.h @@ -22,6 +22,8 @@ extern "C" { struct message; struct curse; + extern const struct curse_type ct_shipspeedup; + struct message *cinfo_ship(const void *obj, objtype_t typ, const struct curse *c, int self); void register_shipcurse(void); diff --git a/src/spells/unitcurse.c b/src/spells/unitcurse.c index ded4a1676..0a19629f1 100644 --- a/src/spells/unitcurse.c +++ b/src/spells/unitcurse.c @@ -170,7 +170,7 @@ message *cinfo_unit(const void *obj, objtype_t typ, const curse * c, int self) static struct curse_type ct_orcish = { "orcish", - CURSETYP_UNIT, CURSE_SPREADMODULO | CURSE_ISNEW, M_MEN, + CURSETYP_UNIT, CURSE_SPREADMODULO, M_MEN, cinfo_unit }; From 7a4a49160c8337479c53da9a8a25129e45f2ba0e Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 18 Aug 2017 19:48:34 +0200 Subject: [PATCH 3/4] unused variable --- src/items.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/items.c b/src/items.c index 37299563f..e33aed1bc 100644 --- a/src/items.c +++ b/src/items.c @@ -89,7 +89,6 @@ static int use_speedsail(struct unit *u, const struct item_type *itype, int amount, struct order *ord) { - curse *c; double effect; ship *sh = u->ship; if (!sh) { @@ -98,8 +97,7 @@ struct order *ord) } effect = SPEEDSAIL_EFFECT; - c = create_curse(u, &sh->attribs, &ct_shipspeedup, 20, INT_MAX, - effect, 0); + create_curse(u, &sh->attribs, &ct_shipspeedup, 20, INT_MAX, effect, 0); ADDMSG(&u->faction->msgs, msg_message("use_speedsail", "unit speed", u, SPEEDSAIL_EFFECT)); From aa618609964a794449f4d6f96ae67fa86784e986 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 18 Aug 2017 20:20:12 +0200 Subject: [PATCH 4/4] BUG 2357: make sure starting regions have enough recruits --- src/kernel/faction.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/kernel/faction.c b/src/kernel/faction.c index e804534c4..0b099df0f 100755 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -283,12 +283,20 @@ faction *addfaction(const char *email, const char *password, return f; } +#define PEASANT_MIN (10 * RECRUITFRACTION) +#define PEASANT_MAX (20 * RECRUITFRACTION) + unit *addplayer(region * r, faction * f) { unit *u; const char * name; const struct equipment* eq; + assert(r->land); + if (rpeasants(r) < PEASANT_MIN) { + rsetpeasants(r, PEASANT_MIN + rng_int() % (PEASANT_MAX - PEASANT_MIN)); + } + assert(f->units == NULL); faction_setorigin(f, 0, r->x, r->y); u = create_unit(r, f, 1, f->race, 0, NULL, NULL);