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