[comp.sources.games] v07i076: NetHack3 - display oriented dungeons & dragons

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