forked from github/server
hashing implemented with linear probing and tombstones.
WIP: this crashes 572 in faction_getmages?
This commit is contained in:
parent
afe4532966
commit
0c16727d41
|
@ -10,10 +10,33 @@
|
||||||
#include "plane.h"
|
#include "plane.h"
|
||||||
|
|
||||||
#include <util/attrib.h>
|
#include <util/attrib.h>
|
||||||
|
#include <util/gamedata.h>
|
||||||
|
|
||||||
|
#include <storage.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
void read_allies(gamedata * data, faction *f)
|
||||||
|
{
|
||||||
|
ally **sfp = &f->allies;
|
||||||
|
for (;;) {
|
||||||
|
int aid;
|
||||||
|
ally * al = ally_add(sfp, NULL);
|
||||||
|
aid = read_faction_reference(data, &al->faction, NULL);
|
||||||
|
if (aid > 0) {
|
||||||
|
int state;
|
||||||
|
READ_INT(data->store, &state);
|
||||||
|
al->status = state & HELP_ALL;
|
||||||
|
sfp = &al->next;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ally * ally_find(ally *al, const struct faction *f) {
|
ally * ally_find(ally *al, const struct faction *f) {
|
||||||
for (; al; al = al->next) {
|
for (; al; al = al->next) {
|
||||||
if (al->faction == f) return al;
|
if (al->faction == f) return al;
|
||||||
|
|
|
@ -26,7 +26,9 @@ extern "C" {
|
||||||
struct attrib_type;
|
struct attrib_type;
|
||||||
struct plane;
|
struct plane;
|
||||||
struct faction;
|
struct faction;
|
||||||
|
struct gamedata;
|
||||||
struct unit;
|
struct unit;
|
||||||
|
|
||||||
extern struct attrib_type at_npcfaction;
|
extern struct attrib_type at_npcfaction;
|
||||||
|
|
||||||
typedef struct ally {
|
typedef struct ally {
|
||||||
|
@ -35,6 +37,7 @@ extern "C" {
|
||||||
int status;
|
int status;
|
||||||
} ally;
|
} ally;
|
||||||
|
|
||||||
|
void read_allies(struct gamedata * data, struct faction *f);
|
||||||
ally * ally_find(ally *al, const struct faction *f);
|
ally * ally_find(ally *al, const struct faction *f);
|
||||||
ally * ally_add(ally **al_p, struct faction *f);
|
ally * ally_add(ally **al_p, struct faction *f);
|
||||||
void ally_remove(ally **al_p, struct faction *f);
|
void ally_remove(ally **al_p, struct faction *f);
|
||||||
|
|
|
@ -1152,31 +1152,6 @@ void write_region(gamedata *data, const region *r)
|
||||||
writeregion(data, r);
|
writeregion(data, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ally **addally(const faction * f, ally ** sfp, int aid, int state)
|
|
||||||
{
|
|
||||||
struct faction *af = findfaction(aid);
|
|
||||||
ally *sf;
|
|
||||||
|
|
||||||
state &= ~HELP_OBSERVE;
|
|
||||||
state &= ~HELP_TRAVEL;
|
|
||||||
state &= HelpMask();
|
|
||||||
|
|
||||||
if (state == 0)
|
|
||||||
return sfp;
|
|
||||||
|
|
||||||
while (*sfp) {
|
|
||||||
sfp = &(*sfp)->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
sf = ally_add(sfp, af);
|
|
||||||
if (!sf->faction) {
|
|
||||||
ur_add(aid, &sf->faction, NULL);
|
|
||||||
}
|
|
||||||
sf->status = state & HELP_ALL;
|
|
||||||
|
|
||||||
return &sf->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_spell_level_faction(const spell * sp, void * cbdata)
|
int get_spell_level_faction(const spell * sp, void * cbdata)
|
||||||
{
|
{
|
||||||
static spellbook * common = 0;
|
static spellbook * common = 0;
|
||||||
|
@ -1385,18 +1360,7 @@ faction *read_faction(gamedata * data)
|
||||||
f->options &= ~want(O_JSON);
|
f->options &= ~want(O_JSON);
|
||||||
}
|
}
|
||||||
sfp = &f->allies;
|
sfp = &f->allies;
|
||||||
for (;;) {
|
read_allies(data, f);
|
||||||
int aid = 0;
|
|
||||||
READ_INT(data->store, &aid);
|
|
||||||
if (aid > 0) {
|
|
||||||
int state;
|
|
||||||
READ_INT(data->store, &state);
|
|
||||||
sfp = addally(f, sfp, aid, state);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
read_groups(data, f);
|
read_groups(data, f);
|
||||||
f->spellbook = 0;
|
f->spellbook = 0;
|
||||||
if (data->version >= REGIONOWNER_VERSION) {
|
if (data->version >= REGIONOWNER_VERSION) {
|
||||||
|
|
40
src/spells.c
40
src/spells.c
|
@ -2892,46 +2892,20 @@ static curse *mk_deathcloud(unit * mage, region * r, double force, int duration)
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define COMPAT_DEATHCLOUD
|
|
||||||
#ifdef COMPAT_DEATHCLOUD
|
|
||||||
static int dc_read_compat(struct attrib *a, void *target, gamedata *data)
|
static int dc_read_compat(struct attrib *a, void *target, gamedata *data)
|
||||||
/* return AT_READ_OK on success, AT_READ_FAIL if attrib needs removal */
|
/* return AT_READ_OK on success, AT_READ_FAIL if attrib needs removal */
|
||||||
{
|
{
|
||||||
struct storage *store = data->store;
|
struct storage *store = data->store;
|
||||||
region *r = NULL;
|
|
||||||
unit *u;
|
|
||||||
int id;
|
|
||||||
int duration;
|
|
||||||
float strength;
|
|
||||||
int rx, ry;
|
|
||||||
|
|
||||||
UNUSED_ARG(a);
|
UNUSED_ARG(a);
|
||||||
UNUSED_ARG(target);
|
UNUSED_ARG(target);
|
||||||
READ_INT(store, &duration);
|
READ_INT(store, NULL);
|
||||||
READ_FLT(store, &strength);
|
READ_FLT(store, NULL);
|
||||||
READ_INT(store, &id);
|
READ_INT(store, NULL);
|
||||||
u = findunit(id);
|
READ_INT(store, NULL);
|
||||||
|
READ_INT(store, NULL);
|
||||||
/* this only affects really old data. no need to change: */
|
return AT_READ_DEPR; /* we don't care for the attribute. */
|
||||||
READ_INT(store, &rx);
|
|
||||||
READ_INT(store, &ry);
|
|
||||||
r = findregion(rx, ry);
|
|
||||||
|
|
||||||
if (r != NULL) {
|
|
||||||
double effect;
|
|
||||||
curse *c;
|
|
||||||
|
|
||||||
effect = strength;
|
|
||||||
c = create_curse(u, &r->attribs, &ct_deathcloud, strength * 2, duration,
|
|
||||||
effect, 0);
|
|
||||||
c->data.v = r;
|
|
||||||
if (u == NULL) {
|
|
||||||
ur_add(id, &c->magician, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return AT_READ_FAIL; /* we don't care for the attribute. */
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------- */
|
/* ------------------------------------------------------------- */
|
||||||
/* Name: Todeswolke
|
/* Name: Todeswolke
|
||||||
|
@ -6704,9 +6678,7 @@ void register_spells(void)
|
||||||
{
|
{
|
||||||
register_borders();
|
register_borders();
|
||||||
|
|
||||||
#ifdef COMPAT_DEATHCLOUD
|
|
||||||
at_deprecate("zauber_todeswolke", dc_read_compat);
|
at_deprecate("zauber_todeswolke", dc_read_compat);
|
||||||
#endif
|
|
||||||
|
|
||||||
/* init_firewall(); */
|
/* init_firewall(); */
|
||||||
ct_register(&ct_firewall);
|
ct_register(&ct_firewall);
|
||||||
|
|
|
@ -17,69 +17,85 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
|
|
||||||
|
#include <selist.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "resolve.h"
|
#include "resolve.h"
|
||||||
#include "storage.h"
|
#include "storage.h"
|
||||||
#include "variant.h"
|
#include "variant.h"
|
||||||
|
|
||||||
typedef struct unresolved {
|
typedef struct unresolved {
|
||||||
void **addr;
|
int id;
|
||||||
/* address to pass to the resolve-function */
|
|
||||||
variant data;
|
|
||||||
/* information on how to resolve the missing object */
|
/* information on how to resolve the missing object */
|
||||||
resolve_fun resolve;
|
resolve_fun resolve;
|
||||||
/* function to resolve the unknown object */
|
/* function to resolve the unknown object */
|
||||||
|
selist *addrs;
|
||||||
|
/* address to pass to the resolve-function */
|
||||||
} unresolved;
|
} unresolved;
|
||||||
|
|
||||||
#define BLOCKSIZE 1024
|
#define HASHSIZE 1024 /* must be a power of 2 */
|
||||||
static unresolved *ur_list;
|
static unresolved ur_hash[HASHSIZE];
|
||||||
static unresolved *ur_begin;
|
|
||||||
static unresolved *ur_current;
|
int ur_key(int id) {
|
||||||
|
int h = id ^ (id >> 16);
|
||||||
|
return h & (HASHSIZE - 1);
|
||||||
|
}
|
||||||
|
|
||||||
void ur_add(int id, void **addr, resolve_fun fun)
|
void ur_add(int id, void **addr, resolve_fun fun)
|
||||||
{
|
{
|
||||||
|
int h, i;
|
||||||
|
|
||||||
|
assert(id > 0);
|
||||||
assert(addr);
|
assert(addr);
|
||||||
assert(!*addr);
|
assert(!*addr);
|
||||||
if (ur_list == NULL) {
|
|
||||||
ur_list = malloc(BLOCKSIZE * sizeof(unresolved));
|
h = ur_key(id);
|
||||||
ur_begin = ur_current = ur_list;
|
for (i = 0; i != HASHSIZE; ++i) {
|
||||||
|
int k = h + i;
|
||||||
|
if (k >= HASHSIZE) k -= HASHSIZE;
|
||||||
|
if (ur_hash[k].id <= 0) {
|
||||||
|
ur_hash[k].id = id;
|
||||||
|
ur_hash[k].resolve = fun;
|
||||||
|
selist_push(&ur_hash[k].addrs, addr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ur_hash[k].id == id && ur_hash[k].resolve == fun) {
|
||||||
|
ur_hash[k].resolve = fun;
|
||||||
|
selist_push(&ur_hash[k].addrs, addr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (ur_current - ur_begin == BLOCKSIZE - 1) {
|
assert(!"hash table is full");
|
||||||
ur_begin = malloc(BLOCKSIZE * sizeof(unresolved));
|
}
|
||||||
ur_current->data.v = ur_begin;
|
|
||||||
ur_current = ur_begin;
|
|
||||||
}
|
|
||||||
ur_current->data.i = id;
|
|
||||||
ur_current->resolve = fun;
|
|
||||||
ur_current->addr = addr;
|
|
||||||
|
|
||||||
++ur_current;
|
static bool addr_cb(void *data, void *more) {
|
||||||
ur_current->addr = NULL;
|
void **addr = (void **)data;
|
||||||
ur_current->data.v = NULL;
|
*addr = more;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void resolve(int id, void *data)
|
void resolve(int id, void *data)
|
||||||
{
|
{
|
||||||
unresolved *ur = ur_list;
|
int h, i;
|
||||||
/* TODO: hella slow! hashing is better */
|
h = ur_key(id);
|
||||||
while (ur) {
|
|
||||||
if (ur->addr == NULL) {
|
for (i = 0; i != HASHSIZE; ++i) {
|
||||||
ur = ur->data.v;
|
int k = h + i;
|
||||||
free(ur_list);
|
|
||||||
ur_list = ur;
|
if (k >= HASHSIZE) k -= HASHSIZE;
|
||||||
continue;
|
if (ur_hash[k].id == 0) break;
|
||||||
}
|
else if (ur_hash[k].id == id) {
|
||||||
if (id == ur->data.i) {
|
if (ur_hash[k].resolve) {
|
||||||
if (ur->resolve) {
|
data = ur_hash[k].resolve(id, data);
|
||||||
*ur->addr = ur->resolve(id, data);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
*ur->addr = data;
|
|
||||||
}
|
}
|
||||||
|
selist_foreach_ex(ur_hash[k].addrs, addr_cb, data);
|
||||||
|
selist_free(ur_hash[k].addrs);
|
||||||
|
ur_hash[k].addrs = NULL;
|
||||||
|
ur_hash[k].id = -1;
|
||||||
}
|
}
|
||||||
++ur;
|
|
||||||
}
|
}
|
||||||
free(ur_list);
|
|
||||||
ur_list = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue