diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 663b54bd1..ddab0d321 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -113,6 +113,7 @@ set (ERESSEA_SRC renumber.c report.c reports.c + sort.c spells.c spy.c steal.c @@ -237,6 +238,7 @@ set(TESTS_SRC renumber.test.c report.test.c reports.test.c + sort.test.c spells.test.c spy.test.c study.test.c diff --git a/src/bind_process.c b/src/bind_process.c index 8626a2820..974bba4bd 100755 --- a/src/bind_process.c +++ b/src/bind_process.c @@ -10,6 +10,7 @@ #include "magic.h" #include "market.h" #include "move.h" +#include "sort.h" #include "study.h" #include diff --git a/src/laws.c b/src/laws.c index d9ec9afca..373bbfb62 100644 --- a/src/laws.c +++ b/src/laws.c @@ -19,6 +19,7 @@ #include "randenc.h" #include "recruit.h" #include "renumber.h" +#include "sort.h" #include "spy.h" #include "study.h" #include "wormhole.h" @@ -2631,93 +2632,6 @@ void sinkships(struct region * r) } } -void restack_units(void) -{ - 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)) { - 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); - - if (!v || v->faction != u->faction || v->region != r) { - 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 if (v == u) { - syntax_error(u, ord); - } - 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) { - cmistake(v, ord, 261, MSG_EVENT); - } - else if (v->building && building_owner(v->building) == v) { - cmistake(v, ord, 261, MSG_EVENT); - } - else { - unit **vp = &r->units; - while (*vp != v) - vp = &(*vp)->next; - *vp = u; - *up = u->next; - u->next = v; - } - fset(u, UFL_MARK); - sorted = true; - break; - default: - /* TODO: syntax error message? */ - break; - } - } - break; - } - } - } - if (u == *up) - up = &u->next; - } - if (sorted) { - unit *u; - for (u = r->units; u; u = u->next) { - freset(u, UFL_MARK); - } - } - } -} - /* blesses stone circles create an astral protection in the astral region * above the shield, which prevents chaos suction and other spells. * The shield is created when a magician enters the blessed stone circle, diff --git a/src/laws.h b/src/laws.h index 5bf81440d..521e28f2b 100755 --- a/src/laws.h +++ b/src/laws.h @@ -44,7 +44,6 @@ extern "C" { void defaultorders(void); void quit(void); void monthly_healing(void); - void restack_units(void); void update_long_order(struct unit *u); void sinkships(struct region * r); void do_enter(struct region *r, bool is_final_attempt); diff --git a/src/laws.test.c b/src/laws.test.c index c51939fa2..cf57224d5 100644 --- a/src/laws.test.c +++ b/src/laws.test.c @@ -1379,7 +1379,7 @@ static void test_ally_cmd(CuTest *tc) { order *ord; test_setup(); - u = test_create_unit(test_create_faction(), test_create_region(0, 0, NULL)); + u = test_create_unit(test_create_faction(), test_create_plain(0, 0)); f = test_create_faction(); ord = create_order(K_ALLY, f->locale, "%s", itoa36(f->no)); diff --git a/src/sort.c b/src/sort.c new file mode 100644 index 000000000..17da43563 --- /dev/null +++ b/src/sort.c @@ -0,0 +1,102 @@ +#include "sort.h" + +#include "kernel/config.h" +#include "kernel/building.h" +#include "kernel/faction.h" +#include "kernel/messages.h" +#include "kernel/order.h" +#include "kernel/region.h" +#include "kernel/ship.h" +#include "kernel/unit.h" + +#include "util/keyword.h" +#include "util/param.h" +#include "util/parser.h" + +void restack_units(void) +{ + 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)) { + 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); + + if (!v || v->faction != u->faction || v->region != r) { + 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 if (v == u) { + syntax_error(u, ord); + } + 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) { + cmistake(v, ord, 261, MSG_EVENT); + } + else if (v->building && building_owner(v->building) == v) { + cmistake(v, ord, 261, MSG_EVENT); + } + else { + unit **vp = &r->units; + while (*vp != v) + vp = &(*vp)->next; + *vp = u; + *up = u->next; + u->next = v; + } + fset(u, UFL_MARK); + sorted = true; + break; + default: + /* TODO: syntax error message? */ + break; + } + } + break; + } + } + } + if (u == *up) + up = &u->next; + } + if (sorted) { + unit *u; + for (u = r->units; u; u = u->next) { + freset(u, UFL_MARK); + } + } + } +} + diff --git a/src/sort.h b/src/sort.h new file mode 100644 index 000000000..d2228fa1c --- /dev/null +++ b/src/sort.h @@ -0,0 +1,3 @@ +#pragma once + +void restack_units(void); diff --git a/src/sort.test.c b/src/sort.test.c new file mode 100644 index 000000000..5e085ec2c --- /dev/null +++ b/src/sort.test.c @@ -0,0 +1,67 @@ +#include "sort.h" + +#include "kernel/faction.h" +#include "kernel/unit.h" +#include "kernel/order.h" +#include "kernel/region.h" + +#include "util/base36.h" +#include "util/keyword.h" +#include "util/language.h" +#include "util/param.h" + +#include "tests.h" +#include + +static void test_sort_after(CuTest *tc) { + unit *u1, *u2; + faction *f; + region *r; + + test_setup(); + u1 = test_create_unit(f = test_create_faction(), r = test_create_plain(0, 0)); + u2 = test_create_unit(f, r); + unit_addorder(u1, create_order(K_SORT, f->locale, "%s %s", + LOC(f->locale, parameters[P_AFTER]), itoa36(u2->no))); + CuAssertPtrEquals(tc, u1, r->units); + CuAssertPtrEquals(tc, u2, u1->next); + CuAssertPtrEquals(tc, NULL, u2->next); + + restack_units(); + CuAssertPtrEquals(tc, u2, r->units); + CuAssertPtrEquals(tc, u1, u2->next); + CuAssertPtrEquals(tc, NULL, u1->next); + + test_teardown(); +} + +static void test_sort_before(CuTest *tc) { + unit *u1, *u2; + faction *f; + region *r; + + test_setup(); + u1 = test_create_unit(f = test_create_faction(), r = test_create_plain(0, 0)); + u2 = test_create_unit(f, r); + unit_addorder(u2, create_order(K_SORT, f->locale, "%s %s", + LOC(f->locale, parameters[P_BEFORE]), itoa36(u1->no))); + CuAssertPtrEquals(tc, u1, r->units); + CuAssertPtrEquals(tc, u2, u1->next); + CuAssertPtrEquals(tc, NULL, u2->next); + + restack_units(); + CuAssertPtrEquals(tc, u2, r->units); + CuAssertPtrEquals(tc, u1, u2->next); + CuAssertPtrEquals(tc, NULL, u1->next); + + test_teardown(); +} + + +CuSuite *get_sort_suite(void) +{ + CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_sort_after); + SUITE_ADD_TEST(suite, test_sort_before); + return suite; +} diff --git a/src/test_eressea.c b/src/test_eressea.c index b644bc771..4c95e6582 100644 --- a/src/test_eressea.c +++ b/src/test_eressea.c @@ -146,6 +146,7 @@ int RunAllTests(int argc, char *argv[]) ADD_SUITE(renumber); ADD_SUITE(report); ADD_SUITE(shock); + ADD_SUITE(sort); ADD_SUITE(spy); ADD_SUITE(stealth); ADD_SUITE(study);