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