ftp.nice.ch/pub/next/games/strategic/NetHack.s.tar.gz#/NetHackSource/src/trap.c

This is trap.c in view mode; [Download] [Up]

/*	SCCS Id: @(#)trap.c	3.0	89/11/20
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed.  See license for details. */

#include	"hack.h"
#include	"edog.h"

#ifdef OVLB

const char *traps[] = {
	"",
	" monster trap",
	" statue trap",
	" bear trap",
	"n arrow trap",
	" dart trap",
	" trapdoor",
	" teleportation trap",
	" pit",
	" sleeping gas trap"
	," magic trap"
	," squeaky board"
	," web"
	," spiked pit"
	," level teleporter"
#ifdef SPELLS
	,"n anti-magic field" 
#endif
	," rust trap"
#ifdef POLYSELF
	," polymorph trap"
#endif
	," land mine"
};

#endif /* OVLB */

void NDECL(domagictrap);
OSTATIC boolean FDECL(thitm, (int, struct monst *, struct obj *, int));

#ifdef OVLB

/* Generic rust-armor function.  Returns TRUE if a message was printed;
 * "print", if set, means to print a message (and thus to return TRUE) even
 * if the item could not be rusted; otherwise a message is printed and TRUE is
 * returned only for rustable items.
 */
boolean
rust_dmg(otmp, ostr, type, print)
register struct obj *otmp;
register const char *ostr;
int type;
boolean print;
{
	static const char *gook[] = { "slag", "rust", "rot", "corrosion" };
	static const char *action[] = { "smolder", "rust", "rot", "corrode" };
	static const char *msg[] =  { "burnt", "rusted", "rotten", "corroded" };
	boolean vulnerable = FALSE;
	boolean plural;

	if (!otmp) return(FALSE);
	switch(type) {
		case 0:
		case 2: vulnerable = is_flammable(otmp); break;
		case 1: vulnerable = is_rustprone(otmp); break;
		case 3: vulnerable = is_corrodeable(otmp); break;
	}

	if (!print && (!vulnerable || otmp->rustfree || otmp->spe < -2))
		return FALSE;

	plural = is_gloves(otmp) || is_boots(otmp);

	if (!vulnerable)
		Your("%s %s not affected!", ostr, plural ? "are" : "is");
	else if (otmp->spe >= -2) {
		if (otmp->rustfree)
			pline("The %s on your %s vanishes instantly!",
						gook[type], ostr);
		else if (otmp->blessed && !rnl(4))
			pline("Somehow, your %s %s not affected!", ostr,
					plural ? "are" : "is");
		else {
			Your("%s %s%s!", ostr, action[type],
				plural ? "" : "s");
			otmp->spe--;
			adj_abon(otmp, -1);
		}
	} else Your("%s %s%s quite %s.", ostr, Blind ? "feel" : "look",
					     plural ? "" : "s", msg[type]);
	return(TRUE);
}

struct trap *
maketrap(x,y,typ)
register int x, y, typ;
{
	register struct trap *ttmp;
	register struct permonst *ptr;

	if (ttmp = t_at(x,y)) {
		if (u.utrap &&
		  ((u.utraptype == TT_BEARTRAP && typ != BEAR_TRAP) ||
		  (u.utraptype == TT_WEB && typ != WEB) ||
		  (u.utraptype == TT_PIT && typ != PIT && typ != SPIKED_PIT)))
			u.utrap = 0;
		ttmp->ttyp = typ;
		return ttmp;
	}
	ttmp = newtrap();
	ttmp->ttyp = typ;
	ttmp->tx = x;
	ttmp->ty = y;
	switch(typ) {
	    case MONST_TRAP:	    /* create a monster in "hiding" */
	    {	int tryct = 0;
		if(rn2(5) && (ptr = mkclass(S_PIERCER)))
			ttmp->pm = monsndx(ptr);
		else do {
			ttmp->pm = rndmonnum();
		} while ((noattacks(&mons[ttmp->pm]) ||
			!mons[ttmp->pm].mmove) && ++tryct < 100);
		if (tryct == 100) {
			free((genericptr_t)ttmp);
			return(struct trap *)0;
		}
		break;
	    }
	    case STATUE_TRAP:	    /* create a "living" statue */
		ttmp->pm = rndmonnum();
		(void) mkcorpstat(STATUE, &mons[ttmp->pm], x, y);
		break;
	    default:
		ttmp->pm = -1;
		break;
	}
	ttmp->tseen = 0;
	ttmp->once = 0;
	ttmp->ntrap = ftrap;
	ftrap = ttmp;
	return(ttmp);
}

int
teleok(x, y)
register int x, y;
{				/* might throw him into a POOL
				 * removed by GAN 10/20/86
				 */
#ifdef STUPID
	boolean	tmp1, tmp2, tmp3;
#  ifdef POLYSELF
	tmp1 = isok(x,y) && (!IS_ROCK(levl[x][y].typ) ||
		passes_walls(uasmon)) && !MON_AT(x, y);
#  else
	tmp1 = isok(x,y) && !IS_ROCK(levl[x][y].typ) && !MON_AT(x, y);
#  endif
	tmp2 = !sobj_at(BOULDER,x,y) && !t_at(x,y);
	tmp3 = !(is_pool(x,y) &&
	       !(Levitation || Wwalking
#ifdef POLYSELF
		 || is_flyer(uasmon)
#endif
		)) && !closed_door(x,y);
	return(tmp1 && tmp2 && tmp3);
#else
	return( isok(x,y) &&
#  ifdef POLYSELF
		(!IS_ROCK(levl[x][y].typ) || passes_walls(uasmon)) &&
#  else
		!IS_ROCK(levl[x][y].typ) &&
#  endif
		!MON_AT(x, y) &&
		!sobj_at(BOULDER,x,y) && !t_at(x,y) &&
		!(is_pool(x,y) &&
		!(Levitation || Wwalking
#ifdef POLYSELF
		  || is_flyer(uasmon)
#endif
		  )) && !closed_door(x,y));
#endif
	/* Note: gold is permitted (because of vaults) */
}

static void
vtele() {
	register struct mkroom *croom;

	for(croom = &rooms[0]; croom->hx >= 0; croom++)
	    if(croom->rtype == VAULT) {
		register int x, y;

		x = rn2(2) ? croom->lx : croom->hx;
		y = rn2(2) ? croom->ly : croom->hy;
		if(teleok(x,y)) {
		    teleds(x,y);
		    return;
		}
	    }
	tele();
}

