1 /* $OpenBSD: hack.trap.c,v 1.6 2003/05/19 06:30:56 pjanzen 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 #ifndef lint 65 static const char rcsid[] = "$OpenBSD: hack.trap.c,v 1.6 2003/05/19 06:30:56 pjanzen Exp $"; 66 #endif /* not lint */ 67 68 #include <ctype.h> 69 #include <stdlib.h> 70 #include "hack.h" 71 72 char vowels[] = "aeiou"; 73 74 char *traps[] = { 75 " bear trap", 76 "n arrow trap", 77 " dart trap", 78 " trapdoor", 79 " teleportation trap", 80 " pit", 81 " sleeping gas trap", 82 " piercer", 83 " mimic" 84 }; 85 86 static void vtele(void); 87 static void teleds(int, int); 88 static int teleok(int, int); 89 90 struct trap * 91 maketrap(int x, int y, int typ) 92 { 93 struct trap *ttmp; 94 95 ttmp = newtrap(); 96 ttmp->ttyp = typ; 97 ttmp->tseen = 0; 98 ttmp->once = 0; 99 ttmp->tx = x; 100 ttmp->ty = y; 101 ttmp->ntrap = ftrap; 102 ftrap = ttmp; 103 return(ttmp); 104 } 105 106 void 107 dotrap(struct trap *trap) 108 { 109 int ttype = trap->ttyp; 110 111 nomul(0); 112 if(trap->tseen && !rn2(5) && ttype != PIT) 113 pline("You escape a%s.", traps[ttype]); 114 else { 115 trap->tseen = 1; 116 switch(ttype) { 117 case SLP_GAS_TRAP: 118 pline("A cloud of gas puts you to sleep!"); 119 nomul(-rnd(25)); 120 break; 121 case BEAR_TRAP: 122 if(Levitation) { 123 pline("You float over a bear trap."); 124 break; 125 } 126 u.utrap = 4 + rn2(4); 127 u.utraptype = TT_BEARTRAP; 128 pline("A bear trap closes on your foot!"); 129 break; 130 case PIERC: 131 deltrap(trap); 132 if(makemon(PM_PIERCER,u.ux,u.uy)) { 133 pline("A piercer suddenly drops from the ceiling!"); 134 if(uarmh) 135 pline("Its blow glances off your helmet."); 136 else 137 (void) thitu(3,d(4,6),"falling piercer"); 138 } 139 break; 140 case ARROW_TRAP: 141 pline("An arrow shoots out at you!"); 142 if(!thitu(8,rnd(6),"arrow")){ 143 mksobj_at(ARROW, u.ux, u.uy); 144 fobj->quan = 1; 145 } 146 break; 147 case TRAPDOOR: 148 if(!xdnstair) { 149 pline("A trap door in the ceiling opens and a rock falls on your head!"); 150 if(uarmh) pline("Fortunately, you are wearing a helmet!"); 151 losehp(uarmh ? 2 : d(2,10),"falling rock"); 152 mksobj_at(ROCK, u.ux, u.uy); 153 fobj->quan = 1; 154 stackobj(fobj); 155 if(Invisible) 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 166 goto_level(newlevel, FALSE); 167 } 168 break; 169 case DART_TRAP: 170 pline("A little dart shoots out at you!"); 171 if(thitu(7,rnd(3),"little dart")) { 172 if(!rn2(6)) 173 poisoned("dart","poison dart"); 174 } else { 175 mksobj_at(DART, u.ux, u.uy); 176 fobj->quan = 1; 177 } 178 break; 179 case TELEP_TRAP: 180 if(trap->once) { 181 deltrap(trap); 182 newsym(u.ux,u.uy); 183 vtele(); 184 } else { 185 newsym(u.ux,u.uy); 186 tele(); 187 } 188 break; 189 case PIT: 190 if(Levitation) { 191 pline("A pit opens up under you!"); 192 pline("You don't fall in!"); 193 break; 194 } 195 pline("You fall into a pit!"); 196 u.utrap = rn1(6,2); 197 u.utraptype = TT_PIT; 198 losehp(rnd(6),"fall into a pit"); 199 selftouch("Falling, you"); 200 break; 201 default: 202 impossible("You hit a trap of type %u", trap->ttyp); 203 } 204 } 205 } 206 207 int 208 mintrap(struct monst *mtmp) 209 { 210 struct trap *trap = t_at(mtmp->mx, mtmp->my); 211 int wasintrap = mtmp->mtrapped; 212 213 if(!trap) { 214 mtmp->mtrapped = 0; /* perhaps teleported? */ 215 } else if(wasintrap) { 216 if(!rn2(40)) mtmp->mtrapped = 0; 217 } else { 218 int tt = trap->ttyp; 219 int in_sight = cansee(mtmp->mx,mtmp->my); 220 extern char mlarge[]; 221 222 if(mtmp->mtrapseen & (1 << tt)) { 223 /* he has been in such a trap - perhaps he escapes */ 224 if(rn2(4)) 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 234 if(mtmp->data->mlet == 'o') 235 pline("You hear the roaring of an angry bear!"); 236 mtmp->mtrapped = 1; 237 } 238 break; 239 case PIT: 240 /* there should be a mtmp/data -> floating */ 241 if(!strchr("EywBfk'& ", mtmp->data->mlet)) { /* ab */ 242 mtmp->mtrapped = 1; 243 if(in_sight) 244 pline("%s falls in a pit!", Monnam(mtmp)); 245 } 246 break; 247 case SLP_GAS_TRAP: 248 if(!mtmp->msleep && !mtmp->mfroz) { 249 mtmp->msleep = 1; 250 if(in_sight) 251 pline("%s suddenly falls asleep!", 252 Monnam(mtmp)); 253 } 254 break; 255 case TELEP_TRAP: 256 rloc(mtmp); 257 if(in_sight && !cansee(mtmp->mx,mtmp->my)) 258 pline("%s suddenly disappears!", 259 Monnam(mtmp)); 260 break; 261 case ARROW_TRAP: 262 if(in_sight) { 263 pline("%s is hit by an arrow!", 264 Monnam(mtmp)); 265 } 266 mtmp->mhp -= 3; 267 break; 268 case DART_TRAP: 269 if(in_sight) { 270 pline("%s is hit by a dart!", 271 Monnam(mtmp)); 272 } 273 mtmp->mhp -= 2; 274 /* not mondied here !! */ 275 break; 276 case TRAPDOOR: 277 if(!xdnstair) { 278 mtmp->mhp -= 10; 279 if(in_sight) 280 pline("A trap door in the ceiling opens and a rock hits %s!", monnam(mtmp)); 281 break; 282 } 283 if(mtmp->data->mlet != 'w'){ 284 fall_down(mtmp); 285 if(in_sight) 286 pline("Suddenly, %s disappears out of sight.", monnam(mtmp)); 287 return(2); /* no longer on this level */ 288 } 289 break; 290 case PIERC: 291 break; 292 default: 293 impossible("Some monster encountered a strange trap."); 294 } 295 } 296 return(mtmp->mtrapped); 297 } 298 299 void 300 selftouch(char *arg) 301 { 302 if(uwep && uwep->otyp == DEAD_COCKATRICE){ 303 pline("%s touch the dead cockatrice.", arg); 304 pline("You turn to stone."); 305 killer = objects[uwep->otyp].oc_name; 306 done("died"); 307 } 308 } 309 310 void 311 float_up() 312 { 313 if(u.utrap) { 314 if(u.utraptype == TT_PIT) { 315 u.utrap = 0; 316 pline("You float up, out of the pit!"); 317 } else { 318 pline("You float up, only your leg is still stuck."); 319 } 320 } else 321 pline("You start to float in the air!"); 322 } 323 324 int 325 float_down() 326 { 327 struct trap *trap; 328 329 pline("You float gently to the ground."); 330 if ((trap = t_at(u.ux,u.uy))) 331 switch(trap->ttyp) { 332 case PIERC: 333 break; 334 case TRAPDOOR: 335 if(!xdnstair || u.ustuck) break; 336 /* fall into next case */ 337 default: 338 dotrap(trap); 339 } 340 pickup(1); 341 return(0); /* XXX value needed in hack.potion.c */ 342 } 343 344 static void 345 vtele() 346 { 347 struct mkroom *croom; 348 349 for(croom = &rooms[0]; croom->hx >= 0; croom++) 350 if(croom->rtype == VAULT) { 351 int x,y; 352 353 x = rn2(2) ? croom->lx : croom->hx; 354 y = rn2(2) ? croom->ly : croom->hy; 355 if(teleok(x,y)) { 356 teleds(x,y); 357 return; 358 } 359 } 360 tele(); 361 } 362 363 void 364 tele() 365 { 366 coord cc; 367 int nux,nuy; 368 369 if(Teleport_control) { 370 pline("To what position do you want to be teleported?"); 371 cc = getpos(1, "the desired position"); /* 1: force valid */ 372 /* possible extensions: introduce a small error if 373 magic power is low; allow transfer to solid rock */ 374 if(teleok(cc.x, cc.y)){ 375 teleds(cc.x, cc.y); 376 return; 377 } 378 pline("Sorry ..."); 379 } 380 do { 381 nux = rnd(COLNO-1); 382 nuy = rn2(ROWNO); 383 } while(!teleok(nux, nuy)); 384 teleds(nux, nuy); 385 } 386 387 static void 388 teleds(int nux, int nuy) 389 { 390 if(Punished) unplacebc(); 391 unsee(); 392 u.utrap = 0; 393 u.ustuck = 0; 394 u.ux = nux; 395 u.uy = nuy; 396 setsee(); 397 if(Punished) 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) read_engr_at(u.ux,u.uy); 408 } 409 410 static int 411 teleok(int x, int y) 412 { /* might throw him into a POOL */ 413 return( isok(x,y) && !IS_ROCK(levl[x][y].typ) && !m_at(x,y) && 414 !sobj_at(ENORMOUS_ROCK,x,y) && !t_at(x,y) 415 ); 416 /* Note: gold is permitted (because of vaults) */ 417 } 418 419 int 420 dotele() 421 { 422 extern char pl_character[]; 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() 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() 474 { 475 int newlevel; 476 477 if(Teleport_control) { 478 char buf[BUFSZ]; 479 480 do { 481 pline("To what level do you want to teleport? [type a number] "); 482 getlin(buf); 483 } while(!isdigit(buf[0]) && (buf[0] != '-' || !isdigit(buf[1]))); 484 newlevel = atoi(buf); 485 } else { 486 newlevel = 5 + rn2(20); /* 5 - 24 */ 487 if(dlevel == newlevel) { 488 if(!xdnstair) 489 newlevel--; 490 else 491 newlevel++; 492 } 493 } 494 if(newlevel >= 30) { 495 if(newlevel > MAXLEVEL) 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 521 goto_level(newlevel, FALSE); /* calls done("escaped") if newlevel==0 */ 522 } 523 524 void 525 drown() 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[(int)u.ux][(int)u.uy].typ != POOL) 541 return; 542 } 543 pline("You drown ..."); 544 killer = "pool of water"; 545 done("drowned"); 546 } 547