From 2557e013fa73f70b4bad844bf087dabffb3437b8 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 22 Apr 2008 10:06:53 +0000 Subject: [PATCH] - regions get a unique id (uid) - new data format - not in the CR yet - fix for terrain (tutorial crash) --- src/common/kernel/eressea.h | 4 ++++ src/common/kernel/region.c | 28 +++++++++++++++++++++++++--- src/common/kernel/region.h | 5 ++++- src/common/kernel/save.c | 12 +++++++++++- src/common/kernel/teleport.c | 2 +- src/common/kernel/version.h | 11 +++-------- src/common/modules/arena.c | 2 +- src/common/modules/autoseed.c | 8 ++++---- src/common/modules/gmcmd.c | 8 ++++---- src/common/modules/museum.c | 8 ++++---- src/eressea/editing.c | 2 +- src/eressea/gmtool.c | 4 ++-- src/eressea/korrektur.c | 2 +- src/eressea/lua/region.cpp | 3 ++- src/res/terrains.xml | 2 +- 15 files changed, 68 insertions(+), 33 deletions(-) diff --git a/src/common/kernel/eressea.h b/src/common/kernel/eressea.h index f57ba0c54..ca0853cd5 100644 --- a/src/common/kernel/eressea.h +++ b/src/common/kernel/eressea.h @@ -46,6 +46,10 @@ extern "C" { #include +#ifndef MAXREGIONS +# define MAXREGIONS 262139 /* must be prime for hashing. 262139=last<2^18 */ +#endif + #define MONSTER_FACTION 0 /* Die Partei, in der die Monster sind. */ #define MAXPEASANTS_PER_AREA 10 /* number of peasants per region-size */ #define TREESIZE (MAXPEASANTS_PER_AREA-2) /* space used by trees (in #peasants) */ diff --git a/src/common/kernel/region.c b/src/common/kernel/region.c index cdf65274c..c4ff12ef2 100644 --- a/src/common/kernel/region.c +++ b/src/common/kernel/region.c @@ -379,8 +379,28 @@ attrib_type at_moveblock = { }; -#define RMAXHASH 65521 -region *regionhash[RMAXHASH]; +#define RMAXHASH 65521 /* last prime <2^16 */ +static region *regionhash[RMAXHASH]; +static unsigned int uidhash[MAXREGIONS]; + +unsigned int +generate_region_id(void) +{ + unsigned int uid; + for (;;) { + int key; + do { + uid = rng_int(); + } while (uid==0); + key = uid % MAXREGIONS; + while (uidhash[key]!=0 && uidhash[key]!=uid) ++key; + if (uidhash[key]==0) { + uidhash[key] = uid; + break; + } + } + return uid; +} static region * rfindhash(short x, short y) @@ -789,7 +809,7 @@ static region *last; static unsigned int max_index = 0; region * -new_region(short x, short y) +new_region(short x, short y, unsigned int uid) { region *r = rfindhash(x, y); @@ -802,6 +822,8 @@ new_region(short x, short y) r = calloc(1, sizeof(region)); r->x = x; r->y = y; + if (uid==0) uid = generate_region_id(); + r->uid = uid; r->age = 1; r->planep = findplane(x, y); rhash(r); diff --git a/src/common/kernel/region.h b/src/common/kernel/region.h index 163a6cd40..d991af5a7 100644 --- a/src/common/kernel/region.h +++ b/src/common/kernel/region.h @@ -96,6 +96,7 @@ typedef struct region { /* an ascending number, to improve the speed of determining the interval in which a faction has its units. See the implementations of firstregion and lastregion */ + unsigned int uid; /* a unique id */ short x, y; struct plane *planep; char *display; @@ -221,7 +222,7 @@ 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 void * resolve_region(variant data); -extern struct region * new_region(short x, short y); +extern struct region * new_region(short x, short y, unsigned int uid); extern void terraform(struct region * r, terrain_t terrain); extern void terraform_region(struct region * r, const struct terrain_type * terrain); @@ -242,6 +243,8 @@ extern struct region * r_connect(const struct region *, direction_t dir); # define rconnect(r, dir) r_connect(r, dir) #endif +extern unsigned int generate_region_id(void); + #ifdef __cplusplus } #endif diff --git a/src/common/kernel/save.c b/src/common/kernel/save.c index e46ca881e..1fb75a7b2 100644 --- a/src/common/kernel/save.c +++ b/src/common/kernel/save.c @@ -1113,10 +1113,18 @@ readregion(FILE * F, int encoding, short x, short y) region * r = findregion(x, y); const terrain_type * terrain; char token[32]; + unsigned int uid = 0; + + if (global.data_version>=UID_VERSION) { + uid = ri(F); + } else { + uid = generate_region_id(); + } if (r==NULL) { - r = new_region(x, y); + r = new_region(x, y, uid); } else { + r->uid = uid; current_region = r; while (r->attribs) a_remove(&r->attribs, r->attribs); if (r->land) { @@ -1257,6 +1265,7 @@ readregion(FILE * F, int encoding, short x, short y) void writeregion(FILE * F, const region * r) { + wi(F, r->uid); fwritestr(F, r->display?(const char *)r->display:""); fputc(' ', F); ws(F, r->terrain->_name); @@ -1659,6 +1668,7 @@ readgame(const char * filename, int backup) /* Regionen */ n = ri(F); + assert(n=0) { diff --git a/src/common/kernel/teleport.c b/src/common/kernel/teleport.c index 513f36199..85a3e70de 100644 --- a/src/common/kernel/teleport.c +++ b/src/common/kernel/teleport.c @@ -209,7 +209,7 @@ create_teleport_plane(void) plane * pl = findplane(x, y); if (pl==aplane) { - ra = new_region(x, y); + ra = new_region(x, y, 0); if (fval(r->terrain, FORBIDDEN_REGION)) { terraform_region(ra, thickfog); diff --git a/src/common/kernel/version.h b/src/common/kernel/version.h index 2cf8e0718..d043d101f 100644 --- a/src/common/kernel/version.h +++ b/src/common/kernel/version.h @@ -51,12 +51,7 @@ #define ATTRIBREAD_VERSION 324 /* remove a_readint */ #define CURSEFLAGS_VERSION 325 /* remove a_readint */ #define UNICODE_VERSION 326 /* everything is stored as UTF8 */ +#define UID_VERSION 327 /* everything is stored as UTF8 */ -#define MIN_VERSION CURSETYPE_VERSION -#define REGIONOWNERS_VERSION 400 - -#ifdef ENEMIES -# define RELEASE_VERSION ENEMIES_VERSION -#else -# define RELEASE_VERSION UNICODE_VERSION -#endif +#define MIN_VERSION CURSETYPE_VERSION /* minimal datafile we support */ +#define RELEASE_VERSION UID_VERSION /* current datafile */ diff --git a/src/common/modules/arena.c b/src/common/modules/arena.c index 8c0a4d4b5..fc7b40f0d 100644 --- a/src/common/modules/arena.c +++ b/src/common/modules/arena.c @@ -362,7 +362,7 @@ block_create(short x1, short y1, char terrain) short x, y; for (x=0;x!=BLOCKSIZE;++x) { for (y=0;y!=BLOCKSIZE;++y) { - region * r = new_region(x1 + x, y1 + y); + region * r = new_region(x1 + x, y1 + y, 0); terraform(r, terrain); } } diff --git a/src/common/modules/autoseed.c b/src/common/modules/autoseed.c index 091606649..211693757 100644 --- a/src/common/modules/autoseed.c +++ b/src/common/modules/autoseed.c @@ -591,7 +591,7 @@ autoseed(newfaction ** players, int nsize, boolean new_island) assert(virgin_region(rconnect(rmin, dmin))); x = rmin->x + delta_x[dmin]; y = rmin->y + delta_y[dmin]; - r = new_region(x, y); + r = new_region(x, y, 0); terraform(r, T_OCEAN); /* we change the terrain later */ } } @@ -618,7 +618,7 @@ autoseed(newfaction ** players, int nsize, boolean new_island) if (rn && fval(rn, RF_MARK)) continue; if (virgin_region(rn)) { if (rn==NULL) { - rn = new_region(r->x + delta_x[d], r->y + delta_y[d]); + rn = new_region(r->x + delta_x[d], r->y + delta_y[d], 0); terraform(rn, T_OCEAN); } add_regionlist(&rlist, rn); @@ -711,7 +711,7 @@ autoseed(newfaction ** players, int nsize, boolean new_island) region * rn = rconnect(r, d); if (rn==NULL) { const struct terrain_type * terrain = newterrain(T_OCEAN); - rn = new_region(r->x + delta_x[d], r->y + delta_y[d]); + rn = new_region(r->x + delta_x[d], r->y + delta_y[d], 0); if (rng_int() % SPECIALCHANCE < special) { terrain = random_terrain(true); special = SPECIALCHANCE / 3; /* 33% chance auf noch eines */ @@ -740,7 +740,7 @@ autoseed(newfaction ** players, int nsize, boolean new_island) } if (i!=MAXFILLDIST) { while (--i) { - region * rn = new_region(r->x + i*delta_x[d], r->y + i*delta_y[d]); + region * rn = new_region(r->x + i*delta_x[d], r->y + i*delta_y[d], 0); terraform(rn, T_OCEAN); } } diff --git a/src/common/modules/gmcmd.c b/src/common/modules/gmcmd.c index 120fdd4f9..c73be72f8 100644 --- a/src/common/modules/gmcmd.c +++ b/src/common/modules/gmcmd.c @@ -650,12 +650,12 @@ gm_addquest(const char * email, const char * name, short radius, unsigned int fl maxx = minx+2*radius; cx = minx+radius; maxy = miny+2*radius; cy = miny+radius; p = create_new_plane(rng_int(), name, minx, maxx, miny, maxy, flags); - center = new_region(cx, cy); + center = new_region(cx, cy, 0); for (x=0;x<=2*radius;++x) { short y; for (y=0;y<=2*radius;++y) { region * r = findregion(minx+x, miny+y); - if (!r) r = new_region(minx+x, miny+y); + if (!r) r = new_region(minx+x, miny+y, 0); freset(r, RF_ENCOUNTER); r->planep = p; if (distance(r, center)==radius) { @@ -763,12 +763,12 @@ gm_addplane(short radius, unsigned int flags, const char * name) maxx = minx+2*radius; cx = minx+radius; maxy = miny+2*radius; cy = miny+radius; p = create_new_plane(rng_int(), name, minx, maxx, miny, maxy, flags); - center = new_region(cx, cy); + center = new_region(cx, cy, 0); for (x=0;x<=2*radius;++x) { short y; for (y=0;y<=2*radius;++y) { region * r = findregion(minx+x, miny+y); - if (!r) r = new_region(minx+x, miny+y); + if (!r) r = new_region(minx+x, miny+y, 0); freset(r, RF_ENCOUNTER); r->planep = p; if (distance(r, center)==radius) { diff --git a/src/common/modules/museum.c b/src/common/modules/museum.c index 34245f319..d85acd862 100644 --- a/src/common/modules/museum.c +++ b/src/common/modules/museum.c @@ -204,7 +204,7 @@ create_museum(void) if (findregion(9525, 9525) == NULL) { /* Eingangshalle */ - r = new_region(9525, 9525); + r = new_region(9525, 9525, 0); terraform_region(r, terrain_hall); r->planep = museum; rsetname(r, "Eingangshalle"); @@ -217,7 +217,7 @@ create_museum(void) r = findregion(9526, 9525); if(!r) { /* Lounge */ - r = new_region(9526, 9525); + r = new_region(9526, 9525, 0); terraform_region(r, terrain_hall); r->planep = museum; rsetname(r, "Lounge"); @@ -261,7 +261,7 @@ create_museum(void) r = findregion(9524, 9526); if(!r) { - r = new_region(9524, 9526); + r = new_region(9524, 9526, 0); terraform_region(r, terrain_corridor); r->planep = museum; rsetname(r, "Nördliche Promenade"); @@ -272,7 +272,7 @@ create_museum(void) } r = findregion(9525, 9524); if(!r) { - r = new_region(9525, 9524); + r = new_region(9525, 9524, 0); terraform_region(r, terrain_corridor); r->planep = museum; rsetname(r, "Südliche Promenade"); diff --git a/src/eressea/editing.c b/src/eressea/editing.c index 873e6fd4b..bc6957cd5 100644 --- a/src/eressea/editing.c +++ b/src/eressea/editing.c @@ -49,7 +49,7 @@ make_block(short x, short y, short radius, const struct terrain_type * terrain) for (cy = y - radius; cy != y+radius; ++cy) { if (koor_distance(cx, cy, x, y) < radius) { if (!findregion(cx, cy)) { - r = new_region(cx, cy); + r = new_region(cx, cy, 0); terraform_region(r, terrain); } } diff --git a/src/eressea/gmtool.c b/src/eressea/gmtool.c index 956244818..8da35d8e2 100644 --- a/src/eressea/gmtool.c +++ b/src/eressea/gmtool.c @@ -440,7 +440,7 @@ terraform_at(coordinate * c, const terrain_type *terrain) if (terrain!=NULL) { short x = (short)c->x, y = (short)c->y; region * r = findregion(x, y); - if (r==NULL) r = new_region(x, y); + if (r==NULL) r = new_region(x, y, 0); terraform_region(r, terrain); } } @@ -457,7 +457,7 @@ terraform_selection(selection * selected, const terrain_type *terrain) tag * t = *tp; short x = (short)t->coord.x, y = (short)t->coord.y; region * r = findregion(x, y); - if (r==NULL) r = new_region(x, y); + if (r==NULL) r = new_region(x, y, 0); terraform_region(r, terrain); tp = &t->nexthash; } diff --git a/src/eressea/korrektur.c b/src/eressea/korrektur.c index 3c67b36de..a599574ec 100644 --- a/src/eressea/korrektur.c +++ b/src/eressea/korrektur.c @@ -597,7 +597,7 @@ frame_regions(void) for (d=0;d!=MAXDIRECTIONS;++d) { region * rn = rconnect(r, d); if (rn==NULL) { - rn = new_region(r->x+delta_x[d], r->y+delta_y[d]); + rn = new_region(r->x+delta_x[d], r->y+delta_y[d], 0); terraform(rn, T_FIREWALL); rn->age=r->age; } diff --git a/src/eressea/lua/region.cpp b/src/eressea/lua/region.cpp index 562162d9e..d549e8825 100644 --- a/src/eressea/lua/region.cpp +++ b/src/eressea/lua/region.cpp @@ -221,7 +221,7 @@ region_terraform(short x, short y, const char * tname) } return NULL; } - if (r==NULL) r = new_region(x, y); + if (r==NULL) r = new_region(x, y, 0); terraform_region(r, terrain); return r; } @@ -380,6 +380,7 @@ bind_region(lua_State * L) .def("set_resource", ®ion_setresource) .def_readonly("x", ®ion::x) .def_readonly("y", ®ion::y) + .def_readonly("id", ®ion::uid) .def_readwrite("age", ®ion::age) .def("add_item", ®ion_additem) .property("items", ®ion_items, return_stl_iterator) diff --git a/src/res/terrains.xml b/src/res/terrains.xml index 9fe342077..dbd15d60f 100644 --- a/src/res/terrains.xml +++ b/src/res/terrains.xml @@ -84,5 +84,5 @@ - +