void
dotrap(trap)
register struct trap *trap;
{
	register int ttype = trap->ttyp;
	register struct monst *mtmp;
	register struct obj *otmp;

	nomul(0);
	if(trap->tseen && !Fumbling && !(ttype == PIT
	   || ttype == SPIKED_PIT
#ifdef SPELLS
	   || ttype == ANTI_MAGIC
#endif
		) && !rn2(5))
		You("escape a%s.", traps[ttype]);
	else {
	    trap->tseen = 1;
	    if(Invisible && ttype != MONST_TRAP)
		newsym(trap->tx,trap->ty);
	    switch(ttype) {
		case SLP_GAS_TRAP:
		    if(Sleep_resistance) {
			You("are enveloped in a cloud of gas!");
			break;
		    }
		    pline("A cloud of gas puts you to sleep!");
		    flags.soundok = 0;
		    nomul(-rnd(25));
		    afternmv = Hear_again;
		    break;
		case BEAR_TRAP:
		    if(Levitation
#ifdef POLYSELF
				|| is_flyer(uasmon)) {
			You("%s over a bear trap.",
			      Levitation ? "float" : "fly");
#else
				) {
			You("float over a bear trap.");
#endif
			break;
		    }
#ifdef POLYSELF
		    if(amorphous(uasmon)) {
			pline("A bear trap closes harmlessly through you.");
			break;
		    }
#endif
		    u.utrap = 4 + rn2(4);
		    u.utraptype = TT_BEARTRAP;
		    pline("A bear trap closes on your %s!",
			body_part(FOOT));
#ifdef POLYSELF
		    if(u.umonnum == PM_OWLBEAR || u.umonnum == PM_BUGBEAR)
			You("howl in anger!");
#endif
		    break;
		case STATUE_TRAP:
		    deltrap(trap);
		    for(otmp=level.objects[u.ux][u.uy];
						otmp; otmp = otmp->nexthere)
			if(otmp->otyp == STATUE && otmp->corpsenm == trap->pm)
			    if(mtmp=makemon(&mons[trap->pm],u.ux,u.uy)) {
				pline("The statue comes to life!");
				delobj(otmp);
				break;
			    }
		    break;
		case MONST_TRAP:
		    if(mtmp=makemon(&mons[trap->pm],u.ux,u.uy)) {
		      switch(mtmp->data->mlet) {
			case S_PIERCER:
			    pline("%s suddenly drops from the ceiling!",
				  Xmonnam(mtmp));
			    if(uarmh)
				pline("Its blow glances off your helmet.");
			    else
				(void) thitu(3,d(4,6),(struct obj *)0,
					"falling piercer");
			    break;
			default:	/* monster surprises you. */
			    pline("%s attacks you by surprise!",
				  Xmonnam(mtmp));
			    break;
		      }
		    }
		    deltrap(trap);
		    break;
		case ARROW_TRAP:
		    pline("An arrow shoots out at you!");
		    if(!thitu(8,rnd(6),(struct obj *)0,"arrow")){
			(void) mksobj_at(ARROW, u.ux, u.uy);
			fobj->quan = 1;
			fobj->owt = weight(fobj);
		    }
		    break;
		case TRAPDOOR:
		    if(is_maze_lev
#ifdef STRONGHOLD
			 && (dlevel > stronghold_level)
#endif
		      ) {
	pline("A trap door in the ceiling opens and a rock falls on your %s!",
				body_part(HEAD));
			if(uarmh)
			    pline("Fortunately, you are wearing a helmet!");
			losehp(uarmh ? 2 : d(2,10),"falling rock", KILLED_BY_AN);
			(void) mksobj_at(ROCK, u.ux, u.uy);
			fobj->quan = 1;
			fobj->owt = weight(fobj);
			stackobj(fobj);
			if(Invisible
#ifdef POLYSELF
				|| u.uundetected
#endif
						) newsym(u.ux, u.uy);
		    } else {
			register int newlevel = dlevel + 1;
			while(!rn2(4) && newlevel < 29) newlevel++;
			pline("A trap door opens up under you!");
			if(Levitation || u.ustuck || dlevel == MAXLEVEL
#ifdef POLYSELF
				|| is_flyer(uasmon) || u.umonnum == PM_WUMPUS
#endif
#ifdef ENDGAME
				|| dlevel == ENDLEVEL
#endif
							) {
			    You("don't fall in.");
			    break;
			}
#ifdef WALKIES
			if(!next_to_u())
			    You("are jerked back by your pet!");
			else {
#endif
			    if(in_shop(u.ux, u.uy)) shopdig(1);
			    unsee();
			    (void) fflush(stdout);
			    goto_level(newlevel, FALSE, TRUE);
#ifdef WALKIES
			}
#endif
		    }
		    break;
		case DART_TRAP:
		    pline("A little dart shoots out at you!");
		    if(thitu(7,rnd(3),(struct obj *)0,"little dart")) {
			if(!rn2(6)) poisoned("dart",A_CON,"poison dart",10);
		    } else {
			(void) mksobj_at(DART, u.ux, u.uy);
			fobj->quan = 1;
			if(!rn2(6)) fobj->opoisoned = 1;
			fobj->owt = weight(fobj);
		    }
		    break;
		case TELEP_TRAP:
		    if(trap->once) {
#ifdef ENDGAME
			if(dlevel == ENDLEVEL) {
			    You("feel a wrenching sensation.");
			    break;
			}
#endif
			if(Antimagic) {
			    shieldeff(u.ux, u.uy);
			    You("feel a wrenching sensation.");
			} else {
			    deltrap(trap);
			    newsym(u.ux, u.uy);
			    vtele();
			}
		    } else {
#ifdef ENDGAME
			if(dlevel == ENDLEVEL) {
			    You("feel a wrenching sensation.");
			    break;
			}
#endif
			if(Antimagic) {
			    shieldeff(u.ux, u.uy);
			    You("feel a wrenching sensation.");
			} else {
			    newsym(u.ux, u.uy);
			    tele();
			}
		    }
		    break;
		case RUST_TRAP:
#ifdef POLYSELF
# ifdef GOLEMS
		    if (u.umonnum == PM_IRON_GOLEM) {
			pline("A gush of water hits you!");
			You("are covered with rust!");
			rehumanize();
			break;
		    } else
# endif /* GOLEMS */
		    if (u.umonnum == PM_GREMLIN && rn2(3)) {
			pline("A gush of water hits you!");
			if(mtmp = cloneu()) {
			    mtmp->mhpmax = (u.mhmax /= 2);
			    You("multiply.");
			}
			break;
		    }
#endif
		/* Unlike monsters, traps cannot aim their rust attacks at
		 * you, so instead of looping through and taking either the
		 * first rustable one or the body, we take whatever we get,
		 * even if it is not rustable.
		 */
		    switch (rn2(5)) {
			case 0:
			    pline("A gush of water hits you on the %s!",
					body_part(HEAD));
			    (void) rust_dmg(uarmh, "helmet", 1, TRUE);
			    break;
			case 1:
			    pline("A gush of water hits your left %s!",
					body_part(ARM));
			    if (rust_dmg(uarms, "shield", 1, TRUE)) break;
			    if (uwep && bimanual(uwep))
				goto two_hand;
			    /* Two goto statements in a row--aaarrrgggh! */
glovecheck:		    (void) rust_dmg(uarmg, "gauntlets", 1, TRUE);
			    /* Not "metal gauntlets" since it gets called
			     * even if it's leather for the message
			     */
			    break;
			case 2:
			    pline("A gush of water hits your right %s!",
					body_part(ARM));
two_hand:		    corrode_weapon();
			    goto glovecheck;
			default:
			    pline("A gush of water hits you!");
			    if (uarmc) (void) rust_dmg(uarmc, "cloak", 1, TRUE);
			    else if (uarm)
				(void) rust_dmg(uarm, "armor", 1, TRUE);
#ifdef SHIRT
			    else if (uarmu)
				(void) rust_dmg(uarmu, "shirt", 1, TRUE);
#endif
		    }
		    break;
		case PIT:
		    if (Levitation
#ifdef POLYSELF
			|| is_flyer(uasmon) || u.umonnum == PM_WUMPUS
#endif
			) {
			pline("A pit opens up under you!");
			You("don't fall in!");
			break;
		    }
		    You("fall into a pit!");
#ifdef POLYSELF
		    if (!passes_walls(uasmon))
#endif
			u.utrap = rn1(6,2);
		    u.utraptype = TT_PIT;
		    losehp(rnd(6),"fell into a pit", NO_KILLER_PREFIX);
		    selftouch("Falling, you");
		    break;
		case SPIKED_PIT:
		    if (Levitation
#ifdef POLYSELF
			|| is_flyer(uasmon) || u.umonnum == PM_WUMPUS
#endif
			) {
			pline("A pit full of spikes opens up under you!");
			You("don't fall in!");
			break;
		    }
		    You("fall into a pit!");
		    You("land on a set of sharp iron spikes!");
#ifdef POLYSELF
		    if (!passes_walls(uasmon))
#endif
			u.utrap = rn1(6,2);
		    u.utraptype = TT_PIT;
		    losehp(rnd(10),"fell into a pit of iron spikes",
			NO_KILLER_PREFIX);
		    if(!rn2(6)) poisoned("spikes",A_STR,"fall onto poison spikes",8);
		    selftouch("Falling, you");
		    break;
		case LEVEL_TELEP:

		    {	int oldl = dlevel;

		    You("%s onto a level teleport trap!",
			  Levitation ? "float" :
#ifdef POLYSELF
			  locomotion(uasmon, "step"));
#else
			  "step");
#endif
		    if(Antimagic) {
			pru();
			shieldeff(u.ux, u.uy);
		    }
		    if(Antimagic
#ifdef ENDGAME
				|| dlevel == ENDLEVEL
#endif
							) {
			You("feel a wrenching sensation.");
			break;
		    }
		    if(!Blind)
		      You("are momentarily blinded by a flash of light.");
		    else
			You("are momentarily disoriented.");
		    deltrap(trap);
		    newsym(u.ux,u.uy);
		    level_tele();
		    if(oldl == dlevel && !Invisible
#ifdef POLYSELF
						&& !u.uundetected
#endif
								) {
			levl[u.ux][u.uy].seen = 0; /* force atl */
			atl(u.ux,u.uy,(char)u.usym);
		    }
		}
		    break;
#ifdef SPELLS
		case ANTI_MAGIC:
		    if(Antimagic) {
			shieldeff(u.ux, u.uy);
			You("feel momentarily lethargic.");
		    } else drain_en(rnd((int)u.ulevel) + 1);
		    break;
#endif
#ifdef POLYSELF
		case POLY_TRAP:
		    if(Antimagic) {
			shieldeff(u.ux, u.uy);
			You("feel momentarily different.");
			/* Trap did nothing; don't remove it --KAA */
		    } else {
			You("feel a change coming over you.");
			polyself();
			deltrap(trap);
		    }
		    break;
#endif
		case MGTRP:	    /* A magic trap. */
		    if (!rn2(30)) {
			You("are caught in a magical explosion!");
			losehp(rnd(10), "magical explosion", KILLED_BY_AN);
#ifdef SPELLS
			Your("body absorbs some of the magical energy!");
			u.uen = (u.uenmax += 2);
#endif
			deltrap(trap);
			if(Invisible
#ifdef POLYSELF
				&& !u.uundetected
#endif
						) newsym(u.ux,u.uy);
		    } else domagictrap();
		    break;
		case SQBRD:	    /* stepped on a squeaky board */
		    if (Levitation
#ifdef POLYSELF
			|| is_flyer(uasmon)
#endif
			) {
			if (Hallucination) You("notice a crease in the linoleum.");
			else You("notice a loose board below you.");
		    } else {
			pline("A board beneath you squeaks loudly.");
			wake_nearby();
		    }
		    break;
		case WEB: /* Our luckless player has stumbled into a web. */

		    You("%s into a spider web!",
			  Levitation ? "float" :
#ifdef POLYSELF
			  locomotion(uasmon, "stumble"));
#else
			  "stumble");
#endif
		    u.utraptype = TT_WEB;

		    /* Time stuck in the web depends on your strength. */

		    if (ACURR(A_STR) == 3) u.utrap = rn1(6,6);
		    else if (ACURR(A_STR) < 6) u.utrap = rn1(6,4);
		    else if (ACURR(A_STR) < 9) u.utrap = rn1(4,4);
		    else if (ACURR(A_STR) < 12) u.utrap = rn1(4,2);
		    else if (ACURR(A_STR) < 15) u.utrap = rn1(2,2);
		    else if (ACURR(A_STR) < 18) u.utrap = rnd(2);
		    else if (ACURR(A_STR) < 69) u.utrap = 1;
		    else {
			u.utrap = 0;
			You("tear through the web!");
			deltrap(trap);
	   		if(Invisible) newsym(u.ux,u.uy);
		    }
		    break;

		case LANDMINE: {
#ifndef LINT
		    register struct monst *mtmp = fmon;
#endif

		    if (Levitation
#ifdef POLYSELF
					|| is_flyer(uasmon)
#endif
								) {
			You("see a trigger in a pile of soil below you.");
			if (rn2(3)) break;
			pline("KAABLAMM!!!  The air currents set it off!");
		    } else {
			pline("KAABLAMM!!!  You triggered a land mine!");
			set_wounded_legs(LEFT_SIDE, 40 + rnd(35));
			set_wounded_legs(RIGHT_SIDE, 40 + rnd(35));
		    }
		    losehp(rnd(16), "land mine", KILLED_BY_AN);
		    /* wake everything on the level */
		    while(mtmp) {
			if(mtmp->msleep) mtmp->msleep = 0;
			mtmp = mtmp->nmon;
		    }
		    deltrap(t_at(u.ux, u.uy)); /* mines only explode once */
		    if(Invisible) newsym(u.ux,u.uy);
		    }
		    break;
		default:
		    impossible("You hit a trap of type %u", trap->ttyp);
	    }
	}
}

