- free_gamedata() is perfect.

- we can now save region uids for references, not x,y
This commit is contained in:
Enno Rehling 2008-05-22 22:55:29 +00:00
parent b9fbf06614
commit 43d73a6b45
6 changed files with 99 additions and 66 deletions

View File

@ -520,10 +520,8 @@ write_borders(struct storage * store)
if (b->type->valid && !b->type->valid(b)) continue; if (b->type->valid && !b->type->valid(b)) continue;
store->w_tok(store, b->type->__name); store->w_tok(store, b->type->__name);
store->w_int(store, b->id); store->w_int(store, b->id);
store->w_int(store, b->from->x); store->w_int(store, b->from->uid);
store->w_int(store, b->from->y); store->w_int(store, b->to->uid);
store->w_int(store, b->to->x);
store->w_int(store, b->to->y);
if (b->type->write) b->type->write(b, store); if (b->type->write) b->type->write(b, store);
store->w_brk(store); store->w_brk(store);
@ -537,7 +535,6 @@ int
read_borders(struct storage * store) read_borders(struct storage * store)
{ {
for (;;) { for (;;) {
short fx, fy, tx, ty;
unsigned int bid = 0; unsigned int bid = 0;
char zText[32]; char zText[32];
border * b; border * b;
@ -547,18 +544,19 @@ read_borders(struct storage * store)
store->r_tok_buf(store, zText, sizeof(zText)); store->r_tok_buf(store, zText, sizeof(zText));
if (!strcmp(zText, "end")) break; if (!strcmp(zText, "end")) break;
bid = store->r_int(store); bid = store->r_int(store);
if (store->version<UIDHASH_VERSION) {
short fx, fy, tx, ty;
fx = (short)store->r_int(store); fx = (short)store->r_int(store);
fy = (short)store->r_int(store); fy = (short)store->r_int(store);
tx = (short)store->r_int(store); tx = (short)store->r_int(store);
ty = (short)store->r_int(store); ty = (short)store->r_int(store);
from = findregion(fx, fy); from = findregion(fx, fy);
if (from==NULL) {
log_error(("border for unknown region %d,%d\n", fx, fy));
}
to = findregion(tx, ty); to = findregion(tx, ty);
if (to==NULL) { } else {
log_error(("border for unknown region %d,%d\n", tx, ty)); unsigned int fid = (unsigned int)store->r_int(store);
unsigned int tid = (unsigned int)store->r_int(store);
from = findregionbyid(fid);
to = findregionbyid(tid);
} }
type = find_bordertype(zText); type = find_bordertype(zText);

View File

@ -389,27 +389,50 @@ attrib_type at_moveblock = {
static region * regionhash[RMAXHASH]; static region * regionhash[RMAXHASH];
static int dummy_data; static int dummy_data;
static region * dummy_ptr = (region*)&dummy_data; /* a funny hack */ static region * dummy_ptr = (region*)&dummy_data; /* a funny hack */
static unsigned int uidhash[MAXREGIONS];
typedef struct uidhashentry {
unsigned int uid;
region * r;
} uidhashentry;
static uidhashentry uidhash[MAXREGIONS];
struct region *
findregionbyid(unsigned int uid)
{
int key = uid % MAXREGIONS;
while (uidhash[key].uid!=0 && uidhash[key].uid!=uid) ++key;
return uidhash[key].r;
}
#define DELMARKER dummy_ptr #define DELMARKER dummy_ptr
unsigned int static void
generate_region_id(void) unhash_uid(region * r)
{ {
unsigned int uid; int key = r->uid % MAXREGIONS;
assert(r->uid);
while (uidhash[key].uid!=0 && uidhash[key].uid!=r->uid) ++key;
assert(uidhash[key].r==r);
uidhash[key].r = NULL;
}
static void
hash_uid(region * r)
{
unsigned int uid = r->uid;
for (;;) { for (;;) {
int key; if (uid!=0) {
do { int key = uid % MAXREGIONS;
uid = rng_int(); while (uidhash[key].uid!=0 && uidhash[key].uid!=uid) ++key;
} while (uid==0); if (uidhash[key].uid==0) {
key = uid % MAXREGIONS; uidhash[key].uid = uid;
while (uidhash[key]!=0 && uidhash[key]!=uid) ++key; uidhash[key].r = r;
if (uidhash[key]==0) {
uidhash[key] = uid;
break; break;
} }
assert(uidhash[key].r!=r || !"duplicate registration");
}
uid = rng_int();
} }
return uid;
} }
#define HASH_STATISTICS 1 #define HASH_STATISTICS 1
@ -837,11 +860,11 @@ new_region(short x, short y, unsigned int uid)
r = calloc(1, sizeof(region)); r = calloc(1, sizeof(region));
r->x = x; r->x = x;
r->y = y; r->y = y;
if (uid==0) uid = generate_region_id();
r->uid = uid; r->uid = uid;
r->age = 1; r->age = 1;
r->planep = findplane(x, y); r->planep = findplane(x, y);
rhash(r); rhash(r);
hash_uid(r);
if (last) if (last)
addlist(&last, r); addlist(&last, r);
else else
@ -865,6 +888,7 @@ remove_region(region ** rlist, region * r)
} }
runhash(r); runhash(r);
unhash_uid(r);
while (*rlist && *rlist!=r) rlist=&(*rlist)->next; while (*rlist && *rlist!=r) rlist=&(*rlist)->next;
assert(*rlist==r); assert(*rlist==r);
*rlist = r->next; *rlist = r->next;
@ -1217,9 +1241,22 @@ production(const region *r)
return p; return p;
} }
static void
resolve_region(variant id, void * address) {
region * r = findregion(id.sa[0], id.sa[1]);
*(region**)address = r;
}
static void
resolve_regionbyid(variant id, void * address) {
region * r = findregionbyid((unsigned int)id.i);
*(region**)address = r;
}
int int
read_region_reference(region ** r, struct storage * store) read_region_reference(region ** r, struct storage * store)
{ {
if (store->version<UIDHASH_VERSION) {
variant coor; variant coor;
coor.sa[0] = (short)store->r_int(store); coor.sa[0] = (short)store->r_int(store);
coor.sa[1] = (short)store->r_int(store); coor.sa[1] = (short)store->r_int(store);
@ -1228,10 +1265,21 @@ read_region_reference(region ** r, struct storage * store)
return AT_READ_FAIL; return AT_READ_FAIL;
} }
*r = findregion(coor.sa[0], coor.sa[1]); *r = findregion(coor.sa[0], coor.sa[1]);
if (*r==NULL) { if (*r==NULL) {
ur_add(coor, (void**)r, resolve_region); ur_add(coor, (void**)r, resolve_region);
} }
} else {
variant uid;
uid.i = store->r_int(store);
if (uid.i==0) {
*r = NULL;
} else {
*r = findregionbyid((unsigned int)uid.i);
if (*r==NULL) {
ur_add(uid, (void**)r, resolve_regionbyid);
}
}
}
return AT_READ_OK; return AT_READ_OK;
} }
@ -1239,22 +1287,12 @@ void
write_region_reference(const region * r, struct storage * store) write_region_reference(const region * r, struct storage * store)
{ {
if (r) { if (r) {
store->w_int(store, r->x); store->w_int(store, r->uid);
store->w_int(store, r->y); } else {
} store->w_int(store, 0);
else {
store->w_int(store, SHRT_MAX);
store->w_int(store, SHRT_MAX);
} }
} }
void
resolve_region(variant id, void * address) {
region * r = findregion(id.sa[0], id.sa[1]);
*(region**)address = r;
}
struct message_list * struct message_list *
r_getmessages(const struct region * r, const struct faction * viewer) r_getmessages(const struct region * r, const struct faction * viewer)
{ {

View File

@ -146,6 +146,7 @@ int distance(const struct region*, const struct region*);
int koor_distance(int ax, int ay, int bx, int by) ; int koor_distance(int ax, int ay, int bx, int by) ;
extern direction_t reldirection(const struct region * from, const struct region * to); extern direction_t reldirection(const struct region * from, const struct region * to);
extern struct region * findregion(short x, short y); extern struct region * findregion(short x, short y);
extern struct region * findregionbyid(unsigned int uid);
extern struct attrib_type at_direction; extern struct attrib_type at_direction;
extern struct attrib_type at_moveblock; extern struct attrib_type at_moveblock;
@ -219,7 +220,6 @@ extern int r_demand(const struct region * r, const struct luxury_type * ltype);
extern const char * regionname(const struct region * r, const struct faction * f); extern const char * regionname(const struct region * r, const struct faction * f);
extern const char * write_regionname(const struct region * r, const struct faction * f, char * buffer, size_t size); extern const char * write_regionname(const struct region * r, const struct faction * f, char * buffer, size_t size);
extern void resolve_region(variant data, void * address);
extern struct region * new_region(short x, short y, unsigned int uid); extern struct region * new_region(short x, short y, unsigned int uid);
extern void remove_region(region ** rlist, region * r); extern void remove_region(region ** rlist, region * r);
extern void terraform(struct region * r, terrain_t terrain); extern void terraform(struct region * r, terrain_t terrain);
@ -242,8 +242,6 @@ extern struct region * r_connect(const struct region *, direction_t dir);
# define rconnect(r, dir) r_connect(r, dir) # define rconnect(r, dir) r_connect(r, dir)
#endif #endif
extern unsigned int generate_region_id(void);
extern void free_regions(void); extern void free_regions(void);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -926,14 +926,12 @@ readregion(struct storage * store, short x, short y)
if (store->version>=UID_VERSION) { if (store->version>=UID_VERSION) {
uid = store->r_int(store); uid = store->r_int(store);
} else {
uid = generate_region_id();
} }
if (r==NULL) { if (r==NULL) {
r = new_region(x, y, uid); r = new_region(x, y, uid);
} else { } else {
r->uid = uid; assert(uid==0 || r->uid==uid);
current_region = r; current_region = r;
while (r->attribs) a_remove(&r->attribs, r->attribs); while (r->attribs) a_remove(&r->attribs, r->attribs);
if (r->land) { if (r->land) {

View File

@ -57,6 +57,7 @@
#define INTPAK_VERSION 329 /* in binary, ints can get packed */ #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 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 NOBORDERATTRIBS_VERSION 331 /* border::attribs has been moved to userdata */
#define UIDHASH_VERSION 332 /* borders use the region.uid to store */
#define MIN_VERSION CURSETYPE_VERSION /* minimal datafile we support */ #define MIN_VERSION CURSETYPE_VERSION /* minimal datafile we support */
#define RELEASE_VERSION NOBORDERATTRIBS_VERSION /* current datafile */ #define RELEASE_VERSION UIDHASH_VERSION /* current datafile */

View File

@ -56,12 +56,12 @@ run_scripts()
local now = os.clock() local now = os.clock()
-- test_free() -- test_free()
read_game("571.dat", "binary") read_game("571.dat", "binary")
write_game("571.txt.1", "text") write_game("571.dat.1", "binary")
free_game() free_game()
read_game("570.dat", "binary") read_game("570.dat", "binary")
free_game() free_game()
read_game("571.dat", "binary") read_game("571.dat", "binary")
write_game("571.txt.2", "text") write_game("571.dat.2", "binary")
local elapsed = os.clock() - now local elapsed = os.clock() - now
print(elapsed) print(elapsed)
-- text: 50.574 -- text: 50.574