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