#endif /* OVLB */

#ifdef WALKIES

OSTATIC boolean FDECL(teleport_pet, (struct monst *));

#ifdef OVLB

XSTATIC boolean
teleport_pet(mtmp)
register struct monst *mtmp;
{
	register struct obj *otmp;

	if(mtmp->mleashed) {
	    otmp = get_mleash(mtmp);
	    if(!otmp)
		impossible("%s is leashed, without a leash.", Monnam(mtmp));
	    if(otmp->cursed) {
# ifdef SOUNDS
		yelp(mtmp);
# endif
		return FALSE;
	    } else {
		Your("leash goes slack.");
		m_unleash(mtmp);
		return TRUE;
	    }
	}
	return TRUE;
}

#endif /* OVLB */

#endif

#ifdef OVLB

XSTATIC void
seetrap(trap)

	register struct trap *trap;
{
	if(!trap->tseen) {

	    trap->tseen = 1;
	    newsym(trap->tx, trap->ty);
	}
}

#endif /* OVLB */
#ifdef OVL1

int
mintrap(mtmp)
register struct monst *mtmp;
{
	register struct trap *trap = t_at(mtmp->mx, mtmp->my);
	register int newlev, wasintrap = mtmp->mtrapped;
	register boolean trapkilled = FALSE, tdoor = FALSE;
	struct obj *otmp;

	if(!trap) {
		mtmp->mtrapped = 0;	/* perhaps teleported? */
	} else if(wasintrap) {
		if(!rn2(40)) mtmp->mtrapped = 0;
	} else {
	    register int tt = trap->ttyp;

	/* A bug fix for dumb messages by ab@unido.
	 */
	    int in_sight = cansee(mtmp->mx,mtmp->my)
			   && (!mtmp->minvis || See_invisible);

	    if(mtmp->mtrapseen & (1 << tt)) {
		/* he has been in such a trap - perhaps he escapes */
		if(rn2(4)) return(0);
	    }
	    mtmp->mtrapseen |= (1 << tt);
	    switch (tt) {
		case BEAR_TRAP:
			if(mtmp->data->msize > MZ_SMALL &&
			   !amorphous(mtmp->data)) {
				mtmp->mtrapped = 1;
				if(in_sight) {
				  pline("%s is caught in a bear trap!",
					Monnam(mtmp));
				  seetrap(trap);
				} else
				    if((mtmp->data == &mons[PM_OWLBEAR]
					|| mtmp->data == &mons[PM_BUGBEAR])
					&& flags.soundok)
			    You("hear the roaring of an angry bear!");
			}
			break;
#ifdef POLYSELF
		case POLY_TRAP:
		    if(!resist(mtmp, WAND_SYM, 0, NOTELL)) {
			(void) newcham(mtmp, (struct permonst *)0);
			seetrap(trap);
		    }
		    break;
#endif
		case RUST_TRAP:
			if(in_sight)
			    pline("A gush of water hits %s!", mon_nam(mtmp));
			if(cansee(mtmp->mx,mtmp->my))
			    seetrap(trap);
#ifdef GOLEMS
			if (mtmp->data == &mons[PM_IRON_GOLEM]) {
				if (in_sight)
				    pline("%s falls to pieces!", Monnam(mtmp));
				else if(mtmp->mtame)
				    pline("May %s rust in peace.",
								mon_nam(mtmp));
				mondied(mtmp);
				trapkilled = TRUE;
			} else
#endif /* GOLEMS */
			if (mtmp->data == &mons[PM_GREMLIN] && rn2(3)) {
				struct monst *mtmp2 = clone_mon(mtmp);

				if (mtmp2) {
				    mtmp2->mhpmax = (mtmp->mhpmax /= 2);
				    if(in_sight)
					pline("%s multiplies.", Monnam(mtmp));
				}
			}
			break;
		case PIT:
		case SPIKED_PIT:
			/* TO DO: there should be a mtmp/data -> floating */
			if(!is_flyer(mtmp->data) &&
			   mtmp->data != &mons[PM_WUMPUS]) {
				if (!passes_walls(mtmp->data))
				    mtmp->mtrapped = 1;
				if(in_sight) {
				    pline("%s falls into a pit!", Monnam(mtmp));
				    seetrap(trap);
				}
				if(thitm(0, mtmp, (struct obj *)0,
					 rnd((tt==PIT) ? 6 : 10)))
				    trapkilled = TRUE;
			}
			break;
		case SLP_GAS_TRAP:
			if(!resists_sleep(mtmp->data) &&
			   !mtmp->msleep && mtmp->mcanmove) {
				mtmp->mcanmove = 0;
				mtmp->mfrozen = rnd(25);
				if(in_sight)
				  pline("%s suddenly falls asleep!",
					Monnam(mtmp));
				if(cansee(mtmp->mx,mtmp->my))
				    seetrap(trap);
			}
			break;
		case TELEP_TRAP:
#ifdef WALKIES
			if(teleport_pet(mtmp)) {
#endif
			    /* Note: don't remove the trap if a vault.  Other-
			     * the monster will be stuck there, since the guard
			     * isn't going to come for it...
			     */
			    if (trap->once) vloc(mtmp);
			    else rloc(mtmp);
			    if(in_sight && !cansee(mtmp->mx,mtmp->my)) {
				pline("%s suddenly disappears!",
					Monnam(mtmp));
				seetrap(trap);
			    }
#ifdef WALKIES
			}
#endif
			break;
		case ARROW_TRAP:
			otmp = mksobj(ARROW, FALSE);
			otmp->quan = 1;
			otmp->owt = weight(otmp);
			if(in_sight) seetrap(trap);
			if(thitm(8, mtmp, otmp, 0)) trapkilled = TRUE;
			break;
		case DART_TRAP:
			otmp = mksobj(DART, FALSE);
			otmp->quan = 1;
			if (!rn2(6)) otmp->opoisoned = 1;
			otmp->owt = weight(otmp);
			if(in_sight) seetrap(trap);
			if(thitm(7, mtmp, otmp, 0)) trapkilled = TRUE;
			break;
		case TRAPDOOR:
			if(is_maze_lev
#ifdef STRONGHOLD
			   && (dlevel > stronghold_level && dlevel < MAXLEVEL)
#endif
			  ) {
				otmp = mksobj(ROCK, FALSE);
				otmp->quan = 1;
				otmp->owt = weight(otmp);
				if(in_sight) seetrap(trap);
				if(thitm(0, mtmp, otmp, d(2, 10)))
					trapkilled = TRUE;
				break;
			}
			if (mtmp->data == &mons[PM_WUMPUS]) break;
			tdoor = TRUE;
			/* Fall through */
		case LEVEL_TELEP:
			if(!is_flyer(mtmp->data)
#ifdef WORM
				&& !mtmp->wormno
			    /* long worms with tails mustn't change levels */
#endif
			    ) {
#ifdef WALKIES
			    if(teleport_pet(mtmp)) {
#endif
				if(tdoor)
				    fall_down(mtmp, dlevel+1);
				else {
				    newlev = rnd(3);
				    if(!rn2(2)) newlev = -(newlev);
				    newlev = dlevel + newlev;
				    if(newlev > MAXLEVEL) {
					if(dlevel != MAXLEVEL)
					    newlev = MAXLEVEL;
					else newlev = MAXLEVEL - rnd(3);
				    }
				    if(newlev < 1) {
					if(dlevel != 1) newlev = 1;
					else newlev = 1 + rnd(3);
				    }
				    fall_down(mtmp, newlev);
				}
				if(in_sight) {
		pline("Suddenly, %s disappears out of sight.", mon_nam(mtmp));
				    seetrap(trap);
				}
				return(2);	/* no longer on this level */
#ifdef WALKIES
			    }
#endif
			}
			break;
		case MONST_TRAP:
		case STATUE_TRAP:
			break;
		case MGTRP:
			/* A magic trap.  Monsters immune. */
			break;
		case SQBRD: {
			register struct monst *ztmp = fmon;

			if(is_flyer(mtmp->data)) break;
			/* stepped on a squeaky board */
			if (in_sight) {
			    pline("A board beneath %s squeaks loudly.", mon_nam(mtmp));
			    seetrap(trap);
			} else
			   You("hear a distant squeak.");
			/* wake up nearby monsters */
			while(ztmp) {
			    if(dist2(mtmp->mx,mtmp->my,ztmp->mx,ztmp->my) < 40)
				if(ztmp->msleep) ztmp->msleep = 0;
			    ztmp = ztmp->nmon;
			}
			break;
		}
	       case WEB:
			/* Monster in a web. */
			if(mtmp->data->mlet != S_SPIDER) {
			    if(in_sight)
				pline("%s is caught in a web.", Monnam(mtmp));
			    else /* Eric Backus */
				if(mtmp->data == &mons[PM_OWLBEAR] ||
					mtmp->data == &mons[PM_BUGBEAR])
				    You("hear the roaring of a confused bear!");
			    mtmp->mtrapped = 1;
			}
			break;
#ifdef SPELLS
		case ANTI_MAGIC:	break;
#endif
		case LANDMINE: {
			register struct monst *mntmp = fmon;

			if(rn2(3))
				break; /* monsters usually don't set it off */
			if(in_sight)
			    pline("KAABLAMM!!!  %s triggers a land mine!",
				  Monnam(mtmp));
			else if (flags.soundok)
				pline("Kaablamm!  You hear an explosion in the distance!");
			deltrap(t_at(mtmp->mx, mtmp->my));
			if(thitm(0, mtmp, (struct obj *)0, rnd(16)))
				trapkilled = TRUE;
			/* wake everything on the level */
			while(mntmp) {
				if(mntmp->msleep)
					mntmp->msleep = 0;
				mntmp = mntmp->nmon;
			}
			break;
		}
		default:
			impossible("Some monster encountered a strange trap of type %d.", tt);
	    }
	}
	if(trapkilled) return 2;
	else return mtmp->mtrapped;
}

