1 | /* SCCS Id: @(#)apply.c 3.3 2000/07/23 */ 2 | /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3 | /* NetHack may be freely redistributed. See license for details. */ 4 | 5 | #include "hack.h" 6 | #include "edog.h" 7 | 8 | #ifdef OVLB 9 | 10 | static const char tools[] = { TOOL_CLASS, WEAPON_CLASS, WAND_CLASS, 0 }; 11 | static const char tools_too[] = { ALL_CLASSES, TOOL_CLASS, POTION_CLASS, 12 | WEAPON_CLASS, WAND_CLASS, 0 }; 13 | 14 | #ifdef TOURIST 15 | STATIC_DCL int FDECL(use_camera, (struct obj *)); 16 | #endif 17 | STATIC_DCL int FDECL(use_towel, (struct obj *)); 18 | STATIC_DCL boolean FDECL(its_dead, (int,int,int *)); 19 | STATIC_DCL int FDECL(use_stethoscope, (struct obj *)); 20 | STATIC_DCL void FDECL(use_whistle, (struct obj *)); 21 | STATIC_DCL void FDECL(use_magic_whistle, (struct obj *)); 22 | STATIC_DCL void FDECL(use_leash, (struct obj *)); 23 | STATIC_DCL int FDECL(use_mirror, (struct obj *)); 24 | STATIC_DCL void FDECL(use_bell, (struct obj *)); 25 | STATIC_DCL void FDECL(use_candelabrum, (struct obj *)); 26 | STATIC_DCL void FDECL(use_candle, (struct obj *)); 27 | STATIC_DCL void FDECL(use_lamp, (struct obj *)); 28 | STATIC_DCL void FDECL(light_cocktail, (struct obj *)); 29 | STATIC_DCL void FDECL(use_tinning_kit, (struct obj *)); 30 | STATIC_DCL void FDECL(use_figurine, (struct obj *)); 31 | STATIC_DCL void FDECL(use_grease, (struct obj *)); 32 | STATIC_DCL void FDECL(use_trap, (struct obj *)); 33 | STATIC_PTR int NDECL(set_trap); /* occupation callback */ 34 | STATIC_DCL int FDECL(use_whip, (struct obj *)); 35 | STATIC_DCL int FDECL(use_pole, (struct obj *)); 36 | STATIC_DCL int FDECL(use_grapple, (struct obj *)); 37 | STATIC_DCL int FDECL(do_break_wand, (struct obj *)); 38 | STATIC_DCL boolean FDECL(figurine_location_checks, 39 | (struct obj *, coord *, BOOLEAN_P)); 40 | 41 | #ifdef AMIGA 42 | void FDECL( amii_speaker, ( struct obj *, char *, int ) ); 43 | #endif 44 | 45 | static char no_elbow_room[] = "don't have enough elbow-room to maneuver."; 46 | 47 | #ifdef TOURIST 48 | STATIC_OVL int 49 | use_camera(obj) 50 | struct obj *obj; 51 | { 52 | register struct monst *mtmp; 53 | 54 | if(Underwater) { 55 | pline("Using your camera underwater would void the warranty."); 56 | return(0); 57 | } 58 | if(!getdir((char *)0)) return(0); 59 | 60 | if (obj->spe <= 0) { 61 | pline(nothing_happens); 62 | return (1); 63 | } 64 | obj->spe--; 65 | if (obj->cursed && !rn2(2)) { 66 | (void) zapyourself(obj, TRUE); 67 | } else if (u.uswallow) { 68 | You("take a picture of %s %s.", s_suffix(mon_nam(u.ustuck)), 69 | is_animal(u.ustuck->data) ? "stomach" : "interior"); 70 | } else if (u.dz) { 71 | You("take a picture of the %s.", 72 | (u.dz > 0) ? surface(u.ux,u.uy) : ceiling(u.ux,u.uy)); 73 | } else if (!u.dx && !u.dy) { 74 | (void) zapyourself(obj, TRUE); 75 | } else if ((mtmp = bhit(u.dx, u.dy, COLNO, FLASHED_LIGHT, 76 | (int FDECL((*),(MONST_P,OBJ_P)))0, 77 | (int FDECL((*),(OBJ_P,OBJ_P)))0, 78 | obj)) != 0) { 79 | obj->ox = u.ux, obj->oy = u.uy; 80 | (void) flash_hits_mon(mtmp, obj); 81 | } 82 | return 1; 83 | } 84 | #endif 85 | 86 | STATIC_OVL int 87 | use_towel(obj) 88 | struct obj *obj; 89 | { 90 | if(!freehand()) { 91 | You("have no free %s!", body_part(HAND)); 92 | return 0; 93 | } else if (obj->owornmask) { 94 | You("cannot use it while you're wearing it!"); 95 | return 0; 96 | } else if (obj->cursed) { 97 | long old; 98 | switch (rn2(3)) { 99 | case 2: 100 | old = Glib; 101 | Glib += rn1(10, 3); 102 | Your("%s %s!", makeplural(body_part(HAND)), 103 | (old ? "are filthier than ever" : "get slimy")); 104 | return 1; 105 | case 1: 106 | if (!ublindf) { 107 | old = u.ucreamed; 108 | u.ucreamed += rn1(10, 3); 109 | pline("Yecch! Your %s %s gunk on it!", body_part(FACE), 110 | (old ? "has more" : "now has")); 111 | make_blinded(Blinded + (long)u.ucreamed - old, TRUE); 112 | } else { 113 | const char *what = (ublindf->otyp == LENSES) ? 114 | "lenses" : "blindfold"; 115 | if (ublindf->cursed) { 116 | You("push your %s %s.", what, 117 | rn2(2) ? "cock-eyed" : "crooked"); 118 | } else { 119 | struct obj *saved_ublindf = ublindf; 120 | You("push your %s off.", what); 121 | Blindf_off(ublindf); 122 | dropx(saved_ublindf); 123 | } 124 | } 125 | return 1; 126 | case 0: 127 | break; 128 | } 129 | } 130 | 131 | if (Glib) { 132 | Glib = 0; 133 | You("wipe off your %s.", makeplural(body_part(HAND))); 134 | return 1; 135 | } else if(u.ucreamed) { 136 | Blinded -= u.ucreamed; 137 | u.ucreamed = 0; 138 | 139 | if (!Blinded) { 140 | pline("You've got the glop off."); 141 | Blinded = 1; 142 | make_blinded(0L,TRUE); 143 | } else { 144 | Your("%s feels clean now.", body_part(FACE)); 145 | } 146 | return 1; 147 | } 148 | 149 | Your("%s and %s are already clean.", 150 | body_part(FACE), makeplural(body_part(HAND))); 151 | 152 | return 0; 153 | } 154 | 155 | /* maybe give a stethoscope message based on floor objects */ 156 | STATIC_OVL boolean 157 | its_dead(rx, ry, resp) 158 | int rx, ry, *resp; 159 | { 160 | struct obj *otmp; 161 | struct trap *ttmp; 162 | 163 | /* additional stethoscope messages from jyoung@apanix.apana.org.au */ 164 | if (Hallucination && sobj_at(CORPSE, rx, ry)) { 165 | /* (a corpse doesn't retain the monster's sex, 166 | so we're forced to use generic pronoun here) */ 167 | You_hear("a voice say, \"It's dead, Jim.\""); 168 | *resp = 1; 169 | return TRUE; 170 | } else if (Role_if(PM_HEALER) && ((otmp = sobj_at(CORPSE, rx, ry)) != 0 || 171 | (otmp = sobj_at(STATUE, rx, ry)) != 0)) { 172 | /* possibly should check uppermost {corpse,statue} in the pile 173 | if both types are present, but it's not worth the effort */ 174 | if (vobj_at(rx, ry)->otyp == STATUE) otmp = vobj_at(rx, ry); 175 | if (otmp->otyp == CORPSE) { 176 | You("determine that %s unfortunate being is dead.", 177 | (rx == u.ux && ry == u.uy) ? "this" : "that"); 178 | } else { 179 | ttmp = t_at(rx, ry); 180 | pline("%s appears to be in %s health for a statue.", 181 | The(mons[otmp->corpsenm].mname), 182 | (ttmp && ttmp->ttyp == STATUE_TRAP) ? 183 | "extraordinary" : "excellent"); 184 | } 185 | return TRUE; 186 | } 187 | return FALSE; 188 | } 189 | 190 | static char hollow_str[] = "a hollow sound. This must be a secret %s!"; 191 | 192 | /* Strictly speaking it makes no sense for usage of a stethoscope to 193 | not take any time; however, unless it did, the stethoscope would be 194 | almost useless. As a compromise, one use per turn is free, another 195 | uses up the turn; this makes curse status have a tangible effect. */ 196 | STATIC_OVL int 197 | use_stethoscope(obj) 198 | register struct obj *obj; 199 | { 200 | static long last_used = 0; 201 | struct monst *mtmp; 202 | struct rm *lev; 203 | int rx, ry, res; 204 | 205 | if (nohands(youmonst.data)) { /* should also check for no ears and/or deaf */ 206 | You("have no hands!"); /* not `body_part(HAND)' */ 207 | return 0; 208 | } else if (!freehand()) { 209 | You("have no free %s.", body_part(HAND)); 210 | return 0; 211 | } 212 | if (!getdir((char *)0)) return 0; 213 | 214 | res = (moves + monstermoves == last_used); 215 | last_used = moves + monstermoves; 216 | 217 | if (u.uswallow && (u.dx || u.dy || u.dz)) { 218 | mstatusline(u.ustuck); 219 | return res; 220 | #ifdef STEED 221 | } else if (u.usteed && u.dz > 0) { 222 | mstatusline(u.usteed); 223 | return res; 224 | #endif 225 | } else if (u.dz) { 226 | if (Underwater) 227 | You_hear("faint splashing."); 228 | else if (u.dz < 0 || !can_reach_floor()) 229 | You_cant("reach the %s.", 230 | (u.dz > 0) ? surface(u.ux,u.uy) : ceiling(u.ux,u.uy)); 231 | else if (its_dead(u.ux, u.uy, &res)) 232 | ; /* message already given */ 233 | else if (Is_stronghold(&u.uz)) 234 | You_hear("the crackling of hellfire."); 235 | else 236 | pline_The("%s seems healthy enough.", surface(u.ux,u.uy)); 237 | return res; 238 | } else if (obj->cursed && !rn2(2)) { 239 | You_hear("your heart beat."); 240 | return res; 241 | } 242 | if (Stunned || (Confusion && !rn2(5))) confdir(); 243 | if (!u.dx && !u.dy) { 244 | ustatusline(); 245 | return res; 246 | } 247 | rx = u.ux + u.dx; ry = u.uy + u.dy; 248 | if (!isok(rx,ry)) { 249 | You_hear("a faint typing noise."); 250 | return 0; 251 | } 252 | if ((mtmp = m_at(rx,ry)) != 0) { 253 | mstatusline(mtmp); 254 | if (mtmp->mundetected) { 255 | mtmp->mundetected = 0; 256 | if (cansee(rx,ry)) newsym(mtmp->my,mtmp->my); 257 | } 258 | if (!canspotmon(mtmp)) 259 | map_invisible(rx,ry); 260 | return res; 261 | } 262 | if (glyph_is_invisible(levl[rx][ry].glyph)) { 263 | unmap_object(rx, ry); 264 | newsym(rx, ry); 265 | pline_The("invisible monster must have moved."); 266 | } 267 | lev = &levl[rx][ry]; 268 | switch(lev->typ) { 269 | case SDOOR: 270 | You_hear(hollow_str, "door"); 271 | cvt_sdoor_to_door(lev); /* ->typ = DOOR */ 272 | if (Blind) feel_location(rx,ry); 273 | else newsym(rx,ry); 274 | return res; 275 | case SCORR: 276 | You_hear(hollow_str, "passage"); 277 | lev->typ = CORR; 278 | if (Blind) feel_location(rx,ry); 279 | else newsym(rx,ry); 280 | return res; 281 | } 282 | 283 | if (!its_dead(rx, ry, &res)) 284 | You("hear nothing special."); /* not You_hear() */ 285 | return res; 286 | } 287 | 288 | static char whistle_str[] = "produce a %s whistling sound."; 289 | 290 | STATIC_OVL void 291 | use_whistle(obj) 292 | struct obj *obj; 293 | { 294 | You(whistle_str, obj->cursed ? "shrill" : "high"); 295 | wake_nearby(); 296 | } 297 | 298 | STATIC_OVL void 299 | use_magic_whistle(obj) 300 | struct obj *obj; 301 | { 302 | register struct monst *mtmp, *nextmon; 303 | 304 | if(obj->cursed && !rn2(2)) { 305 | You("produce a high-pitched humming noise."); 306 | wake_nearby(); 307 | } else { 308 | int pet_cnt = 0; 309 | You(whistle_str, Hallucination ? "normal" : "strange"); 310 | for(mtmp = fmon; mtmp; mtmp = nextmon) { 311 | nextmon = mtmp->nmon; /* trap might kill mon */ 312 | if (DEADMONSTER(mtmp)) continue; 313 | if (mtmp->mtame) { 314 | if (mtmp->mtrapped) { 315 | /* no longer in previous trap (affects mintrap) */ 316 | mtmp->mtrapped = 0; 317 | fill_pit(mtmp->mx, mtmp->my); 318 | } 319 | mnexto(mtmp); 320 | if (canspotmon(mtmp)) ++pet_cnt; 321 | if (mintrap(mtmp) == 2) change_luck(-1); 322 | } 323 | } 324 | if (pet_cnt > 0) makeknown(MAGIC_WHISTLE); 325 | } 326 | } 327 | 328 | boolean 329 | um_dist(x,y,n) 330 | register xchar x, y, n; 331 | { 332 | return((boolean)(abs(u.ux - x) > n || abs(u.uy - y) > n)); 333 | } 334 | 335 | int 336 | number_leashed() 337 | { 338 | register int i = 0; 339 | register struct obj *obj; 340 | 341 | for(obj = invent; obj; obj = obj->nobj) 342 | if(obj->otyp == LEASH && obj->leashmon != 0) i++; 343 | return(i); 344 | } 345 | 346 | void 347 | o_unleash(otmp) /* otmp is about to be destroyed or stolen */ 348 | register struct obj *otmp; 349 | { 350 | register struct monst *mtmp; 351 | 352 | for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 353 | if(mtmp->m_id == (unsigned)otmp->leashmon) 354 | mtmp->mleashed = 0; 355 | otmp->leashmon = 0; 356 | } 357 | 358 | void 359 | m_unleash(mtmp) /* mtmp is about to die, or become untame */ 360 | register struct monst *mtmp; 361 | { 362 | register struct obj *otmp; 363 | 364 | for(otmp = invent; otmp; otmp = otmp->nobj) 365 | if(otmp->otyp == LEASH && 366 | otmp->leashmon == (int)mtmp->m_id) 367 | otmp->leashmon = 0; 368 | mtmp->mleashed = 0; 369 | } 370 | 371 | void 372 | unleash_all() /* player is about to die (for bones) */ 373 | { 374 | register struct obj *otmp; 375 | register struct monst *mtmp; 376 | 377 | for(otmp = invent; otmp; otmp = otmp->nobj) 378 | if(otmp->otyp == LEASH) otmp->leashmon = 0; 379 | for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 380 | if(mtmp->mtame) mtmp->mleashed = 0; 381 | } 382 | 383 | #define MAXLEASHED 2 384 | 385 | /* ARGSUSED */ 386 | STATIC_OVL void 387 | use_leash(obj) 388 | struct obj *obj; 389 | { 390 | register int x, y; 391 | register struct monst *mtmp; 392 | int spotmon; 393 | 394 | if(!obj->leashmon && number_leashed() >= MAXLEASHED) { 395 | You("cannot leash any more pets."); 396 | return; 397 | } 398 | 399 | if(!getdir((char *)0)) return; 400 | 401 | x = u.ux + u.dx; 402 | y = u.uy + u.dy; 403 | 404 | if((x == u.ux) && (y == u.uy)) { 405 | pline("Leash yourself? Very funny..."); 406 | return; 407 | } 408 | 409 | if(!(mtmp = m_at(x, y))) { 410 | There("is no creature there."); 411 | return; 412 | } 413 | 414 | spotmon = canspotmon(mtmp); 415 | 416 | if(!mtmp->mtame) { 417 | if(!spotmon) 418 | There("is no creature there."); 419 | else 420 | pline("%s %s leashed!", Monnam(mtmp), (!obj->leashmon) ? 421 | "cannot be" : "is not"); 422 | return; 423 | } 424 | if(!obj->leashmon) { 425 | if(mtmp->mleashed) { 426 | pline("This %s is already leashed.", 427 | spotmon ? l_monnam(mtmp) : "monster"); 428 | return; 429 | } 430 | You("slip the leash around %s%s.", 431 | spotmon ? "your " : "", l_monnam(mtmp)); 432 | mtmp->mleashed = 1; 433 | obj->leashmon = (int)mtmp->m_id; 434 | mtmp->msleeping = 0; 435 | return; 436 | } 437 | if(obj->leashmon != (int)mtmp->m_id) { 438 | pline("This leash is not attached to that creature."); 439 | return; 440 | } else { 441 | if(obj->cursed) { 442 | pline_The("leash would not come off!"); 443 | obj->bknown = TRUE; 444 | return; 445 | } 446 | mtmp->mleashed = 0; 447 | obj->leashmon = 0; 448 | You("remove the leash from %s%s.", 449 | spotmon ? "your " : "", l_monnam(mtmp)); 450 | } 451 | return; 452 | } 453 | 454 | struct obj * 455 | get_mleash(mtmp) /* assuming mtmp->mleashed has been checked */ 456 | register struct monst *mtmp; 457 | { 458 | register struct obj *otmp; 459 | 460 | otmp = invent; 461 | while(otmp) { 462 | if(otmp->otyp == LEASH && otmp->leashmon == (int)mtmp->m_id) 463 | return(otmp); 464 | otmp = otmp->nobj; 465 | } 466 | return((struct obj *)0); 467 | } 468 | 469 | #endif /* OVLB */ 470 | #ifdef OVL1 471 | 472 | boolean 473 | next_to_u() 474 | { 475 | register struct monst *mtmp; 476 | register struct obj *otmp; 477 | 478 | for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) { 479 | if (DEADMONSTER(mtmp)) continue; 480 | if(mtmp->mleashed) { 481 | if (distu(mtmp->mx,mtmp->my) > 2) mnexto(mtmp); 482 | if (distu(mtmp->mx,mtmp->my) > 2) { 483 | for(otmp = invent; otmp; otmp = otmp->nobj) 484 | if(otmp->otyp == LEASH && 485 | otmp->leashmon == (int)mtmp->m_id) { 486 | if(otmp->cursed) return(FALSE); 487 | You_feel("%s leash go slack.", 488 | (number_leashed() > 1) ? "a" : "the"); 489 | mtmp->mleashed = 0; 490 | otmp->leashmon = 0; 491 | } 492 | } 493 | } 494 | } 495 | return(TRUE); 496 | } 497 | 498 | #endif /* OVL1 */ 499 | #ifdef OVL0 500 | 501 | void 502 | check_leash(x, y) 503 | register xchar x, y; 504 | { 505 | register struct obj *otmp; 506 | register struct monst *mtmp = fmon; 507 | 508 | for(otmp = invent; otmp; otmp = otmp->nobj) 509 | if(otmp->otyp == LEASH && otmp->leashmon != 0) { 510 | while(mtmp) { 511 | if(!DEADMONSTER(mtmp) && ((int)mtmp->m_id == otmp->leashmon && 512 | (dist2(u.ux,u.uy,mtmp->mx,mtmp->my) > 513 | dist2(x,y,mtmp->mx,mtmp->my))) 514 | ) { 515 | if(otmp->cursed && !breathless(mtmp->data)) { 516 | if(um_dist(mtmp->mx, mtmp->my, 5)) { 517 | pline("%s chokes to death!",Monnam(mtmp)); 518 | mondied(mtmp); 519 | } else 520 | if(um_dist(mtmp->mx, mtmp->my, 3)) 521 | pline("%s chokes on the leash!", 522 | Monnam(mtmp)); 523 | } else { 524 | if(um_dist(mtmp->mx, mtmp->my, 5)) { 525 | pline("%s leash snaps loose!", 526 | s_suffix(Monnam(mtmp))); 527 | m_unleash(mtmp); 528 | } else { 529 | if(um_dist(mtmp->mx, mtmp->my, 3)) { 530 | You("pull on the leash."); 531 | if (mtmp->data->msound != MS_SILENT) 532 | switch(rn2(3)) { 533 | case 0: growl(mtmp); break; 534 | case 1: yelp(mtmp); break; 535 | default: whimper(mtmp); break; 536 | } 537 | } 538 | } 539 | } 540 | } 541 | mtmp = mtmp->nmon; 542 | } 543 | } 544 | } 545 | 546 | #endif /* OVL0 */ 547 | #ifdef OVLB 548 | 549 | boolean 550 | wield_tool(obj) 551 | struct obj *obj; 552 | { 553 | if(welded(uwep)) { 554 | /* Andreas Bormann - ihnp4!decvax!mcvax!unido!ab */ 555 | if(flags.verbose) { 556 | pline("Since your weapon is welded to your %s,", 557 | bimanual(uwep) ? 558 | (const char *)makeplural(body_part(HAND)) 559 | : body_part(HAND)); 560 | pline("you cannot wield that %s.", xname(obj)); 561 | } 562 | return(FALSE); 563 | } 564 | if (cantwield(youmonst.data)) { 565 | You_cant("hold it strongly enough."); 566 | return(FALSE); 567 | } 568 | /* Check shield */ 569 | if (uarms && bimanual(obj)) { 570 | You("cannot wield a two-handed tool while wearing a shield."); 571 | return(FALSE); 572 | } 573 | if(uquiver == obj) setuqwep((struct obj *)0); 574 | if(uswapwep == obj) { 575 | (void) doswapweapon(); 576 | /* If doswapweapon failed... */ 577 | if(uswapwep == obj) return (FALSE); 578 | } else { 579 | You("now wield %s.", doname(obj)); 580 | setuwep(obj); 581 | } 582 | if (uwep != obj) return(FALSE); /* rewielded old object after dying */ 583 | /* applying weapon or tool that gets wielded ends two-weapon combat */ 584 | if (u.twoweap) 585 | untwoweapon(); 586 | if (obj->oclass != WEAPON_CLASS) 587 | unweapon = TRUE; 588 | return(TRUE); 589 | } 590 | 591 | #define WEAK 3 /* from eat.c */ 592 | 593 | static char look_str[] = "look %s."; 594 | 595 | STATIC_OVL int 596 | use_mirror(obj) 597 | struct obj *obj; 598 | { 599 | register struct monst *mtmp; 600 | register char mlet; 601 | boolean vis; 602 | 603 | if(!getdir((char *)0)) return 0; 604 | if(obj->cursed && !rn2(2)) { 605 | if (!Blind) 606 | pline_The("mirror fogs up and doesn't reflect!"); 607 | return 1; 608 | } 609 | if(!u.dx && !u.dy && !u.dz) { 610 | if(!Blind && !Invisible) { 611 | if (u.umonnum == PM_FLOATING_EYE) { 612 | if (!Free_action) { 613 | pline(Hallucination ? 614 | "Yow! The mirror stares back!" : 615 | "Yikes! You've frozen yourself!"); 616 | nomul(-rnd((MAXULEV+6) - u.ulevel)); 617 | } else You("stiffen momentarily under your gaze."); 618 | } else if (youmonst.data->mlet == S_VAMPIRE) 619 | You("don't have a reflection."); 620 | else if (u.umonnum == PM_UMBER_HULK) { 621 | pline("Huh? That doesn't look like you!"); 622 | make_confused(HConfusion + d(3,4),FALSE); 623 | } else if (Hallucination) 624 | You(look_str, hcolor((char *)0)); 625 | else if (Sick) 626 | You(look_str, "peaked"); 627 | else if (u.uhs >= WEAK) 628 | You(look_str, "undernourished"); 629 | else You("look as %s as ever.", 630 | ACURR(A_CHA) > 14 ? 631 | (poly_gender()==1 ? "beautiful" : "handsome") : 632 | "ugly"); 633 | } else { 634 | You_cant("see your %s %s.", 635 | ACURR(A_CHA) > 14 ? 636 | (poly_gender()==1 ? "beautiful" : "handsome") : 637 | "ugly", 638 | body_part(FACE)); 639 | } 640 | return 1; 641 | } 642 | if(u.uswallow) { 643 | if (!Blind) You("reflect %s %s.", s_suffix(mon_nam(u.ustuck)), 644 | is_animal(u.ustuck->data)? "stomach" : "interior"); 645 | return 1; 646 | } 647 | if(Underwater) { 648 | You(Hallucination ? 649 | "give the fish a chance to fix their makeup." : 650 | "reflect the murky water."); 651 | return 1; 652 | } 653 | if(u.dz) { 654 | if (!Blind) 655 | You("reflect the %s.", 656 | (u.dz > 0) ? surface(u.ux,u.uy) : ceiling(u.ux,u.uy)); 657 | return 1; 658 | } 659 | mtmp = bhit(u.dx, u.dy, COLNO, INVIS_BEAM, 660 | (int FDECL((*),(MONST_P,OBJ_P)))0, 661 | (int FDECL((*),(OBJ_P,OBJ_P)))0, 662 | obj); 663 | if (!mtmp || !haseyes(mtmp->data)) 664 | return 1; 665 | 666 | vis = canseemon(mtmp); 667 | mlet = mtmp->data->mlet; 668 | if (mtmp->msleeping) { 669 | if (vis) 670 | pline ("%s is too tired to look at your mirror.", 671 | Monnam(mtmp)); 672 | } else if (!mtmp->mcansee) { 673 | if (vis) 674 | pline("%s can't see anything right now.", Monnam(mtmp)); 675 | /* some monsters do special things */ 676 | } else if (mlet == S_VAMPIRE || mlet == S_GHOST) { 677 | if (vis) 678 | pline ("%s doesn't have a reflection.", Monnam(mtmp)); 679 | } else if(!mtmp->mcan && mtmp->data == &mons[PM_MEDUSA]) { 680 | if (mon_reflects(mtmp, "The gaze is reflected away by %s %s!")) 681 | return 1; 682 | if (vis) 683 | pline("%s is turned to stone!", Monnam(mtmp)); 684 | stoned = TRUE; 685 | killed(mtmp); 686 | } else if(!mtmp->mcan && !mtmp->minvis && 687 | mtmp->data == &mons[PM_FLOATING_EYE]) { 688 | int tmp = d((int)mtmp->m_lev, (int)mtmp->data->mattk[0].damd); 689 | if (!rn2(4)) tmp = 120; 690 | /* Note: floating eyes cannot use their abilities while invisible, 691 | * but Medusa and umber hulks can. 692 | */ 693 | if (vis) 694 | pline("%s is frozen by its reflection.", Monnam(mtmp)); 695 | else You_hear("%s stop moving.",something); 696 | mtmp->mcanmove = 0; 697 | if ( (int) mtmp->mfrozen + tmp > 127) 698 | mtmp->mfrozen = 127; 699 | else mtmp->mfrozen += tmp; 700 | } else if(!mtmp->mcan && mtmp->data == &mons[PM_UMBER_HULK]) { 701 | if (vis) 702 | pline ("%s confuses itself!", Monnam(mtmp)); 703 | mtmp->mconf = 1; 704 | } else if(!mtmp->mcan && !mtmp->minvis && (mlet == S_NYMPH 705 | || mtmp->data==&mons[PM_SUCCUBUS])) { 706 | if (vis) { 707 | pline ("%s admires herself in your mirror.", Monnam(mtmp)); 708 | pline ("She takes it!"); 709 | } else pline ("It steals your mirror!"); 710 | setnotworn(obj); /* in case mirror was wielded */ 711 | freeinv(obj); 712 | (void) mpickobj(mtmp,obj); 713 | if (!tele_restrict(mtmp)) rloc(mtmp); 714 | } else if (!is_unicorn(mtmp->data) && !humanoid(mtmp->data) && 715 | (!mtmp->minvis || perceives(mtmp->data)) && rn2(5)) { 716 | if (vis) 717 | pline ("%s is frightened by its reflection.", 718 | Monnam(mtmp)); 719 | mtmp->mflee = 1; 720 | mtmp->mfleetim += d(2,4); 721 | } else if (!Blind) { 722 | if (mtmp->minvis && !See_invisible) 723 | ; 724 | else if ((mtmp->minvis && !perceives(mtmp->data)) 725 | || !haseyes(mtmp->data)) 726 | pline("%s doesn't seem to notice its reflection.", 727 | Monnam(mtmp)); 728 | else 729 | pline("%s ignores %s reflection.", 730 | Monnam(mtmp), his[pronoun_gender(mtmp)]); 731 | } 732 | return 1; 733 | } 734 | 735 | STATIC_OVL void 736 | use_bell(obj) 737 | register struct obj *obj; 738 | { 739 | struct monst *mtmp; 740 | boolean wakem = FALSE, learno = FALSE, 741 | ordinary = (obj->otyp != BELL_OF_OPENING || !obj->spe), 742 | invoking = (obj->otyp == BELL_OF_OPENING && 743 | invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)); 744 | 745 | You("ring %s.", the(xname(obj))); 746 | 747 | if (Underwater || (u.uswallow && ordinary)) { 748 | #ifdef AMIGA 749 | amii_speaker( obj, "AhDhGqEqDhEhAqDqFhGw", AMII_MUFFLED_VOLUME ); 750 | #endif 751 | pline("But the sound is muffled."); 752 | 753 | } else if (invoking && ordinary) { 754 | /* needs to be recharged... */ 755 | pline("But it makes no sound."); 756 | learno = TRUE; /* help player figure out why */ 757 | 758 | } else if (ordinary) { 759 | #ifdef AMIGA 760 | amii_speaker( obj, "ahdhgqeqdhehaqdqfhgw", AMII_MUFFLED_VOLUME ); 761 | #endif 762 | if (obj->cursed && !rn2(4) && 763 | /* note: once any of them are gone, we stop all of them */ 764 | !(mvitals[PM_WOOD_NYMPH].mvflags & G_GONE) && 765 | !(mvitals[PM_WATER_NYMPH].mvflags & G_GONE) && 766 | !(mvitals[PM_MOUNTAIN_NYMPH].mvflags & G_GONE) && 767 | (mtmp = makemon(mkclass(S_NYMPH, 0), 768 | u.ux, u.uy, NO_MINVENT)) != 0) { 769 | You("summon %s!", a_monnam(mtmp)); 770 | if (!obj_resists(obj, 93, 100)) { 771 | pline("%s has shattered!", The(xname(obj))); 772 | useup(obj); 773 | } else switch (rn2(3)) { 774 | default: 775 | break; 776 | case 1: mon_adjust_speed(mtmp, 2); 777 | break; 778 | case 2: /* no explanation; it just happens... */ 779 | nomovemsg = ""; 780 | nomul(-rnd(2)); 781 | break; 782 | } 783 | } 784 | wakem = TRUE; 785 | 786 | } else { 787 | /* charged Bell of Opening */ 788 | check_unpaid(obj); 789 | obj->spe--; 790 | 791 | if (u.uswallow) { 792 | if (!obj->cursed) 793 | (void) openit(); 794 | else 795 | pline(nothing_happens); 796 | 797 | } else if (obj->cursed) { 798 | coord mm; 799 | 800 | mm.x = u.ux; 801 | mm.y = u.uy; 802 | mkundead(&mm, FALSE, NO_MINVENT); 803 | wakem = TRUE; 804 | 805 | } else if (invoking) { 806 | pline("%s issues an unsettling shrill sound...", 807 | The(xname(obj))); 808 | #ifdef AMIGA 809 | amii_speaker( obj, "aefeaefeaefeaefeaefe", AMII_LOUDER_VOLUME ); 810 | #endif 811 | obj->age = moves; 812 | learno = TRUE; 813 | wakem = TRUE; 814 | 815 | } else if (obj->blessed) { 816 | int res = 0; 817 | 818 | #ifdef AMIGA 819 | amii_speaker( obj, "ahahahDhEhCw", AMII_SOFT_VOLUME ); 820 | #endif 821 | if (uchain) { 822 | unpunish(); 823 | res = 1; 824 | } 825 | res += openit(); 826 | switch (res) { 827 | case 0: pline(nothing_happens); break; 828 | case 1: pline("%s opens...", Something); 829 | learno = TRUE; break; 830 | default: pline("Things open around you..."); 831 | learno = TRUE; break; 832 | } 833 | 834 | } else { /* uncursed */ 835 | #ifdef AMIGA 836 | amii_speaker( obj, "AeFeaeFeAefegw", AMII_OKAY_VOLUME ); 837 | #endif 838 | if (findit() != 0) learno = TRUE; 839 | else pline(nothing_happens); 840 | } 841 | 842 | } /* charged BofO */ 843 | 844 | if (learno) { 845 | makeknown(BELL_OF_OPENING); 846 | obj->known = 1; 847 | } 848 | if (wakem) wake_nearby(); 849 | } 850 | 851 | STATIC_OVL void 852 | use_candelabrum(obj) 853 | register struct obj *obj; 854 | { 855 | if(Underwater) { 856 | You("cannot make fire under water."); 857 | return; 858 | } 859 | if(obj->lamplit) { 860 | You("snuff the candle%s.", obj->spe > 1 ? "s" : ""); 861 | end_burn(obj, TRUE); 862 | return; 863 | } 864 | if(obj->spe <= 0) { 865 | pline("This %s has no candles.", xname(obj)); 866 | return; 867 | } 868 | if(u.uswallow || obj->cursed) { 869 | if (!Blind) 870 | pline_The("candle%s flicker%s for a moment, then die%s.", 871 | obj->spe > 1 ? "s" : "", 872 | obj->spe > 1 ? "" : "s", 873 | obj->spe > 1 ? "" : "s"); 874 | return; 875 | } 876 | if(obj->spe < 7) { 877 | There("%s only %d candle%s in %s.", 878 | obj->spe == 1 ? "is" : "are", 879 | obj->spe, 880 | obj->spe > 1 ? "s" : "", 881 | the(xname(obj))); 882 | if (!Blind) 883 | pline("%s lit. %s shines dimly.", 884 | obj->spe == 1 ? "It is" : "They are", The(xname(obj))); 885 | } else { 886 | pline("%s's candles burn%s", The(xname(obj)), 887 | (Blind ? "." : " brightly!")); 888 | } 889 | if (!invocation_pos(u.ux, u.uy)) { 890 | pline_The("candle%s being rapidly consumed!", 891 | (obj->spe > 1 ? "s are" : " is")); 892 | obj->age /= 2; 893 | } else { 894 | if(obj->spe == 7) { 895 | if (Blind) 896 | pline("%s radiates a strange warmth!", The(xname(obj))); 897 | else 898 | pline("%s glows with a strange light!", The(xname(obj))); 899 | } 900 | obj->known = 1; 901 | } 902 | begin_burn(obj, FALSE); 903 | } 904 | 905 | STATIC_OVL void 906 | use_candle(obj) 907 | register struct obj *obj; 908 | { 909 | register struct obj *otmp; 910 | char qbuf[QBUFSZ]; 911 | 912 | if(u.uswallow) { 913 | You(no_elbow_room); 914 | return; 915 | } 916 | if(Underwater) { 917 | pline("Sorry, fire and water don't mix."); 918 | return; 919 | } 920 | 921 | otmp = carrying(CANDELABRUM_OF_INVOCATION); 922 | if(!otmp || otmp->spe == 7) { 923 | use_lamp(obj); 924 | return; 925 | } 926 | 927 | Sprintf(qbuf, "Attach %s", the(xname(obj))); 928 | Sprintf(eos(qbuf), " to %s?", the(xname(otmp))); 929 | if(yn(qbuf) == 'n') { 930 | if (!obj->lamplit) 931 | You("try to light %s...", the(xname(obj))); 932 | use_lamp(obj); 933 | return; 934 | } else { 935 | if ((long)otmp->spe + obj->quan > 7L) 936 | (void)splitobj(obj, 7L - (long)otmp->spe); 937 | You("attach %ld%s candle%s to %s.", 938 | obj->quan, !otmp->spe ? "" : " more", 939 | plur(obj->quan), the(xname(otmp))); 940 | if (!otmp->spe || otmp->age > obj->age) 941 | otmp->age = obj->age; 942 | otmp->spe += (int)obj->quan; 943 | if (otmp->lamplit && !obj->lamplit) 944 | pline_The("new candle%s magically ignite%s!", 945 | plur(obj->quan), 946 | (obj->quan > 1L) ? "" : "s"); 947 | else if (!otmp->lamplit && obj->lamplit) 948 | pline("%s out.", (obj->quan > 1L) ? "They go" : "It goes"); 949 | if (obj->unpaid) 950 | verbalize("You %s %s, you bought %s!", 951 | otmp->lamplit ? "burn" : "use", 952 | (obj->quan > 1L) ? "them" : "it", 953 | (obj->quan > 1L) ? "them" : "it"); 954 | if (obj->quan < 7L && otmp->spe == 7) 955 | pline("%s now has seven%s candles attached.", 956 | The(xname(otmp)), otmp->lamplit ? " lit" : ""); 957 | /* candelabrum's light range might increase */ 958 | if (otmp->lamplit) obj_merge_light_sources(otmp, otmp); 959 | /* candles are no longer a separate light source */ 960 | if (obj->lamplit) end_burn(obj, TRUE); 961 | /* candles are now gone */ 962 | useupall(obj); 963 | } 964 | } 965 | 966 | boolean 967 | snuff_candle(otmp) /* call in drop, throw, and put in box, etc. */ 968 | register struct obj *otmp; 969 | { 970 | register boolean candle = Is_candle(otmp); 971 | 972 | if ((candle || otmp->otyp == CANDELABRUM_OF_INVOCATION) && 973 | otmp->lamplit) { 974 | char buf[BUFSZ]; 975 | xchar x, y; 976 | register boolean many = candle ? otmp->quan > 1L : otmp->spe > 1; 977 | 978 | (void) get_obj_location(otmp, &x, &y, 0); 979 | if (otmp->where == OBJ_MINVENT ? cansee(x,y) : !Blind) 980 | pline("%s %scandle%s flame%s extinguished.", 981 | Shk_Your(buf, otmp), 982 | (candle ? "" : "candelabrum's "), 983 | (many ? "s'" : "'s"), (many ? "s are" : " is")); 984 | end_burn(otmp, TRUE); 985 | return(TRUE); 986 | } 987 | return(FALSE); 988 | } 989 | 990 | /* called when lit lamp is hit by water or put into a container or 991 | you've been swallowed by a monster; obj might be in transit while 992 | being thrown or dropped so don't assume that its location is valid */ 993 | boolean 994 | snuff_lit(obj) 995 | struct obj *obj; 996 | { 997 | xchar x, y; 998 | 999 | if (obj->lamplit) { 1000 | if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP || 1001 | obj->otyp == BRASS_LANTERN || obj->otyp == POT_OIL) { 1002 | (void) get_obj_location(obj, &x, &y, 0); 1003 | if (obj->where == OBJ_MINVENT ? cansee(x,y) : !Blind) 1004 | pline("%s goes out!", Yname2(obj)); 1005 | end_burn(obj, TRUE); 1006 | return TRUE; 1007 | } 1008 | if (snuff_candle(obj)) return TRUE; 1009 | } 1010 | return FALSE; 1011 | } 1012 | 1013 | STATIC_OVL void 1014 | use_lamp(obj) 1015 | struct obj *obj; 1016 | { 1017 | char buf[BUFSZ]; 1018 | 1019 | if(Underwater) { 1020 | pline("This is not a diving lamp."); 1021 | return; 1022 | } 1023 | if(obj->lamplit) { 1024 | if(obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP || 1025 | obj->otyp == BRASS_LANTERN) 1026 | pline("%s lamp is now off.", Shk_Your(buf, obj)); 1027 | else 1028 | You("snuff out %s.", yname(obj)); 1029 | end_burn(obj, TRUE); 1030 | return; 1031 | } 1032 | /* magic lamps with an spe == 0 (wished for) cannot be lit */ 1033 | if ((!Is_candle(obj) && obj->age == 0) 1034 | || (obj->otyp == MAGIC_LAMP && obj->spe == 0)) { 1035 | if (obj->otyp == BRASS_LANTERN) 1036 | Your("lamp has run out of power."); 1037 | else pline("This %s has no oil.", xname(obj)); 1038 | return; 1039 | } 1040 | if (obj->cursed && !rn2(2)) { 1041 | pline("%s flicker%s for a moment, then die%s.", 1042 | The(xname(obj)), 1043 | obj->quan > 1L ? "" : "s", 1044 | obj->quan > 1L ? "" : "s"); 1045 | } else { 1046 | if(obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP || 1047 | obj->otyp == BRASS_LANTERN) { 1048 | check_unpaid(obj); 1049 | pline("%s lamp is now on.", Shk_Your(buf, obj)); 1050 | } else { /* candle(s) */ 1051 | pline("%s flame%s burn%s%s", 1052 | s_suffix(Yname2(obj)), 1053 | plur(obj->quan), 1054 | obj->quan > 1L ? "" : "s", 1055 | Blind ? "." : " brightly!"); 1056 | if (obj->unpaid && costly_spot(u.ux, u.uy) && 1057 | obj->age == 20L * (long)objects[obj->otyp].oc_cost) { 1058 | const char *ithem = obj->quan > 1L ? "them" : "it"; 1059 | verbalize("You burn %s, you bought %s!", ithem, ithem); 1060 | bill_dummy_object(obj); 1061 | } 1062 | } 1063 | begin_burn(obj, FALSE); 1064 | } 1065 | } 1066 | 1067 | STATIC_OVL void 1068 | light_cocktail(obj) 1069 | struct obj *obj; /* obj is a potion of oil */ 1070 | { 1071 | char buf[BUFSZ]; 1072 | 1073 | if (u.uswallow) { 1074 | You(no_elbow_room); 1075 | return; 1076 | } 1077 | 1078 | if (obj->lamplit) { 1079 | You("snuff the lit potion."); 1080 | end_burn(obj, TRUE); 1081 | /* 1082 | * Free & add to re-merge potion. This will average the 1083 | * age of the potions. Not exactly the best solution, 1084 | * but its easy. 1085 | */ 1086 | freeinv(obj); 1087 | (void) addinv(obj); 1088 | return; 1089 | } else if (Underwater) { 1090 | There("is not enough oxygen to sustain a fire."); 1091 | return; 1092 | } 1093 | 1094 | You("light %s potion.%s", shk_your(buf, obj), 1095 | Blind ? "" : " It gives off a dim light."); 1096 | if (obj->unpaid && costly_spot(u.ux, u.uy)) { 1097 | /* Normally, we shouldn't both partially and fully charge 1098 | * for an item, but (Yendorian Fuel) Taxes are inevitable... 1099 | */ 1100 | check_unpaid(obj); 1101 | bill_dummy_object(obj); 1102 | } 1103 | makeknown(obj->otyp); 1104 | 1105 | if (obj->quan > 1L) { 1106 | (void) splitobj(obj, 1L); 1107 | begin_burn(obj, FALSE); /* burn before free to get position */ 1108 | obj_extract_self(obj); /* free from inv */ 1109 | 1110 | /* shouldn't merge */ 1111 | obj = hold_another_object(obj, "You drop %s!", 1112 | doname(obj), (const char *)0); 1113 | } else 1114 | begin_burn(obj, FALSE); 1115 | } 1116 | 1117 | static NEARDATA const char cuddly[] = { TOOL_CLASS, 0 }; 1118 | 1119 | int 1120 | dorub() 1121 | { 1122 | struct obj *obj = getobj(cuddly, "rub"); 1123 | 1124 | if(!obj || (obj != uwep && !wield_tool(obj))) return 0; 1125 | 1126 | /* now uwep is obj */ 1127 | if (uwep->otyp == MAGIC_LAMP) { 1128 | if (uwep->spe > 0 && !rn2(3)) { 1129 | check_unpaid_usage(uwep, TRUE); /* unusual item use */ 1130 | djinni_from_bottle(uwep); 1131 | makeknown(MAGIC_LAMP); 1132 | uwep->otyp = OIL_LAMP; 1133 | uwep->spe = 0; /* for safety */ 1134 | uwep->age = rn1(500,1000); 1135 | if (uwep->lamplit) begin_burn(uwep, TRUE); 1136 | } else if (rn2(2) && !Blind) 1137 | You("see a puff of smoke."); 1138 | else pline(nothing_happens); 1139 | } else if (obj->otyp == BRASS_LANTERN) { 1140 | /* message from Adventure */ 1141 | pline("Rubbing the electric lamp is not particularly rewarding."); 1142 | pline("Anyway, nothing exciting happens."); 1143 | } else pline(nothing_happens); 1144 | return 1; 1145 | } 1146 | 1147 | int 1148 | dojump() 1149 | { 1150 | /* Physical jump */ 1151 | return jump(0); 1152 | } 1153 | 1154 | int 1155 | jump(magic) 1156 | int magic; /* 0=Physical, otherwise skill level */ 1157 | { 1158 | coord cc; 1159 | 1160 | if (!magic && (nolimbs(youmonst.data) || slithy(youmonst.data))) { 1161 | /* normally (nolimbs || slithy) implies !Jumping, 1162 | but that isn't necessarily the case for knights */ 1163 | You_cant("jump; you have no legs!"); 1164 | return 0; 1165 | } else if (!magic && !Jumping) { 1166 | You_cant("jump very far."); 1167 | return 0; 1168 | } else if (u.uswallow) { 1169 | if (magic) { 1170 | You("bounce around a little."); 1171 | return 1; 1172 | } 1173 | pline("You've got to be kidding!"); 1174 | return 0; 1175 | } else if (u.uinwater) { 1176 | if (magic) { 1177 | You("swish around a little."); 1178 | return 1; 1179 | } 1180 | pline("This calls for swimming, not jumping!"); 1181 | return 0; 1182 | } else if (u.ustuck) { 1183 | if (magic) { 1184 | You("writhe a little in the grasp of %s!", mon_nam(u.ustuck)); 1185 | return 1; 1186 | } 1187 | You("cannot escape from %s!", mon_nam(u.ustuck)); 1188 | return 0; 1189 | } else if (Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)) { 1190 | if (magic) { 1191 | You("flail around a little."); 1192 | return 1; 1193 | } 1194 | You("don't have enough traction to jump."); 1195 | return 0; 1196 | } else if (!magic && near_capacity() > UNENCUMBERED) { 1197 | You("are carrying too much to jump!"); 1198 | return 0; 1199 | } else if (!magic && (u.uhunger <= 100 || ACURR(A_STR) < 6)) { 1200 | You("lack the strength to jump!"); 1201 | return 0; 1202 | } else if (Wounded_legs) { 1203 | long wl = (Wounded_legs & BOTH_SIDES); 1204 | const char *bp = body_part(LEG); 1205 | 1206 | if (wl == BOTH_SIDES) bp = makeplural(bp); 1207 | #ifdef STEED 1208 | if (u.usteed) 1209 | pline("%s is in no shape for jumping.", Monnam(u.usteed)); 1210 | else 1211 | #endif 1212 | Your("%s%s %s in no shape for jumping.", 1213 | (wl == LEFT_SIDE) ? "left " : 1214 | (wl == RIGHT_SIDE) ? "right " : "", 1215 | bp, (wl == BOTH_SIDES) ? "are" : "is"); 1216 | return 0; 1217 | } 1218 | #ifdef STEED 1219 | else if (u.usteed && u.utrap) { 1220 | pline("%s is stuck in a trap.", Monnam(u.usteed)); 1221 | return (0); 1222 | } 1223 | #endif 1224 | 1225 | pline("Where do you want to jump?"); 1226 | cc.x = u.ux; 1227 | cc.y = u.uy; 1228 | if (getpos(&cc, TRUE, "the desired position") < 0) 1229 | return 0; /* user pressed ESC */ 1230 | if (!magic && !(HJumping & ~INTRINSIC) && !EJumping && 1231 | distu(cc.x, cc.y) != 5) { 1232 | /* The Knight jumping restriction still applies when riding a 1233 | * horse. After all, what shape is the knight piece in chess? 1234 | */ 1235 | pline("Illegal move!"); 1236 | return 0; 1237 | } else if (distu(cc.x, cc.y) > (magic ? 6+magic*3 : 9)) { 1238 | pline("Too far!"); 1239 | return 0; 1240 | } else if (!cansee(cc.x, cc.y)) { 1241 | You("cannot see where to land!"); 1242 | return 0; 1243 | } else if (!isok(cc.x, cc.y)) { 1244 | You("cannot jump there!"); 1245 | return 0; 1246 | } else { 1247 | coord uc; 1248 | int range, temp; 1249 | 1250 | if(u.utrap) 1251 | switch(u.utraptype) { 1252 | case TT_BEARTRAP: { 1253 | register long side = rn2(3) ? LEFT_SIDE : RIGHT_SIDE; 1254 | You("rip yourself free of the bear trap! Ouch!"); 1255 | losehp(rnd(10), "jumping out of a bear trap", KILLED_BY); 1256 | set_wounded_legs(side, rn1(1000,500)); 1257 | break; 1258 | } 1259 | case TT_PIT: 1260 | You("leap from the pit!"); 1261 | break; 1262 | case TT_WEB: 1263 | You("tear the web apart as you pull yourself free!"); 1264 | deltrap(t_at(u.ux,u.uy)); 1265 | break; 1266 | case TT_LAVA: 1267 | You("pull yourself above the lava!"); 1268 | u.utrap = 0; 1269 | return 1; 1270 | case TT_INFLOOR: 1271 | You("strain your %s, but you're still stuck in the floor.", 1272 | makeplural(body_part(LEG))); 1273 | set_wounded_legs(LEFT_SIDE, rn1(10, 11)); 1274 | set_wounded_legs(RIGHT_SIDE, rn1(10, 11)); 1275 | return 1; 1276 | } 1277 | 1278 | /* 1279 | * Check the path from uc to cc, calling hurtle_step at each 1280 | * location. The final position actually reached will be 1281 | * in cc. 1282 | */ 1283 | uc.x = u.ux; 1284 | uc.y = u.uy; 1285 | /* calculate max(abs(dx), abs(dy)) as the range */ 1286 | range = cc.x - uc.x; 1287 | if (range < 0) range = -range; 1288 | temp = cc.y - uc.y; 1289 | if (temp < 0) temp = -temp; 1290 | if (range < temp) 1291 | range = temp; 1292 | (void) walk_path(&uc, &cc, hurtle_step, (genericptr_t)&range); 1293 | 1294 | /* A little Sokoban guilt... */ 1295 | if (In_sokoban(&u.uz)) 1296 | change_luck(-1); 1297 | 1298 | teleds(cc.x, cc.y); 1299 | nomul(-1); 1300 | nomovemsg = ""; 1301 | morehungry(rnd(25)); 1302 | return 1; 1303 | } 1304 | } 1305 | 1306 | boolean 1307 | tinnable(corpse) 1308 | struct obj *corpse; 1309 | { 1310 | if (corpse->oeaten) return 0; 1311 | if (!mons[corpse->corpsenm].cnutrit) return 0; 1312 | return 1; 1313 | } 1314 | 1315 | STATIC_OVL void 1316 | use_tinning_kit(obj) 1317 | register struct obj *obj; 1318 | { 1319 | register struct obj *corpse, *can; 1320 | 1321 | /* This takes only 1 move. If this is to be changed to take many 1322 | * moves, we've got to deal with decaying corpses... 1323 | */ 1324 | if (obj->spe <= 0) { 1325 | You("seem to be out of tins."); 1326 | return; 1327 | } 1328 | if (!(corpse = floorfood("tin", 2))) return; 1329 | if (corpse->oeaten) { 1330 | You("cannot tin %s which is partly eaten.",something); 1331 | return; 1332 | } 1333 | if (touch_petrifies(&mons[corpse->corpsenm]) 1334 | && !Stone_resistance && !uarmg) { 1335 | char kbuf[BUFSZ]; 1336 | 1337 | if (poly_when_stoned(youmonst.data)) 1338 | You("tin %s without wearing gloves.", 1339 | an(mons[corpse->corpsenm].mname)); 1340 | else { 1341 | pline("Tinning %s without wearing gloves is a fatal mistake...", 1342 | an(mons[corpse->corpsenm].mname)); 1343 | Sprintf(kbuf, "trying to tin %s without gloves", 1344 | an(mons[corpse->corpsenm].mname)); 1345 | } 1346 | instapetrify(kbuf); 1347 | } 1348 | if (is_rider(&mons[corpse->corpsenm])) { 1349 | (void) revive_corpse(corpse); 1350 | verbalize("Yes... But War does not preserve its enemies..."); 1351 | return; 1352 | } 1353 | if (mons[corpse->corpsenm].cnutrit == 0) { 1354 | pline("That's too insubstantial to tin."); 1355 | return; 1356 | } 1357 | obj->spe--; 1358 | if ((can = mksobj(TIN, FALSE, FALSE)) != 0) { 1359 | static const char you_buy_it[] = "You tin it, you bought it!"; 1360 | 1361 | can->corpsenm = corpse->corpsenm; 1362 | can->cursed = obj->cursed; 1363 | can->blessed = obj->blessed; 1364 | can->owt = weight(can); 1365 | can->known = 1; 1366 | can->spe = -1; /* Mark tinned tins. No spinach allowed... */ 1367 | if (carried(corpse)) { 1368 | if (corpse->unpaid) 1369 | verbalize(you_buy_it); 1370 | useup(corpse); 1371 | } else { 1372 | if (costly_spot(corpse->ox, corpse->oy) && !corpse->no_charge) 1373 | verbalize(you_buy_it); 1374 | useupf(corpse, 1L); 1375 | } 1376 | can = hold_another_object(can, "You make, but cannot pick up, %s.", 1377 | doname(can), (const char *)0); 1378 | } else impossible("Tinning failed."); 1379 | } 1380 | 1381 | void 1382 | use_unicorn_horn(obj) 1383 | struct obj *obj; 1384 | { 1385 | #define PROP_COUNT 6 /* number of properties we're dealing with */ 1386 | #define ATTR_COUNT (A_MAX*3) /* number of attribute points we might fix */ 1387 | int idx, val, val_limit, 1388 | trouble_count, unfixable_trbl, did_prop, did_attr; 1389 | int trouble_list[PROP_COUNT + ATTR_COUNT]; 1390 | 1391 | if (obj && obj->cursed) { 1392 | long lcount = (long) rnd(100); 1393 | 1394 | switch (rn2(6)) { 1395 | case 0: make_sick(Sick ? Sick/3L + 1L : (long)rn1(ACURR(A_CON),20), 1396 | xname(obj), TRUE, SICK_NONVOMITABLE); 1397 | break; 1398 | case 1: make_blinded(Blinded + lcount, TRUE); 1399 | break; 1400 | case 2: if (!Confusion) 1401 | You("suddenly feel %s.", 1402 | Hallucination ? "trippy" : "confused"); 1403 | make_confused(HConfusion + lcount, TRUE); 1404 | break; 1405 | case 3: make_stunned(HStun + lcount, TRUE); 1406 | break; 1407 | case 4: (void) adjattrib(rn2(A_MAX), -1, FALSE); 1408 | break; 1409 | case 5: make_hallucinated(HHallucination + lcount, TRUE, 0L); 1410 | break; 1411 | } 1412 | return; 1413 | } 1414 | 1415 | /* 1416 | * Entries in the trouble list use a very simple encoding scheme. 1417 | */ 1418 | #define prop2trbl(X) ((X) + A_MAX) 1419 | #define attr2trbl(Y) (Y) 1420 | #define prop_trouble(X) trouble_list[trouble_count++] = prop2trbl(X) 1421 | #define attr_trouble(Y) trouble_list[trouble_count++] = attr2trbl(Y) 1422 | 1423 | trouble_count = unfixable_trbl = did_prop = did_attr = 0; 1424 | 1425 | /* collect property troubles */ 1426 | if (Sick) prop_trouble(SICK); 1427 | if (Blinded > (long)(u.ucreamed + 1)) prop_trouble(BLINDED); 1428 | if (HHallucination) prop_trouble(HALLUC); 1429 | if (Vomiting) prop_trouble(VOMITING); 1430 | if (HConfusion) prop_trouble(CONFUSION); 1431 | if (HStun) prop_trouble(STUNNED); 1432 | /* keep track of unfixed trouble, for message adjustment below 1433 | (can't "feel great" with these problems present) */ 1434 | if (Stoned) unfixable_trbl++; 1435 | if (Strangled) unfixable_trbl++; 1436 | if (Wounded_legs) unfixable_trbl++; 1437 | 1438 | /* collect attribute troubles */ 1439 | for (idx = 0; idx < A_MAX; idx++) { 1440 | val_limit = AMAX(idx); 1441 | /* don't recover strength lost from hunger */ 1442 | if (idx == A_STR && u.uhs >= WEAK) val_limit--; 1443 | /* don't recover more than 3 points worth of any attribute */ 1444 | if (val_limit > ABASE(idx) + 3) val_limit = ABASE(idx) + 3; 1445 | 1446 | for (val = ABASE(idx); val < val_limit; val++) 1447 | attr_trouble(idx); 1448 | /* keep track of unfixed trouble, for message adjustment below */ 1449 | unfixable_trbl += (AMAX(idx) - val_limit); 1450 | } 1451 | 1452 | if (trouble_count == 0) { 1453 | pline(nothing_happens); 1454 | return; 1455 | } else if (trouble_count > 1) { /* shuffle */ 1456 | int i, j, k; 1457 | 1458 | for (i = trouble_count - 1; i > 0; i--) 1459 | if ((j = rn2(i + 1)) != i) { 1460 | k = trouble_list[j]; 1461 | trouble_list[j] = trouble_list[i]; 1462 | trouble_list[i] = k; 1463 | } 1464 | } 1465 | 1466 | /* 1467 | * Chances for number of troubles to be fixed 1468 | * 0 1 2 3 4 5 6 7 1469 | * blessed: 22.7% 22.7% 19.5% 15.4% 10.7% 5.7% 2.6% 0.8% 1470 | * uncursed: 35.4% 35.4% 22.9% 6.3% 0 0 0 0 1471 | */ 1472 | val_limit = rn2( d(2, (obj && obj->blessed) ? 4 : 2) ); 1473 | if (val_limit > trouble_count) val_limit = trouble_count; 1474 | 1475 | /* fix [some of] the troubles */ 1476 | for (val = 0; val < val_limit; val++) { 1477 | idx = trouble_list[val]; 1478 | 1479 | switch (idx) { 1480 | case prop2trbl(SICK): 1481 | make_sick(0L, (char *) 0, TRUE, SICK_ALL); 1482 | did_prop++; 1483 | break; 1484 | case prop2trbl(BLINDED): 1485 | make_blinded(u.ucreamed ? (long)(u.ucreamed+1) : 0L, TRUE); 1486 | did_prop++; 1487 | break; 1488 | case prop2trbl(HALLUC): 1489 | make_hallucinated(0L, TRUE, 0L); 1490 | did_prop++; 1491 | break; 1492 | case prop2trbl(VOMITING): 1493 | make_vomiting(0L, TRUE); 1494 | did_prop++; 1495 | break; 1496 | case prop2trbl(CONFUSION): 1497 | make_confused(0L, TRUE); 1498 | did_prop++; 1499 | break; 1500 | case prop2trbl(STUNNED): 1501 | make_stunned(0L, TRUE); 1502 | did_prop++; 1503 | break; 1504 | default: 1505 | if (idx >= 0 && idx < A_MAX) { 1506 | ABASE(idx) += 1; 1507 | did_attr++; 1508 | } else 1509 | panic("use_unicorn_horn: bad trouble? (%d)", idx); 1510 | break; 1511 | } 1512 | } 1513 | 1514 | if (did_attr) 1515 | pline("This makes you feel %s!", 1516 | (did_prop + did_attr) == (trouble_count + unfixable_trbl) ? 1517 | "great" : "better"); 1518 | else if (!did_prop) 1519 | pline("Nothing seems to happen."); 1520 | 1521 | flags.botl = (did_attr || did_prop); 1522 | #undef PROP_COUNT 1523 | #undef ATTR_COUNT 1524 | #undef prop2trbl 1525 | #undef attr2trbl 1526 | #undef prop_trouble 1527 | #undef attr_trouble 1528 | } 1529 | 1530 | /* 1531 | * Timer callback routine: turn figurine into monster 1532 | */ 1533 | void 1534 | fig_transform(arg, timeout) 1535 | genericptr_t arg; 1536 | long timeout; 1537 | { 1538 | struct obj *figurine = (struct obj *)arg; 1539 | struct monst *mtmp; 1540 | coord cc; 1541 | boolean cansee_spot, silent, okay_spot; 1542 | boolean redraw = FALSE; 1543 | char monnambuf[BUFSZ], carriedby[BUFSZ]; 1544 | 1545 | if (!figurine) { 1546 | #ifdef DEBUG 1547 | pline("null figurine in fig_transform()"); 1548 | #endif 1549 | return; 1550 | } 1551 | silent = (timeout != monstermoves); /* happened while away */ 1552 | okay_spot = get_obj_location(figurine, &cc.x, &cc.y, 0); 1553 | if (figurine->where == OBJ_INVENT || 1554 | figurine->where == OBJ_MINVENT) 1555 | okay_spot = enexto(&cc, cc.x, cc.y, 1556 | &mons[figurine->corpsenm]); 1557 | if (!okay_spot || 1558 | !figurine_location_checks(figurine,&cc, TRUE)) { 1559 | /* reset the timer to try again later */ 1560 | (void) start_timer((long)rnd(5000), TIMER_OBJECT, 1561 | FIG_TRANSFORM, (genericptr_t)figurine); 1562 | return; 1563 | } 1564 | 1565 | cansee_spot = cansee(cc.x, cc.y); 1566 | mtmp = make_familiar(figurine, cc.x, cc.y, TRUE); 1567 | if (mtmp) { 1568 | Sprintf(monnambuf, "%s",a_monnam(mtmp)); 1569 | switch (figurine->where) { 1570 | case OBJ_INVENT: 1571 | if (Blind) 1572 | You_feel("%s %s from your pack!", something, 1573 | locomotion(mtmp->data,"drop")); 1574 | else 1575 | You("see %s %s out of your pack!", 1576 | monnambuf, 1577 | locomotion(mtmp->data,"drop")); 1578 | break; 1579 | 1580 | case OBJ_FLOOR: 1581 | if (cansee_spot && !silent) { 1582 | You("suddenly see a figurine transform into %s!", 1583 | monnambuf); 1584 | redraw = TRUE; /* update figurine's map location */ 1585 | } 1586 | break; 1587 | 1588 | case OBJ_MINVENT: 1589 | if (cansee_spot && !silent) { 1590 | struct monst *mon; 1591 | mon = figurine->ocarry; 1592 | /* figurine carring monster might be invisible */ 1593 | if (canseemon(figurine->ocarry)) { 1594 | Sprintf(carriedby, "%s pack", 1595 | s_suffix(a_monnam(mon))); 1596 | } 1597 | else if (is_pool(mon->mx, mon->my)) 1598 | Strcpy(carriedby, "empty water"); 1599 | else 1600 | Strcpy(carriedby, "thin air"); 1601 | You("see %s %s out of %s!", monnambuf, 1602 | locomotion(mtmp->data, "drop"), carriedby); 1603 | } 1604 | break; 1605 | #if 0 1606 | case OBJ_MIGRATING: 1607 | break; 1608 | #endif 1609 | 1610 | default: 1611 | impossible("figurine came to life where? (%d)", 1612 | (int)figurine->where); 1613 | break; 1614 | } 1615 | } 1616 | /* free figurine now */ 1617 | obj_extract_self(figurine); 1618 | obfree(figurine, (struct obj *)0); 1619 | if (redraw) newsym(cc.x, cc.y); 1620 | } 1621 | 1622 | STATIC_OVL boolean 1623 | figurine_location_checks(obj, cc, quietly) 1624 | struct obj *obj; 1625 | coord *cc; 1626 | boolean quietly; 1627 | { 1628 | xchar x,y; 1629 | 1630 | x = cc->x; y = cc->y; 1631 | if (!isok(x,y)) { 1632 | if (!quietly) 1633 | You("cannot put the figurine there."); 1634 | return FALSE; 1635 | } 1636 | if (IS_ROCK(levl[x][y].typ) && 1637 | !(passes_walls(&mons[obj->corpsenm]) && may_passwall(x,y))) { 1638 | if (!quietly) 1639 | You("cannot place a figurine in solid rock!"); 1640 | return FALSE; 1641 | } 1642 | if (sobj_at(BOULDER,x,y) && !passes_walls(&mons[obj->corpsenm]) 1643 | && !throws_rocks(&mons[obj->corpsenm])) { 1644 | if (!quietly) 1645 | You("cannot fit the figurine on the boulder."); 1646 | return FALSE; 1647 | } 1648 | return TRUE; 1649 | } 1650 | 1651 | STATIC_OVL void 1652 | use_figurine(obj) 1653 | register struct obj *obj; 1654 | { 1655 | xchar x, y; 1656 | coord cc; 1657 | 1658 | if(!getdir((char *)0)) { 1659 | flags.move = multi = 0; 1660 | return; 1661 | } 1662 | x = u.ux + u.dx; y = u.uy + u.dy; 1663 | cc.x = x; cc.y = y; 1664 | /* Passing FALSE arg here will result in messages displayed */ 1665 | if (!figurine_location_checks(obj, &cc, FALSE)) return; 1666 | You("%s and it transforms.", 1667 | (u.dx||u.dy) ? "set the figurine beside you" : 1668 | (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)) ? 1669 | "release the figurine" : 1670 | (u.dz < 0 ? 1671 | "toss the figurine into the air" : 1672 | "set the figurine on the ground")); 1673 | (void) make_familiar(obj, u.ux+u.dx, u.uy+u.dy, FALSE); 1674 | (void) stop_timer(FIG_TRANSFORM, (genericptr_t)obj); 1675 | useup(obj); 1676 | } 1677 | 1678 | static NEARDATA const char lubricables[] = { ALL_CLASSES, ALLOW_NONE, 0 }; 1679 | static NEARDATA const char need_to_remove_outer_armor[] = 1680 | "need to remove your %s to grease your %s."; 1681 | 1682 | STATIC_OVL void 1683 | use_grease(obj) 1684 | struct obj *obj; 1685 | { 1686 | struct obj *otmp; 1687 | char buf[BUFSZ]; 1688 | 1689 | if (Glib) { 1690 | dropx(obj); 1691 | pline("%s slips from your %s.", The(xname(obj)), 1692 | makeplural(body_part(FINGER))); 1693 | return; 1694 | } 1695 | 1696 | if (obj->spe > 0) { 1697 | if ((obj->cursed || Fumbling) && !rn2(2)) { 1698 | check_unpaid(obj); 1699 | obj->spe--; 1700 | dropx(obj); 1701 | pline("%s slips from your %s.", The(xname(obj)), 1702 | makeplural(body_part(FINGER))); 1703 | return; 1704 | } 1705 | otmp = getobj(lubricables, "grease"); 1706 | if (!otmp) return; 1707 | if ((otmp->owornmask & WORN_ARMOR) && uarmc) { 1708 | Strcpy(buf, xname(uarmc)); 1709 | You(need_to_remove_outer_armor, buf, xname(otmp)); 1710 | return; 1711 | } 1712 | #ifdef TOURIST 1713 | if ((otmp->owornmask & WORN_SHIRT) && (uarmc || uarm)) { 1714 | Strcpy(buf, uarmc ? xname(uarmc) : ""); 1715 | if (uarmc && uarm) Strcat(buf, " and "); 1716 | Strcat(buf, uarm ? xname(uarm) : ""); 1717 | You(need_to_remove_outer_armor, buf, xname(otmp)); 1718 | return; 1719 | } 1720 | #endif 1721 | check_unpaid(obj); 1722 | obj->spe--; 1723 | if (otmp != &zeroobj) { 1724 | You("cover %s with a thick layer of grease.", 1725 | yname(otmp)); 1726 | otmp->greased = 1; 1727 | if (obj->cursed && !nohands(youmonst.data)) { 1728 | incr_itimeout(&Glib, rnd(15)); 1729 | pline("Some of the grease gets all over your %s.", 1730 | makeplural(body_part(HAND))); 1731 | } 1732 | } else { 1733 | Glib += rnd(15); 1734 | You("coat your %s with grease.", 1735 | makeplural(body_part(FINGER))); 1736 | } 1737 | } else { 1738 | pline("%s %s empty.", The(xname(obj)), 1739 | obj->known ? "is" : "seems to be"); 1740 | } 1741 | } 1742 | 1743 | static struct trapinfo { 1744 | struct obj *tobj; 1745 | xchar tx, ty; 1746 | int time_needed; 1747 | } trapinfo; 1748 | 1749 | void 1750 | reset_trapset() 1751 | { 1752 | trapinfo.tobj = 0; 1753 | } 1754 | 1755 | /* Place a landmine/bear trap. Helge Hafting */ 1756 | STATIC_OVL void 1757 | use_trap(otmp) 1758 | struct obj *otmp; 1759 | { 1760 | int ttyp, tmp; 1761 | const char *what = (char *)0; 1762 | char buf[BUFSZ]; 1763 | const char *occutext = "setting the trap"; 1764 | 1765 | if (nohands(youmonst.data)) 1766 | what = "without hands"; 1767 | else if (Stunned) 1768 | what = "while stunned"; 1769 | else if (u.uswallow) 1770 | what = is_animal(u.ustuck->data) ? "while swallowed" : 1771 | "while engulfed"; 1772 | else if (Underwater) 1773 | what = "underwater"; 1774 | else if (Levitation) 1775 | what = "while levitating"; 1776 | else if (is_pool(u.ux, u.uy)) 1777 | what = "in water"; 1778 | else if (is_lava(u.ux, u.uy)) 1779 | what = "in lava"; 1780 | else if (On_stairs(u.ux, u.uy)) 1781 | what = (u.ux == xdnladder || u.ux == xupladder) ? 1782 | "on the ladder" : "on the stairs"; 1783 | else if (IS_FURNITURE(levl[u.ux][u.uy].typ) || 1784 | IS_ROCK(levl[u.ux][u.uy].typ) || 1785 | closed_door(u.ux, u.uy) || t_at(u.ux, u.uy)) 1786 | what = "here"; 1787 | if (what) { 1788 | You_cant("set a trap %s!",what); 1789 | reset_trapset(); 1790 | return; 1791 | } 1792 | ttyp = (otmp->otyp == LAND_MINE) ? LANDMINE : BEAR_TRAP; 1793 | if (otmp == trapinfo.tobj && 1794 | u.ux == trapinfo.tx && u.uy == trapinfo.ty) { 1795 | You("resume setting %s %s.", 1796 | shk_your(buf, otmp), 1797 | defsyms[trap_to_defsym(what_trap(ttyp))].explanation); 1798 | set_occupation(set_trap, occutext, 0); 1799 | return; 1800 | } 1801 | trapinfo.tobj = otmp; 1802 | trapinfo.tx = u.ux, trapinfo.ty = u.uy; 1803 | tmp = ACURR(A_DEX); 1804 | trapinfo.time_needed = (tmp > 17) ? 2 : (tmp > 12) ? 3 : 1805 | (tmp > 7) ? 4 : 5; 1806 | if (Blind) trapinfo.time_needed *= 2; 1807 | tmp = ACURR(A_STR); 1808 | if (ttyp == BEAR_TRAP && tmp < 18) 1809 | trapinfo.time_needed += (tmp > 12) ? 1 : (tmp > 7) ? 2 : 4; 1810 | /*[fumbling and/or confusion and/or cursed object check(s) 1811 | should be incorporated here instead of in set_trap]*/ 1812 | 1813 | You("begin setting %s %s.", 1814 | shk_your(buf, otmp), 1815 | defsyms[trap_to_defsym(what_trap(ttyp))].explanation); 1816 | set_occupation(set_trap, occutext, 0); 1817 | return; 1818 | } 1819 | 1820 | STATIC_PTR 1821 | int 1822 | set_trap() 1823 | { 1824 | struct obj *otmp = trapinfo.tobj; 1825 | struct trap *ttmp; 1826 | int ttyp; 1827 | 1828 | if (!otmp || !carried(otmp) || 1829 | u.ux != trapinfo.tx || u.uy != trapinfo.ty) { 1830 | /* ?? */ 1831 | reset_trapset(); 1832 | return 0; 1833 | } 1834 | 1835 | if (--trapinfo.time_needed > 0) return 1; /* still busy */ 1836 | 1837 | ttyp = (otmp->otyp == LAND_MINE) ? LANDMINE : BEAR_TRAP; 1838 | ttmp = maketrap(u.ux, u.uy, ttyp); 1839 | if (ttmp) { 1840 | ttmp->tseen = 1; 1841 | ttmp->madeby_u = 1; 1842 | newsym(u.ux, u.uy); /* if our hero happens to be invisible */ 1843 | if (*in_rooms(u.ux,u.uy,SHOPBASE)) { 1844 | add_damage(u.ux, u.uy, 0L); /* schedule removal */ 1845 | } 1846 | You("finish arming %s.", 1847 | the(defsyms[trap_to_defsym(what_trap(ttyp))].explanation)); 1848 | if ((otmp->cursed || Fumbling) && (rnl(10) > 5)) dotrap(ttmp); 1849 | } else { 1850 | /* this shouldn't happen */ 1851 | Your("trap setting attempt fails."); 1852 | } 1853 | useup(otmp); 1854 | reset_trapset(); 1855 | return 0; 1856 | } 1857 | 1858 | STATIC_OVL int 1859 | use_whip(obj) 1860 | struct obj *obj; 1861 | { 1862 | char buf[BUFSZ]; 1863 | struct monst *mtmp; 1864 | struct obj *otmp; 1865 | int rx, ry, proficient, res = 0; 1866 | const char *msg_slipsfree = "The bullwhip slips free."; 1867 | const char *msg_snap = "Snap!"; 1868 | 1869 | if (obj != uwep) { 1870 | if (!wield_tool(obj)) return 0; 1871 | else res = 1; 1872 | /* prevent bashing msg */ 1873 | unweapon = FALSE; 1874 | } 1875 | if (!getdir((char *)0)) return res; 1876 | 1877 | if (Stunned || (Confusion && !rn2(5))) confdir(); 1878 | rx = u.ux + u.dx; 1879 | ry = u.uy + u.dy; 1880 | mtmp = m_at(rx, ry); 1881 | 1882 | /* fake some proficiency checks */ 1883 | proficient = 0; 1884 | if (Role_if(PM_ARCHEOLOGIST)) ++proficient; 1885 | if (ACURR(A_DEX) < 6) proficient--; 1886 | else if (ACURR(A_DEX) >= 14) proficient += (ACURR(A_DEX) - 14); 1887 | if (Fumbling) --proficient; 1888 | if (proficient > 3) proficient = 3; 1889 | if (proficient < 0) proficient = 0; 1890 | 1891 | if (u.uswallow && attack(u.ustuck)) { 1892 | There("is not enough room to flick your bullwhip."); 1893 | 1894 | } else if (Underwater) { 1895 | There("is too much resistance to flick your bullwhip."); 1896 | 1897 | } else if (u.dz < 0) { 1898 | You("flick a bug off of the %s.",ceiling(u.ux,u.uy)); 1899 | 1900 | } else if ((!u.dx && !u.dy) || (u.dz > 0)) { 1901 | int dam; 1902 | 1903 | #ifdef STEED 1904 | /* Sometimes you hit your steed by mistake */ 1905 | if (u.usteed && !rn2(proficient + 2)) { 1906 | You("whip %s!", mon_nam(u.usteed)); 1907 | kick_steed(); 1908 | return 1; 1909 | } 1910 | #endif 1911 | if (Levitation 1912 | #ifdef STEED 1913 | || u.usteed 1914 | #endif 1915 | ) { 1916 | /* Have a shot at snaring something on the floor */ 1917 | otmp = level.objects[u.ux][u.uy]; 1918 | if (otmp && otmp->otyp == CORPSE && otmp->corpsenm == PM_HORSE) { 1919 | pline("Why beat a dead horse?"); 1920 | return 1; 1921 | } 1922 | if (otmp && proficient) { 1923 | You("wrap your bullwhip around %s on the %s.", 1924 | an(singular(otmp, xname)), surface(u.ux, u.uy)); 1925 | if (rnl(6) || pickup_object(otmp, 1L, TRUE) < 1) 1926 | pline(msg_slipsfree); 1927 | return 1; 1928 | } 1929 | } 1930 | dam = rnd(2) + dbon() + obj->spe; 1931 | if (dam <= 0) dam = 1; 1932 | You("hit your %s with your bullwhip.", body_part(FOOT)); 1933 | /* self_pronoun() won't work twice in a sentence */ 1934 | Strcpy(buf, self_pronoun("killed %sself with %%s bullwhip", "him")); 1935 | losehp(dam, self_pronoun(buf, "his"), NO_KILLER_PREFIX); 1936 | flags.botl = 1; 1937 | return 1; 1938 | 1939 | } else if ((Fumbling || Glib) && !rn2(5)) { 1940 | pline_The("bullwhip slips out of your %s.", body_part(HAND)); 1941 | dropx(obj); 1942 | setuwep((struct obj *)0); 1943 | 1944 | } else if (u.utrap && u.utraptype == TT_PIT) { 1945 | /* 1946 | * Assumptions: 1947 | * 1948 | * if you're in a pit 1949 | * - you are attempting to get out of the pit 1950 | * - or, if you are applying it towards a small 1951 | * monster then it is assumed that you are 1952 | * trying to hit it. 1953 | * else if the monster is wielding a weapon 1954 | * - you are attempting to disarm a monster 1955 | * else 1956 | * - you are attempting to hit the monster 1957 | * 1958 | * if you're confused (and thus off the mark) 1959 | * - you only end up hitting. 1960 | * 1961 | */ 1962 | const char *wrapped_what = (char *)0; 1963 | 1964 | if (mtmp) { 1965 | if (bigmonst(mtmp->data)) { 1966 | wrapped_what = strcpy(buf, mon_nam(mtmp)); 1967 | } else if (proficient) { 1968 | if (attack(mtmp)) return 1; 1969 | else pline(msg_snap); 1970 | } 1971 | } 1972 | if (!wrapped_what) { 1973 | if (IS_FURNITURE(levl[rx][ry].typ)) 1974 | wrapped_what = something; 1975 | else if (sobj_at(BOULDER, rx, ry)) 1976 | wrapped_what = "a boulder"; 1977 | } 1978 | if (wrapped_what) { 1979 | coord cc; 1980 | 1981 | cc.x = rx; cc.y = ry; 1982 | You("wrap your bullwhip around %s.", wrapped_what); 1983 | if (proficient && rn2(proficient + 2)) { 1984 | if (!mtmp || enexto(&cc, rx, ry, youmonst.data)) { 1985 | You("yank yourself out of the pit!"); 1986 | teleds(cc.x, cc.y); 1987 | u.utrap = 0; 1988 | vision_full_recalc = 1; 1989 | } 1990 | } else { 1991 | pline(msg_slipsfree); 1992 | } 1993 | if (mtmp) wakeup(mtmp); 1994 | } else pline(msg_snap); 1995 | 1996 | } else if (mtmp) { 1997 | if (!canspotmon(mtmp) && 1998 | !glyph_is_invisible(levl[rx][ry].glyph)) { 1999 | pline("A monster is there that you couldn't see."); 2000 | map_invisible(rx, ry); 2001 | } 2002 | otmp = MON_WEP(mtmp); /* can be null */ 2003 | if (otmp) { 2004 | char onambuf[BUFSZ]; 2005 | const char *mon_hand; 2006 | boolean gotit = proficient && (!Fumbling || !rn2(10)); 2007 | 2008 | Strcpy(onambuf, xname(otmp)); 2009 | if (gotit) { 2010 | mon_hand = mbodypart(mtmp, HAND); 2011 | if (bimanual(otmp)) mon_hand = makeplural(mon_hand); 2012 | } else 2013 | mon_hand = 0; /* lint suppression */ 2014 | 2015 | You("wrap your bullwhip around %s %s.", 2016 | s_suffix(mon_nam(mtmp)), onambuf); 2017 | if (gotit && otmp->cursed) { 2018 | pline("%s welded to %s %s%c", 2019 | (otmp->quan == 1L) ? "It is" : "They are", 2020 | his[pronoun_gender(mtmp)], mon_hand, 2021 | !otmp->bknown ? '!' : '.'); 2022 | otmp->bknown = 1; 2023 | gotit = FALSE; /* can't pull it free */ 2024 | } 2025 | if (gotit) { 2026 | obj_extract_self(otmp); 2027 | possibly_unwield(mtmp); 2028 | otmp->owornmask &= ~W_WEP; 2029 | 2030 | switch (rn2(proficient + 1)) { 2031 | case 2: 2032 | /* to floor near you */ 2033 | You("yank %s %s to the %s!", s_suffix(mon_nam(mtmp)), 2034 | onambuf, surface(u.ux, u.uy)); 2035 | if (otmp->otyp == CRYSKNIFE && 2036 | (!otmp->oerodeproof || !rn2(10))) { 2037 | otmp->otyp = WORM_TOOTH; 2038 | otmp->oerodeproof = 0; 2039 | } 2040 | place_object(otmp, u.ux, u.uy); 2041 | stackobj(otmp); 2042 | break; 2043 | case 3: 2044 | /* right to you */ 2045 | #if 0 2046 | if (!rn2(25)) { 2047 | /* proficient with whip, but maybe not 2048 | so proficient at catching weapons */ 2049 | int hitu, hitvalu; 2050 | 2051 | hitvalu = 8 + otmp->spe; 2052 | hitu = thitu(hitvalu, 2053 | dmgval(otmp, &youmonst), 2054 | otmp, (char *)0); 2055 | if (hitu) { 2056 | You("The %s hits you as you try to snatch it!", 2057 | the(onambuf)); 2058 | } 2059 | place_object(otmp, u.ux, u.uy); 2060 | stackobj(otmp); 2061 | break; 2062 | } 2063 | #endif /* 0 */ 2064 | /* right into your inventory */ 2065 | You("snatch %s %s!", s_suffix(mon_nam(mtmp)), onambuf); 2066 | if (otmp->otyp == CORPSE && 2067 | touch_petrifies(&mons[otmp->corpsenm]) && 2068 | !uarmg && !Stone_resistance && 2069 | !(poly_when_stoned(youmonst.data) && 2070 | polymon(PM_STONE_GOLEM))) { 2071 | char kbuf[BUFSZ]; 2072 | 2073 | Sprintf(kbuf, "%s corpse", 2074 | an(mons[otmp->corpsenm].mname)); 2075 | pline("Snatching %s is a fatal mistake.", kbuf); 2076 | instapetrify(kbuf); 2077 | } 2078 | otmp = hold_another_object(otmp, "You drop %s!", 2079 | doname(otmp), (const char *)0); 2080 | break; 2081 | default: 2082 | /* to floor beneath mon */ 2083 | You("yank %s from %s %s!", the(onambuf), 2084 | s_suffix(mon_nam(mtmp)), mon_hand); 2085 | if (otmp->otyp == CRYSKNIFE && 2086 | (!otmp->oerodeproof || !rn2(10))) { 2087 | otmp->otyp = WORM_TOOTH; 2088 | otmp->oerodeproof = 0; 2089 | } 2090 | place_object(otmp, mtmp->mx, mtmp->my); 2091 | stackobj(otmp); 2092 | break; 2093 | } 2094 | } else { 2095 | pline(msg_slipsfree); 2096 | } 2097 | wakeup(mtmp); 2098 | } else { 2099 | You("flick your bullwhip towards %s.", mon_nam(mtmp)); 2100 | if (proficient) { 2101 | if (attack(mtmp)) return 1; 2102 | else pline(msg_snap); 2103 | } 2104 | } 2105 | 2106 | } else if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)) { 2107 | /* it must be air -- water checked above */ 2108 | You("snap your whip through thin air."); 2109 | 2110 | } else { 2111 | pline(msg_snap); 2112 | 2113 | } 2114 | return 1; 2115 | } 2116 | 2117 | 2118 | static const char 2119 | *not_enough_room = "There's not enough room here to use that.", 2120 | *where_to_hit = "Where do you want to hit?", 2121 | *cant_see_spot = "won't hit anything if you can't see that spot."; 2122 | 2123 | /* Distance attacks by pole-weapons */ 2124 | STATIC_OVL int 2125 | use_pole (obj) 2126 | struct obj *obj; 2127 | { 2128 | int res = 0, typ, max_range = 4, min_range = 4; 2129 | coord cc; 2130 | struct monst *mtmp; 2131 | 2132 | 2133 | /* Are you allowed to use the pole? */ 2134 | if (u.uswallow) { 2135 | pline(not_enough_room); 2136 | return (0); 2137 | } 2138 | if (obj != uwep) { 2139 | if (!wield_tool(obj)) return(0); 2140 | else res = 1; 2141 | } 2142 | /* assert(obj == uwep); */ 2143 | 2144 | /* Prompt for a location */ 2145 | pline(where_to_hit); 2146 | cc.x = u.ux; 2147 | cc.y = u.uy; 2148 | if (getpos(&cc, TRUE, "the spot to hit") < 0) 2149 | return 0; /* user pressed ESC */ 2150 | 2151 | /* Calculate range */ 2152 | typ = uwep_skill_type(); 2153 | if (typ == P_NONE || P_SKILL(typ) <= P_BASIC) max_range = 4; 2154 | else if (P_SKILL(typ) == P_SKILLED) max_range = 5; 2155 | else max_range = 8; 2156 | if (distu(cc.x, cc.y) > max_range) { 2157 | pline("Too far!"); 2158 | return (res); 2159 | } else if (distu(cc.x, cc.y) < min_range) { 2160 | pline("Too close!"); 2161 | return (res); 2162 | } else if (!cansee(cc.x, cc.y)) { 2163 | You(cant_see_spot); 2164 | return (res); 2165 | } 2166 | 2167 | /* Attack the monster there */ 2168 | if ((mtmp = m_at(cc.x, cc.y)) != (struct monst *)0) 2169 | (void) thitmonst(mtmp, uwep); 2170 | else 2171 | /* Now you know that nothing is there... */ 2172 | pline(nothing_happens); 2173 | return (1); 2174 | } 2175 | 2176 | 2177 | STATIC_OVL int 2178 | use_grapple (obj) 2179 | struct obj *obj; 2180 | { 2181 | int res = 0, typ, max_range = 4; 2182 | coord cc; 2183 | struct monst *mtmp; 2184 | struct obj *otmp; 2185 | 2186 | /* Are you allowed to use the hook? */ 2187 | if (u.uswallow) { 2188 | pline(not_enough_room); 2189 | return (0); 2190 | } 2191 | if (obj != uwep) { 2192 | if (!wield_tool(obj)) return(0); 2193 | else res = 1; 2194 | } 2195 | /* assert(obj == uwep); */ 2196 | 2197 | /* Prompt for a location */ 2198 | pline(where_to_hit); 2199 | cc.x = u.ux; 2200 | cc.y = u.uy; 2201 | if (getpos(&cc, TRUE, "the spot to hit") < 0) 2202 | return 0; /* user pressed ESC */ 2203 | 2204 | /* Calculate range */ 2205 | typ = uwep_skill_type(); 2206 | if (typ == P_NONE || P_SKILL(typ) <= P_BASIC) max_range = 4; 2207 | else if (P_SKILL(typ) == P_SKILLED) max_range = 5; 2208 | else max_range = 8; 2209 | if (distu(cc.x, cc.y) > max_range) { 2210 | pline("Too far!"); 2211 | return (res); 2212 | } else if (!cansee(cc.x, cc.y)) { 2213 | You(cant_see_spot); 2214 | return (res); 2215 | } 2216 | 2217 | /* What did you hit? */ 2218 | switch (rn2(5)) 2219 | { 2220 | case 0: /* Trap */ 2221 | /* FIXME -- untrap needs to deal with non-adjacent traps */ 2222 | break; 2223 | case 1: /* Object */ 2224 | if ((otmp = level.objects[cc.x][cc.y]) != 0) { 2225 | You("snag an object from the %s!", surface(cc.x, cc.y)); 2226 | (void) pickup_object(otmp, 1L, FALSE); 2227 | /* If pickup fails, leave it alone */ 2228 | newsym(cc.x, cc.y); 2229 | return (1); 2230 | } 2231 | break; 2232 | case 2: /* Monster */ 2233 | if ((mtmp = m_at(cc.x, cc.y)) == (struct monst *)0) break; 2234 | if (verysmall(mtmp->data) && !rn2(4) && 2235 | enexto(&cc, u.ux, u.uy, (struct permonst *)0)) { 2236 | You("pull in %s!", mon_nam(mtmp)); 2237 | mtmp->mundetected = 0; 2238 | rloc_to(mtmp, cc.x, cc.y); 2239 | return (1); 2240 | } else if ((!bigmonst(mtmp->data) && !strongmonst(mtmp->data)) || 2241 | rn2(4)) { 2242 | (void) thitmonst(mtmp, uwep); 2243 | return (1); 2244 | } 2245 | /* FALL THROUGH */ 2246 | case 3: /* Surface */ 2247 | You("are yanked toward the %s!", 2248 | surface(cc.x, cc.y)); 2249 | hurtle(sgn(cc.x-u.ux), sgn(cc.y-u.uy), 1, FALSE); 2250 | return (1); 2251 | default: /* Yourself (oops!) */ 2252 | if (P_SKILL(typ) <= P_BASIC) { 2253 | You("hook yourself!"); 2254 | losehp(rn1(10,10), "a grappling hook", KILLED_BY); 2255 | return (1); 2256 | } 2257 | break; 2258 | } 2259 | pline(nothing_happens); 2260 | return (1); 2261 | } 2262 | 2263 | 2264 | #define BY_OBJECT ((struct monst *)0) 2265 | 2266 | /* return 1 if the wand is broken, hence some time elapsed */ 2267 | STATIC_OVL int 2268 | do_break_wand(obj) 2269 | struct obj *obj; 2270 | { 2271 | static const char nothing_else_happens[] = "But nothing else happens..."; 2272 | register int i, x, y; 2273 | register struct monst *mon; 2274 | int dmg, damage; 2275 | boolean affects_objects; 2276 | char confirm[QBUFSZ], the_wand[BUFSZ]; 2277 | 2278 | Strcpy(the_wand, yname(obj)); 2279 | Sprintf(confirm, "Are you really sure you want to break %s?", the_wand); 2280 | if (yn(confirm) == 'n' ) return 0; 2281 | 2282 | if (nohands(youmonst.data)) { 2283 | You_cant("break %s without hands!", the_wand); 2284 | return 0; 2285 | } else if (ACURR(A_STR) < 10) { 2286 | You("don't have the strength to break %s!", the_wand); 2287 | return 0; 2288 | } 2289 | pline("Raising %s high above your %s, you break it in two!", 2290 | the_wand, body_part(HEAD)); 2291 | 2292 | current_wand = obj; /* destroy_item might reset this */ 2293 | freeinv(obj); /* hide it from destroy_item instead... */ 2294 | setnotworn(obj); /* so we need to do this ourselves */ 2295 | 2296 | if (obj->spe <= 0) { 2297 | pline(nothing_else_happens); 2298 | goto discard_broken_wand; 2299 | } 2300 | obj->ox = u.ux; 2301 | obj->oy = u.uy; 2302 | dmg = obj->spe * 4; 2303 | affects_objects = FALSE; 2304 | 2305 | switch (obj->otyp) { 2306 | case WAN_WISHING: 2307 | case WAN_NOTHING: 2308 | case WAN_LOCKING: 2309 | case WAN_PROBING: 2310 | case WAN_ENLIGHTENMENT: 2311 | case WAN_OPENING: 2312 | case WAN_SECRET_DOOR_DETECTION: 2313 | pline(nothing_else_happens); 2314 | goto discard_broken_wand; 2315 | case WAN_DEATH: 2316 | case WAN_LIGHTNING: 2317 | dmg *= 2; 2318 | case WAN_FIRE: 2319 | case WAN_COLD: 2320 | dmg *= 2; 2321 | case WAN_MAGIC_MISSILE: 2322 | explode(u.ux, u.uy, (obj->otyp - WAN_MAGIC_MISSILE), dmg, WAND_CLASS); 2323 | makeknown(obj->otyp); /* explode described the effect */ 2324 | goto discard_broken_wand; 2325 | case WAN_STRIKING: 2326 | /* we want this before the explosion instead of at the very end */ 2327 | pline("A wall of force smashes down around you!"); 2328 | dmg = d(1 + obj->spe,6); /* normally 2d12 */ 2329 | case WAN_CANCELLATION: 2330 | case WAN_POLYMORPH: 2331 | case WAN_TELEPORTATION: 2332 | case WAN_UNDEAD_TURNING: 2333 | affects_objects = TRUE; 2334 | break; 2335 | default: 2336 | break; 2337 | } 2338 | 2339 | /* magical explosion and its visual effect occur before specific effects */ 2340 | explode(obj->ox, obj->oy, 0, rnd(dmg), WAND_CLASS); 2341 | 2342 | /* this makes it hit us last, so that we can see the action first */ 2343 | for (i = 0; i <= 8; i++) { 2344 | bhitpos.x = x = obj->ox + xdir[i]; 2345 | bhitpos.y = y = obj->oy + ydir[i]; 2346 | if (!isok(x,y)) continue; 2347 | 2348 | if (obj->otyp == WAN_DIGGING) { 2349 | if(dig_check(BY_OBJECT, FALSE, x, y)) 2350 | digactualhole(x, y, BY_OBJECT, 2351 | (rn2(obj->spe) < 3 || !Can_dig_down(&u.uz)) ? 2352 | PIT : HOLE); 2353 | continue; 2354 | } else if(obj->otyp == WAN_CREATE_MONSTER) { 2355 | /* u.ux,u.uy creates it near you--x,y might create it in rock */ 2356 | (void) makemon((struct permonst *)0, u.ux, u.uy, NO_MM_FLAGS); 2357 | continue; 2358 | } else { 2359 | if (x == u.ux && y == u.uy) { 2360 | /* teleport objects first to avoid race with tele control and 2361 | autopickup. Other wand/object effects handled after 2362 | possible wand damage is assessed */ 2363 | if (obj->otyp == WAN_TELEPORTATION && 2364 | affects_objects && level.objects[x][y]) { 2365 | (void) bhitpile(obj, bhito, x, y); 2366 | if (flags.botl) bot(); /* potion effects */ 2367 | } 2368 | damage = zapyourself(obj, FALSE); 2369 | if (damage) 2370 | losehp(damage, 2371 | self_pronoun("killed %sself by breaking a wand", 2372 | "him"), 2373 | NO_KILLER_PREFIX); 2374 | if (flags.botl) bot(); /* blindness */ 2375 | } else if ((mon = m_at(x, y)) != 0) { 2376 | (void) bhitm(mon, obj); 2377 | /* if (flags.botl) bot(); */ 2378 | } 2379 | if (affects_objects && level.objects[x][y]) { 2380 | (void) bhitpile(obj, bhito, x, y); 2381 | if (flags.botl) bot(); /* potion effects */ 2382 | } 2383 | } 2384 | } 2385 | 2386 | if (obj->otyp == WAN_LIGHT) 2387 | litroom(TRUE, obj); /* only needs to be done once */ 2388 | 2389 | discard_broken_wand: 2390 | obj = current_wand; /* [see dozap() and destroy_item()] */ 2391 | current_wand = 0; 2392 | if (obj) { 2393 | /* extra charge for _use_ prior to destruction */ 2394 | check_unpaid(obj); 2395 | delobj(obj); 2396 | } 2397 | nomul(0); 2398 | return 1; 2399 | } 2400 | 2401 | int 2402 | doapply() 2403 | { 2404 | register struct obj *obj; 2405 | register int res = 1; 2406 | 2407 | if(check_capacity((char *)0)) return (0); 2408 | obj = getobj(carrying(POT_OIL) ? tools_too : tools, "use or apply"); 2409 | if(!obj) return 0; 2410 | 2411 | if (obj->oclass == WAND_CLASS) 2412 | return do_break_wand(obj); 2413 | 2414 | switch(obj->otyp){ 2415 | case BLINDFOLD: 2416 | case LENSES: 2417 | if (obj == ublindf) { 2418 | if (!cursed(obj)) Blindf_off(obj); 2419 | } else if (!ublindf) 2420 | Blindf_on(obj); 2421 | else You("are already %s.", 2422 | ublindf->otyp == TOWEL ? "covered by a towel" : 2423 | ublindf->otyp == BLINDFOLD ? "wearing a blindfold" : 2424 | "wearing lenses"); 2425 | break; 2426 | case BULLWHIP: 2427 | res = use_whip(obj); 2428 | break; 2429 | case GRAPPLING_HOOK: 2430 | res = use_grapple(obj); 2431 | break; 2432 | case LARGE_BOX: 2433 | case CHEST: 2434 | case ICE_BOX: 2435 | case SACK: 2436 | case BAG_OF_HOLDING: 2437 | case OILSKIN_SACK: 2438 | res = use_container(obj, 1); 2439 | break; 2440 | case BAG_OF_TRICKS: 2441 | if(obj->spe > 0) { 2442 | register int cnt = 1; 2443 | 2444 | check_unpaid(obj); 2445 | obj->spe--; 2446 | if(!rn2(23)) cnt += rn2(7) + 1; 2447 | while(cnt--) 2448 | (void) makemon((struct permonst *) 0, 2449 | u.ux, u.uy, NO_MM_FLAGS); 2450 | makeknown(BAG_OF_TRICKS); 2451 | } else 2452 | pline(nothing_happens); 2453 | break; 2454 | case CAN_OF_GREASE: 2455 | use_grease(obj); 2456 | break; 2457 | case LOCK_PICK: 2458 | #ifdef TOURIST 2459 | case CREDIT_CARD: 2460 | #endif 2461 | case SKELETON_KEY: 2462 | (void) pick_lock(obj); 2463 | break; 2464 | case PICK_AXE: 2465 | case DWARVISH_MATTOCK: 2466 | res = use_pick_axe(obj); 2467 | break; 2468 | case TINNING_KIT: 2469 | use_tinning_kit(obj); 2470 | break; 2471 | case LEASH: 2472 | use_leash(obj); 2473 | break; 2474 | #ifdef STEED 2475 | case SADDLE: 2476 | res = use_saddle(obj); 2477 | break; 2478 | #endif 2479 | case MAGIC_WHISTLE: 2480 | use_magic_whistle(obj); 2481 | break; 2482 | case TIN_WHISTLE: 2483 | use_whistle(obj); 2484 | break; 2485 | case STETHOSCOPE: 2486 | res = use_stethoscope(obj); 2487 | break; 2488 | case MIRROR: 2489 | res = use_mirror(obj); 2490 | break; 2491 | case BELL: 2492 | case BELL_OF_OPENING: 2493 | use_bell(obj); 2494 | break; 2495 | case CANDELABRUM_OF_INVOCATION: 2496 | use_candelabrum(obj); 2497 | break; 2498 | case WAX_CANDLE: 2499 | case TALLOW_CANDLE: 2500 | use_candle(obj); 2501 | break; 2502 | case OIL_LAMP: 2503 | case MAGIC_LAMP: 2504 | case BRASS_LANTERN: 2505 | use_lamp(obj); 2506 | break; 2507 | case POT_OIL: 2508 | light_cocktail(obj); 2509 | break; 2510 | #ifdef TOURIST 2511 | case EXPENSIVE_CAMERA: 2512 | res = use_camera(obj); 2513 | break; 2514 | #endif 2515 | case TOWEL: 2516 | res = use_towel(obj); 2517 | break; 2518 | case CRYSTAL_BALL: 2519 | use_crystal_ball(obj); 2520 | break; 2521 | case MAGIC_MARKER: 2522 | res = dowrite(obj); 2523 | break; 2524 | case TIN_OPENER: 2525 | if(!carrying(TIN)) { 2526 | You("have no tin to open."); 2527 | goto xit; 2528 | } 2529 | You("cannot open a tin without eating or discarding its contents."); 2530 | if(flags.verbose) 2531 | pline("In order to eat, use the 'e' command."); 2532 | if(obj != uwep) 2533 | pline("Opening the tin will be much easier if you wield the tin opener."); 2534 | goto xit; 2535 | 2536 | case FIGURINE: 2537 | use_figurine(obj); 2538 | break; 2539 | case UNICORN_HORN: 2540 | use_unicorn_horn(obj); 2541 | break; 2542 | case WOODEN_FLUTE: 2543 | case MAGIC_FLUTE: 2544 | case TOOLED_HORN: 2545 | case FROST_HORN: 2546 | case FIRE_HORN: 2547 | case WOODEN_HARP: 2548 | case MAGIC_HARP: 2549 | case BUGLE: 2550 | case LEATHER_DRUM: 2551 | case DRUM_OF_EARTHQUAKE: 2552 | res = do_play_instrument(obj); 2553 | break; 2554 | case HORN_OF_PLENTY: /* not a musical instrument */ 2555 | if (obj->spe > 0) { 2556 | struct obj *otmp; 2557 | const char *what; 2558 | 2559 | check_unpaid(obj); 2560 | obj->spe--; 2561 | if (!rn2(13)) { 2562 | otmp = mkobj(POTION_CLASS, FALSE); 2563 | if (objects[otmp->otyp].oc_magic) do { 2564 | otmp->otyp = rnd_class(POT_BOOZE, POT_WATER); 2565 | } while (otmp->otyp == POT_SICKNESS); 2566 | what = "A potion"; 2567 | } else { 2568 | otmp = mkobj(FOOD_CLASS, FALSE); 2569 | if (otmp->otyp == FOOD_RATION && !rn2(7)) 2570 | otmp->otyp = LUMP_OF_ROYAL_JELLY; 2571 | what = "Some food"; 2572 | } 2573 | pline("%s spills out.", what); 2574 | otmp->blessed = obj->blessed; 2575 | otmp->cursed = obj->cursed; 2576 | otmp->owt = weight(otmp); 2577 | otmp = hold_another_object(otmp, 2578 | (u.uswallow || Is_airlevel(&u.uz) || 2579 | u.uinwater || Is_waterlevel(&u.uz)) ? 2580 | "Oops! %s away from you!" : 2581 | "Oops! %s to the floor!", 2582 | The(aobjnam(otmp, "slip")), 2583 | (const char *)0); 2584 | makeknown(HORN_OF_PLENTY); 2585 | } else 2586 | pline(nothing_happens); 2587 | break; 2588 | case LAND_MINE: 2589 | case BEARTRAP: 2590 | use_trap(obj); 2591 | break; 2592 | default: 2593 | /* Pole-weapons can strike at a distance */ 2594 | if (is_pole(obj)) { 2595 | res = use_pole(obj); 2596 | break; 2597 | } else if (is_pick(obj) /* || is_axe(obj) */) { 2598 | res = use_pick_axe(obj); 2599 | break; 2600 | } 2601 | pline("Sorry, I don't know how to use that."); 2602 | xit: 2603 | nomul(0); 2604 | return 0; 2605 | } 2606 | if (res && obj->oartifact) arti_speak(obj); 2607 | nomul(0); 2608 | return res; 2609 | } 2610 | 2611 | #endif /* OVLB */ 2612 | 2613 | /*apply.c*/