pc-hack

PC HACK 3.61 source code (archival)
git clone http://frotz.net/git/pc-hack.git
Log | Files | Refs

trap.c (10231B)


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