1 /* NetHack 3.7 do.c $NHDT-Date: 1737287889 2025/01/19 03:58:09 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.399 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Derek S. Ray, 2015. */
4 /* NetHack may be freely redistributed. See license for details. */
6 /* Contains code for 'd', 'D' (drop), '>', '<' (up, down) */
10 staticfn boolean
teleport_sink(void);
11 staticfn
void dosinkring(struct obj
*);
12 staticfn
int drop(struct obj
*);
13 staticfn
int menudrop_split(struct obj
*, long);
14 staticfn boolean
engulfer_digests_food(struct obj
*);
15 staticfn boolean
danger_uprops(void);
16 staticfn
int wipeoff(void);
17 staticfn
int menu_drop(int);
18 staticfn boolean
u_stuck_cannot_go(const char *);
19 staticfn NHFILE
*currentlevel_rewrite(void);
20 staticfn
void familiar_level_msg(void);
21 staticfn
void final_level(void);
22 staticfn
void temperature_change_msg(schar
);
23 staticfn boolean
better_not_try_to_drop_that(struct obj
*);
25 /* static boolean badspot(coordxy,coordxy); */
27 /* the #drop command: drop one inventory item */
34 sellobj_state(SELL_DELIBERATE
);
35 result
= drop(getobj("drop", any_obj_ok
,
36 GETOBJ_PROMPT
| GETOBJ_ALLOWCNT
));
38 sellobj_state(SELL_NORMAL
);
45 /* Called when a boulder is dropped, thrown, or pushed. If it ends up
46 * in a pool, it either fills the pool up or sinks away. In either case,
47 * it's gone for good... If the destination is not a pool, returns FALSE.
51 struct obj
*otmp
, /* the object falling into a pool or water or lava */
52 coordxy rx
, coordxy ry
, /* coordinates of the pool */
53 boolean pushing
) /* for a boulder, whether or not it is being pushed */
55 if (!otmp
|| otmp
->otyp
!= BOULDER
) {
56 impossible("Not a boulder?");
57 } else if (is_pool_or_lava(rx
, ry
)) {
58 boolean lava
= is_lava(rx
, ry
), fills_up
;
59 const char *what
= waterbody_name(rx
, ry
);
60 schar ltyp
= levl
[rx
][ry
].typ
;
61 int chance
= rn2(10); /* water: 90%; lava: 10% */
64 /* chance for boulder to fill pool: Plane of Water==0%,
65 lava 10%, wall of water==50%, other water==90% */
66 fills_up
= Is_waterlevel(&u
.uz
) ? FALSE
67 : IS_WATERWALL(ltyp
) ? (chance
< 5)
68 : lava
? (chance
== 0) : (chance
!= 0);
71 struct trap
*ttmp
= t_at(rx
, ry
);
73 if (ltyp
== DRAWBRIDGE_UP
) {
74 levl
[rx
][ry
].drawbridgemask
&= ~DB_UNDER
; /* clear lava */
75 levl
[rx
][ry
].drawbridgemask
|= DB_FLOOR
;
77 levl
[rx
][ry
].typ
= ROOM
, levl
[rx
][ry
].flags
= 0;
78 recalc_block_point(rx
, ry
);
80 /* 3.7: normally DEADMONSTER() is used when traversing the fmon
81 list--dead monsters usually aren't still at specific map
82 locations; however, if ice melts causing a giant to drown,
83 that giant would still be on the map when it drops inventory;
84 if it was carrying a boulder which now fills the pool, 'mtmp'
85 will be dead here; killing it again would yield impossible
86 "dmonsfree: N removed doesn't match N+1 pending" when other
87 monsters have finished their current turn */
88 if ((mtmp
= m_at(rx
, ry
)) != 0 && !DEADMONSTER(mtmp
)
93 (void) delfloortrap(ttmp
);
100 Strcpy(whobuf
, "you");
102 Strcpy(whobuf
, y_monnam(u
.usteed
));
103 pline("%s %s %s into the %s.", upstart(whobuf
),
104 vtense(whobuf
, "push"), the(xname(otmp
)), what
);
105 if (flags
.verbose
&& !Blind
)
106 pline("Now you can cross it!");
107 /* no splashing in this case */
110 if (!fills_up
|| !pushing
) { /* splashing occurs */
112 if (pushing
? !Blind
: cansee(rx
, ry
)) {
113 There("is a large splash as %s %s the %s.",
114 the(xname(otmp
)), fills_up
? "fills" : "falls into",
118 Soundeffect(se_sizzling
, 100);
120 Soundeffect(se_splash
, 100);
122 You_hear("a%s splash.", lava
? " sizzling" : "");
124 wake_nearto(rx
, ry
, 40);
127 if (fills_up
&& u
.uinwater
&& distu(rx
, ry
) == 0) {
128 set_uinwater(0); /* u.uinwater = 0 */
130 gv
.vision_full_recalc
= 1;
131 You("find yourself on dry land again!");
132 } else if (lava
&& next2u(rx
, ry
)) {
135 You("are hit by molten %s%c",
136 hliquid("lava"), Fire_resistance
? '.' : '!');
138 dmg
= d((Fire_resistance
? 1 : 3), 6);
139 losehp(Maybe_Half_Phys(dmg
), /* lava damage */
140 "molten lava", KILLED_BY
);
141 } else if (!fills_up
&& flags
.verbose
142 && (pushing
? !Blind
: cansee(rx
, ry
))) {
143 pline("It sinks without a trace!");
147 /* boulder is now gone */
149 useupf(otmp
, otmp
->quan
);
151 obfree(otmp
, (struct obj
*) 0);
157 /* Used for objects which sometimes do special things when dropped; must be
158 * called with the object not in any chain. Returns TRUE if the object goes
163 struct obj
*obj
, /* the object landing on the floor */
164 coordxy x
, coordxy y
, /* map coordinates for spot where it is landing */
165 const char *verb
) /* "fall", "drop", "land", &c */
172 int ttyp
= NO_TRAP
, res
= FALSE
;
174 if (obj
->where
!= OBJ_FREE
)
175 panic("flooreffects: obj not free");
177 /* make sure things like water_damage() have no pointers to follow */
178 obj
->nobj
= obj
->nexthere
= (struct obj
*) 0;
179 /* erode_obj() (called from water_damage() or lava_damage()) needs
180 bhitpos, but that was screwing up wand zapping that called us from
181 rloco(), so we now restore bhitpos before we return */
182 save_bhitpos
= gb
.bhitpos
;
183 gb
.bhitpos
.x
= x
, gb
.bhitpos
.y
= y
;
185 if (obj
->otyp
== BOULDER
&& boulder_hits_pool(obj
, x
, y
, FALSE
)) {
187 } else if (obj
->otyp
== BOULDER
&& (t
= t_at(x
, y
)) != 0
188 && (is_pit(t
->ttyp
) || is_hole(t
->ttyp
))) {
190 tseen
= t
->tseen
? TRUE
: FALSE
;
191 if (((mtmp
= m_at(x
, y
)) && mtmp
->mtrapped
)
192 || (u
.utrap
&& u_at(x
,y
))) {
193 if (*verb
&& (cansee(x
, y
) || distu(x
, y
) == 0))
194 pline("%s boulder %s into the pit%s.",
196 vtense((const char *) 0, verb
),
197 mtmp
? "" : " with you");
199 if (!passes_walls(mtmp
->data
) && !throws_rocks(mtmp
->data
)) {
200 /* dieroll was rnd(20); 1: maximum chance to hit
201 since trapped target is a sitting duck */
202 int damage
, dieroll
= 1;
204 /* As of 3.6.2: this was calling hmon() unconditionally
205 so always credited/blamed the hero but the boulder
206 might have been thrown by a giant or launched by
207 a rolling boulder trap triggered by a monster or
208 dropped by a scroll of earth read by a monster */
209 if (svc
.context
.mon_moving
) {
210 /* normally we'd use ohitmon() but it can call
211 drop_throw() which calls flooreffects() */
212 damage
= dmgval(obj
, mtmp
);
214 if (DEADMONSTER(mtmp
)) {
215 if (canspotmon(mtmp
))
216 pline("%s is %s!", Monnam(mtmp
),
217 (nonliving(mtmp
->data
)
218 || is_vampshifter(mtmp
))
219 ? "destroyed" : "killed");
223 (void) hmon(mtmp
, obj
, HMON_THROWN
, dieroll
);
225 if (!DEADMONSTER(mtmp
) && !is_whirly(mtmp
->data
))
226 res
= FALSE
; /* still alive, boulder still intact */
231 if (!Passes_walls
&& !throws_rocks(gy
.youmonst
.data
)) {
232 losehp(Maybe_Half_Phys(rnd(15)),
233 "squished under a boulder", NO_KILLER_PREFIX
);
234 goto deletedwithboulder
;
240 if (Blind
&& u_at(x
, y
)) {
241 Soundeffect(se_crashing_boulder
, 100);
242 You_hear("a CRASH! beneath you.");
243 } else if (!Blind
&& cansee(x
, y
)) {
244 pline_The("boulder %s%s.",
245 (ttyp
== TRAPDOOR
&& !tseen
) ? "triggers and " : "",
246 (ttyp
== TRAPDOOR
) ? "plugs a trap door"
247 : (ttyp
== HOLE
) ? "plugs a hole"
250 Soundeffect(se_boulder_drop
, 100);
251 You_hear("a boulder %s.", verb
);
255 * Note: trap might have gone away via ((hmon -> killed -> xkilled)
256 * || mondied) -> mondead -> m_detach -> fill_pit.
259 /* creating a pit in ice results in that ice being turned into
260 floor so we shouldn't need any special ice handing here */
261 if ((t
= t_at(x
, y
)) != 0) {
262 (void) delfloortrap(t
);
263 if (u
.utrap
&& u_at(x
, y
))
270 } else if (is_lava(x
, y
)) {
271 res
= lava_damage(obj
, x
, y
);
272 } else if (is_pool(x
, y
)) {
273 /* Reasonably bulky objects (arbitrary) splash when dropped.
274 * If you're floating above the water even small things make
275 * noise. Stuff dropped near fountains always misses */
276 if ((Blind
|| (Levitation
|| Flying
)) && !Deaf
&& u_at(x
, y
)) {
278 if (weight(obj
) > 9) {
280 } else if (Levitation
|| Flying
) {
284 map_background(x
, y
, 0);
287 res
= water_damage(obj
, NULL
, FALSE
) == ER_DESTROYED
;
288 } else if (u_at(x
, y
) && (t
= t_at(x
, y
)) != 0
289 && (uteetering_at_seen_pit(t
) || uescaped_shaft(t
))) {
290 if (is_pit(t
->ttyp
)) {
291 if (Blind
&& !Deaf
) {
292 Soundeffect(se_item_tumble_downwards
, 50);
293 You_hear("%s tumble downwards.", the(xname(obj
)));
295 pline("%s into %s pit.", Tobjnam(obj
, "tumble"),
296 the_your
[t
->madeby_u
]);
298 } else if (ship_object(obj
, x
, y
, FALSE
)) {
299 /* ship_object will print an appropriate "the item falls
300 * through the hole" message, so no need to do it here. */
303 } else if (obj
->globby
) {
304 struct obj
*globbyobj
= obj
; /* allow obj to be nonnull arg */
306 /* Globby things like puddings might stick together */
308 && (otmp
= obj_nexto_xy(globbyobj
, x
, y
, TRUE
)) != 0) {
309 pudding_merge_message(globbyobj
, otmp
);
310 /* intentionally not getting the melded object; obj_meld may set
312 (void) obj_meld(&globbyobj
, &otmp
);
314 res
= (boolean
) !globbyobj
;
315 } else if (svc
.context
.mon_moving
&& IS_ALTAR(levl
[x
][y
].typ
)
318 } else if (obj
->oclass
== POTION_CLASS
&& svl
.level
.flags
.temperature
> 0
319 && (levl
[x
][y
].typ
== ROOM
|| levl
[x
][y
].typ
== CORR
)) {
320 /* Potions are sometimes destroyed when landing on very hot
321 ground. The basic odds are 50% for nonblessed potions and
322 30% for blessed potions; if you have handled the object
323 (i.e. it is or was yours), these odds are adjusted by Luck
324 (each Luck point affects them by 2%). Artifact potions
325 would not be affected, if any existed.
327 Oil is not affected because its boiling point (and flash
328 point) are higher than that of water. For example, whale
329 oil, one of the substances traditionally used in oil lamps,
330 can survive over 100 degrees Centigrade more heat than
333 /* unconditional "ground" is safe as this only runs for
334 room and corridor tiles */
335 pline("%s up as %s the hot ground.", Tobjnam(obj
, "heat"),
336 is_plural(obj
) ? "they hit" : "it hits");
339 int survival_chance
= obj
->blessed
? 70 : 50;
341 survival_chance
+= Luck
* 2;
342 if (obj
->otyp
== POT_OIL
)
343 survival_chance
= 100;
345 if (!obj_resists(obj
, survival_chance
, 100)) {
347 pline("%s from the heat!",
348 is_plural(obj
) ? "They shatter" : "It shatters");
350 You_hear("a shattering noise.");
352 breakobj(obj
, x
, y
, FALSE
, FALSE
);
357 gb
.bhitpos
= save_bhitpos
;
361 /* obj is an object dropped on an altar */
363 doaltarobj(struct obj
*obj
)
368 if (obj
->oclass
!= COIN_CLASS
) {
370 if (!svc
.context
.mon_moving
&& !u
.uconduct
.gnostic
++)
371 livelog_printf(LL_CONDUCT
,
372 "eschewed atheism, by dropping %s on an altar",
375 /* coins don't have bless/curse status */
376 obj
->blessed
= obj
->cursed
= 0;
379 if (obj
->blessed
|| obj
->cursed
) {
380 There("is %s flash as %s %s the altar.",
381 an(hcolor(obj
->blessed
? NH_AMBER
: NH_BLACK
)), doname(obj
),
384 obj
->bknown
= 1; /* ok to bypass set_bknown() */
386 pline("%s %s on the altar.", Doname2(obj
), otense(obj
, "land"));
387 if (obj
->oclass
!= COIN_CLASS
)
388 obj
->bknown
= 1; /* ok to bypass set_bknown() */
392 /* If obj is neither formally identified nor informally called something
393 * already, prompt the player to call its object type. */
395 trycall(struct obj
*obj
)
397 if (!objects
[obj
->otyp
].oc_name_known
&& !objects
[obj
->otyp
].oc_uname
)
401 /* Transforms the sink at the player's position into
402 a fountain, throne, altar or grave. */
410 if (levl
[u
.ux
][u
.uy
].typ
!= SINK
)
413 sinklooted
= levl
[u
.ux
][u
.uy
].looted
!= 0;
414 /* svl.level.flags.nsinks--; // set_levltyp() will update this */
415 levl
[u
.ux
][u
.uy
].flags
= 0;
420 set_levltyp(u
.ux
, u
.uy
, FOUNTAIN
); /* updates level.flags.nfountains */
421 levl
[u
.ux
][u
.uy
].blessedftn
= 0;
423 SET_FOUNTAIN_LOOTED(u
.ux
, u
.uy
);
427 set_levltyp(u
.ux
, u
.uy
, THRONE
);
429 levl
[u
.ux
][u
.uy
].looted
= T_LOOTED
;
433 set_levltyp(u
.ux
, u
.uy
, ALTAR
);
434 /* 3.6.3: this used to pass 'rn2(A_LAWFUL + 2) - 1' to
435 Align2amask() but that evaluates its argument more than once */
436 algn
= rn2(3) - 1; /* -1 (A_Cha) or 0 (A_Neu) or +1 (A_Law) */
437 levl
[u
.ux
][u
.uy
].altarmask
= ((Inhell
&& rn2(3)) ? AM_NONE
438 : Align2amask(algn
));
442 set_levltyp(u
.ux
, u
.uy
, ROOM
);
443 make_grave(u
.ux
, u
.uy
, (char *) 0);
444 if (levl
[u
.ux
][u
.uy
].typ
== GRAVE
)
448 /* give message even if blind; we know we're not levitating,
449 so can feel the outcome even if we can't directly see it */
450 if (levl
[u
.ux
][u
.uy
].typ
!= ROOM
)
451 pline_The("sink transforms into %s!", an(defsyms
[sym
].explanation
));
453 pline_The("sink vanishes.");
457 /* Teleports the sink at the player's position;
458 return True if sink teleported. */
463 unsigned alreadylooted
;
467 #if 0 /* this isn't incorrect but it is extremely unlikely that spots
468 * on the level's edge will be ROOM so picking such wastes tries */
469 cx
= rnd(COLNO
- 1); /* 1..COLNO-1 */
470 cy
= rn2(ROWNO
); /* 0..ROWNO-1 */
471 #else /* use this instead */
472 cx
= 1 + rnd((COLNO
- 1) - 2); /* 2..COLNO-2 */
473 cy
= 1 + rn2(ROWNO
- 2); /* 1..ROWNO-2 */
475 if (levl
[cx
][cy
].typ
== ROOM
476 && !t_at(cx
, cy
) && !engr_at(cx
, cy
)
477 && (!cansee(cx
, cy
) || distu(cx
, cy
) > 3 * 3)) {
478 /* this ends up having set_levltyp() count all sinks and
479 fountains on the level twice but that is not a problem */
480 alreadylooted
= levl
[u
.ux
][u
.uy
].looted
;
481 /* remove old sink */
482 set_levltyp(u
.ux
, u
.uy
, ROOM
); /* was SINK so updates nsinks */
483 levl
[u
.ux
][u
.uy
].looted
= 0;
485 /* create sink at new position */
486 set_levltyp(cx
, cy
, SINK
); /* now SINK so also updates nsinks */
487 levl
[cx
][cy
].looted
= alreadylooted
? 1 : 0;
491 } while (++trycnt
< 200);
496 /* obj is a ring being dropped over a kitchen sink */
498 dosinkring(struct obj
*obj
)
500 struct obj
*otmp
, *otmp2
;
501 boolean ideed
= TRUE
;
502 boolean nosink
= FALSE
;
504 You("drop %s down the drain.", doname(obj
));
505 obj
->in_use
= TRUE
; /* block free identification via interrupt */
506 switch (obj
->otyp
) { /* effects that can be noticed without eyes */
508 You("thought %s got lost in the sink, but there it is!", yname(obj
));
510 case RIN_SLOW_DIGESTION
:
511 pline_The("ring is regurgitated!");
518 pline_The("sink quivers upward for a moment.");
520 case RIN_POISON_RESISTANCE
:
521 You("smell rotten %s.", makeplural(fruitname(FALSE
)));
523 case RIN_AGGRAVATE_MONSTER
:
524 pline("Several %s buzz angrily around the sink.",
525 Hallucination
? makeplural(rndmonnam(NULL
)) : "flies");
527 case RIN_SHOCK_RESISTANCE
:
528 pline("Static electricity surrounds the sink.");
531 Soundeffect(se_drain_noises
, 50);
532 You_hear("loud noises coming from the drain.");
534 case RIN_SUSTAIN_ABILITY
: /* KMH */
535 pline_The("%s flow seems fixed.", hliquid("water"));
537 case RIN_GAIN_STRENGTH
:
538 pline_The("%s flow seems %ser now.",
540 (obj
->spe
< 0) ? "weak" : "strong");
542 case RIN_GAIN_CONSTITUTION
:
543 pline_The("%s flow seems %ser now.",
545 (obj
->spe
< 0) ? "less" : "great");
547 case RIN_INCREASE_ACCURACY
: /* KMH */
548 pline_The("%s flow %s the drain.",
550 (obj
->spe
< 0) ? "misses" : "hits");
552 case RIN_INCREASE_DAMAGE
:
553 pline_The("water's force seems %ser now.",
554 (obj
->spe
< 0) ? "small" : "great");
558 for (otmp
= svl
.level
.objects
[u
.ux
][u
.uy
]; otmp
; otmp
= otmp2
) {
559 otmp2
= otmp
->nexthere
;
560 if (otmp
!= uball
&& otmp
!= uchain
561 && !obj_resists(otmp
, 1, 99)) {
563 pline("Suddenly, %s %s from the sink!", doname(otmp
),
564 otense(otmp
, "vanish"));
572 /* Not the same as aggravate monster; besides, it's obvious. */
573 pline("Several flies buzz around the sink.");
575 case RIN_TELEPORTATION
:
576 nosink
= teleport_sink();
577 /* give message even if blind; we know we're not levitating,
578 so can feel the outcome even if we can't directly see it */
579 pline_The("sink %svanishes.", nosink
? "" : "momentarily ");
585 /* for S_room case, same message as for teleportation is given */
586 ideed
= (levl
[u
.ux
][u
.uy
].typ
!= ROOM
);
592 if (!Blind
&& !ideed
) {
594 switch (obj
->otyp
) { /* effects that need eyes */
596 pline_The("faucets flash brightly for a moment.");
598 case RIN_REGENERATION
:
599 pline_The("sink looks as good as new.");
601 case RIN_INVISIBILITY
:
602 You("don't see anything happen to the sink.");
604 case RIN_FREE_ACTION
:
605 You_see("the ring slide right down the drain!");
607 case RIN_SEE_INVISIBLE
:
608 You_see("some %s in the sink.",
609 Hallucination
? "oxygen molecules" : "air");
612 pline_The("sink seems to blend into the floor for a moment.");
614 case RIN_FIRE_RESISTANCE
:
615 pline_The("hot %s faucet flashes brightly for a moment.",
618 case RIN_COLD_RESISTANCE
:
619 pline_The("cold %s faucet flashes brightly for a moment.",
622 case RIN_PROTECTION_FROM_SHAPE_CHAN
:
623 pline_The("sink looks nothing like a fountain.");
626 pline_The("sink glows %s for a moment.",
627 hcolor((obj
->spe
< 0) ? NH_BLACK
: NH_SILVER
));
630 pline_The("sink glows %s for a moment.", hcolor(NH_WHITE
));
632 case RIN_TELEPORT_CONTROL
:
633 pline_The("sink looks like it is being beamed aboard somewhere.");
635 case RIN_POLYMORPH_CONTROL
:
637 "sink momentarily looks like a regularly erupting geyser.");
645 } else if (!nosink
) {
646 Soundeffect(se_ring_in_drain
, 50);
647 You_hear("the ring bouncing down the drainpipe.");
649 if (!rn2(20) && !nosink
) {
650 pline_The("sink backs up, leaving %s.", doname(obj
));
653 } else if (!rn2(5)) {
663 /* some common tests when trying to drop or throw items */
665 canletgo(struct obj
*obj
, const char *word
)
667 if (obj
->owornmask
& (W_ARMOR
| W_ACCESSORY
)) {
669 Norep("You cannot %s %s you are wearing.", word
, something
);
672 if (obj
== uwep
&& welded(uwep
)) {
673 /* no weldmsg(), so uwep->bknown might become set silently
676 const char *hand
= body_part(HAND
);
679 hand
= makeplural(hand
);
680 Norep("You cannot %s %s welded to your %s.", word
, something
,
685 if (obj
->otyp
== LOADSTONE
&& obj
->cursed
) {
686 /* getobj() kludge sets corpsenm to user's specified count
687 when refusing to split a stack of cursed loadstones */
689 /* getobj() ignores a count for throwing since that is
690 implicitly forced to be 1; replicate its kludge... */
691 if (!strcmp(word
, "throw") && obj
->quan
> 1L)
693 pline("For some reason, you cannot %s%s the stone%s!", word
,
694 obj
->corpsenm
? " any of" : "", plur(obj
->quan
));
696 obj
->corpsenm
= 0; /* reset */
700 if (obj
->otyp
== LEASH
&& obj
->leashmon
!= 0) {
702 pline_The("leash is tied around your %s.", body_part(HAND
));
705 if (obj
->owornmask
& W_SADDLE
) {
707 You("cannot %s %s you are sitting on.", word
, something
);
714 drop(struct obj
*obj
)
718 if (!canletgo(obj
, "drop"))
720 if (obj
->otyp
== CORPSE
&& better_not_try_to_drop_that(obj
))
727 setuwep((struct obj
*) 0);
729 if (obj
== uquiver
) {
730 setuqwep((struct obj
*) 0);
732 if (obj
== uswapwep
) {
733 setuswapwep((struct obj
*) 0);
737 /* barrier between you and the floor */
739 char *onam_p
, *mnam_p
, monbuf
[BUFSZ
];
741 mnam_p
= mon_nam(u
.ustuck
);
742 /* doname can call s_suffix, reusing its buffer */
743 if (digests(u
.ustuck
->data
)) {
744 Sprintf(monbuf
, "%s %s", s_suffix(mnam_p
),
745 mbodypart(u
.ustuck
, STOMACH
));
748 onam_p
= is_unpaid(obj
) ? yobjnam(obj
, (char *) 0) : doname(obj
);
750 You("drop %s into %s.", onam_p
, mnam_p
);
753 if ((obj
->oclass
== RING_CLASS
|| obj
->otyp
== MEAT_RING
)
754 && IS_SINK(levl
[u
.ux
][u
.uy
].typ
)) {
758 if (!can_reach_floor(TRUE
)) {
759 /* we might be levitating due to #invoke Heart of Ahriman;
760 if so, levitation would end during call to freeinv()
761 and we want hitfloor() to happen before float_down() */
762 boolean levhack
= finesse_ahriman(obj
);
765 ELevitation
= W_ART
; /* other than W_ARTI */
767 You("drop %s.", doname(obj
));
771 float_down(I_SPECIAL
| TIMEOUT
, W_ARTI
| W_ART
);
774 if (!IS_ALTAR(levl
[u
.ux
][u
.uy
].typ
) && flags
.verbose
)
775 You("drop %s.", doname(obj
));
777 obj
->how_lost
= LOST_DROPPED
;
782 /* dropx - take dropped item out of inventory;
783 called in several places - may produce output
784 (eg ship_object() and dropy() -> sellobj() both produce output) */
786 dropx(struct obj
*obj
)
790 if (ship_object(obj
, u
.ux
, u
.uy
, FALSE
))
792 if (IS_ALTAR(levl
[u
.ux
][u
.uy
].typ
))
793 doaltarobj(obj
); /* set bknown */
798 /* dropy - put dropped object at destination; called from lots of places */
800 dropy(struct obj
*obj
)
805 /* dropz - really put dropped object at its destination... */
807 dropz(struct obj
*obj
, boolean with_impact
)
810 setuwep((struct obj
*) 0);
812 setuqwep((struct obj
*) 0);
814 setuswapwep((struct obj
*) 0);
817 /* hero has dropped an item while inside an engulfer */
818 if (obj
!= uball
) { /* mon doesn't pick up ball */
819 /* moving shop item into engulfer's inventory treated as theft */
821 (void) stolen_value(obj
, u
.ux
, u
.uy
, TRUE
, FALSE
);
822 /* add to engulfer's inventory if not immediately eaten */
823 if (!engulfer_digests_food(obj
))
824 (void) mpickobj(u
.ustuck
, obj
);
827 if (flooreffects(obj
, u
.ux
, u
.uy
, "drop"))
829 place_object(obj
, u
.ux
, u
.uy
);
831 container_impact_dmg(obj
, u
.ux
, u
.uy
);
832 impact_disturbs_zombies(obj
, with_impact
);
834 drop_ball(u
.ux
, u
.uy
);
835 else if (svl
.level
.flags
.has_shop
)
836 sellobj(obj
, u
.ux
, u
.uy
);
838 if (Blind
&& Levitation
)
840 newsym(u
.ux
, u
.uy
); /* remap location under self */
842 (void) encumber_msg();
845 /* when swallowed, move dropped object from OBJ_FREE to u.ustuck's inventory;
846 for purple worm, immediately eat any corpse, glob, or special meat item
847 from object polymorph; return True if object is used up, False otherwise */
849 engulfer_digests_food(struct obj
*obj
)
851 /* animal swallower (purple worn) eats any
852 corpse, glob, or meat <item> but not other types of food */
853 if (digests(u
.ustuck
->data
)
854 && (obj
->otyp
== CORPSE
|| obj
->globby
855 || obj
->otyp
== MEATBALL
|| obj
->otyp
== ENORMOUS_MEATBALL
856 || obj
->otyp
== MEAT_RING
|| obj
->otyp
== MEAT_STICK
)) {
857 boolean could_petrify
= FALSE
,
858 could_poly
= FALSE
, could_slime
= FALSE
,
859 could_grow
= FALSE
, could_heal
= FALSE
;
861 if (obj
->otyp
== CORPSE
) {
862 could_petrify
= touch_petrifies(&mons
[obj
->corpsenm
]);
863 could_poly
= polyfood(obj
);
864 could_grow
= (obj
->corpsenm
== PM_WRAITH
);
865 could_heal
= (obj
->corpsenm
== PM_NURSE
);
866 } else if (obj
->otyp
== GLOB_OF_GREEN_SLIME
) {
869 /* see or feel the effect */
870 pline("%s instantly digested!", Tobjnam(obj
, "are"));
872 if (could_poly
|| could_slime
) {
873 (void) newcham(u
.ustuck
, could_slime
? &mons
[PM_GREEN_SLIME
] : 0,
874 could_slime
? NC_SHOW_MSG
: NO_NC_FLAGS
);
875 } else if (could_petrify
) {
876 minstapetrify(u
.ustuck
, TRUE
);
877 } else if (could_grow
) {
878 (void) grow_up(u
.ustuck
, (struct monst
*) 0);
879 } else if (could_heal
) {
880 healmon(u
.ustuck
, u
.ustuck
->mhpmax
, 0);
881 /* False: don't realize that sight is cured from inside */
882 mcureblindness(u
.ustuck
, FALSE
);
884 delobj(obj
); /* always used up */
890 /* things that must change when not held; recurse into containers.
891 Called for both player and monsters */
893 obj_no_longer_held(struct obj
*obj
)
897 } else if (Has_contents(obj
)) {
898 struct obj
*contents
;
900 for (contents
= obj
->cobj
; contents
; contents
= contents
->nobj
)
901 obj_no_longer_held(contents
);
905 /* Normal crysknife reverts to worm tooth when not held by hero
906 * or monster; fixed crysknife has only 10% chance of reverting.
907 * When a stack of the latter is involved, it could be worthwhile
908 * to give each individual crysknife its own separate 10% chance,
909 * but we aren't in any position to handle stack splitting here.
911 if (!obj
->oerodeproof
|| !rn2(10)) {
912 /* if monsters aren't moving, assume player is responsible */
913 if (!svc
.context
.mon_moving
&& !program_state
.gameover
)
914 costly_alteration(obj
, COST_DEGRD
);
915 obj
->otyp
= WORM_TOOTH
;
916 obj
->oerodeproof
= 0;
922 /* the #droptype command: drop several things */
926 int result
= ECMD_OK
;
929 You("have nothing to drop.");
932 add_valid_menu_class(0); /* clear any classes already there */
934 sellobj_state(SELL_DELIBERATE
);
935 if (flags
.menu_style
!= MENU_TRADITIONAL
936 || (result
= ggetobj("drop", drop
, 0, FALSE
, (unsigned *) 0)) < -1)
937 result
= menu_drop(result
);
939 sellobj_state(SELL_NORMAL
);
947 better_not_try_to_drop_that(struct obj
*otmp
)
951 /* u_safe_from_fatal_corpse() with st_all checks for gloves and stoning
952 * resistance before bothering to prompt you.
954 if (otmp
->otyp
== CORPSE
&& !u_safe_from_fatal_corpse(otmp
, st_all
)) {
957 "Drop the %s corpse without %s protection on?",
958 obj_pmname(otmp
), body_part(HAND
));
959 return (paranoid_ynq(TRUE
, buf
, FALSE
) != 'y');
963 staticfn
int /* check callers */
964 menudrop_split(struct obj
*otmp
, long cnt
)
966 if (cnt
&& cnt
< otmp
->quan
) {
969 } else if (otmp
->otyp
== LOADSTONE
&& otmp
->cursed
) {
970 /* same kludge as getobj(), for canletgo()'s use */
971 otmp
->corpsenm
= (int) cnt
; /* don't split */
973 otmp
= splitobj(otmp
, cnt
);
979 /* Drop things from the hero's inventory, using a menu. */
983 int n
, i
, n_dropped
= 0;
984 struct obj
*otmp
, *otmp2
;
985 menu_item
*pick_list
;
986 boolean all_categories
= TRUE
, drop_everything
= FALSE
, autopick
= FALSE
;
987 boolean drop_justpicked
= FALSE
;
988 long justpicked_quan
= 0;
991 all_categories
= (retry
== -2);
992 } else if (flags
.menu_style
== MENU_FULL
) {
993 all_categories
= FALSE
;
994 n
= query_category("Drop what type of items?", gi
.invent
,
995 (UNPAID_TYPES
| ALL_TYPES
| CHOOSE_ALL
996 | BUC_BLESSED
| BUC_CURSED
| BUC_UNCURSED
997 | BUC_UNKNOWN
| JUSTPICKED
| INCLUDE_VENOM
),
998 &pick_list
, PICK_ANY
);
999 /* when paranoid_confirm:A is set, 'A' by itself implies
1000 'A'+'a' which will be followed by a confirmation prompt;
1001 when that option isn't set, 'A' by itself is rejected
1002 by query_categorry() and result here will be n==0 */
1004 goto drop_done
; /* no non-autopick category filters specified */
1006 for (i
= 0; i
< n
; i
++) {
1007 if (pick_list
[i
].item
.a_int
== ALL_TYPES_SELECTED
) {
1008 all_categories
= TRUE
;
1009 } else if (pick_list
[i
].item
.a_int
== 'A') {
1010 drop_everything
= autopick
= TRUE
;
1011 } else if (pick_list
[i
].item
.a_int
== 'P') {
1012 justpicked_quan
= max(0, pick_list
[i
].count
);
1013 drop_justpicked
= TRUE
;
1014 drop_everything
= FALSE
;
1015 add_valid_menu_class(pick_list
[i
].item
.a_int
);
1017 add_valid_menu_class(pick_list
[i
].item
.a_int
);
1018 drop_everything
= FALSE
;
1021 free((genericptr_t
) pick_list
);
1022 } else if (flags
.menu_style
== MENU_COMBINATION
) {
1023 unsigned ggoresults
= 0;
1025 all_categories
= FALSE
;
1026 /* Gather valid classes via traditional NetHack method */
1027 i
= ggetobj("drop", drop
, 0, TRUE
, &ggoresults
);
1029 all_categories
= TRUE
;
1030 if ((ggoresults
& ALL_FINISHED
) != 0) {
1038 * Dropping a burning potion of oil while levitating can cause
1039 * an explosion which might destroy some of hero's inventory,
1041 * for (otmp = gi.invent; otmp; otmp = otmp2) {
1042 * otmp2 = otmp->nobj;
1043 * n_dropped += drop(otmp);
1045 * was unreliable and could lead to an "object lost" panic.
1047 * Use the bypass bit to mark items already processed (hence
1048 * not droppable) and rescan inventory until no unbypassed
1051 * FIXME? if something explodes, or even breaks, we probably
1052 * ought to halt the traversal or perhaps ask player whether
1055 bypass_objlist(gi
.invent
, FALSE
); /* clear bypass bit for invent */
1056 while ((otmp
= nxt_unbypassed_obj(gi
.invent
)) != 0) {
1057 if (drop_everything
|| all_categories
|| allow_category(otmp
))
1058 n_dropped
+= ((drop(otmp
) & ECMD_TIME
) != 0) ? 1 : 0;
1060 /* we might not have dropped everything (worn armor, welded weapon,
1061 cursed loadstones), so reset any remaining inventory to normal */
1062 bypass_objlist(gi
.invent
, FALSE
);
1063 } else if (drop_justpicked
&& count_justpicked(gi
.invent
) == 1) {
1064 /* drop the just picked item automatically, if only one stack */
1065 otmp
= find_justpicked(gi
.invent
);
1067 n_dropped
+= ((menudrop_split(otmp
, justpicked_quan
)
1068 & ECMD_TIME
) != 0) ? 1 : 0;
1070 /* should coordinate with perm invent, maybe not show worn items */
1071 n
= query_objlist("What would you like to drop?", &gi
.invent
,
1072 (USE_INVLET
| INVORDER_SORT
| INCLUDE_VENOM
),
1073 &pick_list
, PICK_ANY
,
1074 all_categories
? allow_all
: allow_category
);
1077 * picklist[] contains a set of pointers into inventory, but
1078 * as soon as something gets dropped, they might become stale
1079 * (see the autopick code above for an explanation).
1080 * Just checking to see whether one is still in the gi.invent
1081 * chain is not sufficient validation since destroyed items
1082 * will be freed and items we've split here might have already
1083 * reused that memory and put the same pointer value back into
1084 * gi.invent. Ditto for using invlet to validate. So we start
1085 * by setting bypass on all of gi.invent, then check each pointer
1086 * to verify that it is in gi.invent and has that bit set.
1088 bypass_objlist(gi
.invent
, TRUE
);
1089 for (i
= 0; i
< n
; i
++) {
1090 otmp
= pick_list
[i
].item
.a_obj
;
1091 for (otmp2
= gi
.invent
; otmp2
; otmp2
= otmp2
->nobj
)
1094 if (!otmp2
|| !otmp2
->bypass
)
1096 /* found next selected invent item */
1097 n_dropped
+= ((menudrop_split(otmp
, pick_list
[i
].count
)
1098 & ECMD_TIME
) != 0) ? 1 : 0;
1100 bypass_objlist(gi
.invent
, FALSE
); /* reset gi.invent to normal */
1101 free((genericptr_t
) pick_list
);
1106 return (n_dropped
? ECMD_TIME
: ECMD_OK
);
1110 u_stuck_cannot_go(const char *updn
)
1113 if (u
.uswallow
|| !sticks(gy
.youmonst
.data
)) {
1114 You("are %s, and cannot go %s.",
1115 !u
.uswallow
? "being held"
1116 : digests(u
.ustuck
->data
) ? "swallowed"
1117 : "engulfed", updn
);
1120 struct monst
*mtmp
= u
.ustuck
;
1122 set_ustuck((struct monst
*) 0);
1123 You("release %s.", mon_nam(mtmp
));
1129 /* the #down command */
1133 struct trap
*trap
= 0;
1135 boolean stairs_down
, ladder_down
;
1137 set_move_cmd(DIR_DOWN
, 0);
1142 if (stucksteed(TRUE
)) {
1146 stairs_down
= ladder_down
= FALSE
;
1147 if ((stway
= stairway_at(u
.ux
, u
.uy
)) != 0 && !stway
->up
) {
1148 stairs_down
= !stway
->isladder
;
1149 ladder_down
= !stairs_down
;
1152 /* Levitation might be blocked, but player can still use '>' to
1153 turn off controlled levitation */
1154 if (HLevitation
|| ELevitation
) {
1155 if ((HLevitation
& I_SPECIAL
) || (ELevitation
& W_ARTI
)) {
1156 /* end controlled levitation */
1157 if (ELevitation
& W_ARTI
) {
1160 for (obj
= gi
.invent
; obj
; obj
= obj
->nobj
) {
1162 && artifact_has_invprop(obj
, LEVITATION
)) {
1163 if (obj
->age
< svm
.moves
)
1164 obj
->age
= svm
.moves
;
1165 obj
->age
+= rnz(100);
1169 if (float_down(I_SPECIAL
| TIMEOUT
, W_ARTI
)) {
1170 return ECMD_TIME
; /* came down, so moved */
1171 } else if (!HLevitation
&& !ELevitation
) {
1172 Your("latent levitation ceases.");
1173 return ECMD_TIME
; /* did something, effectively moved */
1177 ; /* weren't actually floating after all */
1179 /* glyph_to_cmap() is a macro which expands its argument many
1180 times; use this to do part of its work just once */
1181 int glyph_at_uxuy
= levl
[u
.ux
][u
.uy
].glyph
;
1183 /* Avoid alerting player to an unknown stair or ladder.
1184 * Changes the message for a covered, known staircase
1185 * too; staircase knowledge is not stored anywhere.
1188 stairs_down
= (glyph_to_cmap(glyph_at_uxuy
) == S_dnstair
);
1189 else if (ladder_down
)
1190 ladder_down
= (glyph_to_cmap(glyph_at_uxuy
) == S_dnladder
);
1192 if (Is_airlevel(&u
.uz
))
1193 You("are floating in the %s.", surface(u
.ux
, u
.uy
));
1194 else if (Is_waterlevel(&u
.uz
))
1195 You("are floating in %s.",
1196 is_pool(u
.ux
, u
.uy
) ? "the water" : "a bubble of air");
1198 floating_above(stairs_down
? "stairs"
1199 : ladder_down
? "ladder"
1200 : surface(u
.ux
, u
.uy
));
1201 return ECMD_OK
; /* didn't move */
1204 if (Upolyd
&& ceiling_hider(&mons
[u
.umonnum
]) && u
.uundetected
) {
1206 if (Flying
) { /* lurker above */
1207 You("fly out of hiding.");
1208 } else { /* piercer */
1209 You("drop to the %s.", surface(u
.ux
, u
.uy
));
1210 if (is_pool_or_lava(u
.ux
, u
.uy
)) {
1214 if ((trap
= t_at(u
.ux
, u
.uy
)) != 0)
1215 dotrap(trap
, TOOKPLUNGE
);
1218 return ECMD_TIME
; /* came out of hiding; need '>' again to go down */
1221 if (u_stuck_cannot_go("down"))
1224 if (!stairs_down
&& !ladder_down
) {
1225 trap
= t_at(u
.ux
, u
.uy
);
1226 if (trap
&& (uteetering_at_seen_pit(trap
) || uescaped_shaft(trap
))) {
1227 dotrap(trap
, TOOKPLUNGE
);
1229 } else if (!trap
|| !is_hole(trap
->ttyp
)
1230 || !Can_fall_thru(&u
.uz
) || !trap
->tseen
) {
1231 if (flags
.autodig
&& !svc
.context
.nopick
1232 && uwep
&& is_pick(uwep
)) {
1233 return use_pick_axe2(uwep
);
1235 You_cant("go down here%s.",
1236 (trap
&& trap
->ttyp
== VIBRATING_SQUARE
) ? " yet"
1242 if (on_level(&valley_level
, &u
.uz
) && !u
.uevent
.gehennom_entered
) {
1243 You("are standing at the gate to Gehennom.");
1244 pline("Unspeakable cruelty and harm lurk down there.");
1245 if (y_n("Are you sure you want to enter?") != 'y')
1248 u
.uevent
.gehennom_entered
= 1; /* don't ask again */
1252 You("are held back by your pet!");
1257 const char *down_or_thru
= trap
->ttyp
== HOLE
? "down" : "through";
1258 const char *actn
= u_locomotion("jump");
1260 if (gy
.youmonst
.data
->msize
>= MZ_HUGE
) {
1263 You("don't fit %s easily.", down_or_thru
);
1264 Sprintf(qbuf
, "Try to squeeze %s?", down_or_thru
);
1265 if (y_n(qbuf
) == 'y') {
1267 actn
= "manage to squeeze";
1268 losehp(Maybe_Half_Phys(rnd(4)),
1269 "contusion from a small passage", KILLED_BY
);
1271 You("were unable to fit %s.", down_or_thru
);
1278 You("%s %s the %s.", actn
, down_or_thru
,
1279 trap
->ttyp
== HOLE
? "hole" : "trap door");
1281 if (trap
&& Is_stronghold(&u
.uz
)) {
1282 goto_hell(FALSE
, TRUE
);
1283 } else if (trap
&& trap
->dst
.dlevel
!= -1) {
1285 assign_level(&tdst
, &(trap
->dst
));
1286 (void) clamp_hole_destination(&tdst
);
1287 goto_level(&tdst
, FALSE
, FALSE
, FALSE
);
1289 ga
.at_ladder
= (boolean
) (levl
[u
.ux
][u
.uy
].typ
== LADDER
);
1291 ga
.at_ladder
= FALSE
;
1296 /* the #up command - move up a staircase */
1300 stairway
*stway
= stairway_at(u
.ux
,u
.uy
);
1302 set_move_cmd(DIR_UP
, 0);
1307 /* "up" to get out of a pit... */
1308 if (u
.utrap
&& u
.utraptype
== TT_PIT
) {
1313 if (!stway
|| (stway
&& !stway
->up
)) {
1314 You_cant("go up here.");
1317 if (stucksteed(TRUE
)) {
1321 if (u_stuck_cannot_go("up"))
1324 if (near_capacity() > SLT_ENCUMBER
) {
1325 /* No levitation check; inv_weight() already allows for it */
1326 Your("load is too heavy to climb the %s.",
1327 levl
[u
.ux
][u
.uy
].typ
== STAIRS
? "stairs" : "ladder");
1330 if (ledger_no(&u
.uz
) == 1) {
1331 if (iflags
.debug_fuzzer
)
1333 if (y_n("Beware, there will be no return! Still climb?") != 'y')
1337 You("are held back by your pet!");
1340 ga
.at_ladder
= (boolean
) (levl
[u
.ux
][u
.uy
].typ
== LADDER
);
1342 ga
.at_ladder
= FALSE
;
1346 /* check that we can write out the current level */
1348 currentlevel_rewrite(void)
1353 /* since level change might be a bit slow, flush any buffered screen
1354 * output (like "you fall through a trap door") */
1357 nhfp
= create_levelfile(ledger_no(&u
.uz
), whynot
);
1360 * This is not quite impossible: e.g., we may have
1361 * exceeded our quota. If that is the case then we
1362 * cannot leave this level, and cannot save either.
1363 * Another possibility is that the directory was not
1367 return (NHFILE
*) 0;
1375 save_currentstate(void)
1379 program_state
.in_checkpoint
++;
1380 if (flags
.ins_chkpt
) {
1381 /* write out just-attained level, with pets and everything */
1382 nhfp
= currentlevel_rewrite();
1385 if (nhfp
->structlevel
)
1387 nhfp
->mode
= WRITING
;
1388 savelev(nhfp
,ledger_no(&u
.uz
));
1392 /* write out non-level state */
1394 program_state
.in_checkpoint
--;
1400 badspot(coordxy x, coordxy y)
1402 return (boolean) ((levl[x][y].typ != ROOM
1403 && levl[x][y].typ != AIR
1404 && levl[x][y].typ != CORR)
1409 /* when arriving on a level, if hero and a monster are trying to share same
1410 spot, move one; extracted from goto_level(); also used by wiz_makemap() */
1412 u_collide_m(struct monst
*mtmp
)
1416 if (!mtmp
|| mtmp
== u
.usteed
|| mtmp
!= m_at(u
.ux
, u
.uy
)) {
1417 impossible("level arrival collision: %s?",
1418 !mtmp
? "no monster"
1419 : (mtmp
== u
.usteed
) ? "steed is on map"
1420 : "monster not co-located");
1424 /* There's a monster at your target destination; it might be one
1425 which accompanied you--see mon_arrive(dogmove.c)--or perhaps
1426 it was already here. Randomly move you to an adjacent spot
1427 or else the monster to any nearby location. Prior to 3.3.0
1428 the latter was done unconditionally. */
1429 if (!rn2(2) && enexto(&cc
, u
.ux
, u
.uy
, gy
.youmonst
.data
)
1430 && next2u(cc
.x
, cc
.y
))
1431 u_on_newpos(cc
.x
, cc
.y
); /*[maybe give message here?]*/
1433 mnexto(mtmp
, RLOC_NOMSG
);
1435 if ((mtmp
= m_at(u
.ux
, u
.uy
)) != 0) {
1436 /* there was an unconditional impossible("mnexto failed")
1437 here, but it's not impossible and we're prepared to cope
1438 with the situation, so only say something when debugging */
1440 pline("(monster in hero's way)");
1441 if (!rloc(mtmp
, RLOC_NOMSG
) || (mtmp
= m_at(u
.ux
, u
.uy
)) != 0)
1442 /* no room to move it; send it away, to return later */
1448 familiar_level_msg(void)
1450 static const char *const fam_msgs
[4] = {
1451 "You have a sense of deja vu.",
1452 "You feel like you've been here before.",
1453 "This place %s familiar...", 0 /* no message */
1455 static const char *const halu_fam_msgs
[4] = {
1456 "Whoa! Everything %s different.",
1457 "You are surrounded by twisty little passages, all alike.",
1458 "Gee, this %s like uncle Conan's place...", 0 /* no message */
1465 mesg
= halu_fam_msgs
[which
];
1467 mesg
= fam_msgs
[which
];
1468 if (mesg
&& strchr(mesg
, '%')) {
1469 DISABLE_WARNING_FORMAT_NONLITERAL
1470 Sprintf(buf
, mesg
, !Blind
? "looks" : "seems");
1471 RESTORE_WARNING_FORMAT_NONLITERAL
1480 d_level
*newlevel
, /* destination */
1481 boolean at_stairs
, /* True if arriving via stairs/ladder */
1482 boolean falling
, /* when falling to level, objects might tag along */
1483 boolean portal
) /* True if arriving via magic portal */
1485 int l_idx
, save_mode
;
1488 boolean cant_go_back
, great_effort
,
1489 up
= (depth(newlevel
) < depth(&u
.uz
)),
1490 newdungeon
= (u
.uz
.dnum
!= newlevel
->dnum
),
1491 leaving_tutorial
= FALSE
,
1492 was_in_W_tower
= In_W_tower(u
.ux
, u
.uy
, &u
.uz
),
1494 new = FALSE
; /* made a new level? */
1497 int dist
= depth(newlevel
) - depth(&u
.uz
);
1498 boolean do_fall_dmg
= FALSE
;
1499 schar prev_temperature
= svl
.level
.flags
.temperature
;
1501 if (dunlev(newlevel
) > dunlevs_in_dungeon(newlevel
))
1502 newlevel
->dlevel
= dunlevs_in_dungeon(newlevel
);
1504 if (In_endgame(newlevel
)) { /* 1st Endgame Level !!! */
1505 if (!u
.uhave
.amulet
)
1506 return; /* must have the Amulet */
1507 if (!wizard
) /* wizard ^V can bypass Earth level */
1508 assign_level(newlevel
, &earth_level
); /* (redundant) */
1509 } else if (In_tutorial(newlevel
)) {
1510 tutorial(TRUE
); /* entering tutorial */
1511 } else if (In_tutorial(&u
.uz
)) {
1512 tutorial(FALSE
); /* leaving tutorial */
1513 up
= FALSE
; /* re-enter level 1 as if starting new game */
1514 leaving_tutorial
= TRUE
;
1517 new_ledger
= ledger_no(newlevel
);
1518 if (new_ledger
<= 0)
1519 done(ESCAPED
); /* in fact < 0 is impossible */
1521 /* If you have the amulet and are trying to get out of Gehennom,
1522 * going up a set of stairs sometimes does some very strange things!
1523 * Biased against law and towards chaos. (The chance to be sent
1524 * down multiple levels when attempting to go up are significantly
1525 * less than the corresponding comment in older versions indicated
1526 * due to overlooking the effect of the call to assign_rnd_lvl().)
1528 * Odds for making it to the next level up, or of being sent down:
1532 * -1 11.46 12.50 12.5
1536 * 3.7.0: the chance for the "mysterious force" to kick in goes down
1537 * as it kicks in, starting at 25% per climb attempt and dropping off
1538 * gradually but substantially. The drop off is greater when hero is
1539 * sent down farther so benefits lawfuls more than chaotics this time.
1541 if (Inhell
&& up
&& u
.uhave
.amulet
&& !newdungeon
&& !portal
1542 && (dunlev(&u
.uz
) < dunlevs_in_dungeon(&u
.uz
) - 3)) {
1543 if (!rn2(4 + svc
.context
.mysteryforce
)) {
1544 int odds
= 3 + (int) u
.ualign
.type
, /* 2..4 */
1545 diff
= (odds
<= 1) ? 0 : rn2(odds
); /* paranoia */
1548 assign_rnd_level(newlevel
, &u
.uz
, diff
);
1549 /* assign_rnd_level() may have used a value less than diff */
1550 diff
= newlevel
->dlevel
- u
.uz
.dlevel
; /* actual descent */
1551 /* if inside the tower, stay inside */
1552 if (was_in_W_tower
&& !On_W_tower_level(newlevel
))
1556 assign_level(newlevel
, &u
.uz
);
1558 pline("A mysterious force momentarily surrounds you...");
1559 /* each time it kicks in, the chance of doing so again may drop;
1560 that drops faster, on average, when being sent down farther so
1561 while the impact is reduced for everybody compared to earlier
1562 versions, it is reduced least for chaotics, most for lawfuls */
1563 svc
.context
.mysteryforce
+= rn2(diff
+ 2); /* L:0-4,N:0-3,C:0-2 */
1565 if (on_level(newlevel
, &u
.uz
)) {
1566 (void) safe_teleds(TELEDS_NO_FLAGS
);
1570 new_ledger
= ledger_no(newlevel
);
1571 at_stairs
= ga
.at_ladder
= FALSE
;
1575 /* Prevent the player from going past the first quest level unless
1576 * (s)he has been given the go-ahead by the leader.
1578 if (on_level(&u
.uz
, &qstart_level
) && !newdungeon
&& !ok_to_quest()) {
1579 pline("A mysterious force prevents you from descending.");
1583 if (on_level(newlevel
, &u
.uz
))
1584 return; /* this can happen */
1586 if (gl
.luacore
&& nhcb_counts
[NHCB_LVL_LEAVE
]) {
1587 lua_getglobal(gl
.luacore
, "nh_callback_run");
1588 lua_pushstring(gl
.luacore
, nhcb_name
[NHCB_LVL_LEAVE
]);
1589 nhl_pcall_handle(gl
.luacore
, 1, 0, "goto_level", NHLpa_panic
);
1590 lua_settop(gl
.luacore
, 0);
1593 /* tethered movement makes level change while trapped feasible */
1594 if (u
.utrap
&& u
.utraptype
== TT_BURIEDBALL
)
1595 buried_ball_to_punishment(); /* (before we save/leave old level) */
1597 nhfp
= currentlevel_rewrite();
1601 /* discard context which applies to the level we're leaving;
1602 for lock-picking, container may be carried, in which case we
1603 keep context; if on the floor, it's about to be saved+freed and
1604 maybe_reset_pick() needs to do its carried() check before that */
1605 maybe_reset_pick((struct obj
*) 0);
1606 reset_trapset(); /* even if to-be-armed trap obj is accompanying hero */
1607 iflags
.travelcc
.x
= iflags
.travelcc
.y
= 0; /* travel destination cache */
1608 svc
.context
.polearm
.hitmon
= (struct monst
*) 0; /* polearm target */
1609 /* digging context is level-aware and can actually be resumed if
1610 hero returns to the previous level without any intervening dig */
1612 if (falling
) /* assuming this is only trap door or hole */
1613 impact_drop((struct obj
*) 0, u
.ux
, u
.uy
, newlevel
->dlevel
);
1615 check_special_room(TRUE
); /* probably was a trap door */
1618 reset_utrap(FALSE
); /* needed in level_tele */
1619 fill_pit(u
.ux
, u
.uy
);
1620 set_ustuck((struct monst
*) 0); /* clear u.ustuck and u.uswallow */
1621 set_uinwater(0); /* u.uinwater = 0 */
1622 u
.uundetected
= 0; /* not hidden, even if means are available */
1623 if (!iflags
.nofollowers
)
1625 recalc_mapseen(); /* recalculate map overview before we leave the level */
1627 * We no longer see anything on the level. Make sure that this
1628 * follows u.uswallow set to null since uswallow overrides all
1634 * Save the level we're leaving. If we're entering the endgame,
1635 * we can get rid of all existing levels because they cannot be
1636 * reached any more. We still need to use savelev()'s cleanup
1637 * for the level being left, to recover dynamic memory in use and
1638 * to avoid dangling timers and light sources.
1640 cant_go_back
= ((newdungeon
&& In_endgame(newlevel
)) || leaving_tutorial
);
1641 if (!cant_go_back
) {
1642 update_mlstmv(); /* current monsters are becoming inactive */
1643 if (nhfp
->structlevel
)
1644 bufon(nhfp
->fd
); /* use buffered output */
1646 free_luathemes(leaving_tutorial
? tut_themes
: most_themes
);
1648 save_mode
= nhfp
->mode
;
1649 nhfp
->mode
= cant_go_back
? FREEING
: (WRITING
| FREEING
);
1650 savelev(nhfp
, ledger_no(&u
.uz
));
1651 nhfp
->mode
= save_mode
;
1654 /* discard unreachable levels; keep #0 */
1655 for (l_idx
= maxledgerno(); l_idx
> 0; --l_idx
)
1656 if (!leaving_tutorial
|| ledger_to_dnum(l_idx
) == tutorial_dnum
)
1657 delete_levelfile(l_idx
);
1658 /* mark #overview data for all dungeon branches as uninteresting */
1659 for (l_idx
= 0; l_idx
< svn
.n_dgns
; ++l_idx
)
1660 if (!leaving_tutorial
|| l_idx
== tutorial_dnum
)
1661 remdun_mapseen(l_idx
);
1662 /* get rid of mons & objs scheduled to migrate to discarded levels */
1663 discard_migrations();
1666 if (Is_rogue_level(newlevel
) || Is_rogue_level(&u
.uz
))
1667 assign_graphics(Is_rogue_level(newlevel
) ? ROGUESET
: PRIMARYSET
);
1668 check_gold_symbol();
1669 /* record this level transition as a potential seen branch unless using
1670 * some non-standard means of transportation (level teleport).
1672 if ((at_stairs
|| falling
|| portal
) && (u
.uz
.dnum
!= newlevel
->dnum
))
1673 recbranch_mapseen(&u
.uz
, newlevel
);
1674 assign_level(&u
.uz0
, &u
.uz
);
1675 assign_level(&u
.uz
, newlevel
);
1676 assign_level(&u
.utolev
, newlevel
);
1677 u
.utotype
= UTOTYPE_NONE
;
1678 if (!builds_up(&u
.uz
)) { /* usual case */
1679 if (dunlev(&u
.uz
) > dunlev_reached(&u
.uz
))
1680 dunlev_reached(&u
.uz
) = dunlev(&u
.uz
);
1682 if (dunlev_reached(&u
.uz
) == 0
1683 || dunlev(&u
.uz
) < dunlev_reached(&u
.uz
))
1684 dunlev_reached(&u
.uz
) = dunlev(&u
.uz
);
1687 stairway_free_all();
1688 /* set default level change destination areas */
1689 /* the special level code may override these */
1690 (void) memset((genericptr_t
) &svu
.updest
, 0, sizeof svu
.updest
);
1691 (void) memset((genericptr_t
) &svd
.dndest
, 0, sizeof svd
.dndest
);
1693 if (!(svl
.level_info
[new_ledger
].flags
& LFILE_EXISTS
)) {
1694 /* entering this level for first time; make it now */
1695 if (svl
.level_info
[new_ledger
].flags
& (VISITED
)) {
1696 impossible("goto_level: returning to discarded level?");
1697 svl
.level_info
[new_ledger
].flags
&= ~(VISITED
);
1700 new = TRUE
; /* made the level */
1701 familiar
= bones_include_name(svp
.plname
);
1703 /* returning to previously visited level; reload it */
1704 nhfp
= open_levelfile(new_ledger
, whynot
);
1705 if (tricked_fileremoved(nhfp
, whynot
)) {
1706 /* we'll reach here if running in wizard mode */
1707 error("Cannot continue this game.");
1710 reseed_random(rn2_on_display_rng
);
1711 minit(); /* ZEROCOMP */
1712 getlev(nhfp
, svh
.hackpid
, new_ledger
);
1714 oinit(); /* reassign level dependent obj probabilities */
1717 set_uinwater(0); /* u.uinwater = 0 */
1718 /* do this prior to level-change pline messages */
1719 vision_reset(); /* clear old level's line-of-sight */
1720 gv
.vision_full_recalc
= 0; /* don't let that reenable vision yet */
1721 flush_screen(-1); /* ensure all map flushes are postponed */
1723 if (portal
&& !In_endgame(&u
.uz
)) {
1724 /* find the portal on the new level */
1727 for (ttrap
= gf
.ftrap
; ttrap
; ttrap
= ttrap
->ntrap
)
1728 if (ttrap
->ttyp
== MAGIC_PORTAL
)
1732 if (u
.uevent
.qexpelled
1733 && (Is_qstart(&u
.uz0
) || Is_qstart(&u
.uz
))) {
1734 /* we're coming back from or going into the quest home level,
1735 after already getting expelled once. The portal back
1736 doesn't exist anymore - see expulsion(). */
1739 if (!iflags
.debug_fuzzer
)
1740 impossible("goto_level: no corresponding portal!");
1745 u_on_newpos(ttrap
->tx
, ttrap
->ty
);
1747 } else if (at_stairs
&& !In_endgame(&u
.uz
)) {
1749 stairway
*stway
= stairway_find_from(&u
.uz0
, ga
.at_ladder
);
1751 u_on_newpos(stway
->sx
, stway
->sy
);
1752 stway
->u_traversed
= TRUE
;
1753 } else if (newdungeon
)
1757 /* you climb up the {stairs|ladder};
1758 fly up the stairs; fly up along the ladder */
1759 great_effort
= (Punished
&& !Levitation
);
1760 if (flags
.verbose
|| great_effort
)
1761 pline("%s %s up%s the %s.",
1762 great_effort
? "With great effort, you" : "You",
1763 u_locomotion("climb"),
1764 (Flying
&& ga
.at_ladder
) ? " along" : "",
1765 ga
.at_ladder
? "ladder" : "stairs");
1767 stairway
*stway
= stairway_find_from(&u
.uz0
, ga
.at_ladder
);
1769 u_on_newpos(stway
->sx
, stway
->sy
);
1770 stway
->u_traversed
= TRUE
;
1771 } else if (newdungeon
)
1776 ; /* stayed on same level? (no transit effects) */
1777 } else if (Flying
) {
1780 ga
.at_ladder
? "along the ladder" : "the stairs");
1781 } else if (near_capacity() > UNENCUMBERED
1782 || Punished
|| Fumbling
) {
1783 You("fall down the %s.", ga
.at_ladder
? "ladder" : "stairs");
1789 /* falling off steed has its own losehp() call */
1791 dismount_steed(DISMOUNT_FELL
);
1793 losehp(Maybe_Half_Phys(rnd(3)),
1794 ga
.at_ladder
? "falling off a ladder"
1795 : "tumbling down a flight of stairs",
1797 selftouch("Falling, you");
1798 } else { /* ordinary descent */
1800 You("%s.", ga
.at_ladder
? "climb down the ladder"
1801 : "descend the stairs");
1804 } else { /* trap door or level_tele or In_endgame */
1805 u_on_rndspot((up
? 1 : 0) | (was_in_W_tower
? 2 : 0));
1807 if (Punished
&& !welded(uball
))
1809 selftouch("Falling, you");
1816 obj_delivery(FALSE
);
1818 kill_genocided_monsters(); /* for those wiped out while in limbo */
1820 * Expire all timers that have gone off while away. Must be
1821 * after migrating monsters and objects are delivered
1822 * (losedogs and obj_delivery).
1826 /* hero might be arriving at a spot containing a monster;
1827 if so, move one or the other to another location */
1828 if ((mtmp
= m_at(u
.ux
, u
.uy
)) != 0)
1831 /* initial movement of bubbles just before vision_recalc */
1832 if (Is_waterlevel(&u
.uz
) || Is_airlevel(&u
.uz
))
1834 else if (svl
.level
.flags
.fumaroles
)
1837 /* Reset the screen. */
1838 vision_reset(); /* reset the blockages */
1839 reset_glyphmap(gm_levelchange
);
1840 notice_mon_off(); /* not noticing monsters yet! */
1841 docrt(); /* does a full vision recalc */
1845 * Move all plines beyond the screen reset.
1848 /* deferred arrival message for level teleport looks odd if given
1849 after the various messages below, so give it before them;
1850 [it might have already been delivered via docrt() -> see_monsters()
1851 -> Sting_effects() -> maybe_lvltport_feedback(), in which case
1852 'dfr_post_msg' has already been reset to Null];
1853 if 'dfr_post_msg' is "you materialize on a different level" then
1854 maybe_lvltport_feedback() will deliver it now and then free it */
1855 if (gd
.dfr_post_msg
)
1856 maybe_lvltport_feedback(); /* potentially called by Sting_effects() */
1858 /* special levels can have a custom arrival message */
1859 deliver_splev_message();
1861 /* Check whether we just entered Gehennom. */
1862 if (!In_hell(&u
.uz0
) && Inhell
) {
1863 if (Is_valley(&u
.uz
)) {
1864 You("arrive at the Valley of the Dead...");
1865 pline_The("odor of burnt flesh and decay pervades the air.");
1867 display_nhwindow(WIN_MESSAGE
, FALSE
);
1869 Soundeffect(se_groans_and_moans
, 25);
1870 You_hear("groans and moans everywhere.");
1873 record_achievement(ACH_HELL
); /* reached Gehennom */
1875 /* in case we've managed to bypass the Valley's stairway down */
1876 if (Inhell
&& !Is_valley(&u
.uz
))
1877 u
.uevent
.gehennom_entered
= 1;
1880 familiar_level_msg();
1882 /* special location arrival messages/events */
1883 if (In_endgame(&u
.uz
)) {
1885 record_achievement(ACH_ENDG
); /* reached endgame */
1886 if (new && on_level(&u
.uz
, &astral_level
)) {
1887 final_level(); /* guardian angel,&c */
1888 record_achievement(ACH_ASTR
); /* reached Astral level */
1889 } else if (newdungeon
&& u
.uhave
.amulet
) {
1890 resurrect(); /* force confrontation with Wizard */
1892 } else if (In_quest(&u
.uz
)) {
1893 onquest(); /* might be reaching locate|goal level */
1894 } else if (Is_knox(&u
.uz
)) {
1895 /* alarm stops working once Croesus has died */
1896 if (new || !svm
.mvitals
[PM_CROESUS
].died
) {
1897 You("have penetrated a high security area!");
1898 Soundeffect(se_alarm
, 100);
1899 pline("An alarm sounds!");
1900 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
) {
1901 if (DEADMONSTER(mtmp
))
1903 mtmp
->msleeping
= 0;
1906 } else if (In_mines(&u
.uz
)) {
1908 record_achievement(ACH_MINE
);
1909 } else if (In_sokoban(&u
.uz
)) {
1911 record_achievement(ACH_SOKO
);
1913 if (new && Is_rogue_level(&u
.uz
)) {
1914 You("enter what seems to be an older, more primitive world.");
1915 } else if (new && Is_bigroom(&u
.uz
)) {
1916 record_achievement(ACH_BGRM
);
1918 /* main dungeon message from your quest leader */
1919 if (!In_quest(&u
.uz0
) && at_dgn_entrance("The Quest")
1920 && !(u
.uevent
.qcompleted
|| u
.uevent
.qexpelled
1921 || svq
.quest_status
.leader_is_dead
)) {
1922 /* [TODO: copy of same TODO below; if an achievement for
1923 receiving quest call from leader gets added, that should
1924 come after logging new level entry] */
1925 if (!u
.uevent
.qcalled
) {
1926 u
.uevent
.qcalled
= 1;
1927 /* main "leader needs help" message */
1928 com_pager("quest_portal");
1929 } else { /* reminder message */
1930 com_pager(Role_if(PM_ROGUE
) ? "quest_portal_demand"
1931 : "quest_portal_again");
1936 temperature_change_msg(prev_temperature
);
1938 /* this was originally done earlier; moved here to be logged after
1939 any achievement related to entering a dungeon branch
1940 [TODO: if an achievement for receiving quest call from leader
1941 gets added, that should come after this rather than take place
1942 where the message is delivered above] */
1945 /* Astral is excluded as a major event here because entry to it
1946 is already one due to that being an achievement */
1947 boolean major
= In_endgame(&u
.uz
) && !Is_astralevel(&u
.uz
);
1949 (void) describe_level(dloc
, 2);
1950 livelog_printf(major
? LL_ACHIEVE
: LL_DEBUG
, "entered %s", dloc
);
1952 if (Role_if(PM_TOURIST
)) {
1953 more_experienced(level_difficulty(), 0);
1958 assign_level(&u
.uz0
, &u
.uz
); /* reset u.uz0 */
1960 save_currentstate();
1963 notice_all_mons(TRUE
);
1965 print_level_annotation();
1966 /* give room entrance message, if any */
1967 check_special_room(FALSE
);
1968 /* deliver objects traveling with player */
1971 /* assume this will always return TRUE when changing level */
1972 (void) in_out_region(u
.ux
, u
.uy
);
1973 /* shop repair is normally done when shopkeepers move, but we may
1974 need to catch up for lost time here; do this before maybe dying
1975 so bones map will include it */
1981 int dmg
= d(max(dist
, 1), 6);
1983 dmg
= Maybe_Half_Phys(dmg
);
1984 losehp(dmg
, "falling down a mine shaft", KILLED_BY
);
1991 /* give a message when entering a Gehennom level other than the Valley;
1992 also given if restoring a game in that situation */
1994 hellish_smoke_mesg(void)
1996 if (svl
.level
.flags
.temperature
)
1997 pline("It is %s here.",
1998 svl
.level
.flags
.temperature
> 0 ? "hot" : "cold");
2000 if (In_hell(&u
.uz
) && svl
.level
.flags
.temperature
> 0)
2002 olfaction(gy
.youmonst
.data
) ? "smell" : "sense");
2005 /* give a message when the level temperature is different from previous */
2007 temperature_change_msg(schar prev_temperature
)
2009 if (prev_temperature
!= svl
.level
.flags
.temperature
) {
2010 if (svl
.level
.flags
.temperature
)
2011 hellish_smoke_mesg();
2012 else if (prev_temperature
> 0)
2013 pline_The("heat %s gone.",
2015 ? "and smoke are" : "is");
2016 else if (prev_temperature
< 0)
2017 You("are out of the cold.");
2021 /* usually called from goto_level(); might be called from Sting_effects() */
2023 maybe_lvltport_feedback(void)
2026 && !strncmpi(gd
.dfr_post_msg
, "You materialize", 15)) {
2027 /* "You materialize on a different level." */
2028 pline("%s", gd
.dfr_post_msg
);
2029 free((genericptr_t
) gd
.dfr_post_msg
), gd
.dfr_post_msg
= 0;
2036 /* reset monster hostility relative to player */
2037 iter_mons(reset_hostility
);
2039 /* create some player-monsters */
2040 create_mplayers(rn1(4, 3), TRUE
);
2042 /* create a guardian angel next to player, if worthy */
2043 gain_guardian_angel();
2046 /* change levels at the end of this turn, after monsters finish moving */
2051 const char *pre_msg
, const char *post_msg
)
2053 /* UTOTYPE_DEFERRED is used, so UTOTYPE_NONE can trigger deferred_goto() */
2054 u
.utotype
= utotype_flags
| UTOTYPE_DEFERRED
;
2055 /* destination level */
2056 assign_level(&u
.utolev
, tolev
);
2059 gd
.dfr_pre_msg
= dupstr(pre_msg
);
2061 gd
.dfr_post_msg
= dupstr(post_msg
);
2064 /* handle something like portal ejection */
2068 if (!on_level(&u
.uz
, &u
.utolev
)) {
2069 d_level dest
, oldlev
;
2070 int typmask
= u
.utotype
; /* save it; goto_level zeroes u.utotype */
2072 assign_level(&dest
, &u
.utolev
);
2073 assign_level(&oldlev
, &u
.uz
);
2075 pline1(gd
.dfr_pre_msg
);
2076 goto_level(&dest
, !!(typmask
& UTOTYPE_ATSTAIRS
),
2077 !!(typmask
& UTOTYPE_FALLING
),
2078 !!(typmask
& UTOTYPE_PORTAL
));
2079 if (typmask
& UTOTYPE_RMPORTAL
) { /* remove portal */
2080 struct trap
*t
= t_at(u
.ux
, u
.uy
);
2087 if (gd
.dfr_post_msg
&& !on_level(&u
.uz
, &oldlev
))
2088 pline1(gd
.dfr_post_msg
);
2090 u
.utotype
= UTOTYPE_NONE
; /* our caller keys off of this */
2092 free((genericptr_t
) gd
.dfr_pre_msg
), gd
.dfr_pre_msg
= 0;
2093 if (gd
.dfr_post_msg
)
2094 free((genericptr_t
) gd
.dfr_post_msg
), gd
.dfr_post_msg
= 0;
2098 * Return TRUE if we created a monster for the corpse. If successful, the
2102 revive_corpse(struct obj
*corpse
)
2104 struct monst
*mtmp
, *mcarry
;
2105 boolean is_uwep
, chewed
;
2108 struct obj
*container
= (struct obj
*) 0;
2109 int container_where
= 0;
2112 coordxy corpsex
, corpsey
;
2114 where
= corpse
->where
;
2115 montype
= corpse
->corpsenm
;
2116 /* treat buried auto-reviver (troll, Rider?) like a zombie
2117 so that it can dig itself out of the ground if it revives */
2118 is_zomb
= (mons
[montype
].mlet
== S_ZOMBIE
2119 || (where
== OBJ_BURIED
&& is_reviver(&mons
[montype
])));
2120 is_uwep
= (corpse
== uwep
);
2121 chewed
= (corpse
->oeaten
!= 0);
2122 Strcpy(cname
, corpse_xname(corpse
,
2123 chewed
? "bite-covered" : (const char *) 0,
2125 mcarry
= (where
== OBJ_MINVENT
) ? corpse
->ocarry
: 0;
2126 /* mcarry is NULL for (where == OBJ_BURIED and OBJ_CONTAINED) now */
2128 (void) get_obj_location(corpse
, &corpsex
, &corpsey
,
2129 CONTAINED_TOO
| BURIED_TOO
);
2131 if (where
== OBJ_CONTAINED
) {
2132 struct monst
*mtmp2
;
2134 container
= corpse
->ocontainer
;
2135 mtmp2
= get_container_location(container
, &container_where
,
2137 /* container_where is outermost container's location even if nested */
2138 if (container_where
== OBJ_MINVENT
&& mtmp2
)
2141 mtmp
= revive(corpse
, FALSE
); /* corpse is gone if successful */
2147 pline_The("%s writhes out of your grasp!", cname
);
2149 You_feel("squirming in your backpack!");
2153 if (cansee(corpsex
, corpsey
) || canseemon(mtmp
)) {
2154 const char *effect
= "";
2156 if (mtmp
->data
== &mons
[PM_DEATH
])
2157 effect
= " in a whirl of spectral skulls";
2158 else if (mtmp
->data
== &mons
[PM_PESTILENCE
])
2159 effect
= " in a churning pillar of flies";
2160 else if (mtmp
->data
== &mons
[PM_FAMINE
])
2161 effect
= " in a ring of withered crops";
2163 if (canseemon(mtmp
)) {
2164 pline("%s rises from the dead%s!",
2165 chewed
? Adjmonnam(mtmp
, "bite-covered")
2169 pline("%s disappears%s!", The(cname
), effect
);
2174 case OBJ_MINVENT
: /* probably a nymph's */
2175 if (cansee(mtmp
->mx
, mtmp
->my
)) {
2176 if (mcarry
&& canseemon(mcarry
))
2177 pline("Startled, %s drops %s as it %s!",
2178 mon_nam(mcarry
), an(cname
),
2179 canspotmon(mtmp
) ? "revives" : "disappears");
2180 else if (canspotmon(mtmp
))
2181 pline("%s suddenly appears!",
2182 chewed
? Adjmonnam(mtmp
, "bite-covered")
2186 case OBJ_CONTAINED
: {
2187 char sackname
[BUFSZ
];
2188 /* Could use x_monnam(..., AUGMENT_IT) but that'd say "someone"
2189 for humanoid monsters, which seems like a distinction the hero
2190 doesn't have knowledge to make here. */
2191 const char *mnam
= canspotmon(mtmp
) ? Amonnam(mtmp
) : Something
;
2194 impossible("reviving corpse from non-existent container");
2195 } else if (mcarry
&& canseemon(mcarry
)) {
2196 pline("%s writhes out of %s!", mnam
, yname(container
));
2197 } else if (container_where
== OBJ_INVENT
) {
2198 Strcpy(sackname
, an(xname(container
)));
2199 pline("%s %s out of %s in your pack!", mnam
,
2200 locomotion(mtmp
->data
, "writhes"), sackname
);
2201 } else if (container_where
== OBJ_FLOOR
2202 && cansee(corpsex
, corpsey
)) {
2203 Strcpy(sackname
, an(xname(container
)));
2204 pline("%s escapes from %s!", mnam
, sackname
);
2210 maketrap(mtmp
->mx
, mtmp
->my
, PIT
);
2211 if (cansee(mtmp
->mx
, mtmp
->my
)) {
2214 ttmp
= t_at(mtmp
->mx
, mtmp
->my
);
2217 pline("%s claws itself out of the ground!",
2218 canspotmon(mtmp
) ? Amonnam(mtmp
) : Something
);
2219 newsym(mtmp
->mx
, mtmp
->my
);
2220 } else if (mdistu(mtmp
) < 5*5) {
2221 Soundeffect(se_scratching
, 50);
2222 You_hear("scratching noises.");
2224 fill_pit(mtmp
->mx
, mtmp
->my
);
2230 /* we should be able to handle the other cases... */
2231 impossible("revive_corpse: lost corpse @ %d", where
);
2239 /* Revive the corpse via a timeout. */
2242 revive_mon(anything
*arg
, long timeout UNUSED
)
2244 struct obj
*body
= arg
->a_obj
;
2245 struct permonst
*mptr
= &mons
[body
->corpsenm
];
2249 /* corpse will revive somewhere else if there is a monster in the way;
2250 Riders get a chance to try to bump the obstacle out of their way */
2251 if (is_displacer(mptr
) && body
->where
== OBJ_FLOOR
2252 && get_obj_location(body
, &x
, &y
, 0) && (mtmp
= m_at(x
, y
)) != 0) {
2253 boolean notice_it
= canseemon(mtmp
); /* before rloc() */
2254 char *monname
= Monnam(mtmp
);
2256 if (rloc(mtmp
, RLOC_NOMSG
)) {
2257 if (notice_it
&& !canseemon(mtmp
))
2258 pline("%s vanishes.", monname
);
2259 else if (!notice_it
&& canseemon(mtmp
))
2260 pline("%s appears.", Monnam(mtmp
)); /* not pre-rloc monname */
2261 else if (notice_it
&& dist2(mtmp
->mx
, mtmp
->my
, x
, y
) > 2)
2262 pline("%s teleports.", monname
); /* saw it and still see it */
2266 /* if we succeed, the corpse is gone */
2267 if (!revive_corpse(body
)) {
2271 if (is_rider(mptr
) && rn2(99)) { /* Rider usually tries again */
2272 action
= REVIVE_MON
;
2273 when
= rider_revival_time(body
, TRUE
);
2274 } else { /* rot this corpse away */
2275 if (!obj_has_timer(body
, ROT_CORPSE
))
2276 You_feel("%sless hassled.", is_rider(mptr
) ? "much " : "");
2277 action
= ROT_CORPSE
;
2278 when
= (long) d(5, 50) - (svm
.moves
- body
->age
);
2282 if (!obj_has_timer(body
, action
))
2283 (void) start_timer(when
, TIMER_OBJECT
, action
, arg
);
2287 /* Timeout callback. Revive the corpse as a zombie. */
2289 zombify_mon(anything
*arg
, long timeout
)
2291 struct obj
*body
= arg
->a_obj
;
2292 int zmon
= zombie_form(&mons
[body
->corpsenm
]);
2294 if (zmon
!= NON_PM
&& !(svm
.mvitals
[zmon
].mvflags
& G_GENOD
)) {
2297 if (has_omonst(body
))
2300 set_corpsenm(body
, zmon
);
2301 revive_mon(arg
, timeout
);
2303 rot_corpse(arg
, timeout
);
2307 /* return TRUE if hero properties are dangerous to hero */
2311 return (Stoned
|| Slimed
|| Strangled
|| Sick
);
2315 cmd_safety_prevention(const char *ucverb
, const char *cmddesc
,
2316 const char *act
, int *flagcounter
)
2318 if (flags
.safe_wait
&& !iflags
.menu_requested
&& !gm
.multi
) {
2322 if (iflags
.cmdassist
|| !(*flagcounter
)++)
2323 Sprintf(buf
, " Use '%s' prefix to force %s.",
2324 visctrl(cmd_from_func(do_reqmenu
)), cmddesc
);
2326 if (monster_nearby()) {
2327 Norep("%s%s", act
, buf
);
2329 } else if (danger_uprops()) {
2330 Norep("%s doesn't feel like a good idea right now.", ucverb
);
2338 /* '.' command: do nothing == rest; also the
2339 ' ' command iff 'rest_on_space' option is On */
2343 if (cmd_safety_prevention("Waiting", "a no-op (to rest)",
2344 "Are you waiting to get hit?",
2345 &gd
.did_nothing_flag
))
2347 return ECMD_TIME
; /* Do nothing, but let other things happen */
2353 unsigned udelta
= u
.ucreamed
;
2354 long ldelta
= BlindedTimeout
;
2358 u
.ucreamed
-= udelta
; /*u.ucreamed -= min(u.ucreamed,4);*/
2361 incr_itimeout(&HBlinded
, -ldelta
); /*HBlinded -= min(BlindedTimeout,4L);*/
2364 pline("You've got the glop off.");
2366 if (!gulp_blnd_check()) {
2367 set_itimeout(&HBlinded
, 1L);
2368 make_blinded(0L, TRUE
);
2371 } else if (!u
.ucreamed
) {
2372 Your("%s feels clean now.", body_part(FACE
));
2375 return 1; /* still busy */
2378 /* the #wipe command - wipe off your face */
2383 static NEARDATA
char buf
[39];
2385 Sprintf(buf
, "wiping off your %s", body_part(FACE
));
2386 set_occupation(wipeoff
, buf
, 0);
2387 /* Not totally correct; what if they change back after now
2388 * but before they're finished wiping?
2392 Your("%s is already clean.", body_part(FACE
));
2396 /* common wounded legs feedback */
2398 legs_in_no_shape(const char *for_what
, /* jumping, kicking, riding */
2401 if (by_steed
&& u
.usteed
) {
2402 pline("%s is in no shape for %s.", Monnam(u
.usteed
), for_what
);
2404 long wl
= (EWounded_legs
& BOTH_SIDES
);
2405 const char *bp
= body_part(LEG
);
2407 if (wl
== BOTH_SIDES
)
2408 bp
= makeplural(bp
);
2409 Your("%s%s %s in no shape for %s.",
2410 (wl
== LEFT_SIDE
) ? "left " : (wl
== RIGHT_SIDE
) ? "right " : "",
2411 bp
, (wl
== BOTH_SIDES
) ? "are" : "is", for_what
);
2416 set_wounded_legs(long side
, int timex
)
2419 * If you are riding, your steed gets the wounded legs instead.
2420 * You still call this function, but don't lose hp.
2421 * Caller is also responsible for adjusting messages.
2427 if (!Wounded_legs
|| (HWounded_legs
& TIMEOUT
) < (long) timex
)
2428 set_itimeout(&HWounded_legs
, (long) timex
);
2429 /* the leg being wounded and its timeout might differ from one
2430 attack to the next, but we don't track the legs separately;
2431 3.7: both legs will ultimately heal together; this used to use
2432 direct assignment instead of bitwise-OR so getting wounded in
2433 one leg mysteriously healed the other */
2434 EWounded_legs
|= side
;
2435 (void) encumber_msg();
2440 int how
) /* 0: ordinary, 1: dismounting steed, 2: limbs turn to stone */
2444 if (ATEMP(A_DEX
) < 0)
2447 /* when mounted, wounded legs applies to the steed;
2448 during petrification countdown, "your limbs turn to stone"
2449 before the final stages and that calls us (how==2) to cure
2450 wounded legs, but we want to suppress the feel better message */
2451 if (!u
.usteed
&& how
!= 2) {
2452 const char *legs
= body_part(LEG
);
2454 if ((EWounded_legs
& BOTH_SIDES
) == BOTH_SIDES
)
2455 legs
= makeplural(legs
);
2456 /* this used to say "somewhat better" but that was
2457 misleading since legs are being fully healed */
2458 Your("%s %s better.", legs
, vtense(legs
, "feel"));
2461 HWounded_legs
= EWounded_legs
= 0L;
2463 /* Wounded_legs reduces carrying capacity, so we want
2464 an encumbrance check when they're healed. However,
2465 while dismounting, first steed's legs get healed,
2466 then hero is dropped to floor and a new encumbrance
2467 check is made [in dismount_steed()]. So don't give
2468 encumbrance feedback during the dismount stage
2469 because it could seem to be shown out of order and
2470 it might be immediately contradicted [able to carry
2471 more when steed becomes healthy, then possible floor
2472 feedback, then able to carry less when back on foot]. */
2474 (void) encumber_msg();