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