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"
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"

View File

@ -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 */

View File

@ -44,23 +44,6 @@ without prior permission by the authors of Eressea.
#include <string.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)
{
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;
}
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 +572,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);

View File

@ -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);
@ -1018,21 +1016,38 @@ 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, 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 */
static void show_allies_cr(FILE * F, const faction * f, const group *g)
{
ally * sf = g ? g->allies : f->allies;
for (; sf; sf = sf->next)
if (sf->faction && faction_alive(sf->faction)) {
int mode = alliedgroup(f, sf->faction, g, 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);
}
}
struct print_ally_s data;
data.F = F;
data.f = f;
struct allies *sf = g ? g->allies : f->allies;
allies_walk(sf, print_ally_cb, &data);
}
/* prints allies */

View File

@ -19,45 +19,144 @@
#include <string.h>
#include <stdlib.h>
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;
}
}
#define BLOCKSIZE 15
typedef struct allies {
struct allies *next;
int num;
struct faction *factions[BLOCKSIZE];
int status[BLOCKSIZE];
} allies;
static void block_insert(allies *al, struct faction *f, int status) {
int i = al->num++;
al->status[i] = status;
al->factions[i] = f;
/* TODO: heapify */
}
ally * ally_find(ally *al, const struct faction *f) {
for (; al; al = al->next) {
if (al->faction == f) return al;
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_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;
}
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;
int ally_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];
}
}
al = (ally *)calloc(1, sizeof(ally));
al->faction = f;
*al_p = al;
return al;
return 0;
}
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)
@ -101,21 +200,12 @@ int AllianceAuto(void)
static int
autoalliance(const faction * sf, const faction * f2)
{
if (f_get_alliance(sf) != NULL && AllianceAuto()) {
if (sf->alliance == f2->alliance)
return AllianceAuto();
if (sf->alliance == f2->alliance) {
return AllianceAuto();
}
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;
@ -140,12 +230,13 @@ attrib_type at_npcfaction = {
*/
int HelpMask(void)
{
static int config, rule = 0;
static int config, rule;
if (config_changed(&config)) {
const char *str = config_get("rules.help.mask");
if (str != NULL) {
char *sstr = str_strdup(str);
char *tok = strtok(sstr, " ");
rule = 0;
while (tok) {
rule |= ally_flag(tok, -1);
tok = strtok(NULL, " ");
@ -161,71 +252,79 @@ int HelpMask(void)
static int AllianceRestricted(void)
{
const char *str = config_get("alliance.restricted");
int rule = 0;
if (str != NULL) {
char *sstr = str_strdup(str);
char *tok = strtok(sstr, " ");
while (tok) {
rule |= ally_flag(tok, -1);
tok = strtok(NULL, " ");
static int config, rule;
if (config_changed(&config)) {
const char *str = config_get("alliance.restricted");
rule = 0;
if (str != NULL) {
char *sstr = str_strdup(str);
char *tok = strtok(sstr, " ");
while (tok) {
rule |= ally_flag(tok, -1);
tok = strtok(NULL, " ");
}
free(sstr);
}
free(sstr);
rule &= HelpMask();
}
rule &= HelpMask();
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
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))) {
return 0;
}
while (sf && sf->faction != f2) {
sf = sf->next;
}
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;
status = ally_get(all, f2) & mask;
return alliance_status(f, f2, status);
}
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. */
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) {
group *g;
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 */
@ -235,44 +334,12 @@ int alliedunit(const unit * u, const faction * f2, int mode)
}
}
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, mode);
}
g = get_group(u);
if (g) {
return alliedgroup(u->faction, f2, g, mask);
}
return alliedfaction(u->faction, f2, mode);
return alliedfaction(u->faction, f2, 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;
}

View File

@ -23,35 +23,35 @@ 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 attrib_type;
struct faction;
struct group;
struct gamedata;
struct unit;
struct allies;
extern struct attrib_type at_npcfaction;
extern struct attrib_type at_npcfaction;
typedef struct ally {
struct ally *next;
struct faction *faction;
int status;
} ally;
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);
int ally_get(struct ally *allies, const struct faction *f);
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);
void allies_free(struct allies *al);
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);
const struct group *g, int mask);
int alliance_status(const struct faction *f, const struct faction *f2, int status);
#ifdef __cplusplus
}

View File

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

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)
{
funhash(f);

View File

@ -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;
@ -129,9 +129,6 @@ extern "C" {
bool faction_alive(const struct faction *f);
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);
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;
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);
}

View File

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

View File

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

View File

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

View File

@ -1093,7 +1093,6 @@ faction *read_faction(gamedata * data)
void write_faction(gamedata *data, const faction * f)
{
ally *sf;
origin *ur;
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_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);
}

View File

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

View File

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

View File

@ -1290,11 +1290,12 @@ void quit(void)
int ally_cmd(unit * u, struct order *ord)
{
char token[128];
ally *sf, **sfp;
struct allies **sfp;
faction *f;
int keyword, not_kw;
const char *s;
int sf_status;
init_order_depr(ord);
f = getfaction();
@ -1316,29 +1317,18 @@ 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;
}
}
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:
@ -1346,60 +1336,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;
}
@ -1466,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 {
@ -1486,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]);
}
@ -1852,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;
}

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
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 */
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

View File

@ -1511,81 +1511,93 @@ report_template(const char *filename, report_context * ctx, const char *bom)
return 0;
}
static void
show_allies(const faction * f, const 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;
static int count_allies_cb(struct allies *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 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, ", ");
}
}
if (allierte > 0) {
sbstring sbs;
sbs_init(&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, ", ");
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;
}
}
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;
}
if (p != MAXPARAMS) {
if (hh) {
sbs_strcat(&show->sbs, ", ");
}
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 (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);
}

View File

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

View File

@ -1,6 +1,7 @@
#include <platform.h>
#include "upkeep.h"
#include <kernel/ally.h>
#include <kernel/config.h>
#include <kernel/faction.h>
#include <kernel/region.h>
@ -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);