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