#! /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 apply.c <<'END_OF_apply.c' X/* SCCS Id: @(#)apply.c 2.3 88/01/21 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X X#include "hack.h" X#include "edog.h" X#include "mkroom.h" Xstatic struct monst *bchit(); Xextern struct obj *addinv(); Xextern struct trap *maketrap(); Xextern int (*occupation)(); Xextern char *occtxt; Xextern char quitchars[]; Xextern char pl_character[]; X X#ifdef DGKMOD Xextern void set_occupation(); X#endif X#ifdef KAA Xextern boolean unweapon; X#endif Xstatic use_camera(), use_ice_box(), use_whistle(); Xstatic use_magic_whistle(), use_pick_axe(); X#ifdef MARKER Xextern int dowrite(); X#endif X#ifdef RPH Xstatic use_mirror(); X#endif Xstatic use_lamp(); X Xdoapply() { X register struct obj *obj; X register int res = 1; X X obj = getobj("(", "use or apply"); X if(!obj) return(0); X X switch(obj->otyp){ X case EXPENSIVE_CAMERA: X use_camera(obj); break; X case ICE_BOX: X use_ice_box(obj); break; X case PICK_AXE: X res = use_pick_axe(obj); X break; X X case MAGIC_WHISTLE: X if(pl_character[0] == 'W' || u.ulevel > 9) { X use_magic_whistle(obj); X break; X } X /* fall into next case */ X case WHISTLE: X use_whistle(obj); X break; X#ifdef RPH X case MIRROR: X use_mirror(obj); X break; X#endif X case LAMP: X case MAGIC_LAMP: X use_lamp(obj); X break; X#ifdef WALKIES X case LEASH: X use_leash(obj); X break; X#endif X#ifdef MARKER X case MAGIC_MARKER: X dowrite(obj); X break; X#endif X case CAN_OPENER: X if(!carrying(TIN)) { X pline("You have no can to open."); X goto xit; X } X pline("You cannot open a tin without eating its contents."); X pline("In order to eat, use the 'e' command."); X if(obj != uwep) X pline("Opening the tin will be much easier if you wield the can-opener."); X goto xit; X X#ifdef KAA X case STETHOSCOPE: X res = use_stethoscope(); X break; X#endif X case BLINDFOLD: X if (Blindfolded && obj->owornmask) { X pline("You remove the blindfold."); X Blindfolded = 0; X obj->owornmask = 0; X if (!Blinded) Blinded = 1; /* see on nexte */ X else pline("You still cannot see."); X } else if (!Blindfolded) { X pline("You put the blindfold on."); X Blindfolded = INTRINSIC; X obj->owornmask = W_TOOL; X seeoff(0); X } else pline("You are already wearing a blindfold!"); X break; X case BADGE: X if (Badged && obj->owornmask) { X pline("You remove the badge."); X Badged = 0; X obj->owornmask = 0; X } else if (!Badged) { X pline("You pin the badge on your chest."); X Badged = INTRINSIC; X obj->owornmask = W_TOOL; X } else pline("You are already wearing a badge!"); X break; X default: X pline("Sorry, I don't know how to use that."); X xit: X nomul(0); X return(0); X } X nomul(0); X return(res); X} X X/* ARGSUSED */ Xstatic Xuse_camera(obj) /* register */ struct obj *obj; { Xregister struct monst *mtmp; X if(!getdir(1)){ /* ask: in what direction? */ X flags.move = multi = 0; X return; X } X if(u.uswallow) { X pline("You take a picture of %s's stomach.", monnam(u.ustuck)); X return; X } X if(u.dz) { X pline("You take a picture of the %s.", X (u.dz > 0) ? "floor" : "ceiling"); X return; X } X#ifdef KAA X if(!u.dx && !u.dy && !u.dz) { X if(!Blind) { X pline("You are blinded by the flash!"); X Blinded += rnd(25); X seeoff(0); X } X return; X } X#endif X if(mtmp = bchit(u.dx, u.dy, COLNO, '!')) { X if(mtmp->msleep){ X mtmp->msleep = 0; X pline("The flash awakens %s.", monnam(mtmp)); /* a3 */ X } else X if(mtmp->data->mlet != 'y') X if(mtmp->mcansee || mtmp->mblinded){ X register int tmp = dist(mtmp->mx,mtmp->my); X register int tmp2; X if(cansee(mtmp->mx,mtmp->my)) X pline("%s is blinded by the flash!", Monnam(mtmp)); X setmangry(mtmp); X if(tmp < 9 && !mtmp->isshk && rn2(4)) { X mtmp->mflee = 1; X if(rn2(4)) mtmp->mfleetim = rnd(100); X } X if(tmp < 3) mtmp->mcansee = mtmp->mblinded = 0; X else { X tmp2 = mtmp->mblinded; X tmp2 += rnd(1 + 50/tmp); X if(tmp2 > 127) tmp2 = 127; X mtmp->mblinded = tmp2; X mtmp->mcansee = 0; X } X } X } X} X X#ifdef KAA X/* Strictly speaking it makes no sense for usage of a stethoscope to X not take any time; however, unless it did, the stethoscope would be X almost useless. */ Xstatic use_stethoscope() { Xregister struct monst *mtmp; Xregister struct rm *lev; Xregister int rx, ry; X if(!freehand()) { X pline("You have no free hand!"); X return(1); X } X if (!getdir(1)) { X flags.move=multi=0; X return(0); X } X if(u.dz < 0 || (u.dz && Levitation)) { X pline("You can't reach the %s!", u.dz<0 ? "ceiling" : "floor"); X return(1); X } X if(u.dz) { X pline("The floor seems healthy enough."); X return(0); X } X if (Confusion) confdir(); X rx = u.ux + u.dx; ry = u.uy + u.dy; X if(u.uswallow) { X mstatusline(u.ustuck); X return(0); X } X if(mtmp=m_at(rx,ry)) { X mstatusline(mtmp); X return(0); X } X if (!isok(rx,ry)) { X pline("You hear the sounds at the end of the universe."); X return(0); X } X lev = &levl[rx][ry]; X if(lev->typ == SDOOR) { X pline("You hear a hollow sound! This must be a secret door!"); X lev->typ = DOOR; X atl(rx, ry, DOOR_SYM); X return(0); X } X if(lev->typ == SCORR) { X pline("You hear a hollow sound! This must be a secret passage!"); X lev->typ = CORR; X atl(rx, ry, CORR_SYM); X return(0); X } X pline("You hear nothing special."); X return(0); X} X#endif X Xstatic Xstruct obj *current_ice_box; /* a local variable of use_ice_box, to be X used by its local procedures in/ck_ice_box */ Xstatic Xin_ice_box(obj) register struct obj *obj; { X if(obj == current_ice_box || X (Punished && (obj == uball || obj == uchain))){ X pline("You must be kidding."); X return(0); X } X if(obj->owornmask & (W_ARMOR | W_RING)) { X pline("You cannot refrigerate something you are wearing."); X return(0); X } X if(obj->owt + current_ice_box->owt > 70) { X pline("It won't fit."); X return(1); /* be careful! */ X } X if(obj == uwep) { X if(uwep->cursed) { X pline("Your weapon is welded to your hand!"); X return(0); X } X setuwep((struct obj *) 0); X } X current_ice_box->owt += obj->owt; X freeinv(obj); X obj->o_cnt_id = current_ice_box->o_id; X obj->nobj = fcobj; X fcobj = obj; X obj->age = moves - obj->age; /* actual age */ X return(1); X} X Xstatic Xck_ice_box(obj) register struct obj *obj; { X return(obj->o_cnt_id == current_ice_box->o_id); X} X Xstatic Xout_ice_box(obj) register struct obj *obj; { Xregister struct obj *otmp; X if(obj == fcobj) fcobj = fcobj->nobj; X else { X for(otmp = fcobj; otmp->nobj != obj; otmp = otmp->nobj) X if(!otmp->nobj) panic("out_ice_box"); X otmp->nobj = obj->nobj; X } X current_ice_box->owt -= obj->owt; X obj->age = moves - obj->age; /* simulated point of time */ X (void) addinv(obj); X} X Xstatic Xuse_ice_box(obj) register struct obj *obj; { Xregister int cnt = 0; Xregister struct obj *otmp; X current_ice_box = obj; /* for use by in/out_ice_box */ X for(otmp = fcobj; otmp; otmp = otmp->nobj) X if(otmp->o_cnt_id == obj->o_id) X cnt++; X if(!cnt) pline("Your ice-box is empty."); X else { X pline("Do you want to take something out of the ice-box? [yn] "); X if(readchar() == 'y') X if(askchain(fcobj, (char *) 0, 0, out_ice_box, ck_ice_box, 0)) X return; X pline("That was all. Do you wish to put something in? [yn] "); X if(readchar() != 'y') return; X } X /* call getobj: 0: allow cnt; #: allow all types; %: expect food */ X otmp = getobj("0#%", "put in"); X if(!otmp || !in_ice_box(otmp)) X flags.move = multi = 0; X} X Xstatic Xstruct monst * Xbchit(ddx,ddy,range,sym) register int ddx,ddy,range; char sym; { X register struct monst *mtmp = (struct monst *) 0; X register int bchx = u.ux, bchy = u.uy; X X if(sym) Tmp_at(-1, sym); /* open call */ X while(range--) { X bchx += ddx; X bchy += ddy; X if(mtmp = m_at(bchx,bchy)) X break; X if(!ZAP_POS(levl[bchx][bchy].typ)) { X bchx -= ddx; X bchy -= ddy; X break; X } X if(sym) Tmp_at(bchx, bchy); X } X if(sym) Tmp_at(-1, -1); X return(mtmp); X} X X/* ARGSUSED */ Xstatic Xuse_whistle(obj) struct obj *obj; { Xregister struct monst *mtmp = fmon; X pline("You produce a high whistling sound."); X while(mtmp) { X if(dist(mtmp->mx,mtmp->my) < u.ulevel*20) { X if(mtmp->msleep) X mtmp->msleep = 0; X if(mtmp->mtame) X EDOG(mtmp)->whistletime = moves; X } X mtmp = mtmp->nmon; X } X} X X/* ARGSUSED */ Xstatic Xuse_magic_whistle(obj) struct obj *obj; { Xregister struct monst *mtmp = fmon; X pline("You produce a strange whistling sound."); X while(mtmp) { X if(mtmp->mtame) mnexto(mtmp); X mtmp = mtmp->nmon; X } X} X X#ifdef WALKIES X/* ARGSUSED */ Xstatic Xuse_leash(obj) struct obj *obj; { Xregister struct monst *mtmp = fmon; Xextern char *lmonnam(); X X while(mtmp && !mtmp->mleashed) mtmp = mtmp->nmon; X X if(mtmp) { X X if (next_to(mtmp)) { X X mtmp->mleashed = 0; X pline("You remove the leash from your %s.", X#ifdef RPH X /* a hack to include the dogs full name. +4 elminates */ X /* the 'the' at the start of the name */ X lmonnam(mtmp) + 4); X#else X mtmp->data->mname); X#endif X } else pline("You must be next to your %s to unleash him.", X#ifdef RPH X lmonnam(mtmp)+4); X#else X mtmp->data->mname); X#endif X } else { X X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) { X X if(mtmp->mtame && next_to(mtmp)) { X X pline("You slip the leash around your %s.", mtmp->data->mname); X mtmp->mleashed = 1; X if(mtmp->msleep) mtmp->msleep = 0; X return(0); X } X } X pline("There's nothing here to put a leash on."); X } X return(0); X} X Xnext_to(mtmp) register struct monst *mtmp; { X X return((abs(u.ux - mtmp->mx) <= 1) && (abs(u.uy - mtmp->my) <= 1)); X} X#endif X Xstatic int dig_effort; /* effort expended on current pos */ Xstatic uchar dig_level; Xstatic coord dig_pos; Xstatic boolean dig_down; X Xstatic Xdig() { X register struct rm *lev; X register dpx = dig_pos.x, dpy = dig_pos.y; X X /* perhaps a nymph stole his pick-axe while he was busy digging */ X /* or perhaps he teleported away */ X if(u.uswallow || !uwep || uwep->otyp != PICK_AXE || X dig_level != dlevel || X ((dig_down && (dpx != u.ux || dpy != u.uy)) || X (!dig_down && dist(dpx,dpy) > 2))) X return(0); X X dig_effort += 10 + abon() + uwep->spe + rn2(5); X if(dig_down) { X if(!xdnstair) { X pline("The floor here seems too hard to dig in."); X return(0); X } X if(dig_effort > 250) { X dighole(); X return(0); /* done with digging */ X } X if(dig_effort > 50) { X register struct trap *ttmp = t_at(dpx,dpy); X X if(!ttmp) { X ttmp = maketrap(dpx,dpy,PIT); X ttmp->tseen = 1; X pline("You have dug a pit."); X u.utrap = rn1(4,2); X u.utraptype = TT_PIT; X return(0); X } X } X } else X if(dig_effort > 100) { X register char *digtxt; X register struct obj *obj; X X lev = &levl[dpx][dpy]; X if(obj = sobj_at(ENORMOUS_ROCK, dpx, dpy)) { X fracture_rock(obj); X digtxt = "The rock falls apart."; X } else if(!lev->typ || lev->typ == SCORR) { X lev->typ = CORR; X digtxt = "You succeeded in cutting away some rock."; X } else if(lev->typ == HWALL || lev->typ == VWALL X || lev->typ == SDOOR) { X lev->typ = xdnstair ? DOOR : ROOM; X digtxt = "You just made an opening in the wall."; X } else X digtxt = "Now what exactly was it that you were digging in?"; X mnewsym(dpx, dpy); X prl(dpx, dpy); X pline(digtxt); /* after mnewsym & prl */ X return(0); X } else { X if(IS_WALL(levl[dpx][dpy].typ)) { X register int rno = inroom(dpx,dpy); X X if(rno >= 0 && rooms[rno].rtype >= SHOPBASE) { X pline("This wall seems too hard to dig into."); X return(0); X } X } X pline("You hit the rock with all your might."); X } X return(1); X} X X/* When will hole be finished? Very rough indication used by shopkeeper. */ Xholetime() { X return( (occupation == dig) ? (250 - dig_effort)/20 : -1); X} X Xdighole() X{ X register struct trap *ttmp = t_at(u.ux, u.uy); X X if(!xdnstair) { X pline("The floor here seems too hard to dig in."); X } else { X if(ttmp) X ttmp->ttyp = TRAPDOOR; X else X ttmp = maketrap(u.ux, u.uy, TRAPDOOR); X ttmp->tseen = 1; X pline("You've made a hole in the floor."); X if(!u.ustuck && !Levitation) { /* KAA */ X if(inshop()) X shopdig(1); X pline("You fall through ..."); X if(u.utraptype == TT_PIT) { X u.utrap = 0; X u.utraptype = 0; X } X goto_level(dlevel+1, FALSE); X } X } X} X Xstatic Xuse_pick_axe(obj) Xstruct obj *obj; X{ X char dirsyms[12]; X extern char sdir[]; X register char *dsp = dirsyms, *sdp = sdir; X register struct monst *mtmp; X register struct rm *lev; X register int rx, ry, res = 0; X X#ifndef FREEHAND X /* edited by GAN 10/20/86 so that you can't apply the X * pick-axe while wielding a cursed weapon X */ X if(!freehand()) { X pline("You have no free hand to dig with!"); X return(0); X } X# ifdef KAA X if(cantwield(u.usym)) { X pline("You can't hold it strongly enough."); X return(0); X } X# endif X#else X if(obj != uwep) { X if(uwep && uwep->cursed) { X /* Andreas Bormann - ihnp4!decvax!mcvax!unido!ab */ X pline("Since your weapon is welded to your hand,"); X pline("you cannot use that pick-axe."); X return(0); X } X# ifdef KAA X if(cantwield(u.usym)) { X pline("You can't hold it strongly enough."); X return(0); X } X unweapon = TRUE; X# endif X pline("You now wield %s.", doname(obj)); X setuwep(obj); X res = 1; X } X#endif X while(*sdp) { X (void) movecmd(*sdp); /* sets u.dx and u.dy and u.dz */ X rx = u.ux + u.dx; X ry = u.uy + u.dy; X if(u.dz > 0 || (u.dz == 0 && isok(rx, ry) && X (IS_ROCK(levl[rx][ry].typ) X || sobj_at(ENORMOUS_ROCK, rx, ry)))) X *dsp++ = *sdp; X sdp++; X } X *dsp = 0; X pline("In what direction do you want to dig? [%s] ", dirsyms); X if(!getdir(0)) /* no txt */ X return(res); X if(u.uswallow && attack(u.ustuck)) /* return(1) */; X else X if(u.dz < 0) X pline("You cannot reach the ceiling."); X else X#ifdef KAA X if(!u.dx && !u.dy && !u.dz) { X pline("You hit yourself with your own pick-axe."); X losehp(rnd(2)+dbon(), "self-inflicted wound"); X flags.botl=1; X return(1); X } X#endif X if(u.dz == 0) { X if(Confusion) X confdir(); X rx = u.ux + u.dx; X ry = u.uy + u.dy; X if((mtmp = m_at(rx, ry)) && attack(mtmp)) X return(1); X if(!isok(rx, ry)) { X pline("Clash!"); X return(1); X } X lev = &levl[rx][ry]; X if(lev->typ == DOOR) X pline("Your %s against the door.", X aobjnam(obj, "clang")); X else if(!IS_ROCK(lev->typ) X && !sobj_at(ENORMOUS_ROCK, rx, ry)) { X /* ACCESSIBLE or POOL */ X pline("You swing your %s through thin air.", X aobjnam(obj, (char *) 0)); X } else { X if(dig_pos.x != rx || dig_pos.y != ry X || dig_level != dlevel || dig_down) { X dig_down = FALSE; X dig_pos.x = rx; X dig_pos.y = ry; X dig_level = dlevel; X dig_effort = 0; X pline("You start digging."); X } else X pline("You continue digging."); X#ifdef DGKMOD X set_occupation(dig, "digging", 0); X#else X occupation = dig; X occtxt = "digging"; X#endif X } X } else if(Levitation) { X pline("You cannot reach the floor."); X } else { X if(dig_pos.x != u.ux || dig_pos.y != u.uy X || dig_level != dlevel || !dig_down) { X dig_down = TRUE; X dig_pos.x = u.ux; X dig_pos.y = u.uy; X dig_level = dlevel; X dig_effort = 0; X pline("You start digging in the floor."); X if(inshop()) X shopdig(0); X } else X pline("You continue digging in the floor."); X#ifdef DGKMOD X set_occupation(dig, "digging", 0); X#else X occupation = dig; X occtxt = "digging"; X#endif X } X return(1); X} X X#ifdef RPH Xstatic Xuse_mirror(obj) Xstruct obj *obj; X{ X register struct monst *mtmp; X register char mlet; X extern mpickobj(), freeinv(), rloc(); X X if(!getdir(1)){ /* ask: in what direction? */ X flags.move = multi = 0; X return; X } X if(u.uswallow) { X pline("You reflect %s's stomach.", monnam(u.ustuck)); X return; X } X if(u.dz) { X pline("You reflect the %s.", X (u.dz > 0) ? "floor" : "ceiling"); X return; X } X if(!u.dx && !u.dy && !u.dz) { X if(!Blind) X pline ("You look as ugly as ever."); X else { X if (rn2(4-u.uluck/3) || !HTelepat) X pline ("You can't see your ugly face."); X else { X char *tm, *tl; int ll; X if (rn2(4)) { X tm = "ugly monster"; X ll = dlevel - u.medusa_level; X } X else { X tm = "intelligent being"; X ll = dlevel - u.wiz_level; X } X if (ll < -10) tl = "far below you"; X else if (ll < -1) tl = "below you"; X else if (ll == -1) tl = "under your feet"; X else if (ll == 0) tl = "very close to you"; X else if (ll == 1) tl = "above your head"; X else if (ll > 10) tl = "far above you"; X else tl = "above you"; X pline ("You get an impression that an %s lives %s.", X tm, tl); X } X } X return; X } X if(mtmp = bchit(u.dx, u.dy, COLNO, 0)) { X mlet = mtmp->data->mlet; X if(mtmp->msleep){ X pline ("%s is tired and doesn't look at your mirror.", X Monnam(mtmp)); X mtmp->msleep = 0; X } else X if (!mtmp->mcansee) { X pline("%s can't see anything at the moment.", X Monnam(mtmp)); X } X /* some monsters do special things */ X else if (!mtmp->mcan && index("EUN8",mlet)) X switch (mlet) { X case '8': X pline("%s is turned to stone!", Monnam(mtmp)); X killed(mtmp); X break; X case 'E': X pline("%s is frozen by its reflection.",Monnam(mtmp)); X mtmp->mfroz = 1; X break; X case 'U': X pline ("%s has confused itself!", Monnam(mtmp)); X mtmp->mconf = 1; X break; X case 'N': X pline ("%s looks beautiful in your mirror.",Monnam(mtmp)); X pline ("She decides to take it!"); X freeinv(obj); X mpickobj(mtmp,obj); X rloc(mtmp); X break; X default: X break; X } X else if (mlet == 'V' || mlet == '&') X pline ("%s doesn't seem to reflect anything.", Monnam(mtmp)); X else if (!index("agquv1N", mlet) && rn2(5)) { X pline ("%s is frightened by its reflection.", X Monnam(mtmp)); X mtmp->mflee = 1; X mtmp->mfleetim += d(2,4); X } X else X pline ("%s doesn't seem to mind %s refection.", X Monnam(mtmp), X (mlet=='1'?"his":(mlet=='N'?"her":"its"))); X }/* if monster hit with mirror */ X}/* use_mirror */ X X#endif X Xstatic Xuse_lamp(obj) Xstruct obj *obj; X{ X if(obj->spe <= 0 || obj->otyp == MAGIC_LAMP ) { X pline("This lamp has no oil."); X return; X } X litroom(TRUE); X obj->spe -= 1; X} X Xdorub() { X X if (!(carrying(LAMP) || carrying(MAGIC_LAMP))) { X pline("You do not have a lamp!"); X return; X } X if (!(uwep->otyp == LAMP || uwep->otyp == MAGIC_LAMP)) { X pline("You must wield the lamp to rub it!"); X return; X } X if (uwep->otyp == MAGIC_LAMP && uwep->spe > 0 && !rn2(3)) { X uwep->spe = 0; X djinni_from_bottle(); X } else if (uwep->otyp == MAGIC_LAMP && rn2(2) && !Blind) X pline("You see a puff of smoke."); X else pline("Nothing happens."); X} END_OF_apply.c if test 18510 -ne `wc -c fight.c <<'END_OF_fight.c' X/* SCCS Id: @(#)fight.c 2.3 87/12/12 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X X#include X#include "hack.h" X Xextern struct permonst li_dog, dog, la_dog; Xextern char *exclam(), *hcolor(), *xname(); Xextern struct obj *mkobj_at(); X#ifdef KAA Xextern boolean stoned; Xextern boolean unweapon; Xextern char *nomovemsg, *defmonnam(); Xextern struct monst *mkmon_at(); X#endif X#ifdef RPH Xextern struct obj *mk_named_obj_at(); X#endif X Xstatic boolean far_noise; Xstatic long noisetime; X X#ifdef STOOGES Xchar random_joke[][30] = {"Why I ought a ...", X "You'll get what's comming!", X "I'll murder you!", X "I get no respect!", X "Right in the kisser!", X "Wait a minute!", X "Take it easy!", X "Alright already!", X "That's more like it!", X "Well excuse me!", X "Take that!", X "I'll fix you!", X "I'm sorry!", X "Your mama!", X "Shut up!", X "Listen you!", X "Pardon me!", X "Not that!", X "Quiet!", X "Relax!", X "Certainly!", X "Ouch!", X "What happened?", X "What was that for?", X "What's the matter with you?", X "Oh Yea?", X "Wise guy eh?", X "How about a knuckle sandwich?", X "You coward!", X "You rat you!", X "You chuckelhead!", X "You bonehead!", X "You numbskull!", X "Nyak Nyak Nyak ...", X "Woop Woop Woop Woop ..."}; X#define RAND_JOKE 35 X#endif X X/* hitmm returns 0 (miss), 1 (hit), or 2 (kill) */ Xhitmm(magr,mdef) register struct monst *magr,*mdef; { Xregister struct permonst *pa = magr->data, *pd = mdef->data; Xint hit; Xschar tmp; Xboolean vis; X if(!magr || !mdef) return(0); /* mike@genat */ X if(index("Eauy", pa->mlet)) return(0); X if(magr->mfroz) return(0); /* riv05!a3 */ X tmp = pd->ac + pa->mlevel; X if(mdef->mconf || mdef->mfroz || mdef->msleep){ X tmp += 4; X if(mdef->msleep) mdef->msleep = 0; X } X hit = (tmp > rnd(20)); X if(hit) mdef->msleep = 0; X vis = (cansee(magr->mx,magr->my) && cansee(mdef->mx,mdef->my)); X if(vis){ X char buf[BUFSZ]; X if(mdef->mimic) seemimic(mdef); X if(magr->mimic) seemimic(magr); X (void) sprintf(buf,"%s %s", Monnam(magr), X hit ? "hits" : "misses"); X pline("%s %s.", buf, monnam(mdef)); X } else { X boolean farq = (dist(magr->mx, magr->my) > 15); X if(farq != far_noise || moves-noisetime > 10) { X far_noise = farq; X noisetime = moves; X pline("You hear some noises%s.", X farq ? " in the distance" : ""); X } X } X#ifdef STOOGES X if (hit && magr->isstooge) { X if (!rn2(6) && !index("afgvyF",mdef->data->mlet)) { X if(vis) X pline("%s is poked in the eye!", Monnam(mdef)); X mdef->mcansee = 0; X mdef->mblinded += rnd(10); X if (mdef->mblinded <= 0) mdef->mblinded = 127; X } else if (vis && mdef->isstooge) X switch (rn2(100)) { X case 0 : pline("%s is shoved!", Monnam(mdef)); X break; X case 1 : pline("%s is kicked!", Monnam(mdef)); X break; X case 2 : pline("%s is slapped!", Monnam(mdef)); X break; X case 3 : pline("%s is slugged!", Monnam(mdef)); X break; X case 4 : pline("%s is punched!", Monnam(mdef)); X break; X case 5 : pline("%s is pinched!", Monnam(mdef)); X break; X case 6 : pline("But %s dodges!", monnam(mdef)); X break; X case 7 : pline("But %s ducks!", monnam(mdef)); X break; X case 8 : pline("%s gets a black eye!", Monnam(mdef)); X break; X case 9 : pline("%s gets a bloody nose!", Monnam(mdef)); X break; X case 10: pline("%s gets a broken tooth!", Monnam(mdef)); X break; X } X if (!rn2(2)) X stoogejoke(); X } X if (magr->isstooge && mdef->isstooge) X return(hit); /* stooges don't damage each other */ X#endif X if(hit){ X if(magr->data->mlet == 'c' && !magr->cham) { X magr->mhpmax += 3; X if(vis) pline("%s is turned to stone!", Monnam(mdef)); X else if(mdef->mtame) X pline("You have a peculiarly sad feeling for a moment, then it passes."); X monstone(mdef); X hit = 2; X } else X if((mdef->mhp -= d(pa->damn,pa->damd)) < 1) { X magr->mhpmax += 1 + rn2(pd->mlevel+1); X if(magr->mtame && magr->mhpmax > 8*pa->mlevel){ X if(pa == &li_dog) magr->data = pa = &dog; X else if(pa == &dog) magr->data = pa = &la_dog; X } X if(vis) pline("%s is killed!", Monnam(mdef)); X else if(mdef->mtame) X pline("You have a sad feeling for a moment, then it passes."); X mondied(mdef); X hit = 2; X } X /* fixes a bug where max monster hp could overflow. */ X if(magr->mhpmax <= 0) magr->mhpmax = 127; X } X#ifdef KAA X if(hit == 1 && magr->data->mlet == 'Q') { X rloc(mdef); X if(vis && !cansee(mdef->mx,mdef->my)) X pline("%s suddenly disappears!",Monnam(mdef)); X } X#endif X return(hit); X} X X/* drop (perhaps) a cadaver and remove monster */ Xmondied(mdef) register struct monst *mdef; { Xregister struct permonst *pd = mdef->data; X#ifdef KOPS X if(pd->mlet != 'K') X#endif X { X#if defined(ROCKMOLE) && defined(KJSMODS) X /* if a giant rat is killed by a monster, do not make a X * corpse (like Keystone Kops above). */ X if(!(pd->mlet == 'r' && dlevel < 4)) X#endif X if(!(pd->mlet == '&' && mdef->isdjinni)) /* no djinni corpse */ X if(!(pd->mlet == 'G' && mdef->isgremlin)) /* no gremlin corpse */ X if(letter(pd->mlet) && rn2(3)) { X if (pd->mlet == '1') panic("mondied: making obj '1'"); X#ifndef RPH X (void) mkobj_at(pd->mlet,mdef->mx,mdef->my); X#else X (void) mk_named_obj_at(pd->mlet,mdef->mx,mdef->my, X NAME(mdef), mdef->mnamelth); X#endif X if(cansee(mdef->mx,mdef->my)){ X unpmon(mdef); X atl(mdef->mx,mdef->my,fobj->olet); X } X stackobj(fobj); X } X mondead(mdef); X } X} X X/* drop a rock and remove monster */ Xmonstone(mdef) X register struct monst *mdef; X{ X extern char mlarge[]; X if(index(mlarge, mdef->data->mlet)) X mksobj_at(ENORMOUS_ROCK, mdef->mx, mdef->my); X else X mksobj_at(ROCK, mdef->mx, mdef->my); X if(cansee(mdef->mx, mdef->my)){ X unpmon(mdef); X atl(mdef->mx,mdef->my,fobj->olet); X } X mondead(mdef); X} X X Xfightm(mtmp) X register struct monst *mtmp; X{ Xregister struct monst *mon; X X for(mon = fmon; mon; mon = mon->nmon) X if(mon != mtmp) { X if(DIST(mon->mx,mon->my,mtmp->mx,mtmp->my) < 3) X if(rn2(4)) return(hitmm(mtmp,mon)); X } X return(-1); X} X X/* u is hit by sth, but not a monster */ Xthitu(tlev,dam,name) X register tlev,dam; X register char *name; X{ X char buf[BUFSZ]; X X setan(name,buf); X if(u.uac + tlev <= rnd(20)) { X if(Blind) pline("It misses."); X else pline("You are almost hit by %s!", buf); X return(0); X } else { X if(Blind) pline("You are hit!"); X else pline("You are hit by %s!", buf); X losehp(dam,name); X return(1); X } X} X X#ifdef KAA Xchar mlarge[] = "bCDdegIlmnoPSsTUwY',&9"; X#else Xchar mlarge[] = "bCDdegIlmnoPSsTUwY',&"; X#endif X Xboolean Xhmon(mon,obj,thrown) /* return TRUE if mon still alive */ Xregister struct monst *mon; Xregister struct obj *obj; Xregister thrown; X{ X register tmp; X boolean hittxt = FALSE; X X#ifdef KAA X stoned = FALSE; /* this refers to the thing hit, not you */ X#endif X if(!obj){ X#ifdef KAA X/* Note that c, y, and F can never wield weapons anyway */ X if (u.usym == 'c' && mon->data->mlet != 'c') { X pline("You turn %s to stone!", monnam(mon)); X stoned = TRUE; X xkilled(mon,0); X return(FALSE); X } else if (u.usym == 'y' && mon->data->mlet != 'y') { X pline("%s is blinded by your flash of light!",Monnam(mon)); X if (!mon->mblinded) { X mon->mblinded += rn2(25); X mon->mcansee = 0; X } X rehumanize(); X return(TRUE); X } else if (u.usym == 'F') { X pline("You explode!"); X if (!index("gFY",mon->data->mlet)) { X pline("%s gets blasted!", Monnam(mon)); X mon->mhp -= d(6,6); X rehumanize(); X if (mon->mhp <= 0) { X killed(mon); X return(FALSE); X } else return(TRUE); X } else { X pline("The blast doesn't seem to affect %s.", monnam(mon)); X rehumanize(); X return(TRUE); X } X } else if (index("P,'", u.usym) && u.uhunger < 1500 X && !u.uswallow && mon->data->mlet != 'c') { X static char msgbuf[BUFSZ]; X pline("You swallow %s whole!", monnam(mon)); X u.uhunger += 20*mon->mhpmax; X newuhs(FALSE); X xkilled(mon,2); X if (tmp = mon->mhpmax/5) { X nomul(-tmp); X (void)sprintf(msgbuf, "You finished digesting %s.", X monnam(mon)); X nomovemsg = msgbuf; X } X return(FALSE); X } else if (u.usym != '@') { X if (u.usym == '&' && !rn2(5)) { X struct monst *dtmp; X pline("Some hell-p has arrived!"); X if((dtmp = mkmon_at('&',u.ux,u.uy))) X (void)tamedog(dtmp,(struct obj *)0); X } X tmp = d(mons[u.umonnum].damn, mons[u.umonnum].damd); X } else X#endif X tmp = rnd(2); /* attack with bare hands */ X#ifdef KAA X if (mon->data->mlet == 'c' && !uarmg && u.usym != 'c'){ X#else X if(mon->data->mlet == 'c' && !uarmg){ X#endif X pline("You hit the cockatrice with your bare hands."); X pline("You turn to stone ..."); X done_in_by(mon); X } X } else if(obj->olet == WEAPON_SYM || obj->otyp == PICK_AXE) { X if(obj == uwep && (obj->otyp > SPEAR || obj->otyp < BOOMERANG)) X tmp = rnd(2); X else { X if(index(mlarge, mon->data->mlet)) { X tmp = rnd(objects[obj->otyp].wldam); X switch (obj->otyp) { X case SLING_BULLET: X case CROSSBOW_BOLT: X case MORNING_STAR: X case PARTISAN: X case BROAD_SWORD: tmp += 1; break; X X case FLAIL: X case RANSEUR: X case VOULGE: tmp += rnd(4); break; X X case HALBERD: X case SPETUM: tmp += rnd(6); break; X X case BARDICHE: X case TRIDENT: tmp += d(2,4); break; X X case TWO_HANDED_SWORD: X case KATANA: tmp += d(2,6); break; X } X } else { X tmp = rnd(objects[obj->otyp].wsdam); X switch (obj->otyp) { X case SLING_BULLET: X case CROSSBOW_BOLT: X case MACE: X case FLAIL: X case SPETUM: X case TRIDENT: tmp += 1; break; X X case BARDICHE: X case BILL_GUISARME: X case GUISARME: X case LUCERN_HAMMER: X case MORNING_STAR: X case RANSEUR: X case BROAD_SWORD: X case VOULGE: tmp += rnd(4); break; X } X } X tmp += obj->spe; X#ifdef KAA X if(obj->olet == WEAPON_SYM && obj->dknown && index("VWZ &", X mon->data->mlet)) tmp += rn2(4); X#endif X if(!thrown && obj == uwep && obj->otyp == BOOMERANG X && !rn2(3)){ X pline("As you hit %s, the boomerang breaks into splinters.", X monnam(mon)); X freeinv(obj); X setworn((struct obj *) 0, obj->owornmask); X obfree(obj, (struct obj *) 0); X tmp++; X } X } X#ifdef BVH X if(!strcmp(ONAME(obj), "Excalibur")) tmp += rnd(10); X else X#endif X if(obj->otyp == KATANA X && !strcmp(ONAME(obj), "Snickersnee")) tmp += rnd(5); X X else if(mon->data->mlet == 'O' && obj->otyp == TWO_HANDED_SWORD X && !strcmp(ONAME(obj), "Orcrist")) tmp += rnd(10); X X else if((obj->otyp == SHORT_SWORD || obj->otyp == DAGGER) X && !strcmp(ONAME(obj), "Sting")) tmp += rnd(5); X X } else switch(obj->otyp) { X case HEAVY_IRON_BALL: X tmp = rnd(25); break; X case ENORMOUS_ROCK: X tmp = rnd(20); break; X#ifdef RPH X case MIRROR: X pline("You break your mirror. That's bad luck!"); X change_luck(-2); X freeinv(obj); X if(obj->owornmask) X setworn((struct obj *) 0, obj->owornmask); X obfree(obj, (struct obj *) 0); X return(TRUE); X#endif X case EXPENSIVE_CAMERA: X pline("You succeed in destroying your camera. Congratulations!"); X freeinv(obj); X if(obj->owornmask) X setworn((struct obj *) 0, obj->owornmask); X obfree(obj, (struct obj *) 0); X return(TRUE); X case DEAD_COCKATRICE: /* fixed by polder@cs.vu.nl */ X pline("You hit %s with the cockatrice corpse.", X monnam(mon)); X if(mon->data->mlet == 'c') { X tmp = 1; X hittxt = TRUE; X break; X } X pline ("%s is turned to stone!", Monnam(mon)); X#ifdef KAA X stoned = TRUE; X xkilled(mon,0); X#else X killed(mon); X#endif X return(FALSE); X case CLOVE_OF_GARLIC: /* no effect against demons */ X if(index(UNDEAD, mon->data->mlet)) X mon->mflee = 1; X tmp = 1; X break; X default: X /* non-weapons can damage because of their weight */ X /* (but not too much) */ X tmp = obj->owt/10; X if(tmp < 1) tmp = 1; X else tmp = rnd(tmp); X if(tmp > 6) tmp = 6; X } X X /****** NOTE: perhaps obj is undefined!! (if !thrown && BOOMERANG) */ X X tmp += u.udaminc + dbon(); X if(u.uswallow) { X if((tmp -= u.uswldtim) <= 0) { X pline("Your arms are no longer able to hit."); X return(TRUE); X } X } X if(tmp < 1) tmp = 1; X mon->mhp -= tmp; X if(mon->mhp < 1) { X killed(mon); X return(FALSE); X } X if(mon->mtame && (!mon->mflee || mon->mfleetim)) { X mon->mflee = 1; /* Rick Richardson */ X mon->mfleetim += 10*rnd(tmp); X } X X if(!hittxt) { X if(thrown) X /* this assumes that we cannot throw plural things */ X hit( xname(obj) /* or: objects[obj->otyp].oc_name */, X mon, exclam(tmp) ); X else if(Blind) X pline("You hit it."); X else X pline("You hit %s%s", monnam(mon), exclam(tmp)); X } X X if(u.umconf && !thrown) { X if(!Blind) { X pline("Your hands stop glowing %s.", X Hallucination ? hcolor() : "blue"); X } X if (!resist(mon, '+', 0, NOTELL)) mon->mconf = 1; X if(!mon->mfroz && !mon->msleep && !Blind && mon->mconf) X pline("%s appears confused.",Monnam(mon)); X u.umconf = 0; X } X if(!thrown && rn2(2) && index("VW",u.usym) && X !index("VW",mon->data->mlet)){ X int tmp=d(2,6); X pline("%s suddenly seems weaker!",Monnam(mon)); X mon->mhpmax -= tmp; X if ((mon->mhp -= tmp) <= 0) { X pline("%s dies!",Monnam(mon)); X xkilled(mon,0); X return(FALSE); X } X } X return(TRUE); /* mon still alive */ X} X X/* try to attack; return FALSE if monster evaded */ X/* u.dx and u.dy must be set */ Xattack(mtmp) Xregister struct monst *mtmp; X{ X schar tmp; X boolean malive = TRUE; X register struct permonst *mdat; X mdat = mtmp->data; X X#ifdef KAA X if(unweapon) { X unweapon=FALSE; X if(uwep) X pline("You begin bashing monsters with your %s.", X aobjnam(uwep,(char *)0)); X } X#endif X u_wipe_engr(3); /* andrew@orca: prevent unlimited pick-axe attacks */ X X if(mdat->mlet == 'L' && !mtmp->mfroz && !mtmp->msleep && X !mtmp->mconf && mtmp->mcansee && !rn2(7) && X (m_move(mtmp, 0) == 2 /* he died */ || /* he moved: */ X mtmp->mx != u.ux+u.dx || mtmp->my != u.uy+u.dy)) X return(FALSE); X#ifdef SAFE_ATTACK X /* This section of code provides protection against accidentally X * hitting peaceful (like '@') and tame (like 'd') monsters. X * There is protection only if you're not blind, confused or X * invisible. X */ X /* changes by wwp 5/16/85 */ X if (!Blind && !Confusion && !Hallucination X && mdat->mlet == 'd' && mtmp->mtame) { X char *dname; /* added by Janet Walz (walz@mimsy) */ X mtmp->mflee = 1; X mtmp->mfleetim = rnd(6); X if(*(dname = NAME(mtmp))) X pline("You stop to avoid hitting %s.",dname); X else X pline("You stop to avoid hitting your dog."); X return(TRUE); X } X if (flags.confirm && (mtmp->mpeaceful || mtmp->mtame) && ! Confusion X && !Hallucination && !Invisible) X X if (Blind ? Telepat : (!mtmp->minvis || See_invisible)) { X pline("Really attack %s?", monnam(mtmp)); X (void) fflush(stdout); X if (readchar() != 'y') { X flags.move = 0; X return(TRUE); X } X } X#endif /* SAFE_ATTACK /**/ X X if(mtmp->mimic){ X if(!u.ustuck && !mtmp->mflee) u.ustuck = mtmp; X if (levl[u.ux+u.dx][u.uy+u.dy].scrsym == DOOR_SYM) X { X if (okdoor(u.ux+u.dx, u.uy+u.dy)) X pline("The door actually was %s.", defmonnam(mtmp)); X else X pline("That spellbook was %s.", defmonnam(mtmp)); X } X else if (levl[u.ux+u.dx][u.uy+u.dy].scrsym == GOLD_SYM) X pline("The chest was %s!", defmonnam(mtmp)); X else X pline("Wait! That's %s!",defmonnam(mtmp)); X wakeup(mtmp); /* clears mtmp->mimic */ X return(TRUE); X } X X wakeup(mtmp); X X if(mtmp->mhide && mtmp->mundetected){ X register struct obj *obj; X X mtmp->mundetected = 0; X if((obj = o_at(mtmp->mx,mtmp->my)) && !Blind) X pline("Wait! There's %s hiding under %s!", X defmonnam(mtmp), doname(obj)); X return(TRUE); X } X#ifdef KAA X tmp = u.uluck + (u.mtimedone ? mons[u.umonnum].mlevel : u.ulevel) + X mdat->ac + abon(); X if (u.usym=='y' || u.usym=='F') tmp=100; X if (index("uEa",u.usym)) return(TRUE); X#else X tmp = u.uluck + u.ulevel + mdat->ac + abon(); X#endif X if(uwep) { X#ifdef KAA /* Blessed weapons used against undead or demons */ X if(uwep->olet == WEAPON_SYM && uwep->dknown && index("VWZ &", X mtmp->data->mlet)) tmp += 2; X#endif X if(uwep->olet == WEAPON_SYM || uwep->otyp == PICK_AXE) X tmp += uwep->spe; X#ifdef BVH X if(!strcmp(ONAME(uwep),"Excalibur")) tmp += 5; X#endif X if(uwep->otyp == TWO_HANDED_SWORD) tmp -= 1; X else if(uwep->otyp == KATANA) tmp += 1; X else if(uwep->otyp == DAGGER || X uwep->otyp == SHURIKEN) tmp += 2; X else if(uwep->otyp == CRYSKNIFE) tmp += 3; X else if(uwep->otyp == SPEAR && X index("XDne", mdat->mlet)) tmp += 2; X } X if(mtmp->msleep) { X mtmp->msleep = 0; X tmp += 2; X } X if(mtmp->mfroz) { X tmp += 4; X if(!rn2(10)) mtmp->mfroz = 0; X } X if(mtmp->mflee) tmp += 2; X if(u.utrap) tmp -= 3; X X /* with a lot of luggage, your agility diminishes */ X tmp -= (inv_weight() + 40)/20; X X if(tmp <= rnd(20) && !u.uswallow){ X if(Blind) pline("You miss it."); X else pline("You miss %s.",monnam(mtmp)); X } else { X /* we hit the monster; be careful: it might die! */ X X if((malive = hmon(mtmp,uwep,0)) == TRUE) { X /* monster still alive */ X if(!rn2(25) && mtmp->mhp < mtmp->mhpmax/2) { X mtmp->mflee = 1; X if(!rn2(3)) mtmp->mfleetim = rnd(100); X if(u.ustuck == mtmp && !u.uswallow) X u.ustuck = 0; X } X#ifndef NOWORM X if(mtmp->wormno) X cutworm(mtmp, u.ux+u.dx, u.uy+u.dy, X uwep ? uwep->otyp : 0); X#endif X } X if(mdat->mlet == 'a') { X if(rn2(2)) { X if (Blind) pline("You are splashed!"); X else pline("You are splashed by %s's acid!",monnam(mtmp)); X if (u.usym != 'a') { X losehp_m(rnd(6), mtmp); X if(!rn2(30)) corrode_armor(); X } X } X if(!rn2(6)) corrode_weapon(); X } X } X#ifdef KAA X if (malive) if (u.usym=='N' && mtmp->minvent) { X struct obj *otmp, *addinv(); X otmp = mtmp->minvent; X mtmp->minvent = otmp->nobj; X otmp = addinv(otmp); X pline("You steal:"); X prinv(otmp); X } else if (u.usym=='L' && mtmp->mgold) { X u.ugold += mtmp->mgold; X mtmp->mgold = 0; X pline("Your purse feels heavier."); X } else if (u.usym=='Q') rloc(mtmp); X#endif X if(malive && mdat->mlet == 'E' && canseemon(mtmp) X && !mtmp->mcan && rn2(3)) { X if(mtmp->mcansee) { X pline("You are frozen by %s's gaze!",monnam(mtmp)); X nomul((u.ulevel > 6 || rn2(4)) ? rn1(20,-21) : -200); X } else { X pline("%s cannot defend itself.", Amonnam(mtmp,"blinded")); X if(!rn2(500)) change_luck(-1); X } X } X return(TRUE); X} X X#ifdef STOOGES Xstoogejoke() { /* have the stooges say something funny */ X pline("'%s'", random_joke[rn2(RAND_JOKE)]); X} X#endif END_OF_fight.c if test 18493 -ne `wc -c mon.c <<'END_OF_mon.c' X/* SCCS Id: @(#)mon.c 2.3 87/12/12 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X X#include "hack.h" X#include "mfndpos.h" Xextern struct monst *makemon(), *mkmon_at(); Xextern struct trap *maketrap(); Xextern struct obj *mkobj_at(), *mksobj_at(); Xextern char *hcolor(); X#ifdef KAA Xextern boolean stoned; Xextern char mlarge[]; X#endif X#ifdef RPH Xextern struct obj *mk_named_obj_at(); X#endif X Xint warnlevel; /* used by movemon and dochugw */ Xlong lastwarntime; Xint lastwarnlev; Xchar *warnings[] = { "white", "pink", "red", "ruby", "purple", "black" }; X Xmovemon() X{ X register struct monst *mtmp; X register int fr; X X warnlevel = 0; X X while(1) { X /* find a monster that we haven't treated yet */ X /* note that mtmp or mtmp->nmon might get killed X while mtmp moves, so we cannot just walk down the X chain (even new monsters might get created!) */ X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) X if(mtmp->mlstmv < moves) goto next_mon; X /* treated all monsters */ X break; X X next_mon: X mtmp->mlstmv = moves; X X /* most monsters drown in pools */ X { boolean inpool,infountain,iseel,isgremlin; X extern struct permonst pm_gremlin; X X inpool = (levl[mtmp->mx][mtmp->my].typ == POOL); X iseel = (mtmp->data->mlet == ';'); X isgremlin = (mtmp->data->mlet == 'G' && mtmp->isgremlin); X infountain = (levl[mtmp->mx][mtmp->my].typ == FOUNTAIN); X if((inpool || infountain) && isgremlin && rn2(3)) { X coord mm; X enexto(&mm, mtmp->mx, mtmp->my); X if(cansee(mtmp->mx,mtmp->my) && X makemon(PM_GREMLIN, mm.x, mm.y)) X pline("%s multiplies.", Monnam(mtmp)); X if (infountain) dryup(); X } X if(inpool && !iseel && !isgremlin) { X if(cansee(mtmp->mx,mtmp->my)) X pline("%s drowns.", Monnam(mtmp)); X mondead(mtmp); X continue; X } X /* but eels have a difficult time outside */ X if(iseel && !inpool) { X if(mtmp->mhp > 1) mtmp->mhp--; X mtmp->mflee = 1; X mtmp->mfleetim += 2; X } X } X if(mtmp->mblinded && !--mtmp->mblinded) X mtmp->mcansee = 1; X if(mtmp->mfleetim && !--mtmp->mfleetim) X mtmp->mflee = 0; X#ifdef HARD X /* unwatched mimics and piercers may hide again [MRS] */ X if(restrap(mtmp)) continue; X#endif X if(mtmp->mimic) continue; X if(mtmp->mspeed != MSLOW || !(moves%2)){ X /* continue if the monster died fighting */ X fr = -1; X if(Conflict && cansee(mtmp->mx,mtmp->my) X && (fr = fightm(mtmp)) == 2) X continue; X#ifdef STOOGES X if((mtmp->isstooge) && cansee(mtmp->mx,mtmp->my) X && (fr = fightm(mtmp)) == 2) X continue; X#endif X if(fr<0 && dochugw(mtmp)) X continue; X } X if(mtmp->mspeed == MFAST && dochugw(mtmp)) X continue; X } X X warnlevel -= u.ulevel; X if(warnlevel >= SIZE(warnings)) X warnlevel = SIZE(warnings)-1; X if(warnlevel >= 0) X if(warnlevel > lastwarnlev || moves > lastwarntime + 5){ X register char *rr; X switch((int) (Warning & (LEFT_RING | RIGHT_RING))){ X case LEFT_RING: X rr = "Your left ring glows"; X break; X case RIGHT_RING: X rr = "Your right ring glows"; X break; X case LEFT_RING | RIGHT_RING: X rr = "Both your rings glow"; X break; X default: X rr = "Your fingertips glow"; X break; X } X pline("%s %s!", rr, Hallucination ? hcolor() : warnings[warnlevel]); X lastwarntime = moves; X lastwarnlev = warnlevel; X } X X dmonsfree(); /* remove all dead monsters */ X} X Xjustswld(mtmp,name) Xregister struct monst *mtmp; Xchar *name; X{ X X mtmp->mx = u.ux; X mtmp->my = u.uy; X u.ustuck = mtmp; X pmon(mtmp); X kludge("%s swallows you!",name); X more(); X seeoff(1); X u.uswallow = 1; X u.uswldtim = 0; X swallowed(); X} X Xyouswld(mtmp,dam,die,name) Xregister struct monst *mtmp; Xregister dam,die; Xchar *name; X{ X if(mtmp != u.ustuck) return; X kludge("%s digests you!",name); X u.uhp -= dam; X if(u.uswldtim++ >= die){ /* a3 */ X pline("It totally digests you!"); X u.uhp = -1; X } X if(u.uhp < 1) done_in_by(mtmp); X /* flags.botlx = 1; /* should we show status line ? */ X} X X#ifdef ROCKMOLE Xmeatgold(mtmp) register struct monst *mtmp; { Xregister struct gold *gold; Xregister int pile; Xregister struct obj *otmp; X#ifdef KJSMODS X if(dlevel < 4) return; X#endif X /* Eats gold if it is there */ X while(gold = g_at(mtmp->mx, mtmp->my)){ X freegold(gold); X /* Left behind a pile? */ X pile = rnd(25); X if(pile < 3) mksobj_at(ROCK, mtmp->mx, mtmp->my); X newsym(mtmp->mx, mtmp->my); X } X /* Eats armor if it is there */ X otmp = o_at(mtmp->mx,mtmp->my); X if((otmp) && (otmp->otyp >= PLATE_MAIL) && (otmp->otyp <= RING_MAIL)){ X freeobj(otmp); X /* Left behind a pile? */ X pile = rnd(25); X if(pile < 3) mksobj_at(ROCK, mtmp->mx, mtmp->my); X newsym(mtmp->mx, mtmp->my); X } X} X#endif /* ROCKMOLE /**/ X Xmpickgold(mtmp) register struct monst *mtmp; { Xregister struct gold *gold; X while(gold = g_at(mtmp->mx, mtmp->my)){ X mtmp->mgold += gold->amount; X freegold(gold); X if(levl[mtmp->mx][mtmp->my].scrsym == GOLD_SYM) X newsym(mtmp->mx, mtmp->my); X } X} X X/* Now includes giants which pick up enormous rocks. KAA */ Xmpickgems(mtmp) register struct monst *mtmp; { Xregister struct obj *otmp; X for(otmp = fobj; otmp; otmp = otmp->nobj) X if(otmp->olet == X#ifdef KAA X (mtmp->data->mlet=='9' ? ROCK_SYM : GEM_SYM)) X#else X GEM_SYM) X#endif X if(otmp->ox == mtmp->mx && otmp->oy == mtmp->my) X if(mtmp->data->mlet != 'u' || objects[otmp->otyp].g_val != 0){ X freeobj(otmp); X mpickobj(mtmp, otmp); X#ifndef KAA X if(levl[mtmp->mx][mtmp->my].scrsym == GEM_SYM) X#endif X newsym(mtmp->mx, mtmp->my); /* %% */ X return; /* pick only one object */ X } X} X X/* return number of acceptable neighbour positions */ Xmfndpos(mon,poss,info,flag) Xregister struct monst *mon; Xcoord poss[9]; Xlong info[9], flag; X{ X register int x,y,nx,ny,cnt = 0,ntyp; X register struct monst *mtmp; X int nowtyp; X boolean pool; X X x = mon->mx; X y = mon->my; X nowtyp = levl[x][y].typ; X X pool = (mon->data->mlet == ';'); Xnexttry: /* eels prefer the water, but if there is no water nearby, X they will crawl over land */ X if(mon->mconf) { X flag |= ALLOW_ALL; X flag &= ~NOTONL; X } X for(nx = x-1; nx <= x+1; nx++) for(ny = y-1; ny <= y+1; ny++) X if(nx != x || ny != y) if(isok(nx,ny)) X#ifdef ROCKMOLE X if(!IS_ROCK(ntyp = levl[nx][ny].typ) || (flag & ALLOW_WALL)) X#else X if(!IS_ROCK(ntyp = levl[nx][ny].typ)) X#endif X if(!(nx != x && ny != y && (nowtyp == DOOR || ntyp == DOOR))) X if((ntyp == POOL) == pool) { X info[cnt] = 0; X if(nx == u.ux && ny == u.uy){ X if(!(flag & ALLOW_U)) continue; X info[cnt] = ALLOW_U; X } else if(mtmp = m_at(nx,ny)){ X if(!(flag & ALLOW_M)) continue; X info[cnt] = ALLOW_M; X if(mtmp->mtame){ X if(!(flag & ALLOW_TM)) continue; X info[cnt] |= ALLOW_TM; X } X } X if(sobj_at(CLOVE_OF_GARLIC, nx, ny)) { X if(flag & NOGARLIC) continue; X info[cnt] |= NOGARLIC; X } X if(sobj_at(SCR_SCARE_MONSTER, nx, ny) || X (!mon->mpeaceful && sengr_at("Elbereth", nx, ny))) { X if(!(flag & ALLOW_SSM)) continue; X info[cnt] |= ALLOW_SSM; X } X if(sobj_at(ENORMOUS_ROCK, nx, ny)) { X if(!(flag & ALLOW_ROCK)) continue; X info[cnt] |= ALLOW_ROCK; X } X if(!Invis && online(nx,ny)){ X if(flag & NOTONL) continue; X info[cnt] |= NOTONL; X } X /* we cannot avoid traps of an unknown kind */ X { register struct trap *ttmp = t_at(nx, ny); X register long tt; X if(ttmp) { X/* tt = 1L << ttmp->ttyp;*/ X/* why don't we just have code look like what it's supposed to do? then it X/* might start working for every case. try this instead: -sac */ X tt = (ttmp->ttyp < TRAPNUM && ttmp->ttyp > 0); X /* below if added by GAN 02/06/87 to avoid X * traps out of range X */ X if(!(tt & ALLOW_TRAPS)) { X impossible("A monster looked at a very strange trap of type %d.", ttmp->ttyp); X continue; X } X if(mon->mtrapseen & tt){ X if(!(flag & tt)) continue; X info[cnt] |= tt; X } X } X } X poss[cnt].x = nx; X poss[cnt].y = ny; X cnt++; X } X if(!cnt && pool && nowtyp != POOL) { X pool = FALSE; X goto nexttry; X } X return(cnt); X} X Xdist(x,y) int x,y; { X return((x-u.ux)*(x-u.ux) + (y-u.uy)*(y-u.uy)); X} X Xpoisoned(string, pname) Xregister char *string, *pname; X{ X register i, plural; X X plural = (string[strlen(string) - 1] == 's')? 1 : 0; X if(Blind) { X if (plural) pline("They were poisoned."); X else pline("It was poisoned."); X } else { X if (plural) pline("The %s were poisoned!", string); X else pline("The %s was poisoned!", string); X } X X if(Poison_resistance) { X pline("The poison doesn't seem to affect you."); X return; X } X i = rn2(10); X if(i == 0) { X u.uhp = -1; X pline("I am afraid the poison was deadly ..."); X } else if(i <= 5) { X losestr(rn1(3,3)); X } else { X losehp(rn1(10,6), pname); X } X if(u.uhp < 1) { X killer = pname; X done("died"); X } X} X Xmondead(mtmp) Xregister struct monst *mtmp; X{ X relobj(mtmp,1); X unpmon(mtmp); X relmon(mtmp); X unstuck(mtmp); X#ifdef KOPS X if(mtmp->data->mlet == 'K' && X !strcmp(mtmp->data->mname,"Keystone Kop")) { X /* When a Kop dies, he probably comes back. */ X switch(rnd(3)) { X X case 1: /* returns near the stairs */ X mkmon_at('K',xdnstair,ydnstair); X break; X case 2: /* randomly */ X mkmon_at('K',0,0); X break; X default: X break; X } X } X#endif X if(mtmp->isshk) shkdead(mtmp); X if(mtmp->isgd) gddead(); X#ifndef NOWORM X if(mtmp->wormno) wormdead(mtmp); X#endif X#ifdef HARD X if(mtmp->data->mlet == '1') wizdead(mtmp); X#endif X monfree(mtmp); X} X X/* called when monster is moved to larger structure */ Xreplmon(mtmp,mtmp2) Xregister struct monst *mtmp, *mtmp2; X{ X relmon(mtmp); X monfree(mtmp); X mtmp2->nmon = fmon; X fmon = mtmp2; X if(u.ustuck == mtmp) u.ustuck = mtmp2; X if(mtmp2->isshk) replshk(mtmp,mtmp2); X if(mtmp2->isgd) replgd(mtmp,mtmp2); X} X Xrelmon(mon) Xregister struct monst *mon; X{ X register struct monst *mtmp; X X if (fmon == 0) panic ("relmon: no fmon available."); X X if(mon == fmon) fmon = fmon->nmon; X else { X for(mtmp = fmon; mtmp && mtmp->nmon != mon; mtmp = mtmp->nmon) ; X mtmp->nmon = mon->nmon; X } X} X X/* we do not free monsters immediately, in order to have their name X available shortly after their demise */ Xstruct monst *fdmon; /* chain of dead monsters, need not to be saved */ X Xmonfree(mtmp) register struct monst *mtmp; { X mtmp->nmon = fdmon; X fdmon = mtmp; X} X Xdmonsfree(){ Xregister struct monst *mtmp; X while(mtmp = fdmon){ X fdmon = mtmp->nmon; X free((char *) mtmp); X } X} X Xunstuck(mtmp) Xregister struct monst *mtmp; X{ X if(u.ustuck == mtmp) { X if(u.uswallow){ X u.ux = mtmp->mx; X u.uy = mtmp->my; X u.uswallow = 0; X setsee(); X docrt(); X } X u.ustuck = 0; X } X} X Xkilled(mtmp) Xregister struct monst *mtmp; X{ X xkilled(mtmp, 1); X} X Xxkilled(mtmp, dest) Xregister struct monst *mtmp; Xint dest; X/* Dest=1, normal; dest=0, don't print message; dest=2, don't drop corpse X either; dest=3, message but no corpse */ X{ X#ifdef LINT X#define NEW_SCORING X#endif X register int tmp,tmp2,nk,x,y; X register struct permonst *mdat = mtmp->data; X extern long newuexp(); X#ifdef RPH X int old_nlth; X char old_name[BUFSZ]; X#endif X X if(mtmp->cham) mdat = PM_CHAMELEON; X if (dest & 1) { X if(Blind) pline("You destroy it!"); X else { X pline("You destroy %s!", X mtmp->mtame ? amonnam(mtmp, "poor") : monnam(mtmp)); X } X } X if(u.umconf) { X if(!Blind) X { X pline("Your hands stop glowing %s.", X Hallucination ? hcolor() : "blue"); X } X u.umconf = 0; X } X X /* count killed monsters */ X#define MAXMONNO 100 X nk = 1; /* in case we cannot find it in mons */ X tmp = mdat - mons; /* index in mons array (if not 'd', '@', ...) */ X if(tmp >= 0 && tmp < CMNUM+2) { X extern char fut_geno[]; X u.nr_killed[tmp]++; X if((nk = u.nr_killed[tmp]) > MAXMONNO && X#ifdef HARD X# ifdef KOPS X !index("KkO&", mdat->mlet) && X# else X !index("kO&", mdat->mlet) && X# endif X#endif X !index(fut_geno, mdat->mlet)) X charcat(fut_geno, mdat->mlet); X } X X /* punish bad behaviour */ X if(mdat->mlet == '@') { X HTelepat = 0; X change_luck(-2); X } X if(mtmp->mpeaceful || mtmp->mtame) change_luck(-1); X if(mdat->mlet == 'u') change_luck(-5); X X /* give experience points */ X tmp = 1 + mdat->mlevel * mdat->mlevel; X if(mdat->ac < 3) tmp += 2*(7 - mdat->ac); X if(index("AcsSDXaeRTVWU&In:P389",mdat->mlet)) tmp += 2*mdat->mlevel; X if(index("DeV&P",mdat->mlet)) tmp += (7*mdat->mlevel); X if(mdat->mlevel > 6) tmp += 50; X if(mdat->mlet == ';') tmp += 1000; X X#ifdef NEW_SCORING X /* ------- recent addition: make nr of points decrease X when this is not the first of this kind */ X { int ul = u.ulevel; X int ml = mdat->mlevel; X X if(ul < 14) /* points are given based on present and future level */ X for(tmp2 = 0; !tmp2 || ul + tmp2 <= ml; tmp2++) X if(u.uexp + 1 + (tmp + ((tmp2 <= 0) ? 0 : 4<<(tmp2-1)))/nk X >= 10*pow((unsigned)(ul-1))) X if(++ul == 14) break; X X tmp2 = ml - ul -1; X tmp = (tmp + ((tmp2 < 0) ? 0 : 4<= newuexp()){ X#ifdef RPH X /* make experience gaining simiar to d&d, whereby you */ X /* can at most go up by one level at a time, extra expr */ X /* possibly helping you along. Afterall, how much real */ X /* experience does one get shooting a wand of death at */ X /* a dragon created w/ a poymorph?? */ X u.ulevel++; X if (u.uexp >= newuexp()) X u.uexp = newuexp() - 1; X pline("Welcome to experience level %u.", u.ulevel); X#else X pline("Welcome to experience level %u.", ++u.ulevel); X#endif X tmp = rnd(10); X if(tmp < 3) tmp = rnd(10); X u.uhpmax += tmp; X u.uhp += tmp; X#ifdef SPELLS X tmp = rnd(u.ulevel/2+1) + 1; /* M. Stephenson */ X u.uenmax += tmp; X u.uen += tmp; X#endif X flags.botl = 1; X } X X /* dispose of monster and make cadaver */ X x = mtmp->mx; y = mtmp->my; X#ifdef RPH X old_nlth = mtmp->mnamelth; X if (old_nlth > 0) (void) strcpy (old_name, NAME(mtmp)); X#endif X if (mdat->mlet == '&' && mtmp->isdjinni) { /* no djinni corpse */ X mondead(mtmp); X return; X } X if (mdat->mlet == 'G' && mtmp->isgremlin) { /* no gremlin corpse */ X mondead(mtmp); X return; X } X mondead(mtmp); X tmp = mdat->mlet; X if(tmp == 'm') { /* he killed a minotaur, give him a wand of digging */ X /* note: the dead minotaur will be on top of it! */ X mksobj_at(WAN_DIGGING, x, y); X /* if(cansee(x,y)) atl(x,y,fobj->olet); */ X stackobj(fobj); X } else X#ifndef NOWORM X if(tmp == 'w') { X mksobj_at(WORM_TOOTH, x, y); X stackobj(fobj); X } else X#endif X#ifdef KJSMODS X if(tmp == 'N') { X mksobj_at(POT_OBJECT_DETECTION, x, y); X stackobj(fobj); X } else X#endif X#ifdef SAC X if(tmp == '3') { X ; /* don't do anything special- keep it from failing on */ X /* call to letter(tmp) */ X } else X#endif /* SAC */ X#ifdef KAA X if(tmp == '&') (void) mkobj_at(0, x, y); X else X if(stoned == FALSE && (!letter(tmp) || (!index("9&1", tmp) && !rn2(3)))) tmp = 0; X if(dest & 2) { X newsym(x,y); X return; X } X#else X if(!letter(tmp) || (!index("mw", tmp) && !rn2(3))) tmp = 0; X#endif X tmp2 = rn2(5); X#ifdef KJSMODS X /* if a kobold or a giant rat does not become treasure, do X * not make a corpse. */ X# ifdef KOPS X if(mdat->mlet == 'K' X && !strcmp(mdat->mname,"kobold") && tmp) tmp2 = 0; X# endif X# ifdef ROCKMOLE X if((mdat->mlet == 'r' && dlevel < 4) && tmp) tmp2 = 0; X# endif X#endif X if(!ACCESSIBLE(levl[x][y].typ)) { X /* might be mimic in wall or dead eel*/ X newsym(x,y); X } else if(x != u.ux || y != u.uy) { X /* might be here after swallowed */ X#ifdef KAA X if(stoned) { X register int typetmp; X if(index(mlarge, tmp)) typetmp = ENORMOUS_ROCK; X else typetmp = ROCK; X mksobj_at(typetmp, x, y); X if(cansee(x,y)) X atl(x, y, Hallucination ? rndobjsym() : X objects[typetmp].oc_olet); X } else X#endif X if(index("NTVm&w",mdat->mlet) || tmp2) { X#ifndef RPH X register struct obj *obj2 = mkobj_at(tmp,x,y); X#else X register struct obj *obj2; X if (letter(tmp)) X obj2 = mk_named_obj_at(tmp, x, y, X old_name, old_nlth); X# ifdef KOPS X else if (mdat->mlet == 'K') X obj2 = mksobj_at((rn2(2) ? CLUB : X (rn2(2)) ? WHISTLE : BADGE), x, y); X# endif X else X obj2 = mkobj_at(tmp,x,y); X#endif /* RPH /**/ X if(cansee(x,y)) X atl(x, y, Hallucination ? rndobjsym() : obj2->olet); X stackobj(obj2); X } X } X} X Xkludge(str,arg) Xregister char *str,*arg; X{ X if(Blind) { X if(*str == '%') pline(str,"It"); X else pline(str,"it"); X } else pline(str,arg); X} X Xrescham() /* force all chameleons to become normal */ X{ X register struct monst *mtmp; X X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) X if(mtmp->cham) { X mtmp->cham = 0; X (void) newcham(mtmp, PM_CHAMELEON); X } X} X X#ifdef DGKMOD X/* Let the chameleons change again -dgk */ Xrestartcham() X{ X register struct monst *mtmp; X X for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) X if (mtmp->data->mlet == ':') X mtmp->cham = 1; X} X#endif X Xnewcham(mtmp,mdat) /* make a chameleon look like a new monster */ X /* returns 1 if the monster actually changed */ Xregister struct monst *mtmp; Xregister struct permonst *mdat; X{ X register mhp, hpn, hpd; X X#ifdef RPH X /* mdat = 0 -> caller wants a random monster shape */ X if (mdat == 0) { X /* ie. minimum shape is mons[15], minimum random range */ X /* is 3, and randomness tails off as you descend into the */ X /* depths max shape is mons[CMNUM-1] */ X mdat = &mons[CMNUM-1-rn2((CMNUM-17) - (CMNUM-20)*dlevel/MAXLEVEL)]; X } X#endif X if(mdat == mtmp->data) return(0); /* still the same monster */ X#ifndef NOWORM X if(mtmp->wormno) wormdead(mtmp); /* throw tail away */ X#endif X hpn = mtmp->mhp; X hpd = (mtmp->data->mlevel)*8; if(!hpd) hpd = 4; X mhp = (mdat->mlevel)*8; if(!mhp) mhp = 4; X X /* new hp: same fraction of max as before */ X mtmp->mhp = (hpn*mhp)/hpd; X if (mhp > hpd && mtmp->mhp < hpn) mtmp->mhp = 127; X/* Not totally foolproof. A 2HD monster with 80 HP that changes into a 6HD X monster that really should have 240 and actually should have 127, the X maximum possible, will wind up having 113. */ X if (!mtmp->mhp) mtmp->mhp = 1; X/* Unlikely but not impossible; a 1HD creature with 1HP that changes into a X 0HD creature will require this statement */ X mtmp->data = mdat; X/* and the same for maximum hit points */ X hpn = mtmp->mhpmax; X mtmp->mhpmax = (hpn*mhp)/hpd; X if (mhp > hpd && mtmp->mhpmax < hpn) mtmp->mhp = 127; X if (!mtmp->mhp) mtmp->mhp = 1; X X mtmp->minvis = (mdat->mlet == 'I') ? 1 : 0; X /* only snakes and scorpions can hide under things -dgk */ X /* also generated by GAN */ X mtmp->mhide = (mdat->mlet == 'S' || mdat->mlet == 's') ? 1 : 0; X if (!mtmp->mhide) mtmp->mundetected = 0; X#ifndef NOWORM X if(mdat->mlet == 'w' && getwn(mtmp)) initworm(mtmp); X /* perhaps we should clear mtmp->mtame here? */ X#endif X unpmon(mtmp); /* necessary for 'I' and to force pmon */ X pmon(mtmp); X return(1); X} X Xmnexto(mtmp) /* Make monster mtmp next to you (if possible) */ Xstruct monst *mtmp; X{ X coord mm; X enexto(&mm, u.ux, u.uy); X mtmp->mx = mm.x; X mtmp->my = mm.y; X pmon(mtmp); X} X Xishuman(mtmp) register struct monst *mtmp; { X return(mtmp->data->mlet == '@'); X} X Xsetmangry(mtmp) register struct monst *mtmp; { X if(!mtmp->mpeaceful) return; X if(mtmp->mtame) return; X mtmp->mpeaceful = 0; X if(ishuman(mtmp)) pline("%s gets angry!", Monnam(mtmp)); X} X X/* not one hundred procent correct: now a snake may hide under an X invisible object */ Xcanseemon(mtmp) Xregister struct monst *mtmp; X{ X return((!mtmp->minvis || See_invisible) X && (!mtmp->mhide || !o_at(mtmp->mx,mtmp->my)) X && cansee(mtmp->mx, mtmp->my)); X} X Xdisturb(mtmp) /* awaken monsters while in the same room. X * return a 1 if they have been woken. X */ Xregister struct monst *mtmp; X{ X /* wake up, or get out of here. */ X /* ettins are hard to surprise */ X /* Nymphs and Leprechauns do not easily wake up */ X if(cansee(mtmp->mx,mtmp->my) && X (!Stealth || (mtmp->data->mlet == 'e' && rn2(10))) && X (!index("NL",mtmp->data->mlet) || !rn2(50)) && X#ifdef RPH X (Aggravate_monster || index("8d1", mtmp->data->mlet) X#else X (Aggravate_monster || index("d1", mtmp->data->mlet) X#endif X || (!rn2(7) && !mtmp->mimic))) { X mtmp->msleep = 0; X return(1); X } X if(Hallucination) pmon(mtmp); X return(0); X} X X#ifdef HARD Xrestrap(mtmp) /* unwatched mimics and piercers may hide again, X * if so, a 1 is returned. X */ Xregister struct monst *mtmp; X{ X if(mtmp->data->mlet == 'M' && !mtmp->mimic && !mtmp->cham X && !mtmp->mcan && !cansee(mtmp->mx, mtmp->my) X && !rn2(3)) { X mtmp->mimic = 1; X mtmp->mappearance = (levl[mtmp->mx][mtmp->my].typ == DOOR) ? DOOR_SYM : GOLD_SYM; X return(1); X } X X if(mtmp->data->mlet == 'p' && !mtmp->cham X && !mtmp->mcan && !cansee(mtmp->mx, mtmp->my) X && !rn2(3)) { X X if(levl[mtmp->mx][mtmp->my].typ == ROOM) { X X maketrap(mtmp->mx, mtmp->my, PIERC); X mondead(mtmp); X return(1); X } X } X return(0); X} X#endif END_OF_mon.c if test 20710 -ne `wc -c read.c <<'END_OF_read.c' X/* SCCS Id: @(#)read.c 2.3 88/01/21 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X X#include "hack.h" X Xextern struct monst *makemon(); Xextern struct permonst pm_eel; Xextern struct obj *mkobj_at(); Xchar *hcolor(); Xboolean known; Xint identify(); X Xdoread() { X register struct obj *scroll; X register boolean confused = (Confusion != 0); X X known = FALSE; X scroll = getobj("#-?", "read"); /* "#-" added by GAN 10/22/86 */ X if(!scroll) return(0); X X /* below added to allow reading of fortune cookies */ X if(scroll->otyp == FORTUNE_COOKIE) { X if(Blind) { X pline("This cookie has a scrap of paper inside!"); X pline("What a pity, that you cannot read it!"); X } else X outrumor(); X useup(scroll); X return(1); X } else X if(scroll->olet != SCROLL_SYM) { X pline("That is a silly thing to read."); X return(0); X } X X if(!scroll->dknown && Blind) { X pline("Being blind, you cannot read the formula on the scroll."); X return(0); X } X if(Blind) X pline("As you pronounce the formula on it, the scroll disappears."); X else X pline("As you read the scroll, it disappears."); X if(confused) { X if (Hallucination) X pline("Being so trippy, you screw up ... "); X else X pline("Being confused, you mispronounce the magic words ... "); X } X if(!seffects(scroll)) { X if(!objects[scroll->otyp].oc_name_known) { X if(known && !confused) { X objects[scroll->otyp].oc_name_known = 1; X more_experienced(0,10); X } else if(!objects[scroll->otyp].oc_uname) X docall(scroll); X } X#ifdef MARKER X if(!(scroll->otyp == SCR_BLANK_PAPER) || confused) X#endif X useup(scroll); X } X return(1); X} X Xseffects(sobj) X register struct obj *sobj; X{ X extern struct obj *some_armor(); X register boolean confused = (Confusion != 0); X X switch(sobj->otyp) { X#ifdef MAIL X case SCR_MAIL: X readmail(/* scroll */); X break; X#endif X case SCR_ENCHANT_ARMOR: X { X register struct obj *otmp = some_armor(); X if(!otmp) { X strange_feeling(sobj,"Your skin glows then fades."); X return(1); X } X if(confused) { X pline("Your %s is covered by a shimmering %s %s!", X objects[otmp->otyp].oc_name, Hallucination ? hcolor() : X "gold", (otmp->otyp == SHIELD ? "layer" : "shield")); X otmp->rustfree = 1; X break; X } X#ifdef KAA X if(otmp->spe > (otmp->otyp == ELFIN_CHAIN_MAIL ? 5 : 3) X && rn2(otmp->spe)) { X#else X if(otmp->spe > 3 && rn2(otmp->spe)) { X#endif X pline("Your %s glows violently %s for a while, then evaporates.", X objects[otmp->otyp].oc_name, X Hallucination ? hcolor() : "green"); X useup(otmp); X break; X } X pline("Your %s glows %s for a moment.", X objects[otmp->otyp].oc_name, X Hallucination ? hcolor() : "green"); X otmp->cursed = 0; X otmp->spe++; X break; X } X case SCR_DESTROY_ARMOR: X if(confused) { X register struct obj *otmp = some_armor(); X if(!otmp) { X strange_feeling(sobj,"Your bones itch."); X return(1); X } X pline("Your %s glows %s for a moment.", X objects[otmp->otyp].oc_name, X Hallucination ? hcolor() : "purple"); X otmp->rustfree = 0; X break; X } X if(!destroy_arm()) { X strange_feeling(sobj,"Your skin itches."); X return(1); X } X break; X case SCR_CONFUSE_MONSTER: X#ifdef SPELLS X case SPE_CONFUSE_MONSTER: X#endif X if(u.usym != '@') { X pline("You feel confused."); X HConfusion += rnd(100); X } else if(confused) { X pline("Your hands begin to glow %s.", X Hallucination ? hcolor() : "purple"); X HConfusion += rnd(100); X } else { X pline("Your hands begin to glow %s.", X Hallucination ? hcolor() : "blue"); X u.umconf = 1; X } X break; X case SCR_SCARE_MONSTER: X#ifdef SPELLS X case SPE_CAUSE_FEAR: X#endif X { register int ct = 0; X register struct monst *mtmp; X X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) X if(cansee(mtmp->mx,mtmp->my)) { X if(confused) X mtmp->mflee = mtmp->mfroz = mtmp->msleep = 0; X else X if (! resist(mtmp, sobj->olet, 0, NOTELL)) X mtmp->mflee = 1; X ct++; X } X if(!ct) X pline("You hear %s in the distance.", X (confused) ? "sad wailing" : "maniacal laughter"); X#ifdef KAA X# ifdef SPELLS X else if(sobj->otyp == SCR_SCARE_MONSTER) X# endif X pline ("You hear %s close by.", X (confused) ? "sad wailing" : "maniacal laughter"); X#endif X break; X } X case SCR_BLANK_PAPER: X if(confused) X pline("You see strange patterns on this scroll."); X else { X pline("This scroll seems to be blank."); X#ifdef MARKER X pline("No, wait..."); X known = TRUE; X#endif X } X break; X case SCR_REMOVE_CURSE: X#ifdef SPELLS X case SPE_REMOVE_CURSE: X#endif X { register struct obj *obj; X if(confused) X if (Hallucination) X pline("You feel the power of the Force against you!"); X else X pline("You feel like you need some help."); X else X if (Hallucination) X pline("You feel in touch with the Universal Oneness."); X else X pline("You feel like someone is helping you."); X for(obj = invent; obj ; obj = obj->nobj) X if(obj->owornmask) X obj->cursed = confused; X if(Punished && !confused) { X Punished = 0; X freeobj(uchain); X unpobj(uchain); X free((char *) uchain); X uball->spe = 0; X uball->owornmask &= ~W_BALL; X uchain = uball = (struct obj *) 0; X } X break; X } X case SCR_CREATE_MONSTER: X#ifdef SPELLS X case SPE_CREATE_MONSTER: X#endif X { register int cnt = 1; X X if(!rn2(73)) cnt += rnd(4); X if(confused) cnt += 12; X while(cnt--) X#ifdef WIZARD X if(wizard) { X char buf[BUFSZ], cmlet; X struct permonst *crmonst; X X do { X pline("What monster to create? "); X getlin(buf); X } while(strlen(buf) != 1); X cmlet = buf[0]; X for(crmonst = mons; crmonst->mlet != cmlet && X crmonst != PM_EEL; crmonst++) ; X (void) makemon(crmonst, u.ux, u.uy); X } else X#endif /* WIZARD /**/ X (void) makemon(confused ? PM_ACID_BLOB : X (struct permonst *) 0, u.ux, u.uy); X break; X } X case SCR_ENCHANT_WEAPON: X if(uwep && uwep->olet == WEAPON_SYM && confused) { X /* olet check added 10/25/86 GAN */ X pline("Your %s covered by a shimmering %s shield!", X aobjnam(uwep, "are"), X Hallucination ? hcolor() : "gold"); X uwep->rustfree = 1; X } else X if(!chwepon(sobj, 1)) /* tests for !uwep */ X return(1); X break; X case SCR_DAMAGE_WEAPON: X if(uwep && uwep->olet == WEAPON_SYM && confused) { X /* olet check added 10/25/86 GAN */ X pline("Your %s %s for a moment.", X aobjnam(uwep,"glow"), X Hallucination ? hcolor() : "purple"); X uwep->rustfree = 0; X } else X if(!chwepon(sobj, -1)) /* tests for !uwep */ X return(1); X break; X case SCR_TAMING: X#ifdef SPELLS X case SPE_CHARM_MONSTER: X#endif X { register int i,j; X register int bd = confused ? 5 : 1; X register struct monst *mtmp; X X for(i = -bd; i <= bd; i++) for(j = -bd; j <= bd; j++) X if(mtmp = m_at(u.ux+i, u.uy+j)) X if(!resist(mtmp, sobj->olet, 0, NOTELL)) X (void) tamedog(mtmp, (struct obj *) 0); X break; X } X case SCR_GENOCIDE: X pline("You have found a scroll of genocide!"); X#ifdef SPELLS X case SPE_GENOCIDE: X#endif X known = TRUE; X do_genocide(); X break; X case SCR_LIGHT: X if(!Blind) known = TRUE; X litroom(!confused); X break; X case SCR_TELEPORTATION: X if(confused) X level_tele(); X else { X#ifdef QUEST X register int oux = u.ux, ouy = u.uy; X tele(); X if(dist(oux, ouy) > 100) known = TRUE; X#else X register int uroom = inroom(u.ux, u.uy); X tele(); X if(uroom != inroom(u.ux, u.uy)) known = TRUE; X#endif X if(Teleport_control) X known = TRUE; X } X break; X case SCR_GOLD_DETECTION: X /* Unfortunately this code has become slightly less elegant, X now that gold and traps no longer are of the same type. */ X if(confused) { X register struct trap *ttmp; X X if(!ftrap) { X strange_feeling(sobj, "Your toes stop itching."); X return(1); X } else { X for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) X if(ttmp->tx != u.ux || ttmp->ty != u.uy) X goto outtrapmap; X /* only under me - no separate display required */ X pline("Your toes itch!"); X break; X outtrapmap: X cls(); X for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) X at(ttmp->tx, ttmp->ty, Hallucination ? rndobjsym() : GOLD_SYM); X prme(); X pline("You feel very greedy!"); X } X } else { X register struct gold *gtmp; X X if(!fgold) { X strange_feeling(sobj, "You feel materially poor."); X return(1); X } else { X known = TRUE; X for(gtmp = fgold; gtmp; gtmp = gtmp->ngold) X if(gtmp->gx != u.ux || gtmp->gy != u.uy) X goto outgoldmap; X /* only under me - no separate display required */ X pline("You notice some gold between your feet."); X break; X outgoldmap: X cls(); X for(gtmp = fgold; gtmp; gtmp = gtmp->ngold) X at(gtmp->gx, gtmp->gy, Hallucination ? rndobjsym() : GOLD_SYM); X prme(); X pline("You feel very greedy, and sense gold!"); X } X } X /* common sequel */ X more(); X docrt(); X break; X case SCR_FOOD_DETECTION: X#ifdef SPELLS X case SPE_DETECT_FOOD: X#endif X { register ct = 0, ctu = 0; X register struct obj *obj; X register char foodsym = confused ? POTION_SYM : FOOD_SYM; X X for(obj = fobj; obj; obj = obj->nobj) X if(obj->olet == foodsym) { X if(obj->ox == u.ux && obj->oy == u.uy) ctu++; X else ct++; X } X if(!ct && !ctu) { X strange_feeling(sobj,"Your nose twitches."); X return(1); X } else if(!ct) { X known = TRUE; X pline("You smell %s close nearby.", X confused ? "something" : "food"); X X } else { X known = TRUE; X cls(); X for(obj = fobj; obj; obj = obj->nobj) X if(obj->olet == foodsym) X at(obj->ox, obj->oy, Hallucination ? rndobjsym() : X FOOD_SYM); X prme(); X pline("Your nose tingles and you smell %s!", X confused ? "something" : "food"); X more(); X docrt(); X } X break; X } X case SCR_IDENTIFY: X /* known = TRUE; */ X if(confused) X pline("You identify this as an identify scroll."); X else X pline("This is an identify scroll."); X useup(sobj); X objects[SCR_IDENTIFY].oc_name_known = 1; X#ifdef SPELLS X case SPE_IDENTIFY: X#endif X if(!confused) X while(!ggetobj("identify", identify, rn2(5) ? 1 : rn2(5)) && invent); X return(1); X case SCR_MAGIC_MAPPING: X known = TRUE; X pline("On this scroll %s a map!", confused ? "was" : "is"); X#ifdef SPELLS X case SPE_MAGIC_MAPPING: X#endif X do_mapping(); X break; X case SCR_AMNESIA: X { register int zx, zy; X X known = TRUE; X for(zx = 0; zx < COLNO; zx++) for(zy = 0; zy < ROWNO; zy++) X if(!confused || rn2(7)) X if(!cansee(zx,zy)) X levl[zx][zy].seen = 0; X docrt(); X pline("Who was that Maude person anyway?"); X#ifdef SPELLS X losespells(); X#endif X break; X } X case SCR_FIRE: X { register int num; X register struct monst *mtmp; X X/* X * Note: This case was modified 11/4/86 by DKC to eliminate the problem with X * reading a scroll of fire while confused or resistant to fire. Formerly, X * the code failed to initialize the variable "num" in these cases, resulting X * in monsters being hit for a possibly large (and possibly negative) damage. X * The actions taken now are: X * If the player is fire resistant, monsters X * take the normal damage (1-6 except for Y's and F's), and the player is X * unaffected. X */ X known = TRUE; X if(confused) { X if(Fire_resistance) X pline("Oh look, what a pretty fire in your hands."); X else { X pline("The scroll catches fire and you burn your hands."); X losehp(1, "scroll of fire"); X } X break; X } X pline("The scroll erupts in a tower of flame!"); X num = rnd(6); X if(Fire_resistance) X pline("You are uninjured."); X else { X u.uhpmax -= num; X losehp(num, "scroll of fire"); X } X num = (2*num + 1)/3; X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) { X if(dist(mtmp->mx,mtmp->my) < 3) { X mtmp->mhp -= num; /* No saving throw! */ X if(index("FY", mtmp->data->mlet)) X mtmp->mhp -= 3*num; /* this might well kill 'F's */ X if(mtmp->mhp < 1) { X killed(mtmp); X break; /* primitive */ X } X } X } X break; X } X case SCR_PUNISHMENT: X known = TRUE; X if(confused) { X pline("You feel guilty."); X break; X } X pline("You are being punished for your misbehavior!"); X if(Punished){ X pline("Your iron ball gets heavier."); X uball->owt += 15; X break; X } X Punished = INTRINSIC; X setworn(mkobj_at(CHAIN_SYM, u.ux, u.uy), W_CHAIN); X setworn(mkobj_at(BALL_SYM, u.ux, u.uy), W_BALL); X uball->spe = 1; /* special ball (see save) */ X break; X default: X impossible("What weird effect is this? (%u)", sobj->otyp); X } X return(0); X} X Xidentify(otmp) /* also called by newmail() */ Xregister struct obj *otmp; X{ X objects[otmp->otyp].oc_name_known = 1; X#ifdef KAA X otmp->known = 1; X if (otmp->olet != WEAPON_SYM) otmp->dknown = 1; X/* Now, the dknown field is special for weapons, indicating blessing. */ X#else X otmp->known = otmp->dknown = 1; X#endif X prinv(otmp); X return(1); X} X Xlitroom(on) Xregister boolean on; X{ X register num,zx,zy; X X /* first produce the text (provided he is not blind) */ X if(Blind) goto do_it; X if(!on) { X if(u.uswallow || !xdnstair || levl[u.ux][u.uy].typ == CORR || X !levl[u.ux][u.uy].lit) { X pline("It seems even darker in here than before."); X return; X } else X pline("It suddenly becomes dark in here."); X } else { X if(u.uswallow){ X pline("%s's stomach is lit.", Monnam(u.ustuck)); X return; X } X if(!xdnstair){ X pline("Nothing Happens."); X return; X } X#ifdef QUEST X pline("The cave lights up around you, then fades."); X return; X#else X if(levl[u.ux][u.uy].typ == CORR) { X pline("The corridor lights up around you, then fades."); X return; X } else if(levl[u.ux][u.uy].lit) { X pline("The light here seems better now."); X return; X } else X pline("The room is lit."); X#endif X } X Xdo_it: X#ifdef QUEST X return; X#else X if(levl[u.ux][u.uy].lit == on) X return; X if(levl[u.ux][u.uy].typ == DOOR) { X if(IS_ROOM(levl[u.ux][u.uy+1].typ)) zy = u.uy+1; X else if(IS_ROOM(levl[u.ux][u.uy-1].typ)) zy = u.uy-1; X else zy = u.uy; X if(IS_ROOM(levl[u.ux+1][u.uy].typ)) zx = u.ux+1; X else if(IS_ROOM(levl[u.ux-1][u.uy].typ)) zx = u.ux-1; X else zx = u.ux; X } else { X zx = u.ux; X zy = u.uy; X } X for(seelx = u.ux; (num = levl[seelx-1][zy].typ) != CORR && num != 0; X seelx--); X for(seehx = u.ux; (num = levl[seehx+1][zy].typ) != CORR && num != 0; X seehx++); X for(seely = u.uy; (num = levl[zx][seely-1].typ) != CORR && num != 0; X seely--); X for(seehy = u.uy; (num = levl[zx][seehy+1].typ) != CORR && num != 0; X seehy++); X for(zy = seely; zy <= seehy; zy++) X for(zx = seelx; zx <= seehx; zx++) { X levl[zx][zy].lit = on; X if(!Blind && dist(zx,zy) > 2) X if(on) prl(zx,zy); else nosee(zx,zy); X } X if(!on) seehx = 0; X#endif X} X X/* Test whether we may genocide all monsters with symbol ch */ Xmonstersym(ch) /* arnold@ucsfcgl */ Xregister char ch; X{ X register struct permonst *mp; X X /* X * can't genocide certain monsters X */ X#ifdef SAC X if (index("123 &:", ch)) return FALSE; X#else X if (index("12 &:", ch)) return FALSE; X#endif X if (ch == pm_eel.mlet) return TRUE; X for (mp = mons; mp < &mons[CMNUM+2]; mp++) X if (mp->mlet == ch) return TRUE; X X return FALSE; X} X Xdo_genocide() { X extern char genocided[], fut_geno[]; X char buf[BUFSZ]; X register struct monst *mtmp, *mtmp2; X X if(Confusion != 0) *buf = u.usym; X else do { X pline("What monster do you want to genocide (Type the letter)? "); X getlin(buf); X } X X while(strlen(buf) != 1 || !monstersym(*buf)); X X if(!index(fut_geno, *buf)) charcat(fut_geno, *buf); X if(!index(genocided, *buf)) charcat(genocided, *buf); X else { X pline("Such monsters do not exist in this world."); X return; X } X for(mtmp = fmon; mtmp; mtmp = mtmp2){ X mtmp2 = mtmp->nmon; X if(mtmp->data->mlet == *buf) X mondead(mtmp); X } X pline("Wiped out all %c's.", Hallucination ? '@' : *buf); X /* Scare the hallucinating player */ X if(*buf == '@') { X u.uhp = -1; X killer = "scroll of genocide"; X /* A polymorphed character will die as soon as he is rehumanized. */ X if(u.usym != '@') pline("You feel dead inside."); X else done("died"); X } X#ifdef KAA X else if (*buf==u.usym) rehumanize(); X#endif X} X Xdo_mapping() X{ X register struct rm *lev; X register int num, zx, zy; X X for(zy = 0; zy < ROWNO; zy++) X for(zx = 0; zx < COLNO; zx++) { X X if((Confusion != 0) && rn2(7)) continue; X lev = &(levl[zx][zy]); X if((num = lev->typ) == 0) continue; X X if(num == SCORR) { X lev->typ = CORR; X lev->scrsym = CORR_SYM; X } else if(num == SDOOR) { X lev->typ = DOOR; X lev->scrsym = DOOR_SYM; X /* do sth in doors ? */ X } else if(lev->seen) continue; X#ifndef QUEST X if(num != ROOM) X#endif X { X lev->seen = lev->new = 1; X if(lev->scrsym == STONE_SYM || !lev->scrsym) X newsym(zx,zy); X else on_scr(zx,zy); X } X } X} X Xdestroy_arm() { X X if(uarm) { X pline("Your armor turns to dust and falls to the floor!"); X useup(uarm); X#ifdef SHIRT X } else if(uarmu) { X pline("Your shirt crumbles into tiny threads and falls apart!"); X useup(uarmu); X#endif X } else if(uarmh) { X pline("Your helmet turns to dust and is blown away!"); X useup(uarmh); X } else if(uarmg) { X pline("Your gloves vanish!"); X useup(uarmg); X selftouch("You"); X } else if(uarms) { X pline("Your shield crumbles away!"); X useup(uarms); X } else return(0); /* could not destroy anything */ X X return(1); X} END_OF_read.c if test 17107 -ne `wc -c rumors.kaa <<'END_OF_rumors.kaa' XYou should always be sure to learn about quantum mechanics. XAn apple a day keeps the doctor away. XA crystal plate mail will not rust. XTry using your magic marker on wet scrolls! XCrystal plate is the rarest of all. XHealers are immune to the effects of nurses. XBashing monsters with a bow is not such a good idea. XWait! That's a fortune! XEver broken an egg against the ground? XFinding traps is a lot like finding gold. XFinding potions is a lot like finding food. XRust traps are harmless if you are wearing an elven cloak. XDon't bother trying to control teleports if you are not awake. XEver gone into the morgue at midnight? XWielding a dead cockatrice may actually work. XLeaving the dungeon while hallucinating may get you arrested. XDrinking potions of booze may land you in jail if you are under 21. XA dilithium crystal is the most valuable mineral around. XValkyrie comes from the north, and has commensurate abilities. XElf has extra speed. XGushes of water won't necessarily hit your head. XPlaying Gauntlet might be enlightening in some situations. XA short sword is not as good as a long sword. XA bardiche is better than a sword. XA trident is a nice thing to have. XUsing a morning star in the evening has no effect. XPolymorphing a shopkeeper might make you safer. XYou cannot quench your thirst in a water trap. XAfraid of nymphs? Wear a ring of adornment. XGiant bats turn into giant vampires. XI wouldn't advise playing catch with a giant. XAfraid of your valuables being stolen? Carry more junk! XHoly water has many uses. XYou swallowed the fortune!!! XYou hear the fortune cookie's hissing! XA pie fight. Now that's fun! XMesses attract ants. XWhy are you wasting time reading fortunes? XHelp! I'm being held prisoner in a fortune cookie factory! XOnly elves can wear elfin chain mail. XAre you SURE that's a wand of wishing? XCroesus? Who's he? XIf you want a sex change, you must get it before the game. XShopkeepers value money more than revenge. XShopkeepers can't tell identical twins apart. XYou're going into the morgue at midnight???? XDidn't your mother tell you not to eat food off the floor? XTrolls are described as rubbery: they keep bouncing back. XMark your way with a magic marker. XA magic marker is like a wand of digging, but less so. XA dead cockatrice is just a dead lizard. XYou need 512k to implement the magic memory vaults. XEveryone's goal is to get to heaven. XHeaven can wait. XUnused potions are like unburned scrolls. XEver read a tin of fire? XYou may want to dip into a potion of bottled blessings. XTridents are for use underwater. XWe have new ways of detecting treachery... XCave(wo)men all belong to the same club. XIf you thought the wizard was bad, just wait till you meet the Warlord! XYou are filled with a feeling of awwwww. XValkyries, elves, and wizards need food badly. XNetHack was modified by Miracleman (Ken Arromdee). XYou may discover a fine spirit inside a potion bottle. XLong live Phoenix! XMost of the bugs in Hack are on the floor. XWhat does a dead demon taste like? XIf you kill a ghost, how will you find the body? XA ring of dungeon master control is a great find. XEver lifted a dead dragon? XEver see your weapon glow plaid? XPlaying AD&D may be helpful. XWhat is a three sided die shaped like? XWhat is a zero sided die shaped like? XWhat is a cockatrice going to eat when it gets hungry? XHitting a giant that is picking up a boulder may be difficult. XA softly glowing weapon can kill a demon. XThe orc swings his two handed sword named Elfrist at you. You die... XZap yourself and see what happens... END_OF_rumors.kaa if test 3523 -ne `wc -c trap.c <<'END_OF_trap.c' X/* SCCS Id: @(#)trap.c 2.3 87/12/16 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X X#include X#include "hack.h" X Xextern struct monst *makemon(); Xextern struct obj *mksobj_at(); X X#ifdef KAA Xextern char *Xmonnam(); Xextern char *nomovemsg; X#endif X Xchar vowels[] = "aeiou"; X Xchar *traps[] = { X "", X " bear trap", X "n arrow trap", X " dart trap", X " trapdoor", X " teleportation trap", X " pit", X " sleeping gas trap", X " piercer", X " mimic" X#ifdef NEWTRAPS X ," magic trap" X ," squeaky board" X#endif X#ifdef SPIDERS X ," web" X#endif X#ifdef NEWCLASS X ," spiked pit" X ," level teleporter" X#endif X#ifdef SPELLS X ," anti-magic field" X#endif X#ifdef KAA X ," rust trap" X# ifdef RPH X ," polymorph trap" X# endif X#endif X#ifdef SAC X ," land mine" X#endif X}; X Xstruct trap * Xmaketrap(x,y,typ) Xregister x,y,typ; X{ X register struct trap *ttmp; X X ttmp = newtrap(); X ttmp->ttyp = typ; X ttmp->tseen = 0; X ttmp->once = 0; X ttmp->tx = x; X ttmp->ty = y; X ttmp->ntrap = ftrap; X ftrap = ttmp; X return(ttmp); X} X Xdotrap(trap) register struct trap *trap; { X register int ttype = trap->ttyp; X register struct monst *mtmp; X X nomul(0); X if(trap->tseen && !rn2(5) && !(ttype == PIT X#ifdef NEWCLASS X || ttype == SPIKED_PIT X#endif X#ifdef SPELLS X || ttype == ANTI_MAGIC X#endif X )) X pline("You escape a%s.", traps[ttype]); X else { X trap->tseen = 1; X switch(ttype) { X case SLP_GAS_TRAP: X pline("A cloud of gas puts you to sleep!"); X nomul(-rnd(25)); X break; X case BEAR_TRAP: X if(Levitation) { X pline("You float over a bear trap."); X break; X } X u.utrap = 4 + rn2(4); X u.utraptype = TT_BEARTRAP; X pline("A bear trap closes on your foot!"); X if(u.usym=='o') pline("You howl in anger!"); X break; X case PIERC: X deltrap(trap); X if(mtmp=makemon(PM_PIERCER,u.ux,u.uy)) { X pline("%s suddenly drops from the ceiling!", Xmonnam(mtmp)); X if(uarmh) X pline("Its blow glances off your helmet."); X else X (void) thitu(3,d(4,6),"falling piercer"); X } X break; X case ARROW_TRAP: X pline("An arrow shoots out at you!"); X if(!thitu(8,rnd(6),"arrow")){ X mksobj_at(ARROW, u.ux, u.uy); X fobj->quan = 1; X } X break; X case TRAPDOOR: X if(!xdnstair) { Xpline("A trap door in the ceiling opens and a rock falls on your head!"); Xif(uarmh) pline("Fortunately, you are wearing a helmet!"); X losehp(uarmh ? 2 : d(2,10),"falling rock"); X mksobj_at(ROCK, u.ux, u.uy); X fobj->quan = 1; X stackobj(fobj); X if(Invisible) newsym(u.ux, u.uy); X } else { X register int newlevel = dlevel + 1; X while(!rn2(4) && newlevel < 29) X newlevel++; X pline("A trap door opens up under you!"); X if(Levitation || u.ustuck) { X pline("For some reason you don't fall in."); X break; X } X fflush(stdout); X goto_level(newlevel, FALSE); X } X break; X case DART_TRAP: X pline("A little dart shoots out at you!"); X if(thitu(7,rnd(3),"little dart")) { X if(!rn2(6)) X poisoned("dart","poison dart"); X } else { X mksobj_at(DART, u.ux, u.uy); X fobj->quan = 1; X } X break; X case TELEP_TRAP: X if(trap->once) { X deltrap(trap); X newsym(u.ux,u.uy); X vtele(); X } else { X newsym(u.ux,u.uy); X tele(); X } X break; X#ifdef KAA X case RUST_TRAP: X switch (rn2(5)) { X case 0: X pline("A gush of water hits you on the head!"); X if (uarmh) { X if (uarmh->rustfree) X pline("Your helmet is not affected!"); X else if (uarmh->spe > -6) { X pline("Your helmet rusts!"); X uarmh->spe--; X } else X pline("Your helmet looks quite rusted now."); X } X break; X case 1: X pline("A gush of water hits your left arm!"); X if (uarms) { X pline("Your shield is not affected!"); X break; X } X if (uwep && uwep->otyp == TWO_HANDED_SWORD) goto two_hand; X /* Two goto statements in a row--aaarrrgggh! */ X glovecheck: if(uarmg) pline("Your gloves are not affected!"); X break; X case 2: X pline("A gush of water hits your right arm!"); X two_hand: corrode_weapon(); X goto glovecheck; X default: X pline("A gush of water hits you!"); X if (uarm) { X if (uarm->rustfree || X uarm->otyp >= STUDDED_LEATHER_ARMOR) X pline("Your %s not affected!", X aobjnam(uarm,"are")); X else if(uarm->spe > -6) { X pline("Your %s!", X aobjnam(uarm,"corrode")); X uarm->spe--; X } else X pline("Your %s quite rusted now.", X aobjnam(uarm, "look")); X } X } X break; X#endif X case PIT: X if (Levitation || index("EyBfk'&",u.usym)) { X pline("A pit opens up under you!"); X pline("You don't fall in!"); X break; X } X pline("You fall into a pit!"); X u.utrap = rn1(6,2); X u.utraptype = TT_PIT; X losehp(rnd(6),"fall into a pit"); X selftouch("Falling, you"); X break; X#ifdef NEWCLASS X case SPIKED_PIT: X if (Levitation || index("EyBfk'&",u.usym)) { X pline("A pit opens up under you!"); X pline("You don't fall in!"); X pline("There are spikes in that pit!!!"); X break; X } X pline("You fall into a pit!"); X pline("You land on a set of sharp iron spikes!"); X u.utrap = rn1(6,2); X u.utraptype = TT_PIT; X losehp(rnd(10),"fall onto iron spikes"); X if(!rn2(6)) poisoned("spikes","poison spikes"); X selftouch("Falling, you"); X break; X case LEVEL_TELEP: X if (!Blind) pline("You are momentarily blinded by a flash of light"); X else pline("You are momentarily disoriented."); X deltrap(trap); X newsym(u.ux,u.uy); X level_tele(); X break; X#endif X#ifdef SPELLS X case ANTI_MAGIC: X pline("You feel your magical energy drain away!"); X u.uen -= (rnd(u.ulevel) + 1); X if(u.uen < 0) { X u.uenmax += u.uen; X if(u.uenmax < 0) u.uenmax = 0; X u.uen = 0; X } X flags.botl = 1; X break; X#endif X#if defined(RPH) && defined(KAA) X case POLY_TRAP: X pline("You feel a change coming over you."); X polyself(); X deltrap(trap); X break; X#endif X#ifdef NEWTRAPS X case MGTRP: X /* A magic trap. */ X domagictrap(); X break; X case SQBRD: { X#include "edog.h" X register struct monst *mtmp = fmon; X /* Stepped on a squeaky board. */ X pline("A board underfoot gives off a loud squeak!"); X /* Wake up nearby monsters. */ X while(mtmp) { X if(dist(mtmp->mx,mtmp->my) < u.ulevel*20) { X if(mtmp->msleep) X mtmp->msleep = 0; X if(mtmp->mtame) X EDOG(mtmp)->whistletime = moves; X } X mtmp = mtmp->nmon; X } X } X break; X#endif X#ifdef SPIDERS X case WEB: X X /* Our luckless adventurer has stepped into a web. */ X X pline("You've stumbled into a spider web!"); X u.utraptype = TT_WEB; X X /* Time stuck in the web depends on your strength. */ X X if (u.ustr == 3) u.utrap = rn1(6,6); X else if (u.ustr < 6) u.utrap = rn1(6,4); X else if (u.ustr < 9) u.utrap = rn1(4,4); X else if (u.ustr < 12) u.utrap = rn1(4,2); X else if (u.ustr < 15) u.utrap = rn1(2,2); X else if (u.ustr < 18) u.utrap = rnd(2); X else if (u.ustr < 69) u.utrap = 1; X else { X u.utrap = 0; X pline("You tear through the web!"); X deltrap(trap); X } X break; X#endif X#ifdef SAC X case LANDMINE: { X register struct monst *mtmp = fmon; X X pline("KAABLAMM!!! You stepped on a land mine!"); X losehp(rnd(16), "land mine"); X set_wounded_legs(LEFT_SIDE, 40 + rnd(35)); X set_wounded_legs(RIGHT_SIDE, 40 + rnd(35)); X /* wake everything on the level */ X while(mtmp) { X if(mtmp->msleep) X mtmp->msleep = 0; X mtmp = mtmp->nmon; X } X deltrap(t_at(u.ux, u.uy)); /* mines only explode once */ X break; X } X#endif /* SAC */ X default: X impossible("You hit a trap of type %u", trap->ttyp); X } X } X} X Xmintrap(mtmp) register struct monst *mtmp; { X register struct trap *trap = t_at(mtmp->mx, mtmp->my); X register int wasintrap = mtmp->mtrapped; X X if(!trap) { X mtmp->mtrapped = 0; /* perhaps teleported? */ X } else if(wasintrap) { X if(!rn2(40)) mtmp->mtrapped = 0; X } else { X register int tt = trap->ttyp; X#ifdef DGK X /* A bug fix for dumb messages by ab@unido. X */ X int in_sight = cansee(mtmp->mx,mtmp->my) X && (!mtmp->minvis || See_invisible); X#else X int in_sight = cansee(mtmp->mx,mtmp->my); X#endif X extern char mlarge[]; X X if(mtmp->mtrapseen & (1 << tt)) { X /* he has been in such a trap - perhaps he escapes */ X if(rn2(4)) return(0); X } X mtmp->mtrapseen |= (1 << tt); X switch (tt) { X case BEAR_TRAP: X if(index(mlarge, mtmp->data->mlet)) { X if(in_sight) X pline("%s is caught in a bear trap!", X Monnam(mtmp)); X else X if(mtmp->data->mlet == 'o') X pline("You hear the roaring of an angry bear!"); X mtmp->mtrapped = 1; X } X break; X#ifdef KAA X# ifdef RPH X case POLY_TRAP: X if(!resist(mtmp, '/', 0, NOTELL)) X newcham(mtmp,&mons[rn2(CMNUM)]); X break; X# endif X case RUST_TRAP: X if(in_sight) X pline("A gush of water hits %s!",monnam(mtmp)); X break; X#endif X case PIT: X#ifdef NEWCLASS X case SPIKED_PIT: X#endif X /* there should be a mtmp/data -> floating */ X if(!index("EywBIfk'& ", mtmp->data->mlet)) { /* ab */ X mtmp->mtrapped = 1; X if(in_sight) X pline("%s falls into a pit!", Monnam(mtmp)); X } X break; X case SLP_GAS_TRAP: X if(!mtmp->msleep && !mtmp->mfroz) { X mtmp->msleep = 1; X if(in_sight) X pline("%s suddenly falls asleep!", X Monnam(mtmp)); X } X break; X case TELEP_TRAP: X#ifdef NEWCLASS X case LEVEL_TELEP: X#endif X rloc(mtmp); X if(in_sight && !cansee(mtmp->mx,mtmp->my)) X pline("%s suddenly disappears!", X Monnam(mtmp)); X break; X case ARROW_TRAP: X if(in_sight) X pline("%s is hit by an arrow!", Monnam(mtmp)); X mtmp->mhp -= 3; X break; X case DART_TRAP: X if(in_sight) X pline("%s is hit by a dart!", Monnam(mtmp)); X mtmp->mhp -= 2; X /* not mondied here !! */ X break; X case TRAPDOOR: X if(!xdnstair) { X mtmp->mhp -= 10; X if(in_sight) Xpline("A trap door in the ceiling opens and a rock hits %s!", monnam(mtmp)); X break; X } X if(!index("EywBIfk", mtmp->data->mlet)){ X fall_down(mtmp); X if(in_sight) X pline("Suddenly, %s disappears out of sight.", monnam(mtmp)); X return(2); /* no longer on this level */ X } X break; X case PIERC: X break; X#ifdef NEWTRAPS X case MGTRP: X /* A magic trap. Monsters immune. */ X break; X case SQBRD: { X register struct monst *ztmp = fmon; X X if(index("EyBIfk", mtmp->data->mlet)) break; X /* Stepped on a squeaky board. */ X if (in_sight) X pline("%s steps on a squeaky board.", Monnam(mtmp)); X else X pline("You hear a distant squeak."); X /* Wake up nearby monsters. */ X while(ztmp) { X if(dist2(mtmp->mx,mtmp->my,ztmp->mx,ztmp->my) < 40) X if(ztmp->msleep) ztmp->msleep = 0; X ztmp = ztmp->nmon; X } X break; X } X#endif X#ifdef SPIDERS X case WEB: X /* Monster in a web. */ X /* in_sight check and confused bear by Eric Backus */ X if(mtmp->data->mlet != 's') { X if(in_sight) X pline("%s is caught in a web!", Monnam(mtmp)); X else X if(mtmp->data->mlet == 'o') X pline("You hear the roaring of a confused bear!"); X mtmp->mtrapped = 1; X } X break; X#endif X#ifdef SPELLS X case ANTI_MAGIC: break; X#endif X#ifdef SAC X case LANDMINE: { X register struct monst *mntmp = fmon; X X if(rn2(3)) X break; /* monsters usually don't set it off */ X if(in_sight) X pline("KAABLAMM!!! %s steps on a land mine!", X Monnam(mtmp)); X else X pline("Kaablamm! You hear an explosion in the distance!"); X mtmp->mhp -= rn2(16); X deltrap(t_at(mtmp->mx, mtmp->my)); X /* wake everything on the level */ X while(mntmp) { X if(mntmp->msleep) X mntmp->msleep = 0; X mntmp = mntmp->nmon; X } X break; X } X#endif X default: X impossible("Some monster encountered a strange trap of type %d.",tt); X } X } X return(mtmp->mtrapped); X} X Xselftouch(arg) char *arg; { X if(uwep && uwep->otyp == DEAD_COCKATRICE){ X pline("%s touch the dead cockatrice.", arg); X pline("You turn to stone."); X pline("You die..."); X killer = objects[uwep->otyp].oc_name; X done("died"); X } X} X Xfloat_up(){ X if(u.utrap) { X if(u.utraptype == TT_PIT) { X u.utrap = 0; X pline("You float up, out of the pit!"); X } else { X pline("You float up, only your leg is still stuck."); X } X } else X if (Hallucination) X pline("Oh wow! You're floating in the air!"); X else X pline("You start to float in the air!"); X} X Xfloat_down(){ X register struct trap *trap; X X /* check for falling into pool - added by GAN 10/20/86 */ X if(IS_POOL(levl[u.ux][u.uy].typ) && !Levitation) X drown(); X X pline("You float gently to the ground."); X if(trap = t_at(u.ux,u.uy)) X switch(trap->ttyp) { X case PIERC: X break; X case TRAPDOOR: X if(!xdnstair || u.ustuck) break; X /* fall into next case */ X default: X dotrap(trap); X } X pickup(1); X} X X#include "mkroom.h" X Xvtele() { X register struct mkroom *croom; X X for(croom = &rooms[0]; croom->hx >= 0; croom++) X if(croom->rtype == VAULT) { X register x,y; X X x = rn2(2) ? croom->lx : croom->hx; X y = rn2(2) ? croom->ly : croom->hy; X if(teleok(x,y)) { X teleds(x,y); X return; X } X } X tele(); X} X X#ifdef BVH Xint has_amulet() { X register struct obj *otmp; X X for(otmp = invent; otmp; otmp = otmp->nobj) X if(otmp->olet == AMULET_SYM && otmp->spe >= 0) X return(1); X return(0); X} X#endif X Xtele() { X coord cc; X register int nux,nuy; X X#ifdef BVH X if(has_amulet() && rn2(3)) { X pline("You feel disoriented for a moment."); X return; X } X#endif X if(Teleport_control) { X#ifdef KAA X if (multi < 0 && (!nomovemsg || X !strncmp(nomovemsg,"You awake", 9) || X !strncmp(nomovemsg,"You regain con", 15) || X !strncmp(nomovemsg,"You are consci", 15))) X X pline("Being unconscious, you cannot control your teleport."); X else { X#endif X X pline("To what position do you want to be teleported?"); X getpos(&cc, 1, "the desired position"); /* 1: force valid */ X /* possible extensions: introduce a small error if X magic power is low; allow transfer to solid rock */ X if(teleok(cc.x, cc.y)){ X teleds(cc.x, cc.y); X return; X } X pline("Sorry ..."); X#ifdef KAA X } X#endif X } X do { X nux = rnd(COLNO-1); X nuy = rn2(ROWNO); X } while(!teleok(nux, nuy)); X teleds(nux, nuy); X} X Xteleds(nux, nuy) Xregister int nux,nuy; X{ X if(Punished) unplacebc(); X unsee(); X u.utrap = 0; X u.ustuck = 0; X u.ux = nux; X u.uy = nuy; X setsee(); X if(Punished) placebc(1); X if(u.uswallow){ X u.uswldtim = u.uswallow = 0; X docrt(); X } X nomul(0); X if(IS_POOL(levl[nux][nuy].typ) && !Levitation) X drown(); X (void) inshop(); X pickup(1); X read_engr_at(u.ux,u.uy); X} X Xteleok(x,y) register int x,y; { /* might throw him into a POOL X * removed by GAN 10/20/86 X */ X#ifdef STUPID X boolean tmp1, tmp2, tmp3; X tmp1 = isok(x,y) && !IS_ROCK(levl[x][y].typ) && !m_at(x,y); X tmp2 = !sobj_at(ENORMOUS_ROCK,x,y) && !t_at(x,y); X tmp3 = !(IS_POOL(levl[x][y].typ) && !Levitation); X return(tmp1 && tmp2 && tmp3); X#else X return( isok(x,y) && !IS_ROCK(levl[x][y].typ) && !m_at(x,y) && X !sobj_at(ENORMOUS_ROCK,x,y) && !t_at(x,y) && X !(IS_POOL(levl[x][y].typ) && !Levitation) X ); X#endif X /* Note: gold is permitted (because of vaults) */ X} X Xdotele() { X extern char pl_character[]; X X if((!index("LNt",u.usym)) && X#ifdef WIZARD X !wizard && X#endif X (!Teleportation || u.ulevel < 6 || X (pl_character[0] != 'W' && u.ulevel < 10))) { X pline("You are not able to teleport at will."); X return(0); X } X if(u.uhunger <= 100 || u.ustr < 6) { X pline("You miss the strength for a teleport spell."); X#ifdef WIZARD X if(!wizard) X#endif X return(1); X } X tele(); X morehungry(100); X return(1); X} X Xplacebc(attach) int attach; { X if(!uchain || !uball){ X impossible("Where are your chain and ball??"); X return; X } X uball->ox = uchain->ox = u.ux; X uball->oy = uchain->oy = u.uy; X if(attach){ X uchain->nobj = fobj; X fobj = uchain; X if(!carried(uball)){ X uball->nobj = fobj; X fobj = uball; X } X } X} X Xunplacebc(){ X if(!carried(uball)){ X freeobj(uball); X unpobj(uball); X } X freeobj(uchain); X unpobj(uchain); X} X Xlevel_tele() { Xregister int newlevel; X X#ifdef BVH X if(has_amulet() && rn2(5)) { X pline("You feel very disoriented for a moment."); X return; X } X#endif X if(Teleport_control) { X char buf[BUFSZ]; X X do { X pline("To what level do you want to teleport? [type a number] "); X getlin(buf); X } while(!digit(buf[0]) && (buf[0] != '-' || !digit(buf[1]))); X newlevel = atoi(buf); X } else { X#ifdef DGKMOD X newlevel = rn2(5) | !Fire_resistance ? rnd(dlevel + 3) : 30; X#else X newlevel = rnd(dlevel + 3); /* 5 - 24 */ X#endif X if(dlevel == newlevel) X if(!xdnstair) newlevel--; else newlevel++; X } X if(newlevel >= 30) { X if(newlevel > MAXLEVEL) newlevel = MAXLEVEL; X pline("You arrive at the center of the earth ..."); X pline("Unfortunately it is here that hell is located."); X#ifdef DGK X fflush(stdout); X#endif X if(Fire_resistance) { X pline("But the fire doesn't seem to harm you."); X } else { X pline("You burn to a crisp."); X pline("You die..."); X dlevel = maxdlevel = newlevel; X killer = "visit to hell"; X done("burned"); X } X } X if(newlevel < 0) { X if(newlevel <= -10) { X pline("You arrive in heaven."); X pline("\"You are here a bit early, but we'll let you in.\""); X killer = "visit to heaven"; X done("died"); X } else if (newlevel == -9) { X pline("You feel deliriously happy. "); X pline("(In fact, you're on Cloud 9!) "); X more(); X } else newlevel = 0; X pline("You are now high above the clouds ..."); X if(Levitation) { X pline("You float gently down to earth."); X done("escaped"); X } X pline("Unfortunately, you don't know how to fly."); X pline("You plummet a few thousand feet to your death."); X dlevel = 0; X killer = "long fall"; X done("died"); X } X X goto_level(newlevel, FALSE); /* calls done("escaped") if newlevel==0 */ X} X X#ifdef NEWTRAPS X Xdomagictrap() X{ X register int fate = rnd(20); X X /* What happened to the poor sucker? */ X X if (fate < 10) { X X /* Most of the time, it creates some monsters. */ X register int cnt = rnd(4); X X /* below checks for blindness added by GAN 10/30/86 */ X if (!Blind) { X pline("You are momentarily blinded by a flash of light!"); X Blinded += rn1(5,10); X seeoff(0); X } else X pline("You hear a deafening roar!"); X while(cnt--) X (void) makemon((struct permonst *) 0, u.ux, u.uy); X } X else X switch (fate) { X X case 10: X case 11: X /* sometimes nothing happens */ X break; X case 12: X /* a flash of fire */ X { X register int num; X X /* changed to be in conformance with X * SCR_FIRE by GAN 11/02/86 X */ X X pline("A tower of flame bursts from the floor!"); X if(Fire_resistance) X pline("You are uninjured."); X else { X num = rnd(6); X u.uhpmax -= num; X losehp(num,"a burst of flame"); X break; X } X } X X /* odd feelings */ X case 13: pline("A shiver runs up and down your spine!"); X break; X case 14: pline("You hear distant howling."); X break; X case 15: pline("You suddenly yearn for your distant homeland."); X break; X case 16: pline("Your pack shakes violently!"); X break; X X /* very occasionally something nice happens. */ X X case 19: X /* tame nearby monsters */ X { register int i,j; X register boolean confused = (Confusion != 0); X register int bd = confused ? 5 : 1; X register struct monst *mtmp; X X /* below pline added by GAN 10/30/86 */ X pline("You feel charismatic."); X for(i = -bd; i <= bd; i++) for(j = -bd; j <= bd; j++) X if(mtmp = m_at(u.ux+i, u.uy+j)) X (void) tamedog(mtmp, (struct obj *) 0); X break; X } X X case 20: X /* uncurse stuff */ X { register struct obj *obj; X register boolean confused = (Confusion != 0); X X /* below plines added by GAN 10/30/86 */ X if (confused) X if (Hallucination) X pline("You feel the power of the Force against you!"); X else X pline("You feel like you need some help."); X else X if (Hallucination) X pline("You feel in touch with the Universal Oneness."); X else X pline("You feel like someone is helping you."); X for(obj = invent; obj ; obj = obj->nobj) X if(obj->owornmask) X obj->cursed = confused; X if(Punished && !confused) { X Punished = 0; X freeobj(uchain); X unpobj(uchain); X free((char *) uchain); X uball->spe = 0; X uball->owornmask &= ~W_BALL; X uchain = uball = (struct obj *) 0; X } X break; X } X default: break; X } X} X#endif /* NEWTRAPS /**/ X Xdrown() X{ X pline("You fall into a pool!"); X pline("You can't swim!"); X if( X#ifdef WIZARD X wizard || X#endif X rn2(3) < u.uluck+2) { X /* most scrolls become unreadable */ X register struct obj *obj; X X for(obj = invent; obj; obj = obj->nobj) X if(obj->olet == SCROLL_SYM && rn2(12) > u.uluck) X obj->otyp = SCR_BLANK_PAPER; X /* we should perhaps merge these scrolls ? */ X X pline("You attempt a teleport spell."); /* utcsri!carroll */ X (void) dotele(); X if(!IS_POOL(levl[u.ux][u.uy].typ)) return; X } X pline("You drown."); X pline("You die..."); X killer = "pool of water"; X done("drowned"); X} END_OF_trap.c if test 21360 -ne `wc -c