trap.c (10231B)
1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 2 /* trap.c - version 1.0.3 */ 3 4 #include <stdio.h> 5 #include "hack.h" 6 7 extern struct monst *makemon(); 8 9 char vowels[] = "aeiou"; 10 11 char *traps[] = { 12 " bear trap", 13 "n arrow trap", 14 " dart trap", 15 " trapdoor", 16 " teleportation trap", 17 " pit", 18 " sleeping gas trap", 19 " piercer", 20 " mimic" 21 }; 22 23 struct trap * 24 maketrap(x,y,typ) 25 register x,y,typ; 26 { 27 register struct trap *ttmp; 28 29 ttmp = newtrap(); 30 ttmp->ttyp = typ; 31 ttmp->tseen = 0; 32 ttmp->once = 0; 33 ttmp->tx = x; 34 ttmp->ty = y; 35 ttmp->ntrap = ftrap; 36 ftrap = ttmp; 37 return(ttmp); 38 } 39 40 dotrap(trap) register struct trap *trap; { 41 register int ttype = trap->ttyp; 42 43 nomul(0); 44 if(trap->tseen && !rn2(5) && ttype != PIT) 45 pline("You escape a%s.", traps[ttype]); 46 else { 47 trap->tseen = 1; 48 switch(ttype) { 49 case SLP_GAS_TRAP: 50 pline("A cloud of gas puts you to sleep!"); 51 nomul(-rnd(25)); 52 break; 53 case BEAR_TRAP: 54 if(Levitation) { 55 pline("You float over a bear trap."); 56 break; 57 } 58 u.utrap = 4 + rn2(4); 59 u.utraptype = TT_BEARTRAP; 60 pline("A bear trap closes on your foot!"); 61 break; 62 case PIERC: 63 deltrap(trap); 64 if(makemon(PM_PIERCER,u.ux,u.uy)) { 65 pline("A piercer suddenly drops from the ceiling!"); 66 if(uarmh) 67 pline("Its blow glances off your helmet."); 68 else 69 (void) thitu(3,d(4,6),"falling piercer"); 70 } 71 break; 72 case ARROW_TRAP: 73 pline("An arrow shoots out at you!"); 74 if(!thitu(8,rnd(6),"arrow")){ 75 mksobj_at(ARROW, u.ux, u.uy); 76 fobj->quan = 1; 77 } 78 break; 79 case TRAPDOOR: 80 if(!xdnstair) { 81 pline("A trap door in the ceiling opens and a rock falls on your head!"); 82 if(uarmh) pline("Fortunately, you are wearing a helmet!"); 83 losehp(uarmh ? 2 : d(2,10),"falling rock"); 84 mksobj_at(ROCK, u.ux, u.uy); 85 fobj->quan = 1; 86 stackobj(fobj); 87 if(Invisible) newsym(u.ux, u.uy); 88 } else { 89 register int newlevel = dlevel + 1; 90 while(!rn2(4) && newlevel < 29) 91 newlevel++; 92 pline("A trap door opens up under you!"); 93 if(Levitation || u.ustuck) { 94 pline("For some reason you don't fall in."); 95 break; 96 } 97 fflush(stdout); 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) register struct monst *mtmp; { 141 register struct trap *trap = t_at(mtmp->mx, mtmp->my); 142 register 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 register int tt = trap->ttyp; 150 #ifdef DGK 151 /* A bug fix for dumb messages by ab@unido. 152 */ 153 int in_sight = cansee(mtmp->mx,mtmp->my) 154 && (!mtmp->minvis || See_invisible); 155 #else 156 int in_sight = cansee(mtmp->mx,mtmp->my); 157 #endif 158 extern char mlarge[]; 159 160 if(mtmp->mtrapseen & (1 << tt)) { 161 /* he has been in such a trap - perhaps he escapes */ 162 if(rn2(4)) return(0); 163 } 164 mtmp->mtrapseen |= (1 << tt); 165 switch (tt) { 166 case BEAR_TRAP: 167 if(index(mlarge, mtmp->data->mlet)) { 168 if(in_sight) 169 pline("%s is caught in a bear trap!", 170 Monnam(mtmp)); 171 else 172 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(!index("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 selftouch(arg) char *arg; { 238 if(uwep && uwep->otyp == DEAD_COCKATRICE){ 239 pline("%s touch the dead cockatrice.", arg); 240 pline("You turn to stone."); 241 killer = objects[uwep->otyp].oc_name; 242 done("died"); 243 } 244 } 245 246 float_up(){ 247 if(u.utrap) { 248 if(u.utraptype == TT_PIT) { 249 u.utrap = 0; 250 pline("You float up, out of the pit!"); 251 } else { 252 pline("You float up, only your leg is still stuck."); 253 } 254 } else 255 pline("You start to float in the air!"); 256 } 257 258 float_down(){ 259 register struct trap *trap; 260 pline("You float gently to the ground."); 261 if(trap = t_at(u.ux,u.uy)) 262 switch(trap->ttyp) { 263 case PIERC: 264 break; 265 case TRAPDOOR: 266 if(!xdnstair || u.ustuck) break; 267 /* fall into next case */ 268 default: 269 dotrap(trap); 270 } 271 pickup(1); 272 } 273 274 vtele() { 275 #include "mkroom.h" 276 register struct mkroom *croom; 277 for(croom = &rooms[0]; croom->hx >= 0; croom++) 278 if(croom->rtype == VAULT) { 279 register x,y; 280 281 x = rn2(2) ? croom->lx : croom->hx; 282 y = rn2(2) ? croom->ly : croom->hy; 283 if(teleok(x,y)) { 284 teleds(x,y); 285 return; 286 } 287 } 288 tele(); 289 } 290 291 tele() { 292 extern coord getpos(); 293 coord cc; 294 register int nux,nuy; 295 296 if(Teleport_control) { 297 pline("To what position do you want to be teleported?"); 298 cc = getpos(1, "the desired position"); /* 1: force valid */ 299 /* possible extensions: introduce a small error if 300 magic power is low; allow transfer to solid rock */ 301 if(teleok(cc.x, cc.y)){ 302 teleds(cc.x, cc.y); 303 return; 304 } 305 pline("Sorry ..."); 306 } 307 do { 308 nux = rnd(COLNO-1); 309 nuy = rn2(ROWNO); 310 } while(!teleok(nux, nuy)); 311 teleds(nux, nuy); 312 } 313 314 teleds(nux, nuy) 315 register int nux,nuy; 316 { 317 if(Punished) unplacebc(); 318 unsee(); 319 u.utrap = 0; 320 u.ustuck = 0; 321 u.ux = nux; 322 u.uy = nuy; 323 setsee(); 324 if(Punished) placebc(1); 325 if(u.uswallow){ 326 u.uswldtim = u.uswallow = 0; 327 docrt(); 328 } 329 nomul(0); 330 if(levl[nux][nuy].typ == POOL && !Levitation) 331 drown(); 332 (void) inshop(); 333 pickup(1); 334 if(!Blind) read_engr_at(u.ux,u.uy); 335 } 336 337 teleok(x,y) register int x,y; { /* might throw him into a POOL */ 338 return( isok(x,y) && !IS_ROCK(levl[x][y].typ) && !m_at(x,y) && 339 !sobj_at(ENORMOUS_ROCK,x,y) && !t_at(x,y) 340 ); 341 /* Note: gold is permitted (because of vaults) */ 342 } 343 344 dotele() { 345 extern char pl_character[]; 346 347 if( 348 #ifdef WIZARD 349 !wizard && 350 #endif /* WIZARD /**/ 351 (!Teleportation || u.ulevel < 6 || 352 (pl_character[0] != 'W' && u.ulevel < 10))) { 353 pline("You are not able to teleport at will."); 354 return(0); 355 } 356 if(u.uhunger <= 100 || u.ustr < 6) { 357 pline("You miss the strength for a teleport spell."); 358 return(1); 359 } 360 tele(); 361 morehungry(100); 362 return(1); 363 } 364 365 placebc(attach) int attach; { 366 if(!uchain || !uball){ 367 impossible("Where are your chain and ball??"); 368 return; 369 } 370 uball->ox = uchain->ox = u.ux; 371 uball->oy = uchain->oy = u.uy; 372 if(attach){ 373 uchain->nobj = fobj; 374 fobj = uchain; 375 if(!carried(uball)){ 376 uball->nobj = fobj; 377 fobj = uball; 378 } 379 } 380 } 381 382 unplacebc(){ 383 if(!carried(uball)){ 384 freeobj(uball); 385 unpobj(uball); 386 } 387 freeobj(uchain); 388 unpobj(uchain); 389 } 390 391 level_tele() { 392 register int newlevel; 393 if(Teleport_control) { 394 char buf[BUFSZ]; 395 396 do { 397 pline("To what level do you want to teleport? [type a number] "); 398 getlin(buf); 399 } while(!digit(buf[0]) && (buf[0] != '-' || !digit(buf[1]))); 400 newlevel = atoi(buf); 401 } else { 402 #ifdef DGK 403 /* 1 chance in 5 of random tport to HELL */ 404 newlevel = rn2(5) ? 5 + rn2(20) : 30; 405 #else 406 newlevel = 5 + rn2(20); /* 5 - 24 */ 407 #endif 408 if(dlevel == newlevel) 409 if(!xdnstair) newlevel--; else newlevel++; 410 } 411 if(newlevel >= 30) { 412 if(newlevel > MAXLEVEL) newlevel = MAXLEVEL; 413 pline("You arrive at the center of the earth ..."); 414 #ifdef DGK 415 fflush(stdout); 416 #endif 417 pline("Unfortunately it is here that hell is located."); 418 if(Fire_resistance) { 419 pline("But the fire doesn't seem to harm you."); 420 } else { 421 pline("You burn to a crisp."); 422 dlevel = maxdlevel = newlevel; 423 killer = "visit to hell"; 424 done("burned"); 425 } 426 } 427 if(newlevel < 0) { 428 newlevel = 0; 429 pline("You are now high above the clouds ..."); 430 if(Levitation) { 431 pline("You float gently down to earth."); 432 done("escaped"); 433 } 434 pline("Unfortunately, you don't know how to fly."); 435 pline("You plummet to the ground and break your neck."); 436 dlevel = 0; 437 killer = "fall"; 438 done("died"); 439 } 440 441 goto_level(newlevel, FALSE); /* calls done("escaped") if newlevel==0 */ 442 } 443 444 drown() 445 { 446 pline("You fall into a pool!"); 447 pline("You can't swim!"); 448 if(rn2(3) < u.uluck+2) { 449 /* most scrolls become unreadable */ 450 register struct obj *obj; 451 452 for(obj = invent; obj; obj = obj->nobj) 453 if(obj->olet == SCROLL_SYM && rn2(12) > u.uluck) 454 obj->otyp = SCR_BLANK_PAPER; 455 /* we should perhaps merge these scrolls ? */ 456 457 pline("You attempt a teleport spell."); /* utcsri!carroll */ 458 (void) dotele(); 459 if(levl[u.ux][u.uy].typ != POOL) return; 460 } 461 pline("You drown ..."); 462 killer = "pool of water"; 463 done("drowned"); 464 }