From 24ff4c301d3f3b6a9178386cb54c96da19bf1765 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 2 Nov 2015 14:18:50 +0100 Subject: [PATCH 1/5] refactor: separate building_is_active from inside_building --- src/economy.c | 8 ++++---- src/kernel/build.c | 10 ++++++---- src/kernel/building.c | 4 ++++ src/kernel/building.h | 3 ++- src/kernel/unit.c | 6 +----- src/kernel/unit.h | 44 +++++++++++++++++++++---------------------- src/laws.c | 2 +- src/magic.c | 8 ++++---- src/study.c | 17 +++++++++++------ 9 files changed, 55 insertions(+), 47 deletions(-) diff --git a/src/economy.c b/src/economy.c index acccca8f1..c6e0d360a 100644 --- a/src/economy.c +++ b/src/economy.c @@ -1101,7 +1101,7 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want) for (; mod->flags != 0; ++mod) { if (mod->flags & RMF_REQUIREDBUILDING) { struct building *b = inside_building(u); - const struct building_type *btype = b ? b->type : NULL; + const struct building_type *btype = building_is_active(b) ? b->type : NULL; if (mod->btype && mod->btype != btype) { cmistake(u, u->thisorder, 104, MSG_PRODUCE); return; @@ -1157,7 +1157,7 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want) } else { struct building *b = inside_building(u); - const struct building_type *btype = b ? b->type : NULL; + const struct building_type *btype = building_is_active(b) ? b->type : NULL; if (rdata->modifiers) { resource_mod *mod = rdata->modifiers; @@ -1213,7 +1213,7 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want) if (rdata->modifiers) { struct building *b = inside_building(u); - const struct building_type *btype = b ? b->type : NULL; + const struct building_type *btype = building_is_active(b) ? b->type : NULL; resource_mod *mod = rdata->modifiers; for (; mod->flags != 0; ++mod) { @@ -2422,7 +2422,7 @@ static void breedhorses(unit * u) { int n, c, breed = 0; struct building *b = inside_building(u); - const struct building_type *btype = b ? b->type : NULL; + const struct building_type *btype = building_is_active(b) ? b->type : NULL; const struct resource_type *rhorse = get_resourcetype(R_HORSE); int horses, effsk; diff --git a/src/kernel/build.c b/src/kernel/build.c index 924dccf49..e38d76641 100644 --- a/src/kernel/build.c +++ b/src/kernel/build.c @@ -448,8 +448,9 @@ int build(unit * u, const construction * ctype, int completed, int want) return EBUILDINGREQ; } b = inside_building(u); - if (b == NULL) + if (!b || !building_is_active(b)) { return EBUILDINGREQ; + } } if (type->skill != NOSKILL) { @@ -462,7 +463,7 @@ int build(unit * u, const construction * ctype, int completed, int want) return ENEEDSKILL; effsk = basesk; - if (inside_building(u)) { + if (building_is_active(u->building) && inside_building(u)) { effsk = skillmod(u->building->type->attribs, u, u->region, type->skill, effsk, SMF_PRODUCTION); } @@ -558,7 +559,7 @@ int build(unit * u, const construction * ctype, int completed, int want) int need, prebuilt; int canuse = get_pooled(u, rtype, GET_DEFAULT, INT_MAX); - if (inside_building(u)) { + if (building_is_active(u->building) && inside_building(u)) { canuse = matmod(u->building->type->attribs, u, rtype, canuse); } @@ -597,8 +598,9 @@ int build(unit * u, const construction * ctype, int completed, int want) required(completed + n, type->reqsize, type->materials[c].number); int multi = 1; int canuse = 100; /* normalization */ - if (inside_building(u)) + if (building_is_active(u->building) && inside_building(u)) { canuse = matmod(u->building->type->attribs, u, rtype, canuse); + } if (canuse < 0) return canuse; /* pass errors to caller */ canuse = matmod(type->attribs, u, rtype, canuse); diff --git a/src/kernel/building.c b/src/kernel/building.c index da4f58867..d63ada88e 100644 --- a/src/kernel/building.c +++ b/src/kernel/building.c @@ -642,6 +642,10 @@ region *building_getregion(const building * b) return b->region; } +bool building_is_active(const struct building *b) { + return b && fval(b, BLD_WORKING); +} + void building_setregion(building * b, region * r) { building **blist = &b->region->buildings; diff --git a/src/kernel/building.h b/src/kernel/building.h index b4bb23efa..c0796b352 100644 --- a/src/kernel/building.h +++ b/src/kernel/building.h @@ -78,6 +78,7 @@ extern "C" { } building_type; extern struct quicklist *buildingtypes; + extern struct attrib_type at_building_action; building_type *bt_get_or_create(const char *name); const building_type *bt_find(const char *name); @@ -163,7 +164,7 @@ extern "C" { extern void building_set_owner(struct unit * u); extern void building_update_owner(struct building * bld); - extern struct attrib_type at_building_action; + bool building_is_active(const struct building *b); #ifdef WDW_PYRAMID extern int wdw_pyramid_level(const struct building *b); diff --git a/src/kernel/unit.c b/src/kernel/unit.c index 5e9b39705..23919eeac 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -1072,11 +1072,7 @@ void transfermen(unit * u, unit * dst, int n) struct building *inside_building(const struct unit *u) { - if (u->building == NULL) - return NULL; - - if (!fval(u->building, BLD_WORKING)) { - /* Unterhalt nicht bezahlt */ + if (!u->building || !building_is_active(u->building)) { return NULL; } else if (u->building->size < u->building->type->maxsize) { diff --git a/src/kernel/unit.h b/src/kernel/unit.h index 606bccbcf..89fb90d9b 100644 --- a/src/kernel/unit.h +++ b/src/kernel/unit.h @@ -183,36 +183,36 @@ extern "C" { void make_zombie(unit * u); /* see resolve.h */ - extern int resolve_unit(variant data, void *address); - extern void write_unit_reference(const struct unit *u, struct storage *store); - extern variant read_unit_reference(struct storage *store); + int resolve_unit(variant data, void *address); + void write_unit_reference(const struct unit *u, struct storage *store); + variant read_unit_reference(struct storage *store); - extern bool leave(struct unit *u, bool force); - extern bool can_leave(struct unit *u); + bool leave(struct unit *u, bool force); + bool can_leave(struct unit *u); - extern void u_set_building(struct unit * u, struct building * b); - extern void u_set_ship(struct unit * u, struct ship * sh); - extern void leave_ship(struct unit * u); - extern void leave_building(struct unit * u); + void u_set_building(struct unit * u, struct building * b); + void u_set_ship(struct unit * u, struct ship * sh); + void leave_ship(struct unit * u); + void leave_building(struct unit * u); - extern void set_leftship(struct unit *u, struct ship *sh); - extern struct ship *leftship(const struct unit *); - extern bool can_survive(const struct unit *u, const struct region *r); - extern void move_unit(struct unit *u, struct region *target, - struct unit **ulist); + void set_leftship(struct unit *u, struct ship *sh); + struct ship *leftship(const struct unit *); + bool can_survive(const struct unit *u, const struct region *r); + void move_unit(struct unit *u, struct region *target, + struct unit **ulist); - extern struct building *inside_building(const struct unit *u); + struct building *inside_building(const struct unit *u); /* cleanup code for this module */ - extern void free_units(void); - extern struct faction *dfindhash(int no); - extern void u_setfaction(struct unit *u, struct faction *f); - extern void set_number(struct unit *u, int count); + void free_units(void); + struct faction *dfindhash(int no); + void u_setfaction(struct unit *u, struct faction *f); + void set_number(struct unit *u, int count); - extern bool learn_skill(struct unit *u, skill_t sk, double chance); + bool learn_skill(struct unit *u, skill_t sk, double chance); - extern int invisible(const struct unit *target, const struct unit *viewer); - extern void free_unit(struct unit *u); + int invisible(const struct unit *target, const struct unit *viewer); + void free_unit(struct unit *u); extern void name_unit(struct unit *u); extern struct unit *create_unit(struct region *r1, struct faction *f, diff --git a/src/laws.c b/src/laws.c index d3cdcaba4..3b4cc6fca 100755 --- a/src/laws.c +++ b/src/laws.c @@ -3545,7 +3545,7 @@ void monthly_healing(void) double maxheal = _max(u->number, umhp / 20.0); int addhp; struct building *b = inside_building(u); - const struct building_type *btype = b ? b->type : NULL; + const struct building_type *btype = building_is_active(b) ? b->type : NULL; if (btype == bt_find("inn")) { p *= 1.5; } diff --git a/src/magic.c b/src/magic.c index 52d85f435..e0a5ca921 100644 --- a/src/magic.c +++ b/src/magic.c @@ -1025,7 +1025,7 @@ spellpower(region * r, unit * u, const spell * sp, int cast_level, struct order else { /* Bonus durch Magieturm und gesegneten Steinkreis */ struct building *b = inside_building(u); - const struct building_type *btype = b ? b->type : NULL; + const struct building_type *btype = building_is_active(b) ? b->type : NULL; if (btype && btype->flags & BTF_MAGIC) ++force; } @@ -1170,7 +1170,7 @@ double magic_resistance(unit * target) /* Bonus durch Gebäude */ { struct building *b = inside_building(target); - const struct building_type *btype = b ? b->type : NULL; + const struct building_type *btype = building_is_active(b) ? b->type : NULL; /* gesegneter Steinkreis gibt 30% dazu */ if (btype) @@ -1284,7 +1284,7 @@ bool fumble(region * r, unit * u, const spell * sp, int cast_grade) int fumble_chance, rnd = 0; int effsk = effskill(u, SK_MAGIC, r); struct building *b = inside_building(u); - const struct building_type *btype = b ? b->type : NULL; + const struct building_type *btype = building_is_active(b) ? b->type : NULL; int fumble_enabled = get_param_int(global.parameters, "magic.fumble.enable", 1); sc_mage * mage; @@ -1468,7 +1468,7 @@ void regenerate_aura(void) auramax = max_spellpoints(r, u); if (aura < auramax) { struct building *b = inside_building(u); - const struct building_type *btype = b ? b->type : NULL; + const struct building_type *btype = building_is_active(b) ? b->type : NULL; reg_aura = regeneration(u); /* Magierturm erhöht die Regeneration um 75% */ diff --git a/src/study.c b/src/study.c index 5edba9168..b798277ca 100644 --- a/src/study.c +++ b/src/study.c @@ -175,6 +175,13 @@ static int study_days(unit * student, skill_t sk) return student->number * speed; } +static building *active_building(const unit *u, const struct building_type *btype) { + if (u->building && u->building->type == btype && building_is_active(u->building)) { + return inside_building(u); + } + return 0; +} + static int teach_unit(unit * teacher, unit * student, int nteaching, skill_t sk, bool report, int *academy) @@ -205,8 +212,7 @@ bool report, int *academy) n = _min(n, nteaching); if (n != 0) { - struct building *b = inside_building(teacher); - const struct building_type *btype = b ? b->type : NULL; + const struct building_type *btype = bt_find("academy"); int index = 0; if (teach == NULL) { @@ -229,8 +235,7 @@ bool report, int *academy) /* Solange Akademien groessenbeschraenkt sind, sollte Lehrer und * Student auch in unterschiedlichen Gebaeuden stehen duerfen */ - if (btype == bt_find("academy") - && student->building && student->building->type == bt_find("academy")) { + if (active_building(teacher, btype) && active_building(student, btype)) { int j = study_cost(student, sk); j = _max(50, j * 2); /* kann Einheit das zahlen? */ @@ -542,7 +547,7 @@ int study_cmd(unit * u, order * ord) int speed_rule = (study_rule_t)get_param_int(global.parameters, "study.speedup", 0); static int learn_newskills = -1; struct building *b = inside_building(u); - const struct building_type *btype = b ? b->type : NULL; + const struct building_type *btype = building_is_active(b) ? b->type : NULL; if (learn_newskills < 0) { const char *str = get_param(global.parameters, "study.newskills"); @@ -606,7 +611,7 @@ int study_cmd(unit * u, order * ord) } /* Akademie: */ b = inside_building(u); - btype = b ? b->type : NULL; + btype = building_is_active(b) ? b->type : NULL; if (btype && btype == bt_find("academy")) { studycost = _max(50, studycost * 2); From 42ae086def9db60d466dd4b824a2dc35b78dfd8f Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 2 Nov 2015 14:49:48 +0100 Subject: [PATCH 2/5] unit is inisde a building also when it was not paid for --- src/kernel/unit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kernel/unit.c b/src/kernel/unit.c index 23919eeac..336231d7d 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -1072,7 +1072,7 @@ void transfermen(unit * u, unit * dst, int n) struct building *inside_building(const struct unit *u) { - if (!u->building || !building_is_active(u->building)) { + if (!u->building) { return NULL; } else if (u->building->size < u->building->type->maxsize) { From 4bf2509fb3c10c14ef2a958a406778563c9213a0 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 2 Nov 2015 14:56:58 +0100 Subject: [PATCH 3/5] test inside_building vs. overflow fix default building capacity (should be 1 per size) --- src/kernel/building.c | 2 +- src/kernel/building.test.c | 2 +- src/kernel/unit.test.c | 22 ++++++++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/kernel/building.c b/src/kernel/building.c index d63ada88e..c17830e5d 100644 --- a/src/kernel/building.c +++ b/src/kernel/building.c @@ -115,7 +115,7 @@ building_type *bt_get_or_create(const char *name) btype->_name = _strdup(name); btype->auraregen = 1.0; btype->maxsize = -1; - btype->capacity = -1; + btype->capacity = 1; btype->maxcapacity = -1; bt_register(btype); } diff --git a/src/kernel/building.test.c b/src/kernel/building.test.c index e414544e6..e0d5180d0 100644 --- a/src/kernel/building.test.c +++ b/src/kernel/building.test.c @@ -373,7 +373,7 @@ static void test_btype_defaults(CuTest *tc) { CuAssertTrue(tc, !btype->taxes); CuAssertDblEquals(tc, 1.0, btype->auraregen, 0.0); CuAssertIntEquals(tc, -1, btype->maxsize); - CuAssertIntEquals(tc, -1, btype->capacity); + CuAssertIntEquals(tc, 1, btype->capacity); CuAssertIntEquals(tc, -1, btype->maxcapacity); CuAssertIntEquals(tc, 0, btype->magres); CuAssertIntEquals(tc, 0, btype->magresbonus); diff --git a/src/kernel/unit.test.c b/src/kernel/unit.test.c index 91333aa74..fc9cd4f27 100644 --- a/src/kernel/unit.test.c +++ b/src/kernel/unit.test.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -376,6 +377,26 @@ static void test_produceexp(CuTest *tc) { test_cleanup(); } +static void test_inside_building(CuTest *tc) { + unit *u; + building *b; + + test_cleanup(); + u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); + b = test_create_building(u->region, 0); + + b->size = 1; + scale_number(u, 1); + CuAssertPtrEquals(tc, 0, inside_building(u)); + u->building = b; + CuAssertPtrEquals(tc, b, inside_building(u)); + scale_number(u, 2); + CuAssertPtrEquals(tc, 0, inside_building(u)); + b->size = 2; + CuAssertPtrEquals(tc, b, inside_building(u)); + test_cleanup(); +} + CuSuite *get_unit_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -394,6 +415,7 @@ CuSuite *get_unit_suite(void) SUITE_ADD_TEST(suite, test_skill_hunger); SUITE_ADD_TEST(suite, test_skill_familiar); SUITE_ADD_TEST(suite, test_age_familiar); + SUITE_ADD_TEST(suite, test_inside_building); SUITE_ADD_TEST(suite, test_produceexp); return suite; } From 072bfd39129f133e0be848edf48f38d44a44f435 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 2 Nov 2015 15:05:54 +0100 Subject: [PATCH 4/5] testin building_is_active testing multiple units in one building --- src/kernel/building.test.c | 14 ++++++++++++++ src/kernel/unit.test.c | 5 +++++ 2 files changed, 19 insertions(+) diff --git a/src/kernel/building.test.c b/src/kernel/building.test.c index e0d5180d0..1f0ca303c 100644 --- a/src/kernel/building.test.c +++ b/src/kernel/building.test.c @@ -382,6 +382,19 @@ static void test_btype_defaults(CuTest *tc) { test_cleanup(); } +static void test_active_building(CuTest *tc) { + building *b; + + test_cleanup(); + b = test_create_building(test_create_region(0,0,0), 0); + CuAssertIntEquals(tc, false, building_is_active(b)); + b->flags |= BLD_WORKING; + CuAssertIntEquals(tc, true, building_is_active(b)); + b->flags &= ~BLD_WORKING; + CuAssertIntEquals(tc, false, building_is_active(b)); + test_cleanup(); +} + CuSuite *get_building_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -396,5 +409,6 @@ 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_active_building); return suite; } diff --git a/src/kernel/unit.test.c b/src/kernel/unit.test.c index fc9cd4f27..0fd58a55a 100644 --- a/src/kernel/unit.test.c +++ b/src/kernel/unit.test.c @@ -394,6 +394,11 @@ static void test_inside_building(CuTest *tc) { CuAssertPtrEquals(tc, 0, inside_building(u)); b->size = 2; CuAssertPtrEquals(tc, b, inside_building(u)); + u = test_create_unit(u->faction, u->region); + u->building = b; + CuAssertPtrEquals(tc, 0, inside_building(u)); + b->size = 3; + CuAssertPtrEquals(tc, b, inside_building(u)); test_cleanup(); } From f70b385bef849de44fa1843b49b79e7e5e7c68c1 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 2 Nov 2015 15:27:01 +0100 Subject: [PATCH 5/5] clean up plan_monsters and make it a bit more readable --- src/monsters.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/monsters.c b/src/monsters.c index 523c6f02a..bc195174c 100644 --- a/src/monsters.c +++ b/src/monsters.c @@ -769,13 +769,14 @@ static order *plan_dragon(unit * u) void plan_monsters(faction * f) { region *r; + double attack_chance = monster_attack_chance(); assert(f); f->lastorders = turn; for (r = regions; r; r = r->next) { unit *u; - double attack_chance = monster_attack_chance(); + double rchance = attack_chance; bool attacking = false; for (u = r->units; u; u = u->next) { @@ -786,25 +787,23 @@ void plan_monsters(faction * f) if (!is_monsters(u->faction)) continue; - if (attack_chance > 0.0) { - if (chance(attack_chance)) - attacking = true; - attack_chance = 0.0; - } - - if (u->status > ST_BEHIND) { - setstatus(u, ST_FIGHT); - /* all monsters fight */ - } + /* Befehle müssen jede Runde neu gegeben werden: */ + free_orders(&u->orders); if (skill_enabled(SK_PERCEPTION)) { /* Monster bekommen jede Runde ein paar Tage Wahrnehmung dazu */ /* TODO: this only works for playerrace */ produceexp(u, SK_PERCEPTION, u->number); } - /* Befehle müssen jede Runde neu gegeben werden: */ - free_orders(&u->orders); - + if (rchance > 0.0) { + if (chance(rchance)) + attacking = true; + rchance = 0.0; + } + if (u->status > ST_BEHIND) { + setstatus(u, ST_FIGHT); + /* all monsters fight */ + } if (attacking && is_guard(u, GUARD_TAX)) { monster_attacks(u); }