Source:NetHack 3.0.0/trap.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to trap.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.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.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

1.    /*	SCCS Id: @(#)trap.c	3.0	88/10/22
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    #include	"hack.h"
6.    #include	"edog.h"
7.    #include	"trapname.h"
8.    
9.    void domagictrap();
10.   static boolean thitm();
11.   
12.   /* Generic rust-armor function.  Returns TRUE if a message was printed;
13.    * "print", if set, means to print a message (and thus to return TRUE) even
14.    * if the item could not be rusted; otherwise a message is printed and TRUE is
15.    * returned only for rustable items.
16.    */
17.   boolean
18.   rust_dmg(otmp, ostr, type, print)
19.   register struct obj *otmp;
20.   register char *ostr;
21.   int type;
22.   boolean print;
23.   {
24.   	static const char *gook[] = { "slag", "rust", "rot", "corrosion" };
25.   	static const char *action[] = { "smolder", "rust", "rot", "corrode" };
26.   	boolean vulnerable = FALSE;
27.   	boolean plural;
28.   
29.   	if (!otmp) return(FALSE);
30.   	switch(type) {
31.   		case 0:
32.   		case 2: vulnerable = is_flammable(otmp); break;
33.   		case 1: vulnerable = is_rustprone(otmp); break;
34.   		case 3: vulnerable = (otmp->otyp == BRONZE_PLATE_MAIL); break;
35.   	}
36.   
37.   	if (!print && (!vulnerable || otmp->rustfree || otmp->spe < -2))
38.   		return FALSE;
39.   
40.   	plural = is_gloves(otmp) || is_boots(otmp);
41.   
42.   	if (!vulnerable)
43.   		Your("%s %s not affected!", ostr, plural ? "are" : "is");
44.   	else if (otmp->spe >= -2) {
45.   		if (otmp->rustfree)
46.   			pline("The %s on your %s vanishes instantly!",
47.   						gook[type], ostr);
48.   		else if (otmp->blessed && !rnl(4))
49.   			pline("Somehow, your %s %s not affected!", ostr,
50.   					plural ? "are" : "is");
51.   		else {
52.   			Your("%s %s%s!", ostr, action[type],
53.   				plural ? "" : "s");
54.   			otmp->spe--;
55.   			adj_abon(otmp, -1);
56.   		}
57.   	} else Your("%s look%s quite rusted.", ostr, plural ? "" : "s");
58.   	return(TRUE);
59.   }
60.   
61.   struct trap *
62.   maketrap(x,y,typ)
63.   register int x, y, typ;
64.   {
65.   	register struct trap *ttmp;
66.   	register struct permonst *ptr;
67.   
68.   	ttmp = newtrap();
69.   	ttmp->ttyp = typ;
70.   	ttmp->tx = x;
71.   	ttmp->ty = y;
72.   	switch(typ) {
73.   	    case MONST_TRAP:	    /* create a monster in "hiding" */
74.   		if(rn2(5) && (ptr = mkclass(S_PIERCER)))
75.   			ttmp->pm = monsndx(ptr);
76.   		else
77.   			ttmp->pm = rndmonnum();
78.   		break;
79.   	    case STATUE_TRAP:	    /* create a "living" statue */
80.   		ttmp->pm = rndmonnum();
81.   		(void) mkstatue(&mons[ttmp->pm], x, y);
82.   		break;
83.   	    default:
84.   		ttmp->pm = -1;
85.   		break;
86.   	}
87.   	ttmp->tseen = 0;
88.   	ttmp->once = 0;
89.   	ttmp->ntrap = ftrap;
90.   	ftrap = ttmp;
91.   	return(ttmp);
92.   }
93.   
94.   int
95.   teleok(x, y)
96.   register int x, y;
97.   {				/* might throw him into a POOL
98.   				 * removed by GAN 10/20/86
99.   				 */
100.  #ifdef STUPID
101.  	boolean	tmp1, tmp2, tmp3;
102.  #  ifdef POLYSELF
103.  	tmp1 = isok(x,y) && (!IS_ROCK(levl[x][y].typ) ||
104.  		passes_walls(uasmon)) && !levl[x][y].mmask;
105.  #  else
106.  	tmp1 = isok(x,y) && !IS_ROCK(levl[x][y].typ) && !levl[x][y].mmask;
107.  #  endif
108.  	tmp2 = !sobj_at(BOULDER,x,y) && !t_at(x,y);
109.  	tmp3 = !(is_pool(x,y) &&
110.  	       !(Levitation || Wwalking
111.  #ifdef POLYSELF
112.  		 || is_flyer(uasmon)
113.  #endif
114.  		)) &&
115.  	       !(IS_DOOR(levl[x][y].typ) &&
116.  		     (levl[x][y].doormask & (D_LOCKED | D_CLOSED)));
117.  	return(tmp1 && tmp2 && tmp3);
118.  #else
119.  	return( isok(x,y) &&
120.  #  ifdef POLYSELF
121.  		(!IS_ROCK(levl[x][y].typ) || passes_walls(uasmon)) &&
122.  #  else
123.  		!IS_ROCK(levl[x][y].typ) &&
124.  #  endif
125.  		!levl[x][y].mmask &&
126.  		!sobj_at(BOULDER,x,y) && !t_at(x,y) &&
127.  		!(is_pool(x,y) &&
128.  		!(Levitation || Wwalking
129.  #ifdef POLYSELF
130.  		  || is_flyer(uasmon)
131.  #endif
132.  		  )) &&
133.  		!(IS_DOOR(levl[x][y].typ) &&
134.  		     (levl[x][y].doormask & (D_LOCKED | D_CLOSED)))
135.  	);
136.  #endif
137.  	/* Note: gold is permitted (because of vaults) */
138.  }
139.  
140.  static void
141.  vtele() {
142.  	register struct mkroom *croom;
143.  
144.  	for(croom = &rooms[0]; croom->hx >= 0; croom++)
145.  	    if(croom->rtype == VAULT) {
146.  		register int x, y;
147.  
148.  		x = rn2(2) ? croom->lx : croom->hx;
149.  		y = rn2(2) ? croom->ly : croom->hy;
150.  		if(teleok(x,y)) {
151.  		    teleds(x,y);
152.  		    return;
153.  		}
154.  	    }
155.  	tele();
156.  }
157.  
158.  void
159.  dotrap(trap)
160.  register struct trap *trap;
161.  {
162.  	register int ttype = trap->ttyp;
163.  	register struct monst *mtmp;
164.  	register struct obj *otmp;
165.  
166.  	nomul(0);
167.  	if(trap->tseen && !Fumbling && !(ttype == PIT
168.  	   || ttype == SPIKED_PIT
169.  #ifdef SPELLS
170.  	   || ttype == ANTI_MAGIC
171.  #endif
172.  		) && !rn2(5))
173.  		You("escape a%s.", traps[ttype]);
174.  	else {
175.  	    trap->tseen = 1;
176.  	    if(Invisible && ttype != MONST_TRAP)
177.  		newsym(trap->tx,trap->ty);
178.  	    switch(ttype) {
179.  		case SLP_GAS_TRAP:
180.  		    if(Sleep_resistance) {
181.  			You("are enveloped in a cloud of gas!");
182.  			break;
183.  		    }
184.  		    pline("A cloud of gas puts you to sleep!");
185.  		    flags.soundok = 0;
186.  		    nomul(-rnd(25));
187.  		    afternmv = Hear_again;
188.  		    break;
189.  		case BEAR_TRAP:
190.  		    if(Levitation
191.  #ifdef POLYSELF
192.  			|| is_flyer(uasmon)
193.  #endif
194.  			) {
195.  			You("%s over a bear trap.",
196.  			      Levitation ? "float" : "fly");
197.  			break;
198.  		    }
199.  		    u.utrap = 4 + rn2(4);
200.  		    u.utraptype = TT_BEARTRAP;
201.  		    pline("A bear trap closes on your %s!",
202.  			body_part(FOOT));
203.  #ifdef POLYSELF
204.  		    if(u.umonnum == PM_OWLBEAR)
205.  			You("howl in anger!");
206.  #endif
207.  		    break;
208.  		case STATUE_TRAP:
209.  		    for(otmp=fobj; otmp; otmp=otmp->nobj) {
210.  			if(otmp->otyp == STATUE && otmp->ox == u.ux &&
211.  				otmp->oy == u.uy && otmp->corpsenm == trap->pm)
212.  			    if(mtmp=makemon(&mons[trap->pm],u.ux,u.uy)) {
213.  				pline("The statue comes to life!");
214.  				delobj(otmp);
215.  				break;
216.  			    }
217.  		    }
218.  		    deltrap(trap);
219.  		    break;
220.  		case MONST_TRAP:
221.  		    if(mtmp=makemon(&mons[trap->pm],u.ux,u.uy)) {
222.  		      switch(mtmp->data->mlet) {
223.  			case S_PIERCER:
224.  			    pline("%s suddenly drops from the ceiling!",
225.  				  Xmonnam(mtmp));
226.  			    if(uarmh)
227.  				pline("Its blow glances off your helmet.");
228.  			    else
229.  				(void) thitu(3,d(4,6),"falling piercer");
230.  			    break;
231.  			default:	/* monster surprises you. */
232.  			    pline("%s attacks you by surprise!",
233.  				  Xmonnam(mtmp));
234.  			    break;
235.  		      }
236.  		    }
237.  		    deltrap(trap);
238.  		    break;
239.  		case ARROW_TRAP:
240.  		    pline("An arrow shoots out at you!");
241.  		    if(!thitu(8,rnd(6),"arrow")){
242.  			(void) mksobj_at(ARROW, u.ux, u.uy);
243.  			fobj->quan = 1;
244.  			fobj->owt = weight(fobj);
245.  		    }
246.  		    break;
247.  		case TRAPDOOR:
248.  		    if(is_maze_lev
249.  #ifdef STRONGHOLD
250.  		 	 && (dlevel > stronghold_level)
251.  #endif /* STRONGHOLD /**/
252.  		      ) {
253.  	pline("A trap door in the ceiling opens and a rock falls on your %s!",
254.  				body_part(HEAD));
255.  			if(uarmh)
256.  			    pline("Fortunately, you are wearing a helmet!");
257.  			losehp(uarmh ? 2 : d(2,10),"falling rock");
258.  			(void) mksobj_at(ROCK, u.ux, u.uy);
259.  			fobj->quan = 1;
260.  			fobj->owt = weight(fobj);
261.  			stackobj(fobj);
262.  			if(Invisible) newsym(u.ux, u.uy);
263.  		    } else {
264.  			register int newlevel = dlevel + 1;
265.  			while(!rn2(4) && newlevel < 29) newlevel++;
266.  			pline("A trap door opens up under you!");
267.  			if(Levitation || u.ustuck || dlevel == MAXLEVEL
268.  #ifdef POLYSELF
269.  					|| is_flyer(uasmon)
270.  #endif
271.  #ifdef ENDGAME
272.  					|| dlevel == ENDLEVEL
273.  #endif
274.  							) {
275.  			    You("don't fall in.");
276.  			    break;
277.  			}
278.  #ifdef WALKIES
279.  			if(!next_to_u())
280.  			    You("are jerked back by your pet!");
281.  			else {
282.  #endif
283.  			    unsee();
284.  			    (void) fflush(stdout);
285.  			    goto_level(newlevel, FALSE);
286.  #ifdef WALKIES
287.  			}
288.  #endif
289.  		    }
290.  		    break;
291.  		case DART_TRAP:
292.  		    pline("A little dart shoots out at you!");
293.  		    if(thitu(7,rnd(3),"little dart")) {
294.  			if(!rn2(6)) poisoned("dart",A_CON,"poison dart");
295.  		    } else {
296.  			(void) mksobj_at(DART, u.ux, u.uy);
297.  			fobj->quan = 1;
298.  			fobj->opoisoned = 1;
299.  			fobj->owt = weight(fobj);
300.  		    }
301.  		    break;
302.  		case TELEP_TRAP:
303.  		    if(trap->once) {
304.  			deltrap(trap);
305.  #ifdef ENDGAME
306.  			if(dlevel == ENDLEVEL) {
307.  			    You("feel a wrenching sensation.");
308.  			    break;
309.  			}
310.  #endif
311.  			if(Antimagic) {
312.  			    shieldeff(u.ux, u.uy);
313.  			    You("feel a wrenching sensation.");
314.  			} else {
315.  			    newsym(u.ux, u.uy);
316.  			    vtele();
317.  			}
318.  		    } else {
319.  #ifdef ENDGAME
320.  			if(dlevel == ENDLEVEL) {
321.  			    pline("A shiver runs down your spine...");
322.  			    break;
323.  			}
324.  #endif
325.  			if(Antimagic) {
326.  			    shieldeff(u.ux, u.uy);
327.  			    You("feel a wrenching sensation.");
328.  			} else {
329.  			    newsym(u.ux, u.uy);
330.  			    tele();
331.  			}
332.  		    }
333.  		    break;
334.  		case RUST_TRAP:
335.  #ifdef POLYSELF
336.  #ifdef GOLEMS
337.  		    if (u.umonnum == PM_IRON_GOLEM) {
338.  			pline("A gush of water hits you!");
339.  			You("are covered with rust!");
340.  			rehumanize();
341.  			break;
342.  		    }
343.  #endif /* GOLEMS */
344.  #endif
345.  		/* Unlike monsters, traps cannot aim their rust attacks at
346.  		 * you, so instead of looping through and taking either the
347.  		 * first rustable one or the body, we take whatever we get,
348.  		 * even if it is not rustable.
349.  		 */
350.  		    switch (rn2(5)) {
351.  			case 0:
352.  			    pline("A gush of water hits you on the %s!",
353.  					body_part(HEAD));
354.  			    (void) rust_dmg(uarmh, "helmet", 1, TRUE);
355.  			    break;
356.  			case 1:
357.  			    pline("A gush of water hits your left %s!",
358.  					body_part(ARM));
359.  			    if (rust_dmg(uarms, "shield", 1, TRUE)) break;
360.  			    if (uwep && bimanual(uwep))
361.  				goto two_hand;
362.  			    /* Two goto statements in a row--aaarrrgggh! */
363.  glovecheck:		    (void) rust_dmg(uarmg, "gauntlets", 1, TRUE);
364.  			    /* Not "metal gauntlets" since it gets called
365.  			     * even if it's leather for the message
366.  			     */
367.  			    break;
368.  			case 2:
369.  			    pline("A gush of water hits your right %s!",
370.  					body_part(ARM));
371.  two_hand:		    corrode_weapon();
372.  			    goto glovecheck;
373.  			default:
374.  			    pline("A gush of water hits you!");
375.  			    if (uarmc) (void) rust_dmg(uarmc, "cloak", 1, TRUE);
376.  			    else if (uarm)
377.  				(void) rust_dmg(uarm, "armor", 1, TRUE);
378.  #ifdef SHIRT
379.  			    else if (uarmu)
380.  				(void) rust_dmg(uarmu, "shirt", 1, TRUE);
381.  #endif
382.  		    }
383.  		    break;
384.  		case PIT:
385.  		    if (Levitation
386.  #ifdef POLYSELF
387.  			|| is_flyer(uasmon) || u.umonnum == PM_WUMPUS
388.  #endif
389.  			) {
390.  			pline("A pit opens up under you!");
391.  			You("don't fall in!");
392.  			break;
393.  		    }
394.  		    You("fall into a pit!");
395.  #ifdef POLYSELF
396.  		    if (!passes_walls(uasmon))
397.  #endif
398.  			u.utrap = rn1(6,2);
399.  		    u.utraptype = TT_PIT;
400.  		    losehp(rnd(6),"fall into a pit");
401.  		    selftouch("Falling, you");
402.  		    break;
403.  		case SPIKED_PIT:
404.  		    if (Levitation
405.  #ifdef POLYSELF
406.  			|| is_flyer(uasmon) || u.umonnum == PM_WUMPUS
407.  #endif
408.  			) {
409.  			pline("A pit full of spikes opens up under you!");
410.  			You("don't fall in!");
411.  			break;
412.  		    }
413.  		    You("fall into a pit!");
414.  		    You("land on a set of sharp iron spikes!");
415.  #ifdef POLYSELF
416.  		    if (!passes_walls(uasmon))
417.  #endif
418.  			u.utrap = rn1(6,2);
419.  		    u.utraptype = TT_PIT;
420.  		    losehp(rnd(10),"fall onto iron spikes");
421.  		    if(!rn2(6)) poisoned("spikes",A_STR,"poison spikes");
422.  		    selftouch("Falling, you");
423.  		    break;
424.  		case LEVEL_TELEP:
425.  		    pline("You have %s onto a level teleport trap!",
426.  #ifdef POLYSELF
427.  			is_flyer(uasmon) ? "flown" :
428.  			(Levitation || nolimbs(uasmon)) ? "moved" : "stepped");
429.  #else
430.  			Levitation ? "moved" : "stepped");
431.  #endif
432.  		    if(Antimagic)
433.  			shieldeff(u.ux, u.uy);
434.  		    if(Antimagic
435.  #ifdef ENDGAME
436.  				|| dlevel == ENDLEVEL
437.  #endif
438.  							) {
439.  			You("feel a wrenching sensation.");
440.  			break;
441.  		    }
442.  		    if(!Blind)
443.  		      You("are momentarily blinded by a flash of light.");
444.  		    else
445.  			You("are momentarily disoriented.");
446.  		    deltrap(trap);
447.  		    newsym(u.ux,u.uy);
448.  		    level_tele();
449.  		    break;
450.  #ifdef SPELLS
451.  		case ANTI_MAGIC:
452.  		    if(Antimagic) {
453.  			shieldeff(u.ux, u.uy);
454.  			You("feel momentarily lethargic.");
455.  		    } else drain_en(rnd((int)u.ulevel) + 1);
456.  		    break;
457.  #endif
458.  #ifdef POLYSELF
459.  		case POLY_TRAP:
460.  		    if(Antimagic) {
461.  			shieldeff(u.ux, u.uy);
462.  			You("feel momentarily different.");
463.  			/* Trap did nothing; don't remove it --KAA */
464.  		    } else {
465.  			You("feel a change coming over you.");
466.  			polyself();
467.  			deltrap(trap);
468.  		    }
469.  		    break;
470.  #endif
471.  		case MGTRP:	    /* A magic trap. */
472.  		    if (!rn2(30)) {
473.  			You("are caught in a magical explosion!");
474.  			losehp(rnd(10), "magical explosion");
475.  #ifdef SPELLS
476.  			Your("body absorbs some of the magical energy!");
477.  			u.uen = (u.uenmax += 2);
478.  #endif
479.  			deltrap(trap);
480.  			if(Invisible) newsym(u.ux,u.uy);
481.  		    } else domagictrap();
482.  		    break;
483.  		case SQBRD:	    /* Stepped on a squeaky board. */
484.  		    if (Levitation
485.  #ifdef POLYSELF
486.  			|| is_flyer(uasmon)
487.  #endif
488.  			) {
489.  			if (Hallucination) You("notice a crease in the linoleum.");
490.  			else You("notice a loose board below you.");
491.  		    } else {
492.  			pline("A board underfoot gives off a loud squeak!");
493.  			wake_nearby();
494.  		    }
495.  		    break;
496.  		case WEB: /* Our luckless player has stumbled into a web. */
497.  
498.  		    pline("You've %s into a spider web!",
499.  			  Levitation ? "floated" :
500.  #ifdef POLYSELF
501.  			  is_flyer(uasmon) ? "flown" :
502.  #endif
503.  			  "stumbled");
504.  		    u.utraptype = TT_WEB;
505.  
506.  		    /* Time stuck in the web depends on your strength. */
507.  
508.  		    if (ACURR(A_STR) == 3) u.utrap = rn1(6,6);
509.  		    else if (ACURR(A_STR) < 6) u.utrap = rn1(6,4);
510.  		    else if (ACURR(A_STR) < 9) u.utrap = rn1(4,4);
511.  		    else if (ACURR(A_STR) < 12) u.utrap = rn1(4,2);
512.  		    else if (ACURR(A_STR) < 15) u.utrap = rn1(2,2);
513.  		    else if (ACURR(A_STR) < 18) u.utrap = rnd(2);
514.  		    else if (ACURR(A_STR) < 69) u.utrap = 1;
515.  		    else {
516.  			u.utrap = 0;
517.  			You("tear through the web!");
518.  			deltrap(trap);
519.  	   		if(Invisible) newsym(u.ux,u.uy);
520.  		    }
521.  		    break;
522.  
523.  		case LANDMINE: {
524.  #		ifndef LINT
525.  		    register struct monst *mtmp = fmon;
526.  #		endif /* LINT */
527.  
528.  		    if (Levitation
529.  #ifdef POLYSELF
530.  						|| is_flyer(uasmon)
531.  #endif
532.  								) {
533.  			You("see a trigger in a pile of soil below you!");
534.  			if (rn2(3)) break;
535.  			pline("KAABLAMM!!!  The air currents set it off!");
536.  		    } else {
537.  #ifdef POLYSELF
538.  			pline("KAABLAMM!!!  You %s a land mine!",
539.  				nolimbs(uasmon) ? "encountered" : "stepped on");
540.  #else
541.  			pline("KAABLAMM!!!  You stepped on a land mine!");
542.  #endif
543.  			set_wounded_legs(LEFT_SIDE, 40 + rnd(35));
544.  			set_wounded_legs(RIGHT_SIDE, 40 + rnd(35));
545.  		    }
546.  		    losehp(rnd(16), "land mine");
547.  		    /* wake everything on the level */
548.  		    while(mtmp) {
549.  			if(mtmp->msleep) mtmp->msleep = 0;
550.  			mtmp = mtmp->nmon;
551.  		    }
552.  		    deltrap(t_at(u.ux, u.uy)); /* mines only explode once */
553.  		    if(Invisible) newsym(u.ux,u.uy);
554.  		    }
555.  		    break;
556.  		default:
557.  		    impossible("You hit a trap of type %u", trap->ttyp);
558.  	    }
559.  	}
560.  }
561.  
562.  #ifdef WALKIES
563.  static boolean
564.  teleport_pet(mtmp)
565.  register struct monst *mtmp;
566.  {
567.  	register struct obj *otmp;
568.  
569.  	if(mtmp->mleashed) {
570.  	    otmp = get_mleash(mtmp);
571.  	    if(!otmp)
572.  		impossible("%s is leashed, without a leash.", Monnam(mtmp));
573.  	    if(otmp->cursed) {
574.  # ifdef SOUNDS
575.  		yelp(mtmp);
576.  # endif
577.  		return FALSE;
578.  	    } else {
579.  		Your("leash goes slack.");
580.  		m_unleash(mtmp);
581.  		return TRUE;
582.  	    }
583.  	}
584.  	return TRUE;
585.  }
586.  #endif
587.  
588.  int
589.  mintrap(mtmp)
590.  register struct monst *mtmp;
591.  {
592.  	register struct trap *trap = t_at(mtmp->mx, mtmp->my);
593.  	register int newlev, wasintrap = mtmp->mtrapped;
594.  	register boolean trapkilled = FALSE, tdoor = FALSE;
595.  	struct obj *otmp;
596.  
597.  	if(!trap) {
598.  		mtmp->mtrapped = 0;	/* perhaps teleported? */
599.  	} else if(wasintrap) {
600.  		if(!rn2(40)) mtmp->mtrapped = 0;
601.  	} else {
602.  	    register int tt = trap->ttyp;
603.  
604.  	/* A bug fix for dumb messages by ab@unido.
605.  	 */
606.  	    int in_sight = cansee(mtmp->mx,mtmp->my)
607.  			   && (!mtmp->minvis || See_invisible);
608.  
609.  	    if(mtmp->mtrapseen & (1 << tt)) {
610.  		/* he has been in such a trap - perhaps he escapes */
611.  		if(rn2(4)) return(0);
612.  	    }
613.  	    mtmp->mtrapseen |= (1 << tt);
614.  	    switch (tt) {
615.  		case BEAR_TRAP:
616.  			if(bigmonst(mtmp->data)) {
617.  				if(in_sight)
618.  				  pline("%s is caught in a bear trap!",
619.  					Monnam(mtmp));
620.  				else
621.  				    if(mtmp->data == &mons[PM_OWLBEAR]
622.  					&& flags.soundok)
623.  			    You("hear the roaring of an angry bear!");
624.  				mtmp->mtrapped = 1;
625.  			}
626.  			break;
627.  #ifdef POLYSELF
628.  		case POLY_TRAP:
629.  		    if(!resist(mtmp, WAND_SYM, 0, NOTELL))
630.  			(void) newcham(mtmp, (struct permonst *)0);
631.  		    break;
632.  #endif
633.  		case RUST_TRAP:
634.  			if(in_sight)
635.  				pline("A gush of water hits %s!", mon_nam(mtmp));
636.  #ifdef GOLEMS
637.  			if (mtmp->data == &mons[PM_IRON_GOLEM]) {
638.  				if (in_sight) pline("%s falls to pieces!",
639.  								Monnam(mtmp));
640.  				else if(mtmp->mtame)
641.  				     pline("May %s rust in peace.",
642.  								mon_nam(mtmp));
643.  				mondied(mtmp);
644.  				trapkilled = TRUE;
645.  			}
646.  #endif /* GOLEMS */
647.  			break;
648.  		case PIT:
649.  		case SPIKED_PIT:
650.  			/* there should be a mtmp/data -> floating */
651.  			if(!is_flyer(mtmp->data) /* ab */
652.  			   && mtmp->data != &mons[PM_WUMPUS] /* 3. */) {
653.  				if (!passes_walls(mtmp->data))
654.  				  mtmp->mtrapped = 1;
655.  				if(in_sight)
656.  				  pline("%s falls into a pit!", Monnam(mtmp));
657.  				if(thitm(0, mtmp, (struct obj *)0,
658.  				  rnd((tt==PIT) ? 6 : 10)))
659.  				  trapkilled = TRUE;
660.  			}
661.  			break;
662.  		case SLP_GAS_TRAP:
663.  			if(!resists_sleep(mtmp->data) &&
664.  			   !mtmp->msleep && !mtmp->mfroz) {
665.  				mtmp->msleep = 1;
666.  				if(in_sight)
667.  				  pline("%s suddenly falls asleep!",
668.  					Monnam(mtmp));
669.  			}
670.  			break;
671.  		case TELEP_TRAP:
672.  #ifdef WALKIES
673.  			if(teleport_pet(mtmp)) {
674.  #endif
675.  			    rloc(mtmp);
676.  			    if(in_sight && !cansee(mtmp->mx,mtmp->my))
677.  				pline("%s suddenly disappears!",
678.  					Monnam(mtmp));
679.  #ifdef WALKIES
680.  			}
681.  #endif
682.  			break;
683.  		case ARROW_TRAP:
684.  			otmp = mksobj(ARROW, FALSE);
685.  			otmp->quan = 1;
686.  			otmp->owt = weight(otmp);
687.  			if(thitm(8, mtmp, otmp, 0)) trapkilled = TRUE;
688.  			break;
689.  		case DART_TRAP:
690.  			otmp = mksobj(DART, FALSE);
691.  			otmp->quan = 1;
692.  			otmp->owt = weight(otmp);
693.  			if(thitm(7, mtmp, otmp, 0)) trapkilled = TRUE;
694.  			break;
695.  		case TRAPDOOR:
696.  			if(is_maze_lev
697.  #ifdef STRONGHOLD
698.  			   && (dlevel > stronghold_level && dlevel < MAXLEVEL)
699.  #endif
700.  			  ) {
701.  				otmp = mksobj(ROCK, FALSE);
702.  				otmp->quan = 1;
703.  				otmp->owt = weight(otmp);
704.  				if(thitm(0, mtmp, otmp, d(2, 10)))
705.  					trapkilled = TRUE;
706.  				break;
707.  			}
708.  			tdoor = TRUE;
709.  			/* Fall through */
710.  		case LEVEL_TELEP:
711.  			if(!is_flyer(mtmp->data)
712.  #ifdef WORM
713.  				&& !mtmp->wormno
714.  			    /* long worms cannot be allowed to change levels */
715.  #endif
716.  			    ){
717.  #ifdef WALKIES
718.  			    if(teleport_pet(mtmp)) {
719.  #endif
720.  				if(tdoor)
721.  				    fall_down(mtmp, dlevel+1);
722.  				else {
723.  				    newlev = rnd(3);
724.  				    if(!rn2(2)) newlev = -(newlev);
725.  				    newlev = dlevel + newlev;
726.  				    if(newlev > MAXLEVEL) {
727.  					if(dlevel != MAXLEVEL)
728.  					    newlev = MAXLEVEL;
729.  					else newlev = MAXLEVEL - rnd(3);
730.  				    }
731.  				    if(newlev < 1) {
732.  					if(dlevel != 1) newlev = 1;
733.  					else newlev = 1 + rnd(3);
734.  				    }
735.  				    fall_down(mtmp, newlev);
736.  				}
737.  				if(in_sight)
738.  		pline("Suddenly, %s disappears out of sight.", mon_nam(mtmp));
739.  				return(2);	/* no longer on this level */
740.  #ifdef WALKIES
741.  			    }
742.  #endif
743.  			}
744.  			break;
745.  		case MONST_TRAP:
746.  		case STATUE_TRAP:
747.  			break;
748.  		case MGTRP:
749.  			/* A magic trap.  Monsters immune. */
750.  			break;
751.  		case SQBRD: {
752.  			register struct monst *ztmp = fmon;
753.  
754.  			if(is_flyer(mtmp->data)) break;
755.  			/* Stepped on a squeaky board. */
756.  			if (in_sight)
757.  			   pline("%s steps on a squeaky board.", Monnam(mtmp));
758.  			else
759.  			   You("hear a distant squeak.");
760.  			/* Wake up nearby monsters. */
761.  		       while(ztmp) {
762.  			 if(dist2(mtmp->mx,mtmp->my,ztmp->mx,ztmp->my) < 40)
763.  			       if(ztmp->msleep) ztmp->msleep = 0;
764.  			 ztmp = ztmp->nmon;
765.  		       }
766.  			break;
767.  		}
768.  	       case WEB:
769.  		       /* Monster in a web. */
770.  			/* in_sight check and confused bear by Eric Backus */
771.  		       if(mtmp->data->mlet != S_SPIDER) {
772.  			 if(in_sight)
773.  				pline("%s is caught in a web!", Monnam(mtmp));
774.  			  else
775.  			    if(mtmp->data == &mons[PM_OWLBEAR])
776.  			      You("hear the roaring of a confused bear!");
777.  			 mtmp->mtrapped = 1;
778.  		       }
779.  		      break;
780.  #ifdef SPELLS
781.  		case ANTI_MAGIC:	break;
782.  #endif
783.  		case LANDMINE: {
784.  			register struct monst *mntmp = fmon;
785.  
786.  			if(rn2(3))
787.  				break; /* monsters usually don't set it off */
788.  			if(in_sight)
789.  				pline("KAABLAMM!!!  %s steps on a land mine!",
790.  				      Monnam(mtmp));
791.  			else if (flags.soundok)
792.  				pline("Kaablamm!  You hear an explosion in the distance!");
793.  			deltrap(t_at(mtmp->mx, mtmp->my));
794.  			if(thitm(0, mtmp, (struct obj *)0, rnd(16)))
795.  				trapkilled = TRUE;
796.  			/* wake everything on the level */
797.  			while(mntmp) {
798.  				if(mntmp->msleep)
799.  					mntmp->msleep = 0;
800.  				mntmp = mntmp->nmon;
801.  			}
802.  			break;
803.  		}
804.  		default:
805.  			impossible("Some monster encountered a strange trap of type %d.",tt);
806.  	    }
807.  	}
808.  	if(trapkilled) return 2;
809.  	else return mtmp->mtrapped;
810.  }
811.  
812.  void
813.  selftouch(arg)
814.  char *arg;
815.  {
816.  	if(uwep && (uwep->otyp == CORPSE && uwep->corpsenm == PM_COCKATRICE)
817.  #ifdef POLYSELF
818.  			&& !resists_ston(uasmon)
819.  #endif
820.  	){
821.  		pline("%s touch the cockatrice corpse.", arg);
822.  		You("turn to stone...");
823.  		killer = "cockatrice corpse accident";
824.  		done("stoned");
825.  	}
826.  }
827.  
828.  void
829.  float_up() {
830.  	if(u.utrap) {
831.  		if(u.utraptype == TT_PIT) {
832.  			u.utrap = 0;
833.  			You("float up, out of the pit!");
834.  		} else {
835.  			You("float up, only your %s is still stuck.",
836.  				body_part(LEG));
837.  		}
838.  	} else
839.  		if (Hallucination)
840.  			pline("Oh wow!  You're floating in the air!");
841.  		else
842.  			You("start to float in the air!");
843.  }
844.  
845.  int
846.  float_down() {
847.  	register struct trap *trap;
848.  
849.  	if(Levitation) return(0); /* maybe another ring/potion/boots */
850.  
851.  	/* check for falling into pool - added by GAN 10/20/86 */
852.  	if(is_pool(u.ux,u.uy) && !(Wwalking
853.  #ifdef POLYSELF
854.  				    || is_flyer(uasmon)
855.  #endif
856.  				    ))
857.  		drown();
858.  
859.  	You("float gently to the ground.");
860.  	if(trap = t_at(u.ux,u.uy))
861.  		switch(trap->ttyp) {
862.  		case MONST_TRAP:
863.  		case STATUE_TRAP:
864.  			break;
865.  		case TRAPDOOR:
866.  			if(is_maze_lev
867.  #ifdef STRONGHOLD
868.  			   && (dlevel >= stronghold_level || dlevel < MAXLEVEL)
869.  #endif
870.  			   || u.ustuck) break;
871.  			/* fall into next case */
872.  		default:
873.  			dotrap(trap);
874.  	}
875.  	if(!flags.nopick && (levl[u.ux][u.uy].omask || levl[u.ux][u.uy].gmask))
876.  	    pickup(1);
877.  	return 0;
878.  }
879.  
880.  
881.  void
882.  tele() {
883.  	coord cc;
884.  	register int nux,nuy;
885.  
886.  #ifdef STRONGHOLD
887.  	/* Disable teleportation in stronghold && Vlad's Tower */
888.  	if(dlevel == stronghold_level ||
889.  # ifdef ENDGAME
890.  	   dlevel == ENDLEVEL ||
891.  # endif
892.  	   (dlevel >= tower_level && dlevel <= tower_level + 2)) {
893.  # ifdef WIZARD
894.  		if (!wizard) {
895.  # endif
896.  		    pline("A mysterious force prevents you from teleporting!");
897.  		    return;
898.  # ifdef WIZARD
899.  		}
900.  # endif
901.  	}
902.  #endif /* STRONGHOLD /**/
903.  	if((u.uhave_amulet || dlevel == wiz_level) && !rn2(3)) {
904.  	    You("feel disoriented for a moment.");
905.  	    return;
906.  	}
907.  	if(Teleport_control) {
908.  	    if (unconscious())
909.  		pline("Being unconscious, you cannot control your teleport.");
910.  	    else {
911.  		    pline("To what position do you want to be teleported?");
912.  		    getpos(&cc, 1, "the desired position"); /* 1: force valid */
913.  		    /* possible extensions: introduce a small error if
914.  		       magic power is low; allow transfer to solid rock */
915.  		    if(teleok(cc.x, cc.y)){
916.  			teleds(cc.x, cc.y);
917.  			return;
918.  		    }
919.  		    pline("Sorry...");
920.  		}
921.  	}
922.  	do {
923.  		nux = rnd(COLNO-1);
924.  		nuy = rn2(ROWNO);
925.  	} while(!teleok(nux, nuy));
926.  	teleds(nux, nuy);
927.  }
928.  
929.  void
930.  teleds(nux, nuy)
931.  register int nux,nuy;
932.  {
933.  	if(Punished) unplacebc();
934.  	unsee();
935.  	u.utrap = 0;
936.  	u.ustuck = 0;
937.  	u.ux = nux;
938.  	u.uy = nuy;
939.  #ifdef POLYSELF
940.  	if (hides_under(uasmon))
941.  		u.uundetected = (levl[nux][nuy].omask || levl[nux][nuy].gmask);
942.  	else 
943.  		u.uundetected = 0;
944.  	if (u.usym == S_MIMIC_DEF) u.usym = S_MIMIC;
945.  #endif
946.  	setsee();
947.  	if(Punished) placebc(1);
948.  	if(u.uswallow){
949.  		u.uswldtim = u.uswallow = 0;
950.  		docrt();
951.  	}
952.  	nomul(0);
953.  	spoteffects();
954.  }
955.  
956.  int
957.  dotele()
958.  {
959.  	struct trap *trap;
960.  #ifdef SPELLS
961.  	boolean castit = FALSE;
962.  	register int sp_no;
963.  #endif
964.  
965.  	trap = t_at(u.ux, u.uy);
966.  	if (trap && (!trap->tseen || trap->ttyp != TELEP_TRAP || trap->once))
967.  		trap = 0;
968.  
969.  	if (trap) 
970.  		You("jump onto the teleportation trap...");
971.  	else if(!Teleportation ||
972.  	   (u.ulevel < (pl_character[0] == 'W' ? 8 : 12)
973.  #ifdef POLYSELF
974.  	    && !can_teleport(uasmon)
975.  #endif
976.  	   )
977.  	  ) {
978.  #ifdef SPELLS
979.  		/* Try to use teleport away spell. */
980.  		castit = objects[SPE_TELEPORT_AWAY].oc_name_known;
981.  		if (castit) {
982.  		    for (sp_no = 0; sp_no < MAXSPELL &&
983.  				spl_book[sp_no].sp_id != NO_SPELL &&
984.  				spl_book[sp_no].sp_id != SPE_TELEPORT_AWAY; sp_no++);
985.  
986.  		    if (sp_no == MAXSPELL ||
987.  			spl_book[sp_no].sp_id != SPE_TELEPORT_AWAY)
988.  			    castit = FALSE;
989.  		}
990.  #endif
991.  #ifdef WIZARD
992.  		if (!wizard) {
993.  #endif
994.  #ifdef SPELLS
995.  		    if (!castit) {
996.  			if (!Teleportation)
997.  			    You("don't know that spell.");
998.  			else
999.  #endif
1000. 			    You("are not able to teleport at will.");
1001. 			return(0);
1002. #ifdef SPELLS
1003. 		    }
1004. #endif
1005. #ifdef WIZARD
1006. 		}
1007. #endif
1008. 	}
1009. 
1010. 	if(!trap && (u.uhunger <= 100 || ACURR(A_STR) < 6)) {
1011. 		You("lack the strength for a teleport spell.");
1012. #ifdef WIZARD
1013. 		if(!wizard)
1014. #endif
1015. 		return(1);
1016. 	}
1017. 
1018. #ifdef SPELLS
1019. 	if (castit)
1020. # ifdef WIZARD
1021. 		if (!spelleffects(++sp_no, TRUE) && !wizard) return(0);
1022. # else
1023. 		return spelleffects(++sp_no, TRUE);
1024. # endif
1025. #endif
1026. 
1027. #ifdef WALKIES
1028. 	if(next_to_u()) {
1029. #endif
1030. 		tele();
1031. #ifdef WALKIES
1032. 		(void) next_to_u();
1033. 	} else {
1034. 		You("shudder for a moment.");
1035. 		return(0);
1036. 	}
1037. #endif
1038. 	if (!trap) morehungry(100);
1039. 	return(1);
1040. }
1041. 
1042. void
1043. placebc(attach)
1044. int attach;
1045. {
1046. 	if(!uchain || !uball){
1047. 		impossible("Where are your chain and ball??");
1048. 		return;
1049. 	}
1050. 	uball->ox = uchain->ox = u.ux;
1051. 	uball->oy = uchain->oy = u.uy;
1052. 	levl[u.ux][u.uy].omask = 1;
1053. 	if(attach){
1054. 		uchain->nobj = fobj;
1055. 		fobj = uchain;
1056. 		if(!carried(uball)){
1057. 			uball->nobj = fobj;
1058. 			fobj = uball;
1059. 		}
1060. 	}
1061. }
1062. 
1063. void
1064. unplacebc(){
1065. 	if(!carried(uball)){
1066. 		freeobj(uball);
1067. 		unpobj(uball);
1068. 	}
1069. 	freeobj(uchain);
1070. 	unpobj(uchain);
1071. }
1072. 
1073. void
1074. level_tele() {
1075. register int newlevel;
1076. #ifdef WALKIES
1077. register boolean pet_by_u = next_to_u();
1078. #endif
1079. 
1080. 	if(u.uhave_amulet
1081. #ifdef ENDGAME
1082. 		|| dlevel == ENDLEVEL
1083. #endif
1084. 	) {
1085. 	    You("feel very disoriented for a moment.");
1086. 	    return;
1087. 	}
1088. 	if(Teleport_control
1089. #ifdef WIZARD
1090. 	   || wizard
1091. #endif
1092. 		) {
1093. 	    char buf[BUFSZ];
1094. 
1095. 	    do {
1096. 	      pline("To what level do you want to teleport? [type a number] ");
1097. 	      getlin(buf);
1098. 	    } while(!digit(buf[0]) && (buf[0] != '-' || !digit(buf[1])));
1099. 	    newlevel = atoi(buf);
1100. 	} else {
1101. 	    newlevel = rn2(5) | !Fire_resistance ? rnd(dlevel + 3) :
1102. #ifdef STRONGHOLD
1103. 		stronghold_level + 1;
1104. #else
1105. 		HELLLEVEL;
1106. #endif
1107. 	    if(dlevel == newlevel)
1108. 		if(is_maze_lev) newlevel--; else newlevel++;
1109. 	}
1110. 	if(newlevel < 0) {
1111. #ifdef WALKIES
1112. 	    if(pet_by_u) {
1113. #endif
1114. 		if(newlevel <= -10) {
1115. 			You("arrive in heaven.");
1116. 			pline("\"You are here a bit early, but we'll let you in.\"");
1117. 			killer = "visit to heaven";
1118. 			done("died");
1119. 		} else	if (newlevel == -9) {
1120. 			You("feel deliriously happy. ");
1121. 			pline("(In fact, you're on Cloud 9!) ");
1122. 			more();
1123. 		} else
1124. #ifndef STRONGHOLD
1125. 			newlevel = 0;
1126. #else
1127. 			newlevel = 1;
1128. #endif
1129. 		You("are now high above the clouds...");
1130. 		if(Levitation) {
1131. 		    You("float gently down to earth.");
1132. #ifndef STRONGHOLD
1133. 		    done("escaped");
1134. #endif
1135. 		}
1136. #ifdef POLYSELF
1137. 		if(is_flyer(uasmon)) {
1138. 		    You("fly down to earth.");
1139. # ifndef STRONGHOLD
1140. 		    done("escaped");
1141. # endif
1142. 		}
1143. #endif
1144. 		pline("Unfortunately, you don't know how to fly.");
1145. 		You("plummet a few thousand feet to your death.");
1146. 		dlevel = 0;
1147. 		killer = "long fall";
1148. 		done("died");
1149. #ifdef WALKIES
1150. 	    } else {
1151. 		You("shudder for a moment...");
1152. 		return;
1153. 	    }
1154. #endif
1155. 	}
1156. 	/* calls done("escaped") if newlevel==0 */
1157. #ifdef WALKIES
1158. 	if(!pet_by_u)
1159. 	    You("shudder for a moment...");
1160. 	else
1161. #endif
1162. 	    goto_level(newlevel, FALSE);
1163. }
1164. 
1165. void
1166. domagictrap() {
1167. 	register int fate = rnd(20);
1168. 
1169. 	/* What happened to the poor sucker? */
1170. 
1171. 	if (fate < 10) {
1172. 
1173. 	  /* Most of the time, it creates some monsters. */
1174. 	  register int cnt = rnd(4);
1175. 
1176. 	  /* below checks for blindness added by GAN 10/30/86 */
1177. 	  if (!Blind)  {
1178. 		You("are momentarily blinded by a flash of light!");
1179. 		make_blinded((long)rn1(5,10),FALSE);
1180. 	  }  else
1181. 		You("hear a deafening roar!");
1182. 	  while(cnt--)
1183. 	   (void) makemon((struct permonst *) 0, u.ux, u.uy);
1184. 	}
1185. 	else
1186. 	  switch (fate) {
1187. 
1188. 	     case 10:
1189. 	     case 11:
1190. 		      /* sometimes nothing happens */
1191. 			break;
1192. 	     case 12:
1193. 		      /* a flash of fire */
1194. 		      {
1195. 			register int num;
1196. 
1197. 			/* changed to be in conformance with
1198. 			 * SCR_FIRE by GAN 11/02/86
1199. 			 */
1200. 
1201. 			pline("A tower of flame bursts from the floor!");
1202. 			if(Fire_resistance) {
1203. 				shieldeff(u.ux, u.uy);
1204. 				You("are uninjured.");
1205. 				break;
1206. 			} else {
1207. 				num = rnd(6);
1208. 				u.uhpmax -= num;
1209. 				losehp(num,"a burst of flame");
1210. 				break;
1211. 			}
1212. 		      }
1213. 
1214. 	     /* odd feelings */
1215. 	     case 13:   pline("A shiver runs up and down your spine!");
1216. 			break;
1217. 	     case 14:   You("hear distant howling.");
1218. 			break;
1219. 	     case 15:   You("suddenly yearn for your distant homeland.");
1220. 			break;
1221. 	     case 16:   Your("pack shakes violently!");
1222. 			break;
1223. 	     case 17:	You("smell charred flesh.");
1224. 			break;
1225. 
1226. 	     /* very occasionally something nice happens. */
1227. 
1228. 	     case 19:
1229. 		    /* tame nearby monsters */
1230. 		   {   register int i,j;
1231. 		       register boolean confused = (Confusion != 0);
1232. 		       register int bd = confused ? 5 : 1;
1233. 
1234. 		       /* below pline added by GAN 10/30/86 */
1235. 		       adjattrib(A_CHA,1,FALSE);
1236. 		       for(i = -bd; i <= bd; i++) for(j = -bd; j <= bd; j++)
1237. 		       if(levl[u.ux+i][u.uy+j].mmask)
1238. 			   (void) tamedog(m_at(u.ux+i, u.uy+j), (struct obj *)0);
1239. 		       break;
1240. 		   }
1241. 
1242. 	     case 20:
1243. 		    /* uncurse stuff */
1244. 		   {  register struct obj *obj;
1245. 		      register boolean confused = (Confusion != 0);
1246. 
1247. 			/* below plines added by GAN 10/30/86 */
1248. 			if (confused)
1249. 			    if (Hallucination)
1250. 				You("feel the power of the Force against you!");
1251. 			    else
1252. 				You("feel like you need some help.");
1253. 			else
1254. 			    if (Hallucination)
1255. 				You("feel in touch with the Universal Oneness.");
1256. 			    else
1257. 				You("feel like someone is helping you.");
1258. 		       for(obj = invent; obj ; obj = obj->nobj)
1259. 			       if(obj->owornmask)
1260. 				    if(confused)
1261. 					curse(obj);
1262. 				    else
1263. 					obj->cursed = 0;
1264. 		       if(Punished && !confused)
1265. 			    unpunish();
1266. 		       break;
1267. 		   }
1268. 	     default: break;
1269. 	  }
1270. }
1271. 
1272. void
1273. drown() {
1274. 	register struct obj *obj;
1275. 
1276. 	/* Scrolls and potions get affected by the water */
1277. 	for(obj = invent; obj; obj = obj->nobj) {
1278. 		if(obj->olet == SCROLL_SYM && rn2(12) > u.uluck)
1279. 			obj->otyp = SCR_BLANK_PAPER;
1280. 		if(obj->olet == POTION_SYM && rn2(12) > u.uluck) {
1281. 			if (obj->spe == -1) {
1282. 				obj->otyp = POT_WATER;
1283. 				obj->blessed = obj->cursed = 0;
1284. 				obj->spe = 0;
1285. 			} else obj->spe--;
1286. 		}
1287. 	}
1288. 
1289. #ifdef POLYSELF
1290. 	if(u.usym == S_GREMLIN && rn2(3)) {
1291. 		struct monst *mtmp;
1292. 		if(mtmp = cloneu()) {
1293. 			mtmp->mhpmax = (u.mhmax /= 2);
1294. 			You("multiply.");
1295. 		}
1296. 	}
1297. 
1298. 	if(is_swimmer(uasmon)) return;
1299. #endif
1300. 
1301. 	You("fell into %s!",
1302. 	      levl[u.ux][u.uy].typ == POOL ? "a pool" : "the moat");
1303. 	You("can't swim!");
1304. 	if(
1305. #ifdef WIZARD
1306. 	wizard ||
1307. #endif
1308. 	rn2(3) < u.uluck+2) {
1309. 		You("attempt a teleport spell.");	/* utcsri!carroll */
1310. 		(void) dotele();
1311. 		if(!is_pool(u.ux,u.uy)) return;
1312. 	}
1313. 	You("drown.");
1314. 	killer = levl[u.ux][u.uy].typ == POOL ? "pool of water" : "moat";
1315. 	done("drowned");
1316. }
1317. 
1318. #ifdef SPELLS
1319. void
1320. drain_en(n)
1321. register int n;
1322. {
1323. 	if (!u.uenmax) return;
1324. 	You("feel your magical energy drain away!");
1325. 	u.uen -= n;
1326. 	if(u.uen < 0)  {
1327. 		u.uenmax += u.uen;
1328. 		if(u.uenmax < 0) u.uenmax = 0;
1329. 		u.uen = 0;
1330. 	}
1331. 	flags.botl = 1;
1332. }
1333. #endif
1334. 
1335. int
1336. dountrap() {	/* disarm a trapped object */
1337. 	register struct obj *otmp;
1338. 	register boolean confused = (Confusion > 0);
1339. 	register int x,y;
1340. 	int ch;
1341. 	struct trap *ttmp;
1342. 
1343. #ifdef POLYSELF
1344. 	if(nohands(uasmon)) {
1345. 	    pline("And just how do you expect to do that?");
1346. 	    return(0);
1347. 	}
1348. #endif
1349. 	if(!getdir(TRUE)) return(0);
1350. 	x = u.ux + u.dx;
1351. 	y = u.uy + u.dy;
1352. 
1353. 	if(!u.dx && !u.dy) {
1354. 	    if(levl[x][y].omask)
1355. 		for(otmp = fobj; otmp; otmp = otmp->nobj)
1356. 		    if((otmp->ox == x) && (otmp->oy == y))
1357. 			if(Is_box(otmp)) {
1358. 			    pline("There is %s here, check for traps? ",
1359. 				  doname(otmp));
1360. 
1361. 			    switch (ynq()) {
1362. 				case 'q': return(0);
1363. 				case 'n': continue;
1364. 			    }
1365. 
1366. 			    if((otmp->otrapped && !confused && rn2(44-dlevel*2) < 10)
1367. 			       || confused && !rn2(3)) {
1368. 				You("find a trap on the %s!  Disarm it? ",
1369. 				       xname(otmp));
1370. 
1371. 				switch (ynq()) {
1372. 				    case 'q': return(1);
1373. 				    case 'n': continue;
1374. 				}
1375. 
1376. 				if(otmp->otrapped) {
1377. 				    ch = 15 +
1378. 					 (pl_character[0] == 'R') ? u.ulevel*3 :
1379. 					 u.ulevel;

The above statement contains a bug. It is meant to assign 15 + u.ulevel*3 to ch if the player is a Rogue, and 15 + u.ulevel otherwise. In fact, the conditional is always either 15 or 16, both of which are interpreted as true, and the statement assigns u.ulevel*3 to ch regardless of the role. Thus rogues do not in fact have a better chance of disarming a chest trap than other roles.

The logic is changed in 3.1.0 and rogues from then on have an increased chance of disarming a chest trap.

1380. 				    if(confused || Fumbling || rnd(75+dlevel/2) > ch) {
1381. 					You("set it off!");
1382. 					chest_trap(otmp, FINGER);
1383. 				    } else {
1384. 					You("disarm it!");
1385. 					otmp->otrapped = 0;
1386. 				    }
1387. 				} else pline("That %s was not trapped.",
1388. 					     doname(otmp));
1389. 				return(1);
1390. 			    } else {
1391. 				You("find no traps on the %s.",
1392. 				    xname(otmp));
1393. 				return(1);
1394. 			    }
1395. 			}
1396. 	    if ((ttmp = t_at(x,y)) && ttmp->tseen)
1397. 		You("cannot disable this trap.");
1398. 	    else
1399. 		You("know of no traps here.");
1400. 	    return(0);
1401. 	}
1402. 
1403. 	if (!IS_DOOR(levl[x][y].typ)) {
1404. 	    if ((ttmp = t_at(x,y)) && ttmp->tseen)
1405. 		You("cannot disable that trap.");
1406. 	    else
1407. 		You("know of no traps there.");
1408. 	    return(0);
1409. 	}
1410. 
1411. 	switch (levl[x][y].doormask) {
1412. 	    case D_NODOOR:
1413. 		You("%s no door there.", Blind ? "feel" : "see");
1414. 		return(0);
1415. 	    case D_ISOPEN:
1416. 		pline("This door is safely open.");
1417. 		return(0);
1418. 	    case D_BROKEN:
1419. 		pline("This door is broken.");
1420. 		return(0);
1421. 	}
1422. 
1423. 	if ((levl[x][y].doormask & D_TRAPPED && !confused &&
1424. 	     rn2(44-dlevel*2) < 10)
1425. 	    || confused && !rn2(3)) {
1426. 		You("find a trap on the door!  Disarm it? ");
1427. 		if (ynq() != 'y') return(1);
1428. 		if (levl[x][y].doormask & D_TRAPPED) {
1429. 		    ch = 15 +
1430. 			 (pl_character[0] == 'R') ? u.ulevel*3 :
1431. 			 u.ulevel;

The above statement contains the same bug as line 1377. This one, however, was left unfixed in 3.1.0. It is fixed in 3.2.0.

1432. 		    if(confused || Fumbling || rnd(75+dlevel/2) > ch) {
1433. 			    You("set it off!");
1434. 			    b_trapped("door");
1435. 		    } else {
1436. 			    You("disarm it!");
1437. 			    levl[x][y].doormask &= ~D_TRAPPED;
1438. 		    }
1439. 		} else pline("This door was not trapped.");
1440. 		return(1);
1441. 	} else {
1442. 		You("find no traps on the door.");
1443. 		return(1);
1444. 	}
1445. }
1446. 
1447. /* this is only called when the player is doing something to the chest
1448.  * -- i.e., the player and the chest are in the same position */
1449. void
1450. chest_trap(obj, bodypart)
1451. register struct obj *obj;
1452. register int bodypart;
1453. {
1454. 	register struct obj *otmp,*otmp2;
1455. 	char	buf[80];
1456. 
1457. 	if(rn2(13+u.uluck) > 7) return;
1458. 
1459. 	otmp = obj;
1460. 	switch(rn2(13-u.uluck)) {	/* which trap? */
1461. 		case 23:
1462. 		case 22:
1463. 		case 21:
1464. 			pline("The %s explodes!", xname(obj));
1465. 			Sprintf(buf, "exploding %s", xname(obj));
1466. 
1467. 			delete_contents(obj);
1468. 			for(otmp = fobj; otmp; otmp = otmp2) {
1469. 			    otmp2 = otmp->nobj;
1470. 			    if((otmp->ox == u.ux) && (otmp->oy == u.uy))
1471. 				delobj(otmp);
1472. 			}
1473. 
1474. 			losehp(d(6,6), buf);
1475. 			wake_nearby();
1476. 			return;
1477. 		case 20:
1478. 		case 19:
1479. 		case 18:
1480. 		case 17:
1481. 			pline("A cloud of noxious gas billows from the %s.",
1482. 			      xname(obj));
1483. 			poisoned("gas cloud", A_STR, "cloud of poison gas");
1484. 			break;
1485. 		case 16:
1486. 		case 15:
1487. 		case 14:
1488. 		case 13:
1489. 			pline("A tower of flame erupts from the %s",
1490. 			      xname(obj));
1491. 			if(Fire_resistance) {
1492. 			    shieldeff(u.ux, u.uy);
1493. 			    You("don't seem to be affected.");
1494. 			} else	losehp(d(4, 6), "tower of flame");
1495. 			destroy_item(SCROLL_SYM, AD_FIRE);
1496. #ifdef SPELLS
1497. 			destroy_item(SPBOOK_SYM, AD_FIRE);
1498. #endif
1499. 			destroy_item(POTION_SYM, AD_FIRE);
1500. 			break;
1501. 		case 12:
1502. 		case 10:
1503. 		case 9:
1504. 			You("are jolted by a surge of electricity!");
1505. 			if(Shock_resistance)  {
1506. 			    shieldeff(u.ux, u.uy);
1507. 			    You("don't seem to be affected.");
1508. 			} else	losehp(d(4, 4), "electric shock");
1509. 			destroy_item(RING_SYM, AD_ELEC);
1510. 			destroy_item(WAND_SYM, AD_ELEC);
1511. 			break;
1512. 		case 8:
1513. 		case 7:
1514. 		case 6:
1515. 			pline("Suddenly you are frozen in place!");
1516. 			nomovemsg = "You can move again.";
1517. 			multi = -d(5, 6);
1518. 			break;
1519. 		case 5:
1520. 		case 4:
1521. 		case 3:
1522. 			pline("A cloud of %s gas billows from the %s",
1523. 			      hcolor(), xname(obj));
1524. 			if(!Stunned)
1525. 			    if (Hallucination)
1526. 				pline("What a groovy feeling!");
1527. 			    else
1528. 				You("stagger and your vision blurs...");
1529. 			make_stunned(HStun + rn1(7, 16),FALSE);
1530. 			make_hallucinated(Hallucination + rn1(5, 16),FALSE);
1531. 			break;
1532. 		default:
1533. 			You("feel a needle prick your %s.",body_part(bodypart));
1534. 			poisoned("needle", A_CON, "a poisoned needle");
1535. 			break;
1536. 	}
1537. 	otmp->otrapped = 0;		/* these traps are one-shot things */
1538. }
1539. 
1540. void
1541. wake_nearby() {			/* Wake up nearby monsters. */
1542. 	register struct monst *mtmp;
1543. 
1544. 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
1545. 	    if(dist(mtmp->mx,mtmp->my) < u.ulevel*20) {
1546. 		if(mtmp->msleep)  mtmp->msleep = 0;
1547. 		if(mtmp->mtame)   EDOG(mtmp)->whistletime = moves;
1548. 	    }
1549. 	}
1550. }
1551. 
1552. struct trap *
1553. t_at(x,y)
1554. register int x, y;
1555. {
1556. 	register struct trap *trap = ftrap;
1557. 	while(trap) {
1558. 		if(trap->tx == x && trap->ty == y) return(trap);
1559. 		trap = trap->ntrap;
1560. 	}
1561. 	return((struct trap *)0);
1562. }
1563. 
1564. void
1565. deltrap(trap)
1566. register struct trap *trap;
1567. {
1568. 	register struct trap *ttmp;
1569. 
1570. 	if(trap == ftrap)
1571. 		ftrap = ftrap->ntrap;
1572. 	else {
1573. 		for(ttmp = ftrap; ttmp->ntrap != trap; ttmp = ttmp->ntrap) ;
1574. 		ttmp->ntrap = trap->ntrap;
1575. 	}
1576. 	free((genericptr_t) trap);
1577. }
1578. 
1579. void
1580. b_trapped(item)		/* used for doors. can be used */
1581. register char *item;    /* for anything else that opens */
1582. {
1583. 	register int dmg = rn2(15) + rnd((int)u.ulevel);
1584. 
1585. 	pline("KABOOM!!  The %s was booby-trapped!", item);
1586. 	make_stunned(HStun + dmg, TRUE);
1587. 	losehp(dmg, "explosion");
1588. }
1589. 
1590. /* Monster is hit by trap. */
1591. /* Note: doesn't work if both obj and d_override are null */
1592. static boolean
1593. thitm(tlev, mon, obj, d_override)
1594. register int tlev;
1595. register struct monst *mon;
1596. register struct obj *obj;
1597. int d_override;
1598. {
1599. 	register int strike;
1600. 	register boolean trapkilled = FALSE;
1601. 
1602. 	if (d_override) strike = 1;
1603. 	else if (obj) strike = (mon->data->ac + tlev + obj->spe <= rnd(20));
1604. 	else strike = (mon->data->ac + tlev <= rnd(20));
1605. 
1606. 	/* Actually more accurate than thitu, which doesn't take
1607. 	 * obj->spe into account.
1608. 	 */
1609. 	if(!strike) {
1610. 		if (cansee(mon->mx, mon->my))
1611. 			pline("%s is almost hit by %s!", Monnam(mon),
1612. 								doname(obj));
1613. 	} else {
1614. 		int dam = 1;
1615. 
1616. 		if (obj && cansee(mon->mx, mon->my))
1617. 			pline("%s is hit by %s!", Monnam(mon), doname(obj));
1618. 		if (d_override) dam = d_override;
1619. 		else if (obj) {
1620. 			dam = dmgval(obj, mon->data);
1621. 			if (dam < 1) dam = 1;
1622. 		}
1623. 		if ((mon->mhp -= dam) <= 0) {
1624. 			if (cansee(mon->mx, mon->my))
1625. 				pline("%s is killed!", Monnam(mon));
1626. 			else if (mon->mtame)
1627. 	You("have a sad feeling for a moment, then it passes.");
1628. 			mondied(mon);
1629. 			trapkilled = TRUE;
1630. 		}
1631. 	}
1632. 	if (obj && (!strike || d_override)) {
1633. 		obj->ox = mon->mx;
1634. 		obj->oy = mon->my;
1635. 		obj->nobj = fobj;
1636. 		fobj = obj;
1637. 		stackobj(fobj);
1638. 		levl[obj->ox][obj->oy].omask = 1;
1639. 	} else if (obj) free ((genericptr_t)obj);
1640. 
1641. 	return trapkilled;
1642. }
1643. 
1644. boolean
1645. unconscious()
1646. {
1647. 	return (multi < 0 && (!nomovemsg ||
1648. 	      !strncmp(nomovemsg,"You wake", 8) ||
1649. 	      !strncmp(nomovemsg,"You awake", 9) ||
1650. 	      !strncmp(nomovemsg,"You regain con", 15) ||
1651. 	      !strncmp(nomovemsg,"You are consci", 15)));
1652. }