#endif /* OVL1 */
#ifdef OVLB

void
selftouch(arg)
const char *arg;
{
	if(uwep && (uwep->otyp == CORPSE && uwep->corpsenm == PM_COCKATRICE)
#ifdef POLYSELF
			&& !resists_ston(uasmon)
#endif
	){
		pline("%s touch the cockatrice corpse.", arg);
		You("turn to stone...");
		killer_format = KILLED_BY;
		killer = "touching a cockatrice corpse";
		done(STONING);
	}
}

void
float_up() {
	if(u.utrap) {
		if(u.utraptype == TT_PIT) {
			u.utrap = 0;
			You("float up, out of the pit!");
		} else {
			You("float up, only your %s is still stuck.",
				body_part(LEG));
		}
	} else
		if (Hallucination)
			pline("Up, up, and awaaaay!  You're walking on air!");
		else
			You("start to float in the air!");
}

int
float_down() {
	register struct trap *trap;

	if(Levitation) return(0); /* maybe another ring/potion/boots */

	/* check for falling into pool - added by GAN 10/20/86 */
	if(is_pool(u.ux,u.uy) && !(Wwalking
#ifdef POLYSELF
				    || is_flyer(uasmon)
#endif
				    ))
		drown();

	You("float gently to the ground.");
	if(trap = t_at(u.ux,u.uy))
		switch(trap->ttyp) {
		case MONST_TRAP:
		case STATUE_TRAP:
			break;
		case TRAPDOOR:
			if(is_maze_lev
#ifdef STRONGHOLD
			   && (dlevel >= stronghold_level || dlevel < MAXLEVEL)
#endif
			   || u.ustuck) break;
			/* fall into next case */
		default:
			dotrap(trap);
	}
	if(!flags.nopick && (OBJ_AT(u.ux, u.uy) || levl[u.ux][u.uy].gmask))
	    pickup(1);
	return 0;
}


