From 6637c9485298c63fcb456eef2160bca4e953dcc3 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 1 May 2019 20:46:26 +0200 Subject: [PATCH] do not allow transfer of heros and limited units. --- src/give.c | 32 ++++++++++++++----------- src/give.h | 2 ++ src/laws.c | 62 ++++++++++++++++++++++++++++--------------------- src/laws.test.c | 46 ++++++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 40 deletions(-) diff --git a/src/give.c b/src/give.c index c6e77aa68..5f9127b23 100644 --- a/src/give.c +++ b/src/give.c @@ -299,7 +299,7 @@ static bool can_give_men(const unit *u, const unit *dst, order *ord, message **m return false; } -static bool rule_transfermen(void) +bool rule_transfermen(void) { int rule = config_get_int("rules.transfermen", 1); return rule != 0; @@ -472,9 +472,23 @@ message * disband_men(int n, unit * u, struct order *ord) { return msg_message("give_person_peasants", "unit amount", u, n); } +int give_unit_allowed(const unit * u) +{ + if (unit_has_cursed_item(u)) { + return 78; + } + if (fval(u, UFL_HERO)) { + return 75; + } + if (fval(u, UFL_LOCKED) || fval(u, UFL_HUNGER)) { + return 74; + } + return 0; +} + void give_unit(unit * u, unit * u2, order * ord) { - int maxt = max_transfers(); + int err, maxt = max_transfers(); assert(u); if (!rule_transfermen() && u2 && u->faction != u2->faction) { @@ -482,17 +496,9 @@ void give_unit(unit * u, unit * u2, order * ord) return; } - if (unit_has_cursed_item(u)) { - cmistake(u, ord, 78, MSG_COMMERCE); - return; - } - - if (fval(u, UFL_HERO)) { - cmistake(u, ord, 75, MSG_COMMERCE); - return; - } - if (fval(u, UFL_LOCKED) || fval(u, UFL_HUNGER)) { - cmistake(u, ord, 74, MSG_COMMERCE); + err = give_unit_allowed(u); + if (err != 0) { + cmistake(u, ord, err, MSG_COMMERCE); return; } diff --git a/src/give.h b/src/give.h index 94eee729c..4d44790a7 100644 --- a/src/give.h +++ b/src/give.h @@ -29,10 +29,12 @@ extern "C" { struct message * disband_men(int n, struct unit * u, struct order *ord); struct message * give_men(int n, struct unit *u, struct unit *u2, struct order *ord); + int give_unit_allowed(const struct unit * u); void give_unit(struct unit *u, struct unit *u2, struct order *ord); void give_cmd(struct unit * u, struct order * ord); struct message * check_give(const struct unit * u, const struct unit * u2, struct order *ord); bool can_give_to(struct unit *u, struct unit *u2); + bool rule_transfermen(void); #ifdef __cplusplus } diff --git a/src/laws.c b/src/laws.c index d6c754f08..9e9e337b1 100644 --- a/src/laws.c +++ b/src/laws.c @@ -30,6 +30,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "battle.h" #include "contact.h" #include "economy.h" +#include "give.h" #include "market.h" #include "morale.h" #include "monsters.h" @@ -940,8 +941,13 @@ int leave_cmd(unit * u, struct order *ord) return 0; } -int transfer_faction(faction *fsrc, faction *fdst) { - return 0; +void transfer_faction(faction *fsrc, faction *fdst) { + unit *u; + for (u = fsrc->units; u != NULL; u = u->nextF) { + if (give_unit_allowed(u) == 0) { + u_setfaction(u, fdst); + } + } } int quit_cmd(unit * u, struct order *ord) @@ -955,35 +961,37 @@ int quit_cmd(unit * u, struct order *ord) assert(kwd == K_QUIT); passwd = gettoken(token, sizeof(token)); if (checkpasswd(f, (const char *)passwd)) { - param_t p; - p = getparam(f->locale); - if (p == P_FACTION) { - faction *f2 = getfaction(); - if (f2 == NULL) { - cmistake(u, ord, 66, MSG_EVENT); - } - else if (f->race != f2->race) { - cmistake(u, ord, 281, MSG_EVENT); - } - else { - unit *u2; - for (u2 = u->region->units; u2; u2 = u2->next) { - if (u2->faction == f2 && ucontact(u2, u)) { - int err = transfer_faction(u->faction, u2->faction); - if (err != 0) { - /* something went wrong */ - cmistake(u, ord, err, MSG_EVENT); - } - break; - } + int flags = FFL_QUIT; + if (rule_transfermen()) { + param_t p; + p = getparam(f->locale); + if (p == P_FACTION) { + faction *f2 = getfaction(); + if (f2 == NULL) { + cmistake(u, ord, 66, MSG_EVENT); + flags = 0; } - if (u2 == NULL) { - /* no target unit found */ - cmistake(u, ord, 0, MSG_EVENT); + else if (f->race != f2->race) { + cmistake(u, ord, 281, MSG_EVENT); + flags = 0; + } + else { + unit *u2; + for (u2 = u->region->units; u2; u2 = u2->next) { + if (u2->faction == f2 && ucontact(u2, u)) { + transfer_faction(u->faction, u2->faction); + break; + } + } + if (u2 == NULL) { + /* no target unit found */ + cmistake(u, ord, 0, MSG_EVENT); + flags = 0; + } } } } - fset(f, FFL_QUIT); + f->flags |= flags; } else { char buffer[64]; diff --git a/src/laws.test.c b/src/laws.test.c index cead8605a..573e1a486 100644 --- a/src/laws.test.c +++ b/src/laws.test.c @@ -1,6 +1,7 @@ #include #include "laws.h" #include "battle.h" +#include "contact.h" #include "guard.h" #include "monsters.h" @@ -1868,6 +1869,49 @@ static void test_long_order_on_ocean(CuTest *tc) { test_teardown(); } +static void test_quit(CuTest *tc) { + faction *f; + unit *u; + region *r; + + test_setup(); + r = test_create_plain(0, 0); + f = test_create_faction(NULL); + u = test_create_unit(f, r); + u->thisorder = create_order(K_QUIT, f->locale, "password"); + + faction_setpassword(f, "passwort"); + quit_cmd(u, u->thisorder); + CuAssertIntEquals(tc, 0, f->flags & FFL_QUIT); + + faction_setpassword(f, "password"); + quit_cmd(u, u->thisorder); + CuAssertIntEquals(tc, FFL_QUIT, f->flags & FFL_QUIT); + + test_teardown(); +} + +static void test_quit_transfer(CuTest *tc) { + faction *f1, *f2; + unit *u1, *u2; + region *r; + + test_setup(); + r = test_create_plain(0, 0); + f1 = test_create_faction(NULL); + faction_setpassword(f1, "password"); + u1 = test_create_unit(f1, r); + f2 = test_create_faction(NULL); + u2 = test_create_unit(f2, r); + contact_unit(u2, u1); + u1->thisorder = create_order(K_QUIT, f1->locale, "password %s %s", + LOC(f1->locale, parameters[P_FACTION]), itoa36(f2->no)); + quit_cmd(u1, u1->thisorder); + CuAssertIntEquals(tc, FFL_QUIT, f1->flags & FFL_QUIT); + CuAssertPtrEquals(tc, f2, u1->faction); + test_teardown(); +} + CuSuite *get_laws_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -1943,6 +1987,8 @@ CuSuite *get_laws_suite(void) SUITE_ADD_TEST(suite, test_nmr_timeout); SUITE_ADD_TEST(suite, test_long_orders); SUITE_ADD_TEST(suite, test_long_order_on_ocean); + SUITE_ADD_TEST(suite, test_quit); + SUITE_ADD_TEST(suite, test_quit_transfer); return suite; }