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