From d35181b5d6922331be62f4c0ef4499df943d8763 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 1 Jun 2021 20:35:40 +0200 Subject: [PATCH 1/3] ignore lines that contain only whitespace. --- src/orderfile.c | 72 +++++++++++++++++++++++++---------------------- src/util/parser.c | 2 +- src/util/parser.h | 1 + 3 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/orderfile.c b/src/orderfile.c index 582d1fc56..11efa31a9 100644 --- a/src/orderfile.c +++ b/src/orderfile.c @@ -95,51 +95,55 @@ static void handle_unit(void *userData, int no) { static void handle_order(void *userData, const char *str) { parser_state *state = (parser_state *)userData; - const char * tok, *input = str; + const char * tok, *input; char buffer[64]; const struct locale *lang; - param_t p; faction * f = state->f; lang = f ? f->locale : default_locale; + ltrim(&str); + if (*str == 0) return; + input = str; tok = parse_token(&input, buffer, sizeof(buffer)); - p = findparam(tok, lang); - if (p == P_FACTION || p == P_GAMENAME) { - tok = parse_token(&input, buffer, sizeof(buffer)); - if (tok) { - int no = atoi36(tok); + if (tok) { + param_t p = findparam(tok, lang); + if (p == P_FACTION || p == P_GAMENAME) { tok = parse_token(&input, buffer, sizeof(buffer)); - handle_faction(userData, no, tok); + if (tok) { + int no = atoi36(tok); + tok = parse_token(&input, buffer, sizeof(buffer)); + handle_faction(userData, no, tok); + } + else { + /* TODO: log_error() */ + } } - else { - /* TODO: log_error() */ + else if (p == P_UNIT) { + tok = parse_token(&input, buffer, sizeof(buffer)); + if (tok) { + int no = atoi36(tok); + handle_unit(userData, no); + } } - } - else if (p == P_UNIT) { - tok = parse_token(&input, buffer, sizeof(buffer)); - if (tok) { - int no = atoi36(tok); - handle_unit(userData, no); + else if (p == P_NEXT) { + state->f = NULL; + state->u = NULL; + state->next_order = NULL; } - } - else if (p == P_NEXT) { - state->f = NULL; - state->u = NULL; - state->next_order = NULL; - } - else if (p == P_REGION) { - state->u = NULL; - state->next_order = NULL; - } - else if (state->u) { - unit * u = state->u; - order * ord = parse_order(str, lang); - if (ord) { - *state->next_order = ord; - state->next_order = &ord->next; + else if (p == P_REGION) { + state->u = NULL; + state->next_order = NULL; } - else { - ADDMSG(&u->faction->msgs, msg_message("parse_error", "unit command", u, str)); + else if (state->u) { + unit *u = state->u; + order *ord = parse_order(str, lang); + if (ord) { + *state->next_order = ord; + state->next_order = &ord->next; + } + else { + ADDMSG(&u->faction->msgs, msg_message("parse_error", "unit command", u, str)); + } } } } diff --git a/src/util/parser.c b/src/util/parser.c index 794c1b856..506e8ce59 100644 --- a/src/util/parser.c +++ b/src/util/parser.c @@ -26,7 +26,7 @@ static parse_state *states; #define TRIMMED(wc) (iswspace(wc) || iswcntrl(wc) || (wc) == 160 || (wc) == 8199 || (wc) == 8239) -static int ltrim(const char **str_p) +int ltrim(const char **str_p) { int ret = 0; wint_t wc; diff --git a/src/util/parser.h b/src/util/parser.h index a08133775..5ac418789 100644 --- a/src/util/parser.h +++ b/src/util/parser.h @@ -22,6 +22,7 @@ extern "C" { int getint(void); int getid(void); unsigned int atoip(const char *s); + int ltrim(const char **str_p); #ifdef __cplusplus } From 1711812b0beb901f7ea49f069e4c64c852cdcc58 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 10 Jun 2021 22:21:15 +0200 Subject: [PATCH 2/3] VERTREIBE Kommando (expel). Braucht noch Fehlermeldungen. --- conf/keywords.json | 11 ++- res/translations/strings.de.po | 4 + res/translations/strings.en.po | 4 + src/laws.c | 56 ++++++++++- src/laws.h | 1 + src/laws.test.c | 55 +++++++++++ src/sort.c | 173 +++++++++++++++++---------------- src/sort.h | 3 + src/spy.c | 2 +- src/util/keyword.c | 3 +- src/util/keyword.h | 1 + 11 files changed, 220 insertions(+), 93 deletions(-) diff --git a/conf/keywords.json b/conf/keywords.json index b35147472..ac3d71671 100644 --- a/conf/keywords.json +++ b/conf/keywords.json @@ -1,11 +1,11 @@ { "keywords": { "en" : { - "plant": "PLANT", - "grow": [ "GROW", "BREED" ], - "promote": ["PROMOTE", "PROMOTION" ], - "locale": ["LANGUAGE", "LOCALE"], - "combat": [ "COMBAT", "FIGHT" ] + "plant": "PLANT", + "grow": [ "GROW", "BREED" ], + "promote": ["PROMOTE", "PROMOTION" ], + "locale": ["LANGUAGE", "LOCALE"], + "combat": [ "COMBAT", "FIGHT" ] }, "de": { "//" : "//", @@ -36,6 +36,7 @@ "maketemp": ["MACHE TEMP", "MACHETEMP"], "move" : "NACH", "password" : "PASSWORT", + "expel" : "VERTREIBE", "loot" : ["PLÜNDERE", "PLÜNDERN"], "recruit": ["REKRUTIERE", "REKRUTIEREN"], "reserve": ["RESERVIERE", "RESERVIEREN"], diff --git a/res/translations/strings.de.po b/res/translations/strings.de.po index 16be866d0..596e318d0 100644 --- a/res/translations/strings.de.po +++ b/res/translations/strings.de.po @@ -2496,6 +2496,10 @@ msgctxt "keyword" msgid "loot" msgstr "PLÜNDERE" +msgctxt "keyword" +msgid "expel" +msgstr "VERTREIBE" + msgctxt "calendar" msgid "month_1" msgstr "Feldsegen" diff --git a/res/translations/strings.en.po b/res/translations/strings.en.po index 6d5c8bdaf..73b899091 100644 --- a/res/translations/strings.en.po +++ b/res/translations/strings.en.po @@ -2167,6 +2167,10 @@ msgctxt "keyword" msgid "loot" msgstr "loot" +msgctxt "keyword" +msgid "expel" +msgstr "EXPEL" + msgctxt "keyword" msgid "guard" msgstr "GUARD" diff --git a/src/laws.c b/src/laws.c index e921a5530..fc9a2b834 100644 --- a/src/laws.c +++ b/src/laws.c @@ -3939,11 +3939,12 @@ void init_processor(void) add_proc_global(p, defaultorders, "Defaults setzen"); } add_proc_global(p, demographics, "Nahrung, Seuchen, Wachstum, Wanderung"); + p += 10; if (!keyword_disabled(K_SORT)) { - p += 10; - add_proc_global(p, restack_units, "Einheiten sortieren"); + add_proc_region(p, do_sort, "Einheiten sortieren"); } + add_proc_order(p, K_EXPEL, expel_cmd, 0, "Einheiten verjagen"); if (!keyword_disabled(K_NUMBER)) { add_proc_order(p, K_NUMBER, renumber_cmd, 0, "Neue Nummern (Einheiten)"); p += 10; @@ -4187,3 +4188,54 @@ int locale_cmd(unit * u, order * ord) } return 0; } + +static void expel_building(unit *u, unit *u2, order *ord) { + building *b = u->building; + + if (u != building_owner(b)) { + /* error: must be the owner */ + cmistake(u, ord, 5, MSG_EVENT); + } + else { + leave_building(u2); + } +} + +static void expel_ship(unit *u, unit *u2, order *ord) { + ship *sh = u->ship; + if (u != ship_owner(sh)) { + /* error: must be the owner */ + cmistake(u, ord, 146, MSG_EVENT); + } + else if (!u->region->land) { + /* error: must not be at sea */ + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "error_onlandonly", NULL)); + } + else { + leave_ship(u2); + } +} + +int expel_cmd(unit *u, order *ord) { + faction *f = u->faction; + unit *u2; + init_order(ord, f->locale); + getunit(u->region, u->faction, &u2); + if (u2 == NULL) { + /* error: target unit not found */ + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "feedback_unit_not_found", NULL)); + return 0; + } + if (u->building) { + expel_building(u, u2, ord); + } + else if (u->ship) { + expel_ship(u, u2, ord); + } + else { + /* error: unit must be owner of a ship or building */ + } + return 0; +} diff --git a/src/laws.h b/src/laws.h index f165ad6da..7fdd03863 100755 --- a/src/laws.h +++ b/src/laws.h @@ -50,6 +50,7 @@ extern "C" { bool long_order_allowed(const struct unit *u, bool flags_only); bool password_wellformed(const char *password); + int expel_cmd(struct unit *u, struct order *ord); int locale_cmd(struct unit *u, struct order *ord); int password_cmd(struct unit *u, struct order *ord); int banner_cmd(struct unit *u, struct order *ord); diff --git a/src/laws.test.c b/src/laws.test.c index 3726bbca0..e57118088 100644 --- a/src/laws.test.c +++ b/src/laws.test.c @@ -173,6 +173,59 @@ static void test_enter_ship(CuTest * tc) test_teardown(); } +static void test_expel_building(CuTest *tc) { + unit *u1, *u2; + order *ord; + building *b; + + test_setup(); + u1 = test_create_unit(test_create_faction(), test_create_plain(0, 0)); + u2 = test_create_unit(test_create_faction(), u1->region); + b = u2->building = u1->building = test_create_building(u1->region, NULL); + CuAssertPtrEquals(tc, u1, building_owner(b)); + + ord = create_order(K_EXPEL, u2->faction->locale, "%s", itoa36(u1->no)); + expel_cmd(u2, ord); + /* Nothing happened: */ + CuAssertPtrEquals(tc, u1, building_owner(b)); + CuAssertPtrEquals(tc, b, u1->building); + CuAssertPtrEquals(tc, b, u2->building); + free_order(ord); + + ord = create_order(K_EXPEL, u1->faction->locale, "%s", itoa36(u2->no)); + expel_cmd(u1, ord); + /* owner has expelled u2: */ + CuAssertPtrEquals(tc, NULL, u2->building); + test_teardown(); +} + +static void test_expel_ship(CuTest *tc) { + unit *u1, *u2; + order *ord; + ship *sh; + + test_setup(); + u1 = test_create_unit(test_create_faction(), test_create_plain(0, 0)); + u2 = test_create_unit(test_create_faction(), u1->region); + sh = u2->ship = u1->ship = test_create_ship(u1->region, NULL); + CuAssertPtrEquals(tc, u1, ship_owner(sh)); + + ord = create_order(K_EXPEL, u2->faction->locale, "%s", itoa36(u1->no)); + expel_cmd(u2, ord); + /* Nothing happened: */ + CuAssertPtrEquals(tc, u1, ship_owner(sh)); + CuAssertPtrEquals(tc, sh, u1->ship); + CuAssertPtrEquals(tc, sh, u2->ship); + free_order(ord); + + ord = create_order(K_EXPEL, u1->faction->locale, "%s", itoa36(u2->no)); + expel_cmd(u1, ord); + /* owner has expelled u2: */ + CuAssertPtrEquals(tc, NULL, u2->ship); + CuAssertPtrEquals(tc, sh, leftship(u2)); + test_teardown(); +} + static void test_display_cmd(CuTest *tc) { unit *u; faction *f; @@ -2320,6 +2373,8 @@ CuSuite *get_laws_suite(void) SUITE_ADD_TEST(suite, test_enter_building); SUITE_ADD_TEST(suite, test_enter_ship); SUITE_ADD_TEST(suite, test_display_cmd); + SUITE_ADD_TEST(suite, test_expel_building); + SUITE_ADD_TEST(suite, test_expel_ship); SUITE_ADD_TEST(suite, test_rule_force_leave); SUITE_ADD_TEST(suite, test_force_leave_buildings); SUITE_ADD_TEST(suite, test_force_leave_ships); diff --git a/src/sort.c b/src/sort.c index 150f35785..3d688645a 100644 --- a/src/sort.c +++ b/src/sort.c @@ -13,7 +13,7 @@ #include "util/param.h" #include "util/parser.h" -void sort_before(unit *v, unit **up) { +static void sort_before(unit *v, unit **up) { unit *u = *up; region *r = u->region; unit **vp = &r->units; @@ -24,102 +24,107 @@ void sort_before(unit *v, unit **up) { u->next = v; } -void restack_units(void) +void do_sort(region *r) { - region *r; - for (r = regions; r; r = r->next) { - unit **up = &r->units; - bool sorted = false; - while (*up) { - unit *u = *up; - if (!fval(u, UFL_MARK) && !is_paused(u->faction)) { - struct order *ord; - for (ord = u->orders; ord; ord = ord->next) { - if (getkeyword(ord) == K_SORT) { - char token[128]; - const char *s; - param_t p; - int id; - unit *v; + unit **up = &r->units; + bool sorted = false; + while (*up) { + unit *u = *up; + if (!fval(u, UFL_MARK) && !is_paused(u->faction)) { + struct order *ord; + for (ord = u->orders; ord; ord = ord->next) { + if (getkeyword(ord) == K_SORT) { + char token[128]; + const char *s; + param_t p; + int id; + unit *v; - init_order(ord, NULL); - s = gettoken(token, sizeof(token)); - p = findparam(s, u->faction->locale); - id = getid(); - v = findunit(id); + init_order(ord, NULL); + s = gettoken(token, sizeof(token)); + p = findparam(s, u->faction->locale); + id = getid(); + v = findunit(id); - if (v == u) { - syntax_error(u, ord); - } - else if (!v || v->region != r) { - cmistake(u, ord, 258, MSG_EVENT); - } - else if (v->faction != u->faction && !is_paused(v->faction)) { - cmistake(u, ord, 258, MSG_EVENT); - } - else if (v->building != u->building || v->ship != u->ship) { - cmistake(u, ord, 259, MSG_EVENT); - } - else if (u->building && building_owner(u->building) == u) { - cmistake(u, ord, 260, MSG_EVENT); - } - else if (u->ship && ship_owner(u->ship) == u) { - cmistake(u, ord, 260, MSG_EVENT); - } - else { - switch (p) { - case P_AFTER: - *up = u->next; - u->next = v->next; - v->next = u; - fset(u, UFL_MARK); - sorted = true; - break; - case P_BEFORE: - if (v->ship && ship_owner(v->ship) == v) { - if (is_paused(v->faction)) { - sort_before(v, up); - ship_set_owner(u); - } - else { - cmistake(v, ord, 261, MSG_EVENT); - break; - } - } - else if (v->building && building_owner(v->building) == v) { - if (is_paused(v->faction)) { - sort_before(v, up); - building_set_owner(u); - } - else { - cmistake(v, ord, 261, MSG_EVENT); - break; - } + if (v == u) { + syntax_error(u, ord); + } + else if (!v || v->region != r) { + cmistake(u, ord, 258, MSG_EVENT); + } + else if (v->faction != u->faction && !is_paused(v->faction)) { + cmistake(u, ord, 258, MSG_EVENT); + } + else if (v->building != u->building || v->ship != u->ship) { + cmistake(u, ord, 259, MSG_EVENT); + } + else if (u->building && building_owner(u->building) == u) { + cmistake(u, ord, 260, MSG_EVENT); + } + else if (u->ship && ship_owner(u->ship) == u) { + cmistake(u, ord, 260, MSG_EVENT); + } + else { + switch (p) { + case P_AFTER: + *up = u->next; + u->next = v->next; + v->next = u; + fset(u, UFL_MARK); + sorted = true; + break; + case P_BEFORE: + if (v->ship && ship_owner(v->ship) == v) { + if (is_paused(v->faction)) { + sort_before(v, up); + ship_set_owner(u); } else { - sort_before(v, up); + cmistake(v, ord, 261, MSG_EVENT); + break; } - fset(u, UFL_MARK); - sorted = true; - break; - default: - /* TODO: syntax error message? */ - break; } + else if (v->building && building_owner(v->building) == v) { + if (is_paused(v->faction)) { + sort_before(v, up); + building_set_owner(u); + } + else { + cmistake(v, ord, 261, MSG_EVENT); + break; + } + } + else { + sort_before(v, up); + } + fset(u, UFL_MARK); + sorted = true; + break; + default: + /* TODO: syntax error message? */ + break; } - break; } + break; } } - if (u == *up) - up = &u->next; } - if (sorted) { - unit *u; - for (u = r->units; u; u = u->next) { - freset(u, UFL_MARK); - } + if (u == *up) + up = &u->next; + } + if (sorted) { + unit *u; + for (u = r->units; u; u = u->next) { + freset(u, UFL_MARK); } } } +void restack_units(void) +{ + region *r; + for (r = regions; r; r = r->next) { + do_sort(r); + } +} + diff --git a/src/sort.h b/src/sort.h index d2228fa1c..cc1033799 100644 --- a/src/sort.h +++ b/src/sort.h @@ -1,3 +1,6 @@ #pragma once +struct region; + void restack_units(void); +void do_sort(struct region *r); diff --git a/src/spy.c b/src/spy.c index 063adfca7..c6d2881de 100644 --- a/src/spy.c +++ b/src/spy.c @@ -119,7 +119,7 @@ int spy_cmd(unit * u, struct order *ord) if (!target) { ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "feedback_unit_not_found", "")); + msg_feedback(u, u->thisorder, "feedback_unit_not_found", NULL)); return 0; } if (effskill(u, SK_SPY, NULL) < 1) { diff --git a/src/util/keyword.c b/src/util/keyword.c index 19829f830..df397b3d5 100644 --- a/src/util/keyword.c +++ b/src/util/keyword.c @@ -156,7 +156,8 @@ const char *keywords[MAXKEYWORDS] = { "promote", "pay", "loot", + "expel", "autostudy", - "locale", + "locale" }; diff --git a/src/util/keyword.h b/src/util/keyword.h index 0dcb44ce5..fb51edd5e 100644 --- a/src/util/keyword.h +++ b/src/util/keyword.h @@ -71,6 +71,7 @@ extern "C" K_PROMOTION, K_PAY, K_LOOT, + K_EXPEL, K_AUTOSTUDY, K_LOCALE, MAXKEYWORDS, From 592601601074ec29962ba718eb182fd97532781f Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 11 Jun 2021 21:02:30 +0200 Subject: [PATCH 3/3] EXPEL: additional messages and tests. --- res/core/messages.xml | 7 ++++++ res/translations/messages.de.po | 3 +++ res/translations/messages.en.po | 3 +++ src/battle.c | 28 ++++++++++++---------- src/laws.c | 16 +++++++++++-- src/laws.test.c | 41 +++++++++++++++++++++++++++++++-- 6 files changed, 82 insertions(+), 16 deletions(-) diff --git a/res/core/messages.xml b/res/core/messages.xml index 5b8ccdd72..1423a1efb 100644 --- a/res/core/messages.xml +++ b/res/core/messages.xml @@ -4732,6 +4732,13 @@ + + + + + + + diff --git a/res/translations/messages.de.po b/res/translations/messages.de.po index 81a366ff7..7df50e031 100644 --- a/res/translations/messages.de.po +++ b/res/translations/messages.de.po @@ -590,6 +590,9 @@ msgstr "\"$unit($unit) in $region($region): '$order($command)' - Um in Gletscher msgid "feedback_unit_not_found" msgstr "\"$unit($unit) in $region($region): '$order($command)' - Die Einheit wurde nicht gefunden.\"" +msgid "feedback_not_inside" +msgstr "\"$unit($unit) in $region($region): '$order($command)' - Die Einheit kontrolliert kein Schiff oder Gebäude.\"" + msgid "error206" msgstr "\"$unit($unit) in $region($region): '$order($command)' - Auf dem Gebäude liegt bereits so ein Zauber.\"" diff --git a/res/translations/messages.en.po b/res/translations/messages.en.po index 9eba8090e..c9124a770 100644 --- a/res/translations/messages.en.po +++ b/res/translations/messages.en.po @@ -590,6 +590,9 @@ msgstr "\"$unit($unit) in $region($region): '$order($command)' - You must build msgid "feedback_unit_not_found" msgstr "\"$unit($unit) in $region($region): '$order($command)' - The unit could not be found.\"" +msgid "feedback_unit_not_found" +msgstr "\"$unit($unit) in $region($region): '$order($command)' - The unit is not the owner of a ship or building.\"" + msgid "error206" msgstr "\"$unit($unit) in $region($region): '$order($command)' - There is alrady a spell on that building.\"" diff --git a/src/battle.c b/src/battle.c index e2379c0e7..c32296ec1 100644 --- a/src/battle.c +++ b/src/battle.c @@ -3925,21 +3925,25 @@ void force_leave(region *r, battle *b) { if (u->building) { uo = building_owner(u->building); } - if (u->ship && r->land) { + else if (u->ship && r->land) { uo = ship_owner(u->ship); } - if (uo && is_enemy(b, uo, u)) { - message *msg = NULL; - if (u->building) { - msg = msg_message("force_leave_building", "unit owner building", u, uo, u->building); + else { + continue; + } + if (is_enemy(b, uo, u)) { + if (leave(u, true)) { + message *msg; + if (uo->building) { + msg = msg_message("force_leave_building", "unit owner building", u, uo, uo->building); + } + else { + msg = msg_message("force_leave_ship", "unit owner ship", u, uo, uo->ship); + } + add_message(&u->faction->msgs, msg); + add_message(&uo->faction->msgs, msg); + msg_release(msg); } - else { - msg = msg_message("force_leave_ship", "unit owner ship", u, uo, u->ship); - } - if (msg) { - ADDMSG(&u->faction->msgs, msg); - } - leave(u, false); } } } diff --git a/src/laws.c b/src/laws.c index fc9a2b834..89506612d 100644 --- a/src/laws.c +++ b/src/laws.c @@ -4197,7 +4197,12 @@ static void expel_building(unit *u, unit *u2, order *ord) { cmistake(u, ord, 5, MSG_EVENT); } else { - leave_building(u2); + if (leave(u2, true)) { + message *msg = msg_message("force_leave_building", "owner unit building", u, u2, u->building); + add_message(&u->faction->msgs, msg); + add_message(&u2->faction->msgs, msg); + msg_release(msg); + } } } @@ -4213,7 +4218,12 @@ static void expel_ship(unit *u, unit *u2, order *ord) { msg_feedback(u, ord, "error_onlandonly", NULL)); } else { - leave_ship(u2); + if (leave(u2, true)) { + message *msg = msg_message("force_leave_ship", "owner unit ship", u, u2, u->ship); + add_message(&u->faction->msgs, msg); + add_message(&u2->faction->msgs, msg); + msg_release(msg); + } } } @@ -4235,6 +4245,8 @@ int expel_cmd(unit *u, order *ord) { expel_ship(u, u2, ord); } else { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "feedback_not_inside", NULL)); /* error: unit must be owner of a ship or building */ } return 0; diff --git a/src/laws.test.c b/src/laws.test.c index e57118088..5f9b2bcd4 100644 --- a/src/laws.test.c +++ b/src/laws.test.c @@ -181,21 +181,30 @@ static void test_expel_building(CuTest *tc) { test_setup(); u1 = test_create_unit(test_create_faction(), test_create_plain(0, 0)); u2 = test_create_unit(test_create_faction(), u1->region); + ord = create_order(K_EXPEL, u2->faction->locale, "%s", itoa36(u1->no)); + + expel_cmd(u2, ord); + CuAssertPtrNotNull(tc, test_find_messagetype(u2->faction->msgs, "feedback_not_inside")); + test_clear_messages(u2->faction); + b = u2->building = u1->building = test_create_building(u1->region, NULL); CuAssertPtrEquals(tc, u1, building_owner(b)); - ord = create_order(K_EXPEL, u2->faction->locale, "%s", itoa36(u1->no)); expel_cmd(u2, ord); /* Nothing happened: */ CuAssertPtrEquals(tc, u1, building_owner(b)); CuAssertPtrEquals(tc, b, u1->building); CuAssertPtrEquals(tc, b, u2->building); + CuAssertPtrNotNull(tc, test_find_messagetype(u2->faction->msgs, "error5")); + test_clear_messages(u1->faction); free_order(ord); ord = create_order(K_EXPEL, u1->faction->locale, "%s", itoa36(u2->no)); expel_cmd(u1, ord); /* owner has expelled u2: */ CuAssertPtrEquals(tc, NULL, u2->building); + CuAssertPtrNotNull(tc, test_find_messagetype(u1->faction->msgs, "force_leave_building")); + CuAssertPtrNotNull(tc, test_find_messagetype(u2->faction->msgs, "force_leave_building")); test_teardown(); } @@ -207,15 +216,21 @@ static void test_expel_ship(CuTest *tc) { test_setup(); u1 = test_create_unit(test_create_faction(), test_create_plain(0, 0)); u2 = test_create_unit(test_create_faction(), u1->region); + ord = create_order(K_EXPEL, u2->faction->locale, "%s", itoa36(u1->no)); + expel_cmd(u2, ord); + CuAssertPtrNotNull(tc, test_find_messagetype(u2->faction->msgs, "feedback_not_inside")); + test_clear_messages(u2->faction); + sh = u2->ship = u1->ship = test_create_ship(u1->region, NULL); CuAssertPtrEquals(tc, u1, ship_owner(sh)); - ord = create_order(K_EXPEL, u2->faction->locale, "%s", itoa36(u1->no)); expel_cmd(u2, ord); /* Nothing happened: */ CuAssertPtrEquals(tc, u1, ship_owner(sh)); CuAssertPtrEquals(tc, sh, u1->ship); CuAssertPtrEquals(tc, sh, u2->ship); + CuAssertPtrNotNull(tc, test_find_messagetype(u2->faction->msgs, "error146")); + test_clear_messages(u2->faction); free_order(ord); ord = create_order(K_EXPEL, u1->faction->locale, "%s", itoa36(u2->no)); @@ -223,6 +238,27 @@ static void test_expel_ship(CuTest *tc) { /* owner has expelled u2: */ CuAssertPtrEquals(tc, NULL, u2->ship); CuAssertPtrEquals(tc, sh, leftship(u2)); + CuAssertPtrNotNull(tc, test_find_messagetype(u1->faction->msgs, "force_leave_ship")); + CuAssertPtrNotNull(tc, test_find_messagetype(u2->faction->msgs, "force_leave_ship")); + test_teardown(); +} + +static void test_expel_ship_at_sea(CuTest *tc) { + unit *u1, *u2; + order *ord; + ship *sh; + + test_setup(); + u1 = test_create_unit(test_create_faction(), test_create_ocean(0, 0)); + u2 = test_create_unit(test_create_faction(), u1->region); + sh = u2->ship = u1->ship = test_create_ship(u1->region, NULL); + CuAssertPtrEquals(tc, u1, ship_owner(sh)); + + ord = create_order(K_EXPEL, u1->faction->locale, "%s", itoa36(u2->no)); + expel_cmd(u1, ord); + /* owner has not expelled u2: */ + CuAssertPtrNotNull(tc, test_find_messagetype(u1->faction->msgs, "error_onlandonly")); + CuAssertPtrEquals(tc, sh, u2->ship); test_teardown(); } @@ -2375,6 +2411,7 @@ CuSuite *get_laws_suite(void) SUITE_ADD_TEST(suite, test_display_cmd); SUITE_ADD_TEST(suite, test_expel_building); SUITE_ADD_TEST(suite, test_expel_ship); + SUITE_ADD_TEST(suite, test_expel_ship_at_sea); SUITE_ADD_TEST(suite, test_rule_force_leave); SUITE_ADD_TEST(suite, test_force_leave_buildings); SUITE_ADD_TEST(suite, test_force_leave_ships);