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