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_PTR boolean
FDECL(check_jump
, (genericptr_t
, int, int));
40 STATIC_DCL boolean
FDECL(is_valid_jump_pos
, (int, int, int, BOOLEAN_P
));
41 STATIC_DCL boolean
FDECL(find_poleable_mon
, (coord
*, int, int));
44 void FDECL(amii_speaker
, (struct obj
*, char *, int));
47 static const char no_elbow_room
[] =
48 "don't have enough elbow-room to maneuver.";
57 pline("Using your camera underwater would void the warranty.");
60 if (!getdir((char *) 0))
64 pline1(nothing_happens
);
67 consume_obj_charge(obj
, TRUE
);
69 if (obj
->cursed
&& !rn2(2)) {
70 (void) zapyourself(obj
, TRUE
);
71 } else if (u
.uswallow
) {
72 You("take a picture of %s %s.", s_suffix(mon_nam(u
.ustuck
)),
73 mbodypart(u
.ustuck
, STOMACH
));
75 You("take a picture of the %s.",
76 (u
.dz
> 0) ? surface(u
.ux
, u
.uy
) : ceiling(u
.ux
, u
.uy
));
77 } else if (!u
.dx
&& !u
.dy
) {
78 (void) zapyourself(obj
, TRUE
);
79 } else if ((mtmp
= bhit(u
.dx
, u
.dy
, COLNO
, FLASHED_LIGHT
,
80 (int FDECL((*), (MONST_P
, OBJ_P
))) 0,
81 (int FDECL((*), (OBJ_P
, OBJ_P
))) 0, &obj
)) != 0) {
82 obj
->ox
= u
.ux
, obj
->oy
= u
.uy
;
83 (void) flash_hits_mon(mtmp
, obj
);
92 boolean drying_feedback
= (obj
== uwep
);
95 You("have no free %s!", body_part(HAND
));
97 } else if (obj
== ublindf
) {
98 You("cannot use it while you're wearing it!");
100 } else if (obj
->cursed
) {
106 incr_itimeout(&Glib
, rn1(10, 3));
107 Your("%s %s!", makeplural(body_part(HAND
)),
108 (old
? "are filthier than ever" : "get slimy"));
109 if (is_wet_towel(obj
))
110 dry_a_towel(obj
, -1, drying_feedback
);
115 u
.ucreamed
+= rn1(10, 3);
116 pline("Yecch! Your %s %s gunk on it!", body_part(FACE
),
117 (old
? "has more" : "now has"));
118 make_blinded(Blinded
+ (long) u
.ucreamed
- old
, TRUE
);
122 what
= (ublindf
->otyp
== LENSES
)
124 : (obj
->otyp
== ublindf
->otyp
) ? "other towel"
126 if (ublindf
->cursed
) {
127 You("push your %s %s.", what
,
128 rn2(2) ? "cock-eyed" : "crooked");
130 struct obj
*saved_ublindf
= ublindf
;
131 You("push your %s off.", what
);
133 dropx(saved_ublindf
);
136 if (is_wet_towel(obj
))
137 dry_a_towel(obj
, -1, drying_feedback
);
146 You("wipe off your %s.", makeplural(body_part(HAND
)));
147 if (is_wet_towel(obj
))
148 dry_a_towel(obj
, -1, drying_feedback
);
150 } else if (u
.ucreamed
) {
151 Blinded
-= u
.ucreamed
;
154 pline("You've got the glop off.");
155 if (!gulp_blnd_check()) {
157 make_blinded(0L, TRUE
);
160 Your("%s feels clean now.", body_part(FACE
));
162 if (is_wet_towel(obj
))
163 dry_a_towel(obj
, -1, drying_feedback
);
167 Your("%s and %s are already clean.", body_part(FACE
),
168 makeplural(body_part(HAND
)));
173 /* maybe give a stethoscope message based on floor objects */
175 its_dead(rx
, ry
, resp
)
179 boolean more_corpses
;
180 struct permonst
*mptr
;
181 struct obj
*corpse
= sobj_at(CORPSE
, rx
, ry
),
182 *statue
= sobj_at(STATUE
, rx
, ry
);
184 if (!can_reach_floor(TRUE
)) { /* levitation or unskilled riding */
185 corpse
= 0; /* can't reach corpse on floor */
186 /* you can't reach tiny statues (even though you can fight
187 tiny monsters while levitating--consistency, what's that?) */
188 while (statue
&& mons
[statue
->corpsenm
].msize
== MZ_TINY
)
189 statue
= nxtobj(statue
, STATUE
, TRUE
);
191 /* when both corpse and statue are present, pick the uppermost one */
192 if (corpse
&& statue
) {
193 if (nxtobj(statue
, CORPSE
, TRUE
) == corpse
)
194 corpse
= 0; /* corpse follows statue; ignore it */
196 statue
= 0; /* corpse precedes statue; ignore statue */
198 more_corpses
= (corpse
&& nxtobj(corpse
, CORPSE
, TRUE
));
200 /* additional stethoscope messages from jyoung@apanix.apana.org.au */
201 if (!corpse
&& !statue
) {
202 ; /* nothing to do */
204 } else if (Hallucination
) {
207 Strcpy(buf
, "You're both stoned");
208 } else if (corpse
->quan
== 1L && !more_corpses
) {
209 int gndr
= 2; /* neuter: "it" */
210 struct monst
*mtmp
= get_mtraits(corpse
, FALSE
);
212 /* (most corpses don't retain the monster's sex, so
213 we're usually forced to use generic pronoun here) */
215 mptr
= &mons
[mtmp
->mnum
];
216 /* can't use mhe() here; it calls pronoun_gender() which
217 expects monster to be on the map (visibility check) */
218 if ((humanoid(mptr
) || (mptr
->geno
& G_UNIQ
)
219 || type_is_pname(mptr
)) && !is_neuter(mptr
))
220 gndr
= (int) mtmp
->female
;
222 mptr
= &mons
[corpse
->corpsenm
];
225 else if (is_male(mptr
))
228 Sprintf(buf
, "%s's dead", genders
[gndr
].he
); /* "he"/"she"/"it" */
229 buf
[0] = highc(buf
[0]);
230 } else { /* plural */
231 Strcpy(buf
, "They're dead");
233 /* variations on "He's dead, Jim." (Star Trek's Dr McCoy) */
234 You_hear("a voice say, \"%s, Jim.\"", buf
);
239 boolean here
= (rx
== u
.ux
&& ry
== u
.uy
),
240 one
= (corpse
->quan
== 1L && !more_corpses
), reviver
= FALSE
;
241 int visglyph
, corpseglyph
;
243 visglyph
= glyph_at(rx
, ry
);
244 corpseglyph
= obj_to_glyph(corpse
);
246 if (Blind
&& (visglyph
!= corpseglyph
))
247 map_object(corpse
, TRUE
);
249 if (Role_if(PM_HEALER
)) {
250 /* ok to reset `corpse' here; we're done with it */
252 if (obj_has_timer(corpse
, REVIVE_MON
))
255 corpse
= nxtobj(corpse
, CORPSE
, TRUE
);
256 } while (corpse
&& !reviver
);
258 You("determine that %s unfortunate being%s %s%s dead.",
259 one
? (here
? "this" : "that") : (here
? "these" : "those"),
260 one
? "" : "s", one
? "is" : "are", reviver
? " mostly" : "");
263 } else { /* statue */
264 const char *what
, *how
;
266 mptr
= &mons
[statue
->corpsenm
];
267 if (Blind
) { /* ignore statue->dknown; it'll always be set */
268 Sprintf(buf
, "%s %s",
269 (rx
== u
.ux
&& ry
== u
.uy
) ? "This" : "That",
270 humanoid(mptr
) ? "person" : "creature");
274 if (!type_is_pname(mptr
))
278 if (Role_if(PM_HEALER
)) {
279 struct trap
*ttmp
= t_at(rx
, ry
);
281 if (ttmp
&& ttmp
->ttyp
== STATUE_TRAP
)
282 how
= "extraordinary";
283 else if (Has_contents(statue
))
287 pline("%s is in %s health for a statue.", what
, how
);
290 return FALSE
; /* no corpse or statue */
293 static const char hollow_str
[] = "a hollow sound. This must be a secret %s!";
295 /* Strictly speaking it makes no sense for usage of a stethoscope to
296 not take any time; however, unless it did, the stethoscope would be
297 almost useless. As a compromise, one use per turn is free, another
298 uses up the turn; this makes curse status have a tangible effect. */
301 register struct obj
*obj
;
306 boolean interference
= (u
.uswallow
&& is_whirly(u
.ustuck
->data
)
307 && !rn2(Role_if(PM_HEALER
) ? 10 : 3));
309 if (nohands(youmonst
.data
)) {
310 You("have no hands!"); /* not `body_part(HAND)' */
313 You_cant("hear anything!");
315 } else if (!freehand()) {
316 You("have no free %s.", body_part(HAND
));
319 if (!getdir((char *) 0))
322 res
= (moves
== context
.stethoscope_move
)
323 && (youmonst
.movement
== context
.stethoscope_movement
);
324 context
.stethoscope_move
= moves
;
325 context
.stethoscope_movement
= youmonst
.movement
;
327 bhitpos
.x
= u
.ux
, bhitpos
.y
= u
.uy
; /* tentative, reset below */
328 notonhead
= u
.uswallow
;
329 if (u
.usteed
&& u
.dz
> 0) {
331 pline("%s interferes.", Monnam(u
.ustuck
));
332 mstatusline(u
.ustuck
);
334 mstatusline(u
.usteed
);
336 } else if (u
.uswallow
&& (u
.dx
|| u
.dy
|| u
.dz
)) {
337 mstatusline(u
.ustuck
);
339 } else if (u
.uswallow
&& interference
) {
340 pline("%s interferes.", Monnam(u
.ustuck
));
341 mstatusline(u
.ustuck
);
345 You_hear("faint splashing.");
346 else if (u
.dz
< 0 || !can_reach_floor(TRUE
))
347 cant_reach_floor(u
.ux
, u
.uy
, (u
.dz
< 0), TRUE
);
348 else if (its_dead(u
.ux
, u
.uy
, &res
))
349 ; /* message already given */
350 else if (Is_stronghold(&u
.uz
))
351 You_hear("the crackling of hellfire.");
353 pline_The("%s seems healthy enough.", surface(u
.ux
, u
.uy
));
355 } else if (obj
->cursed
&& !rn2(2)) {
356 You_hear("your heart beat.");
359 if (Stunned
|| (Confusion
&& !rn2(5)))
361 if (!u
.dx
&& !u
.dy
) {
368 You_hear("a faint typing noise.");
371 if ((mtmp
= m_at(rx
, ry
)) != 0) {
372 const char *mnm
= x_monnam(mtmp
, ARTICLE_A
, (const char *) 0,
373 SUPPRESS_IT
| SUPPRESS_INVISIBLE
, FALSE
);
375 /* bhitpos needed by mstatusline() iff mtmp is a long worm */
376 bhitpos
.x
= rx
, bhitpos
.y
= ry
;
377 notonhead
= (mtmp
->mx
!= rx
|| mtmp
->my
!= ry
);
379 if (mtmp
->mundetected
) {
380 if (!canspotmon(mtmp
))
381 There("is %s hidden there.", mnm
);
382 mtmp
->mundetected
= 0;
383 newsym(mtmp
->mx
, mtmp
->my
);
384 } else if (mtmp
->mappearance
) {
385 const char *what
= "thing";
387 switch (mtmp
->m_ap_type
) {
389 what
= simple_typename(mtmp
->mappearance
);
391 case M_AP_MONSTER
: /* ignore Hallucination here */
392 what
= mons
[mtmp
->mappearance
].mname
;
395 what
= defsyms
[mtmp
->mappearance
].explanation
;
399 pline("That %s is really %s.", what
, mnm
);
400 } else if (flags
.verbose
&& !canspotmon(mtmp
)) {
401 There("is %s there.", mnm
);
405 if (!canspotmon(mtmp
))
406 map_invisible(rx
, ry
);
409 if (glyph_is_invisible(levl
[rx
][ry
].glyph
)) {
410 unmap_object(rx
, ry
);
412 pline_The("invisible monster must have moved.");
418 You_hear(hollow_str
, "door");
419 cvt_sdoor_to_door(lev
); /* ->typ = DOOR */
423 You_hear(hollow_str
, "passage");
425 unblock_point(rx
, ry
);
430 if (!its_dead(rx
, ry
, &res
))
431 You("hear nothing special."); /* not You_hear() */
435 static const char whistle_str
[] = "produce a %s whistling sound.";
441 if (!can_blow(&youmonst
)) {
442 You("are incapable of using the whistle.");
443 } else if (Underwater
) {
444 You("blow bubbles through %s.", yname(obj
));
446 You(whistle_str
, obj
->cursed
? "shrill" : "high");
452 use_magic_whistle(obj
)
455 register struct monst
*mtmp
, *nextmon
;
457 if (!can_blow(&youmonst
)) {
458 You("are incapable of using the whistle.");
459 } else if (obj
->cursed
&& !rn2(2)) {
460 You("produce a %shigh-pitched humming noise.",
461 Underwater
? "very " : "");
464 int pet_cnt
= 0, omx
, omy
;
466 /* it's magic! it works underwater too (at a higher pitch) */
468 Hallucination
? "normal" : Underwater
? "strange, high-pitched"
470 for (mtmp
= fmon
; mtmp
; mtmp
= nextmon
) {
471 nextmon
= mtmp
->nmon
; /* trap might kill mon */
472 if (DEADMONSTER(mtmp
))
474 /* steed is already at your location, so not affected;
475 this avoids trap issues if you're on a trap location */
476 if (mtmp
== u
.usteed
)
479 if (mtmp
->mtrapped
) {
480 /* no longer in previous trap (affects mintrap) */
482 fill_pit(mtmp
->mx
, mtmp
->my
);
484 /* mimic must be revealed before we know whether it
485 actually moves because line-of-sight may change */
488 omx
= mtmp
->mx
, omy
= mtmp
->my
;
490 if (mtmp
->mx
!= omx
|| mtmp
->my
!= omy
) {
491 mtmp
->mundetected
= 0; /* reveal non-mimic hider */
492 if (canspotmon(mtmp
))
494 if (mintrap(mtmp
) == 2)
500 makeknown(obj
->otyp
);
508 return (boolean
) (abs(u
.ux
- x
) > n
|| abs(u
.uy
- y
) > n
);
517 for (obj
= invent
; obj
; obj
= obj
->nobj
)
518 if (obj
->otyp
== LEASH
&& obj
->leashmon
!= 0)
523 /* otmp is about to be destroyed or stolen */
526 register struct obj
*otmp
;
528 register struct monst
*mtmp
;
530 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
)
531 if (mtmp
->m_id
== (unsigned) otmp
->leashmon
)
536 /* mtmp is about to die, or become untame */
538 m_unleash(mtmp
, feedback
)
539 register struct monst
*mtmp
;
542 register struct obj
*otmp
;
546 pline("%s pulls free of %s leash!", Monnam(mtmp
), mhis(mtmp
));
548 Your("leash falls slack.");
550 for (otmp
= invent
; otmp
; otmp
= otmp
->nobj
)
551 if (otmp
->otyp
== LEASH
&& otmp
->leashmon
== (int) mtmp
->m_id
)
556 /* player is about to die (for bones) */
560 register struct obj
*otmp
;
561 register struct monst
*mtmp
;
563 for (otmp
= invent
; otmp
; otmp
= otmp
->nobj
)
564 if (otmp
->otyp
== LEASH
)
566 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
)
576 return (boolean
) (mtmp
->mnum
!= PM_LONG_WORM
);
585 register struct monst
*mtmp
;
588 if (!obj
->leashmon
&& number_leashed() >= MAXLEASHED
) {
589 You("cannot leash any more pets.");
593 if (!get_adjacent_loc((char *) 0, (char *) 0, u
.ux
, u
.uy
, &cc
))
596 if ((cc
.x
== u
.ux
) && (cc
.y
== u
.uy
)) {
597 if (u
.usteed
&& u
.dz
> 0) {
602 pline("Leash yourself? Very funny...");
606 if (!(mtmp
= m_at(cc
.x
, cc
.y
))) {
607 There("is no creature there.");
611 spotmon
= canspotmon(mtmp
);
616 There("is no creature there.");
618 pline("%s %s leashed!", Monnam(mtmp
),
619 (!obj
->leashmon
) ? "cannot be" : "is not");
622 if (!obj
->leashmon
) {
623 if (mtmp
->mleashed
) {
624 pline("This %s is already leashed.",
625 spotmon
? l_monnam(mtmp
) : "monster");
628 if (!leashable(mtmp
)) {
629 pline("The leash won't fit onto %s%s.", spotmon
? "your " : "",
634 You("slip the leash around %s%s.", spotmon
? "your " : "",
637 obj
->leashmon
= (int) mtmp
->m_id
;
641 if (obj
->leashmon
!= (int) mtmp
->m_id
) {
642 pline("This leash is not attached to that creature.");
646 pline_The("leash would not come off!");
652 You("remove the leash from %s%s.", spotmon
? "your " : "",
658 /* assuming mtmp->mleashed has been checked */
667 if (otmp
->otyp
== LEASH
&& otmp
->leashmon
== (int) mtmp
->m_id
)
671 return (struct obj
*) 0;
677 register struct monst
*mtmp
;
678 register struct obj
*otmp
;
680 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
) {
681 if (DEADMONSTER(mtmp
))
683 if (mtmp
->mleashed
) {
684 if (distu(mtmp
->mx
, mtmp
->my
) > 2)
686 if (distu(mtmp
->mx
, mtmp
->my
) > 2) {
687 for (otmp
= invent
; otmp
; otmp
= otmp
->nobj
)
688 if (otmp
->otyp
== LEASH
689 && otmp
->leashmon
== (int) mtmp
->m_id
) {
692 You_feel("%s leash go slack.",
693 (number_leashed() > 1) ? "a" : "the");
700 /* no pack mules for the Amulet */
701 if (u
.usteed
&& mon_has_amulet(u
.usteed
))
710 register struct obj
*otmp
;
711 register struct monst
*mtmp
;
713 for (otmp
= invent
; otmp
; otmp
= otmp
->nobj
) {
714 if (otmp
->otyp
!= LEASH
|| otmp
->leashmon
== 0)
716 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
) {
717 if (DEADMONSTER(mtmp
))
719 if ((int) mtmp
->m_id
== otmp
->leashmon
)
723 impossible("leash in use isn't attached to anything?");
727 if (dist2(u
.ux
, u
.uy
, mtmp
->mx
, mtmp
->my
)
728 > dist2(x
, y
, mtmp
->mx
, mtmp
->my
)) {
729 if (!um_dist(mtmp
->mx
, mtmp
->my
, 3)) {
730 ; /* still close enough */
731 } else if (otmp
->cursed
&& !breathless(mtmp
->data
)) {
732 if (um_dist(mtmp
->mx
, mtmp
->my
, 5)
733 || (mtmp
->mhp
-= rnd(2)) <= 0) {
734 long save_pacifism
= u
.uconduct
.killer
;
736 Your("leash chokes %s to death!", mon_nam(mtmp
));
737 /* hero might not have intended to kill pet, but
738 that's the result of his actions; gain experience,
739 lose pacifism, take alignment and luck hit, make
740 corpse less likely to remain tame after revival */
741 xkilled(mtmp
, XKILL_NOMSG
);
742 /* life-saving doesn't ordinarily reset this */
744 u
.uconduct
.killer
= save_pacifism
;
746 pline("%s is choked by the leash!", Monnam(mtmp
));
747 /* tameness eventually drops to 1 here (never 0) */
748 if (mtmp
->mtame
&& rn2(mtmp
->mtame
))
752 if (um_dist(mtmp
->mx
, mtmp
->my
, 5)) {
753 pline("%s leash snaps loose!", s_suffix(Monnam(mtmp
)));
754 m_unleash(mtmp
, FALSE
);
756 You("pull on the leash.");
757 if (mtmp
->data
->msound
!= MS_SILENT
)
778 return ((ACURR(A_CHA
) > 14)
779 ? ((poly_gender() == 1)
785 static const char look_str
[] = "look %s.";
791 const char *mirror
, *uvisage
;
795 boolean vis
, invis_mirror
, useeit
, monable
;
797 if (!getdir((char *) 0))
799 invis_mirror
= Invis
;
800 useeit
= !Blind
&& (!invis_mirror
|| See_invisible
);
801 uvisage
= beautiful();
802 mirror
= simpleonames(obj
); /* "mirror" or "looking glass" */
803 if (obj
->cursed
&& !rn2(2)) {
805 pline_The("%s fogs up and doesn't reflect!", mirror
);
808 if (!u
.dx
&& !u
.dy
&& !u
.dz
) {
810 You_cant("see your %s %s.", uvisage
, body_part(FACE
));
812 if (u
.umonnum
== PM_FLOATING_EYE
) {
814 You("stiffen momentarily under your gaze.");
817 pline("Yow! The %s stares back!", mirror
);
819 pline("Yikes! You've frozen yourself!");
820 if (!Hallucination
|| !rn2(4)) {
821 nomul(-rnd(MAXULEV
+ 6 - u
.ulevel
));
822 multi_reason
= "gazing into a mirror";
824 nomovemsg
= 0; /* default, "you can move again" */
826 } else if (youmonst
.data
->mlet
== S_VAMPIRE
)
827 You("don't have a reflection.");
828 else if (u
.umonnum
== PM_UMBER_HULK
) {
829 pline("Huh? That doesn't look like you!");
830 make_confused(HConfusion
+ d(3, 4), FALSE
);
831 } else if (Hallucination
)
832 You(look_str
, hcolor((char *) 0));
834 You(look_str
, "peaked");
835 else if (u
.uhs
>= WEAK
)
836 You(look_str
, "undernourished");
838 You("look as %s as ever.", uvisage
);
844 You("reflect %s %s.", s_suffix(mon_nam(u
.ustuck
)),
845 mbodypart(u
.ustuck
, STOMACH
));
850 You(Hallucination
? "give the fish a chance to fix their makeup."
851 : "reflect the murky water.");
856 You("reflect the %s.",
857 (u
.dz
> 0) ? surface(u
.ux
, u
.uy
) : ceiling(u
.ux
, u
.uy
));
860 mtmp
= bhit(u
.dx
, u
.dy
, COLNO
, INVIS_BEAM
,
861 (int FDECL((*), (MONST_P
, OBJ_P
))) 0,
862 (int FDECL((*), (OBJ_P
, OBJ_P
))) 0, &obj
);
863 if (!mtmp
|| !haseyes(mtmp
->data
) || notonhead
)
866 /* couldsee(mtmp->mx, mtmp->my) is implied by the fact that bhit()
867 targetted it, so we can ignore possibility of X-ray vision */
868 vis
= canseemon(mtmp
);
869 /* ways to directly see monster (excludes X-ray vision, telepathy,
870 extended detection, type-specific warning) */
871 #define SEENMON (MONSEEN_NORMAL | MONSEEN_SEEINVIS | MONSEEN_INFRAVIS)
872 how_seen
= vis
? howmonseen(mtmp
) : 0;
873 /* whether monster is able to use its vision-based capabilities */
874 monable
= !mtmp
->mcan
&& (!mtmp
->minvis
|| perceives(mtmp
->data
));
875 mlet
= mtmp
->data
->mlet
;
876 if (mtmp
->msleeping
) {
878 pline("%s is too tired to look at your %s.", Monnam(mtmp
),
880 } else if (!mtmp
->mcansee
) {
882 pline("%s can't see anything right now.", Monnam(mtmp
));
883 } else if (invis_mirror
&& !perceives(mtmp
->data
)) {
885 pline("%s fails to notice your %s.", Monnam(mtmp
), mirror
);
886 /* infravision doesn't produce an image in the mirror */
887 } else if ((how_seen
& SEENMON
) == MONSEEN_INFRAVIS
) {
888 if (vis
) /* (redundant) */
889 pline("%s is too far away to see %sself in the dark.",
890 Monnam(mtmp
), mhim(mtmp
));
891 /* some monsters do special things */
892 } else if (mlet
== S_VAMPIRE
|| mlet
== S_GHOST
|| is_vampshifter(mtmp
)) {
894 pline("%s doesn't have a reflection.", Monnam(mtmp
));
895 } else if (monable
&& mtmp
->data
== &mons
[PM_MEDUSA
]) {
896 if (mon_reflects(mtmp
, "The gaze is reflected away by %s %s!"))
899 pline("%s is turned to stone!", Monnam(mtmp
));
902 } else if (monable
&& mtmp
->data
== &mons
[PM_FLOATING_EYE
]) {
903 int tmp
= d((int) mtmp
->m_lev
, (int) mtmp
->data
->mattk
[0].damd
);
907 pline("%s is frozen by its reflection.", Monnam(mtmp
));
909 You_hear("%s stop moving.", something
);
910 paralyze_monst(mtmp
, (int) mtmp
->mfrozen
+ tmp
);
911 } else if (monable
&& mtmp
->data
== &mons
[PM_UMBER_HULK
]) {
913 pline("%s confuses itself!", Monnam(mtmp
));
915 } else if (monable
&& (mlet
== S_NYMPH
|| mtmp
->data
== &mons
[PM_SUCCUBUS
]
916 || mtmp
->data
== &mons
[PM_INCUBUS
])) {
918 char buf
[BUFSZ
]; /* "She" or "He" */
920 pline("%s admires %sself in your %s.", Monnam(mtmp
), mhim(mtmp
),
922 pline("%s takes it!", upstart(strcpy(buf
, mhe(mtmp
))));
924 pline("It steals your %s!", mirror
);
925 setnotworn(obj
); /* in case mirror was wielded */
927 (void) mpickobj(mtmp
, obj
);
928 if (!tele_restrict(mtmp
))
929 (void) rloc(mtmp
, TRUE
);
930 } else if (!is_unicorn(mtmp
->data
) && !humanoid(mtmp
->data
)
931 && (!mtmp
->minvis
|| perceives(mtmp
->data
)) && rn2(5)) {
933 pline("%s is frightened by its reflection.", Monnam(mtmp
));
934 monflee(mtmp
, d(2, 4), FALSE
, FALSE
);
936 if (mtmp
->minvis
&& !See_invisible
)
938 else if ((mtmp
->minvis
&& !perceives(mtmp
->data
))
939 /* redundant: can't get here if these are true */
940 || !haseyes(mtmp
->data
) || notonhead
|| !mtmp
->mcansee
)
941 pline("%s doesn't seem to notice %s reflection.", Monnam(mtmp
),
944 pline("%s ignores %s reflection.", Monnam(mtmp
), mhis(mtmp
));
953 register struct obj
*obj
= *optr
;
955 boolean wakem
= FALSE
, learno
= FALSE
,
956 ordinary
= (obj
->otyp
!= BELL_OF_OPENING
|| !obj
->spe
),
958 (obj
->otyp
== BELL_OF_OPENING
&& invocation_pos(u
.ux
, u
.uy
)
959 && !On_stairs(u
.ux
, u
.uy
));
961 You("ring %s.", the(xname(obj
)));
963 if (Underwater
|| (u
.uswallow
&& ordinary
)) {
965 amii_speaker(obj
, "AhDhGqEqDhEhAqDqFhGw", AMII_MUFFLED_VOLUME
);
967 pline("But the sound is muffled.");
969 } else if (invoking
&& ordinary
) {
970 /* needs to be recharged... */
971 pline("But it makes no sound.");
972 learno
= TRUE
; /* help player figure out why */
974 } else if (ordinary
) {
976 amii_speaker(obj
, "ahdhgqeqdhehaqdqfhgw", AMII_MUFFLED_VOLUME
);
978 if (obj
->cursed
&& !rn2(4)
979 /* note: once any of them are gone, we stop all of them */
980 && !(mvitals
[PM_WOOD_NYMPH
].mvflags
& G_GONE
)
981 && !(mvitals
[PM_WATER_NYMPH
].mvflags
& G_GONE
)
982 && !(mvitals
[PM_MOUNTAIN_NYMPH
].mvflags
& G_GONE
)
983 && (mtmp
= makemon(mkclass(S_NYMPH
, 0), u
.ux
, u
.uy
, NO_MINVENT
))
985 You("summon %s!", a_monnam(mtmp
));
986 if (!obj_resists(obj
, 93, 100)) {
987 pline("%s shattered!", Tobjnam(obj
, "have"));
995 mon_adjust_speed(mtmp
, 2, (struct obj
*) 0);
997 case 2: /* no explanation; it just happens... */
1007 /* charged Bell of Opening */
1008 consume_obj_charge(obj
, TRUE
);
1014 pline1(nothing_happens
);
1016 } else if (obj
->cursed
) {
1021 mkundead(&mm
, FALSE
, NO_MINVENT
);
1024 } else if (invoking
) {
1025 pline("%s an unsettling shrill sound...", Tobjnam(obj
, "issue"));
1027 amii_speaker(obj
, "aefeaefeaefeaefeaefe", AMII_LOUDER_VOLUME
);
1033 } else if (obj
->blessed
) {
1037 amii_speaker(obj
, "ahahahDhEhCw", AMII_SOFT_VOLUME
);
1042 } else if (u
.utrap
&& u
.utraptype
== TT_BURIEDBALL
) {
1043 buried_ball_to_freedom();
1049 pline1(nothing_happens
);
1052 pline("%s opens...", Something
);
1056 pline("Things open around you...");
1061 } else { /* uncursed */
1063 amii_speaker(obj
, "AeFeaeFeAefegw", AMII_OKAY_VOLUME
);
1068 pline1(nothing_happens
);
1071 } /* charged BofO */
1074 makeknown(BELL_OF_OPENING
);
1082 use_candelabrum(obj
)
1083 register struct obj
*obj
;
1085 const char *s
= (obj
->spe
!= 1) ? "candles" : "candle";
1088 You("snuff the %s.", s
);
1089 end_burn(obj
, TRUE
);
1092 if (obj
->spe
<= 0) {
1093 pline("This %s has no %s.", xname(obj
), s
);
1097 You("cannot make fire under water.");
1100 if (u
.uswallow
|| obj
->cursed
) {
1102 pline_The("%s %s for a moment, then %s.", s
, vtense(s
, "flicker"),
1107 There("%s only %d %s in %s.", vtense(s
, "are"), obj
->spe
, s
,
1110 pline("%s lit. %s dimly.", obj
->spe
== 1 ? "It is" : "They are",
1111 Tobjnam(obj
, "shine"));
1113 pline("%s's %s burn%s", The(xname(obj
)), s
,
1114 (Blind
? "." : " brightly!"));
1116 if (!invocation_pos(u
.ux
, u
.uy
) || On_stairs(u
.ux
, u
.uy
)) {
1117 pline_The("%s %s being rapidly consumed!", s
, vtense(s
, "are"));
1118 /* this used to be obj->age /= 2, rounding down; an age of
1119 1 would yield 0, confusing begin_burn() and producing an
1120 unlightable, unrefillable candelabrum; round up instead */
1121 obj
->age
= (obj
->age
+ 1L) / 2L;
1123 if (obj
->spe
== 7) {
1125 pline("%s a strange warmth!", Tobjnam(obj
, "radiate"));
1127 pline("%s with a strange light!", Tobjnam(obj
, "glow"));
1131 begin_burn(obj
, FALSE
);
1138 register struct obj
*obj
= *optr
;
1139 register struct obj
*otmp
;
1140 const char *s
= (obj
->quan
!= 1) ? "candles" : "candle";
1141 char qbuf
[QBUFSZ
], qsfx
[QBUFSZ
], *q
;
1148 otmp
= carrying(CANDELABRUM_OF_INVOCATION
);
1149 if (!otmp
|| otmp
->spe
== 7) {
1154 /* first, minimal candelabrum suffix for formatting candles */
1155 Sprintf(qsfx
, " to\033%s?", thesimpleoname(otmp
));
1156 /* next, format the candles as a prefix for the candelabrum */
1157 (void) safe_qbuf(qbuf
, "Attach ", qsfx
, obj
, yname
, thesimpleoname
, s
);
1158 /* strip temporary candelabrum suffix */
1159 if ((q
= strstri(qbuf
, " to\033")) != 0)
1161 /* last, format final "attach candles to candelabrum?" query */
1162 if (yn(safe_qbuf(qbuf
, qbuf
, "?", otmp
, yname
, thesimpleoname
, "it"))
1167 if ((long) otmp
->spe
+ obj
->quan
> 7L) {
1168 obj
= splitobj(obj
, 7L - (long) otmp
->spe
);
1169 /* avoid a grammatical error if obj->quan gets
1170 reduced to 1 candle from more than one */
1171 s
= (obj
->quan
!= 1) ? "candles" : "candle";
1174 You("attach %ld%s %s to %s.", obj
->quan
, !otmp
->spe
? "" : " more", s
,
1176 if (!otmp
->spe
|| otmp
->age
> obj
->age
)
1177 otmp
->age
= obj
->age
;
1178 otmp
->spe
+= (int) obj
->quan
;
1179 if (otmp
->lamplit
&& !obj
->lamplit
)
1180 pline_The("new %s magically %s!", s
, vtense(s
, "ignite"));
1181 else if (!otmp
->lamplit
&& obj
->lamplit
)
1182 pline("%s out.", (obj
->quan
> 1L) ? "They go" : "It goes");
1184 verbalize("You %s %s, you bought %s!",
1185 otmp
->lamplit
? "burn" : "use",
1186 (obj
->quan
> 1L) ? "them" : "it",
1187 (obj
->quan
> 1L) ? "them" : "it");
1188 if (obj
->quan
< 7L && otmp
->spe
== 7)
1189 pline("%s now has seven%s candles attached.", The(xname(otmp
)),
1190 otmp
->lamplit
? " lit" : "");
1191 /* candelabrum's light range might increase */
1193 obj_merge_light_sources(otmp
, otmp
);
1194 /* candles are no longer a separate light source */
1196 end_burn(obj
, TRUE
);
1197 /* candles are now gone */
1202 /* call in drop, throw, and put in box, etc. */
1207 boolean candle
= Is_candle(otmp
);
1209 if ((candle
|| otmp
->otyp
== CANDELABRUM_OF_INVOCATION
)
1213 boolean many
= candle
? (otmp
->quan
> 1L) : (otmp
->spe
> 1);
1215 (void) get_obj_location(otmp
, &x
, &y
, 0);
1216 if (otmp
->where
== OBJ_MINVENT
? cansee(x
, y
) : !Blind
)
1217 pline("%s%scandle%s flame%s extinguished.", Shk_Your(buf
, otmp
),
1218 (candle
? "" : "candelabrum's "), (many
? "s'" : "'s"),
1219 (many
? "s are" : " is"));
1220 end_burn(otmp
, TRUE
);
1226 /* called when lit lamp is hit by water or put into a container or
1227 you've been swallowed by a monster; obj might be in transit while
1228 being thrown or dropped so don't assume that its location is valid */
1236 if (obj
->otyp
== OIL_LAMP
|| obj
->otyp
== MAGIC_LAMP
1237 || obj
->otyp
== BRASS_LANTERN
|| obj
->otyp
== POT_OIL
) {
1238 (void) get_obj_location(obj
, &x
, &y
, 0);
1239 if (obj
->where
== OBJ_MINVENT
? cansee(x
, y
) : !Blind
)
1240 pline("%s %s out!", Yname2(obj
), otense(obj
, "go"));
1241 end_burn(obj
, TRUE
);
1244 if (snuff_candle(obj
))
1250 /* Called when potentially lightable object is affected by fire_damage().
1251 Return TRUE if object was lit and FALSE otherwise --ALI */
1258 if (!obj
->lamplit
&& (obj
->otyp
== MAGIC_LAMP
|| ignitable(obj
))) {
1259 if ((obj
->otyp
== MAGIC_LAMP
1260 || obj
->otyp
== CANDELABRUM_OF_INVOCATION
) && obj
->spe
== 0)
1262 else if (obj
->otyp
!= MAGIC_LAMP
&& obj
->age
== 0)
1264 if (!get_obj_location(obj
, &x
, &y
, 0))
1266 if (obj
->otyp
== CANDELABRUM_OF_INVOCATION
&& obj
->cursed
)
1268 if ((obj
->otyp
== OIL_LAMP
|| obj
->otyp
== MAGIC_LAMP
1269 || obj
->otyp
== BRASS_LANTERN
) && obj
->cursed
&& !rn2(2))
1271 if (obj
->where
== OBJ_MINVENT
? cansee(x
, y
) : !Blind
)
1272 pline("%s %s light!", Yname2(obj
), otense(obj
, "catch"));
1273 if (obj
->otyp
== POT_OIL
)
1274 makeknown(obj
->otyp
);
1275 if (carried(obj
) && obj
->unpaid
&& costly_spot(u
.ux
, u
.uy
)) {
1276 /* if it catches while you have it, then it's your tough luck */
1278 verbalize("That's in addition to the cost of %s %s, of course.",
1279 yname(obj
), obj
->quan
== 1L ? "itself" : "themselves");
1280 bill_dummy_object(obj
);
1282 begin_burn(obj
, FALSE
);
1295 if (obj
->otyp
== OIL_LAMP
|| obj
->otyp
== MAGIC_LAMP
1296 || obj
->otyp
== BRASS_LANTERN
)
1297 pline("%slamp is now off.", Shk_Your(buf
, obj
));
1299 You("snuff out %s.", yname(obj
));
1300 end_burn(obj
, TRUE
);
1304 pline(!Is_candle(obj
) ? "This is not a diving lamp"
1305 : "Sorry, fire and water don't mix.");
1308 /* magic lamps with an spe == 0 (wished for) cannot be lit */
1309 if ((!Is_candle(obj
) && obj
->age
== 0)
1310 || (obj
->otyp
== MAGIC_LAMP
&& obj
->spe
== 0)) {
1311 if (obj
->otyp
== BRASS_LANTERN
)
1312 Your("lamp has run out of power.");
1314 pline("This %s has no oil.", xname(obj
));
1317 if (obj
->cursed
&& !rn2(2)) {
1319 pline("%s for a moment, then %s.", Tobjnam(obj
, "flicker"),
1320 otense(obj
, "die"));
1322 if (obj
->otyp
== OIL_LAMP
|| obj
->otyp
== MAGIC_LAMP
1323 || obj
->otyp
== BRASS_LANTERN
) {
1325 pline("%slamp is now on.", Shk_Your(buf
, obj
));
1326 } else { /* candle(s) */
1327 pline("%s flame%s %s%s", s_suffix(Yname2(obj
)), plur(obj
->quan
),
1328 otense(obj
, "burn"), Blind
? "." : " brightly!");
1329 if (obj
->unpaid
&& costly_spot(u
.ux
, u
.uy
)
1330 && obj
->age
== 20L * (long) objects
[obj
->otyp
].oc_cost
) {
1331 const char *ithem
= (obj
->quan
> 1L) ? "them" : "it";
1333 verbalize("You burn %s, you bought %s!", ithem
, ithem
);
1334 bill_dummy_object(obj
);
1337 begin_burn(obj
, FALSE
);
1342 light_cocktail(optr
)
1345 struct obj
*obj
= *optr
; /* obj is a potion of oil */
1355 You("snuff the lit potion.");
1356 end_burn(obj
, TRUE
);
1358 * Free & add to re-merge potion. This will average the
1359 * age of the potions. Not exactly the best solution,
1363 *optr
= addinv(obj
);
1365 } else if (Underwater
) {
1366 There("is not enough oxygen to sustain a fire.");
1370 split1off
= (obj
->quan
> 1L);
1372 obj
= splitobj(obj
, 1L);
1374 You("light %spotion.%s", shk_your(buf
, obj
),
1375 Blind
? "" : " It gives off a dim light.");
1377 if (obj
->unpaid
&& costly_spot(u
.ux
, u
.uy
)) {
1378 /* Normally, we shouldn't both partially and fully charge
1379 * for an item, but (Yendorian Fuel) Taxes are inevitable...
1382 verbalize("That's in addition to the cost of the potion, of course.");
1383 bill_dummy_object(obj
);
1385 makeknown(obj
->otyp
);
1387 begin_burn(obj
, FALSE
); /* after shop billing */
1389 obj_extract_self(obj
); /* free from inv */
1391 obj
= hold_another_object(obj
, "You drop %s!", doname(obj
),
1399 static NEARDATA
const char cuddly
[] = { TOOL_CLASS
, GEM_CLASS
, 0 };
1404 struct obj
*obj
= getobj(cuddly
, "rub");
1406 if (obj
&& obj
->oclass
== GEM_CLASS
) {
1407 if (is_graystone(obj
)) {
1411 pline("Sorry, I don't know how to use that.");
1416 if (!obj
|| !wield_tool(obj
, "rub"))
1419 /* now uwep is obj */
1420 if (uwep
->otyp
== MAGIC_LAMP
) {
1421 if (uwep
->spe
> 0 && !rn2(3)) {
1422 check_unpaid_usage(uwep
, TRUE
); /* unusual item use */
1423 /* bones preparation: perform the lamp transformation
1424 before releasing the djinni in case the latter turns out
1425 to be fatal (a hostile djinni has no chance to attack yet,
1426 but an indebted one who grants a wish might bestow an
1427 artifact which blasts the hero with lethal results) */
1428 uwep
->otyp
= OIL_LAMP
;
1429 uwep
->spe
= 0; /* for safety */
1430 uwep
->age
= rn1(500, 1000);
1432 begin_burn(uwep
, TRUE
);
1433 djinni_from_bottle(uwep
);
1434 makeknown(MAGIC_LAMP
);
1436 } else if (rn2(2)) {
1437 You("%s smoke.", !Blind
? "see a puff of" : "smell");
1439 pline1(nothing_happens
);
1440 } else if (obj
->otyp
== BRASS_LANTERN
) {
1441 /* message from Adventure */
1442 pline("Rubbing the electric lamp is not particularly rewarding.");
1443 pline("Anyway, nothing exciting happens.");
1445 pline1(nothing_happens
);
1456 enum jump_trajectory
{
1457 jAny
= 0, /* any direction => magical jump */
1460 jDiag
= 3 /* jHorz|jVert */
1463 /* callback routine for walk_path() */
1465 check_jump(arg
, x
, y
)
1469 int traj
= *(int *) arg
;
1470 struct rm
*lev
= &levl
[x
][y
];
1474 if (IS_STWALL(lev
->typ
))
1476 if (IS_DOOR(lev
->typ
)) {
1477 if (closed_door(x
, y
))
1479 if ((lev
->doormask
& D_ISOPEN
) != 0 && traj
!= jAny
1480 /* reject diagonal jump into or out-of or through open door */
1482 /* reject horizontal jump through horizontal open door
1483 and non-horizontal (ie, vertical) jump through
1484 non-horizontal (vertical) open door */
1485 || ((traj
& jHorz
) != 0) == (lev
->horizontal
!= 0)))
1487 /* empty doorways aren't restricted */
1489 /* let giants jump over boulders (what about Flying?
1490 and is there really enough head room for giants to jump
1491 at all, let alone over something tall?) */
1492 if (sobj_at(BOULDER
, x
, y
) && !throws_rocks(youmonst
.data
))
1498 is_valid_jump_pos(x
, y
, magic
, showmsg
)
1502 if (!magic
&& !(HJumping
& ~INTRINSIC
) && !EJumping
&& distu(x
, y
) != 5) {
1503 /* The Knight jumping restriction still applies when riding a
1504 * horse. After all, what shape is the knight piece in chess?
1507 pline("Illegal move!");
1509 } else if (distu(x
, y
) > (magic
? 6 + magic
* 3 : 9)) {
1513 } else if (!isok(x
, y
)) {
1515 You("cannot jump there!");
1517 } else if (!cansee(x
, y
)) {
1519 You("cannot see where to land!");
1523 struct rm
*lev
= &levl
[u
.ux
][u
.uy
];
1524 /* we want to categorize trajectory for use in determining
1525 passage through doorways: horizonal, vertical, or diagonal;
1526 since knight's jump and other irregular directions are
1527 possible, we flatten those out to simplify door checks */
1529 dx
= x
- u
.ux
, dy
= y
- u
.uy
,
1530 ax
= abs(dx
), ay
= abs(dy
);
1532 /* diag: any non-orthogonal destination classifed as diagonal */
1533 diag
= (magic
|| Passes_walls
|| (!dx
&& !dy
)) ? jAny
1534 : !dy
? jHorz
: !dx
? jVert
: jDiag
;
1535 /* traj: flatten out the trajectory => some diagonals re-classified */
1538 else if (ay
>= 2 * ax
)
1540 traj
= (magic
|| Passes_walls
|| (!ax
&& !ay
)) ? jAny
1541 : !ay
? jHorz
: !ax
? jVert
: jDiag
;
1542 /* walk_path doesn't process the starting spot;
1543 this is iffy: if you're starting on a closed door spot,
1544 you _can_ jump diagonally from doorway (without needing
1545 Passes_walls); that's intentional but is it correct? */
1546 if (diag
== jDiag
&& IS_DOOR(lev
->typ
)
1547 && (lev
->doormask
& D_ISOPEN
) != 0
1549 || ((traj
& jHorz
) != 0) == (lev
->horizontal
!= 0))) {
1551 You_cant("jump diagonally out of a doorway.");
1554 uc
.x
= u
.ux
, uc
.y
= u
.uy
;
1555 tc
.x
= x
, tc
.y
= y
; /* target */
1556 if (!walk_path(&uc
, &tc
, check_jump
, (genericptr_t
) &traj
)) {
1558 There("is an obstacle preventing that jump.");
1565 static int jumping_is_magic
;
1568 display_jump_positions(state
)
1572 tmp_at(DISP_BEAM
, cmap_to_glyph(S_goodpos
));
1573 } else if (state
== 1) {
1576 for (dx
= -4; dx
<= 4; dx
++)
1577 for (dy
= -4; dy
<= 4; dy
++) {
1578 x
= dx
+ (int) u
.ux
;
1579 y
= dy
+ (int) u
.uy
;
1581 && (ACCESSIBLE(levl
[x
][y
].typ
) || Passes_walls
)
1582 && is_valid_jump_pos(x
, y
, jumping_is_magic
, FALSE
))
1586 tmp_at(DISP_END
, 0);
1592 int magic
; /* 0=Physical, otherwise skill level */
1596 /* attempt "jumping" spell if hero has no innate jumping ability */
1597 if (!magic
&& !Jumping
) {
1600 for (sp_no
= 0; sp_no
< MAXSPELL
; ++sp_no
)
1601 if (spl_book
[sp_no
].sp_id
== NO_SPELL
)
1603 else if (spl_book
[sp_no
].sp_id
== SPE_JUMPING
)
1604 return spelleffects(sp_no
, FALSE
);
1607 if (!magic
&& (nolimbs(youmonst
.data
) || slithy(youmonst
.data
))) {
1608 /* normally (nolimbs || slithy) implies !Jumping,
1609 but that isn't necessarily the case for knights */
1610 You_cant("jump; you have no legs!");
1612 } else if (!magic
&& !Jumping
) {
1613 You_cant("jump very far.");
1615 /* if steed is immobile, can't do physical jump but can do spell one */
1616 } else if (!magic
&& u
.usteed
&& stucksteed(FALSE
)) {
1617 /* stucksteed gave "<steed> won't move" message */
1619 } else if (u
.uswallow
) {
1621 You("bounce around a little.");
1624 pline("You've got to be kidding!");
1626 } else if (u
.uinwater
) {
1628 You("swish around a little.");
1631 pline("This calls for swimming, not jumping!");
1633 } else if (u
.ustuck
) {
1634 if (u
.ustuck
->mtame
&& !Conflict
&& !u
.ustuck
->mconf
) {
1635 You("pull free from %s.", mon_nam(u
.ustuck
));
1640 You("writhe a little in the grasp of %s!", mon_nam(u
.ustuck
));
1643 You("cannot escape from %s!", mon_nam(u
.ustuck
));
1645 } else if (Levitation
|| Is_airlevel(&u
.uz
) || Is_waterlevel(&u
.uz
)) {
1647 You("flail around a little.");
1650 You("don't have enough traction to jump.");
1652 } else if (!magic
&& near_capacity() > UNENCUMBERED
) {
1653 You("are carrying too much to jump!");
1655 } else if (!magic
&& (u
.uhunger
<= 100 || ACURR(A_STR
) < 6)) {
1656 You("lack the strength to jump!");
1658 } else if (!magic
&& Wounded_legs
) {
1659 long wl
= (Wounded_legs
& BOTH_SIDES
);
1660 const char *bp
= body_part(LEG
);
1662 if (wl
== BOTH_SIDES
)
1663 bp
= makeplural(bp
);
1665 pline("%s is in no shape for jumping.", Monnam(u
.usteed
));
1667 Your("%s%s %s in no shape for jumping.",
1668 (wl
== LEFT_SIDE
) ? "left " : (wl
== RIGHT_SIDE
) ? "right "
1670 bp
, (wl
== BOTH_SIDES
) ? "are" : "is");
1672 } else if (u
.usteed
&& u
.utrap
) {
1673 pline("%s is stuck in a trap.", Monnam(u
.usteed
));
1677 pline("Where do you want to jump?");
1680 jumping_is_magic
= magic
;
1681 getpos_sethilite(display_jump_positions
);
1682 if (getpos(&cc
, TRUE
, "the desired position") < 0)
1683 return 0; /* user pressed ESC */
1684 if (!is_valid_jump_pos(cc
.x
, cc
.y
, magic
, TRUE
)) {
1691 switch (u
.utraptype
) {
1693 long side
= rn2(3) ? LEFT_SIDE
: RIGHT_SIDE
;
1695 You("rip yourself free of the bear trap! Ouch!");
1696 losehp(Maybe_Half_Phys(rnd(10)), "jumping out of a bear trap",
1698 set_wounded_legs(side
, rn1(1000, 500));
1702 You("leap from the pit!");
1705 You("tear the web apart as you pull yourself free!");
1706 deltrap(t_at(u
.ux
, u
.uy
));
1709 You("pull yourself above the %s!", hliquid("lava"));
1714 You("strain your %s, but you're still %s.",
1715 makeplural(body_part(LEG
)),
1716 (u
.utraptype
== TT_INFLOOR
)
1717 ? "stuck in the floor"
1718 : "attached to the buried ball");
1719 set_wounded_legs(LEFT_SIDE
, rn1(10, 11));
1720 set_wounded_legs(RIGHT_SIDE
, rn1(10, 11));
1725 * Check the path from uc to cc, calling hurtle_step at each
1726 * location. The final position actually reached will be
1731 /* calculate max(abs(dx), abs(dy)) as the range */
1732 range
= cc
.x
- uc
.x
;
1740 (void) walk_path(&uc
, &cc
, hurtle_step
, (genericptr_t
) &range
);
1741 /* hurtle_step results in (u.ux, u.uy) == (cc.x, cc.y) and usually
1742 * moves the ball if punished, but does not handle all the effects
1743 * of landing on the final position.
1745 teleds(cc
.x
, cc
.y
, FALSE
);
1748 multi_reason
= "jumping around";
1750 morehungry(rnd(25));
1761 if (!mons
[corpse
->corpsenm
].cnutrit
)
1767 use_tinning_kit(obj
)
1770 struct obj
*corpse
, *can
;
1772 /* This takes only 1 move. If this is to be changed to take many
1773 * moves, we've got to deal with decaying corpses...
1775 if (obj
->spe
<= 0) {
1776 You("seem to be out of tins.");
1779 if (!(corpse
= floorfood("tin", 2)))
1781 if (corpse
->oeaten
) {
1782 You("cannot tin %s which is partly eaten.", something
);
1785 if (touch_petrifies(&mons
[corpse
->corpsenm
]) && !Stone_resistance
1789 if (poly_when_stoned(youmonst
.data
))
1790 You("tin %s without wearing gloves.",
1791 an(mons
[corpse
->corpsenm
].mname
));
1793 pline("Tinning %s without wearing gloves is a fatal mistake...",
1794 an(mons
[corpse
->corpsenm
].mname
));
1795 Sprintf(kbuf
, "trying to tin %s without gloves",
1796 an(mons
[corpse
->corpsenm
].mname
));
1800 if (is_rider(&mons
[corpse
->corpsenm
])) {
1801 if (revive_corpse(corpse
))
1802 verbalize("Yes... But War does not preserve its enemies...");
1804 pline_The("corpse evades your grasp.");
1807 if (mons
[corpse
->corpsenm
].cnutrit
== 0) {
1808 pline("That's too insubstantial to tin.");
1811 consume_obj_charge(obj
, TRUE
);
1813 if ((can
= mksobj(TIN
, FALSE
, FALSE
)) != 0) {
1814 static const char you_buy_it
[] = "You tin it, you bought it!";
1816 can
->corpsenm
= corpse
->corpsenm
;
1817 can
->cursed
= obj
->cursed
;
1818 can
->blessed
= obj
->blessed
;
1819 can
->owt
= weight(can
);
1821 /* Mark tinned tins. No spinach allowed... */
1822 set_tin_variety(can
, HOMEMADE_TIN
);
1823 if (carried(corpse
)) {
1825 verbalize(you_buy_it
);
1828 if (costly_spot(corpse
->ox
, corpse
->oy
) && !corpse
->no_charge
)
1829 verbalize(you_buy_it
);
1832 can
= hold_another_object(can
, "You make, but cannot pick up, %s.",
1833 doname(can
), (const char *) 0);
1835 impossible("Tinning failed.");
1839 use_unicorn_horn(obj
)
1842 #define PROP_COUNT 7 /* number of properties we're dealing with */
1843 #define ATTR_COUNT (A_MAX * 3) /* number of attribute points we might fix */
1844 int idx
, val
, val_limit
, trouble_count
, unfixable_trbl
, did_prop
,
1846 int trouble_list
[PROP_COUNT
+ ATTR_COUNT
];
1848 if (obj
&& obj
->cursed
) {
1849 long lcount
= (long) rn1(90, 10);
1851 switch (rn2(13) / 2) { /* case 6 is half as likely as the others */
1853 make_sick((Sick
& TIMEOUT
) ? (Sick
& TIMEOUT
) / 3L + 1L
1854 : (long) rn1(ACURR(A_CON
), 20),
1855 xname(obj
), TRUE
, SICK_NONVOMITABLE
);
1858 make_blinded((Blinded
& TIMEOUT
) + lcount
, TRUE
);
1862 You("suddenly feel %s.",
1863 Hallucination
? "trippy" : "confused");
1864 make_confused((HConfusion
& TIMEOUT
) + lcount
, TRUE
);
1867 make_stunned((HStun
& TIMEOUT
) + lcount
, TRUE
);
1870 (void) adjattrib(rn2(A_MAX
), -1, FALSE
);
1873 (void) make_hallucinated((HHallucination
& TIMEOUT
) + lcount
,
1877 if (Deaf
) /* make_deaf() won't give feedback when already deaf */
1878 pline("Nothing seems to happen.");
1879 make_deaf((HDeaf
& TIMEOUT
) + lcount
, TRUE
);
1880 context
.botl
= TRUE
;
1887 * Entries in the trouble list use a very simple encoding scheme.
1889 #define prop2trbl(X) ((X) + A_MAX)
1890 #define attr2trbl(Y) (Y)
1891 #define prop_trouble(X) trouble_list[trouble_count++] = prop2trbl(X)
1892 #define attr_trouble(Y) trouble_list[trouble_count++] = attr2trbl(Y)
1893 #define TimedTrouble(P) (((P) && !((P) & ~TIMEOUT)) ? ((P) & TIMEOUT) : 0L)
1895 trouble_count
= unfixable_trbl
= did_prop
= did_attr
= 0;
1897 /* collect property troubles */
1898 if (TimedTrouble(Sick
))
1900 if (TimedTrouble(Blinded
) > (long) u
.ucreamed
1902 && attacktype_fordmg(u
.ustuck
->data
, AT_ENGL
, AD_BLND
)))
1903 prop_trouble(BLINDED
);
1904 if (TimedTrouble(HHallucination
))
1905 prop_trouble(HALLUC
);
1906 if (TimedTrouble(Vomiting
))
1907 prop_trouble(VOMITING
);
1908 if (TimedTrouble(HConfusion
))
1909 prop_trouble(CONFUSION
);
1910 if (TimedTrouble(HStun
))
1911 prop_trouble(STUNNED
);
1912 if (TimedTrouble(HDeaf
))
1915 unfixable_trbl
= unfixable_trouble_count(TRUE
);
1917 /* collect attribute troubles */
1918 for (idx
= 0; idx
< A_MAX
; idx
++) {
1919 if (ABASE(idx
) >= AMAX(idx
))
1921 val_limit
= AMAX(idx
);
1922 /* don't recover strength lost from hunger */
1923 if (idx
== A_STR
&& u
.uhs
>= WEAK
)
1926 /* potion/spell of restore ability override sustain ability
1927 intrinsic but unicorn horn usage doesn't */
1928 unfixable_trbl
+= val_limit
- ABASE(idx
);
1931 /* don't recover more than 3 points worth of any attribute */
1932 if (val_limit
> ABASE(idx
) + 3)
1933 val_limit
= ABASE(idx
) + 3;
1935 for (val
= ABASE(idx
); val
< val_limit
; val
++)
1937 /* keep track of unfixed trouble, for message adjustment below */
1938 unfixable_trbl
+= (AMAX(idx
) - val_limit
);
1941 if (trouble_count
== 0) {
1942 pline1(nothing_happens
);
1944 } else if (trouble_count
> 1) { /* shuffle */
1947 for (i
= trouble_count
- 1; i
> 0; i
--)
1948 if ((j
= rn2(i
+ 1)) != i
) {
1949 k
= trouble_list
[j
];
1950 trouble_list
[j
] = trouble_list
[i
];
1951 trouble_list
[i
] = k
;
1956 * Chances for number of troubles to be fixed
1958 * blessed: 22.7% 22.7% 19.5% 15.4% 10.7% 5.7% 2.6% 0.8%
1959 * uncursed: 35.4% 35.4% 22.9% 6.3% 0 0 0 0
1961 val_limit
= rn2(d(2, (obj
&& obj
->blessed
) ? 4 : 2));
1962 if (val_limit
> trouble_count
)
1963 val_limit
= trouble_count
;
1965 /* fix [some of] the troubles */
1966 for (val
= 0; val
< val_limit
; val
++) {
1967 idx
= trouble_list
[val
];
1970 case prop2trbl(SICK
):
1971 make_sick(0L, (char *) 0, TRUE
, SICK_ALL
);
1974 case prop2trbl(BLINDED
):
1975 make_blinded((long) u
.ucreamed
, TRUE
);
1978 case prop2trbl(HALLUC
):
1979 (void) make_hallucinated(0L, TRUE
, 0L);
1982 case prop2trbl(VOMITING
):
1983 make_vomiting(0L, TRUE
);
1986 case prop2trbl(CONFUSION
):
1987 make_confused(0L, TRUE
);
1990 case prop2trbl(STUNNED
):
1991 make_stunned(0L, TRUE
);
1994 case prop2trbl(DEAF
):
1995 make_deaf(0L, TRUE
);
1999 if (idx
>= 0 && idx
< A_MAX
) {
2003 panic("use_unicorn_horn: bad trouble? (%d)", idx
);
2009 pline("This makes you feel %s!",
2010 (did_prop
+ did_attr
) == (trouble_count
+ unfixable_trbl
)
2014 pline("Nothing seems to happen.");
2016 context
.botl
= (did_attr
|| did_prop
);
2027 * Timer callback routine: turn figurine into monster
2030 fig_transform(arg
, timeout
)
2034 struct obj
*figurine
= arg
->a_obj
;
2037 boolean cansee_spot
, silent
, okay_spot
;
2038 boolean redraw
= FALSE
;
2039 boolean suppress_see
= FALSE
;
2040 char monnambuf
[BUFSZ
], carriedby
[BUFSZ
];
2043 debugpline0("null figurine in fig_transform()");
2046 silent
= (timeout
!= monstermoves
); /* happened while away */
2047 okay_spot
= get_obj_location(figurine
, &cc
.x
, &cc
.y
, 0);
2048 if (figurine
->where
== OBJ_INVENT
|| figurine
->where
== OBJ_MINVENT
)
2049 okay_spot
= enexto(&cc
, cc
.x
, cc
.y
, &mons
[figurine
->corpsenm
]);
2050 if (!okay_spot
|| !figurine_location_checks(figurine
, &cc
, TRUE
)) {
2051 /* reset the timer to try again later */
2052 (void) start_timer((long) rnd(5000), TIMER_OBJECT
, FIG_TRANSFORM
,
2053 obj_to_any(figurine
));
2057 cansee_spot
= cansee(cc
.x
, cc
.y
);
2058 mtmp
= make_familiar(figurine
, cc
.x
, cc
.y
, TRUE
);
2060 char and_vanish
[BUFSZ
];
2061 struct obj
*mshelter
= level
.objects
[mtmp
->mx
][mtmp
->my
];
2063 Sprintf(monnambuf
, "%s", an(m_monnam(mtmp
)));
2064 and_vanish
[0] = '\0';
2065 if ((mtmp
->minvis
&& !See_invisible
)
2066 || (mtmp
->data
->mlet
== S_MIMIC
2067 && mtmp
->m_ap_type
!= M_AP_NOTHING
))
2068 suppress_see
= TRUE
;
2070 if (mtmp
->mundetected
) {
2071 if (hides_under(mtmp
->data
) && mshelter
) {
2072 Sprintf(and_vanish
, " and %s under %s",
2073 locomotion(mtmp
->data
, "crawl"), doname(mshelter
));
2074 } else if (mtmp
->data
->mlet
== S_MIMIC
2075 || mtmp
->data
->mlet
== S_EEL
) {
2076 suppress_see
= TRUE
;
2078 Strcpy(and_vanish
, " and vanish");
2081 switch (figurine
->where
) {
2083 if (Blind
|| suppress_see
)
2084 You_feel("%s %s from your pack!", something
,
2085 locomotion(mtmp
->data
, "drop"));
2087 You_see("%s %s out of your pack%s!", monnambuf
,
2088 locomotion(mtmp
->data
, "drop"), and_vanish
);
2092 if (cansee_spot
&& !silent
) {
2094 pline("%s suddenly vanishes!", an(xname(figurine
)));
2096 You_see("a figurine transform into %s%s!", monnambuf
,
2098 redraw
= TRUE
; /* update figurine's map location */
2103 if (cansee_spot
&& !silent
&& !suppress_see
) {
2106 mon
= figurine
->ocarry
;
2107 /* figurine carrying monster might be invisible */
2108 if (canseemon(figurine
->ocarry
)
2109 && (!mon
->wormno
|| cansee(mon
->mx
, mon
->my
)))
2110 Sprintf(carriedby
, "%s pack", s_suffix(a_monnam(mon
)));
2111 else if (is_pool(mon
->mx
, mon
->my
))
2112 Strcpy(carriedby
, "empty water");
2114 Strcpy(carriedby
, "thin air");
2115 You_see("%s %s out of %s%s!", monnambuf
,
2116 locomotion(mtmp
->data
, "drop"), carriedby
,
2126 impossible("figurine came to life where? (%d)",
2127 (int) figurine
->where
);
2131 /* free figurine now */
2132 if (carried(figurine
)) {
2135 obj_extract_self(figurine
);
2136 obfree(figurine
, (struct obj
*) 0);
2143 figurine_location_checks(obj
, cc
, quietly
)
2150 if (carried(obj
) && u
.uswallow
) {
2152 You("don't have enough room in here.");
2155 x
= cc
? cc
->x
: u
.ux
;
2156 y
= cc
? cc
->y
: u
.uy
;
2159 You("cannot put the figurine there.");
2162 if (IS_ROCK(levl
[x
][y
].typ
)
2163 && !(passes_walls(&mons
[obj
->corpsenm
]) && may_passwall(x
, y
))) {
2165 You("cannot place a figurine in %s!",
2166 IS_TREE(levl
[x
][y
].typ
) ? "a tree" : "solid rock");
2169 if (sobj_at(BOULDER
, x
, y
) && !passes_walls(&mons
[obj
->corpsenm
])
2170 && !throws_rocks(&mons
[obj
->corpsenm
])) {
2172 You("cannot fit the figurine on the boulder.");
2182 register struct obj
*obj
= *optr
;
2187 /* can't activate a figurine while swallowed */
2188 if (!figurine_location_checks(obj
, (coord
*) 0, FALSE
))
2191 if (!getdir((char *) 0)) {
2192 context
.move
= multi
= 0;
2199 /* Passing FALSE arg here will result in messages displayed */
2200 if (!figurine_location_checks(obj
, &cc
, FALSE
))
2202 You("%s and it transforms.",
2203 (u
.dx
|| u
.dy
) ? "set the figurine beside you"
2204 : (Is_airlevel(&u
.uz
) || Is_waterlevel(&u
.uz
)
2205 || is_pool(cc
.x
, cc
.y
))
2206 ? "release the figurine"
2207 : (u
.dz
< 0 ? "toss the figurine into the air"
2208 : "set the figurine on the ground"));
2209 (void) make_familiar(obj
, cc
.x
, cc
.y
, FALSE
);
2210 (void) stop_timer(FIG_TRANSFORM
, obj_to_any(obj
));
2215 static NEARDATA
const char lubricables
[] = { ALL_CLASSES
, ALLOW_NONE
, 0 };
2224 pline("%s from your %s.", Tobjnam(obj
, "slip"),
2225 makeplural(body_part(FINGER
)));
2231 if ((obj
->cursed
|| Fumbling
) && !rn2(2)) {
2232 consume_obj_charge(obj
, TRUE
);
2234 pline("%s from your %s.", Tobjnam(obj
, "slip"),
2235 makeplural(body_part(FINGER
)));
2239 otmp
= getobj(lubricables
, "grease");
2242 if (inaccessible_equipment(otmp
, "grease", FALSE
))
2244 consume_obj_charge(obj
, TRUE
);
2246 if (otmp
!= &zeroobj
) {
2247 You("cover %s with a thick layer of grease.", yname(otmp
));
2249 if (obj
->cursed
&& !nohands(youmonst
.data
)) {
2250 incr_itimeout(&Glib
, rnd(15));
2251 pline("Some of the grease gets all over your %s.",
2252 makeplural(body_part(HAND
)));
2255 incr_itimeout(&Glib
, rnd(15));
2256 You("coat your %s with grease.", makeplural(body_part(FINGER
)));
2260 pline("%s empty.", Tobjnam(obj
, "are"));
2262 pline("%s to be empty.", Tobjnam(obj
, "seem"));
2267 /* touchstones - by Ken Arnold */
2274 const char *streak_color
, *choices
;
2275 char stonebuf
[QBUFSZ
];
2276 static const char scritch
[] = "\"scritch, scritch\"";
2277 static const char allowall
[3] = { COIN_CLASS
, ALL_CLASSES
, 0 };
2278 static const char coins_gems
[3] = { COIN_CLASS
, GEM_CLASS
, 0 };
2280 /* in case it was acquired while blinded */
2283 /* when the touchstone is fully known, don't bother listing extra
2284 junk as likely candidates for rubbing */
2285 choices
= (tstone
->otyp
== TOUCHSTONE
&& tstone
->dknown
2286 && objects
[TOUCHSTONE
].oc_name_known
)
2289 Sprintf(stonebuf
, "rub on the stone%s", plur(tstone
->quan
));
2290 if ((obj
= getobj(choices
, stonebuf
)) == 0)
2293 if (obj
== tstone
&& obj
->quan
== 1L) {
2294 You_cant("rub %s on itself.", the(xname(obj
)));
2298 if (tstone
->otyp
== TOUCHSTONE
&& tstone
->cursed
2299 && obj
->oclass
== GEM_CLASS
&& !is_graystone(obj
)
2300 && !obj_resists(obj
, 80, 100)) {
2302 pline("You feel something shatter.");
2303 else if (Hallucination
)
2304 pline("Oh, wow, look at the pretty shards.");
2306 pline("A sharp crack shatters %s%s.",
2307 (obj
->quan
> 1L) ? "one of " : "", the(xname(obj
)));
2315 } else if (Hallucination
) {
2316 pline("Oh wow, man: Fractals!");
2323 switch (obj
->oclass
) {
2324 case GEM_CLASS
: /* these have class-specific handling below */
2326 if (tstone
->otyp
!= TOUCHSTONE
) {
2328 } else if (obj
->oclass
== GEM_CLASS
2330 || (!tstone
->cursed
&& (Role_if(PM_ARCHEOLOGIST
)
2331 || Race_if(PM_GNOME
))))) {
2332 makeknown(TOUCHSTONE
);
2333 makeknown(obj
->otyp
);
2334 prinv((char *) 0, obj
, 0L);
2337 /* either a ring or the touchstone was not effective */
2338 if (objects
[obj
->otyp
].oc_material
== GLASS
) {
2343 streak_color
= c_obj_colors
[objects
[obj
->otyp
].oc_color
];
2344 break; /* gem or ring */
2347 switch (objects
[obj
->otyp
].oc_material
) {
2349 pline("%s a little more polished now.", Tobjnam(tstone
, "look"));
2352 if (!obj
->known
) /* note: not "whetstone" */
2353 You("must think this is a wetstone, do you?");
2355 pline("%s a little wetter now.", Tobjnam(tstone
, "are"));
2358 streak_color
= "waxy";
2359 break; /* okay even if not touchstone */
2361 streak_color
= "wooden";
2362 break; /* okay even if not touchstone */
2364 do_scratch
= TRUE
; /* scratching and streaks */
2365 streak_color
= "golden";
2368 do_scratch
= TRUE
; /* scratching and streaks */
2369 streak_color
= "silvery";
2372 /* Objects passing the is_flimsy() test will not
2373 scratch a stone. They will leave streaks on
2374 non-touchstones and touchstones alike. */
2376 streak_color
= c_obj_colors
[objects
[obj
->otyp
].oc_color
];
2378 do_scratch
= (tstone
->otyp
!= TOUCHSTONE
);
2381 break; /* default oclass */
2384 Sprintf(stonebuf
, "stone%s", plur(tstone
->quan
));
2386 You("make %s%sscratch marks on the %s.",
2387 streak_color
? streak_color
: (const char *) "",
2388 streak_color
? " " : "", stonebuf
);
2389 else if (streak_color
)
2390 You_see("%s streaks on the %s.", streak_color
, stonebuf
);
2396 static struct trapinfo
{
2400 boolean force_bungle
;
2407 trapinfo
.force_bungle
= 0;
2410 /* Place a landmine/bear trap. Helge Hafting */
2416 const char *what
= (char *) 0;
2418 int levtyp
= levl
[u
.ux
][u
.uy
].typ
;
2419 const char *occutext
= "setting the trap";
2421 if (nohands(youmonst
.data
))
2422 what
= "without hands";
2424 what
= "while stunned";
2425 else if (u
.uswallow
)
2427 is_animal(u
.ustuck
->data
) ? "while swallowed" : "while engulfed";
2428 else if (Underwater
)
2429 what
= "underwater";
2430 else if (Levitation
)
2431 what
= "while levitating";
2432 else if (is_pool(u
.ux
, u
.uy
))
2434 else if (is_lava(u
.ux
, u
.uy
))
2436 else if (On_stairs(u
.ux
, u
.uy
))
2437 what
= (u
.ux
== xdnladder
|| u
.ux
== xupladder
) ? "on the ladder"
2439 else if (IS_FURNITURE(levtyp
) || IS_ROCK(levtyp
)
2440 || closed_door(u
.ux
, u
.uy
) || t_at(u
.ux
, u
.uy
))
2442 else if (Is_airlevel(&u
.uz
) || Is_waterlevel(&u
.uz
))
2443 what
= (levtyp
== AIR
)
2447 : "in this place"; /* Air/Water Plane catch-all */
2449 You_cant("set a trap %s!", what
);
2453 ttyp
= (otmp
->otyp
== LAND_MINE
) ? LANDMINE
: BEAR_TRAP
;
2454 if (otmp
== trapinfo
.tobj
&& u
.ux
== trapinfo
.tx
&& u
.uy
== trapinfo
.ty
) {
2455 You("resume setting %s%s.", shk_your(buf
, otmp
),
2456 defsyms
[trap_to_defsym(what_trap(ttyp
))].explanation
);
2457 set_occupation(set_trap
, occutext
, 0);
2460 trapinfo
.tobj
= otmp
;
2461 trapinfo
.tx
= u
.ux
, trapinfo
.ty
= u
.uy
;
2463 trapinfo
.time_needed
=
2464 (tmp
> 17) ? 2 : (tmp
> 12) ? 3 : (tmp
> 7) ? 4 : 5;
2466 trapinfo
.time_needed
*= 2;
2468 if (ttyp
== BEAR_TRAP
&& tmp
< 18)
2469 trapinfo
.time_needed
+= (tmp
> 12) ? 1 : (tmp
> 7) ? 2 : 4;
2470 /*[fumbling and/or confusion and/or cursed object check(s)
2471 should be incorporated here instead of in set_trap]*/
2472 if (u
.usteed
&& P_SKILL(P_RIDING
) < P_BASIC
) {
2475 if (Fumbling
|| otmp
->cursed
)
2476 chance
= (rnl(10) > 3);
2478 chance
= (rnl(10) > 5);
2479 You("aren't very skilled at reaching from %s.", mon_nam(u
.usteed
));
2480 Sprintf(buf
, "Continue your attempt to set %s?",
2481 the(defsyms
[trap_to_defsym(what_trap(ttyp
))].explanation
));
2482 if (yn(buf
) == 'y') {
2485 case LANDMINE
: /* set it off */
2486 trapinfo
.time_needed
= 0;
2487 trapinfo
.force_bungle
= TRUE
;
2489 case BEAR_TRAP
: /* drop it without arming it */
2492 the(defsyms
[trap_to_defsym(what_trap(ttyp
))]
2503 You("begin setting %s%s.", shk_your(buf
, otmp
),
2504 defsyms
[trap_to_defsym(what_trap(ttyp
))].explanation
);
2505 set_occupation(set_trap
, occutext
, 0);
2513 struct obj
*otmp
= trapinfo
.tobj
;
2517 if (!otmp
|| !carried(otmp
) || u
.ux
!= trapinfo
.tx
2518 || u
.uy
!= trapinfo
.ty
) {
2524 if (--trapinfo
.time_needed
> 0)
2525 return 1; /* still busy */
2527 ttyp
= (otmp
->otyp
== LAND_MINE
) ? LANDMINE
: BEAR_TRAP
;
2528 ttmp
= maketrap(u
.ux
, u
.uy
, ttyp
);
2532 if (*in_rooms(u
.ux
, u
.uy
, SHOPBASE
)) {
2533 add_damage(u
.ux
, u
.uy
, 0L); /* schedule removal */
2535 if (!trapinfo
.force_bungle
)
2536 You("finish arming %s.",
2537 the(defsyms
[trap_to_defsym(what_trap(ttyp
))].explanation
));
2538 if (((otmp
->cursed
|| Fumbling
) && (rnl(10) > 5))
2539 || trapinfo
.force_bungle
)
2541 (unsigned) (trapinfo
.force_bungle
? FORCEBUNGLE
: 0));
2543 /* this shouldn't happen */
2544 Your("trap setting attempt fails.");
2558 int rx
, ry
, proficient
, res
= 0;
2559 const char *msg_slipsfree
= "The bullwhip slips free.";
2560 const char *msg_snap
= "Snap!";
2563 if (!wield_tool(obj
, "lash"))
2568 if (!getdir((char *) 0))
2576 if (Stunned
|| (Confusion
&& !rn2(5)))
2580 if (!isok(rx
, ry
)) {
2584 mtmp
= m_at(rx
, ry
);
2587 /* fake some proficiency checks */
2589 if (Role_if(PM_ARCHEOLOGIST
))
2591 if (ACURR(A_DEX
) < 6)
2593 else if (ACURR(A_DEX
) >= 14)
2594 proficient
+= (ACURR(A_DEX
) - 14);
2602 if (u
.uswallow
&& attack(u
.ustuck
)) {
2603 There("is not enough room to flick your bullwhip.");
2605 } else if (Underwater
) {
2606 There("is too much resistance to flick your bullwhip.");
2608 } else if (u
.dz
< 0) {
2609 You("flick a bug off of the %s.", ceiling(u
.ux
, u
.uy
));
2611 } else if ((!u
.dx
&& !u
.dy
) || (u
.dz
> 0)) {
2614 /* Sometimes you hit your steed by mistake */
2615 if (u
.usteed
&& !rn2(proficient
+ 2)) {
2616 You("whip %s!", mon_nam(u
.usteed
));
2620 if (Levitation
|| u
.usteed
) {
2621 /* Have a shot at snaring something on the floor */
2622 otmp
= level
.objects
[u
.ux
][u
.uy
];
2623 if (otmp
&& otmp
->otyp
== CORPSE
&& otmp
->corpsenm
== PM_HORSE
) {
2624 pline("Why beat a dead horse?");
2627 if (otmp
&& proficient
) {
2628 You("wrap your bullwhip around %s on the %s.",
2629 an(singular(otmp
, xname
)), surface(u
.ux
, u
.uy
));
2630 if (rnl(6) || pickup_object(otmp
, 1L, TRUE
) < 1)
2631 pline1(msg_slipsfree
);
2635 dam
= rnd(2) + dbon() + obj
->spe
;
2638 You("hit your %s with your bullwhip.", body_part(FOOT
));
2639 Sprintf(buf
, "killed %sself with %s bullwhip", uhim(), uhis());
2640 losehp(Maybe_Half_Phys(dam
), buf
, NO_KILLER_PREFIX
);
2644 } else if ((Fumbling
|| Glib
) && !rn2(5)) {
2645 pline_The("bullwhip slips out of your %s.", body_part(HAND
));
2648 } else if (u
.utrap
&& u
.utraptype
== TT_PIT
) {
2652 * if you're in a pit
2653 * - you are attempting to get out of the pit
2654 * or, if you are applying it towards a small monster
2655 * - then it is assumed that you are trying to hit it
2656 * else if the monster is wielding a weapon
2657 * - you are attempting to disarm a monster
2659 * - you are attempting to hit the monster.
2661 * if you're confused (and thus off the mark)
2662 * - you only end up hitting.
2665 const char *wrapped_what
= (char *) 0;
2668 if (bigmonst(mtmp
->data
)) {
2669 wrapped_what
= strcpy(buf
, mon_nam(mtmp
));
2670 } else if (proficient
) {
2677 if (!wrapped_what
) {
2678 if (IS_FURNITURE(levl
[rx
][ry
].typ
))
2679 wrapped_what
= something
;
2680 else if (sobj_at(BOULDER
, rx
, ry
))
2681 wrapped_what
= "a boulder";
2688 You("wrap your bullwhip around %s.", wrapped_what
);
2689 if (proficient
&& rn2(proficient
+ 2)) {
2690 if (!mtmp
|| enexto(&cc
, rx
, ry
, youmonst
.data
)) {
2691 You("yank yourself out of the pit!");
2692 teleds(cc
.x
, cc
.y
, TRUE
);
2694 vision_full_recalc
= 1;
2697 pline1(msg_slipsfree
);
2705 if (!canspotmon(mtmp
) && !glyph_is_invisible(levl
[rx
][ry
].glyph
)) {
2706 pline("A monster is there that you couldn't see.");
2707 map_invisible(rx
, ry
);
2709 otmp
= MON_WEP(mtmp
); /* can be null */
2711 char onambuf
[BUFSZ
];
2712 const char *mon_hand
;
2713 boolean gotit
= proficient
&& (!Fumbling
|| !rn2(10));
2715 Strcpy(onambuf
, cxname(otmp
));
2717 mon_hand
= mbodypart(mtmp
, HAND
);
2719 mon_hand
= makeplural(mon_hand
);
2721 mon_hand
= 0; /* lint suppression */
2723 You("wrap your bullwhip around %s.", yname(otmp
));
2724 if (gotit
&& mwelded(otmp
)) {
2725 pline("%s welded to %s %s%c",
2726 (otmp
->quan
== 1L) ? "It is" : "They are", mhis(mtmp
),
2727 mon_hand
, !otmp
->bknown
? '!' : '.');
2729 gotit
= FALSE
; /* can't pull it free */
2732 obj_extract_self(otmp
);
2733 possibly_unwield(mtmp
, FALSE
);
2734 setmnotwielded(mtmp
, otmp
);
2736 switch (rn2(proficient
+ 1)) {
2738 /* to floor near you */
2739 You("yank %s to the %s!", yname(otmp
),
2740 surface(u
.ux
, u
.uy
));
2741 place_object(otmp
, u
.ux
, u
.uy
);
2748 /* proficient with whip, but maybe not
2749 so proficient at catching weapons */
2752 hitvalu
= 8 + otmp
->spe
;
2753 hitu
= thitu(hitvalu
,
2754 dmgval(otmp
, &youmonst
),
2757 pline_The("%s hits you as you try to snatch it!",
2760 place_object(otmp
, u
.ux
, u
.uy
);
2765 /* right into your inventory */
2766 You("snatch %s!", yname(otmp
));
2767 if (otmp
->otyp
== CORPSE
2768 && touch_petrifies(&mons
[otmp
->corpsenm
]) && !uarmg
2769 && !Stone_resistance
2770 && !(poly_when_stoned(youmonst
.data
)
2771 && polymon(PM_STONE_GOLEM
))) {
2774 Sprintf(kbuf
, "%s corpse",
2775 an(mons
[otmp
->corpsenm
].mname
));
2776 pline("Snatching %s is a fatal mistake.", kbuf
);
2779 otmp
= hold_another_object(
2780 otmp
, "You drop %s!", doname(otmp
), (const char *) 0);
2783 /* to floor beneath mon */
2784 You("yank %s from %s %s!", the(onambuf
),
2785 s_suffix(mon_nam(mtmp
)), mon_hand
);
2786 obj_no_longer_held(otmp
);
2787 place_object(otmp
, mtmp
->mx
, mtmp
->my
);
2792 pline1(msg_slipsfree
);
2796 if (mtmp
->m_ap_type
&& !Protection_from_shape_changers
2798 stumble_onto_mimic(mtmp
);
2800 You("flick your bullwhip towards %s.", mon_nam(mtmp
));
2809 } else if (Is_airlevel(&u
.uz
) || Is_waterlevel(&u
.uz
)) {
2810 /* it must be air -- water checked above */
2811 You("snap your whip through thin air.");
2820 not_enough_room
[] = "There's not enough room here to use that.",
2821 where_to_hit
[] = "Where do you want to hit?",
2822 cant_see_spot
[] = "won't hit anything if you can't see that spot.",
2823 cant_reach
[] = "can't reach that spot from here.";
2825 /* find pos of monster in range, if only one monster */
2827 find_poleable_mon(pos
, min_range
, max_range
)
2829 int min_range
, max_range
;
2832 struct monst
*selmon
= (struct monst
*) 0;
2834 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
)
2835 if (mtmp
&& !DEADMONSTER(mtmp
) && !mtmp
->mtame
2836 && cansee(mtmp
->mx
, mtmp
->my
)
2837 && distu(mtmp
->mx
, mtmp
->my
) <= max_range
2838 && distu(mtmp
->mx
, mtmp
->my
) >= min_range
) {
2845 pos
->x
= selmon
->mx
;
2846 pos
->y
= selmon
->my
;
2850 static int polearm_range_min
= -1;
2851 static int polearm_range_max
= -1;
2854 display_polearm_positions(state
)
2858 tmp_at(DISP_BEAM
, cmap_to_glyph(S_goodpos
));
2859 } else if (state
== 1) {
2862 for (dx
= -4; dx
<= 4; dx
++)
2863 for (dy
= -4; dy
<= 4; dy
++) {
2864 x
= dx
+ (int) u
.ux
;
2865 y
= dy
+ (int) u
.uy
;
2866 if (isok(x
, y
) && ACCESSIBLE(levl
[x
][y
].typ
)
2867 && distu(x
, y
) >= polearm_range_min
2868 && distu(x
, y
) <= polearm_range_max
) {
2873 tmp_at(DISP_END
, 0);
2877 /* Distance attacks by pole-weapons */
2882 int res
= 0, typ
, max_range
, min_range
, glyph
;
2885 struct monst
*hitm
= context
.polearm
.hitmon
;
2887 /* Are you allowed to use the pole? */
2889 pline(not_enough_room
);
2893 if (!wield_tool(obj
, "swing"))
2898 /* assert(obj == uwep); */
2901 * Calculate allowable range (pole's reach is always 2 steps):
2902 * unskilled and basic: orthogonal direction, 4..4;
2903 * skilled: as basic, plus knight's jump position, 4..5;
2904 * expert: as skilled, plus diagonal, 4..8.
2912 * (Note: no roles in nethack can become expert or better
2913 * for polearm skill; Yeoman in slash'em can become expert.)
2916 typ
= uwep_skill_type();
2917 if (typ
== P_NONE
|| P_SKILL(typ
) <= P_BASIC
)
2919 else if (P_SKILL(typ
) == P_SKILLED
)
2922 max_range
= 8; /* (P_SKILL(typ) >= P_EXPERT) */
2924 polearm_range_min
= min_range
;
2925 polearm_range_max
= max_range
;
2927 /* Prompt for a location */
2928 pline(where_to_hit
);
2931 if (!find_poleable_mon(&cc
, min_range
, max_range
) && hitm
2932 && !DEADMONSTER(hitm
) && cansee(hitm
->mx
, hitm
->my
)
2933 && distu(hitm
->mx
, hitm
->my
) <= max_range
2934 && distu(hitm
->mx
, hitm
->my
) >= min_range
) {
2938 getpos_sethilite(display_polearm_positions
);
2939 if (getpos(&cc
, TRUE
, "the spot to hit") < 0)
2940 return res
; /* ESC; uses turn iff polearm became wielded */
2942 glyph
= glyph_at(cc
.x
, cc
.y
);
2943 if (distu(cc
.x
, cc
.y
) > max_range
) {
2946 } else if (distu(cc
.x
, cc
.y
) < min_range
) {
2947 pline("Too close!");
2949 } else if (!cansee(cc
.x
, cc
.y
) && !glyph_is_monster(glyph
)
2950 && !glyph_is_invisible(glyph
) && !glyph_is_statue(glyph
)) {
2953 } else if (!couldsee(cc
.x
, cc
.y
)) { /* Eyes of the Overworld */
2958 context
.polearm
.hitmon
= NULL
;
2959 /* Attack the monster there */
2961 if ((mtmp
= m_at(bhitpos
.x
, bhitpos
.y
)) != (struct monst
*) 0) {
2962 if (attack_checks(mtmp
, uwep
))
2965 return 1; /* burn nutrition; maybe pass out */
2966 context
.polearm
.hitmon
= mtmp
;
2967 check_caitiff(mtmp
);
2968 notonhead
= (bhitpos
.x
!= mtmp
->mx
|| bhitpos
.y
!= mtmp
->my
);
2969 (void) thitmonst(mtmp
, uwep
);
2970 } else if (glyph_is_statue(glyph
) /* might be hallucinatory */
2971 && sobj_at(STATUE
, bhitpos
.x
, bhitpos
.y
)) {
2972 struct trap
*t
= t_at(bhitpos
.x
, bhitpos
.y
);
2974 if (t
&& t
->ttyp
== STATUE_TRAP
2975 && activate_statue_trap(t
, t
->tx
, t
->ty
, FALSE
)) {
2976 ; /* feedback has been give by animate_statue() */
2978 /* Since statues look like monsters now, we say something
2979 different from "you miss" or "there's nobody there".
2980 Note: we only do this when a statue is displayed here,
2981 because the player is probably attempting to attack it;
2982 other statues obscured by anything are just ignored. */
2983 pline("Thump! Your blow bounces harmlessly off the statue.");
2984 wake_nearto(bhitpos
.x
, bhitpos
.y
, 25);
2987 /* no monster here and no statue seen or remembered here */
2988 if (glyph_is_invisible(glyph
)) {
2989 /* now you know that nothing is there... */
2990 unmap_object(bhitpos
.x
, bhitpos
.y
);
2991 newsym(bhitpos
.x
, bhitpos
.y
);
2993 You("miss; there is no one there to hit.");
2995 u_wipe_engr(2); /* same as for melee or throwing */
3003 boolean wasblind
= Blind
;
3004 boolean wascreamed
= u
.ucreamed
;
3005 boolean several
= FALSE
;
3007 if (obj
->quan
> 1L) {
3009 obj
= splitobj(obj
, 1L);
3012 You("give yourself a facial.");
3014 pline("You immerse your %s in %s%s.", body_part(FACE
),
3015 several
? "one of " : "",
3016 several
? makeplural(the(xname(obj
))) : the(xname(obj
)));
3017 if (can_blnd((struct monst
*) 0, &youmonst
, AT_WEAP
, obj
)) {
3018 int blindinc
= rnd(25);
3019 u
.ucreamed
+= blindinc
;
3020 make_blinded(Blinded
+ (long) blindinc
, FALSE
);
3021 if (!Blind
|| (Blind
&& wasblind
))
3022 pline("There's %ssticky goop all over your %s.",
3023 wascreamed
? "more " : "", body_part(FACE
));
3024 else /* Blind && !wasblind */
3025 You_cant("see through all the sticky goop on your %s.",
3030 /* useup() is appropriate, but we want costly_alteration()'s message */
3031 costly_alteration(obj
, COST_SPLAT
);
3032 obj_extract_self(obj
);
3041 int res
= 0, typ
, max_range
= 4, tohit
;
3042 boolean save_confirm
;
3047 /* Are you allowed to use the hook? */
3049 pline(not_enough_room
);
3053 if (!wield_tool(obj
, "cast"))
3058 /* assert(obj == uwep); */
3060 /* Prompt for a location */
3061 pline(where_to_hit
);
3064 if (getpos(&cc
, TRUE
, "the spot to hit") < 0)
3065 return res
; /* ESC; uses turn iff grapnel became wielded */
3067 /* Calculate range; unlike use_pole(), there's no minimum for range */
3068 typ
= uwep_skill_type();
3069 if (typ
== P_NONE
|| P_SKILL(typ
) <= P_BASIC
)
3071 else if (P_SKILL(typ
) == P_SKILLED
)
3075 if (distu(cc
.x
, cc
.y
) > max_range
) {
3078 } else if (!cansee(cc
.x
, cc
.y
)) {
3081 } else if (!couldsee(cc
.x
, cc
.y
)) { /* Eyes of the Overworld */
3086 /* What do you want to hit? */
3088 if (typ
!= P_NONE
&& P_SKILL(typ
) >= P_SKILLED
) {
3089 winid tmpwin
= create_nhwindow(NHW_MENU
);
3092 menu_item
*selected
;
3094 any
= zeroany
; /* set all bits to zero */
3095 any
.a_int
= 1; /* use index+1 (cant use 0) as identifier */
3098 Sprintf(buf
, "an object on the %s", surface(cc
.x
, cc
.y
));
3099 add_menu(tmpwin
, NO_GLYPH
, &any
, 0, 0, ATR_NONE
, buf
,
3102 add_menu(tmpwin
, NO_GLYPH
, &any
, 0, 0, ATR_NONE
, "a monster",
3105 Sprintf(buf
, "the %s", surface(cc
.x
, cc
.y
));
3106 add_menu(tmpwin
, NO_GLYPH
, &any
, 0, 0, ATR_NONE
, buf
,
3108 end_menu(tmpwin
, "Aim for what?");
3110 if (select_menu(tmpwin
, PICK_ONE
, &selected
) > 0
3111 && rn2(P_SKILL(typ
) > P_SKILLED
? 20 : 2))
3112 tohit
= selected
[0].item
.a_int
- 1;
3113 free((genericptr_t
) selected
);
3114 destroy_nhwindow(tmpwin
);
3117 /* possibly scuff engraving at your feet;
3118 any engraving at the target location is unaffected */
3119 if (tohit
== 2 || !rn2(2))
3120 u_wipe_engr(rnd(2));
3122 /* What did you hit? */
3125 /* FIXME -- untrap needs to deal with non-adjacent traps */
3127 case 1: /* Object */
3128 if ((otmp
= level
.objects
[cc
.x
][cc
.y
]) != 0) {
3129 You("snag an object from the %s!", surface(cc
.x
, cc
.y
));
3130 (void) pickup_object(otmp
, 1L, FALSE
);
3131 /* If pickup fails, leave it alone */
3136 case 2: /* Monster */
3138 if ((mtmp
= m_at(cc
.x
, cc
.y
)) == (struct monst
*) 0)
3140 notonhead
= (bhitpos
.x
!= mtmp
->mx
|| bhitpos
.y
!= mtmp
->my
);
3141 save_confirm
= flags
.confirm
;
3142 if (verysmall(mtmp
->data
) && !rn2(4)
3143 && enexto(&cc
, u
.ux
, u
.uy
, (struct permonst
*) 0)) {
3144 flags
.confirm
= FALSE
;
3145 (void) attack_checks(mtmp
, uwep
);
3146 flags
.confirm
= save_confirm
;
3147 check_caitiff(mtmp
); /* despite fact there's no damage */
3148 You("pull in %s!", mon_nam(mtmp
));
3149 mtmp
->mundetected
= 0;
3150 rloc_to(mtmp
, cc
.x
, cc
.y
);
3152 } else if ((!bigmonst(mtmp
->data
) && !strongmonst(mtmp
->data
))
3154 flags
.confirm
= FALSE
;
3155 (void) attack_checks(mtmp
, uwep
);
3156 flags
.confirm
= save_confirm
;
3157 check_caitiff(mtmp
);
3158 (void) thitmonst(mtmp
, uwep
);
3162 case 3: /* Surface */
3163 if (IS_AIR(levl
[cc
.x
][cc
.y
].typ
) || is_pool(cc
.x
, cc
.y
))
3164 pline_The("hook slices through the %s.", surface(cc
.x
, cc
.y
));
3166 You("are yanked toward the %s!", surface(cc
.x
, cc
.y
));
3167 hurtle(sgn(cc
.x
- u
.ux
), sgn(cc
.y
- u
.uy
), 1, FALSE
);
3171 default: /* Yourself (oops!) */
3172 if (P_SKILL(typ
) <= P_BASIC
) {
3173 You("hook yourself!");
3174 losehp(Maybe_Half_Phys(rn1(10, 10)), "a grappling hook",
3180 pline1(nothing_happens
);
3184 #define BY_OBJECT ((struct monst *) 0)
3186 /* return 1 if the wand is broken, hence some time elapsed */
3191 static const char nothing_else_happens
[] = "But nothing else happens...";
3192 register int i
, x
, y
;
3193 register struct monst
*mon
;
3195 boolean affects_objects
;
3196 boolean shop_damage
= FALSE
;
3197 boolean fillmsg
= FALSE
;
3198 int expltype
= EXPL_MAGICAL
;
3199 char confirm
[QBUFSZ
], buf
[BUFSZ
];
3200 boolean is_fragile
= (!strcmp(OBJ_DESCR(objects
[obj
->otyp
]), "balsa"));
3202 if (!paranoid_query(ParanoidBreakwand
,
3204 "Are you really sure you want to break ",
3205 "?", obj
, yname
, ysimple_name
, "the wand")))
3208 if (nohands(youmonst
.data
)) {
3209 You_cant("break %s without hands!", yname(obj
));
3211 } else if (ACURR(A_STR
) < (is_fragile
? 5 : 10)) {
3212 You("don't have the strength to break %s!", yname(obj
));
3215 pline("Raising %s high above your %s, you %s it in two!", yname(obj
),
3216 body_part(HEAD
), is_fragile
? "snap" : "break");
3218 /* [ALI] Do this first so that wand is removed from bill. Otherwise,
3219 * the freeinv() below also hides it from setpaid() which causes problems.
3222 check_unpaid(obj
); /* Extra charge for use */
3223 costly_alteration(obj
, COST_DSTROY
);
3226 current_wand
= obj
; /* destroy_item might reset this */
3227 freeinv(obj
); /* hide it from destroy_item instead... */
3228 setnotworn(obj
); /* so we need to do this ourselves */
3230 if (!zappable(obj
)) {
3231 pline(nothing_else_happens
);
3232 goto discard_broken_wand
;
3234 /* successful call to zappable() consumes a charge; put it back */
3236 /* might have "wrested" a final charge, taking it from 0 to -1;
3237 if so, we just brought it back up to 0, which wouldn't do much
3238 below so give it 1..3 charges now, usually making it stronger
3239 than an ordinary last charge (the wand is already gone from
3240 inventory, so perm_invent can't accidentally reveal this) */
3247 affects_objects
= FALSE
;
3249 switch (obj
->otyp
) {
3254 case WAN_ENLIGHTENMENT
:
3256 case WAN_SECRET_DOOR_DETECTION
:
3257 pline(nothing_else_happens
);
3258 goto discard_broken_wand
;
3264 expltype
= EXPL_FIERY
;
3266 if (expltype
== EXPL_MAGICAL
)
3267 expltype
= EXPL_FROSTY
;
3269 case WAN_MAGIC_MISSILE
:
3271 explode(u
.ux
, u
.uy
, -(obj
->otyp
), dmg
, WAND_CLASS
, expltype
);
3272 makeknown(obj
->otyp
); /* explode describes the effect */
3273 goto discard_broken_wand
;
3275 /* we want this before the explosion instead of at the very end */
3276 pline("A wall of force smashes down around you!");
3277 dmg
= d(1 + obj
->spe
, 6); /* normally 2d12 */
3279 case WAN_CANCELLATION
:
3281 case WAN_TELEPORTATION
:
3282 case WAN_UNDEAD_TURNING
:
3283 affects_objects
= TRUE
;
3289 /* magical explosion and its visual effect occur before specific effects
3291 /* [TODO? This really ought to prevent the explosion from being
3292 fatal so that we never leave a bones file where none of the
3293 surrounding targets (or underlying objects) got affected yet.] */
3294 explode(obj
->ox
, obj
->oy
, -(obj
->otyp
), rnd(dmg
), WAND_CLASS
,
3297 /* prepare for potential feedback from polymorph... */
3300 /* this makes it hit us last, so that we can see the action first */
3301 for (i
= 0; i
<= 8; i
++) {
3302 bhitpos
.x
= x
= obj
->ox
+ xdir
[i
];
3303 bhitpos
.y
= y
= obj
->oy
+ ydir
[i
];
3307 if (obj
->otyp
== WAN_DIGGING
) {
3310 if (dig_check(BY_OBJECT
, FALSE
, x
, y
)) {
3311 if (IS_WALL(levl
[x
][y
].typ
) || IS_DOOR(levl
[x
][y
].typ
)) {
3312 /* normally, pits and holes don't anger guards, but they
3313 * do if it's a wall or door that's being dug */
3314 watch_dig((struct monst
*) 0, x
, y
, TRUE
);
3315 if (*in_rooms(x
, y
, SHOPBASE
))
3319 * Let liquid flow into the newly created pits.
3320 * Adjust corresponding code in music.c for
3321 * drum of earthquake if you alter this sequence.
3323 typ
= fillholetyp(x
, y
, FALSE
);
3325 levl
[x
][y
].typ
= typ
;
3326 liquid_flow(x
, y
, typ
, t_at(x
, y
),
3329 : "Some holes are quickly filled with %s!");
3332 digactualhole(x
, y
, BY_OBJECT
, (rn2(obj
->spe
) < 3
3333 || (!Can_dig_down(&u
.uz
)
3334 && !levl
[x
][y
].candig
))
3339 } else if (obj
->otyp
== WAN_CREATE_MONSTER
) {
3340 /* u.ux,u.uy creates it near you--x,y might create it in rock */
3341 (void) makemon((struct permonst
*) 0, u
.ux
, u
.uy
, NO_MM_FLAGS
);
3343 } else if (x
!= u
.ux
|| y
!= u
.uy
) {
3345 * Wand breakage is targetting a square adjacent to the hero,
3346 * which might contain a monster or a pile of objects or both.
3347 * Handle objects last; avoids having undead turning raise an
3348 * undead's corpse and then attack resulting undead monster.
3349 * obj->bypass in bhitm() prevents the polymorphing of items
3350 * dropped due to monster's polymorph and prevents undead
3351 * turning that kills an undead from raising resulting corpse.
3353 if ((mon
= m_at(x
, y
)) != 0) {
3354 (void) bhitm(mon
, obj
);
3355 /* if (context.botl) bot(); */
3357 if (affects_objects
&& level
.objects
[x
][y
]) {
3358 (void) bhitpile(obj
, bhito
, x
, y
, 0);
3360 bot(); /* potion effects */
3364 * Wand breakage is targetting the hero. Using xdir[]+ydir[]
3365 * deltas for location selection causes this case to happen
3366 * after all the surrounding squares have been handled.
3367 * Process objects first, in case damage is fatal and leaves
3368 * bones, or teleportation sends one or more of the objects to
3369 * same destination as hero (lookhere/autopickup); also avoids
3370 * the polymorphing of gear dropped due to hero's transformation.
3371 * (Unlike with monsters being hit by zaps, we can't rely on use
3372 * of obj->bypass in the zap code to accomplish that last case
3373 * since it's also used by retouch_equipment() for polyself.)
3375 if (affects_objects
&& level
.objects
[x
][y
]) {
3376 (void) bhitpile(obj
, bhito
, x
, y
, 0);
3378 bot(); /* potion effects */
3380 damage
= zapyourself(obj
, FALSE
);
3382 Sprintf(buf
, "killed %sself by breaking a wand", uhim());
3383 losehp(Maybe_Half_Phys(damage
), buf
, NO_KILLER_PREFIX
);
3386 bot(); /* blindness */
3390 /* potentially give post zap/break feedback */
3393 /* Note: if player fell thru, this call is a no-op.
3394 Damage is handled in digactualhole in that case */
3396 pay_for_damage("dig into", FALSE
);
3398 if (obj
->otyp
== WAN_LIGHT
)
3399 litroom(TRUE
, obj
); /* only needs to be done once */
3401 discard_broken_wand
:
3402 obj
= current_wand
; /* [see dozap() and destroy_item()] */
3411 add_class(cl
, class)
3422 static const char tools
[] = { TOOL_CLASS
, WEAPON_CLASS
, WAND_CLASS
, 0 };
3424 /* augment tools[] if various items are carried */
3426 setapplyclasses(class_list
)
3429 register struct obj
*otmp
;
3431 boolean knowoil
, knowtouchstone
, addpotions
, addstones
, addfood
;
3433 knowoil
= objects
[POT_OIL
].oc_name_known
;
3434 knowtouchstone
= objects
[TOUCHSTONE
].oc_name_known
;
3435 addpotions
= addstones
= addfood
= FALSE
;
3436 for (otmp
= invent
; otmp
; otmp
= otmp
->nobj
) {
3439 || (otmp
->oclass
== POTION_CLASS
3441 || (!knowoil
&& !objects
[otyp
].oc_name_known
))))
3443 if (otyp
== TOUCHSTONE
3444 || (is_graystone(otmp
)
3446 || (!knowtouchstone
&& !objects
[otyp
].oc_name_known
))))
3448 if (otyp
== CREAM_PIE
|| otyp
== EUCALYPTUS_LEAF
)
3452 class_list
[0] = '\0';
3453 if (addpotions
|| addstones
)
3454 add_class(class_list
, ALL_CLASSES
);
3455 Strcat(class_list
, tools
);
3457 add_class(class_list
, POTION_CLASS
);
3459 add_class(class_list
, GEM_CLASS
);
3461 add_class(class_list
, FOOD_CLASS
);
3464 /* the 'a' command */
3469 register int res
= 1;
3470 char class_list
[MAXOCLASSES
+ 2];
3472 if (check_capacity((char *) 0))
3475 setapplyclasses(class_list
); /* tools[] */
3476 obj
= getobj(class_list
, "use or apply");
3480 if (!retouch_object(&obj
, FALSE
))
3481 return 1; /* evading your grasp costs a turn; just be
3482 grateful that you don't drop it as well */
3484 if (obj
->oclass
== WAND_CLASS
)
3485 return do_break_wand(obj
);
3487 switch (obj
->otyp
) {
3490 if (obj
== ublindf
) {
3493 } else if (!ublindf
) {
3496 You("are already %s.", ublindf
->otyp
== TOWEL
3497 ? "covered by a towel"
3498 : ublindf
->otyp
== BLINDFOLD
3499 ? "wearing a blindfold"
3500 : "wearing lenses");
3504 res
= use_cream_pie(obj
);
3507 res
= use_whip(obj
);
3509 case GRAPPLING_HOOK
:
3510 res
= use_grapple(obj
);
3516 case BAG_OF_HOLDING
:
3518 res
= use_container(&obj
, 1, FALSE
);
3521 (void) bagotricks(obj
, FALSE
, (int *) 0);
3529 res
= (pick_lock(obj
) != 0);
3532 case DWARVISH_MATTOCK
:
3533 res
= use_pick_axe(obj
);
3536 use_tinning_kit(obj
);
3542 res
= use_saddle(obj
);
3545 use_magic_whistle(obj
);
3550 case EUCALYPTUS_LEAF
:
3551 /* MRKR: Every Australian knows that a gum leaf makes an excellent
3552 * whistle, especially if your pet is a tame kangaroo named Skippy.
3555 use_magic_whistle(obj
);
3556 /* sometimes the blessing will be worn off */
3559 pline("%s %s.", Yobjnam2(obj
, "glow"), hcolor("brown"));
3569 res
= use_stethoscope(obj
);
3572 res
= use_mirror(obj
);
3575 case BELL_OF_OPENING
:
3578 case CANDELABRUM_OF_INVOCATION
:
3579 use_candelabrum(obj
);
3591 light_cocktail(&obj
);
3593 case EXPENSIVE_CAMERA
:
3594 res
= use_camera(obj
);
3597 res
= use_towel(obj
);
3600 use_crystal_ball(&obj
);
3606 res
= use_tin_opener(obj
);
3612 use_unicorn_horn(obj
);
3623 case DRUM_OF_EARTHQUAKE
:
3624 res
= do_play_instrument(obj
);
3626 case HORN_OF_PLENTY
: /* not a musical instrument */
3627 (void) hornoplenty(obj
, FALSE
);
3640 /* Pole-weapons can strike at a distance */
3642 res
= use_pole(obj
);
3644 } else if (is_pick(obj
) || is_axe(obj
)) {
3645 res
= use_pick_axe(obj
);
3648 pline("Sorry, I don't know how to use that.");
3652 if (res
&& obj
&& obj
->oartifact
)
3658 /* Keep track of unfixable troubles for purposes of messages saying you feel
3662 unfixable_trouble_count(is_horn
)
3665 int unfixable_trbl
= 0;
3671 if (Wounded_legs
&& !u
.usteed
)
3675 /* lycanthropy is undesirable, but it doesn't actually make you feel bad */
3677 if (!is_horn
|| (Confusion
& ~TIMEOUT
))
3679 if (!is_horn
|| (Sick
& ~TIMEOUT
))
3681 if (!is_horn
|| (HHallucination
& ~TIMEOUT
))
3683 if (!is_horn
|| (Vomiting
& ~TIMEOUT
))
3685 if (!is_horn
|| (HStun
& ~TIMEOUT
))
3687 if (!is_horn
|| (HDeaf
& ~TIMEOUT
))
3690 return unfixable_trbl
;