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