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