move unit reordering into sort.c

This commit is contained in:
Enno Rehling 2021-06-06 13:12:02 +02:00
parent 1994a66f85
commit 62aaf71b35
9 changed files with 178 additions and 89 deletions

View File

@ -113,6 +113,7 @@ set (ERESSEA_SRC
renumber.c renumber.c
report.c report.c
reports.c reports.c
sort.c
spells.c spells.c
spy.c spy.c
steal.c steal.c
@ -237,6 +238,7 @@ set(TESTS_SRC
renumber.test.c renumber.test.c
report.test.c report.test.c
reports.test.c reports.test.c
sort.test.c
spells.test.c spells.test.c
spy.test.c spy.test.c
study.test.c study.test.c

View File

@ -10,6 +10,7 @@
#include "magic.h" #include "magic.h"
#include "market.h" #include "market.h"
#include "move.h" #include "move.h"
#include "sort.h"
#include "study.h" #include "study.h"
#include <kernel/alliance.h> #include <kernel/alliance.h>

View File

@ -19,6 +19,7 @@
#include "randenc.h" #include "randenc.h"
#include "recruit.h" #include "recruit.h"
#include "renumber.h" #include "renumber.h"
#include "sort.h"
#include "spy.h" #include "spy.h"
#include "study.h" #include "study.h"
#include "wormhole.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 /* blesses stone circles create an astral protection in the astral region
* above the shield, which prevents chaos suction and other spells. * above the shield, which prevents chaos suction and other spells.
* The shield is created when a magician enters the blessed stone circle, * The shield is created when a magician enters the blessed stone circle,

View File

@ -44,7 +44,6 @@ extern "C" {
void defaultorders(void); void defaultorders(void);
void quit(void); void quit(void);
void monthly_healing(void); void monthly_healing(void);
void restack_units(void);
void update_long_order(struct unit *u); void update_long_order(struct unit *u);
void sinkships(struct region * r); void sinkships(struct region * r);
void do_enter(struct region *r, bool is_final_attempt); void do_enter(struct region *r, bool is_final_attempt);

View File

@ -1379,7 +1379,7 @@ static void test_ally_cmd(CuTest *tc) {
order *ord; order *ord;
test_setup(); 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(); f = test_create_faction();
ord = create_order(K_ALLY, f->locale, "%s", itoa36(f->no)); ord = create_order(K_ALLY, f->locale, "%s", itoa36(f->no));

102
src/sort.c Normal file
View File

@ -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);
}
}
}
}

3
src/sort.h Normal file
View File

@ -0,0 +1,3 @@
#pragma once
void restack_units(void);

67
src/sort.test.c Normal file
View File

@ -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 <CuTest.h>
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;
}

View File

@ -146,6 +146,7 @@ int RunAllTests(int argc, char *argv[])
ADD_SUITE(renumber); ADD_SUITE(renumber);
ADD_SUITE(report); ADD_SUITE(report);
ADD_SUITE(shock); ADD_SUITE(shock);
ADD_SUITE(sort);
ADD_SUITE(spy); ADD_SUITE(spy);
ADD_SUITE(stealth); ADD_SUITE(stealth);
ADD_SUITE(study); ADD_SUITE(study);