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