diff --git a/ai.c b/ai.c index 0a18937..0c6d130 100644 --- a/ai.c +++ b/ai.c @@ -669,7 +669,8 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) { if (db) { dblog(".oO { moving towards target. }"); } - if (!movetowards(lf, target->cell, DT_ORTH)) { + if (!movetowards(lf, target->cell, DT_ORTH, B_FALSE)) { + turntoface(lf, target->cell); // success return B_FALSE; } else { @@ -678,7 +679,7 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) { } } else if (dist < wantdistmin) { if (db) dblog(".oO { moving away from target to maintain mindist %d. }", wantdistmin); - if (!moveawayfrom(lf, target->cell, DT_ORTH, B_KEEPLOF)) { // maintain LOF + if (!moveawayfrom(lf, target->cell, DT_ORTH, B_KEEPLOF, B_TRUE)) { // maintain LOF, and keep facing the target // success return B_FALSE; } else { @@ -772,7 +773,7 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) { } else { // try going in last known dir if (db) dblog(".oO { trying my master's last known move dir (%s) }",getdirname(lastdir)); - if (!trymove(lf, lastdir, B_TRUE)) { + if (!trymove(lf, lastdir, B_TRUE, B_FALSE)) { if (db) dblog(".oO { ...successfully }"); // we now don't know their last known dir. if (targetflag) { @@ -819,8 +820,8 @@ void aimovetotargetcell(lifeform_t *lf, flag_t *f) { if (db) dblog(".oO { walking from %d,%d towards f_targetcell (%d,%d) ... }", lf->cell->x, lf->cell->y, x, y); c = getcellat(lf->cell->map, x, y); if (c) { - // try to move towards the cll - if (movetowards(lf, c, DT_ORTH)) { + // try to move towards the cell + if (movetowards(lf, c, DT_ORTH, B_FALSE )) { // couldn't move towards it for some reason. // so stop trying. if (db) dblog(".oO { couldn't walk towards f_targetcell. abandoning it. }"); @@ -849,6 +850,8 @@ void aimovetotargetcell(lifeform_t *lf, flag_t *f) { } killflag(f); + } else { + turntoface(lf, c); } } } else { @@ -957,7 +960,7 @@ void aiturn(lifeform_t *lf) { if (db) { char lfname[BUFLEN]; real_getlfname(lf, lfname, B_FALSE); - dblog("AIMOVE: %s", lfname); + dblog("AIMOVE: %s, facing %s", lfname, getdirnameshort(lf->facing)); } // if lifeform isn't alive, skip turn @@ -1224,8 +1227,8 @@ void aiturn(lifeform_t *lf) { if (lfhasflagval(lf, F_GRABBING, target->id, NA, NA, NULL) && isaquatic(lf) ) { if ( hasobwithflag(lf->cell->obpile, F_DEEPWATER) && !hasobwithflag(target->cell->obpile, F_DEEPWATER)) { - // move away! - if (!moveawayfrom(lf, target->cell, DT_ORTH, B_FALSE)) { + // move away! + if (!moveawayfrom(lf, target->cell, DT_ORTH, B_FALSE, B_TRUE)) { return; } } @@ -1400,10 +1403,14 @@ void aiturn(lifeform_t *lf) { // death? } else { // then move towards them... - if (db) dblog(".oO { moving towards my new target }"); + if (db) dblog(".oO { moving towards my new target (%d,%d) -> (%d,%d) }", lf->cell->x, lf->cell->y, + newtarget->cell->x, newtarget->cell->y); if (icanattack) { - if (!movetowards(lf, newtarget->cell, DT_ORTH)) return; + if (!movetowards(lf, newtarget->cell, DT_ORTH, B_FALSE)) { + turntoface(lf, newtarget->cell); + return; + } } else { if (db) dblog(".oO { won't move towards target - i have no weapon. }"); } diff --git a/attack.c b/attack.c index 744b249..ee3174a 100644 --- a/attack.c +++ b/attack.c @@ -496,6 +496,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) int deflected = B_FALSE; int weppassthrough = B_FALSE; int firstisbackstab = B_FALSE; + int blocked = B_FALSE; int hit = B_FALSE; int critical = 0; char wepname[BUFLEN]; @@ -752,6 +753,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) } if (ndam > 0) { + object_t *shield = NULL; flag_t *f; for (i = 0; i < ndam; i++) { int reduceamt = 0; @@ -790,6 +792,29 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) if (lfhasflag(lf, F_HOLYAURA) && isvulnto(victim->flags, DT_HOLY)) { damtype[i] = DT_HOLY; } + // blocked by defender's shield? + shield = getshield(victim); + if (shield && cansee(victim, lf)) { + int difficulty; + difficulty = 25 + ((gethitdice(lf) - gethitdice(victim)*3) ); + if (skillcheck(victim, SC_SHIELDBLOCK, difficulty, 0)) { + char shname[BUFLEN]; + // announce + real_getobname(shield, shname, 1, B_TRUE, B_FALSE, B_TRUE, B_FALSE, B_FALSE); + if (isplayer(lf)) { // player is atatcking + msg("%s blocks your attack with %s.", victimname, shname); + } else if (cansee(player, lf) || cansee(player, victim)) { // monster is attacking + msg("%s block%s %s%s attack with %s.", victimname, isplayer(victim) ? "" : "s", + attackername, getpossessive(attackername), + shname); + } + // apply all damage to shield + takedamage(shield, dam[i], damtype[i]); + practice(victim, SK_SHIELDS, 1); + blocked = B_TRUE; + break; // stop processing damage now. + } + } } // modify based on resistances @@ -986,13 +1011,13 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) } } // end foreach damtype - // special weapon effects, as long as you're not doing a heavy blow - if (!lfhasflag(lf, F_HEAVYBLOW)) { - wepeffects(wep->flags, victim->cell, damflag, dam[0]); - } // other effects - if (!isdead(victim)) { + if (!isdead(victim) && !blocked) { + // special weapon effects, as long as you're not doing a heavy blow + if (!lfhasflag(lf, F_HEAVYBLOW)) { + wepeffects(wep->flags, victim->cell, damflag, dam[0]); + } if (isunarmed) { f = lfhasflag(lf, F_FREEZINGTOUCH); if (f) { @@ -1086,27 +1111,28 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) } fightback(victim, lf); - } + } // end if !isdead(victim) // retaliation happens even if victim died - getflags(victim->flags, retflag, &nretflags, F_RETALIATE, F_NONE); - for (i = 0; i < nretflags; i++) { - f = retflag[i]; - if (f->id == F_RETALIATE) { - int rdam; - char damstring[BUFLEN]; - rdam = rolldie(f->val[0], f->val[1]); - if (cansee(player, victim)) { - msg("^%c%s%s %s %s %s!", isplayer(victim) ? 'b' : 'n', victimname, getpossessive(victimname), - noprefix(f->text), - getattackverb(victim, NULL, f->val[2], rdam, lf->maxhp), - attackername); + if (!blocked) { + getflags(victim->flags, retflag, &nretflags, F_RETALIATE, F_NONE); + for (i = 0; i < nretflags; i++) { + f = retflag[i]; + if (f->id == F_RETALIATE) { + int rdam; + char damstring[BUFLEN]; + rdam = rolldie(f->val[0], f->val[1]); + if (cansee(player, victim)) { + msg("^%c%s%s %s %s %s!", isplayer(victim) ? 'b' : 'n', victimname, getpossessive(victimname), + noprefix(f->text), + getattackverb(victim, NULL, f->val[2], rdam, lf->maxhp), + attackername); + } + snprintf(damstring, BUFLEN, "%s%s %s", victimname, getpossessive(victimname), noprefix(f->text)); + losehp_real(lf, rdam, f->val[2], victim, damstring, B_TRUE, NULL, B_TRUE); } - snprintf(damstring, BUFLEN, "%s%s %s", victimname, getpossessive(victimname), noprefix(f->text)); - losehp_real(lf, rdam, f->val[2], victim, damstring, B_TRUE, NULL, B_TRUE); } } - } else { // miss! if (aidb) dblog(".oO { i missed! }"); // announce it @@ -1176,7 +1202,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) } // twoweapon? - if (hit) { + if (hit && !blocked) { enum SKILLLEVEL slev; slev = getskill(lf, SK_TWOWEAPON); if (slev >= PR_SKILLED) { diff --git a/data/hiscores.db b/data/hiscores.db index 63fddad..53c9459 100644 Binary files a/data/hiscores.db and b/data/hiscores.db differ diff --git a/defs.h b/defs.h index fd6c045..abe055f 100644 --- a/defs.h +++ b/defs.h @@ -2,7 +2,6 @@ #define __DEFS_H - // MACROS #define MAXOF(a,b) (a > b ? a : b) @@ -52,6 +51,8 @@ #define B_APPENDYOU (-1) #define B_SPLATTER (-1) #define B_FROMINJURY (-1) +#define B_KEEPDIR (-2) + //#define B_TEMP (-1) //#define B_PERM (-2) @@ -201,6 +202,7 @@ // DIRECTIONS #define D_NONE -1 #define D_UNKNOWN -2 +#define D_ALL -3 // Orthogonal directions #define D_N 0 @@ -225,6 +227,13 @@ #define MAXDIR_MAP 15 +// relative directions +enum RELATIVEDIR { + RD_FORWARDS, + RD_BACKWARDS, + RD_SIDEWAYS, +}; + /////////////////////////////////////// // STRINGS /////////////////////////////////////// @@ -347,6 +356,18 @@ enum NOISECLASS { NC_OTHER = 2, }; +enum QUADRANT { + Q_NONE = -1, + Q_NNE = 0, + Q_ENE = 1, + Q_ESE = 2, + Q_SSE = 3, + Q_SSW = 4, + Q_WSW = 5, + Q_WNW = 6, + Q_NNW = 7, +}; + enum SAYPHRASE { SP_BEG, SP_BEGATTACK, @@ -1795,6 +1816,7 @@ enum FLAG { // check. // v2 = sc_dodge difficulty F_OBJECTTRAP, // this trap can go onto an object (door, chest, etc) + F_SMELLY, // lfs with enhacned scent can smell this object // doors F_DOOR, // this object is a door - ie. can open it // v0 and v1 are like F_IMPASSABLE @@ -2251,7 +2273,7 @@ enum FLAG { F_DISEASEIMMUNE, // lf can't be diseased F_DRUNK, // v1 is drunknness - 1-5. F_ENHANCESEARCH, // gives v0 bonus on search checks. - F_ENHANCESMELL, // can 'see' scents. + F_ENHANCESMELL, // can 'see' scents with v0 range. F_EXTRADAM, // do 'text' extra damage of damtype v0 when you hit // if v1 is TRUE, also deal extra damage based on // the flagpile's F_BONUS flag. @@ -2800,6 +2822,7 @@ typedef struct cell_s { // known to player? int known; struct glyph_s knownglyph; + int knowntime; // FOR CONSTRUCTION int visited; @@ -2884,6 +2907,8 @@ typedef struct lifeform_s { long oblist[MAXPILEOBS]; int x,y; + int facing; // which way are we facing + int losdirty; int nlos; cell_t **los; diff --git a/io.c b/io.c index 1f9ca9c..9e1e8e4 100644 --- a/io.c +++ b/io.c @@ -856,6 +856,12 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src strcat(extrainfo, buf2); } } + if (c->lf->facing != D_ALL) { + char buf2[BUFLEN]; + snprintf(buf2, BUFLEN, "facing %s",getdirnameshort(c->lf->facing)); + if (strlen(extrainfo)) strcat(extrainfo, ", "); + strcat(extrainfo, buf2); + } // show iextra info if lf isn't feigning death if (strlen(extrainfo) && !lfhasflag(c->lf, F_FEIGNINGDEATH)) { @@ -3416,6 +3422,8 @@ void describeob(object_t *o) { f = hasflag(o->flags, F_OBHP); if (isarmour(o) && getskill(player, SK_ARMOUR)) { showfullhp = B_TRUE; + } else if (isshield(o) && getskill(player, SK_SHIELDS)) { + showfullhp = B_TRUE; } else if ((o->type->material->id == MT_METAL) && getskill(player, SK_METALWORK)) { showfullhp = B_TRUE; } else if ( ((o->type->material->id == MT_LEATHER) || (o->type->material->id == MT_CLOTH)) && @@ -4131,13 +4139,12 @@ void doclose(void) { int adjdoors; int forcedir = D_NONE; - // how many doors are nearby? adjdoors = 0; for (dir = DC_N; dir <= DC_NW; dir++) { cell_t *c; c = getcellindir(player->cell, dir); - if (c) { + if (c && haslos(player, c)) { object_t *door; door = hasobwithflag(c->obpile, F_DOOR); if (door) { @@ -4152,7 +4159,7 @@ void doclose(void) { } if (adjdoors == 0) { - msg("There are no open doors nearby!"); + msg("You can't see any open doors nearby!"); return; } else if (adjdoors == 1) { dir = forcedir; @@ -4167,7 +4174,7 @@ void doclose(void) { } else { cell_t *c; c = getcellindir(player->cell, dir); - if (c) { + if (c && haslos(player, c)) { failed = closedoorat(player, c); } } @@ -6848,7 +6855,7 @@ void handleinput(void) { if (stopnow) { stoprunning(player); } else { - if (trymove(player, rundir, B_TRUE)) { + if (trymove(player, rundir, B_TRUE, B_FALSE)) { // failed. stoprunning(player); } else { @@ -6868,6 +6875,7 @@ void handleinput(void) { char temp[2]; flag_t repeatflag; int wantrepeat = B_FALSE; + int dir; repeatflag.val[0] = NA; repeatflag.val[1] = NA; repeatflag.val[2] = NA; repeatflag.text = NULL; @@ -6978,9 +6986,9 @@ void handleinput(void) { case 'u': case 'b': case 'n': - trymove(player, chartodir(ch), B_TRUE); + trymove(player, chartodir(ch), B_TRUE, B_FALSE); break; - // running + // run / strafe case 'H': case 'J': case 'K': @@ -6989,7 +6997,12 @@ void handleinput(void) { case 'U': case 'B': case 'N': - tryrun(player, chartodir(ch)); + dir = chartodir(ch); + if (dir == player->facing) { // shift+samedir = run + tryrun(player, dir); + } else { // shift + diffdir = strafe + trymove(player, dir, B_TRUE, B_TRUE); + } break; case 's': // slowwalk trysneak(player, D_NONE); @@ -7326,6 +7339,10 @@ void msg_real(char *format, ... ) { if (db) dblog("adding to msgbuf: [%s]",buf); + if (strstr(buf, "(null)")) { + assert(2 == 3); + } + assert(!strchr(buf, '#')); // ie. can the message buffer fit: // what is already there + 2 spaces + the new text + '--more--' ? @@ -8106,20 +8123,22 @@ void showlfstats(lifeform_t *lf, int showall) { } if (isplayer(lf)) { int attpoints; + int pct; attpoints = getattpoints(lf); doheadingsmall(mainwin, y, 0, ftext, "Training"); - if ((lf->skillpoints == 0) && (attpoints == 0)) { - wprintw(mainwin, "n/a"); - } else { + pct = ((float)lf->skillxp / (float)SKILLXPPERPOINT) * 100.0; + limit(&pct, 0, 100); + if (lf->skillpoints || attpoints ) { /* wprintw(mainwin, "%d skill%s, %d attrib%s", lf->skillpoints, (lf->skillpoints == 1) ? "" : "s", attpoints, (attpoints == 1) ? "" : "s"); */ - wprintw(mainwin, "%d skill point%s", lf->skillpoints, + wprintw(mainwin, "%d skill point%s, ", lf->skillpoints, (lf->skillpoints == 1) ? "" : "s"); } + wprintw(mainwin, "%d%%", pct); y++; } } diff --git a/lf.c b/lf.c index 4661078..be5ee43 100644 --- a/lf.c +++ b/lf.c @@ -145,10 +145,18 @@ int appearsrandomly(enum RACE rid) { void awardxpfor(lifeform_t *killed, float pct) { int xpval,xpeach,i,nposs; + int initialxp; lifeform_t *poss[MAXCANDIDATES], *l; int n; + - xpval = (int) ((float)calcxp(killed) * (pct/100)); + initialxp = calcxp(killed); + assert(initialxp < 10000); + assert(initialxp >= 0); + + xpval = (int) ((float)initialxp * (pct/100)); + assert(xpval < 10000); + assert(xpval >= 0); // find all allies on the map nposs = 0; @@ -3332,7 +3340,7 @@ void fightback(lifeform_t *lf, lifeform_t *attacker) { interrupt(lf); if (lfhasflag(lf, F_FEIGNINGDEATH)) { - // don't responsd. + // don't respond. return; } @@ -3349,7 +3357,6 @@ void fightback(lifeform_t *lf, lifeform_t *attacker) { killflagsofid(lf->flags, F_ASLEEP); // monsters might flee, fight back, etc if (!isplayer(lf)) { - if (isplayer(attacker) && ishirable(lf)) { // can never recruit this person now! addflag(lf->flags, F_NOHIRE, B_TRUE, NA, NA, NULL); @@ -3366,6 +3373,10 @@ void fightback(lifeform_t *lf, lifeform_t *attacker) { if (!isplayer(attacker)) return; } + // turn to face our attacker + if (isadjacent(lf->cell, attacker->cell)) { + turntoface(lf, attacker->cell); + } aiattack(lf, attacker, DEF_AIFOLLOWTIME); // any nearby monsters which will help out? @@ -3651,7 +3662,7 @@ int flee(lifeform_t *lf) { } } // move away from them - if (!moveawayfrom(lf, fleefrom->cell, DT_ORTH, B_FALSE)) { + if (!moveawayfrom(lf, fleefrom->cell, DT_ORTH, B_FALSE, B_FALSE)) { if (db) dblog("%s - fleeing by moving away", lfname); return B_TRUE; } @@ -3875,6 +3886,9 @@ void gainmp(lifeform_t *lf, int amt) { void gainxp(lifeform_t *lf, long amt) { int newskillpoints = 0; int doxp = B_TRUE; + + assert(amt >= 0); + if (lfhasflag(lf, F_HASNEWLEVEL) || (lf->level == 0)) { doxp = B_FALSE; } @@ -3882,11 +3896,13 @@ void gainxp(lifeform_t *lf, long amt) { if (doxp) { lf->xp += amt; if (isplayer(lf)) statdirty = B_TRUE; + assert(lf->xp >= 0); } // skill xp if (isplayer(lf)) { lf->skillxp += amt; + assert(lf->skillxp >= 0); while (lf->skillxp >= SKILLXPPERPOINT) { newskillpoints++; lf->skillxp -= SKILLXPPERPOINT; @@ -3906,6 +3922,221 @@ void gainxp(lifeform_t *lf, long amt) { } } +int fovlist_contains(int *endx, int *endy, int nendcells, int x, int y) { + int i; + for (i = 0;i < nendcells; i++) { + if ((endx[i] == x) && (endy[i] == y)) { + return B_TRUE; + } + } + return B_FALSE; +} + +int get_fov_quad_endpoints(lifeform_t *lf, enum QUADRANT quad, int maxvisrange, int *endx, int *endy, int *nendcells) { + int ix,iy,start,end; + switch (quad) { + case Q_NNE: // n to ne + iy = lf->cell->y - maxvisrange; + start = lf->cell->x; + end = lf->cell->x + maxvisrange; + for (ix = start; ix <= end; ix++) { + if (!fovlist_contains(endx,endy,*nendcells,ix,iy)) { + endx[*nendcells] = ix; + endy[*nendcells] = iy; + (*nendcells)++; + assert(*nendcells < MAXVISLIMIT); + } + } + break; + case Q_ENE: // ne to e + ix = lf->cell->x + maxvisrange; + start = lf->cell->y - maxvisrange; + end = lf->cell->y; + for (iy = start; iy <= end; iy++) { + if (!fovlist_contains(endx,endy,*nendcells,ix,iy)) { + endx[*nendcells] = ix; + endy[*nendcells] = iy; + (*nendcells)++; + assert(*nendcells < MAXVISLIMIT); + } + } + break; + case Q_ESE: // e to se + ix = lf->cell->x + maxvisrange; + start = lf->cell->y; + end = lf->cell->y + maxvisrange; + for (iy = start; iy <= end; iy++) { + if (!fovlist_contains(endx,endy,*nendcells,ix,iy)) { + endx[*nendcells] = ix; + endy[*nendcells] = iy; + (*nendcells)++; + assert(*nendcells < MAXVISLIMIT); + } + } + break; + case Q_SSE: // se to s + iy = lf->cell->y + maxvisrange; + start = lf->cell->x + maxvisrange; + end = lf->cell->x; + for (ix = start; ix >= end; ix--) { + if (!fovlist_contains(endx,endy,*nendcells,ix,iy)) { + endx[*nendcells] = ix; + endy[*nendcells] = iy; + (*nendcells)++; + assert(*nendcells < MAXVISLIMIT); + } + } + break; + case Q_SSW: // s to sw + iy = lf->cell->y + maxvisrange; + start = lf->cell->x; + end = lf->cell->x - maxvisrange; + for (ix = start; ix >= end; ix--) { + if (!fovlist_contains(endx,endy,*nendcells,ix,iy)) { + endx[*nendcells] = ix; + endy[*nendcells] = iy; + (*nendcells)++; + assert(*nendcells < MAXVISLIMIT); + } + } + break; + case Q_WSW: // sw to w + ix = lf->cell->x - maxvisrange; + start = lf->cell->y + maxvisrange; + end = lf->cell->y; + for (iy = start; iy >= end; iy--) { + if (!fovlist_contains(endx,endy,*nendcells,ix,iy)) { + endx[*nendcells] = ix; + endy[*nendcells] = iy; + (*nendcells)++; + assert(*nendcells < MAXVISLIMIT); + } + } + break; + case Q_WNW: // w to nw + ix = lf->cell->x - maxvisrange; + start = lf->cell->y; + end = lf->cell->y - maxvisrange; + for (iy = start; iy >= end; iy--) { + if (!fovlist_contains(endx,endy,*nendcells,ix,iy)) { + endx[*nendcells] = ix; + endy[*nendcells] = iy; + (*nendcells)++; + assert(*nendcells < MAXVISLIMIT); + } + } + break; + case Q_NNW: // nw to n + iy = lf->cell->y - maxvisrange; + start = lf->cell->x - maxvisrange; + end = lf->cell->x; + for (ix = start; ix <= end; ix++) { + if (!fovlist_contains(endx,endy,*nendcells,ix,iy)) { + endx[*nendcells] = ix; + endy[*nendcells] = iy; + (*nendcells)++; + assert(*nendcells < MAXVISLIMIT); + } + } + break; + case Q_NONE: + break; + } + return *nendcells; +} + +int get_adjacent_quadrants(int dir, enum QUADRANT *start, enum QUADRANT *end) { + switch (dir) { + case DC_N: // nw to ne + if (start) *start = Q_NNW; + if (end) *end = Q_NNE; + break; + case DC_NE: // n to ne, ne to e + if (start) *start = Q_NNE; + if (end) *end = Q_ENE; + break; + case DC_E: // ne to se + if (start) *start = Q_ENE; + if (end) *end = Q_ESE; + break; + case DC_SE: // e to se, se to s + if (start) *start = Q_ESE; + if (end) *end = Q_SSE; + break; + case DC_S: // se to sw + if (start) *start = Q_SSE; + if (end) *end = Q_SSW; + break; + case DC_SW: // s to sw, sw to w + if (start) *start = Q_SSW; + if (end) *end = Q_WSW; + break; + case DC_W: //sw to nw + if (start) *start = Q_WSW; + if (end) *end = Q_WNW; + break; + case DC_NW: // w to nw, nw to n + if (start) *start = Q_WNW; + if (end) *end = Q_NNW; + break; + default: + if (start) *start = Q_NONE; + if (end) *end = Q_NONE; + return B_TRUE; + } + return B_FALSE; +} + +int get_circular_fov_endpoints(lifeform_t *lf, int maxvisrange, int *endx, int *endy, int *nendcells) { + int ix,iy,start,end,db = B_FALSE; + *nendcells = 0; + // n + iy = lf->cell->y - maxvisrange; + start = lf->cell->x - maxvisrange; + end = lf->cell->x + maxvisrange; + if (db) dblog("North::%d,%d - %d,%d",start,iy,end,iy); + for (ix = start; ix < end; ix++) { + endx[*nendcells] = ix; + endy[*nendcells] = iy; + (*nendcells)++; + assert(*nendcells < MAXVISLIMIT); + } + // e + ix = lf->cell->x + maxvisrange; + start = lf->cell->y - maxvisrange; + end = lf->cell->y + maxvisrange; + if (db) dblog("East::%d,%d - %d,%d",ix,start,ix,end); + for (iy = start; iy < end; iy++) { + endx[*nendcells] = ix; + endy[*nendcells] = iy; + (*nendcells)++; + assert(*nendcells < MAXVISLIMIT); + } + // s + iy = lf->cell->y + maxvisrange; + start = lf->cell->x + maxvisrange; + end = lf->cell->x - maxvisrange; + if (db) dblog("South::%d,%d - %d,%d",start,iy,end,iy); + for (ix = start; ix > end; ix--) { + endx[*nendcells] = ix; + endy[*nendcells] = iy; + (*nendcells)++; + assert(*nendcells < MAXVISLIMIT); + } + // w + ix = lf->cell->x - maxvisrange; + start = lf->cell->y + maxvisrange; + end = lf->cell->y - maxvisrange; + if (db) dblog("West::%d,%d - %d,%d",ix,start,ix,end); + for (iy = start; iy > end; iy--) { + endx[*nendcells] = ix; + endy[*nendcells] = iy; + (*nendcells)++; + assert(*nendcells < MAXVISLIMIT); + } + return *nendcells; +} + int getactspeed(lifeform_t *lf) { int speed = 0; flag_t *f; @@ -4741,12 +4972,6 @@ int getfootprinttime(lifeform_t *lf) { case SZ_ENORMOUS: time += 30; break; } - if (time > 0) { - if (getskill(lf, SK_PERCEPTION) == PR_EXPERT) { - time /= 2; - limit(&time, 1, NA); - } - } return time; } @@ -5495,7 +5720,6 @@ int getvisrange(lifeform_t *lf, int useambient) { for (i = 0; i < nretflags; i++) { switch (retflag[i]->val[0]) { case IJ_BLACKEYE: - case IJ_EYEDESTROYED: range /= 2; break; } @@ -6252,6 +6476,10 @@ object_t *getrestob(lifeform_t *lf) { // returns proficiency level in a given skill enum SKILLLEVEL getskill(lifeform_t *lf, enum SKILL id) { flag_t *f; + // special case: + if ((id == SK_CARTOGRAPHY) && lfhasflag(lf, F_RAGE)) { + return PR_INEPT; + } f = lfhasflagval(lf, F_HASSKILL, id, NA, NA, NULL); if (f) { return f->val[1]; @@ -7008,6 +7236,12 @@ int giveskill(lifeform_t *lf, enum SKILL id) { newf = addflag(lf->flags, F_CANWILL, OT_A_COOK, NA, NA, NULL); newf->lifetime = FROMSKILL; } + } else if (id == SK_PERCEPTION) { + if ((f->val[1] == PR_ADEPT) || (f->val[1] == PR_MASTER)) { + // our FOV gets wider + lf->losdirty = B_TRUE; + if (isplayer(lf)) needredraw = B_TRUE; + } } else if (id == SK_STEALTH) { if (f->val[1] == PR_BEGINNER) { newf = addflag(lf->flags, F_CANWILL, OT_A_HIDE, NA, NA, NULL); @@ -7398,6 +7632,20 @@ job_t *hasjob(lifeform_t *lf, enum JOB job) { return j; } +void inc_quad_range(enum QUADRANT *start, enum QUADRANT *end, int howmuch) { + int i; + for (i = 0; i < abs(howmuch); i++) { + if (start) { + if (*start == Q_NNE) *start = Q_NNW; + else (*start)--; + } + if (end) { + if (*end == Q_NNW) *end = Q_NNE; + else (*end)++; + } + } +} + // where shoudl always be body, hands, legs or head // damtype should be bash or slash int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype) { @@ -7526,7 +7774,7 @@ int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype) { case 1: inj = IJ_EYELIDSCRAPED; desc = strdup("eyelid is scraped^accuracy penalty"); break; case 2: - inj = IJ_EYEDESTROYED; desc = strdup("right eye is destroyed^permenant vision loss"); + inj = IJ_EYEDESTROYED; desc = strdup("right eye is destroyed^field of view halved"); howlong = PERMENANT; break; @@ -8271,6 +8519,7 @@ void initjobs(void) { } } addflag(lastjob->flags, F_NOSCORE, B_TRUE, NA, NA, NULL); + addflag(lastjob->flags, F_ENHANCESMELL, 5, NA, NA, NULL); addjob(J_ADVENTURER, "Adventurer"); // stats @@ -8584,7 +8833,7 @@ void initjobs(void) { addflag(lastjob->flags, F_EXTRALUCK, B_TRUE, NA, NA, NULL); addflag(lastjob->flags, F_HASPET, NA, NA, NA, "young hawk"); addflag(lastjob->flags, F_MAXATTACKS, 2, 2, NA, NULL);// this is so that our hookhand works - addflag(lastjob->flags, F_VISRANGEMOD, -4, NA, NA, NULL); + addflag(lastjob->flags, F_INJURY, IJ_EYEDESTROYED, NA, NA, NULL); // also: has a hook instead of fists. addflag(lastjob->flags, F_HIRABLE, B_TRUE, NA, NA, NULL); @@ -8647,7 +8896,6 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "helmet"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "suit of ring mail"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "pair of gauntlets"); - addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "set of greaves"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "pair of metal boots"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "buckler"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "10-20 gold coins"); @@ -9174,7 +9422,7 @@ void initrace(void) { addflag(lastrace->flags, F_RARITY, H_DUNGEON, 63, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "4d4+5"); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 5, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "2d4+1"); @@ -9442,7 +9690,7 @@ void initrace(void) { addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 72, NA, NULL); addflag(lastrace->flags, F_RARITY, H_FOREST, 72, NA, NULL); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 4, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "8d4"); addflag(lastrace->flags, F_ARMOURRATING, 9, NA, NA, NULL); addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); @@ -9470,7 +9718,7 @@ void initrace(void) { addflag(lastrace->flags, F_RARITY, H_FOREST, 68, NA, NULL); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "6d4"); addflag(lastrace->flags, F_ARMOURRATING, 9, NA, NA, NULL); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 5, NA, NA, NULL); addflag(lastrace->flags, F_EVASION, 0, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); @@ -9500,7 +9748,7 @@ void initrace(void) { addflag(lastrace->flags, F_RARITY, H_FOREST, 65, NA, NULL); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "10d4"); addflag(lastrace->flags, F_ARMOURRATING, 9, NA, NA, NULL); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 4, NA, NA, NULL); addflag(lastrace->flags, F_EVASION, 0, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); @@ -9787,12 +10035,11 @@ void initrace(void) { addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 62, NA, NULL); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 5, NA, NA, NULL); addflag(lastrace->flags, F_HATESRACE, R_GNOLL, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "6d4+3"); addflag(lastrace->flags, F_ARMOURRATING, 12, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STAYINROOM, NA, NA, NA, NULL); // stay in our maze addflag(lastrace->flags, F_CARNIVORE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, NA, NA, "5-7"); @@ -10018,7 +10265,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 4, NA, "screams in pain^screams of pain"); addflag(lastrace->flags, F_RESISTMAG, 5, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 25, NA, NA, NULL); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 3, NA, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_SKILLED, NA, NULL); addrace(R_POLTERGEIST, "poltergeist", 50, 'p', C_GREEN, MT_FLESH, RC_UNDEAD); // sPirit @@ -10088,7 +10335,7 @@ void initrace(void) { addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 5, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "2d4+3"); addflag(lastrace->flags, F_EVASION, 40, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); @@ -10207,7 +10454,7 @@ void initrace(void) { addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "1d4+0"); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 3, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, AT_LOW, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_LTAVERAGE, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); @@ -10436,7 +10683,7 @@ void initrace(void) { addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL); addflag(lastrace->flags, F_MATVULN, MT_SILVER, 200, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_FLY, 1, NA, "^flapping wings"); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 4, NA, NA, NULL); addrace(R_BEAR, "black bear", 150, 'q', C_BLUE, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 63, NA, NULL); @@ -10446,7 +10693,7 @@ void initrace(void) { addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "3d4+3"); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 5, NA, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d3"); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d3"); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d6"); @@ -10469,7 +10716,7 @@ void initrace(void) { addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "5d4+5"); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 5, NA, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d6"); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d6"); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d8"); @@ -10493,7 +10740,7 @@ void initrace(void) { addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "3d4+3"); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 4, NA, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d4"); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d4"); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d3"); @@ -10525,7 +10772,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^scuttling"); addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 4, NA, NA, NULL); addrace(R_ANTS, "giant soldier ant", 25, 'a', C_BROWN, MT_FLESH, RC_ANIMAL); lastrace->baseid = R_ANT; addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -10549,7 +10796,7 @@ void initrace(void) { addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^scuttling"); addflag(lastrace->flags, F_MINIONS, 50, 1, 3, "giant worker ant"); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 4, NA, NA, NULL); addrace(R_ANTLION, "giant antlion", 30, 'a', C_YELLOW, MT_FLESH, RC_ANIMAL); lastrace->baseid = R_ANT; addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -10573,7 +10820,7 @@ void initrace(void) { addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^scuttling"); addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 4, NA, "roars^a roars"); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 4, NA, NA, NULL); addrace(R_CHICKEN, "chicken", 0.5, 'c', C_BROWN, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL); @@ -10599,7 +10846,7 @@ void initrace(void) { addflag(lastrace->flags, F_RARITY, H_VILLAGE, 100, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); addflag(lastrace->flags, F_RARITY, H_FOREST, 82, NA, NULL); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 6, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "1d4"); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d3"); addflag(lastrace->flags, F_MAXATTACKS, 1, 2, NA, NULL); @@ -10623,7 +10870,7 @@ void initrace(void) { addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 77, NA, ""); addflag(lastrace->flags, F_RARITY, H_FOREST, 77, NA, ""); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 6, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "2d4+3"); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d6"); addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL); @@ -10661,7 +10908,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOBODYPART, BP_SHOULDERS, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_HANDS, NA, NA, NULL); addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 6, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 2, NA, "whines in pain^whining"); addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "howls^a howl"); @@ -10686,7 +10933,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SHOULDERS, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_HANDS, NA, NA, NULL); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 6, NA, NA, NULL); addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL); @@ -10709,7 +10956,7 @@ void initrace(void) { addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d2"); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d2"); addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 4, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SHOULDERS, NA, NA, NULL); @@ -10737,7 +10984,7 @@ void initrace(void) { addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d3"); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d3"); addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 5, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SHOULDERS, NA, NA, NULL); @@ -10766,7 +11013,7 @@ void initrace(void) { addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d3+3"); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d4+3"); addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 5, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SHOULDERS, NA, NA, NULL); @@ -10791,7 +11038,7 @@ void initrace(void) { addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d6+5"); addflag(lastrace->flags, F_EXTRADAM, DT_COLD, NA, NA, "1d6"); addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 5, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SHOULDERS, NA, NA, NULL); @@ -10828,7 +11075,7 @@ void initrace(void) { addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_CHARGE, NA, NA, "range:4;"); addflag(lastrace->flags, F_CANWILL, OT_A_SUCKBLOOD, NA, NA, "dam:0d1+4;"); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 5, NA, NA, NULL); addrace(R_NEWT, "giant newt", 4, ':', C_BROWN, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); @@ -10876,7 +11123,7 @@ void initrace(void) { addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d2"); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d3"); addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 5, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_SHOULDERS, NA, NA, NULL); @@ -11135,7 +11382,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTATT, A_CON, AT_VHIGH, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, ""); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 5, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 87, NA, ""); addflag(lastrace->flags, F_RARITY, H_FOREST, 97, NA, ""); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "2d4+2"); @@ -11159,7 +11406,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_FAST, NA, NA, ""); - addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ENHANCESMELL, 6, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 80, NA, ""); addflag(lastrace->flags, F_RARITY, H_FOREST, 90, NA, ""); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "3d4+3"); @@ -12213,6 +12460,7 @@ lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller) { a->polyrevert = B_FALSE; // for precalcing line of sight + a->facing = rnd(DC_N, DC_NW); a->losdirty = B_TRUE; a->nlos = 0; //a->los = malloc(sizeof(cell_t *) * MAXVISRANGE); @@ -12391,19 +12639,14 @@ void addtrail(lifeform_t *lf, int dir) { // footprints first if (!isairborne(lf) && !lfhasflag(lf, F_NONCORPOREAL)) { int fpdir; - enum SKILLLEVEL slev; - slev = getskill(lf, SK_PERCEPTION); - if (slev == PR_MASTER) { + if (getskill(lf, SK_PERCEPTION) >= PR_EXPERT) { // no footprints! return; - } else if (slev == PR_EXPERT) { - fpdir = D_NONE; } else { fpdir = dir; } - footprint = hastrailof(lf->cell->obpile, lf, OT_FOOTPRINT, &fpflag, NULL); if (footprint) { assert(fpflag); @@ -13893,7 +14136,7 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nt, int volume, cha dist = getcelldist(l->cell, c); // listen check difficulty is based on sound distance vs max hearing distance - if (nt == NC_SPEECH) { + if ((nt == NC_SPEECH) && isplayer(l)) { // you always hear it, as long as you're in range difficulty = 0; } else { @@ -14010,7 +14253,7 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nt, int volume, cha practice(l, SK_LISTEN, 1); } } - } + } // end if !isplayer and not asleep // wake up a little f = lfhasflag(l, F_ASLEEP); @@ -14028,7 +14271,6 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nt, int volume, cha } else { // ie resting on purpose via 'R' // only wake up if the sound if very close - //if (getcelldist(c, l->cell) == 1) { if (volume >= getcelldist(c, l->cell)) { // wake up! if (isplayer(l)) { @@ -14056,8 +14298,27 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nt, int volume, cha isplayer(l) ? "your" : "its"); } } + } else { // not alseep + // monsters will turn to face the sound, as long as they're + // not attacking something + if (!isplayer(l)) { + flag_t *f; + int willrespond = B_FALSE; + f = aihastarget(l); + if (f && (f->id == F_TARGETLF)) { + // might ignore the sound... + if (pctchance(volume*20)) { + willrespond = B_TRUE; + } + } else willrespond = B_TRUE; + + if (willrespond) { + // turn to face the sound + turntoface(l, c); + } + } } - } + } // end for each lf on map return rv; } @@ -14349,14 +14610,14 @@ void precalclos_new(lifeform_t *lf) { cell_t **los; int *blocker; int nlos = 0,i,nn; - int ix,iy; flag_t *f; - cell_t *endcell[MAXVISLIMIT]; + int endx[MAXVISLIMIT],endy[MAXVISLIMIT]; int nendcells = 0; cell_t *retcell[MAXRETCELLS]; int numpixels; - int db = B_FALSE; - int start,end; + //int db = B_FALSE; + enum SKILLLEVEL plev; + flag_t *missingeye,*enhancesmell; f = hasflag(lf->flags, F_XRAYVIS); if (f) { @@ -14365,6 +14626,13 @@ void precalclos_new(lifeform_t *lf) { startxray = 0; } + // right eye missing? + missingeye = lfhasflagval(lf, F_INJURY, IJ_EYEDESTROYED, NA, NA, NULL); + + // enhanced smell means we can "see" lifeforms and "smelly" objects in all + // directions. + enhancesmell = lfhasflag(lf, F_ENHANCESMELL); + los = malloc( sizeof(cell_t *) * (MAX_MAPW * MAX_MAPH)); blocker = malloc( sizeof(cell_t *) * (MAX_MAPW * MAX_MAPH)); @@ -14375,79 +14643,36 @@ void precalclos_new(lifeform_t *lf) { maxvisrange = getvisrange(lf, B_FALSE); nightvisrange = getnightvisrange(lf); + plev = getskill(lf, SK_PERCEPTION); // find all cells at max fov nendcells = 0; - // n - iy = lf->cell->y - maxvisrange; - limit(&iy,0,lf->cell->map->h-1); - start = lf->cell->x - maxvisrange; - end = lf->cell->x + maxvisrange; - limit(&start,0,lf->cell->map->w-1); - limit(&end,0,lf->cell->map->w-1); - if (db) dblog("North::%d,%d - %d,%d",start,iy,end,iy); - for (ix = start; ix < end; ix++) { - c = getcellat(lf->cell->map, ix, iy); - if (c) { - if (db) dblog("N:endcell[%d] = %d,%d",nendcells,c->x, c->y); - endcell[nendcells++] = c; - } - assert(nendcells < MAXVISLIMIT); - } - // e - ix = lf->cell->x + maxvisrange; - limit(&ix,0,lf->cell->map->w-1); - start = lf->cell->y - maxvisrange; - end = lf->cell->y + maxvisrange; - limit(&start,0,lf->cell->map->h-1); - limit(&end,0,lf->cell->map->h-1); - if (db) dblog("East::%d,%d - %d,%d",ix,start,ix,end); - for (iy = start; iy < end; iy++) { - c = getcellat(lf->cell->map, ix, iy); - if (c) { - if (db) dblog("E:endcell[%d] = %d,%d",nendcells,c->x, c->y); - endcell[nendcells++] = c; - } - assert(nendcells < MAXVISLIMIT); - } - // s - iy = lf->cell->y + maxvisrange; - limit(&iy,0,lf->cell->map->h-1); - start = lf->cell->x + maxvisrange; - end = lf->cell->x - maxvisrange; - limit(&start,0,lf->cell->map->w-1); - limit(&end,0,lf->cell->map->w-1); - if (db) dblog("South::%d,%d - %d,%d",start,iy,end,iy); - for (ix = start; ix > end; ix--) { - c = getcellat(lf->cell->map, ix, iy); - if (c) { - if (db) dblog("S:endcell[%d] = %d,%d",nendcells,c->x, c->y); - endcell[nendcells++] = c; - } - assert(nendcells < MAXVISLIMIT); - } - // w - ix = lf->cell->x - maxvisrange; - limit(&ix,0,lf->cell->map->w-1); - start = lf->cell->y + maxvisrange; - end = lf->cell->y - maxvisrange; - limit(&start,0,lf->cell->map->h-1); - limit(&end,0,lf->cell->map->h-1); - if (db) dblog("West::%d,%d - %d,%d",ix,start,ix,end); - for (iy = start; iy > end; iy--) { - c = getcellat(lf->cell->map, ix, iy); - if (c) { - if (db) dblog("W:endcell[%d] = %d,%d",nendcells,c->x, c->y); - endcell[nendcells++] = c; - } - assert(nendcells < MAXVISLIMIT); - } + if (MAXOF(maxvisrange, nightvisrange) == 0) { + } else if (lf->facing == D_ALL) { + get_circular_fov_endpoints(lf, maxvisrange, endx, endy, &nendcells); + } else { + enum QUADRANT startq, endq,curq; + if (!get_adjacent_quadrants(lf->facing, &startq, &endq)) { + if (missingeye) endq = startq; // ie. lose the right hand one + if (plev >= PR_MASTER) inc_quad_range(&startq, missingeye ? NULL : &endq, 2); + else if (plev >= PR_ADEPT) inc_quad_range(&startq, missingeye ? NULL : &endq, 1); + + curq = startq; + get_fov_quad_endpoints(lf, curq, maxvisrange, endx, endy, &nendcells); + while (curq != endq) { + if (curq == Q_NNW) curq = Q_NNE; + else curq++; + get_fov_quad_endpoints(lf, curq, maxvisrange, endx, endy, &nendcells); + } + } + + } // end if facing == all assert(nendcells < MAXVISLIMIT); - // look in circle around lf + // look in the lf's field of vision arc //for (ang = 0; ang < 360; ang += 30) { for (nn = 0; nn < nendcells; nn++) { int keepgoing = B_TRUE; @@ -14460,7 +14685,7 @@ void precalclos_new(lifeform_t *lf) { xray = startxray; currange = 0; // calc path to end cell - calcbresnham(lf->cell->map, lf->cell->x, lf->cell->y, endcell[nn]->x, endcell[nn]->y, retcell, &numpixels ); + calcbresnham(lf->cell->map, lf->cell->x, lf->cell->y, endx[nn], endy[nn], retcell, &numpixels ); // keep going until we lose los for (n = 0; keepgoing && (n < numpixels); n++) { /* @@ -14507,16 +14732,39 @@ void precalclos_new(lifeform_t *lf) { blocker[nlos] = keepgoing ? B_FALSE : B_TRUE; nlos++; } - // TODO: remember if we saw any _lit_ cells } } else { // ie. if !c keepgoing = B_FALSE; } } // end foreach cell and while keepgoing } - assert(nlos < (MAX_MAPW * MAX_MAPH)); + // deal with enhanced smell - do a second sweep in all directions. + if (enhancesmell) { + int n; + get_circular_fov_endpoints(lf, enhancesmell->val[0], endx, endy, &nendcells); + + for (i = 0;i < nendcells; i++) { + calcbresnham(lf->cell->map, lf->cell->x, lf->cell->y, endx[i], endy[i], retcell, &numpixels ); + // keep going until we lose los + for (n = 0; n < numpixels; n++) { + if ((retcell[n]->lf && (retcell[n]->lf->race->raceclass->id != RC_UNDEAD)) || + hasobwithflag(retcell[n]->obpile, F_SMELLY) ) { // && (endcell[i]->lf != lf)) { + int nn,found = B_FALSE; + for (nn = 0; nn < nlos; nn++) { // can we already see this cell? + if (los[nn] == retcell[n]) { + found = B_TRUE; break; + } + } + if (!found) { + los[nlos++] = retcell[n]; + } + } + } + } + } + // now fill in lifeform structure lf->los = malloc(sizeof(cell_t *) * nlos); for (i = 0; i < nlos; i++) { @@ -15110,6 +15358,16 @@ void setattr(lifeform_t *lf, enum ATTRIB attr, int val) { } } +int setfacing(lifeform_t *lf, int dir) { + if (lf->facing == dir) { // already facing that way + return B_TRUE; + } + lf->facing = dir; + lf->losdirty = B_TRUE; + if (isplayer(lf)) needredraw = B_TRUE; + return B_FALSE; +} + void setfollowdistance(lifeform_t *lf, int min, int max) { flag_t *f; f = lfhasflag(lf, F_FOLLOWRANGE); @@ -15406,12 +15664,13 @@ void initskills(void) { addskilldesc(SK_BACKSTAB, PR_EXPERT, "^gYour unseen attacks inflict 6x damage.", B_FALSE); addskilldesc(SK_BACKSTAB, PR_MASTER, "^gYour unseen attacks inflict 7x damage.", B_FALSE); addskill(SK_CARTOGRAPHY, "Cartography", "Your ability to create and interpret maps.", 0); // untrainable - addskilldesc(SK_CARTOGRAPHY, PR_NOVICE, "^gYou now make basic maps of your surroundings.", B_TRUE); - addskilldesc(SK_CARTOGRAPHY, PR_BEGINNER, "^gYour map now shows the location of staircases.", B_TRUE); - addskilldesc(SK_CARTOGRAPHY, PR_ADEPT, "^gYour map now shows the location of doors.", B_TRUE); + addskilldesc(SK_CARTOGRAPHY, PR_INEPT, "- Without this skill, you will quickly forget your surroundings.", B_FALSE); + addskilldesc(SK_CARTOGRAPHY, PR_NOVICE, "^gYou can now remember the basics of your surroundings.", B_TRUE); + addskilldesc(SK_CARTOGRAPHY, PR_BEGINNER, "^gYou can now remember the location of staircases.", B_TRUE); + addskilldesc(SK_CARTOGRAPHY, PR_ADEPT, "^gYour can now remember the location of doors.", B_TRUE); addskilldesc(SK_CARTOGRAPHY, PR_SKILLED, "^gYou no longer forget your surroundings.", B_FALSE); - addskilldesc(SK_CARTOGRAPHY, PR_EXPERT, "^gYour map will now show the location of objects.", B_TRUE); - addskilldesc(SK_CARTOGRAPHY, PR_MASTER, "^gEvery 50 turns, you can map a small area around you.", B_FALSE); + addskilldesc(SK_CARTOGRAPHY, PR_EXPERT, "^gYour can now remember the location of objects.", B_TRUE); + addskilldesc(SK_CARTOGRAPHY, PR_MASTER, "^gEvery 50 turns, you can intuitively map a small area around you.", B_FALSE); addskill(SK_CHANNELING, "Channeling", "Lets you make better use of magical items.", 0); // untrainable addskilldesc(SK_CHANNELING, PR_NOVICE, "^gThe power level of wands and scrolls is increased by 1.", B_FALSE); addskilldesc(SK_CHANNELING, PR_BEGINNER, "^gThe power level of wands and scrolls is increased by 2.", B_FALSE); @@ -15465,7 +15724,7 @@ void initskills(void) { addskilldesc(SK_SEWING, PR_SKILLED, "^gYou can repair cloth items up to 70% condition", B_FALSE); addskilldesc(SK_SEWING, PR_EXPERT, "^gYou can repair cloth items up to 85% condition", B_FALSE); addskilldesc(SK_SEWING, PR_MASTER, "^gYou can fully repair cloth items.", B_FALSE); - addskill(SK_SHIELDS, "Shields", "Reduces shield accuracy penalty, and raises chance to block projectiles.", 50); + addskill(SK_SHIELDS, "Shields", "Reduces shield accuracy penalty, and raises chance to block attacks.", 50); addskilldesc(SK_SHIELDS, PR_INEPT, "- Without this skill, shield accuracy penalties are tripled.", B_FALSE); addskilldesc(SK_SHIELDS, PR_NOVICE, "^gShield accuracy penalties are reduced by 5%.", B_FALSE); addskilldesc(SK_SHIELDS, PR_BEGINNER, "^gShield accuracy penalties are reduced by 10%.", B_FALSE); @@ -15487,9 +15746,10 @@ void initskills(void) { addskilldesc(SK_PERCEPTION, PR_NOVICE, "^gYou can now see footprints.", B_TRUE); addskilldesc(SK_PERCEPTION, PR_BEGINNER, "^gYou can now determine how recently footprints were made.", B_TRUE); addskilldesc(SK_PERCEPTION, PR_ADEPT, "^gYou can now identify creatures from their footprints.", B_TRUE); + addskilldesc(SK_PERCEPTION, PR_ADEPT, "^gYour field of vision is now wider.", B_TRUE); addskilldesc(SK_PERCEPTION, PR_SKILLED, "^gYou can now recognise the direction of footprints.", B_TRUE); - addskilldesc(SK_PERCEPTION, PR_EXPERT, "^gYou can now partially obscure your own footprints.", B_TRUE); - addskilldesc(SK_PERCEPTION, PR_MASTER, "^gYou can now move without leaving footprints.", B_TRUE); + addskilldesc(SK_PERCEPTION, PR_EXPERT, "^gYou can now move without leaving footprints.", B_TRUE); + addskilldesc(SK_PERCEPTION, PR_MASTER, "^gYou now have perception of your blind spots.", B_TRUE); addskill(SK_STEALTH, "Stealth", "Affects your ability to move silently.", 0); // untrainable? addskilldesc(SK_STEALTH, PR_BEGINNER, "^gYou gain the 'hide' ability.", B_FALSE); addskilldesc(SK_STEALTH, PR_EXPERT, "^gYou can now hide even when monsters are nearby.", B_TRUE); @@ -17545,6 +17805,11 @@ int touch(lifeform_t *lf, object_t *o) { return B_FALSE; } +void turntoface(lifeform_t *lf, cell_t *dstcell) { + setfacing(lf, getdirtowards(lf->cell, dstcell, lf, B_FALSE, DT_COMPASS) ); +} + + void unsummon(lifeform_t *lf, int vanishobs) { lifeform_t *creator = NULL; flag_t *f; diff --git a/lf.h b/lf.h index c948092..b2207f6 100644 --- a/lf.h +++ b/lf.h @@ -88,12 +88,15 @@ skill_t *findskillbyname(char *name); enum SKILLLEVEL findskilllevbyname(char *name); int flee(lifeform_t *lf); void fleefrom(lifeform_t *lf, lifeform_t *enemy, int howlong, int onpurpose); +int fovlist_contains(int *endx, int *endy, int nendcells, int x, int y); int freezelf(lifeform_t *freezee, lifeform_t *freezer, int howlong); void gainhp(lifeform_t *lf, int amt); void gainlevel(lifeform_t *lf); void gainmp(lifeform_t *lf, int amt); void gainxp(lifeform_t *lf, long amt); void genxplist(void); +int get_adjacent_quadrants(int dir, enum QUADRANT *start, enum QUADRANT *end); +int get_circular_fov_endpoints(lifeform_t *lf, int maxvisrange, int *endx, int *endy, int *nendcells); int getactspeed(lifeform_t *lf); int getadjenemies(lifeform_t *lf, lifeform_t **adjlf, int *nadjlfs); void getwhowillfollow(lifeform_t *lf, object_t *stairob, lifeform_t **adjally, int *nadjallies); @@ -214,6 +217,7 @@ map_t *gotolev(lifeform_t *lf, int depth, object_t *fromstairs); int gotosleep(lifeform_t *lf, int onpurpose); int hasfreeaction(lifeform_t *lf); job_t *hasjob(lifeform_t *lf, enum JOB job); +void inc_quad_range(enum QUADRANT *start, enum QUADRANT *end, int howmuch); int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype); int lfcanbestoned(lifeform_t *lf); flag_t *lfhasflag(lifeform_t *lf, enum FLAG fid); @@ -314,6 +318,7 @@ int sayphrase(lifeform_t *lf, enum SAYPHRASE what, int volume, int val0, char *t int scare(lifeform_t *lf, lifeform_t *scarer, int howlong, int scarerbonus); //int setammo(lifeform_t *lf, object_t *o); void setattr(lifeform_t *lf, enum ATTRIB attr, int val); +int setfacing(lifeform_t *lf, int dir); void setfollowdistance(lifeform_t *lf, int min, int max); void setguntarget(lifeform_t *lf, lifeform_t *targ); void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph); @@ -343,6 +348,7 @@ int throwat(lifeform_t *thrower, object_t *o, cell_t *where); void timeeffectslf(lifeform_t *lf); int tryclimb(lifeform_t *lf, cell_t *where, char *towhat); int touch(lifeform_t *lf, object_t *o); +void turntoface(lifeform_t *lf, cell_t *dstcell); void unpoison(lifeform_t *lf); void unsummon(lifeform_t *lf, int vanishobs); int unweild(lifeform_t *lf, object_t *o); diff --git a/map.c b/map.c index dc19aa8..d0ee113 100644 --- a/map.c +++ b/map.c @@ -60,6 +60,7 @@ cell_t *addcell(map_t *m, int x, int y) { cell->origlittimer = 0; cell->writing = NULL; cell->known = B_FALSE; + cell->knowntime = 0; cell->knownglyph.ch = ' '; cell->knownglyph.colour = C_GREY; cell->visited = B_FALSE; @@ -397,7 +398,9 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int ot = NULL; } if (ot) { - addobfast(lf->pack, ot->id); + object_t *o; + o = addobfast(lf->pack, ot->id); + if (o) turnon(NULL, o); } } } @@ -3871,7 +3874,6 @@ void forgetcells(map_t *map, int amt) { poss[nposs] = c; nposs++; } - } if (amtleft > nposs) amtleft = nposs; @@ -5098,39 +5100,37 @@ void setcellknown(cell_t *cell, int forcelev) { slev = getskill(player, SK_CARTOGRAPHY); } - // photographic memory counts as novice level - if ((slev == PR_INEPT) && lfhasflag(player, F_PHOTOMEM)) { - slev = PR_NOVICE; - } - - - if (slev >= PR_NOVICE) { - cell->known = B_TRUE; - // default to remembering the cell's glyph - cell->knownglyph = cell->type->glyph; - // high cartography skill lets us remember certain objects... - if (slev >= PR_EXPERT) { - o = gettopobject(cell, B_TRUE); - if (o) { - cell->knownglyph = *(getglyph(o)); - } + cell->known = B_TRUE; + // default to remembering the cell's glyph + cell->knownglyph = cell->type->glyph; + // high cartography skill lets us remember certain objects... + if (slev >= PR_EXPERT) { + o = gettopobject(cell, B_TRUE); + if (o) { + cell->knownglyph = *(getglyph(o)); } - if (slev >= PR_ADEPT) { - for (o = cell->obpile->first ; o ; o = o->next) { - if ((o->type->obclass->id == OC_DFEATURE) || (o->type->obclass->id == OC_TERRAIN)) { - if (!issecretdoor(o)) { - cell->knownglyph = *(getglyph(o)); - } + } + if (slev >= PR_ADEPT) { + for (o = cell->obpile->first ; o ; o = o->next) { + if ((o->type->obclass->id == OC_DFEATURE) || (o->type->obclass->id == OC_TERRAIN)) { + if (!issecretdoor(o)) { + cell->knownglyph = *(getglyph(o)); } } } - if (slev >= PR_BEGINNER) { - o = hasobwithflag(cell->obpile, F_CLIMBABLE); - if (o) { - cell->knownglyph = *(getglyph(o)); - } + } + if (slev >= PR_BEGINNER) { + o = hasobwithflag(cell->obpile, F_CLIMBABLE); + if (o) { + cell->knownglyph = *(getglyph(o)); } } + + if (slev == PR_INEPT) { + cell->knowntime = getattr(player, A_IQ)*3; + } else { + cell->knowntime = PERMENANT; + } //getcellglyph(&(cell->knownglyph), cell, player); } diff --git a/move.c b/move.c index d98ab71..002b6c2 100644 --- a/move.c +++ b/move.c @@ -345,6 +345,17 @@ int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error) { return B_TRUE; } +int getrelativedir(lifeform_t *lf, int dir) { + int diff; + diff = abs(lf->facing - dir); + if (diff <= 1) { + return RD_FORWARDS; + } else if (diff == 2) { + return RD_SIDEWAYS; + } + return RD_BACKWARDS; +} + int diropposite(int dir) { switch (dir) { case D_N: @@ -427,7 +438,7 @@ int dorandommove(lifeform_t *lf, int badmovesok, int restonfail) { } } } - return trymove(lf, dir, B_TRUE); + return trymove(lf, dir, B_TRUE, B_FALSE); } @@ -702,7 +713,7 @@ int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallc if ((i == 0) && seen) { msg("%s %s knocked backwards!",lfname,is(lf)); } - trymove(lf, dir, B_FALSE); + trymove(lf, dir, B_FALSE, B_FALSE); } if (reason != E_OK) { @@ -796,7 +807,7 @@ int makeorthogonal(int dir) { } // see 'movetowards' for description of dirtype -int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype, int keepinlof ) { +int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype, int keepinlof, int strafe ) { int dir; int rv = B_TRUE; @@ -810,7 +821,7 @@ int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype, int keepinlof ) { if (dir == D_NONE) { rv = B_TRUE; } else { - rv = trymove(lf, dir, B_TRUE); + rv = trymove(lf, dir, B_TRUE, strafe); } return rv; } @@ -1442,11 +1453,16 @@ int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose, int dontclearmsg) { // use compass/dt_compass for involuntary movement (eg. being knocked back by // an explosion) // -int movetowards(lifeform_t *lf, cell_t *dst, int dirtype) { +int movetowards(lifeform_t *lf, cell_t *dst, int dirtype, int strafe) { int dir; int rv = B_TRUE; + int db = B_FALSE; + + if (lfhasflag(lf, F_DEBUG)) db = B_TRUE; + if (isblind(lf)) { + if (db) dblog(".oO { i am blind - movetorwards calling dorandommove. }"); dorandommove(lf, B_TRUE, B_TRUE); return B_FALSE; } @@ -1454,7 +1470,8 @@ int movetowards(lifeform_t *lf, cell_t *dst, int dirtype) { // move towards them dir = getdirtowards(lf->cell, dst, lf, B_TRUE, dirtype); if (dir != D_NONE) { - rv = trymove(lf, dir, B_TRUE); + if (db) dblog(".oO { dir from %d,%d -> %d,%d is %s }", lf->cell->x, lf->cell->y, dst->x, dst->y, getdirname(dir)); + rv = trymove(lf, dir, B_TRUE, strafe); } return rv; } @@ -1757,7 +1774,7 @@ int closedoor(lifeform_t *lf, object_t *o) { } int tryrun(lifeform_t *lf, int dir) { - if (!trymove(lf, dir, B_TRUE)) { + if (!trymove(lf, dir, B_TRUE, B_TRUE)) { // success! addflag(lf->flags, F_RUNNING, dir, B_FALSE, NA, NULL); } @@ -1778,7 +1795,7 @@ int trysneak(lifeform_t *lf, int dir) { } } addflag(lf->flags, F_SNEAK, NA, NA, NA, NULL); - trymove(lf, dir, B_TRUE); + trymove(lf, dir, B_TRUE, B_FALSE); killflagsofid(lf->flags, F_SNEAK); return B_FALSE; @@ -2129,15 +2146,29 @@ void triggertrap(lifeform_t *lf, object_t *o, object_t *trapob, cell_t *where) { if (lf) interrupt(lf); } -int trymove(lifeform_t *lf, int dir, int onpurpose) { +int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) { cell_t *cell; enum ERROR errcode; char buf[BUFLEN]; int dontclearmsg = B_FALSE; int moveok; int rndmove = B_FALSE; + int howlong; flag_t *f; + howlong = getmovespeed(lf); + + if (onpurpose && !strafe) { + // if the given dir is behind us, just turn. + if (getrelativedir(lf, dir) != RD_FORWARDS) { + howlong /= 2; + limit(&howlong, 1, NA); + setfacing(lf, dir); + taketime(lf, howlong); + return B_FALSE; + } + } + f = lfhasflag(lf, F_DRUNK); if (f) { if (!hasjob(lf, J_PIRATE)) { @@ -2224,7 +2255,18 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) { // now move to new cell moveto(lf, cell, rndmove ? B_FALSE : onpurpose, dontclearmsg); if (onpurpose) { - taketime(lf, getmovespeed(lf)); + // strafing sideways/backwards takes longer + if (strafe) { + switch (getrelativedir(lf, dir)) { + case RD_SIDEWAYS: howlong = pctof(125, howlong); break; + case RD_BACKWARDS: howlong = pctof(150, howlong); break; + case RD_FORWARDS: + default: + break; + } + } + taketime(lf, howlong); + if (!rndmove && !strafe) setfacing(lf, dir); // face the way we moved } // attached lfs or lfs you have grabbed will move the same direction if they can diff --git a/move.h b/move.h index da47675..343eb4b 100644 --- a/move.h +++ b/move.h @@ -6,6 +6,7 @@ int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *err int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error); int closedoorat(lifeform_t *lf, cell_t *c); int closedoor(lifeform_t *lf, object_t *o); +int getrelativedir(lifeform_t *lf, int dir); int diropposite(int dir); int dorandommove(lifeform_t *lf, int badmovesok, int restonfail); int getdiraway(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype, int keepinlof); @@ -13,12 +14,12 @@ int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, in int getwalkoffdir(lifeform_t *lf, int dir); int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallcheckdiff); int makeorthogonal(int dir); -int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype, int keepinlof); +int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype, int keepinlof, int strafe); int moveclear(lifeform_t *lf, int dir, enum ERROR *error); int moveeffects(lifeform_t *lf); int movelf(lifeform_t *lf, cell_t *newcell); int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose, int dontclearmsg); -int movetowards(lifeform_t *lf, cell_t *dst, int dirtype); +int movetowards(lifeform_t *lf, cell_t *dst, int dirtype, int strafe); int move_will_hurt(lifeform_t *lf); int opendoorat(lifeform_t *lf, cell_t *c); int opendoor(lifeform_t *lf, object_t *o); @@ -29,7 +30,7 @@ int ispossiblemove(lifeform_t *lf, int dir); void swapplaces(lifeform_t *lf1, lifeform_t *lf2, int onpurpose); int teleportto(lifeform_t *lf, cell_t *c, int wantsmoke); void triggertrap(lifeform_t *lf, object_t *o, object_t *trapob, cell_t *where); -int trymove(lifeform_t *lf, int dir, int onpurpose); +int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe); int tryrun(lifeform_t *lf, int dir); int trysneak(lifeform_t *lf, int dir); int walkoffmap(lifeform_t *lf, int dir, int onpurpose); diff --git a/nexus.c b/nexus.c index 4cb73df..05d560a 100644 --- a/nexus.c +++ b/nexus.c @@ -110,6 +110,7 @@ int main(int argc, char **argv) { int x,y; cell_t *c; vault_t *v; + enum SKILLLEVEL slev; atexit(cleanup); @@ -233,6 +234,7 @@ int main(int argc, char **argv) { real_addlf(where, R_HUMAN, 1, C_PLAYER); // this will assign 'player' addflag(player->flags, F_CANWILL, OT_A_PRAY, NA, NA, NULL); addflag(player->flags, F_CANWILL, OT_A_TRAIN, NA, NA, NULL); + addflag(player->flags, F_CANWILL, OT_A_DEBUG, NA, NA, NULL); ///////// o = hasob(where->obpile, OT_PLAYERSTART); killob(o); @@ -326,14 +328,17 @@ int main(int argc, char **argv) { calclight(player->cell->map); // pre-calc line-of-sight for player //precalclos(player); + player->facing = D_ALL; setlosdirty(player); // don't want any mosnters starting within los/lof of player + slev = getskill(player, SK_CARTOGRAPHY); for (y = 0; y < player->cell->map->h; y++) { for (x = 0; x < player->cell->map->w; x++) { c = getcellat(player->cell->map, x, y); - if (c && c->lf && (haslos(player, c) || haslof(player->cell, c, LOF_WALLSTOP, NULL))) { - if (!isplayer(c->lf) && !ispetof(c->lf, player)) { + if (c && (haslos(player, c) || haslof(player->cell, c, LOF_WALLSTOP, NULL))) { + setcellknown(c, slev); + if (c->lf && !isplayer(c->lf) && !ispetof(c->lf, player)) { killlf(c->lf); } } @@ -348,6 +353,7 @@ int main(int argc, char **argv) { // redo light and player los calclight(player->cell->map); + player->facing = rnd(DC_N, DC_NW); precalclos(player); // show level @@ -776,43 +782,6 @@ void donextturn(map_t *map) { } } -char *getdirname(int dir) { - switch (dir) { - case D_N: - return "North"; - case D_E: - return "East"; - case D_S: - return "South"; - case D_W: - return "West"; - case D_UP: - return "up"; - case D_DOWN: - return "down"; - case D_UNKNOWN: - return "D_UNKNOWN"; - case D_NONE: - return "D_NONE"; - case DC_N: - return "North"; - case DC_NE: - return "Northeast"; - case DC_E: - return "East"; - case DC_SE: - return "Southeast"; - case DC_S: - return "South"; - case DC_SW: - return "Southwest"; - case DC_W: - return "West"; - case DC_NW: - return "Northwest"; - } - return "?errordir?"; -} enum COLOUR getpctcol(float num, float max) { float pct; @@ -923,6 +892,10 @@ void calcbresnham(map_t *m, int x1, int y1, int x2, int y2, cell_t **retcell, in y = y1; for (i = 0; i < *numpixels; i++) { retcell[i] = getcellat(m, x, y); + if (!retcell[i]) { // we've gone off the map - stop here + *numpixels = i; + return; + } dobresnham(d, xinc1, yinc1, dinc1, xinc2, yinc2, dinc2, &xinc, &yinc, &dinc); // move to next cell d += dinc; @@ -1414,6 +1387,9 @@ void timeeffectsworld(map_t *map, int updategametime) { object_t *o,*nexto; int x,y; long firstlftime; + enum SKILLLEVEL cartskill; + + cartskill = getskill(player, SK_CARTOGRAPHY); // now go through the list and make the first element be 0 l = map->lf; @@ -1466,6 +1442,19 @@ void timeeffectsworld(map_t *map, int updategametime) { c = getcellat(map, x, y); if (c) { object_t *pit; + + if (cartskill <= PR_INEPT) { + // if you are inept at cartography, you will forget + // cells outside your view which are far away. + if (c->knowntime > 0) { + c->knowntime--; + if (c->knowntime <= 0) { + c->known = B_FALSE; + c->knowntime = 0; + } + } + } + pit = hasobwithflagval(c->obpile, F_PIT, D_DOWN, NA, NA, NULL); if (pit) { obsfallthrough(c, pit); diff --git a/nexus.h b/nexus.h index 4f528ec..4cc5fa4 100644 --- a/nexus.h +++ b/nexus.h @@ -10,7 +10,6 @@ void dbtimeend(char *text); void dbtimestart(char *text); void dobresnham(int d, int xinc1, int yinc1, int dinc1, int xinc2, int yinc2, int dinc2, int *xinc, int *yinc, int *dinc); void donextturn(map_t *map); -char *getdirname(int dir); enum COLOUR getpctcol(float num, float max); void getrarityrange(int depth, int *min, int *max, int range, int oodok); int init(void); diff --git a/objects.c b/objects.c index 52010fa..1f3121b 100644 --- a/objects.c +++ b/objects.c @@ -5854,6 +5854,7 @@ void initobjects(void) { addocnoun(lastobjectclass, "food"); addflag(lastobjectclass->flags, F_STACKABLE, B_TRUE, NA, NA, ""); addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); + addflag(lastobjectclass->flags, F_SMELLY, B_TRUE, NA, NA, NULL); addoc(OC_GODSTONE, "Godstones", "Ancient artifacts, created by the elder gods.", '*', C_BOLDMAGENTA); addflag(lastobjectclass->flags, F_UNIQUE, NA, NA, NA, NULL); addflag(lastobjectclass->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "pulsating purple stone"); @@ -9134,7 +9135,6 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL); addflag(lastot->flags, F_SHIELD, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_GOESON, BP_SECWEAPON, NA, NA, NULL); - addflag(lastot->flags, F_ARMOURRATING, 4, NA, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_SHIELDPENALTY, 5, NA, NULL); addflag(lastot->flags, F_OBHP, 20, 20, NA, NULL); // similar to a buckler, but repairable, lighter, and less durable @@ -9142,28 +9142,24 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL); addflag(lastot->flags, F_SHIELD, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_GOESON, BP_SECWEAPON, NA, NA, NULL); - addflag(lastot->flags, F_ARMOURRATING, 4, NA, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_SHIELDPENALTY, 5, NA, NULL); addflag(lastot->flags, F_OBHP, 18, 18, NA, NULL); addot(OT_SHIELD, "shield", "A medium-sized metal shield.", MT_METAL, 4.00, OC_ARMOUR, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL); addflag(lastot->flags, F_SHIELD, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_GOESON, BP_SECWEAPON, NA, NA, NULL); - addflag(lastot->flags, F_ARMOURRATING, 6, NA, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_SHIELDPENALTY, 15, NA, NULL); addflag(lastot->flags, F_OBHP, 30, 30, NA, NULL); addot(OT_SHIELDLARGE, "large shield", "A large (if somewhat cumbersome) shield.", MT_METAL, 6.00, OC_ARMOUR, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL); addflag(lastot->flags, F_SHIELD, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_GOESON, BP_SECWEAPON, NA, NA, NULL); - addflag(lastot->flags, F_ARMOURRATING, 8, NA, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_SHIELDPENALTY, 20, NA, NULL); addflag(lastot->flags, F_OBHP, 40, 40, NA, NULL); addot(OT_SHIELDTOWER, "tower shield", "An enormous but very cumbersome shield.", MT_METAL, 11.00, OC_ARMOUR, SZ_HUMAN); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, NULL); addflag(lastot->flags, F_SHIELD, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_GOESON, BP_SECWEAPON, NA, NA, NULL); - addflag(lastot->flags, F_ARMOURRATING, 12, NA, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_SHIELDPENALTY, 30, NA, NULL); addflag(lastot->flags, F_OBHP, 50, 50, NA, NULL); @@ -10537,6 +10533,7 @@ void killob(object_t *o) { if (o->type->id == OT_STAIRSUP) { msg("warning: removing an up staircase!"); dblog("warning: removing an up staircase!"); + assert(1 == 0); } // remove flags conferred by this object @@ -11240,7 +11237,7 @@ void obdie(object_t *o) { if (strlen(desc)) { if (o->pile->owner) { if (isplayer(o->pile->owner)) { - msg("Your %s %s!",noprefix(obname), desc); + msg("^wYour %s %s!",noprefix(obname), desc); } else if (cansee(player, o->pile->owner)) { char monname[BUFLEN]; getlfname(o->pile->owner, monname); @@ -14383,7 +14380,6 @@ int real_takedamage(object_t *o, unsigned int howmuch, int damtype, int wantanno } if (!hpflag || (hpflag->val[0] <= 0)) { - // special cases.... if (damtype == DT_FIRE) { if ((o->material->id == MT_FLESH) && onein(3)) { // fire sometimes roasts flesh diff --git a/save.c b/save.c index 5aa0189..e0a3936 100644 --- a/save.c +++ b/save.c @@ -363,8 +363,8 @@ map_t *loadmap(char *basefile) { c = addcell(m, x, y); // cell info - fscanf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", - &roomid, &celltypeid, &c->known, &c->knownglyph.ch, &c->knownglyph.colour, &c->visited, &c->lit, &c->origlit, &c->littimer,&temphab); + fscanf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", + &roomid, &celltypeid, &c->known, &c->knowntime, &c->knownglyph.ch, &c->knownglyph.colour, &c->visited, &c->lit, &c->origlit, &c->littimer,&temphab); c->habitat = findhabitat(temphab); c->room = findroom(m, roomid); @@ -910,8 +910,8 @@ int savemap(map_t *m) { cell_t *c; c = getcellat(m, x, y); // cell info - fprintf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", - c->room ? c->room->id : -1, c->type->id, c->known, c->knownglyph.ch, c->knownglyph.colour, c->visited,c->lit,c->origlit,c->littimer,c->habitat->id ); + fprintf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", + c->room ? c->room->id : -1, c->type->id, c->known, c->knowntime, c->knownglyph.ch, c->knownglyph.colour, c->visited,c->lit,c->origlit,c->littimer,c->habitat->id ); // cell objects for (o = c->obpile->first ; o ; o = o->next) { fprintf(f, "ob:%ld\n",o->id); diff --git a/spell.c b/spell.c index 00d23f6..d0dfa28 100644 --- a/spell.c +++ b/spell.c @@ -4556,9 +4556,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ donesomething = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE; } - getflags(target->flags, retflag, &nretflags, F_NOBODYPART, F_NONE); + // severed body parts + getflags(target->flags, retflag, &nretflags, F_INJURY, F_NOBODYPART, F_NONE); for (i = 0; i < nretflags; i++) { - if (retflag[i]->val[1] == B_FROMINJURY) { + if ((retflag[i]->id == F_NOBODYPART) && (retflag[i]->val[1] == B_FROMINJURY)) { if (isplayer(target)) { msg("Your %s grows back!", getbodypartname(retflag[0]->val[0])); if (seenbyplayer) *seenbyplayer = B_TRUE; @@ -4571,6 +4572,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } killflag(retflag[i]); donesomething = B_TRUE; + } else if ((retflag[i]->id == F_INJURY) && (retflag[i]->lifetime > 0)) { + killflag(retflag[i]); + donesomething = B_TRUE; } } diff --git a/text.c b/text.c index d56c425..ed23569 100644 --- a/text.c +++ b/text.c @@ -193,6 +193,82 @@ char *getattrname(enum ATTRIB att) { return "?badattrib?"; } +char *getdirname(int dir) { + switch (dir) { + case D_N: + return "North"; + case D_E: + return "East"; + case D_S: + return "South"; + case D_W: + return "West"; + case D_UP: + return "up"; + case D_DOWN: + return "down"; + case D_UNKNOWN: + return "D_UNKNOWN"; + case D_NONE: + return "D_NONE"; + case DC_N: + return "North"; + case DC_NE: + return "Northeast"; + case DC_E: + return "East"; + case DC_SE: + return "Southeast"; + case DC_S: + return "South"; + case DC_SW: + return "Southwest"; + case DC_W: + return "West"; + case DC_NW: + return "Northwest"; + } + return "?errordir?"; +} + +char *getdirnameshort(int dir) { + switch (dir) { + case D_N: + return "N"; + case D_E: + return "E"; + case D_S: + return "S"; + case D_W: + return "W"; + case D_UP: + return "U"; + case D_DOWN: + return "D"; + case D_UNKNOWN: + return "?"; + case D_NONE: + return "-"; + case DC_N: + return "N"; + case DC_NE: + return "NE"; + case DC_E: + return "E"; + case DC_SE: + return "SE"; + case DC_S: + return "S"; + case DC_SW: + return "SW"; + case DC_W: + return "W"; + case DC_NW: + return "NW"; + } + return "?"; +} + int gethitconferlifetime(char *text, int *min, int *max) { int howlong; int localmin = -1,localmax = -1; @@ -950,10 +1026,9 @@ void texttospellopts(char *text, ... ) { va_start(args, text); wantname = va_arg(args, char *); if (wantname) writeto = va_arg(args, void *); - while (wantname) { + while (wantname) { // process this one int foundidx = -1,i; - // process this one - + // validate 'wantname' - must match one of 'validname[]' for (i = 0; validname[i]; i++) { if (streq(validname[i], wantname)) { @@ -963,21 +1038,21 @@ void texttospellopts(char *text, ... ) { } assert(foundidx != -1); + // blank our dest buffer + if (argtype[foundidx] == 'i') { + *((int *)writeto) = 0; + } else if (argtype[foundidx] == 'b') { + *((int *)writeto) = B_FALSE; + } else if (argtype[foundidx] == 's') { + strcpy((char *)writeto, ""); + } + // look for 'wantname' within 'text' for (p = text ; *p ; p++) { if (!strncmp(p, wantname, strlen(wantname)) ) { // found it! char localval[BUFLEN]; char *valfull; - // blank our dest buffer - if (argtype[foundidx] == 'i') { - *((int *)writeto) = 0; - } else if (argtype[foundidx] == 'b') { - *((int *)writeto) = B_FALSE; - } else if (argtype[foundidx] == 's') { - strcpy((char *)writeto, ""); - } - // extract value from text // p will point to "pw:xxx;" strcpy(localval, p + strlen(wantname)); // localval is "xxx;" diff --git a/text.h b/text.h index c545887..e43b2c0 100644 --- a/text.h +++ b/text.h @@ -8,6 +8,8 @@ char *dicetotext(int ndice, int nsides, int bonus, int *min, int *max, char *dic int flip(int ch); char *getattrabbrev(enum ATTRIB att); char *getattrname(enum ATTRIB att); +char *getdirname(int dir); +char *getdirnameshort(int dir); int gethitconferlifetime(char *text, int *min, int *max); char *getpossessive(char *text); char *getdrunktext(flag_t *drunkflag); diff --git a/vaults/playerstart4.vlt b/vaults/playerstart4.vlt index 6937c42..3957173 100644 --- a/vaults/playerstart4.vlt +++ b/vaults/playerstart4.vlt @@ -1,12 +1,12 @@ @id:playerstart_4 @map -####### -#wwwww# +###x### +#ww_ww# #ww.ww# -#w.p._x +x_.p._x #ww.ww# -#wwwww# -####### +#ww_ww# +###x### @end @legend #:cell:rock wall