From 595dc1334ee261bbbd1a901a0bafa2dea6d52f29 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 3 Oct 2014 21:26:11 +0200 Subject: [PATCH] fix new harbor code, add tests. - alliances were checked in the opposite direction - code crashed when harbor has no owner --- res/core/de/strings.xml | 5 ++ src/move.c | 28 +++--- src/move.test.c | 191 +++++++++++++++++++++++++++++----------- 3 files changed, 162 insertions(+), 62 deletions(-) diff --git a/res/core/de/strings.xml b/res/core/de/strings.xml index cc252c343..cd408f9ea 100644 --- a/res/core/de/strings.xml +++ b/res/core/de/strings.xml @@ -4754,6 +4754,11 @@ Der Landstrich kann über Jahre hinaus von den Folgen einer solchen Dürre betroffen sein. + This powerful ritual opens a gate to the elemental plane of + fire. A great drought comes over the land. Farmers, animals and + plants of the region are fighting for survival, but only half of + all living things will be able to survive a drought like this. + The region will suffer the consequences of such a drought for years to come. diff --git a/src/move.c b/src/move.c index fd6bf2933..32d325304 100644 --- a/src/move.c +++ b/src/move.c @@ -696,10 +696,14 @@ int check_ship_allowed(struct ship *sh, const region * r) } if (bt_harbour && buildingtype_exists(r, bt_harbour, true)) { - unit* hafenmeister = NULL; - hafenmeister = owner_buildingtyp(r, bt_harbour); - if ((sh->_owner->faction == hafenmeister->faction) || (ucontact(sh->_owner, hafenmeister)) || (alliedunit(sh->_owner, hafenmeister->faction, HELP_GUARD))) + unit* harbourmaster = NULL; + harbourmaster = owner_buildingtyp(r, bt_harbour); + if (!harbourmaster || !sh->_owner) { return SA_HARBOUR; + } + else if ((sh->_owner->faction == harbourmaster->faction) || (ucontact(harbourmaster, sh->_owner)) || (alliedunit(harbourmaster, sh->_owner->faction, HELP_GUARD))) { + return SA_HARBOUR; + } } if (fval(r->terrain, SEA_REGION)) { return SA_COAST; @@ -2060,7 +2064,7 @@ sail(unit * u, order * ord, bool move_on_land, region_list ** routep) * Inland zu segeln versuchte */ if (sh != NULL && fval(sh, SF_MOVED)) { - unit *hafenmeister; + unit *harbourmaster; /* nachdem alle Richtungen abgearbeitet wurden, und alle Einheiten * transferiert wurden, kann der aktuelle Befehl gelöscht werden. */ cycle_route(ord, u, step); @@ -2089,25 +2093,25 @@ sail(unit * u, order * ord, bool move_on_land, region_list ** routep) /* Hafengebühren ? */ - hafenmeister = owner_buildingtyp(current_point, bt_find("harbour")); - if (sh && hafenmeister != NULL) { + harbourmaster = owner_buildingtyp(current_point, bt_find("harbour")); + if (sh && harbourmaster != NULL) { item *itm; unit *u2; item *trans = NULL; for (u2 = current_point->units; u2; u2 = u2->next) { - if (u2->ship == sh && !alliedunit(hafenmeister, u->faction, HELP_GUARD)) { + if (u2->ship == sh && !alliedunit(harbourmaster, u->faction, HELP_GUARD)) { - if (effskill(hafenmeister, SK_PERCEPTION) > effskill(u2, SK_STEALTH)) { + if (effskill(harbourmaster, SK_PERCEPTION) > effskill(u2, SK_STEALTH)) { for (itm = u2->items; itm; itm = itm->next) { const luxury_type *ltype = resource2luxury(itm->type->rtype); if (ltype != NULL && itm->number > 0) { - int st = itm->number * effskill(hafenmeister, SK_TRADE) / 50; + int st = itm->number * effskill(harbourmaster, SK_TRADE) / 50; st = _min(itm->number, st); if (st > 0) { i_change(&u2->items, itm->type, -st); - i_change(&hafenmeister->items, itm->type, st); + i_change(&harbourmaster->items, itm->type, st); i_add(&trans, i_new(itm->type, st)); } } @@ -2117,10 +2121,10 @@ sail(unit * u, order * ord, bool move_on_land, region_list ** routep) } if (trans) { message *msg = - msg_message("harbor_trade", "unit items ship", hafenmeister, trans, + msg_message("harbor_trade", "unit items ship", harbourmaster, trans, u->ship); add_message(&u->faction->msgs, msg); - add_message(&hafenmeister->faction->msgs, msg); + add_message(&harbourmaster->faction->msgs, msg); msg_release(msg); while (trans) i_remove(&trans, trans); diff --git a/src/move.test.c b/src/move.test.c index 90307586a..83c7c7066 100644 --- a/src/move.test.c +++ b/src/move.test.c @@ -3,10 +3,13 @@ #include #include "move.h" +#include #include +#include #include #include #include +#include #include @@ -15,77 +18,165 @@ static void test_ship_not_allowed_in_coast(CuTest * tc) { - region *r1, *r2; - ship * sh; - terrain_type *ttype, *otype; - ship_type *stype; + region *r1, *r2; + ship * sh; + terrain_type *ttype, *otype; + ship_type *stype; - test_cleanup(); - test_create_world(); + test_cleanup(); + test_create_world(); - ttype = test_create_terrain("glacier", LAND_REGION|ARCTIC_REGION|WALK_INTO|SAIL_INTO); - otype = test_create_terrain("ocean", SEA_REGION|SAIL_INTO); - stype = test_create_shiptype("derp"); - stype->coasts = (const struct terrain_type **)calloc(2, sizeof(const struct terrain_type *)); + ttype = test_create_terrain("glacier", LAND_REGION | ARCTIC_REGION | WALK_INTO | SAIL_INTO); + otype = test_create_terrain("ocean", SEA_REGION | SAIL_INTO); + stype = test_create_shiptype("derp"); + stype->coasts = (const struct terrain_type **)calloc(2, sizeof(const struct terrain_type *)); - r1 = test_create_region(0, 0, ttype); - r2 = test_create_region(1, 0, otype); - sh = test_create_ship(0, stype); + r1 = test_create_region(0, 0, ttype); + r2 = test_create_region(1, 0, otype); + sh = test_create_ship(0, stype); - CuAssertIntEquals(tc, SA_COAST, check_ship_allowed(sh, r2)); - CuAssertIntEquals(tc, SA_NO_COAST, check_ship_allowed(sh, r1)); - stype->coasts[0] = ttype; - CuAssertIntEquals(tc, SA_COAST, check_ship_allowed(sh, r1)); + CuAssertIntEquals(tc, SA_COAST, check_ship_allowed(sh, r2)); + CuAssertIntEquals(tc, SA_NO_COAST, check_ship_allowed(sh, r1)); + stype->coasts[0] = ttype; + CuAssertIntEquals(tc, SA_COAST, check_ship_allowed(sh, r1)); } -static void test_ship_allowed_with_harbor(CuTest * tc) +typedef struct move_fixture { + region *r; + ship *sh; + building * b; + unit *u; +} move_fixture; + +static void setup_harbor(move_fixture *mf) { + region *r; + ship * sh; + terrain_type * ttype; + building_type * btype; + building * b; + unit *u; + + test_cleanup(); + test_create_world(); + + ttype = test_create_terrain("glacier", LAND_REGION | ARCTIC_REGION | WALK_INTO | SAIL_INTO); + btype = test_create_buildingtype("harbour"); + + sh = test_create_ship(0, 0); + r = test_create_region(0, 0, ttype); + + b = test_create_building(r, btype); + b->flags |= BLD_WORKING; + + u = test_create_unit(test_create_faction(0), r); + u->ship = sh; + ship_set_owner(u); + + mf->r = r; + mf->u = u; + mf->sh = sh; + mf->b = b; +} + +static void test_ship_allowed_without_harbormaster(CuTest * tc) { - region *r; - ship * sh; - terrain_type * ttype; - building_type * btype; - building * b; + move_fixture mf; - test_cleanup(); - test_create_world(); + setup_harbor(&mf); - ttype = test_create_terrain("glacier", LAND_REGION|ARCTIC_REGION|WALK_INTO|SAIL_INTO); - btype = test_create_buildingtype("harbour"); + CuAssertIntEquals(tc, SA_HARBOUR, check_ship_allowed(mf.sh, mf.r)); +} - r = test_create_region(0, 0, ttype); - sh = test_create_ship(0, 0); +static void test_ship_blocked_by_harbormaster(CuTest * tc) { + unit *u; + move_fixture mf; - b = test_create_building(r, btype); - b->flags |= BLD_WORKING; - CuAssertIntEquals(tc, SA_HARBOUR, check_ship_allowed(sh, r)); + setup_harbor(&mf); + + u = test_create_unit(test_create_faction(0), mf.r); + u->building = mf.b; + building_set_owner(u); + + CuAssertIntEquals_Msg(tc, "harbor master must contact ship", SA_NO_COAST, check_ship_allowed(mf.sh, mf.r)); + test_cleanup(); +} + +static void test_ship_has_harbormaster_contact(CuTest * tc) { + unit *u; + move_fixture mf; + + setup_harbor(&mf); + + u = test_create_unit(test_create_faction(0), mf.r); + u->building = mf.b; + building_set_owner(u); + usetcontact(mf.b->_owner, mf.sh->_owner); + + CuAssertIntEquals(tc, SA_HARBOUR, check_ship_allowed(mf.sh, mf.r)); + test_cleanup(); +} + +static void test_ship_has_harbormaster_same_faction(CuTest * tc) { + unit *u; + move_fixture mf; + + setup_harbor(&mf); + + u = test_create_unit(mf.u->faction, mf.r); + u->building = mf.b; + building_set_owner(u); + + CuAssertIntEquals(tc, SA_HARBOUR, check_ship_allowed(mf.sh, mf.r)); + test_cleanup(); +} + +static void test_ship_has_harbormaster_ally(CuTest * tc) { + unit *u; + move_fixture mf; + ally *al; + + setup_harbor(&mf); + + u = test_create_unit(test_create_faction(0), mf.r); + u->building = mf.b; + building_set_owner(u); + al = ally_add(&u->faction->allies, mf.u->faction); + al->status = HELP_GUARD; + + CuAssertIntEquals(tc, SA_HARBOUR, check_ship_allowed(mf.sh, mf.r)); + test_cleanup(); } static void test_building_type_exists(CuTest * tc) { - region *r; - building *b; - building_type *btype, *btype2; + region *r; + building *b; + building_type *btype, *btype2; - test_cleanup(); - test_create_world(); + test_cleanup(); + test_create_world(); - btype2 = bt_get_or_create("lighthouse"); - btype = bt_get_or_create("castle"); + btype2 = bt_get_or_create("lighthouse"); + btype = bt_get_or_create("castle"); - r = findregion(-1, 0); - b = new_building(btype, r, default_locale); + r = findregion(-1, 0); + b = new_building(btype, r, default_locale); - CuAssertPtrNotNull(tc, b); - CuAssertTrue(tc, !buildingtype_exists(r, NULL, false)); - CuAssertTrue(tc, buildingtype_exists(r, btype, false)); - CuAssertTrue(tc, !buildingtype_exists(r, btype2, false)); + CuAssertPtrNotNull(tc, b); + CuAssertTrue(tc, !buildingtype_exists(r, NULL, false)); + CuAssertTrue(tc, buildingtype_exists(r, btype, false)); + CuAssertTrue(tc, !buildingtype_exists(r, btype2, false)); } CuSuite *get_move_suite(void) { - CuSuite *suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, test_building_type_exists); - SUITE_ADD_TEST(suite, test_ship_not_allowed_in_coast); - SUITE_ADD_TEST(suite, test_ship_allowed_with_harbor); - return suite; + CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_building_type_exists); + SUITE_ADD_TEST(suite, test_ship_not_allowed_in_coast); + SUITE_ADD_TEST(suite, test_ship_allowed_without_harbormaster); + SUITE_ADD_TEST(suite, test_ship_blocked_by_harbormaster); + SUITE_ADD_TEST(suite, test_ship_has_harbormaster_contact); + SUITE_ADD_TEST(suite, test_ship_has_harbormaster_ally); + SUITE_ADD_TEST(suite, test_ship_has_harbormaster_same_faction); + return suite; }