xref: /csrg-svn/games/hack/hack.trap.c (revision 41267)
1*41267Sbostic /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
2*41267Sbostic /* hack.trap.c - version 1.0.3 */
3*41267Sbostic 
4*41267Sbostic #include	"hack.h"
5*41267Sbostic 
6*41267Sbostic extern struct monst *makemon();
7*41267Sbostic 
8*41267Sbostic char vowels[] = "aeiou";
9*41267Sbostic 
10*41267Sbostic char *traps[] = {
11*41267Sbostic 	" bear trap",
12*41267Sbostic 	"n arrow trap",
13*41267Sbostic 	" dart trap",
14*41267Sbostic 	" trapdoor",
15*41267Sbostic 	" teleportation trap",
16*41267Sbostic 	" pit",
17*41267Sbostic 	" sleeping gas trap",
18*41267Sbostic 	" piercer",
19*41267Sbostic 	" mimic"
20*41267Sbostic };
21*41267Sbostic 
22*41267Sbostic struct trap *
maketrap(x,y,typ)23*41267Sbostic maketrap(x,y,typ)
24*41267Sbostic register x,y,typ;
25*41267Sbostic {
26*41267Sbostic 	register struct trap *ttmp;
27*41267Sbostic 
28*41267Sbostic 	ttmp = newtrap();
29*41267Sbostic 	ttmp->ttyp = typ;
30*41267Sbostic 	ttmp->tseen = 0;
31*41267Sbostic 	ttmp->once = 0;
32*41267Sbostic 	ttmp->tx = x;
33*41267Sbostic 	ttmp->ty = y;
34*41267Sbostic 	ttmp->ntrap = ftrap;
35*41267Sbostic 	ftrap = ttmp;
36*41267Sbostic 	return(ttmp);
37*41267Sbostic }
38*41267Sbostic 
dotrap(trap)39*41267Sbostic dotrap(trap) register struct trap *trap; {
40*41267Sbostic 	register int ttype = trap->ttyp;
41*41267Sbostic 
42*41267Sbostic 	nomul(0);
43*41267Sbostic 	if(trap->tseen && !rn2(5) && ttype != PIT)
44*41267Sbostic 		pline("You escape a%s.", traps[ttype]);
45*41267Sbostic 	else {
46*41267Sbostic 		trap->tseen = 1;
47*41267Sbostic 		switch(ttype) {
48*41267Sbostic 		case SLP_GAS_TRAP:
49*41267Sbostic 			pline("A cloud of gas puts you to sleep!");
50*41267Sbostic 			nomul(-rnd(25));
51*41267Sbostic 			break;
52*41267Sbostic 		case BEAR_TRAP:
53*41267Sbostic 			if(Levitation) {
54*41267Sbostic 				pline("You float over a bear trap.");
55*41267Sbostic 				break;
56*41267Sbostic 			}
57*41267Sbostic 			u.utrap = 4 + rn2(4);
58*41267Sbostic 			u.utraptype = TT_BEARTRAP;
59*41267Sbostic 			pline("A bear trap closes on your foot!");
60*41267Sbostic 			break;
61*41267Sbostic 		case PIERC:
62*41267Sbostic 			deltrap(trap);
63*41267Sbostic 			if(makemon(PM_PIERCER,u.ux,u.uy)) {
64*41267Sbostic 			  pline("A piercer suddenly drops from the ceiling!");
65*41267Sbostic 			  if(uarmh)
66*41267Sbostic 				pline("Its blow glances off your helmet.");
67*41267Sbostic 			  else
68*41267Sbostic 				(void) thitu(3,d(4,6),"falling piercer");
69*41267Sbostic 			}
70*41267Sbostic 			break;
71*41267Sbostic 		case ARROW_TRAP:
72*41267Sbostic 			pline("An arrow shoots out at you!");
73*41267Sbostic 			if(!thitu(8,rnd(6),"arrow")){
74*41267Sbostic 				mksobj_at(ARROW, u.ux, u.uy);
75*41267Sbostic 				fobj->quan = 1;
76*41267Sbostic 			}
77*41267Sbostic 			break;
78*41267Sbostic 		case TRAPDOOR:
79*41267Sbostic 			if(!xdnstair) {
80*41267Sbostic pline("A trap door in the ceiling opens and a rock falls on your head!");
81*41267Sbostic if(uarmh) pline("Fortunately, you are wearing a helmet!");
82*41267Sbostic 			    losehp(uarmh ? 2 : d(2,10),"falling rock");
83*41267Sbostic 			    mksobj_at(ROCK, u.ux, u.uy);
84*41267Sbostic 			    fobj->quan = 1;
85*41267Sbostic 			    stackobj(fobj);
86*41267Sbostic 			    if(Invisible) newsym(u.ux, u.uy);
87*41267Sbostic 			} else {
88*41267Sbostic 			    register int newlevel = dlevel + 1;
89*41267Sbostic 				while(!rn2(4) && newlevel < 29)
90*41267Sbostic 					newlevel++;
91*41267Sbostic 				pline("A trap door opens up under you!");
92*41267Sbostic 				if(Levitation || u.ustuck) {
93*41267Sbostic  				pline("For some reason you don't fall in.");
94*41267Sbostic 					break;
95*41267Sbostic 				}
96*41267Sbostic 
97*41267Sbostic 				goto_level(newlevel, FALSE);
98*41267Sbostic 			}
99*41267Sbostic 			break;
100*41267Sbostic 		case DART_TRAP:
101*41267Sbostic 			pline("A little dart shoots out at you!");
102*41267Sbostic 			if(thitu(7,rnd(3),"little dart")) {
103*41267Sbostic 			    if(!rn2(6))
104*41267Sbostic 				poisoned("dart","poison dart");
105*41267Sbostic 			} else {
106*41267Sbostic 				mksobj_at(DART, u.ux, u.uy);
107*41267Sbostic 				fobj->quan = 1;
108*41267Sbostic 			}
109*41267Sbostic 			break;
110*41267Sbostic 		case TELEP_TRAP:
111*41267Sbostic 			if(trap->once) {
112*41267Sbostic 				deltrap(trap);
113*41267Sbostic 				newsym(u.ux,u.uy);
114*41267Sbostic 				vtele();
115*41267Sbostic 			} else {
116*41267Sbostic 				newsym(u.ux,u.uy);
117*41267Sbostic 				tele();
118*41267Sbostic 			}
119*41267Sbostic 			break;
120*41267Sbostic 		case PIT:
121*41267Sbostic 			if(Levitation) {
122*41267Sbostic 				pline("A pit opens up under you!");
123*41267Sbostic 				pline("You don't fall in!");
124*41267Sbostic 				break;
125*41267Sbostic 			}
126*41267Sbostic 			pline("You fall into a pit!");
127*41267Sbostic 			u.utrap = rn1(6,2);
128*41267Sbostic 			u.utraptype = TT_PIT;
129*41267Sbostic 			losehp(rnd(6),"fall into a pit");
130*41267Sbostic 			selftouch("Falling, you");
131*41267Sbostic 			break;
132*41267Sbostic 		default:
133*41267Sbostic 			impossible("You hit a trap of type %u", trap->ttyp);
134*41267Sbostic 		}
135*41267Sbostic 	}
136*41267Sbostic }
137*41267Sbostic 
mintrap(mtmp)138*41267Sbostic mintrap(mtmp) register struct monst *mtmp; {
139*41267Sbostic 	register struct trap *trap = t_at(mtmp->mx, mtmp->my);
140*41267Sbostic 	register int wasintrap = mtmp->mtrapped;
141*41267Sbostic 
142*41267Sbostic 	if(!trap) {
143*41267Sbostic 		mtmp->mtrapped = 0;	/* perhaps teleported? */
144*41267Sbostic 	} else if(wasintrap) {
145*41267Sbostic 		if(!rn2(40)) mtmp->mtrapped = 0;
146*41267Sbostic 	} else {
147*41267Sbostic 	    register int tt = trap->ttyp;
148*41267Sbostic 	    int in_sight = cansee(mtmp->mx,mtmp->my);
149*41267Sbostic 	    extern char mlarge[];
150*41267Sbostic 
151*41267Sbostic 	    if(mtmp->mtrapseen & (1 << tt)) {
152*41267Sbostic 		/* he has been in such a trap - perhaps he escapes */
153*41267Sbostic 		if(rn2(4)) return(0);
154*41267Sbostic 	    }
155*41267Sbostic 	    mtmp->mtrapseen |= (1 << tt);
156*41267Sbostic 	    switch (tt) {
157*41267Sbostic 		case BEAR_TRAP:
158*41267Sbostic 			if(index(mlarge, mtmp->data->mlet)) {
159*41267Sbostic 				if(in_sight)
160*41267Sbostic 				  pline("%s is caught in a bear trap!",
161*41267Sbostic 					Monnam(mtmp));
162*41267Sbostic 				else
163*41267Sbostic 				  if(mtmp->data->mlet == 'o')
164*41267Sbostic 			    pline("You hear the roaring of an angry bear!");
165*41267Sbostic 				mtmp->mtrapped = 1;
166*41267Sbostic 			}
167*41267Sbostic 			break;
168*41267Sbostic 		case PIT:
169*41267Sbostic 			/* there should be a mtmp/data -> floating */
170*41267Sbostic 			if(!index("EywBfk'& ", mtmp->data->mlet)) { /* ab */
171*41267Sbostic 				mtmp->mtrapped = 1;
172*41267Sbostic 				if(in_sight)
173*41267Sbostic 				  pline("%s falls in a pit!", Monnam(mtmp));
174*41267Sbostic 			}
175*41267Sbostic 			break;
176*41267Sbostic 		case SLP_GAS_TRAP:
177*41267Sbostic 			if(!mtmp->msleep && !mtmp->mfroz) {
178*41267Sbostic 				mtmp->msleep = 1;
179*41267Sbostic 				if(in_sight)
180*41267Sbostic 				  pline("%s suddenly falls asleep!",
181*41267Sbostic 					Monnam(mtmp));
182*41267Sbostic 			}
183*41267Sbostic 			break;
184*41267Sbostic 		case TELEP_TRAP:
185*41267Sbostic 			rloc(mtmp);
186*41267Sbostic 			if(in_sight && !cansee(mtmp->mx,mtmp->my))
187*41267Sbostic 				pline("%s suddenly disappears!",
188*41267Sbostic 					Monnam(mtmp));
189*41267Sbostic 			break;
190*41267Sbostic 		case ARROW_TRAP:
191*41267Sbostic 			if(in_sight) {
192*41267Sbostic 				pline("%s is hit by an arrow!",
193*41267Sbostic 					Monnam(mtmp));
194*41267Sbostic 			}
195*41267Sbostic 			mtmp->mhp -= 3;
196*41267Sbostic 			break;
197*41267Sbostic 		case DART_TRAP:
198*41267Sbostic 			if(in_sight) {
199*41267Sbostic 				pline("%s is hit by a dart!",
200*41267Sbostic 					Monnam(mtmp));
201*41267Sbostic 			}
202*41267Sbostic 			mtmp->mhp -= 2;
203*41267Sbostic 			/* not mondied here !! */
204*41267Sbostic 			break;
205*41267Sbostic 		case TRAPDOOR:
206*41267Sbostic 			if(!xdnstair) {
207*41267Sbostic 				mtmp->mhp -= 10;
208*41267Sbostic 				if(in_sight)
209*41267Sbostic pline("A trap door in the ceiling opens and a rock hits %s!", monnam(mtmp));
210*41267Sbostic 				break;
211*41267Sbostic 			}
212*41267Sbostic 			if(mtmp->data->mlet != 'w'){
213*41267Sbostic 				fall_down(mtmp);
214*41267Sbostic 				if(in_sight)
215*41267Sbostic 		pline("Suddenly, %s disappears out of sight.", monnam(mtmp));
216*41267Sbostic 				return(2);	/* no longer on this level */
217*41267Sbostic 			}
218*41267Sbostic 			break;
219*41267Sbostic 		case PIERC:
220*41267Sbostic 			break;
221*41267Sbostic 		default:
222*41267Sbostic 			impossible("Some monster encountered a strange trap.");
223*41267Sbostic 	    }
224*41267Sbostic 	}
225*41267Sbostic 	return(mtmp->mtrapped);
226*41267Sbostic }
227*41267Sbostic 
selftouch(arg)228*41267Sbostic selftouch(arg) char *arg; {
229*41267Sbostic 	if(uwep && uwep->otyp == DEAD_COCKATRICE){
230*41267Sbostic 		pline("%s touch the dead cockatrice.", arg);
231*41267Sbostic 		pline("You turn to stone.");
232*41267Sbostic 		killer = objects[uwep->otyp].oc_name;
233*41267Sbostic 		done("died");
234*41267Sbostic 	}
235*41267Sbostic }
236*41267Sbostic 
float_up()237*41267Sbostic float_up(){
238*41267Sbostic 	if(u.utrap) {
239*41267Sbostic 		if(u.utraptype == TT_PIT) {
240*41267Sbostic 			u.utrap = 0;
241*41267Sbostic 			pline("You float up, out of the pit!");
242*41267Sbostic 		} else {
243*41267Sbostic 			pline("You float up, only your leg is still stuck.");
244*41267Sbostic 		}
245*41267Sbostic 	} else
246*41267Sbostic 		pline("You start to float in the air!");
247*41267Sbostic }
248*41267Sbostic 
float_down()249*41267Sbostic float_down(){
250*41267Sbostic 	register struct trap *trap;
251*41267Sbostic 	pline("You float gently to the ground.");
252*41267Sbostic 	if(trap = t_at(u.ux,u.uy))
253*41267Sbostic 		switch(trap->ttyp) {
254*41267Sbostic 		case PIERC:
255*41267Sbostic 			break;
256*41267Sbostic 		case TRAPDOOR:
257*41267Sbostic 			if(!xdnstair || u.ustuck) break;
258*41267Sbostic 			/* fall into next case */
259*41267Sbostic 		default:
260*41267Sbostic 			dotrap(trap);
261*41267Sbostic 	}
262*41267Sbostic 	pickup(1);
263*41267Sbostic }
264*41267Sbostic 
vtele()265*41267Sbostic vtele() {
266*41267Sbostic #include "def.mkroom.h"
267*41267Sbostic 	register struct mkroom *croom;
268*41267Sbostic 	for(croom = &rooms[0]; croom->hx >= 0; croom++)
269*41267Sbostic 	    if(croom->rtype == VAULT) {
270*41267Sbostic 		register x,y;
271*41267Sbostic 
272*41267Sbostic 		x = rn2(2) ? croom->lx : croom->hx;
273*41267Sbostic 		y = rn2(2) ? croom->ly : croom->hy;
274*41267Sbostic 		if(teleok(x,y)) {
275*41267Sbostic 		    teleds(x,y);
276*41267Sbostic 		    return;
277*41267Sbostic 		}
278*41267Sbostic 	    }
279*41267Sbostic 	tele();
280*41267Sbostic }
281*41267Sbostic 
tele()282*41267Sbostic tele() {
283*41267Sbostic 	extern coord getpos();
284*41267Sbostic 	coord cc;
285*41267Sbostic 	register int nux,nuy;
286*41267Sbostic 
287*41267Sbostic 	if(Teleport_control) {
288*41267Sbostic 		pline("To what position do you want to be teleported?");
289*41267Sbostic 		cc = getpos(1, "the desired position"); /* 1: force valid */
290*41267Sbostic 		/* possible extensions: introduce a small error if
291*41267Sbostic 		   magic power is low; allow transfer to solid rock */
292*41267Sbostic 		if(teleok(cc.x, cc.y)){
293*41267Sbostic 			teleds(cc.x, cc.y);
294*41267Sbostic 			return;
295*41267Sbostic 		}
296*41267Sbostic 		pline("Sorry ...");
297*41267Sbostic 	}
298*41267Sbostic 	do {
299*41267Sbostic 		nux = rnd(COLNO-1);
300*41267Sbostic 		nuy = rn2(ROWNO);
301*41267Sbostic 	} while(!teleok(nux, nuy));
302*41267Sbostic 	teleds(nux, nuy);
303*41267Sbostic }
304*41267Sbostic 
teleds(nux,nuy)305*41267Sbostic teleds(nux, nuy)
306*41267Sbostic register int nux,nuy;
307*41267Sbostic {
308*41267Sbostic 	if(Punished) unplacebc();
309*41267Sbostic 	unsee();
310*41267Sbostic 	u.utrap = 0;
311*41267Sbostic 	u.ustuck = 0;
312*41267Sbostic 	u.ux = nux;
313*41267Sbostic 	u.uy = nuy;
314*41267Sbostic 	setsee();
315*41267Sbostic 	if(Punished) placebc(1);
316*41267Sbostic 	if(u.uswallow){
317*41267Sbostic 		u.uswldtim = u.uswallow = 0;
318*41267Sbostic 		docrt();
319*41267Sbostic 	}
320*41267Sbostic 	nomul(0);
321*41267Sbostic 	if(levl[nux][nuy].typ == POOL && !Levitation)
322*41267Sbostic 		drown();
323*41267Sbostic 	(void) inshop();
324*41267Sbostic 	pickup(1);
325*41267Sbostic 	if(!Blind) read_engr_at(u.ux,u.uy);
326*41267Sbostic }
327*41267Sbostic 
teleok(x,y)328*41267Sbostic teleok(x,y) register int x,y; {	/* might throw him into a POOL */
329*41267Sbostic 	return( isok(x,y) && !IS_ROCK(levl[x][y].typ) && !m_at(x,y) &&
330*41267Sbostic 		!sobj_at(ENORMOUS_ROCK,x,y) && !t_at(x,y)
331*41267Sbostic 	);
332*41267Sbostic 	/* Note: gold is permitted (because of vaults) */
333*41267Sbostic }
334*41267Sbostic 
dotele()335*41267Sbostic dotele() {
336*41267Sbostic 	extern char pl_character[];
337*41267Sbostic 
338*41267Sbostic 	if(
339*41267Sbostic #ifdef WIZARD
340*41267Sbostic 	   !wizard &&
341*41267Sbostic #endif WIZARD
342*41267Sbostic 		      (!Teleportation || u.ulevel < 6 ||
343*41267Sbostic 			(pl_character[0] != 'W' && u.ulevel < 10))) {
344*41267Sbostic 		pline("You are not able to teleport at will.");
345*41267Sbostic 		return(0);
346*41267Sbostic 	}
347*41267Sbostic 	if(u.uhunger <= 100 || u.ustr < 6) {
348*41267Sbostic 		pline("You miss the strength for a teleport spell.");
349*41267Sbostic 		return(1);
350*41267Sbostic 	}
351*41267Sbostic 	tele();
352*41267Sbostic 	morehungry(100);
353*41267Sbostic 	return(1);
354*41267Sbostic }
355*41267Sbostic 
placebc(attach)356*41267Sbostic placebc(attach) int attach; {
357*41267Sbostic 	if(!uchain || !uball){
358*41267Sbostic 		impossible("Where are your chain and ball??");
359*41267Sbostic 		return;
360*41267Sbostic 	}
361*41267Sbostic 	uball->ox = uchain->ox = u.ux;
362*41267Sbostic 	uball->oy = uchain->oy = u.uy;
363*41267Sbostic 	if(attach){
364*41267Sbostic 		uchain->nobj = fobj;
365*41267Sbostic 		fobj = uchain;
366*41267Sbostic 		if(!carried(uball)){
367*41267Sbostic 			uball->nobj = fobj;
368*41267Sbostic 			fobj = uball;
369*41267Sbostic 		}
370*41267Sbostic 	}
371*41267Sbostic }
372*41267Sbostic 
unplacebc()373*41267Sbostic unplacebc(){
374*41267Sbostic 	if(!carried(uball)){
375*41267Sbostic 		freeobj(uball);
376*41267Sbostic 		unpobj(uball);
377*41267Sbostic 	}
378*41267Sbostic 	freeobj(uchain);
379*41267Sbostic 	unpobj(uchain);
380*41267Sbostic }
381*41267Sbostic 
level_tele()382*41267Sbostic level_tele() {
383*41267Sbostic register int newlevel;
384*41267Sbostic 	if(Teleport_control) {
385*41267Sbostic 	    char buf[BUFSZ];
386*41267Sbostic 
387*41267Sbostic 	    do {
388*41267Sbostic 	      pline("To what level do you want to teleport? [type a number] ");
389*41267Sbostic 	      getlin(buf);
390*41267Sbostic 	    } while(!digit(buf[0]) && (buf[0] != '-' || !digit(buf[1])));
391*41267Sbostic 	    newlevel = atoi(buf);
392*41267Sbostic 	} else {
393*41267Sbostic 	    newlevel  = 5 + rn2(20);	/* 5 - 24 */
394*41267Sbostic 	    if(dlevel == newlevel)
395*41267Sbostic 		if(!xdnstair) newlevel--; else newlevel++;
396*41267Sbostic 	}
397*41267Sbostic 	if(newlevel >= 30) {
398*41267Sbostic 	    if(newlevel > MAXLEVEL) newlevel = MAXLEVEL;
399*41267Sbostic 	    pline("You arrive at the center of the earth ...");
400*41267Sbostic 	    pline("Unfortunately it is here that hell is located.");
401*41267Sbostic 	    if(Fire_resistance) {
402*41267Sbostic 		pline("But the fire doesn't seem to harm you.");
403*41267Sbostic 	    } else {
404*41267Sbostic 		pline("You burn to a crisp.");
405*41267Sbostic 		dlevel = maxdlevel = newlevel;
406*41267Sbostic 		killer = "visit to the hell";
407*41267Sbostic 		done("burned");
408*41267Sbostic 	    }
409*41267Sbostic 	}
410*41267Sbostic 	if(newlevel < 0) {
411*41267Sbostic 	    newlevel = 0;
412*41267Sbostic 	    pline("You are now high above the clouds ...");
413*41267Sbostic 	    if(Levitation) {
414*41267Sbostic 		pline("You float gently down to earth.");
415*41267Sbostic 		done("escaped");
416*41267Sbostic 	    }
417*41267Sbostic 	    pline("Unfortunately, you don't know how to fly.");
418*41267Sbostic 	    pline("You fall down a few thousand feet and break your neck.");
419*41267Sbostic 	    dlevel = 0;
420*41267Sbostic 	    killer = "fall";
421*41267Sbostic 	    done("died");
422*41267Sbostic 	}
423*41267Sbostic 
424*41267Sbostic 	goto_level(newlevel, FALSE); /* calls done("escaped") if newlevel==0 */
425*41267Sbostic }
426*41267Sbostic 
drown()427*41267Sbostic drown()
428*41267Sbostic {
429*41267Sbostic 	pline("You fall into a pool!");
430*41267Sbostic 	pline("You can't swim!");
431*41267Sbostic 	if(rn2(3) < u.uluck+2) {
432*41267Sbostic 		/* most scrolls become unreadable */
433*41267Sbostic 		register struct obj *obj;
434*41267Sbostic 
435*41267Sbostic 		for(obj = invent; obj; obj = obj->nobj)
436*41267Sbostic 			if(obj->olet == SCROLL_SYM && rn2(12) > u.uluck)
437*41267Sbostic 				obj->otyp = SCR_BLANK_PAPER;
438*41267Sbostic 		/* we should perhaps merge these scrolls ? */
439*41267Sbostic 
440*41267Sbostic 		pline("You attempt a teleport spell.");	/* utcsri!carroll */
441*41267Sbostic 		(void) dotele();
442*41267Sbostic 		if(levl[u.ux][u.uy].typ != POOL) return;
443*41267Sbostic 	}
444*41267Sbostic 	pline("You drown ...");
445*41267Sbostic 	killer = "pool of water";
446*41267Sbostic 	done("drowned");
447*41267Sbostic }
448