void
tele() {
	coord cc;
	register int nux,nuy;

#ifdef STRONGHOLD
	/* Disable teleportation in stronghold && Vlad's Tower */
	if(dlevel == stronghold_level ||
# ifdef ENDGAME
	   dlevel == ENDLEVEL ||
# endif
	   (dlevel >= tower_level && dlevel <= tower_level + 2)) {
# ifdef WIZARD
		if (!wizard) {
# endif
		    pline("A mysterious force prevents you from teleporting!");
		    return;
# ifdef WIZARD
		}
# endif
	}
#endif /* STRONGHOLD /**/
	if((u.uhave_amulet || dlevel == wiz_level) && !rn2(3)) {
	    You("feel disoriented for a moment.");
	    return;
	}
	if(Teleport_control) {
	    if (unconscious())
		pline("Being unconscious, you cannot control your teleport.");
	    else {
		    pline("To what position do you want to be teleported?");
		    cc.x = u.ux;
		    cc.y = u.uy;
		    getpos(&cc, 1, "the desired position"); /* 1: force valid */
		    /* possible extensions: introduce a small error if
		       magic power is low; allow transfer to solid rock */
		    if(teleok(cc.x, cc.y)){
			teleds(cc.x, cc.y);
			return;
		    }
		    pline("Sorry...");
		}
	}
	do {
		nux = rnd(COLNO-1);
		nuy = rn2(ROWNO);
	} while(!teleok(nux, nuy));
	teleds(nux, nuy);
}

void
teleds(nux, nuy)
register int nux,nuy;
{
	if(Punished) unplacebc();
	unsee();
	u.utrap = 0;
	u.ustuck = 0;
	u.ux0 = u.ux;
	u.uy0 = u.uy;
	u.ux = nux;
	u.uy = nuy;
#ifdef POLYSELF
	if (hides_under(uasmon))
		u.uundetected = (OBJ_AT(nux, nuy) || levl[nux][nuy].gmask);
	else 
		u.uundetected = 0;
	if (u.usym == S_MIMIC_DEF) u.usym = S_MIMIC;
#endif
	if(Punished) placebc(1);
	if(u.uswallow){
		u.uswldtim = u.uswallow = 0;
		docrt();
	}
	setsee();
	nomul(0);
	spoteffects();
}

