diff --git a/src/attributes/otherfaction.c b/src/attributes/otherfaction.c index 8e4e7a6af..83196f959 100644 --- a/src/attributes/otherfaction.c +++ b/src/attributes/otherfaction.c @@ -58,7 +58,8 @@ attrib_type at_otherfaction = { struct faction *get_otherfaction(const struct attrib *a) { - return (faction *)(a->data.v); + faction * f = (faction *)(a->data.v); + return (f && f->_alive) ? f : NULL; } struct attrib *make_otherfaction(struct faction *f) diff --git a/src/bind_faction.c b/src/bind_faction.c index c6b747416..a4302f3c9 100644 --- a/src/bind_faction.c +++ b/src/bind_faction.c @@ -384,8 +384,9 @@ static int tolua_faction_create(lua_State * L) static int tolua_faction_get_password(lua_State * L) { - unused_arg(L); - return 0; + faction *self = (faction *)tolua_tousertype(L, 1, 0); + tolua_pushstring(L, self->_password); + return 1; } static int tolua_faction_set_password(lua_State * L) diff --git a/src/kernel/faction.c b/src/kernel/faction.c index 10c614505..f67dbe47a 100755 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -217,6 +217,7 @@ int resolve_faction(variant id, void *address) result = -1; } } + assert(address); *(faction **)address = f; return result; } @@ -333,7 +334,8 @@ variant read_faction_reference(struct storage * store) void write_faction_reference(const faction * f, struct storage *store) { - WRITE_INT(store, (f && f->_alive) ? f->no : 0); + assert(!f || f->_alive); + WRITE_INT(store, f ? f->no : 0); } static faction *dead_factions; diff --git a/src/kernel/group.c b/src/kernel/group.c index 7d45572cc..fdef2b8b8 100755 --- a/src/kernel/group.c +++ b/src/kernel/group.c @@ -203,12 +203,12 @@ void write_groups(struct storage *store, const faction * f) WRITE_INT(store, g->gid); WRITE_STR(store, g->name); for (a = g->allies; a; a = a->next) { - if (a->faction) { + if (a->faction && a->faction->_alive) { write_faction_reference(a->faction, store); WRITE_INT(store, a->status); } } - WRITE_INT(store, 0); + write_faction_reference(NULL, store); a_write(store, g->attribs, g); WRITE_SECTION(store); } @@ -233,7 +233,7 @@ void read_groups(struct storage *store, faction * f) ally *a; variant fid; - READ_INT(store, &fid.i); + fid = read_faction_reference(store); if (fid.i <= 0) break; a = ally_add(pa, findfaction(fid.i)); diff --git a/src/kernel/group.test.c b/src/kernel/group.test.c index 6fe140863..7daca2829 100644 --- a/src/kernel/group.test.c +++ b/src/kernel/group.test.c @@ -5,6 +5,8 @@ #include "faction.h" #include "unit.h" #include "region.h" +#include +#include #include #include #include @@ -22,34 +24,47 @@ static void test_group_readwrite(CuTest * tc) storage store; FILE *F; stream strm; + int i; - F = fopen("test.dat", "w"); + F = fopen("test.dat", "wb"); fstream_init(&strm, F); binstore_init(&store, &strm); test_cleanup(); test_create_world(); f = test_create_faction(0); - g = new_group(f, "test", 42); + g = new_group(f, "NW", 42); + g = new_group(f, "Egoisten", 43); + a_add(&g->attribs, make_key(44)); al = ally_add(&g->allies, f); al->status = HELP_GIVE; write_groups(&store, f); + WRITE_INT(&store, 47); binstore_done(&store); fstream_done(&strm); - F = fopen("test.dat", "r"); + F = fopen("test.dat", "rb"); fstream_init(&strm, F); binstore_init(&store, &strm); f->groups = 0; - free_group(g); read_groups(&store, f); + READ_INT(&store, &i); binstore_done(&store); fstream_done(&strm); + CuAssertIntEquals(tc, 47, i); CuAssertPtrNotNull(tc, f->groups); - CuAssertPtrNotNull(tc, f->groups->allies); - CuAssertPtrEquals(tc, 0, f->groups->allies->next); - CuAssertPtrEquals(tc, f, f->groups->allies->faction); - CuAssertIntEquals(tc, HELP_GIVE, f->groups->allies->status); + CuAssertIntEquals(tc, 42, f->groups->gid); + CuAssertStrEquals(tc, "NW", f->groups->name); + CuAssertPtrNotNull(tc, f->groups->next); + CuAssertIntEquals(tc, 43, f->groups->next->gid); + CuAssertStrEquals(tc, "Egoisten", f->groups->next->name); + CuAssertPtrEquals(tc, 0, f->groups->allies); + g = f->groups->next; + CuAssertPtrNotNull(tc, find_key(g->attribs, 44)); + CuAssertPtrNotNull(tc, g->allies); + CuAssertPtrEquals(tc, 0, g->allies->next); + CuAssertPtrEquals(tc, f, g->allies->faction); + CuAssertIntEquals(tc, HELP_GIVE, g->allies->status); remove("test.dat"); test_cleanup(); } diff --git a/src/kernel/plane.h b/src/kernel/plane.h index d8ec176a9..926ffb4e2 100644 --- a/src/kernel/plane.h +++ b/src/kernel/plane.h @@ -22,6 +22,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. extern "C" { #endif + struct faction; struct region; struct faction; struct plane; diff --git a/src/kernel/region.h b/src/kernel/region.h index 5974fd96c..72496193b 100644 --- a/src/kernel/region.h +++ b/src/kernel/region.h @@ -66,6 +66,7 @@ extern "C" { struct message_list; struct rawmaterial; struct item; + struct faction; #define MORALE_TAX_FACTOR 0.005 /* 0.5% tax per point of morale */ #define MORALE_MAX 10 /* Maximum morale allowed */ diff --git a/src/kernel/save.c b/src/kernel/save.c index de6dba3a3..44e3f1edf 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -238,8 +238,8 @@ static faction *factionorders(void) /* Die Partei hat sich zumindest gemeldet, so dass sie noch * nicht als untätig gilt */ - /* TODO: +1 ist ein Workaround, weil cturn erst in process_orders - * incrementiert wird. */ + /* TODO: +1 ist ein Workaround, weil cturn erst in process_orders + * incrementiert wird. */ f->lastorders = global.data_turn + 1; } @@ -513,13 +513,14 @@ static void read_owner(struct gamedata *data, region_owner ** powner) int id; READ_INT(data->store, &id); owner->last_owner = id ? findfaction(id) : NULL; - } else if (data->version >= OWNER_2_VERSION) { + } + else if (data->version >= OWNER_2_VERSION) { int id; alliance *a; READ_INT(data->store, &id); a = id ? findalliance(id) : NULL; /* don't know which faction, take the leader */ - owner->last_owner = a? a->_leader : NULL; + owner->last_owner = a ? a->_leader : NULL; } else { owner->last_owner = NULL; @@ -535,11 +536,14 @@ static void read_owner(struct gamedata *data, region_owner ** powner) static void write_owner(struct gamedata *data, region_owner * owner) { if (owner) { + faction *f; WRITE_INT(data->store, owner->since_turn); WRITE_INT(data->store, owner->morale_turn); WRITE_INT(data->store, owner->flags); - write_faction_reference(owner->last_owner, data->store); - write_faction_reference(owner->owner, data->store); + f = owner->last_owner; + write_faction_reference((f && f->_alive) ? f : NULL, data->store); + f = owner->owner; + write_faction_reference((f && f->_alive) ? f : NULL, data->store); } else { WRITE_INT(data->store, -1); @@ -569,7 +573,7 @@ int current_turn(void) static void writeorder(struct gamedata *data, const struct order *ord, -const struct locale *lang) + const struct locale *lang) { char obuf[1024]; write_order(ord, obuf, sizeof(obuf)); @@ -818,7 +822,7 @@ void write_unit(struct gamedata *data, const unit * u) WRITE_SECTION(data->store); write_items(data->store, u->items); WRITE_SECTION(data->store); - if (u->hp == 0 && u_race(u)!= get_race(RC_SPELL)) { + if (u->hp == 0 && u_race(u) != get_race(RC_SPELL)) { log_error("unit %s has 0 hitpoints, adjusting.\n", itoa36(u->no)); ((unit *)u)->hp = u->number; } @@ -979,7 +983,7 @@ static region *readregion(struct gamedata *data, int x, int y) read_items(data->store, &r->land->items); if (data->version >= REGIONOWNER_VERSION) { READ_INT(data->store, &n); - region_set_morale(r, _max(0, (short) n), -1); + region_set_morale(r, _max(0, (short)n), -1); read_owner(data, &r->land->ownership); } } @@ -1002,7 +1006,7 @@ void writeregion(struct gamedata *data, const region * r) const item_type *rht; struct demand *demand; rawmaterial *res = r->resources; - + assert(r->land); WRITE_STR(data->store, (const char *)r->land->name); assert(rtrees(r, 0) >= 0); @@ -1133,7 +1137,7 @@ void read_spellbook(spellbook **bookp, struct storage *store, int(*get_level)(co *bookp = create_spellbook(0); sb = *bookp; } - if (level>0 && (global.data_version >= SPELLBOOK_VERSION || !spellbook_get(sb, sp))) { + if (level > 0 && (global.data_version >= SPELLBOOK_VERSION || !spellbook_get(sb, sp))) { spellbook_add(sb, sp, level); } } @@ -1163,12 +1167,12 @@ static char * getpasswd(int fno) { if (F) { while (!feof(F)) { fgets(line, sizeof(line), F); - if (line[len]==':' && strncmp(prefix, line, len)==0) { - size_t slen = strlen(line)-1; - assert(line[slen]=='\n'); + if (line[len] == ':' && strncmp(prefix, line, len) == 0) { + size_t slen = strlen(line) - 1; + assert(line[slen] == '\n'); line[slen] = 0; fclose(F); - return _strdup(line+len+1); + return _strdup(line + len + 1); } } fclose(F); @@ -1466,10 +1470,10 @@ int readgame(const char *filename, bool backup) return -1; } sz = fread(&gdata.version, sizeof(int), 1, F); - if (sz!=sizeof(int) || gdata.version >= INTPAK_VERSION) { + if (sz != sizeof(int) || gdata.version >= INTPAK_VERSION) { int stream_version; size_t sz = fread(&stream_version, sizeof(int), 1, F); - assert((sz==1 && stream_version == STREAM_VERSION) || !"unsupported data format"); + assert((sz == 1 && stream_version == STREAM_VERSION) || !"unsupported data format"); } assert(gdata.version >= MIN_VERSION || !"unsupported data format"); assert(gdata.version <= MAX_VERSION || !"unsupported data format"); diff --git a/src/triggers/changefaction.c b/src/triggers/changefaction.c index 6aa0de463..47eee5874 100644 --- a/src/triggers/changefaction.c +++ b/src/triggers/changefaction.c @@ -79,7 +79,7 @@ static void changefaction_write(const trigger * t, struct storage *store) { changefaction_data *td = (changefaction_data *)t->data.v; write_unit_reference(td->unit, store); - write_faction_reference(td->faction, store); + write_faction_reference(td->faction->_alive ? td->faction : NULL, store); } static int changefaction_read(trigger * t, struct storage *store) diff --git a/src/triggers/createunit.c b/src/triggers/createunit.c index ee75916b4..bd8595378 100644 --- a/src/triggers/createunit.c +++ b/src/triggers/createunit.c @@ -82,7 +82,7 @@ static int createunit_handle(trigger * t, void *data) static void createunit_write(const trigger * t, struct storage *store) { createunit_data *td = (createunit_data *)t->data.v; - write_faction_reference(td->f, store); + write_faction_reference(td->f->_alive ? td->f : NULL, store); write_region_reference(td->r, store); write_race_reference(td->race, store); WRITE_INT(store, td->number); @@ -93,7 +93,6 @@ static int createunit_read(trigger * t, struct storage *store) createunit_data *td = (createunit_data *)t->data.v; variant var; int result = AT_READ_OK; - var = read_faction_reference(store); if (var.i > 0) { td->f = findfaction(var.i); @@ -104,6 +103,8 @@ static int createunit_read(trigger * t, struct storage *store) else { result = AT_READ_FAIL; } + // read_reference(&td->f, store, read_faction_reference, resolve_faction); + read_reference(&td->r, store, read_region_reference, RESOLVE_REGION(global.data_version)); td->race = (const struct race *)read_race_reference(store).v; diff --git a/src/util/resolve.c b/src/util/resolve.c index cee4a9d19..e8dd0c17a 100644 --- a/src/util/resolve.c +++ b/src/util/resolve.c @@ -58,6 +58,7 @@ resolve_fun resolver) void ur_add(variant data, void *ptrptr, resolve_fun fun) { + assert(ptrptr); if (ur_list == NULL) { ur_list = malloc(BLOCKSIZE * sizeof(unresolved)); ur_begin = ur_current = ur_list; @@ -86,6 +87,7 @@ void resolve(void) ur_list = ur; continue; } + assert(ur->ptrptr); ur->resolve(ur->data, ur->ptrptr); ++ur; } diff --git a/tests/data/184.dat b/tests/data/184.dat index 734e5a19f..d219f92dd 100644 Binary files a/tests/data/184.dat and b/tests/data/184.dat differ diff --git a/tests/orders.184 b/tests/orders.184 index 87825c1fd..980993481 100644 --- a/tests/orders.184 +++ b/tests/orders.184 @@ -1,4 +1,16 @@ -ERESSEA 6rLo "4jLm82" +ERESSEA 6rLo "6rLo" EINHEIT 7Lgf NACH NW NW NAECHSTER +ERESSEA w86y "w86y" +EINHEIT uc3u +STIRB "mrqa" +NAECHSTER +ERESSEA ngij "ngij" +EINHEIT iwbz +HELFE w86y ALLES +EINHEIT j536 +GRUPPE "Hodor" +HELFE w86y ALLES +HELFE w86y SILBER NICHT +NAECHSTER diff --git a/tests/run-turn.sh b/tests/run-turn.sh index 89e4f1d8b..e6118329c 100755 --- a/tests/run-turn.sh +++ b/tests/run-turn.sh @@ -37,7 +37,7 @@ SUPP=../share/ubuntu-12_04.supp SERVER="$VALGRIND --suppressions=$SUPP --error-exitcode=1 --leak-check=no $SERVER" fi echo "running $SERVER" -$SERVER -t 184 ../scripts/run-turn.lua +$SERVER -t 184 test-turn.lua [ -d reports ] || quit 4 "no reports directory created" CRFILE=185-zvto.cr for file in $NEWFILES reports/$CRFILE ; do diff --git a/tests/test-turn.lua b/tests/test-turn.lua new file mode 100644 index 000000000..03178b74d --- /dev/null +++ b/tests/test-turn.lua @@ -0,0 +1,5 @@ +dofile('../scripts/run-turn.lua') +turn = get_turn() +eressea.free_game() +print("trying to read data from " .. turn) +eressea.read_game(turn .. ".dat")