billr@saab.CNA.TEK.COM (Bill Randle) (07/25/89)
Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu>
Posting-number: Volume 7, Issue 76
Archive-name: NetHack3/Part21
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 21 (of 38)."
# Contents: src/hack.c src/potion.c src/track.c
# Wrapped by billr@saab on Sun Jul 23 21:33:04 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/hack.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/hack.c'\"
else
echo shar: Extracting \"'src/hack.c'\" \(25233 characters\)
sed "s/^X//" >'src/hack.c' <<'END_OF_FILE'
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X
X#include "hack.h"
X
X#if defined(UNIX) && !defined(LINT)
Xstatic const char SCCS_Id[] = "@(#)hack.c 3.0\t88/10/25";
X#endif
X
X/* called on movement:
X 1. when throwing ball+chain far away
X 2. when teleporting
X 3. when walking out of a lit room
X */
Xvoid
Xunsee() {
X register xchar x,y;
X register struct rm *lev;
X
X if(seehx){
X seehx = 0;
X } else
X for(x = u.ux-1; x < u.ux+2; x++)
X for(y = u.uy-1; y < u.uy+2; y++) {
X if(!isok(x, y)) continue;
X lev = &levl[x][y];
X if(!lev->lit && lev->scrsym == ROOM_SYM) {
X lev->scrsym = STONE_SYM;
X lev->new = 1;
X on_scr(x,y);
X }
X }
X}
X
X/* called:
X in apply.c: seeoff(0) - when taking a picture of yourself
X - when donning a blindfold
X in do.c: seeoff(0) - blind after drinking potion
X in do.c: seeoff(1) - go up or down the stairs
X in eat.c: seeoff(0) - blind after eating rotten food
X in mhitu.c: seeoff(0) - blinded by a glowing eye
X in mhitu.c: seeoff(1) - swallowed
X in mthrow.c: seeoff(0) - hit by a cream pie.
X in potion.c: seeoff(0) - quaffing or sniffing a potion of blindness
X in spell.c: seeoff(0) - due to a cursed spellbook
X in trap.c: seeoff(1) - fall through trapdoor
X */
Xvoid
Xseeoff(mode) { /* 1 to redo @, 0 to leave them */
X /* 1 means misc movement, 0 means blindness */
X register xchar x,y;
X register struct rm *lev;
X
X if(u.udispl && mode){
X u.udispl = 0;
X levl[u.udisx][u.udisy].scrsym = news0(u.udisx,u.udisy);
X }
X if(seehx) {
X seehx = 0;
X } else
X if(!mode) {
X for(x = u.ux-1; x < u.ux+2; x++)
X for(y = u.uy-1; y < u.uy+2; y++) {
X if(!isok(x, y)) continue;
X lev = &levl[x][y];
X if(lev->mmask) unpmon(m_at(x,y));
X if(!lev->lit && lev->scrsym == ROOM_SYM) {
X lev->seen = 0;
X atl(x, y, (char)STONE_SYM);
X }
X }
X }
X}
X
Xstatic int
Xmoverock() {
X register xchar rx, ry;
X register struct obj *otmp;
X register struct trap *ttmp;
X register struct monst *mtmp;
X xchar oldrx, oldry;
X
X#ifdef POLYSELF
X if (passes_walls(uasmon)) return 0;
X#endif
X while(otmp = sobj_at(BOULDER, u.ux+u.dx, u.uy+u.dy)) {
X rx = u.ux+2*u.dx;
X ry = u.uy+2*u.dy;
X nomul(0);
X#ifdef POLYSELF
X if (verysmall(uasmon)) {
X pline("You're too small to push that boulder.");
X goto cannot_push;
X }
X#endif
X if(isok(rx,ry) && !IS_ROCK(levl[rx][ry].typ) &&
X (!IS_DOOR(levl[rx][ry].typ) || !(u.dx && u.dy)) &&
X !sobj_at(BOULDER, rx, ry)) {
X if(levl[rx][ry].mmask) {
X mtmp = m_at(rx,ry);
X if(canseemon(mtmp))
X pline("There's %s on the other side.",
X mon_nam(mtmp));
X else
X You("hear a monster behind the boulder.");
X if(flags.verbose)
X pline("Perhaps that's why you cannot move it.");
X goto cannot_push;
X }
X if(ttmp = t_at(rx,ry))
X switch(ttmp->ttyp) {
X case SPIKED_PIT:
X case PIT:
X You("push the boulder into a pit!");
X deltrap(ttmp);
X delobj(otmp);
X if(flags.verbose)
X pline("It completely fills the pit!");
X continue;
X case TRAPDOOR:
X pline("The boulder falls into and plugs a hole in the ground!");
X deltrap(ttmp);
X delobj(otmp);
X continue;
X case LEVEL_TELEP:
X case TELEP_TRAP:
X You("push the boulder and suddenly it disappears!");
X rloco(otmp);
X continue;
X }
X if(levl[rx][ry].typ == DOOR &&
X (levl[rx][ry].doormask & (D_LOCKED | D_CLOSED)))
X goto nopushmsg;
X if(is_pool(rx,ry)) {
X#ifdef STRONGHOLD
X if(levl[rx][ry].typ == DRAWBRIDGE_UP)
X levl[rx][ry].drawbridgemask |= DB_FLOOR;
X else
X#endif
X levl[rx][ry].typ = ROOM;
X mnewsym(rx,ry);
X if(!Blind) prl(rx,ry);
X You("push the boulder into the water.");
X if(flags.verbose && !Blind)
X pline("Now you can cross the water!");
X delobj(otmp);
X continue;
X }
X oldrx = otmp->ox;
X oldry = otmp->oy;
X otmp->ox = rx;
X otmp->oy = ry;
X set_omask(oldrx, oldry);
X levl[rx][ry].omask = 1;
X /* pobj(otmp); */
X if(cansee(rx,ry)) atl(rx,ry,otmp->olet);
X newsym(u.ux+u.dx, u.uy+u.dy);
X
X {
X#ifdef LINT /* static long lastmovetime; */
X long lastmovetime;
X lastmovetime = 0;
X#else
X static long lastmovetime;
X#endif
X /* note: this var contains garbage initially and
X after a restore */
X if(moves > lastmovetime+2 || moves < lastmovetime)
X pline("With great effort you move the boulder.");
X lastmovetime = moves;
X }
X } else {
Xnopushmsg:
X You("try to move the boulder, but in vain.");
X cannot_push:
X#ifdef POLYSELF
X if (throws_rocks(uasmon)) {
X if(!flags.pickup)
X pline("However, you easily can push it aside.");
X else
X pline("However, you easily can pick it up.");
X break;
X }
X#endif
X if((!invent || inv_weight()+90 <= 0) &&
X (!u.dx || !u.dy || (IS_ROCK(levl[u.ux][u.uy+u.dy].typ)
X && IS_ROCK(levl[u.ux+u.dx][u.uy].typ)))
X#ifdef POLYSELF
X || verysmall(uasmon)
X#endif
X )
X {
X pline("However, you can squeeze yourself into a small opening.");
X break;
X } else
X return (-1);
X }
X }
X return (0);
X}
X
Xvoid
Xmovobj(obj, ox, oy)
Xregister struct obj *obj;
Xregister xchar ox, oy;
X{
X register xchar ox2 = obj->ox, oy2= obj->oy;
X
X /* Some dirty programming to get display right */
X freeobj(obj);
X unpobj(obj);
X obj->nobj = fobj;
X fobj = obj;
X obj->ox = ox;
X obj->oy = oy;
X set_omask(ox2,oy2);
X levl[ox][oy].omask = 1;
X}
X
X#ifdef SINKS
Xstatic
Xvoid
Xdosinkfall() {
X register struct obj *obj;
X
X# ifdef POLYSELF
X if (is_floater(uasmon)) {
X You("wobble unsteadily for a moment.");
X } else {
X# endif
X You("crash to the floor!");
X losehp((rn1(10, 20 - (int)ACURR(A_CON))),"fall onto a sink");
X if(levl[u.ux][u.uy].omask)
X for(obj=fobj; obj; obj=obj->nobj)
X if(obj->ox == u.ux && obj->oy == u.uy &&
X obj->olet == WEAPON_SYM) {
X You("fell on %s.",doname(obj));
X losehp(rn2(3),"fall onto a sink");
X }
X# ifdef POLYSELF
X }
X# endif
X
X HLevitation = (HLevitation & ~TIMEOUT) + 1;
X if(uleft && uleft->otyp == RIN_LEVITATION) {
X obj = uleft;
X Ring_off(obj);
X off_msg(obj);
X }
X if(uright && uright->otyp == RIN_LEVITATION) {
X obj = uright;
X Ring_off(obj);
X off_msg(obj);
X }
X if(uarmf && uarmf->otyp == LEVITATION_BOOTS) {
X obj = uarmf;
X (void)Boots_off();
X off_msg(obj);
X }
X HLevitation--;
X}
X#endif
X
Xstatic boolean
Xis_edge(x,y)
Xregister xchar x,y;
X/* return true if (x,y) is on the edge of a room
X * we cannot rely on IS_DOOR(levl[x][y].typ) because some of the stronghold
X * "rooms" are actually outside areas without doors
X */
X{
X register int roomno = inroom(x,y);
X
X if(roomno < 0) return FALSE;
X return((x == rooms[roomno].lx - 1) || (x == rooms[roomno].hx + 1) ||
X (y == rooms[roomno].ly - 1) || (y == rooms[roomno].hy + 1));
X}
X
Xboolean
Xmay_dig(x,y)
Xregister xchar x,y;
X/* intended to be called only on ROCKs */
X{
Xreturn (!(IS_STWALL(levl[x][y].typ) && (levl[x][y].diggable & W_NONDIGGABLE)));
X}
X
Xstatic boolean
Xbad_rock(x,y)
Xregister xchar x,y;
X{
X return(IS_ROCK(levl[x][y].typ)
X#ifdef POLYSELF
X && !passes_walls(uasmon)
X && (!tunnels(uasmon) || needspick(uasmon) || !may_dig(x,y))
X#endif
X );
X}
X
Xvoid
Xdomove() {
X register struct monst *mtmp = (struct monst *)0;
X register struct rm *tmpr,*ust;
X register xchar x,y;
X struct trap *trap;
X
X u_wipe_engr(rnd(5));
X
X if(inv_weight() > 0){
X You("collapse under your load.");
X nomul(0);
X return;
X }
X if(u.uswallow) {
X u.dx = u.dy = 0;
X x = u.ux = u.ustuck->mx;
X y = u.uy = u.ustuck->my;
X } else {
X x = u.ux + u.dx;
X y = u.uy + u.dy;
X if(Stunned || (Confusion && !rn2(5))) {
X register int tries = 0;
X
X do {
X if(tries++ > 50) {
X nomul(0);
X return;
X }
X confdir();
X x = u.ux + u.dx;
X y = u.uy + u.dy;
X } while(!isok(x, y) || bad_rock(x, y));
X }
X if(!isok(x, y)) {
X nomul(0);
X return;
X }
X if((trap = t_at(x, y)) && trap->tseen)
X nomul(0);
X if(u.ustuck && (x != u.ustuck->mx ||
X y != u.ustuck->my)) {
X if(dist(u.ustuck->mx, u.ustuck->my) > 2) {
X /* perhaps it fled (or was teleported or ... ) */
X u.ustuck = 0;
X } else {
X#ifdef POLYSELF
X /* If polymorphed into a sticking monster,
X * u.ustuck means it's stuck to you, not you
X * to it.
X */
X if (sticks(uasmon)) {
X kludge("You release %s.",
X mon_nam(u.ustuck));
X u.ustuck = 0;
X } else {
X#endif
X kludge("You cannot escape from %s!",
X mon_nam(u.ustuck));
X nomul(0);
X return;
X#ifdef POLYSELF
X }
X#endif
X }
X }
X }
X
X u.ux0 = u.ux;
X u.uy0 = u.uy;
X /* attack monster */
X tmpr = &levl[x][y];
X if (tmpr->mmask) {
X mtmp = m_at(x,y);
X /* Don't attack if you're running */
X if (flags.run && !mtmp->mimic &&
X (Blind ? Telepat : (!mtmp->minvis || See_invisible))) {
X nomul(0);
X flags.move = 0;
X return;
X }
X }
X if(mtmp || u.uswallow) {
X nomul(0);
X gethungry();
X if(multi < 0) return; /* we just fainted */
X
X /* try to attack; note that it might evade */
X if(attack(u.uswallow ? u.ustuck : mtmp))
X return;
X }
X /* not attacking an animal, so we try to move */
X#ifdef POLYSELF
X if(!uasmon->mmove) {
X You("are rooted %s.", Levitation ? "in place"
X : "to the ground");
X nomul(0);
X return;
X }
X#endif
X if(u.utrap) {
X if(u.utraptype == TT_PIT) {
X if(flags.verbose)
X You("are still in a pit.");
X u.utrap--;
X } else if (u.utraptype == TT_WEB) {
X if(flags.verbose)
X You("are stuck to the web.");
X u.utrap--;
X } else {
X if(flags.verbose)
X You("are caught in a bear trap.");
X if((u.dx && u.dy) || !rn2(5)) u.utrap--;
X }
X return;
X }
X /* check for physical obstacles */
X#ifdef POLYSELF
X if (!passes_walls(uasmon)) {
X#endif
X#ifdef STRONGHOLD
X if(dlevel == stronghold_level && is_db_wall(x,y)) {
X pline("The drawbridge is up!");
X nomul(0);
X return;
X }
X#endif
X if(IS_DOOR(tmpr->typ) && (tmpr->doormask & (D_LOCKED | D_CLOSED))
X#ifdef POLYSELF
X && !amorphous(uasmon)
X#endif
X ){
X flags.move = 0;
X if(x == u.ux || y == u.uy) {
X if (Blind || Stunned || ACURR(A_DEX) < 10 || Fumbling)
X pline("Ouch! You bump into a door.");
X else pline("That door is closed.");
X }
X nomul(0);
X return;
X }
X#ifdef POLYSELF
X }
X#endif
X ust = &levl[u.ux][u.uy];
X if(bad_rock(x,y) ||
X (u.dx && u.dy && (IS_DOOR(tmpr->typ) || IS_DOOR(ust->typ)))){
X flags.move = 0;
X nomul(0);
X return;
X }
X if(moverock() < 0) return;
X if(u.dx && u.dy && bad_rock(u.ux,y) &&
X bad_rock(x,u.uy)) {
X#ifdef POLYSELF
X if (bigmonst(uasmon)) {
X Your("body is too large to fit through.");
X nomul(0);
X return;
X }
X#endif
X if (invent && inv_weight()+40 > 0) {
X You("are carrying too much to get through.");
X nomul(0);
X return;
X }
X }
X if(Punished &&
X dist2(x, y, uchain->ox, uchain->oy) > 2) {
X if(carried(uball)) {
X movobj(uchain, u.ux, u.uy);
X goto nodrag;
X }
X
X if(dist2(x, y, uball->ox, uball->oy) < 3) {
X /* leave ball, move chain under/over ball */
X movobj(uchain, uball->ox, uball->oy);
X goto nodrag;
X }
X
X if(inv_weight() + (int)(uball->owt >> 1) > 0) {
X You("cannot %sdrag the heavy iron ball.",
X invent ? "carry all that and also " : "");
X nomul(0);
X return;
X }
X
X movobj(uball, uchain->ox, uchain->oy);
X unpobj(uball); /* BAH %% */
X uchain->ox = u.ux;
X uchain->oy = u.uy;
X ust->omask = 1;
X nomul(-2);
X nomovemsg = "";
X nodrag: ;
X }
X#ifdef POLYSELF
X if (tunnels(uasmon) && !needspick(uasmon) && IS_ROCK(tmpr->typ)) {
X static char *digtxt;
X
X if(dig_pos.x != x || dig_pos.y != y
X || dig_level != dlevel || dig_down) {
X dig_down = FALSE;
X dig_pos.x = x;
X dig_pos.y = y;
X dig_level = dlevel;
X dig_effort = 30;
X You("start chewing a hole in the rock.");
X return;
X } else if ((dig_effort += 30) < 100) {
X if(flags.verbose)
X You("continue chewing the rock up.");
X return;
X } else {
X if (IS_WALL(tmpr->typ)) {
X digtxt = "You chew a hole in the wall.";
X tmpr->typ = DOOR;
X } else if (tmpr->typ==SDOOR) {
X digtxt = "You chew through a secret door.";
X tmpr->typ = DOOR;
X if(!(tmpr->doormask & D_TRAPPED))
X tmpr->doormask = D_BROKEN;
X } else {
X digtxt = "You chew a passage through the rock.";
X tmpr->typ = CORR;
X }
X mnewsym(x, y);
X prl(x, y);
X pline(digtxt);
X if(IS_DOOR(tmpr->typ) && (tmpr->doormask & D_TRAPPED)) {
X b_trapped("door");
X tmpr->doormask = D_NODOOR;
X }
X dig_level = -1;
X }
X }
X#endif
X u.ux += u.dx;
X u.uy += u.dy;
X if(flags.run) {
X if(IS_DOOR(tmpr->typ) ||
X#ifdef POLYSELF
X (IS_ROCK(tmpr->typ)) ||
X#endif
X (xupstair == u.ux && yupstair == u.uy) ||
X (xdnstair == u.ux && ydnstair == u.uy)
X#ifdef STRONGHOLD
X || (xupladder == u.ux && yupladder == u.uy)
X || (xdnladder == u.ux && ydnladder == u.uy)
X#endif
X#ifdef FOUNTAINS
X || IS_FOUNTAIN(tmpr->typ)
X#endif
X#ifdef THRONES
X || IS_THRONE(tmpr->typ)
X#endif
X#ifdef SINKS
X || IS_SINK(tmpr->typ)
X#endif
X#ifdef ALTARS
X || IS_ALTAR(tmpr->typ)
X#endif
X )
X nomul(0);
X }
X#ifdef POLYSELF
X if (hides_under(uasmon))
X u.uundetected = (levl[u.ux][u.uy].omask || levl[u.ux][u.uy].gmask);
X else if (u.dx || u.dy) { /* i.e. piercer */
X if (u.usym == S_MIMIC_DEF)
X u.usym = S_MIMIC;
X u.uundetected = 0;
X }
X#endif
X
X/*
X if(u.udispl) {
X u.udispl = 0;
X newsym(u.ux0,u.uy0);
X }
X*/
X if(!Blind) {
X register xchar backx = u.ux0 - u.dx; /* one step beyond old pos */
X register xchar backy = u.uy0 - u.dy;
X register xchar frontx = u.ux + u.dx; /* one step beyond new pos */
X register xchar fronty = u.uy + u.dy;
X register boolean newedge = is_edge(u.ux,u.uy);
X register boolean oldedge = is_edge(u.ux0,u.uy0);
X
X /* ust is old position, tmpr is new position */
X if(oldedge && newedge && inroom(u.ux0,u.uy0) == inroom(u.ux,u.uy)) {
X /* moving along wall */
X nose1(backx,backy);
X prl1(frontx,fronty);
X
X } else if(oldedge || newedge) {
X if(isok(backx,backy) && levl[backx][backy].lit)
X setsee();
X else
X nose1(backx,backy);
X
X if(isok(frontx,fronty) && levl[frontx][fronty].lit)
X setsee();
X else {
X prl1(frontx,fronty);
X prl1(u.ux,u.uy); /* make sure side walls are seen */
X }
X
X } else if(!tmpr->lit) {
X /* we haven't crossed an edge, so old & new are both light or
X * both dark. if both light, we need do nothing.
X */
X nose1(backx,backy);
X prl1(frontx,fronty);
X }
X
X } else {
X pru();
X }
X#ifdef WALKIES
X check_leash(u.ux0,u.uy0);
X#endif
X if(u.ux0 != u.ux || u.uy0 != u.uy) u.umoved = TRUE;
X spoteffects();
X}
X
Xvoid
Xspoteffects()
X{
X register struct trap *trap;
X
X if(is_pool(u.ux,u.uy) && !(Levitation || Wwalking
X#ifdef POLYSELF
X || is_flyer(uasmon)
X#endif
X ))
X drown(); /* not necessarily fatal */
X else {
X (void) inshop();
X#ifdef SINKS
X if(IS_SINK(levl[u.ux][u.uy].typ) && Levitation)
X dosinkfall();
X#endif
X if(!flags.nopick &&
X (levl[u.ux][u.uy].omask || levl[u.ux][u.uy].gmask))
X pickup(1);
X else read_engr_at(u.ux,u.uy);
X if(trap = t_at(u.ux,u.uy))
X dotrap(trap); /* fall into pit, arrow trap, etc. */
X }
X
X}
X
Xint
Xdopickup() {
X /* uswallow case added by GAN 01/29/87 */
X if(u.uswallow) {
X if (is_animal(u.ustuck->data)) {
X You("pick up %s's tongue.", mon_nam(u.ustuck));
X pline("But it's kind of slimy, so you drop it.");
X } else
X pline("You don't %s anything in here to pick up.",
X Blind ? "feel" : "see");
X return(1);
X }
X if(levl[u.ux][u.uy].omask == 0 && levl[u.ux][u.uy].gmask == 0) {
X pline("There is nothing here to pick up.");
X return(0);
X }
X if(Levitation) {
X You("cannot reach the floor.");
X return(1);
X }
X pickup(0);
X return(1);
X}
X
X/* stop running if we see something interesting */
X/* turn around a corner if that is the only way we can proceed */
X/* do not turn left or right twice */
Xvoid
Xlookaround() {
X register int x, y, i, x0, y0, m0, i0 = 9, corrct = 0, noturn = 0;
X register struct monst *mtmp;
X#ifdef LINT
X /* suppress "used before set" message */
X x0 = y0 = 0;
X#endif
X if(Blind || flags.run == 0) return;
X for(x = u.ux-1; x <= u.ux+1; x++) for(y = u.uy-1; y <= u.uy+1; y++) {
X if(x == u.ux && y == u.uy) continue;
X if(levl[x][y].mmask && (mtmp = m_at(x,y)) && !mtmp->mimic &&
X (!mtmp->minvis || See_invisible)) {
X if((flags.run != 1 && !mtmp->mtame) || (x == u.ux+u.dx && y == u.uy+u.dy))
X goto stop;
X } else mtmp = 0;
X if(levl[x][y].typ == STONE) continue;
X if(x == u.ux-u.dx && y == u.uy-u.dy) continue;
X {
X register uchar sym = levl[x][y].scrsym;
X
X if (IS_ROCK(levl[x][y].typ) || sym == ROOM_SYM) continue;
X else if (sym == DOOR_SYM) {
X if(x != u.ux && y != u.uy) continue;
X if(flags.run != 1) goto stop;
X goto bcorr;
X } else if (sym == CORR_SYM) {
X bcorr:
X if(levl[u.ux][u.uy].typ != ROOM) {
X if(flags.run == 1 || flags.run == 3) {
X i = dist2(x,y,u.ux+u.dx,u.uy+u.dy);
X if(i > 2) continue;
X if(corrct == 1 && dist2(x,y,x0,y0) != 1)
X noturn = 1;
X if(i < i0) {
X i0 = i;
X x0 = x;
X y0 = y;
X m0 = mtmp ? 1 : 0;
X }
X }
X corrct++;
X }
X continue;
X } else if (sym == TRAP_SYM) {
X if(flags.run == 1) goto bcorr; /* if you must */
X if(x == u.ux+u.dx && y == u.uy+u.dy) goto stop;
X continue;
X } else if (sym == POOL_SYM) {
X /* pools only stop you if directly in front, and stop
X * you even if you are running
X */
X if(!Levitation &&
X#ifdef POLYSELF
X !is_flyer(uasmon) &&
X#endif
X /* No Wwalking check; otherwise they'd be able
X * to test boots by trying to SHIFT-direction
X * into a pool and seeing if the game allowed it
X */
X x == u.ux+u.dx && y == u.uy+u.dy) goto stop;
X continue;
X } else { /* e.g. objects or trap or stairs */
X if(flags.run == 1) goto bcorr;
X if(mtmp) continue; /* d */
X }
X stop:
X nomul(0);
X return;
X }
X }
X if(corrct > 1 && flags.run == 2) goto stop;
X if((flags.run == 1 || flags.run == 3) && !noturn && !m0 && i0 &&
X (corrct == 1 || (corrct == 2 && i0 == 1))) {
X /* make sure that we do not turn too far */
X if(i0 == 2) {
X if(u.dx == y0-u.uy && u.dy == u.ux-x0)
X i = 2; /* straight turn right */
X else
X i = -2; /* straight turn left */
X } else if(u.dx && u.dy) {
X if((u.dx == u.dy && y0 == u.uy) ||
X (u.dx != u.dy && y0 != u.uy))
X i = -1; /* half turn left */
X else
X i = 1; /* half turn right */
X } else {
X if((x0-u.ux == y0-u.uy && !u.dy) ||
X (x0-u.ux != y0-u.uy && u.dy))
X i = 1; /* half turn right */
X else
X i = -1; /* half turn left */
X }
X i += u.last_str_turn;
X if(i <= 2 && i >= -2) {
X u.last_str_turn = i;
X u.dx = x0-u.ux, u.dy = y0-u.uy;
X }
X }
X}
X
X/* something like lookaround, but we are not running */
X/* react only to monsters that might hit us */
Xint
Xmonster_nearby() {
X register int x,y;
X register struct monst *mtmp;
X
X if(!Blind)
X for(x = u.ux-1; x <= u.ux+1; x++)
X for(y = u.uy-1; y <= u.uy+1; y++) {
X if(x == u.ux && y == u.uy) continue;
X if(levl[x][y].mmask && (mtmp = m_at(x,y)) && !mtmp->mimic &&
X !mtmp->mtame && !mtmp->mpeaceful &&
X !noattacks(mtmp->data) &&
X !mtmp->mfroz && !mtmp->msleep && /* aplvax!jcn */
X (!mtmp->minvis || See_invisible) &&
X !onscary(u.ux, u.uy, mtmp))
X return(1);
X }
X return(0);
X}
X
Xint
Xcansee(x,y)
Xxchar x,y;
X{
X if(Blind || u.uswallow) return(0);
X if(dist(x,y) < 3) return(1);
X if(IS_ROCK(levl[x][y].typ) && levl[u.ux][u.uy].typ == CORR &&
X !levl[u.ux][u.uy].lit)
X return(0);
X if(levl[x][y].lit &&
X ((seelx <= x && x <= seehx && seely <= y && y <= seehy) ||
X (seelx2 <= x && x <= seehx2 && seely2 <= y && y <= seehy2)))
X return(1);
X return(0);
X}
X
Xint
Xsgn(a)
X register int a;
X{
X return((a > 0) ? 1 : (a == 0) ? 0 : -1);
X}
X
Xvoid
Xgetcorners(lx1,hx1,ly1,hy1,lx2,hx2,ly2,hy2)
Xxchar *lx1,*hx1,*ly1,*hy1,*lx2,*hx2,*ly2,*hy2;
X/* return corners of one or two rooms player is in, so we can tell what areas
X * can be seen, or otherwise affected by room-specific things. (two rooms are
X * possible when in a doorway of the stronghold)
X * the player is already known to be in at least one room
X */
X{
X register int uroom1,uroom2;
X register xchar ux,uy;
X
X uroom1 = inroom(u.ux,u.uy);
X *lx1 = rooms[uroom1].lx - 1;
X *hx1 = rooms[uroom1].hx + 1;
X *ly1 = rooms[uroom1].ly - 1;
X *hy1 = rooms[uroom1].hy + 1;
X
X if(!IS_DOOR(levl[u.ux][u.uy].typ)) {
X *lx2 = 1;
X *hx2 = 0;
X *ly2 = 1;
X *hy2 = 0;
X } else {
X for(ux = u.ux-1; ux <= u.ux+1; ux++)
X for(uy = u.uy-1; uy <= u.uy+1; uy++) {
X if(IS_ROCK(levl[ux][uy].typ) ||
X IS_DOOR(levl[ux][uy].typ)) continue;
X /* might have side-by-side walls, in which case
X * should only be able to see one room */
X uroom2 = inroom(ux,uy);
X if(uroom2 >= 0 && uroom2 != uroom1 &&
X rooms[uroom2].rlit) {
X *lx2 = rooms[uroom2].lx - 1;
X *ly2 = rooms[uroom2].ly - 1;
X *hx2 = rooms[uroom2].hx + 1;
X *hy2 = rooms[uroom2].hy + 1;
X return;
X }
X }
X *lx2 = 1;
X *hx2 = 0;
X *ly2 = 1;
X *hy2 = 0;
X }
X}
X
Xvoid
Xsetsee() {
X register int x, y;
X
X if(Blind) {
X pru();
X return;
X }
X if(!levl[u.ux][u.uy].lit) {
X seelx = u.ux-1;
X seehx = u.ux+1;
X seely = u.uy-1;
X seehy = u.uy+1;
X seelx2 = seely2 = 1;
X seehx2 = seehy2 = 0;
X } else {
X getcorners(&seelx,&seehx,&seely,&seehy,
X &seelx2,&seehx2,&seely2,&seehy2);
X }
X for(y = seely; y <= seehy; y++)
X for(x = seelx; x <= seehx; x++) {
X prl(x,y);
X }
X for(y = seely2; y <= seehy2; y++)
X for(x = seelx2; x <= seehx2; x++) {
X prl(x,y);
X }
X if(!levl[u.ux][u.uy].lit) seehx = 0; /* seems necessary elsewhere */
X else {
X if(seely == u.uy) for(x = u.ux-1; x <= u.ux+1; x++) prl(x,seely-1);
X if(seehy == u.uy) for(x = u.ux-1; x <= u.ux+1; x++) prl(x,seehy+1);
X if(seelx == u.ux) for(y = u.uy-1; y <= u.uy+1; y++) prl(seelx-1,y);
X if(seehx == u.ux) for(y = u.uy-1; y <= u.uy+1; y++) prl(seehx+1,y);
X }
X}
X
Xvoid
Xnomul(nval)
X register int nval;
X{
X if(multi < nval) return; /* This is a bug fix by ab@unido */
X multi = nval;
X flags.mv = flags.run = 0;
X}
X
Xvoid
Xlosehp(n, knam)
X register int n;
X register char *knam;
X{
X#ifdef POLYSELF
X if (u.mtimedone) {
X u.mh -= n;
X if (u.mhmax < u.mh) u.mhmax = u.mh;
X flags.botl = 1;
X if (u.mh < 1) rehumanize();
X return;
X }
X#endif
X u.uhp -= n;
X if(u.uhp > u.uhpmax)
X u.uhpmax = u.uhp; /* perhaps n was negative */
X flags.botl = 1;
X if(u.uhp < 1) {
X killer = knam; /* the thing that killed you */
X You("die...");
X done("died");
X } else if(u.uhp*10 < u.uhpmax && moves-wailmsg > 50 && n > 0){
X wailmsg = moves;
X if(index("WEV", pl_character[0])) {
X if (u.uhp == 1)
X pline("%s is about to die.", pl_character);
X else if (4 <= (!!(HTeleportation & INTRINSIC)) +
X (!!(HSee_invisible & INTRINSIC)) +
X (!!(HPoison_resistance & INTRINSIC)) +
X (!!(HCold_resistance & INTRINSIC)) +
X (!!(HShock_resistance & INTRINSIC)) +
X (!!(HFire_resistance & INTRINSIC)) +
X (!!(HSleep_resistance & INTRINSIC)) +
X (!!(HDisint_resistance & INTRINSIC)) +
X (!!(HTeleport_control & INTRINSIC)) +
X (!!(Fast & INTRINSIC)) +
X (!!(HInvis & INTRINSIC)))
X pline("%s, all your powers will be lost...",
X pl_character);
X else
X pline("%s, your life force is running out.",
X pl_character);
X } else {
X if(u.uhp == 1)
X You("hear the wailing of the Banshee...");
X else
X You("hear the howling of the CwnAnnwn...");
X }
X }
X}
X
Xint
Xweight_cap() {
X register int carrcap;
X
X#ifdef HARD
X carrcap = 5 * (((ACURR(A_STR) > 18) ? 20 : ACURR(A_STR)) + u.ulevel);
X#else
X carrcap = 5 * u.ulevel; /* New strength stewr 870807 */
X if (ACURR(A_STR) < 19) carrcap += 5 * ACURR(A_STR);
X if (ACURR(A_STR) > 18) carrcap += ACURR(A_STR) - 18 + 90;
X if (ACURR(A_STR) > 68) carrcap += ACURR(A_STR) - 68;
X if (ACURR(A_STR) > 93) carrcap += ACURR(A_STR) - 93;
X if (ACURR(A_STR) > 108) carrcap += 2 * (ACURR(A_STR) - 108);
X if (ACURR(A_STR) > 113) carrcap += 5 * (ACURR(A_STR) - 113);
X if (ACURR(A_STR) == 118) carrcap += 100;
X#endif
X#ifdef POLYSELF
X if (u.mtimedone) {
X /* consistent with can_carry() in mon.c */
X if (u.usym==S_NYMPH) carrcap = MAX_CARR_CAP;
X else if (!uasmon->cwt)
X carrcap = (carrcap * uasmon->mlevel * 6)/45;
X else carrcap = (carrcap * uasmon->cwt / 45);
X }
X#endif
X if(Levitation) /* pugh@cornell */
X carrcap = MAX_CARR_CAP;
X else {
X if(carrcap > MAX_CARR_CAP) carrcap = MAX_CARR_CAP;
X if(Wounded_legs & LEFT_SIDE) carrcap -= 10;
X if(Wounded_legs & RIGHT_SIDE) carrcap -= 10;
X }
X return(carrcap);
X}
X
Xint
Xinv_weight() {
X register struct obj *otmp = invent;
X#ifdef LINT /* long to int conversion */
X register int wt = 0;
X#else
X register int wt = (int)((u.ugold + 500L)/1000L);
X#endif /* LINT */
X while(otmp){
X#ifdef POLYSELF
X if (otmp->otyp != BOULDER || !throws_rocks(uasmon))
X#endif
X wt += otmp->owt;
X otmp = otmp->nobj;
X }
X return(wt - weight_cap());
X}
X
Xint
Xinv_cnt() {
X register struct obj *otmp = invent;
X register int ct = 0;
X
X while(otmp){
X ct++;
X otmp = otmp->nobj;
X }
X return(ct);
X}
X
X#ifdef STUPID_CPP /* otherwise these functions are macros in hack.h */
Xchar
Xyn() {
X return(yn_function(ynchars, 'n'));
X}
X
Xchar
Xynq() {
X return(yn_function(ynqchars, 'q'));
X}
X
Xchar
Xynaq() {
X return(yn_function(ynaqchars, 'y'));
X}
X
Xchar
Xnyaq() {
X return(yn_function(nyaqchars, 'n'));
X}
X
Xint
Xmax(a,b) int a,b; {
X return((a > b) ? a : b);
X}
X
Xint
Xmin(a,b) int a,b; {
X return((a < b) ? a : b);
X}
X
Xchar *
Xplur(x) long x; {
X return((x == 1L) ? "" : "s");
X}
X
Xvoid
Xmakeknown(x) unsigned x; {
X objects[x].oc_name_known = 1;
X}
X#endif /* STUPID_CPP */
END_OF_FILE
if test 25233 -ne `wc -c <'src/hack.c'`; then
echo shar: \"'src/hack.c'\" unpacked with wrong size!
fi
# end of 'src/hack.c'
fi
if test -f 'src/potion.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/potion.c'\"
else
echo shar: Extracting \"'src/potion.c'\" \(25055 characters\)
sed "s/^X//" >'src/potion.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)potion.c 3.0 88/11/11
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X
X#include "hack.h"
X
Xstatic int nothing, unkn;
X#ifdef WORM
Xboolean notonhead = FALSE;
X#endif
X
Xstatic const char beverages[] = { POTION_SYM, 0 };
X
Xvoid
Xmake_confused(xtime,talk)
Xlong xtime;
Xboolean talk;
X{
X long old = HConfusion;
X
X if (!xtime && old) {
X if (talk) {
X if (Hallucination) You("feel less trippy now.");
X else You("feel less confused now.");
X }
X flags.botl = 1;
X }
X if (xtime && !old)
X flags.botl = 1;
X HConfusion = xtime;
X}
X
Xvoid
Xmake_stunned(xtime,talk)
Xlong xtime;
Xboolean talk;
X{
X long old = HStun;
X
X if (!xtime && old) {
X if (talk) {
X if (Hallucination) You("feel less wobbly now.");
X else You("feel a bit steadier now.");
X }
X flags.botl = 1;
X }
X if (xtime && !old) {
X if (talk)
X You("stagger...");
X flags.botl = 1;
X }
X HStun = xtime;
X}
X
Xvoid
Xmake_sick(xtime, talk)
Xlong xtime;
Xboolean talk;
X{
X long old = Sick;
X
X#ifdef POLYSELF
X if (xtime && u.usym == S_FUNGUS) return;
X#endif
X if (!xtime && old) {
X if (talk) pline("What a relief!");
X flags.botl = 1;
X }
X if (!old && xtime) {
X You("feel deathly sick.");
X flags.botl = 1;
X }
X Sick = xtime;
X}
X
Xvoid
Xmake_blinded(xtime, talk)
Xlong xtime;
Xboolean talk;
X{
X long old = Blinded;
X
X if (!xtime && old) {
X if (talk) {
X if (Hallucination) pline("Oh, like, wow! What a rush.");
X else You("can see again.");
X }
X flags.botl = 1;
X }
X if (xtime && !old && !Blindfolded) {
X if (talk) {
X if (Hallucination)
X pline("Bummer! Everything is dark! Help!");
X else
X pline("A cloud of darkness falls upon you.");
X }
X seeoff(0);
X flags.botl = 1;
X }
X Blinded = xtime;
X if (!Blind)
X setsee();
X}
X
Xvoid
Xmake_hallucinated(xtime, talk)
Xlong xtime;
Xboolean talk;
X{
X long old = Hallucination;
X register struct monst *mtmp;
X
X if (!xtime && old ) {
X if (!Blind && talk) pline("Everything looks SO boring now.");
X for (mtmp=fmon; mtmp; mtmp=mtmp->nmon)
X if ((Blind && Telepat) || canseemon(mtmp))
X atl(mtmp->mx, mtmp->my, (!mtmp->mappearance ||
X Protection_from_shape_changers)
X ? mtmp->data->mlet : mtmp->mappearance);
X flags.botl = 1;
X }
X if (xtime && !old ) {
X if (!Blind && talk) pline("Oh wow! Everything looks so cosmic!");
X flags.botl = 1;
X }
X Hallucination = xtime;
X setsee();
X}
X
Xstatic void
Xghost_from_bottle()
X{
X register struct monst *mtmp;
X
X if(!(mtmp = makemon(&mons[PM_GHOST],u.ux,u.uy))){
X pline("This bottle turns out to be empty.");
X return;
X }
X mnexto(mtmp);
X pline("As you open the bottle, an enormous ghost emerges!");
X if(flags.verbose)
X You("are frightened to death, and unable to move.");
X nomul(-3);
X nomovemsg = "You regain your composure.";
X}
X
Xint
Xdodrink() {
X register struct obj *otmp;
X
X#ifdef FOUNTAINS
X
X /* Is there something to drink here, i.e., a fountain? */
X if (IS_FOUNTAIN(levl[u.ux][u.uy].typ)) {
X pline("Drink from the fountain? ");
X if(yn() == 'y') {
X (void) drinkfountain();
X return(1);
X }
X }
X
X#endif /* FOUNTAINS /**/
X#ifdef SINKS
X /* Now, check for kitchen sinks... */
X if (IS_SINK(levl[u.ux][u.uy].typ)) {
X pline("Drink from the sink? ");
X if (yn() == 'y') {
X (void) drinksink();
X return 1;
X }
X }
X#endif
X
X unkn = 0;
X otmp = getobj(beverages, "drink");
X if(!otmp) return(0);
X if(objects[otmp->otyp].oc_descr && !strcmp(objects[otmp->otyp].oc_descr, "smoky") && !rn2(13)) {
X ghost_from_bottle();
X useup(otmp);
X return(1);
X }
X if(objects[otmp->otyp].oc_descr && !strcmp(objects[otmp->otyp].oc_descr, "glowing") && !rn2(13)) {
X djinni_from_bottle(otmp);
X useup(otmp);
X return(1);
X }
X return dopotion(otmp);
X}
X
Xint
Xdopotion(otmp)
Xregister struct obj *otmp;
X{
X int retval;
X
X nothing = 0;
X if((retval = peffects(otmp)) >= 0) return(retval);
X
X if(nothing) {
X unkn++;
X You("have a %s feeling for a moment, then it passes.",
X Hallucination ? "normal" : "peculiar");
X }
X if(otmp->dknown && !objects[otmp->otyp].oc_name_known) {
X if(!unkn) {
X makeknown(otmp->otyp);
X more_experienced(0,10);
X } else if(!objects[otmp->otyp].oc_uname)
X docall(otmp);
X }
X useup(otmp);
X return(1);
X}
X
Xint
Xpeffects(otmp)
X register struct obj *otmp;
X{
X register int i, ii, isdone;
X
X switch(otmp->otyp){
X case POT_RESTORE_ABILITY:
X#ifdef SPELLS
X case SPE_RESTORE_ABILITY:
X#endif
X unkn++;
X if(otmp->cursed) {
X pline("Ulch! This makes you feel mediocre!");
X break;
X } else {
X pline("Wow! This makes you feel %s!",
X (otmp->blessed) ? "great" : "good");
X i = rn2(A_MAX); /* start at a random point */
X for(isdone = ii = 0; !isdone && ii < A_MAX; ii++) {
X if(ABASE(i) < AMAX(i)) {
X ABASE(i) = AMAX(i);
X /* only first found if not blessed */
X isdone = !(otmp->blessed);
X flags.botl = 1;
X }
X if(++i >= A_MAX) i = 0;
X }
X }
X break;
X case POT_HALLUCINATION:
X if (Hallucination) nothing++;
X make_hallucinated(Hallucination +
X rn1(200, 600 - 300*bcsign(otmp)), TRUE);
X break;
X case POT_WATER:
X if(!otmp->blessed && !otmp->cursed) {
X pline("This tastes like %swater.",
X otmp->spe == -1 ? "impure " :
X !otmp->rustfree ? "" : "mineral "
X );
X lesshungry(rnd(otmp->spe == -1 ? 3 : 10));
X break;
X }
X unkn++;
X#ifdef POLYSELF
X if(is_undead(uasmon) || is_demon(uasmon) ||
X u.ualigntyp == U_CHAOTIC) {
X if(otmp->blessed) {
X pline("This burns like acid!");
X losehp(d(2,6), "potion of holy water");
X } else if(otmp->cursed) {
X You("feel quite proud of yourself.");
X healup(d(2,6),0,0,0);
X }
X } else
X#endif
X if(otmp->blessed) {
X You("feel full of awe.");
X make_sick(0L,TRUE);
X#ifdef POLYSELF
X if (u.ulycn != -1) {
X You("feel purified.");
X if(uasmon == &mons[u.ulycn] && !Polymorph_control)
X rehumanize();
X u.ulycn = -1;
X }
X#endif
X /* make_confused(0L,TRUE); */
X } else {
X if(u.ualigntyp == U_LAWFUL) {
X pline("This burns like acid!");
X losehp(d(2,6), "potion of unholy water");
X } else
X You("feel full of dread.");
X }
X break;
X case POT_BOOZE:
X unkn++;
X pline("Ooph! This tastes like %s!",
X Hallucination ? "furniture polish" : "liquid fire");
X if (!otmp->blessed) make_confused(HConfusion + d(3,8),FALSE);
X /* the whiskey makes us feel better */
X if(u.uhp < u.uhpmax) losehp(-1, "bottle of whiskey");
X lesshungry(10 * (2 + bcsign(otmp)));
X if(otmp->cursed) {
X You("pass out.");
X multi = -rnd(15);
X nomovemsg = "You awake with a headache.";
X }
X break;
X case POT_ENLIGHTENMENT:
X if(otmp->cursed) {
X unkn++;
X You("have an uneasy feeling...");
X } else {
X You("feel self-knowledgable...");
X if (otmp->blessed) {
X adjattrib(A_INT, 1, FALSE);
X adjattrib(A_WIS, 1, FALSE);
X }
X more();
X enlightenment();
X pline("The feeling subsides.");
X }
X break;
X case POT_INVISIBILITY:
X#ifdef SPELLS
X case SPE_INVISIBILITY:
X#endif
X if(Invisible || See_invisible) nothing++;
X else {
X newsym(u.ux,u.uy);
X if(!Blind)
X pline("Gee! All of a sudden, you can't see yourself.");
X else
X You("feel rather airy."), unkn++;
X }
X if (otmp->blessed && !(HInvis & INTRINSIC)) {
X pline("Do you want the invisibility to be permanent? ");
X nothing = 0;
X if (yn()=='n') HInvis += rn1(15,31);
X else HInvis |= INTRINSIC;
X } else HInvis += rn1(15,31);
X if(otmp->cursed) {
X pline("For some reason, you feel your presence is known.");
X aggravate();
X }
X break;
X case POT_SEE_INVISIBLE:
X case POT_FRUIT_JUICE:
X unkn++;
X if(otmp->cursed)
X pline("Yecch! This tastes %s.",
X Hallucination ? "overripe" : "rotten"
X );
X else pline (Hallucination ?
X "This tastes like 10%% real %s juice all-natural beverage." :
X "This tastes like %s juice.", pl_fruit);
X if (otmp->otyp == POT_FRUIT_JUICE) {
X lesshungry(10 * (2 + bcsign(otmp)));
X break;
X }
X if (!otmp->cursed) {
X /* Tell them they can see again immediately, which
X * will help them identify the potion...
X */
X make_blinded(0L,TRUE);
X }
X if (otmp->blessed)
X HSee_invisible |= INTRINSIC;
X else
X HSee_invisible += rn1(100,750);
X break;
X case POT_PARALYSIS:
X if(Levitation)
X You("are motionlessly suspended.");
X else
X Your("%s are frozen to the floor!",
X makeplural(body_part(FOOT)));
X nomul(-(rn1(10, 25 - 12*bcsign(otmp))));
X break;
X case POT_MONSTER_DETECTION:
X#ifdef SPELLS
X case SPE_DETECT_MONSTERS:
X#endif
X if (monster_detect(otmp))
X return(1); /* nothing detected */
X break;
X case POT_OBJECT_DETECTION:
X#ifdef SPELLS
X case SPE_DETECT_TREASURE:
X#endif
X if (object_detect(otmp))
X return(1); /* nothing detected */
X break;
X case POT_SICKNESS:
X pline("Yecch! This stuff tastes like poison.");
X if (otmp->blessed) {
X pline("(But in fact it was mildly stale %s juice.)",
X pl_fruit);
X if (pl_character[0] != 'H')
X losehp(1, "mildly contaminated potion");
X } else {
X if(Poison_resistance)
X pline("(But in fact it was biologically contaminated %s juice.)",pl_fruit);
X if (pl_character[0] == 'H')
X pline("Fortunately, you have been immunized.");
X else {
X int typ = rn2(A_MAX);
X poisontell(typ);
X adjattrib(typ,Poison_resistance ? -1 : -rn1(4,3), TRUE);
X if(!Poison_resistance)
X losehp(rnd(10)+5*!!(otmp->cursed),
X "contaminated potion");
X }
X }
X if(Hallucination) {
X You("are shocked back to your senses!");
X make_hallucinated(0L,FALSE);
X }
X break;
X case POT_CONFUSION:
X if(!Confusion)
X if (Hallucination) {
X pline("What a trippy feeling!");
X unkn++;
X } else
X pline("Huh, What? Where am I?");
X else nothing++;
X make_confused(HConfusion + rn1(7,16-8*bcsign(otmp)),FALSE);
X break;
X case POT_GAIN_ABILITY:
X if(otmp->cursed) {
X pline("Ulch! That potion tasted foul!");
X unkn++;
X } else {
X i = rn2(A_MAX); /* start at a random point */
X for(isdone = ii = 0; !isdone && ii < A_MAX; ii++) {
X adjattrib(i, 1, FALSE);
X /* only first found if not blessed */
X isdone = !(otmp->blessed);
X flags.botl = 1;
X if(++i >= A_MAX) i = 0;
X }
X }
X break;
X case POT_SPEED:
X if(Wounded_legs && !otmp->cursed) {
X heal_legs();
X unkn++;
X break;
X } /* and fall through */
X#ifdef SPELLS
X case SPE_HASTE_SELF:
X#endif
X if(!(Fast & TIMEOUT))
X You("are suddenly moving much faster.");
X else {
X Your("%s get new energy.",
X makeplural(body_part(LEG)));
X unkn++;
X }
X Fast += rn1(10,100+60*bcsign(otmp));
X break;
X case POT_BLINDNESS:
X if(Blind) nothing++;
X make_blinded(Blinded + rn1(200, 250-125*bcsign(otmp)), TRUE);
X break;
X case POT_GAIN_LEVEL:
X if (otmp->cursed) {
X unkn++;
X You("rise up, through the ceiling!");
X /* they went up a level */
X goto_level(dlevel-1, FALSE);
X break;
X }
X pluslvl();
X if (otmp->blessed)
X /* blessed potions place you at a random spot in the
X * middle of the new level instead of the low point
X */
X u.uexp = rndexp();
X break;
X case POT_HEALING:
X You("begin to feel better.");
X healup(d(5,2) + 5 * bcsign(otmp),
X 1, !!(otmp->blessed), !(otmp->cursed));
X break;
X case POT_EXTRA_HEALING:
X You("feel much better.");
X healup(d(5,4) + 5 * bcsign(otmp),
X 2+3*!!(otmp->blessed), !(otmp->cursed), 1);
X make_hallucinated(0L,TRUE);
X break;
X case POT_LEVITATION:
X#ifdef SPELLS
X case SPE_LEVITATION:
X#endif
X if(!Levitation) {
X float_up();
X if (otmp->cursed) {
X#ifdef STRONGHOLD
X if((u.ux != xupstair || u.uy != yupstair) &&
X (!xupladder || u.ux != xupladder || u.uy != yupladder)) {
X#else
X if(u.ux != xupstair || u.uy != yupstair) {
X#endif /* STRONGHOLD /**/
X You("hit your %s on the ceiling.",
X body_part(HEAD));
X losehp(uarmh ? 1 : rnd(10),
X "collision with the ceiling");
X } else (void) doup();
X }
X } else
X nothing++;
X if (otmp->blessed) {
X char buf[BUFSZ];
X int lmoves = 0;
X
X makeknown(POT_LEVITATION);
X pline("How many moves do you wish to levitate for? [1-300] ");
X do {
X getlin(buf);
X } while (buf[0]=='\033' || !buf[0] ||
X (lmoves = atoi(buf)) < 1 || lmoves > 300);
X HLevitation += lmoves;
X } else HLevitation += rnd(150);
X u.uprops[LEVITATION].p_tofn = float_down;
X break;
X#ifdef SPELLS
X case POT_GAIN_ENERGY: /* M. Stephenson */
X { register int num;
X if(otmp->cursed)
X You("feel lackluster.");
X else
X pline("Magical energies course through your body.");
X num = rnd(5) + 5 * otmp->blessed + 1;
X u.uenmax += (otmp->cursed) ? -num : num;
X u.uen += (otmp->cursed) ? -num : num;
X if(u.uenmax <= 0) u.uen = u.uenmax = 0;
X flags.botl = 1;
X }
X break;
X#endif
X default:
X impossible("What a funny potion! (%u)", otmp->otyp);
X return(0);
X }
X return(-1);
X}
X
Xvoid
Xhealup(nhp, nxtra, curesick, cureblind)
X int nhp, nxtra;
X register boolean curesick, cureblind;
X{
X#ifdef POLYSELF
X if (u.mtimedone && nhp) {
X u.mh += nhp;
X if (u.mh > u.mhmax) u.mh = (u.mhmax += nxtra);
X }
X#endif
X if(nhp) {
X u.uhp += nhp;
X if(u.uhp > u.uhpmax) u.uhp = (u.uhpmax += nxtra);
X }
X if(cureblind) make_blinded(0L,TRUE);
X if(curesick) make_sick(0L,TRUE);
X flags.botl = 1;
X return;
X}
X
Xvoid
Xstrange_feeling(obj,txt)
Xregister struct obj *obj;
Xregister char *txt;
X{
X if(flags.beginner)
X You("have a %s feeling for a moment, then it passes.",
X Hallucination ? "normal" : "strange");
X else
X pline(txt);
X
X if(!obj) /* e.g., crystal ball finds no traps */
X return;
X
X if(obj->dknown && !objects[obj->otyp].oc_name_known &&
X !objects[obj->otyp].oc_uname)
X docall(obj);
X useup(obj);
X}
X
Xconst char *bottlenames[] = {
X "bottle", "phial", "flagon", "carafe", "flask", "jar", "vial"
X};
X
Xvoid
Xpotionhit(mon, obj)
Xregister struct monst *mon;
Xregister struct obj *obj;
X{
X register char *botlnam = bottlenames[rn2(SIZE(bottlenames))];
X boolean uclose, isyou = (mon == &youmonst);
X
X if(isyou) {
X uclose = TRUE;
X pline("The %s crashes on your %s and breaks into shivers.",
X botlnam, body_part(HEAD));
X losehp(rnd(2), "thrown potion");
X } else {
X uclose = (dist(mon->mx,mon->my) < 3);
X if(Blind) pline("Crash!");
X else pline("The %s crashes on %s%s and breaks into shivers.",
X botlnam, mon_nam(mon), (haseyes(mon->data) &&
X mon->data != &mons[PM_FLOATING_EYE]) ?
X#ifdef WORM
X (notonhead ? "'s body" : "'s head")
X#else
X "'s head"
X#endif
X : "");
X if(rn2(5) && mon->mhp > 1)
X mon->mhp--;
X }
X#ifdef WORM
X notonhead = FALSE;
X#endif
X pline("The %s evaporates.", xname(obj));
X
X if(!isyou) switch (obj->otyp) {
X
X case POT_RESTORE_ABILITY:
X case POT_GAIN_ABILITY:
X case POT_HEALING:
X case POT_EXTRA_HEALING:
X if(mon->mhp < mon->mhpmax) {
X mon->mhp = mon->mhpmax;
X if(!Blind)
X pline("%s looks sound and hale again.", Monnam(mon));
X }
X break;
X case POT_SICKNESS:
X if((mon->mhpmax > 3) && !resist(mon, POTION_SYM, 0, NOTELL))
X mon->mhpmax /= 2;
X if((mon->mhp > 2) && !resist(mon, POTION_SYM, 0, NOTELL))
X mon->mhp /= 2;
X if(!Blind)
X pline("%s looks rather ill.", Monnam(mon));
X break;
X case POT_CONFUSION:
X case POT_BOOZE:
X if(!resist(mon, POTION_SYM, 0, NOTELL)) mon->mconf = 1;
X break;
X case POT_INVISIBILITY:
X unpmon(mon);
X mon->minvis = 1;
X pmon(mon);
X break;
X case POT_PARALYSIS:
X mon->mfroz = 1;
X break;
X case POT_SPEED:
X mon->mspeed = MFAST;
X break;
X case POT_BLINDNESS:
X {
X register int btmp = 64 + rn2(32) +
X rn2(32) * !resist(mon, POTION_SYM, 0, NOTELL);
X mon->mblinded |= btmp;
X }
X break;
X case POT_WATER:
X if (is_undead(mon->data) || is_demon(mon->data)) {
X if (obj->blessed) {
X kludge("%s shrieks in pain!", Monnam(mon));
X mon->mhp -= d(2,6);
X if (mon->mhp <1) killed(mon);
X } else if (obj->cursed) {
X if(!Blind)
X pline("%s looks healthier.", Monnam(mon));
X mon->mhp += d(2,6);
X }
X }
X /* TO DO: Gremlins multiply when doused with water */
X break;
X/*
X case POT_GAIN_LEVEL:
X case POT_LEVITATION:
X case POT_FRUIT_JUICE:
X case POT_MONSTER_DETECTION:
X case POT_OBJECT_DETECTION:
X break;
X*/
X }
X if(uclose && rn2(5))
X potionbreathe(obj);
X obfree(obj, (struct obj *)0);
X}
X
Xvoid
Xpotionbreathe(obj)
Xregister struct obj *obj;
X{
X register int i, ii, isdone;
X
X switch(obj->otyp) {
X case POT_RESTORE_ABILITY:
X case POT_GAIN_ABILITY:
X if(obj->cursed) {
X pline("Ulch! That potion smells terrible!");
X break;
X } else {
X i = rn2(A_MAX); /* start at a random point */
X for(isdone = ii = 0; !isdone && ii < A_MAX; ii++) {
X if(ABASE(i) < AMAX(i)) {
X ABASE(i)++;
X /* only first found if not blessed */
X isdone = !(obj->blessed);
X flags.botl = 1;
X }
X if(++i >= A_MAX) i = 0;
X }
X }
X break;
X case POT_HEALING:
X case POT_EXTRA_HEALING:
X if(u.uhp < u.uhpmax) u.uhp++, flags.botl = 1;
X break;
X case POT_SICKNESS:
X if(u.uhp <= 5) u.uhp = 1; else u.uhp -= 5;
X flags.botl = 1;
X break;
X case POT_HALLUCINATION:
X You("have a vision for a moment.");
X break;
X case POT_CONFUSION:
X case POT_BOOZE:
X if(!Confusion)
X You("feel somewhat dizzy.");
X make_confused(HConfusion + rnd(5),FALSE);
X break;
X case POT_INVISIBILITY:
X if (!See_invisible && !Invis)
X pline("For an instant you could see through yourself!");
X break;
X case POT_PARALYSIS:
X pline("Something seems to be holding you.");
X nomul(-rnd(5));
X break;
X case POT_SPEED:
X Fast += rnd(5);
X Your("knees seem more flexible now.");
X break;
X case POT_BLINDNESS:
X if(!Blind) pline("It suddenly gets dark.");
X make_blinded(Blinded + rnd(5),FALSE);
X seeoff(0);
X break;
X/*
X case POT_GAIN_LEVEL:
X case POT_LEVITATION:
X case POT_FRUIT_JUICE:
X case POT_MONSTER_DETECTION:
X case POT_OBJECT_DETECTION:
X break;
X*/
X }
X /* note: no obfree() */
X}
X
Xstatic int
Xneutralizes(o1, o2)
Xregister struct obj *o1, *o2;
X{
X switch (o1->otyp) {
X case POT_SICKNESS:
X case POT_HALLUCINATION:
X case POT_BLINDNESS:
X case POT_CONFUSION:
X if (o2->otyp == POT_HEALING ||
X o2->otyp == POT_EXTRA_HEALING)
X return 1;
X case POT_HEALING:
X case POT_EXTRA_HEALING:
X if (o2->otyp == POT_SICKNESS ||
X o2->otyp == POT_HALLUCINATION ||
X o2->otyp == POT_BLINDNESS ||
X o2->otyp == POT_CONFUSION)
X return 1;
X }
X
X return 0;
X}
X
Xint
Xdodip()
X{
X register struct obj *potion, *obj;
X char *tmp;
X
X if(!(obj = getobj("#", "dip")))
X return(0);
X#ifdef FOUNTAINS
X /* Is there something to dip into here, i.e., a fountain? */
X if (levl[u.ux][u.uy].typ == FOUNTAIN) {
X pline("Dip it into the fountain? ");
X if(yn() == 'y') {
X dipfountain(obj);
X return(1);
X }
X }
X#endif
X if(!(potion = getobj(beverages, "dip into")))
X return(0);
X if (potion==obj && potion->quan==1) {
X pline("That is a potion bottle, not a Klein bottle!");
X return 0;
X }
X if(potion->otyp == POT_WATER) {
X if (potion->blessed) {
X if (obj->cursed) {
X if (!Blind)
X Your("%s %s.",
X aobjnam(obj, "softly glow"),
X Hallucination ? hcolor() : amber);
X obj->cursed=0;
X obj->bknown=1;
X poof:
X if(!(objects[potion->otyp].oc_name_known) &&
X !(objects[potion->otyp].oc_uname))
X docall(potion);
X useup(potion);
X return(1);
X } else if(!obj->blessed) {
X if (!Blind) {
X tmp = Hallucination ? hcolor() : light_blue;
X Your("%s with a%s %s aura.",
X aobjnam(obj, "softly glow"),
X index(vowels, *tmp) ? "n" : "", tmp);
X }
X obj->blessed=1;
X obj->bknown=1;
X goto poof;
X }
X } else if (potion->cursed) {
X if (obj->blessed) {
X if (!Blind)
X Your("%s %s.", aobjnam(obj, "glow"),
X Hallucination ? hcolor() : "brown");
X obj->blessed=0;
X obj->bknown=1;
X goto poof;
X } else if(!obj->cursed) {
X if (!Blind) {
X tmp = Hallucination ? hcolor() : black;
X Your("%s with a%s %s aura.",
X aobjnam(obj, "glow"),
X index(vowels, *tmp) ? "n" : "", tmp);
X }
X obj->cursed=1;
X obj->bknown=1;
X goto poof;
X }
X } else if (obj->otyp != POT_WATER) {
X if (obj->olet == WEAPON_SYM && !obj->rustfree &&
X objects[obj->otyp].oc_material == METAL &&
X obj->spe > -6 && !rn2(10)) {
X Your("%s somewhat.", aobjnam(obj,"rust"));
X obj->spe--;
X } else if (obj->olet == POTION_SYM) {
X Your("%s.", aobjnam(obj,"dilute"));
X if (obj->spe == -1) {
X obj->spe = 0;
X obj->blessed = obj->cursed = 0;
X obj->otyp = POT_WATER;
X } else obj->spe--;
X } else if (obj->olet == SCROLL_SYM &&
X obj->otyp != SCR_BLANK_PAPER) {
X if (!Blind) pline("The scroll fades.");
X obj->otyp = SCR_BLANK_PAPER;
X } else
X Your("%s wet.", aobjnam(obj,"get"));
X }
X }
X else if(obj->olet == POTION_SYM && obj->otyp != potion->otyp) {
X /* Mixing potions is dangerous... */
X pline("The potions mix...");
X if (obj->cursed || !rn2(10)) {
X pline("BOOM! They explode!");
X u.uhp -= rnd(10);
X flags.botl = 1;
X potionbreathe(obj);
X useup(obj);
X useup(potion);
X return(1);
X }
X
X obj->blessed = obj->cursed = obj->bknown = 0;
X if (Blind) obj->dknown = 0;
X
X switch (neutralizes(obj, potion) || obj->spe == -1 ?
X 1 : rnd(8)) {
X case 1:
X obj->otyp = POT_WATER;
X obj->blessed = obj->cursed = 0;
X break;
X case 2:
X case 3:
X obj->otyp = POT_SICKNESS;
X break;
X case 4:
X {
X struct obj *otmp;
X otmp = mkobj(POTION_SYM,FALSE);
X obj->otyp = otmp->otyp;
X obfree(otmp, (struct obj *)0);
X }
X break;
X default:
X if (!Blind)
X pline("The mixture glows brightly and evaporates.");
X useup(obj);
X useup(potion);
X return(1);
X }
X
X obj->spe--; /* diluted */
X if (obj->otyp == POT_WATER)
X pline("The mixture bubbles violently, then clears.");
X else {
X if (!Blind) {
X pline("The mixture looks %s.", objects[obj->otyp].oc_descr);
X obj->dknown = 1;
X }
X }
X
X useup(potion);
X return(1);
X }
X
X if(obj->olet == WEAPON_SYM && obj->otyp <= SHURIKEN) {
X if(potion->otyp == POT_SICKNESS && !obj->opoisoned) {
X char buf[BUFSZ];
X Strcpy(buf, xname(potion));
X pline("The %s form%s a coating on the %s.",
X buf, (potion->quan==1) ? "s" : "", xname(obj));
X obj->opoisoned = 1;
X goto poof;
X } else if(obj->opoisoned &&
X (potion->otyp == POT_HEALING ||
X potion->otyp == POT_EXTRA_HEALING)) {
X pline("A coating wears off the %s.", xname(obj));
X obj->opoisoned = 0;
X goto poof;
X }
X }
X pline("Interesting...");
X return(1);
X}
X
X
Xvoid
Xdjinni_from_bottle(obj)
Xregister struct obj *obj;
X{
X register struct monst *mtmp;
X
X if(!(mtmp = makemon(&mons[PM_DJINNI], u.ux, u.uy))){
X pline("It turns out to be empty.");
X return;
X }
X
X mnexto(mtmp);
X if (!Blind)
X pline("In a cloud of smoke, a djinni emerges!");
X else You("smell acrid fumes.");
X if (!Blind)
X pline("%s speaks.", Monnam(mtmp));
X else pline("Something speaks.");
X
X switch (obj->blessed ? 0 : obj->cursed ? 4 : rn2(5)) {
X case 0 : pline("\"I am in your debt. I will grant one wish!\"");
X makewish();
X mongone(mtmp);
X break;
X case 1 : pline("\"Thank you for freeing me!\"");
X (void) tamedog(mtmp, (struct obj *)0);
X break;
X case 2 : pline("\"You freed me!\"");
X mtmp->mpeaceful = 1;
X break;
X case 3 : pline("\"It is about time!\"");
X pline("The djinni vanishes.");
X mongone(mtmp);
X break;
X default: pline("\"You disturbed me, fool!\"");
X break;
X }
X}
X
X/* monster_detect is also used in the crystal ball routine */
X/* returns 1 if nothing was detected */
X/* returns 0 if something was detected */
Xint
Xmonster_detect(otmp)
Xregister struct obj *otmp;
X{
X register struct monst *mtmp;
X
X if(!fmon) {
X if (otmp)
X strange_feeling(otmp, Hallucination ?
X "You get the heebie jeebies." :
X "You feel threatened.");
X return(1);
X } else {
X int woken = FALSE;
X
X cls();
X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
X if(mtmp->mx > 0)
X at(mtmp->mx, mtmp->my,
X (uchar)(Hallucination ? rndmonsym() : mtmp->data->mlet),
X AT_MON);
X if (otmp && otmp->cursed && (mtmp->msleep || mtmp->mfroz)) {
X mtmp->msleep = mtmp->mfroz = 0;
X woken = TRUE;
X }
X }
X prme();
X You("sense the presence of monsters.");
X if (woken)
X pline("Monsters sense the presence of you.");
X more();
X docrt();
X }
X return(0);
X}
X
X/* object_detect is also used in the crystal ball routine */
X/* returns 1 if nothing was detected */
X/* returns 0 if something was detected */
Xint
Xobject_detect(otmp)
Xregister struct obj *otmp;
X{
X register struct obj *objs;
X register struct monst *mtmp;
X
X if(!fobj) {
X if (otmp)
X strange_feeling(otmp, "You feel a pull downward.");
X return(1);
X } else {
X int mfound=FALSE;
X
X for(objs = fobj; objs; objs = objs->nobj)
X if(objs->ox != u.ux || objs->oy != u.uy)
X goto outobjmap;
X You("sense the presence of objects nearby.");
X return(0);
X outobjmap:
X cls();
X for(objs = fobj; objs; objs = objs->nobj)
Xat(objs->ox, objs->oy, (uchar)(Hallucination ? rndobjsym() : objs->olet), AT_OBJ);
X /* monster possessions added by GAN 12/16/86 */
X for(mtmp = fmon ; mtmp ; mtmp = mtmp->nmon)
X if(mtmp->minvent)
X for(objs = mtmp->minvent;objs;objs = objs->nobj)
X at(mtmp->mx, mtmp->my, (uchar)objs->olet, AT_OBJ);
X if (otmp && otmp->cursed) {
X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
X if (mtmp->mimic) {
X mnexto(mtmp);
X mfound = TRUE;
X }
X }
X }
X prme();
X You("sense the presence of objects.");
X if (mfound) pline("Objects sense the presence of you.");
X more();
X docrt();
X }
X return(0);
X}
END_OF_FILE
if test 25055 -ne `wc -c <'src/potion.c'`; then
echo shar: \"'src/potion.c'\" unpacked with wrong size!
fi
# end of 'src/potion.c'
fi
if test -f 'src/track.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/track.c'\"
else
echo shar: Extracting \"'src/track.c'\" \(781 characters\)
sed "s/^X//" >'src/track.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)track.c 1.4 87/08/08
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X/* track.c - version 1.0.2 */
X
X#include "hack.h"
X
X#define UTSZ 50
X
Xcoord utrack[UTSZ];
Xint utcnt = 0;
Xint utpnt = 0;
X
Xvoid
Xinitrack(){
X utcnt = utpnt = 0;
X}
X
X/* add to track */
Xvoid
Xsettrack(){
X if(utcnt < UTSZ) utcnt++;
X if(utpnt == UTSZ) utpnt = 0;
X utrack[utpnt].x = u.ux;
X utrack[utpnt].y = u.uy;
X utpnt++;
X}
X
Xcoord *
Xgettrack(x, y)
Xregister int x, y;
X{
X register int i, cnt, ndist;
X coord tc;
X cnt = utcnt;
X for(i = utpnt-1; cnt--; i--){
X if(i == -1) i = UTSZ-1;
X tc = utrack[i];
X ndist = dist2(x,y,tc.x,tc.y);
X if(ndist < 3)
X return(ndist ? (coord *)&(utrack[i]) : 0);
X }
X return (coord *)0;
X}
END_OF_FILE
if test 781 -ne `wc -c <'src/track.c'`; then
echo shar: \"'src/track.c'\" unpacked with wrong size!
fi
# end of 'src/track.c'
fi
echo shar: End of archive 21 \(of 38\).
cp /dev/null ark21isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 38 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0