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