diff --git a/src/give.test.c b/src/give.test.c index 604e42549..33a9ebfd9 100644 --- a/src/give.test.c +++ b/src/give.test.c @@ -88,6 +88,7 @@ static void test_give_unit_limits(CuTest * tc) { CuAssertIntEquals(tc, 0, env.f2->newbies); CuAssertIntEquals(tc, 1, env.f1->num_units); CuAssertIntEquals(tc, 1, env.f2->num_units); + CuAssertPtrNotNull(tc, test_find_messagetype(env.f1->msgs, "too_many_units_in_faction")); test_cleanup(); } diff --git a/src/kernel/alliance.c b/src/kernel/alliance.c index 0feb8407d..910670d10 100644 --- a/src/kernel/alliance.c +++ b/src/kernel/alliance.c @@ -239,8 +239,25 @@ static void perform_transfer(void) } } +bool num_units_cb(void *entry, void *more) { + faction *f = (faction *)entry; + int *num = (int *)more; + *num += f->num_units; + return true; +} + +int alliance_size(const alliance *al) +{ + int num = 0; + if (al) { + selist_foreach_ex(al->members, num_units_cb, &num); + } + return num; +} + static void perform_join(void) { + int alimit = rule_alliance_limit(); alliance_transaction **tap = transactions + ALLIANCE_JOIN; while (*tap) { alliance_transaction *ta = *tap; @@ -270,7 +287,16 @@ static void perform_join(void) ti = *tip; } if (ti) { - setalliance(fj, al); + int maxsize = (alimit > 0) ? (alimit - alliance_size(al)) : 0; + if (alimit > 0 && fj->num_units > maxsize) { + ADDMSG(&fj->msgs, + msg_feedback(ta->u, ta->ord, + "too_many_units_in_alliance", + "allowed", alimit)); + } + else { + setalliance(fj, al); + } *tip = ti->next; free(ti); } diff --git a/src/kernel/alliance.h b/src/kernel/alliance.h index 8e112e8c9..00b4b29e4 100644 --- a/src/kernel/alliance.h +++ b/src/kernel/alliance.h @@ -67,7 +67,7 @@ extern "C" { struct faction *alliance_get_leader(struct alliance *al); void alliance_cmd(void); bool is_allied(const struct faction *f1, const struct faction *f2); - + int alliance_size(const struct alliance *al); /* #units in the alliance */ void alliance_setname(alliance * self, const char *name); /* execute commands */ diff --git a/src/kernel/alliance.test.c b/src/kernel/alliance.test.c index f63767672..885bc8413 100644 --- a/src/kernel/alliance.test.c +++ b/src/kernel/alliance.test.c @@ -112,6 +112,29 @@ static void test_alliance_cmd(CuTest *tc) { test_cleanup(); } +static void test_alliance_limits(CuTest *tc) { + unit *u1, *u2; + struct region *r; + + test_setup(); + r = test_create_region(0, 0, 0); + u1 = test_create_unit(test_create_faction(0), r); + u2 = test_create_unit(test_create_faction(0), r); + + config_set("rules.limit.alliance", "1"); + unit_addorder(u1, create_order(K_ALLIANCE, u1->faction->locale, "%s %s", alliance_kwd[ALLIANCE_NEW], itoa36(42))); + unit_addorder(u1, create_order(K_ALLIANCE, u1->faction->locale, "%s %s", alliance_kwd[ALLIANCE_INVITE], itoa36(u2->faction->no))); + unit_addorder(u2, create_order(K_ALLIANCE, u1->faction->locale, "%s %s", alliance_kwd[ALLIANCE_JOIN], itoa36(42))); + CuAssertTrue(tc, !is_allied(u1->faction, u2->faction)); + CuAssertPtrEquals(tc, 0, f_get_alliance(u1->faction)); + alliance_cmd(); + CuAssertPtrNotNull(tc, f_get_alliance(u1->faction)); + CuAssertPtrEquals(tc, 0, f_get_alliance(u2->faction)); + CuAssertTrue(tc, !is_allied(u1->faction, u2->faction)); + CuAssertPtrNotNull(tc, test_find_messagetype(u2->faction->msgs, "too_many_units_in_alliance")); + test_cleanup(); +} + static void test_alliance_cmd_kick(CuTest *tc) { unit *u1, *u2; struct region *r; @@ -200,6 +223,7 @@ CuSuite *get_alliance_suite(void) SUITE_ADD_TEST(suite, test_alliance_dead_faction); SUITE_ADD_TEST(suite, test_alliance_make); SUITE_ADD_TEST(suite, test_alliance_join); + SUITE_ADD_TEST(suite, test_alliance_limits); SUITE_ADD_TEST(suite, test_alliance_cmd); SUITE_ADD_TEST(suite, test_alliance_cmd_no_invite); SUITE_ADD_TEST(suite, test_alliance_cmd_kick); diff --git a/src/laws.c b/src/laws.c index 9c25ac461..736510cd2 100644 --- a/src/laws.c +++ b/src/laws.c @@ -3028,20 +3028,10 @@ int checkunitnumber(const faction * f, int add) alimit = rule_alliance_limit(); if (alimit) { - faction *f2; - int unitsinalliance = fno; - if (unitsinalliance > alimit) { + int unitsinalliance = alliance_size(f->alliance); + if (unitsinalliance + add > alimit) { return 1; } - - for (f2 = factions; f2; f2 = f2->next) { - if (f != f2 && f->alliance == f2->alliance) { - unitsinalliance += f2->num_units; - if (unitsinalliance > alimit) { - return 1; - } - } - } } return 0;