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