int
dotele()
{
	struct trap *trap;
#ifdef SPELLS
	boolean castit = FALSE;
# ifdef __GNULINT__
	register int sp_no = 0;
# else
	register int sp_no;
# endif
#endif

	trap = t_at(u.ux, u.uy);
	if (trap && (!trap->tseen || trap->ttyp != TELEP_TRAP))
		trap = 0;

	if (trap) {
		if (trap->once) {
			pline("This is a vault teleport, usable once only.");
			pline("Jump in? ");
			if (yn() == 'n')
				trap = 0;
			else {
				deltrap(trap);
				newsym(u.ux, u.uy);
			}
		}
		if (trap)
#ifdef POLYSELF
			You("%s onto the teleportation trap.",
			    locomotion(uasmon, "jump"));
#else
			You("jump onto the teleportation trap.");
#endif
	}
	if(!trap && (!Teleportation ||
	   (u.ulevel < (pl_character[0] == 'W' ? 8 : 12)
#ifdef POLYSELF
	    && !can_teleport(uasmon)
#endif
	   )
	  )) {
#ifdef SPELLS
		/* Try to use teleport away spell. */
		castit = objects[SPE_TELEPORT_AWAY].oc_name_known;
		if (castit) {
		    for (sp_no = 0; sp_no < MAXSPELL &&
				spl_book[sp_no].sp_id != NO_SPELL &&
				spl_book[sp_no].sp_id != SPE_TELEPORT_AWAY; sp_no++);

		    if (sp_no == MAXSPELL ||
			spl_book[sp_no].sp_id != SPE_TELEPORT_AWAY)
			    castit = FALSE;
		}
#endif
#ifdef WIZARD
		if (!wizard) {
#endif
#ifdef SPELLS
		    if (!castit) {
			if (!Teleportation)
			    You("don't know that spell.");
			else
#endif
			    You("are not able to teleport at will.");
			return(0);
#ifdef SPELLS
		    }
#endif
#ifdef WIZARD
		}
#endif
	}

	if(!trap && (u.uhunger <= 100 || ACURR(A_STR) < 6)) {
		You("lack the strength for a teleport spell.");
#ifdef WIZARD
		if(!wizard)
#endif
		return(1);
	}

#ifdef SPELLS
	if (castit)
# ifdef WIZARD
		if (!spelleffects(++sp_no, TRUE) && !wizard) return(0);
# else
		return spelleffects(++sp_no, TRUE);
# endif
#endif

#ifdef WALKIES
	if(next_to_u()) {
#endif
		if (trap && trap->once) vtele();
		else tele();
#ifdef WALKIES
		(void) next_to_u();
	} else {
		You("shudder for a moment.");
		return(0);
	}
#endif
	if (!trap) morehungry(100);
	return(1);
}

void
placebc(attach)
int attach;
{
	if(!uchain || !uball){
		impossible("Where are your ball and chain?");
		return;
	}
	if(!carried(uball))
		place_object(uball, u.ux, u.uy);
	place_object(uchain, u.ux, u.uy);
	if(attach){
		uchain->nobj = fobj;
		fobj = uchain;
		if(!carried(uball)){
			uball->nobj = fobj;
			fobj = uball;
		}
	}
}

void
unplacebc(){
	if(!carried(uball)){
		freeobj(uball);
		unpobj(uball);
	}
	freeobj(uchain);
	unpobj(uchain);
}

void
level_tele() {
register int newlevel;
#ifdef WALKIES
register boolean pet_by_u = next_to_u();
#endif

	if(u.uhave_amulet
#ifdef ENDGAME
		|| dlevel == ENDLEVEL
#endif
	) {
	    You("feel very disoriented for a moment.");
	    return;
	}
	if(Teleport_control
#ifdef WIZARD
	   || wizard
#endif
		) {
	    char buf[BUFSZ];

	    do {
	      pline("To what level do you want to teleport? [type a number] ");
	      getlin(buf);
	    } while(!digit(buf[0]) && (buf[0] != '-' || !digit(buf[1])));
	    newlevel = atoi(buf);
	} else {
#ifdef STRONGHOLD
	    /* We cannot send them to Hell if STRONGHOLD is defined, since
	     * they may find themselves trapped on the other side of the
	     * stronghold...
	     */
	    newlevel = rn2(5) ? rnd(dlevel + 3) : rnd(stronghold_level);
#else
	    newlevel = rn2(5) || !Fire_resistance ? rnd(dlevel + 3) : HELLLEVEL;
#endif
	    if(dlevel == newlevel)
		if(is_maze_lev) newlevel--; else newlevel++;
	}
	if(newlevel < 0) {
#ifdef WALKIES
	    if(pet_by_u) {
#endif
		if(newlevel <= -10) {
			You("arrive in heaven.");
			verbalize("Thou art early, but we'll admit thee.");
			killer_format = NO_KILLER_PREFIX;
			killer = "went to heaven prematurely";
			done(DIED);
		} else	if (newlevel == -9) {
			You("feel deliriously happy. ");
			pline("(In fact, you're on Cloud 9!) ");
			more();
		} else
#ifndef STRONGHOLD
			newlevel = 0;
#else
			newlevel = 1;
#endif
		You("are now high above the clouds...");
		if(Levitation) {
		    You("float gently down to earth.");
#ifndef STRONGHOLD
		    done(ESCAPED);
#endif
		}
#ifdef POLYSELF
		if(is_flyer(uasmon)) {
		    You("fly down to earth.");
# ifndef STRONGHOLD
		    done(ESCAPED);
# endif
		}
#endif
		pline("Unfortunately, you don't know how to fly.");
		You("plummet a few thousand feet to your death.");
		dlevel = 0;
		killer_format = NO_KILLER_PREFIX;
		killer =
    self_pronoun("teleported out of the dungeon and fell to %s death","his");
		done(DIED);
#ifdef WIZARD
		return;  
#endif
#ifdef WALKIES
	    } else {
		You("shudder for a moment...");
		return;
	    }
#endif
	}
	/* calls done(ESCAPED) if newlevel==0 */
#ifdef WALKIES
	if(!pet_by_u)
	    You("shudder for a moment...");
	else
#endif
	    goto_level(newlevel, FALSE, FALSE);
}

