From 644d0d9a4a839d67b363d3dde50fe44f86c9d17f Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 22 May 2008 14:40:21 +0000 Subject: [PATCH] implementing free_gamedata(): - fixed freeing of borders - fixed freeing of global.attribs - more static-variable reinitialization - reseting the RNG removed border.attribs: - new savegame-version --- src/common/kernel/border.c | 87 +++++++++++++++++++------------------ src/common/kernel/border.h | 6 +-- src/common/kernel/eressea.c | 14 +++++- src/common/kernel/group.c | 20 ++++++--- src/common/kernel/region.c | 2 + src/common/kernel/save.c | 1 + src/common/kernel/version.h | 3 +- src/common/spells/spells.c | 35 +++++++++------ src/common/spells/spells.h | 1 + src/eressea/korrektur.c | 55 +++++------------------ src/eressea/server.cpp | 5 --- src/scripts/run-tests.lua | 51 +++++++++++++++++++++- 12 files changed, 162 insertions(+), 118 deletions(-) diff --git a/src/common/kernel/border.c b/src/common/kernel/border.c index 7b9b30831..9728e2b36 100644 --- a/src/common/kernel/border.c +++ b/src/common/kernel/border.c @@ -20,6 +20,9 @@ #include "save.h" #include "terrain.h" #include "unit.h" +#include "version.h" + +#include /* for backward compat reading of bt_firewall */ #include #include @@ -33,7 +36,8 @@ unsigned int nextborder = 0; -border * borders[BMAXHASH]; +#define BORDER_MAXHASH 8191 +border * borders[BORDER_MAXHASH]; border_type * bordertypes; @@ -41,8 +45,20 @@ void free_borders(void) { int i; - for (i=0;i!=BMAXHASH;++i) { - borders[i] = NULL; + for (i=0;i!=BORDER_MAXHASH;++i) { + while (borders[i]) { + border * b = borders[i]; + borders[i] = b->nexthash; + while (b) { + border * bf = b; + b = b->next; + assert(b==NULL || b->nexthash==NULL); + if (bf->type->destroy) { + bf->type->destroy(bf); + } + free(bf); + } + } } } @@ -50,7 +66,7 @@ border * find_border(unsigned int id) { int key; - for (key=0;key!=BMAXHASH;key++) { + for (key=0;key!=BORDER_MAXHASH;key++) { border * bhash; for (bhash=borders[key];bhash!=NULL;bhash=bhash->nexthash) { border * b; @@ -74,7 +90,7 @@ get_borders_i(const region * r1, const region * r2) int key = reg_hashkey(r1); int k2 = reg_hashkey(r2); - key = min(k2, key) % BMAXHASH; + key = min(k2, key) % BORDER_MAXHASH; bp = &borders[key]; while (*bp) { border * b = *bp; @@ -113,10 +129,6 @@ new_border(border_type * type, region * from, region * to) void erase_border(border * b) { - attrib ** ap = &b->attribs; - - while (*ap) a_remove(&b->attribs, *ap); - if (b->from && b->to) { border ** bp = get_borders_i(b->from, b->to); assert(*bp!=NULL || !"error: border is not registered"); @@ -136,7 +148,9 @@ erase_border(border * b) *bp = b->next; } } - if (b->type->destroy) b->type->destroy(b); + if (b->type->destroy) { + b->type->destroy(b); + } free(b); } @@ -210,23 +224,16 @@ boolean b_rinvisible(const border * b, const region * r) { unused(r); unused(b); boolean b_finvisible(const border * b, const struct faction * f, const region * r) { unused(r); unused(f); unused(b); return false; } boolean b_uinvisible(const border * b, const unit * u) { unused(u); unused(b); return false; } -/*********************/ -/* at_countdown */ -/*********************/ - -static int -a_agecountdown(attrib * a) -{ - a->data.i = max(a->data.i-1, 0); - return a->data.i; -} +/**************************************/ +/* at_countdown - legacy, do not use */ +/**************************************/ attrib_type at_countdown = { "countdown", DEFAULT_INIT, DEFAULT_FINALIZE, - a_agecountdown, - a_writeint, + NULL, + NULL, a_readint }; @@ -236,25 +243,13 @@ age_borders(void) border_list * deleted = NULL; int i; - for (i=0;i!=BMAXHASH;++i) { + for (i=0;i!=BORDER_MAXHASH;++i) { border * bhash = borders[i]; for (;bhash;bhash=bhash->nexthash) { border * b = bhash; for (;b;b=b->next) { - attrib ** ap = &b->attribs; - while (*ap) { - attrib * a = *ap; - if (a->type->age && a->type->age(a)==0) { - if (a->type == &at_countdown) { - border_list * bnew = malloc(sizeof(border_list)); - bnew->next = deleted; - bnew->data = b; - deleted = bnew; - break; - } - a_remove(&b->attribs, a); - } - else ap=&a->next; + if (b->type->age) { + b->type->age(b); } } } @@ -517,7 +512,7 @@ void write_borders(struct storage * store) { int i; - for (i=0;i!=BMAXHASH;++i) { + for (i=0;i!=BORDER_MAXHASH;++i) { border * bhash; for (bhash=borders[i];bhash;bhash=bhash->nexthash) { border * b; @@ -531,7 +526,6 @@ write_borders(struct storage * store) store->w_int(store, b->to->y); if (b->type->write) b->type->write(b, store); - a_write(store, b->attribs); store->w_brk(store); } } @@ -549,7 +543,6 @@ read_borders(struct storage * store) border * b; region * from, * to; border_type * type; - int result; store->r_tok_buf(store, zText, sizeof(zText)); if (!strcmp(zText, "end")) break; @@ -587,8 +580,18 @@ read_borders(struct storage * store) b->id = bid; assert(bid<=nextborder); if (type->read) type->read(b, store); - result = a_read(store, &b->attribs); - if (result<0) return result; + if (store->versiontype==&at_countdown) { + wall_data * fd = (wall_data *)b->data.v; + fd->countdown = a->data.i; + } + a_remove(&a, a); + } + if (result<0) return result; + } if (!to || !from) { erase_border(b); } diff --git a/src/common/kernel/border.h b/src/common/kernel/border.h index a88bc74db..e4fcf631b 100644 --- a/src/common/kernel/border.h +++ b/src/common/kernel/border.h @@ -21,8 +21,6 @@ extern "C" { #endif -#define BMAXHASH 8191 - extern unsigned int nextborder; typedef struct border { @@ -30,7 +28,6 @@ extern "C" { struct border * next; /* next border between these regions */ struct border * nexthash; /* next border between these regions */ struct region * from, * to; /* borders can be directed edges */ - struct attrib * attribs; variant data; unsigned int id; /* unique id */ } border; @@ -84,12 +81,15 @@ extern "C" { */ struct region * (*move)(const border *, struct unit * u, struct region * from, struct region * to, boolean routing); /* executed when the units traverses this border */ + int (*age)(struct border *); + /* return 0 if border needs to be removed. >0 if still aging, <0 if not aging */ struct border_type * next; /* for internal use only */ } border_type; extern border * find_border(unsigned int id); void resolve_borderid(variant data, void * addr); + extern void free_borders(void); extern border * get_borders(const struct region * r1, const struct region * r2); /* returns the list of borders between r1 and r2 or r2 and r1 */ diff --git a/src/common/kernel/eressea.c b/src/common/kernel/eressea.c index 0ae4be1ac..97d2952ec 100644 --- a/src/common/kernel/eressea.c +++ b/src/common/kernel/eressea.c @@ -679,6 +679,11 @@ stripfaction (faction * f) free(bm); } + while (f->groups) { + group * g = f->groups; + f->groups = g->next; + free_group(g); + } freelist(f->allies); free(f->email); @@ -687,7 +692,9 @@ stripfaction (faction * f) free(f->override); free(f->name); - while (f->attribs) a_remove (&f->attribs, f->attribs); + while (f->attribs) { + a_remove (&f->attribs, f->attribs); + } i_freeall(&f->items); @@ -3005,6 +3012,7 @@ free_gamedata(void) { free_units(); free_regions(); + free_borders(); while (factions) { faction * f = factions; @@ -3019,4 +3027,8 @@ free_gamedata(void) free(pl->name); free(pl); } + + while (global.attribs) { + a_remove(&global.attribs, global.attribs); + } } \ No newline at end of file diff --git a/src/common/kernel/group.c b/src/common/kernel/group.c index ae7da0a79..1286fd4f9 100644 --- a/src/common/kernel/group.c +++ b/src/common/kernel/group.c @@ -124,13 +124,19 @@ at_group = { /* attribute for units assigned to a group */ void free_group(group * g) { - while (g->allies) { - ally * a = g->allies; - g->allies = a->next; - free(a); - } - free(g->name); - free(g); + int index = g->gid % GMAXHASH; + group ** g_ptr = ghash+index; + while (*g_ptr && (*g_ptr)->gid!=g->gid) g_ptr = &(*g_ptr)->nexthash; + assert(*g_ptr==g); + *g_ptr = g->nexthash; + + while (g->allies) { + ally * a = g->allies; + g->allies = a->next; + free(a); + } + free(g->name); + free(g); } void diff --git a/src/common/kernel/region.c b/src/common/kernel/region.c index 16584fb54..795259b96 100644 --- a/src/common/kernel/region.c +++ b/src/common/kernel/region.c @@ -959,6 +959,8 @@ free_regions(void) runhash(r); free_region(r); } + max_index = 0; + last = NULL; } /** creates a name for a region diff --git a/src/common/kernel/save.c b/src/common/kernel/save.c index 49cb56b5a..12d8bce56 100644 --- a/src/common/kernel/save.c +++ b/src/common/kernel/save.c @@ -1410,6 +1410,7 @@ readgame(const char * filename, int mode, int backup) } a_read(store, &global.attribs); global.data_turn = turn = store->r_int(store); + rng_init(turn); store->r_int(store); /* max_unique_id = */ nextborder = store->r_int(store); diff --git a/src/common/kernel/version.h b/src/common/kernel/version.h index 0a53de7de..2486411cb 100644 --- a/src/common/kernel/version.h +++ b/src/common/kernel/version.h @@ -56,6 +56,7 @@ #define STORAGE_VERSION 328 /* with storage.h, some things are stored smarter (ids as base36, fractions as float) */ #define INTPAK_VERSION 329 /* in binary, ints can get packed */ #define NOZEROIDS_VERSION 330 /* zero is not a valid ID for anything (including factions) */ +#define NOBORDERATTRIBS_VERSION 331 /* border::attribs has been moved to userdata */ #define MIN_VERSION CURSETYPE_VERSION /* minimal datafile we support */ -#define RELEASE_VERSION NOZEROIDS_VERSION /* current datafile */ +#define RELEASE_VERSION NOBORDERATTRIBS_VERSION /* current datafile */ diff --git a/src/common/spells/spells.c b/src/common/spells/spells.c index 74b586fab..81c3d5bea 100644 --- a/src/common/spells/spells.c +++ b/src/common/spells/spells.c @@ -2766,7 +2766,9 @@ b_namefirewall(const border * b, const region * r, const faction * f, int gflags static void wall_init(border * b) { - b->data.v = calloc(sizeof(wall_data), 1); + wall_data * fd = (wall_data*)calloc(sizeof(wall_data), 1); + fd->countdown = -1; /* infinite */ + b->data.v = fd; } static void @@ -2791,6 +2793,9 @@ wall_read(border * b, storage * store) read_unit_reference(&fd->mage, store); } fd->force = store->r_int(store); + if (store->version>=NOBORDERATTRIBS_VERSION) { + fd->countdown = store->r_int(store); + } fd->active = true; } @@ -2800,6 +2805,17 @@ wall_write(const border * b, storage * store) wall_data * fd = (wall_data*)b->data.v; write_unit_reference(fd->mage, store); store->w_int(store, fd->force); + store->w_int(store, fd->countdown); +} + +static int +wall_age(border * b) +{ + wall_data * fd = (wall_data*)b->data.v; + if (fd->countdown>0) { + if (--fd->countdown==0) return 0; + } + return fd->countdown; } static region * @@ -2836,7 +2852,8 @@ border_type bt_firewall = { b_finvisible, /* fvisible */ b_uinvisible, /* uvisible */ NULL, - wall_move + wall_move, + wall_age }; static int @@ -2844,7 +2861,6 @@ sp_firewall(castorder *co) { border * b; wall_data * fd; - attrib * a; region *r = co->rt; unit *mage = co->magician.u; int cast_level = co->level; @@ -2877,17 +2893,11 @@ sp_firewall(castorder *co) fd->force = (int)(force/2+0.5); fd->mage = mage; fd->active = false; + fd->countdown = cast_level+1; } else { fd = (wall_data*)b->data.v; fd->force = (int)max(fd->force, force/2+0.5); - } - - a = a_find(b->attribs, &at_countdown); - if (a==NULL) { - a = a_add(&b->attribs, a_new(&at_countdown)); - a->data.i = cast_level+1; - } else { - a->data.i = max(a->data.i, cast_level+1); + fd->countdown = max(fd->countdown, cast_level+1); } /* melden, 1x pro Partei */ @@ -2997,8 +3007,7 @@ sp_wisps(castorder *co) fd->force = (int)(force/2+0.5); fd->mage = mage; fd->active = false; - - a_add(&b->attribs, a_new(&at_countdown))->data.i = cast_level; + fd->countdown = cast_level+1; /* melden, 1x pro Partei */ { diff --git a/src/common/spells/spells.h b/src/common/spells/spells.h index 69af9a40d..19c0ec60b 100644 --- a/src/common/spells/spells.h +++ b/src/common/spells/spells.h @@ -33,6 +33,7 @@ extern "C" { struct unit * mage; int force; boolean active; + int countdown; } wall_data; #ifdef __cplusplus diff --git a/src/eressea/korrektur.c b/src/eressea/korrektur.c index 47d82adf9..03a5e22ae 100644 --- a/src/eressea/korrektur.c +++ b/src/eressea/korrektur.c @@ -265,42 +265,6 @@ fix_age(void) } } - -static void -fix_firewalls(void) -{ - region * r = regions; - int fixes = 0; - - while (r) { - direction_t d; - for (d=0;d!=MAXDIRECTIONS;++d) { - region * r2 = rconnect(r, d); - if (r2) { - border * b = get_borders(r, r2); - while (b) { - if (b->type==&bt_firewall) { - attrib * a = a_find(b->attribs, &at_countdown); - if (a==NULL || a->data.i <= 0) { - erase_border(b); - log_warning(("firewall between regions %s and %s was bugged. removed.\n", - regionname(r, NULL), regionname(r2, NULL))); - b = get_borders(r, r2); - ++fixes; - } else { - b = b->next; - } - } else { - b = b->next; - } - } - } - } - r = r->next; - } - log_printf("fixed %d firewalls.\n", fixes); -} - static void fix_otherfaction(void) { @@ -613,19 +577,20 @@ fix_astralplane(void) extern border *borders[]; +#define BORDER_MAXHASH 8191 static void fix_road_borders(void) { #define MAXDEL 10000 border *deleted[MAXDEL]; int hash; - int i = 0; + int fixes = 0; - for (hash=0; hashnexthash) { + for (blist=borders[hash];blist && fixes!=MAXDEL;blist=blist->nexthash) { border * b; - for (b=blist;b && i!=MAXDEL;b=b->next) { + for (b=blist;b && fixes!=MAXDEL;b=b->next) { if (b->type == &bt_road) { short x1, x2, y1, y2; region *r1, *r2; @@ -642,16 +607,17 @@ fix_road_borders(void) || r1->terrain->max_road<=0 || r2->terrain->max_road<=0) { - deleted[i++] = b; + deleted[fixes++] = b; } } } } } - while (i>0) { - i--; - erase_border(deleted[i]); + log_printf("fixed %d roads.\n", fixes); + while (fixes>0) { + fixes--; + erase_border(deleted[fixes]); } } @@ -931,7 +897,6 @@ korrektur(void) do_once("atrx", &fix_attribflags); do_once("asfi", &fix_astral_firewalls); fix_astralplane(); - fix_firewalls(); fix_toads(); /* fix_heroes(); */ verify_owners(false); diff --git a/src/eressea/server.cpp b/src/eressea/server.cpp index 5e13a3ab4..c1f8aa0d9 100644 --- a/src/eressea/server.cpp +++ b/src/eressea/server.cpp @@ -144,11 +144,6 @@ extern "C" { extern boolean battledebug; extern int loadplane; - - extern void debug_messagetypes(FILE * out); - extern void free_region(region * r); - extern void render_init(void); - extern void free_borders(void); extern boolean opt_cr_absolute_coords; } diff --git a/src/scripts/run-tests.lua b/src/scripts/run-tests.lua index 3d7ae2510..86907a854 100644 --- a/src/scripts/run-tests.lua +++ b/src/scripts/run-tests.lua @@ -9,10 +9,59 @@ function test_locales() return 0 end +function loadscript(name) + local script = scriptpath .. "/" .. name + print("- loading " .. script) + if pcall(dofile, script)==0 then + print("Could not load " .. script) + end +end + +function run_scripts() + scripts = { + "spells.lua", + "extensions.lua", + "familiars.lua", + } + for index, value in pairs(scripts) do + loadscript(value) + end +end --test_locales() +function run_turn() + plan_monsters() + process_orders() + spawn_dragons() + spawn_undead() + spawn_braineaters(0.25) + autoseed(basepath .. "/newfactions", false) +end + + +function test_free() + read_game("571.dat", "binary") + read_orders("orders.571") + run_turn() + free_game() + read_game("570.dat", "binary") + read_orders("orders.570") + run_turn() + free_game() +end + +loadscript("default.lua") +run_scripts() +-- go local now = os.clock() -read_game("572.dat", "binary") +-- test_free() +read_game("571.dat", "binary") +write_game("571.txt.1", "text") +free_game() +read_game("570.dat", "binary") +free_game() +read_game("571.dat", "binary") +write_game("571.txt.2", "text") local elapsed = os.clock() - now print(elapsed) -- text: 50.574