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