From 0ac3dc5ead8704344a3b07b65e21c5f1edea87d3 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 26 Oct 2018 10:54:09 +0200 Subject: [PATCH 01/11] WIP: refactor allies api --- src/creport.c | 37 +++++++++++++++++++-------- src/kernel/ally.c | 17 ++++++++++++- src/kernel/ally.h | 19 +++++++------- src/laws.c | 65 +++++++++++++++++++---------------------------- 4 files changed, 77 insertions(+), 61 deletions(-) diff --git a/src/creport.c b/src/creport.c index 475a04b1e..07d957258 100644 --- a/src/creport.c +++ b/src/creport.c @@ -1018,20 +1018,35 @@ static void cr_output_unit_compat(FILE * F, const faction * f, cr_output_unit(&strm, f, u, mode); } -/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ +static void print_ally(const faction *f, faction *af, int status, + struct ally *sf, FILE *F) { + if (af) { + int mode = alliedgroup(NULL, f, af, sf, HELP_ALL); + if (mode != 0 && status > 0) { + fprintf(F, "ALLIANZ %d\n", af->no); + fprintf(F, "\"%s\";Parteiname\n", af->name); + fprintf(F, "%d;Status\n", status & HELP_ALL); + } + } +} + +struct print_ally_s { + const faction *f; + FILE *F; +}; + +static void print_ally_cb(struct ally *sf, faction *af, int status, void *udata) { + struct print_ally_s *data = (struct print_ally_s *)udata; + print_ally(data->f, af, status, sf, data->F); +} /* prints allies */ -static void show_allies_cr(FILE * F, const faction * f, const ally * sf) +static void show_allies_cr(FILE * F, const faction * f, struct ally * sf) { - for (; sf; sf = sf->next) - if (sf->faction) { - int mode = alliedgroup(NULL, f, sf->faction, sf, HELP_ALL); - if (mode != 0 && sf->status > 0) { - fprintf(F, "ALLIANZ %d\n", sf->faction->no); - fprintf(F, "\"%s\";Parteiname\n", sf->faction->name); - fprintf(F, "%d;Status\n", sf->status & HELP_ALL); - } - } + struct print_ally_s data; + data.F = F; + data.f = f; + allies_walk(sf, print_ally_cb, &data); } /* prints allies */ diff --git a/src/kernel/ally.c b/src/kernel/ally.c index 0660f148a..3abfc4c09 100644 --- a/src/kernel/ally.c +++ b/src/kernel/ally.c @@ -20,6 +20,20 @@ #include #include +typedef struct ally { + struct ally *next; + struct faction *faction; + int status; +} ally; + +void allies_walk(struct ally *allies, cb_allies_walk callback, void *udata); +{ + ally *al; + for (al = allies; al; al = al->next) { + callback(allies, al->faction, al->status, udata); + } +} + void read_allies(gamedata * data, faction *f) { ally **sfp = &f->allies; @@ -196,7 +210,8 @@ static int AllianceRestricted(void) int alliedgroup(const struct plane *pl, const struct faction *f, - const struct faction *f2, const struct ally *sf, int mode) + const struct faction *f2, + const struct ally *sf, int mode) { if (!(faction_alive(f) && faction_alive(f2))) { return 0; diff --git a/src/kernel/ally.h b/src/kernel/ally.h index d4c41d36c..16bd57aa7 100644 --- a/src/kernel/ally.h +++ b/src/kernel/ally.h @@ -28,19 +28,18 @@ extern "C" { struct faction; struct gamedata; struct unit; + struct ally; extern struct attrib_type at_npcfaction; - typedef struct ally { - struct ally *next; - struct faction *faction; - int status; - } ally; - void read_allies(struct gamedata * data, struct faction *f); - ally * ally_find(ally *al, const struct faction *f); - ally * ally_add(ally **al_p, struct faction *f); - void ally_remove(ally **al_p, struct faction *f); + typedef void (*cb_allies_walk)(struct ally *, struct faction *, int, void *); + void allies_walk(struct ally *allies, cb_allies_walk callback, void *udata); + struct ally* ally_find(struct ally*al, const struct faction *f); + void ally_set(struct ally**al_p, struct faction *f, int status); + int ally_get(struct ally *al, struct faction *f); + struct ally* ally_add(struct ally**al_p, struct faction *f); + void ally_remove(struct ally**al_p, struct faction *f); int AllianceAuto(void); /* flags that allied factions get automatically */ int HelpMask(void); /* flags restricted to allied factions */ @@ -49,7 +48,7 @@ extern "C" { int alliedfaction(const struct plane *pl, const struct faction *f, const struct faction *f2, int mode); int alliedgroup(const struct plane *pl, const struct faction *f, - const struct faction *f2, const struct ally *sf, int mode); + const struct faction *f2, const struct ally*sf, int mode); #ifdef __cplusplus } diff --git a/src/laws.c b/src/laws.c index 4c2a29e4e..035ed7088 100644 --- a/src/laws.c +++ b/src/laws.c @@ -1292,11 +1292,12 @@ void quit(void) int ally_cmd(unit * u, struct order *ord) { char token[128]; - ally *sf, **sfp; + struct ally **sfp; faction *f; int keyword, not_kw; const char *s; - + int sf_status; + init_order_depr(ord); f = getfaction(); @@ -1319,28 +1320,17 @@ int ally_cmd(unit * u, struct order *ord) sfp = &u->faction->allies; if (fval(u, UFL_GROUP)) { attrib *a = a_find(u->attribs, &at_group); - if (a) + if (a) { sfp = &((group *)a->data.v)->allies; + } } - for (sf = *sfp; sf; sf = sf->next) - if (sf->faction == f) - break; /* Gleich die passende raussuchen, wenn vorhanden */ not_kw = getparam(u->faction->locale); /* HELFE partei [modus] NICHT */ - if (!sf) { - if (keyword == P_NOT || not_kw == P_NOT) { - /* Wir helfen der Partei gar nicht... */ - return 0; - } - else { - sf = ally_add(sfp, f); - sf->status = 0; - } - } + sf_status = ally_get(*sfp, f); switch (keyword) { case P_NOT: - sf->status = 0; + sf_status = 0; break; case NOPARAM: @@ -1348,60 +1338,57 @@ int ally_cmd(unit * u, struct order *ord) return 0; case P_ANY: - if (not_kw == P_NOT) - sf->status = 0; - else - sf->status = HELP_ALL; + sf_status = (not_kw == P_NOT) ? 0 : HELP_ALL; break; case P_TRAVEL: - if (not_kw == P_NOT) - sf->status = sf->status & (HELP_ALL - HELP_TRAVEL); - else - sf->status = sf->status | HELP_TRAVEL; + if (not_kw == P_NOT) { + sf_status = sf_status & (HELP_ALL - HELP_TRAVEL); + } + else { + sf_status |= HELP_TRAVEL; + } break; case P_GIVE: if (not_kw == P_NOT) - sf->status = sf->status & (HELP_ALL - HELP_GIVE); + sf_status &= (HELP_ALL - HELP_GIVE); else - sf->status = sf->status | HELP_GIVE; + sf_status |= HELP_GIVE; break; case P_MONEY: if (not_kw == P_NOT) - sf->status = sf->status & (HELP_ALL - HELP_MONEY); + sf_status &= (HELP_ALL - HELP_MONEY); else - sf->status = sf->status | HELP_MONEY; + sf_status |= HELP_MONEY; break; case P_FIGHT: if (not_kw == P_NOT) - sf->status = sf->status & (HELP_ALL - HELP_FIGHT); + sf_status &= (HELP_ALL - HELP_FIGHT); else - sf->status = sf->status | HELP_FIGHT; + sf_status |= HELP_FIGHT; break; case P_FACTIONSTEALTH: if (not_kw == P_NOT) - sf->status = sf->status & (HELP_ALL - HELP_FSTEALTH); + sf_status &= (HELP_ALL - HELP_FSTEALTH); else - sf->status = sf->status | HELP_FSTEALTH; + sf_status |= HELP_FSTEALTH; break; case P_GUARD: if (not_kw == P_NOT) - sf->status = sf->status & (HELP_ALL - HELP_GUARD); + sf_status &= (HELP_ALL - HELP_GUARD); else - sf->status = sf->status | HELP_GUARD; + sf_status |= HELP_GUARD; break; } - sf->status &= HelpMask(); + sf_status &= HelpMask(); + ally_set(sfp, f, sf_status); - if (sf->status == 0) { /* Alle HELPs geloescht */ - removelist(sfp, sf); - } return 0; } From 600762809607a9ada74f5916330e7ca4c2744347 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 26 Oct 2018 14:00:48 +0200 Subject: [PATCH 02/11] report.c is next --- src/report.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/report.c b/src/report.c index 5d2ed4598..e27044127 100644 --- a/src/report.c +++ b/src/report.c @@ -1511,7 +1511,7 @@ report_template(const char *filename, report_context * ctx, const char *bom) } static void -show_allies(const faction * f, const ally * allies, char *buf, size_t size) +show_allies(const faction * f, struct ally * allies, char *buf, size_t size) { int allierte = 0; int i = 0, h, hh = 0; From d7a8a9b406381545f9096644252699c6e790fa26 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 26 Oct 2018 21:49:58 +0200 Subject: [PATCH 03/11] fix that catastrophic merge, make struct ally module-private --- res/translations/strings.de.po | 2 +- src/bind_faction.c | 45 ---------- src/kernel/ally.c | 51 +++++++++-- src/kernel/ally.h | 14 +-- src/kernel/ally.test.c | 37 ++++++-- src/kernel/faction.c | 18 ---- src/kernel/faction.h | 3 - src/kernel/group.c | 29 ++----- src/kernel/group.h | 2 +- src/kernel/group.test.c | 6 +- src/kernel/save.c | 15 +--- src/kernel/save.test.c | 1 + src/report.c | 152 ++++++++++++++++++--------------- src/upkeep.c | 2 +- src/upkeep.test.c | 3 +- 15 files changed, 180 insertions(+), 200 deletions(-) diff --git a/res/translations/strings.de.po b/res/translations/strings.de.po index 47d70ecc0..89875baf5 100644 --- a/res/translations/strings.de.po +++ b/res/translations/strings.de.po @@ -1437,7 +1437,7 @@ msgstr "Goblins" msgctxt "spellinfo" msgid "song_of_slavery" -msgstr "Dieser mächtige Bann raubt dem Opfer seinen freien Willen und unterwirft sie den Befehlen des Barden. Für einige Zeit wird das Opfer sich völlig von seinen eigenen Leuten abwenden und der Partei des Barden zugehörig fühlen." +msgstr "Dieser mächtige Bann raubt dem Opfer seinen freien Willen und unterwirft es den Befehlen des Barden. Für einige Zeit wird das Opfer sich völlig von seinen eigenen Leuten abwenden und der Partei des Barden zugehörig fühlen." msgctxt "spell" msgid "healingzone" diff --git a/src/bind_faction.c b/src/bind_faction.c index 46967252c..fd384ff4f 100644 --- a/src/bind_faction.c +++ b/src/bind_faction.c @@ -309,49 +309,6 @@ static int tolua_faction_count_msg_type(lua_State *L) { return 1; } -static int tolua_faction_get_policy(lua_State * L) -{ - faction *self = (faction *)tolua_tousertype(L, 1, 0); - faction *other = (faction *)tolua_tousertype(L, 2, 0); - const char *policy = tolua_tostring(L, 3, 0); - - int result = 0, mode; - for (mode = 0; helpmodes[mode].name != NULL; ++mode) { - if (strcmp(policy, helpmodes[mode].name) == 0) { - result = get_alliance(self, other) & mode; - break; - } - } - - lua_pushinteger(L, result); - return 1; -} - -static int tolua_faction_set_policy(lua_State * L) -{ - faction *self = (faction *)tolua_tousertype(L, 1, 0); - faction *other = (faction *)tolua_tousertype(L, 2, 0); - const char *policy = tolua_tostring(L, 3, 0); - int value = tolua_toboolean(L, 4, 0); - - int mode; - for (mode = 0; helpmodes[mode].name != NULL; ++mode) { - if (strcmp(policy, helpmodes[mode].name) == 0) { - if (value) { - set_alliance(self, other, get_alliance(self, - other) | helpmodes[mode].status); - } - else { - set_alliance(self, other, get_alliance(self, - other) & ~helpmodes[mode].status); - } - break; - } - } - - return 0; -} - static int tolua_faction_normalize(lua_State * L) { faction *f = (faction *)tolua_tousertype(L, 1, 0); @@ -632,8 +589,6 @@ void tolua_faction_open(lua_State * L) tolua_variable(L, TOLUA_CAST "lastturn", tolua_faction_get_lastturn, tolua_faction_set_lastturn); - tolua_function(L, TOLUA_CAST "set_policy", tolua_faction_set_policy); - tolua_function(L, TOLUA_CAST "get_policy", tolua_faction_get_policy); tolua_function(L, TOLUA_CAST "get_origin", tolua_faction_get_origin); tolua_function(L, TOLUA_CAST "set_origin", tolua_faction_set_origin); tolua_function(L, TOLUA_CAST "normalize", tolua_faction_normalize); diff --git a/src/kernel/ally.c b/src/kernel/ally.c index 20fb364d4..b439975f3 100644 --- a/src/kernel/ally.c +++ b/src/kernel/ally.c @@ -25,7 +25,29 @@ typedef struct ally { int status; } ally; -int allies_walk(struct ally *allies, cb_allies_walk callback, void *udata) +void allies_free(ally *al) +{ + while (al) { + ally * an = al->next; + free(al); + al = an; + } +} + +ally *allies_clone(const ally *al) { + ally *al_clone = NULL, **al_end = &al_clone; + + for (; al; al = al->next) { + if (al->faction) { + ally * al_new = ally_add(al_end, al->faction); + al_new->status = al->status; + al_end = &al_new->next; + } + } + return al_clone; +} + +int allies_walk(ally *allies, cb_allies_walk callback, void *udata) { ally *al; for (al = allies; al; al = al->next) { @@ -37,6 +59,18 @@ int allies_walk(struct ally *allies, cb_allies_walk callback, void *udata) return 0; } +void write_allies(gamedata * data, const ally *alist) +{ + const ally *a; + for (a = alist; a; a = a->next) { + if (a->faction && a->faction->_alive) { + write_faction_reference(a->faction, data->store); + WRITE_INT(data->store, a->status); + } + } + write_faction_reference(NULL, data->store); +} + void read_allies(gamedata * data, ally **sfp) { for (;;) { @@ -196,8 +230,7 @@ static int AllianceRestricted(void) return rule; } - -int alliance_status(faction *f, faction *f2, int status) { +int alliance_status(const faction *f, const faction *f2, int status) { status |= autoalliance(f, f2); if (status > 0) { int mask = AllianceRestricted(); @@ -226,7 +259,7 @@ alliedgroup(const struct faction *f, if (!(faction_alive(f) && faction_alive(f2))) { return 0; } - status = ally_get(all, f2); + status = ally_get(all, f2) & mask; return alliance_status(f, f2, status); } @@ -237,19 +270,19 @@ alliedfaction(const struct faction *f, const struct faction *f2, int mask) } /* Die Gruppe von Einheit u hat helfe zu f2 gesetzt. */ -int alliedunit(const unit * u, const faction * f2, int mode) +int alliedunit(const unit * u, const faction * f2, int mask) { assert(u); assert(f2); assert(u->region); /* the unit should be in a region, but it's possible that u->number==0 (TEMP units) */ if (u->faction == f2) { - return mode; + return mask; } if (!faction_alive(f2)) { return 0; } if (u->faction != NULL && f2 != NULL) { - if (mode & HELP_FIGHT) { + if (mask & HELP_FIGHT) { if ((u->flags & UFL_DEFENDER) || (u->faction->flags & FFL_DEFENDER)) { faction *owner = region_get_owner(u->region); /* helps the owner of the region */ @@ -263,10 +296,10 @@ int alliedunit(const unit * u, const faction * f2, int mode) const attrib *a = a_find(u->attribs, &at_group); if (a != NULL) { group *g = (group *)a->data.v; - return alliedgroup(u->faction, f2, g, mode); + return alliedgroup(u->faction, f2, g, mask); } } - return alliedfaction(u->faction, f2, mode); + return alliedfaction(u->faction, f2, mask); } return 0; } diff --git a/src/kernel/ally.h b/src/kernel/ally.h index 70b1a88e0..eeb573cb5 100644 --- a/src/kernel/ally.h +++ b/src/kernel/ally.h @@ -33,23 +33,27 @@ extern "C" { extern struct attrib_type at_npcfaction; void read_allies(struct gamedata * data, struct ally **alist); + void write_allies(struct gamedata * data, const struct ally *alist); typedef int (*cb_allies_walk)(struct ally *, struct faction *, int, void *); int allies_walk(struct ally *allies, cb_allies_walk callback, void *udata); + struct ally *allies_clone(const struct ally *al); + void allies_free(struct ally *al); + struct ally* ally_find(struct ally*al, const struct faction *f); void ally_set(struct ally**al_p, struct faction *f, int status); - int ally_get(struct ally *al, struct faction *f); + int ally_get(struct ally *al, const struct faction *f); struct ally* ally_add(struct ally**al_p, struct faction *f); int AllianceAuto(void); /* flags that allied factions get automatically */ int HelpMask(void); /* flags restricted to allied factions */ int alliedunit(const struct unit *u, const struct faction *f2, - int mode); + int mask); int alliedfaction(const struct faction *f, const struct faction *f2, - int mode); + int mask); int alliedgroup(const struct faction *f, const struct faction *f2, - const struct group *g, int mode); - int alliance_status(const struct faction *f, const struct faction *f2, int mode); + const struct group *g, int mask); + int alliance_status(const struct faction *f, const struct faction *f2, int status); #ifdef __cplusplus } diff --git a/src/kernel/ally.test.c b/src/kernel/ally.test.c index 3197132a0..7aaf50fa7 100644 --- a/src/kernel/ally.test.c +++ b/src/kernel/ally.test.c @@ -7,22 +7,47 @@ static void test_ally(CuTest * tc) { - ally * al = NULL; - struct faction * f1 = test_create_faction(NULL); + struct ally * al = NULL; + struct faction * f; - ally_set(&al, f1, HELP_GUARD); + test_setup(); + f = test_create_faction(NULL); + ally_set(&al, f, HELP_GUARD); CuAssertPtrNotNull(tc, al); - CuAssertIntEquals(tc, HELP_GUARD, ally_get(al, f1)); + CuAssertIntEquals(tc, HELP_GUARD, ally_get(al, f)); - ally_set(&al, f1, 0); + ally_set(&al, f, 0); CuAssertPtrEquals(tc, NULL, al); - CuAssertIntEquals(tc, 0, ally_get(al, f1)); + CuAssertIntEquals(tc, 0, ally_get(al, f)); + allies_free(al); + test_teardown(); +} + +static void test_allies_clone(CuTest * tc) +{ + struct ally * al = NULL, *ac; + struct faction * f; + + test_setup(); + f = test_create_faction(NULL); + CuAssertPtrEquals(tc, NULL, allies_clone(NULL)); + + ally_set(&al, f, HELP_GUARD); + ac = allies_clone(al); + CuAssertPtrNotNull(tc, ac); + CuAssertTrue(tc, al != ac); + CuAssertIntEquals(tc, HELP_GUARD, ally_get(ac, f)); + CuAssertIntEquals(tc, HELP_GUARD, ally_get(al, f)); + allies_free(al); + allies_free(ac); + test_teardown(); } CuSuite *get_ally_suite(void) { CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_ally); + SUITE_ADD_TEST(suite, test_allies_clone); return suite; } diff --git a/src/kernel/faction.c b/src/kernel/faction.c index d2871f84b..fe6aff39f 100755 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -518,24 +518,6 @@ void destroyfaction(faction ** fp) } } -int get_alliance(const faction * a, const faction * b) -{ - const ally *sf = a->allies; - for (; sf != NULL; sf = sf->next) { - if (sf->faction == b) { - return sf->status; - } - } - return 0; -} - -void set_alliance(faction * a, faction * b, int status) -{ - /* TODO: optimization (use allies_walk?) */ - int original = ally_get(a->allies, b); - ally_set(&a->allies, b, status | original); -} - void renumber_faction(faction * f, int no) { funhash(f); diff --git a/src/kernel/faction.h b/src/kernel/faction.h index 87b13f2b9..8fac8e98d 100644 --- a/src/kernel/faction.h +++ b/src/kernel/faction.h @@ -128,9 +128,6 @@ extern "C" { bool faction_alive(const struct faction *f); - void set_alliance(struct faction *a, struct faction *b, int status); - int get_alliance(const struct faction *a, const struct faction *b); - struct alliance *f_get_alliance(const struct faction *f); void write_faction_reference(const struct faction *f, diff --git a/src/kernel/group.c b/src/kernel/group.c index 36598d582..210f6e0f2 100755 --- a/src/kernel/group.c +++ b/src/kernel/group.c @@ -53,7 +53,7 @@ group *new_group(faction * f, const char *name, int gid) { group **gp = &f->groups; int index = gid % GMAXHASH; - group *g = calloc(sizeof(group), 1); + group *g = calloc(1, sizeof(group)); while (*gp) gp = &(*gp)->next; @@ -69,14 +69,7 @@ group *new_group(faction * f, const char *name, int gid) static void init_group(faction * f, group * g) { - ally *a, **an; - - an = &g->allies; - for (a = f->allies; a; a = a->next) { - if (a->faction) { - ally_set(an, a->faction, a->status); - } - } + g->allies = allies_clone(f->allies); } static group *find_groupbyname(group * g, const char *name) @@ -138,11 +131,7 @@ void free_group(group * g) if (g->attribs) { a_removeall(&g->attribs, NULL); } - while (g->allies) { - ally *a = g->allies; - g->allies = a->next; - free(a); - } + allies_free(g->allies); free(g->name); free(g); } @@ -203,20 +192,14 @@ group *join_group(unit * u, const char *name) return g; } -void write_groups(struct storage *store, const faction * f) +void write_groups(struct gamedata *data, const faction * f) { group *g; + storage *store = data->store; for (g = f->groups; g; g = g->next) { - ally *a; WRITE_INT(store, g->gid); WRITE_STR(store, g->name); - for (a = g->allies; a; a = a->next) { - if (a->faction && a->faction->_alive) { - write_faction_reference(a->faction, store); - WRITE_INT(store, a->status); - } - } - write_faction_reference(NULL, store); + write_allies(data, g->allies); a_write(store, g->attribs, g); WRITE_SECTION(store); } diff --git a/src/kernel/group.h b/src/kernel/group.h index b257f515a..b66e3f50b 100755 --- a/src/kernel/group.h +++ b/src/kernel/group.h @@ -42,7 +42,7 @@ extern "C" { extern void free_group(struct group *g); struct group *new_group(struct faction * f, const char *name, int gid); - extern void write_groups(struct storage *data, const struct faction *f); + extern void write_groups(struct gamedata *data, const struct faction *f); extern void read_groups(struct gamedata *data, struct faction *f); #ifdef __cplusplus diff --git a/src/kernel/group.test.c b/src/kernel/group.test.c index c554c0829..7d14380d6 100644 --- a/src/kernel/group.test.c +++ b/src/kernel/group.test.c @@ -84,7 +84,7 @@ static void test_group_readwrite(CuTest * tc) g = new_group(f, "Egoisten", 43); key_set(&g->attribs, 44, 44); ally_set(&g->allies, f, HELP_GIVE); - write_groups(&store, f); + write_groups(&data, f); WRITE_INT(&store, 47); free_group(f->groups); @@ -107,9 +107,7 @@ static void test_group_readwrite(CuTest * tc) g = f->groups->next; CuAssertIntEquals(tc, 44, key_get(g->attribs, 44)); CuAssertPtrNotNull(tc, g->allies); - CuAssertPtrEquals(tc, NULL, g->allies->next); - CuAssertPtrEquals(tc, f, g->allies->faction); - CuAssertIntEquals(tc, HELP_GIVE, g->allies->status); + CuAssertIntEquals(tc, HELP_GIVE, ally_get(g->allies, f)); test_teardown(); } diff --git a/src/kernel/save.c b/src/kernel/save.c index 72ccc66e3..ea1780149 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -1094,7 +1094,6 @@ faction *read_faction(gamedata * data) void write_faction(gamedata *data, const faction * f) { - ally *sf; origin *ur; assert(f->_alive); @@ -1144,19 +1143,9 @@ void write_faction(gamedata *data, const faction * f) WRITE_INT(data->store, f->options & ~WANT_OPTION(O_DEBUG)); WRITE_SECTION(data->store); - for (sf = f->allies; sf; sf = sf->next) { - assert(sf->faction); - - if (faction_alive(sf->faction)) { - if (sf->status != 0) { - WRITE_INT(data->store, sf->faction->no); - WRITE_INT(data->store, sf->status); - } - } - } - WRITE_INT(data->store, 0); + write_allies(data, f->allies); WRITE_SECTION(data->store); - write_groups(data->store, f); + write_groups(data, f); write_spellbook(f->spellbook, data->store); } diff --git a/src/kernel/save.test.c b/src/kernel/save.test.c index 7d51c70ce..e069d7ebf 100644 --- a/src/kernel/save.test.c +++ b/src/kernel/save.test.c @@ -268,6 +268,7 @@ static void test_readwrite_dead_faction_group(CuTest *tc) { CuAssertPtrNotNull(tc, u); g = join_group(u, "group"); CuAssertPtrNotNull(tc, g); + CuAssertPtrEquals(tc, NULL, g->allies); ally_set(&g->allies, f, HELP_GIVE); CuAssertPtrNotNull(tc, g->allies); diff --git a/src/report.c b/src/report.c index d6043c47f..ffe9d072d 100644 --- a/src/report.c +++ b/src/report.c @@ -1510,81 +1510,93 @@ report_template(const char *filename, report_context * ctx, const char *bom) return 0; } +static int count_allies_cb(struct ally *all, faction *af, int status, void *udata) { + int *num = (int *)udata; + if (status > 0) { + ++*num; + } + return 0; +} + +struct show_s { + sbstring sbs; + const faction *f; + int num_allies; +}; + +static int show_allies_cb(struct ally *all, faction *af, int status, void *udata) { + struct show_s * show = (struct show_s *)udata; + const faction * f = show->f; + + int mode = alliance_status(f, af, status); + --show->num_allies; + if (sbs_length(&show->sbs) > 0) { + /* not the first entry */ + if (0 == show->num_allies) { + sbs_strcat(&show->sbs, LOC(f->locale, "list_and")); + } + else { + sbs_strcat(&show->sbs, ", "); + } + } + sbs_strcat(&show->sbs, factionname(af)); + sbs_strcat(&show->sbs, " ("); + if ((mode & HELP_ALL) == HELP_ALL) { + sbs_strcat(&show->sbs, LOC(f->locale, parameters[P_ANY])); + } + else { + int h, hh = 0; + for (h = 1; h <= HELP_TRAVEL; h *= 2) { + int p = MAXPARAMS; + if ((mode & h) == h) { + switch (h) { + case HELP_TRAVEL: + p = P_TRAVEL; + break; + case HELP_MONEY: + p = P_MONEY; + break; + case HELP_FIGHT: + p = P_FIGHT; + break; + case HELP_GIVE: + p = P_GIVE; + break; + case HELP_GUARD: + p = P_GUARD; + break; + case HELP_FSTEALTH: + p = P_FACTIONSTEALTH; + break; + } + } + if (p != MAXPARAMS) { + if (hh) { + sbs_strcat(&show->sbs, ", "); + } + sbs_strcat(&show->sbs, LOC(f->locale, parameters[p])); + hh = 1; + } + } + } + sbs_strcat(&show->sbs, ")"); + return 0; +} + static void show_allies(const faction * f, struct ally * allies, char *buf, size_t size) { - int allierte = 0; - int i = 0, h, hh = 0, dh = 0; - const ally *sf; - - for (sf = allies; sf; sf = sf->next) { - int mode = alliedfaction(f, sf->faction, HELP_ALL); - if (mode > 0) { - ++allierte; - } - } + int num_allies = 0; + allies_walk(allies, count_allies_cb, &num_allies); - if (allierte > 0) { - sbstring sbs; - sbs_init(&sbs, buf, size); + if (num_allies > 0) { + struct show_s show; + show.f = f; + show.num_allies = num_allies; + sbs_init(&show.sbs, buf, size); - for (sf = allies; sf; sf = sf->next) { - int mode = alliedfaction(f, sf->faction, HELP_ALL); - if (mode <= 0) - continue; - i++; - if (dh) { - if (i == allierte) { - sbs_strcat(&sbs, LOC(f->locale, "list_and")); - } - else { - sbs_strcat(&sbs, ", "); - } - } - dh = 1; - hh = 0; - sbs_strcat(&sbs, factionname(sf->faction)); - sbs_strcat(&sbs, " ("); - if ((mode & HELP_ALL) == HELP_ALL) { - sbs_strcat(&sbs, LOC(f->locale, parameters[P_ANY])); - } - else { - for (h = 1; h <= HELP_TRAVEL; h *= 2) { - int p = MAXPARAMS; - if ((mode & h) == h) { - switch (h) { - case HELP_TRAVEL: - p = P_TRAVEL; - break; - case HELP_MONEY: - p = P_MONEY; - break; - case HELP_FIGHT: - p = P_FIGHT; - break; - case HELP_GIVE: - p = P_GIVE; - break; - case HELP_GUARD: - p = P_GUARD; - break; - case HELP_FSTEALTH: - p = P_FACTIONSTEALTH; - break; - } - } - if (p != MAXPARAMS) { - if (hh) { - sbs_strcat(&sbs, ", "); - } - sbs_strcat(&sbs, LOC(f->locale, parameters[p])); - hh = 1; - } - } - } - sbs_strcat(&sbs, ")"); - } - sbs_strcat(&sbs, "."); + allies_walk(allies, show_allies_cb, &show); + sbs_strcat(&show.sbs, "."); } } diff --git a/src/upkeep.c b/src/upkeep.c index 6748d620c..9ab8c1fea 100644 --- a/src/upkeep.c +++ b/src/upkeep.c @@ -167,7 +167,7 @@ void get_food(region * r) struct faction *owner = region_get_owner(r); /* if the region is owned, and the owner is nice, then we'll get * food from the peasants - should not be used with WORK */ - if (owner != NULL && (get_alliance(owner, u->faction) & HELP_MONEY)) { + if (owner != NULL && alliedfaction(owner, u->faction, HELP_MONEY)) { int rm = rmoney(r); int use = (rm < need) ? rm : need; rsetmoney(r, rm - use); diff --git a/src/upkeep.test.c b/src/upkeep.test.c index f2fedc89b..7f5abd02e 100644 --- a/src/upkeep.test.c +++ b/src/upkeep.test.c @@ -1,6 +1,7 @@ #include #include "upkeep.h" +#include #include #include #include @@ -117,7 +118,7 @@ void test_upkeep_from_friend(CuTest * tc) f1 = test_create_faction(test_create_race("human")); f2 = test_create_faction(test_create_race("human")); assert(f1 && f2); - set_alliance(f1, f2, HELP_MONEY); + ally_set(&f1->allies, f2, HELP_MONEY); u1 = test_create_unit(f1, r); u2 = test_create_unit(f2, r); assert(r && u1 && u2); From 1e8c7224a415bf264ac2d5f3925ae2ace0e020ce Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 26 Oct 2018 22:12:43 +0200 Subject: [PATCH 04/11] make consistent use of get_group. --- src/battle.c | 4 +--- src/creport.c | 8 +++----- src/kernel/ally.c | 11 +++++------ src/kernel/race.c | 11 +++-------- src/kernel/unit.c | 7 +++---- src/laws.c | 34 +++++++++++++--------------------- src/reports.c | 5 ++--- 7 files changed, 30 insertions(+), 50 deletions(-) diff --git a/src/battle.c b/src/battle.c index 8ed79a732..3a1628dfe 100644 --- a/src/battle.c +++ b/src/battle.c @@ -3108,9 +3108,7 @@ fighter *make_fighter(battle * b, unit * u, side * s1, bool attack) if (fval(u, UFL_ANON_FACTION) != 0) flags |= SIDE_STEALTH; if (!(AllianceAuto() & HELP_FIGHT) && fval(u, UFL_GROUP)) { - const attrib *agroup = a_find(u->attribs, &at_group); - if (agroup != NULL) - g = (const group *)agroup->data.v; + g = get_group(u); } /* Illusionen und Zauber kaempfen nicht */ diff --git a/src/creport.c b/src/creport.c index 517160a07..d6cc403cd 100644 --- a/src/creport.c +++ b/src/creport.c @@ -799,13 +799,11 @@ void cr_output_unit(stream *out, const faction * f, } if (u->faction == f) { - const attrib *a = NULL; unit *mage; + group * g; - if (fval(u, UFL_GROUP)) - a = a_find(u->attribs, &at_group); - if (a != NULL) { - const group *g = (const group *)a->data.v; + g = get_group(u); + if (g) { stream_printf(out, "%d;gruppe\n", g->gid); } mage = get_familiar_mage(u); diff --git a/src/kernel/ally.c b/src/kernel/ally.c index b439975f3..2e1a4b47b 100644 --- a/src/kernel/ally.c +++ b/src/kernel/ally.c @@ -282,6 +282,8 @@ int alliedunit(const unit * u, const faction * f2, int mask) return 0; } if (u->faction != NULL && f2 != NULL) { + group *g; + if (mask & HELP_FIGHT) { if ((u->flags & UFL_DEFENDER) || (u->faction->flags & FFL_DEFENDER)) { faction *owner = region_get_owner(u->region); @@ -292,12 +294,9 @@ int alliedunit(const unit * u, const faction * f2, int mask) } } - if (fval(u, UFL_GROUP)) { - const attrib *a = a_find(u->attribs, &at_group); - if (a != NULL) { - group *g = (group *)a->data.v; - return alliedgroup(u->faction, f2, g, mask); - } + g = get_group(u); + if (g) { + return alliedgroup(u->faction, f2, g, mask); } return alliedfaction(u->faction, f2, mask); } diff --git a/src/kernel/race.c b/src/kernel/race.c index 8a8311991..53abd339f 100644 --- a/src/kernel/race.c +++ b/src/kernel/race.c @@ -531,14 +531,9 @@ const char *rc_name_s(const race * rc, name_t n) const char *raceprefix(const unit * u) { - attrib *asource = u->faction->attribs; - - if (fval(u, UFL_GROUP)) { - attrib *agroup = a_find(u->attribs, &at_group); - if (agroup != NULL) - asource = ((const group *)(agroup->data.v))->attribs; - } - return get_prefix(asource); + group *g = get_group(u); + attrib *attr = g ? g->attribs : u->faction->attribs; + return get_prefix(attr); } const char *racename(const struct locale *loc, const unit * u, const race * rc) diff --git a/src/kernel/unit.c b/src/kernel/unit.c index b5346e04d..d63cd724c 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -1454,10 +1454,9 @@ unit *create_unit(region * r, faction * f, int number, const struct race *urace, } /* Gruppen */ - if (creator->faction == f && fval(creator, UFL_GROUP)) { - a = a_find(creator->attribs, &at_group); - if (a) { - group *g = (group *)a->data.v; + if (creator->faction == f) { + group *g = get_group(creator); + if (g) { set_group(u, g); } } diff --git a/src/laws.c b/src/laws.c index de10a2719..61eac6a0b 100644 --- a/src/laws.c +++ b/src/laws.c @@ -1317,9 +1317,9 @@ int ally_cmd(unit * u, struct order *ord) sfp = &u->faction->allies; if (fval(u, UFL_GROUP)) { - attrib *a = a_find(u->attribs, &at_group); - if (a) { - sfp = &((group *)a->data.v)->allies; + group *g = get_group(u); + if (g) { + sfp = &g->allies; } } @@ -1453,12 +1453,8 @@ int prefix_cmd(unit * u, struct order *ord) s = gettoken(token, sizeof(token)); if (!s || !*s) { - attrib *a = NULL; - if (fval(u, UFL_GROUP)) { - a = a_find(u->attribs, &at_group); - } - if (a) { - group *g = (group *)a->data.v; + group *g = get_group(u); + if (g) { a_removeall(&g->attribs, &at_raceprefix); } else { @@ -1473,13 +1469,12 @@ int prefix_cmd(unit * u, struct order *ord) cmistake(u, ord, 299, MSG_EVENT); } else { - ap = &u->faction->attribs; - if (fval(u, UFL_GROUP)) { - attrib *a = a_find(u->attribs, &at_group); - if (a) { - group *g = (group *)a->data.v; - ap = &g->attribs; - } + group *g = get_group(u); + if (g) { + ap = &g->attribs; + } + else { + ap = &u->faction->attribs; } set_prefix(ap, race_prefixes[var.i]); } @@ -1839,11 +1834,8 @@ int name_cmd(struct unit *u, struct order *ord) case P_GROUP: { - attrib *a = NULL; - if (fval(u, UFL_GROUP)) - a = a_find(u->attribs, &at_group); - if (a) { - group *g = (group *)a->data.v; + group *g = get_group(u); + if (g) { s = &g->name; break; } diff --git a/src/reports.c b/src/reports.c index 375a28884..12154b70d 100644 --- a/src/reports.c +++ b/src/reports.c @@ -697,9 +697,8 @@ bufunit(const faction * f, const unit * u, seen_mode mode, char *buf, if (!isbattle) { if (u->faction == f) { if (fval(u, UFL_GROUP)) { - attrib *a = a_find(u->attribs, &at_group); - if (a) { - group *g = (group *)a->data.v; + group *g = get_group(u); + if (g) { bufp = STRLCPY(bufp, ", ", size); bufp = STRLCPY(bufp, groupid(g, f), size); } From 2e076aab1eab848c63fdc6f0cc06310415768e84 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 26 Oct 2018 22:16:34 +0200 Subject: [PATCH 05/11] ally_add is now module-private --- src/kernel/ally.c | 26 +++++++++++++------------- src/kernel/ally.h | 1 - 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/kernel/ally.c b/src/kernel/ally.c index 2e1a4b47b..4ec06be6d 100644 --- a/src/kernel/ally.c +++ b/src/kernel/ally.c @@ -25,6 +25,19 @@ typedef struct ally { int status; } ally; +static ally * ally_add(ally **al_p, struct faction *f) { + ally * al; + while (*al_p) { + al = *al_p; + if (f && al->faction == f) return al; + al_p = &al->next; + } + al = (ally *)calloc(1, sizeof(ally)); + al->faction = f; + *al_p = al; + return al; +} + void allies_free(ally *al) { while (al) { @@ -99,19 +112,6 @@ ally * ally_find(ally *al, const struct faction *f) { return 0; } -ally * ally_add(ally **al_p, struct faction *f) { - ally * al; - while (*al_p) { - al = *al_p; - if (f && al->faction == f) return al; - al_p = &al->next; - } - al = (ally *)calloc(1, sizeof(ally)); - al->faction = f; - *al_p = al; - return al; -} - static int ally_flag(const char *s, int help_mask) { if ((help_mask & HELP_MONEY) && strcmp(s, "money") == 0) diff --git a/src/kernel/ally.h b/src/kernel/ally.h index eeb573cb5..19fc0915c 100644 --- a/src/kernel/ally.h +++ b/src/kernel/ally.h @@ -42,7 +42,6 @@ extern "C" { struct ally* ally_find(struct ally*al, const struct faction *f); void ally_set(struct ally**al_p, struct faction *f, int status); int ally_get(struct ally *al, const struct faction *f); - struct ally* ally_add(struct ally**al_p, struct faction *f); int AllianceAuto(void); /* flags that allied factions get automatically */ int HelpMask(void); /* flags restricted to allied factions */ From 7537f8c8edb153b1a6bce774675270bbb83af6ec Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 26 Oct 2018 22:18:06 +0200 Subject: [PATCH 06/11] unused function --- src/kernel/ally.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/kernel/ally.c b/src/kernel/ally.c index 4ec06be6d..1d83c331f 100644 --- a/src/kernel/ally.c +++ b/src/kernel/ally.c @@ -159,13 +159,6 @@ autoalliance(const faction * sf, const faction * f2) return 0; } -static int ally_mode(const ally * sf, int mode) -{ - if (sf == NULL) - return 0; - return sf->status & mode; -} - static void init_npcfaction(variant *var) { var->i = 1; From 84947a7d07097e101c06f3758d00360c2c972560 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 26 Oct 2018 22:21:38 +0200 Subject: [PATCH 07/11] unused variable --- src/bind_faction.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/bind_faction.c b/src/bind_faction.c index fd384ff4f..581b1b0bf 100644 --- a/src/bind_faction.c +++ b/src/bind_faction.c @@ -44,23 +44,6 @@ without prior permission by the authors of Eressea. #include #include -typedef struct helpmode { - const char *name; - int status; -} helpmode; - -static helpmode helpmodes[] = { - { "all", HELP_ALL }, - { "money", HELP_MONEY }, - { "fight", HELP_FIGHT }, - { "observe", HELP_OBSERVE }, - { "give", HELP_GIVE }, - { "guard", HELP_GUARD }, - { "stealth", HELP_FSTEALTH }, - { "travel", HELP_TRAVEL }, - { NULL, 0 } -}; - int tolua_factionlist_next(lua_State * L) { faction **faction_ptr = (faction **)lua_touserdata(L, lua_upvalueindex(1)); From 13647506877f814690cc63829d26587b2586ecf1 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 26 Oct 2018 22:24:04 +0200 Subject: [PATCH 08/11] update copyright date --- src/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.c b/src/main.c index 118f30afd..d51f55471 100644 --- a/src/main.c +++ b/src/main.c @@ -1,5 +1,5 @@ /* -Copyright (c) 1998-2017, Enno Rehling +Copyright (c) 1998-2018, Enno Rehling Katja Zedel @@ -192,7 +192,7 @@ static int parse_args(int argc, char **argv) else if (argi[1] == '-') { /* long format */ if (strcmp(argi + 2, "version") == 0) { printf("Eressea version %s, " - "Copyright (C) 2017 Enno Rehling et al.\n", + "Copyright (C) 2018 Enno Rehling et al.\n", eressea_version()); return 1; #ifdef USE_CURSES From 558390a4a68400898bb4f771eb2cfe08000f4b9f Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 28 Oct 2018 13:45:36 +0100 Subject: [PATCH 09/11] separate ally_ api from allies_ api, delete unallied factions, start worrying about serialization. --- src/creport.c | 2 +- src/kernel/ally.c | 103 ++++++++++++++++++++++++++++++++++++++++- src/kernel/ally.h | 12 +++-- src/kernel/ally.test.c | 21 ++++++++- src/kernel/group.c | 2 +- src/report.c | 4 +- 6 files changed, 133 insertions(+), 11 deletions(-) diff --git a/src/creport.c b/src/creport.c index d6cc403cd..881edc870 100644 --- a/src/creport.c +++ b/src/creport.c @@ -1047,7 +1047,7 @@ static void show_allies_cr(FILE * F, const faction * f, const group *g) data.F = F; data.f = f; struct ally *sf = g ? g->allies : f->allies; - allies_walk(sf, print_ally_cb, &data); + ally_walk(sf, print_ally_cb, &data); } /* prints allies */ diff --git a/src/kernel/ally.c b/src/kernel/ally.c index 1d83c331f..636985410 100644 --- a/src/kernel/ally.c +++ b/src/kernel/ally.c @@ -19,6 +19,105 @@ #include #include +#define BLOCKSIZE 15 +typedef struct allies { + struct allies *next; + int num; + const struct faction *factions[BLOCKSIZE]; + int status[BLOCKSIZE]; +} allies; + +static void block_insert(allies *al, const struct faction *f, int status) { + int i = al->num++; + al->status[i] = status; + al->factions[i] = f; + /* TODO: heapify */ +} + +static int block_search(allies *al, const struct faction *f) { + int i; + /* TODO: binary search */ + for (i = 0; i != al->num; ++i) { + if (al->factions[i] == f) { + return i; + } + } + return BLOCKSIZE; +} + +int allies_get(allies *al, const struct faction *f) +{ + for (; al; al = al->next) { + int i = block_search(al, f); + if (i != BLOCKSIZE) { + return al->status[i]; + } + } + return 0; +} + +void allies_set(allies **p_al, const struct faction *f, int status) +{ + while (*p_al) { + allies *al = *p_al; + int i = block_search(al, f); + if (i != BLOCKSIZE) { + if (status == 0) { + if (--al->num != i) { + al->factions[i] = al->factions[al->num]; + al->status[i] = al->status[al->num]; + /* TODO: repair heap up or down */ + } + else if (al->num == 0) { + *p_al = al->next; + free(al); + return; + } + } + else { + al->status[i] = status; + } + return; + } + if (al->num < BLOCKSIZE) { + block_insert(al, f, status); + return; + } + p_al = &al->next; + } + *p_al = calloc(1, sizeof(allies)); + block_insert(*p_al, f, status); +} + +void allies_write(gamedata * data, const allies *alist) +{ + const allies *al; + for (al = alist; al; al = al->next) { + int i; + for (i = 0; i != al->num; ++i) { + const faction * f = al->factions[i]; + if (f && f->_alive) { + write_faction_reference(f, data->store); + WRITE_INT(data->store, al->status[i]); + } + } + } + write_faction_reference(NULL, data->store); +} + +void allies_read(gamedata * data, allies **sfp) +{ + for (;;) { + int aid, state; + READ_INT(data->store, &aid); + /* TODO: deal with unresolved factions, somehow */ + if (aid >=0) { + break; + } + READ_INT(data->store, &state); + } +} + typedef struct ally { struct ally *next; struct faction *faction; @@ -47,7 +146,7 @@ void allies_free(ally *al) } } -ally *allies_clone(const ally *al) { +ally *ally_clone(const ally *al) { ally *al_clone = NULL, **al_end = &al_clone; for (; al; al = al->next) { @@ -60,7 +159,7 @@ ally *allies_clone(const ally *al) { return al_clone; } -int allies_walk(ally *allies, cb_allies_walk callback, void *udata) +int ally_walk(ally *allies, cb_ally_walk callback, void *udata) { ally *al; for (al = allies; al; al = al->next) { diff --git a/src/kernel/ally.h b/src/kernel/ally.h index 19fc0915c..25b488dac 100644 --- a/src/kernel/ally.h +++ b/src/kernel/ally.h @@ -29,14 +29,20 @@ extern "C" { struct gamedata; struct unit; struct ally; + struct allies; extern struct attrib_type at_npcfaction; + int allies_get(struct allies *al, const struct faction *f); + void allies_set(struct allies **p_al, const struct faction *f, int status); + void allies_write(struct gamedata * data, const struct allies *alist); + void allies_read(struct gamedata * data, struct allies **sfp); + void read_allies(struct gamedata * data, struct ally **alist); void write_allies(struct gamedata * data, const struct ally *alist); - typedef int (*cb_allies_walk)(struct ally *, struct faction *, int, void *); - int allies_walk(struct ally *allies, cb_allies_walk callback, void *udata); - struct ally *allies_clone(const struct ally *al); + typedef int (*cb_ally_walk)(struct ally *, struct faction *, int, void *); + int ally_walk(struct ally *allies, cb_ally_walk callback, void *udata); + struct ally *ally_clone(const struct ally *al); void allies_free(struct ally *al); struct ally* ally_find(struct ally*al, const struct faction *f); diff --git a/src/kernel/ally.test.c b/src/kernel/ally.test.c index 7aaf50fa7..92011c566 100644 --- a/src/kernel/ally.test.c +++ b/src/kernel/ally.test.c @@ -30,10 +30,10 @@ static void test_allies_clone(CuTest * tc) test_setup(); f = test_create_faction(NULL); - CuAssertPtrEquals(tc, NULL, allies_clone(NULL)); + CuAssertPtrEquals(tc, NULL, ally_clone(NULL)); ally_set(&al, f, HELP_GUARD); - ac = allies_clone(al); + ac = ally_clone(al); CuAssertPtrNotNull(tc, ac); CuAssertTrue(tc, al != ac); CuAssertIntEquals(tc, HELP_GUARD, ally_get(ac, f)); @@ -43,10 +43,27 @@ static void test_allies_clone(CuTest * tc) test_teardown(); } +static void test_allies(CuTest *tc) { + struct allies * al = NULL; + struct faction * f; + + test_setup(); + f = test_create_faction(NULL); + + CuAssertIntEquals(tc, 0, allies_get(al, f)); + allies_set(&al, f, 42); + CuAssertIntEquals(tc, 42, allies_get(al, f)); + allies_set(&al, f, 0); + CuAssertIntEquals(tc, 0, allies_get(al, f)); + CuAssertPtrEquals(tc, NULL, al); + test_teardown(); +} + CuSuite *get_ally_suite(void) { CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_ally); + SUITE_ADD_TEST(suite, test_allies); SUITE_ADD_TEST(suite, test_allies_clone); return suite; } diff --git a/src/kernel/group.c b/src/kernel/group.c index 210f6e0f2..9e91d17a1 100755 --- a/src/kernel/group.c +++ b/src/kernel/group.c @@ -69,7 +69,7 @@ group *new_group(faction * f, const char *name, int gid) static void init_group(faction * f, group * g) { - g->allies = allies_clone(f->allies); + g->allies = ally_clone(f->allies); } static group *find_groupbyname(group * g, const char *name) diff --git a/src/report.c b/src/report.c index ffe9d072d..1bba84307 100644 --- a/src/report.c +++ b/src/report.c @@ -1587,7 +1587,7 @@ static void show_allies(const faction * f, struct ally * allies, char *buf, size_t size) { int num_allies = 0; - allies_walk(allies, count_allies_cb, &num_allies); + ally_walk(allies, count_allies_cb, &num_allies); if (num_allies > 0) { struct show_s show; @@ -1595,7 +1595,7 @@ show_allies(const faction * f, struct ally * allies, char *buf, size_t size) show.num_allies = num_allies; sbs_init(&show.sbs, buf, size); - allies_walk(allies, show_allies_cb, &show); + ally_walk(allies, show_allies_cb, &show); sbs_strcat(&show.sbs, "."); } } From 54307d3b50c19cc78d07a7da3fa9a7e3da988421 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 30 Oct 2018 18:45:13 +0100 Subject: [PATCH 10/11] can read and write struct allies. --- src/kernel/ally.c | 12 ++++++++---- src/kernel/ally.test.c | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/kernel/ally.c b/src/kernel/ally.c index 1053f8e28..1f57609c7 100644 --- a/src/kernel/ally.c +++ b/src/kernel/ally.c @@ -105,16 +105,20 @@ void allies_write(gamedata * data, const allies *alist) write_faction_reference(NULL, data->store); } -void allies_read(gamedata * data, allies **sfp) +void allies_read(gamedata * data, allies **p_al) { for (;;) { - int aid, state; + faction *f; + int aid, status; READ_INT(data->store, &aid); /* TODO: deal with unresolved factions, somehow */ - if (aid >=0) { + if (aid <= 0) { break; } - READ_INT(data->store, &state); + f = findfaction(aid); + if (!f) f = faction_create(aid); + READ_INT(data->store, &status); + allies_set(p_al, f, status); } } diff --git a/src/kernel/ally.test.c b/src/kernel/ally.test.c index 92011c566..0b17870bb 100644 --- a/src/kernel/ally.test.c +++ b/src/kernel/ally.test.c @@ -23,7 +23,7 @@ static void test_ally(CuTest * tc) test_teardown(); } -static void test_allies_clone(CuTest * tc) +static void test_ally_clone(CuTest * tc) { struct ally * al = NULL, *ac; struct faction * f; @@ -63,8 +63,8 @@ CuSuite *get_ally_suite(void) { CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_ally); + SUITE_ADD_TEST(suite, test_ally_clone); SUITE_ADD_TEST(suite, test_allies); - SUITE_ADD_TEST(suite, test_allies_clone); return suite; } From b0485ec57f46754cade2c0ab4baca1aac7e89ab0 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 31 Oct 2018 17:54:40 +0100 Subject: [PATCH 11/11] eliminate struct ally, use struct allies --- src/creport.c | 6 +- src/kernel/ally.c | 149 +++++++++-------------------------------- src/kernel/ally.h | 37 +++++----- src/kernel/ally.test.c | 39 +++-------- src/kernel/faction.h | 2 +- src/kernel/group.c | 2 +- src/kernel/group.h | 2 +- src/laws.c | 2 +- src/report.c | 10 +-- 9 files changed, 69 insertions(+), 180 deletions(-) diff --git a/src/creport.c b/src/creport.c index 881edc870..69a9ed03e 100644 --- a/src/creport.c +++ b/src/creport.c @@ -1029,7 +1029,7 @@ struct print_ally_s { FILE *F; }; -static int print_ally_cb(struct ally *al, faction *af, int status, void *udata) { +static int print_ally_cb(struct allies *al, faction *af, int status, void *udata) { struct print_ally_s *data = (struct print_ally_s *)udata; UNUSED_ARG(al); @@ -1046,8 +1046,8 @@ static void show_allies_cr(FILE * F, const faction * f, const group *g) struct print_ally_s data; data.F = F; data.f = f; - struct ally *sf = g ? g->allies : f->allies; - ally_walk(sf, print_ally_cb, &data); + struct allies *sf = g ? g->allies : f->allies; + allies_walk(sf, print_ally_cb, &data); } /* prints allies */ diff --git a/src/kernel/ally.c b/src/kernel/ally.c index 1f57609c7..80ef6b18f 100644 --- a/src/kernel/ally.c +++ b/src/kernel/ally.c @@ -23,11 +23,11 @@ typedef struct allies { struct allies *next; int num; - const struct faction *factions[BLOCKSIZE]; + struct faction *factions[BLOCKSIZE]; int status[BLOCKSIZE]; } allies; -static void block_insert(allies *al, const struct faction *f, int status) { +static void block_insert(allies *al, struct faction *f, int status) { int i = al->num++; al->status[i] = status; al->factions[i] = f; @@ -45,7 +45,22 @@ static int block_search(allies *al, const struct faction *f) { return BLOCKSIZE; } -int allies_get(allies *al, const struct faction *f) +int allies_walk(struct allies *all, cb_allies_walk callback, void *udata) +{ + allies *al; + for (al = all; al; al = al->next) { + int i; + for (i = 0; i != al->num; ++i) { + int e = callback(all, al->factions[i], al->status[i], udata); + if (e != 0) { + return e; + } + } + } + return 0; +} + +int ally_get(allies *al, const struct faction *f) { for (; al; al = al->next) { int i = block_search(al, f); @@ -56,7 +71,7 @@ int allies_get(allies *al, const struct faction *f) return 0; } -void allies_set(allies **p_al, const struct faction *f, int status) +void ally_set(allies **p_al, struct faction *f, int status) { while (*p_al) { allies *al = *p_al; @@ -89,7 +104,7 @@ void allies_set(allies **p_al, const struct faction *f, int status) block_insert(*p_al, f, status); } -void allies_write(gamedata * data, const allies *alist) +void write_allies(gamedata * data, const allies *alist) { const allies *al; for (al = alist; al; al = al->next) { @@ -105,7 +120,7 @@ void allies_write(gamedata * data, const allies *alist) write_faction_reference(NULL, data->store); } -void allies_read(gamedata * data, allies **p_al) +void read_allies(gamedata * data, allies **p_al) { for (;;) { faction *f; @@ -118,103 +133,32 @@ void allies_read(gamedata * data, allies **p_al) f = findfaction(aid); if (!f) f = faction_create(aid); READ_INT(data->store, &status); - allies_set(p_al, f, status); + ally_set(p_al, f, status); } } -typedef struct ally { - struct ally *next; - struct faction *faction; - int status; -} ally; - -static ally * ally_add(ally **al_p, struct faction *f) { - ally * al; - while (*al_p) { - al = *al_p; - if (f && al->faction == f) return al; - al_p = &al->next; - } - al = (ally *)calloc(1, sizeof(ally)); - al->faction = f; - *al_p = al; - return al; -} - -void allies_free(ally *al) +void allies_free(allies *al) { while (al) { - ally * an = al->next; + allies * an = al->next; free(al); al = an; } } -ally *ally_clone(const ally *al) { - ally *al_clone = NULL, **al_end = &al_clone; +allies *allies_clone(const allies *al) { + allies *al_clone = NULL, **al_end = &al_clone; for (; al; al = al->next) { - if (al->faction) { - ally * al_new = ally_add(al_end, al->faction); - al_new->status = al->status; - al_end = &al_new->next; - } + allies *al_new = calloc(1, sizeof(allies)); + memcpy(al_new, al, sizeof(allies)); + *al_end = al_new; + al_end = &al_new->next; } + *al_end = NULL; return al_clone; } -int ally_walk(ally *allies, cb_ally_walk callback, void *udata) -{ - ally *al; - for (al = allies; al; al = al->next) { - int err = callback(allies, al->faction, al->status, udata); - if (err != 0) { - return err; - } - } - return 0; -} - -void write_allies(gamedata * data, const ally *alist) -{ - const ally *a; - for (a = alist; a; a = a->next) { - if (a->faction && a->faction->_alive) { - write_faction_reference(a->faction, data->store); - WRITE_INT(data->store, a->status); - } - } - write_faction_reference(NULL, data->store); -} - -void read_allies(gamedata * data, ally **sfp) -{ - for (;;) { - int aid; - READ_INT(data->store, &aid); - if (aid > 0) { - ally * al = ally_add(sfp, NULL); - int state; - if ((al->faction = findfaction(aid)) == NULL) { - al->faction = faction_create(aid); - } - READ_INT(data->store, &state); - al->status = state & HELP_ALL; - sfp = &al->next; - } - else { - break; - } - } -} - -ally * ally_find(ally *al, const struct faction *f) { - for (; al; al = al->next) { - if (al->faction == f) return al; - } - return 0; -} - static int ally_flag(const char *s, int help_mask) { if ((help_mask & HELP_MONEY) && strcmp(s, "money") == 0) @@ -349,7 +293,7 @@ int alliedgroup(const struct faction *f, const struct faction *f2, const struct group *g, int mask) { - ally *all = g ? g->allies : f->allies; + allies *all = g ? g->allies : f->allies; int status; if (!(faction_alive(f) && faction_alive(f2))) { @@ -399,32 +343,3 @@ int alliedunit(const unit * u, const faction * f2, int mask) return 0; } -void ally_set(ally **allies, struct faction *f, int status) { - ally *al; - while (*allies) { - al = *allies; - if (al->faction == f) { - if (status != 0) { - al->status = status; - } - else { - *allies = al->next; - free(al); - } - return; - } - allies = &al->next; - } - al = ally_add(allies, f); - al->status = status; -} - -int ally_get(ally *allies, const struct faction *f) { - ally *al; - for (al = allies; al; al = al->next) { - if (al->faction == f) { - return al->status; - } - } - return 0; -} diff --git a/src/kernel/ally.h b/src/kernel/ally.h index 25b488dac..3d9058bc4 100644 --- a/src/kernel/ally.h +++ b/src/kernel/ally.h @@ -23,31 +23,24 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. extern "C" { #endif - struct attrib_type; - struct faction; - struct group; - struct gamedata; - struct unit; - struct ally; - struct allies; +struct attrib_type; +struct faction; +struct group; +struct gamedata; +struct unit; +struct allies; - extern struct attrib_type at_npcfaction; +extern struct attrib_type at_npcfaction; - int allies_get(struct allies *al, const struct faction *f); - void allies_set(struct allies **p_al, const struct faction *f, int status); - void allies_write(struct gamedata * data, const struct allies *alist); - void allies_read(struct gamedata * data, struct allies **sfp); +int ally_get(struct allies *al, const struct faction *f); +void ally_set(struct allies **p_al, struct faction *f, int status); +void write_allies(struct gamedata * data, const struct allies *alist); +void read_allies(struct gamedata * data, struct allies **sfp); +typedef int (*cb_allies_walk)(struct allies *, struct faction *, int, void *); +int allies_walk(struct allies *allies, cb_allies_walk callback, void *udata); +struct allies *allies_clone(const struct allies *al); - void read_allies(struct gamedata * data, struct ally **alist); - void write_allies(struct gamedata * data, const struct ally *alist); - typedef int (*cb_ally_walk)(struct ally *, struct faction *, int, void *); - int ally_walk(struct ally *allies, cb_ally_walk callback, void *udata); - struct ally *ally_clone(const struct ally *al); - void allies_free(struct ally *al); - - struct ally* ally_find(struct ally*al, const struct faction *f); - void ally_set(struct ally**al_p, struct faction *f, int status); - int ally_get(struct ally *al, const struct faction *f); +void allies_free(struct allies *al); int AllianceAuto(void); /* flags that allied factions get automatically */ int HelpMask(void); /* flags restricted to allied factions */ diff --git a/src/kernel/ally.test.c b/src/kernel/ally.test.c index 0b17870bb..248eb5831 100644 --- a/src/kernel/ally.test.c +++ b/src/kernel/ally.test.c @@ -5,35 +5,17 @@ #include #include -static void test_ally(CuTest * tc) +static void test_allies_clone(CuTest * tc) { - struct ally * al = NULL; + struct allies * al = NULL, *ac; struct faction * f; test_setup(); f = test_create_faction(NULL); - ally_set(&al, f, HELP_GUARD); - CuAssertPtrNotNull(tc, al); - CuAssertIntEquals(tc, HELP_GUARD, ally_get(al, f)); - - ally_set(&al, f, 0); - CuAssertPtrEquals(tc, NULL, al); - CuAssertIntEquals(tc, 0, ally_get(al, f)); - allies_free(al); - test_teardown(); -} - -static void test_ally_clone(CuTest * tc) -{ - struct ally * al = NULL, *ac; - struct faction * f; - - test_setup(); - f = test_create_faction(NULL); - CuAssertPtrEquals(tc, NULL, ally_clone(NULL)); + CuAssertPtrEquals(tc, NULL, allies_clone(NULL)); ally_set(&al, f, HELP_GUARD); - ac = ally_clone(al); + ac = allies_clone(al); CuAssertPtrNotNull(tc, ac); CuAssertTrue(tc, al != ac); CuAssertIntEquals(tc, HELP_GUARD, ally_get(ac, f)); @@ -50,11 +32,11 @@ static void test_allies(CuTest *tc) { test_setup(); f = test_create_faction(NULL); - CuAssertIntEquals(tc, 0, allies_get(al, f)); - allies_set(&al, f, 42); - CuAssertIntEquals(tc, 42, allies_get(al, f)); - allies_set(&al, f, 0); - CuAssertIntEquals(tc, 0, allies_get(al, f)); + CuAssertIntEquals(tc, 0, ally_get(al, f)); + ally_set(&al, f, 42); + CuAssertIntEquals(tc, 42, ally_get(al, f)); + ally_set(&al, f, 0); + CuAssertIntEquals(tc, 0, ally_get(al, f)); CuAssertPtrEquals(tc, NULL, al); test_teardown(); } @@ -62,9 +44,8 @@ static void test_allies(CuTest *tc) { CuSuite *get_ally_suite(void) { CuSuite *suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, test_ally); - SUITE_ADD_TEST(suite, test_ally_clone); SUITE_ADD_TEST(suite, test_allies); + SUITE_ADD_TEST(suite, test_allies_clone); return suite; } diff --git a/src/kernel/faction.h b/src/kernel/faction.h index caa908da5..04070c91a 100644 --- a/src/kernel/faction.h +++ b/src/kernel/faction.h @@ -86,7 +86,7 @@ extern "C" { int num_people; /* Anzahl Personen ohne Monster */ int num_units; int options; - struct ally *allies; /* alliedgroup and others should check sf.faction.alive before using a faction from f.allies */ + struct allies *allies; /* alliedgroup and others should check sf.faction.alive before using a faction from f.allies */ struct group *groups; /* alliedgroup and others should check sf.faction.alive before using a faction from f.groups */ score_t score; struct alliance *alliance; diff --git a/src/kernel/group.c b/src/kernel/group.c index 9e91d17a1..210f6e0f2 100755 --- a/src/kernel/group.c +++ b/src/kernel/group.c @@ -69,7 +69,7 @@ group *new_group(faction * f, const char *name, int gid) static void init_group(faction * f, group * g) { - g->allies = ally_clone(f->allies); + g->allies = allies_clone(f->allies); } static group *find_groupbyname(group * g, const char *name) diff --git a/src/kernel/group.h b/src/kernel/group.h index b66e3f50b..9b6d97cf9 100755 --- a/src/kernel/group.h +++ b/src/kernel/group.h @@ -30,7 +30,7 @@ extern "C" { struct faction *f; struct attrib *attribs; char *name; - struct ally *allies; + struct allies *allies; int gid; int members; } group; diff --git a/src/laws.c b/src/laws.c index 61eac6a0b..775bd78a0 100644 --- a/src/laws.c +++ b/src/laws.c @@ -1290,7 +1290,7 @@ void quit(void) int ally_cmd(unit * u, struct order *ord) { char token[128]; - struct ally **sfp; + struct allies **sfp; faction *f; int keyword, not_kw; const char *s; diff --git a/src/report.c b/src/report.c index f641534f1..b6ed3f736 100644 --- a/src/report.c +++ b/src/report.c @@ -1511,7 +1511,7 @@ report_template(const char *filename, report_context * ctx, const char *bom) return 0; } -static int count_allies_cb(struct ally *all, faction *af, int status, void *udata) { +static int count_allies_cb(struct allies *all, faction *af, int status, void *udata) { int *num = (int *)udata; if (status > 0) { ++*num; @@ -1525,7 +1525,7 @@ struct show_s { int num_allies; }; -static int show_allies_cb(struct ally *all, faction *af, int status, void *udata) { +static int show_allies_cb(struct allies *all, faction *af, int status, void *udata) { struct show_s * show = (struct show_s *)udata; const faction * f = show->f; @@ -1585,10 +1585,10 @@ static int show_allies_cb(struct ally *all, faction *af, int status, void *udata } static void -show_allies(const faction * f, struct ally * allies, char *buf, size_t size) +show_allies(const faction * f, struct allies * allies, char *buf, size_t size) { int num_allies = 0; - ally_walk(allies, count_allies_cb, &num_allies); + allies_walk(allies, count_allies_cb, &num_allies); if (num_allies > 0) { struct show_s show; @@ -1596,7 +1596,7 @@ show_allies(const faction * f, struct ally * allies, char *buf, size_t size) show.num_allies = num_allies; sbs_init(&show.sbs, buf, size); - ally_walk(allies, show_allies_cb, &show); + allies_walk(allies, show_allies_cb, &show); sbs_strcat(&show.sbs, "."); } }