Wikihack
Advertisement

Below is the full text to trap.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.0/trap.c#line123]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

The NetHack General Public License applies to screenshots, source code and other content from NetHack.
1.    /*	SCCS Id: @(#)trap.c	3.2	96/04/08	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    #include "hack.h"
6.    
7.    STATIC_DCL void FDECL(dofiretrap, (struct obj *));
8.    STATIC_DCL void NDECL(domagictrap);
9.    STATIC_DCL boolean FDECL(emergency_disrobe,(boolean *));
10.   STATIC_DCL int FDECL(untrap_prob, (struct trap *ttmp));
11.   STATIC_DCL void FDECL(cnv_trap_obj, (int, int, struct trap *));
12.   STATIC_DCL void FDECL(move_into_trap, (struct trap *));
13.   STATIC_DCL int FDECL(try_disarm, (struct trap *,BOOLEAN_P));
14.   STATIC_DCL void FDECL(reward_untrap, (struct trap *, struct monst *));
15.   STATIC_DCL int FDECL(disarm_beartrap, (struct trap *));
16.   STATIC_DCL int FDECL(disarm_landmine, (struct trap *));
17.   STATIC_DCL int FDECL(disarm_squeaky_board, (struct trap *));
18.   STATIC_DCL int FDECL(disarm_shooting_trap, (struct trap *, int));
19.   STATIC_DCL int FDECL(try_lift, (struct monst *, struct trap *, int, BOOLEAN_P));
20.   STATIC_DCL int FDECL(help_monster_out, (struct monst *, struct trap *));
21.   STATIC_DCL boolean FDECL(thitm, (int, struct monst *, struct obj *, int));
22.   STATIC_DCL int FDECL(mkroll_launch,
23.   			(struct trap *,XCHAR_P,XCHAR_P,SHORT_P,long));
24.   STATIC_DCL boolean FDECL(isclearpath,(coord *, int, SCHAR_P, SCHAR_P));
25.   
26.   #ifndef OVLB
27.   STATIC_VAR const char *a_your[2];
28.   STATIC_VAR const char *A_Your[2];
29.   STATIC_VAR const char *the_your[2];
30.   STATIC_VAR const char tower_of_flame[];
31.   STATIC_VAR const char *A_gush_of_water_hits;
32.   
33.   #else
34.   
35.   STATIC_VAR const char *a_your[2] = { "a", "your" };
36.   STATIC_VAR const char *A_Your[2] = { "A", "Your" };
37.   STATIC_VAR const char *the_your[2] = { "the", "your" };
38.   STATIC_VAR const char tower_of_flame[] = "tower of flame";
39.   STATIC_VAR const char *A_gush_of_water_hits = "A gush of water hits";
40.   
41.   #endif /* OVLB */
42.   
43.   #ifdef OVLB
44.   
45.   /* called when you're hit by fire (dofiretrap,buzz,zapyourself,explode) */
46.   boolean			/* returns TRUE if hit on torso */
47.   burnarmor()
48.   {
49.   #define burn_dmg(obj,descr) rust_dmg(obj, descr, 0, FALSE)
50.       while (1) {
51.   	switch (rn2(5)) {
52.   	case 0:
53.   	    if (!burn_dmg(uarmh, "leather helmet")) continue;
54.   	    break;
55.   	case 1:
56.   	    if (uarmc)
57.   		(void) burn_dmg(uarmc, "cloak");
58.   	    else if (uarm)
59.   		(void) burn_dmg(uarm, xname(uarm));
60.   #ifdef TOURIST
61.   	    else if (uarmu)
62.   		(void) burn_dmg(uarmu, "shirt");
63.   #endif
64.   	    return TRUE;
65.   	case 2:
66.   	    if (!burn_dmg(uarms, "wooden shield")) continue;
67.   	    break;
68.   	case 3:
69.   	    if (!burn_dmg(uarmg, "gloves")) continue;
70.   	    break;
71.   	case 4:
72.   	    if (!burn_dmg(uarmf, "boots")) continue;
73.   	    break;
74.   	}
75.   	break; /* Out of while loop */
76.       }
77.       return FALSE;
78.   #undef burn_dmg
79.   }
80.   
81.   /* Generic rust-armor function.  Returns TRUE if a message was printed;
82.    * "print", if set, means to print a message (and thus to return TRUE) even
83.    * if the item could not be rusted; otherwise a message is printed and TRUE is
84.    * returned only for rustable items.
85.    */
86.   boolean
87.   rust_dmg(otmp, ostr, type, print)
88.   register struct obj *otmp;
89.   register const char *ostr;
90.   int type;
91.   boolean print;
92.   {
93.   	static NEARDATA const char *action[] = { "smoulder", "rust", "rot", "corrode" };
94.   	static NEARDATA const char *msg[] =  { "burnt", "rusted", "rotten", "corroded" };
95.   	boolean vulnerable = FALSE;
96.   	boolean plural;
97.   	boolean grprot = FALSE;
98.   
99.   	if (!otmp) return(FALSE);
100.  	switch(type) {
101.  		case 0:
102.  		case 2: vulnerable = is_flammable(otmp); break;
103.  		case 1: vulnerable = is_rustprone(otmp); grprot = TRUE; break;
104.  		case 3: vulnerable = is_corrodeable(otmp); grprot = TRUE; break;
105.  	}
106.  
107.  	if (!print && (!vulnerable || otmp->oerodeproof || otmp->oeroded == MAX_ERODE))
108.  		return FALSE;
109.  
110.  	plural = is_gloves(otmp) || is_boots(otmp);
111.  
112.  	if (!vulnerable) {
113.  		if (flags.verbose)
114.  		    Your("%s %s not affected.", ostr, plural ? "are" : "is");
115.  	} else if (otmp->oeroded < MAX_ERODE) {
116.  		if (grprot && otmp->greased) {
117.  			grease_protect(otmp,ostr,plural);
118.  		} else if (otmp->oerodeproof || (otmp->blessed && !rnl(4))) {
119.  			if (flags.verbose)
120.  				pline("Somehow, your %s %s not affected.",
121.  					ostr, plural ? "are" : "is");
122.  		} else {
123.  			Your("%s %s%s%s!", ostr, action[type],
124.  				plural ? "" : "s",
125.  				otmp->oeroded+1 == MAX_ERODE ? " completely" :
126.  				otmp->oeroded ? " further" : "");
127.  			otmp->oeroded++;
128.  		}
129.  	} else {
130.  		if (flags.verbose)
131.  			Your("%s %s%s completely %s.", ostr,
132.  			     Blind ? "feel" : "look",
133.  			     plural ? "" : "s", msg[type]);
134.  	}
135.  	return(TRUE);
136.  }
137.  
138.  void
139.  grease_protect(otmp,ostr,plu)
140.  register struct obj *otmp;
141.  register const char *ostr;
142.  register boolean plu;
143.  {
144.  	static const char txt[] = "protected by the layer of grease!";
145.  
146.  	if (ostr)
147.  		Your("%s %s %s",ostr,plu ? "are" : "is",txt);
148.  	else
149.  		Your("%s %s",aobjnam(otmp,"are"),txt);
150.  	if (!rn2(2)) {
151.  		pline_The("grease dissolves.");
152.  		otmp->greased = 0;
153.  	}
154.  }
155.  
156.  struct trap *
157.  maketrap(x,y,typ)
158.  register int x, y, typ;
159.  {
160.  	register struct trap *ttmp;
161.  	register struct rm *lev;
162.  	register boolean oldplace;
163.  
164.  	if ((ttmp = t_at(x,y)) != 0) {
165.  	    if (ttmp->ttyp == MAGIC_PORTAL) return (struct trap *)0;
166.  	    oldplace = TRUE;
167.  	    if (u.utrap && (x == u.ux) && (y == u.uy) &&
168.  	      ((u.utraptype == TT_BEARTRAP && typ != BEAR_TRAP) ||
169.  	      (u.utraptype == TT_WEB && typ != WEB) ||
170.  	      (u.utraptype == TT_PIT && typ != PIT && typ != SPIKED_PIT)))
171.  		    u.utrap = 0;
172.  	} else {
173.  	    oldplace = FALSE;
174.  	    ttmp = newtrap();
175.  	    ttmp->tx = x;
176.  	    ttmp->ty = y;
177.  	    ttmp->launch.x = -1;	/* force error if used before set */
178.  	    ttmp->launch.y = -1;
179.  	}
180.  	ttmp->ttyp = typ;
181.  	switch(typ) {
182.  	    case STATUE_TRAP:	    /* create a "living" statue */
183.  		(void) mkcorpstat(STATUE, &mons[rndmonnum()], x, y, FALSE);
184.  		break;
185.  	    case ROLLING_BOULDER_TRAP:	/* boulder will roll towards trigger */
186.  		(void) mkroll_launch(ttmp, x, y, BOULDER, 1L);
187.  		break;
188.  	    case HOLE:
189.  	    case PIT:
190.  	    case SPIKED_PIT:
191.  	    case TRAPDOOR:
192.  		lev = &levl[x][y];
193.  		if (*in_rooms(x, y, SHOPBASE) &&
194.  			((typ == HOLE || typ == TRAPDOOR) || IS_DOOR(lev->typ)))
195.  		    add_damage(x, y,		/* schedule repair */
196.  			(IS_DOOR(lev->typ) && !flags.mon_moving) ? 200L : 0L);
197.  		lev->doormask = 0;	/* subsumes altarmask, icedpool... */
198.  		if (IS_ROOM(lev->typ)) /* && !IS_AIR(lev->typ) */
199.  		    lev->typ = ROOM;
200.  
201.  		/*
202.  		 * some cases which can happen when digging
203.  		 * down while phazing thru solid areas
204.  		 */
205.  		else if (lev->typ == STONE || lev->typ == SCORR)
206.  		    lev->typ = CORR;
207.  		else if (IS_WALL(lev->typ) || lev->typ == SDOOR)
208.  		    lev->typ = level.flags.is_maze_lev ? ROOM :
209.  			       level.flags.is_cavernous_lev ? CORR : DOOR;
210.  
211.  		unearth_objs(x, y);
212.  		break;
213.  	}
214.  	if (ttmp->ttyp == HOLE) ttmp->tseen = 1;  /* You can't hide a hole */
215.  	else ttmp->tseen = 0;
216.  	ttmp->once = 0;
217.  	ttmp->madeby_u = 0;
218.  	ttmp->dst.dnum = -1;
219.  	ttmp->dst.dlevel = -1;
220.  	if (!oldplace) {
221.  	    ttmp->ntrap = ftrap;
222.  	    ftrap = ttmp;
223.  	}
224.  	return(ttmp);
225.  }
226.  
227.  void
228.  fall_through(td)
229.  boolean td;	/* td == TRUE : trapdoor or hole */
230.  {
231.  	d_level dtmp;
232.  	char msgbuf[BUFSZ];
233.  	const char *dont_fall = 0;
234.  	register int newlevel = dunlev(&u.uz);
235.  
236.  	if(Blind && Levitation) return;
237.  
238.  	do {
239.  	    newlevel++;
240.  	} while(!rn2(4) && newlevel < dunlevs_in_dungeon(&u.uz));
241.  
242.  	if(td) {
243.  		struct trap *t=t_at(u.ux,u.uy);
244.  		if (t->ttyp == TRAPDOOR)
245.  			pline("A trap door opens up under you!");
246.  		else
247.  			pline("There's a gaping hole under you!");
248.  	} else pline_The("%s opens up under you!", surface(u.ux,u.uy));
249.  
250.  	if(Levitation || u.ustuck || !Can_fall_thru(&u.uz)
251.  	   || is_flyer(uasmon) || is_clinger(uasmon)
252.  	   || (Inhell && !u.uevent.invoked &&
253.  					newlevel == dunlevs_in_dungeon(&u.uz))
254.  		) {
255.  	    dont_fall = "don't fall in.";
256.  	} else if (uasmon->msize >= MZ_HUGE) {
257.  	    dont_fall = "don't fit through.";
258.  	} else if (!next_to_u()) {
259.  	    dont_fall = "are jerked back by your pet!";
260.  	}
261.  	if (dont_fall) {
262.  	    You(dont_fall);
263.  	    /* hero didn't fall through, but any objects here might */
264.  	    impact_drop((struct obj *)0, u.ux, u.uy, 0);
265.  	    if (!td) {
266.  		display_nhwindow(WIN_MESSAGE, FALSE);
267.  		pline_The("opening under you closes up.");
268.  	    }
269.  	    return;
270.  	}
271.  
272.  	if(*u.ushops) shopdig(1);
273.  	if (Is_stronghold(&u.uz)) {
274.  	    find_hell(&dtmp);
275.  	} else {
276.  	    dtmp.dnum = u.uz.dnum;
277.  	    dtmp.dlevel = newlevel;
278.  	}
279.  	if (!td)
280.  	    Sprintf(msgbuf, "The hole in the %s above you closes up.",
281.  		    ceiling(u.ux,u.uy));
282.  	schedule_goto(&dtmp, FALSE, TRUE, 0,
283.  		      (char *)0, !td ? msgbuf : (char *)0);
284.  }
285.  
286.  /* you've either stepped onto a statue trap's location
287.     or you've triggered a statue trap by searching next to it */
288.  void
289.  activate_statue_trap(trap, x, y)
290.  struct trap *trap;
291.  xchar x, y;
292.  {
293.  	struct monst *mtmp;
294.  	struct obj *otmp = sobj_at(STATUE, x, y);
295.  
296.  	deltrap(trap);
297.  	if (otmp && (mtmp = makemon(&mons[otmp->corpsenm], x, y)) != 0) {
298.  	    delobj(otmp);
299.  	    /* mimic statue becomes seen mimic; other hiders won't be hidden */
300.  	    if (mtmp->m_ap_type) seemimic(mtmp);
301.  	    else mtmp->mundetected = FALSE;
302.  	    if (x == u.ux && y == u.uy)
303.  		pline_The("statue comes to life!");
304.  	    else
305.  		You("find %s posing as a statue.", a_monnam(mtmp));
306.  	    /* avoid hiding under nothing */
307.  	    if (x == u.ux && y == u.uy &&
308.  		    Upolyd && hides_under(uasmon) && !OBJ_AT(x, y))
309.  		u.uundetected = 0;
310.  	}
311.  	if (Blind) feel_location(x, y);
312.  	else newsym(x, y);
313.  }
314.  
315.  void
316.  dotrap(trap)
317.  register struct trap *trap;
318.  {
319.  	register int ttype = trap->ttyp;
320.  	register struct monst *mtmp;
321.  	register struct obj *otmp;
322.  	boolean already_seen = trap->tseen;
323.  
324.  	nomul(0);
325.  	if(already_seen) {
326.  	    if ((Levitation || is_flyer(uasmon)) &&
327.  		    (ttype == PIT || ttype == SPIKED_PIT || ttype == HOLE ||
328.  		    ttype == BEAR_TRAP)) {
329.  		You("%s over %s %s.",
330.  		    Levitation ? "float" : "fly",
331.  		    a_your[trap->madeby_u],
332.  		    defsyms[trap_to_defsym(ttype)].explanation);
333.  		return;
334.  	    }
335.  	    if(!Fumbling && ttype != MAGIC_PORTAL && ttype != ANTI_MAGIC &&
336.  		(!rn2(5) ||
337.  	    ((ttype == PIT || ttype == SPIKED_PIT) && is_clinger(uasmon)))) {
338.  		You("escape %s %s.",
339.  		    (ttype == ARROW_TRAP && !trap->madeby_u) ? "an" :
340.  			a_your[trap->madeby_u],
341.  		    defsyms[trap_to_defsym(ttype)].explanation);
342.  		return;
343.  	    }
344.  	}
345.  		
346.  	switch(ttype) {
347.  	    case ARROW_TRAP:
348.  		seetrap(trap);
349.  		pline("An arrow shoots out at you!");
350.  		otmp = mksobj(ARROW, TRUE, FALSE);
351.  		otmp->quan = 1L;
352.  		otmp->owt = weight(otmp);
353.  		if (thitu(8, dmgval(otmp, &youmonst), otmp, "arrow")) {
354.  		    obfree(otmp, (struct obj *)0);
355.  		} else {
356.  		    place_object(otmp, u.ux, u.uy);
357.  		    if (!Blind) otmp->dknown = 1;
358.  		    stackobj(otmp);
359.  		    newsym(u.ux, u.uy);
360.  		}
361.  		break;
362.  	    case DART_TRAP:
363.  		seetrap(trap);
364.  		pline("A little dart shoots out at you!");
365.  		otmp = mksobj(DART, TRUE, FALSE);
366.  		otmp->quan = 1L;
367.  		otmp->owt = weight(otmp);
368.  		if (!rn2(6)) otmp->opoisoned = 1;
369.  		if (thitu(7, dmgval(otmp, &youmonst), otmp, "little dart")) {
370.  		    if (otmp->opoisoned)
371.  			poisoned("dart",A_CON,"poison dart",10);
372.  		    obfree(otmp, (struct obj *)0);
373.  		} else {
374.  		    place_object(otmp, u.ux, u.uy);
375.  		    if (!Blind) otmp->dknown = 1;
376.  		    stackobj(otmp);
377.  		    newsym(u.ux, u.uy);
378.  		}
379.  		break;
380.  	    case ROCKTRAP:
381.  		{
382.  		    int dmg = d(2,6); /* should be std ROCK dmg? */
383.  
384.  		    seetrap(trap);
385.  		    otmp = mksobj_at(ROCK, u.ux, u.uy, TRUE);
386.  		    otmp->quan = 1L;
387.  		    otmp->owt = weight(otmp);
388.  
389.      pline("A trap door in the %s opens and a rock falls on your %s!",
390.  			    ceiling(u.ux,u.uy),
391.  			    body_part(HEAD));
392.  
393.  		    if (uarmh) {
394.  			if(is_metallic(uarmh)) {
395.  			    pline("Fortunately, you are wearing a hard helmet.");
396.  			    dmg = 2;
397.  			} else if (flags.verbose) {
398.  			    Your("%s does not protect you.", xname(uarmh));
399.  			}
400.  		    }
401.  
402.  		    if (!Blind) otmp->dknown = 1;
403.  		    stackobj(otmp);
404.  		    newsym(u.ux,u.uy);	/* map the rock */
405.  
406.  		    losehp(dmg, "falling rock", KILLED_BY_AN);
407.  		    exercise(A_STR, FALSE);
408.  		}
409.  		break;
410.  
411.  	    case SQKY_BOARD:	    /* stepped on a squeaky board */
412.  		if (Levitation || is_flyer(uasmon)) {
413.  		    if (!Blind) {
414.  			seetrap(trap);
415.  			if (Hallucination)
416.  				You("notice a crease in the linoleum.");
417.  			else
418.  				You("notice a loose board below you.");
419.  		    }
420.  		} else {
421.  		    seetrap(trap);
422.  		    pline("A board beneath you squeaks loudly.");
423.  		    wake_nearby();
424.  		}
425.  		break;
426.  
427.  	    case BEAR_TRAP:
428.  		if(Levitation || is_flyer(uasmon)) break;
429.  		seetrap(trap);
430.  		if(amorphous(uasmon) || is_whirly(uasmon) ||
431.  						    unsolid(uasmon)) {
432.  		    pline("%s bear trap closes harmlessly through you.",
433.  			    A_Your[trap->madeby_u]);
434.  		    break;
435.  		}
436.  		if(uasmon->msize <= MZ_SMALL) {
437.  		    pline("%s bear trap closes harmlessly over you.",
438.  			    A_Your[trap->madeby_u]);
439.  		    break;
440.  		}
441.  		u.utrap = rn1(4, 4);
442.  		u.utraptype = TT_BEARTRAP;
443.  		pline("%s bear trap closes on your %s!",
444.  			    A_Your[trap->madeby_u], body_part(FOOT));
445.  		if(u.umonnum == PM_OWLBEAR || u.umonnum == PM_BUGBEAR)
446.  		    You("howl in anger!");
447.  		exercise(A_DEX, FALSE);
448.  		break;
449.  
450.  	    case SLP_GAS_TRAP:
451.  		seetrap(trap);
452.  		if(Sleep_resistance) {
453.  		    You("are enveloped in a cloud of gas!");
454.  		    break;
455.  		}
456.  		pline("A cloud of gas puts you to sleep!");
457.  		flags.soundok = 0;
458.  		fall_asleep(-rnd(25), TRUE);
459.  		afternmv = Hear_again;
460.  		break;
461.  
462.  	    case RUST_TRAP:
463.  		seetrap(trap);
464.  		if (u.umonnum == PM_IRON_GOLEM) {
465.  		    pline("%s you!", A_gush_of_water_hits);
466.  		    You("are covered with rust!");
467.  		    rehumanize();
468.  		    break;
469.  		} else if (u.umonnum == PM_GREMLIN && rn2(3)) {
470.  		    pline("%s you!", A_gush_of_water_hits);
471.  		    if ((mtmp = cloneu()) != 0) {
472.  			mtmp->mhpmax = (u.mhmax /= 2);
473.  			You("multiply.");
474.  		    }
475.  		    break;
476.  		}
477.  
478.  	    /* Unlike monsters, traps cannot aim their rust attacks at
479.  	     * you, so instead of looping through and taking either the
480.  	     * first rustable one or the body, we take whatever we get,
481.  	     * even if it is not rustable.
482.  	     */
483.  		switch (rn2(5)) {
484.  		    case 0:
485.  			pline("%s you on the %s!", A_gush_of_water_hits,
486.  				    body_part(HEAD));
487.  			(void) rust_dmg(uarmh, "helmet", 1, TRUE);
488.  			break;
489.  		    case 1:
490.  			pline("%s your left %s!", A_gush_of_water_hits,
491.  				    body_part(ARM));
492.  			if (rust_dmg(uarms, "shield", 1, TRUE)) break;
493.  			if (uwep && bimanual(uwep))
494.  			    goto two_hand;
495.  			/* Two goto statements in a row--aaarrrgggh! */
496.  glovecheck:		    (void) rust_dmg(uarmg, "gauntlets", 1, TRUE);
497.  			/* Not "metal gauntlets" since it gets called
498.  			 * even if it's leather for the message
499.  			 */
500.  			break;
501.  		    case 2:
502.  			pline("%s your right %s!", A_gush_of_water_hits,
503.  				    body_part(ARM));
504.  two_hand:		    erode_weapon(FALSE);
505.  			goto glovecheck;
506.  		    default:
507.  			pline("%s you!", A_gush_of_water_hits);
508.  			for (otmp=invent; otmp; otmp = otmp->nobj)
509.  				    (void) snuff_lit(otmp);
510.  			if (uarmc) (void) rust_dmg(uarmc, "cloak", 1, TRUE);
511.  			else if (uarm)
512.  			    (void) rust_dmg(uarm, "armor", 1, TRUE);
513.  #ifdef TOURIST
514.  			else if (uarmu)
515.  			    (void) rust_dmg(uarmu, "shirt", 1, TRUE);
516.  #endif
517.  		}
518.  		break;
519.  
520.  	    case FIRE_TRAP:
521.  		seetrap(trap);
522.  		dofiretrap((struct obj *)0);
523.  		break;
524.  
525.  	    case PIT:
526.  	    case SPIKED_PIT:
527.  		if (Levitation || is_flyer(uasmon)) break;
528.  		seetrap(trap);
529.  		if (is_clinger(uasmon)) {
530.  		    if(trap->tseen) {
531.  			You("see %s %spit below you.", a_your[trap->madeby_u],
532.  			    ttype == SPIKED_PIT ? "spiked " : "");
533.  		    } else {
534.  			pline("%s pit %sopens up under you!",
535.  			    A_Your[trap->madeby_u],
536.  			    ttype == SPIKED_PIT ? "full of spikes " : "");
537.  			You("don't fall in!");
538.  		    }
539.  		    break;
540.  		}
541.  		You("fall into %s pit!", a_your[trap->madeby_u]);
542.  		if (ttype == SPIKED_PIT)
543.  		    You("land on a set of sharp iron spikes!");
544.  		if (!passes_walls(uasmon))
545.  		    u.utrap = rn1(6,2);
546.  		u.utraptype = TT_PIT;
547.  		if (ttype == SPIKED_PIT) {
548.  		    losehp(rnd(10),"fell into a pit of iron spikes",
549.  			NO_KILLER_PREFIX);
550.  		    if (!rn2(6))
551.  			poisoned("spikes", A_STR, "fall onto poison spikes", 8);
552.  		} else
553.  		    losehp(rnd(6),"fell into a pit", NO_KILLER_PREFIX);
554.  		if (Punished && !carried(uball)) {
555.  		    unplacebc();
556.  		    ballfall();
557.  		    placebc();
558.  		}
559.  		selftouch("Falling, you");
560.  		vision_full_recalc = 1;	/* vision limits change */
561.  		exercise(A_STR, FALSE);
562.  		exercise(A_DEX, FALSE);
563.  		break;
564.  	    case HOLE:
565.  	    case TRAPDOOR:
566.  		seetrap(trap);
567.  		if(!Can_fall_thru(&u.uz))
568.  		    panic("Holes & trapdoors cannot exist on this level.");
569.  		fall_through(TRUE);
570.  		break;
571.  
572.  	    case TELEP_TRAP:
573.  		seetrap(trap);
574.  		tele_trap(trap);
575.  		break;
576.  	    case LEVEL_TELEP:
577.  		seetrap(trap);
578.  		level_tele_trap(trap);
579.  		break;
580.  
581.  	    case WEB: /* Our luckless player has stumbled into a web. */
582.  		seetrap(trap);
583.  		if (amorphous(uasmon) || is_whirly(uasmon) ||
584.  						    unsolid(uasmon)) {
585.  		    if (acidic(uasmon) || u.umonnum == PM_GELATINOUS_CUBE ||
586.  			u.umonnum == PM_FIRE_ELEMENTAL) {
587.  			You("%s %s spider web!",
588.  			    (u.umonnum == PM_FIRE_ELEMENTAL) ? "burn" : "dissolve",
589.  			    a_your[trap->madeby_u]);
590.  			deltrap(trap);
591.  			newsym(u.ux,u.uy);
592.  			break;
593.  		    }
594.  		    You("flow through %s spider web.",
595.  			    a_your[trap->madeby_u]);
596.  		    break;
597.  		}
598.  		if (uasmon->mlet == S_SPIDER) {
599.  		    pline(trap->madeby_u ? "You take a walk on your web."
600.  					 : "There is a spider web here.");
601.  		    break;
602.  		}
603.  		You("%s into %s spider web!",
604.  		      Levitation ? (const char *)"float" :
605.  		      locomotion(uasmon, "stumble"),
606.  		      a_your[trap->madeby_u]);
607.  		u.utraptype = TT_WEB;
608.  
609.  		/* Time stuck in the web depends on your strength. */
610.  		{
611.  		    register int str = ACURR(A_STR);
612.  
613.  		    if (str == 3) u.utrap = rn1(6,6);
614.  		    else if (str < 6) u.utrap = rn1(6,4);
615.  		    else if (str < 9) u.utrap = rn1(4,4);
616.  		    else if (str < 12) u.utrap = rn1(4,2);
617.  		    else if (str < 15) u.utrap = rn1(2,2);
618.  		    else if (str < 18) u.utrap = rnd(2);
619.  		    else if (str < 69) u.utrap = 1;
620.  		    else {
621.  			u.utrap = 0;
622.  			You("tear through %s web!", a_your[trap->madeby_u]);
623.  			deltrap(trap);
624.  			newsym(u.ux,u.uy);	/* get rid of trap symbol */
625.  		    }
626.  		}
627.  		break;
628.  
629.  	    case STATUE_TRAP:
630.  		activate_statue_trap(trap, u.ux, u.uy);
631.  		break;
632.  
633.  	    case MAGIC_TRAP:	    /* A magic trap. */
634.  		seetrap(trap);
635.  		if (!rn2(30)) {
636.  		    deltrap(trap);
637.  		    newsym(u.ux,u.uy);	/* update position */
638.  		    You("are caught in a magical explosion!");
639.  		    losehp(rnd(10), "magical explosion", KILLED_BY_AN);
640.  		    Your("body absorbs some of the magical energy!");
641.  		    u.uen = (u.uenmax += 2);
642.  		} else domagictrap();
643.  		break;
644.  
645.  	    case ANTI_MAGIC:
646.  		seetrap(trap);
647.  		if(Antimagic) {
648.  		    shieldeff(u.ux, u.uy);
649.  		    You_feel("momentarily lethargic.");
650.  		} else drain_en(rnd(u.ulevel) + 1);
651.  		break;
652.  
653.  	    case POLY_TRAP:
654.  		seetrap(trap);
655.  		You("%s onto a polymorph trap!",
656.  		    Levitation ? (const char *)"float" :
657.  		    locomotion(uasmon, "step"));
658.  		if(Antimagic) {
659.  		    shieldeff(u.ux, u.uy);
660.  		    You_feel("momentarily different.");
661.  		    /* Trap did nothing; don't remove it --KAA */
662.  		} else {
663.  		    deltrap(trap);	/* delete trap before polymorph */
664.  		    newsym(u.ux,u.uy);	/* get rid of trap symbol */
665.  		    You_feel("a change coming over you.");
666.  		    polyself();
667.  		}
668.  		break;
669.  
670.  	    case LANDMINE:
671.  		if (Levitation || is_flyer(uasmon)) {
672.  		    if (!already_seen && rn2(3)) break;
673.  		    seetrap(trap);
674.  		    pline("%s %s in a pile of soil below you.",
675.  			    already_seen ? "There is" : "You discover",
676.  			    trap->madeby_u ? "the trigger of your mine" :
677.  					     "a trigger");
678.  		    if (already_seen && rn2(3)) break;
679.  		    pline("KAABLAMM!!!  The air currents set %s%s off!",
680.  			    already_seen ? a_your[trap->madeby_u] : "",
681.  			    already_seen ? " land mine" : "it");
682.  		} else {
683.  		    seetrap(trap);
684.  		    pline("KAABLAMM!!!  You triggered %s land mine!",
685.  					    a_your[trap->madeby_u]);
686.  		    set_wounded_legs(LEFT_SIDE, rn1(35, 41));
687.  		    set_wounded_legs(RIGHT_SIDE, rn1(35, 41));
688.  		    exercise(A_DEX, FALSE);
689.  		}
690.  		scatter(u.ux, u.uy, 4,
691.  			    MAY_DESTROY | MAY_HIT | MAY_FRACTURE | VIS_EFFECTS);
692.  		del_engr_at(u.ux, u.uy);
693.  		wake_nearto(u.ux, u.uy, 500);
694.  		trap->ttyp = PIT;		/* turn the mine into a pit */
695.  		trap->madeby_u = FALSE;	/* resulting pit isn't yours */
696.  		if (IS_DOOR(levl[u.ux][u.uy].typ))
697.  		    levl[u.ux][u.uy].doormask = D_BROKEN;
698.  		newsym(u.ux,u.uy);		/* update trap symbol */
699.  		losehp(rnd(16), "land mine", KILLED_BY_AN);
700.  		dotrap(trap);	/* fall recursively into the pit... */
701.  		break;
702.  
703.  	    case ROLLING_BOULDER_TRAP:
704.  		seetrap(trap);
705.  		pline("Click! You trigger a rolling boulder trap!");
706.  		if(!launch_obj(BOULDER, trap->launch.x, trap->launch.y,
707.  		      trap->launch2.x,trap->launch2.y, ROLL)) {
708.  		    deltrap(trap);
709.  		    newsym(u.ux,u.uy);	/* get rid of trap symbol */
710.  		    pline("Fortunately for you, no boulder was released.");
711.  		}
712.  		break;
713.  
714.  	    case MAGIC_PORTAL:
715.  		seetrap(trap);
716.  		domagicportal(trap);
717.  		break;
718.  
719.  	    default:
720.  		seetrap(trap);
721.  		impossible("You hit a trap of type %u", trap->ttyp);
722.  	}
723.  }
724.  #endif /* OVLB */
725.  #ifdef OVL3
726.  
727.  /*
728.   * Move obj from (x1,y1) to (x2,y2)
729.   *
730.   * Return 0 if no object was launched.
731.   *        1 if an object was launched and placed somewhere.
732.   *        2 if an object was launched, but used up.
733.   */
734.  int
735.  launch_obj(otyp, x1, y1, x2, y2, style)
736.  short otyp;
737.  register int x1,y1,x2,y2;
738.  int style;
739.  {
740.  	register struct monst *mtmp;
741.  	register struct obj *otmp;
742.  	register int dx,dy;
743.  	struct obj *singleobj;
744.  	boolean used_up = FALSE;
745.  	boolean otherside = FALSE;
746.  	int dist;
747.  	int tmp;
748.  	int delaycnt = 0;
749.  
750.  	otmp = sobj_at(otyp, x1, y1);
751.  	/* Try the other side too, for rolling boulder traps */
752.  	if (!otmp && otyp == BOULDER) {
753.  		otherside = TRUE;
754.  		otmp = sobj_at(otyp, x2, y2);
755.  	}
756.  	if (!otmp) return 0;
757.  	if (otherside) {	/* swap 'em */
758.  		int tx, ty;
759.  
760.  		tx = x1; ty = y1;
761.  		x1 = x2; y1 = y2;
762.  		x2 = tx; y2 = ty;
763.  	}
764.  
765.  	if (otmp->quan == 1L) {
766.  	    obj_extract_self(otmp);
767.  	    singleobj = otmp;
768.  	    otmp = (struct obj *) 0;
769.  	} else {
770.  	    singleobj = splitobj(otmp, otmp->quan - 1L);
771.  	    obj_extract_self(singleobj);
772.  	}
773.  	newsym(x1,y1);
774.  	/* in case you're using a pick-axe to chop the boulder that's being
775.  	   launched (perhaps a monster triggered it), destroy context so that
776.  	   next dig attempt never thinks you're resuming previous effort */
777.  	if ((otyp == BOULDER || otyp == STATUE) &&
778.  	    singleobj->ox == digging.pos.x && singleobj->oy == digging.pos.y)
779.  	    (void) memset((genericptr_t)&digging, 0, sizeof digging);
780.  
781.  	dist = distmin(x1,y1,x2,y2);
782.  	bhitpos.x = x1;
783.  	bhitpos.y = y1;
784.  	dx = sgn(x2 - x1);
785.  	dy = sgn(y2 - y1);
786.  	switch (style) {
787.  	    case ROLL:
788.  			delaycnt = 2;
789.  			/* fall through */
790.  	    default:
791.  			if (!delaycnt) delaycnt = 1;
792.  			if (!cansee(bhitpos.x,bhitpos.y)) curs_on_u();
793.  			tmp_at(DISP_FLASH, obj_to_glyph(singleobj));
794.  			tmp_at(bhitpos.x, bhitpos.y);
795.  	}
796.  	while(dist-- > 0 && !used_up) {
797.  		tmp_at(bhitpos.x, bhitpos.y);
798.  		tmp = delaycnt;
799.  		while (tmp-- > 0) delay_output();
800.  		bhitpos.x += dx;
801.  		bhitpos.y += dy;
802.  
803.  		if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != 0) {
804.  			if (otyp == BOULDER && throws_rocks(mtmp->data)) {
805.  			    if (rn2(3)) {
806.  				pline("%s snatches the boulder.",
807.  					Monnam(mtmp));
808.  				mpickobj(mtmp, singleobj);
809.  				used_up = TRUE;
810.  				break;
811.  			    }
812.  			}
813.  			if (ohitmon(mtmp,singleobj,
814.  					(style==ROLL) ? -1 : dist, FALSE)) {
815.  				used_up = TRUE;
816.  				break;
817.  			}
818.  		} else if (bhitpos.x==u.ux && bhitpos.y==u.uy) {
819.  			int hitvalu, hitu;
820.  			if (multi) nomul(0);
821.  			hitvalu = 9 + singleobj->spe;
822.  			hitu = thitu(hitvalu,
823.  				dmgval(singleobj, &youmonst),
824.  				singleobj,
825.  				xname(singleobj));
826.  			if (hitu) stop_occupation();
827.  		}
828.  		if (style == ROLL) {
829.  		    if (down_gate(bhitpos.x, bhitpos.y) != -1) {
830.  		       if (ship_object(singleobj, bhitpos.x, bhitpos.y, FALSE)){
831.  				used_up = TRUE;
832.  				break;
833.  			}
834.  		    }
835.  		    if (flooreffects(singleobj, bhitpos.x, bhitpos.y, "fall")) {
836.  			used_up = TRUE;
837.  			break;
838.  		    }
839.  		}
840.  		if (otyp == BOULDER && closed_door(bhitpos.x,bhitpos.y)) {
841.  			if (cansee(bhitpos.x, bhitpos.y))
842.  				pline_The("boulder crashes through a door.");
843.  			levl[bhitpos.x][bhitpos.y].doormask = D_BROKEN;
844.  		}
845.  	}
846.  	tmp_at(DISP_END, 0);
847.  	if (!used_up) {
848.  		place_object(singleobj, x2,y2);
849.  		newsym(x2,y2);
850.  		return 1;
851.  	} else
852.  		return 2;
853.  }
854.  #endif /* OVL3 */
855.  #ifdef OVLB
856.  
857.  void
858.  seetrap(trap)
859.  	register struct trap *trap;
860.  {
861.  	if(!trap->tseen) {
862.  	    trap->tseen = 1;
863.  	    newsym(trap->tx, trap->ty);
864.  	}
865.  }
866.  
867.  #endif /* OVLB */
868.  #ifdef OVL3
869.  
870.  STATIC_OVL int
871.  mkroll_launch(ttmp, x, y, otyp, ocount)
872.  struct trap *ttmp;
873.  xchar x,y;
874.  short otyp;
875.  long ocount;
876.  {
877.  	struct obj *otmp;
878.  	register int tmp;
879.  	schar dx,dy;
880.  	int distance;
881.  	coord cc;
882.  	coord bcc;
883.  	int trycount = 0;
884.  	boolean success = FALSE;
885.  	int mindist = 4;
886.  
887.  	if (ttmp->ttyp == ROLLING_BOULDER_TRAP) mindist = 2;
888.  	distance = rn1(5,4);    /* 4..8 away */
889.  	tmp = rn2(8);		/* randomly pick a direction to try first */
890.  	while (distance >= mindist) {
891.  		dx = xdir[tmp];
892.  		dy = ydir[tmp];
893.  		cc.x = x; cc.y = y;
894.  		/* Prevent boulder from being placed on water */
895.  		if (ttmp->ttyp == ROLLING_BOULDER_TRAP
896.  				&& is_pool(x+distance*dx,y+distance*dy))
897.  			success = FALSE;
898.  		else success = isclearpath(&cc, distance, dx, dy);
899.  		if (ttmp->ttyp == ROLLING_BOULDER_TRAP) {
900.  			boolean success_otherway;
901.  			bcc.x = x; bcc.y = y;
902.  			success_otherway = isclearpath(&bcc, distance,
903.  						-(dx), -(dy));
904.  			if (!success_otherway) success = FALSE;
905.  		}
906.  		if (success) break;
907.  		if (++tmp > 7) tmp = 0;
908.  		if ((++trycount % 8) == 0) --distance;
909.  	}
910.  	if (!success) {
911.  	    /* create the trap without any ammo, launch pt at trap location */
912.  		cc.x = bcc.x = x;
913.  		cc.y = bcc.y = y;
914.  	} else {
915.  		otmp = mksobj(otyp, TRUE, FALSE);
916.  		otmp->quan = ocount;
917.  		otmp->owt = weight(otmp);
918.  		place_object(otmp, cc.x, cc.y);
919.  		stackobj(otmp);
920.  	}
921.  	ttmp->launch.x = cc.x;
922.  	ttmp->launch.y = cc.y;
923.  	if (ttmp->ttyp == ROLLING_BOULDER_TRAP) {
924.  		ttmp->launch2.x = bcc.x;
925.  		ttmp->launch2.y = bcc.y;
926.  	} else
927.  		ttmp->launch_otyp = otyp;
928.  	newsym(ttmp->launch.x, ttmp->launch.y);
929.  	return 1;
930.  }
931.  
932.  STATIC_OVL boolean
933.  isclearpath(cc,distance,dx,dy)
934.  coord *cc;
935.  int distance;
936.  schar dx,dy;
937.  {
938.  	uchar typ;
939.  	xchar x, y;
940.  
941.  	x = cc->x;
942.  	y = cc->y;
943.  	while (distance-- > 0) {
944.  		x += dx;
945.  		y += dy;
946.  		typ = levl[x][y].typ;
947.  		if (!isok(x,y) || !ZAP_POS(typ) || closed_door(x,y))
948.  			return FALSE;
949.  	}
950.  	cc->x = x;
951.  	cc->y = y;
952.  	return TRUE;
953.  }
954.  #endif /* OVL3 */
955.  #ifdef OVL1
956.  
957.  int
958.  mintrap(mtmp)
959.  register struct monst *mtmp;
960.  {
961.  	register struct trap *trap = t_at(mtmp->mx, mtmp->my);
962.  	boolean trapkilled = FALSE;
963.  	struct permonst *mptr = mtmp->data;
964.  	struct obj *otmp;
965.  
966.  	if(!trap) {
967.  		mtmp->mtrapped = 0;	/* perhaps teleported? */
968.  	} else if (mtmp->mtrapped) {	/* was in trap */
969.  		if(!rn2(40)) {
970.  			if (sobj_at(BOULDER, mtmp->mx, mtmp->my) &&
971.  			    ((trap->ttyp == PIT) ||
972.  			     (trap->ttyp == SPIKED_PIT))) {
973.  				if (!rn2(2)) {
974.  					mtmp->mtrapped = 0;
975.  					fill_pit(mtmp->mx, mtmp->my);
976.  				}
977.  			} else
978.  				mtmp->mtrapped = 0;
979.  		} else if (trap->ttyp == BEAR_TRAP && metallivorous(mptr)) {
980.  			if (canseemon(mtmp))
981.  			    pline("%s eats a bear trap!", Monnam(mtmp));
982.  			deltrap(trap);
983.  			mtmp->meating = 5;
984.  			mtmp->mtrapped = 0;
985.  		}
986.  	} else {
987.  	    register int tt = trap->ttyp;
988.  	    boolean in_sight, tear_web, see_it;
989.  
990.  	    if ((mtmp->mtrapseen & (1 << (tt-1))) != 0 ||
991.  		    (tt == HOLE && !mindless(mtmp->data))) {
992.  		/* it has been in such a trap - perhaps it escapes */
993.  		if(rn2(4)) return(0);
994.  	    } else {
995.  		mtmp->mtrapseen |= (1 << (tt-1));
996.  	    }
997.  	    /* Monster is aggravated by being trapped by you.
998.  	       Recognizing who made the trap isn't completely
999.  	       unreasonable; everybody has their own style. */
1000. 	    if (trap->madeby_u && rnl(5)) setmangry(mtmp);
1001. 
1002. 	    /* bug?  `in_sight' ought to be split to distinguish between
1003. 	       trap_in_sight and can_see_victim to handle invisible monsters */
1004. 	    in_sight = canseemon(mtmp);
1005. 	    switch (tt) {
1006. 		case ARROW_TRAP:
1007. 			otmp = mksobj(ARROW, TRUE, FALSE);
1008. 			otmp->quan = 1L;
1009. 			otmp->owt = weight(otmp);
1010. 			if (in_sight) seetrap(trap);
1011. 			if(thitm(8, mtmp, otmp, 0)) trapkilled = TRUE;
1012. 			break;
1013. 		case DART_TRAP:
1014. 			otmp = mksobj(DART, TRUE, FALSE);
1015. 			otmp->quan = 1L;
1016. 			otmp->owt = weight(otmp);
1017. 			if (!rn2(6)) otmp->opoisoned = 1;
1018. 			if (in_sight) seetrap(trap);
1019. 			if(thitm(7, mtmp, otmp, 0)) trapkilled = TRUE;
1020. 			break;
1021. 		case ROCKTRAP:
1022. 			otmp = mksobj(ROCK, TRUE, FALSE);
1023. 			otmp->quan = 1L;
1024. 			otmp->owt = weight(otmp);
1025. 			if (in_sight) seetrap(trap);
1026. 			if (is_whirly(mptr) || passes_walls(mptr)) {
1027. 			    if (in_sight)
1028. 				pline("A rock falls harmlessly through %s.",
1029. 				      mon_nam(mtmp));
1030. 			    else if (cansee(mtmp->mx, mtmp->my))
1031. 				pline("A rock falls to the %s.",
1032. 				      surface(mtmp->mx, mtmp->my));
1033. 			    place_object(otmp, mtmp->mx, mtmp->my);
1034. 			    stackobj(otmp);
1035. 			} else if (thitm(0, mtmp, otmp, d(2, 6)))
1036. 			    trapkilled = TRUE;
1037. 			break;
1038. 
1039. 		case SQKY_BOARD:
1040. 			if(is_flyer(mptr)) break;
1041. 			/* stepped on a squeaky board */
1042. 			if (in_sight) {
1043. 			    pline("A board beneath %s squeaks loudly.", mon_nam(mtmp));
1044. 			    seetrap(trap);
1045. 			} else
1046. 			   You_hear("a distant squeak.");
1047. 			/* wake up nearby monsters */
1048. 			wake_nearto(mtmp->mx, mtmp->my, 40);
1049. 			break;
1050. 
1051. 		case BEAR_TRAP:
1052. 			if(mptr->msize > MZ_SMALL &&
1053. 				!amorphous(mptr) && !is_flyer(mptr) &&
1054. 				!is_whirly(mptr) && !unsolid(mptr)) {
1055. 			    mtmp->mtrapped = 1;
1056. 			    if(in_sight) {
1057. 				pline("%s is caught in %s bear trap!",
1058. 				      Monnam(mtmp), a_your[trap->madeby_u]);
1059. 				seetrap(trap);
1060. 			    } else {
1061. 				if((mptr == &mons[PM_OWLBEAR]
1062. 				    || mptr == &mons[PM_BUGBEAR])
1063. 				   && flags.soundok)
1064. 				    You_hear("the roaring of an angry bear!");
1065. 			    }
1066. 			}
1067. 			break;
1068. 
1069. 		case SLP_GAS_TRAP:
1070. 			if (!resists_sleep(mtmp) &&
1071. 				!mtmp->msleep && mtmp->mcanmove) {
1072. 			    mtmp->mcanmove = 0;
1073. 			    mtmp->mfrozen = rnd(25);
1074. 			    if (in_sight) {
1075. 				pline("%s suddenly falls asleep!",
1076. 				      Monnam(mtmp));
1077. 				seetrap(trap);
1078. 			    }
1079. 			}
1080. 			break;
1081. 
1082. 		case RUST_TRAP:
1083. 			if (in_sight) {
1084. 			    pline("%s %s!", A_gush_of_water_hits,
1085. 				  mon_nam(mtmp));
1086. 			    seetrap(trap);
1087. 			}
1088. 			if (mptr == &mons[PM_IRON_GOLEM]) {
1089. 				if (in_sight)
1090. 				    pline("%s falls to pieces!", Monnam(mtmp));
1091. 				else if(mtmp->mtame)
1092. 				    pline("May %s rust in peace.",
1093. 								mon_nam(mtmp));
1094. 				mondied(mtmp);
1095. 				if (mtmp->mhp <= 0)
1096. 					trapkilled = TRUE;
1097. 			} else if (mptr == &mons[PM_GREMLIN] && rn2(3)) {
1098. 				struct monst *mtmp2 = clone_mon(mtmp);
1099. 
1100. 				if (mtmp2) {
1101. 				    mtmp2->mhpmax = (mtmp->mhpmax /= 2);
1102. 				    if(in_sight)
1103. 					pline("%s multiplies.", Monnam(mtmp));
1104. 				}
1105. 			}
1106. 			if (rn2(2))
1107. 			    for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
1108. 				(void) snuff_lit(otmp);
1109. 			break;
1110. 
1111. 		case FIRE_TRAP:
1112.  mfiretrap:
1113. 			see_it = cansee(mtmp->mx, mtmp->my);
1114. 			if (in_sight)
1115. 			    pline("A %s erupts from the %s under %s!",
1116. 				  tower_of_flame,
1117. 				  surface(mtmp->mx,mtmp->my), mon_nam(mtmp));
1118. 			else if (see_it)  /* evidently `mtmp' is invisible */
1119. 			    You("see a %s erupt from the %s!",
1120. 				tower_of_flame, surface(mtmp->mx,mtmp->my));
1121. 
1122. 			if (resists_fire(mtmp)) {
1123. 			    if (in_sight) {
1124. 				shieldeff(mtmp->mx,mtmp->my);
1125. 				pline("%s is uninjured.", Monnam(mtmp));
1126. 			    }
1127. 			} else {
1128. 			    int num = d(2,4);
1129. 
1130. 			    if (thitm(0, mtmp, (struct obj *)0, num))
1131. 				trapkilled = TRUE;
1132. 			    else
1133. 				/* we know mhp is at least `num' below mhpmax,
1134. 				   so no (mhp > mhpmax) check is needed here */
1135. 				mtmp->mhpmax -= rn2(num + 1);
1136. 			}
1137. 			(void) destroy_mitem(mtmp, SCROLL_CLASS, AD_FIRE);
1138. 			(void) destroy_mitem(mtmp, SPBOOK_CLASS, AD_FIRE);
1139. 			(void) destroy_mitem(mtmp, POTION_CLASS, AD_FIRE);
1140. 			if (burn_floor_paper(mtmp->mx, mtmp->my, see_it) &&
1141. 				!see_it && distu(mtmp->mx, mtmp->my) <= 3*3)
1142. 			    You("smell smoke.");
1143. 			if (is_ice(mtmp->mx,mtmp->my))
1144. 			    melt_ice(mtmp->mx,mtmp->my);
1145. 			if (see_it) seetrap(trap);
1146. 			break;
1147. 
1148. 		case PIT:
1149. 		case SPIKED_PIT:
1150. 			if ( !is_flyer(mptr) &&
1151. 			     (!mtmp->wormno || (count_wsegs(mtmp) < 6)) &&
1152. 			     !is_clinger(mptr) ) {
1153. 				if (!passes_walls(mptr))
1154. 				    mtmp->mtrapped = 1;
1155. 				if(in_sight) {
1156. 				    pline("%s falls into %s pit!",
1157. 					Monnam(mtmp), a_your[trap->madeby_u]);
1158. 				    seetrap(trap);
1159. 				}
1160. 				mselftouch(mtmp, "Falling, ", FALSE);
1161. 				if(mtmp->mhp <= 0 ||
1162. 					thitm(0, mtmp, (struct obj *)0,
1163. 					 rnd((tt==PIT) ? 6 : 10)))
1164. 				    trapkilled = TRUE;
1165. 			}
1166. 			break;
1167. 		case HOLE:
1168. 		case TRAPDOOR:
1169. 			if(!Can_fall_thru(&u.uz))
1170. 			 panic("Holes & trapdoors cannot exist on this level.");
1171. 
1172. 			if (is_flyer(mptr) || mptr == &mons[PM_WUMPUS] ||
1173. 			    (mtmp->wormno && count_wsegs(mtmp) > 5) ||
1174. 			    mptr->msize >= MZ_HUGE) break;
1175. 			/* Fall through */
1176. 		case LEVEL_TELEP:
1177. 		case MAGIC_PORTAL:
1178. 			{
1179. 			    int mlev_res;
1180. 			    mlev_res = mlevel_tele_trap(mtmp, trap, in_sight);
1181. 			    if (mlev_res) return(mlev_res);
1182. 			}
1183. 			break;
1184. 
1185. 		case TELEP_TRAP:
1186. 			mtele_trap(mtmp, trap, in_sight);
1187. 			break;
1188. 
1189. 		case WEB:
1190. 			/* Monster in a web. */
1191. 			if (mptr->mlet == S_SPIDER) break;
1192. 			if (amorphous(mptr) || is_whirly(mptr) || unsolid(mptr)){
1193. 			    if(acidic(mptr) ||
1194. 			       mptr == &mons[PM_GELATINOUS_CUBE] ||
1195. 			       mptr == &mons[PM_FIRE_ELEMENTAL]) {
1196. 				if (in_sight)
1197. 				    pline("%s %s %s spider web!",
1198. 					  Monnam(mtmp),
1199. 					  (mptr == &mons[PM_FIRE_ELEMENTAL]) ?
1200. 					    "burns" : "dissolves",
1201. 					  a_your[trap->madeby_u]);
1202. 				deltrap(trap);
1203. 				newsym(mtmp->mx, mtmp->my);
1204. 				break;
1205. 			    }
1206. 			    if (in_sight) {
1207. 				pline("%s flows through %s spider web.",
1208. 				      Monnam(mtmp),
1209. 				      a_your[trap->madeby_u]);
1210. 				seetrap(trap);
1211. 			    }
1212. 			    break;
1213. 			}
1214. 			tear_web = FALSE;
1215. 			switch (monsndx(mptr)) {
1216. 			    case PM_OWLBEAR: /* Eric Backus */
1217. 			    case PM_BUGBEAR:
1218. 				if (!in_sight) {
1219. 				    You_hear("the roaring of a confused bear!");
1220. 				    mtmp->mtrapped = 1;
1221. 				    break;
1222. 				}
1223. 				/* fall though */
1224. 			    default:
1225. 				if (mptr->mlet == S_GIANT ||
1226. 				    (mptr->mlet == S_DRAGON &&
1227. 					extra_nasty(mptr)) || /* excl. babies */
1228. 				    (mtmp->wormno && count_wsegs(mtmp) > 5)) {
1229. 				    tear_web = TRUE;
1230. 				} else if (in_sight) {
1231. 				    pline("%s is caught in %s spider web.",
1232. 					  Monnam(mtmp),
1233. 					  a_your[trap->madeby_u]);
1234. 				    seetrap(trap);
1235. 				}
1236. 				mtmp->mtrapped = tear_web ? 0 : 1;
1237. 				break;
1238. 			    /* this list is fairly arbitrary; it deliberately
1239. 			       excludes wumpus & giant/ettin zombies/mummies */
1240. 			    case PM_TITANOTHERE:
1241. 			    case PM_BALUCHITHERIUM:
1242. 			    case PM_PURPLE_WORM:
1243. 			    case PM_JABBERWOCK:
1244. 			    case PM_IRON_GOLEM:
1245. 			    case PM_BALROG:
1246. 			    case PM_KRAKEN:
1247. 				tear_web = TRUE;
1248. 				break;
1249. 			}
1250. 			if (tear_web) {
1251. 			    if (in_sight)
1252. 				pline("%s tears through %s spider web!",
1253. 				      Monnam(mtmp), a_your[trap->madeby_u]);
1254. 			    deltrap(trap);
1255. 			    newsym(mtmp->mx, mtmp->my);
1256. 			}
1257. 			break;
1258. 
1259. 		case STATUE_TRAP:
1260. 			break;
1261. 
1262. 		case MAGIC_TRAP:
1263. 			/* A magic trap.  Monsters usually immune. */
1264. 			if (!rn2(21)) goto mfiretrap;
1265. 			break;
1266. 		case ANTI_MAGIC:
1267. 			break;
1268. 
1269. 		case LANDMINE:
1270. 			if(rn2(3))
1271. 				break; /* monsters usually don't set it off */
1272. 			if(is_flyer(mptr)) {
1273. 				boolean already_seen = trap->tseen;
1274. 				if (in_sight && !already_seen) {
1275. 	pline("A trigger appears in a pile of soil below %s.", mon_nam(mtmp));
1276. 					seetrap(trap);
1277. 				}
1278. 				if (rn2(3)) break;
1279. 				if (in_sight) {
1280. 					newsym(mtmp->mx, mtmp->my);
1281. 					pline_The("air currents set %s off!",
1282. 					  already_seen ? "a land mine" : "it");
1283. 				}
1284. 			} else if(in_sight) {
1285. 			    newsym(mtmp->mx, mtmp->my);
1286. 			    pline("KAABLAMM!!!  %s triggers %s land mine!",
1287. 				Monnam(mtmp), a_your[trap->madeby_u]);
1288. 			}
1289. 			if (!in_sight)
1290. 				pline("Kaablamm!  You hear an explosion in the distance!");
1291. 			scatter(mtmp->mx, mtmp->my, 4,
1292. 				MAY_DESTROY | MAY_HIT | MAY_FRACTURE | VIS_EFFECTS);
1293. 			del_engr_at(mtmp->mx, mtmp->my);
1294. 			if (IS_DOOR(levl[mtmp->mx][mtmp->my].typ))
1295. 				levl[mtmp->mx][mtmp->my].doormask = D_BROKEN;
1296. 
1297. 			trap->ttyp = PIT;       /* explosion creates a pit */
1298. 			trap->madeby_u = FALSE; /* resulting pit isn't yours */
1299. 			if(thitm(0, mtmp, (struct obj *)0, rnd(16)))
1300. 				trapkilled = TRUE;
1301. 			else {
1302. 				/* monsters recursively fall into new pit */
1303. 				if (mintrap(mtmp) == 2) trapkilled=TRUE;
1304. 			}
1305. 			wake_nearto(mtmp->mx, mtmp->my, 500);
1306. 			if (unconscious()) {
1307. 				multi = -1;
1308. 				nomovemsg="The explosion awakens you!";
1309. 			}
1310. 			break;
1311. 
1312. 		case POLY_TRAP:
1313. 		    if (resists_magm(mtmp)) {
1314. 			shieldeff(mtmp->mx, mtmp->my);
1315. 		    } else if (!resist(mtmp, WAND_CLASS, 0, NOTELL)) {
1316. 			(void) newcham(mtmp, (struct permonst *)0);
1317. 			if (in_sight) seetrap(trap);
1318. 		    }
1319. 		    break;
1320. 
1321. 		case ROLLING_BOULDER_TRAP:
1322. 		    newsym(mtmp->mx,mtmp->my);
1323. 		    if (in_sight)
1324. 			pline("Click! %s triggers %s.", Monnam(mtmp),
1325. 				trap->tseen ?
1326. 				"a rolling boulder trap" :
1327. 				something);
1328. 		    if (launch_obj(BOULDER, trap->launch.x, trap->launch.y,
1329. 				   trap->launch2.x, trap->launch2.y, ROLL)) {
1330. 			if (in_sight) trap->tseen = TRUE;
1331. 			else You_hear(Hallucination ?
1332. 					"someone bowling." :
1333. 					"rumbling in the distance.");
1334. 			if (mtmp->mhp <= 0) trapkilled = TRUE;
1335. 		    } else {
1336. 			deltrap(trap);
1337. 			newsym(mtmp->mx,mtmp->my);
1338. 		    }
1339. 		    break;
1340. 
1341. 		default:
1342. 			impossible("Some monster encountered a strange trap of type %d.", tt);
1343. 	    }
1344. 	}
1345. 	if(trapkilled) return 2;
1346. 	return mtmp->mtrapped;
1347. }
1348. 
1349. #endif /* OVL1 */
1350. #ifdef OVLB
1351. 
1352. /* Combine cockatrice checks into single functions to avoid repeating code. */
1353. void
1354. instapetrify(str)
1355. const char *str;
1356. {
1357. 	if (resists_ston(&youmonst)) return;
1358. 	if (poly_when_stoned(uasmon) && polymon(PM_STONE_GOLEM))
1359. 	    return;
1360. 	You("turn to stone...");
1361. 	killer_format = KILLED_BY;
1362. 	killer = str;
1363. 	done(STONING);
1364. }
1365. 
1366. void
1367. minstapetrify(mon,byplayer)
1368. struct monst *mon;
1369. boolean byplayer;
1370. {
1371. 	if (resists_ston(mon)) return;
1372. 	if (cansee(mon->mx, mon->my))
1373. 		pline("%s turns to stone.", Monnam(mon));
1374. 	if (poly_when_stoned(mon->data)) {
1375. 		mon_to_stone(mon);
1376. 		return;
1377. 	}
1378. 	if (byplayer) {
1379. 		stoned = TRUE;
1380. 		xkilled(mon,0);
1381. 	} else monstone(mon);
1382. }
1383. 
1384. void
1385. selftouch(arg)
1386. const char *arg;
1387. {
1388. 	if (uwep && uwep->otyp == CORPSE && uwep->corpsenm == PM_COCKATRICE) {
1389. 		pline("%s touch the cockatrice corpse.", arg);
1390. 		instapetrify("cockatrice corpse");
1391. 	}
1392. }
1393. 
1394. void
1395. mselftouch(mon,arg,byplayer)
1396. struct monst *mon;
1397. const char *arg;
1398. boolean byplayer;
1399. {
1400. 	struct obj *mwep = MON_WEP(mon);
1401. 
1402. 	if (mwep && mwep->otyp == CORPSE && mwep->corpsenm == PM_COCKATRICE) {
1403. 		if (cansee(mon->mx, mon->my)) {
1404. 			pline("%s%s touches the cockatrice corpse.",
1405. 			    arg ? arg : "", arg ? mon_nam(mon) : Monnam(mon));
1406. 		}
1407. 		minstapetrify(mon, byplayer);
1408. 	}
1409. }
1410. 
1411. void
1412. float_up()
1413. {
1414. 	if(u.utrap) {
1415. 		if(u.utraptype == TT_PIT) {
1416. 			u.utrap = 0;
1417. 			You("float up, out of the pit!");
1418. 			vision_full_recalc = 1;	/* vision limits change */
1419. 			fill_pit(u.ux, u.uy);
1420. 		} else if (u.utraptype == TT_INFLOOR) {
1421. 			Your("body pulls upward, but your %s are still stuck.",
1422. 			     makeplural(body_part(LEG)));
1423. 		} else {
1424. 			You("float up, only your %s is still stuck.",
1425. 				body_part(LEG));
1426. 		}
1427. 	}
1428. 	else if(Is_waterlevel(&u.uz))
1429. 		pline("It feels as though you'd lost some weight.");
1430. 	else if(u.uinwater)
1431. 		spoteffects();
1432. 	else if(u.uswallow)
1433. 		You(is_animal(u.ustuck->data) ?
1434. 			"float away from the %s."  :
1435. 			"spiral up into %s.",
1436. 		    is_animal(u.ustuck->data) ?
1437. 			surface(u.ux, u.uy) :
1438. 			mon_nam(u.ustuck));
1439. 	else if (Hallucination)
1440. 		pline("Up, up, and awaaaay!  You're walking on air!");
1441. 	else if(Is_airlevel(&u.uz))
1442. 		You("gain control over your movements.");
1443. 	else
1444. 		You("start to float in the air!");
1445. }
1446. 
1447. void
1448. fill_pit(x, y)
1449. int x, y;
1450. {
1451. 	struct obj *otmp;
1452. 	struct trap *t;
1453. 
1454. 	if ((t = t_at(x, y)) &&
1455. 	    ((t->ttyp == PIT) || (t->ttyp == SPIKED_PIT)) &&
1456. 	    (otmp = sobj_at(BOULDER, x, y))) {
1457. 		obj_extract_self(otmp);
1458. 		(void) flooreffects(otmp, x, y, "settle");
1459. 	}
1460. }
1461. 
1462. int
1463. float_down(override_mask)
1464. long override_mask;	/* might cancel timeout */
1465. {
1466. 	register struct trap *trap = (struct trap *)0;
1467. 	d_level current_dungeon_level;
1468. 	boolean no_msg = FALSE;
1469. 
1470. 	HLevitation &= ~override_mask;
1471. 	if(Levitation) return(0); /* maybe another ring/potion/boots */
1472. 
1473. 	if (Punished && !carried(uball) &&
1474. 	    (is_pool(uball->ox, uball->oy) ||
1475. 	     ((trap = t_at(uball->ox, uball->oy)) &&
1476. 	      ((trap->ttyp == PIT) || (trap->ttyp == SPIKED_PIT) ||
1477. 	       (trap->ttyp == TRAPDOOR) || (trap->ttyp == HOLE))))) {
1478. 			u.ux0 = u.ux;
1479. 			u.uy0 = u.uy;
1480. 			u.ux = uball->ox;
1481. 			u.uy = uball->oy;
1482. 			movobj(uchain, uball->ox, uball->oy);
1483. 			newsym(u.ux0, u.uy0);
1484. 			vision_full_recalc = 1;	/* in case the hero moved. */
1485. 	}
1486. 	/* check for falling into pool - added by GAN 10/20/86 */
1487. 	if(!is_flyer(uasmon)) {
1488. 		/* kludge alert:
1489. 		 * drown() and lava_effects() print various messages almost
1490. 		 * every time they're called which conflict with the "fall
1491. 		 * into" message below.  Thus, we want to avoid printing
1492. 		 * confusing, duplicate or out-of-order messages.
1493. 		 * Use knowledge of the two routines as a hack -- this
1494. 		 * should really handled differently -dlc
1495. 		 */
1496. 		if(is_pool(u.ux,u.uy) && !Wwalking && !u.uinwater)
1497. 			no_msg = drown();
1498. 
1499. 		if(is_lava(u.ux,u.uy)) {
1500. 			(void) lava_effects();
1501. 			no_msg = TRUE;
1502. 		}
1503. 	}
1504. 	if (!trap) {
1505. 		if(Is_airlevel(&u.uz))
1506. 			You("begin to tumble in place.");
1507. 		else if (Is_waterlevel(&u.uz) && !no_msg)
1508. 			You_feel("heavier.");
1509. 		/* u.uinwater msgs already in spoteffects()/drown() */
1510. 		else if (!u.uinwater && !no_msg) {
1511. 			if (Hallucination)
1512. 				pline("Bummer!  You've %s.",
1513. 				      is_pool(u.ux,u.uy) ?
1514. 					"splashed down" : "hit the ground");
1515. 			else
1516. 				You("float gently to the %s.",
1517. 				    surface(u.ux, u.uy));
1518. 		}
1519. 		trap = t_at(u.ux,u.uy);
1520. 	}
1521. 
1522. 	/* can't rely on u.uz0 for detecting trap door-induced level change;
1523. 	   it gets changed to reflect the new level before we can check it */
1524. 	assign_level(&current_dungeon_level, &u.uz);
1525. 
1526. 	if(trap)
1527. 		switch(trap->ttyp) {
1528. 		case STATUE_TRAP:
1529. 			break;
1530. 		case HOLE:
1531. 		case TRAPDOOR:
1532. 			if(!Can_fall_thru(&u.uz) || u.ustuck)
1533. 				break;
1534. 			/* fall into next case */
1535. 		default:
1536. 			dotrap(trap);
1537. 	}
1538. 
1539. 	if (!Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz) && !u.uswallow &&
1540. 		/* falling through trap door calls goto_level,
1541. 		   and goto_level does its own pickup() call */
1542. 		on_level(&u.uz, &current_dungeon_level))
1543. 	    pickup(1);
1544. 	return 1;
1545. }
1546. 
1547. STATIC_OVL void
1548. dofiretrap(box)
1549. struct obj *box;	/* null for floor trap */
1550. {
1551. 	boolean see_it = !Blind;
1552. 	int num;
1553. 
1554. 	if ((box && !carried(box)) ? is_pool(box->ox, box->oy) : Underwater) {
1555. 	    pline("A cascade of steamy bubbles erupts from %s!",
1556. 		    the(box ? xname(box) : surface(u.ux,u.uy)));
1557. 	    if (Fire_resistance) You("are uninjured.");
1558. 	    else losehp(rnd(3), "boiling water", KILLED_BY);
1559. 	    return;
1560. 	}
1561. 	pline("A %s %s from %s!", tower_of_flame,
1562. 	      box ? "bursts" : "erupts",
1563. 	      the(box ? xname(box) : surface(u.ux,u.uy)));
1564. 	if (Fire_resistance) {
1565. 	    shieldeff(u.ux, u.uy);
1566. 	    num = rn2(2);
1567. 	} else {
1568. 	    num = d(2,4);
1569. 	    if (u.uhpmax > u.ulevel)
1570. 		u.uhpmax -= rn2(min(u.uhpmax,num + 1)), flags.botl = 1;
1571. 	}
1572. 	if (!num)
1573. 	    You("are uninjured.");
1574. 	else
1575. 	    losehp(num, tower_of_flame, KILLED_BY_AN);
1576. 
1577. 	if (burnarmor() || rn2(3)) {
1578. 	    destroy_item(SCROLL_CLASS, AD_FIRE);
1579. 	    destroy_item(SPBOOK_CLASS, AD_FIRE);
1580. 	    destroy_item(POTION_CLASS, AD_FIRE);
1581. 	}
1582. 	if (!box && burn_floor_paper(u.ux, u.uy, see_it) && !see_it)
1583. 	    You("smell paper burning.");
1584. 	if (is_ice(u.ux, u.uy))
1585. 	    melt_ice(u.ux, u.uy);
1586. }
1587. 
1588. STATIC_OVL void
1589. domagictrap()
1590. {
1591. 	register int fate = rnd(20);
1592. 
1593. 	/* What happened to the poor sucker? */
1594. 
1595. 	if (fate < 10) {
1596. 
1597. 	  /* Most of the time, it creates some monsters. */
1598. 	  register int cnt = rnd(4);
1599. 
1600. 	  /* below checks for blindness added by GAN 10/30/86 */
1601. 	  if (!Blind)  {
1602. 		You("are momentarily blinded by a flash of light!");
1603. 		make_blinded((long)rn1(5,10),FALSE);
1604. 	  }  else
1605. 		You_hear("a deafening roar!");
1606. 	  while(cnt--)
1607. 		(void) makemon((struct permonst *) 0, u.ux, u.uy);
1608. 	}
1609. 	else
1610. 	  switch (fate) {
1611. 
1612. 	     case 10:
1613. 	     case 11:
1614. 		      /* sometimes nothing happens */
1615. 			break;
1616. 	     case 12: /* a flash of fire */
1617. 			dofiretrap((struct obj *)0);
1618. 			break;
1619. 
1620. 	     /* odd feelings */
1621. 	     case 13:	pline("A shiver runs up and down your %s!",
1622. 			      body_part(SPINE));
1623. 			break;
1624. 	     case 14:	You_hear(Hallucination ?
1625. 				"the moon howling at you." :
1626. 				"distant howling.");
1627. 			break;
1628. 	     case 15:	if (on_level(&u.uz, &qstart_level))
1629. 			    You_feel("%slike the prodigal son.",
1630. 			      (flags.female || (Upolyd && is_neuter(uasmon))) ?
1631. 				     "oddly " : "");
1632. 			else
1633. 			    You("suddenly yearn for %s.",
1634. 				Hallucination ? "Cleveland" :
1635. 			    (In_quest(&u.uz) || at_dgn_entrance("The Quest")) ?
1636. 						"your nearby homeland" :
1637. 						"your distant homeland");
1638. 			break;
1639. 	     case 16:   Your("pack shakes violently!");
1640. 			break;
1641. 	     case 17:	You(Hallucination ?
1642. 				"smell hamburgers." :
1643. 				"smell charred flesh.");
1644. 			break;
1645. 	     case 18:	You_feel("tired.");
1646. 			break;
1647. 
1648. 	     /* very occasionally something nice happens. */
1649. 
1650. 	     case 19:
1651. 		    /* tame nearby monsters */
1652. 		   {   register int i,j;
1653. 		       register struct monst *mtmp;
1654. 
1655. 		       (void) adjattrib(A_CHA,1,FALSE);
1656. 		       for(i = -1; i <= 1; i++) for(j = -1; j <= 1; j++) {
1657. 			   if(!isok(u.ux+i, u.uy+j)) continue;
1658. 			   mtmp = m_at(u.ux+i, u.uy+j);
1659. 			   if(mtmp)
1660. 			       (void) tamedog(mtmp, (struct obj *)0);
1661. 		       }
1662. 		       break;
1663. 		   }
1664. 
1665. 	     case 20:
1666. 		    /* uncurse stuff */
1667. 		   {  register struct obj *obj;
1668. 
1669. 			/* below plines added by GAN 10/30/86 */
1670. 			You_feel(Hallucination ?
1671. 				"in touch with the Universal Oneness." :
1672. 				"like someone is helping you.");
1673. 			for(obj = invent; obj ; obj = obj->nobj)
1674. 			       if(obj->owornmask || obj->otyp == LOADSTONE)
1675. 					uncurse(obj);
1676. 		       if(Punished) unpunish();
1677. 		       break;
1678. 		   }
1679. 	     default: break;
1680. 	  }
1681. }
1682. 
1683. void
1684. water_damage(obj, force, here)
1685. register struct obj *obj;
1686. register boolean force, here;
1687. {
1688. 	/* Scrolls, spellbooks, potions, weapons and
1689. 	   pieces of armor may get affected by the water */
1690. 	for (; obj; obj = (here ? obj->nexthere : obj->nobj)) {
1691. 
1692. 		(void) snuff_lit(obj);
1693. 
1694. 		if(obj->greased) {
1695. 			if (force || !rn2(2)) obj->greased = 0;
1696. 		} else if(Is_container(obj) && !Is_box(obj) &&
1697. 			(obj->otyp != OILSKIN_SACK || (obj->cursed && !rn2(3)))) {
1698. 			water_damage(obj->cobj, force, FALSE);
1699. 		} else if (!force && (Luck + 5) > rn2(20)) {
1700. 			/*  chance per item of sustaining damage:
1701. 			 *	max luck (full moon):	 5%
1702. 			 *	max luck (elsewhen):	10%
1703. 			 *	avg luck (Luck==0):	75%
1704. 			 *	awful luck (Luck<-4):  100%
1705. 			 */
1706. 			continue;
1707. 		} else if (obj->oclass == SCROLL_CLASS) {
1708. #ifdef MAIL
1709. 		    if (obj->otyp != SCR_MAIL)
1710. #endif
1711. 			obj->otyp = SCR_BLANK_PAPER;
1712. 			obj->spe = 0;
1713. 		} else if (obj->oclass == SPBOOK_CLASS) {
1714. 			if (obj->otyp == SPE_BOOK_OF_THE_DEAD)
1715. 				pline("Steam rises from %s.", the(xname(obj)));
1716. 			else obj->otyp = SPE_BLANK_PAPER;
1717. 		} else if (obj->oclass == POTION_CLASS) {
1718. 			if (obj->odiluted) {
1719. 				obj->otyp = POT_WATER;
1720. 				obj->blessed = obj->cursed = 0;
1721. 				obj->odiluted = 0;
1722. 			} else if (obj->otyp != POT_WATER ||
1723. 				   obj->blessed || obj->cursed)
1724. 				obj->odiluted++;
1725. 		} else if (is_rustprone(obj) && obj->oeroded < MAX_ERODE &&
1726. 			  !(obj->oerodeproof || (obj->blessed && !rnl(4)))) {
1727. 			/* all metal stuff and armor except (body armor
1728. 			   protected by oilskin cloak) */
1729. 			if(obj->oclass != ARMOR_CLASS || obj != uarm ||
1730. 			   !uarmc || uarmc->otyp != OILSKIN_CLOAK ||
1731. 			   (uarmc->cursed && !rn2(3)))
1732. 				obj->oeroded++;
1733. 		}
1734. 	}
1735. }
1736. 
1737. /*
1738.  * This function is potentially expensive - rolling
1739.  * inventory list multiple times.  Luckily it's seldom needed.
1740.  * Returns TRUE if disrobing made player unencumbered enough to
1741.  * crawl out of the current predicament.
1742.  */
1743. STATIC_OVL boolean
1744. emergency_disrobe(lostsome)
1745. boolean *lostsome;
1746. {
1747. 	int invc = inv_cnt();
1748. 
1749. 	while (near_capacity() > (Punished ? UNENCUMBERED : SLT_ENCUMBER)) {
1750. 		register struct obj *obj, *otmp = (struct obj *)0;
1751. 		register int i = rn2(invc);
1752. 
1753. 		for (obj = invent; obj; obj = obj->nobj) {
1754. 			/*
1755. 			 * Undroppables are: body armor, boots, gloves,
1756. 			 * amulets, and rings because of the time and effort
1757. 			 * in removing them + loadstone and other cursed stuff
1758. 			 * for obvious reasons.
1759. 			 */
1760. 			if (!((obj->otyp == LOADSTONE && obj->cursed) ||
1761. 			      obj == uamul || obj == uleft || obj == uright ||
1762. 			      obj == ublindf || obj == uarm || obj == uarmc ||
1763. 			      obj == uarmg || obj == uarmf ||
1764. #ifdef TOURIST
1765. 			      obj == uarmu ||
1766. #endif
1767. 			      (obj->cursed && (obj == uarmh || obj == uarms)) ||
1768. 			      welded(obj)))
1769. 				otmp = obj;
1770. 			/* reached the mark and found some stuff to drop? */
1771. 			if (--i < 0 && otmp) break;
1772. 
1773. 			/* else continue */
1774. 		}
1775. 
1776. 		/* nothing to drop and still overweight */
1777. 		if (!otmp) return(FALSE);
1778. 
1779. 		if (otmp == uarmh) (void) Helmet_off();
1780. 		else if (otmp == uarms) (void) Shield_off();
1781. 		else if (otmp == uwep) setuwep((struct obj *)0);
1782. 		*lostsome = TRUE;
1783. 		dropx(otmp);
1784. 		invc--;
1785. 	}
1786. 	return(TRUE);
1787. }
1788. 
1789. /*
1790.  *  return(TRUE) == player relocated
1791.  */
1792. boolean
1793. drown()
1794. {
1795. 	boolean inpool_ok = FALSE, crawl_ok;
1796. 	int i, x, y;
1797. 
1798. 	/* happily wading in the same contiguous pool */
1799. 	if (u.uinwater && is_pool(u.ux-u.dx,u.uy-u.dy) &&
1800. 	    (is_swimmer(uasmon) || Amphibious)) {
1801. 		/* water effects on objects every now and then */
1802. 		if (!rn2(5)) inpool_ok = TRUE;
1803. 		else return(FALSE);
1804. 	}
1805. 
1806. 	if (!u.uinwater) {
1807. 	    You("%s into the water%c",
1808. 		Is_waterlevel(&u.uz) ? "plunge" : "fall",
1809. 		Amphibious ? '.' : '!');
1810. 	    if(!is_swimmer(uasmon))
1811. 		if (!Is_waterlevel(&u.uz))
1812. 		    You("sink like %s.",
1813. 			Hallucination ? "the Titanic" : "a rock");
1814. 	}
1815. 
1816. 	water_damage(invent, FALSE, FALSE);
1817. 
1818. 	if(u.umonnum == PM_GREMLIN && rn2(3)) {
1819. 		struct monst *mtmp;
1820. 		if ((mtmp = cloneu()) != 0) {
1821. 			mtmp->mhpmax = (u.mhmax /= 2);
1822. 			You("multiply.");
1823. 		}
1824. 	}
1825. 	if (inpool_ok) return(FALSE);
1826. 
1827. 	if ((i = number_leashed()) > 0) {
1828. 		pline_The("leash%s slip%s loose.",
1829. 			(i > 1) ? "es" : "",
1830. 			(i > 1) ? "" : "s");
1831. 		unleash_all();
1832. 	}
1833. 
1834. 	if (Amphibious || is_swimmer(uasmon)) {
1835. 		if (Amphibious) {
1836. 			if (flags.verbose)
1837. 				pline("But you aren't drowning.");
1838. 			if (!Is_waterlevel(&u.uz))
1839. 				if (Hallucination)
1840. 					Your("keel hits the bottom.");
1841. 				else
1842. 					You("touch bottom.");
1843. 		}
1844. 		if (Punished) {
1845. 			unplacebc();
1846. 			placebc();
1847. 		}
1848. 		vision_recalc(2);	/* unsee old position */
1849. 		u.uinwater = 1;
1850. 		under_water(1);
1851. 		vision_full_recalc = 1;
1852. 		return(FALSE);
1853. 	}
1854. 	if((Teleportation || can_teleport(uasmon)) &&
1855. 	   (Teleport_control || rn2(3) < Luck+2)) {
1856. 		You("attempt a teleport spell.");	/* utcsri!carroll */
1857. 		(void) dotele();
1858. 		if(!is_pool(u.ux,u.uy))
1859. 			return(TRUE);
1860. 	}
1861. 	crawl_ok = FALSE;
1862. 	/* look around for a place to crawl to */
1863. 	for (i = 0; i < 100; i++) {
1864. 		x = rn1(3,u.ux - 1);
1865. 		y = rn1(3,u.uy - 1);
1866. 		if (goodpos(x, y, (struct monst *)0, &playermon)
1867. 			|| goodpos(x, y, (struct monst *)0, uasmon)) {
1868. 			crawl_ok = TRUE;
1869. 			goto crawl;
1870. 		}
1871. 	}
1872. 	/* one more scan */
1873. 	for (x = u.ux - 1; x <= u.ux + 1; x++)
1874. 		for (y = u.uy - 1; y <= u.uy + 1; y++)
1875. 			if (goodpos(x, y, (struct monst *)0, &playermon)
1876. 				|| goodpos(x, y, (struct monst *)0, uasmon)) {
1877. 				crawl_ok = TRUE;
1878. 				goto crawl;
1879. 			}
1880. crawl:;
1881. 	if (crawl_ok) {
1882. 		boolean lost = FALSE;
1883. 		/* time to do some strip-tease... */
1884. 		boolean succ = Is_waterlevel(&u.uz) ? TRUE :
1885. 				emergency_disrobe(&lost);
1886. 
1887. 		You("try to crawl out of the water.");
1888. 		if (lost)
1889. 			You("dump some of your gear to lose weight...");
1890. 		if (succ) {
1891. 			pline("Pheew!  That was close.");
1892. 			teleds(x,y);
1893. 			return(TRUE);
1894. 		}
1895. 		/* still too much weight */
1896. 		pline("But in vain.");
1897. 	}
1898. 	u.uinwater = 1;
1899. 	You("drown.");
1900. 	killer_format = KILLED_BY_AN;
1901. 	killer = (levl[u.ux][u.uy].typ == POOL || Is_medusa_level(&u.uz)) ?
1902. 	    "pool of water" : "moat";
1903. 	done(DROWNING);
1904. 	/* oops, we're still alive.  better get out of the water. */
1905. 	while (!safe_teleds()) {
1906. 		pline("You're still drowning.");
1907. 		done(DROWNING);
1908. 	}
1909. 	u.uinwater = 0;
1910. 	You("find yourself back %s.", Is_waterlevel(&u.uz) ?
1911. 		"in an air bubble" : "on land");
1912. 	return(TRUE);
1913. }
1914. 
1915. void
1916. drain_en(n)
1917. register int n;
1918. {
1919. 	if (!u.uenmax) return;
1920. 	You_feel("your magical energy drain away!");
1921. 	u.uen -= n;
1922. 	if(u.uen < 0)  {
1923. 		u.uenmax += u.uen;
1924. 		if(u.uenmax < 0) u.uenmax = 0;
1925. 		u.uen = 0;
1926. 	}
1927. 	flags.botl = 1;
1928. }
1929. 
1930. int
1931. dountrap()	/* disarm a trap */
1932. {
1933. 	if (near_capacity() >= HVY_ENCUMBER) {
1934. 	    pline("You're too strained to do that.");
1935. 	    return 0;
1936. 	}
1937. 	if (nohands(uasmon) || !uasmon->mmove) {
1938. 	    pline("And just how do you expect to do that?");
1939. 	    return 0;
1940. 	} else if (u.ustuck && sticks(uasmon)) {
1941. 	    pline("You'll have to let go of %s first.", mon_nam(u.ustuck));
1942. 	    return 0;
1943. 	}
1944. 	if (u.ustuck || (welded(uwep) && bimanual(uwep))) {
1945. 	    Your("%s seem to be too busy for that.",
1946. 		 makeplural(body_part(HAND)));
1947. 	    return 0;
1948. 	}
1949. 	return untrap(FALSE);
1950. }
1951. #endif /* OVLB */
1952. #ifdef OVL2
1953. 
1954. /* Probability of disabling a trap.  Helge Hafting */
1955. STATIC_OVL int
1956. untrap_prob(ttmp)
1957. struct trap *ttmp;
1958. {
1959. 	int chance = 3;
1960. 
1961. 	if (Confusion || Hallucination) chance++;
1962. 	if (Blind) chance++;
1963. 	if (Stunned) chance += 2;
1964. 	if (Fumbling) chance *= 2;
1965. 	/* Your own traps are better known than others. */
1966. 	if (ttmp && ttmp->madeby_u) chance--;
1967. 	if (Role_is('R')) {
1968. 	    if (rn2(2 * MAXULEV) < u.ulevel) chance--;
1969. 	    if (u.uhave.questart && chance > 1) chance--;
1970. 	}
1971. 	return rn2(chance);
1972. }
1973. 
1974. /* Replace trap with object(s).  Helge Hafting */
1975. STATIC_OVL void
1976. cnv_trap_obj(otyp, cnt, ttmp)
1977. int otyp;
1978. int cnt;
1979. struct trap *ttmp;
1980. {
1981. 	struct obj *otmp = mksobj(otyp, TRUE, FALSE);
1982. 	otmp->quan=cnt;
1983. 	otmp->owt = weight(otmp);
1984. 	place_object(otmp, ttmp->tx, ttmp->ty);
1985. 	/* Sell your own traps only... */
1986. 	if (ttmp->madeby_u) sellobj(otmp, ttmp->tx, ttmp->ty);
1987. 	stackobj(otmp);
1988. 	newsym(ttmp->tx, ttmp->ty);
1989. 	deltrap(ttmp);
1990. }
1991. 
1992. /* while attempting to disarm an adjacent trap, we've fallen into it */
1993. STATIC_OVL void
1994. move_into_trap(ttmp)
1995. struct trap *ttmp;
1996. {
1997. 	int bc;
1998. 	xchar x = ttmp->tx, y = ttmp->ty, bx, by, cx, cy;
1999. 	boolean unused;
2000. 
2001. 	/* we know there's no monster in the way, and we're not trapped */
2002. 	if (!Punished || drag_ball(x, y, &bc, &bx, &by, &cx, &cy, &unused)) {
2003. 	    u.ux0 = u.ux,  u.uy0 = u.uy;
2004. 	    u.ux = x,  u.uy = y;
2005. 	    u.umoved = TRUE;
2006. 	    newsym(u.ux0, u.uy0);
2007. 	    vision_recalc(1);
2008. 	    check_leash(u.ux0, u.uy0);
2009. 	    if (Punished) move_bc(0, bc, bx, by, cx, cy);
2010. 	    spoteffects();	/* dotrap() */
2011. 	    exercise(A_WIS, FALSE);
2012. 	}
2013. }
2014. 
2015. /* 0: doesn't even try
2016.  * 1: tries and fails
2017.  * 2: succeeds
2018.  */
2019. STATIC_OVL int
2020. try_disarm(ttmp, force_failure)
2021. struct trap *ttmp;
2022. boolean force_failure;
2023. {
2024. 	struct monst *mtmp = m_at(ttmp->tx,ttmp->ty);
2025. 	int ttype = ttmp->ttyp;
2026. 	boolean under_u = (!u.dx && !u.dy);
2027. 
2028. 	/* Test for monster first, monsters are displayed instead of trap. */
2029. 	if (mtmp && (!mtmp->mtrapped || ttype != BEAR_TRAP)) {
2030. 		pline("%s is in the way.", Monnam(mtmp));
2031. 		return 0;
2032. 	}
2033. 	/* We might be forced to move onto the trap's location. */
2034. 	if (sobj_at(BOULDER, ttmp->tx, ttmp->ty)
2035. 				&& !passes_walls(uasmon) && !under_u) {
2036. 		pline("There is a boulder in your way.");
2037. 		return 0;
2038. 	}
2039. 	/* untrappable traps are located on the ground. */
2040. 	if (!can_reach_floor()) {
2041. 		You("are unable to reach the %s!",
2042. 			defsyms[trap_to_defsym(ttype)].explanation);
2043. 		return 0;
2044. 	}
2045. 
2046. 	/* Will our hero succeed? */
2047. 	if (force_failure || untrap_prob(ttmp)) {
2048. 		if (rnl(5)) {
2049. 		    pline("Whoops...");
2050. 		    if (mtmp) {		/* must be a bear trap */
2051. 			if (mtmp->mtame) abuse_dog(mtmp);
2052. 			if ((mtmp->mhp -= rnd(4)) <= 0) killed(mtmp);
2053. 		    } else if (under_u) {
2054. 			dotrap(ttmp);
2055. 		    } else {
2056. 			move_into_trap(ttmp);
2057. 		    }
2058. 		} else {
2059. 		    pline("%s %s is difficult to disarm.",
2060. 			  ttmp->madeby_u ? "Your" : under_u ? "This" : "That",
2061. 			  defsyms[trap_to_defsym(ttype)].explanation);
2062. 		}
2063. 		return 1;
2064. 	}
2065. 	return 2;
2066. }
2067. 
2068. STATIC_OVL void
2069. reward_untrap(ttmp, mtmp)
2070. struct trap *ttmp;
2071. struct monst *mtmp;
2072. {
2073. 	if (!ttmp->madeby_u) {
2074. 		if (rnl(10)<8 && !mtmp->mpeaceful &&
2075. 						mtmp->data->mlet != S_HUMAN) {
2076. 			mtmp->mpeaceful = 1;
2077. 			pline("%s is grateful.", Monnam(mtmp));
2078. 		}
2079. 		/* Helping someone out of a trap is a nice thing to do,
2080. 		 * A lawful may be rewarded, but not too often.  */
2081. 		if (!rn2(3) && !rnl(8) && u.ualign.type == A_LAWFUL) {
2082. 			adjalign(1);
2083. 			You_feel("that you did the right thing.");
2084. 		}
2085. 	}
2086. }
2087. 
2088. STATIC_OVL int
2089. disarm_beartrap(ttmp) /* Helge Hafting */
2090. struct trap *ttmp;
2091. {
2092. 	struct monst *mtmp;
2093. 	int fails = try_disarm(ttmp, FALSE);
2094. 
2095. 	if (fails < 2) return fails;
2096. 
2097. 	/* ok, disarm it. */
2098. 
2099. 	/* untrap the monster, if any.
2100. 	   There's no need for a cockatrice test, only the trap is touched */
2101. 	if ((mtmp = m_at(ttmp->tx,ttmp->ty)) != 0) {
2102. 		mtmp->mtrapped = 0;
2103. 		You("remove %s bear trap from %s.", the_your[ttmp->madeby_u],
2104. 			mon_nam(mtmp));
2105. 		reward_untrap(ttmp, mtmp);
2106. 	} else You("disarm %s bear trap.", the_your[ttmp->madeby_u]);
2107. 	cnv_trap_obj(BEARTRAP, 1, ttmp);
2108. 	return 1;
2109. }
2110. 
2111. STATIC_OVL int
2112. disarm_landmine(ttmp) /* Helge Hafting */
2113. struct trap *ttmp;
2114. {
2115. 	int fails = try_disarm(ttmp, FALSE);
2116. 
2117. 	if (fails < 2) return fails;
2118. 	You("disarm %s land mine.", the_your[ttmp->madeby_u]);
2119. 	cnv_trap_obj(LAND_MINE, 1, ttmp);
2120. 	return 1;
2121. }
2122. 
2123. /* getobj will filter down to cans of grease and known potions of oil */
2124. static NEARDATA const char oil[] = { ALL_CLASSES, TOOL_CLASS, POTION_CLASS, 0 };
2125. 
2126. /* it may not make much sense to use grease on floor boards, but so what? */
2127. STATIC_OVL int
2128. disarm_squeaky_board(ttmp)
2129. struct trap *ttmp;
2130. {
2131. 	struct obj *obj;
2132. 	boolean bad_tool;
2133. 	int fails;
2134. 
2135. 	obj = getobj(oil, "untrap with");
2136. 	if (!obj) return 0;
2137. 
2138. 	bad_tool = (obj->cursed ||
2139. 			((obj->otyp != POT_OIL || obj->lamplit) &&
2140. 			 (obj->otyp != CAN_OF_GREASE || !obj->spe)));
2141. 
2142. 	fails = try_disarm(ttmp, bad_tool);
2143. 	if (fails < 2) return fails;
2144. 
2145. 	/* successfully used oil or grease to fix squeaky board */
2146. 	if (obj->otyp == CAN_OF_GREASE) {
2147. 	    check_unpaid(obj);
2148. 	    obj->spe--;
2149. 	} else {
2150. 	    useup(obj);	/* oil */
2151. 	    makeknown(POT_OIL);
2152. 	}
2153. 	You("repair the squeaky board.");	/* no madeby_u */
2154. 	deltrap(ttmp);
2155. 	newsym(u.ux + u.dx, u.uy + u.dy);
2156. 	more_experienced(1, 5);
2157. 	return 1;
2158. }
2159. 
2160. /* removes traps that shoot arrows, darts, etc. */
2161. STATIC_OVL int
2162. disarm_shooting_trap(ttmp, otyp)
2163. struct trap *ttmp;
2164. int otyp;
2165. {
2166. 	int fails = try_disarm(ttmp, FALSE);
2167. 
2168. 	if (fails < 2) return fails;
2169. 	You("disarm %s trap", the_your[ttmp->madeby_u]);
2170. 	cnv_trap_obj(otyp, 50-rnl(50), ttmp);
2171. 	return 1;
2172. }
2173. 
2174. /* Is the weight too heavy?
2175.  * Formula as in near_capacity() & check_capacity() */
2176. STATIC_OVL int
2177. try_lift(mtmp, ttmp, wt, stuff)
2178. struct monst *mtmp;
2179. struct trap *ttmp;
2180. int wt;
2181. boolean stuff;
2182. {
2183. 	int wc = weight_cap();
2184. 
2185. 	if ((((wt<<1) / wc)+1) >= EXT_ENCUMBER) {
2186. 		pline("%s is %s for you to lift.", Monnam(mtmp),
2187. 			stuff ? "carrying too much" : "too heavy");
2188. 		if (!ttmp->madeby_u && !mtmp->mpeaceful
2189. 			&& mtmp->data->mlet != S_HUMAN && rnl(10) < 3) {
2190. 		    mtmp->mpeaceful = 1;
2191. 		    pline("%s thinks it was nice of you to try.", Monnam(mtmp));
2192. 		}
2193. 		return 0;
2194. 	}
2195. 	return 1;
2196. }
2197. 
2198. /* Help trapped monster (out of a (spiked) pit) */
2199. STATIC_OVL int
2200. help_monster_out(mtmp, ttmp)
2201. struct monst *mtmp;
2202. struct trap *ttmp;
2203. {
2204. 	int wt;
2205. 	struct obj *otmp;
2206. 
2207. 	/*
2208. 	 * This works when levitating too -- consistent with the ability
2209. 	 * to hit monsters while levitating.
2210. 	 *
2211. 	 * Should perhaps check that our hero has arms/hands at the
2212. 	 * moment.  Helping can also be done by engulfing...
2213. 	 *
2214. 	 * Test the monster first - monsters are displayed before traps.
2215. 	 */
2216. 	if (!mtmp->mtrapped) {
2217. 		pline("%s isn't trapped.", Monnam(mtmp));
2218. 		return 0;
2219. 	}
2220. 	/* Do you have the necessary capacity to lift anything? */
2221. 	if (check_capacity((char *)0)) return 1;
2222. 
2223. 	/* Will our hero succeed? */
2224. 	if (untrap_prob(ttmp)) {
2225. 		You("try to reach out your %s, but %s backs away skeptically.",
2226. 			makeplural(body_part(ARM)),
2227. 			mon_nam(mtmp));
2228. 		return 1;
2229. 	}
2230. 
2231. 
2232. 	/* is it a cockatrice?... */
2233. 	if (mtmp->data == &mons[PM_COCKATRICE] && !uarmg
2234. 		    && !resists_ston(&youmonst)) {
2235. 		You("grab the trapped cockatrice using your bare %s.",
2236. 			makeplural(body_part(HAND)));
2237. 
2238. 		if (poly_when_stoned(uasmon) && polymon(PM_STONE_GOLEM))
2239. 			display_nhwindow(WIN_MESSAGE, FALSE);
2240. 		else {
2241. 		      instapetrify("trying to help a cockatrice out of a pit");
2242. 			return 1;
2243. 		}
2244. 	}
2245. 	You("reach out your %s and grab %s.",
2246. 			makeplural(body_part(ARM)), mon_nam(mtmp));
2247. 
2248. 	/* is the monster too heavy? */
2249. 	wt = inv_weight() + mtmp->data->cwt;
2250. 	if (!try_lift(mtmp, ttmp, wt, FALSE)) return 1;
2251. 
2252. 	/* is the monster with inventory too heavy? */
2253. 	for (otmp = mtmp->minvent; otmp; otmp=otmp->nobj)
2254. 		wt += otmp->owt;
2255. 	if (!try_lift(mtmp, ttmp, wt, TRUE)) return 1;
2256. 
2257. 	You("pull %s out of the pit.", mon_nam(mtmp));
2258. 	mtmp->mtrapped = 0;
2259. 	reward_untrap(ttmp, mtmp);
2260. 	return 1;
2261. }
2262. 
2263. int
2264. untrap(force)
2265. boolean force;
2266. {
2267. 	register struct obj *otmp;
2268. 	register boolean confused = (Confusion > 0 || Hallucination > 0);
2269. 	register int x,y;
2270. 	int ch;
2271. 	struct trap *ttmp;
2272. 	struct monst *mtmp;
2273. 	boolean trap_skipped = FALSE;
2274. 
2275. 	if(!getdir((char *)0)) return(0);
2276. 	x = u.ux + u.dx;
2277. 	y = u.uy + u.dy;
2278. 
2279. 	if ((ttmp = t_at(x,y)) && ttmp->tseen) {
2280. 		if (u.utrap) {
2281. 			You("cannot deal with traps while trapped!");
2282. 			return 1;
2283. 		}
2284. 		switch(ttmp->ttyp) {
2285. 			case BEAR_TRAP:
2286. 				return disarm_beartrap(ttmp);
2287. 			case LANDMINE:
2288. 				return disarm_landmine(ttmp);
2289. 			case SQKY_BOARD:
2290. 				return disarm_squeaky_board(ttmp);
2291. 			case DART_TRAP:
2292. 				return disarm_shooting_trap(ttmp, DART);
2293. 			case ARROW_TRAP:
2294. 				return disarm_shooting_trap(ttmp, ARROW);
2295. 			case PIT:
2296. 			case SPIKED_PIT:
2297. 				if (!u.dx && !u.dy) {
2298. 				    You("are already on the edge of the pit.");
2299. 				    return 0;
2300. 				}
2301. 				if (!(mtmp = m_at(x,y))) {
2302. 				    pline("Try filling the pit instead.");
2303. 				    return 0;
2304. 				}
2305. 				return help_monster_out(mtmp, ttmp);
2306. 			default:
2307. 				You("cannot disable %s trap.", (u.dx || u.dy) ? "that" : "this");
2308. 				return 0;
2309. 		} /* end switch */
2310. 	} /* end if */
2311. 
2312. 	if(!u.dx && !u.dy) {
2313. 	    for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
2314. 		if(Is_box(otmp)) {
2315. 		    pline("There is %s here.", doname(otmp));
2316. 
2317. 		    switch (ynq("Check for traps?")) {
2318. 			case 'q': return(0);
2319. 			case 'n': continue;
2320. 		    }
2321. 
2322. 		    if((otmp->otrapped && (force || (!confused
2323. 				&& rn2(MAXULEV + 1 - u.ulevel) < 10)))
2324. 		       || (!force && confused && !rn2(3))) {
2325. 			You("find a trap on %s!", the(xname(otmp)));
2326. 			exercise(A_WIS, TRUE);
2327. 
2328. 			switch (ynq("Disarm it?")) {
2329. 			    case 'q': return(1);
2330. 			    case 'n': trap_skipped = TRUE;  continue;
2331. 			}
2332. 
2333. 			if(otmp->otrapped) {
2334. 			    exercise(A_DEX, TRUE);
2335. 			    ch = ACURR(A_DEX) + u.ulevel;
2336. 			    if (Role_is('R')) ch *= 2;
2337. 			    if(!force && (confused || Fumbling ||
2338. 				rnd(75+level_difficulty()/2) > ch)) {
2339. 				(void) chest_trap(otmp, FINGER, TRUE);
2340. 			    } else {
2341. 				You("disarm it!");
2342. 				otmp->otrapped = 0;
2343. 			    }
2344. 			} else pline("That %s was not trapped.", doname(otmp));
2345. 			return(1);
2346. 		    } else {
2347. 			You("find no traps on %s.", the(xname(otmp)));
2348. 			return(1);
2349. 		    }
2350. 		}
2351. 
2352. 	    You(trap_skipped ? "find no other traps here."
2353. 			     : "know of no traps here.");
2354. 	    return(0);
2355. 	}
2356. 
2357. 	if ((mtmp = m_at(x,y))				&&
2358. 		mtmp->m_ap_type == M_AP_FURNITURE	&&
2359. 		(mtmp->mappearance == S_hcdoor ||
2360. 			mtmp->mappearance == S_vcdoor)	&&
2361. 		!Protection_from_shape_changers)	 {
2362. 
2363. 	    stumble_onto_mimic(mtmp);
2364. 	    return(1);
2365. 	}
2366. 
2367. 	if (!IS_DOOR(levl[x][y].typ)) {
2368. 	    if ((ttmp = t_at(x,y)) && ttmp->tseen)
2369. 		You("cannot disable that trap.");
2370. 	    else
2371. 		You("know of no traps there.");
2372. 	    return(0);
2373. 	}
2374. 
2375. 	switch (levl[x][y].doormask) {
2376. 	    case D_NODOOR:
2377. 		You("%s no door there.", Blind ? "feel" : "see");
2378. 		return(0);
2379. 	    case D_ISOPEN:
2380. 		pline("This door is safely open.");
2381. 		return(0);
2382. 	    case D_BROKEN:
2383. 		pline("This door is broken.");
2384. 		return(0);
2385. 	}
2386. 
2387. 	if ((levl[x][y].doormask & D_TRAPPED
2388. 	     && (force ||
2389. 		 (!confused && rn2(MAXULEV - u.ulevel + 11) < 10)))
2390. 	    || (!force && confused && !rn2(3))) {
2391. 		You("find a trap on the door!");
2392. 		exercise(A_WIS, TRUE);
2393. 		if (ynq("Disarm it?") != 'y') return(1);
2394. 		if (levl[x][y].doormask & D_TRAPPED) {
2395. 		    ch = 15 + (Role_is('R') ? u.ulevel*3 : u.ulevel);
2396. 		    exercise(A_DEX, TRUE);
2397. 		    if(!force && (confused || Fumbling ||
2398. 				     rnd(75+level_difficulty()/2) > ch)) {
2399. 			    You("set it off!");
2400. 			    b_trapped("door", FINGER);
2401. 		    } else
2402. 			    You("disarm it!");
2403. 		    levl[x][y].doormask &= ~D_TRAPPED;
2404. 		} else pline("This door was not trapped.");
2405. 		return(1);
2406. 	} else {
2407. 		You("find no traps on the door.");
2408. 		return(1);
2409. 	}
2410. }
2411. #endif /* OVL2 */
2412. #ifdef OVLB
2413. 
2414. /* only called when the player is doing something to the chest directly */
2415. boolean
2416. chest_trap(obj, bodypart, disarm)
2417. register struct obj *obj;
2418. register int bodypart;
2419. boolean disarm;
2420. {
2421. 	register struct obj *otmp = obj, *otmp2;
2422. 	char	buf[80];
2423. 	const char *msg;
2424. 
2425. 	You(disarm ? "set it off!" : "trigger a trap!");
2426. 	display_nhwindow(WIN_MESSAGE, FALSE);
2427. 	if (Luck > -13 && rn2(13+Luck) > 7) {	/* saved by luck */
2428. 	    /* trap went off, but good luck prevents damage */
2429. 	    switch (rn2(13)) {
2430. 		case 12:
2431. 		case 11:  msg = "explosive charge is a dud";  break;
2432. 		case 10:
2433. 		case  9:  msg = "electric charge is grounded";  break;
2434. 		case  8:
2435. 		case  7:  msg = "flame fizzles out";  break;
2436. 		case  6:
2437. 		case  5:
2438. 		case  4:  msg = "poisoned needle misses";  break;
2439. 		case  3:
2440. 		case  2:
2441. 		case  1:
2442. 		case  0:  msg = "gas cloud blows away";  break;
2443. 		default:  impossible("chest disarm bug");  msg = (char *)0;
2444. 			  break;
2445. 	    }
2446. 	    if (msg) pline("But luckily the %s!", msg);
2447. 	} else {
2448. 	    switch(rn2(20) ? ((Luck >= 13) ? 0 : rn2(13-Luck)) : rn2(26)) {
2449. 		case 25:
2450. 		case 24:
2451. 		case 23:
2452. 		case 22:
2453. 		case 21: {
2454. 			  struct monst *shkp = 0;
2455. 			  long loss = 0L;
2456. 			  boolean costly, insider;
2457. 			  register xchar ox = obj->ox, oy = obj->oy;
2458. 
2459. 			  /* the obj location need not be that of player */
2460. 			  costly = (costly_spot(ox, oy) &&
2461. 				   (shkp = shop_keeper(*in_rooms(ox, oy,
2462. 				    SHOPBASE))) != (struct monst *)0);
2463. 			  insider = (*u.ushops && inside_shop(u.ux, u.uy) &&
2464. 				    *in_rooms(ox, oy, SHOPBASE) == *u.ushops);
2465. 
2466. 			  pline("%s explodes!", The(xname(obj)));
2467. 			  Sprintf(buf, "exploding %s", xname(obj));
2468. 
2469. 			  if(costly)
2470. 			      loss += stolen_value(obj, ox, oy,
2471. 						(boolean)shkp->mpeaceful, TRUE);
2472. 			  delete_contents(obj);
2473. 			  for(otmp = level.objects[u.ux][u.uy];
2474. 							otmp; otmp = otmp2) {
2475. 			      otmp2 = otmp->nexthere;
2476. 			      if(costly)
2477. 				  loss += stolen_value(otmp, otmp->ox,
2478. 					  otmp->oy, (boolean)shkp->mpeaceful,
2479. 					  TRUE);
2480. 			      delobj(otmp);
2481. 			  }
2482. 			  wake_nearby();
2483. 			  losehp(d(6,6), buf, KILLED_BY_AN);
2484. 			  exercise(A_STR, FALSE);
2485. 			  if(costly && loss) {
2486. 			      if(insider)
2487. 			      You("owe %ld zorkmids for objects destroyed.",
2488. 							loss);
2489. 			      else {
2490. 				  You("caused %ld zorkmids worth of damage!",
2491. 							loss);
2492. 				  make_angry_shk(shkp, ox, oy);
2493. 			      }
2494. 			  }
2495. 			  return TRUE;
2496. 			}
2497. 		case 20:
2498. 		case 19:
2499. 		case 18:
2500. 		case 17:
2501. 			pline("A cloud of noxious gas billows from %s.",
2502. 							the(xname(obj)));
2503. 			poisoned("gas cloud", A_STR, "cloud of poison gas",15);
2504. 			exercise(A_CON, FALSE);
2505. 			break;
2506. 		case 16:
2507. 		case 15:
2508. 		case 14:
2509. 		case 13:
2510. 			You_feel("a needle prick your %s.",body_part(bodypart));
2511. 			poisoned("needle", A_CON, "poisoned needle",10);
2512. 			exercise(A_CON, FALSE);
2513. 			break;
2514. 		case 12:
2515. 		case 11:
2516. 		case 10:
2517. 		case 9:
2518. 			dofiretrap(obj);
2519. 			break;
2520. 		case 8:
2521. 		case 7:
2522. 		case 6: {
2523. 			int dmg;
2524. 
2525. 			You("are jolted by a surge of electricity!");
2526. 			if(Shock_resistance)  {
2527. 			    shieldeff(u.ux, u.uy);
2528. 			    You("don't seem to be affected.");
2529. 			    dmg = 0;
2530. 			} else
2531. 			    dmg = d(4, 4);
2532. 			destroy_item(RING_CLASS, AD_ELEC);
2533. 			destroy_item(WAND_CLASS, AD_ELEC);
2534. 			if (dmg) losehp(dmg, "electric shock", KILLED_BY_AN);
2535. 			break;
2536. 		      }
2537. 		case 5:
2538. 		case 4:
2539. 		case 3:
2540. 			pline("Suddenly you are frozen in place!");
2541. 			nomul(-d(5, 6));
2542. 			exercise(A_DEX, FALSE);
2543. 			nomovemsg = "You can move again.";
2544. 			break;
2545. 		case 2:
2546. 		case 1:
2547. 		case 0:
2548. 			pline("A cloud of %s gas billows from %s.",
2549. 						hcolor((char *)0),
2550. 						the(xname(obj)));
2551. 			if(!Stunned) {
2552. 			    if (Hallucination)
2553. 				pline("What a groovy feeling!");
2554. 			    else if (Blind)
2555. 				You("stagger and get dizzy...");
2556. 			    else
2557. 				You("stagger and your vision blurs...");
2558. 			}
2559. 			make_stunned(HStun + rn1(7, 16),FALSE);
2560. 			make_hallucinated(HHallucination + rn1(5, 16),FALSE,0L);
2561. 			break;
2562. 		default: impossible("bad chest trap");
2563. 			break;
2564. 	    }
2565. 	    bot();			/* to get immediate botl re-display */
2566. 	}
2567. 	otmp->otrapped = 0;		/* these traps are one-shot things */
2568. 
2569. 	return FALSE;
2570. }
2571. 
2572. #endif /* OVLB */
2573. #ifdef OVL0
2574. 
2575. struct trap *
2576. t_at(x,y)
2577. register int x, y;
2578. {
2579. 	register struct trap *trap = ftrap;
2580. 	while(trap) {
2581. 		if(trap->tx == x && trap->ty == y) return(trap);
2582. 		trap = trap->ntrap;
2583. 	}
2584. 	return((struct trap *)0);
2585. }
2586. 
2587. #endif /* OVL0 */
2588. #ifdef OVLB
2589. 
2590. void
2591. deltrap(trap)
2592. register struct trap *trap;
2593. {
2594. 	register struct trap *ttmp;
2595. 
2596. 	if(trap == ftrap)
2597. 		ftrap = ftrap->ntrap;
2598. 	else {
2599. 		for(ttmp = ftrap; ttmp->ntrap != trap; ttmp = ttmp->ntrap) ;
2600. 		ttmp->ntrap = trap->ntrap;
2601. 	}
2602. 	dealloc_trap(trap);
2603. }
2604. 
2605. boolean delfloortrap(ttmp)
2606. register struct trap *ttmp;
2607. {
2608. 	/* Destroy a trap that emanates from the floor. */
2609. 	/* some of these are arbitrary -dlc */
2610. 	if (ttmp && ((ttmp->ttyp == SQKY_BOARD) ||
2611. 		     (ttmp->ttyp == BEAR_TRAP) ||
2612. 		     (ttmp->ttyp == LANDMINE) ||
2613. 		     (ttmp->ttyp == FIRE_TRAP) ||
2614. 		     (ttmp->ttyp == PIT) ||
2615. 		     (ttmp->ttyp == SPIKED_PIT) ||
2616. 		     (ttmp->ttyp == HOLE) ||
2617. 		     (ttmp->ttyp == TRAPDOOR) ||
2618. 		     (ttmp->ttyp == TELEP_TRAP) ||
2619. 		     (ttmp->ttyp == LEVEL_TELEP) ||
2620. 		     (ttmp->ttyp == WEB) ||
2621. 		     (ttmp->ttyp == MAGIC_TRAP) ||
2622. 		     (ttmp->ttyp == ANTI_MAGIC))) {
2623. 	    register struct monst *mtmp;
2624. 
2625. 	    if (ttmp->tx == u.ux && ttmp->ty == u.uy) {
2626. 		u.utrap = 0;
2627. 		u.utraptype = 0;
2628. 	    } else if ((mtmp = m_at(ttmp->tx, ttmp->ty)) != 0) {
2629. 		mtmp->mtrapped = 0;
2630. 	    }
2631. 	    deltrap(ttmp);
2632. 	    return TRUE;
2633. 	} else
2634. 	    return FALSE;
2635. }
2636. 
2637. /* used for doors (also tins).  can be used for anything else that opens. */
2638. void
2639. b_trapped(item, bodypart)
2640. register const char *item;
2641. register int bodypart;
2642. {
2643. 	register int lvl = level_difficulty();
2644. 	int dmg = rnd(5 + (lvl < 5 ? lvl : 2+lvl/2));
2645. 
2646. 	pline("KABOOM!!  %s was booby-trapped!", The(item));
2647. 	wake_nearby();
2648. 	losehp(dmg, "explosion", KILLED_BY_AN);
2649. 	exercise(A_STR, FALSE);
2650. 	if (bodypart) exercise(A_CON, FALSE);
2651. 	make_stunned(HStun + dmg, TRUE);
2652. }
2653. 
2654. /* Monster is hit by trap. */
2655. /* Note: doesn't work if both obj and d_override are null */
2656. STATIC_OVL boolean
2657. thitm(tlev, mon, obj, d_override)
2658. register int tlev;
2659. register struct monst *mon;
2660. register struct obj *obj;
2661. int d_override;
2662. {
2663. 	register int strike;
2664. 	register boolean trapkilled = FALSE;
2665. 
2666. 	if (d_override) strike = 1;
2667. 	else if (obj) strike = (find_mac(mon) + tlev + obj->spe <= rnd(20));
2668. 	else strike = (find_mac(mon) + tlev <= rnd(20));
2669. 
2670. 	/* Actually more accurate than thitu, which doesn't take
2671. 	 * obj->spe into account.
2672. 	 */
2673. 	if(!strike) {
2674. 		if (cansee(mon->mx, mon->my))
2675. 			pline("%s is almost hit by %s!", Monnam(mon),
2676. 								doname(obj));
2677. 	} else {
2678. 		int dam = 1;
2679. 
2680. 		if (obj && cansee(mon->mx, mon->my))
2681. 			pline("%s is hit by %s!", Monnam(mon), doname(obj));
2682. 		if (d_override) dam = d_override;
2683. 		else if (obj) {
2684. 			dam = dmgval(obj, mon);
2685. 			if (dam < 1) dam = 1;
2686. 		}
2687. 		if ((mon->mhp -= dam) <= 0) {
2688. 			int xx = mon->mx;
2689. 			int yy = mon->my;
2690. 
2691. 			monkilled(mon, "", AD_PHYS);
2692. 			if (mon->mhp <= 0) {
2693. 				newsym(xx, yy);
2694. 				trapkilled = TRUE;
2695. 			}
2696. 		}
2697. 	}
2698. 	if (obj && (!strike || d_override)) {
2699. 		place_object(obj, mon->mx, mon->my);
2700. 		stackobj(obj);
2701. 	} else if (obj) dealloc_obj(obj);
2702. 
2703. 	return trapkilled;
2704. }
2705. 
2706. boolean
2707. unconscious()
2708. {
2709. 	return((boolean)(multi < 0 && (!nomovemsg ||
2710. 		u.usleep ||
2711. 		!strncmp(nomovemsg,"You regain con", 15) ||
2712. 		!strncmp(nomovemsg,"You are consci", 15))));
2713. }
2714. 
2715. static char lava_killer[] = "molten lava";
2716. 
2717. boolean
2718. lava_effects()
2719. {
2720.     register struct obj *obj, *obj2;
2721.     int dmg;
2722. 
2723.     if (likes_lava(uasmon)) return FALSE;
2724. 
2725.     if (!Fire_resistance) {
2726. 	if(Wwalking) {
2727. 	    dmg = d(6,6);
2728. 	    pline_The("lava here burns you!");
2729. 	    if(dmg < u.uhp) {
2730. 		losehp(dmg, lava_killer, KILLED_BY);
2731. 		goto burn_stuff;
2732. 	    }
2733. 	} else
2734. 	    You("fall into the lava!");
2735. 
2736. 	for(obj = invent; obj; obj = obj2) {
2737. 	    obj2 = obj->nobj;
2738. 	    if(is_organic(obj) && !obj->oerodeproof) {
2739. 		if(obj->owornmask) {
2740. 		    if(obj == uarm) (void) Armor_gone();
2741. 		    else if(obj == uarmc) (void) Cloak_off();
2742. 		    else if(obj == uarmh) (void) Helmet_off();
2743. 		    else if(obj == uarms) (void) Shield_off();
2744. 		    else if(obj == uarmg) (void) Gloves_off();
2745. 		    else if(obj == uarmf) (void) Boots_off();
2746. #ifdef TOURIST
2747. 		    else if(obj == uarmu) setnotworn(obj);
2748. #endif
2749. 		    else if(obj == uleft) Ring_gone(obj);
2750. 		    else if(obj == uright) Ring_gone(obj);
2751. 		    else if(obj == ublindf) Blindf_off(obj);
2752. 		    else if(obj == uwep) uwepgone();
2753. 		    if(Lifesaved
2754. #ifdef WIZARD
2755. 		       || wizard
2756. #endif
2757. 		       ) Your("%s into flame!", aobjnam(obj, "burst"));
2758. 		}
2759. 		useup(obj);
2760. 	    }
2761. 	}
2762. 
2763. 	/* s/he died... */
2764. 	u.uhp = -1;
2765. 	killer_format = KILLED_BY;
2766. 	killer = lava_killer;
2767. 	You("burn to a crisp...");
2768. 	done(BURNING);
2769. 	while (!safe_teleds()) {
2770. 		pline("You're still burning.");
2771. 		done(BURNING);
2772. 	}
2773. 	You("find yourself back on solid %s.", surface(u.ux, u.uy));
2774. 	return(TRUE);
2775.     }
2776. 
2777.     if (!Wwalking) {
2778. 	u.utrap = rn1(4, 4) + (rn1(4, 12) << 8);
2779. 	u.utraptype = TT_LAVA;
2780. 	You("sink into the lava, but it only burns slightly!");
2781. 	if (u.uhp > 1)
2782. 	    losehp(1, lava_killer, KILLED_BY);
2783.     }
2784.     /* just want to burn boots, not all armor; destroy_item doesn't work on
2785.        armor anyway */
2786. burn_stuff:
2787.     if(uarmf && !uarmf->oerodeproof && is_organic(uarmf)) {
2788. 	/* save uarmf value because Boots_off() sets uarmf to null */
2789. 	obj = uarmf;
2790. 	Your("%s burst into flame!", xname(obj));
2791. 	(void) Boots_off();
2792. 	useup(obj);
2793.     }
2794.     destroy_item(SCROLL_CLASS, AD_FIRE);
2795.     destroy_item(SPBOOK_CLASS, AD_FIRE);
2796.     destroy_item(POTION_CLASS, AD_FIRE);
2797.     return(FALSE);
2798. }
2799. 
2800. #endif /* OVLB */
2801. 
2802. /*trap.c*/
Advertisement