void
domagictrap() {
	register int fate = rnd(20);

	/* What happened to the poor sucker? */

	if (fate < 10) {

	  /* Most of the time, it creates some monsters. */
	  register int cnt = rnd(4);

	  /* below checks for blindness added by GAN 10/30/86 */
	  if (!Blind)  {
		You("are momentarily blinded by a flash of light!");
		make_blinded((long)rn1(5,10),FALSE);
	  }  else
		You("hear a deafening roar!");
	  while(cnt--)
		(void) makemon((struct permonst *) 0, u.ux, u.uy);
	}
	else
	  switch (fate) {

	     case 10:
	     case 11:
		      /* sometimes nothing happens */
			break;
	     case 12:
		      /* a flash of fire */
		      {
			register int num;

			/* changed to be in conformance with
			 * SCR_FIRE by GAN 11/02/86
			 */

			pline("A tower of flame bursts from the floor!");
			if(Fire_resistance) {
				shieldeff(u.ux, u.uy);
				You("are uninjured.");
				break;
			} else {
				num = rnd(6);
				u.uhpmax -= num;
				losehp(num,"burst of flame", KILLED_BY_AN);
				break;
			}
		      }

	     /* odd feelings */
	     case 13:	pline("A shiver runs up and down your %s!",
			      body_part(SPINE));
			break;
	     case 14:	You(Hallucination ?
				"hear the moon howling at you." :
				"hear distant howling.");
			break;
	     case 15:	You("suddenly yearn for %s.",
				Hallucination ? "Cleveland" :
						"your distant homeland");
			break;
	     case 16:   Your("pack shakes violently!");
			break;
	     case 17:	You(Hallucination ?
				"smell hamburgers." :
				"smell charred flesh.");
			break;

	     /* very occasionally something nice happens. */

	     case 19:
		    /* tame nearby monsters */
		   {   register int i,j;

		       /* below pline added by GAN 10/30/86 */
		       adjattrib(A_CHA,1,FALSE);
		       for(i = -1; i <= 1; i++) for(j = -1; j <= 1; j++)
		       if(MON_AT(u.ux+i, u.uy+j))
			   (void) tamedog(m_at(u.ux+i, u.uy+j), (struct obj *)0);
		       break;
		   }

	     case 20:
		    /* uncurse stuff */
		   {  register struct obj *obj;

			/* below plines added by GAN 10/30/86 */
			You(Hallucination ?
				"feel in touch with the Universal Oneness." :
				"feel like someone is helping you.");
			for(obj = invent; obj ; obj = obj->nobj)
			       if(obj->owornmask || obj->otyp == LOADSTONE)
					obj->cursed = 0;
		       if(Punished) unpunish();
		       break;
		   }
	     default: break;
	  }
}

void
drown() {
	register struct obj *obj;

	/* Scrolls and potions get affected by the water */
	for(obj = invent; obj; obj = obj->nobj) {
		if(obj->olet == SCROLL_SYM && rn2(12) > Luck
#ifdef MAIL
			&& obj->otyp != SCR_MAIL
#endif
								)
			obj->otyp = SCR_BLANK_PAPER;
		if(obj->olet == POTION_SYM && rn2(12) > Luck) {
			if (obj->spe == -1) {
				obj->otyp = POT_WATER;
				obj->blessed = obj->cursed = 0;
				obj->spe = 0;
			} else obj->spe--;
		}
	}

#ifdef POLYSELF
	if(u.umonnum == PM_GREMLIN && rn2(3)) {
		struct monst *mtmp;
		if(mtmp = cloneu()) {
			mtmp->mhpmax = (u.mhmax /= 2);
			You("multiply.");
		}
	}

	if(is_swimmer(uasmon)) return;
#endif

	You("fell into %s!",
	      levl[u.ux][u.uy].typ == POOL ? "a pool" : "the moat");
	You("can't swim!");
	if(
#ifdef WIZARD
	wizard ||
#endif
	rn2(3) < Luck+2) {
		You("attempt a teleport spell.");	/* utcsri!carroll */
		(void) dotele();
		if(!is_pool(u.ux,u.uy)) return;
	}
	You("drown.");
	killer_format = KILLED_BY_AN;
	killer = levl[u.ux][u.uy].typ == POOL ? "pool of water" : "moat";
	done(DROWNING);
}

#ifdef SPELLS
void
drain_en(n)
register int n;
{
	if (!u.uenmax) return;
	You("feel your magical energy drain away!");
	u.uen -= n;
	if(u.uen < 0)  {
		u.uenmax += u.uen;
		if(u.uenmax < 0) u.uenmax = 0;
		u.uen = 0;
	}
	flags.botl = 1;
}
#endif

int
dountrap() {	/* disarm a trapped object */
	register struct obj *otmp;
	register boolean confused = (Confusion > 0 || Hallucination > 0);
	register int x,y;
	int ch;
	struct trap *ttmp;

#ifdef POLYSELF
	if(nohands(uasmon)) {
	    pline("And just how do you expect to do that?");
	    return(0);
	}
#endif
	if(!getdir(TRUE)) return(0);
	x = u.ux + u.dx;
	y = u.uy + u.dy;

	if(!u.dx && !u.dy) {
	    for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
		if(Is_box(otmp)) {
		    pline("There is %s here, check for traps? ", doname(otmp));

		    switch (ynq()) {
			case 'q': return(0);
			case 'n': continue;
		    }

		    if((otmp->otrapped && !confused 
				&& rn2(MAXLEVEL+2-dlevel) < 10)
		       || confused && !rn2(3)) {
			You("find a trap on the %s!  Disarm it? ", xname(otmp));

			switch (ynq()) {
			    case 'q': return(1);
			    case 'n': continue;
			}

			if(otmp->otrapped) {
			    ch = 15 + (pl_character[0] == 'R') ? u.ulevel*3
								: u.ulevel;
			    if(confused || Fumbling || rnd(75+dlevel/2) > ch) {
				You("set it off!");
				chest_trap(otmp, FINGER);
			    } else {
				You("disarm it!");
				otmp->otrapped = 0;
			    }
			} else pline("That %s was not trapped.", doname(otmp));
			return(1);
		    } else {
			You("find no traps on the %s.", xname(otmp));
			return(1);
		    }
		}
	    if ((ttmp = t_at(x,y)) && ttmp->tseen)
		You("cannot disable this trap.");
	    else
		You("know of no traps here.");
	    return(0);
	}

	if (!IS_DOOR(levl[x][y].typ)) {
	    if ((ttmp = t_at(x,y)) && ttmp->tseen)
		You("cannot disable that trap.");
	    else
		You("know of no traps there.");
	    return(0);
	}

	switch (levl[x][y].doormask) {
	    case D_NODOOR:
		You("%s no door there.", Blind ? "feel" : "see");
		return(0);
	    case D_ISOPEN:
		pline("This door is safely open.");
		return(0);
	    case D_BROKEN:
		pline("This door is broken.");
		return(0);
	}

	if ((levl[x][y].doormask & D_TRAPPED && !confused &&
	     rn2(MAXLEVEL+2-dlevel) < 10)
	    || confused && !rn2(3)) {
		You("find a trap on the door!  Disarm it? ");
		if (ynq() != 'y') return(1);
		if (levl[x][y].doormask & D_TRAPPED) {
		    ch = 15 +
			 (pl_character[0] == 'R') ? u.ulevel*3 :
			 u.ulevel;
		    if(confused || Fumbling || rnd(75+dlevel/2) > ch) {
			    You("set it off!");
			    b_trapped("door");
		    } else
			    You("disarm it!");
		    levl[x][y].doormask &= ~D_TRAPPED;
		} else pline("This door was not trapped.");
		return(1);
	} else {
		You("find no traps on the door.");
		return(1);
	}
}

