1 /* NetHack 3.6 apply.c $NHDT-Date: 1457397477 2016/03/08 00:37:57 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.224 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
7 extern boolean notonhead
; /* for long worms */
9 STATIC_DCL
int FDECL(use_camera
, (struct obj
*));
10 STATIC_DCL
int FDECL(use_towel
, (struct obj
*));
11 STATIC_DCL boolean
FDECL(its_dead
, (int, int, int *));
12 STATIC_DCL
int FDECL(use_stethoscope
, (struct obj
*));
13 STATIC_DCL
void FDECL(use_whistle
, (struct obj
*));
14 STATIC_DCL
void FDECL(use_magic_whistle
, (struct obj
*));
15 STATIC_DCL
void FDECL(use_leash
, (struct obj
*));
16 STATIC_DCL
int FDECL(use_mirror
, (struct obj
*));
17 STATIC_DCL
void FDECL(use_bell
, (struct obj
**));
18 STATIC_DCL
void FDECL(use_candelabrum
, (struct obj
*));
19 STATIC_DCL
void FDECL(use_candle
, (struct obj
**));
20 STATIC_DCL
void FDECL(use_lamp
, (struct obj
*));
21 STATIC_DCL
void FDECL(light_cocktail
, (struct obj
*));
22 STATIC_PTR
void FDECL(display_jump_positions
, (int));
23 STATIC_DCL
void FDECL(use_tinning_kit
, (struct obj
*));
24 STATIC_DCL
void FDECL(use_figurine
, (struct obj
**));
25 STATIC_DCL
void FDECL(use_grease
, (struct obj
*));
26 STATIC_DCL
void FDECL(use_trap
, (struct obj
*));
27 STATIC_DCL
void FDECL(use_stone
, (struct obj
*));
28 STATIC_PTR
int NDECL(set_trap
); /* occupation callback */
29 STATIC_DCL
int FDECL(use_whip
, (struct obj
*));
30 STATIC_PTR
void FDECL(display_polearm_positions
, (int));
31 STATIC_DCL
int FDECL(use_pole
, (struct obj
*));
32 STATIC_DCL
int FDECL(use_cream_pie
, (struct obj
*));
33 STATIC_DCL
int FDECL(use_grapple
, (struct obj
*));
34 STATIC_DCL
int FDECL(do_break_wand
, (struct obj
*));
35 STATIC_DCL boolean
FDECL(figurine_location_checks
, (struct obj
*,
37 STATIC_DCL
void FDECL(add_class
, (char *, CHAR_P
));
38 STATIC_DCL
void FDECL(setapplyclasses
, (char *));
39 STATIC_DCL boolean
FDECL(is_valid_jump_pos
, (int, int, int, BOOLEAN_P
));
40 STATIC_DCL boolean
FDECL(find_poleable_mon
, (coord
*, int, int));
43 void FDECL(amii_speaker
, (struct obj
*, char *, int));
46 static const char no_elbow_room
[] =
47 "don't have enough elbow-room to maneuver.";
56 pline("Using your camera underwater would void the warranty.");
59 if (!getdir((char *) 0))
63 pline1(nothing_happens
);
66 consume_obj_charge(obj
, TRUE
);
68 if (obj
->cursed
&& !rn2(2)) {
69 (void) zapyourself(obj
, TRUE
);
70 } else if (u
.uswallow
) {
71 You("take a picture of %s %s.", s_suffix(mon_nam(u
.ustuck
)),
72 mbodypart(u
.ustuck
, STOMACH
));
74 You("take a picture of the %s.",
75 (u
.dz
> 0) ? surface(u
.ux
, u
.uy
) : ceiling(u
.ux
, u
.uy
));
76 } else if (!u
.dx
&& !u
.dy
) {
77 (void) zapyourself(obj
, TRUE
);
78 } else if ((mtmp
= bhit(u
.dx
, u
.dy
, COLNO
, FLASHED_LIGHT
,
79 (int FDECL((*), (MONST_P
, OBJ_P
))) 0,
80 (int FDECL((*), (OBJ_P
, OBJ_P
))) 0, &obj
)) != 0) {
81 obj
->ox
= u
.ux
, obj
->oy
= u
.uy
;
82 (void) flash_hits_mon(mtmp
, obj
);
91 boolean drying_feedback
= (obj
== uwep
);
94 You("have no free %s!", body_part(HAND
));
96 } else if (obj
== ublindf
) {
97 You("cannot use it while you're wearing it!");
99 } else if (obj
->cursed
) {
105 incr_itimeout(&Glib
, rn1(10, 3));
106 Your("%s %s!", makeplural(body_part(HAND
)),
107 (old
? "are filthier than ever" : "get slimy"));
108 if (is_wet_towel(obj
))
109 dry_a_towel(obj
, -1, drying_feedback
);
114 u
.ucreamed
+= rn1(10, 3);
115 pline("Yecch! Your %s %s gunk on it!", body_part(FACE
),
116 (old
? "has more" : "now has"));
117 make_blinded(Blinded
+ (long) u
.ucreamed
- old
, TRUE
);
121 what
= (ublindf
->otyp
== LENSES
)
123 : (obj
->otyp
== ublindf
->otyp
) ? "other towel"
125 if (ublindf
->cursed
) {
126 You("push your %s %s.", what
,
127 rn2(2) ? "cock-eyed" : "crooked");
129 struct obj
*saved_ublindf
= ublindf
;
130 You("push your %s off.", what
);
132 dropx(saved_ublindf
);
135 if (is_wet_towel(obj
))
136 dry_a_towel(obj
, -1, drying_feedback
);
145 You("wipe off your %s.", makeplural(body_part(HAND
)));
146 if (is_wet_towel(obj
))
147 dry_a_towel(obj
, -1, drying_feedback
);
149 } else if (u
.ucreamed
) {
150 Blinded
-= u
.ucreamed
;
153 pline("You've got the glop off.");
154 if (!gulp_blnd_check()) {
156 make_blinded(0L, TRUE
);
159 Your("%s feels clean now.", body_part(FACE
));
161 if (is_wet_towel(obj
))
162 dry_a_towel(obj
, -1, drying_feedback
);
166 Your("%s and %s are already clean.", body_part(FACE
),
167 makeplural(body_part(HAND
)));
172 /* maybe give a stethoscope message based on floor objects */
174 its_dead(rx
, ry
, resp
)
178 boolean more_corpses
;
179 struct permonst
*mptr
;
180 struct obj
*corpse
= sobj_at(CORPSE
, rx
, ry
),
181 *statue
= sobj_at(STATUE
, rx
, ry
);
183 if (!can_reach_floor(TRUE
)) { /* levitation or unskilled riding */
184 corpse
= 0; /* can't reach corpse on floor */
185 /* you can't reach tiny statues (even though you can fight
186 tiny monsters while levitating--consistency, what's that?) */
187 while (statue
&& mons
[statue
->corpsenm
].msize
== MZ_TINY
)
188 statue
= nxtobj(statue
, STATUE
, TRUE
);
190 /* when both corpse and statue are present, pick the uppermost one */
191 if (corpse
&& statue
) {
192 if (nxtobj(statue
, CORPSE
, TRUE
) == corpse
)
193 corpse
= 0; /* corpse follows statue; ignore it */
195 statue
= 0; /* corpse precedes statue; ignore statue */
197 more_corpses
= (corpse
&& nxtobj(corpse
, CORPSE
, TRUE
));
199 /* additional stethoscope messages from jyoung@apanix.apana.org.au */
200 if (!corpse
&& !statue
) {
201 ; /* nothing to do */
203 } else if (Hallucination
) {
206 Strcpy(buf
, "You're both stoned");
207 } else if (corpse
->quan
== 1L && !more_corpses
) {
208 int gndr
= 2; /* neuter: "it" */
209 struct monst
*mtmp
= get_mtraits(corpse
, FALSE
);
211 /* (most corpses don't retain the monster's sex, so
212 we're usually forced to use generic pronoun here) */
214 mptr
= &mons
[mtmp
->mnum
];
215 /* can't use mhe() here; it calls pronoun_gender() which
216 expects monster to be on the map (visibility check) */
217 if ((humanoid(mptr
) || (mptr
->geno
& G_UNIQ
)
218 || type_is_pname(mptr
)) && !is_neuter(mptr
))
219 gndr
= (int) mtmp
->female
;
221 mptr
= &mons
[corpse
->corpsenm
];
224 else if (is_male(mptr
))
227 Sprintf(buf
, "%s's dead", genders
[gndr
].he
); /* "he"/"she"/"it" */
228 buf
[0] = highc(buf
[0]);
229 } else { /* plural */
230 Strcpy(buf
, "They're dead");
232 /* variations on "He's dead, Jim." (Star Trek's Dr McCoy) */
233 You_hear("a voice say, \"%s, Jim.\"", buf
);
238 boolean here
= (rx
== u
.ux
&& ry
== u
.uy
),
239 one
= (corpse
->quan
== 1L && !more_corpses
), reviver
= FALSE
;
240 int visglyph
, corpseglyph
;
242 visglyph
= glyph_at(rx
, ry
);
243 corpseglyph
= obj_to_glyph(corpse
);
245 if (Blind
&& (visglyph
!= corpseglyph
))
246 map_object(corpse
, TRUE
);
248 if (Role_if(PM_HEALER
)) {
249 /* ok to reset `corpse' here; we're done with it */
251 if (obj_has_timer(corpse
, REVIVE_MON
))
254 corpse
= nxtobj(corpse
, CORPSE
, TRUE
);
255 } while (corpse
&& !reviver
);
257 You("determine that %s unfortunate being%s %s%s dead.",
258 one
? (here
? "this" : "that") : (here
? "these" : "those"),
259 one
? "" : "s", one
? "is" : "are", reviver
? " mostly" : "");
262 } else { /* statue */
263 const char *what
, *how
;
265 mptr
= &mons
[statue
->corpsenm
];
266 if (Blind
) { /* ignore statue->dknown; it'll always be set */
267 Sprintf(buf
, "%s %s",
268 (rx
== u
.ux
&& ry
== u
.uy
) ? "This" : "That",
269 humanoid(mptr
) ? "person" : "creature");
273 if (!type_is_pname(mptr
))
277 if (Role_if(PM_HEALER
)) {
278 struct trap
*ttmp
= t_at(rx
, ry
);
280 if (ttmp
&& ttmp
->ttyp
== STATUE_TRAP
)
281 how
= "extraordinary";
282 else if (Has_contents(statue
))
286 pline("%s is in %s health for a statue.", what
, how
);
289 return FALSE
; /* no corpse or statue */
292 static const char hollow_str
[] = "a hollow sound. This must be a secret %s!";
294 /* Strictly speaking it makes no sense for usage of a stethoscope to
295 not take any time; however, unless it did, the stethoscope would be
296 almost useless. As a compromise, one use per turn is free, another
297 uses up the turn; this makes curse status have a tangible effect. */
300 register struct obj
*obj
;
305 boolean interference
= (u
.uswallow
&& is_whirly(u
.ustuck
->data
)
306 && !rn2(Role_if(PM_HEALER
) ? 10 : 3));
308 if (nohands(youmonst
.data
)) {
309 You("have no hands!"); /* not `body_part(HAND)' */
312 You_cant("hear anything!");
314 } else if (!freehand()) {
315 You("have no free %s.", body_part(HAND
));
318 if (!getdir((char *) 0))
321 res
= (moves
== context
.stethoscope_move
)
322 && (youmonst
.movement
== context
.stethoscope_movement
);
323 context
.stethoscope_move
= moves
;
324 context
.stethoscope_movement
= youmonst
.movement
;
326 bhitpos
.x
= u
.ux
, bhitpos
.y
= u
.uy
; /* tentative, reset below */
327 notonhead
= u
.uswallow
;
328 if (u
.usteed
&& u
.dz
> 0) {
330 pline("%s interferes.", Monnam(u
.ustuck
));
331 mstatusline(u
.ustuck
);
333 mstatusline(u
.usteed
);
335 } else if (u
.uswallow
&& (u
.dx
|| u
.dy
|| u
.dz
)) {
336 mstatusline(u
.ustuck
);
338 } else if (u
.uswallow
&& interference
) {
339 pline("%s interferes.", Monnam(u
.ustuck
));
340 mstatusline(u
.ustuck
);
344 You_hear("faint splashing.");
345 else if (u
.dz
< 0 || !can_reach_floor(TRUE
))
346 cant_reach_floor(u
.ux
, u
.uy
, (u
.dz
< 0), TRUE
);
347 else if (its_dead(u
.ux
, u
.uy
, &res
))
348 ; /* message already given */
349 else if (Is_stronghold(&u
.uz
))
350 You_hear("the crackling of hellfire.");
352 pline_The("%s seems healthy enough.", surface(u
.ux
, u
.uy
));
354 } else if (obj
->cursed
&& !rn2(2)) {
355 You_hear("your heart beat.");
358 if (Stunned
|| (Confusion
&& !rn2(5)))
360 if (!u
.dx
&& !u
.dy
) {
367 You_hear("a faint typing noise.");
370 if ((mtmp
= m_at(rx
, ry
)) != 0) {
371 const char *mnm
= x_monnam(mtmp
, ARTICLE_A
, (const char *) 0,
372 SUPPRESS_IT
| SUPPRESS_INVISIBLE
, FALSE
);
374 /* bhitpos needed by mstatusline() iff mtmp is a long worm */
375 bhitpos
.x
= rx
, bhitpos
.y
= ry
;
376 notonhead
= (mtmp
->mx
!= rx
|| mtmp
->my
!= ry
);
378 if (mtmp
->mundetected
) {
379 if (!canspotmon(mtmp
))
380 There("is %s hidden there.", mnm
);
381 mtmp
->mundetected
= 0;
382 newsym(mtmp
->mx
, mtmp
->my
);
383 } else if (mtmp
->mappearance
) {
384 const char *what
= "thing";
386 switch (mtmp
->m_ap_type
) {
388 what
= simple_typename(mtmp
->mappearance
);
390 case M_AP_MONSTER
: /* ignore Hallucination here */
391 what
= mons
[mtmp
->mappearance
].mname
;
394 what
= defsyms
[mtmp
->mappearance
].explanation
;
398 pline("That %s is really %s.", what
, mnm
);
399 } else if (flags
.verbose
&& !canspotmon(mtmp
)) {
400 There("is %s there.", mnm
);
404 if (!canspotmon(mtmp
))
405 map_invisible(rx
, ry
);
408 if (glyph_is_invisible(levl
[rx
][ry
].glyph
)) {
409 unmap_object(rx
, ry
);
411 pline_The("invisible monster must have moved.");
417 You_hear(hollow_str
, "door");
418 cvt_sdoor_to_door(lev
); /* ->typ = DOOR */
422 You_hear(hollow_str
, "passage");
424 unblock_point(rx
, ry
);
429 if (!its_dead(rx
, ry
, &res
))
430 You("hear nothing special."); /* not You_hear() */
434 static const char whistle_str
[] = "produce a %s whistling sound.";
440 if (!can_blow(&youmonst
)) {
441 You("are incapable of using the whistle.");
442 } else if (Underwater
) {
443 You("blow bubbles through %s.", yname(obj
));
445 You(whistle_str
, obj
->cursed
? "shrill" : "high");
451 use_magic_whistle(obj
)
454 register struct monst
*mtmp
, *nextmon
;
456 if (!can_blow(&youmonst
)) {
457 You("are incapable of using the whistle.");
458 } else if (obj
->cursed
&& !rn2(2)) {
459 You("produce a %shigh-pitched humming noise.",
460 Underwater
? "very " : "");
463 int pet_cnt
= 0, omx
, omy
;
465 /* it's magic! it works underwater too (at a higher pitch) */
467 Hallucination
? "normal" : Underwater
? "strange, high-pitched"
469 for (mtmp
= fmon
; mtmp
; mtmp
= nextmon
) {
470 nextmon
= mtmp
->nmon
; /* trap might kill mon */
471 if (DEADMONSTER(mtmp
))
473 /* steed is already at your location, so not affected;
474 this avoids trap issues if you're on a trap location */
475 if (mtmp
== u
.usteed
)
478 if (mtmp
->mtrapped
) {
479 /* no longer in previous trap (affects mintrap) */
481 fill_pit(mtmp
->mx
, mtmp
->my
);
483 /* mimic must be revealed before we know whether it
484 actually moves because line-of-sight may change */
487 omx
= mtmp
->mx
, omy
= mtmp
->my
;
489 if (mtmp
->mx
!= omx
|| mtmp
->my
!= omy
) {
490 mtmp
->mundetected
= 0; /* reveal non-mimic hider */
491 if (canspotmon(mtmp
))
493 if (mintrap(mtmp
) == 2)
499 makeknown(obj
->otyp
);
507 return (boolean
) (abs(u
.ux
- x
) > n
|| abs(u
.uy
- y
) > n
);
516 for (obj
= invent
; obj
; obj
= obj
->nobj
)
517 if (obj
->otyp
== LEASH
&& obj
->leashmon
!= 0)
522 /* otmp is about to be destroyed or stolen */
525 register struct obj
*otmp
;
527 register struct monst
*mtmp
;
529 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
)
530 if (mtmp
->m_id
== (unsigned) otmp
->leashmon
)
535 /* mtmp is about to die, or become untame */
537 m_unleash(mtmp
, feedback
)
538 register struct monst
*mtmp
;
541 register struct obj
*otmp
;
545 pline("%s pulls free of %s leash!", Monnam(mtmp
), mhis(mtmp
));
547 Your("leash falls slack.");
549 for (otmp
= invent
; otmp
; otmp
= otmp
->nobj
)
550 if (otmp
->otyp
== LEASH
&& otmp
->leashmon
== (int) mtmp
->m_id
)
555 /* player is about to die (for bones) */
559 register struct obj
*otmp
;
560 register struct monst
*mtmp
;
562 for (otmp
= invent
; otmp
; otmp
= otmp
->nobj
)
563 if (otmp
->otyp
== LEASH
)
565 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
)
575 return (boolean
) (mtmp
->mnum
!= PM_LONG_WORM
);
584 register struct monst
*mtmp
;
587 if (!obj
->leashmon
&& number_leashed() >= MAXLEASHED
) {
588 You("cannot leash any more pets.");
592 if (!get_adjacent_loc((char *) 0, (char *) 0, u
.ux
, u
.uy
, &cc
))
595 if ((cc
.x
== u
.ux
) && (cc
.y
== u
.uy
)) {
596 if (u
.usteed
&& u
.dz
> 0) {
601 pline("Leash yourself? Very funny...");
605 if (!(mtmp
= m_at(cc
.x
, cc
.y
))) {
606 There("is no creature there.");
610 spotmon
= canspotmon(mtmp
);
615 There("is no creature there.");
617 pline("%s %s leashed!", Monnam(mtmp
),
618 (!obj
->leashmon
) ? "cannot be" : "is not");
621 if (!obj
->leashmon
) {
622 if (mtmp
->mleashed
) {
623 pline("This %s is already leashed.",
624 spotmon
? l_monnam(mtmp
) : "monster");
627 if (!leashable(mtmp
)) {
628 pline("The leash won't fit onto %s%s.", spotmon
? "your " : "",
633 You("slip the leash around %s%s.", spotmon
? "your " : "",
636 obj
->leashmon
= (int) mtmp
->m_id
;
640 if (obj
->leashmon
!= (int) mtmp
->m_id
) {
641 pline("This leash is not attached to that creature.");
645 pline_The("leash would not come off!");
651 You("remove the leash from %s%s.", spotmon
? "your " : "",
657 /* assuming mtmp->mleashed has been checked */
666 if (otmp
->otyp
== LEASH
&& otmp
->leashmon
== (int) mtmp
->m_id
)
670 return (struct obj
*) 0;
676 register struct monst
*mtmp
;
677 register struct obj
*otmp
;
679 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
) {
680 if (DEADMONSTER(mtmp
))
682 if (mtmp
->mleashed
) {
683 if (distu(mtmp
->mx
, mtmp
->my
) > 2)
685 if (distu(mtmp
->mx
, mtmp
->my
) > 2) {
686 for (otmp
= invent
; otmp
; otmp
= otmp
->nobj
)
687 if (otmp
->otyp
== LEASH
688 && otmp
->leashmon
== (int) mtmp
->m_id
) {
691 You_feel("%s leash go slack.",
692 (number_leashed() > 1) ? "a" : "the");
699 /* no pack mules for the Amulet */
700 if (u
.usteed
&& mon_has_amulet(u
.usteed
))
709 register struct obj
*otmp
;
710 register struct monst
*mtmp
;
712 for (otmp
= invent
; otmp
; otmp
= otmp
->nobj
) {
713 if (otmp
->otyp
!= LEASH
|| otmp
->leashmon
== 0)
715 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
) {
716 if (DEADMONSTER(mtmp
))
718 if ((int) mtmp
->m_id
== otmp
->leashmon
)
722 impossible("leash in use isn't attached to anything?");
726 if (dist2(u
.ux
, u
.uy
, mtmp
->mx
, mtmp
->my
)
727 > dist2(x
, y
, mtmp
->mx
, mtmp
->my
)) {
728 if (!um_dist(mtmp
->mx
, mtmp
->my
, 3)) {
729 ; /* still close enough */
730 } else if (otmp
->cursed
&& !breathless(mtmp
->data
)) {
731 if (um_dist(mtmp
->mx
, mtmp
->my
, 5)
732 || (mtmp
->mhp
-= rnd(2)) <= 0) {
733 long save_pacifism
= u
.uconduct
.killer
;
735 Your("leash chokes %s to death!", mon_nam(mtmp
));
736 /* hero might not have intended to kill pet, but
737 that's the result of his actions; gain experience,
738 lose pacifism, take alignment and luck hit, make
739 corpse less likely to remain tame after revival */
740 xkilled(mtmp
, XKILL_NOMSG
);
741 /* life-saving doesn't ordinarily reset this */
743 u
.uconduct
.killer
= save_pacifism
;
745 pline("%s is choked by the leash!", Monnam(mtmp
));
746 /* tameness eventually drops to 1 here (never 0) */
747 if (mtmp
->mtame
&& rn2(mtmp
->mtame
))
751 if (um_dist(mtmp
->mx
, mtmp
->my
, 5)) {
752 pline("%s leash snaps loose!", s_suffix(Monnam(mtmp
)));
753 m_unleash(mtmp
, FALSE
);
755 You("pull on the leash.");
756 if (mtmp
->data
->msound
!= MS_SILENT
)
777 return ((ACURR(A_CHA
) > 14)
778 ? ((poly_gender() == 1)
784 static const char look_str
[] = "look %s.";
790 const char *mirror
, *uvisage
;
794 boolean vis
, invis_mirror
, useeit
, monable
;
796 if (!getdir((char *) 0))
798 invis_mirror
= Invis
;
799 useeit
= !Blind
&& (!invis_mirror
|| See_invisible
);
800 uvisage
= beautiful();
801 mirror
= simpleonames(obj
); /* "mirror" or "looking glass" */
802 if (obj
->cursed
&& !rn2(2)) {
804 pline_The("%s fogs up and doesn't reflect!", mirror
);
807 if (!u
.dx
&& !u
.dy
&& !u
.dz
) {
809 You_cant("see your %s %s.", uvisage
, body_part(FACE
));
811 if (u
.umonnum
== PM_FLOATING_EYE
) {
813 You("stiffen momentarily under your gaze.");
816 pline("Yow! The %s stares back!", mirror
);
818 pline("Yikes! You've frozen yourself!");
819 if (!Hallucination
|| !rn2(4)) {
820 nomul(-rnd(MAXULEV
+ 6 - u
.ulevel
));
821 multi_reason
= "gazing into a mirror";
823 nomovemsg
= 0; /* default, "you can move again" */
825 } else if (youmonst
.data
->mlet
== S_VAMPIRE
)
826 You("don't have a reflection.");
827 else if (u
.umonnum
== PM_UMBER_HULK
) {
828 pline("Huh? That doesn't look like you!");
829 make_confused(HConfusion
+ d(3, 4), FALSE
);
830 } else if (Hallucination
)
831 You(look_str
, hcolor((char *) 0));
833 You(look_str
, "peaked");
834 else if (u
.uhs
>= WEAK
)
835 You(look_str
, "undernourished");
837 You("look as %s as ever.", uvisage
);
843 You("reflect %s %s.", s_suffix(mon_nam(u
.ustuck
)),
844 mbodypart(u
.ustuck
, STOMACH
));
849 You(Hallucination
? "give the fish a chance to fix their makeup."
850 : "reflect the murky water.");
855 You("reflect the %s.",
856 (u
.dz
> 0) ? surface(u
.ux
, u
.uy
) : ceiling(u
.ux
, u
.uy
));
859 mtmp
= bhit(u
.dx
, u
.dy
, COLNO
, INVIS_BEAM
,
860 (int FDECL((*), (MONST_P
, OBJ_P
))) 0,
861 (int FDECL((*), (OBJ_P
, OBJ_P
))) 0, &obj
);
862 if (!mtmp
|| !haseyes(mtmp
->data
) || notonhead
)
865 /* couldsee(mtmp->mx, mtmp->my) is implied by the fact that bhit()
866 targetted it, so we can ignore possibility of X-ray vision */
867 vis
= canseemon(mtmp
);
868 /* ways to directly see monster (excludes X-ray vision, telepathy,
869 extended detection, type-specific warning) */
870 #define SEENMON (MONSEEN_NORMAL | MONSEEN_SEEINVIS | MONSEEN_INFRAVIS)
871 how_seen
= vis
? howmonseen(mtmp
) : 0;
872 /* whether monster is able to use its vision-based capabilities */
873 monable
= !mtmp
->mcan
&& (!mtmp
->minvis
|| perceives(mtmp
->data
));
874 mlet
= mtmp
->data
->mlet
;
875 if (mtmp
->msleeping
) {
877 pline("%s is too tired to look at your %s.", Monnam(mtmp
),
879 } else if (!mtmp
->mcansee
) {
881 pline("%s can't see anything right now.", Monnam(mtmp
));
882 } else if (invis_mirror
&& !perceives(mtmp
->data
)) {
884 pline("%s fails to notice your %s.", Monnam(mtmp
), mirror
);
885 /* infravision doesn't produce an image in the mirror */
886 } else if ((how_seen
& SEENMON
) == MONSEEN_INFRAVIS
) {
887 if (vis
) /* (redundant) */
888 pline("%s is too far away to see %sself in the dark.",
889 Monnam(mtmp
), mhim(mtmp
));
890 /* some monsters do special things */
891 } else if (mlet
== S_VAMPIRE
|| mlet
== S_GHOST
|| is_vampshifter(mtmp
)) {
893 pline("%s doesn't have a reflection.", Monnam(mtmp
));
894 } else if (monable
&& mtmp
->data
== &mons
[PM_MEDUSA
]) {
895 if (mon_reflects(mtmp
, "The gaze is reflected away by %s %s!"))
898 pline("%s is turned to stone!", Monnam(mtmp
));
901 } else if (monable
&& mtmp
->data
== &mons
[PM_FLOATING_EYE
]) {
902 int tmp
= d((int) mtmp
->m_lev
, (int) mtmp
->data
->mattk
[0].damd
);
906 pline("%s is frozen by its reflection.", Monnam(mtmp
));
908 You_hear("%s stop moving.", something
);
909 paralyze_monst(mtmp
, (int) mtmp
->mfrozen
+ tmp
);
910 } else if (monable
&& mtmp
->data
== &mons
[PM_UMBER_HULK
]) {
912 pline("%s confuses itself!", Monnam(mtmp
));
914 } else if (monable
&& (mlet
== S_NYMPH
|| mtmp
->data
== &mons
[PM_SUCCUBUS
]
915 || mtmp
->data
== &mons
[PM_INCUBUS
])) {
917 char buf
[BUFSZ
]; /* "She" or "He" */
919 pline("%s admires %sself in your %s.", Monnam(mtmp
), mhim(mtmp
),
921 pline("%s takes it!", upstart(strcpy(buf
, mhe(mtmp
))));
923 pline("It steals your %s!", mirror
);
924 setnotworn(obj
); /* in case mirror was wielded */
926 (void) mpickobj(mtmp
, obj
);
927 if (!tele_restrict(mtmp
))
928 (void) rloc(mtmp
, TRUE
);
929 } else if (!is_unicorn(mtmp
->data
) && !humanoid(mtmp
->data
)
930 && (!mtmp
->minvis
|| perceives(mtmp
->data
)) && rn2(5)) {
932 pline("%s is frightened by its reflection.", Monnam(mtmp
));
933 monflee(mtmp
, d(2, 4), FALSE
, FALSE
);
935 if (mtmp
->minvis
&& !See_invisible
)
937 else if ((mtmp
->minvis
&& !perceives(mtmp
->data
))
938 /* redundant: can't get here if these are true */
939 || !haseyes(mtmp
->data
) || notonhead
|| !mtmp
->mcansee
)
940 pline("%s doesn't seem to notice %s reflection.", Monnam(mtmp
),
943 pline("%s ignores %s reflection.", Monnam(mtmp
), mhis(mtmp
));
952 register struct obj
*obj
= *optr
;
954 boolean wakem
= FALSE
, learno
= FALSE
,
955 ordinary
= (obj
->otyp
!= BELL_OF_OPENING
|| !obj
->spe
),
957 (obj
->otyp
== BELL_OF_OPENING
&& invocation_pos(u
.ux
, u
.uy
)
958 && !On_stairs(u
.ux
, u
.uy
));
960 You("ring %s.", the(xname(obj
)));
962 if (Underwater
|| (u
.uswallow
&& ordinary
)) {
964 amii_speaker(obj
, "AhDhGqEqDhEhAqDqFhGw", AMII_MUFFLED_VOLUME
);
966 pline("But the sound is muffled.");
968 } else if (invoking
&& ordinary
) {
969 /* needs to be recharged... */
970 pline("But it makes no sound.");
971 learno
= TRUE
; /* help player figure out why */
973 } else if (ordinary
) {
975 amii_speaker(obj
, "ahdhgqeqdhehaqdqfhgw", AMII_MUFFLED_VOLUME
);
977 if (obj
->cursed
&& !rn2(4)
978 /* note: once any of them are gone, we stop all of them */
979 && !(mvitals
[PM_WOOD_NYMPH
].mvflags
& G_GONE
)
980 && !(mvitals
[PM_WATER_NYMPH
].mvflags
& G_GONE
)
981 && !(mvitals
[PM_MOUNTAIN_NYMPH
].mvflags
& G_GONE
)
982 && (mtmp
= makemon(mkclass(S_NYMPH
, 0), u
.ux
, u
.uy
, NO_MINVENT
))
984 You("summon %s!", a_monnam(mtmp
));
985 if (!obj_resists(obj
, 93, 100)) {
986 pline("%s shattered!", Tobjnam(obj
, "have"));
994 mon_adjust_speed(mtmp
, 2, (struct obj
*) 0);
996 case 2: /* no explanation; it just happens... */
1006 /* charged Bell of Opening */
1007 consume_obj_charge(obj
, TRUE
);
1013 pline1(nothing_happens
);
1015 } else if (obj
->cursed
) {
1020 mkundead(&mm
, FALSE
, NO_MINVENT
);
1023 } else if (invoking
) {
1024 pline("%s an unsettling shrill sound...", Tobjnam(obj
, "issue"));
1026 amii_speaker(obj
, "aefeaefeaefeaefeaefe", AMII_LOUDER_VOLUME
);
1032 } else if (obj
->blessed
) {
1036 amii_speaker(obj
, "ahahahDhEhCw", AMII_SOFT_VOLUME
);
1041 } else if (u
.utrap
&& u
.utraptype
== TT_BURIEDBALL
) {
1042 buried_ball_to_freedom();
1048 pline1(nothing_happens
);
1051 pline("%s opens...", Something
);
1055 pline("Things open around you...");
1060 } else { /* uncursed */
1062 amii_speaker(obj
, "AeFeaeFeAefegw", AMII_OKAY_VOLUME
);
1067 pline1(nothing_happens
);
1070 } /* charged BofO */
1073 makeknown(BELL_OF_OPENING
);
1081 use_candelabrum(obj
)
1082 register struct obj
*obj
;
1084 const char *s
= (obj
->spe
!= 1) ? "candles" : "candle";
1087 You("snuff the %s.", s
);
1088 end_burn(obj
, TRUE
);
1091 if (obj
->spe
<= 0) {
1092 pline("This %s has no %s.", xname(obj
), s
);
1096 You("cannot make fire under water.");
1099 if (u
.uswallow
|| obj
->cursed
) {
1101 pline_The("%s %s for a moment, then %s.", s
, vtense(s
, "flicker"),
1106 There("%s only %d %s in %s.", vtense(s
, "are"), obj
->spe
, s
,
1109 pline("%s lit. %s dimly.", obj
->spe
== 1 ? "It is" : "They are",
1110 Tobjnam(obj
, "shine"));
1112 pline("%s's %s burn%s", The(xname(obj
)), s
,
1113 (Blind
? "." : " brightly!"));
1115 if (!invocation_pos(u
.ux
, u
.uy
) || On_stairs(u
.ux
, u
.uy
)) {
1116 pline_The("%s %s being rapidly consumed!", s
, vtense(s
, "are"));
1117 /* this used to be obj->age /= 2, rounding down; an age of
1118 1 would yield 0, confusing begin_burn() and producing an
1119 unlightable, unrefillable candelabrum; round up instead */
1120 obj
->age
= (obj
->age
+ 1L) / 2L;
1122 if (obj
->spe
== 7) {
1124 pline("%s a strange warmth!", Tobjnam(obj
, "radiate"));
1126 pline("%s with a strange light!", Tobjnam(obj
, "glow"));
1130 begin_burn(obj
, FALSE
);
1137 register struct obj
*obj
= *optr
;
1138 register struct obj
*otmp
;
1139 const char *s
= (obj
->quan
!= 1) ? "candles" : "candle";
1140 char qbuf
[QBUFSZ
], qsfx
[QBUFSZ
], *q
;
1147 otmp
= carrying(CANDELABRUM_OF_INVOCATION
);
1148 if (!otmp
|| otmp
->spe
== 7) {
1153 /* first, minimal candelabrum suffix for formatting candles */
1154 Sprintf(qsfx
, " to\033%s?", thesimpleoname(otmp
));
1155 /* next, format the candles as a prefix for the candelabrum */
1156 (void) safe_qbuf(qbuf
, "Attach ", qsfx
, obj
, yname
, thesimpleoname
, s
);
1157 /* strip temporary candelabrum suffix */
1158 if ((q
= strstri(qbuf
, " to\033")) != 0)
1160 /* last, format final "attach candles to candelabrum?" query */
1161 if (yn(safe_qbuf(qbuf
, qbuf
, "?", otmp
, yname
, thesimpleoname
, "it"))
1166 if ((long) otmp
->spe
+ obj
->quan
> 7L) {
1167 obj
= splitobj(obj
, 7L - (long) otmp
->spe
);
1168 /* avoid a grammatical error if obj->quan gets
1169 reduced to 1 candle from more than one */
1170 s
= (obj
->quan
!= 1) ? "candles" : "candle";
1173 You("attach %ld%s %s to %s.", obj
->quan
, !otmp
->spe
? "" : " more", s
,
1175 if (!otmp
->spe
|| otmp
->age
> obj
->age
)
1176 otmp
->age
= obj
->age
;
1177 otmp
->spe
+= (int) obj
->quan
;
1178 if (otmp
->lamplit
&& !obj
->lamplit
)
1179 pline_The("new %s magically %s!", s
, vtense(s
, "ignite"));
1180 else if (!otmp
->lamplit
&& obj
->lamplit
)
1181 pline("%s out.", (obj
->quan
> 1L) ? "They go" : "It goes");
1183 verbalize("You %s %s, you bought %s!",
1184 otmp
->lamplit
? "burn" : "use",
1185 (obj
->quan
> 1L) ? "them" : "it",
1186 (obj
->quan
> 1L) ? "them" : "it");
1187 if (obj
->quan
< 7L && otmp
->spe
== 7)
1188 pline("%s now has seven%s candles attached.", The(xname(otmp
)),
1189 otmp
->lamplit
? " lit" : "");
1190 /* candelabrum's light range might increase */
1192 obj_merge_light_sources(otmp
, otmp
);
1193 /* candles are no longer a separate light source */
1195 end_burn(obj
, TRUE
);
1196 /* candles are now gone */
1201 /* call in drop, throw, and put in box, etc. */
1206 boolean candle
= Is_candle(otmp
);
1208 if ((candle
|| otmp
->otyp
== CANDELABRUM_OF_INVOCATION
)
1212 boolean many
= candle
? (otmp
->quan
> 1L) : (otmp
->spe
> 1);
1214 (void) get_obj_location(otmp
, &x
, &y
, 0);
1215 if (otmp
->where
== OBJ_MINVENT
? cansee(x
, y
) : !Blind
)
1216 pline("%s%scandle%s flame%s extinguished.", Shk_Your(buf
, otmp
),
1217 (candle
? "" : "candelabrum's "), (many
? "s'" : "'s"),
1218 (many
? "s are" : " is"));
1219 end_burn(otmp
, TRUE
);
1225 /* called when lit lamp is hit by water or put into a container or
1226 you've been swallowed by a monster; obj might be in transit while
1227 being thrown or dropped so don't assume that its location is valid */
1235 if (obj
->otyp
== OIL_LAMP
|| obj
->otyp
== MAGIC_LAMP
1236 || obj
->otyp
== BRASS_LANTERN
|| obj
->otyp
== POT_OIL
) {
1237 (void) get_obj_location(obj
, &x
, &y
, 0);
1238 if (obj
->where
== OBJ_MINVENT
? cansee(x
, y
) : !Blind
)
1239 pline("%s %s out!", Yname2(obj
), otense(obj
, "go"));
1240 end_burn(obj
, TRUE
);
1243 if (snuff_candle(obj
))
1249 /* Called when potentially lightable object is affected by fire_damage().
1250 Return TRUE if object was lit and FALSE otherwise --ALI */
1257 if (!obj
->lamplit
&& (obj
->otyp
== MAGIC_LAMP
|| ignitable(obj
))) {
1258 if ((obj
->otyp
== MAGIC_LAMP
1259 || obj
->otyp
== CANDELABRUM_OF_INVOCATION
) && obj
->spe
== 0)
1261 else if (obj
->otyp
!= MAGIC_LAMP
&& obj
->age
== 0)
1263 if (!get_obj_location(obj
, &x
, &y
, 0))
1265 if (obj
->otyp
== CANDELABRUM_OF_INVOCATION
&& obj
->cursed
)
1267 if ((obj
->otyp
== OIL_LAMP
|| obj
->otyp
== MAGIC_LAMP
1268 || obj
->otyp
== BRASS_LANTERN
) && obj
->cursed
&& !rn2(2))
1270 if (obj
->where
== OBJ_MINVENT
? cansee(x
, y
) : !Blind
)
1271 pline("%s %s light!", Yname2(obj
), otense(obj
, "catch"));
1272 if (obj
->otyp
== POT_OIL
)
1273 makeknown(obj
->otyp
);
1274 if (carried(obj
) && obj
->unpaid
&& costly_spot(u
.ux
, u
.uy
)) {
1275 /* if it catches while you have it, then it's your tough luck */
1277 verbalize("That's in addition to the cost of %s %s, of course.",
1278 yname(obj
), obj
->quan
== 1L ? "itself" : "themselves");
1279 bill_dummy_object(obj
);
1281 begin_burn(obj
, FALSE
);
1294 if (obj
->otyp
== OIL_LAMP
|| obj
->otyp
== MAGIC_LAMP
1295 || obj
->otyp
== BRASS_LANTERN
)
1296 pline("%slamp is now off.", Shk_Your(buf
, obj
));
1298 You("snuff out %s.", yname(obj
));
1299 end_burn(obj
, TRUE
);
1303 pline(!Is_candle(obj
) ? "This is not a diving lamp"
1304 : "Sorry, fire and water don't mix.");
1307 /* magic lamps with an spe == 0 (wished for) cannot be lit */
1308 if ((!Is_candle(obj
) && obj
->age
== 0)
1309 || (obj
->otyp
== MAGIC_LAMP
&& obj
->spe
== 0)) {
1310 if (obj
->otyp
== BRASS_LANTERN
)
1311 Your("lamp has run out of power.");
1313 pline("This %s has no oil.", xname(obj
));
1316 if (obj
->cursed
&& !rn2(2)) {
1318 pline("%s for a moment, then %s.", Tobjnam(obj
, "flicker"),
1319 otense(obj
, "die"));
1321 if (obj
->otyp
== OIL_LAMP
|| obj
->otyp
== MAGIC_LAMP
1322 || obj
->otyp
== BRASS_LANTERN
) {
1324 pline("%slamp is now on.", Shk_Your(buf
, obj
));
1325 } else { /* candle(s) */
1326 pline("%s flame%s %s%s", s_suffix(Yname2(obj
)), plur(obj
->quan
),
1327 otense(obj
, "burn"), Blind
? "." : " brightly!");
1328 if (obj
->unpaid
&& costly_spot(u
.ux
, u
.uy
)
1329 && obj
->age
== 20L * (long) objects
[obj
->otyp
].oc_cost
) {
1330 const char *ithem
= (obj
->quan
> 1L) ? "them" : "it";
1332 verbalize("You burn %s, you bought %s!", ithem
, ithem
);
1333 bill_dummy_object(obj
);
1336 begin_burn(obj
, FALSE
);
1342 struct obj
*obj
; /* obj is a potion of oil */
1353 You("snuff the lit potion.");
1354 end_burn(obj
, TRUE
);
1356 * Free & add to re-merge potion. This will average the
1357 * age of the potions. Not exactly the best solution,
1363 } else if (Underwater
) {
1364 There("is not enough oxygen to sustain a fire.");
1368 split1off
= (obj
->quan
> 1L);
1370 obj
= splitobj(obj
, 1L);
1372 You("light %spotion.%s", shk_your(buf
, obj
),
1373 Blind
? "" : " It gives off a dim light.");
1375 if (obj
->unpaid
&& costly_spot(u
.ux
, u
.uy
)) {
1376 /* Normally, we shouldn't both partially and fully charge
1377 * for an item, but (Yendorian Fuel) Taxes are inevitable...
1380 verbalize("That's in addition to the cost of the potion, of course.");
1381 bill_dummy_object(obj
);
1383 makeknown(obj
->otyp
);
1385 begin_burn(obj
, FALSE
); /* after shop billing */
1387 obj_extract_self(obj
); /* free from inv */
1389 obj
= hold_another_object(obj
, "You drop %s!", doname(obj
),
1396 static NEARDATA
const char cuddly
[] = { TOOL_CLASS
, GEM_CLASS
, 0 };
1401 struct obj
*obj
= getobj(cuddly
, "rub");
1403 if (obj
&& obj
->oclass
== GEM_CLASS
) {
1404 if (is_graystone(obj
)) {
1408 pline("Sorry, I don't know how to use that.");
1413 if (!obj
|| !wield_tool(obj
, "rub"))
1416 /* now uwep is obj */
1417 if (uwep
->otyp
== MAGIC_LAMP
) {
1418 if (uwep
->spe
> 0 && !rn2(3)) {
1419 check_unpaid_usage(uwep
, TRUE
); /* unusual item use */
1420 /* bones preparation: perform the lamp transformation
1421 before releasing the djinni in case the latter turns out
1422 to be fatal (a hostile djinni has no chance to attack yet,
1423 but an indebted one who grants a wish might bestow an
1424 artifact which blasts the hero with lethal results) */
1425 uwep
->otyp
= OIL_LAMP
;
1426 uwep
->spe
= 0; /* for safety */
1427 uwep
->age
= rn1(500, 1000);
1429 begin_burn(uwep
, TRUE
);
1430 djinni_from_bottle(uwep
);
1431 makeknown(MAGIC_LAMP
);
1433 } else if (rn2(2)) {
1434 You("%s smoke.", !Blind
? "see a puff of" : "smell");
1436 pline1(nothing_happens
);
1437 } else if (obj
->otyp
== BRASS_LANTERN
) {
1438 /* message from Adventure */
1439 pline("Rubbing the electric lamp is not particularly rewarding.");
1440 pline("Anyway, nothing exciting happens.");
1442 pline1(nothing_happens
);
1454 is_valid_jump_pos(x
, y
, magic
, showmsg
)
1458 if (!magic
&& !(HJumping
& ~INTRINSIC
) && !EJumping
&& distu(x
, y
) != 5) {
1459 /* The Knight jumping restriction still applies when riding a
1460 * horse. After all, what shape is the knight piece in chess?
1463 pline("Illegal move!");
1465 } else if (distu(x
, y
) > (magic
? 6 + magic
* 3 : 9)) {
1469 } else if (!cansee(x
, y
)) {
1471 You("cannot see where to land!");
1473 } else if (!isok(x
, y
)) {
1475 You("cannot jump there!");
1481 static int jumping_is_magic
;
1484 display_jump_positions(state
)
1488 tmp_at(DISP_BEAM
, cmap_to_glyph(S_goodpos
));
1489 } else if (state
== 1) {
1492 for (dx
= -4; dx
<= 4; dx
++)
1493 for (dy
= -4; dy
<= 4; dy
++) {
1494 x
= dx
+ (int) u
.ux
;
1495 y
= dy
+ (int) u
.uy
;
1496 if (isok(x
, y
) && ACCESSIBLE(levl
[x
][y
].typ
)
1497 && is_valid_jump_pos(x
, y
, jumping_is_magic
, FALSE
))
1501 tmp_at(DISP_END
, 0);
1507 int magic
; /* 0=Physical, otherwise skill level */
1511 /* attempt "jumping" spell if hero has no innate jumping ability */
1512 if (!magic
&& !Jumping
) {
1515 for (sp_no
= 0; sp_no
< MAXSPELL
; ++sp_no
)
1516 if (spl_book
[sp_no
].sp_id
== NO_SPELL
)
1518 else if (spl_book
[sp_no
].sp_id
== SPE_JUMPING
)
1519 return spelleffects(sp_no
, FALSE
);
1522 if (!magic
&& (nolimbs(youmonst
.data
) || slithy(youmonst
.data
))) {
1523 /* normally (nolimbs || slithy) implies !Jumping,
1524 but that isn't necessarily the case for knights */
1525 You_cant("jump; you have no legs!");
1527 } else if (!magic
&& !Jumping
) {
1528 You_cant("jump very far.");
1530 /* if steed is immobile, can't do physical jump but can do spell one */
1531 } else if (!magic
&& u
.usteed
&& stucksteed(FALSE
)) {
1532 /* stucksteed gave "<steed> won't move" message */
1534 } else if (u
.uswallow
) {
1536 You("bounce around a little.");
1539 pline("You've got to be kidding!");
1541 } else if (u
.uinwater
) {
1543 You("swish around a little.");
1546 pline("This calls for swimming, not jumping!");
1548 } else if (u
.ustuck
) {
1549 if (u
.ustuck
->mtame
&& !Conflict
&& !u
.ustuck
->mconf
) {
1550 You("pull free from %s.", mon_nam(u
.ustuck
));
1555 You("writhe a little in the grasp of %s!", mon_nam(u
.ustuck
));
1558 You("cannot escape from %s!", mon_nam(u
.ustuck
));
1560 } else if (Levitation
|| Is_airlevel(&u
.uz
) || Is_waterlevel(&u
.uz
)) {
1562 You("flail around a little.");
1565 You("don't have enough traction to jump.");
1567 } else if (!magic
&& near_capacity() > UNENCUMBERED
) {
1568 You("are carrying too much to jump!");
1570 } else if (!magic
&& (u
.uhunger
<= 100 || ACURR(A_STR
) < 6)) {
1571 You("lack the strength to jump!");
1573 } else if (!magic
&& Wounded_legs
) {
1574 long wl
= (Wounded_legs
& BOTH_SIDES
);
1575 const char *bp
= body_part(LEG
);
1577 if (wl
== BOTH_SIDES
)
1578 bp
= makeplural(bp
);
1580 pline("%s is in no shape for jumping.", Monnam(u
.usteed
));
1582 Your("%s%s %s in no shape for jumping.",
1583 (wl
== LEFT_SIDE
) ? "left " : (wl
== RIGHT_SIDE
) ? "right "
1585 bp
, (wl
== BOTH_SIDES
) ? "are" : "is");
1587 } else if (u
.usteed
&& u
.utrap
) {
1588 pline("%s is stuck in a trap.", Monnam(u
.usteed
));
1592 pline("Where do you want to jump?");
1595 jumping_is_magic
= magic
;
1596 getpos_sethilite(display_jump_positions
);
1597 if (getpos(&cc
, TRUE
, "the desired position") < 0)
1598 return 0; /* user pressed ESC */
1599 if (!is_valid_jump_pos(cc
.x
, cc
.y
, magic
, TRUE
)) {
1606 switch (u
.utraptype
) {
1608 long side
= rn2(3) ? LEFT_SIDE
: RIGHT_SIDE
;
1610 You("rip yourself free of the bear trap! Ouch!");
1611 losehp(Maybe_Half_Phys(rnd(10)), "jumping out of a bear trap",
1613 set_wounded_legs(side
, rn1(1000, 500));
1617 You("leap from the pit!");
1620 You("tear the web apart as you pull yourself free!");
1621 deltrap(t_at(u
.ux
, u
.uy
));
1624 You("pull yourself above the lava!");
1629 You("strain your %s, but you're still %s.",
1630 makeplural(body_part(LEG
)),
1631 (u
.utraptype
== TT_INFLOOR
)
1632 ? "stuck in the floor"
1633 : "attached to the buried ball");
1634 set_wounded_legs(LEFT_SIDE
, rn1(10, 11));
1635 set_wounded_legs(RIGHT_SIDE
, rn1(10, 11));
1640 * Check the path from uc to cc, calling hurtle_step at each
1641 * location. The final position actually reached will be
1646 /* calculate max(abs(dx), abs(dy)) as the range */
1647 range
= cc
.x
- uc
.x
;
1655 (void) walk_path(&uc
, &cc
, hurtle_step
, (genericptr_t
) &range
);
1656 /* hurtle_step results in (u.ux, u.uy) == (cc.x, cc.y) and usually
1657 * moves the ball if punished, but does not handle all the effects
1658 * of landing on the final position.
1660 teleds(cc
.x
, cc
.y
, FALSE
);
1663 multi_reason
= "jumping around";
1665 morehungry(rnd(25));
1676 if (!mons
[corpse
->corpsenm
].cnutrit
)
1682 use_tinning_kit(obj
)
1685 struct obj
*corpse
, *can
;
1687 /* This takes only 1 move. If this is to be changed to take many
1688 * moves, we've got to deal with decaying corpses...
1690 if (obj
->spe
<= 0) {
1691 You("seem to be out of tins.");
1694 if (!(corpse
= floorfood("tin", 2)))
1696 if (corpse
->oeaten
) {
1697 You("cannot tin %s which is partly eaten.", something
);
1700 if (touch_petrifies(&mons
[corpse
->corpsenm
]) && !Stone_resistance
1704 if (poly_when_stoned(youmonst
.data
))
1705 You("tin %s without wearing gloves.",
1706 an(mons
[corpse
->corpsenm
].mname
));
1708 pline("Tinning %s without wearing gloves is a fatal mistake...",
1709 an(mons
[corpse
->corpsenm
].mname
));
1710 Sprintf(kbuf
, "trying to tin %s without gloves",
1711 an(mons
[corpse
->corpsenm
].mname
));
1715 if (is_rider(&mons
[corpse
->corpsenm
])) {
1716 if (revive_corpse(corpse
))
1717 verbalize("Yes... But War does not preserve its enemies...");
1719 pline_The("corpse evades your grasp.");
1722 if (mons
[corpse
->corpsenm
].cnutrit
== 0) {
1723 pline("That's too insubstantial to tin.");
1726 consume_obj_charge(obj
, TRUE
);
1728 if ((can
= mksobj(TIN
, FALSE
, FALSE
)) != 0) {
1729 static const char you_buy_it
[] = "You tin it, you bought it!";
1731 can
->corpsenm
= corpse
->corpsenm
;
1732 can
->cursed
= obj
->cursed
;
1733 can
->blessed
= obj
->blessed
;
1734 can
->owt
= weight(can
);
1736 /* Mark tinned tins. No spinach allowed... */
1737 set_tin_variety(can
, HOMEMADE_TIN
);
1738 if (carried(corpse
)) {
1740 verbalize(you_buy_it
);
1743 if (costly_spot(corpse
->ox
, corpse
->oy
) && !corpse
->no_charge
)
1744 verbalize(you_buy_it
);
1747 can
= hold_another_object(can
, "You make, but cannot pick up, %s.",
1748 doname(can
), (const char *) 0);
1750 impossible("Tinning failed.");
1754 use_unicorn_horn(obj
)
1757 #define PROP_COUNT 7 /* number of properties we're dealing with */
1758 #define ATTR_COUNT (A_MAX * 3) /* number of attribute points we might fix */
1759 int idx
, val
, val_limit
, trouble_count
, unfixable_trbl
, did_prop
,
1761 int trouble_list
[PROP_COUNT
+ ATTR_COUNT
];
1763 if (obj
&& obj
->cursed
) {
1764 long lcount
= (long) rn1(90, 10);
1766 switch (rn2(13) / 2) { /* case 6 is half as likely as the others */
1768 make_sick((Sick
& TIMEOUT
) ? (Sick
& TIMEOUT
) / 3L + 1L
1769 : (long) rn1(ACURR(A_CON
), 20),
1770 xname(obj
), TRUE
, SICK_NONVOMITABLE
);
1773 make_blinded((Blinded
& TIMEOUT
) + lcount
, TRUE
);
1777 You("suddenly feel %s.",
1778 Hallucination
? "trippy" : "confused");
1779 make_confused((HConfusion
& TIMEOUT
) + lcount
, TRUE
);
1782 make_stunned((HStun
& TIMEOUT
) + lcount
, TRUE
);
1785 (void) adjattrib(rn2(A_MAX
), -1, FALSE
);
1788 (void) make_hallucinated((HHallucination
& TIMEOUT
) + lcount
,
1792 if (Deaf
) /* make_deaf() won't give feedback when already deaf */
1793 pline("Nothing seems to happen.");
1794 make_deaf((HDeaf
& TIMEOUT
) + lcount
, TRUE
);
1795 context
.botl
= TRUE
;
1802 * Entries in the trouble list use a very simple encoding scheme.
1804 #define prop2trbl(X) ((X) + A_MAX)
1805 #define attr2trbl(Y) (Y)
1806 #define prop_trouble(X) trouble_list[trouble_count++] = prop2trbl(X)
1807 #define attr_trouble(Y) trouble_list[trouble_count++] = attr2trbl(Y)
1808 #define TimedTrouble(P) (((P) && !((P) & ~TIMEOUT)) ? ((P) & TIMEOUT) : 0L)
1810 trouble_count
= unfixable_trbl
= did_prop
= did_attr
= 0;
1812 /* collect property troubles */
1813 if (TimedTrouble(Sick
))
1815 if (TimedTrouble(Blinded
) > (long) u
.ucreamed
1817 && attacktype_fordmg(u
.ustuck
->data
, AT_ENGL
, AD_BLND
)))
1818 prop_trouble(BLINDED
);
1819 if (TimedTrouble(HHallucination
))
1820 prop_trouble(HALLUC
);
1821 if (TimedTrouble(Vomiting
))
1822 prop_trouble(VOMITING
);
1823 if (TimedTrouble(HConfusion
))
1824 prop_trouble(CONFUSION
);
1825 if (TimedTrouble(HStun
))
1826 prop_trouble(STUNNED
);
1827 if (TimedTrouble(HDeaf
))
1830 unfixable_trbl
= unfixable_trouble_count(TRUE
);
1832 /* collect attribute troubles */
1833 for (idx
= 0; idx
< A_MAX
; idx
++) {
1834 if (ABASE(idx
) >= AMAX(idx
))
1836 val_limit
= AMAX(idx
);
1837 /* don't recover strength lost from hunger */
1838 if (idx
== A_STR
&& u
.uhs
>= WEAK
)
1841 /* potion/spell of restore ability override sustain ability
1842 intrinsic but unicorn horn usage doesn't */
1843 unfixable_trbl
+= val_limit
- ABASE(idx
);
1846 /* don't recover more than 3 points worth of any attribute */
1847 if (val_limit
> ABASE(idx
) + 3)
1848 val_limit
= ABASE(idx
) + 3;
1850 for (val
= ABASE(idx
); val
< val_limit
; val
++)
1852 /* keep track of unfixed trouble, for message adjustment below */
1853 unfixable_trbl
+= (AMAX(idx
) - val_limit
);
1856 if (trouble_count
== 0) {
1857 pline1(nothing_happens
);
1859 } else if (trouble_count
> 1) { /* shuffle */
1862 for (i
= trouble_count
- 1; i
> 0; i
--)
1863 if ((j
= rn2(i
+ 1)) != i
) {
1864 k
= trouble_list
[j
];
1865 trouble_list
[j
] = trouble_list
[i
];
1866 trouble_list
[i
] = k
;
1871 * Chances for number of troubles to be fixed
1873 * blessed: 22.7% 22.7% 19.5% 15.4% 10.7% 5.7% 2.6% 0.8%
1874 * uncursed: 35.4% 35.4% 22.9% 6.3% 0 0 0 0
1876 val_limit
= rn2(d(2, (obj
&& obj
->blessed
) ? 4 : 2));
1877 if (val_limit
> trouble_count
)
1878 val_limit
= trouble_count
;
1880 /* fix [some of] the troubles */
1881 for (val
= 0; val
< val_limit
; val
++) {
1882 idx
= trouble_list
[val
];
1885 case prop2trbl(SICK
):
1886 make_sick(0L, (char *) 0, TRUE
, SICK_ALL
);
1889 case prop2trbl(BLINDED
):
1890 make_blinded((long) u
.ucreamed
, TRUE
);
1893 case prop2trbl(HALLUC
):
1894 (void) make_hallucinated(0L, TRUE
, 0L);
1897 case prop2trbl(VOMITING
):
1898 make_vomiting(0L, TRUE
);
1901 case prop2trbl(CONFUSION
):
1902 make_confused(0L, TRUE
);
1905 case prop2trbl(STUNNED
):
1906 make_stunned(0L, TRUE
);
1909 case prop2trbl(DEAF
):
1910 make_deaf(0L, TRUE
);
1914 if (idx
>= 0 && idx
< A_MAX
) {
1918 panic("use_unicorn_horn: bad trouble? (%d)", idx
);
1924 pline("This makes you feel %s!",
1925 (did_prop
+ did_attr
) == (trouble_count
+ unfixable_trbl
)
1929 pline("Nothing seems to happen.");
1931 context
.botl
= (did_attr
|| did_prop
);
1942 * Timer callback routine: turn figurine into monster
1945 fig_transform(arg
, timeout
)
1949 struct obj
*figurine
= arg
->a_obj
;
1952 boolean cansee_spot
, silent
, okay_spot
;
1953 boolean redraw
= FALSE
;
1954 boolean suppress_see
= FALSE
;
1955 char monnambuf
[BUFSZ
], carriedby
[BUFSZ
];
1958 debugpline0("null figurine in fig_transform()");
1961 silent
= (timeout
!= monstermoves
); /* happened while away */
1962 okay_spot
= get_obj_location(figurine
, &cc
.x
, &cc
.y
, 0);
1963 if (figurine
->where
== OBJ_INVENT
|| figurine
->where
== OBJ_MINVENT
)
1964 okay_spot
= enexto(&cc
, cc
.x
, cc
.y
, &mons
[figurine
->corpsenm
]);
1965 if (!okay_spot
|| !figurine_location_checks(figurine
, &cc
, TRUE
)) {
1966 /* reset the timer to try again later */
1967 (void) start_timer((long) rnd(5000), TIMER_OBJECT
, FIG_TRANSFORM
,
1968 obj_to_any(figurine
));
1972 cansee_spot
= cansee(cc
.x
, cc
.y
);
1973 mtmp
= make_familiar(figurine
, cc
.x
, cc
.y
, TRUE
);
1975 char and_vanish
[BUFSZ
];
1976 struct obj
*mshelter
= level
.objects
[mtmp
->mx
][mtmp
->my
];
1978 Sprintf(monnambuf
, "%s", an(m_monnam(mtmp
)));
1979 and_vanish
[0] = '\0';
1980 if ((mtmp
->minvis
&& !See_invisible
)
1981 || (mtmp
->data
->mlet
== S_MIMIC
1982 && mtmp
->m_ap_type
!= M_AP_NOTHING
))
1983 suppress_see
= TRUE
;
1985 if (mtmp
->mundetected
) {
1986 if (hides_under(mtmp
->data
) && mshelter
) {
1987 Sprintf(and_vanish
, " and %s under %s",
1988 locomotion(mtmp
->data
, "crawl"), doname(mshelter
));
1989 } else if (mtmp
->data
->mlet
== S_MIMIC
1990 || mtmp
->data
->mlet
== S_EEL
) {
1991 suppress_see
= TRUE
;
1993 Strcpy(and_vanish
, " and vanish");
1996 switch (figurine
->where
) {
1998 if (Blind
|| suppress_see
)
1999 You_feel("%s %s from your pack!", something
,
2000 locomotion(mtmp
->data
, "drop"));
2002 You_see("%s %s out of your pack%s!", monnambuf
,
2003 locomotion(mtmp
->data
, "drop"), and_vanish
);
2007 if (cansee_spot
&& !silent
) {
2009 pline("%s suddenly vanishes!", an(xname(figurine
)));
2011 You_see("a figurine transform into %s%s!", monnambuf
,
2013 redraw
= TRUE
; /* update figurine's map location */
2018 if (cansee_spot
&& !silent
&& !suppress_see
) {
2021 mon
= figurine
->ocarry
;
2022 /* figurine carrying monster might be invisible */
2023 if (canseemon(figurine
->ocarry
)
2024 && (!mon
->wormno
|| cansee(mon
->mx
, mon
->my
)))
2025 Sprintf(carriedby
, "%s pack", s_suffix(a_monnam(mon
)));
2026 else if (is_pool(mon
->mx
, mon
->my
))
2027 Strcpy(carriedby
, "empty water");
2029 Strcpy(carriedby
, "thin air");
2030 You_see("%s %s out of %s%s!", monnambuf
,
2031 locomotion(mtmp
->data
, "drop"), carriedby
,
2041 impossible("figurine came to life where? (%d)",
2042 (int) figurine
->where
);
2046 /* free figurine now */
2047 if (carried(figurine
)) {
2050 obj_extract_self(figurine
);
2051 obfree(figurine
, (struct obj
*) 0);
2058 figurine_location_checks(obj
, cc
, quietly
)
2065 if (carried(obj
) && u
.uswallow
) {
2067 You("don't have enough room in here.");
2070 x
= cc
? cc
->x
: u
.ux
;
2071 y
= cc
? cc
->y
: u
.uy
;
2074 You("cannot put the figurine there.");
2077 if (IS_ROCK(levl
[x
][y
].typ
)
2078 && !(passes_walls(&mons
[obj
->corpsenm
]) && may_passwall(x
, y
))) {
2080 You("cannot place a figurine in %s!",
2081 IS_TREE(levl
[x
][y
].typ
) ? "a tree" : "solid rock");
2084 if (sobj_at(BOULDER
, x
, y
) && !passes_walls(&mons
[obj
->corpsenm
])
2085 && !throws_rocks(&mons
[obj
->corpsenm
])) {
2087 You("cannot fit the figurine on the boulder.");
2097 register struct obj
*obj
= *optr
;
2102 /* can't activate a figurine while swallowed */
2103 if (!figurine_location_checks(obj
, (coord
*) 0, FALSE
))
2106 if (!getdir((char *) 0)) {
2107 context
.move
= multi
= 0;
2114 /* Passing FALSE arg here will result in messages displayed */
2115 if (!figurine_location_checks(obj
, &cc
, FALSE
))
2117 You("%s and it transforms.",
2118 (u
.dx
|| u
.dy
) ? "set the figurine beside you"
2119 : (Is_airlevel(&u
.uz
) || Is_waterlevel(&u
.uz
)
2120 || is_pool(cc
.x
, cc
.y
))
2121 ? "release the figurine"
2122 : (u
.dz
< 0 ? "toss the figurine into the air"
2123 : "set the figurine on the ground"));
2124 (void) make_familiar(obj
, cc
.x
, cc
.y
, FALSE
);
2125 (void) stop_timer(FIG_TRANSFORM
, obj_to_any(obj
));
2130 static NEARDATA
const char lubricables
[] = { ALL_CLASSES
, ALLOW_NONE
, 0 };
2139 pline("%s from your %s.", Tobjnam(obj
, "slip"),
2140 makeplural(body_part(FINGER
)));
2146 if ((obj
->cursed
|| Fumbling
) && !rn2(2)) {
2147 consume_obj_charge(obj
, TRUE
);
2149 pline("%s from your %s.", Tobjnam(obj
, "slip"),
2150 makeplural(body_part(FINGER
)));
2154 otmp
= getobj(lubricables
, "grease");
2157 if (inaccessible_equipment(otmp
, "grease", FALSE
))
2159 consume_obj_charge(obj
, TRUE
);
2161 if (otmp
!= &zeroobj
) {
2162 You("cover %s with a thick layer of grease.", yname(otmp
));
2164 if (obj
->cursed
&& !nohands(youmonst
.data
)) {
2165 incr_itimeout(&Glib
, rnd(15));
2166 pline("Some of the grease gets all over your %s.",
2167 makeplural(body_part(HAND
)));
2170 incr_itimeout(&Glib
, rnd(15));
2171 You("coat your %s with grease.", makeplural(body_part(FINGER
)));
2175 pline("%s empty.", Tobjnam(obj
, "are"));
2177 pline("%s to be empty.", Tobjnam(obj
, "seem"));
2182 /* touchstones - by Ken Arnold */
2189 const char *streak_color
, *choices
;
2190 char stonebuf
[QBUFSZ
];
2191 static const char scritch
[] = "\"scritch, scritch\"";
2192 static const char allowall
[3] = { COIN_CLASS
, ALL_CLASSES
, 0 };
2193 static const char coins_gems
[3] = { COIN_CLASS
, GEM_CLASS
, 0 };
2195 /* in case it was acquired while blinded */
2198 /* when the touchstone is fully known, don't bother listing extra
2199 junk as likely candidates for rubbing */
2200 choices
= (tstone
->otyp
== TOUCHSTONE
&& tstone
->dknown
2201 && objects
[TOUCHSTONE
].oc_name_known
)
2204 Sprintf(stonebuf
, "rub on the stone%s", plur(tstone
->quan
));
2205 if ((obj
= getobj(choices
, stonebuf
)) == 0)
2208 if (obj
== tstone
&& obj
->quan
== 1L) {
2209 You_cant("rub %s on itself.", the(xname(obj
)));
2213 if (tstone
->otyp
== TOUCHSTONE
&& tstone
->cursed
2214 && obj
->oclass
== GEM_CLASS
&& !is_graystone(obj
)
2215 && !obj_resists(obj
, 80, 100)) {
2217 pline("You feel something shatter.");
2218 else if (Hallucination
)
2219 pline("Oh, wow, look at the pretty shards.");
2221 pline("A sharp crack shatters %s%s.",
2222 (obj
->quan
> 1L) ? "one of " : "", the(xname(obj
)));
2230 } else if (Hallucination
) {
2231 pline("Oh wow, man: Fractals!");
2238 switch (obj
->oclass
) {
2239 case GEM_CLASS
: /* these have class-specific handling below */
2241 if (tstone
->otyp
!= TOUCHSTONE
) {
2243 } else if (obj
->oclass
== GEM_CLASS
2245 || (!tstone
->cursed
&& (Role_if(PM_ARCHEOLOGIST
)
2246 || Race_if(PM_GNOME
))))) {
2247 makeknown(TOUCHSTONE
);
2248 makeknown(obj
->otyp
);
2249 prinv((char *) 0, obj
, 0L);
2252 /* either a ring or the touchstone was not effective */
2253 if (objects
[obj
->otyp
].oc_material
== GLASS
) {
2258 streak_color
= c_obj_colors
[objects
[obj
->otyp
].oc_color
];
2259 break; /* gem or ring */
2262 switch (objects
[obj
->otyp
].oc_material
) {
2264 pline("%s a little more polished now.", Tobjnam(tstone
, "look"));
2267 if (!obj
->known
) /* note: not "whetstone" */
2268 You("must think this is a wetstone, do you?");
2270 pline("%s a little wetter now.", Tobjnam(tstone
, "are"));
2273 streak_color
= "waxy";
2274 break; /* okay even if not touchstone */
2276 streak_color
= "wooden";
2277 break; /* okay even if not touchstone */
2279 do_scratch
= TRUE
; /* scratching and streaks */
2280 streak_color
= "golden";
2283 do_scratch
= TRUE
; /* scratching and streaks */
2284 streak_color
= "silvery";
2287 /* Objects passing the is_flimsy() test will not
2288 scratch a stone. They will leave streaks on
2289 non-touchstones and touchstones alike. */
2291 streak_color
= c_obj_colors
[objects
[obj
->otyp
].oc_color
];
2293 do_scratch
= (tstone
->otyp
!= TOUCHSTONE
);
2296 break; /* default oclass */
2299 Sprintf(stonebuf
, "stone%s", plur(tstone
->quan
));
2301 You("make %s%sscratch marks on the %s.",
2302 streak_color
? streak_color
: (const char *) "",
2303 streak_color
? " " : "", stonebuf
);
2304 else if (streak_color
)
2305 You_see("%s streaks on the %s.", streak_color
, stonebuf
);
2311 static struct trapinfo
{
2315 boolean force_bungle
;
2322 trapinfo
.force_bungle
= 0;
2325 /* Place a landmine/bear trap. Helge Hafting */
2331 const char *what
= (char *) 0;
2333 int levtyp
= levl
[u
.ux
][u
.uy
].typ
;
2334 const char *occutext
= "setting the trap";
2336 if (nohands(youmonst
.data
))
2337 what
= "without hands";
2339 what
= "while stunned";
2340 else if (u
.uswallow
)
2342 is_animal(u
.ustuck
->data
) ? "while swallowed" : "while engulfed";
2343 else if (Underwater
)
2344 what
= "underwater";
2345 else if (Levitation
)
2346 what
= "while levitating";
2347 else if (is_pool(u
.ux
, u
.uy
))
2349 else if (is_lava(u
.ux
, u
.uy
))
2351 else if (On_stairs(u
.ux
, u
.uy
))
2352 what
= (u
.ux
== xdnladder
|| u
.ux
== xupladder
) ? "on the ladder"
2354 else if (IS_FURNITURE(levtyp
) || IS_ROCK(levtyp
)
2355 || closed_door(u
.ux
, u
.uy
) || t_at(u
.ux
, u
.uy
))
2357 else if (Is_airlevel(&u
.uz
) || Is_waterlevel(&u
.uz
))
2358 what
= (levtyp
== AIR
)
2362 : "in this place"; /* Air/Water Plane catch-all */
2364 You_cant("set a trap %s!", what
);
2368 ttyp
= (otmp
->otyp
== LAND_MINE
) ? LANDMINE
: BEAR_TRAP
;
2369 if (otmp
== trapinfo
.tobj
&& u
.ux
== trapinfo
.tx
&& u
.uy
== trapinfo
.ty
) {
2370 You("resume setting %s%s.", shk_your(buf
, otmp
),
2371 defsyms
[trap_to_defsym(what_trap(ttyp
))].explanation
);
2372 set_occupation(set_trap
, occutext
, 0);
2375 trapinfo
.tobj
= otmp
;
2376 trapinfo
.tx
= u
.ux
, trapinfo
.ty
= u
.uy
;
2378 trapinfo
.time_needed
=
2379 (tmp
> 17) ? 2 : (tmp
> 12) ? 3 : (tmp
> 7) ? 4 : 5;
2381 trapinfo
.time_needed
*= 2;
2383 if (ttyp
== BEAR_TRAP
&& tmp
< 18)
2384 trapinfo
.time_needed
+= (tmp
> 12) ? 1 : (tmp
> 7) ? 2 : 4;
2385 /*[fumbling and/or confusion and/or cursed object check(s)
2386 should be incorporated here instead of in set_trap]*/
2387 if (u
.usteed
&& P_SKILL(P_RIDING
) < P_BASIC
) {
2390 if (Fumbling
|| otmp
->cursed
)
2391 chance
= (rnl(10) > 3);
2393 chance
= (rnl(10) > 5);
2394 You("aren't very skilled at reaching from %s.", mon_nam(u
.usteed
));
2395 Sprintf(buf
, "Continue your attempt to set %s?",
2396 the(defsyms
[trap_to_defsym(what_trap(ttyp
))].explanation
));
2397 if (yn(buf
) == 'y') {
2400 case LANDMINE
: /* set it off */
2401 trapinfo
.time_needed
= 0;
2402 trapinfo
.force_bungle
= TRUE
;
2404 case BEAR_TRAP
: /* drop it without arming it */
2407 the(defsyms
[trap_to_defsym(what_trap(ttyp
))]
2418 You("begin setting %s%s.", shk_your(buf
, otmp
),
2419 defsyms
[trap_to_defsym(what_trap(ttyp
))].explanation
);
2420 set_occupation(set_trap
, occutext
, 0);
2428 struct obj
*otmp
= trapinfo
.tobj
;
2432 if (!otmp
|| !carried(otmp
) || u
.ux
!= trapinfo
.tx
2433 || u
.uy
!= trapinfo
.ty
) {
2439 if (--trapinfo
.time_needed
> 0)
2440 return 1; /* still busy */
2442 ttyp
= (otmp
->otyp
== LAND_MINE
) ? LANDMINE
: BEAR_TRAP
;
2443 ttmp
= maketrap(u
.ux
, u
.uy
, ttyp
);
2447 if (*in_rooms(u
.ux
, u
.uy
, SHOPBASE
)) {
2448 add_damage(u
.ux
, u
.uy
, 0L); /* schedule removal */
2450 if (!trapinfo
.force_bungle
)
2451 You("finish arming %s.",
2452 the(defsyms
[trap_to_defsym(what_trap(ttyp
))].explanation
));
2453 if (((otmp
->cursed
|| Fumbling
) && (rnl(10) > 5))
2454 || trapinfo
.force_bungle
)
2456 (unsigned) (trapinfo
.force_bungle
? FORCEBUNGLE
: 0));
2458 /* this shouldn't happen */
2459 Your("trap setting attempt fails.");
2473 int rx
, ry
, proficient
, res
= 0;
2474 const char *msg_slipsfree
= "The bullwhip slips free.";
2475 const char *msg_snap
= "Snap!";
2478 if (!wield_tool(obj
, "lash"))
2483 if (!getdir((char *) 0))
2491 if (Stunned
|| (Confusion
&& !rn2(5)))
2495 if (!isok(rx
, ry
)) {
2499 mtmp
= m_at(rx
, ry
);
2502 /* fake some proficiency checks */
2504 if (Role_if(PM_ARCHEOLOGIST
))
2506 if (ACURR(A_DEX
) < 6)
2508 else if (ACURR(A_DEX
) >= 14)
2509 proficient
+= (ACURR(A_DEX
) - 14);
2517 if (u
.uswallow
&& attack(u
.ustuck
)) {
2518 There("is not enough room to flick your bullwhip.");
2520 } else if (Underwater
) {
2521 There("is too much resistance to flick your bullwhip.");
2523 } else if (u
.dz
< 0) {
2524 You("flick a bug off of the %s.", ceiling(u
.ux
, u
.uy
));
2526 } else if ((!u
.dx
&& !u
.dy
) || (u
.dz
> 0)) {
2529 /* Sometimes you hit your steed by mistake */
2530 if (u
.usteed
&& !rn2(proficient
+ 2)) {
2531 You("whip %s!", mon_nam(u
.usteed
));
2535 if (Levitation
|| u
.usteed
) {
2536 /* Have a shot at snaring something on the floor */
2537 otmp
= level
.objects
[u
.ux
][u
.uy
];
2538 if (otmp
&& otmp
->otyp
== CORPSE
&& otmp
->corpsenm
== PM_HORSE
) {
2539 pline("Why beat a dead horse?");
2542 if (otmp
&& proficient
) {
2543 You("wrap your bullwhip around %s on the %s.",
2544 an(singular(otmp
, xname
)), surface(u
.ux
, u
.uy
));
2545 if (rnl(6) || pickup_object(otmp
, 1L, TRUE
) < 1)
2546 pline1(msg_slipsfree
);
2550 dam
= rnd(2) + dbon() + obj
->spe
;
2553 You("hit your %s with your bullwhip.", body_part(FOOT
));
2554 Sprintf(buf
, "killed %sself with %s bullwhip", uhim(), uhis());
2555 losehp(Maybe_Half_Phys(dam
), buf
, NO_KILLER_PREFIX
);
2559 } else if ((Fumbling
|| Glib
) && !rn2(5)) {
2560 pline_The("bullwhip slips out of your %s.", body_part(HAND
));
2563 } else if (u
.utrap
&& u
.utraptype
== TT_PIT
) {
2567 * if you're in a pit
2568 * - you are attempting to get out of the pit
2569 * or, if you are applying it towards a small monster
2570 * - then it is assumed that you are trying to hit it
2571 * else if the monster is wielding a weapon
2572 * - you are attempting to disarm a monster
2574 * - you are attempting to hit the monster.
2576 * if you're confused (and thus off the mark)
2577 * - you only end up hitting.
2580 const char *wrapped_what
= (char *) 0;
2583 if (bigmonst(mtmp
->data
)) {
2584 wrapped_what
= strcpy(buf
, mon_nam(mtmp
));
2585 } else if (proficient
) {
2592 if (!wrapped_what
) {
2593 if (IS_FURNITURE(levl
[rx
][ry
].typ
))
2594 wrapped_what
= something
;
2595 else if (sobj_at(BOULDER
, rx
, ry
))
2596 wrapped_what
= "a boulder";
2603 You("wrap your bullwhip around %s.", wrapped_what
);
2604 if (proficient
&& rn2(proficient
+ 2)) {
2605 if (!mtmp
|| enexto(&cc
, rx
, ry
, youmonst
.data
)) {
2606 You("yank yourself out of the pit!");
2607 teleds(cc
.x
, cc
.y
, TRUE
);
2609 vision_full_recalc
= 1;
2612 pline1(msg_slipsfree
);
2620 if (!canspotmon(mtmp
) && !glyph_is_invisible(levl
[rx
][ry
].glyph
)) {
2621 pline("A monster is there that you couldn't see.");
2622 map_invisible(rx
, ry
);
2624 otmp
= MON_WEP(mtmp
); /* can be null */
2626 char onambuf
[BUFSZ
];
2627 const char *mon_hand
;
2628 boolean gotit
= proficient
&& (!Fumbling
|| !rn2(10));
2630 Strcpy(onambuf
, cxname(otmp
));
2632 mon_hand
= mbodypart(mtmp
, HAND
);
2634 mon_hand
= makeplural(mon_hand
);
2636 mon_hand
= 0; /* lint suppression */
2638 You("wrap your bullwhip around %s.", yname(otmp
));
2639 if (gotit
&& mwelded(otmp
)) {
2640 pline("%s welded to %s %s%c",
2641 (otmp
->quan
== 1L) ? "It is" : "They are", mhis(mtmp
),
2642 mon_hand
, !otmp
->bknown
? '!' : '.');
2644 gotit
= FALSE
; /* can't pull it free */
2647 obj_extract_self(otmp
);
2648 possibly_unwield(mtmp
, FALSE
);
2649 setmnotwielded(mtmp
, otmp
);
2651 switch (rn2(proficient
+ 1)) {
2653 /* to floor near you */
2654 You("yank %s to the %s!", yname(otmp
),
2655 surface(u
.ux
, u
.uy
));
2656 place_object(otmp
, u
.ux
, u
.uy
);
2663 /* proficient with whip, but maybe not
2664 so proficient at catching weapons */
2667 hitvalu
= 8 + otmp
->spe
;
2668 hitu
= thitu(hitvalu
,
2669 dmgval(otmp
, &youmonst
),
2672 pline_The("%s hits you as you try to snatch it!",
2675 place_object(otmp
, u
.ux
, u
.uy
);
2680 /* right into your inventory */
2681 You("snatch %s!", yname(otmp
));
2682 if (otmp
->otyp
== CORPSE
2683 && touch_petrifies(&mons
[otmp
->corpsenm
]) && !uarmg
2684 && !Stone_resistance
2685 && !(poly_when_stoned(youmonst
.data
)
2686 && polymon(PM_STONE_GOLEM
))) {
2689 Sprintf(kbuf
, "%s corpse",
2690 an(mons
[otmp
->corpsenm
].mname
));
2691 pline("Snatching %s is a fatal mistake.", kbuf
);
2694 otmp
= hold_another_object(
2695 otmp
, "You drop %s!", doname(otmp
), (const char *) 0);
2698 /* to floor beneath mon */
2699 You("yank %s from %s %s!", the(onambuf
),
2700 s_suffix(mon_nam(mtmp
)), mon_hand
);
2701 obj_no_longer_held(otmp
);
2702 place_object(otmp
, mtmp
->mx
, mtmp
->my
);
2707 pline1(msg_slipsfree
);
2711 if (mtmp
->m_ap_type
&& !Protection_from_shape_changers
2713 stumble_onto_mimic(mtmp
);
2715 You("flick your bullwhip towards %s.", mon_nam(mtmp
));
2724 } else if (Is_airlevel(&u
.uz
) || Is_waterlevel(&u
.uz
)) {
2725 /* it must be air -- water checked above */
2726 You("snap your whip through thin air.");
2735 not_enough_room
[] = "There's not enough room here to use that.",
2736 where_to_hit
[] = "Where do you want to hit?",
2737 cant_see_spot
[] = "won't hit anything if you can't see that spot.",
2738 cant_reach
[] = "can't reach that spot from here.";
2740 /* find pos of monster in range, if only one monster */
2742 find_poleable_mon(pos
, min_range
, max_range
)
2744 int min_range
, max_range
;
2747 struct monst
*selmon
= (struct monst
*) 0;
2749 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
)
2750 if (mtmp
&& !DEADMONSTER(mtmp
) && !mtmp
->mtame
2751 && cansee(mtmp
->mx
, mtmp
->my
)
2752 && distu(mtmp
->mx
, mtmp
->my
) <= max_range
2753 && distu(mtmp
->mx
, mtmp
->my
) >= min_range
) {
2760 pos
->x
= selmon
->mx
;
2761 pos
->y
= selmon
->my
;
2765 static int polearm_range_min
= -1;
2766 static int polearm_range_max
= -1;
2769 display_polearm_positions(state
)
2773 tmp_at(DISP_BEAM
, cmap_to_glyph(S_goodpos
));
2774 } else if (state
== 1) {
2777 for (dx
= -4; dx
<= 4; dx
++)
2778 for (dy
= -4; dy
<= 4; dy
++) {
2779 x
= dx
+ (int) u
.ux
;
2780 y
= dy
+ (int) u
.uy
;
2781 if (isok(x
, y
) && ACCESSIBLE(levl
[x
][y
].typ
)
2782 && distu(x
, y
) >= polearm_range_min
2783 && distu(x
, y
) <= polearm_range_max
) {
2788 tmp_at(DISP_END
, 0);
2792 /* Distance attacks by pole-weapons */
2797 int res
= 0, typ
, max_range
, min_range
, glyph
;
2800 struct monst
*hitm
= context
.polearm
.hitmon
;
2802 /* Are you allowed to use the pole? */
2804 pline(not_enough_room
);
2808 if (!wield_tool(obj
, "swing"))
2813 /* assert(obj == uwep); */
2816 * Calculate allowable range (pole's reach is always 2 steps):
2817 * unskilled and basic: orthogonal direction, 4..4;
2818 * skilled: as basic, plus knight's jump position, 4..5;
2819 * expert: as skilled, plus diagonal, 4..8.
2827 * (Note: no roles in nethack can become expert or better
2828 * for polearm skill; Yeoman in slash'em can become expert.)
2831 typ
= uwep_skill_type();
2832 if (typ
== P_NONE
|| P_SKILL(typ
) <= P_BASIC
)
2834 else if (P_SKILL(typ
) == P_SKILLED
)
2837 max_range
= 8; /* (P_SKILL(typ) >= P_EXPERT) */
2839 polearm_range_min
= min_range
;
2840 polearm_range_max
= max_range
;
2842 /* Prompt for a location */
2843 pline(where_to_hit
);
2846 if (!find_poleable_mon(&cc
, min_range
, max_range
) && hitm
2847 && !DEADMONSTER(hitm
) && cansee(hitm
->mx
, hitm
->my
)
2848 && distu(hitm
->mx
, hitm
->my
) <= max_range
2849 && distu(hitm
->mx
, hitm
->my
) >= min_range
) {
2853 getpos_sethilite(display_polearm_positions
);
2854 if (getpos(&cc
, TRUE
, "the spot to hit") < 0)
2855 return res
; /* ESC; uses turn iff polearm became wielded */
2857 glyph
= glyph_at(cc
.x
, cc
.y
);
2858 if (distu(cc
.x
, cc
.y
) > max_range
) {
2861 } else if (distu(cc
.x
, cc
.y
) < min_range
) {
2862 pline("Too close!");
2864 } else if (!cansee(cc
.x
, cc
.y
) && !glyph_is_monster(glyph
)
2865 && !glyph_is_invisible(glyph
) && !glyph_is_statue(glyph
)) {
2868 } else if (!couldsee(cc
.x
, cc
.y
)) { /* Eyes of the Overworld */
2873 context
.polearm
.hitmon
= NULL
;
2874 /* Attack the monster there */
2876 if ((mtmp
= m_at(bhitpos
.x
, bhitpos
.y
)) != (struct monst
*) 0) {
2877 if (attack_checks(mtmp
, uwep
))
2880 return 1; /* burn nutrition; maybe pass out */
2881 context
.polearm
.hitmon
= mtmp
;
2882 check_caitiff(mtmp
);
2883 notonhead
= (bhitpos
.x
!= mtmp
->mx
|| bhitpos
.y
!= mtmp
->my
);
2884 (void) thitmonst(mtmp
, uwep
);
2885 } else if (glyph_is_statue(glyph
) /* might be hallucinatory */
2886 && sobj_at(STATUE
, bhitpos
.x
, bhitpos
.y
)) {
2887 struct trap
*t
= t_at(bhitpos
.x
, bhitpos
.y
);
2889 if (t
&& t
->ttyp
== STATUE_TRAP
2890 && activate_statue_trap(t
, t
->tx
, t
->ty
, FALSE
)) {
2891 ; /* feedback has been give by animate_statue() */
2893 /* Since statues look like monsters now, we say something
2894 different from "you miss" or "there's nobody there".
2895 Note: we only do this when a statue is displayed here,
2896 because the player is probably attempting to attack it;
2897 other statues obscured by anything are just ignored. */
2898 pline("Thump! Your blow bounces harmlessly off the statue.");
2899 wake_nearto(bhitpos
.x
, bhitpos
.y
, 25);
2902 /* no monster here and no statue seen or remembered here */
2903 if (glyph_is_invisible(glyph
)) {
2904 /* now you know that nothing is there... */
2905 unmap_object(bhitpos
.x
, bhitpos
.y
);
2906 newsym(bhitpos
.x
, bhitpos
.y
);
2908 You("miss; there is no one there to hit.");
2910 u_wipe_engr(2); /* same as for melee or throwing */
2918 boolean wasblind
= Blind
;
2919 boolean wascreamed
= u
.ucreamed
;
2920 boolean several
= FALSE
;
2922 if (obj
->quan
> 1L) {
2924 obj
= splitobj(obj
, 1L);
2927 You("give yourself a facial.");
2929 pline("You immerse your %s in %s%s.", body_part(FACE
),
2930 several
? "one of " : "",
2931 several
? makeplural(the(xname(obj
))) : the(xname(obj
)));
2932 if (can_blnd((struct monst
*) 0, &youmonst
, AT_WEAP
, obj
)) {
2933 int blindinc
= rnd(25);
2934 u
.ucreamed
+= blindinc
;
2935 make_blinded(Blinded
+ (long) blindinc
, FALSE
);
2936 if (!Blind
|| (Blind
&& wasblind
))
2937 pline("There's %ssticky goop all over your %s.",
2938 wascreamed
? "more " : "", body_part(FACE
));
2939 else /* Blind && !wasblind */
2940 You_cant("see through all the sticky goop on your %s.",
2945 /* useup() is appropriate, but we want costly_alteration()'s message */
2946 costly_alteration(obj
, COST_SPLAT
);
2947 obj_extract_self(obj
);
2956 int res
= 0, typ
, max_range
= 4, tohit
;
2957 boolean save_confirm
;
2962 /* Are you allowed to use the hook? */
2964 pline(not_enough_room
);
2968 if (!wield_tool(obj
, "cast"))
2973 /* assert(obj == uwep); */
2975 /* Prompt for a location */
2976 pline(where_to_hit
);
2979 if (getpos(&cc
, TRUE
, "the spot to hit") < 0)
2980 return res
; /* ESC; uses turn iff grapnel became wielded */
2982 /* Calculate range; unlike use_pole(), there's no minimum for range */
2983 typ
= uwep_skill_type();
2984 if (typ
== P_NONE
|| P_SKILL(typ
) <= P_BASIC
)
2986 else if (P_SKILL(typ
) == P_SKILLED
)
2990 if (distu(cc
.x
, cc
.y
) > max_range
) {
2993 } else if (!cansee(cc
.x
, cc
.y
)) {
2996 } else if (!couldsee(cc
.x
, cc
.y
)) { /* Eyes of the Overworld */
3001 /* What do you want to hit? */
3003 if (typ
!= P_NONE
&& P_SKILL(typ
) >= P_SKILLED
) {
3004 winid tmpwin
= create_nhwindow(NHW_MENU
);
3007 menu_item
*selected
;
3009 any
= zeroany
; /* set all bits to zero */
3010 any
.a_int
= 1; /* use index+1 (cant use 0) as identifier */
3013 Sprintf(buf
, "an object on the %s", surface(cc
.x
, cc
.y
));
3014 add_menu(tmpwin
, NO_GLYPH
, &any
, 0, 0, ATR_NONE
, buf
,
3017 add_menu(tmpwin
, NO_GLYPH
, &any
, 0, 0, ATR_NONE
, "a monster",
3020 Sprintf(buf
, "the %s", surface(cc
.x
, cc
.y
));
3021 add_menu(tmpwin
, NO_GLYPH
, &any
, 0, 0, ATR_NONE
, buf
,
3023 end_menu(tmpwin
, "Aim for what?");
3025 if (select_menu(tmpwin
, PICK_ONE
, &selected
) > 0
3026 && rn2(P_SKILL(typ
) > P_SKILLED
? 20 : 2))
3027 tohit
= selected
[0].item
.a_int
- 1;
3028 free((genericptr_t
) selected
);
3029 destroy_nhwindow(tmpwin
);
3032 /* possibly scuff engraving at your feet;
3033 any engraving at the target location is unaffected */
3034 if (tohit
== 2 || !rn2(2))
3035 u_wipe_engr(rnd(2));
3037 /* What did you hit? */
3040 /* FIXME -- untrap needs to deal with non-adjacent traps */
3042 case 1: /* Object */
3043 if ((otmp
= level
.objects
[cc
.x
][cc
.y
]) != 0) {
3044 You("snag an object from the %s!", surface(cc
.x
, cc
.y
));
3045 (void) pickup_object(otmp
, 1L, FALSE
);
3046 /* If pickup fails, leave it alone */
3051 case 2: /* Monster */
3053 if ((mtmp
= m_at(cc
.x
, cc
.y
)) == (struct monst
*) 0)
3055 notonhead
= (bhitpos
.x
!= mtmp
->mx
|| bhitpos
.y
!= mtmp
->my
);
3056 save_confirm
= flags
.confirm
;
3057 if (verysmall(mtmp
->data
) && !rn2(4)
3058 && enexto(&cc
, u
.ux
, u
.uy
, (struct permonst
*) 0)) {
3059 flags
.confirm
= FALSE
;
3060 (void) attack_checks(mtmp
, uwep
);
3061 flags
.confirm
= save_confirm
;
3062 check_caitiff(mtmp
); /* despite fact there's no damage */
3063 You("pull in %s!", mon_nam(mtmp
));
3064 mtmp
->mundetected
= 0;
3065 rloc_to(mtmp
, cc
.x
, cc
.y
);
3067 } else if ((!bigmonst(mtmp
->data
) && !strongmonst(mtmp
->data
))
3069 flags
.confirm
= FALSE
;
3070 (void) attack_checks(mtmp
, uwep
);
3071 flags
.confirm
= save_confirm
;
3072 check_caitiff(mtmp
);
3073 (void) thitmonst(mtmp
, uwep
);
3077 case 3: /* Surface */
3078 if (IS_AIR(levl
[cc
.x
][cc
.y
].typ
) || is_pool(cc
.x
, cc
.y
))
3079 pline_The("hook slices through the %s.", surface(cc
.x
, cc
.y
));
3081 You("are yanked toward the %s!", surface(cc
.x
, cc
.y
));
3082 hurtle(sgn(cc
.x
- u
.ux
), sgn(cc
.y
- u
.uy
), 1, FALSE
);
3086 default: /* Yourself (oops!) */
3087 if (P_SKILL(typ
) <= P_BASIC
) {
3088 You("hook yourself!");
3089 losehp(Maybe_Half_Phys(rn1(10, 10)), "a grappling hook",
3095 pline1(nothing_happens
);
3099 #define BY_OBJECT ((struct monst *) 0)
3101 /* return 1 if the wand is broken, hence some time elapsed */
3106 static const char nothing_else_happens
[] = "But nothing else happens...";
3107 register int i
, x
, y
;
3108 register struct monst
*mon
;
3110 boolean affects_objects
;
3111 boolean shop_damage
= FALSE
;
3112 boolean fillmsg
= FALSE
;
3113 int expltype
= EXPL_MAGICAL
;
3114 char confirm
[QBUFSZ
], buf
[BUFSZ
];
3115 boolean is_fragile
= (!strcmp(OBJ_DESCR(objects
[obj
->otyp
]), "balsa"));
3117 if (!paranoid_query(ParanoidBreakwand
,
3119 "Are you really sure you want to break ",
3120 "?", obj
, yname
, ysimple_name
, "the wand")))
3123 if (nohands(youmonst
.data
)) {
3124 You_cant("break %s without hands!", yname(obj
));
3126 } else if (ACURR(A_STR
) < (is_fragile
? 5 : 10)) {
3127 You("don't have the strength to break %s!", yname(obj
));
3130 pline("Raising %s high above your %s, you break it in two!", yname(obj
),
3133 /* [ALI] Do this first so that wand is removed from bill. Otherwise,
3134 * the freeinv() below also hides it from setpaid() which causes problems.
3137 check_unpaid(obj
); /* Extra charge for use */
3138 costly_alteration(obj
, COST_DSTROY
);
3141 current_wand
= obj
; /* destroy_item might reset this */
3142 freeinv(obj
); /* hide it from destroy_item instead... */
3143 setnotworn(obj
); /* so we need to do this ourselves */
3145 if (!zappable(obj
)) {
3146 pline(nothing_else_happens
);
3147 goto discard_broken_wand
;
3149 /* successful call to zappable() consumes a charge; put it back */
3151 /* might have "wrested" a final charge, taking it from 0 to -1;
3152 if so, we just brought it back up to 0, which wouldn't do much
3153 below so give it 1..3 charges now, usually making it stronger
3154 than an ordinary last charge (the wand is already gone from
3155 inventory, so perm_invent can't accidentally reveal this) */
3162 affects_objects
= FALSE
;
3164 switch (obj
->otyp
) {
3169 case WAN_ENLIGHTENMENT
:
3171 case WAN_SECRET_DOOR_DETECTION
:
3172 pline(nothing_else_happens
);
3173 goto discard_broken_wand
;
3179 expltype
= EXPL_FIERY
;
3181 if (expltype
== EXPL_MAGICAL
)
3182 expltype
= EXPL_FROSTY
;
3184 case WAN_MAGIC_MISSILE
:
3186 explode(u
.ux
, u
.uy
, -(obj
->otyp
), dmg
, WAND_CLASS
, expltype
);
3187 makeknown(obj
->otyp
); /* explode describes the effect */
3188 goto discard_broken_wand
;
3190 /* we want this before the explosion instead of at the very end */
3191 pline("A wall of force smashes down around you!");
3192 dmg
= d(1 + obj
->spe
, 6); /* normally 2d12 */
3194 case WAN_CANCELLATION
:
3196 case WAN_TELEPORTATION
:
3197 case WAN_UNDEAD_TURNING
:
3198 affects_objects
= TRUE
;
3204 /* magical explosion and its visual effect occur before specific effects
3206 /* [TODO? This really ought to prevent the explosion from being
3207 fatal so that we never leave a bones file where none of the
3208 surrounding targets (or underlying objects) got affected yet.] */
3209 explode(obj
->ox
, obj
->oy
, -(obj
->otyp
), rnd(dmg
), WAND_CLASS
,
3212 /* prepare for potential feedback from polymorph... */
3215 /* this makes it hit us last, so that we can see the action first */
3216 for (i
= 0; i
<= 8; i
++) {
3217 bhitpos
.x
= x
= obj
->ox
+ xdir
[i
];
3218 bhitpos
.y
= y
= obj
->oy
+ ydir
[i
];
3222 if (obj
->otyp
== WAN_DIGGING
) {
3225 if (dig_check(BY_OBJECT
, FALSE
, x
, y
)) {
3226 if (IS_WALL(levl
[x
][y
].typ
) || IS_DOOR(levl
[x
][y
].typ
)) {
3227 /* normally, pits and holes don't anger guards, but they
3228 * do if it's a wall or door that's being dug */
3229 watch_dig((struct monst
*) 0, x
, y
, TRUE
);
3230 if (*in_rooms(x
, y
, SHOPBASE
))
3234 * Let liquid flow into the newly created pits.
3235 * Adjust corresponding code in music.c for
3236 * drum of earthquake if you alter this sequence.
3238 typ
= fillholetyp(x
, y
, FALSE
);
3240 levl
[x
][y
].typ
= typ
;
3241 liquid_flow(x
, y
, typ
, t_at(x
, y
),
3244 : "Some holes are quickly filled with %s!");
3247 digactualhole(x
, y
, BY_OBJECT
, (rn2(obj
->spe
) < 3
3248 || (!Can_dig_down(&u
.uz
)
3249 && !levl
[x
][y
].candig
))
3254 } else if (obj
->otyp
== WAN_CREATE_MONSTER
) {
3255 /* u.ux,u.uy creates it near you--x,y might create it in rock */
3256 (void) makemon((struct permonst
*) 0, u
.ux
, u
.uy
, NO_MM_FLAGS
);
3258 } else if (x
!= u
.ux
|| y
!= u
.uy
) {
3260 * Wand breakage is targetting a square adjacent to the hero,
3261 * which might contain a monster or a pile of objects or both.
3262 * Handle objects last; avoids having undead turning raise an
3263 * undead's corpse and then attack resulting undead monster.
3264 * obj->bypass in bhitm() prevents the polymorphing of items
3265 * dropped due to monster's polymorph and prevents undead
3266 * turning that kills an undead from raising resulting corpse.
3268 if ((mon
= m_at(x
, y
)) != 0) {
3269 (void) bhitm(mon
, obj
);
3270 /* if (context.botl) bot(); */
3272 if (affects_objects
&& level
.objects
[x
][y
]) {
3273 (void) bhitpile(obj
, bhito
, x
, y
, 0);
3275 bot(); /* potion effects */
3279 * Wand breakage is targetting the hero. Using xdir[]+ydir[]
3280 * deltas for location selection causes this case to happen
3281 * after all the surrounding squares have been handled.
3282 * Process objects first, in case damage is fatal and leaves
3283 * bones, or teleportation sends one or more of the objects to
3284 * same destination as hero (lookhere/autopickup); also avoids
3285 * the polymorphing of gear dropped due to hero's transformation.
3286 * (Unlike with monsters being hit by zaps, we can't rely on use
3287 * of obj->bypass in the zap code to accomplish that last case
3288 * since it's also used by retouch_equipment() for polyself.)
3290 if (affects_objects
&& level
.objects
[x
][y
]) {
3291 (void) bhitpile(obj
, bhito
, x
, y
, 0);
3293 bot(); /* potion effects */
3295 damage
= zapyourself(obj
, FALSE
);
3297 Sprintf(buf
, "killed %sself by breaking a wand", uhim());
3298 losehp(Maybe_Half_Phys(damage
), buf
, NO_KILLER_PREFIX
);
3301 bot(); /* blindness */
3305 /* potentially give post zap/break feedback */
3308 /* Note: if player fell thru, this call is a no-op.
3309 Damage is handled in digactualhole in that case */
3311 pay_for_damage("dig into", FALSE
);
3313 if (obj
->otyp
== WAN_LIGHT
)
3314 litroom(TRUE
, obj
); /* only needs to be done once */
3316 discard_broken_wand
:
3317 obj
= current_wand
; /* [see dozap() and destroy_item()] */
3326 add_class(cl
, class)
3337 static const char tools
[] = { TOOL_CLASS
, WEAPON_CLASS
, WAND_CLASS
, 0 };
3339 /* augment tools[] if various items are carried */
3341 setapplyclasses(class_list
)
3344 register struct obj
*otmp
;
3346 boolean knowoil
, knowtouchstone
, addpotions
, addstones
, addfood
;
3348 knowoil
= objects
[POT_OIL
].oc_name_known
;
3349 knowtouchstone
= objects
[TOUCHSTONE
].oc_name_known
;
3350 addpotions
= addstones
= addfood
= FALSE
;
3351 for (otmp
= invent
; otmp
; otmp
= otmp
->nobj
) {
3354 || (otmp
->oclass
== POTION_CLASS
3356 || (!knowoil
&& !objects
[otyp
].oc_name_known
))))
3358 if (otyp
== TOUCHSTONE
3359 || (is_graystone(otmp
)
3361 || (!knowtouchstone
&& !objects
[otyp
].oc_name_known
))))
3363 if (otyp
== CREAM_PIE
|| otyp
== EUCALYPTUS_LEAF
)
3367 class_list
[0] = '\0';
3368 if (addpotions
|| addstones
)
3369 add_class(class_list
, ALL_CLASSES
);
3370 Strcat(class_list
, tools
);
3372 add_class(class_list
, POTION_CLASS
);
3374 add_class(class_list
, GEM_CLASS
);
3376 add_class(class_list
, FOOD_CLASS
);
3379 /* the 'a' command */
3384 register int res
= 1;
3385 char class_list
[MAXOCLASSES
+ 2];
3387 if (check_capacity((char *) 0))
3390 setapplyclasses(class_list
); /* tools[] */
3391 obj
= getobj(class_list
, "use or apply");
3395 if (!retouch_object(&obj
, FALSE
))
3396 return 1; /* evading your grasp costs a turn; just be
3397 grateful that you don't drop it as well */
3399 if (obj
->oclass
== WAND_CLASS
)
3400 return do_break_wand(obj
);
3402 switch (obj
->otyp
) {
3405 if (obj
== ublindf
) {
3408 } else if (!ublindf
) {
3411 You("are already %s.", ublindf
->otyp
== TOWEL
3412 ? "covered by a towel"
3413 : ublindf
->otyp
== BLINDFOLD
3414 ? "wearing a blindfold"
3415 : "wearing lenses");
3419 res
= use_cream_pie(obj
);
3422 res
= use_whip(obj
);
3424 case GRAPPLING_HOOK
:
3425 res
= use_grapple(obj
);
3431 case BAG_OF_HOLDING
:
3433 res
= use_container(&obj
, 1, FALSE
);
3436 (void) bagotricks(obj
, FALSE
, (int *) 0);
3444 res
= (pick_lock(obj
) != 0);
3447 case DWARVISH_MATTOCK
:
3448 res
= use_pick_axe(obj
);
3451 use_tinning_kit(obj
);
3457 res
= use_saddle(obj
);
3460 use_magic_whistle(obj
);
3465 case EUCALYPTUS_LEAF
:
3466 /* MRKR: Every Australian knows that a gum leaf makes an excellent
3467 * whistle, especially if your pet is a tame kangaroo named Skippy.
3470 use_magic_whistle(obj
);
3471 /* sometimes the blessing will be worn off */
3474 pline("%s %s.", Yobjnam2(obj
, "glow"), hcolor("brown"));
3484 res
= use_stethoscope(obj
);
3487 res
= use_mirror(obj
);
3490 case BELL_OF_OPENING
:
3493 case CANDELABRUM_OF_INVOCATION
:
3494 use_candelabrum(obj
);
3506 light_cocktail(obj
);
3508 case EXPENSIVE_CAMERA
:
3509 res
= use_camera(obj
);
3512 res
= use_towel(obj
);
3515 use_crystal_ball(&obj
);
3521 res
= use_tin_opener(obj
);
3527 use_unicorn_horn(obj
);
3538 case DRUM_OF_EARTHQUAKE
:
3539 res
= do_play_instrument(obj
);
3541 case HORN_OF_PLENTY
: /* not a musical instrument */
3542 (void) hornoplenty(obj
, FALSE
);
3555 /* Pole-weapons can strike at a distance */
3557 res
= use_pole(obj
);
3559 } else if (is_pick(obj
) || is_axe(obj
)) {
3560 res
= use_pick_axe(obj
);
3563 pline("Sorry, I don't know how to use that.");
3567 if (res
&& obj
&& obj
->oartifact
)
3573 /* Keep track of unfixable troubles for purposes of messages saying you feel
3577 unfixable_trouble_count(is_horn
)
3580 int unfixable_trbl
= 0;
3586 if (Wounded_legs
&& !u
.usteed
)
3590 /* lycanthropy is undesirable, but it doesn't actually make you feel bad */
3592 if (!is_horn
|| (Confusion
& ~TIMEOUT
))
3594 if (!is_horn
|| (Sick
& ~TIMEOUT
))
3596 if (!is_horn
|| (HHallucination
& ~TIMEOUT
))
3598 if (!is_horn
|| (Vomiting
& ~TIMEOUT
))
3600 if (!is_horn
|| (HStun
& ~TIMEOUT
))
3602 if (!is_horn
|| (HDeaf
& ~TIMEOUT
))
3605 return unfixable_trbl
;