Merge branch 'allies' into develop

This commit is contained in:
Enno Rehling 2018-10-31 19:10:51 +01:00
commit 923c895382
22 changed files with 413 additions and 437 deletions

View file

@ -1437,7 +1437,7 @@ msgstr "Goblins"
msgctxt "spellinfo" msgctxt "spellinfo"
msgid "song_of_slavery" 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" msgctxt "spell"
msgid "healingzone" msgid "healingzone"

View file

@ -3108,9 +3108,7 @@ fighter *make_fighter(battle * b, unit * u, side * s1, bool attack)
if (fval(u, UFL_ANON_FACTION) != 0) if (fval(u, UFL_ANON_FACTION) != 0)
flags |= SIDE_STEALTH; flags |= SIDE_STEALTH;
if (!(AllianceAuto() & HELP_FIGHT) && fval(u, UFL_GROUP)) { if (!(AllianceAuto() & HELP_FIGHT) && fval(u, UFL_GROUP)) {
const attrib *agroup = a_find(u->attribs, &at_group); g = get_group(u);
if (agroup != NULL)
g = (const group *)agroup->data.v;
} }
/* Illusionen und Zauber kaempfen nicht */ /* Illusionen und Zauber kaempfen nicht */

View file

@ -44,23 +44,6 @@ without prior permission by the authors of Eressea.
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
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) int tolua_factionlist_next(lua_State * L)
{ {
faction **faction_ptr = (faction **)lua_touserdata(L, lua_upvalueindex(1)); faction **faction_ptr = (faction **)lua_touserdata(L, lua_upvalueindex(1));
@ -309,49 +292,6 @@ static int tolua_faction_count_msg_type(lua_State *L) {
return 1; 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) static int tolua_faction_normalize(lua_State * L)
{ {
faction *f = (faction *)tolua_tousertype(L, 1, 0); faction *f = (faction *)tolua_tousertype(L, 1, 0);
@ -632,8 +572,6 @@ void tolua_faction_open(lua_State * L)
tolua_variable(L, TOLUA_CAST "lastturn", tolua_faction_get_lastturn, tolua_variable(L, TOLUA_CAST "lastturn", tolua_faction_get_lastturn,
tolua_faction_set_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 "get_origin", tolua_faction_get_origin);
tolua_function(L, TOLUA_CAST "set_origin", tolua_faction_set_origin); tolua_function(L, TOLUA_CAST "set_origin", tolua_faction_set_origin);
tolua_function(L, TOLUA_CAST "normalize", tolua_faction_normalize); tolua_function(L, TOLUA_CAST "normalize", tolua_faction_normalize);

View file

@ -799,13 +799,11 @@ void cr_output_unit(stream *out, const faction * f,
} }
if (u->faction == f) { if (u->faction == f) {
const attrib *a = NULL;
unit *mage; unit *mage;
group * g;
if (fval(u, UFL_GROUP)) g = get_group(u);
a = a_find(u->attribs, &at_group); if (g) {
if (a != NULL) {
const group *g = (const group *)a->data.v;
stream_printf(out, "%d;gruppe\n", g->gid); stream_printf(out, "%d;gruppe\n", g->gid);
} }
mage = get_familiar_mage(u); mage = get_familiar_mage(u);
@ -1018,21 +1016,38 @@ static void cr_output_unit_compat(FILE * F, const faction * f,
cr_output_unit(&strm, f, u, mode); cr_output_unit(&strm, f, u, mode);
} }
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ static void print_ally(const faction *f, faction *af, int status, FILE *F) {
if (af && 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 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);
if (af && faction_alive(af)) {
int mode = alliance_status(data->f, af, status);
print_ally(data->f, af, mode, data->F);
}
return 0;
}
/* prints allies */ /* prints allies */
static void show_allies_cr(FILE * F, const faction * f, const group *g) static void show_allies_cr(FILE * F, const faction * f, const group *g)
{ {
ally * sf = g ? g->allies : f->allies; struct print_ally_s data;
for (; sf; sf = sf->next) data.F = F;
if (sf->faction && faction_alive(sf->faction)) { data.f = f;
int mode = alliedgroup(f, sf->faction, g, HELP_ALL); struct allies *sf = g ? g->allies : f->allies;
if (mode != 0 && sf->status > 0) { allies_walk(sf, print_ally_cb, &data);
fprintf(F, "ALLIANZ %d\n", sf->faction->no);
fprintf(F, "\"%s\";Parteiname\n", sf->faction->name);
fprintf(F, "%d;Status\n", sf->status);
}
}
} }
/* prints allies */ /* prints allies */

View file

@ -19,45 +19,144 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
void read_allies(gamedata * data, ally **sfp) #define BLOCKSIZE 15
{ typedef struct allies {
for (;;) { struct allies *next;
int aid; int num;
READ_INT(data->store, &aid); struct faction *factions[BLOCKSIZE];
if (aid > 0) { int status[BLOCKSIZE];
ally * al = ally_add(sfp, NULL); } allies;
int state;
if ((al->faction = findfaction(aid)) == NULL) { static void block_insert(allies *al, struct faction *f, int status) {
al->faction = faction_create(aid); int i = al->num++;
} al->status[i] = status;
READ_INT(data->store, &state); al->factions[i] = f;
al->status = state & HELP_ALL; /* TODO: heapify */
sfp = &al->next;
}
else {
break;
}
}
} }
ally * ally_find(ally *al, const struct faction *f) { static int block_search(allies *al, const struct faction *f) {
for (; al; al = al->next) { int i;
if (al->faction == f) return al; /* TODO: binary search */
for (i = 0; i != al->num; ++i) {
if (al->factions[i] == f) {
return i;
}
}
return BLOCKSIZE;
}
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; return 0;
} }
ally * ally_add(ally **al_p, struct faction *f) { int ally_get(allies *al, const struct faction *f)
ally * al; {
while (*al_p) { for (; al; al = al->next) {
al = *al_p; int i = block_search(al, f);
if (f && al->faction == f) return al; if (i != BLOCKSIZE) {
al_p = &al->next; return al->status[i];
}
} }
al = (ally *)calloc(1, sizeof(ally)); return 0;
al->faction = f; }
*al_p = al;
return al; void ally_set(allies **p_al, 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 write_allies(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 read_allies(gamedata * data, allies **p_al)
{
for (;;) {
faction *f;
int aid, status;
READ_INT(data->store, &aid);
/* TODO: deal with unresolved factions, somehow */
if (aid <= 0) {
break;
}
f = findfaction(aid);
if (!f) f = faction_create(aid);
READ_INT(data->store, &status);
ally_set(p_al, f, status);
}
}
void allies_free(allies *al)
{
while (al) {
allies * an = al->next;
free(al);
al = an;
}
}
allies *allies_clone(const allies *al) {
allies *al_clone = NULL, **al_end = &al_clone;
for (; al; al = al->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;
} }
static int ally_flag(const char *s, int help_mask) static int ally_flag(const char *s, int help_mask)
@ -101,21 +200,12 @@ int AllianceAuto(void)
static int static int
autoalliance(const faction * sf, const faction * f2) autoalliance(const faction * sf, const faction * f2)
{ {
if (f_get_alliance(sf) != NULL && AllianceAuto()) { if (sf->alliance == f2->alliance) {
if (sf->alliance == f2->alliance) return AllianceAuto();
return AllianceAuto();
} }
return 0; 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) static void init_npcfaction(variant *var)
{ {
var->i = 1; var->i = 1;
@ -140,12 +230,13 @@ attrib_type at_npcfaction = {
*/ */
int HelpMask(void) int HelpMask(void)
{ {
static int config, rule = 0; static int config, rule;
if (config_changed(&config)) { if (config_changed(&config)) {
const char *str = config_get("rules.help.mask"); const char *str = config_get("rules.help.mask");
if (str != NULL) { if (str != NULL) {
char *sstr = str_strdup(str); char *sstr = str_strdup(str);
char *tok = strtok(sstr, " "); char *tok = strtok(sstr, " ");
rule = 0;
while (tok) { while (tok) {
rule |= ally_flag(tok, -1); rule |= ally_flag(tok, -1);
tok = strtok(NULL, " "); tok = strtok(NULL, " ");
@ -161,71 +252,79 @@ int HelpMask(void)
static int AllianceRestricted(void) static int AllianceRestricted(void)
{ {
const char *str = config_get("alliance.restricted"); static int config, rule;
int rule = 0; if (config_changed(&config)) {
if (str != NULL) { const char *str = config_get("alliance.restricted");
char *sstr = str_strdup(str); rule = 0;
char *tok = strtok(sstr, " "); if (str != NULL) {
while (tok) { char *sstr = str_strdup(str);
rule |= ally_flag(tok, -1); char *tok = strtok(sstr, " ");
tok = strtok(NULL, " "); while (tok) {
rule |= ally_flag(tok, -1);
tok = strtok(NULL, " ");
}
free(sstr);
} }
free(sstr); rule &= HelpMask();
} }
rule &= HelpMask();
return rule; return rule;
} }
int alliance_status(const faction *f, const faction *f2, int status) {
status |= autoalliance(f, f2);
if (status > 0) {
int mask = AllianceRestricted();
if (mask) {
if (a_find(f->attribs, &at_npcfaction)) {
return status;
}
if (a_find(f2->attribs, &at_npcfaction)) {
return status;
}
if (f->alliance != f2->alliance) {
status &= ~mask;
}
}
}
return status;
}
int int
alliedgroup(const struct faction *f, alliedgroup(const struct faction *f,
const struct faction *f2, const struct group *g, int mode) const struct faction *f2, const struct group *g, int mask)
{ {
ally *sf = g ? g->allies : f->allies; allies *all = g ? g->allies : f->allies;
int status;
if (!(faction_alive(f) && faction_alive(f2))) { if (!(faction_alive(f) && faction_alive(f2))) {
return 0; return 0;
} }
while (sf && sf->faction != f2) { status = ally_get(all, f2) & mask;
sf = sf->next; return alliance_status(f, f2, status);
}
if (sf == NULL) {
mode = mode & autoalliance(f, f2);
}
mode = ally_mode(sf, mode) | (mode & autoalliance(f, f2));
if (AllianceRestricted()) {
if (a_find(f->attribs, &at_npcfaction)) {
return mode;
}
if (a_find(f2->attribs, &at_npcfaction)) {
return mode;
}
if (f->alliance != f2->alliance) {
mode &= ~AllianceRestricted();
}
}
return mode;
} }
int int
alliedfaction(const struct faction *f, const struct faction *f2, int mode) alliedfaction(const struct faction *f, const struct faction *f2, int mask)
{ {
return alliedgroup(f, f2, NULL, mode); return alliedgroup(f, f2, NULL, mask);
} }
/* Die Gruppe von Einheit u hat helfe zu f2 gesetzt. */ /* 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(u);
assert(f2); assert(f2);
assert(u->region); /* the unit should be in a region, but it's possible that u->number==0 (TEMP units) */ assert(u->region); /* the unit should be in a region, but it's possible that u->number==0 (TEMP units) */
if (u->faction == f2) { if (u->faction == f2) {
return mode; return mask;
} }
if (!faction_alive(f2)) { if (!faction_alive(f2)) {
return 0; return 0;
} }
if (u->faction != NULL && f2 != NULL) { if (u->faction != NULL && f2 != NULL) {
if (mode & HELP_FIGHT) { group *g;
if (mask & HELP_FIGHT) {
if ((u->flags & UFL_DEFENDER) || (u->faction->flags & FFL_DEFENDER)) { if ((u->flags & UFL_DEFENDER) || (u->faction->flags & FFL_DEFENDER)) {
faction *owner = region_get_owner(u->region); faction *owner = region_get_owner(u->region);
/* helps the owner of the region */ /* helps the owner of the region */
@ -235,44 +334,12 @@ int alliedunit(const unit * u, const faction * f2, int mode)
} }
} }
if (fval(u, UFL_GROUP)) { g = get_group(u);
const attrib *a = a_find(u->attribs, &at_group); if (g) {
if (a != NULL) { return alliedgroup(u->faction, f2, g, mask);
group *g = (group *)a->data.v;
return alliedgroup(u->faction, f2, g, mode);
}
} }
return alliedfaction(u->faction, f2, mode); return alliedfaction(u->faction, f2, mask);
} }
return 0; 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;
}

View file

@ -23,35 +23,35 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
extern "C" { extern "C" {
#endif #endif
struct attrib_type; struct attrib_type;
struct faction; struct faction;
struct group; struct group;
struct gamedata; struct gamedata;
struct unit; struct unit;
struct allies;
extern struct attrib_type at_npcfaction; extern struct attrib_type at_npcfaction;
typedef struct ally { int ally_get(struct allies *al, const struct faction *f);
struct ally *next; void ally_set(struct allies **p_al, struct faction *f, int status);
struct faction *faction; void write_allies(struct gamedata * data, const struct allies *alist);
int status; void read_allies(struct gamedata * data, struct allies **sfp);
} ally; 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);
int ally_get(struct ally *allies, const struct faction *f); void allies_free(struct allies *al);
void ally_set(struct ally **allies, struct faction *f, int status);
void read_allies(struct gamedata * data, struct ally **allies);
ally * ally_find(ally *al, const struct faction *f);
ally * ally_add(ally **al_p, struct faction *f);
int AllianceAuto(void); /* flags that allied factions get automatically */ int AllianceAuto(void); /* flags that allied factions get automatically */
int HelpMask(void); /* flags restricted to allied factions */ int HelpMask(void); /* flags restricted to allied factions */
int alliedunit(const struct unit *u, const struct faction *f2, 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 alliedfaction(const struct faction *f, const struct faction *f2,
int mode); int mask);
int alliedgroup(const struct faction *f, const struct faction *f2, int alliedgroup(const struct faction *f, const struct faction *f2,
const struct group *g, int mode); const struct group *g, int mask);
int alliance_status(const struct faction *f, const struct faction *f2, int status);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -5,24 +5,47 @@
#include <CuTest.h> #include <CuTest.h>
#include <tests.h> #include <tests.h>
static void test_ally(CuTest * tc) static void test_allies_clone(CuTest * tc)
{ {
ally * al = NULL; struct allies * al = NULL, *ac;
struct faction * f1 = test_create_faction(NULL); struct faction * f;
ally_set(&al, f1, HELP_GUARD); test_setup();
CuAssertPtrNotNull(tc, al); f = test_create_faction(NULL);
CuAssertIntEquals(tc, HELP_GUARD, ally_get(al, f1)); 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();
}
ally_set(&al, f1, 0); static void test_allies(CuTest *tc) {
struct allies * al = NULL;
struct faction * f;
test_setup();
f = test_create_faction(NULL);
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); CuAssertPtrEquals(tc, NULL, al);
CuAssertIntEquals(tc, 0, ally_get(al, f1)); test_teardown();
} }
CuSuite *get_ally_suite(void) CuSuite *get_ally_suite(void)
{ {
CuSuite *suite = CuSuiteNew(); CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_ally); SUITE_ADD_TEST(suite, test_allies);
SUITE_ADD_TEST(suite, test_allies_clone);
return suite; return suite;
} }

View file

@ -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) void renumber_faction(faction * f, int no)
{ {
funhash(f); funhash(f);

View file

@ -86,7 +86,7 @@ extern "C" {
int num_people; /* Anzahl Personen ohne Monster */ int num_people; /* Anzahl Personen ohne Monster */
int num_units; int num_units;
int options; 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 */ struct group *groups; /* alliedgroup and others should check sf.faction.alive before using a faction from f.groups */
score_t score; score_t score;
struct alliance *alliance; struct alliance *alliance;
@ -129,9 +129,6 @@ extern "C" {
bool faction_alive(const struct faction *f); bool faction_alive(const struct faction *f);
struct faction *faction_create(int no); struct faction *faction_create(int no);
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); struct alliance *f_get_alliance(const struct faction *f);
void write_faction_reference(const struct faction *f, void write_faction_reference(const struct faction *f,

View file

@ -53,7 +53,7 @@ group *new_group(faction * f, const char *name, int gid)
{ {
group **gp = &f->groups; group **gp = &f->groups;
int index = gid % GMAXHASH; int index = gid % GMAXHASH;
group *g = calloc(sizeof(group), 1); group *g = calloc(1, sizeof(group));
while (*gp) while (*gp)
gp = &(*gp)->next; 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) static void init_group(faction * f, group * g)
{ {
ally *a, **an; g->allies = allies_clone(f->allies);
an = &g->allies;
for (a = f->allies; a; a = a->next) {
if (a->faction) {
ally_set(an, a->faction, a->status);
}
}
} }
static group *find_groupbyname(group * g, const char *name) static group *find_groupbyname(group * g, const char *name)
@ -138,11 +131,7 @@ void free_group(group * g)
if (g->attribs) { if (g->attribs) {
a_removeall(&g->attribs, NULL); a_removeall(&g->attribs, NULL);
} }
while (g->allies) { allies_free(g->allies);
ally *a = g->allies;
g->allies = a->next;
free(a);
}
free(g->name); free(g->name);
free(g); free(g);
} }
@ -203,20 +192,14 @@ group *join_group(unit * u, const char *name)
return g; return g;
} }
void write_groups(struct storage *store, const faction * f) void write_groups(struct gamedata *data, const faction * f)
{ {
group *g; group *g;
storage *store = data->store;
for (g = f->groups; g; g = g->next) { for (g = f->groups; g; g = g->next) {
ally *a;
WRITE_INT(store, g->gid); WRITE_INT(store, g->gid);
WRITE_STR(store, g->name); WRITE_STR(store, g->name);
for (a = g->allies; a; a = a->next) { write_allies(data, g->allies);
if (a->faction && a->faction->_alive) {
write_faction_reference(a->faction, store);
WRITE_INT(store, a->status);
}
}
write_faction_reference(NULL, store);
a_write(store, g->attribs, g); a_write(store, g->attribs, g);
WRITE_SECTION(store); WRITE_SECTION(store);
} }

View file

@ -30,7 +30,7 @@ extern "C" {
struct faction *f; struct faction *f;
struct attrib *attribs; struct attrib *attribs;
char *name; char *name;
struct ally *allies; struct allies *allies;
int gid; int gid;
int members; int members;
} group; } group;
@ -42,7 +42,7 @@ extern "C" {
extern void free_group(struct group *g); extern void free_group(struct group *g);
struct group *new_group(struct faction * f, const char *name, int gid); 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); extern void read_groups(struct gamedata *data, struct faction *f);
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -84,7 +84,7 @@ static void test_group_readwrite(CuTest * tc)
g = new_group(f, "Egoisten", 43); g = new_group(f, "Egoisten", 43);
key_set(&g->attribs, 44, 44); key_set(&g->attribs, 44, 44);
ally_set(&g->allies, f, HELP_GIVE); ally_set(&g->allies, f, HELP_GIVE);
write_groups(&store, f); write_groups(&data, f);
WRITE_INT(&store, 47); WRITE_INT(&store, 47);
free_group(f->groups); free_group(f->groups);
@ -107,9 +107,7 @@ static void test_group_readwrite(CuTest * tc)
g = f->groups->next; g = f->groups->next;
CuAssertIntEquals(tc, 44, key_get(g->attribs, 44)); CuAssertIntEquals(tc, 44, key_get(g->attribs, 44));
CuAssertPtrNotNull(tc, g->allies); CuAssertPtrNotNull(tc, g->allies);
CuAssertPtrEquals(tc, NULL, g->allies->next); CuAssertIntEquals(tc, HELP_GIVE, ally_get(g->allies, f));
CuAssertPtrEquals(tc, f, g->allies->faction);
CuAssertIntEquals(tc, HELP_GIVE, g->allies->status);
test_teardown(); test_teardown();
} }

View file

@ -531,14 +531,9 @@ const char *rc_name_s(const race * rc, name_t n)
const char *raceprefix(const unit * u) const char *raceprefix(const unit * u)
{ {
attrib *asource = u->faction->attribs; group *g = get_group(u);
attrib *attr = g ? g->attribs : u->faction->attribs;
if (fval(u, UFL_GROUP)) { return get_prefix(attr);
attrib *agroup = a_find(u->attribs, &at_group);
if (agroup != NULL)
asource = ((const group *)(agroup->data.v))->attribs;
}
return get_prefix(asource);
} }
const char *racename(const struct locale *loc, const unit * u, const race * rc) const char *racename(const struct locale *loc, const unit * u, const race * rc)

View file

@ -1093,7 +1093,6 @@ faction *read_faction(gamedata * data)
void write_faction(gamedata *data, const faction * f) void write_faction(gamedata *data, const faction * f)
{ {
ally *sf;
origin *ur; origin *ur;
assert(f->_alive); assert(f->_alive);
@ -1143,19 +1142,9 @@ void write_faction(gamedata *data, const faction * f)
WRITE_INT(data->store, f->options & ~WANT_OPTION(O_DEBUG)); WRITE_INT(data->store, f->options & ~WANT_OPTION(O_DEBUG));
WRITE_SECTION(data->store); WRITE_SECTION(data->store);
for (sf = f->allies; sf; sf = sf->next) { write_allies(data, f->allies);
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_SECTION(data->store); WRITE_SECTION(data->store);
write_groups(data->store, f); write_groups(data, f);
write_spellbook(f->spellbook, data->store); write_spellbook(f->spellbook, data->store);
} }

View file

@ -268,6 +268,7 @@ static void test_readwrite_dead_faction_group(CuTest *tc) {
CuAssertPtrNotNull(tc, u); CuAssertPtrNotNull(tc, u);
g = join_group(u, "group"); g = join_group(u, "group");
CuAssertPtrNotNull(tc, g); CuAssertPtrNotNull(tc, g);
CuAssertPtrEquals(tc, NULL, g->allies);
ally_set(&g->allies, f, HELP_GIVE); ally_set(&g->allies, f, HELP_GIVE);
CuAssertPtrNotNull(tc, g->allies); CuAssertPtrNotNull(tc, g->allies);

View file

@ -1454,10 +1454,9 @@ unit *create_unit(region * r, faction * f, int number, const struct race *urace,
} }
/* Gruppen */ /* Gruppen */
if (creator->faction == f && fval(creator, UFL_GROUP)) { if (creator->faction == f) {
a = a_find(creator->attribs, &at_group); group *g = get_group(creator);
if (a) { if (g) {
group *g = (group *)a->data.v;
set_group(u, g); set_group(u, g);
} }
} }

View file

@ -1290,11 +1290,12 @@ void quit(void)
int ally_cmd(unit * u, struct order *ord) int ally_cmd(unit * u, struct order *ord)
{ {
char token[128]; char token[128];
ally *sf, **sfp; struct allies **sfp;
faction *f; faction *f;
int keyword, not_kw; int keyword, not_kw;
const char *s; const char *s;
int sf_status;
init_order_depr(ord); init_order_depr(ord);
f = getfaction(); f = getfaction();
@ -1316,29 +1317,18 @@ int ally_cmd(unit * u, struct order *ord)
sfp = &u->faction->allies; sfp = &u->faction->allies;
if (fval(u, UFL_GROUP)) { if (fval(u, UFL_GROUP)) {
attrib *a = a_find(u->attribs, &at_group); group *g = get_group(u);
if (a) if (g) {
sfp = &((group *)a->data.v)->allies; sfp = &g->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 */ not_kw = getparam(u->faction->locale); /* HELFE partei [modus] NICHT */
if (!sf) { sf_status = ally_get(*sfp, f);
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;
}
}
switch (keyword) { switch (keyword) {
case P_NOT: case P_NOT:
sf->status = 0; sf_status = 0;
break; break;
case NOPARAM: case NOPARAM:
@ -1346,60 +1336,57 @@ int ally_cmd(unit * u, struct order *ord)
return 0; return 0;
case P_ANY: case P_ANY:
if (not_kw == P_NOT) sf_status = (not_kw == P_NOT) ? 0 : HELP_ALL;
sf->status = 0;
else
sf->status = HELP_ALL;
break; break;
case P_TRAVEL: case P_TRAVEL:
if (not_kw == P_NOT) if (not_kw == P_NOT) {
sf->status = sf->status & (HELP_ALL - HELP_TRAVEL); sf_status = sf_status & (HELP_ALL - HELP_TRAVEL);
else }
sf->status = sf->status | HELP_TRAVEL; else {
sf_status |= HELP_TRAVEL;
}
break; break;
case P_GIVE: case P_GIVE:
if (not_kw == P_NOT) if (not_kw == P_NOT)
sf->status = sf->status & (HELP_ALL - HELP_GIVE); sf_status &= (HELP_ALL - HELP_GIVE);
else else
sf->status = sf->status | HELP_GIVE; sf_status |= HELP_GIVE;
break; break;
case P_MONEY: case P_MONEY:
if (not_kw == P_NOT) if (not_kw == P_NOT)
sf->status = sf->status & (HELP_ALL - HELP_MONEY); sf_status &= (HELP_ALL - HELP_MONEY);
else else
sf->status = sf->status | HELP_MONEY; sf_status |= HELP_MONEY;
break; break;
case P_FIGHT: case P_FIGHT:
if (not_kw == P_NOT) if (not_kw == P_NOT)
sf->status = sf->status & (HELP_ALL - HELP_FIGHT); sf_status &= (HELP_ALL - HELP_FIGHT);
else else
sf->status = sf->status | HELP_FIGHT; sf_status |= HELP_FIGHT;
break; break;
case P_FACTIONSTEALTH: case P_FACTIONSTEALTH:
if (not_kw == P_NOT) if (not_kw == P_NOT)
sf->status = sf->status & (HELP_ALL - HELP_FSTEALTH); sf_status &= (HELP_ALL - HELP_FSTEALTH);
else else
sf->status = sf->status | HELP_FSTEALTH; sf_status |= HELP_FSTEALTH;
break; break;
case P_GUARD: case P_GUARD:
if (not_kw == P_NOT) if (not_kw == P_NOT)
sf->status = sf->status & (HELP_ALL - HELP_GUARD); sf_status &= (HELP_ALL - HELP_GUARD);
else else
sf->status = sf->status | HELP_GUARD; sf_status |= HELP_GUARD;
break; 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; return 0;
} }
@ -1466,12 +1453,8 @@ int prefix_cmd(unit * u, struct order *ord)
s = gettoken(token, sizeof(token)); s = gettoken(token, sizeof(token));
if (!s || !*s) { if (!s || !*s) {
attrib *a = NULL; group *g = get_group(u);
if (fval(u, UFL_GROUP)) { if (g) {
a = a_find(u->attribs, &at_group);
}
if (a) {
group *g = (group *)a->data.v;
a_removeall(&g->attribs, &at_raceprefix); a_removeall(&g->attribs, &at_raceprefix);
} }
else { else {
@ -1486,13 +1469,12 @@ int prefix_cmd(unit * u, struct order *ord)
cmistake(u, ord, 299, MSG_EVENT); cmistake(u, ord, 299, MSG_EVENT);
} }
else { else {
ap = &u->faction->attribs; group *g = get_group(u);
if (fval(u, UFL_GROUP)) { if (g) {
attrib *a = a_find(u->attribs, &at_group); ap = &g->attribs;
if (a) { }
group *g = (group *)a->data.v; else {
ap = &g->attribs; ap = &u->faction->attribs;
}
} }
set_prefix(ap, race_prefixes[var.i]); set_prefix(ap, race_prefixes[var.i]);
} }
@ -1852,11 +1834,8 @@ int name_cmd(struct unit *u, struct order *ord)
case P_GROUP: case P_GROUP:
{ {
attrib *a = NULL; group *g = get_group(u);
if (fval(u, UFL_GROUP)) if (g) {
a = a_find(u->attribs, &at_group);
if (a) {
group *g = (group *)a->data.v;
s = &g->name; s = &g->name;
break; break;
} }

View file

@ -1,5 +1,5 @@
/* /*
Copyright (c) 1998-2017, Enno Rehling <enno@eressea.de> Copyright (c) 1998-2018, Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de> Christian Schlittchen <corwin@amber.kn-bremen.de>
@ -192,7 +192,7 @@ static int parse_args(int argc, char **argv)
else if (argi[1] == '-') { /* long format */ else if (argi[1] == '-') { /* long format */
if (strcmp(argi + 2, "version") == 0) { if (strcmp(argi + 2, "version") == 0) {
printf("Eressea version %s, " printf("Eressea version %s, "
"Copyright (C) 2017 Enno Rehling et al.\n", "Copyright (C) 2018 Enno Rehling et al.\n",
eressea_version()); eressea_version());
return 1; return 1;
#ifdef USE_CURSES #ifdef USE_CURSES

View file

@ -1511,81 +1511,93 @@ report_template(const char *filename, report_context * ctx, const char *bom)
return 0; return 0;
} }
static void static int count_allies_cb(struct allies *all, faction *af, int status, void *udata) {
show_allies(const faction * f, const ally * allies, char *buf, size_t size) int *num = (int *)udata;
{ if (status > 0) {
int allierte = 0; ++*num;
int i = 0, h, hh = 0, dh = 0; }
const ally *sf; return 0;
}
for (sf = allies; sf; sf = sf->next) {
int mode = alliedfaction(f, sf->faction, HELP_ALL); struct show_s {
if (mode > 0) { sbstring sbs;
++allierte; const faction *f;
int num_allies;
};
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;
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));
if (allierte > 0) { sbs_strcat(&show->sbs, " (");
sbstring sbs; if ((mode & HELP_ALL) == HELP_ALL) {
sbs_init(&sbs, buf, size); sbs_strcat(&show->sbs, LOC(f->locale, parameters[P_ANY]));
}
for (sf = allies; sf; sf = sf->next) { else {
int mode = alliedfaction(f, sf->faction, HELP_ALL); int h, hh = 0;
if (mode <= 0) for (h = 1; h <= HELP_TRAVEL; h *= 2) {
continue; int p = MAXPARAMS;
i++; if ((mode & h) == h) {
if (dh) { switch (h) {
if (i == allierte) { case HELP_TRAVEL:
sbs_strcat(&sbs, LOC(f->locale, "list_and")); p = P_TRAVEL;
} break;
else { case HELP_MONEY:
sbs_strcat(&sbs, ", "); 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;
} }
} }
dh = 1; if (p != MAXPARAMS) {
hh = 0; if (hh) {
sbs_strcat(&sbs, factionname(sf->faction)); sbs_strcat(&show->sbs, ", ");
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(&show->sbs, LOC(f->locale, parameters[p]));
hh = 1;
} }
sbs_strcat(&sbs, ")");
} }
sbs_strcat(&sbs, "."); }
sbs_strcat(&show->sbs, ")");
return 0;
}
static void
show_allies(const faction * f, struct allies * allies, char *buf, size_t size)
{
int num_allies = 0;
allies_walk(allies, count_allies_cb, &num_allies);
if (num_allies > 0) {
struct show_s show;
show.f = f;
show.num_allies = num_allies;
sbs_init(&show.sbs, buf, size);
allies_walk(allies, show_allies_cb, &show);
sbs_strcat(&show.sbs, ".");
} }
} }

View file

@ -697,9 +697,8 @@ bufunit(const faction * f, const unit * u, seen_mode mode, char *buf,
if (!isbattle) { if (!isbattle) {
if (u->faction == f) { if (u->faction == f) {
if (fval(u, UFL_GROUP)) { if (fval(u, UFL_GROUP)) {
attrib *a = a_find(u->attribs, &at_group); group *g = get_group(u);
if (a) { if (g) {
group *g = (group *)a->data.v;
bufp = STRLCPY(bufp, ", ", size); bufp = STRLCPY(bufp, ", ", size);
bufp = STRLCPY(bufp, groupid(g, f), size); bufp = STRLCPY(bufp, groupid(g, f), size);
} }

View file

@ -167,7 +167,7 @@ void get_food(region * r)
struct faction *owner = region_get_owner(r); struct faction *owner = region_get_owner(r);
/* if the region is owned, and the owner is nice, then we'll get /* if the region is owned, and the owner is nice, then we'll get
* food from the peasants - should not be used with WORK */ * 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 rm = rmoney(r);
int use = (rm < need) ? rm : need; int use = (rm < need) ? rm : need;
rsetmoney(r, rm - use); rsetmoney(r, rm - use);

View file

@ -1,6 +1,7 @@
#include <platform.h> #include <platform.h>
#include "upkeep.h" #include "upkeep.h"
#include <kernel/ally.h>
#include <kernel/config.h> #include <kernel/config.h>
#include <kernel/faction.h> #include <kernel/faction.h>
#include <kernel/region.h> #include <kernel/region.h>
@ -117,7 +118,7 @@ void test_upkeep_from_friend(CuTest * tc)
f1 = test_create_faction(test_create_race("human")); f1 = test_create_faction(test_create_race("human"));
f2 = test_create_faction(test_create_race("human")); f2 = test_create_faction(test_create_race("human"));
assert(f1 && f2); assert(f1 && f2);
set_alliance(f1, f2, HELP_MONEY); ally_set(&f1->allies, f2, HELP_MONEY);
u1 = test_create_unit(f1, r); u1 = test_create_unit(f1, r);
u2 = test_create_unit(f2, r); u2 = test_create_unit(f2, r);
assert(r && u1 && u2); assert(r && u1 && u2);