From 9fcbceb8c6ba8169d1af48182c349fa41d5b1d1f Mon Sep 17 00:00:00 2001 From: rob Date: Sun, 28 Aug 2022 15:13:30 +1000 Subject: [PATCH] WIP: implementing hash tables for flagpiles. flag code done, need to wrap all walks of flagpiles with foreach_bucket() --- ai.c | 17 +- data.c | 13 +- defs.h | 6 +- flag.c | 354 ++++++++------ flag.h | 3 + god.c | 18 +- io.c | 1492 ++++++++++++++++++++++++++++---------------------------- 7 files changed, 1007 insertions(+), 896 deletions(-) diff --git a/ai.c b/ai.c index 7b19bc3..80a2cdc 100755 --- a/ai.c +++ b/ai.c @@ -3387,13 +3387,16 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG } } if (ot->id == OT_S_WEAKEN) { - flag_t *lff; - for (lff = lf->flags->first; lff ; lff = lff->next) { - if ((lff->id == F_ATTRMOD) && (lff->val[0] == A_STR) && (lff->obfrom == OT_S_WEAKEN)) { - specificcheckok = B_FALSE; - break; - } - } + int nretflags,i; + flag_t *retflag[MAXCANDIDATES]; + + getflags(lf->flags, retflag, &nretflags, F_ATTRMOD, F_NONE); + for (i=0; i< nretflags; i++) { + if ((retflag[i]->id == F_ATTRMOD) && (retflag[i]->val[0] == A_STR) && (retflag[i]->obfrom == OT_S_WEAKEN)) { + specificcheckok = B_FALSE; + break; + } + } } if (!specificcheckok) { if (db) dblog(".oO { cant cast %s - specific spell check failed }", ot ? ot->name : "?unkownspell?"); diff --git a/data.c b/data.c index 842592c..bbd4866 100755 --- a/data.c +++ b/data.c @@ -46,13 +46,14 @@ extern objecttype_t *lastot; extern condset_t ccwalkable; void addbonustext(flagpile_t *fp, enum FLAG fid, char *text) { - int idx = -1; - flag_t *f; + int idx = -1, i; + flag_t *retflag[MAXCANDIDATES]; + int nretflags = 0; + getflags(fp, retflag, &nretflags, fid, F_NONE); + // find last index - for (f = fp->first ; f; f = f->next) { - if (f->id == fid) { - if (f->val[0] > idx) idx = f->val[0]; - } + for (i=0; i< nretflags; i++) { + if (retflag[i]->val[0] > idx) idx = retflag[i]->val[0]; } addflag(fp, fid, idx+1, NA, NA, text); } diff --git a/defs.h b/defs.h index 5e640ec..00d849d 100755 --- a/defs.h +++ b/defs.h @@ -11,10 +11,14 @@ #define OBNOS1(o) (o->amt == 1) ? "" : "s" #define ISINRANGE(a,min,max) ((a >= min) && (a <= max)) +#define foreach_bucket(a) for (a=0; a= 0); + assert(h < NHASHBUCKETS); + return h; +} + flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int lifetime, int known, long obfromid) { lifeform_t *lf; flag_t *f = NULL; @@ -67,6 +75,7 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, int redrawstatatend = B_FALSE; int i; int rv; + int hash; enum { NONE, FIRST, FIRST2, MIDDLE, LAST } fml = NONE; checkflagpile(fp); @@ -168,17 +177,21 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, */ //if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging + + // determine bucket + hash = getflaghash(id); + //////////////////////////////// // ACTUAL FLAG ADDITION IS HERE //////////////////////////////// - if (fp->first == NULL) { - fp->first = (flag_t *)calloc(1, sizeof(flag_t)); - f = fp->first; + if (fp->first[hash] == NULL) { + fp->first[hash] = (flag_t *)calloc(1, sizeof(flag_t)); + f = fp->first[hash]; f->prev = NULL; // also the last - fp->last = f; + fp->last[hash] = f; f->next = NULL; fml = FIRST; @@ -186,7 +199,7 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, flag_t *ff,*insertbefore = NULL,*insertafter = NULL; // we will keep flags sorted. // find correct position in list... - ff = fp->first; + ff = fp->first[hash]; while (ff && (ff->id < id)) { ff = ff->next; } @@ -223,8 +236,8 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, } else { // first one //fp->first = (flag_t *)calloc(1, sizeof(flag_t)); - fp->first = newone; - assert(fp->first != NULL); + fp->first[hash] = newone; + assert(fp->first[hash] != NULL); //f = fp->first; f = newone; fml = FIRST2; @@ -238,11 +251,11 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, ff->prev = f; } else { // last one. insert at end of list. - f = fp->last; + f = fp->last[hash]; f->next = (flag_t *)malloc(sizeof(flag_t)); /// <- died here! f->next->prev = f; f = f->next; - fp->last = f; + fp->last[hash] = f; f->next = NULL; fml = LAST; @@ -463,13 +476,16 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, } flagpile_t *addflagpile(lifeform_t *owner, object_t *ob) { + int i; flagpile_t *fp; fp = malloc(sizeof(flagpile_t)); - fp->first = NULL; - fp->last = NULL; + foreach_bucket(i) { + fp->first[i] = NULL; + fp->last[i] = NULL; + fp->nitems = 0; + } fp->owner = owner; fp->ob = ob; - fp->nitems = 0; return fp; } @@ -552,22 +568,27 @@ void checkflagpile(flagpile_t *fp) { } } + +/// TODO: remove this function int fpisbad(flagpile_t *fp) { flag_t *f; + int i; if (!flagcheck) return B_FALSE; - for (f = fp->first ; f ; f = f->next) { - if (f->next) { - if(f->next->prev != f) { - dblog("flag after %d is bad! its prev = 0x%x, should be this flag (0x%x)",f->id, f->next->prev, f); - return B_TRUE; - } - } - if (fp->ob && fp->owner) { - dblog("flag %d has both ob and owner",f->id); - return B_TRUE; - } + foreach_bucket(i) { + for (f = fp->first[i] ; f ; f = f->next) { + if (f->next) { + if(f->next->prev != f) { + dblog("flag after %d is bad! its prev = 0x%x, should be this flag (0x%x)",f->id, f->next->prev, f); + return B_TRUE; + } + } + if (fp->ob && fp->owner) { + dblog("flag %d has both ob and owner",f->id); + return B_TRUE; + } + } } return B_FALSE; } @@ -576,10 +597,11 @@ int fpisbad(flagpile_t *fp) { // returns # of flags copied int copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id) { flag_t *f; - int ndone = 0; - for (f = src->first ; f ; f = f->next) { + int ndone = 0, i; + foreach_bucket(i) { + for (f = src->first[i] ; f ; f = f->next) { // gone past the requrested id's number - ie. it's not there. - if (f->id > id) break; + //if (f->id > id) break; if (f->id == id) { flag_t *newf; newf = addflag_real(dst, f->id, f->val[0], f->val[1], f->val[2], f->text, @@ -596,64 +618,75 @@ int copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id) { } ndone++; } + } } return ndone; } void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime) { flag_t *f,*newf; - for (f = src->first ; f ; f = f->next) { - // omit certain flags - if (lifetime == FROMBRAND) { - if ((f->id == F_ONLYFOROBTYPE) || - (f->id == F_ONLYFORDAMTYPE) || - (f->id == F_ONLYFORWEPSKILL)) { - continue; - } - } - newf = addflag_real(dst, f->id, f->val[0], f->val[1], f->val[2], f->text, - (lifetime == NA) ? f->lifetime : lifetime, f->known, -1); - // newf might not be set, if (for example) we are coyping a duplicate - // f_linkrace flag. - if (newf) { - newf->condition = f->condition; - newf->origlifetime = f->origlifetime; - newf->chance = f->chance; - if (f->altval) { - addaltval(newf, f->altval->id, - f->altval->val[0], - f->altval->val[1], - f->altval->val[2], - f->altval->text); - } - } - } + int i; + foreach_bucket(i) { + for (f = src->first[i] ; f ; f = f->next) { + // omit certain flags + if (lifetime == FROMBRAND) { + if ((f->id == F_ONLYFOROBTYPE) || + (f->id == F_ONLYFORDAMTYPE) || + (f->id == F_ONLYFORWEPSKILL)) { + continue; + } + } + newf = addflag_real(dst, f->id, f->val[0], f->val[1], f->val[2], f->text, + (lifetime == NA) ? f->lifetime : lifetime, f->known, -1); + // newf might not be set, if (for example) we are coyping a duplicate + // f_linkrace flag. + if (newf) { + newf->condition = f->condition; + newf->origlifetime = f->origlifetime; + newf->chance = f->chance; + if (f->altval) { + addaltval(newf, f->altval->id, + f->altval->val[0], + f->altval->val[1], + f->altval->val[2], + f->altval->text); + } + } + } + } } int countflags(flagpile_t *fp) { flag_t *f; - int count = 0; - for (f = fp->first ; f ; f = f->next) { - count++; - } + int count = 0, i; + foreach_bucket(i) { + for (f = fp->first[i] ; f ; f = f->next) { + count++; + } + } return count; } int countflagsofid(flagpile_t *fp, enum FLAG fid) { flag_t *f; - int count = 0; - for (f = fp->first ; f ; f = f->next) { + int count = 0, i; + foreach_bucket(i) { + for (f = fp->first[i] ; f ; f = f->next) { if (f->id == fid) count++; - } + } + } return count; } void dumpflags(flagpile_t *fp) { flag_t *f; dblog("START FLAGDUMP"); - for (f = fp->first ; f ; f = f->next) { - dblog("fid=%d, v0=%d v1=%d v2=%d text=[%s]", - f->id, f->val[0], f->val[1], f->val[2], f->text); + int i; + foreach_bucket(i) { + for (f = fp->first[i] ; f ; f = f->next) { + dblog("[b=%d] fid=%d, v0=%d v1=%d v2=%d text=[%s]", + i, f->id, f->val[0], f->val[1], f->val[2], f->text); + } } dblog("END FLAGDUMP"); } @@ -817,11 +850,75 @@ flag_t *hasflagknown(flagpile_t *fp, int id) { return hasflag_real(fp, id, B_TRUE, NULL, NA); } +flag_t *flag_bsearch(flagpile_t *fp, int id, int *iterp) { + flag_t *f,*searchfrom = NULL; + int pos; + int iter = 0; + int l,r; + // binary search for this flag id. + l = 0; + r = fp->nitems-1; + while (!searchfrom) { + //if (db) dblog(" iter#%d: l=%d,r=%d", iter, l, r); + if (r < l) { + // NOT FOUND. + //if (db) dblog(" r < l: not found!"); + break; + } else if (fp->item[l]->id > id) { + // NOT FOUND. + //if (db) dblog(" leftid %d > wantid %d. not found!",fp->item[l]->id, id); + break; + } else if (fp->item[r]->id < id) { + // NOT FOUND. + //if (db) dblog(" rightid %d > wantid %d. not found!",fp->item[r]->id, id); + break; + } + // half way inbetween l and r + pos = ((l+r)/2); + f = fp->item[pos]; + //if (db) dblog(" iter#%d: pos=%d. item here is %d (looking for %d)", iter, pos, f->id, id); + + if (f->id == id) { + // go back to first occurence + while (f->prev && (f->prev->id == id)) { + f = f->prev; + iter++; + } + searchfrom = f; + break; + } else if (f->id > id) { + // go left + r = pos-1; + } else { + // go right + l = pos+1; + } + iter++; + } + if (iterp) *iterp += iter; + return searchfrom; +} + +flag_t *flag_hsearch(flagpile_t *fp, int id, int *iterp) { + flag_t *f,*searchfrom = NULL; + int hash; + int iter = 0; + + hash = getflaghash(id); + for (f = fp->first[hash]; f ; f=f->next) { + iter++; + if (f->id == id) { + searchfrom = f; + break; + } + } + if (iterp) *iterp += iter; + return searchfrom; +} + flag_t *hasflag_real(flagpile_t *fp, int id, int wantknown, flag_t *exception, int lifetimeexception) { flag_t *f,*foundflag = NULL, *searchfrom = NULL; lifeform_t *owner; - int pos; - int l,r; int iter = 0,subiter = 0; int db = B_FALSE; @@ -829,52 +926,17 @@ flag_t *hasflag_real(flagpile_t *fp, int id, int wantknown, flag_t *exception, i if (flagdb) db = B_TRUE; - if (db) dblog("hasflag %d in flagpile with %d entries", id, fp->nitems); - // binary search for this flag id. - l = 0; - r = fp->nitems-1; - while (!searchfrom) { - //if (db) dblog(" iter#%d: l=%d,r=%d", iter, l, r); - if (r < l) { - // NOT FOUND. - //if (db) dblog(" r < l: not found!"); - break; - } else if (fp->item[l]->id > id) { - // NOT FOUND. - //if (db) dblog(" leftid %d > wantid %d. not found!",fp->item[l]->id, id); - break; - } else if (fp->item[r]->id < id) { - // NOT FOUND. - //if (db) dblog(" rightid %d > wantid %d. not found!",fp->item[r]->id, id); - break; - } - // half way inbetween l and r - pos = ((l+r)/2); - f = fp->item[pos]; - //if (db) dblog(" iter#%d: pos=%d. item here is %d (looking for %d)", iter, pos, f->id, id); + if (db) dblog("call to hasflag %d in flagpile with %d entries", id, fp->nitems); - if (f->id == id) { - // go back to first occurence - while (f->prev && (f->prev->id == id)) { - f = f->prev; - iter++; - } - searchfrom = f; - break; - } else if (f->id > id) { - // go left - r = pos-1; - } else { - // go right - l = pos+1; - } - iter++; - } + // find first occurence of this id + //searchfrom = flag_bsearch(fp, id, &iter); + searchfrom = flag_hsearch(fp, id, &iter); - // now find a valid one f = searchfrom; - while (f && (f->id == id)) { + //while (f && (f->id == id)) { for binary search + while (f) { + if (f->id == id) { int valid = B_TRUE; if (f == exception) valid = B_FALSE; if ((lifetimeexception != NA) && (f->lifetime == lifetimeexception)) valid = B_FALSE; @@ -889,6 +951,7 @@ flag_t *hasflag_real(flagpile_t *fp, int id, int wantknown, flag_t *exception, i f = f->next; subiter++; } + } } if (db) dblog("finished - %s - iter=%d, subiter=%d", foundflag ? "found it" : "NOT FOUND",iter,subiter); @@ -1131,7 +1194,7 @@ void real_killflag(flag_t *f, int wantannounce) { cell_t *redolos = NULL; int redostat = B_FALSE; int redoscreen = B_FALSE; - int i,dopleasegod[MAXGODS]; + int i,hash,dopleasegod[MAXGODS]; flagpile_t *newflags = NULL; @@ -1261,6 +1324,8 @@ void real_killflag(flag_t *f, int wantannounce) { } checkflagpile(pile); + // determine bucket + hash = getflaghash(f->id); ///////////////////////////////////////////// // now we are actually removing the flag. ///////////////////////////////////////////// @@ -1284,13 +1349,13 @@ void real_killflag(flag_t *f, int wantannounce) { if (nextone != NULL) { nextone->prev = f->prev; } else { /* last */ - f->pile->last = f->prev; + f->pile->last[hash] = f->prev; } if (f->prev == NULL) { /* first */ nextone = f->next; - f->pile->first = nextone; + f->pile->first[hash] = nextone; free(f); } else { lastone = f->prev; @@ -1362,43 +1427,49 @@ void real_killflag(flag_t *f, int wantannounce) { } void killflagpile(flagpile_t *fp) { - if (fp->ob && !fp->ob->dying) { - assert(0 == "calling killflagpile on non-dying object"); - } + int i; + if (fp->ob && !fp->ob->dying) { + assert(0 == "calling killflagpile on non-dying object"); + } - //checkflagpile(fp); - while (fp->first) { - killflag(fp->first); - } - //checkflagpile(fp); - free(fp); + //checkflagpile(fp); + foreach_bucket(i) { + while (fp->first[i]) { + killflag(fp->first[i]); + } + } + //checkflagpile(fp); + free(fp); } int killtransitoryflags(flagpile_t *fp, enum FLAG fid) { - flag_t *f,*nextf; - int nkilled = 0; - for (f = fp->first ; f ; f = nextf) { - nextf = f->next; + flag_t *f,*nextf; + int nkilled = 0, i; + foreach_bucket(i) { + for (f = fp->first[i] ; f ; f = nextf) { + nextf = f->next; - // gone past the requrested id's number - ie. it's not there. - if (f->id > fid) break; + // gone past the requrested id's number - ie. it's not there. + //if (f->id > fid) break; - if (istransitoryflag(f) && (f->id == fid)) { - killflag(f); - nkilled++; - } - } - return nkilled; + if (istransitoryflag(f) && (f->id == fid)) { + killflag(f); + nkilled++; + } + } + } + return nkilled; } int killtransitoryflagvals(flagpile_t *fp, enum FLAG fid, int val1, int val2, int val3, char *text) { flag_t *f, *nextf; - int nkilled = 0; - for (f = fp->first ; f ; f = nextf) { + int nkilled = 0, i; + foreach_bucket(i) { + for (f = fp->first[i] ; f ; f = nextf) { nextf = f->next; // gone past the requrested id's number - ie. it's not there. - if (f->id > fid) break; + //if (f->id > fid) break; if (istransitoryflag(f) && (f->id == fid)) { if ( ((val1 == NA) || (f->val[0] == val1)) && @@ -1409,6 +1480,7 @@ int killtransitoryflagvals(flagpile_t *fp, enum FLAG fid, int val1, int val2, in nkilled++; } } + } } return nkilled; } @@ -1661,19 +1733,22 @@ char *getflagtext(flagpile_t *fp, enum FLAG fid) { } void getmaxflags(flagpile_t *fp, int id, int *max0, int *max1, int *max2) { + int i; flag_t *f; if (max0) *max0 = 0; if (max1) *max1 = 0; if (max2) *max2 = 0; - for (f = fp->first ; f ; f = f->next) { + foreach_bucket(i) { + for (f = fp->first[i] ; f ; f = f->next) { // gone past the requrested id's number - ie. it's not there. - if (f->id > id) break; + //if (f->id > id) break; if (f->id == id) { if (max0 && (f->val[0] > *max0)) *max0 = f->val[0]; if (max1 && (f->val[1] > *max1)) *max1 = f->val[1]; if (max2 && (f->val[2] > *max2)) *max2 = f->val[2]; } + } } } @@ -1758,21 +1833,26 @@ void sumflags(flagpile_t *fp, enum FLAG id, int *val0, int *val1, int *val2) { void timeeffectsflags(flagpile_t *fp) { flag_t *f,*nextf; enum FLAG thisid; + int i; - for (f = fp->first ; f ; f = nextf) { + foreach_bucket(i) { + for (f = fp->first[i] ; f ; f = nextf) { nextf = f->next; thisid = f->id; timeeffectsflag(f, 1); // if this checkflag() crashes, we know there we a bug during processing of // flag 'thisid' checkflagpile(fp); + } } //checkflagpile(fp); } // generate an index void updatefpindex(flagpile_t *fp) { + return; +/* flag_t *f; fp->nitems = 0; @@ -1784,5 +1864,5 @@ void updatefpindex(flagpile_t *fp) { fp->nitems++; assert(fp->nitems < MAXFLAGS); } - //checkflagpile(fp); +*/ } diff --git a/flag.h b/flag.h index a9cc5fd..5a08426 100755 --- a/flag.h +++ b/flag.h @@ -21,6 +21,8 @@ void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime); int countflags(flagpile_t *fp); int countflagsofid(flagpile_t *fp, enum FLAG fid ); void dumpflags(flagpile_t *fp); +flag_t *flag_bsearch(flagpile_t *fp, int id, int *iterp); +flag_t *flag_hsearch(flagpile_t *fp, int id, int *iterp); int flagcausesinterrupt(flag_t *f, enum GAINORLOSS gol); int flagcausesloscalc(enum FLAG fid); int flagcausesredraw(lifeform_t *lf, enum FLAG fid); @@ -30,6 +32,7 @@ int flagstacks(enum FLAG fid); int flagtomaxhp(flag_t *f); cell_t *getflagpilelocation(flagpile_t *fp); int getflags(flagpile_t *fp, flag_t **retflag, int *nretflags, ... ); +int getflaghash(enum FLAG fid); char *getflagtext(flagpile_t *fp, enum FLAG fid); void getmaxflags(flagpile_t *fp, int id, int *max0, int *max1, int *max2); flag_t *getrandomflag(flagpile_t *fp, enum FLAG fid); diff --git a/god.c b/god.c index dcb9e0a..d155f29 100755 --- a/god.c +++ b/god.c @@ -166,7 +166,7 @@ void angergod(enum RACE rid, int amt, enum GODANGERREASON why) { object_t *o; flag_t *f; int isflag[MAXCANDIDATES]; - int nposs = 0; + int nposs = 0, b; enum ATTRIB a; // lose at least one god gift for (o = player->pack->first ; o ; o = o->next) { @@ -177,13 +177,15 @@ void angergod(enum RACE rid, int amt, enum GODANGERREASON why) { } } - for (f = player->flags->first ; f ; f = f->next) { - if ((f->lifetime == FROMGODGIFT) && (f->obfrom == god->race->id)) { - poss[nposs] = f; - isflag[nposs] = B_TRUE; - nposs++; - } - } + foreach_bucket(b) { + for (f = player->flags->first[b] ; f ; f = f->next) { + if ((f->lifetime == FROMGODGIFT) && (f->obfrom == god->race->id)) { + poss[nposs] = f; + isflag[nposs] = B_TRUE; + nposs++; + } + } + } if (nposs) { int sel; msg("\"You are unworthy of my gifts, mortal!\""); diff --git a/io.c b/io.c index 0f55481..592aa1d 100755 --- a/io.c +++ b/io.c @@ -6239,7 +6239,7 @@ char *makedesc_ob(object_t *o, char *retbuf) { char buf3[BUFLEN]; recipe_t *rec; flag_t *f; - int obknown,i,throwrange; + int obknown,i,throwrange, b; flag_t *retflag[MAXCANDIDATES]; int nretflags; object_t *compareob = NULL; @@ -7053,12 +7053,14 @@ char *makedesc_ob(object_t *o, char *retbuf) { // skip line strncat(retbuf, "\n", HUGEBUFLEN); - for (f = o->flags->first ; f ; f = f->next) { - if ((f->id == F_HITCONFER) && (f->val[0] == F_POISONED) && (f->lifetime == FROMOBMOD)) { - sprintf(buf, "It has been coated with poison.\n"); - strncat(retbuf, buf, HUGEBUFLEN); - } - } + foreach_bucket(b) { + for (f = o->flags->first[b] ; f ; f = f->next) { + if ((f->id == F_HITCONFER) && (f->val[0] == F_POISONED) && (f->lifetime == FROMOBMOD)) { + sprintf(buf, "It has been coated with poison.\n"); + strncat(retbuf, buf, HUGEBUFLEN); + } + } + } // physical properties @@ -7211,497 +7213,501 @@ char *makedesc_ob(object_t *o, char *retbuf) { } // if known, show what it confers - for (f = o->flags->first ; f ; f = f->next) { - if ((f->id == F_HOLDCONFER) || (f->id == F_EQUIPCONFER) || (f->id == F_ACTIVATECONFER)) { - if (obknown && f->known) { - objecttype_t *ot; - if (f->id == F_HOLDCONFER) strcpy(buf, "When held, it"); - else if (f->id == F_ACTIVATECONFER) strcpy(buf, "When activated, it"); - else if (f->id == F_HITCONFER) strcpy(buf, "When hit by it, it"); - else strcpy(buf, "When equipped, it"); + foreach_bucket(b) { + for (f = o->flags->first[b] ; f ; f = f->next) { + if ((f->id == F_HOLDCONFER) || (f->id == F_EQUIPCONFER) || (f->id == F_ACTIVATECONFER)) { + if (obknown && f->known) { + objecttype_t *ot; + if (f->id == F_HOLDCONFER) strcpy(buf, "When held, it"); + else if (f->id == F_ACTIVATECONFER) strcpy(buf, "When activated, it"); + else if (f->id == F_HITCONFER) strcpy(buf, "When hit by it, it"); + else strcpy(buf, "When equipped, it"); - // conferred intrinsics - switch (f->val[0]) { - int amt,amt2; - case F_ARMOURPENALTY: - amt = adjustarmourpenalty(player, f->val[1]); - amt2 = adjustarmourpenalty(player, f->val[2]); - if (amt > 0) { - snprintf(buf2, BUFLEN, "^B%s lowers your accuracy by %d. (Armour skill penalty)^n\n", buf, getaccuracymodnum(amt)); - strncat(retbuf, buf2, HUGEBUFLEN); - } - if (amt2 > 0) { - snprintf(buf2, BUFLEN, "^B%s lowers your evasion by %d. (Armour skill penalty)^n\n", buf, amt2); - strncat(retbuf, buf2, HUGEBUFLEN); - } - break; - case F_SHIELDPENALTY: - amt = adjustshieldpenalty(player, f->val[1]); - amt2 = adjustshieldpenalty(player, f->val[2]); - if (amt > 0) { - snprintf(buf2, BUFLEN, "^B%s lowers your attack accuracy by %d. (Shields skill too low)^n\n", buf, getaccuracymodnum(amt)); - strncat(retbuf, buf2, HUGEBUFLEN); - } - if (amt2 > 0) { - snprintf(buf2, BUFLEN, "^B%s lowers your evasion by %d. (Shields skill penalty)^n\n", buf, amt2); - strncat(retbuf, buf2, HUGEBUFLEN); - } - break; - case F_ANONYMOUS: - snprintf(buf2, BUFLEN, "%s obscures your identity.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_ARBOOST: - snprintf(buf2, BUFLEN, "%s %s your Armour Rating.\n", buf, (f->val[0] >= 0) ? "increases" : "decreases"); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_ATTRMOD: - snprintf(buf2, BUFLEN, "%s %s your %s.\n", buf, (f->val[2] > 0) ? "increases" : "decreases", getattrname(f->val[1])); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_ATTRSET: - snprintf(buf2, BUFLEN, "%s modifies your %s.\n", buf, getattrname(f->val[1])); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_AWARENESS: - snprintf(buf2, BUFLEN, "%s grants you heightened awareness.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_BLIND: - snprintf(buf2, BUFLEN, "%s prevents you from seeing anything.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_BREATHWATER: - snprintf(buf2, BUFLEN, "%s allows you to breath normally while underwater.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_CONTROL: - snprintf(buf2, BUFLEN, "%s lets you control teleportation and polymorphic effects.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_CONSUMESOULS: - snprintf(buf2, BUFLEN, "%s allows you to consume the souls of nearby dead.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_DEAF: - snprintf(buf2, BUFLEN, "%s prevents you from hearing anything.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_DETECTLIFE: - snprintf(buf2, BUFLEN, "%s lets you detect nearby lifeforms.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_DETECTOBS: - snprintf(buf2, BUFLEN, "%s lets you detect nearby objects.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_DETECTMAGIC: - snprintf(buf2, BUFLEN, "%s will detect magical enchantments on objects.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_DETECTMETAL: - snprintf(buf2, BUFLEN, "%s will detect nearby metal.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_DODGES: - snprintf(buf2, BUFLEN, "%s lets you use remaining stamina to dodge fatal attacks.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_ENHANCESEARCH: - snprintf(buf2, BUFLEN, "%s enhances your searching ability.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_ENHANCESMELL: - snprintf(buf2, BUFLEN, "%s enhances your sense of smell.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_DISEASEIMMUNE: - snprintf(buf2, BUFLEN, "%s makes you immune to disease.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_DTIMMUNE: - snprintf(buf2, BUFLEN, "%s makes you immune to %s.\n", buf, getdamnamenoun(f->val[1])); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_DTRESIST: - snprintf(buf2, BUFLEN, "%s makes you resistant to %s.\n", buf, getdamnamenoun(f->val[1])); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_DTVULN: - snprintf(buf2, BUFLEN, "%s renders you vulnerable to %s.\n", buf, getdamnamenoun(f->val[1])); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_DRUNK: - snprintf(buf2, BUFLEN, "%s makes you tipsy.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_EXTRAINFO: - snprintf(buf2, BUFLEN, "%s provides enhanced knowledge to you.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_EXTRADAM: - snprintf(buf2, BUFLEN, "%s will cause you to deal additional %s damage on each attack.\n", buf, - getdamname(f->val[0])); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_WOUNDING: - snprintf(buf2, BUFLEN, "%s will grant +%d extra damage on all attacks.\n", buf, f->val[0]); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_EXTRALUCK: - snprintf(buf2, BUFLEN, "%s will give you a bonus to all skill checks.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_EXTRAMP: - snprintf(buf2, BUFLEN, "%s will increase your mana pool by %d%%.\n", buf, f->val[0]); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_FEARLESS: - snprintf(buf2, BUFLEN, "%s will reder you fearless.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_FASTACT: - snprintf(buf2, BUFLEN, "%s will speed up your actions.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_FASTMETAB: - snprintf(buf2, BUFLEN, "%s will increase your metabolic rate.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_FASTMOVE: - snprintf(buf2, BUFLEN, "%s will speed up your movement.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_FLYING: - snprintf(buf2, BUFLEN, "%s will allow you to fly.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_FREEZINGTOUCH: - snprintf(buf2, BUFLEN, "%s will cause objects you touch to turn to ice.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_FROZEN: - snprintf(buf2, BUFLEN, "%s turns you to ice.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_GRAVBOOSTED: - snprintf(buf2, BUFLEN, "%s increases gravity around you.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_GRAVLESSENED: - snprintf(buf2, BUFLEN, "%s decreases gravity around you.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_HOTFEET: - snprintf(buf2, BUFLEN, "%s causes your feet to constantly burn.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_INVISIBLE: - snprintf(buf2, BUFLEN, "%s renders you invisible to normal sight.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_INVULNERABLE: - snprintf(buf2, BUFLEN, "%s protects you from all physical harm.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_CANWILL: - ot = findot(f->val[1]); - if (ot) { - char sname[BUFLEN]; - strcpy(sname, ot->name); - capitalise(sname); - snprintf(buf2, BUFLEN, "%s allows you to %s '%s' at will.\n", buf, - (ot->obclass->id == OC_SPELL) ? "cast" : "use the ability", - sname); - strncat(retbuf, buf2, HUGEBUFLEN); - } - break; - case F_CAFFEINATED: - snprintf(buf2, BUFLEN, "%s acts as a stimulant.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_CANCAST: - ot = findot(f->val[1]); - if (ot) { - char sname[BUFLEN]; - strcpy(sname, ot->name); - capitalise(sname); - snprintf(buf2, BUFLEN, "%s allows you to cast '%s'.\n", buf, sname); - strncat(retbuf, buf2, HUGEBUFLEN); - } - break; - case F_DAYBOOST: - if (f->val[0] > 0) { - snprintf(buf2, BUFLEN, "%s grants a +%d accuracy bonus during daytime.\n", buf,getaccuracymodnum(f->val[0])); - } else { - snprintf(buf2, BUFLEN, "%s imposes a -%d accuracy penalty during daytime.\n", buf, getaccuracymodnum(abs(f->val[0]))); - } - break; - case F_DETECTAURAS: - snprintf(buf2, BUFLEN, "%s allows you to detect blessings or curses.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_HOLYAURA: - snprintf(buf2, BUFLEN, "%s surrounds you with a holy aura.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_LEARNBOOST: - snprintf(buf2, BUFLEN, "%s grants a bonus to earned experience points.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_LEVITATING: - snprintf(buf2, BUFLEN, "%s causes you to levitate.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_MAGICBOOST: - snprintf(buf2, BUFLEN, "%s boosts the power of your spells by %d.\n", buf, f->val[1]); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_MINDSHIELD: - snprintf(buf2, BUFLEN, "%s protects you from psionic attacks.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_MISCASTCHANCE: - snprintf(buf2, BUFLEN, "%s causes your spells to become unreliable.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_MEDITATES: - snprintf(buf2, BUFLEN, "%s allows you to retain awareness while resting.", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_MAGSHIELD: - snprintf(buf2, BUFLEN, "%s surrounds you with a magnetic shield.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_MUTABLE: - snprintf(buf2, BUFLEN, "%s allows your body to mutate.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_NAUSEATED: - snprintf(buf2, BUFLEN, "%s causes you to feel nauseated.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_NIGHTBOOST: - if (f->val[0] > 0) { - snprintf(buf2, BUFLEN, "%s grants a +%d accuracy bonus at night.\n", buf,getaccuracymodnum(f->val[0])); - } else { - snprintf(buf2, BUFLEN, "%s imposes a -%d accuracy penalty at night.\n", buf, getaccuracymodnum(abs(f->val[0]))); - } - break; - case F_NONCORPOREAL: - snprintf(buf2, BUFLEN, "%s makes you non-corporeal.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_PAIN: - snprintf(buf2, BUFLEN, "%s causes you intense pain.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_PARALYZED: - snprintf(buf2, BUFLEN, "%s paralyzes you.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_PHOTOMEM: - snprintf(buf2, BUFLEN, "%s prevents you from forgetting your surroundings.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_POLYIMMUNE: - snprintf(buf2, BUFLEN, "%s prevents you from being polymorphed.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_SIXTHSENSE: - snprintf(buf2, BUFLEN, "%s warns you about nearby enemies.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_STABILITY: - snprintf(buf2, BUFLEN, "%s prevents you from slipping over.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_STAMBOOST: - snprintf(buf2, BUFLEN, "%s boosts your stamina by %d.\n", buf, f->val[1]); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_STENCH: - snprintf(buf2, BUFLEN, "%s makes you smell bad.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_PRODUCESLIGHT: - snprintf(buf2, BUFLEN, "%s produces light out to %d metre%s.\n", buf, - f->val[1], (f->val[1] == 1) ? "" : "s"); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_RETALIATE: - loctext = strdup(f->text); - p = readuntil(dicetext, loctext, '^'); - readuntil(retalname, p, '^'); - snprintf(buf2, BUFLEN, "%s protects you with %s.\n", buf, retalname); - strncat(retbuf, buf2, HUGEBUFLEN); - free(loctext); - break; - case F_PROTALIGN: - snprintf(buf2, BUFLEN, "%s repels attacks from %s aligned creatures.\n", buf, - getalignmentname(f->val[1])); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_RAGE: - snprintf(buf2, BUFLEN, "%s makes you enraged.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_REFLECTION: - snprintf(buf2, BUFLEN, "%s reflects all projectiles back to their source.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_REGENERATES: - if (f->val[1] == 1) { - strcpy(buf3, ""); - } else if (f->val[1] == 2) { - strcpy(buf3, "quickly"); - } else if (f->val[1] == 3) { - strcpy(buf3, "very quickly"); - } else { // >= 4 - strcpy(buf3, "extremely quickly"); - } - snprintf(buf2, BUFLEN, "%s allows you to regenerate health%s.\n", buf,buf3); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_RESISTMAG: - snprintf(buf2, BUFLEN, "%s grants you %s immunity to magic.\n", buf, - (f->val[0] >= 10) ? "strong" : "minor"); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_RISEASGHOST: - snprintf(buf2, BUFLEN, "%s cause you to rise as a ghost after death.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_SEEINVIS: - snprintf(buf2, BUFLEN, "%s allows you to see invisible things.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_SEEINDARK: - snprintf(buf2, BUFLEN, "%s allows you to see in the dark.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_SHADOWED: - snprintf(buf2, BUFLEN, "%s prevents distant creatures from seeing you.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_SILENCED: - snprintf(buf2, BUFLEN, "%s prevents you from making sounds.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_SILENTMOVE: - snprintf(buf2, BUFLEN, "%s allows you to move silently.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_SLOWACT: - snprintf(buf2, BUFLEN, "%s will slow down your actions.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_SLOWMETAB: - snprintf(buf2, BUFLEN, "%s will decrease your metabolic rate.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_SLOWMOVE: - snprintf(buf2, BUFLEN, "%s will slow down your movement.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_SPIDERCLIMB: - snprintf(buf2, BUFLEN, "%s allows you to adhere to walls.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_TREMORSENSE: - snprintf(buf2, BUFLEN, "%s allows you to 'see' by sensing vibrations around you.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_TRUESTRIKE: - snprintf(buf2, BUFLEN, "%s makes your attacks automatically hit.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_WINDSHIELD: - snprintf(buf2, BUFLEN, "%s will surround you with a cyclonic shield.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_VISRANGEMOD: - snprintf(buf2, BUFLEN, "%s %s your vision range by %d metre%s.\n", buf, (f->val[1] > 0) ? "increases" : "decreases", - abs(f->val[1]), (abs(f->val[1]) == 1) ? "" : "s" ); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - case F_XRAYVIS: - snprintf(buf2, BUFLEN, "%s allows you to see through walls.\n", buf); - strncat(retbuf, buf2, HUGEBUFLEN); - break; - } - } - } - } + // conferred intrinsics + switch (f->val[0]) { + int amt,amt2; + case F_ARMOURPENALTY: + amt = adjustarmourpenalty(player, f->val[1]); + amt2 = adjustarmourpenalty(player, f->val[2]); + if (amt > 0) { + snprintf(buf2, BUFLEN, "^B%s lowers your accuracy by %d. (Armour skill penalty)^n\n", buf, getaccuracymodnum(amt)); + strncat(retbuf, buf2, HUGEBUFLEN); + } + if (amt2 > 0) { + snprintf(buf2, BUFLEN, "^B%s lowers your evasion by %d. (Armour skill penalty)^n\n", buf, amt2); + strncat(retbuf, buf2, HUGEBUFLEN); + } + break; + case F_SHIELDPENALTY: + amt = adjustshieldpenalty(player, f->val[1]); + amt2 = adjustshieldpenalty(player, f->val[2]); + if (amt > 0) { + snprintf(buf2, BUFLEN, "^B%s lowers your attack accuracy by %d. (Shields skill too low)^n\n", buf, getaccuracymodnum(amt)); + strncat(retbuf, buf2, HUGEBUFLEN); + } + if (amt2 > 0) { + snprintf(buf2, BUFLEN, "^B%s lowers your evasion by %d. (Shields skill penalty)^n\n", buf, amt2); + strncat(retbuf, buf2, HUGEBUFLEN); + } + break; + case F_ANONYMOUS: + snprintf(buf2, BUFLEN, "%s obscures your identity.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_ARBOOST: + snprintf(buf2, BUFLEN, "%s %s your Armour Rating.\n", buf, (f->val[0] >= 0) ? "increases" : "decreases"); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_ATTRMOD: + snprintf(buf2, BUFLEN, "%s %s your %s.\n", buf, (f->val[2] > 0) ? "increases" : "decreases", getattrname(f->val[1])); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_ATTRSET: + snprintf(buf2, BUFLEN, "%s modifies your %s.\n", buf, getattrname(f->val[1])); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_AWARENESS: + snprintf(buf2, BUFLEN, "%s grants you heightened awareness.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_BLIND: + snprintf(buf2, BUFLEN, "%s prevents you from seeing anything.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_BREATHWATER: + snprintf(buf2, BUFLEN, "%s allows you to breath normally while underwater.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_CONTROL: + snprintf(buf2, BUFLEN, "%s lets you control teleportation and polymorphic effects.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_CONSUMESOULS: + snprintf(buf2, BUFLEN, "%s allows you to consume the souls of nearby dead.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_DEAF: + snprintf(buf2, BUFLEN, "%s prevents you from hearing anything.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_DETECTLIFE: + snprintf(buf2, BUFLEN, "%s lets you detect nearby lifeforms.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_DETECTOBS: + snprintf(buf2, BUFLEN, "%s lets you detect nearby objects.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_DETECTMAGIC: + snprintf(buf2, BUFLEN, "%s will detect magical enchantments on objects.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_DETECTMETAL: + snprintf(buf2, BUFLEN, "%s will detect nearby metal.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_DODGES: + snprintf(buf2, BUFLEN, "%s lets you use remaining stamina to dodge fatal attacks.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_ENHANCESEARCH: + snprintf(buf2, BUFLEN, "%s enhances your searching ability.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_ENHANCESMELL: + snprintf(buf2, BUFLEN, "%s enhances your sense of smell.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_DISEASEIMMUNE: + snprintf(buf2, BUFLEN, "%s makes you immune to disease.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_DTIMMUNE: + snprintf(buf2, BUFLEN, "%s makes you immune to %s.\n", buf, getdamnamenoun(f->val[1])); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_DTRESIST: + snprintf(buf2, BUFLEN, "%s makes you resistant to %s.\n", buf, getdamnamenoun(f->val[1])); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_DTVULN: + snprintf(buf2, BUFLEN, "%s renders you vulnerable to %s.\n", buf, getdamnamenoun(f->val[1])); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_DRUNK: + snprintf(buf2, BUFLEN, "%s makes you tipsy.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_EXTRAINFO: + snprintf(buf2, BUFLEN, "%s provides enhanced knowledge to you.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_EXTRADAM: + snprintf(buf2, BUFLEN, "%s will cause you to deal additional %s damage on each attack.\n", buf, + getdamname(f->val[0])); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_WOUNDING: + snprintf(buf2, BUFLEN, "%s will grant +%d extra damage on all attacks.\n", buf, f->val[0]); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_EXTRALUCK: + snprintf(buf2, BUFLEN, "%s will give you a bonus to all skill checks.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_EXTRAMP: + snprintf(buf2, BUFLEN, "%s will increase your mana pool by %d%%.\n", buf, f->val[0]); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_FEARLESS: + snprintf(buf2, BUFLEN, "%s will reder you fearless.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_FASTACT: + snprintf(buf2, BUFLEN, "%s will speed up your actions.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_FASTMETAB: + snprintf(buf2, BUFLEN, "%s will increase your metabolic rate.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_FASTMOVE: + snprintf(buf2, BUFLEN, "%s will speed up your movement.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_FLYING: + snprintf(buf2, BUFLEN, "%s will allow you to fly.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_FREEZINGTOUCH: + snprintf(buf2, BUFLEN, "%s will cause objects you touch to turn to ice.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_FROZEN: + snprintf(buf2, BUFLEN, "%s turns you to ice.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_GRAVBOOSTED: + snprintf(buf2, BUFLEN, "%s increases gravity around you.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_GRAVLESSENED: + snprintf(buf2, BUFLEN, "%s decreases gravity around you.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_HOTFEET: + snprintf(buf2, BUFLEN, "%s causes your feet to constantly burn.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_INVISIBLE: + snprintf(buf2, BUFLEN, "%s renders you invisible to normal sight.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_INVULNERABLE: + snprintf(buf2, BUFLEN, "%s protects you from all physical harm.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_CANWILL: + ot = findot(f->val[1]); + if (ot) { + char sname[BUFLEN]; + strcpy(sname, ot->name); + capitalise(sname); + snprintf(buf2, BUFLEN, "%s allows you to %s '%s' at will.\n", buf, + (ot->obclass->id == OC_SPELL) ? "cast" : "use the ability", + sname); + strncat(retbuf, buf2, HUGEBUFLEN); + } + break; + case F_CAFFEINATED: + snprintf(buf2, BUFLEN, "%s acts as a stimulant.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_CANCAST: + ot = findot(f->val[1]); + if (ot) { + char sname[BUFLEN]; + strcpy(sname, ot->name); + capitalise(sname); + snprintf(buf2, BUFLEN, "%s allows you to cast '%s'.\n", buf, sname); + strncat(retbuf, buf2, HUGEBUFLEN); + } + break; + case F_DAYBOOST: + if (f->val[0] > 0) { + snprintf(buf2, BUFLEN, "%s grants a +%d accuracy bonus during daytime.\n", buf,getaccuracymodnum(f->val[0])); + } else { + snprintf(buf2, BUFLEN, "%s imposes a -%d accuracy penalty during daytime.\n", buf, getaccuracymodnum(abs(f->val[0]))); + } + break; + case F_DETECTAURAS: + snprintf(buf2, BUFLEN, "%s allows you to detect blessings or curses.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_HOLYAURA: + snprintf(buf2, BUFLEN, "%s surrounds you with a holy aura.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_LEARNBOOST: + snprintf(buf2, BUFLEN, "%s grants a bonus to earned experience points.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_LEVITATING: + snprintf(buf2, BUFLEN, "%s causes you to levitate.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_MAGICBOOST: + snprintf(buf2, BUFLEN, "%s boosts the power of your spells by %d.\n", buf, f->val[1]); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_MINDSHIELD: + snprintf(buf2, BUFLEN, "%s protects you from psionic attacks.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_MISCASTCHANCE: + snprintf(buf2, BUFLEN, "%s causes your spells to become unreliable.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_MEDITATES: + snprintf(buf2, BUFLEN, "%s allows you to retain awareness while resting.", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_MAGSHIELD: + snprintf(buf2, BUFLEN, "%s surrounds you with a magnetic shield.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_MUTABLE: + snprintf(buf2, BUFLEN, "%s allows your body to mutate.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_NAUSEATED: + snprintf(buf2, BUFLEN, "%s causes you to feel nauseated.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_NIGHTBOOST: + if (f->val[0] > 0) { + snprintf(buf2, BUFLEN, "%s grants a +%d accuracy bonus at night.\n", buf,getaccuracymodnum(f->val[0])); + } else { + snprintf(buf2, BUFLEN, "%s imposes a -%d accuracy penalty at night.\n", buf, getaccuracymodnum(abs(f->val[0]))); + } + break; + case F_NONCORPOREAL: + snprintf(buf2, BUFLEN, "%s makes you non-corporeal.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_PAIN: + snprintf(buf2, BUFLEN, "%s causes you intense pain.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_PARALYZED: + snprintf(buf2, BUFLEN, "%s paralyzes you.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_PHOTOMEM: + snprintf(buf2, BUFLEN, "%s prevents you from forgetting your surroundings.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_POLYIMMUNE: + snprintf(buf2, BUFLEN, "%s prevents you from being polymorphed.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_SIXTHSENSE: + snprintf(buf2, BUFLEN, "%s warns you about nearby enemies.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_STABILITY: + snprintf(buf2, BUFLEN, "%s prevents you from slipping over.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_STAMBOOST: + snprintf(buf2, BUFLEN, "%s boosts your stamina by %d.\n", buf, f->val[1]); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_STENCH: + snprintf(buf2, BUFLEN, "%s makes you smell bad.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_PRODUCESLIGHT: + snprintf(buf2, BUFLEN, "%s produces light out to %d metre%s.\n", buf, + f->val[1], (f->val[1] == 1) ? "" : "s"); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_RETALIATE: + loctext = strdup(f->text); + p = readuntil(dicetext, loctext, '^'); + readuntil(retalname, p, '^'); + snprintf(buf2, BUFLEN, "%s protects you with %s.\n", buf, retalname); + strncat(retbuf, buf2, HUGEBUFLEN); + free(loctext); + break; + case F_PROTALIGN: + snprintf(buf2, BUFLEN, "%s repels attacks from %s aligned creatures.\n", buf, + getalignmentname(f->val[1])); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_RAGE: + snprintf(buf2, BUFLEN, "%s makes you enraged.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_REFLECTION: + snprintf(buf2, BUFLEN, "%s reflects all projectiles back to their source.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_REGENERATES: + if (f->val[1] == 1) { + strcpy(buf3, ""); + } else if (f->val[1] == 2) { + strcpy(buf3, "quickly"); + } else if (f->val[1] == 3) { + strcpy(buf3, "very quickly"); + } else { // >= 4 + strcpy(buf3, "extremely quickly"); + } + snprintf(buf2, BUFLEN, "%s allows you to regenerate health%s.\n", buf,buf3); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_RESISTMAG: + snprintf(buf2, BUFLEN, "%s grants you %s immunity to magic.\n", buf, + (f->val[0] >= 10) ? "strong" : "minor"); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_RISEASGHOST: + snprintf(buf2, BUFLEN, "%s cause you to rise as a ghost after death.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_SEEINVIS: + snprintf(buf2, BUFLEN, "%s allows you to see invisible things.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_SEEINDARK: + snprintf(buf2, BUFLEN, "%s allows you to see in the dark.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_SHADOWED: + snprintf(buf2, BUFLEN, "%s prevents distant creatures from seeing you.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_SILENCED: + snprintf(buf2, BUFLEN, "%s prevents you from making sounds.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_SILENTMOVE: + snprintf(buf2, BUFLEN, "%s allows you to move silently.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_SLOWACT: + snprintf(buf2, BUFLEN, "%s will slow down your actions.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_SLOWMETAB: + snprintf(buf2, BUFLEN, "%s will decrease your metabolic rate.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_SLOWMOVE: + snprintf(buf2, BUFLEN, "%s will slow down your movement.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_SPIDERCLIMB: + snprintf(buf2, BUFLEN, "%s allows you to adhere to walls.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_TREMORSENSE: + snprintf(buf2, BUFLEN, "%s allows you to 'see' by sensing vibrations around you.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_TRUESTRIKE: + snprintf(buf2, BUFLEN, "%s makes your attacks automatically hit.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_WINDSHIELD: + snprintf(buf2, BUFLEN, "%s will surround you with a cyclonic shield.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_VISRANGEMOD: + snprintf(buf2, BUFLEN, "%s %s your vision range by %d metre%s.\n", buf, (f->val[1] > 0) ? "increases" : "decreases", + abs(f->val[1]), (abs(f->val[1]) == 1) ? "" : "s" ); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + case F_XRAYVIS: + snprintf(buf2, BUFLEN, "%s allows you to see through walls.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; + } + } + } + } + } // requirements i = B_FALSE; - for (f = o->flags->first ; f ; f = f->next) { - if (f->id == F_ATTREQ) { - enum COLOUR col; - int pctmod; - int usable = B_TRUE; - if (!meetsattreq(player, f, o, &pctmod)) { - col = C_RED; - usable = B_FALSE; - } else { - col = C_GREY; - } - if (f->val[1] != NA) { - sprintf(buf, "^%dMinimum %s to use%s: %d", col, getattrname(f->val[0]), - strlen(f->text) ? " effectively" : "", f->val[1]); - } - if (f->val[2] != NA) { - char addon[BUFLEN]; - if (f->val[1] == NA) { - sprintf(addon, "It gains a bonus at at %d %s.\n", f->val[2], getattrname(f->val[0])); - } else { - sprintf(addon, " (bonus at %d)^n.\n", f->val[2]); - } - strcat(buf,addon); - } else { - strcat(buf, "\n"); - } - strncat(retbuf, buf, HUGEBUFLEN); + foreach_bucket(b) { + for (f = o->flags->first[b] ; f ; f = f->next) { + if (f->id == F_ATTREQ) { + enum COLOUR col; + int pctmod; + int usable = B_TRUE; + if (!meetsattreq(player, f, o, &pctmod)) { + col = C_RED; + usable = B_FALSE; + } else { + col = C_GREY; + } + if (f->val[1] != NA) { + sprintf(buf, "^%dMinimum %s to use%s: %d", col, getattrname(f->val[0]), + strlen(f->text) ? " effectively" : "", f->val[1]); + } + if (f->val[2] != NA) { + char addon[BUFLEN]; + if (f->val[1] == NA) { + sprintf(addon, "It gains a bonus at at %d %s.\n", f->val[2], getattrname(f->val[0])); + } else { + sprintf(addon, " (bonus at %d)^n.\n", f->val[2]); + } + strcat(buf,addon); + } else { + strcat(buf, "\n"); + } + strncat(retbuf, buf, HUGEBUFLEN); - if (usable && isweapon(o)) { - if (pctmod > 0) { - char howmuch[BUFLEN]; - if ((f->val[0] == A_AGI) && (pctmod < 5)) { - sprintf(howmuch, "fractionally"); - } else { - sprintf(howmuch, "by %d%s", - (f->val[0] == A_AGI) ? getaccuracynum(100 + pctmod) : pctmod, - (f->val[0] == A_AGI) ? "" : "%"); - } - sprintf(buf, "^%dYour high %s will increase your %s with this weapon %s.^n\n", - C_GREEN, - getattrname(f->val[0]), - (f->val[0] == A_AGI) ? "accuracy" : "damage", - howmuch); + if (usable && isweapon(o)) { + if (pctmod > 0) { + char howmuch[BUFLEN]; + if ((f->val[0] == A_AGI) && (pctmod < 5)) { + sprintf(howmuch, "fractionally"); + } else { + sprintf(howmuch, "by %d%s", + (f->val[0] == A_AGI) ? getaccuracynum(100 + pctmod) : pctmod, + (f->val[0] == A_AGI) ? "" : "%"); + } + sprintf(buf, "^%dYour high %s will increase your %s with this weapon %s.^n\n", + C_GREEN, + getattrname(f->val[0]), + (f->val[0] == A_AGI) ? "accuracy" : "damage", + howmuch); - strncat(retbuf, buf, HUGEBUFLEN); - } else if (pctmod < 0) { - char howmuch[BUFLEN]; - if ((f->val[0] == A_AGI) && (pctmod > -5)) { - sprintf(howmuch, "fractionally"); - } else { - sprintf(howmuch, "by %d%s", - (f->val[0] == A_AGI) ? getaccuracynum(100 + abs(pctmod)) : abs(pctmod), - (f->val[0] == A_AGI) ? "" : "%"); - } - sprintf(buf, "^%dYour low %s will decrease your %s with this weapon %s.^n\n", - C_DARKYELLOW, - getattrname(f->val[0]), - (f->val[0] == A_AGI) ? "accuracy" : "damage", - howmuch); - strncat(retbuf, buf, HUGEBUFLEN); - } - } - i = B_TRUE; - } - } + strncat(retbuf, buf, HUGEBUFLEN); + } else if (pctmod < 0) { + char howmuch[BUFLEN]; + if ((f->val[0] == A_AGI) && (pctmod > -5)) { + sprintf(howmuch, "fractionally"); + } else { + sprintf(howmuch, "by %d%s", + (f->val[0] == A_AGI) ? getaccuracynum(100 + abs(pctmod)) : abs(pctmod), + (f->val[0] == A_AGI) ? "" : "%"); + } + sprintf(buf, "^%dYour low %s will decrease your %s with this weapon %s.^n\n", + C_DARKYELLOW, + getattrname(f->val[0]), + (f->val[0] == A_AGI) ? "accuracy" : "damage", + howmuch); + strncat(retbuf, buf, HUGEBUFLEN); + } + } + i = B_TRUE; + } + } + } // blank line strncat(retbuf, "\n", HUGEBUFLEN); @@ -7816,7 +7822,7 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra, int forplayersel race_t *r; char buf[HUGEBUFLEN]; flag_t *retflag[MAXCANDIDATES],*f; - int nretflags,i; + int nretflags,i,b; flagpile_t *doneflags; enum SKILLLEVEL lorelev; @@ -7982,148 +7988,150 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra, int forplayersel } // auto bonuses from flags - for (f = r->flags->first ; f ; f = f->next) { - char *p; - strcpy(buf, ""); - switch (f->id) { - case F_AUTOCREATEOB: - if (lorelev >= PR_NOVICE) { - p = strdup(f->text); - makeplural(&p); - sprintf(buf, "Automatically creates %s around itself.", p); - free(p); - } - break; - case F_AUTOTANGLE: - if (lorelev >= PR_BEGINNER) { - sprintf(buf, "%d%% chance to entangle enemies", f->val[0]); - } - break; - case F_ABSORBKINETIC: if (lorelev >= PR_BEGINNER) strcpy(buf, "Grows stronger through kinetic damage."); break; - case F_AQUATIC: if (lorelev >= PR_NOVICE) strcpy(buf, "Moves normally through water"); break; - case F_AWARENESS: if (lorelev >= PR_BEGINNER) strcpy(buf, "Can see in all directions."); break; - case F_CANEATRAW: if (lorelev >= PR_ADEPT) strcpy(buf, "Can safely digest raw meat."); break; - case F_CONSUMESOULS: - if (lorelev >= PR_BEGINNER) { - strcpy(buf, "Consumes the souls of nearby dead."); ; - } - break; - case F_DAYBOOST: - if (lorelev >= PR_ADEPT) { - if (f->val[0] > 0) { - sprintf(buf, "+%d accuracy during the day.", getaccuracymodnum(f->val[0])); - } - } - break; - case F_DODGES: if (lorelev >= PR_ADEPT) strcpy(buf, "Can dodge fatal attacks into adjacent locations."); break; - case F_DTIMMUNE: - if ((lorelev >= PR_BEGINNER) && !hasflag(doneflags, F_DTIMMUNE)) { - if (f->val[0] == DT_ALL) { - sprintf(buf, "Immune to %s.", getdamname(DT_ALL)); - } else { - char buf2[BUFLEN]; - int first = B_TRUE,n; - strcpy(buf, ""); - for (n = 0; n < MAXDAMTYPE; n++) { - if (basedamagetype(n) != n) continue; - if (isimmuneto(r->flags, n, B_FALSE)) { - if (first) { - snprintf(buf2, BUFLEN, "Immune to: %s", getdamname(n)); - first = B_FALSE; - } else { - snprintf(buf2, BUFLEN, ", %s", getdamname(n)); - } - strcat(buf, buf2); - } - } - } - addflag(doneflags, F_DTIMMUNE, B_TRUE, NA, NA, NULL); - } - break; - case F_DTRESIST: - if ((lorelev >= PR_BEGINNER) && !hasflag(doneflags, F_DTRESIST)) { - if (f->val[0] == DT_ALL) { - sprintf(buf, "Resistant to %s.", getdamname(DT_ALL)); - } else { - char buf2[BUFLEN]; - int first = B_TRUE,n; - strcpy(buf, ""); - for (n = 0; n < MAXDAMTYPE; n++) { - if (basedamagetype(n) != n) continue; - if (isresistantto(r->flags, n, B_FALSE)) { - if (first) { - snprintf(buf2, BUFLEN, "Resistant to: %s", getdamname(n)); - first = B_FALSE; - } else { - snprintf(buf2, BUFLEN, ", %s", getdamname(n)); - } - strcat(buf, buf2); - } - } - } - addflag(doneflags, F_DTRESIST, B_TRUE, NA, NA, NULL); - } - break; - case F_ENHANCESMELL: if (lorelev >= PR_BEGINNER) sprintf(buf, "Enhanced sense of smell (range %d)", f->val[0]); break; - case F_FEARLESS: if (lorelev >= PR_BEGINNER) sprintf(buf, "Fearless"); break; - case F_FLYING: if (lorelev >= PR_NOVICE) sprintf(buf, "Can fly at will"); break; - case F_HEAVYBLOW: if (lorelev >= PR_ADEPT) sprintf(buf, "Attacks will knock enemies backwards"); break; - case F_HITCONFER: - if (lorelev >= PR_BEGINNER) { - if (f->val[0] == F_POISONED) { - flag_t *f2; - f2 = hasflag(r->flags, F_HITCONFERVALS); - if (f2) { - poisontype_t *pt; - pt = findpoisontype(f2->val[0]); - sprintf(buf, "Attacks inflict %s.", pt->name); - } - } - } - break; - case F_HUMANOID: if (!forplayersel) sprintf(buf, "Can use weapons and armour."); break; - case F_LEARNBOOST: - if ((lorelev >= PR_BEGINNER) && (f->val[0] >= 0)) { - sprintf(buf, "Gains XP %d%% faster.", f->val[0]); - } - break; - case F_LEVITATING: if (lorelev >= PR_NOVICE) sprintf(buf, "Can levitate at will"); break; - case F_MEDITATES: if (lorelev >= PR_ADEPT) sprintf(buf, "Meditates to retain awareness while sleeping."); break; - case F_MPMOD: if (f->val[0] > 0) sprintf(buf, "+%d Mana", f->val[0]); break; - case F_NIGHTBOOST: - if (lorelev >= PR_ADEPT) { - if (f->val[0] > 0) { - sprintf(buf, "+%d accuracy at night.", getaccuracymodnum(f->val[0])); - } - } - break; - case F_NONCORPOREAL: if (lorelev >= PR_NOVICE) sprintf(buf, "Only affected by blessed, magic or silver weapons"); break; - case F_NOSLEEP: if (lorelev >= PR_BEGINNER) sprintf(buf, "Does not sleep"); break; - case F_PHALANX: if (lorelev >= PR_ADEPT) sprintf(buf, "Gains extra defence when in a pack."); break; - case F_PHOTOMEM: sprintf(buf, "Photographic memory"); break; - case F_POLYIMMUNE: if (lorelev >= PR_BEGINNER) sprintf(buf, "Immune to polymophic effects."); break; - case F_REGENERATES: if (lorelev >= PR_BEGINNER) sprintf(buf, "Automatically regenerates health."); break; - case F_RESISTMAG: if (lorelev >= PR_BEGINNER) sprintf(buf, "Magic-resistant"); break; - case F_SEEINDARK: if (lorelev >= PR_BEGINNER) sprintf(buf, "Darkvision (range %d)", f->val[0]); break; - case F_SEEINVIS: if (lorelev >= PR_ADEPT) sprintf(buf, "Can see invisible things"); break; - case F_SHADOWED: if (lorelev >= PR_BEGINNER) sprintf(buf, "Cannot be seen from a distance."); break; - case F_SILENTMOVE: if (lorelev >= PR_BEGINNER) sprintf(buf, "Moves silently"); break; - case F_SPIDERCLIMB: if (lorelev >= PR_NOVICE) sprintf(buf, "Adheres to walls"); break; - case F_STABILITY: if (lorelev >= PR_BEGINNER) sprintf(buf, "Will not fall on slippery ground."); break; - case F_STENCH: sprintf(buf, "Emits a foul odour which affects others"); break; - case F_SWIMEVASION: if (lorelev >= PR_BEGINNER) sprintf(buf, "%d%% evasion while swimming", f->val[0]); break; - case F_TREMORSENSE: if (lorelev >= PR_BEGINNER) sprintf(buf, "Can sense vibrations (range %d)", f->val[0]); break; - case F_VISRANGEMOD: if (lorelev >= PR_BEGINNER) if (f->val[0] > 0) sprintf(buf, "Enhanced vision range (+%d)", f->val[0]); break; - default: - break; - } - if (strlen(buf)) { - strncat(retbuf, "@- ", HUGEBUFLEN); - strcat(buf, "\n"); - strncat(retbuf, buf, HUGEBUFLEN); - curidx++; - } - } + foreach_bucket(b) { + for (f = r->flags->first[b] ; f ; f = f->next) { + char *p; + strcpy(buf, ""); + switch (f->id) { + case F_AUTOCREATEOB: + if (lorelev >= PR_NOVICE) { + p = strdup(f->text); + makeplural(&p); + sprintf(buf, "Automatically creates %s around itself.", p); + free(p); + } + break; + case F_AUTOTANGLE: + if (lorelev >= PR_BEGINNER) { + sprintf(buf, "%d%% chance to entangle enemies", f->val[0]); + } + break; + case F_ABSORBKINETIC: if (lorelev >= PR_BEGINNER) strcpy(buf, "Grows stronger through kinetic damage."); break; + case F_AQUATIC: if (lorelev >= PR_NOVICE) strcpy(buf, "Moves normally through water"); break; + case F_AWARENESS: if (lorelev >= PR_BEGINNER) strcpy(buf, "Can see in all directions."); break; + case F_CANEATRAW: if (lorelev >= PR_ADEPT) strcpy(buf, "Can safely digest raw meat."); break; + case F_CONSUMESOULS: + if (lorelev >= PR_BEGINNER) { + strcpy(buf, "Consumes the souls of nearby dead."); ; + } + break; + case F_DAYBOOST: + if (lorelev >= PR_ADEPT) { + if (f->val[0] > 0) { + sprintf(buf, "+%d accuracy during the day.", getaccuracymodnum(f->val[0])); + } + } + break; + case F_DODGES: if (lorelev >= PR_ADEPT) strcpy(buf, "Can dodge fatal attacks into adjacent locations."); break; + case F_DTIMMUNE: + if ((lorelev >= PR_BEGINNER) && !hasflag(doneflags, F_DTIMMUNE)) { + if (f->val[0] == DT_ALL) { + sprintf(buf, "Immune to %s.", getdamname(DT_ALL)); + } else { + char buf2[BUFLEN]; + int first = B_TRUE,n; + strcpy(buf, ""); + for (n = 0; n < MAXDAMTYPE; n++) { + if (basedamagetype(n) != n) continue; + if (isimmuneto(r->flags, n, B_FALSE)) { + if (first) { + snprintf(buf2, BUFLEN, "Immune to: %s", getdamname(n)); + first = B_FALSE; + } else { + snprintf(buf2, BUFLEN, ", %s", getdamname(n)); + } + strcat(buf, buf2); + } + } + } + addflag(doneflags, F_DTIMMUNE, B_TRUE, NA, NA, NULL); + } + break; + case F_DTRESIST: + if ((lorelev >= PR_BEGINNER) && !hasflag(doneflags, F_DTRESIST)) { + if (f->val[0] == DT_ALL) { + sprintf(buf, "Resistant to %s.", getdamname(DT_ALL)); + } else { + char buf2[BUFLEN]; + int first = B_TRUE,n; + strcpy(buf, ""); + for (n = 0; n < MAXDAMTYPE; n++) { + if (basedamagetype(n) != n) continue; + if (isresistantto(r->flags, n, B_FALSE)) { + if (first) { + snprintf(buf2, BUFLEN, "Resistant to: %s", getdamname(n)); + first = B_FALSE; + } else { + snprintf(buf2, BUFLEN, ", %s", getdamname(n)); + } + strcat(buf, buf2); + } + } + } + addflag(doneflags, F_DTRESIST, B_TRUE, NA, NA, NULL); + } + break; + case F_ENHANCESMELL: if (lorelev >= PR_BEGINNER) sprintf(buf, "Enhanced sense of smell (range %d)", f->val[0]); break; + case F_FEARLESS: if (lorelev >= PR_BEGINNER) sprintf(buf, "Fearless"); break; + case F_FLYING: if (lorelev >= PR_NOVICE) sprintf(buf, "Can fly at will"); break; + case F_HEAVYBLOW: if (lorelev >= PR_ADEPT) sprintf(buf, "Attacks will knock enemies backwards"); break; + case F_HITCONFER: + if (lorelev >= PR_BEGINNER) { + if (f->val[0] == F_POISONED) { + flag_t *f2; + f2 = hasflag(r->flags, F_HITCONFERVALS); + if (f2) { + poisontype_t *pt; + pt = findpoisontype(f2->val[0]); + sprintf(buf, "Attacks inflict %s.", pt->name); + } + } + } + break; + case F_HUMANOID: if (!forplayersel) sprintf(buf, "Can use weapons and armour."); break; + case F_LEARNBOOST: + if ((lorelev >= PR_BEGINNER) && (f->val[0] >= 0)) { + sprintf(buf, "Gains XP %d%% faster.", f->val[0]); + } + break; + case F_LEVITATING: if (lorelev >= PR_NOVICE) sprintf(buf, "Can levitate at will"); break; + case F_MEDITATES: if (lorelev >= PR_ADEPT) sprintf(buf, "Meditates to retain awareness while sleeping."); break; + case F_MPMOD: if (f->val[0] > 0) sprintf(buf, "+%d Mana", f->val[0]); break; + case F_NIGHTBOOST: + if (lorelev >= PR_ADEPT) { + if (f->val[0] > 0) { + sprintf(buf, "+%d accuracy at night.", getaccuracymodnum(f->val[0])); + } + } + break; + case F_NONCORPOREAL: if (lorelev >= PR_NOVICE) sprintf(buf, "Only affected by blessed, magic or silver weapons"); break; + case F_NOSLEEP: if (lorelev >= PR_BEGINNER) sprintf(buf, "Does not sleep"); break; + case F_PHALANX: if (lorelev >= PR_ADEPT) sprintf(buf, "Gains extra defence when in a pack."); break; + case F_PHOTOMEM: sprintf(buf, "Photographic memory"); break; + case F_POLYIMMUNE: if (lorelev >= PR_BEGINNER) sprintf(buf, "Immune to polymophic effects."); break; + case F_REGENERATES: if (lorelev >= PR_BEGINNER) sprintf(buf, "Automatically regenerates health."); break; + case F_RESISTMAG: if (lorelev >= PR_BEGINNER) sprintf(buf, "Magic-resistant"); break; + case F_SEEINDARK: if (lorelev >= PR_BEGINNER) sprintf(buf, "Darkvision (range %d)", f->val[0]); break; + case F_SEEINVIS: if (lorelev >= PR_ADEPT) sprintf(buf, "Can see invisible things"); break; + case F_SHADOWED: if (lorelev >= PR_BEGINNER) sprintf(buf, "Cannot be seen from a distance."); break; + case F_SILENTMOVE: if (lorelev >= PR_BEGINNER) sprintf(buf, "Moves silently"); break; + case F_SPIDERCLIMB: if (lorelev >= PR_NOVICE) sprintf(buf, "Adheres to walls"); break; + case F_STABILITY: if (lorelev >= PR_BEGINNER) sprintf(buf, "Will not fall on slippery ground."); break; + case F_STENCH: sprintf(buf, "Emits a foul odour which affects others"); break; + case F_SWIMEVASION: if (lorelev >= PR_BEGINNER) sprintf(buf, "%d%% evasion while swimming", f->val[0]); break; + case F_TREMORSENSE: if (lorelev >= PR_BEGINNER) sprintf(buf, "Can sense vibrations (range %d)", f->val[0]); break; + case F_VISRANGEMOD: if (lorelev >= PR_BEGINNER) if (f->val[0] > 0) sprintf(buf, "Enhanced vision range (+%d)", f->val[0]); break; + default: + break; + } + if (strlen(buf)) { + strncat(retbuf, "@- ", HUGEBUFLEN); + strcat(buf, "\n"); + strncat(retbuf, buf, HUGEBUFLEN); + curidx++; + } + } + } if (curidx == 0) { strncat(retbuf, "^n@None known.\n", HUGEBUFLEN); @@ -8157,104 +8165,106 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra, int forplayersel } // auto penalties from flags - for (f = r->flags->first ; f ; f = f->next) { - material_t *mt; - strcpy(buf, ""); - switch (f->id) { - case F_CARNIVORE: if (lorelev >= PR_BEGINNER) sprintf(buf, "Will only eat meat."); break; - case F_DAYBOOST: - if (lorelev >= PR_ADEPT) { - if ((f->val[0] != NA) && (f->val[0] < 0)) { - sprintf(buf, "-%d accuracy during the day.", getaccuracymodnum(abs(f->val[0]))); - } - } - break; - case F_DEAF: if (lorelev >= PR_BEGINNER) sprintf(buf, "Deaf"); break; - case F_DIURNAL: if ((lorelev >= PR_BEGINNER) && !forplayersel) sprintf(buf, "Sleeps at night."); break; - case F_DTVULN: - if ((lorelev >= PR_BEGINNER) && !hasflag(doneflags, F_DTVULN)) { - if (f->val[0] == DT_ALL) { - sprintf(buf, "Vulnerable to %s.", getdamname(DT_ALL)); - } else { - char buf2[BUFLEN]; - int first = B_TRUE,n; - strcpy(buf, ""); - for (n = 0; n < MAXDAMTYPE; n++) { - if (basedamagetype(n) != n) continue; - if (isvulnto(r->flags, n, B_FALSE)) { - if (first) { - snprintf(buf2, BUFLEN, "Vulnerable to: %s", getdamname(n)); - first = B_FALSE; - } else { - snprintf(buf2, BUFLEN, ", %s", getdamname(n)); - } - strcat(buf, buf2); - } - } - } - addflag(doneflags, F_DTVULN, B_TRUE, NA, NA, NULL); - } - break; - case F_FASTMETAB: if (lorelev >= PR_BEGINNER) sprintf(buf, "Fast metabolism (needs to eat often)"); break; - case F_LEARNBOOST: - if ((lorelev >= PR_BEGINNER) && (f->val[0] < 0)) { - sprintf(buf, "Gains XP %d%% slower.", abs(f->val[0])); - } - break; - case F_MATVULN: - if (lorelev >= PR_ADEPT) { - mt = findmaterial(f->val[0]); - sprintf(buf, "Takes %d%% damage from weapons made of %s.", f->val[1], mt->name); - } - break; - case F_MPMOD: if (f->val[0] < 0) sprintf(buf, "%d Mana", f->val[0]); break; - case F_NEEDSWATER: if (lorelev >= PR_NOVICE) sprintf(buf, "Will suffocate without water"); break; - case F_NIGHTBOOST: - if (lorelev >= PR_ADEPT) { - if ((f->val[0] != NA) && (f->val[0] < 0)) { - sprintf(buf, "-%d accuracy at night.", getaccuracymodnum(abs(f->val[0]))); - } - } - break; - case F_NOTAKECRITS: if (lorelev >= PR_NOVICE) sprintf(buf, "Immune to critical hits."); break; - case F_NOPRAY: if (lorelev >= PR_BEGINNER) sprintf(buf, "Cannot worship gods."); break; - case F_NORESTHEAL: if (lorelev >= PR_NOVICE) sprintf(buf, "Cannot restore HP by resting."); break; - case F_NOSMELL: if ((lorelev >= PR_NOVICE) ) sprintf(buf, "No sense of smell."); break; - case F_NOCTURNAL: if ((lorelev >= PR_BEGINNER) && !forplayersel) sprintf(buf, "Sleeps during the day."); break; - case F_NOSPELLS: if (lorelev >= PR_NOVICE) sprintf(buf, "Cannot use magic."); break; - case F_NOPACK: sprintf(buf, "Cannot carry objects."); break; - case F_SIZE: - if (hasflag(r->flags, F_HUMANOID) && (f->val[0] != SZ_HUMAN)) { - sprintf(buf, "Only specially sized armour will fit."); - } - break; - case F_STAYINROOM: - if (lorelev >= PR_ADEPT) { - sprintf(buf, "Will not leave its home territory."); break; - } - break; - case F_TAMABLE: - if ((lorelev >= PR_ADEPT) && !forplayersel) { - sprintf(buf, "Susceptible to bribery."); - } - break; - case F_VEGETARIAN: if (lorelev >= PR_ADEPT) sprintf(buf, "Will not eat meat."); break; - case F_VISRANGEMOD: - if (lorelev >= PR_BEGINNER) { - if (f->val[0] < 0) sprintf(buf, "Reduced vision range (%d)", f->val[0]); - } - break; - case F_PARTVEGETARIAN: if (lorelev >= PR_ADEPT) sprintf(buf, "Will only eat meat when hungry."); break; - default: - break; - } - if (strlen(buf)) { - strncat(retbuf, "@- ", HUGEBUFLEN); - strcat(buf, "\n"); - strncat(retbuf, buf, HUGEBUFLEN); - curidx++; - } - } + foreach_bucket(b) { + for (f = r->flags->first[b] ; f ; f = f->next) { + material_t *mt; + strcpy(buf, ""); + switch (f->id) { + case F_CARNIVORE: if (lorelev >= PR_BEGINNER) sprintf(buf, "Will only eat meat."); break; + case F_DAYBOOST: + if (lorelev >= PR_ADEPT) { + if ((f->val[0] != NA) && (f->val[0] < 0)) { + sprintf(buf, "-%d accuracy during the day.", getaccuracymodnum(abs(f->val[0]))); + } + } + break; + case F_DEAF: if (lorelev >= PR_BEGINNER) sprintf(buf, "Deaf"); break; + case F_DIURNAL: if ((lorelev >= PR_BEGINNER) && !forplayersel) sprintf(buf, "Sleeps at night."); break; + case F_DTVULN: + if ((lorelev >= PR_BEGINNER) && !hasflag(doneflags, F_DTVULN)) { + if (f->val[0] == DT_ALL) { + sprintf(buf, "Vulnerable to %s.", getdamname(DT_ALL)); + } else { + char buf2[BUFLEN]; + int first = B_TRUE,n; + strcpy(buf, ""); + for (n = 0; n < MAXDAMTYPE; n++) { + if (basedamagetype(n) != n) continue; + if (isvulnto(r->flags, n, B_FALSE)) { + if (first) { + snprintf(buf2, BUFLEN, "Vulnerable to: %s", getdamname(n)); + first = B_FALSE; + } else { + snprintf(buf2, BUFLEN, ", %s", getdamname(n)); + } + strcat(buf, buf2); + } + } + } + addflag(doneflags, F_DTVULN, B_TRUE, NA, NA, NULL); + } + break; + case F_FASTMETAB: if (lorelev >= PR_BEGINNER) sprintf(buf, "Fast metabolism (needs to eat often)"); break; + case F_LEARNBOOST: + if ((lorelev >= PR_BEGINNER) && (f->val[0] < 0)) { + sprintf(buf, "Gains XP %d%% slower.", abs(f->val[0])); + } + break; + case F_MATVULN: + if (lorelev >= PR_ADEPT) { + mt = findmaterial(f->val[0]); + sprintf(buf, "Takes %d%% damage from weapons made of %s.", f->val[1], mt->name); + } + break; + case F_MPMOD: if (f->val[0] < 0) sprintf(buf, "%d Mana", f->val[0]); break; + case F_NEEDSWATER: if (lorelev >= PR_NOVICE) sprintf(buf, "Will suffocate without water"); break; + case F_NIGHTBOOST: + if (lorelev >= PR_ADEPT) { + if ((f->val[0] != NA) && (f->val[0] < 0)) { + sprintf(buf, "-%d accuracy at night.", getaccuracymodnum(abs(f->val[0]))); + } + } + break; + case F_NOTAKECRITS: if (lorelev >= PR_NOVICE) sprintf(buf, "Immune to critical hits."); break; + case F_NOPRAY: if (lorelev >= PR_BEGINNER) sprintf(buf, "Cannot worship gods."); break; + case F_NORESTHEAL: if (lorelev >= PR_NOVICE) sprintf(buf, "Cannot restore HP by resting."); break; + case F_NOSMELL: if ((lorelev >= PR_NOVICE) ) sprintf(buf, "No sense of smell."); break; + case F_NOCTURNAL: if ((lorelev >= PR_BEGINNER) && !forplayersel) sprintf(buf, "Sleeps during the day."); break; + case F_NOSPELLS: if (lorelev >= PR_NOVICE) sprintf(buf, "Cannot use magic."); break; + case F_NOPACK: sprintf(buf, "Cannot carry objects."); break; + case F_SIZE: + if (hasflag(r->flags, F_HUMANOID) && (f->val[0] != SZ_HUMAN)) { + sprintf(buf, "Only specially sized armour will fit."); + } + break; + case F_STAYINROOM: + if (lorelev >= PR_ADEPT) { + sprintf(buf, "Will not leave its home territory."); break; + } + break; + case F_TAMABLE: + if ((lorelev >= PR_ADEPT) && !forplayersel) { + sprintf(buf, "Susceptible to bribery."); + } + break; + case F_VEGETARIAN: if (lorelev >= PR_ADEPT) sprintf(buf, "Will not eat meat."); break; + case F_VISRANGEMOD: + if (lorelev >= PR_BEGINNER) { + if (f->val[0] < 0) sprintf(buf, "Reduced vision range (%d)", f->val[0]); + } + break; + case F_PARTVEGETARIAN: if (lorelev >= PR_ADEPT) sprintf(buf, "Will only eat meat when hungry."); break; + default: + break; + } + if (strlen(buf)) { + strncat(retbuf, "@- ", HUGEBUFLEN); + strcat(buf, "\n"); + strncat(retbuf, buf, HUGEBUFLEN); + curidx++; + } + } + } if (curidx == 0) { strncat(retbuf, "^n@None known.\n", HUGEBUFLEN); @@ -8265,7 +8275,8 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra, int forplayersel ////////////////////////////////////////////// // auto misc from flags - for (f = r->flags->first ; f ; f = f->next) { + foreach_bucket(b) { + for (f = r->flags->first[b] ; f ; f = f->next) { char buf2[BUFLEN]; strcpy(buf, ""); switch (f->id) { @@ -8295,6 +8306,7 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra, int forplayersel strncat(retbuf, buf, HUGEBUFLEN); curidx++; } + } } if (donemischeading && (curidx == 0)) { strncat(retbuf, "^n@None known.\n", HUGEBUFLEN); @@ -12454,7 +12466,7 @@ void showlfstats(lifeform_t *lf, int showall) { int nweps = 0; objecttype_t *ot; int first; - int i; + int i,b; int dammod; //int accmod; enum BODYPART bp; @@ -13411,7 +13423,8 @@ void showlfstats(lifeform_t *lf, int showall) { } // fleeing? if (showall) { - for (f = lf->flags->first ; f ; f = f->next) { + foreach_bucket(b) { + for (f = lf->flags->first[b] ; f ; f = f->next) { if (f->id == F_FLEEFROM) { lifeform_t *lf2; lf2 = findlf(NULL, f->val[0]); @@ -13421,6 +13434,7 @@ void showlfstats(lifeform_t *lf, int showall) { } } } + } } // diff materials? @@ -13855,7 +13869,8 @@ void showlfstats(lifeform_t *lf, int showall) { } // spells nfound = 0; - for (f = lf->flags->first ; f ; f = f->next) { + foreach_bucket(b) { + for (f = lf->flags->first[b] ; f ; f = f->next) { if (f->id == F_BOOSTSPELL) { objecttype_t *sp; sp = findot(f->val[0]); @@ -13880,6 +13895,7 @@ void showlfstats(lifeform_t *lf, int showall) { nfound++; } } + } } //if (nfound) // obvious physical effects first. @@ -14659,7 +14675,8 @@ void showlfstats(lifeform_t *lf, int showall) { effectline(&stopnow, &count, offset, &nextoffset, headinglines, mainwin, &y, &x, 0, "%s receive enhanced knowledge about the world.%s", you(lf),source); } - for (f = lf->flags->first ; f ; f = f->next ){ + foreach_bucket(b) { + for (f = lf->flags->first[b] ; f ; f = f->next) { if (f->known && (f->id == F_POISONED)) { int knownfatal = B_FALSE; poisontype_t *pt; @@ -14698,6 +14715,7 @@ void showlfstats(lifeform_t *lf, int showall) { effectline(&stopnow, &count, offset, &nextoffset, headinglines, mainwin, &y, &x, 0, buf); } + } } f = lfhasflag(lf, F_MUTABLE); if (f && (f->known)) {