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