diff --git a/src/kernel/curse.c b/src/kernel/curse.c index 1761d754d..7735e3333 100644 --- a/src/kernel/curse.c +++ b/src/kernel/curse.c @@ -1,7 +1,7 @@ /* -Copyright (c) 1998-2010, Enno Rehling - Katja Zedel +Copyright (c) 1998-2014, Enno Rehling +Katja Zedel Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -61,228 +61,233 @@ curse *cursehash[MAXENTITYHASH]; void c_setflag(curse * c, unsigned int flags) { - assert(c); - c->flags = (c->flags & ~flags) | (flags & (c->type->flags ^ flags)); + assert(c); + c->flags = (c->flags & ~flags) | (flags & (c->type->flags ^ flags)); } /* -------------------------------------------------------------------------- */ void c_clearflag(curse * c, unsigned int flags) { - assert(c); - c->flags = (c->flags & ~flags) | (c->type->flags & flags); + assert(c); + c->flags = (c->flags & ~flags) | (c->type->flags & flags); } void chash(curse * c) { - curse *old = cursehash[c->no % MAXENTITYHASH]; + curse *old = cursehash[c->no % MAXENTITYHASH]; - cursehash[c->no % MAXENTITYHASH] = c; - c->nexthash = old; + cursehash[c->no % MAXENTITYHASH] = c; + c->nexthash = old; } static void cunhash(curse * c) { - curse **show; + curse **show; - for (show = &cursehash[c->no % MAXENTITYHASH]; *show; - show = &(*show)->nexthash) { - if ((*show)->no == c->no) - break; - } - if (*show) { - assert(*show == c); - *show = (*show)->nexthash; - c->nexthash = 0; - } + for (show = &cursehash[c->no % MAXENTITYHASH]; *show; + show = &(*show)->nexthash) { + if ((*show)->no == c->no) + break; + } + if (*show) { + assert(*show == c); + *show = (*show)->nexthash; + c->nexthash = 0; + } } curse *cfindhash(int i) { - curse *old; + curse *old; - for (old = cursehash[i % MAXENTITYHASH]; old; old = old->nexthash) - if (old->no == i) - return old; - return NULL; + for (old = cursehash[i % MAXENTITYHASH]; old; old = old->nexthash) + if (old->no == i) + return old; + return NULL; } /* ------------------------------------------------------------- */ /* at_curse */ void curse_init(attrib * a) { - a->data.v = calloc(1, sizeof(curse)); + a->data.v = calloc(1, sizeof(curse)); } int curse_age(attrib * a) { - curse *c = (curse *) a->data.v; - int result = 0; + curse *c = (curse *)a->data.v; + int result = 0; - if (c_flags(c) & CURSE_NOAGE) { - c->duration = INT_MAX; - } - if (c->type->age) { - result = c->type->age(c); - } - if (result != 0) { - c->duration = 0; - } else if (c->duration != INT_MAX) { - c->duration = _max(0, c->duration - 1); - } - return c->duration; + if (c_flags(c) & CURSE_NOAGE) { + c->duration = INT_MAX; + } + if (c->type->age) { + result = c->type->age(c); + } + if (result != 0) { + c->duration = 0; + } + else if (c->duration != INT_MAX) { + c->duration = _max(0, c->duration - 1); + } + return c->duration; } void destroy_curse(curse * c) { - cunhash(c); - free(c); + cunhash(c); + free(c); } void curse_done(attrib * a) { - destroy_curse((curse *) a->data.v); + destroy_curse((curse *)a->data.v); } /** reads curses that have been removed from the code */ static int read_ccompat(const char *cursename, struct storage *store) { - struct compat { - const char *name; - const char *tokens; - } *seek, old_curses[] = { { - "disorientationzone", ""}, { - "shipdisorientation", ""}, { - NULL, NULL}}; - for (seek = old_curses; seek->name; ++seek) { - if (strcmp(seek->tokens, cursename) == 0) { - const char *p; - for (p = seek->name; p; ++p) { - switch (*p) { - case 'd': - READ_INT(store, 0); - break; - case 's': - READ_STR(store, 0, 0); - break; - case 't': - READ_TOK(store, 0, 0); - break; - case 'i': - READ_INT(store, 0); - break; - case 'f': - READ_FLT(store, 0); - break; + struct compat { + const char *name; + const char *tokens; + } *seek, old_curses[] = { { + "disorientationzone", "" }, { + "shipdisorientation", "" }, { + NULL, NULL } }; + for (seek = old_curses; seek->name; ++seek) { + if (strcmp(seek->tokens, cursename) == 0) { + const char *p; + for (p = seek->name; p; ++p) { + switch (*p) { + case 'd': + READ_INT(store, 0); + break; + case 's': + READ_STR(store, 0, 0); + break; + case 't': + READ_TOK(store, 0, 0); + break; + case 'i': + READ_INT(store, 0); + break; + case 'f': + READ_FLT(store, 0); + break; + } + } + return 0; } - } - return 0; } - } - return -1; + return -1; } int curse_read(attrib * a, void *owner, struct storage *store) { - curse *c = (curse *) a->data.v; - int ur; - char cursename[64]; - int n; - int flags; - float flt; + curse *c = (curse *)a->data.v; + int ur; + char cursename[64]; + int n; + int flags; + float flt; - READ_INT(store, &c->no); - chash(c); - READ_TOK(store, cursename, sizeof(cursename)); - READ_INT(store, &flags); - READ_INT(store, &c->duration); - if (global.data_version >= CURSEVIGOURISFLOAT_VERSION) { - READ_FLT(store, &flt); - c->vigour = flt; - } else { - READ_INT(store, &n); - c->vigour = (float)n; - } - if (global.data_version < INTPAK_VERSION) { - ur = read_reference(&c->magician, store, read_int, resolve_unit); - } else { - ur = read_reference(&c->magician, store, read_unit_reference, resolve_unit); - } - if (global.data_version < CURSEFLOAT_VERSION) { - READ_INT(store, &n); - c->effect = (float)n; - } else { - READ_FLT(store, &flt); - c->effect = flt; - } - c->type = ct_find(cursename); - if (c->type == NULL) { - int result = read_ccompat(cursename, store); - if (result != 0) { - log_error("missing curse %s, no compatibility code either.\n", cursename); + READ_INT(store, &c->no); + chash(c); + READ_TOK(store, cursename, sizeof(cursename)); + READ_INT(store, &flags); + READ_INT(store, &c->duration); + if (global.data_version >= CURSEVIGOURISFLOAT_VERSION) { + READ_FLT(store, &flt); + c->vigour = flt; } - assert(result == 0); - return AT_READ_FAIL; - } - if (global.data_version < CURSEFLAGS_VERSION) { - c_setflag(c, flags); - } else { - c->flags = flags; - } - c_clearflag(c, CURSE_ISNEW); - - if (c->type->read) - c->type->read(store, c, owner); - else if (c->type->typ == CURSETYP_UNIT) { - READ_INT(store, &c->data.i); - } - if (c->type->typ == CURSETYP_REGION) { - int rr = - read_reference(&c->data.v, store, read_region_reference, - RESOLVE_REGION(global.data_version)); - if (ur == 0 && rr == 0 && !c->data.v) { - return AT_READ_FAIL; + else { + READ_INT(store, &n); + c->vigour = (float)n; } - } + if (global.data_version < INTPAK_VERSION) { + ur = read_reference(&c->magician, store, read_int, resolve_unit); + } + else { + ur = read_reference(&c->magician, store, read_unit_reference, resolve_unit); + } + if (global.data_version < CURSEFLOAT_VERSION) { + READ_INT(store, &n); + c->effect = (float)n; + } + else { + READ_FLT(store, &flt); + c->effect = flt; + } + c->type = ct_find(cursename); + if (c->type == NULL) { + int result = read_ccompat(cursename, store); + if (result != 0) { + log_error("missing curse %s, no compatibility code either.\n", cursename); + } + assert(result == 0); + return AT_READ_FAIL; + } + if (global.data_version < CURSEFLAGS_VERSION) { + c_setflag(c, flags); + } + else { + c->flags = flags; + } + c_clearflag(c, CURSE_ISNEW); - return AT_READ_OK; + if (c->type->read) + c->type->read(store, c, owner); + else if (c->type->typ == CURSETYP_UNIT) { + READ_INT(store, &c->data.i); + } + if (c->type->typ == CURSETYP_REGION) { + int rr = + read_reference(&c->data.v, store, read_region_reference, + RESOLVE_REGION(global.data_version)); + if (ur == 0 && rr == 0 && !c->data.v) { + return AT_READ_FAIL; + } + } + + return AT_READ_OK; } void curse_write(const attrib * a, const void *owner, struct storage *store) { - unsigned int flags; - curse *c = (curse *) a->data.v; - const curse_type *ct = c->type; - unit *mage = (c->magician && c->magician->number) ? c->magician : NULL; + unsigned int flags; + curse *c = (curse *)a->data.v; + const curse_type *ct = c->type; + unit *mage = (c->magician && c->magician->number) ? c->magician : NULL; - /* copied from c_clearflag */ - flags = (c->flags & ~CURSE_ISNEW) | (c->type->flags & CURSE_ISNEW); + /* copied from c_clearflag */ + flags = (c->flags & ~CURSE_ISNEW) | (c->type->flags & CURSE_ISNEW); - WRITE_INT(store, c->no); - WRITE_TOK(store, ct->cname); - WRITE_INT(store, flags); - WRITE_INT(store, c->duration); - WRITE_FLT(store, (float)c->vigour); - write_unit_reference(mage, store); - WRITE_FLT(store, (float)c->effect); + WRITE_INT(store, c->no); + WRITE_TOK(store, ct->cname); + WRITE_INT(store, flags); + WRITE_INT(store, c->duration); + WRITE_FLT(store, (float)c->vigour); + write_unit_reference(mage, store); + WRITE_FLT(store, (float)c->effect); - if (c->type->write) - c->type->write(store, c, owner); - else if (c->type->typ == CURSETYP_UNIT) { - WRITE_INT(store, c->data.i); - } - if (c->type->typ == CURSETYP_REGION) { - write_region_reference((region *) c->data.v, store); - } + if (c->type->write) + c->type->write(store, c, owner); + else if (c->type->typ == CURSETYP_UNIT) { + WRITE_INT(store, c->data.i); + } + if (c->type->typ == CURSETYP_REGION) { + write_region_reference((region *)c->data.v, store); + } } attrib_type at_curse = { - "curse", - curse_init, - curse_done, - curse_age, - curse_write, - curse_read, - ATF_CURSE + "curse", + curse_init, + curse_done, + curse_age, + curse_write, + curse_read, + ATF_CURSE }; /* ------------------------------------------------------------- */ @@ -295,31 +300,32 @@ static quicklist *cursetypes[256]; void ct_register(const curse_type * ct) { - unsigned int hash = tolower(ct->cname[0]); - quicklist **ctlp = cursetypes + hash; + unsigned int hash = tolower(ct->cname[0]); + quicklist **ctlp = cursetypes + hash; - ql_set_insert(ctlp, (void *)ct); + ql_set_insert(ctlp, (void *)ct); } const curse_type *ct_find(const char *c) { - unsigned int hash = tolower(c[0]); - quicklist *ctl = cursetypes[hash]; - int qi; + unsigned int hash = tolower(c[0]); + quicklist *ctl = cursetypes[hash]; + int qi; - for (qi = 0; ctl; ql_advance(&ctl, &qi, 1)) { - curse_type *type = (curse_type *) ql_get(ctl, qi); + for (qi = 0; ctl; ql_advance(&ctl, &qi, 1)) { + curse_type *type = (curse_type *)ql_get(ctl, qi); - if (strcmp(c, type->cname) == 0) { - return type; - } else { - size_t k = _min(strlen(c), strlen(type->cname)); - if (!_memicmp(c, type->cname, k)) { - return type; - } + if (strcmp(c, type->cname) == 0) { + return type; + } + else { + size_t k = _min(strlen(c), strlen(type->cname)); + if (!_memicmp(c, type->cname, k)) { + return type; + } + } } - } - return NULL; + return NULL; } /* ------------------------------------------------------------- */ @@ -327,56 +333,34 @@ const curse_type *ct_find(const char *c) * einen pointer auf die struct zurück. */ -bool cmp_curse(const attrib * a, const void *data) +static bool cmp_curse(const attrib * a, const void *data) { - const curse *c = (const curse *)data; - if (a->type->flags & ATF_CURSE) { - if (!data || c == (curse *) a->data.v) - return true; - } - return false; -} - -bool cmp_cursetype(const attrib * a, const void *data) -{ - const curse_type *ct = (const curse_type *)data; - if (a->type->flags & ATF_CURSE) { - if (!data || ct == ((curse *) a->data.v)->type) - return true; - } - return false; -} - -curse *get_cursex(attrib * ap, const curse_type * ctype, variant data, - bool(*compare) (const curse *, variant)) -{ - attrib *a = a_select(ap, ctype, cmp_cursetype); - while (a) { - curse *c = (curse *) a->data.v; - if (compare(c, data)) - return c; - a = a_select(a->next, ctype, cmp_cursetype); - } - return NULL; + const curse *c = (const curse *)data; + if (a->type->flags & ATF_CURSE) { + if (!data || c == (curse *)a->data.v) + return true; + } + return false; } curse *get_curse(attrib * ap, const curse_type * ctype) { - attrib *a = ap; - while (a) { - if (a->type->flags & ATF_CURSE) { - const attrib_type *at = a->type; - while (a && a->type == at) { - curse *c = (curse *) a->data.v; - if (c->type == ctype) - return c; - a = a->next; - } - } else { - a = a->nexttype; + attrib *a = ap; + while (a) { + if (a->type->flags & ATF_CURSE) { + const attrib_type *at = a->type; + while (a && a->type == at) { + curse *c = (curse *)a->data.v; + if (c->type == ctype) + return c; + a = a->next; + } + } + else { + a = a->nexttype; + } } - } - return NULL; + return NULL; } /* ------------------------------------------------------------- */ @@ -384,15 +368,14 @@ curse *get_curse(attrib * ap, const curse_type * ctype) curse *findcurse(int cid) { - return cfindhash(cid); + return cfindhash(cid); } /* ------------------------------------------------------------- */ -void remove_curse(attrib ** ap, const curse * c) +bool remove_curse(attrib ** ap, const curse * c) { - attrib *a = a_select(*ap, c, cmp_curse); - if (a) - a_remove(ap, a); + attrib *a = a_select(*ap, c, cmp_curse); + return a && a_remove(ap, a) == 1; } /* gibt die allgemeine Stärke der Verzauberung zurück. id2 wird wie @@ -400,16 +383,16 @@ void remove_curse(attrib ** ap, const curse * c) * damit der gegen Antimagie wirkende Widerstand einer Verzauberung */ static float get_cursevigour(const curse * c) { - if (c) - return c->vigour; - return 0; + if (c) + return c->vigour; + return 0; } /* setzt die Stärke der Verzauberung auf i */ static void set_cursevigour(curse * c, float vigour) { - assert(c && vigour > 0); - c->vigour = vigour; + assert(c && vigour > 0); + c->vigour = vigour; } /* verändert die Stärke der Verzauberung um +i und gibt die neue @@ -418,47 +401,48 @@ static void set_cursevigour(curse * c, float vigour) */ float curse_changevigour(attrib ** ap, curse * c, float vigour) { - vigour += get_cursevigour(c); + vigour += get_cursevigour(c); - if (vigour <= 0) { - remove_curse(ap, c); - vigour = 0; - } else { - set_cursevigour(c, vigour); - } - return vigour; + if (vigour <= 0) { + remove_curse(ap, c); + vigour = 0; + } + else { + set_cursevigour(c, vigour); + } + return vigour; } /* ------------------------------------------------------------- */ float curse_geteffect(const curse * c) { - if (c == NULL) - return 0; - if (c_flags(c) & CURSE_ISNEW) - return 0; - return c->effect; + if (c == NULL) + return 0; + if (c_flags(c) & CURSE_ISNEW) + return 0; + return c->effect; } int curse_geteffect_int(const curse * c) { - float effect = curse_geteffect(c); - if (effect - (int)effect != 0) { - log_error("curse has an integer attribute with float value: '%s' = %lf", - c->type->cname, effect); - } - return (int)effect; + float effect = curse_geteffect(c); + if (effect - (int)effect != 0) { + log_error("curse has an integer attribute with float value: '%s' = %lf", + c->type->cname, effect); + } + return (int)effect; } /* ------------------------------------------------------------- */ static void set_curseingmagician(struct unit *magician, struct attrib *ap_target, - const curse_type * ct) +const curse_type * ct) { - curse *c = get_curse(ap_target, ct); - if (c) { - c->magician = magician; - } + curse *c = get_curse(ap_target, ct); + if (c) { + c->magician = magician; + } } /* ------------------------------------------------------------- */ @@ -466,29 +450,29 @@ set_curseingmagician(struct unit *magician, struct attrib *ap_target, * betroffenen Personen zurück. Ansonsten wird 0 zurückgegeben. */ int get_cursedmen(unit * u, const curse * c) { - int cursedmen = u->number; + int cursedmen = u->number; - if (!c) - return 0; + if (!c) + return 0; - /* je nach curse_type andere data struct */ - if (c->type->typ == CURSETYP_UNIT) { - cursedmen = c->data.i; - } + /* je nach curse_type andere data struct */ + if (c->type->typ == CURSETYP_UNIT) { + cursedmen = c->data.i; + } - return _min(u->number, cursedmen); + return _min(u->number, cursedmen); } /* setzt die Anzahl der betroffenen Personen auf cursedmen */ static void set_cursedmen(curse * c, int cursedmen) { - if (!c) - return; + if (!c) + return; - /* je nach curse_type andere data struct */ - if (c->type->typ == CURSETYP_UNIT) { - c->data.i = cursedmen; - } + /* je nach curse_type andere data struct */ + if (c->type->typ == CURSETYP_UNIT) { + c->data.i = cursedmen; + } } /* ------------------------------------------------------------- */ @@ -496,90 +480,91 @@ static void set_cursedmen(curse * c, int cursedmen) * dieses Typs geben, gibt es den bestehenden zurück. */ static curse *make_curse(unit * mage, attrib ** ap, const curse_type * ct, - float vigour, int duration, float effect, int men) + float vigour, int duration, float effect, int men) { - curse *c; - attrib *a; + curse *c; + attrib *a; - a = a_new(&at_curse); - a_add(ap, a); - c = (curse *) a->data.v; + a = a_new(&at_curse); + a_add(ap, a); + c = (curse *)a->data.v; - c->type = ct; - c->flags = 0; - c->vigour = vigour; - c->duration = duration; - c->effect = effect; - c->magician = mage; + c->type = ct; + c->flags = 0; + c->vigour = vigour; + c->duration = duration; + c->effect = effect; + c->magician = mage; - c->no = newunitid(); - chash(c); + c->no = newunitid(); + chash(c); - switch (c->type->typ) { + switch (c->type->typ) { case CURSETYP_NORM: - break; + break; case CURSETYP_UNIT: { - c->data.i = men; - break; + c->data.i = men; + break; } - } - return c; + } + return c; } /* Mapperfunktion für das Anlegen neuer curse. Automatisch wird zum * passenden Typ verzweigt und die relevanten Variablen weitergegeben. */ curse *create_curse(unit * magician, attrib ** ap, const curse_type * ct, - float vigour, int duration, float effect, int men) + float vigour, int duration, float effect, int men) { - curse *c; + curse *c; - /* die Kraft eines Spruchs darf nicht 0 sein */ - assert(vigour > 0); + /* die Kraft eines Spruchs darf nicht 0 sein */ + assert(vigour > 0); - c = get_curse(*ap, ct); + c = get_curse(*ap, ct); - if (c && (c_flags(c) & CURSE_ONLYONE)) { - return NULL; - } - assert(c == NULL || ct == c->type); + if (c && (c_flags(c) & CURSE_ONLYONE)) { + return NULL; + } + assert(c == NULL || ct == c->type); - /* es gibt schon eins diese Typs */ - if (c && ct->mergeflags != NO_MERGE) { - if (ct->mergeflags & M_DURATION) { - c->duration = _max(c->duration, duration); - } - if (ct->mergeflags & M_SUMDURATION) { - c->duration += duration; - } - if (ct->mergeflags & M_SUMEFFECT) { - c->effect += effect; - } - if (ct->mergeflags & M_MAXEFFECT) { - c->effect = _max(c->effect, effect); - } - if (ct->mergeflags & M_VIGOUR) { - c->vigour = _max(vigour, c->vigour); - } - if (ct->mergeflags & M_VIGOUR_ADD) { - c->vigour = vigour + c->vigour; - } - if (ct->mergeflags & M_MEN) { - switch (ct->typ) { - case CURSETYP_UNIT: - { - c->data.i += men; + /* es gibt schon eins diese Typs */ + if (c && ct->mergeflags != NO_MERGE) { + if (ct->mergeflags & M_DURATION) { + c->duration = _max(c->duration, duration); } - } + if (ct->mergeflags & M_SUMDURATION) { + c->duration += duration; + } + if (ct->mergeflags & M_SUMEFFECT) { + c->effect += effect; + } + if (ct->mergeflags & M_MAXEFFECT) { + c->effect = _max(c->effect, effect); + } + if (ct->mergeflags & M_VIGOUR) { + c->vigour = _max(vigour, c->vigour); + } + if (ct->mergeflags & M_VIGOUR_ADD) { + c->vigour = vigour + c->vigour; + } + if (ct->mergeflags & M_MEN) { + switch (ct->typ) { + case CURSETYP_UNIT: + { + c->data.i += men; + } + } + } + set_curseingmagician(magician, *ap, ct); } - set_curseingmagician(magician, *ap, ct); - } else { - c = make_curse(magician, ap, ct, vigour, duration, effect, men); - } - return c; + else { + c = make_curse(magician, ap, ct, vigour, duration, effect, men); + } + return c; } /* ------------------------------------------------------------- */ @@ -588,99 +573,99 @@ curse *create_curse(unit * magician, attrib ** ap, const curse_type * ct, static void do_transfer_curse(curse * c, unit * u, unit * u2, int n) { - int cursedmen = 0; - int men = get_cursedmen(u, c); - bool dogive = false; - const curse_type *ct = c->type; + int cursedmen = 0; + int men = get_cursedmen(u, c); + bool dogive = false; + const curse_type *ct = c->type; - switch ((ct->flags | c->flags) & CURSE_SPREADMASK) { + switch ((ct->flags | c->flags) & CURSE_SPREADMASK) { case CURSE_SPREADALWAYS: - dogive = true; - men = u2->number + n; - break; + dogive = true; + men = u2->number + n; + break; case CURSE_SPREADMODULO: { - int i; - int u_number = u->number; - for (i = 0; i < n + 1 && u_number > 0; i++) { - if (rng_int() % u_number < cursedmen) { - ++men; - --cursedmen; - dogive = true; + int i; + int u_number = u->number; + for (i = 0; i < n + 1 && u_number > 0; i++) { + if (rng_int() % u_number < cursedmen) { + ++men; + --cursedmen; + dogive = true; + } + --u_number; } - --u_number; - } - break; + break; } case CURSE_SPREADCHANCE: - if (chance(u2->number / (double)(u2->number + n))) { - men = u2->number + n; - dogive = true; - } - break; + if (chance(u2->number / (double)(u2->number + n))) { + men = u2->number + n; + dogive = true; + } + break; case CURSE_SPREADNEVER: - break; - } + break; + } - if (dogive) { - curse *cnew = make_curse(c->magician, &u2->attribs, c->type, c->vigour, - c->duration, c->effect, men); - cnew->flags = c->flags; + if (dogive) { + curse *cnew = make_curse(c->magician, &u2->attribs, c->type, c->vigour, + c->duration, c->effect, men); + cnew->flags = c->flags; - if (ct->typ == CURSETYP_UNIT) - set_cursedmen(cnew, men); - } + if (ct->typ == CURSETYP_UNIT) + set_cursedmen(cnew, men); + } } void transfer_curse(unit * u, unit * u2, int n) { - attrib *a; + attrib *a; - a = a_find(u->attribs, &at_curse); - while (a && a->type == &at_curse) { - curse *c = (curse *) a->data.v; - do_transfer_curse(c, u, u2, n); - a = a->next; - } + a = a_find(u->attribs, &at_curse); + while (a && a->type == &at_curse) { + curse *c = (curse *)a->data.v; + do_transfer_curse(c, u, u2, n); + a = a->next; + } } /* ------------------------------------------------------------- */ bool curse_active(const curse * c) { - if (!c) - return false; - if (c_flags(c) & CURSE_ISNEW) - return false; - if (c->vigour <= 0) - return false; + if (!c) + return false; + if (c_flags(c) & CURSE_ISNEW) + return false; + if (c->vigour <= 0) + return false; - return true; + return true; } bool is_cursed_internal(attrib * ap, const curse_type * ct) { - curse *c = get_curse(ap, ct); + curse *c = get_curse(ap, ct); - if (!c) - return false; + if (!c) + return false; - return true; + return true; } bool is_cursed_with(const attrib * ap, const curse * c) { - const attrib *a = ap; + const attrib *a = ap; - while (a) { - if ((a->type->flags & ATF_CURSE) && (c == (const curse *)a->data.v)) { - return true; + while (a) { + if ((a->type->flags & ATF_CURSE) && (c == (const curse *)a->data.v)) { + return true; + } + a = a->next; } - a = a->next; - } - return false; + return false; } /* ------------------------------------------------------------- */ @@ -701,81 +686,81 @@ bool is_cursed_with(const attrib * ap, const curse * c) int resolve_curse(variant id, void *address) { - int result = 0; - curse *c = NULL; - if (id.i != 0) { - c = cfindhash(id.i); - if (c == NULL) { - result = -1; + int result = 0; + curse *c = NULL; + if (id.i != 0) { + c = cfindhash(id.i); + if (c == NULL) { + result = -1; + } } - } - *(curse **) address = c; - return result; + *(curse **)address = c; + return result; } static const char *oldnames[MAXCURSE] = { - /* OBS: when removing curses, remember to update read_ccompat() */ - "fogtrap", - "antimagiczone", - "farvision", - "gbdream", - "auraboost", - "maelstrom", - "blessedharvest", - "drought", - "badlearn", - "stormwind", - "flyingship", - "nodrift", - "depression", - "magicwalls", - "strongwall", - "astralblock", - "generous", - "peacezone", - "magicstreet", - "magicrunes", - "badmagicresistancezone", - "goodmagicresistancezone", - "slavery", - "calmmonster", - "oldrace", - "fumble", - "riotzone", - "nocostbuilding", - "godcursezone", - "speed", - "orcish", - "magicboost", - "insectfur", - "strength", - "worse", - "magicresistance", - "itemcloak", - "sparkle", - "skillmod" + /* OBS: when removing curses, remember to update read_ccompat() */ + "fogtrap", + "antimagiczone", + "farvision", + "gbdream", + "auraboost", + "maelstrom", + "blessedharvest", + "drought", + "badlearn", + "stormwind", + "flyingship", + "nodrift", + "depression", + "magicwalls", + "strongwall", + "astralblock", + "generous", + "peacezone", + "magicstreet", + "magicrunes", + "badmagicresistancezone", + "goodmagicresistancezone", + "slavery", + "calmmonster", + "oldrace", + "fumble", + "riotzone", + "nocostbuilding", + "godcursezone", + "speed", + "orcish", + "magicboost", + "insectfur", + "strength", + "worse", + "magicresistance", + "itemcloak", + "sparkle", + "skillmod" }; const char *oldcursename(int id) { - return oldnames[id]; + return oldnames[id]; } /* ------------------------------------------------------------- */ message *cinfo_simple(const void *obj, objtype_t typ, const struct curse * c, - int self) + int self) { - struct message *msg; + struct message *msg; - unused_arg(typ); - unused_arg(self); - unused_arg(obj); + unused_arg(typ); + unused_arg(self); + unused_arg(obj); - msg = msg_message(mkname("curseinfo", c->type->cname), "id", c->no); - if (msg == NULL) { - log_error("There is no curseinfo for %s.\n", c->type->cname); - } - return msg; + msg = msg_message(mkname("curseinfo", c->type->cname), "id", c->no); + if (msg == NULL) { + log_error("There is no curseinfo for %s.\n", c->type->cname); + } + return msg; } /* ------------------------------------------------------------- */ @@ -791,27 +776,30 @@ message *cinfo_simple(const void *obj, objtype_t typ, const struct curse * c, */ float destr_curse(curse * c, int cast_level, float force) { - if (cast_level < c->vigour) { /* Zauber ist nicht stark genug */ - double probability = 0.1 + (cast_level - c->vigour) * 0.2; - /* pro Stufe Unterschied -20% */ - if (chance(probability)) { - force -= c->vigour; - if (c->type->change_vigour) { - c->type->change_vigour(c, -((float)cast_level + 1) / 2); - } else { - c->vigour -= cast_level + 1 / 2; - } + if (cast_level < c->vigour) { /* Zauber ist nicht stark genug */ + double probability = 0.1 + (cast_level - c->vigour) * 0.2; + /* pro Stufe Unterschied -20% */ + if (chance(probability)) { + force -= c->vigour; + if (c->type->change_vigour) { + c->type->change_vigour(c, -((float)cast_level + 1) / 2); + } + else { + c->vigour -= cast_level + 1 / 2; + } + } } - } else { /* Zauber ist stärker als curse */ - if (force >= c->vigour) { /* reicht die Kraft noch aus? */ - force -= c->vigour; - if (c->type->change_vigour) { - c->type->change_vigour(c, -c->vigour); - } else { - c->vigour = 0; - } + else { /* Zauber ist stärker als curse */ + if (force >= c->vigour) { /* reicht die Kraft noch aus? */ + force -= c->vigour; + if (c->type->change_vigour) { + c->type->change_vigour(c, -c->vigour); + } + else { + c->vigour = 0; + } + } } - } - return force; + return force; } diff --git a/src/kernel/curse.h b/src/kernel/curse.h index 4ad472a96..7bc6f9652 100644 --- a/src/kernel/curse.h +++ b/src/kernel/curse.h @@ -1,5 +1,5 @@ /* -Copyright (c) 1998-2010, Enno Rehling +Copyright (c) 1998-2014, Enno Rehling Katja Zedel @@ -251,7 +251,7 @@ extern "C" { bool is_cursed_internal(struct attrib *ap, const curse_type * ctype); /* ignoriert CURSE_ISNEW */ - extern void remove_curse(struct attrib **ap, const struct curse *c); + bool remove_curse(struct attrib **ap, const struct curse *c); /* löscht einen konkreten Spruch auf einem Objekt. */ @@ -280,11 +280,6 @@ extern "C" { * unterschiedlich gewünscht sein * */ - extern struct curse *get_cursex(struct attrib *ap, const curse_type * ctype, - variant data, bool(*compare) (const struct curse *, variant)); - /* gibt pointer auf die erste curse-struct zurück, deren Typ ctype ist, - * und für die compare() true liefert, oder einen NULL-pointer. - * */ extern struct curse *get_curse(struct attrib *ap, const curse_type * ctype); /* gibt pointer auf die erste curse-struct zurück, deren Typ ctype ist, * oder einen NULL-pointer @@ -303,9 +298,6 @@ extern "C" { extern void curse_done(struct attrib *a); extern int curse_age(struct attrib *a); - extern bool cmp_curse(const struct attrib *a, const void *data); - extern bool cmp_cursetype(const struct attrib *a, const void *data); - extern float destr_curse(struct curse *c, int cast_level, float force); extern int resolve_curse(variant data, void *address); diff --git a/src/kernel/save.c b/src/kernel/save.c index 7febc0d23..c52eae383 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -1313,7 +1313,6 @@ faction *readfaction(struct gamedata * data) f->flags = FFL_NPC | FFL_NOIDLEOUT; } } - assert((f->flags&FFL_SAVEMASK) == f->flags); a_read(data->store, &f->attribs, f); if (data->version >= CLAIM_VERSION) { diff --git a/src/modules/gmcmd.c b/src/modules/gmcmd.c index 110e418cd..9a5085ecf 100644 --- a/src/modules/gmcmd.c +++ b/src/modules/gmcmd.c @@ -35,16 +35,6 @@ /* util includes */ #include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include /* libc includes */ @@ -56,18 +46,11 @@ static int read_permissions(attrib * a, void *owner, struct storage *store) { attrib *attr = NULL; - a_read(store, &attr, NULL); - a_free(attr); + a_read(store, &attr, owner); + a_remove(&attr, a); return AT_READ_OK; } -struct attrib_type at_permissions = { - "GM:permissions", - NULL, NULL, NULL, - NULL, read_permissions, - ATF_UNIQUE -}; - static int read_gmcreate(attrib * a, void *owner, struct storage *store) { char zText[32]; @@ -75,15 +58,8 @@ static int read_gmcreate(attrib * a, void *owner, struct storage *store) return AT_READ_OK; } -/* at_gmcreate specifies that the owner can create items of a particular type */ -attrib_type at_gmcreate = { - "GM:create", - NULL, NULL, NULL, - NULL, read_gmcreate -}; - void register_gmcmd(void) { - at_register(&at_gmcreate); - at_register(&at_permissions); + at_deprecate("GM:create", read_gmcreate); + at_deprecate("GM:permissions", read_permissions); } diff --git a/src/triggers/removecurse.c b/src/triggers/removecurse.c index f6fcbc659..38cdbc989 100644 --- a/src/triggers/removecurse.c +++ b/src/triggers/removecurse.c @@ -1,7 +1,7 @@ /* -Copyright (c) 1998-2010, Enno Rehling - Katja Zedel +Copyright (c) 1998-2014, Enno Rehling +Katja Zedel Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -41,68 +41,66 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include typedef struct removecurse_data { - curse *curse; - unit *target; + curse *curse; + unit *target; } removecurse_data; static void removecurse_init(trigger * t) { - t->data.v = calloc(sizeof(removecurse_data), 1); + t->data.v = calloc(sizeof(removecurse_data), 1); } static void removecurse_free(trigger * t) { - free(t->data.v); + free(t->data.v); } static int removecurse_handle(trigger * t, void *data) { - /* call an event handler on removecurse. - * data.v -> ( variant event, int timer ) - */ - removecurse_data *td = (removecurse_data *) t->data.v; - if (td->curse && td->target) { - attrib *a = a_select(td->target->attribs, td->curse, cmp_curse); - if (a) { - a_remove(&td->target->attribs, a); - } else - log_error("could not perform removecurse::handle()\n"); - } - unused_arg(data); - return 0; + /* call an event handler on removecurse. + * data.v -> ( variant event, int timer ) + */ + removecurse_data *td = (removecurse_data *)t->data.v; + if (td->curse && td->target) { + if (!remove_curse(&td->target->attribs, td->curse)) { + log_error("could not perform removecurse::handle()\n"); + } + } + unused_arg(data); + return 0; } static void removecurse_write(const trigger * t, struct storage *store) { - removecurse_data *td = (removecurse_data *) t->data.v; - WRITE_TOK(store, td->target ? itoa36(td->target->no) : 0); - WRITE_INT(store, td->curse ? td->curse->no : 0); + removecurse_data *td = (removecurse_data *)t->data.v; + WRITE_TOK(store, td->target ? itoa36(td->target->no) : 0); + WRITE_INT(store, td->curse ? td->curse->no : 0); } static int removecurse_read(trigger * t, struct storage *store) { - removecurse_data *td = (removecurse_data *) t->data.v; + removecurse_data *td = (removecurse_data *)t->data.v; - read_reference(&td->target, store, read_unit_reference, resolve_unit); - read_reference(&td->curse, store, read_int, resolve_curse); + read_reference(&td->target, store, read_unit_reference, resolve_unit); + read_reference(&td->curse, store, read_int, resolve_curse); - return AT_READ_OK; + return AT_READ_OK; } trigger_type tt_removecurse = { - "removecurse", - removecurse_init, - removecurse_free, - removecurse_handle, - removecurse_write, - removecurse_read + "removecurse", + removecurse_init, + removecurse_free, + removecurse_handle, + removecurse_write, + removecurse_read }; trigger *trigger_removecurse(curse * c, unit * target) { - trigger *t = t_new(&tt_removecurse); - removecurse_data *td = (removecurse_data *) t->data.v; - td->curse = c; - td->target = target; - return t; + trigger *t = t_new(&tt_removecurse); + removecurse_data *td = (removecurse_data *)t->data.v; + td->curse = c; + td->target = target; + return t; } diff --git a/src/util/attrib.c b/src/util/attrib.c index 2b83b60ec..7dc067cc4 100644 --- a/src/util/attrib.c +++ b/src/util/attrib.c @@ -151,14 +151,6 @@ attrib *a_add(attrib ** pa, attrib * a) return a; } -void a_free(attrib * a) -{ - const attrib_type *at = a->type; - if (at->finalize) - at->finalize(a); - free(a); -} - static int a_unlink(attrib ** pa, attrib * a) { attrib **pnexttype = pa; @@ -197,6 +189,14 @@ static int a_unlink(attrib ** pa, attrib * a) return 0; } +static void a_free(attrib * a) +{ + const attrib_type *at = a->type; + if (at->finalize) + at->finalize(a); + free(a); +} + int a_remove(attrib ** pa, attrib * a) { int ok; diff --git a/src/util/attrib.h b/src/util/attrib.h index 2bea8d2b8..7dc3e1a3d 100644 --- a/src/util/attrib.h +++ b/src/util/attrib.h @@ -73,7 +73,6 @@ extern "C" { extern int a_remove(attrib ** pa, attrib * at); extern void a_removeall(attrib ** a, const attrib_type * at); extern attrib *a_new(const attrib_type * at); - extern void a_free(attrib * a); extern int a_age(attrib ** attribs); extern int a_read(struct storage *store, attrib ** attribs, void *owner); diff --git a/src/util/attrib.test.c b/src/util/attrib.test.c index be3987bfe..2e15c8321 100644 --- a/src/util/attrib.test.c +++ b/src/util/attrib.test.c @@ -12,6 +12,8 @@ static void test_attrib_new(CuTest * tc) CuAssertPtrEquals(tc, 0, a->next); CuAssertPtrEquals(tc, 0, a->nexttype); CuAssertPtrEquals(tc, (void *)a->type, (void *)&at_test); + a_remove(&a, a); + CuAssertPtrEquals(tc, 0, a); } @@ -20,18 +22,55 @@ static void test_attrib_add(CuTest * tc) attrib_type at_foo = { "foo" }; attrib_type at_bar = { "bar" }; attrib *a, *alist = 0; + CuAssertPtrNotNull(tc, (a = a_new(&at_foo))); CuAssertPtrEquals(tc, a, a_add(&alist, a)); CuAssertPtrEquals(tc, a, alist); - CuAssertPtrEquals(tc, 0, alist->nexttype); CuAssertPtrNotNull(tc, (a = a_add(&alist, a_new(&at_foo)))); - CuAssertPtrEquals(tc, alist->next, a); + CuAssertPtrEquals_Msg(tc, "new attribute not added after existing", alist->next, a); + + CuAssertPtrNotNull(tc, (a = a_add(&alist, a_new(&at_bar)))); + CuAssertPtrEquals_Msg(tc, "new atribute not added at end of list", alist->next->next, a); + + CuAssertPtrNotNull(tc, (a = a_add(&alist, a_new(&at_foo)))); + CuAssertPtrEquals_Msg(tc, "messages not sorted by type", alist->next->next, a); + a_removeall(&alist, &at_foo); + a_removeall(&alist, &at_bar); +} + +static void test_attrib_remove(CuTest * tc) +{ + attrib_type at_foo = { "foo" }; + attrib *a, *alist = 0; + + CuAssertPtrNotNull(tc, a_add(&alist, a_new(&at_foo))); + CuAssertPtrNotNull(tc, a = a_add(&alist, a_new(&at_foo))); + CuAssertIntEquals(tc, 1, a_remove(&alist, a)); + CuAssertPtrNotNull(tc, alist); + CuAssertIntEquals(tc, 1, a_remove(&alist, alist)); + CuAssertPtrEquals(tc, 0, alist); +} + +static void test_attrib_nexttype(CuTest * tc) +{ + attrib_type at_foo = { "foo" }; + attrib_type at_bar = { "bar" }; + attrib *a, *alist = 0; + CuAssertPtrNotNull(tc, (a = a_new(&at_foo))); + CuAssertPtrEquals(tc, 0, a->nexttype); + CuAssertPtrEquals(tc, a, a_add(&alist, a)); + CuAssertPtrEquals(tc, 0, alist->nexttype); + + CuAssertPtrNotNull(tc, a_add(&alist, a_new(&at_foo))); CuAssertPtrEquals(tc, 0, alist->nexttype); CuAssertPtrNotNull(tc, (a = a_add(&alist, a_new(&at_bar)))); - CuAssertPtrEquals(tc, alist->next->next, a); CuAssertPtrEquals(tc, a, alist->nexttype); + CuAssertPtrEquals(tc, 0, a->nexttype); + + a_removeall(&alist, &at_foo); + a_removeall(&alist, &at_bar); } CuSuite *get_attrib_suite(void) @@ -39,5 +78,7 @@ CuSuite *get_attrib_suite(void) CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_attrib_new); SUITE_ADD_TEST(suite, test_attrib_add); + SUITE_ADD_TEST(suite, test_attrib_remove); + SUITE_ADD_TEST(suite, test_attrib_nexttype); return suite; }