1 /* SCCS Id: @(#)apply.c 3.4 2003/11/18 */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
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, GEM_CLASS, 0 };
15 STATIC_DCL int FDECL(use_camera, (struct obj *));
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_DCL void FDECL(use_stone, (struct obj *));
34 STATIC_PTR int NDECL(set_trap); /* occupation callback */
35 STATIC_DCL int FDECL(use_whip, (struct obj *));
36 STATIC_DCL int FDECL(use_pole, (struct obj *));
37 STATIC_DCL int FDECL(use_cream_pie, (struct obj *));
38 STATIC_DCL int FDECL(use_grapple, (struct obj *));
39 STATIC_DCL int FDECL(do_break_wand, (struct obj *));
40 STATIC_DCL boolean FDECL(figurine_location_checks,
41 (struct obj *, coord *, BOOLEAN_P));
42 STATIC_DCL boolean NDECL(uhave_graystone);
43 STATIC_DCL void FDECL(add_class, (char *, CHAR_P));
46 void FDECL( amii_speaker, ( struct obj *, char *, int ) );
49 static const char no_elbow_room[] = "don't have enough elbow-room to maneuver.";
56 register struct monst *mtmp;
59 pline("Using your camera underwater would void the warranty.");
62 if(!getdir((char *)0)) return(0);
65 pline(nothing_happens);
68 consume_obj_charge(obj, TRUE);
70 if (obj->cursed && !rn2(2)) {
71 (void) zapyourself(obj, TRUE);
72 } else if (u.uswallow) {
73 You("take a picture of %s %s.", s_suffix(mon_nam(u.ustuck)),
74 mbodypart(u.ustuck, STOMACH));
76 You("take a picture of the %s.",
77 (u.dz > 0) ? surface(u.ux,u.uy) : ceiling(u.ux,u.uy));
78 } else if (!u.dx && !u.dy) {
79 (void) zapyourself(obj, TRUE);
80 } else if ((mtmp = bhit(u.dx, u.dy, COLNO, FLASHED_LIGHT,
81 (int FDECL((*),(MONST_P,OBJ_P)))0,
82 (int FDECL((*),(OBJ_P,OBJ_P)))0,
84 obj->ox = u.ux, obj->oy = u.uy;
85 (void) flash_hits_mon(mtmp, obj);
96 You("have no free %s!", body_part(HAND));
98 } else if (obj->owornmask) {
99 You("cannot use it while you're wearing it!");
101 } else if (obj->cursed) {
107 Your("%s %s!", makeplural(body_part(HAND)),
108 (old ? "are filthier than ever" : "get slimy"));
113 u.ucreamed += rn1(10, 3);
114 pline("Yecch! Your %s %s gunk on it!", body_part(FACE),
115 (old ? "has more" : "now has"));
116 make_blinded(Blinded + (long)u.ucreamed - old, TRUE);
118 const char *what = (ublindf->otyp == LENSES) ?
119 "lenses" : "blindfold";
120 if (ublindf->cursed) {
121 You("push your %s %s.", what,
122 rn2(2) ? "cock-eyed" : "crooked");
124 struct obj *saved_ublindf = ublindf;
125 You("push your %s off.", what);
127 dropx(saved_ublindf);
138 You("wipe off your %s.", makeplural(body_part(HAND)));
140 } else if(u.ucreamed) {
141 Blinded -= u.ucreamed;
145 pline("You've got the glop off.");
147 make_blinded(0L,TRUE);
149 Your("%s feels clean now.", body_part(FACE));
154 Your("%s and %s are already clean.",
155 body_part(FACE), makeplural(body_part(HAND)));
160 /* maybe give a stethoscope message based on floor objects */
162 its_dead(rx, ry, resp)
168 if (!can_reach_floor()) return FALSE;
170 /* additional stethoscope messages from jyoung@apanix.apana.org.au */
171 if (Hallucination && sobj_at(CORPSE, rx, ry)) {
172 /* (a corpse doesn't retain the monster's sex,
173 so we're forced to use generic pronoun here) */
174 You_hear("a voice say, \"It's dead, Jim.\"");
177 } else if (Role_if(PM_HEALER) && ((otmp = sobj_at(CORPSE, rx, ry)) != 0 ||
178 (otmp = sobj_at(STATUE, rx, ry)) != 0)) {
179 /* possibly should check uppermost {corpse,statue} in the pile
180 if both types are present, but it's not worth the effort */
181 if (vobj_at(rx, ry)->otyp == STATUE) otmp = vobj_at(rx, ry);
182 if (otmp->otyp == CORPSE) {
183 You("determine that %s unfortunate being is dead.",
184 (rx == u.ux && ry == u.uy) ? "this" : "that");
187 pline("%s appears to be in %s health for a statue.",
188 The(mons[otmp->corpsenm].mname),
189 (ttmp && ttmp->ttyp == STATUE_TRAP) ?
190 "extraordinary" : "excellent");
197 static const char hollow_str[] = "a hollow sound. This must be a secret %s!";
199 /* Strictly speaking it makes no sense for usage of a stethoscope to
200 not take any time; however, unless it did, the stethoscope would be
201 almost useless. As a compromise, one use per turn is free, another
202 uses up the turn; this makes curse status have a tangible effect. */
205 register struct obj *obj;
207 static long last_used_move = -1;
208 static short last_used_movement = 0;
212 boolean interference = (u.uswallow && is_whirly(u.ustuck->data) &&
213 !rn2(Role_if(PM_HEALER) ? 10 : 3));
215 if (nohands(youmonst.data)) { /* should also check for no ears and/or deaf */
216 You("have no hands!"); /* not `body_part(HAND)' */
218 } else if (!freehand()) {
219 You("have no free %s.", body_part(HAND));
222 if (!getdir((char *)0)) return 0;
224 res = (moves == last_used_move) &&
225 (youmonst.movement == last_used_movement);
226 last_used_move = moves;
227 last_used_movement = youmonst.movement;
230 if (u.usteed && u.dz > 0) {
232 pline("%s interferes.", Monnam(u.ustuck));
233 mstatusline(u.ustuck);
235 mstatusline(u.usteed);
239 if (u.uswallow && (u.dx || u.dy || u.dz)) {
240 mstatusline(u.ustuck);
242 } else if (u.uswallow && interference) {
243 pline("%s interferes.", Monnam(u.ustuck));
244 mstatusline(u.ustuck);
248 You_hear("faint splashing.");
249 else if (u.dz < 0 || !can_reach_floor())
250 You_cant("reach the %s.",
251 (u.dz > 0) ? surface(u.ux,u.uy) : ceiling(u.ux,u.uy));
252 else if (its_dead(u.ux, u.uy, &res))
253 ; /* message already given */
254 else if (Is_stronghold(&u.uz))
255 You_hear("the crackling of hellfire.");
257 pline_The("%s seems healthy enough.", surface(u.ux,u.uy));
259 } else if (obj->cursed && !rn2(2)) {
260 You_hear("your heart beat.");
263 if (Stunned || (Confusion && !rn2(5))) confdir();
264 if (!u.dx && !u.dy) {
268 rx = u.ux + u.dx; ry = u.uy + u.dy;
270 You_hear("a faint typing noise.");
273 if ((mtmp = m_at(rx,ry)) != 0) {
275 if (mtmp->mundetected) {
276 mtmp->mundetected = 0;
277 if (cansee(rx,ry)) newsym(mtmp->mx,mtmp->my);
279 if (!canspotmon(mtmp))
280 map_invisible(rx,ry);
283 if (glyph_is_invisible(levl[rx][ry].glyph)) {
284 unmap_object(rx, ry);
286 pline_The("invisible monster must have moved.");
291 You_hear(hollow_str, "door");
292 cvt_sdoor_to_door(lev); /* ->typ = DOOR */
293 if (Blind) feel_location(rx,ry);
297 You_hear(hollow_str, "passage");
299 unblock_point(rx,ry);
300 if (Blind) feel_location(rx,ry);
305 if (!its_dead(rx, ry, &res))
306 You("hear nothing special."); /* not You_hear() */
310 static const char whistle_str[] = "produce a %s whistling sound.";
316 You(whistle_str, obj->cursed ? "shrill" : "high");
321 use_magic_whistle(obj)
324 register struct monst *mtmp, *nextmon;
326 if(obj->cursed && !rn2(2)) {
327 You("produce a high-pitched humming noise.");
331 You(whistle_str, Hallucination ? "normal" : "strange");
332 for(mtmp = fmon; mtmp; mtmp = nextmon) {
333 nextmon = mtmp->nmon; /* trap might kill mon */
334 if (DEADMONSTER(mtmp)) continue;
336 if (mtmp->mtrapped) {
337 /* no longer in previous trap (affects mintrap) */
339 fill_pit(mtmp->mx, mtmp->my);
342 if (canspotmon(mtmp)) ++pet_cnt;
343 if (mintrap(mtmp) == 2) change_luck(-1);
346 if (pet_cnt > 0) makeknown(obj->otyp);
352 register xchar x, y, n;
354 return((boolean)(abs(u.ux - x) > n || abs(u.uy - y) > n));
361 register struct obj *obj;
363 for(obj = invent; obj; obj = obj->nobj)
364 if(obj->otyp == LEASH && obj->leashmon != 0) i++;
369 o_unleash(otmp) /* otmp is about to be destroyed or stolen */
370 register struct obj *otmp;
372 register struct monst *mtmp;
374 for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
375 if(mtmp->m_id == (unsigned)otmp->leashmon)
381 m_unleash(mtmp, feedback) /* mtmp is about to die, or become untame */
382 register struct monst *mtmp;
385 register struct obj *otmp;
389 pline("%s pulls free of %s leash!", Monnam(mtmp), mhis(mtmp));
391 Your("leash falls slack.");
393 for(otmp = invent; otmp; otmp = otmp->nobj)
394 if(otmp->otyp == LEASH &&
395 otmp->leashmon == (int)mtmp->m_id)
401 unleash_all() /* player is about to die (for bones) */
403 register struct obj *otmp;
404 register struct monst *mtmp;
406 for(otmp = invent; otmp; otmp = otmp->nobj)
407 if(otmp->otyp == LEASH) otmp->leashmon = 0;
408 for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
420 register struct monst *mtmp;
423 if(!obj->leashmon && number_leashed() >= MAXLEASHED) {
424 You("cannot leash any more pets.");
428 if(!get_adjacent_loc((char *)0, (char *)0, u.ux, u.uy, &cc)) return;
430 if((cc.x == u.ux) && (cc.y == u.uy)) {
432 if (u.usteed && u.dz > 0) {
438 pline("Leash yourself? Very funny...");
442 if(!(mtmp = m_at(cc.x, cc.y))) {
443 There("is no creature there.");
447 spotmon = canspotmon(mtmp);
454 There("is no creature there.");
456 pline("%s %s leashed!", Monnam(mtmp), (!obj->leashmon) ?
457 "cannot be" : "is not");
462 pline("This %s is already leashed.",
463 spotmon ? l_monnam(mtmp) : "monster");
466 You("slip the leash around %s%s.",
467 spotmon ? "your " : "", l_monnam(mtmp));
469 obj->leashmon = (int)mtmp->m_id;
473 if(obj->leashmon != (int)mtmp->m_id) {
474 pline("This leash is not attached to that creature.");
478 pline_The("leash would not come off!");
484 You("remove the leash from %s%s.",
485 spotmon ? "your " : "", l_monnam(mtmp));
491 get_mleash(mtmp) /* assuming mtmp->mleashed has been checked */
492 register struct monst *mtmp;
494 register struct obj *otmp;
498 if(otmp->otyp == LEASH && otmp->leashmon == (int)mtmp->m_id)
502 return((struct obj *)0);
511 register struct monst *mtmp;
512 register struct obj *otmp;
514 for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
515 if (DEADMONSTER(mtmp)) continue;
517 if (distu(mtmp->mx,mtmp->my) > 2) mnexto(mtmp);
518 if (distu(mtmp->mx,mtmp->my) > 2) {
519 for(otmp = invent; otmp; otmp = otmp->nobj)
520 if(otmp->otyp == LEASH &&
521 otmp->leashmon == (int)mtmp->m_id) {
522 if(otmp->cursed) return(FALSE);
523 You_feel("%s leash go slack.",
524 (number_leashed() > 1) ? "a" : "the");
532 /* no pack mules for the Amulet */
533 if (u.usteed && mon_has_amulet(u.usteed)) return FALSE;
545 register struct obj *otmp;
546 register struct monst *mtmp;
548 for (otmp = invent; otmp; otmp = otmp->nobj) {
549 if (otmp->otyp != LEASH || otmp->leashmon == 0) continue;
550 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
551 if (DEADMONSTER(mtmp)) continue;
552 if ((int)mtmp->m_id == otmp->leashmon) break;
555 impossible("leash in use isn't attached to anything?");
559 if (dist2(u.ux,u.uy,mtmp->mx,mtmp->my) >
560 dist2(x,y,mtmp->mx,mtmp->my)) {
561 if (!um_dist(mtmp->mx, mtmp->my, 3)) {
562 ; /* still close enough */
563 } else if (otmp->cursed && !breathless(mtmp->data)) {
564 if (um_dist(mtmp->mx, mtmp->my, 5) ||
565 (mtmp->mhp -= rnd(2)) <= 0) {
566 long save_pacifism = u.uconduct.killer;
568 Your("leash chokes %s to death!", mon_nam(mtmp));
569 /* hero might not have intended to kill pet, but
570 that's the result of his actions; gain experience,
571 lose pacifism, take alignment and luck hit, make
572 corpse less likely to remain tame after revival */
573 xkilled(mtmp, 0); /* no "you kill it" message */
574 /* life-saving doesn't ordinarily reset this */
575 if (mtmp->mhp > 0) u.uconduct.killer = save_pacifism;
577 pline("%s chokes on the leash!", Monnam(mtmp));
578 /* tameness eventually drops to 1 here (never 0) */
579 if (mtmp->mtame && rn2(mtmp->mtame)) mtmp->mtame--;
582 if (um_dist(mtmp->mx, mtmp->my, 5)) {
583 pline("%s leash snaps loose!", s_suffix(Monnam(mtmp)));
584 m_unleash(mtmp, FALSE);
586 You("pull on the leash.");
587 if (mtmp->data->msound != MS_SILENT)
589 case 0: growl(mtmp); break;
590 case 1: yelp(mtmp); break;
591 default: whimper(mtmp); break;
602 #define WEAK 3 /* from eat.c */
604 static const char look_str[] = "look %s.";
610 register struct monst *mtmp;
614 if(!getdir((char *)0)) return 0;
615 if(obj->cursed && !rn2(2)) {
617 pline_The("mirror fogs up and doesn't reflect!");
620 if(!u.dx && !u.dy && !u.dz) {
621 if(!Blind && !Invisible) {
622 if (u.umonnum == PM_FLOATING_EYE) {
624 pline(Hallucination ?
625 "Yow! The mirror stares back!" :
626 "Yikes! You've frozen yourself!");
627 nomul(-rnd((MAXULEV+6) - u.ulevel));
628 } else You("stiffen momentarily under your gaze.");
629 } else if (youmonst.data->mlet == S_VAMPIRE)
630 You("don't have a reflection.");
631 else if (u.umonnum == PM_UMBER_HULK) {
632 pline("Huh? That doesn't look like you!");
633 make_confused(HConfusion + d(3,4),FALSE);
634 } else if (Hallucination)
635 You(look_str, hcolor((char *)0));
637 You(look_str, "peaked");
638 else if (u.uhs >= WEAK)
639 You(look_str, "undernourished");
640 else You("look as %s as ever.",
642 (poly_gender()==1 ? "beautiful" : "handsome") :
645 You_cant("see your %s %s.",
647 (poly_gender()==1 ? "beautiful" : "handsome") :
654 if (!Blind) You("reflect %s %s.", s_suffix(mon_nam(u.ustuck)),
655 mbodypart(u.ustuck, STOMACH));
660 "give the fish a chance to fix their makeup." :
661 "reflect the murky water.");
666 You("reflect the %s.",
667 (u.dz > 0) ? surface(u.ux,u.uy) : ceiling(u.ux,u.uy));
670 mtmp = bhit(u.dx, u.dy, COLNO, INVIS_BEAM,
671 (int FDECL((*),(MONST_P,OBJ_P)))0,
672 (int FDECL((*),(OBJ_P,OBJ_P)))0,
674 if (!mtmp || !haseyes(mtmp->data))
677 vis = canseemon(mtmp);
678 mlet = mtmp->data->mlet;
679 if (mtmp->msleeping) {
681 pline ("%s is too tired to look at your mirror.",
683 } else if (!mtmp->mcansee) {
685 pline("%s can't see anything right now.", Monnam(mtmp));
686 /* some monsters do special things */
687 } else if (mlet == S_VAMPIRE || mlet == S_GHOST) {
689 pline ("%s doesn't have a reflection.", Monnam(mtmp));
690 } else if(!mtmp->mcan && !mtmp->minvis &&
691 mtmp->data == &mons[PM_MEDUSA]) {
692 if (mon_reflects(mtmp, "The gaze is reflected away by %s %s!"))
695 pline("%s is turned to stone!", Monnam(mtmp));
698 } else if(!mtmp->mcan && !mtmp->minvis &&
699 mtmp->data == &mons[PM_FLOATING_EYE]) {
700 int tmp = d((int)mtmp->m_lev, (int)mtmp->data->mattk[0].damd);
701 if (!rn2(4)) tmp = 120;
703 pline("%s is frozen by its reflection.", Monnam(mtmp));
704 else You_hear("%s stop moving.",something);
706 if ( (int) mtmp->mfrozen + tmp > 127)
708 else mtmp->mfrozen += tmp;
709 } else if(!mtmp->mcan && !mtmp->minvis &&
710 mtmp->data == &mons[PM_UMBER_HULK]) {
712 pline ("%s confuses itself!", Monnam(mtmp));
714 } else if(!mtmp->mcan && !mtmp->minvis && (mlet == S_NYMPH
715 || mtmp->data==&mons[PM_SUCCUBUS])) {
717 pline ("%s admires herself in your mirror.", Monnam(mtmp));
718 pline ("She takes it!");
719 } else pline ("It steals your mirror!");
720 setnotworn(obj); /* in case mirror was wielded */
722 (void) mpickobj(mtmp,obj);
723 if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
724 } else if (!is_unicorn(mtmp->data) && !humanoid(mtmp->data) &&
725 (!mtmp->minvis || perceives(mtmp->data)) && rn2(5)) {
727 pline("%s is frightened by its reflection.", Monnam(mtmp));
728 monflee(mtmp, d(2,4), FALSE, FALSE);
730 if (mtmp->minvis && !See_invisible)
732 else if ((mtmp->minvis && !perceives(mtmp->data))
733 || !haseyes(mtmp->data))
734 pline("%s doesn't seem to notice its reflection.",
737 pline("%s ignores %s reflection.",
738 Monnam(mtmp), mhis(mtmp));
747 register struct obj *obj = *optr;
749 boolean wakem = FALSE, learno = FALSE,
750 ordinary = (obj->otyp != BELL_OF_OPENING || !obj->spe),
751 invoking = (obj->otyp == BELL_OF_OPENING &&
752 invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy));
754 You("ring %s.", the(xname(obj)));
756 if (Underwater || (u.uswallow && ordinary)) {
758 amii_speaker( obj, "AhDhGqEqDhEhAqDqFhGw", AMII_MUFFLED_VOLUME );
760 pline("But the sound is muffled.");
762 } else if (invoking && ordinary) {
763 /* needs to be recharged... */
764 pline("But it makes no sound.");
765 learno = TRUE; /* help player figure out why */
767 } else if (ordinary) {
769 amii_speaker( obj, "ahdhgqeqdhehaqdqfhgw", AMII_MUFFLED_VOLUME );
771 if (obj->cursed && !rn2(4) &&
772 /* note: once any of them are gone, we stop all of them */
773 !(mvitals[PM_WOOD_NYMPH].mvflags & G_GONE) &&
774 !(mvitals[PM_WATER_NYMPH].mvflags & G_GONE) &&
775 !(mvitals[PM_MOUNTAIN_NYMPH].mvflags & G_GONE) &&
776 (mtmp = makemon(mkclass(S_NYMPH, 0),
777 u.ux, u.uy, NO_MINVENT)) != 0) {
778 You("summon %s!", a_monnam(mtmp));
779 if (!obj_resists(obj, 93, 100)) {
780 pline("%s shattered!", Tobjnam(obj, "have"));
783 } else switch (rn2(3)) {
787 mon_adjust_speed(mtmp, 2, (struct obj *)0);
789 case 2: /* no explanation; it just happens... */
798 /* charged Bell of Opening */
799 consume_obj_charge(obj, TRUE);
805 pline(nothing_happens);
807 } else if (obj->cursed) {
812 mkundead(&mm, FALSE, NO_MINVENT);
815 } else if (invoking) {
816 pline("%s an unsettling shrill sound...",
817 Tobjnam(obj, "issue"));
819 amii_speaker( obj, "aefeaefeaefeaefeaefe", AMII_LOUDER_VOLUME );
825 } else if (obj->blessed) {
829 amii_speaker( obj, "ahahahDhEhCw", AMII_SOFT_VOLUME );
837 case 0: pline(nothing_happens); break;
838 case 1: pline("%s opens...", Something);
839 learno = TRUE; break;
840 default: pline("Things open around you...");
841 learno = TRUE; break;
844 } else { /* uncursed */
846 amii_speaker( obj, "AeFeaeFeAefegw", AMII_OKAY_VOLUME );
848 if (findit() != 0) learno = TRUE;
849 else pline(nothing_happens);
855 makeknown(BELL_OF_OPENING);
858 if (wakem) wake_nearby();
863 register struct obj *obj;
865 const char *s = (obj->spe != 1) ? "candles" : "candle";
868 You("cannot make fire under water.");
872 You("snuff the %s.", s);
877 pline("This %s has no %s.", xname(obj), s);
880 if(u.uswallow || obj->cursed) {
882 pline_The("%s %s for a moment, then %s.",
883 s, vtense(s, "flicker"), vtense(s, "die"));
887 There("%s only %d %s in %s.",
888 vtense(s, "are"), obj->spe, s, the(xname(obj)));
890 pline("%s lit. %s dimly.",
891 obj->spe == 1 ? "It is" : "They are",
892 Tobjnam(obj, "shine"));
894 pline("%s's %s burn%s", The(xname(obj)), s,
895 (Blind ? "." : " brightly!"));
897 if (!invocation_pos(u.ux, u.uy)) {
898 pline_The("%s %s being rapidly consumed!", s, vtense(s, "are"));
903 pline("%s a strange warmth!", Tobjnam(obj, "radiate"));
905 pline("%s with a strange light!", Tobjnam(obj, "glow"));
909 begin_burn(obj, FALSE);
916 register struct obj *obj = *optr;
917 register struct obj *otmp;
918 const char *s = (obj->quan != 1) ? "candles" : "candle";
926 pline("Sorry, fire and water don't mix.");
930 otmp = carrying(CANDELABRUM_OF_INVOCATION);
931 if(!otmp || otmp->spe == 7) {
936 Sprintf(qbuf, "Attach %s", the(xname(obj)));
937 Sprintf(eos(qbuf), " to %s?",
938 safe_qbuf(qbuf, sizeof(" to ?"), the(xname(otmp)),
939 the(simple_typename(otmp->otyp)), "it"));
940 if(yn(qbuf) == 'n') {
942 You("try to light %s...", the(xname(obj)));
946 if ((long)otmp->spe + obj->quan > 7L)
947 obj = splitobj(obj, 7L - (long)otmp->spe);
949 You("attach %ld%s %s to %s.",
950 obj->quan, !otmp->spe ? "" : " more",
951 s, the(xname(otmp)));
952 if (!otmp->spe || otmp->age > obj->age)
953 otmp->age = obj->age;
954 otmp->spe += (int)obj->quan;
955 if (otmp->lamplit && !obj->lamplit)
956 pline_The("new %s magically %s!", s, vtense(s, "ignite"));
957 else if (!otmp->lamplit && obj->lamplit)
958 pline("%s out.", (obj->quan > 1L) ? "They go" : "It goes");
960 verbalize("You %s %s, you bought %s!",
961 otmp->lamplit ? "burn" : "use",
962 (obj->quan > 1L) ? "them" : "it",
963 (obj->quan > 1L) ? "them" : "it");
964 if (obj->quan < 7L && otmp->spe == 7)
965 pline("%s now has seven%s candles attached.",
966 The(xname(otmp)), otmp->lamplit ? " lit" : "");
967 /* candelabrum's light range might increase */
968 if (otmp->lamplit) obj_merge_light_sources(otmp, otmp);
969 /* candles are no longer a separate light source */
970 if (obj->lamplit) end_burn(obj, TRUE);
971 /* candles are now gone */
977 snuff_candle(otmp) /* call in drop, throw, and put in box, etc. */
978 register struct obj *otmp;
980 register boolean candle = Is_candle(otmp);
982 if ((candle || otmp->otyp == CANDELABRUM_OF_INVOCATION) &&
986 register boolean many = candle ? otmp->quan > 1L : otmp->spe > 1;
988 (void) get_obj_location(otmp, &x, &y, 0);
989 if (otmp->where == OBJ_MINVENT ? cansee(x,y) : !Blind)
990 pline("%s %scandle%s flame%s extinguished.",
992 (candle ? "" : "candelabrum's "),
993 (many ? "s'" : "'s"), (many ? "s are" : " is"));
994 end_burn(otmp, TRUE);
1000 /* called when lit lamp is hit by water or put into a container or
1001 you've been swallowed by a monster; obj might be in transit while
1002 being thrown or dropped so don't assume that its location is valid */
1010 if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
1011 obj->otyp == BRASS_LANTERN || obj->otyp == POT_OIL) {
1012 (void) get_obj_location(obj, &x, &y, 0);
1013 if (obj->where == OBJ_MINVENT ? cansee(x,y) : !Blind)
1014 pline("%s %s out!", Yname2(obj), otense(obj, "go"));
1015 end_burn(obj, TRUE);
1018 if (snuff_candle(obj)) return TRUE;
1023 /* Called when potentially lightable object is affected by fire_damage().
1024 Return TRUE if object was lit and FALSE otherwise --ALI */
1031 if (!obj->lamplit && (obj->otyp == MAGIC_LAMP || ignitable(obj))) {
1032 if ((obj->otyp == MAGIC_LAMP ||
1033 obj->otyp == CANDELABRUM_OF_INVOCATION) &&
1036 else if (obj->otyp != MAGIC_LAMP && obj->age == 0)
1038 if (!get_obj_location(obj, &x, &y, 0))
1040 if (obj->otyp == CANDELABRUM_OF_INVOCATION && obj->cursed)
1042 if ((obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
1043 obj->otyp == BRASS_LANTERN) && obj->cursed && !rn2(2))
1045 if (obj->where == OBJ_MINVENT ? cansee(x,y) : !Blind)
1046 pline("%s %s light!", Yname2(obj), otense(obj, "catch"));
1047 if (obj->otyp == POT_OIL) makeknown(obj->otyp);
1048 if (obj->unpaid && costly_spot(u.ux, u.uy) && (obj->where == OBJ_INVENT)) {
1049 /* if it catches while you have it, then it's your tough luck */
1051 verbalize("That's in addition to the cost of %s %s, of course.",
1052 Yname2(obj), obj->quan == 1 ? "itself" : "themselves");
1053 bill_dummy_object(obj);
1055 begin_burn(obj, FALSE);
1068 pline("This is not a diving lamp.");
1072 if(obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
1073 obj->otyp == BRASS_LANTERN)
1074 pline("%s lamp is now off.", Shk_Your(buf, obj));
1076 You("snuff out %s.", yname(obj));
1077 end_burn(obj, TRUE);
1080 /* magic lamps with an spe == 0 (wished for) cannot be lit */
1081 if ((!Is_candle(obj) && obj->age == 0)
1082 || (obj->otyp == MAGIC_LAMP && obj->spe == 0)) {
1083 if (obj->otyp == BRASS_LANTERN)
1084 Your("lamp has run out of power.");
1085 else pline("This %s has no oil.", xname(obj));
1088 if (obj->cursed && !rn2(2)) {
1089 pline("%s for a moment, then %s.",
1090 Tobjnam(obj, "flicker"), otense(obj, "die"));
1092 if(obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
1093 obj->otyp == BRASS_LANTERN) {
1095 pline("%s lamp is now on.", Shk_Your(buf, obj));
1096 } else { /* candle(s) */
1097 pline("%s flame%s %s%s",
1098 s_suffix(Yname2(obj)),
1099 plur(obj->quan), otense(obj, "burn"),
1100 Blind ? "." : " brightly!");
1101 if (obj->unpaid && costly_spot(u.ux, u.uy) &&
1102 obj->age == 20L * (long)objects[obj->otyp].oc_cost) {
1103 const char *ithem = obj->quan > 1L ? "them" : "it";
1104 verbalize("You burn %s, you bought %s!", ithem, ithem);
1105 bill_dummy_object(obj);
1108 begin_burn(obj, FALSE);
1114 struct obj *obj; /* obj is a potion of oil */
1124 You("snuff the lit potion.");
1125 end_burn(obj, TRUE);
1127 * Free & add to re-merge potion. This will average the
1128 * age of the potions. Not exactly the best solution,
1134 } else if (Underwater) {
1135 There("is not enough oxygen to sustain a fire.");
1139 You("light %s potion.%s", shk_your(buf, obj),
1140 Blind ? "" : " It gives off a dim light.");
1141 if (obj->unpaid && costly_spot(u.ux, u.uy)) {
1142 /* Normally, we shouldn't both partially and fully charge
1143 * for an item, but (Yendorian Fuel) Taxes are inevitable...
1146 verbalize("That's in addition to the cost of the potion, of course.");
1147 bill_dummy_object(obj);
1149 makeknown(obj->otyp);
1151 if (obj->quan > 1L) {
1152 obj = splitobj(obj, 1L);
1153 begin_burn(obj, FALSE); /* burn before free to get position */
1154 obj_extract_self(obj); /* free from inv */
1156 /* shouldn't merge */
1157 obj = hold_another_object(obj, "You drop %s!",
1158 doname(obj), (const char *)0);
1160 begin_burn(obj, FALSE);
1163 static NEARDATA const char cuddly[] = { TOOL_CLASS, GEM_CLASS, 0 };
1168 struct obj *obj = getobj(cuddly, "rub");
1170 if (obj && obj->oclass == GEM_CLASS) {
1171 if (is_graystone(obj)) {
1175 pline("Sorry, I don't know how to use that.");
1180 if (!obj || !wield_tool(obj, "rub")) return 0;
1182 /* now uwep is obj */
1183 if (uwep->otyp == MAGIC_LAMP) {
1184 if (uwep->spe > 0 && !rn2(3)) {
1185 check_unpaid_usage(uwep, TRUE); /* unusual item use */
1186 djinni_from_bottle(uwep);
1187 makeknown(MAGIC_LAMP);
1188 uwep->otyp = OIL_LAMP;
1189 uwep->spe = 0; /* for safety */
1190 uwep->age = rn1(500,1000);
1191 if (uwep->lamplit) begin_burn(uwep, TRUE);
1193 } else if (rn2(2) && !Blind)
1194 You("see a puff of smoke.");
1195 else pline(nothing_happens);
1196 } else if (obj->otyp == BRASS_LANTERN) {
1197 /* message from Adventure */
1198 pline("Rubbing the electric lamp is not particularly rewarding.");
1199 pline("Anyway, nothing exciting happens.");
1200 } else pline(nothing_happens);
1213 int magic; /* 0=Physical, otherwise skill level */
1217 if (!magic && (nolimbs(youmonst.data) || slithy(youmonst.data))) {
1218 /* normally (nolimbs || slithy) implies !Jumping,
1219 but that isn't necessarily the case for knights */
1220 You_cant("jump; you have no legs!");
1222 } else if (!magic && !Jumping) {
1223 You_cant("jump very far.");
1225 } else if (u.uswallow) {
1227 You("bounce around a little.");
1230 pline("You've got to be kidding!");
1232 } else if (u.uinwater) {
1234 You("swish around a little.");
1237 pline("This calls for swimming, not jumping!");
1239 } else if (u.ustuck) {
1240 if (u.ustuck->mtame && !Conflict && !u.ustuck->mconf) {
1241 You("pull free from %s.", mon_nam(u.ustuck));
1246 You("writhe a little in the grasp of %s!", mon_nam(u.ustuck));
1249 You("cannot escape from %s!", mon_nam(u.ustuck));
1251 } else if (Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)) {
1253 You("flail around a little.");
1256 You("don't have enough traction to jump.");
1258 } else if (!magic && near_capacity() > UNENCUMBERED) {
1259 You("are carrying too much to jump!");
1261 } else if (!magic && (u.uhunger <= 100 || ACURR(A_STR) < 6)) {
1262 You("lack the strength to jump!");
1264 } else if (Wounded_legs) {
1265 long wl = (Wounded_legs & BOTH_SIDES);
1266 const char *bp = body_part(LEG);
1268 if (wl == BOTH_SIDES) bp = makeplural(bp);
1271 pline("%s is in no shape for jumping.", Monnam(u.usteed));
1274 Your("%s%s %s in no shape for jumping.",
1275 (wl == LEFT_SIDE) ? "left " :
1276 (wl == RIGHT_SIDE) ? "right " : "",
1277 bp, (wl == BOTH_SIDES) ? "are" : "is");
1281 else if (u.usteed && u.utrap) {
1282 pline("%s is stuck in a trap.", Monnam(u.usteed));
1287 pline("Where do you want to jump?");
1290 if (getpos(&cc, TRUE, "the desired position") < 0)
1291 return 0; /* user pressed ESC */
1292 if (!magic && !(HJumping & ~INTRINSIC) && !EJumping &&
1293 distu(cc.x, cc.y) != 5) {
1294 /* The Knight jumping restriction still applies when riding a
1295 * horse. After all, what shape is the knight piece in chess?
1297 pline("Illegal move!");
1299 } else if (distu(cc.x, cc.y) > (magic ? 6+magic*3 : 9)) {
1302 } else if (!cansee(cc.x, cc.y)) {
1303 You("cannot see where to land!");
1305 } else if (!isok(cc.x, cc.y)) {
1306 You("cannot jump there!");
1313 switch(u.utraptype) {
1315 register long side = rn2(3) ? LEFT_SIDE : RIGHT_SIDE;
1316 You("rip yourself free of the bear trap! Ouch!");
1317 losehp(rnd(10), "jumping out of a bear trap", KILLED_BY);
1318 set_wounded_legs(side, rn1(1000,500));
1322 You("leap from the pit!");
1325 You("tear the web apart as you pull yourself free!");
1326 deltrap(t_at(u.ux,u.uy));
1329 You("pull yourself above the lava!");
1333 You("strain your %s, but you're still stuck in the floor.",
1334 makeplural(body_part(LEG)));
1335 set_wounded_legs(LEFT_SIDE, rn1(10, 11));
1336 set_wounded_legs(RIGHT_SIDE, rn1(10, 11));
1341 * Check the path from uc to cc, calling hurtle_step at each
1342 * location. The final position actually reached will be
1347 /* calculate max(abs(dx), abs(dy)) as the range */
1348 range = cc.x - uc.x;
1349 if (range < 0) range = -range;
1351 if (temp < 0) temp = -temp;
1354 (void) walk_path(&uc, &cc, hurtle_step, (genericptr_t)&range);
1356 /* A little Sokoban guilt... */
1357 if (In_sokoban(&u.uz))
1360 teleds(cc.x, cc.y, TRUE);
1363 morehungry(rnd(25));
1372 if (corpse->oeaten) return 0;
1373 if (!mons[corpse->corpsenm].cnutrit) return 0;
1378 use_tinning_kit(obj)
1379 register struct obj *obj;
1381 register struct obj *corpse, *can;
1383 /* This takes only 1 move. If this is to be changed to take many
1384 * moves, we've got to deal with decaying corpses...
1386 if (obj->spe <= 0) {
1387 You("seem to be out of tins.");
1390 if (!(corpse = floorfood("tin", 2))) return;
1391 if (corpse->oeaten) {
1392 You("cannot tin %s which is partly eaten.",something);
1395 if (touch_petrifies(&mons[corpse->corpsenm])
1396 && !Stone_resistance && !uarmg) {
1399 if (poly_when_stoned(youmonst.data))
1400 You("tin %s without wearing gloves.",
1401 an(mons[corpse->corpsenm].mname));
1403 pline("Tinning %s without wearing gloves is a fatal mistake...",
1404 an(mons[corpse->corpsenm].mname));
1405 Sprintf(kbuf, "trying to tin %s without gloves",
1406 an(mons[corpse->corpsenm].mname));
1410 if (is_rider(&mons[corpse->corpsenm])) {
1411 (void) revive_corpse(corpse);
1412 verbalize("Yes... But War does not preserve its enemies...");
1415 if (mons[corpse->corpsenm].cnutrit == 0) {
1416 pline("That's too insubstantial to tin.");
1419 consume_obj_charge(obj, TRUE);
1421 if ((can = mksobj(TIN, FALSE, FALSE)) != 0) {
1422 static const char you_buy_it[] = "You tin it, you bought it!";
1424 can->corpsenm = corpse->corpsenm;
1425 can->cursed = obj->cursed;
1426 can->blessed = obj->blessed;
1427 can->owt = weight(can);
1429 can->spe = -1; /* Mark tinned tins. No spinach allowed... */
1430 if (carried(corpse)) {
1432 verbalize(you_buy_it);
1435 if (costly_spot(corpse->ox, corpse->oy) && !corpse->no_charge)
1436 verbalize(you_buy_it);
1439 can = hold_another_object(can, "You make, but cannot pick up, %s.",
1440 doname(can), (const char *)0);
1441 } else impossible("Tinning failed.");
1445 use_unicorn_horn(obj)
1448 #define PROP_COUNT 6 /* number of properties we're dealing with */
1449 #define ATTR_COUNT (A_MAX*3) /* number of attribute points we might fix */
1450 int idx, val, val_limit,
1451 trouble_count, unfixable_trbl, did_prop, did_attr;
1452 int trouble_list[PROP_COUNT + ATTR_COUNT];
1454 if (obj && obj->cursed) {
1455 long lcount = (long) rnd(100);
1458 case 0: make_sick(Sick ? Sick/3L + 1L : (long)rn1(ACURR(A_CON),20),
1459 xname(obj), TRUE, SICK_NONVOMITABLE);
1461 case 1: make_blinded(Blinded + lcount, TRUE);
1463 case 2: if (!Confusion)
1464 You("suddenly feel %s.",
1465 Hallucination ? "trippy" : "confused");
1466 make_confused(HConfusion + lcount, TRUE);
1468 case 3: make_stunned(HStun + lcount, TRUE);
1470 case 4: (void) adjattrib(rn2(A_MAX), -1, FALSE);
1472 case 5: (void) make_hallucinated(HHallucination + lcount, TRUE, 0L);
1479 * Entries in the trouble list use a very simple encoding scheme.
1481 #define prop2trbl(X) ((X) + A_MAX)
1482 #define attr2trbl(Y) (Y)
1483 #define prop_trouble(X) trouble_list[trouble_count++] = prop2trbl(X)
1484 #define attr_trouble(Y) trouble_list[trouble_count++] = attr2trbl(Y)
1486 trouble_count = unfixable_trbl = did_prop = did_attr = 0;
1488 /* collect property troubles */
1489 if (Sick) prop_trouble(SICK);
1490 if (Blinded > (long)u.ucreamed) prop_trouble(BLINDED);
1491 if (HHallucination) prop_trouble(HALLUC);
1492 if (Vomiting) prop_trouble(VOMITING);
1493 if (HConfusion) prop_trouble(CONFUSION);
1494 if (HStun) prop_trouble(STUNNED);
1496 unfixable_trbl = unfixable_trouble_count(TRUE);
1498 /* collect attribute troubles */
1499 for (idx = 0; idx < A_MAX; idx++) {
1500 val_limit = AMAX(idx);
1501 /* don't recover strength lost from hunger */
1502 if (idx == A_STR && u.uhs >= WEAK) val_limit--;
1503 /* don't recover more than 3 points worth of any attribute */
1504 if (val_limit > ABASE(idx) + 3) val_limit = ABASE(idx) + 3;
1506 for (val = ABASE(idx); val < val_limit; val++)
1508 /* keep track of unfixed trouble, for message adjustment below */
1509 unfixable_trbl += (AMAX(idx) - val_limit);
1512 if (trouble_count == 0) {
1513 pline(nothing_happens);
1515 } else if (trouble_count > 1) { /* shuffle */
1518 for (i = trouble_count - 1; i > 0; i--)
1519 if ((j = rn2(i + 1)) != i) {
1520 k = trouble_list[j];
1521 trouble_list[j] = trouble_list[i];
1522 trouble_list[i] = k;
1527 * Chances for number of troubles to be fixed
1529 * blessed: 22.7% 22.7% 19.5% 15.4% 10.7% 5.7% 2.6% 0.8%
1530 * uncursed: 35.4% 35.4% 22.9% 6.3% 0 0 0 0
1532 val_limit = rn2( d(2, (obj && obj->blessed) ? 4 : 2) );
1533 if (val_limit > trouble_count) val_limit = trouble_count;
1535 /* fix [some of] the troubles */
1536 for (val = 0; val < val_limit; val++) {
1537 idx = trouble_list[val];
1540 case prop2trbl(SICK):
1541 make_sick(0L, (char *) 0, TRUE, SICK_ALL);
1544 case prop2trbl(BLINDED):
1545 make_blinded((long)u.ucreamed, TRUE);
1548 case prop2trbl(HALLUC):
1549 (void) make_hallucinated(0L, TRUE, 0L);
1552 case prop2trbl(VOMITING):
1553 make_vomiting(0L, TRUE);
1556 case prop2trbl(CONFUSION):
1557 make_confused(0L, TRUE);
1560 case prop2trbl(STUNNED):
1561 make_stunned(0L, TRUE);
1565 if (idx >= 0 && idx < A_MAX) {
1569 panic("use_unicorn_horn: bad trouble? (%d)", idx);
1575 pline("This makes you feel %s!",
1576 (did_prop + did_attr) == (trouble_count + unfixable_trbl) ?
1577 "great" : "better");
1579 pline("Nothing seems to happen.");
1581 flags.botl = (did_attr || did_prop);
1591 * Timer callback routine: turn figurine into monster
1594 fig_transform(arg, timeout)
1598 struct obj *figurine = (struct obj *)arg;
1601 boolean cansee_spot, silent, okay_spot;
1602 boolean redraw = FALSE;
1603 char monnambuf[BUFSZ], carriedby[BUFSZ];
1607 pline("null figurine in fig_transform()");
1611 silent = (timeout != monstermoves); /* happened while away */
1612 okay_spot = get_obj_location(figurine, &cc.x, &cc.y, 0);
1613 if (figurine->where == OBJ_INVENT ||
1614 figurine->where == OBJ_MINVENT)
1615 okay_spot = enexto(&cc, cc.x, cc.y,
1616 &mons[figurine->corpsenm]);
1618 !figurine_location_checks(figurine,&cc, TRUE)) {
1619 /* reset the timer to try again later */
1620 (void) start_timer((long)rnd(5000), TIMER_OBJECT,
1621 FIG_TRANSFORM, (genericptr_t)figurine);
1625 cansee_spot = cansee(cc.x, cc.y);
1626 mtmp = make_familiar(figurine, cc.x, cc.y, TRUE);
1628 Sprintf(monnambuf, "%s",an(m_monnam(mtmp)));
1629 switch (figurine->where) {
1632 You_feel("%s %s from your pack!", something,
1633 locomotion(mtmp->data,"drop"));
1635 You("see %s %s out of your pack!",
1637 locomotion(mtmp->data,"drop"));
1641 if (cansee_spot && !silent) {
1642 You("suddenly see a figurine transform into %s!",
1644 redraw = TRUE; /* update figurine's map location */
1649 if (cansee_spot && !silent) {
1651 mon = figurine->ocarry;
1652 /* figurine carring monster might be invisible */
1653 if (canseemon(figurine->ocarry)) {
1654 Sprintf(carriedby, "%s pack",
1655 s_suffix(a_monnam(mon)));
1657 else if (is_pool(mon->mx, mon->my))
1658 Strcpy(carriedby, "empty water");
1660 Strcpy(carriedby, "thin air");
1661 You("see %s %s out of %s!", monnambuf,
1662 locomotion(mtmp->data, "drop"), carriedby);
1671 impossible("figurine came to life where? (%d)",
1672 (int)figurine->where);
1676 /* free figurine now */
1677 obj_extract_self(figurine);
1678 obfree(figurine, (struct obj *)0);
1679 if (redraw) newsym(cc.x, cc.y);
1683 figurine_location_checks(obj, cc, quietly)
1690 if (carried(obj) && u.uswallow) {
1692 You("don't have enough room in here.");
1695 x = cc->x; y = cc->y;
1698 You("cannot put the figurine there.");
1701 if (IS_ROCK(levl[x][y].typ) &&
1702 !(passes_walls(&mons[obj->corpsenm]) && may_passwall(x,y))) {
1704 You("cannot place a figurine in %s!",
1705 IS_TREE(levl[x][y].typ) ? "a tree" : "solid rock");
1708 if (sobj_at(BOULDER,x,y) && !passes_walls(&mons[obj->corpsenm])
1709 && !throws_rocks(&mons[obj->corpsenm])) {
1711 You("cannot fit the figurine on the boulder.");
1721 register struct obj *obj = *optr;
1726 /* can't activate a figurine while swallowed */
1727 if (!figurine_location_checks(obj, (coord *)0, FALSE))
1730 if(!getdir((char *)0)) {
1731 flags.move = multi = 0;
1734 x = u.ux + u.dx; y = u.uy + u.dy;
1736 /* Passing FALSE arg here will result in messages displayed */
1737 if (!figurine_location_checks(obj, &cc, FALSE)) return;
1738 You("%s and it transforms.",
1739 (u.dx||u.dy) ? "set the figurine beside you" :
1740 (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ||
1741 is_pool(cc.x, cc.y)) ?
1742 "release the figurine" :
1744 "toss the figurine into the air" :
1745 "set the figurine on the ground"));
1746 (void) make_familiar(obj, cc.x, cc.y, FALSE);
1747 (void) stop_timer(FIG_TRANSFORM, (genericptr_t)obj);
1752 static NEARDATA const char lubricables[] = { ALL_CLASSES, ALLOW_NONE, 0 };
1753 static NEARDATA const char need_to_remove_outer_armor[] =
1754 "need to remove your %s to grease your %s.";
1764 pline("%s from your %s.", Tobjnam(obj, "slip"),
1765 makeplural(body_part(FINGER)));
1771 if ((obj->cursed || Fumbling) && !rn2(2)) {
1772 consume_obj_charge(obj, TRUE);
1774 pline("%s from your %s.", Tobjnam(obj, "slip"),
1775 makeplural(body_part(FINGER)));
1779 otmp = getobj(lubricables, "grease");
1781 if ((otmp->owornmask & WORN_ARMOR) && uarmc) {
1782 Strcpy(buf, xname(uarmc));
1783 You(need_to_remove_outer_armor, buf, xname(otmp));
1787 if ((otmp->owornmask & WORN_SHIRT) && (uarmc || uarm)) {
1788 Strcpy(buf, uarmc ? xname(uarmc) : "");
1789 if (uarmc && uarm) Strcat(buf, " and ");
1790 Strcat(buf, uarm ? xname(uarm) : "");
1791 You(need_to_remove_outer_armor, buf, xname(otmp));
1795 consume_obj_charge(obj, TRUE);
1797 if (otmp != &zeroobj) {
1798 You("cover %s with a thick layer of grease.",
1801 if (obj->cursed && !nohands(youmonst.data)) {
1802 incr_itimeout(&Glib, rnd(15));
1803 pline("Some of the grease gets all over your %s.",
1804 makeplural(body_part(HAND)));
1808 You("coat your %s with grease.",
1809 makeplural(body_part(FINGER)));
1813 pline("%s empty.", Tobjnam(obj, "are"));
1815 pline("%s to be empty.", Tobjnam(obj, "seem"));
1820 static struct trapinfo {
1824 boolean force_bungle;
1831 trapinfo.force_bungle = 0;
1834 /* touchstones - by Ken Arnold */
1841 const char *streak_color, *choices;
1842 char stonebuf[QBUFSZ];
1843 static const char scritch[] = "\"scritch, scritch\"";
1844 static const char allowall[3] = { COIN_CLASS, ALL_CLASSES, 0 };
1845 static const char justgems[3] = { ALLOW_NONE, GEM_CLASS, 0 };
1850 /* in case it was acquired while blinded */
1851 if (!Blind) tstone->dknown = 1;
1852 /* when the touchstone is fully known, don't bother listing extra
1853 junk as likely candidates for rubbing */
1854 choices = (tstone->otyp == TOUCHSTONE && tstone->dknown &&
1855 objects[TOUCHSTONE].oc_name_known) ? justgems : allowall;
1856 Sprintf(stonebuf, "rub on the stone%s", plur(tstone->quan));
1857 if ((obj = getobj(choices, stonebuf)) == 0)
1860 if (obj->oclass == COIN_CLASS) {
1861 u.ugold += obj->quan; /* keep botl up to date */
1868 if (obj == tstone && obj->quan == 1) {
1869 You_cant("rub %s on itself.", the(xname(obj)));
1873 if (tstone->otyp == TOUCHSTONE && tstone->cursed &&
1874 obj->oclass == GEM_CLASS && !is_graystone(obj) &&
1875 !obj_resists(obj, 80, 100)) {
1877 pline("You feel something shatter.");
1878 else if (Hallucination)
1879 pline("Oh, wow, look at the pretty shards.");
1881 pline("A sharp crack shatters %s%s.",
1882 (obj->quan > 1) ? "one of " : "", the(xname(obj)));
1884 /* assert(obj != &goldobj); */
1893 } else if (Hallucination) {
1894 pline("Oh wow, man: Fractals!");
1901 switch (obj->oclass) {
1902 case GEM_CLASS: /* these have class-specific handling below */
1904 if (tstone->otyp != TOUCHSTONE) {
1906 } else if (obj->oclass == GEM_CLASS && (tstone->blessed ||
1908 (Role_if(PM_ARCHEOLOGIST) || Race_if(PM_GNOME))))) {
1909 makeknown(TOUCHSTONE);
1910 makeknown(obj->otyp);
1911 prinv((char *)0, obj, 0L);
1914 /* either a ring or the touchstone was not effective */
1915 if (objects[obj->otyp].oc_material == GLASS) {
1920 streak_color = c_obj_colors[objects[obj->otyp].oc_color];
1921 break; /* gem or ring */
1924 switch (objects[obj->otyp].oc_material) {
1926 pline("%s a little more polished now.", Tobjnam(tstone, "look"));
1929 if (!obj->known) /* note: not "whetstone" */
1930 You("must think this is a wetstone, do you?");
1932 pline("%s a little wetter now.", Tobjnam(tstone, "are"));
1935 streak_color = "waxy";
1936 break; /* okay even if not touchstone */
1938 streak_color = "wooden";
1939 break; /* okay even if not touchstone */
1941 do_scratch = TRUE; /* scratching and streaks */
1942 streak_color = "golden";
1945 do_scratch = TRUE; /* scratching and streaks */
1946 streak_color = "silvery";
1949 /* Objects passing the is_flimsy() test will not
1950 scratch a stone. They will leave streaks on
1951 non-touchstones and touchstones alike. */
1953 streak_color = c_obj_colors[objects[obj->otyp].oc_color];
1955 do_scratch = (tstone->otyp != TOUCHSTONE);
1958 break; /* default oclass */
1961 Sprintf(stonebuf, "stone%s", plur(tstone->quan));
1963 pline("You make %s%sscratch marks on the %s.",
1964 streak_color ? streak_color : (const char *)"",
1965 streak_color ? " " : "", stonebuf);
1966 else if (streak_color)
1967 pline("You see %s streaks on the %s.", streak_color, stonebuf);
1973 /* Place a landmine/bear trap. Helge Hafting */
1979 const char *what = (char *)0;
1981 const char *occutext = "setting the trap";
1983 if (nohands(youmonst.data))
1984 what = "without hands";
1986 what = "while stunned";
1987 else if (u.uswallow)
1988 what = is_animal(u.ustuck->data) ? "while swallowed" :
1990 else if (Underwater)
1991 what = "underwater";
1992 else if (Levitation)
1993 what = "while levitating";
1994 else if (is_pool(u.ux, u.uy))
1996 else if (is_lava(u.ux, u.uy))
1998 else if (On_stairs(u.ux, u.uy))
1999 what = (u.ux == xdnladder || u.ux == xupladder) ?
2000 "on the ladder" : "on the stairs";
2001 else if (IS_FURNITURE(levl[u.ux][u.uy].typ) ||
2002 IS_ROCK(levl[u.ux][u.uy].typ) ||
2003 closed_door(u.ux, u.uy) || t_at(u.ux, u.uy))
2006 You_cant("set a trap %s!",what);
2010 ttyp = (otmp->otyp == LAND_MINE) ? LANDMINE : BEAR_TRAP;
2011 if (otmp == trapinfo.tobj &&
2012 u.ux == trapinfo.tx && u.uy == trapinfo.ty) {
2013 You("resume setting %s %s.",
2014 shk_your(buf, otmp),
2015 defsyms[trap_to_defsym(what_trap(ttyp))].explanation);
2016 set_occupation(set_trap, occutext, 0);
2019 trapinfo.tobj = otmp;
2020 trapinfo.tx = u.ux, trapinfo.ty = u.uy;
2022 trapinfo.time_needed = (tmp > 17) ? 2 : (tmp > 12) ? 3 :
2024 if (Blind) trapinfo.time_needed *= 2;
2026 if (ttyp == BEAR_TRAP && tmp < 18)
2027 trapinfo.time_needed += (tmp > 12) ? 1 : (tmp > 7) ? 2 : 4;
2028 /*[fumbling and/or confusion and/or cursed object check(s)
2029 should be incorporated here instead of in set_trap]*/
2031 if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) {
2034 if (Fumbling || otmp->cursed) chance = (rnl(10) > 3);
2035 else chance = (rnl(10) > 5);
2036 You("aren't very skilled at reaching from %s.",
2038 Sprintf(buf, "Continue your attempt to set %s?",
2039 the(defsyms[trap_to_defsym(what_trap(ttyp))].explanation));
2040 if(yn(buf) == 'y') {
2043 case LANDMINE: /* set it off */
2044 trapinfo.time_needed = 0;
2045 trapinfo.force_bungle = TRUE;
2047 case BEAR_TRAP: /* drop it without arming it */
2050 the(defsyms[trap_to_defsym(what_trap(ttyp))].explanation));
2061 You("begin setting %s %s.",
2062 shk_your(buf, otmp),
2063 defsyms[trap_to_defsym(what_trap(ttyp))].explanation);
2064 set_occupation(set_trap, occutext, 0);
2072 struct obj *otmp = trapinfo.tobj;
2076 if (!otmp || !carried(otmp) ||
2077 u.ux != trapinfo.tx || u.uy != trapinfo.ty) {
2083 if (--trapinfo.time_needed > 0) return 1; /* still busy */
2085 ttyp = (otmp->otyp == LAND_MINE) ? LANDMINE : BEAR_TRAP;
2086 ttmp = maketrap(u.ux, u.uy, ttyp);
2090 newsym(u.ux, u.uy); /* if our hero happens to be invisible */
2091 if (*in_rooms(u.ux,u.uy,SHOPBASE)) {
2092 add_damage(u.ux, u.uy, 0L); /* schedule removal */
2094 if (!trapinfo.force_bungle)
2095 You("finish arming %s.",
2096 the(defsyms[trap_to_defsym(what_trap(ttyp))].explanation));
2097 if (((otmp->cursed || Fumbling) && (rnl(10) > 5)) || trapinfo.force_bungle)
2099 (unsigned)(trapinfo.force_bungle ? FORCEBUNGLE : 0));
2101 /* this shouldn't happen */
2102 Your("trap setting attempt fails.");
2116 int rx, ry, proficient, res = 0;
2117 const char *msg_slipsfree = "The bullwhip slips free.";
2118 const char *msg_snap = "Snap!";
2121 if (!wield_tool(obj, "lash")) return 0;
2124 if (!getdir((char *)0)) return res;
2126 if (Stunned || (Confusion && !rn2(5))) confdir();
2129 mtmp = m_at(rx, ry);
2131 /* fake some proficiency checks */
2133 if (Role_if(PM_ARCHEOLOGIST)) ++proficient;
2134 if (ACURR(A_DEX) < 6) proficient--;
2135 else if (ACURR(A_DEX) >= 14) proficient += (ACURR(A_DEX) - 14);
2136 if (Fumbling) --proficient;
2137 if (proficient > 3) proficient = 3;
2138 if (proficient < 0) proficient = 0;
2140 if (u.uswallow && attack(u.ustuck)) {
2141 There("is not enough room to flick your bullwhip.");
2143 } else if (Underwater) {
2144 There("is too much resistance to flick your bullwhip.");
2146 } else if (u.dz < 0) {
2147 You("flick a bug off of the %s.",ceiling(u.ux,u.uy));
2149 } else if ((!u.dx && !u.dy) || (u.dz > 0)) {
2153 /* Sometimes you hit your steed by mistake */
2154 if (u.usteed && !rn2(proficient + 2)) {
2155 You("whip %s!", mon_nam(u.usteed));
2165 /* Have a shot at snaring something on the floor */
2166 otmp = level.objects[u.ux][u.uy];
2167 if (otmp && otmp->otyp == CORPSE && otmp->corpsenm == PM_HORSE) {
2168 pline("Why beat a dead horse?");
2171 if (otmp && proficient) {
2172 You("wrap your bullwhip around %s on the %s.",
2173 an(singular(otmp, xname)), surface(u.ux, u.uy));
2174 if (rnl(6) || pickup_object(otmp, 1L, TRUE) < 1)
2175 pline(msg_slipsfree);
2179 dam = rnd(2) + dbon() + obj->spe;
2180 if (dam <= 0) dam = 1;
2181 You("hit your %s with your bullwhip.", body_part(FOOT));
2182 Sprintf(buf, "killed %sself with %s bullwhip", uhim(), uhis());
2183 losehp(dam, buf, NO_KILLER_PREFIX);
2187 } else if ((Fumbling || Glib) && !rn2(5)) {
2188 pline_The("bullwhip slips out of your %s.", body_part(HAND));
2191 } else if (u.utrap && u.utraptype == TT_PIT) {
2195 * if you're in a pit
2196 * - you are attempting to get out of the pit
2197 * - or, if you are applying it towards a small
2198 * monster then it is assumed that you are
2200 * else if the monster is wielding a weapon
2201 * - you are attempting to disarm a monster
2203 * - you are attempting to hit the monster
2205 * if you're confused (and thus off the mark)
2206 * - you only end up hitting.
2209 const char *wrapped_what = (char *)0;
2212 if (bigmonst(mtmp->data)) {
2213 wrapped_what = strcpy(buf, mon_nam(mtmp));
2214 } else if (proficient) {
2215 if (attack(mtmp)) return 1;
2216 else pline(msg_snap);
2219 if (!wrapped_what) {
2220 if (IS_FURNITURE(levl[rx][ry].typ))
2221 wrapped_what = something;
2222 else if (sobj_at(BOULDER, rx, ry))
2223 wrapped_what = "a boulder";
2228 cc.x = rx; cc.y = ry;
2229 You("wrap your bullwhip around %s.", wrapped_what);
2230 if (proficient && rn2(proficient + 2)) {
2231 if (!mtmp || enexto(&cc, rx, ry, youmonst.data)) {
2232 You("yank yourself out of the pit!");
2233 teleds(cc.x, cc.y, TRUE);
2235 vision_full_recalc = 1;
2238 pline(msg_slipsfree);
2240 if (mtmp) wakeup(mtmp);
2241 } else pline(msg_snap);
2244 if (!canspotmon(mtmp) &&
2245 !glyph_is_invisible(levl[rx][ry].glyph)) {
2246 pline("A monster is there that you couldn't see.");
2247 map_invisible(rx, ry);
2249 otmp = MON_WEP(mtmp); /* can be null */
2251 char onambuf[BUFSZ];
2252 const char *mon_hand;
2253 boolean gotit = proficient && (!Fumbling || !rn2(10));
2255 Strcpy(onambuf, cxname(otmp));
2257 mon_hand = mbodypart(mtmp, HAND);
2258 if (bimanual(otmp)) mon_hand = makeplural(mon_hand);
2260 mon_hand = 0; /* lint suppression */
2262 You("wrap your bullwhip around %s %s.",
2263 s_suffix(mon_nam(mtmp)), onambuf);
2264 if (gotit && otmp->cursed) {
2265 pline("%s welded to %s %s%c",
2266 (otmp->quan == 1L) ? "It is" : "They are",
2267 mhis(mtmp), mon_hand,
2268 !otmp->bknown ? '!' : '.');
2270 gotit = FALSE; /* can't pull it free */
2273 obj_extract_self(otmp);
2274 possibly_unwield(mtmp, FALSE);
2275 setmnotwielded(mtmp,otmp);
2277 switch (rn2(proficient + 1)) {
2279 /* to floor near you */
2280 You("yank %s %s to the %s!", s_suffix(mon_nam(mtmp)),
2281 onambuf, surface(u.ux, u.uy));
2282 place_object(otmp, u.ux, u.uy);
2289 /* proficient with whip, but maybe not
2290 so proficient at catching weapons */
2293 hitvalu = 8 + otmp->spe;
2294 hitu = thitu(hitvalu,
2295 dmgval(otmp, &youmonst),
2298 pline_The("%s hits you as you try to snatch it!",
2301 place_object(otmp, u.ux, u.uy);
2306 /* right into your inventory */
2307 You("snatch %s %s!", s_suffix(mon_nam(mtmp)), onambuf);
2308 if (otmp->otyp == CORPSE &&
2309 touch_petrifies(&mons[otmp->corpsenm]) &&
2310 !uarmg && !Stone_resistance &&
2311 !(poly_when_stoned(youmonst.data) &&
2312 polymon(PM_STONE_GOLEM))) {
2315 Sprintf(kbuf, "%s corpse",
2316 an(mons[otmp->corpsenm].mname));
2317 pline("Snatching %s is a fatal mistake.", kbuf);
2320 otmp = hold_another_object(otmp, "You drop %s!",
2321 doname(otmp), (const char *)0);
2324 /* to floor beneath mon */
2325 You("yank %s from %s %s!", the(onambuf),
2326 s_suffix(mon_nam(mtmp)), mon_hand);
2327 obj_no_longer_held(otmp);
2328 place_object(otmp, mtmp->mx, mtmp->my);
2333 pline(msg_slipsfree);
2337 if (mtmp->m_ap_type &&
2338 !Protection_from_shape_changers && !sensemon(mtmp))
2339 stumble_onto_mimic(mtmp);
2340 else You("flick your bullwhip towards %s.", mon_nam(mtmp));
2342 if (attack(mtmp)) return 1;
2343 else pline(msg_snap);
2347 } else if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)) {
2348 /* it must be air -- water checked above */
2349 You("snap your whip through thin air.");
2360 not_enough_room[] = "There's not enough room here to use that.",
2361 where_to_hit[] = "Where do you want to hit?",
2362 cant_see_spot[] = "won't hit anything if you can't see that spot.",
2363 cant_reach[] = "can't reach that spot from here.";
2365 /* Distance attacks by pole-weapons */
2370 int res = 0, typ, max_range = 4, min_range = 4;
2375 /* Are you allowed to use the pole? */
2377 pline(not_enough_room);
2381 if (!wield_tool(obj, "swing")) return(0);
2384 /* assert(obj == uwep); */
2386 /* Prompt for a location */
2387 pline(where_to_hit);
2390 if (getpos(&cc, TRUE, "the spot to hit") < 0)
2391 return 0; /* user pressed ESC */
2393 /* Calculate range */
2394 typ = uwep_skill_type();
2395 if (typ == P_NONE || P_SKILL(typ) <= P_BASIC) max_range = 4;
2396 else if (P_SKILL(typ) == P_SKILLED) max_range = 5;
2398 if (distu(cc.x, cc.y) > max_range) {
2401 } else if (distu(cc.x, cc.y) < min_range) {
2402 pline("Too close!");
2404 } else if (!cansee(cc.x, cc.y) &&
2405 ((mtmp = m_at(cc.x, cc.y)) == (struct monst *)0 ||
2406 !canseemon(mtmp))) {
2409 } else if (!couldsee(cc.x, cc.y)) { /* Eyes of the Overworld */
2414 /* Attack the monster there */
2415 if ((mtmp = m_at(cc.x, cc.y)) != (struct monst *)0) {
2416 int oldhp = mtmp->mhp;
2419 check_caitiff(mtmp);
2420 (void) thitmonst(mtmp, uwep);
2421 /* check the monster's HP because thitmonst() doesn't return
2422 * an indication of whether it hit. Not perfect (what if it's a
2423 * non-silver weapon on a shade?)
2425 if (mtmp->mhp < oldhp)
2426 u.uconduct.weaphit++;
2428 /* Now you know that nothing is there... */
2429 pline(nothing_happens);
2437 boolean wasblind = Blind;
2438 boolean wascreamed = u.ucreamed;
2439 boolean several = FALSE;
2441 if (obj->quan > 1L) {
2443 obj = splitobj(obj, 1L);
2446 You("give yourself a facial.");
2448 pline("You immerse your %s in %s%s.", body_part(FACE),
2449 several ? "one of " : "",
2450 several ? makeplural(the(xname(obj))) : the(xname(obj)));
2451 if(can_blnd((struct monst*)0, &youmonst, AT_WEAP, obj)) {
2452 int blindinc = rnd(25);
2453 u.ucreamed += blindinc;
2454 make_blinded(Blinded + (long)blindinc, FALSE);
2455 if (!Blind || (Blind && wasblind))
2456 pline("There's %ssticky goop all over your %s.",
2457 wascreamed ? "more " : "",
2459 else /* Blind && !wasblind */
2460 You_cant("see through all the sticky goop on your %s.",
2464 verbalize("You used it, you bought it!");
2465 bill_dummy_object(obj);
2467 obj_extract_self(obj);
2476 int res = 0, typ, max_range = 4, tohit;
2481 /* Are you allowed to use the hook? */
2483 pline(not_enough_room);
2487 if (!wield_tool(obj, "cast")) return(0);
2490 /* assert(obj == uwep); */
2492 /* Prompt for a location */
2493 pline(where_to_hit);
2496 if (getpos(&cc, TRUE, "the spot to hit") < 0)
2497 return 0; /* user pressed ESC */
2499 /* Calculate range */
2500 typ = uwep_skill_type();
2501 if (typ == P_NONE || P_SKILL(typ) <= P_BASIC) max_range = 4;
2502 else if (P_SKILL(typ) == P_SKILLED) max_range = 5;
2504 if (distu(cc.x, cc.y) > max_range) {
2507 } else if (!cansee(cc.x, cc.y)) {
2510 } else if (!couldsee(cc.x, cc.y)) { /* Eyes of the Overworld */
2515 /* What do you want to hit? */
2517 if (typ != P_NONE && P_SKILL(typ) >= P_SKILLED) {
2518 winid tmpwin = create_nhwindow(NHW_MENU);
2521 menu_item *selected;
2523 any.a_void = 0; /* set all bits to zero */
2524 any.a_int = 1; /* use index+1 (cant use 0) as identifier */
2527 Sprintf(buf, "an object on the %s", surface(cc.x, cc.y));
2528 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
2529 buf, MENU_UNSELECTED);
2531 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
2532 "a monster", MENU_UNSELECTED);
2534 Sprintf(buf, "the %s", surface(cc.x, cc.y));
2535 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
2536 buf, MENU_UNSELECTED);
2537 end_menu(tmpwin, "Aim for what?");
2539 if (select_menu(tmpwin, PICK_ONE, &selected) > 0 &&
2540 rn2(P_SKILL(typ) > P_SKILLED ? 20 : 2))
2541 tohit = selected[0].item.a_int - 1;
2542 free((genericptr_t)selected);
2543 destroy_nhwindow(tmpwin);
2546 /* What did you hit? */
2549 /* FIXME -- untrap needs to deal with non-adjacent traps */
2551 case 1: /* Object */
2552 if ((otmp = level.objects[cc.x][cc.y]) != 0) {
2553 You("snag an object from the %s!", surface(cc.x, cc.y));
2554 (void) pickup_object(otmp, 1L, FALSE);
2555 /* If pickup fails, leave it alone */
2560 case 2: /* Monster */
2561 if ((mtmp = m_at(cc.x, cc.y)) == (struct monst *)0) break;
2562 if (verysmall(mtmp->data) && !rn2(4) &&
2563 enexto(&cc, u.ux, u.uy, (struct permonst *)0)) {
2564 You("pull in %s!", mon_nam(mtmp));
2565 mtmp->mundetected = 0;
2566 rloc_to(mtmp, cc.x, cc.y);
2568 } else if ((!bigmonst(mtmp->data) && !strongmonst(mtmp->data)) ||
2570 (void) thitmonst(mtmp, uwep);
2574 case 3: /* Surface */
2575 if (IS_AIR(levl[cc.x][cc.y].typ) || is_pool(cc.x, cc.y))
2576 pline_The("hook slices through the %s.", surface(cc.x, cc.y));
2578 You("are yanked toward the %s!", surface(cc.x, cc.y));
2579 hurtle(sgn(cc.x-u.ux), sgn(cc.y-u.uy), 1, FALSE);
2583 default: /* Yourself (oops!) */
2584 if (P_SKILL(typ) <= P_BASIC) {
2585 You("hook yourself!");
2586 losehp(rn1(10,10), "a grappling hook", KILLED_BY);
2591 pline(nothing_happens);
2596 #define BY_OBJECT ((struct monst *)0)
2598 /* return 1 if the wand is broken, hence some time elapsed */
2603 static const char nothing_else_happens[] = "But nothing else happens...";
2604 register int i, x, y;
2605 register struct monst *mon;
2607 boolean affects_objects;
2608 boolean shop_damage = FALSE;
2609 int expltype = EXPL_MAGICAL;
2610 char confirm[QBUFSZ], the_wand[BUFSZ], buf[BUFSZ];
2612 Strcpy(the_wand, yname(obj));
2613 Sprintf(confirm, "Are you really sure you want to break %s?",
2614 safe_qbuf("", sizeof("Are you really sure you want to break ?"),
2615 the_wand, ysimple_name(obj), "the wand"));
2616 if (yn(confirm) == 'n' ) return 0;
2618 if (nohands(youmonst.data)) {
2619 You_cant("break %s without hands!", the_wand);
2621 } else if (ACURR(A_STR) < 10) {
2622 You("don't have the strength to break %s!", the_wand);
2625 pline("Raising %s high above your %s, you break it in two!",
2626 the_wand, body_part(HEAD));
2628 /* [ALI] Do this first so that wand is removed from bill. Otherwise,
2629 * the freeinv() below also hides it from setpaid() which causes problems.
2632 check_unpaid(obj); /* Extra charge for use */
2633 bill_dummy_object(obj);
2636 current_wand = obj; /* destroy_item might reset this */
2637 freeinv(obj); /* hide it from destroy_item instead... */
2638 setnotworn(obj); /* so we need to do this ourselves */
2640 if (obj->spe <= 0) {
2641 pline(nothing_else_happens);
2642 goto discard_broken_wand;
2647 affects_objects = FALSE;
2649 switch (obj->otyp) {
2654 case WAN_ENLIGHTENMENT:
2656 case WAN_SECRET_DOOR_DETECTION:
2657 pline(nothing_else_happens);
2658 goto discard_broken_wand;
2664 expltype = EXPL_FIERY;
2666 if (expltype == EXPL_MAGICAL) expltype = EXPL_FROSTY;
2668 case WAN_MAGIC_MISSILE:
2671 (obj->otyp - WAN_MAGIC_MISSILE), dmg, WAND_CLASS, expltype);
2672 makeknown(obj->otyp); /* explode described the effect */
2673 goto discard_broken_wand;
2675 /* we want this before the explosion instead of at the very end */
2676 pline("A wall of force smashes down around you!");
2677 dmg = d(1 + obj->spe,6); /* normally 2d12 */
2678 case WAN_CANCELLATION:
2680 case WAN_TELEPORTATION:
2681 case WAN_UNDEAD_TURNING:
2682 affects_objects = TRUE;
2688 /* magical explosion and its visual effect occur before specific effects */
2689 explode(obj->ox, obj->oy, 0, rnd(dmg), WAND_CLASS, EXPL_MAGICAL);
2691 /* this makes it hit us last, so that we can see the action first */
2692 for (i = 0; i <= 8; i++) {
2693 bhitpos.x = x = obj->ox + xdir[i];
2694 bhitpos.y = y = obj->oy + ydir[i];
2695 if (!isok(x,y)) continue;
2697 if (obj->otyp == WAN_DIGGING) {
2698 if(dig_check(BY_OBJECT, FALSE, x, y)) {
2699 if (IS_WALL(levl[x][y].typ) || IS_DOOR(levl[x][y].typ)) {
2700 /* normally, pits and holes don't anger guards, but they
2701 * do if it's a wall or door that's being dug */
2702 watch_dig((struct monst *)0, x, y, TRUE);
2703 if (*in_rooms(x,y,SHOPBASE)) shop_damage = TRUE;
2705 digactualhole(x, y, BY_OBJECT,
2706 (rn2(obj->spe) < 3 || !Can_dig_down(&u.uz)) ?
2710 } else if(obj->otyp == WAN_CREATE_MONSTER) {
2711 /* u.ux,u.uy creates it near you--x,y might create it in rock */
2712 (void) makemon((struct permonst *)0, u.ux, u.uy, NO_MM_FLAGS);
2715 if (x == u.ux && y == u.uy) {
2716 /* teleport objects first to avoid race with tele control and
2717 autopickup. Other wand/object effects handled after
2718 possible wand damage is assessed */
2719 if (obj->otyp == WAN_TELEPORTATION &&
2720 affects_objects && level.objects[x][y]) {
2721 (void) bhitpile(obj, bhito, x, y);
2722 if (flags.botl) bot(); /* potion effects */
2724 damage = zapyourself(obj, FALSE);
2726 Sprintf(buf, "killed %sself by breaking a wand", uhim());
2727 losehp(damage, buf, NO_KILLER_PREFIX);
2729 if (flags.botl) bot(); /* blindness */
2730 } else if ((mon = m_at(x, y)) != 0) {
2731 (void) bhitm(mon, obj);
2732 /* if (flags.botl) bot(); */
2734 if (affects_objects && level.objects[x][y]) {
2735 (void) bhitpile(obj, bhito, x, y);
2736 if (flags.botl) bot(); /* potion effects */
2741 /* Note: if player fell thru, this call is a no-op.
2742 Damage is handled in digactualhole in that case */
2743 if (shop_damage) pay_for_damage("dig into", FALSE);
2745 if (obj->otyp == WAN_LIGHT)
2746 litroom(TRUE, obj); /* only needs to be done once */
2748 discard_broken_wand:
2749 obj = current_wand; /* [see dozap() and destroy_item()] */
2760 register struct obj *otmp;
2762 for(otmp = invent; otmp; otmp = otmp->nobj)
2763 if(is_graystone(otmp))
2769 add_class(cl, class)
2783 register int res = 1;
2784 char class_list[MAXOCLASSES+2];
2786 if(check_capacity((char *)0)) return (0);
2788 if (carrying(POT_OIL) || uhave_graystone())
2789 Strcpy(class_list, tools_too);
2791 Strcpy(class_list, tools);
2792 if (carrying(CREAM_PIE) || carrying(EUCALYPTUS_LEAF))
2793 add_class(class_list, FOOD_CLASS);
2795 obj = getobj(class_list, "use or apply");
2798 if (obj->oartifact && !touch_artifact(obj, &youmonst))
2799 return 1; /* evading your grasp costs a turn; just be
2800 grateful that you don't drop it as well */
2802 if (obj->oclass == WAND_CLASS)
2803 return do_break_wand(obj);
2808 if (obj == ublindf) {
2809 if (!cursed(obj)) Blindf_off(obj);
2810 } else if (!ublindf)
2812 else You("are already %s.",
2813 ublindf->otyp == TOWEL ? "covered by a towel" :
2814 ublindf->otyp == BLINDFOLD ? "wearing a blindfold" :
2818 res = use_cream_pie(obj);
2821 res = use_whip(obj);
2823 case GRAPPLING_HOOK:
2824 res = use_grapple(obj);
2830 case BAG_OF_HOLDING:
2832 res = use_container(obj, 1);
2845 (void) pick_lock(obj);
2848 case DWARVISH_MATTOCK:
2849 res = use_pick_axe(obj);
2852 use_tinning_kit(obj);
2859 res = use_saddle(obj);
2863 use_magic_whistle(obj);
2868 case EUCALYPTUS_LEAF:
2869 /* MRKR: Every Australian knows that a gum leaf makes an */
2870 /* excellent whistle, especially if your pet is a */
2871 /* tame kangaroo named Skippy. */
2873 use_magic_whistle(obj);
2874 /* sometimes the blessing will be worn off */
2879 pline("%s %s %s.", Shk_Your(buf, obj),
2880 aobjnam(obj, "glow"), hcolor("brown"));
2890 res = use_stethoscope(obj);
2893 res = use_mirror(obj);
2896 case BELL_OF_OPENING:
2899 case CANDELABRUM_OF_INVOCATION:
2900 use_candelabrum(obj);
2912 light_cocktail(obj);
2915 case EXPENSIVE_CAMERA:
2916 res = use_camera(obj);
2920 res = use_towel(obj);
2923 use_crystal_ball(obj);
2929 if(!carrying(TIN)) {
2930 You("have no tin to open.");
2933 You("cannot open a tin without eating or discarding its contents.");
2935 pline("In order to eat, use the 'e' command.");
2937 pline("Opening the tin will be much easier if you wield the tin opener.");
2944 use_unicorn_horn(obj);
2955 case DRUM_OF_EARTHQUAKE:
2956 res = do_play_instrument(obj);
2958 case HORN_OF_PLENTY: /* not a musical instrument */
2963 consume_obj_charge(obj, TRUE);
2965 otmp = mkobj(POTION_CLASS, FALSE);
2966 if (objects[otmp->otyp].oc_magic) do {
2967 otmp->otyp = rnd_class(POT_BOOZE, POT_WATER);
2968 } while (otmp->otyp == POT_SICKNESS);
2971 otmp = mkobj(FOOD_CLASS, FALSE);
2972 if (otmp->otyp == FOOD_RATION && !rn2(7))
2973 otmp->otyp = LUMP_OF_ROYAL_JELLY;
2976 pline("%s spills out.", what);
2977 otmp->blessed = obj->blessed;
2978 otmp->cursed = obj->cursed;
2979 otmp->owt = weight(otmp);
2980 otmp = hold_another_object(otmp, u.uswallow ?
2981 "Oops! %s out of your reach!" :
2982 (Is_airlevel(&u.uz) ||
2983 Is_waterlevel(&u.uz) ||
2984 levl[u.ux][u.uy].typ < IRONBARS ||
2985 levl[u.ux][u.uy].typ >= ICE) ?
2986 "Oops! %s away from you!" :
2987 "Oops! %s to the floor!",
2988 The(aobjnam(otmp, "slip")),
2990 makeknown(HORN_OF_PLENTY);
2992 pline(nothing_happens);
3005 /* Pole-weapons can strike at a distance */
3007 res = use_pole(obj);
3009 } else if (is_pick(obj) || is_axe(obj)) {
3010 res = use_pick_axe(obj);
3013 pline("Sorry, I don't know how to use that.");
3018 if (res && obj && obj->oartifact) arti_speak(obj);
3023 /* Keep track of unfixable troubles for purposes of messages saying you feel
3027 unfixable_trouble_count(is_horn)
3030 int unfixable_trbl = 0;
3032 if (Stoned) unfixable_trbl++;
3033 if (Strangled) unfixable_trbl++;
3039 if (Slimed) unfixable_trbl++;
3040 /* lycanthropy is not desirable, but it doesn't actually make you feel
3043 /* we'll assume that intrinsic stunning from being a bat/stalker
3044 doesn't make you feel bad */
3046 if (Confusion) unfixable_trbl++;
3047 if (Sick) unfixable_trbl++;
3048 if (HHallucination) unfixable_trbl++;
3049 if (Vomiting) unfixable_trbl++;
3050 if (HStun) unfixable_trbl++;
3052 return unfixable_trbl;