diff --git a/src/sort.c b/src/sort.c index 066897ac5..150f35785 100644 --- a/src/sort.c +++ b/src/sort.c @@ -13,6 +13,17 @@ #include "util/param.h" #include "util/parser.h" +void sort_before(unit *v, unit **up) { + unit *u = *up; + region *r = u->region; + unit **vp = &r->units; + while (*vp != v) + vp = &(*vp)->next; + *vp = u; + *up = u->next; + u->next = v; +} + void restack_units(void) { region *r; @@ -37,7 +48,13 @@ void restack_units(void) id = getid(); v = findunit(id); - if (!v || v->faction != u->faction || v->region != r) { + 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) { @@ -49,9 +66,6 @@ void restack_units(void) 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: @@ -63,18 +77,27 @@ void restack_units(void) break; case P_BEFORE: if (v->ship && ship_owner(v->ship) == v) { - cmistake(v, ord, 261, MSG_EVENT); + 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) { - cmistake(v, ord, 261, MSG_EVENT); + if (is_paused(v->faction)) { + sort_before(v, up); + building_set_owner(u); + } + else { + cmistake(v, ord, 261, MSG_EVENT); + break; + } } else { - unit **vp = &r->units; - while (*vp != v) - vp = &(*vp)->next; - *vp = u; - *up = u->next; - u->next = v; + sort_before(v, up); } fset(u, UFL_MARK); sorted = true; diff --git a/src/sort.test.c b/src/sort.test.c index 58171ca36..b9d4a144c 100644 --- a/src/sort.test.c +++ b/src/sort.test.c @@ -123,6 +123,84 @@ static void test_sort_before_owner(CuTest *tc) { test_teardown(); } +static void test_sort_before_paused_building_owner(CuTest *tc) { + unit *u1, *u2; + faction *f; + region *r; + building *b; + + test_setup(); + u1 = test_create_unit(f = test_create_faction(), r = test_create_plain(0, 0)); + f->flags |= FFL_PAUSED; + b = test_create_building(r, NULL); + + u2 = test_create_unit(f = test_create_faction(), r); + unit_addorder(u2, create_order(K_SORT, f->locale, "%s %s", + LOC(f->locale, parameters[P_BEFORE]), itoa36(u1->no))); + u1->building = b; + building_update_owner(b); + CuAssertPtrEquals(tc, u1, r->units); + CuAssertPtrEquals(tc, u2, u1->next); + CuAssertPtrEquals(tc, NULL, u2->next); + + /* not in building, nothing happend: */ + restack_units(); + CuAssertPtrEquals(tc, u1, r->units); + CuAssertPtrEquals(tc, u2, u1->next); + CuAssertPtrEquals(tc, NULL, u2->next); + CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "error259")); + test_clear_messagelist(&f->msgs); + + /* u1 allows u2 to steal the top spot: */ + u2->building = b; + restack_units(); + CuAssertPtrEquals(tc, u2, r->units); + CuAssertPtrEquals(tc, u1, u2->next); + CuAssertPtrEquals(tc, NULL, u1->next); + CuAssertPtrEquals(tc, u2, building_owner(b)); + CuAssertPtrEquals(tc, NULL, f->msgs); + test_teardown(); +} + +static void test_sort_before_paused_ship_owner(CuTest *tc) { + unit *u1, *u2; + faction *f; + region *r; + ship *sh; + + test_setup(); + u1 = test_create_unit(f = test_create_faction(), r = test_create_plain(0, 0)); + f->flags |= FFL_PAUSED; + sh = test_create_ship(r, NULL); + + u2 = test_create_unit(f = test_create_faction(), r); + unit_addorder(u2, create_order(K_SORT, f->locale, "%s %s", + LOC(f->locale, parameters[P_BEFORE]), itoa36(u1->no))); + u1->ship = sh; + ship_update_owner(sh); + CuAssertPtrEquals(tc, u1, r->units); + CuAssertPtrEquals(tc, u2, u1->next); + CuAssertPtrEquals(tc, NULL, u2->next); + + /* not in ship, nothing happend: */ + restack_units(); + CuAssertPtrEquals(tc, u1, r->units); + CuAssertPtrEquals(tc, u2, u1->next); + CuAssertPtrEquals(tc, NULL, u2->next); + CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "error259")); + test_clear_messagelist(&f->msgs); + + /* u1 allows u2 to steal the top spot: */ + u2->ship = sh; + restack_units(); + CuAssertPtrEquals(tc, u2, r->units); + CuAssertPtrEquals(tc, u1, u2->next); + CuAssertPtrEquals(tc, NULL, u1->next); + CuAssertPtrEquals(tc, u2, ship_owner(sh)); + CuAssertPtrEquals(tc, NULL, f->msgs); + test_teardown(); +} + static void test_sort_paused(CuTest *tc) { unit *u1, *u2; faction *f; @@ -152,6 +230,8 @@ CuSuite *get_sort_suite(void) { CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_sort_before_owner); + SUITE_ADD_TEST(suite, test_sort_before_paused_ship_owner); + SUITE_ADD_TEST(suite, test_sort_before_paused_building_owner); SUITE_ADD_TEST(suite, test_sort_after); SUITE_ADD_TEST(suite, test_sort_before); SUITE_ADD_TEST(suite, test_sort_paused);