forked from github/server
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
This commit is contained in:
parent
1052e46613
commit
644d0d9a4a
12 changed files with 162 additions and 118 deletions
|
@ -20,6 +20,9 @@
|
|||
#include "save.h"
|
||||
#include "terrain.h"
|
||||
#include "unit.h"
|
||||
#include "version.h"
|
||||
|
||||
#include <spells/spells.h> /* for backward compat reading of bt_firewall */
|
||||
|
||||
#include <util/attrib.h>
|
||||
#include <util/log.h>
|
||||
|
@ -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->version<NOBORDERATTRIBS_VERSION) {
|
||||
attrib * a = NULL;
|
||||
int result = a_read(store, &a);
|
||||
while (a) {
|
||||
if (type==&bt_firewall && a->type==&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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -959,6 +959,8 @@ free_regions(void)
|
|||
runhash(r);
|
||||
free_region(r);
|
||||
}
|
||||
max_index = 0;
|
||||
last = NULL;
|
||||
}
|
||||
|
||||
/** creates a name for a region
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
{
|
||||
|
|
|
@ -33,6 +33,7 @@ extern "C" {
|
|||
struct unit * mage;
|
||||
int force;
|
||||
boolean active;
|
||||
int countdown;
|
||||
} wall_data;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -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; hash<BMAXHASH && i!=MAXDEL; hash++) {
|
||||
for (hash=0; hash<BORDER_MAXHASH && fixes!=MAXDEL; hash++) {
|
||||
border * blist;
|
||||
for (blist=borders[hash];blist && i!=MAXDEL;blist=blist->nexthash) {
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue