diff --git a/.gitignore b/.gitignore index 4e63f5d9c..d7c102f5a 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,6 @@ tmp/ tests/config.lua tests/reports/ tests/data/185.dat +/quicklist/ +/cutest/ +/critbit/ diff --git a/res/buildings/castle-2.xml b/res/buildings/castle-2.xml index 593e9ae5e..7b015d199 100644 --- a/res/buildings/castle-2.xml +++ b/res/buildings/castle-2.xml @@ -1,24 +1,23 @@ - - + - + - + - + - + - + diff --git a/res/buildings/castle.xml b/res/buildings/castle.xml index 253f49811..6e9140222 100644 --- a/res/buildings/castle.xml +++ b/res/buildings/castle.xml @@ -1,26 +1,25 @@ - - + - + - + - + - + - + - + diff --git a/res/e3a/buildings.xml b/res/e3a/buildings.xml index f65654e2f..9eeca952f 100644 --- a/res/e3a/buildings.xml +++ b/res/e3a/buildings.xml @@ -5,15 +5,14 @@ - - + - + - + diff --git a/src/battle.c b/src/battle.c index 0ff8eecaa..23c219109 100644 --- a/src/battle.c +++ b/src/battle.c @@ -1892,10 +1892,11 @@ int skilldiff(troop at, troop dt, int dist) } if (df->building) { - if (df->building->attribs) { + building *b = df->building; + if (b->attribs) { const curse_type *strongwall_ct = ct_find("strongwall"); if (strongwall_ct) { - curse *c = get_curse(df->building->attribs, strongwall_ct); + curse *c = get_curse(b->attribs, strongwall_ct); if (curse_active(c)) { /* wirkt auf alle Geb�ude */ skdiff -= curse_geteffect_int(c); @@ -1903,15 +1904,16 @@ int skilldiff(troop at, troop dt, int dist) } } } - if (df->building->type->protection) { - int beff = df->building->type->protection(df->building, du, DEFENSE_BONUS); - if (beff) { + if (b->type->flags & BTF_FORTIFICATION) { + int stage = buildingeffsize(b, false); + int beff = building_protection(b->type, stage); + if (beff > 0) { skdiff -= beff; is_protected = 2; - if (df->building->attribs) { + if (b->attribs) { const curse_type *magicwalls_ct = ct_find("magicwalls"); if (magicwalls_ct - && curse_active(get_curse(df->building->attribs, magicwalls_ct))) { + && curse_active(get_curse(b->attribs, magicwalls_ct))) { /* Verdoppelt Burgenbonus */ skdiff -= beff; } @@ -2022,7 +2024,7 @@ void damage_building(battle * b, building * bldg, int damage_abs) /* Wenn Burg, dann gucken, ob die Leute alle noch in das Geb�ude passen. */ - if (bldg->type->protection) { + if (bldg->type->flags & BTF_FORTIFICATION) { side *s; bldg->sizeleft = bldg->size; diff --git a/src/battle.test.c b/src/battle.test.c index 5d34766db..987613277 100644 --- a/src/battle.test.c +++ b/src/battle.test.c @@ -60,10 +60,23 @@ static void test_make_fighter(CuTest * tc) test_cleanup(); } -static int add_two(const building * b, const unit * u, building_bonus bonus) { +static int add_two(const building * b, const unit * u) { return 2; } +static building_type * setup_castle(void) { + building_type * btype; + construction *cons; + + btype = bt_get_or_create("castle"); + btype->flags |= BTF_FORTIFICATION; + cons = btype->construction = calloc(1, sizeof(construction)); + cons->maxsize = 5; + cons = cons->improvement = calloc(1, sizeof(construction)); + cons->maxsize = -1; + return btype; +} + static void test_defenders_get_building_bonus(CuTest * tc) { unit *du, *au; @@ -72,16 +85,13 @@ static void test_defenders_get_building_bonus(CuTest * tc) fighter *df, *af; battle *b; side *ds, *as; - int diff; troop dt, at; building_type * btype; test_cleanup(); + btype = setup_castle(); r = test_create_region(0, 0, 0); - btype = bt_get_or_create("castle"); - btype->protection = &add_two; bld = test_create_building(r, btype); - bld->size = 10; du = test_create_unit(test_create_faction(NULL), r); au = test_create_unit(test_create_faction(NULL), r); @@ -101,11 +111,14 @@ static void test_defenders_get_building_bonus(CuTest * tc) at.fighter = af; at.index = 0; - diff = skilldiff(at, dt, 0); - CuAssertIntEquals(tc, -2, diff); + bld->size = 10; /* stage 1 building */ + CuAssertIntEquals(tc, -1, skilldiff(at, dt, 0)); + CuAssertIntEquals(tc, 0, skilldiff(dt, at, 0)); + + bld->size = 1; /* stage 0 building */ + CuAssertIntEquals(tc, 0, skilldiff(at, dt, 0)); + CuAssertIntEquals(tc, 0, skilldiff(dt, at, 0)); - diff = skilldiff(dt, at, 0); - CuAssertIntEquals(tc, 0, diff); free_battle(b); test_cleanup(); } @@ -122,8 +135,8 @@ static void test_attackers_get_no_building_bonus(CuTest * tc) test_cleanup(); r = test_create_region(0, 0, 0); - btype = bt_get_or_create("castle"); - btype->protection = &add_two; + btype = setup_castle(); + btype->flags |= BTF_FORTIFICATION; bld = test_create_building(r, btype); bld->size = 10; @@ -151,9 +164,9 @@ static void test_building_bonus_respects_size(CuTest * tc) faction * f; test_cleanup(); + btype = setup_castle(); r = test_create_region(0, 0, 0); - btype = bt_get_or_create("castle"); - btype->protection = &add_two; + btype->flags |= BTF_FORTIFICATION; bld = test_create_building(r, btype); bld->size = 10; @@ -178,28 +191,25 @@ static void test_building_bonus_respects_size(CuTest * tc) static void test_building_defence_bonus(CuTest * tc) { - unit *au; - region *r; - building * bld; building_type * btype; - faction * f; - int def; test_cleanup(); - r = test_create_region(0, 0, 0); - btype = test_create_buildingtype("castle"); - 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; + btype = setup_castle(); - f = test_create_faction(NULL); - au = test_create_unit(f, r); - scale_number(au, 1); - u_set_building(au, bld); + btype->maxsize = -1; /* unlimited buildigs get the castle bonus */ + CuAssertIntEquals(tc, 0, building_protection(btype, 0)); + CuAssertIntEquals(tc, 1, building_protection(btype, 1)); + CuAssertIntEquals(tc, 3, building_protection(btype, 2)); + CuAssertIntEquals(tc, 5, building_protection(btype, 3)); + CuAssertIntEquals(tc, 8, building_protection(btype, 4)); + CuAssertIntEquals(tc, 12, building_protection(btype, 5)); + CuAssertIntEquals(tc, 12, building_protection(btype, 6)); - def = btype->protection(bld, au, DEFENSE_BONUS); - CuAssertIntEquals(tc, 3, def); + btype->maxsize = 10; /* limited-size buildings are treated like an E3 watchtower */ + CuAssertIntEquals(tc, 0, building_protection(btype, 0)); + CuAssertIntEquals(tc, 1, building_protection(btype, 1)); + CuAssertIntEquals(tc, 2, building_protection(btype, 2)); + CuAssertIntEquals(tc, 2, building_protection(btype, 3)); test_cleanup(); } @@ -441,10 +451,6 @@ static void test_battle_skilldiff(CuTest *tc) 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; @@ -455,7 +461,7 @@ static void test_battle_skilldiff_building(CuTest *tc) const curse_type *strongwall_ct, *magicwalls_ct; test_cleanup(); - btype = test_create_buildingtype("castle"); + btype = setup_castle(); strongwall_ct = ct_find("strongwall"); magicwalls_ct = ct_find("magicwalls"); @@ -470,14 +476,14 @@ static void test_battle_skilldiff_building(CuTest *tc) 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)); + ud->building->size = 10; + CuAssertIntEquals(tc, -1, skilldiff(ta, td, 0)); create_curse(NULL, &ud->building->attribs, magicwalls_ct, 1, 1, 1, 1); - CuAssertIntEquals(tc, -8, skilldiff(ta, td, 0)); + CuAssertIntEquals(tc, -2, skilldiff(ta, td, 0)); create_curse(NULL, &ud->building->attribs, strongwall_ct, 1, 1, 2, 1); - CuAssertIntEquals(tc, -10, skilldiff(ta, td, 0)); + CuAssertIntEquals(tc, -4, skilldiff(ta, td, 0)); free_battle(b); test_cleanup(); diff --git a/src/kernel/build.h b/src/kernel/build.h index 38fefb88a..7780a6cd2 100644 --- a/src/kernel/build.h +++ b/src/kernel/build.h @@ -45,9 +45,6 @@ extern "C" { int maxsize; /* maximum size of this type */ int reqsize; /* size of object using up 1 set of requirement. */ - int defense_bonus; /* protection bonus (defense) during combat */ - int close_combat_bonus; /* close combat attack bonus*/ - int ranged_bonus; /* ranged attack bonus */ requirement *materials; /* material req'd to build one object */ const struct building_type *btype; /* building type required to make this thing */ diff --git a/src/kernel/building.c b/src/kernel/building.c index 06078aaba..3c21f4dbe 100644 --- a/src/kernel/building.c +++ b/src/kernel/building.c @@ -337,40 +337,24 @@ const building_type *findbuildingtype(const char *name, int cmp_castle_size(const building * b, const building * a) { - if (!b || !b->type->protection || !building_owner(b)) { + if (!b || !(b->type->flags & BTF_FORTIFICATION) || !building_owner(b)) { return -1; } - if (!a || !a->type->protection || !building_owner(a)) { + if (!a || !(a->type->flags & BTF_FORTIFICATION) || !building_owner(a)) { return 1; } return b->size - a->size; } -int building_protection(const building * b, const unit * u, building_bonus bonus) +static const int castle_bonus[6] = { 0, 1, 3, 5, 8, 12 }; +static const int watch_bonus[3] = { 0, 1, 2 }; + +int building_protection(const building_type * btype, int stage) { - int i = 0; - int bsize = buildingeffsize(b, false); - const construction *cons = b->type->construction; - if (!cons) { - return 0; - } - - for (i = 0; i < bsize; i++) - { - cons = cons->improvement; - } - - switch (bonus) - { - case DEFENSE_BONUS: - return cons->defense_bonus; - case CLOSE_COMBAT_ATTACK_BONUS: - return cons->close_combat_bonus; - case RANGED_ATTACK_BONUS: - return cons->ranged_bonus; - default: - return 0; + if (btype->maxsize < 0) { + return castle_bonus[MIN(stage, 5)]; } + return watch_bonus[MIN(stage, 2)]; } void write_building_reference(const struct building *b, struct storage *store) @@ -925,8 +909,6 @@ int cmp_current_owner(const building * b, const building * a) void register_buildings(void) { register_function((pf_generic)minimum_wage, "minimum_wage"); - register_function((pf_generic)building_protection, - "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 1adce7e09..8c23fdb7c 100644 --- a/src/kernel/building.h +++ b/src/kernel/building.h @@ -51,13 +51,7 @@ extern "C" { #define BTF_MAGIC 0x40 /* magical effect */ #define BTF_ONEPERTURN 0x80 /* one one sizepoint can be added per turn */ #define BTF_NAMECHANGE 0x100 /* name and description can be changed more than once */ -#define BTF_FORTIFICATION 0x200 /* safe from monsters */ - - typedef enum { - DEFENSE_BONUS, - CLOSE_COMBAT_ATTACK_BONUS, /* TODO: only DEFENSE_BONUS is in use? */ - RANGED_ATTACK_BONUS - } building_bonus; +#define BTF_FORTIFICATION 0x200 /* building_protection, safe from monsters */ typedef struct building_type { char *_name; @@ -77,7 +71,6 @@ extern "C" { const struct building * b, int size); void(*init) (struct building_type *); void(*age) (struct building *); - int(*protection) (const struct building *, const struct unit *, building_bonus bonus); double(*taxes) (const struct building *, int size); struct attrib *attribs; } building_type; @@ -85,8 +78,8 @@ extern "C" { extern struct selist *buildingtypes; extern struct attrib_type at_building_action; - int cmp_castle_size(const struct building * b, const struct building * a); - int building_protection(const struct building * b, const struct unit * u, building_bonus bonus); + int cmp_castle_size(const struct building *b, const struct building *a); + int building_protection(const struct building_type *btype, int stage); building_type *bt_get_or_create(const char *name); bool bt_changed(int *cache); const building_type *bt_find(const char *name); diff --git a/src/kernel/building.test.c b/src/kernel/building.test.c index e02d16556..4395f1c40 100644 --- a/src/kernel/building.test.c +++ b/src/kernel/building.test.c @@ -376,7 +376,6 @@ static void test_btype_defaults(CuTest *tc) { CuAssertTrue(tc, !btype->name); CuAssertTrue(tc, !btype->init); CuAssertTrue(tc, !btype->age); - CuAssertTrue(tc, !btype->protection); CuAssertTrue(tc, !btype->taxes); CuAssertDblEquals(tc, 1.0, btype->auraregen, 0.0); CuAssertIntEquals(tc, -1, btype->maxsize); diff --git a/src/kernel/xmlreader.c b/src/kernel/xmlreader.c index 695f91d69..555c0f679 100644 --- a/src/kernel/xmlreader.c +++ b/src/kernel/xmlreader.c @@ -167,9 +167,6 @@ construction ** consPtr) con->maxsize = xml_ivalue(node, "maxsize", -1); con->minskill = xml_ivalue(node, "minskill", -1); con->reqsize = xml_ivalue(node, "reqsize", 1); - con->defense_bonus = xml_ivalue(node, "defense_bonus", 0); - con->close_combat_bonus = xml_ivalue(node, "close_combat_bonus", 0); - con->ranged_bonus = xml_ivalue(node, "ranged_bonus", 0); propValue = xmlGetProp(node, BAD_CAST "building"); if (propValue != NULL) { @@ -301,9 +298,6 @@ static int parse_buildings(xmlDocPtr doc) else if (strcmp((const char *)propValue, "age") == 0) { btype->age = (void(*)(struct building *))fun; } - else if (strcmp((const char *)propValue, "protection") == 0) { - 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; } diff --git a/src/tests.c b/src/tests.c index 6a43e6e79..c448a27ae 100644 --- a/src/tests.c +++ b/src/tests.c @@ -230,7 +230,7 @@ building * test_create_building(region * r, const building_type * btype) assert(r); if (!btype) { building_type *bt_castle = test_create_buildingtype("castle"); - bt_castle->protection = building_protection; + bt_castle->flags |= BTF_FORTIFICATION; btype = bt_castle; } b = new_building(btype, r, default_locale);