home *** CD-ROM | disk | FTP | other *** search
- /* SCCS Id: @(#)trap.c 3.1 92/12/10 */
- /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
- /* NetHack may be freely redistributed. See license for details. */
-
- #include "hack.h"
-
- #ifdef OVLB
- const char *traps[TRAPNUM] = {
- "",
- "n arrow trap",
- " dart trap",
- " falling rock trap",
- " squeaky board",
- " bear trap",
- " land mine",
- " sleeping gas trap",
- " rust trap",
- " fire trap",
- " pit",
- " spiked pit",
- " trapdoor",
- " teleportation trap",
- " level teleporter",
- " magic portal",
- " web",
- " statue trap",
- " magic trap",
- "n anti-magic field"
- #ifdef POLYSELF
- ," polymorph trap"
- #endif
- };
-
- #endif /* OVLB */
-
- static void FDECL(domagicportal,(struct trap *));
- static void NDECL(dofiretrap);
- static void NDECL(domagictrap);
- static boolean FDECL(emergency_disrobe,(boolean *));
- STATIC_DCL boolean FDECL(thitm, (int, struct monst *, struct obj *, int));
-
- #ifdef OVLB
-
- static int FDECL(teleok, (int,int,BOOLEAN_P));
- static void NDECL(vtele);
- static void FDECL(no_fall_through, (BOOLEAN_P));
-
- /* 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 NEARDATA *action[] = { "smoulder", "rust", "rot", "corrode" };
- static const char NEARDATA *msg[] = { "burnt", "rusted", "rotten", "corroded" };
- boolean vulnerable = FALSE;
- boolean plural;
- boolean grprot = FALSE;
-
- if (!otmp) return(FALSE);
- switch(type) {
- case 0:
- case 2: vulnerable = is_flammable(otmp); break;
- case 1: vulnerable = is_rustprone(otmp); grprot = TRUE; break;
- case 3: vulnerable = is_corrodeable(otmp); grprot = TRUE; break;
- }
-
- if (!print && (!vulnerable || otmp->oerodeproof || otmp->oeroded == MAX_ERODE))
- return FALSE;
-
- plural = is_gloves(otmp) || is_boots(otmp);
-
- if (!vulnerable)
- if (flags.verbose)
- Your("%s %s not affected.", ostr, plural ? "are" : "is");
- else if (otmp->oeroded < MAX_ERODE) {
- if (grprot && otmp->greased)
- grease_protect(otmp,ostr,plural);
- else if (otmp->oerodeproof || (otmp->blessed && !rnl(4))) {
- if (flags.verbose)
- pline("Somehow, your %s %s not affected.",
- ostr, plural ? "are" : "is");
- } else {
- Your("%s %s%s%s!", ostr, action[type],
- plural ? "" : "s",
- otmp->oeroded+1 == MAX_ERODE ? " completely" :
- otmp->oeroded ? " further" : "");
- otmp->oeroded++;
- }
- } else
- if (flags.verbose)
- Your("%s %s%s completely %s.", ostr,
- Blind ? "feel" : "look",
- plural ? "" : "s", msg[type]);
- return(TRUE);
- }
-
- void
- grease_protect(otmp,ostr,plu)
- register struct obj *otmp;
- register const char *ostr;
- register boolean plu;
- {
- static const char txt[] = "protected by the layer of grease!";
-
- if (ostr)
- Your("%s %s %s",ostr,plu ? "are" : "is",txt);
- else
- Your("%s %s",aobjnam(otmp,"are"),txt);
- if (!rn2(2)) {
- pline("The grease dissolves.");
- otmp->greased = 0;
- }
- }
-
- struct trap *
- maketrap(x,y,typ)
- register int x, y, typ;
- {
- register struct trap *ttmp;
- register boolean oldplace;
-
- if (ttmp = t_at(x,y)) {
- oldplace = TRUE;
- if (u.utrap && (x == u.ux) && (y == u.uy) &&
- ((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;
- } else {
- oldplace = FALSE;
- ttmp = newtrap();
- ttmp->tx = x;
- ttmp->ty = y;
- }
- ttmp->ttyp = typ;
- switch(typ) {
- case STATUE_TRAP: /* create a "living" statue */
- (void) mkcorpstat(STATUE, &mons[rndmonnum()], x, y, FALSE);
- break;
- case PIT:
- case SPIKED_PIT:
- case TRAPDOOR:
- levl[x][y].doormask = 0; /* subsumes altarmask, icedpool... */
- if (IS_ROOM(levl[x][y].typ))
- levl[x][y].typ = ROOM;
- break;
- }
- ttmp->tseen = 0;
- ttmp->once = 0;
- ttmp->dst.dnum = -1;
- ttmp->dst.dlevel = -1;
- if (!oldplace) {
- ttmp->ntrap = ftrap;
- ftrap = ttmp;
- }
- return(ttmp);
- }
-
- static int
- teleok(x, y, trapok)
- register int x, y;
- boolean trapok;
- { /* might throw him into a POOL
- * removed by GAN 10/20/86
- */
- #ifdef STUPID
- boolean tmp1, tmp2, tmp3, tmp4;
- # 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) && (trapok || !t_at(x,y));
- tmp3 = !(is_pool(x,y) &&
- !(Levitation || Wwalking || Magical_breathing
- # ifdef POLYSELF
- || is_flyer(uasmon) || is_swimmer(uasmon)
- || is_clinger(uasmon)
- # endif
- )) && !closed_door(x,y);
- tmp4 = !is_lava(x,y);
- return(tmp1 && tmp2 && tmp3 && tmp4);
- #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) && (trapok || !t_at(x,y)) &&
- !(is_pool(x,y) &&
- !(Levitation || Wwalking || Magical_breathing
- # ifdef POLYSELF
- || is_flyer(uasmon) || is_swimmer(uasmon)
- || is_clinger(uasmon)
- # endif
- )) && !is_lava(x,y) && !closed_door(x,y));
- #endif
- /* Note: gold is permitted (because of vaults) */
- }
-
- boolean
- safe_teleds()
- {
- register int nux, nuy;
- short tcnt = 0;
-
- do {
- nux = rnd(COLNO-1);
- nuy = rn2(ROWNO);
- } while (!teleok(nux, nuy, tcnt>200) && tcnt++ < 400);
-
- if (tcnt < 400) {
- teleds(nux, nuy);
- return TRUE;
- } else
- return FALSE;
- }
-
- static void
- vtele()
- {
- register struct mkroom *croom = search_special(VAULT);
- coord c;
-
- if(croom && somexy(croom, &c) && teleok(c.x,c.y,FALSE)) {
- teleds(c.x,c.y);
- return;
- }
- tele();
- }
-
- static void
- no_fall_through(td)
- boolean td;
- {
- /* floor objects get a chance of falling down. the case
- * where the hero does NOT fall down is treated here. the
- * case where the hero does fall down is treated in goto_level().
- * reason: the target level of the fall is not determined here,
- * and it need not be the next level. if we want falling
- * objects to arrive near the player, we must call impact_drop()
- * _after_ the target level is determined.
- */
- impact_drop((struct obj *)0, u.ux, u.uy, 0);
- if (!td) {
- display_nhwindow(WIN_MESSAGE, FALSE);
- pline("The opening under you closes up.");
- }
- }
-
- void
- fall_through(td)
- boolean td; /* td == TRUE : trapdoor */
- {
- register int newlevel = dunlev(&u.uz);
-
- if(Blind && Levitation) return;
-
- do {
- newlevel++;
- } while(!rn2(4) && newlevel < dunlevs_in_dungeon(&u.uz));
-
- if(td) pline("A trap door opens up under you!");
- else pline("The floor opens up under you!");
-
- if(Levitation || u.ustuck || !Can_fall_thru(&u.uz)
- #ifdef POLYSELF
- || is_flyer(uasmon) || is_clinger(uasmon)
- #endif
- || (Inhell && !u.uevent.invoked &&
- newlevel == dunlevs_in_dungeon(&u.uz))
- ) {
- You("don't fall in.");
- no_fall_through(td);
- return;
- }
- #ifdef WALKIES
- if(!next_to_u()) {
- You("are jerked back by your pet!");
- no_fall_through(td);
- return;
- }
- #endif
- if(*u.ushops) shopdig(1);
- if(Is_stronghold(&u.uz)) goto_hell(TRUE, TRUE);
- else {
- d_level dtmp;
- dtmp.dnum = u.uz.dnum;
- dtmp.dlevel = newlevel;
- goto_level(&dtmp, FALSE, TRUE, FALSE);
- if(!td) pline("The hole in the ceiling above you closes up.");
- }
- }
-
- 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 &&
- #ifdef POLYSELF
- !((ttype == PIT || ttype == SPIKED_PIT) && !is_clinger(uasmon)) &&
- #else
- !(ttype == PIT || ttype == SPIKED_PIT) &&
- #endif
- !(ttype == MAGIC_PORTAL || ttype == ANTI_MAGIC) && !rn2(5))
- You("escape a%s.", traps[ttype]);
- else {
- seetrap(trap);
- switch(ttype) {
- case ARROW_TRAP:
- pline("An arrow shoots out at you!");
- otmp = mksobj(ARROW, TRUE, FALSE);
- otmp->quan = 1L;
- otmp->owt = weight(otmp);
- if(thitu(8,dmgval(otmp,uasmon),otmp,"arrow"))
- obfree(otmp, (struct obj *)0);
- else {
- place_object(otmp, u.ux, u.uy);
- otmp->nobj = fobj;
- fobj = otmp;
- stackobj(otmp);
- newsym(u.ux, u.uy);
- }
- break;
- case DART_TRAP:
- pline("A little dart shoots out at you!");
- otmp = mksobj(DART, TRUE, FALSE);
- otmp->quan = 1L;
- otmp->owt = weight(otmp);
- if (!rn2(6)) otmp->opoisoned = 1;
- if(thitu(7,dmgval(otmp,uasmon),otmp,"little dart")) {
- if (otmp->opoisoned)
- poisoned("dart",A_CON,"poison dart",10);
- obfree(otmp, (struct obj *)0);
- } else {
- place_object(otmp, u.ux, u.uy);
- otmp->nobj = fobj;
- fobj = otmp;
- stackobj(otmp);
- newsym(u.ux, u.uy);
- }
- break;
- case ROCKTRAP:
- {
- int dmg = d(2,6); /* should be std ROCK dmg? */
-
- otmp = mksobj_at(ROCK, u.ux, u.uy, TRUE);
- otmp->quan = 1L;
- otmp->owt = weight(otmp);
-
- pline("A trap door in the ceiling opens and a rock falls on your %s!",
- body_part(HEAD));
-
- if (uarmh)
- if(is_metallic(uarmh)) {
- pline("Fortunately, you are wearing a hard helmet.");
- dmg = 2;
- } else if (flags.verbose)
- Your("%s does not protect you.", xname(uarmh));
-
- stackobj(otmp);
- newsym(u.ux,u.uy); /* map the rock */
-
- losehp(dmg, "falling rock", KILLED_BY_AN);
- exercise(A_STR, FALSE);
- }
- break;
-
- case SQKY_BOARD: /* stepped on a squeaky board */
- if (Levitation
- #ifdef POLYSELF
- || is_flyer(uasmon) || is_clinger(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 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 = rn1(4, 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
- exercise(A_DEX, FALSE);
- break;
-
- 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));
- u.usleep = 1;
- nomovemsg = "You wake up.";
- afternmv = Hear_again;
- break;
-
- case RUST_TRAP:
- #ifdef POLYSELF
- if (u.umonnum == PM_IRON_GOLEM) {
- pline("A gush of water hits you!");
- You("are covered with rust!");
- rehumanize();
- break;
- } else
- 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: erode_weapon(FALSE);
- 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 TOURIST
- else if (uarmu)
- (void) rust_dmg(uarmu, "shirt", 1, TRUE);
- #endif
- }
- break;
-
- case FIRE_TRAP:
- dofiretrap();
- break;
-
- case PIT:
- if (Levitation
- #ifdef POLYSELF
- || is_flyer(uasmon) || is_clinger(uasmon)
- #endif
- ) {
- if(Blind) break;
- if(trap->tseen)
- You("see a pit below you.");
- else {
- 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);
- if (Punished && !carried(uball)) {
- unplacebc();
- ballfall();
- placebc();
- }
- selftouch("Falling, you");
- exercise(A_STR, FALSE);
- vision_full_recalc = 1; /* vision limits change */
- break;
- case SPIKED_PIT:
- if (Levitation
- #ifdef POLYSELF
- || is_flyer(uasmon) || is_clinger(uasmon)
- #endif
- ) {
- if(Blind) break;
- 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);
- if (Punished && !carried(uball)) {
- unplacebc();
- ballfall();
- placebc();
- }
- selftouch("Falling, you");
- vision_full_recalc = 1; /* vision limits change */
- exercise(A_STR, FALSE);
- exercise(A_DEX, FALSE);
- break;
-
- case TRAPDOOR:
- if(!Can_fall_thru(&u.uz))
- panic("Trapdoors cannot exist on this level.");
- fall_through(TRUE);
- break;
-
- case TELEP_TRAP:
- if(In_endgame(&u.uz) || Antimagic) {
- if(Antimagic)
- shieldeff(u.ux, u.uy);
- You("feel a wrenching sensation.");
- #ifdef WALKIES
- } else if(!next_to_u()) {
- You(shudder_for_moment);
- #endif
- } else if(trap->once) {
- deltrap(trap);
- newsym(u.ux,u.uy); /* get rid of trap symbol */
- vtele();
- } else
- tele();
- break;
- case LEVEL_TELEP:
- You("%s onto a level teleport trap!",
- Levitation ? (const char *)"float" :
- #ifdef POLYSELF
- locomotion(uasmon, "step"));
- #else
- (const char *)"step");
- #endif
- if(Antimagic) {
- shieldeff(u.ux, u.uy);
- }
- if(Antimagic || In_endgame(&u.uz)) {
- 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); /* get rid of trap symbol */
- level_tele();
- break;
-
- case WEB: /* Our luckless player has stumbled into a web. */
- #ifdef POLYSELF
- if (amorphous(uasmon)) {
- if (acidic(uasmon) || u.umonnum == PM_GELATINOUS_CUBE)
- {
- deltrap(trap);
- newsym(u.ux,u.uy);/* update position */
- You("dissolve a spider web.");
- break;
- }
- You("flow through a spider web.");
- break;
- }
- if (uasmon->mlet == S_SPIDER) {
- pline("There is a spider web here.");
- break;
- }
- #endif
- You("%s into a spider web!",
- Levitation ? (const char *)"float" :
- #ifdef POLYSELF
- locomotion(uasmon, "stumble"));
- #else
- (const char *)"stumble");
- #endif
- u.utraptype = TT_WEB;
-
- /* Time stuck in the web depends on your strength. */
- {
- register int str = ACURR(A_STR);
-
- if (str == 3) u.utrap = rn1(6,6);
- else if (str < 6) u.utrap = rn1(6,4);
- else if (str < 9) u.utrap = rn1(4,4);
- else if (str < 12) u.utrap = rn1(4,2);
- else if (str < 15) u.utrap = rn1(2,2);
- else if (str < 18) u.utrap = rnd(2);
- else if (str < 69) u.utrap = 1;
- else {
- u.utrap = 0;
- You("tear through the web!");
- deltrap(trap);
- newsym(u.ux,u.uy); /* get rid of trap symbol */
- }
- }
- break;
-
- case STATUE_TRAP:
- deltrap(trap);
- newsym(u.ux,u.uy); /* get rid of trap symbol */
- for(otmp=level.objects[u.ux][u.uy];
- otmp; otmp = otmp->nexthere)
- if(otmp->otyp == STATUE)
- if(mtmp=makemon(&mons[otmp->corpsenm],u.ux,u.uy)) {
- pline("The statue comes to life!");
- /* mimic statues become seen mimics */
- if(mtmp->m_ap_type) seemimic(mtmp);
- delobj(otmp);
- break;
- }
- break;
-
- case MAGIC_TRAP: /* A magic trap. */
- if (!rn2(30)) {
- deltrap(trap);
- newsym(u.ux,u.uy); /* update position */
- You("are caught in a magical explosion!");
- losehp(rnd(10), "magical explosion", KILLED_BY_AN);
- Your("body absorbs some of the magical energy!");
- u.uen = (u.uenmax += 2);
- } else domagictrap();
- break;
-
- case ANTI_MAGIC:
- if(Antimagic) {
- shieldeff(u.ux, u.uy);
- You("feel momentarily lethargic.");
- } else drain_en(rnd((int)u.ulevel) + 1);
- break;
-
- #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 {
- deltrap(trap); /* delete trap before polymorph */
- newsym(u.ux,u.uy); /* get rid of trap symbol */
- You("feel a change coming over you.");
- polyself();
- }
- break;
- #endif
-
- case LANDMINE: {
- 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, rn1(35, 41));
- set_wounded_legs(RIGHT_SIDE, rn1(35, 41));
- }
- losehp(rnd(16), "land mine", KILLED_BY_AN);
- /* wake everything on the level */
- for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
- if(mtmp->msleep) mtmp->msleep = 0;
- }
- deltrap(t_at(u.ux, u.uy)); /* mines only explode once */
- newsym(u.ux,u.uy); /* get rid of trap symbol */
- }
- break;
-
- case MAGIC_PORTAL:
- #ifdef WALKIES
- if(!next_to_u())
- You(shudder_for_moment);
- else
- #endif
- domagicportal(trap);
- break;
-
- default:
- impossible("You hit a trap of type %u", trap->ttyp);
- }
- }
- }
-
- #endif /* OVLB */
-
- #ifdef WALKIES
-
- STATIC_DCL boolean FDECL(teleport_pet, (struct monst *));
-
- #ifdef OVLB
-
- STATIC_OVL 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 /* WALKIES */
-
- #ifdef OVLB
-
- 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);
- boolean trapkilled = FALSE, tdoor = FALSE;
- struct permonst *mptr = mtmp->data;
- struct obj *otmp;
-
- if(!trap) {
- mtmp->mtrapped = 0; /* perhaps teleported? */
- } else if (mtmp->mtrapped) { /* was in trap */
- if(!rn2(40))
- if (sobj_at(BOULDER, mtmp->mx, mtmp->my) &&
- ((trap->ttyp == PIT) ||
- (trap->ttyp == SPIKED_PIT))) {
- if (!rn2(2)) {
- mtmp->mtrapped = 0;
- fill_pit(mtmp->mx, mtmp->my);
- }
- } else
- mtmp->mtrapped = 0;
- } else {
- register int tt = trap->ttyp;
-
- /* A bug fix for dumb messages by ab@unido.
- */
- int in_sight = canseemon(mtmp);
-
- if(mtmp->mtrapseen & (1 << tt)) {
- /* it has been in such a trap - perhaps it escapes */
- if(rn2(4)) return(0);
- }
- mtmp->mtrapseen |= (1 << tt);
- switch (tt) {
- case ARROW_TRAP:
- otmp = mksobj(ARROW, TRUE, FALSE);
- otmp->quan = 1L;
- otmp->owt = weight(otmp);
- if(in_sight) seetrap(trap);
- if(thitm(8, mtmp, otmp, 0)) trapkilled = TRUE;
- break;
- case DART_TRAP:
- otmp = mksobj(DART, TRUE, FALSE);
- otmp->quan = 1L;
- otmp->owt = weight(otmp);
- if (!rn2(6)) otmp->opoisoned = 1;
- if(in_sight) seetrap(trap);
- if(thitm(7, mtmp, otmp, 0)) trapkilled = TRUE;
- break;
- case ROCKTRAP:
- otmp = mksobj(ROCK, TRUE, FALSE);
- otmp->quan = 1L;
- otmp->owt = weight(otmp);
- if(in_sight) seetrap(trap);
- if(!is_whirly(mptr) && !passes_walls(mptr) &&
- thitm(0, mtmp, otmp, d(2, 6)))
- trapkilled = TRUE;
- break;
-
- case SQKY_BOARD: {
- register struct monst *ztmp = fmon;
-
- if(is_flyer(mptr)) 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 BEAR_TRAP:
- if(mptr->msize > MZ_SMALL &&
- !amorphous(mptr) && !is_flyer(mptr)) {
- mtmp->mtrapped = 1;
- if(in_sight) {
- pline("%s is caught in a bear trap!",
- Monnam(mtmp));
- seetrap(trap);
- } else
- if((mptr == &mons[PM_OWLBEAR]
- || mptr == &mons[PM_BUGBEAR])
- && flags.soundok)
- You("hear the roaring of an angry bear!");
- }
- break;
-
- case SLP_GAS_TRAP:
- if(!resists_sleep(mptr) &&
- !mtmp->msleep && mtmp->mcanmove) {
- mtmp->mcanmove = 0;
- mtmp->mfrozen = rnd(25);
- if (in_sight) {
- pline("%s suddenly falls asleep!",
- Monnam(mtmp));
- seetrap(trap);
- }
- }
- break;
-
- case RUST_TRAP:
- if (in_sight) {
- pline("A gush of water hits %s!", mon_nam(mtmp));
- seetrap(trap);
- }
- if (mptr == &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 if (mptr == &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 FIRE_TRAP:
- if (in_sight)
- pline("A tower of flame bursts from the floor under %s!",
- mon_nam(mtmp));
- if(resists_fire(mptr)) {
- if (in_sight) {
- shieldeff(mtmp->mx,mtmp->my);
- pline("%s is uninjured.", Monnam(mtmp));
- }
- } else {
- int num=rnd(6);
-
- if (thitm(0, mtmp, (struct obj *)0, num))
- trapkilled = TRUE;
- else mtmp->mhpmax -= num;
- }
- (void) destroy_mitem(mtmp, SCROLL_CLASS, AD_FIRE);
- (void) destroy_mitem(mtmp, SPBOOK_CLASS, AD_FIRE);
- (void) destroy_mitem(mtmp, POTION_CLASS, AD_FIRE);
- if (in_sight) seetrap(trap);
- break;
-
- case PIT:
- case SPIKED_PIT:
- if ( !is_flyer(mptr) &&
- (!mtmp->wormno || (count_wsegs(mtmp) < 6)) &&
- !is_clinger(mptr) ) {
- if (!passes_walls(mptr))
- 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 TRAPDOOR:
- if(!Can_fall_thru(&u.uz))
- panic("Trapdoors cannot exist on this level.");
-
- if ( (mptr == &mons[PM_WUMPUS]) ||
- (mtmp->wormno && count_wsegs(mtmp) > 5) ) break;
- tdoor = TRUE;
- /* Fall through */
- case LEVEL_TELEP:
- /* long worms w/tails can now change levels! - Norm */
- if (!is_flyer(mptr)) {
- register int nlev;
- d_level tolevel;
- #ifdef WALKIES
- if(teleport_pet(mtmp)) {
- #endif
- if(tdoor) {
- if(Is_stronghold(&u.uz))
- assign_level(&tolevel, &valley_level);
- else if(Is_botlevel(&u.uz)) {
- pline("%s avoids the trap.",
- Monnam(mtmp));
- break;
- } else get_level(&tolevel,depth(&u.uz)+1);
- } else {
- #ifdef MULDGN
- if(Is_knox(&u.uz)) {
- rloc(mtmp);
- break;
- }
- #endif
- nlev = rnd(3);
- if(!rn2(2)) nlev = -(nlev);
- nlev = dunlev(&u.uz) + nlev;
- if(nlev > dunlevs_in_dungeon(&u.uz)) {
- nlev = dunlevs_in_dungeon(&u.uz);
- /* teleport up if already on bottom */
- if (Is_botlevel(&u.uz))
- nlev -= rnd(3);
- }
- if (nlev < 1) {
- nlev = 1;
- if (dunlev(&u.uz) == 1) {
- nlev += rnd(3);
- if (nlev >
- dunlevs_in_dungeon(&u.uz))
- nlev =
- dunlevs_in_dungeon(&u.uz);
- }
- }
- /* can't seem to go anywhere */
- /* (possible in short dungeons) */
- if (nlev == dunlev(&u.uz)) {
- rloc(mtmp);
- break;
- }
- nlev = dungeons[u.uz.dnum].depth_start +
- nlev;
- get_level(&tolevel, nlev);
- }
- if(in_sight) {
- pline("Suddenly, %s disappears out of sight.", mon_nam(mtmp));
- seetrap(trap);
- }
- migrate_to_level(mtmp,
- ledger_no(&tolevel), 0);
- return(3); /* no longer on this level */
- #ifdef WALKIES
- }
- #endif
- }
- break;
-
- case TELEP_TRAP:
- case MAGIC_PORTAL:
- #ifdef WALKIES
- if(teleport_pet(mtmp)) {
- #endif
- /* Note: don't remove the trap if a vault. Other-
- * wise the monster will be stuck there, since
- * the guard isn't going to come for it...
- * Also: don't remove if magic portal. In short,
- * don't remove :-)
- */
- if (in_sight) {
- pline("%s suddenly disappears!",
- Monnam(mtmp));
- seetrap(trap);
- }
- if (trap->once) vloc(mtmp);
- else rloc(mtmp);
- #ifdef WALKIES
- }
- #endif
- break;
-
- case WEB:
- /* Monster in a web. */
- if (mptr->mlet == S_SPIDER) break;
- if (amorphous(mptr)) {
- if (acidic(mptr) ||
- mptr == &mons[PM_GELATINOUS_CUBE]) {
- if (in_sight)
- pline("%s dissolves a spider web.",
- Monnam(mtmp));
- deltrap(trap);
- break;
- }
- if (in_sight)
- pline("%s flows through a spider web.",
- Monnam(mtmp));
- break;
- }
- switch (monsndx(mptr)) {
- case PM_FIRE_ELEMENTAL:
- if (in_sight)
- pline("%s burns a spider web!", Monnam(mtmp));
- deltrap(trap);
- break;
- case PM_OWLBEAR: /* Eric Backus */
- case PM_BUGBEAR:
- if (!in_sight) {
- You("hear the roaring of a confused bear!");
- mtmp->mtrapped = 1;
- break;
- }
- /* fall though */
- default:
- if (in_sight)
- pline("%s is caught in a spider web.",
- Monnam(mtmp));
- mtmp->mtrapped = 1;
- break;
- }
- break;
-
- case STATUE_TRAP:
- break;
-
- case MAGIC_TRAP:
- /* A magic trap. Monsters immune. */
- break;
- case ANTI_MAGIC:
- break;
-
- case LANDMINE: {
- register struct monst *mntmp = fmon;
-
- if(rn2(3))
- break; /* monsters usually don't set it off */
- if(is_flyer(mptr)) {
- if (in_sight) {
- pline("A trigger appears in a pile of soil below %s.", Monnam(mtmp));
- seetrap(trap);
- }
- if (rn2(3)) break;
- if (in_sight)
- pline("The air currents set it off!");
- } else if(in_sight)
- pline("KAABLAMM!!! %s triggers a land mine!",
- Monnam(mtmp));
- if (!in_sight)
- pline("Kaablamm! You hear an explosion in the distance!");
- deltrap(trap);
- 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;
- }
- if (unconscious()) {
- multi = -1;
- nomovemsg="The explosion awakens you!";
- }
- break;
- }
-
- #ifdef POLYSELF
- case POLY_TRAP:
- if(!resist(mtmp, WAND_CLASS, 0, NOTELL)) {
- (void) newcham(mtmp, (struct permonst *)0);
- if (in_sight) seetrap(trap);
- }
- break;
- #endif
-
- default:
- impossible("Some monster encountered a strange trap of type %d.", tt);
- }
- }
- if(trapkilled) return 2;
- 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);
- #ifdef POLYSELF
- if(poly_when_stoned(uasmon) && polymon(PM_STONE_GOLEM))
- return;
- #endif
- 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!");
- vision_full_recalc = 1; /* vision limits change */
- fill_pit(u.ux, u.uy);
- } else if (u.utraptype == TT_INFLOOR) {
- Your("body pulls upward, but your %s are still stuck.",
- makeplural(body_part(LEG)));
- } else {
- You("float up, only your %s is still stuck.",
- body_part(LEG));
- }
- }
- else if(Is_waterlevel(&u.uz))
- pline("It feels as though you'd lost some weight.");
- else if(u.uinwater)
- spoteffects();
- else if (Hallucination)
- pline("Up, up, and awaaaay! You're walking on air!");
- else if(Is_airlevel(&u.uz))
- You("gain control over your movements.");
- else
- You("start to float in the air!");
- }
-
- void
- fill_pit(x, y)
- int x, y;
- {
- struct obj *otmp;
- struct trap *t;
-
- if ((t = t_at(x, y)) &&
- ((t->ttyp == PIT) || (t->ttyp == SPIKED_PIT)) &&
- (otmp = sobj_at(BOULDER, x, y))) {
- freeobj(otmp);
- (void) flooreffects(otmp, x, y, "settle");
- }
- }
-
- int
- float_down()
- {
- register struct trap *trap = (struct trap *)0;
- boolean no_msg = FALSE;
-
- if(Levitation) return(0); /* maybe another ring/potion/boots */
-
- if (Punished && !carried(uball) &&
- (is_pool(uball->ox, uball->oy) ||
- ((trap = t_at(uball->ox, uball->oy)) &&
- ((trap->ttyp == PIT) || (trap->ttyp == SPIKED_PIT) ||
- (trap->ttyp == TRAPDOOR))))) {
- u.ux0 = u.ux;
- u.uy0 = u.uy;
- u.ux = uball->ox;
- u.uy = uball->oy;
- movobj(uchain, uball->ox, uball->oy);
- newsym(u.ux0, u.uy0);
- vision_full_recalc = 1; /* in case the hero moved. */
- }
- /* check for falling into pool - added by GAN 10/20/86 */
- #ifdef POLYSELF
- if(!is_flyer(uasmon)) {
- #endif
- /* kludge alert:
- * drown() and lava_effects() print various messages almost
- * every time they're called which conflict with the "fall
- * into" message below. Thus, we want to avoid printing
- * confusing, duplicate or out-of-order messages.
- * Use knowledge of the two routines as a hack -- this
- * should really handled differently -dlc
- */
- if(is_pool(u.ux,u.uy) && !Wwalking && !u.uinwater)
- no_msg = drown();
-
- if(is_lava(u.ux,u.uy)) {
- (void) lava_effects();
- no_msg = TRUE;
- }
- #ifdef POLYSELF
- }
- #endif
- if (!trap) {
- if(Is_airlevel(&u.uz))
- You("begin to tumble in place.");
- if(Is_waterlevel(&u.uz) && !no_msg)
- You("feel heavier.");
- /* u.uinwater msgs already in spoteffects()/drown() */
- else if (!u.uinwater && !no_msg) {
- if (Hallucination)
- pline("Bummer! You've %s.",
- is_pool(u.ux,u.uy) ?
- "splashed down" : "hit the ground");
- else
- You("float gently to the %s.",
- is_pool(u.ux,u.uy) ? "water" : "ground");
- }
- trap = t_at(u.ux,u.uy);
- }
-
- if(trap)
- switch(trap->ttyp) {
- case STATUE_TRAP:
- break;
- case TRAPDOOR:
- if(!Can_fall_thru(&u.uz) || u.ustuck)
- break;
- /* fall into next case */
- default:
- dotrap(trap);
- }
- if(!flags.nopick && OBJ_AT(u.ux, u.uy) &&
- !Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz) &&
- (!is_pool(u.ux,u.uy) || Underwater))
- pickup(1);
- return 0;
- }
-
-
- void
- tele()
- {
- coord cc;
-
- /* Disable teleportation in stronghold && Vlad's Tower */
- if(level.flags.noteleport) {
- #ifdef WIZARD
- if (!wizard) {
- #endif
- pline("A mysterious force prevents you from teleporting!");
- return;
- #ifdef WIZARD
- }
- #endif
- }
-
- /* don't show trap if "Sorry..." */
- if(!Blinded) make_blinded(0L,FALSE);
-
- if((u.uhave.amulet || Is_wiz1_level(&u.uz) || Is_wiz2_level(&u.uz) ||
- Is_wiz3_level(&u.uz)) && !rn2(3)) {
- You("feel disoriented for a moment.");
- return;
- }
- if(Teleport_control
- #ifdef WIZARD
- || wizard
- #endif
- ) {
- 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, TRUE, "the desired position");/* force valid*/
- if(cc.x == -10) return; /* abort */
- /* possible extensions: introduce a small error if
- magic power is low; allow transfer to solid rock */
- if(teleok(cc.x, cc.y, FALSE)){
- teleds(cc.x, cc.y);
- return;
- }
- pline("Sorry...");
- }
- }
-
- (void) safe_teleds();
- }
-
- void
- teleds(nux, nuy)
- register int nux,nuy;
- {
- if (Punished) unplacebc();
- u.utrap = 0;
- u.ustuck = 0;
- u.ux0 = u.ux;
- u.uy0 = u.uy;
- u.ux = nux;
- u.uy = nuy;
- fill_pit(u.ux0, u.uy0); /* do this now so that cansee() is correct */
- #ifdef POLYSELF
- if (hides_under(uasmon))
- u.uundetected = OBJ_AT(nux, nuy);
- else
- u.uundetected = 0;
- if (u.usym == S_MIMIC_DEF) u.usym = S_MIMIC;
- #endif
- if(Punished) placebc();
- if(u.uswallow){
- u.uswldtim = u.uswallow = 0;
- docrt();
- }
- initrack(); /* teleports mess up tracking monsters without this */
- /*
- * Make sure the hero disappears from the old location. This will
- * not happen if she is teleported within sight of her previous
- * location. Force a full vision recalculation because the hero
- * is now in a new location.
- */
- newsym(u.ux0,u.uy0);
- vision_full_recalc = 1;
- nomul(0);
- spoteffects();
- }
-
- int
- dotele()
- {
- struct trap *trap;
- boolean castit = FALSE;
- register int sp_no = 0;
-
- 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.");
- if (yn("Jump in?") == '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
- )
- )) {
- /* 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;
- }
- #ifdef WIZARD
- if (!wizard) {
- #endif
- if (!castit) {
- if (!Teleportation)
- You("don't know that spell.");
- else You("are not able to teleport at will.");
- return(0);
- }
- #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);
- }
- if(!trap &&
- check_capacity("Your concentration falters from carrying so much."))
- return 1;
-
- if (castit) {
- exercise(A_WIS, TRUE);
- if (spelleffects(++sp_no, TRUE))
- return(1);
- else
- #ifdef WIZARD
- if (!wizard)
- #endif
- return(0);
- }
- #ifdef WALKIES
- if(next_to_u()) {
- #endif
- if (trap && trap->once) vtele();
- else tele();
- #ifdef WALKIES
- (void) next_to_u();
- } else {
- You(shudder_for_moment);
- return(0);
- }
- #endif
- if (!trap) morehungry(100);
- return(1);
- }
-
-
- void
- level_tele()
- {
- register int newlev;
- d_level newlevel;
-
- if((u.uhave.amulet || In_endgame(&u.uz))
- #ifdef WIZARD
- && !wizard
- #endif
- ) {
- You("feel very disoriented for a moment.");
- return;
- }
- if(Teleport_control
- #ifdef WIZARD
- || wizard
- #endif
- ) {
- char buf[BUFSZ];
-
- do {
- getlin("To what level do you want to teleport? [type a number]",
- buf);
- } while(!digit(buf[0]) && (buf[0] != '-' || !digit(buf[1])));
- newlev = atoi(buf);
-
- /* no dungeon escape via this route */
- if(newlev == 0) {
- if(ynq("Go to Nowhere. Are you sure?") != 'y') return;
- You("scream in agony as your body begins to warp...");
- display_nhwindow(WIN_MESSAGE, FALSE);
- You("cease to exist.");
- killer_format = NO_KILLER_PREFIX;
- killer = "committed suicide";
- done(DIED);
- return;
- }
- #ifdef MULDGN
- /* if in Knox and the requested level > 0, stay put.
- * we let negative values requests fall into the "heaven" loop.
- */
- if(Is_knox(&u.uz) && newlev > 0) {
- You(shudder_for_moment);
- return;
- }
- /* if in Quest, the player sees "Home 1", etc., on the status
- * line, instead of the logical depth of the level. controlled
- * level teleport request is likely to be relativized to the
- * status line, and consequently it should be incremented to
- * the value of the logical depth of the target level.
- *
- * we let negative values requests fall into the "heaven" loop.
- */
- if(In_quest(&u.uz) && newlev > 0)
- newlev = newlev + dungeons[u.uz.dnum].depth_start - 1;
- #endif
- } else { /* involuntary level tele */
- #ifdef MULDGN
- if(Is_knox(&u.uz)) {
- You(shudder_for_moment);
- return;
- }
- #endif
- if(rn2(5)) newlev = rnd((int)depth(&u.uz) + 3);
- else {
- You(shudder_for_moment);
- return;
- }
- if(newlev == depth(&u.uz)) {
- /* if in a single-level dungeon... */
- if(dunlevs_in_dungeon(&u.uz) == 1) {
- You(shudder_for_moment);
- return;
- }
- else if(dunlev(&u.uz) == 1) newlev++;
- else if(dunlev(&u.uz) == dunlevs_in_dungeon(&u.uz)) newlev--;
- else if(In_hell(&u.uz)) newlev--;
- else newlev++;
- }
- }
-
- #ifdef WALKIES
- if(!next_to_u()) {
- You(shudder_for_moment);
- return;
- }
- #endif
- if(newlev < 0) {
- if(newlev <= -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);
- return;
- } else if (newlev == -9) {
- You("feel deliriously happy. ");
- pline("(In fact, you're on Cloud 9!) ");
- display_nhwindow(WIN_MESSAGE, FALSE);
- } else
- You("are now high above the clouds...");
-
- if(Levitation || is_floater(uasmon)) {
- You("float gently down to earth.");
- u.uz.dnum = 0; /* he might have been in another dgn */
- newlev = 1;
- }
- #ifdef POLYSELF
- else if(is_flyer(uasmon)) {
- You("fly down to earth.");
- u.uz.dnum = 0; /* he might have been in another dgn */
- newlev = 1;
- }
- #endif
- else {
- d_level save_dlevel;
-
- assign_level(&save_dlevel, &u.uz);
- pline("Unfortunately, you don't know how to fly.");
- You("plummet a few thousand feet to your death.");
- u.uz.dnum = 0;
- u.uz.dlevel = 0;
- killer_format = NO_KILLER_PREFIX;
- killer =
- self_pronoun("teleported out of the dungeon and fell to %s death","his");
- done(DIED);
- assign_level(&u.uz, &save_dlevel);
- flags.botl = 1;
- return;
- }
- }
-
- # ifdef WIZARD
- if (In_endgame(&u.uz)) { /* must already be wizard */
- newlevel.dnum = u.uz.dnum;
- newlevel.dlevel = newlev;
- goto_level(&newlevel, FALSE, FALSE, FALSE);
- return;
- }
- # endif
-
- /* calls done(ESCAPED) if newlevel==0 */
- if(u.uz.dnum == medusa_level.dnum &&
- newlev >= dungeons[u.uz.dnum].depth_start +
- dunlevs_in_dungeon(&u.uz)) {
-
- goto_hell(TRUE, FALSE);
- } else {
- /* if invocation did not yet occur, teleporting into
- * the last level of Gehennom is forbidden.
- */
- if(Inhell && !u.uevent.invoked &&
- newlev >= (dungeons[u.uz.dnum].depth_start +
- dunlevs_in_dungeon(&u.uz) - 1)) {
- newlev = dungeons[u.uz.dnum].depth_start +
- dunlevs_in_dungeon(&u.uz) - 2;
- pline("Sorry...");
- }
- #ifdef MULDGN
- /* no teleporting out of quest dungeon */
- if(In_quest(&u.uz) && newlev < depth(&qstart_level))
- newlev = depth(&qstart_level);
- #endif
- /* the player thinks of levels purely in logical terms, so
- * we must translate newlev to a number relative to the
- * current dungeon.
- */
- get_level(&newlevel, newlev);
- goto_level(&newlevel, FALSE, FALSE, FALSE);
- }
- }
-
- static void
- dofiretrap()
- {
-
- 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.");
- } else {
- num = rnd(6);
- u.uhpmax -= num;
- losehp(num,"burst of flame", KILLED_BY_AN);
- }
- destroy_item(SCROLL_CLASS, AD_FIRE);
- destroy_item(SPBOOK_CLASS, AD_FIRE);
- destroy_item(POTION_CLASS, AD_FIRE);
- }
-
- static void
- domagicportal(ttmp)
- register struct trap *ttmp;
- {
- struct d_level target_level;
-
- /* if landed from another portal, do nothing */
- /* problem: level teleport landing escapes the check */
- if(!on_level(&u.uz, &u.uz0)) return;
-
- You("activated a magic portal!");
- You("feel dizzy for a moment, but the sensation passes.");
-
- /* prevent the poor shnook, whose amulet was stolen */
- /* while in the endgame, from accidently triggering */
- /* the portal to the next level, and thus losing the */
- /* game */
- if(In_endgame(&u.uz) && !u.uhave.amulet) return;
-
- target_level = ttmp->dst;
- goto_level(&target_level, FALSE, FALSE, TRUE);
- }
-
- static 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 */
- dofiretrap();
- 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;
- register struct monst *mtmp;
-
- /* below pline added by GAN 10/30/86 */
- (void) adjattrib(A_CHA,1,FALSE);
- for(i = -1; i <= 1; i++) for(j = -1; j <= 1; j++) {
- if(!isok(u.ux+i, u.uy+j)) continue;
- mtmp = m_at(u.ux+i, u.uy+j);
- if(mtmp)
- (void) tamedog(mtmp, (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)
- uncurse(obj);
- if(Punished) unpunish();
- break;
- }
- default: break;
- }
- }
-
- void
- water_damage(obj,force)
- register struct obj *obj;
- register boolean force;
- {
- /* Scrolls, spellbooks, potions, weapons and
- pieces of armor may get affected by the water */
- for(; obj; obj = obj->nobj) {
-
- (void) snuff_lit(obj);
-
- if(obj->greased) {
- if (force || !rn2(2)) obj->greased = 0;
- } else if(Is_container(obj) && !Is_box(obj) &&
- (obj->otyp != OILSKIN_SACK || (obj->cursed && !rn2(3)))) {
- water_damage(obj->cobj,force);
- } else if(obj->oclass == SCROLL_CLASS && (force || rn2(12) > Luck)
- #ifdef MAIL
- && obj->otyp != SCR_MAIL
- #endif
- ) {
- obj->otyp = SCR_BLANK_PAPER;
- } else if(obj->oclass == SPBOOK_CLASS && (force || rn2(12) > Luck)) {
- if (obj->otyp == SPE_BOOK_OF_THE_DEAD)
- pline("Steam rises from %s.", the(xname(obj)));
- else obj->otyp = SPE_BLANK_PAPER;
- } else if(obj->oclass == POTION_CLASS && (force || rn2(12) > Luck)) {
- if (obj->spe == -1) {
- obj->otyp = POT_WATER;
- obj->blessed = obj->cursed = 0;
- obj->spe = 0;
- } else obj->spe--;
- } else if(is_rustprone(obj) && obj->oeroded < MAX_ERODE &&
- !(obj->oerodeproof || (obj->blessed && !rnl(4))) &&
- (force || rn2(12) > Luck)) {
- /* all metal stuff and armor except body armor
- protected by oilskin cloak */
- if(obj->oclass != ARMOR_CLASS || obj != uarm ||
- !uarmc || uarmc->otyp != OILSKIN_CLOAK ||
- (uarmc->cursed && !rn2(3)))
- obj->oeroded++;
- }
- }
- }
-
- /*
- * This function is potentially expensive - rolling
- * inventory list multiple times. Luckily it's seldom needed.
- * Returns TRUE if disrobing made player unencumbered enough to
- * crawl out of the current predicament.
- */
- static boolean
- emergency_disrobe(lostsome)
- boolean *lostsome;
- {
- int invc = inv_cnt();
-
- while (near_capacity() > (Punished ? UNENCUMBERED : SLT_ENCUMBER)) {
- register struct obj *obj, *otmp = (struct obj *)0;
- register int i = rn2(invc);
-
- for (obj = invent; obj; obj = obj->nobj) {
- /*
- * Undroppables are: body armor, boots, gloves,
- * amulets, and rings because of the time and effort
- * in removing them + loadstone and other cursed stuff
- * for obvious reasons.
- */
- if (!(obj->otyp == LOADSTONE ||
- obj == uamul || obj == uleft || obj == uright ||
- obj == ublindf || obj == uarm || obj == uarmc ||
- obj == uarmg || obj == uarmf ||
- #ifdef TOURIST
- obj == uarmu ||
- #endif
- (obj->cursed && (obj == uarmh || obj == uarms)) ||
- welded(obj)))
- otmp = obj;
- /* reached the mark and found some stuff to drop? */
- if (--i < 0 && otmp) break;
-
- /* else continue */
- }
-
- /* nothing to drop and still overweight */
- if (!otmp) return(FALSE);
-
- if (otmp == uarmh) (void) Helmet_off();
- else if (otmp == uarms) (void) Shield_off();
- else if (otmp == uwep) setuwep((struct obj *)0);
- *lostsome = TRUE;
- dropx(otmp);
- invc--;
- }
- return(TRUE);
- }
-
- /*
- * return(TRUE) == player relocated
- */
- boolean
- drown()
- {
- boolean inpool_ok = FALSE, crawl_ok;
- int i, x, y;
-
- /* happily wading in the same contiguous pool */
- if (u.uinwater && is_pool(u.ux-u.dx,u.uy-u.dy) &&
- Magical_breathing) {
- /* water effects on objects every now and then */
- if (!rn2(5)) inpool_ok = TRUE;
- else return(FALSE);
- }
-
- if (!u.uinwater) {
- You("%s into the water!",
- Is_waterlevel(&u.uz) ? "plunge" : "fall");
- #ifdef POLYSELF
- if(!is_swimmer(uasmon))
- #endif
- if (!Is_waterlevel(&u.uz))
- You("sink like %s.",
- Hallucination ? "the Titanic" : "a rock");
- }
-
- water_damage(invent,FALSE);
-
- #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(FALSE);
- #endif
- if (inpool_ok) return(FALSE);
- #ifdef WALKIES
- if ((i = number_leashed()) > 0) {
- pline("The leash%s slip%s loose.",
- (i > 1) ? "es" : "",
- (i > 1) ? "" : "s");
- unleash_all();
- }
- #endif
- if (Magical_breathing) {
- pline("But wait!");
- Your("lungs start acting like gills.");
- if (!Is_waterlevel(&u.uz))
- Your("%s the bottom.",Hallucination ? "keel hits" : "feet touch");
- if (Punished) placebc();
- u.uinwater = 1;
- under_water(1);
- return(FALSE);
- }
- if((Teleportation || can_teleport(uasmon)) &&
- (Teleport_control || rn2(3) < Luck+2)) {
- You("attempt a teleport spell."); /* utcsri!carroll */
- (void) dotele();
- if(!is_pool(u.ux,u.uy))
- return(TRUE);
- }
- crawl_ok = FALSE;
- /* look around for a place to crawl to */
- for (i = 0; i < 100; i++) {
- x = rn1(3,u.ux - 1);
- y = rn1(3,u.uy - 1);
- if (teleok(x,y,TRUE)) {
- crawl_ok = TRUE;
- goto crawl;
- }
- }
- /* one more scan */
- for (x = u.ux - 1; x <= u.ux + 1; x++)
- for (y = u.uy - 1; y <= u.uy + 1; y++)
- if (teleok(x,y,TRUE)) {
- crawl_ok = TRUE;
- goto crawl;
- }
- crawl:;
- if (crawl_ok) {
- boolean lost = FALSE;
- /* time to do some strip-tease... */
- boolean succ = Is_waterlevel(&u.uz) ? TRUE :
- emergency_disrobe(&lost);
-
- You("try to crawl out of the water.");
- if (lost)
- You("dump some of your gear to lose weight...");
- if (succ) {
- pline("Pheew! That was close.");
- teleds(x,y);
- return(TRUE);
- }
- /* still too much weight */
- pline("But in vain.");
- }
- u.uinwater = 1;
- You("drown.");
- killer_format = KILLED_BY_AN;
- killer = (levl[u.ux][u.uy].typ == POOL || Is_medusa_level(&u.uz)) ?
- "pool of water" : "moat";
- done(DROWNING);
- /* oops, we're still alive. better get out of the water. */
- if (!safe_teleds())
- while (1) {
- pline("You're still drowning.");
- done(DROWNING);
- }
- u.uinwater = 0;
- You("find yourself back %s.",Is_waterlevel(&u.uz) ?
- "in an air bubble" : "on dry land");
- return(TRUE);
- }
-
- 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;
- }
-
- int
- dountrap() /* disarm a trapped object */
- {
- #ifdef POLYSELF
- if(nohands(uasmon)) {
- pline("And just how do you expect to do that?");
- return(0);
- }
- #endif
- return untrap(FALSE);
- }
-
- int
- untrap(force)
- boolean force;
- {
- register struct obj *otmp;
- register boolean confused = (Confusion > 0 || Hallucination > 0);
- register int x,y;
- int ch;
- struct trap *ttmp;
- struct monst *mtmp;
- boolean trap_skipped = FALSE;
-
- if(!getdir(NULL)) 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.", doname(otmp));
-
- switch (ynq("Check for traps?")) {
- case 'q': return(0);
- case 'n': continue;
- }
-
- if((otmp->otrapped && (force || (!confused
- && rn2(MAXULEV + 1 - (int)u.ulevel) < 10)))
- || (!force && confused && !rn2(3))) {
- You("find a trap on %s!", the(xname(otmp)));
- exercise(A_WIS, TRUE);
-
- switch (ynq("Disarm it?")) {
- case 'q': return(1);
- case 'n': trap_skipped = TRUE; continue;
- }
-
- if(otmp->otrapped) {
- exercise(A_DEX, TRUE);
- ch = ACURR(A_DEX) + u.ulevel;
- if (pl_character[0] == 'R') ch *= 2;
- if(!force && (confused || Fumbling ||
- rnd(75+level_difficulty()/2) > ch)) {
- (void) chest_trap(otmp, FINGER, TRUE);
- } else {
- You("disarm it!");
- otmp->otrapped = 0;
- }
- } else pline("That %s was not trapped.", doname(otmp));
- return(1);
- } else {
- You("find no traps on %s.", the(xname(otmp)));
- return(1);
- }
- }
- if ((ttmp = t_at(x,y)) && ttmp->tseen)
- You("cannot disable this trap.");
- else
- You(trap_skipped ? "find no other traps here."
- : "know of no traps here.");
- return(0);
- }
-
- if ((mtmp = m_at(x,y)) &&
- mtmp->m_ap_type == M_AP_FURNITURE &&
- (mtmp->mappearance == S_hcdoor ||
- mtmp->mappearance == S_vcdoor) &&
- !Protection_from_shape_changers) {
-
- stumble_onto_mimic(mtmp);
- return(1);
- }
-
- 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
- && (force ||
- (!confused && rn2(MAXULEV - (int)u.ulevel + 11) < 10)))
- || (!force && confused && !rn2(3))) {
- You("find a trap on the door!");
- exercise(A_WIS, TRUE);
- if (ynq("Disarm it?") != 'y') return(1);
- if (levl[x][y].doormask & D_TRAPPED) {
- ch = 15 +
- (pl_character[0] == 'R') ? u.ulevel*3 :
- u.ulevel;
- exercise(A_DEX, TRUE);
- if(!force && (confused || Fumbling ||
- rnd(75+level_difficulty()/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 */
- boolean
- chest_trap(obj, bodypart, disarm)
- register struct obj *obj;
- register int bodypart;
- boolean disarm;
- {
- register struct obj *otmp = obj, *otmp2;
- char buf[80];
- const char *msg;
-
- You(disarm ? "set it off!" : "trigger a trap!");
- display_nhwindow(WIN_MESSAGE, FALSE);
- if (Luck > -13 && rn2(13+Luck) > 7) { /* saved by luck */
- /* trap went off, but good luck prevents damage */
- switch (rn2(13)) {
- case 12:
- case 11: msg = "explosive charge is a dud"; break;
- case 10:
- case 9: msg = "electric charge is grounded"; break;
- case 8:
- case 7: msg = "flame fizzles out"; break;
- case 6:
- case 5:
- case 4: msg = "poisoned needle misses"; break;
- case 3:
- case 2:
- case 1:
- case 0: msg = "gas cloud blows away"; break;
- default: impossible("chest disarm bug"); msg = NULL; break;
- }
- if (msg) pline("But luckily the %s!", msg);
- } else {
- switch(rn2(20) ? ((Luck >= 13) ? 0 : rn2(13-Luck)) : rn2(26)) {
- case 25:
- case 24:
- case 23:
- case 22:
- case 21: {
- register struct monst *shkp;
- long loss = 0L;
- boolean costly, insider;
- register xchar ox = obj->ox, oy = obj->oy;
-
- #ifdef GCC_WARN
- shkp = (struct monst *) 0;
- #endif
- /* the obj location need not be that of player */
- costly = (costly_spot(ox, oy) &&
- (shkp = shop_keeper(*in_rooms(ox, oy,
- SHOPBASE))) != (struct monst *)0);
- insider = (*u.ushops && inside_shop(u.ux, u.uy) &&
- *in_rooms(ox, oy, SHOPBASE) == *u.ushops);
-
- pline("%s explodes!", The(xname(obj)));
- Sprintf(buf, "exploding %s", xname(obj));
-
- if(costly)
- loss += stolen_value(obj, ox, oy,
- (boolean)shkp->mpeaceful, TRUE);
- delete_contents(obj);
- for(otmp = level.objects[u.ux][u.uy];
- otmp; otmp = otmp2) {
- otmp2 = otmp->nexthere;
- if(costly)
- loss += stolen_value(otmp, otmp->ox,
- otmp->oy, (boolean)shkp->mpeaceful,
- TRUE);
- delobj(otmp);
- }
- exercise(A_STR, FALSE);
- losehp(d(6,6), buf, KILLED_BY_AN);
- if(costly && loss) {
- if(insider)
- You("owe %ld zorkmids for objects destroyed.",
- loss);
- else {
- You("caused %ld zorkmids worth of damage!",
- loss);
- make_angry_shk(shkp, ox, oy);
- }
- }
- wake_nearby();
- return TRUE;
- }
- case 20:
- case 19:
- case 18:
- case 17:
- pline("A cloud of noxious gas billows from %s.",
- the(xname(obj)));
- poisoned("gas cloud", A_STR, "cloud of poison gas",15);
- exercise(A_CON, FALSE);
- 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);
- exercise(A_CON, FALSE);
- break;
- case 12:
- case 11:
- case 10:
- case 9:
- pline("A tower of flame erupts from %s!",
- the(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_CLASS, AD_FIRE);
- destroy_item(SPBOOK_CLASS, AD_FIRE);
- destroy_item(POTION_CLASS, 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_CLASS, AD_ELEC);
- destroy_item(WAND_CLASS, AD_ELEC);
- break;
- case 5:
- case 4:
- case 3:
- pline("Suddenly you are frozen in place!");
- nomul(-d(5, 6));
- exercise(A_DEX, FALSE);
- nomovemsg = "You can move again.";
- break;
- case 2:
- case 1:
- case 0:
- pline("A cloud of %s gas billows from %s",
- hcolor(), the(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(HHallucination + rn1(5, 16),FALSE,0L);
- break;
- default: impossible("bad chest trap");
- break;
- }
- bot(); /* to get immediate botl re-display */
- }
- otmp->otrapped = 0; /* these traps are one-shot things */
-
- return FALSE;
- }
-
- #endif /* OVLB */
- #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;
- }
- dealloc_trap(trap);
- }
-
- /* used for doors. can be used for anything else that opens. */
- void
- b_trapped(item)
- register const char *item;
- {
- register int lvl = level_difficulty();
- int dmg = rnd(5 + (lvl<5 ? lvl : 2+lvl/2));
-
- pline("KABOOM!! %s was booby-trapped!", The(item));
- if (u.ulevel < 4 && lvl < 3 && !rnl(3))
- You("are shaken, but luckily unhurt.");
- else losehp(dmg, "explosion", KILLED_BY_AN);
- exercise(A_STR, FALSE);
- make_stunned(HStun + dmg, TRUE);
- }
-
- /* Monster is hit by trap. */
- /* Note: doesn't work if both obj and d_override are null */
- STATIC_OVL 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 = (find_mac(mon) + tlev + obj->spe <= rnd(20));
- else strike = (find_mac(mon) + 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;
-
- monkilled(mon, "", AD_PHYS);
- 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) dealloc_obj(obj);
-
- return trapkilled;
- }
-
- boolean
- unconscious()
- {
- return (multi < 0 && (!nomovemsg ||
- u.usleep ||
- !strncmp(nomovemsg,"You regain con", 15) ||
- !strncmp(nomovemsg,"You are consci", 15)));
- }
-
- static char lava_killer[] = "molten lava";
-
- boolean
- lava_effects()
- {
- register struct obj *obj, *obj2;
- int dmg;
-
- if (!Fire_resistance) {
- if(Wwalking) {
- dmg = d(6,6);
- pline("The lava here burns you!");
- if(dmg < u.uhp) {
- losehp(dmg, lava_killer, KILLED_BY);
- goto burn_stuff;
- }
- } else
- You("fall into the lava!");
-
- for(obj = invent; obj; obj = obj2) {
- obj2 = obj->nobj;
- if(is_organic(obj) && !obj->oerodeproof) {
- if(obj->owornmask) {
- if(obj == uarm) (void) Armor_gone();
- else if(obj == uarmc) (void) Cloak_off();
- else if(obj == uarmh) (void) Helmet_off();
- else if(obj == uarms) (void) Shield_off();
- else if(obj == uarmg) (void) Gloves_off();
- else if(obj == uarmf) (void) Boots_off();
- #ifdef TOURIST
- else if(obj == uarmu) setnotworn(obj);
- #endif
- else if(obj == uleft) Ring_gone(obj);
- else if(obj == uright) Ring_gone(obj);
- else if(obj == ublindf) Blindf_off(obj);
- else if(obj == uwep) uwepgone();
- if(Lifesaved
- #ifdef WIZARD
- || wizard
- #endif
- ) Your("%s into flame!", aobjnam(obj, "burst"));
- }
- useup(obj);
- }
- }
-
- /* s/he died... */
- u.uhp = -1;
- killer_format = KILLED_BY;
- killer = lava_killer;
- You("burn to a crisp...");
- done(BURNING);
- if (!safe_teleds())
- while (1) {
- pline("You're still burning.");
- done(BURNING);
- }
- You("find yourself back on solid ground.");
- return(TRUE);
- }
-
- if (!Wwalking) {
- u.utrap = rn1(4, 4) + (rn1(4, 12) << 8);
- u.utraptype = TT_LAVA;
- You("sink into the lava, but it doesn't burn you!");
- }
- /* just want to burn boots, not all armor; destroy_item doesn't work on
- armor anyway */
- burn_stuff:
- if(uarmf && !uarmf->oerodeproof && is_organic(uarmf)) {
- /* save uarmf value because Boots_off() sets uarmf to NULL */
- obj = uarmf;
- Your("%s burst into flame!", xname(obj));
- (void) Boots_off();
- useup(obj);
- }
- destroy_item(SCROLL_CLASS, AD_FIRE);
- destroy_item(SPBOOK_CLASS, AD_FIRE);
- destroy_item(POTION_CLASS, AD_FIRE);
- return(FALSE);
- }
-
- #endif /* OVLB */
-
- /*trap.c*/
-