1 /* $NetBSD: hack.trap.c,v 1.6 2001/03/25 20:44:03 jsm 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.6 2001/03/25 20:44:03 jsm 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 const char vowels[] = "aeiou"; 18 19 const char *const 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 const 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 } 443 if (newlevel >= 30) { 444 if (newlevel > MAXLEVEL) 445 newlevel = MAXLEVEL; 446 pline("You arrive at the center of the earth ..."); 447 pline("Unfortunately it is here that hell is located."); 448 if (Fire_resistance) { 449 pline("But the fire doesn't seem to harm you."); 450 } else { 451 pline("You burn to a crisp."); 452 dlevel = maxdlevel = newlevel; 453 killer = "visit to the hell"; 454 done("burned"); 455 } 456 } 457 if (newlevel < 0) { 458 newlevel = 0; 459 pline("You are now high above the clouds ..."); 460 if (Levitation) { 461 pline("You float gently down to earth."); 462 done("escaped"); 463 } 464 pline("Unfortunately, you don't know how to fly."); 465 pline("You fall down a few thousand feet and break your neck."); 466 dlevel = 0; 467 killer = "fall"; 468 done("died"); 469 } 470 goto_level(newlevel, FALSE); /* calls done("escaped") if 471 * newlevel==0 */ 472 } 473 474 void 475 drown() 476 { 477 pline("You fall into a pool!"); 478 pline("You can't swim!"); 479 if (rn2(3) < u.uluck + 2) { 480 /* most scrolls become unreadable */ 481 struct obj *obj; 482 483 for (obj = invent; obj; obj = obj->nobj) 484 if (obj->olet == SCROLL_SYM && rn2(12) > u.uluck) 485 obj->otyp = SCR_BLANK_PAPER; 486 /* we should perhaps merge these scrolls ? */ 487 488 pline("You attempt a teleport spell."); /* utcsri!carroll */ 489 (void) dotele(); 490 if (levl[u.ux][u.uy].typ != POOL) 491 return; 492 } 493 pline("You drown ..."); 494 killer = "pool of water"; 495 done("drowned"); 496 } 497