/* only called when the player is doing something to the chest directly */
void
chest_trap(obj, bodypart)
register struct obj *obj;
register int bodypart;
{
	register struct obj *otmp,*otmp2;
	char	buf[80];

	if(Luck > -13 && rn2(13+Luck) > 7) return;

	otmp = obj;
	switch(rn2(20) ? ((Luck >= 13) ? 0 : rn2(13-Luck)) : rn2(26)) {
		case 25:
		case 24:
		case 23:
		case 22:
		case 21:
			pline("The %s explodes!", xname(obj));
			Sprintf(buf, "exploding %s", xname(obj));

			delete_contents(obj);
			for(otmp = level.objects[u.ux][u.uy];
							otmp; otmp = otmp2) {
			    otmp2 = otmp->nexthere;
			    delobj(otmp);
			}

			losehp(d(6,6), buf, KILLED_BY_AN);
			wake_nearby();
			return;
		case 20:
		case 19:
		case 18:
		case 17:
			pline("A cloud of noxious gas billows from the %s.",
			      xname(obj));
			poisoned("gas cloud", A_STR, "cloud of poison gas",15);
			break;
		case 16:
		case 15:
		case 14:
		case 13:
			You("feel a needle prick your %s.",body_part(bodypart));
			poisoned("needle", A_CON, "poison needle",10);
			break;
		case 12:
		case 11:
		case 10:
		case 9:
			pline("A tower of flame erupts from the %s",
			      xname(obj));
			if(Fire_resistance) {
			    shieldeff(u.ux, u.uy);
			    You("don't seem to be affected.");
			} else	losehp(d(4, 6), "tower of flame", KILLED_BY_AN);
			destroy_item(SCROLL_SYM, AD_FIRE);
#ifdef SPELLS
			destroy_item(SPBOOK_SYM, AD_FIRE);
#endif
			destroy_item(POTION_SYM, AD_FIRE);
			break;
		case 8:
		case 7:
		case 6:
			You("are jolted by a surge of electricity!");
			if(Shock_resistance)  {
			    shieldeff(u.ux, u.uy);
			    You("don't seem to be affected.");
			} else	losehp(d(4, 4), "electric shock", KILLED_BY_AN);
			destroy_item(RING_SYM, AD_ELEC);
			destroy_item(WAND_SYM, AD_ELEC);
			break;
		case 5:
		case 4:
		case 3:
			pline("Suddenly you are frozen in place!");
			nomovemsg = "You can move again.";
			multi = -d(5, 6);
			break;
		case 2:
		case 1:
		case 0:
			pline("A cloud of %s gas billows from the %s",
			      hcolor(), xname(obj));
			if(!Stunned)
			    if (Hallucination)
				pline("What a groovy feeling!");
			    else
				You("stagger and your vision blurs...");
			make_stunned(HStun + rn1(7, 16),FALSE);
			make_hallucinated(Hallucination + rn1(5, 16),FALSE);
			break;
		default: impossible("bad chest trap");
			break;
	}
	bot(); 			/* to get immediate botl re-display */
	otmp->otrapped = 0;		/* these traps are one-shot things */
}

#endif /* OVLB */
#ifdef OVL2

void
wake_nearby() {			/* Wake up nearby monsters. */
	register struct monst *mtmp;

	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
	    if(dist(mtmp->mx,mtmp->my) < u.ulevel*20) {
		if(mtmp->msleep)  mtmp->msleep = 0;
		if(mtmp->mtame)   EDOG(mtmp)->whistletime = moves;
	    }
	}
}

#endif /* OVL2 */
#ifdef OVL0

struct trap *
t_at(x,y)
register int x, y;
{
	register struct trap *trap = ftrap;
	while(trap) {
		if(trap->tx == x && trap->ty == y) return(trap);
		trap = trap->ntrap;
	}
	return((struct trap *)0);
}

#endif /* OVL0 */
#ifdef OVLB

void
deltrap(trap)
register struct trap *trap;
{
	register struct trap *ttmp;

	if(trap == ftrap)
		ftrap = ftrap->ntrap;
	else {
		for(ttmp = ftrap; ttmp->ntrap != trap; ttmp = ttmp->ntrap) ;
		ttmp->ntrap = trap->ntrap;
	}
	free((genericptr_t) trap);
}

void
b_trapped(item)		/* used for doors. can be used */
register const char *item;    /* for anything else that opens */
{
	register int dmg = rnd(5+(dlevel < 5 ? dlevel : 2+dlevel/2));

	pline("KABOOM!!  The %s was booby-trapped!", item);
	if(u.ulevel < 4 && dlevel < 3 && !rnl(3))
		You("are shaken, but luckily unhurt.");		
	else losehp(dmg, "explosion", KILLED_BY_AN);
	make_stunned(HStun + dmg, TRUE);
}

/* Monster is hit by trap. */
/* Note: doesn't work if both obj and d_override are null */
XSTATIC boolean
thitm(tlev, mon, obj, d_override)
register int tlev;
register struct monst *mon;
register struct obj *obj;
int d_override;
{
	register int strike;
	register boolean trapkilled = FALSE;

	if (d_override) strike = 1;
	else if (obj) strike = (mon->data->ac + tlev + obj->spe <= rnd(20));
	else strike = (mon->data->ac + tlev <= rnd(20));

	/* Actually more accurate than thitu, which doesn't take
	 * obj->spe into account.
	 */
	if(!strike) {
		if (cansee(mon->mx, mon->my))
			pline("%s is almost hit by %s!", Monnam(mon),
								doname(obj));
	} else {
		int dam = 1;

		if (obj && cansee(mon->mx, mon->my))
			pline("%s is hit by %s!", Monnam(mon), doname(obj));
		if (d_override) dam = d_override;
		else if (obj) {
			dam = dmgval(obj, mon->data);
			if (dam < 1) dam = 1;
		}
		if ((mon->mhp -= dam) <= 0) {
			int xx = mon->mx;
			int yy = mon->my;

			if (cansee(mon->mx, mon->my))
				pline("%s is killed!", Monnam(mon));
			else if (mon->mtame)
	You("have a sad feeling for a moment, then it passes.");
			mondied(mon);
			newsym(xx, yy);
			trapkilled = TRUE;
		}
	}
	if (obj && (!strike || d_override)) {
		place_object(obj, mon->mx, mon->my);
		obj->nobj = fobj;
		fobj = obj;
		stackobj(fobj);
	} else if (obj) free ((genericptr_t)obj);

	return trapkilled;
}

boolean
unconscious()
{
	return (multi < 0 && (!nomovemsg ||
		!strncmp(nomovemsg,"You wake", 8) ||
		!strncmp(nomovemsg,"You awake", 9) ||
		!strncmp(nomovemsg,"You regain con", 15) ||
		!strncmp(nomovemsg,"You are consci", 15)));
}

#endif /* OVLB */

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.