1 /* NetHack 3.6 do.c $NHDT-Date: 1489623049 2017/03/16 00:10:49 $ $NHDT-Branch: master $:$NHDT-Revision: 1.159 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 /* Contains code for 'd', 'D' (drop), '>', '<' (up, down) */
10 STATIC_DCL
void FDECL(trycall
, (struct obj
*));
11 STATIC_DCL
void NDECL(polymorph_sink
);
12 STATIC_DCL boolean
NDECL(teleport_sink
);
13 STATIC_DCL
void FDECL(dosinkring
, (struct obj
*));
14 STATIC_PTR
int FDECL(drop
, (struct obj
*));
15 STATIC_PTR
int NDECL(wipeoff
);
16 STATIC_DCL
int FDECL(menu_drop
, (int));
17 STATIC_DCL
int NDECL(currentlevel_rewrite
);
18 STATIC_DCL
void NDECL(final_level
);
19 /* static boolean FDECL(badspot, (XCHAR_P,XCHAR_P)); */
21 extern int n_dgns
; /* number of dungeons, from dungeon.c */
23 static NEARDATA
const char drop_types
[] = { ALLOW_COUNT
, COIN_CLASS
,
26 /* 'd' command: drop one inventory item */
30 int result
, i
= (invent
) ? 0 : (SIZE(drop_types
) - 1);
33 sellobj_state(SELL_DELIBERATE
);
34 result
= drop(getobj(&drop_types
[i
], "drop"));
36 sellobj_state(SELL_NORMAL
);
43 /* Called when a boulder is dropped, thrown, or pushed. If it ends up
44 * in a pool, it either fills the pool up or sinks away. In either case,
45 * it's gone for good... If the destination is not a pool, returns FALSE.
48 boulder_hits_pool(otmp
, rx
, ry
, pushing
)
53 if (!otmp
|| otmp
->otyp
!= BOULDER
) {
54 impossible("Not a boulder?");
55 } else if (!Is_waterlevel(&u
.uz
) && is_pool_or_lava(rx
, ry
)) {
56 boolean lava
= is_lava(rx
, ry
), fills_up
;
57 const char *what
= waterbody_name(rx
, ry
);
58 schar ltyp
= levl
[rx
][ry
].typ
;
59 int chance
= rn2(10); /* water: 90%; lava: 10% */
60 fills_up
= lava
? chance
== 0 : chance
!= 0;
63 struct trap
*ttmp
= t_at(rx
, ry
);
65 if (ltyp
== DRAWBRIDGE_UP
) {
66 levl
[rx
][ry
].drawbridgemask
&= ~DB_UNDER
; /* clear lava */
67 levl
[rx
][ry
].drawbridgemask
|= DB_FLOOR
;
69 levl
[rx
][ry
].typ
= ROOM
;
72 (void) delfloortrap(ttmp
);
79 Strcpy(whobuf
, "you");
81 Strcpy(whobuf
, y_monnam(u
.usteed
));
82 pline("%s %s %s into the %s.", upstart(whobuf
),
83 vtense(whobuf
, "push"), the(xname(otmp
)), what
);
84 if (flags
.verbose
&& !Blind
)
85 pline("Now you can cross it!");
86 /* no splashing in this case */
89 if (!fills_up
|| !pushing
) { /* splashing occurs */
91 if (pushing
? !Blind
: cansee(rx
, ry
)) {
92 There("is a large splash as %s %s the %s.",
93 the(xname(otmp
)), fills_up
? "fills" : "falls into",
96 You_hear("a%s splash.", lava
? " sizzling" : "");
97 wake_nearto(rx
, ry
, 40);
100 if (fills_up
&& u
.uinwater
&& distu(rx
, ry
) == 0) {
103 vision_full_recalc
= 1;
104 You("find yourself on dry land again!");
105 } else if (lava
&& distu(rx
, ry
) <= 2) {
107 You("are hit by molten %s%c",
108 hliquid("lava"), Fire_resistance
? '.' : '!');
110 dmg
= d((Fire_resistance
? 1 : 3), 6);
111 losehp(Maybe_Half_Phys(dmg
), /* lava damage */
112 "molten lava", KILLED_BY
);
113 } else if (!fills_up
&& flags
.verbose
114 && (pushing
? !Blind
: cansee(rx
, ry
)))
115 pline("It sinks without a trace!");
118 /* boulder is now gone */
122 obfree(otmp
, (struct obj
*) 0);
128 /* Used for objects which sometimes do special things when dropped; must be
129 * called with the object not in any chain. Returns TRUE if the object goes
133 flooreffects(obj
, x
, y
, verb
)
142 if (obj
->where
!= OBJ_FREE
)
143 panic("flooreffects: obj not free");
145 /* make sure things like water_damage() have no pointers to follow */
146 obj
->nobj
= obj
->nexthere
= (struct obj
*) 0;
148 if (obj
->otyp
== BOULDER
&& boulder_hits_pool(obj
, x
, y
, FALSE
)) {
150 } else if (obj
->otyp
== BOULDER
&& (t
= t_at(x
, y
)) != 0
151 && (t
->ttyp
== PIT
|| t
->ttyp
== SPIKED_PIT
152 || t
->ttyp
== TRAPDOOR
|| t
->ttyp
== HOLE
)) {
153 if (((mtmp
= m_at(x
, y
)) && mtmp
->mtrapped
)
154 || (u
.utrap
&& u
.ux
== x
&& u
.uy
== y
)) {
156 pline_The("boulder %s into the pit%s.",
157 vtense((const char *) 0, verb
),
158 (mtmp
) ? "" : " with you");
160 if (!passes_walls(mtmp
->data
) && !throws_rocks(mtmp
->data
)) {
161 if (hmon(mtmp
, obj
, TRUE
) && !is_whirly(mtmp
->data
))
162 return FALSE
; /* still alive */
166 if (!Passes_walls
&& !throws_rocks(youmonst
.data
)) {
167 losehp(Maybe_Half_Phys(rnd(15)),
168 "squished under a boulder", NO_KILLER_PREFIX
);
169 return FALSE
; /* player remains trapped */
175 if (Blind
&& (x
== u
.ux
) && (y
== u
.uy
)) {
176 You_hear("a CRASH! beneath you.");
177 } else if (!Blind
&& cansee(x
, y
)) {
178 pline_The("boulder %s%s.", t
->tseen
? "" : "triggers and ",
180 ? "plugs a trap door"
181 : t
->ttyp
== HOLE
? "plugs a hole"
184 You_hear("a boulder %s.", verb
);
192 } else if (is_lava(x
, y
)) {
193 return fire_damage(obj
, FALSE
, x
, y
);
194 } else if (is_pool(x
, y
)) {
195 /* Reasonably bulky objects (arbitrary) splash when dropped.
196 * If you're floating above the water even small things make
197 * noise. Stuff dropped near fountains always misses */
198 if ((Blind
|| (Levitation
|| Flying
)) && !Deaf
199 && ((x
== u
.ux
) && (y
== u
.uy
))) {
201 if (weight(obj
) > 9) {
203 } else if (Levitation
|| Flying
) {
207 map_background(x
, y
, 0);
210 return water_damage(obj
, NULL
, FALSE
) == ER_DESTROYED
;
211 } else if (u
.ux
== x
&& u
.uy
== y
&& (t
= t_at(x
, y
)) != 0
212 && uteetering_at_seen_pit(t
)) {
214 You_hear("%s tumble downwards.", the(xname(obj
)));
216 pline("%s %s into %s pit.", The(xname(obj
)),
217 otense(obj
, "tumble"), the_your
[t
->madeby_u
]);
218 } else if (obj
->globby
) {
219 /* Globby things like puddings might stick together */
220 while (obj
&& (otmp
= obj_nexto_xy(obj
, x
, y
, TRUE
)) != 0) {
221 pudding_merge_message(obj
, otmp
);
222 /* intentionally not getting the melded object; obj_meld may set
224 (void) obj_meld(&obj
, &otmp
);
226 return (boolean
) !obj
;
231 /* obj is an object dropped on an altar */
234 register struct obj
*obj
;
239 if (obj
->oclass
!= COIN_CLASS
) {
241 u
.uconduct
.gnostic
++;
243 /* coins don't have bless/curse status */
244 obj
->blessed
= obj
->cursed
= 0;
247 if (obj
->blessed
|| obj
->cursed
) {
248 There("is %s flash as %s %s the altar.",
249 an(hcolor(obj
->blessed
? NH_AMBER
: NH_BLACK
)), doname(obj
),
254 pline("%s %s on the altar.", Doname2(obj
), otense(obj
, "land"));
255 if (obj
->oclass
!= COIN_CLASS
)
262 register struct obj
*obj
;
264 if (!objects
[obj
->otyp
].oc_name_known
&& !objects
[obj
->otyp
].oc_uname
)
268 /* Transforms the sink at the player's position into
269 a fountain, throne, altar or grave. */
275 if (levl
[u
.ux
][u
.uy
].typ
!= SINK
)
278 level
.flags
.nsinks
--;
279 levl
[u
.ux
][u
.uy
].doormask
= 0;
284 levl
[u
.ux
][u
.uy
].typ
= FOUNTAIN
;
285 level
.flags
.nfountains
++;
289 levl
[u
.ux
][u
.uy
].typ
= THRONE
;
293 levl
[u
.ux
][u
.uy
].typ
= ALTAR
;
294 levl
[u
.ux
][u
.uy
].altarmask
= Align2amask(rn2((int) A_LAWFUL
+ 2) - 1);
298 levl
[u
.ux
][u
.uy
].typ
= ROOM
;
299 make_grave(u
.ux
, u
.uy
, (char *) 0);
300 if (levl
[u
.ux
][u
.uy
].typ
== GRAVE
)
304 /* give message even if blind; we know we're not levitating,
305 so can feel the outcome even if we can't directly see it */
306 if (levl
[u
.ux
][u
.uy
].typ
!= ROOM
)
307 pline_The("sink transforms into %s!", an(defsyms
[sym
].explanation
));
309 pline_The("sink vanishes.");
313 /* Teleports the sink at the player's position;
314 return True if sink teleported. */
327 eng
= engr_at(cx
, cy
);
328 } while ((levl
[cx
][cy
].typ
!= ROOM
|| trp
|| eng
|| cansee(cx
, cy
))
331 if (levl
[cx
][cy
].typ
== ROOM
&& !trp
&& !eng
) {
332 /* create sink at new position */
333 levl
[cx
][cy
].typ
= SINK
;
334 levl
[cx
][cy
].looted
= levl
[u
.ux
][u
.uy
].looted
;
336 /* remove old sink */
337 levl
[u
.ux
][u
.uy
].typ
= ROOM
;
338 levl
[u
.ux
][u
.uy
].looted
= 0;
345 /* obj is a ring being dropped over a kitchen sink */
348 register struct obj
*obj
;
350 struct obj
*otmp
, *otmp2
;
351 boolean ideed
= TRUE
;
352 boolean nosink
= FALSE
;
354 You("drop %s down the drain.", doname(obj
));
355 obj
->in_use
= TRUE
; /* block free identification via interrupt */
356 switch (obj
->otyp
) { /* effects that can be noticed without eyes */
358 You("thought %s got lost in the sink, but there it is!", yname(obj
));
360 case RIN_SLOW_DIGESTION
:
361 pline_The("ring is regurgitated!");
368 pline_The("sink quivers upward for a moment.");
370 case RIN_POISON_RESISTANCE
:
371 You("smell rotten %s.", makeplural(fruitname(FALSE
)));
373 case RIN_AGGRAVATE_MONSTER
:
374 pline("Several %s buzz angrily around the sink.",
375 Hallucination
? makeplural(rndmonnam(NULL
)) : "flies");
377 case RIN_SHOCK_RESISTANCE
:
378 pline("Static electricity surrounds the sink.");
381 You_hear("loud noises coming from the drain.");
383 case RIN_SUSTAIN_ABILITY
: /* KMH */
384 pline_The("%s flow seems fixed.", hliquid("water"));
386 case RIN_GAIN_STRENGTH
:
387 pline_The("%s flow seems %ser now.",
389 (obj
->spe
< 0) ? "weak" : "strong");
391 case RIN_GAIN_CONSTITUTION
:
392 pline_The("%s flow seems %ser now.",
394 (obj
->spe
< 0) ? "less" : "great");
396 case RIN_INCREASE_ACCURACY
: /* KMH */
397 pline_The("%s flow %s the drain.",
399 (obj
->spe
< 0) ? "misses" : "hits");
401 case RIN_INCREASE_DAMAGE
:
402 pline_The("water's force seems %ser now.",
403 (obj
->spe
< 0) ? "small" : "great");
407 for (otmp
= level
.objects
[u
.ux
][u
.uy
]; otmp
; otmp
= otmp2
) {
408 otmp2
= otmp
->nexthere
;
409 if (otmp
!= uball
&& otmp
!= uchain
410 && !obj_resists(otmp
, 1, 99)) {
412 pline("Suddenly, %s %s from the sink!", doname(otmp
),
413 otense(otmp
, "vanish"));
421 /* Not the same as aggravate monster; besides, it's obvious. */
422 pline("Several flies buzz around the sink.");
424 case RIN_TELEPORTATION
:
425 nosink
= teleport_sink();
426 /* give message even if blind; we know we're not levitating,
427 so can feel the outcome even if we can't directly see it */
428 pline_The("sink %svanishes.", nosink
? "" : "momentarily ");
434 /* for S_room case, same message as for teleportation is given */
435 ideed
= (levl
[u
.ux
][u
.uy
].typ
!= ROOM
);
441 if (!Blind
&& !ideed
) {
443 switch (obj
->otyp
) { /* effects that need eyes */
445 pline_The("faucets flash brightly for a moment.");
447 case RIN_REGENERATION
:
448 pline_The("sink looks as good as new.");
450 case RIN_INVISIBILITY
:
451 You("don't see anything happen to the sink.");
453 case RIN_FREE_ACTION
:
454 You_see("the ring slide right down the drain!");
456 case RIN_SEE_INVISIBLE
:
457 You_see("some %s in the sink.",
458 Hallucination
? "oxygen molecules" : "air");
461 pline_The("sink seems to blend into the floor for a moment.");
463 case RIN_FIRE_RESISTANCE
:
464 pline_The("hot %s faucet flashes brightly for a moment.",
467 case RIN_COLD_RESISTANCE
:
468 pline_The("cold %s faucet flashes brightly for a moment.",
471 case RIN_PROTECTION_FROM_SHAPE_CHAN
:
472 pline_The("sink looks nothing like a fountain.");
475 pline_The("sink glows %s for a moment.",
476 hcolor((obj
->spe
< 0) ? NH_BLACK
: NH_SILVER
));
479 pline_The("sink glows %s for a moment.", hcolor(NH_WHITE
));
481 case RIN_TELEPORT_CONTROL
:
482 pline_The("sink looks like it is being beamed aboard somewhere.");
484 case RIN_POLYMORPH_CONTROL
:
486 "sink momentarily looks like a regularly erupting geyser.");
495 You_hear("the ring bouncing down the drainpipe.");
497 if (!rn2(20) && !nosink
) {
498 pline_The("sink backs up, leaving %s.", doname(obj
));
505 /* some common tests when trying to drop or throw items */
511 if (obj
->owornmask
& (W_ARMOR
| W_ACCESSORY
)) {
513 Norep("You cannot %s %s you are wearing.", word
, something
);
516 if (obj
->otyp
== LOADSTONE
&& obj
->cursed
) {
517 /* getobj() kludge sets corpsenm to user's specified count
518 when refusing to split a stack of cursed loadstones */
520 /* getobj() ignores a count for throwing since that is
521 implicitly forced to be 1; replicate its kludge... */
522 if (!strcmp(word
, "throw") && obj
->quan
> 1L)
524 pline("For some reason, you cannot %s%s the stone%s!", word
,
525 obj
->corpsenm
? " any of" : "", plur(obj
->quan
));
527 obj
->corpsenm
= 0; /* reset */
531 if (obj
->otyp
== LEASH
&& obj
->leashmon
!= 0) {
533 pline_The("leash is tied around your %s.", body_part(HAND
));
536 if (obj
->owornmask
& W_SADDLE
) {
538 You("cannot %s %s you are sitting on.", word
, something
);
546 register struct obj
*obj
;
550 if (!canletgo(obj
, "drop"))
557 setuwep((struct obj
*) 0);
559 if (obj
== uquiver
) {
560 setuqwep((struct obj
*) 0);
562 if (obj
== uswapwep
) {
563 setuswapwep((struct obj
*) 0);
567 /* barrier between you and the floor */
571 /* doname can call s_suffix, reusing its buffer */
572 Strcpy(buf
, s_suffix(mon_nam(u
.ustuck
)));
573 You("drop %s into %s %s.", doname(obj
), buf
,
574 mbodypart(u
.ustuck
, STOMACH
));
577 if ((obj
->oclass
== RING_CLASS
|| obj
->otyp
== MEAT_RING
)
578 && IS_SINK(levl
[u
.ux
][u
.uy
].typ
)) {
582 if (!can_reach_floor(TRUE
)) {
583 /* we might be levitating due to #invoke Heart of Ahriman;
584 if so, levitation would end during call to freeinv()
585 and we want hitfloor() to happen before float_down() */
586 boolean levhack
= finesse_ahriman(obj
);
589 ELevitation
= W_ART
; /* other than W_ARTI */
591 You("drop %s.", doname(obj
));
592 /* Ensure update when we drop gold objects */
593 if (obj
->oclass
== COIN_CLASS
)
598 float_down(I_SPECIAL
| TIMEOUT
, W_ARTI
| W_ART
);
601 if (!IS_ALTAR(levl
[u
.ux
][u
.uy
].typ
) && flags
.verbose
)
602 You("drop %s.", doname(obj
));
608 /* dropx - take dropped item out of inventory;
609 called in several places - may produce output
610 (eg ship_object() and dropy() -> sellobj() both produce output) */
613 register struct obj
*obj
;
615 /* Ensure update when we drop gold objects */
616 if (obj
->oclass
== COIN_CLASS
)
620 if (ship_object(obj
, u
.ux
, u
.uy
, FALSE
))
622 if (IS_ALTAR(levl
[u
.ux
][u
.uy
].typ
))
623 doaltarobj(obj
); /* set bknown */
628 /* dropy - put dropped object at destination; called from lots of places */
636 /* dropz - really put dropped object at its destination... */
638 dropz(obj
, with_impact
)
643 setuwep((struct obj
*) 0);
645 setuqwep((struct obj
*) 0);
647 setuswapwep((struct obj
*) 0);
649 if (!u
.uswallow
&& flooreffects(obj
, u
.ux
, u
.uy
, "drop"))
651 /* uswallow check done by GAN 01/29/87 */
653 boolean could_petrify
= FALSE
;
654 boolean could_poly
= FALSE
;
655 boolean could_slime
= FALSE
;
656 boolean could_grow
= FALSE
;
657 boolean could_heal
= FALSE
;
659 if (obj
!= uball
) { /* mon doesn't pick up ball */
660 if (obj
->otyp
== CORPSE
) {
661 could_petrify
= touch_petrifies(&mons
[obj
->corpsenm
]);
662 could_poly
= polyfodder(obj
);
663 could_slime
= (obj
->corpsenm
== PM_GREEN_SLIME
);
664 could_grow
= (obj
->corpsenm
== PM_WRAITH
);
665 could_heal
= (obj
->corpsenm
== PM_NURSE
);
667 (void) mpickobj(u
.ustuck
, obj
);
668 if (is_animal(u
.ustuck
->data
)) {
669 if (could_poly
|| could_slime
) {
670 (void) newcham(u
.ustuck
,
671 could_poly
? (struct permonst
*) 0
672 : &mons
[PM_GREEN_SLIME
],
674 delobj(obj
); /* corpse is digested */
675 } else if (could_petrify
) {
676 minstapetrify(u
.ustuck
, TRUE
);
677 /* Don't leave a cockatrice corpse in a statue */
680 } else if (could_grow
) {
681 (void) grow_up(u
.ustuck
, (struct monst
*) 0);
682 delobj(obj
); /* corpse is digested */
683 } else if (could_heal
) {
684 u
.ustuck
->mhp
= u
.ustuck
->mhpmax
;
685 delobj(obj
); /* corpse is digested */
690 place_object(obj
, u
.ux
, u
.uy
);
692 container_impact_dmg(obj
, u
.ux
, u
.uy
);
694 drop_ball(u
.ux
, u
.uy
);
695 else if (level
.flags
.has_shop
)
696 sellobj(obj
, u
.ux
, u
.uy
);
698 if (Blind
&& Levitation
)
700 newsym(u
.ux
, u
.uy
); /* remap location under self */
704 /* things that must change when not held; recurse into containers.
705 Called for both player and monsters */
707 obj_no_longer_held(obj
)
712 } else if (Has_contents(obj
)) {
713 struct obj
*contents
;
715 for (contents
= obj
->cobj
; contents
; contents
= contents
->nobj
)
716 obj_no_longer_held(contents
);
720 /* Normal crysknife reverts to worm tooth when not held by hero
721 * or monster; fixed crysknife has only 10% chance of reverting.
722 * When a stack of the latter is involved, it could be worthwhile
723 * to give each individual crysknife its own separate 10% chance,
724 * but we aren't in any position to handle stack splitting here.
726 if (!obj
->oerodeproof
|| !rn2(10)) {
727 /* if monsters aren't moving, assume player is responsible */
728 if (!context
.mon_moving
&& !program_state
.gameover
)
729 costly_alteration(obj
, COST_DEGRD
);
730 obj
->otyp
= WORM_TOOTH
;
731 obj
->oerodeproof
= 0;
737 /* 'D' command: drop several things */
744 You("have nothing to drop.");
747 add_valid_menu_class(0); /* clear any classes already there */
749 sellobj_state(SELL_DELIBERATE
);
750 if (flags
.menu_style
!= MENU_TRADITIONAL
751 || (result
= ggetobj("drop", drop
, 0, FALSE
, (unsigned *) 0)) < -1)
752 result
= menu_drop(result
);
754 sellobj_state(SELL_NORMAL
);
761 /* Drop things from the hero's inventory, using a menu. */
766 int n
, i
, n_dropped
= 0;
768 struct obj
*otmp
, *otmp2
;
769 menu_item
*pick_list
;
770 boolean all_categories
= TRUE
;
771 boolean drop_everything
= FALSE
;
774 all_categories
= (retry
== -2);
775 } else if (flags
.menu_style
== MENU_FULL
) {
776 all_categories
= FALSE
;
777 n
= query_category("Drop what type of items?", invent
,
778 UNPAID_TYPES
| ALL_TYPES
| CHOOSE_ALL
| BUC_BLESSED
779 | BUC_CURSED
| BUC_UNCURSED
| BUC_UNKNOWN
,
780 &pick_list
, PICK_ANY
);
783 for (i
= 0; i
< n
; i
++) {
784 if (pick_list
[i
].item
.a_int
== ALL_TYPES_SELECTED
)
785 all_categories
= TRUE
;
786 else if (pick_list
[i
].item
.a_int
== 'A')
787 drop_everything
= TRUE
;
789 add_valid_menu_class(pick_list
[i
].item
.a_int
);
791 free((genericptr_t
) pick_list
);
792 } else if (flags
.menu_style
== MENU_COMBINATION
) {
793 unsigned ggoresults
= 0;
795 all_categories
= FALSE
;
796 /* Gather valid classes via traditional NetHack method */
797 i
= ggetobj("drop", drop
, 0, TRUE
, &ggoresults
);
799 all_categories
= TRUE
;
800 if (ggoresults
& ALL_FINISHED
) {
806 if (drop_everything
) {
808 * Dropping a burning potion of oil while levitating can cause
809 * an explosion which might destroy some of hero's inventory,
811 * for (otmp = invent; otmp; otmp = otmp2) {
812 * otmp2 = otmp->nobj;
813 * n_dropped += drop(otmp);
815 * was unreliable and could lead to an "object lost" panic.
817 * Use the bypass bit to mark items already processed (hence
818 * not droppable) and rescan inventory until no unbypassed
821 bypass_objlist(invent
, FALSE
); /* clear bypass bit for invent */
822 while ((otmp
= nxt_unbypassed_obj(invent
)) != 0)
823 n_dropped
+= drop(otmp
);
824 /* we might not have dropped everything (worn armor, welded weapon,
825 cursed loadstones), so reset any remaining inventory to normal */
826 bypass_objlist(invent
, FALSE
);
828 /* should coordinate with perm invent, maybe not show worn items */
829 n
= query_objlist("What would you like to drop?", &invent
,
830 (USE_INVLET
| INVORDER_SORT
), &pick_list
, PICK_ANY
,
831 all_categories
? allow_all
: allow_category
);
834 * picklist[] contains a set of pointers into inventory, but
835 * as soon as something gets dropped, they might become stale
836 * (see the drop_everything code above for an explanation).
837 * Just checking to see whether one is still in the invent
838 * chain is not sufficient validation since destroyed items
839 * will be freed and items we've split here might have already
840 * reused that memory and put the same pointer value back into
841 * invent. Ditto for using invlet to validate. So we start
842 * by setting bypass on all of invent, then check each pointer
843 * to verify that it is in invent and has that bit set.
845 bypass_objlist(invent
, TRUE
);
846 for (i
= 0; i
< n
; i
++) {
847 otmp
= pick_list
[i
].item
.a_obj
;
848 for (otmp2
= invent
; otmp2
; otmp2
= otmp2
->nobj
)
851 if (!otmp2
|| !otmp2
->bypass
)
853 /* found next selected invent item */
854 cnt
= pick_list
[i
].count
;
855 if (cnt
< otmp
->quan
) {
858 } else if (otmp
->otyp
== LOADSTONE
&& otmp
->cursed
) {
859 /* same kludge as getobj(), for canletgo()'s use */
860 otmp
->corpsenm
= (int) cnt
; /* don't split */
862 otmp
= splitobj(otmp
, cnt
);
865 n_dropped
+= drop(otmp
);
867 bypass_objlist(invent
, FALSE
); /* reset invent to normal */
868 free((genericptr_t
) pick_list
);
876 /* on a ladder, used in goto_level */
877 static NEARDATA boolean at_ladder
= FALSE
;
879 /* the '>' command */
883 struct trap
*trap
= 0;
884 boolean stairs_down
= ((u
.ux
== xdnstair
&& u
.uy
== ydnstair
)
885 || (u
.ux
== sstairs
.sx
&& u
.uy
== sstairs
.sy
887 ladder_down
= (u
.ux
== xdnladder
&& u
.uy
== ydnladder
);
892 if (stucksteed(TRUE
)) {
895 /* Levitation might be blocked, but player can still use '>' to
896 turn off controlled levitation */
897 if (HLevitation
|| ELevitation
) {
898 if ((HLevitation
& I_SPECIAL
) || (ELevitation
& W_ARTI
)) {
899 /* end controlled levitation */
900 if (ELevitation
& W_ARTI
) {
903 for (obj
= invent
; obj
; obj
= obj
->nobj
) {
905 && artifact_has_invprop(obj
, LEVITATION
)) {
906 if (obj
->age
< monstermoves
)
907 obj
->age
= monstermoves
;
908 obj
->age
+= rnz(100);
912 if (float_down(I_SPECIAL
| TIMEOUT
, W_ARTI
)) {
913 return 1; /* came down, so moved */
914 } else if (!HLevitation
&& !ELevitation
) {
915 Your("latent levitation ceases.");
916 return 1; /* did something, effectively moved */
920 ; /* weren't actually floating after all */
922 /* Avoid alerting player to an unknown stair or ladder.
923 * Changes the message for a covered, known staircase
924 * too; staircase knowledge is not stored anywhere.
928 (glyph_to_cmap(levl
[u
.ux
][u
.uy
].glyph
) == S_dnstair
);
929 else if (ladder_down
)
931 (glyph_to_cmap(levl
[u
.ux
][u
.uy
].glyph
) == S_dnladder
);
933 if (Is_airlevel(&u
.uz
))
934 You("are floating in the %s.", surface(u
.ux
, u
.uy
));
935 else if (Is_waterlevel(&u
.uz
))
936 You("are floating in %s.",
937 is_pool(u
.ux
, u
.uy
) ? "the water" : "a bubble of air");
939 floating_above(stairs_down
? "stairs" : ladder_down
941 : surface(u
.ux
, u
.uy
));
942 return 0; /* didn't move */
944 if (!stairs_down
&& !ladder_down
) {
945 trap
= t_at(u
.ux
, u
.uy
);
946 if (trap
&& uteetering_at_seen_pit(trap
)) {
947 dotrap(trap
, TOOKPLUNGE
);
949 } else if (!trap
|| (trap
->ttyp
!= TRAPDOOR
&& trap
->ttyp
!= HOLE
)
950 || !Can_fall_thru(&u
.uz
) || !trap
->tseen
) {
951 if (flags
.autodig
&& !context
.nopick
&& uwep
&& is_pick(uwep
)) {
952 return use_pick_axe2(uwep
);
954 You_cant("go down here.");
960 You("are %s, and cannot go down.",
961 !u
.uswallow
? "being held" : is_animal(u
.ustuck
->data
)
966 if (on_level(&valley_level
, &u
.uz
) && !u
.uevent
.gehennom_entered
) {
967 You("are standing at the gate to Gehennom.");
968 pline("Unspeakable cruelty and harm lurk down there.");
969 if (yn("Are you sure you want to enter?") != 'y')
973 u
.uevent
.gehennom_entered
= 1; /* don't ask again */
977 You("are held back by your pet!");
982 You("%s %s.", Flying
? "fly" : locomotion(youmonst
.data
, "jump"),
983 trap
->ttyp
== HOLE
? "down the hole" : "through the trap door");
985 if (trap
&& Is_stronghold(&u
.uz
)) {
986 goto_hell(FALSE
, TRUE
);
988 at_ladder
= (boolean
) (levl
[u
.ux
][u
.uy
].typ
== LADDER
);
995 /* the '<' command */
1002 /* "up" to get out of a pit... */
1003 if (u
.utrap
&& u
.utraptype
== TT_PIT
) {
1008 if ((u
.ux
!= xupstair
|| u
.uy
!= yupstair
)
1009 && (!xupladder
|| u
.ux
!= xupladder
|| u
.uy
!= yupladder
)
1010 && (!sstairs
.sx
|| u
.ux
!= sstairs
.sx
|| u
.uy
!= sstairs
.sy
1012 You_cant("go up here.");
1015 if (stucksteed(TRUE
)) {
1019 You("are %s, and cannot go up.",
1020 !u
.uswallow
? "being held" : is_animal(u
.ustuck
->data
)
1025 if (near_capacity() > SLT_ENCUMBER
) {
1026 /* No levitation check; inv_weight() already allows for it */
1027 Your("load is too heavy to climb the %s.",
1028 levl
[u
.ux
][u
.uy
].typ
== STAIRS
? "stairs" : "ladder");
1031 if (ledger_no(&u
.uz
) == 1) {
1032 if (yn("Beware, there will be no return! Still climb?") != 'y')
1036 You("are held back by your pet!");
1039 at_ladder
= (boolean
) (levl
[u
.ux
][u
.uy
].typ
== LADDER
);
1045 d_level save_dlevel
= { 0, 0 };
1047 /* check that we can write out the current level */
1049 currentlevel_rewrite()
1054 /* since level change might be a bit slow, flush any buffered screen
1055 * output (like "you fall through a trap door") */
1058 fd
= create_levelfile(ledger_no(&u
.uz
), whynot
);
1061 * This is not quite impossible: e.g., we may have
1062 * exceeded our quota. If that is the case then we
1063 * cannot leave this level, and cannot save either.
1064 * Another possibility is that the directory was not
1072 if (!savelev(fd
, ledger_no(&u
.uz
), COUNT_SAVE
)) {
1074 delete_levelfile(ledger_no(&u
.uz
));
1075 pline("aNetHack is out of disk space for making levels!");
1076 You("can save, quit, or continue playing.");
1089 if (flags
.ins_chkpt
) {
1090 /* write out just-attained level, with pets and everything */
1091 fd
= currentlevel_rewrite();
1095 savelev(fd
, ledger_no(&u
.uz
), WRITE_SAVE
);
1099 /* write out non-level state */
1107 register xchar x, y;
1109 return (boolean) ((levl[x][y].typ != ROOM
1110 && levl[x][y].typ != AIR
1111 && levl[x][y].typ != CORR)
1117 goto_level(newlevel
, at_stairs
, falling
, portal
)
1119 boolean at_stairs
, falling
, portal
;
1123 boolean cant_go_back
, great_effort
,
1124 up
= (depth(newlevel
) < depth(&u
.uz
)),
1125 newdungeon
= (u
.uz
.dnum
!= newlevel
->dnum
),
1126 was_in_W_tower
= In_W_tower(u
.ux
, u
.uy
, &u
.uz
),
1128 new = FALSE
; /* made a new level? */
1133 if (dunlev(newlevel
) > dunlevs_in_dungeon(newlevel
))
1134 newlevel
->dlevel
= dunlevs_in_dungeon(newlevel
);
1135 if (newdungeon
&& In_endgame(newlevel
)) { /* 1st Endgame Level !!! */
1136 if (!u
.uhave
.amulet
)
1137 return; /* must have the Amulet */
1138 if (!wizard
) /* wizard ^V can bypass Earth level */
1139 assign_level(newlevel
, &earth_level
); /* (redundant) */
1141 new_ledger
= ledger_no(newlevel
);
1142 if (new_ledger
<= 0)
1143 done(ESCAPED
); /* in fact < 0 is impossible */
1145 /* If you have the amulet and are trying to get out of Gehennom,
1146 * going up a set of stairs sometimes does some very strange things!
1147 * Biased against law and towards chaos. (The chance to be sent
1148 * down multiple levels when attempting to go up are significantly
1149 * less than the corresponding comment in older versions indicated
1150 * due to overlooking the effect of the call to assign_rnd_lvl().)
1152 * Odds for making it to the next level up, or of being sent down:
1156 * -1 11.46 12.50 12.5
1160 if (Inhell
&& up
&& u
.uhave
.amulet
&& !newdungeon
&& !portal
1161 && (dunlev(&u
.uz
) < dunlevs_in_dungeon(&u
.uz
) - 3)) {
1163 int odds
= 3 + (int) u
.ualign
.type
, /* 2..4 */
1164 diff
= odds
<= 1 ? 0 : rn2(odds
); /* paranoia */
1167 assign_rnd_level(newlevel
, &u
.uz
, diff
);
1168 /* if inside the tower, stay inside */
1169 if (was_in_W_tower
&& !On_W_tower_level(newlevel
))
1173 assign_level(newlevel
, &u
.uz
);
1175 new_ledger
= ledger_no(newlevel
);
1177 pline("A mysterious force momentarily surrounds you...");
1178 if (on_level(newlevel
, &u
.uz
)) {
1179 (void) safe_teleds(FALSE
);
1183 at_stairs
= at_ladder
= FALSE
;
1187 /* Prevent the player from going past the first quest level unless
1188 * (s)he has been given the go-ahead by the leader.
1190 if (on_level(&u
.uz
, &qstart_level
) && !newdungeon
&& !ok_to_quest()) {
1191 pline("A mysterious force prevents you from descending.");
1195 if (on_level(newlevel
, &u
.uz
))
1196 return; /* this can happen */
1198 /* tethered movement makes level change while trapped feasible */
1199 if (u
.utrap
&& u
.utraptype
== TT_BURIEDBALL
)
1200 buried_ball_to_punishment(); /* (before we save/leave old level) */
1202 fd
= currentlevel_rewrite();
1206 if (falling
) /* assuming this is only trap door or hole */
1207 impact_drop((struct obj
*) 0, u
.ux
, u
.uy
, newlevel
->dlevel
);
1209 check_special_room(TRUE
); /* probably was a trap door */
1212 u
.utrap
= 0; /* needed in level_tele */
1213 fill_pit(u
.ux
, u
.uy
);
1214 u
.ustuck
= 0; /* idem */
1216 u
.uundetected
= 0; /* not hidden, even if means are available */
1218 if (u
.uswallow
) /* idem */
1219 u
.uswldtim
= u
.uswallow
= 0;
1220 recalc_mapseen(); /* recalculate map overview before we leave the level */
1222 * We no longer see anything on the level. Make sure that this
1223 * follows u.uswallow set to null since uswallow overrides all
1229 * Save the level we're leaving. If we're entering the endgame,
1230 * we can get rid of all existing levels because they cannot be
1231 * reached any more. We still need to use savelev()'s cleanup
1232 * for the level being left, to recover dynamic memory in use and
1233 * to avoid dangling timers and light sources.
1235 cant_go_back
= (newdungeon
&& In_endgame(newlevel
));
1236 if (!cant_go_back
) {
1237 update_mlstmv(); /* current monsters are becoming inactive */
1238 bufon(fd
); /* use buffered output */
1240 savelev(fd
, ledger_no(&u
.uz
),
1241 cant_go_back
? FREE_SAVE
: (WRITE_SAVE
| FREE_SAVE
));
1244 /* discard unreachable levels; keep #0 */
1245 for (l_idx
= maxledgerno(); l_idx
> 0; --l_idx
)
1246 delete_levelfile(l_idx
);
1247 /* mark #overview data for all dungeon branches as uninteresting */
1248 for (l_idx
= 0; l_idx
< n_dgns
; ++l_idx
)
1249 remdun_mapseen(l_idx
);
1252 if (Is_rogue_level(newlevel
) || Is_rogue_level(&u
.uz
))
1253 assign_graphics(Is_rogue_level(newlevel
) ? ROGUESET
: PRIMARY
);
1255 substitute_tiles(newlevel
);
1257 /* record this level transition as a potential seen branch unless using
1258 * some non-standard means of transportation (level teleport).
1260 if ((at_stairs
|| falling
|| portal
) && (u
.uz
.dnum
!= newlevel
->dnum
))
1261 recbranch_mapseen(&u
.uz
, newlevel
);
1262 assign_level(&u
.uz0
, &u
.uz
);
1263 assign_level(&u
.uz
, newlevel
);
1264 assign_level(&u
.utolev
, newlevel
);
1266 if (!builds_up(&u
.uz
)) { /* usual case */
1267 if (dunlev(&u
.uz
) > dunlev_reached(&u
.uz
))
1268 dunlev_reached(&u
.uz
) = dunlev(&u
.uz
);
1270 if (dunlev_reached(&u
.uz
) == 0
1271 || dunlev(&u
.uz
) < dunlev_reached(&u
.uz
))
1272 dunlev_reached(&u
.uz
) = dunlev(&u
.uz
);
1274 reset_rndmonst(NON_PM
); /* u.uz change affects monster generation */
1276 /* set default level change destination areas */
1277 /* the special level code may override these */
1278 (void) memset((genericptr_t
) &updest
, 0, sizeof updest
);
1279 (void) memset((genericptr_t
) &dndest
, 0, sizeof dndest
);
1281 if (!(level_info
[new_ledger
].flags
& LFILE_EXISTS
)) {
1282 /* entering this level for first time; make it now */
1283 if (level_info
[new_ledger
].flags
& (FORGOTTEN
| VISITED
)) {
1284 impossible("goto_level: returning to discarded level?");
1285 level_info
[new_ledger
].flags
&= ~(FORGOTTEN
| VISITED
);
1288 new = TRUE
; /* made the level */
1290 /* returning to previously visited level; reload it */
1291 fd
= open_levelfile(new_ledger
, whynot
);
1292 if (tricked_fileremoved(fd
, whynot
)) {
1293 /* we'll reach here if running in wizard mode */
1294 error("Cannot continue this game.");
1296 minit(); /* ZEROCOMP */
1297 getlev(fd
, hackpid
, new_ledger
, FALSE
);
1299 oinit(); /* reassign level dependent obj probabilities */
1302 /* do this prior to level-change pline messages */
1303 vision_reset(); /* clear old level's line-of-sight */
1304 vision_full_recalc
= 0; /* don't let that reenable vision yet */
1305 flush_screen(-1); /* ensure all map flushes are postponed */
1307 if (portal
&& !In_endgame(&u
.uz
)) {
1308 /* find the portal on the new level */
1309 register struct trap
*ttrap
;
1311 for (ttrap
= ftrap
; ttrap
; ttrap
= ttrap
->ntrap
)
1312 if (ttrap
->ttyp
== MAGIC_PORTAL
)
1316 panic("goto_level: no corresponding portal!");
1318 u_on_newpos(ttrap
->tx
, ttrap
->ty
);
1319 } else if (at_stairs
&& !In_endgame(&u
.uz
)) {
1322 u_on_newpos(xdnladder
, ydnladder
);
1323 else if (newdungeon
)
1327 /* you climb up the {stairs|ladder};
1328 fly up the stairs; fly up along the ladder */
1329 great_effort
= (Punished
&& !Levitation
);
1330 if (flags
.verbose
|| great_effort
)
1331 pline("%s %s up%s the %s.",
1332 great_effort
? "With great effort, you" : "You",
1333 Levitation
? "float" : Flying
? "fly" : "climb",
1334 (Flying
&& at_ladder
) ? " along" : "",
1335 at_ladder
? "ladder" : "stairs");
1338 u_on_newpos(xupladder
, yupladder
);
1339 else if (newdungeon
)
1344 ; /* stayed on same level? (no transit effects) */
1345 } else if (Flying
) {
1348 at_ladder
? "along the ladder" : "the stairs");
1349 } else if (near_capacity() > UNENCUMBERED
1350 || Punished
|| Fumbling
) {
1351 You("fall down the %s.", at_ladder
? "ladder" : "stairs");
1356 /* falling off steed has its own losehp() call */
1358 dismount_steed(DISMOUNT_FELL
);
1360 losehp(Maybe_Half_Phys(rnd(3)),
1361 at_ladder
? "falling off a ladder"
1362 : "tumbling down a flight of stairs",
1364 selftouch("Falling, you");
1365 } else { /* ordinary descent */
1367 You("%s.", at_ladder
? "climb down the ladder"
1368 : "descend the stairs");
1371 } else { /* trap door or level_tele or In_endgame */
1372 u_on_rndspot((up
? 1 : 0) | (was_in_W_tower
? 2 : 0));
1376 selftouch("Falling, you");
1382 obj_delivery(FALSE
);
1384 kill_genocided_monsters(); /* for those wiped out while in limbo */
1386 * Expire all timers that have gone off while away. Must be
1387 * after migrating monsters and objects are delivered
1388 * (losedogs and obj_delivery).
1394 if ((mtmp
= m_at(u
.ux
, u
.uy
)) != 0 && mtmp
!= u
.usteed
) {
1395 /* There's a monster at your target destination; it might be one
1396 which accompanied you--see mon_arrive(dogmove.c)--or perhaps
1397 it was already here. Randomly move you to an adjacent spot
1398 or else the monster to any nearby location. Prior to 3.3.0
1399 the latter was done unconditionally. */
1402 if (!rn2(2) && enexto(&cc
, u
.ux
, u
.uy
, youmonst
.data
)
1403 && distu(cc
.x
, cc
.y
) <= 2)
1404 u_on_newpos(cc
.x
, cc
.y
); /*[maybe give message here?]*/
1408 if ((mtmp
= m_at(u
.ux
, u
.uy
)) != 0) {
1409 /* there was an unconditional impossible("mnearto failed")
1410 here, but it's not impossible and we're prepared to cope
1411 with the situation, so only say something when debugging */
1413 pline("(monster in hero's way)");
1414 if (!rloc(mtmp
, TRUE
))
1415 /* no room to move it; send it away, to return later */
1416 migrate_to_level(mtmp
, ledger_no(&u
.uz
), MIGR_RANDOM
,
1421 /* initial movement of bubbles just before vision_recalc */
1422 if (Is_waterlevel(&u
.uz
) || Is_airlevel(&u
.uz
))
1424 else if (Is_firelevel(&u
.uz
))
1427 if (level_info
[new_ledger
].flags
& FORGOTTEN
) {
1428 forget_map(ALL_MAP
); /* forget the map */
1429 forget_traps(); /* forget all traps too */
1431 level_info
[new_ledger
].flags
&= ~FORGOTTEN
;
1434 /* Reset the screen. */
1435 vision_reset(); /* reset the blockages */
1436 docrt(); /* does a full vision recalc */
1440 * Move all plines beyond the screen reset.
1443 /* special levels can have a custom arrival message */
1444 deliver_splev_message();
1446 /* give room entrance message, if any */
1447 check_special_room(FALSE
);
1449 /* deliver objects traveling with player */
1452 /* Check whether we just entered Gehennom. */
1453 if (!In_hell(&u
.uz0
) && Inhell
) {
1454 if (Is_valley(&u
.uz
)) {
1455 You("arrive at the Valley of the Dead...");
1456 pline_The("odor of burnt flesh and decay pervades the air.");
1458 display_nhwindow(WIN_MESSAGE
, FALSE
);
1460 You_hear("groans and moans everywhere.");
1462 pline("It is hot here. You smell smoke...");
1463 u
.uachieve
.enter_gehennom
= 1;
1465 /* in case we've managed to bypass the Valley's stairway down */
1466 if (Inhell
&& !Is_valley(&u
.uz
))
1467 u
.uevent
.gehennom_entered
= 1;
1470 static const char *const fam_msgs
[4] = {
1471 "You have a sense of deja vu.",
1472 "You feel like you've been here before.",
1473 "This place %s familiar...", 0 /* no message */
1475 static const char *const halu_fam_msgs
[4] = {
1476 "Whoa! Everything %s different.",
1477 "You are surrounded by twisty little passages, all alike.",
1478 "Gee, this %s like uncle Conan's place...", 0 /* no message */
1485 mesg
= halu_fam_msgs
[which
];
1487 mesg
= fam_msgs
[which
];
1488 if (mesg
&& index(mesg
, '%')) {
1489 Sprintf(buf
, mesg
, !Blind
? "looks" : "seems");
1496 /* special location arrival messages/events */
1497 if (In_endgame(&u
.uz
)) {
1498 if (new &&on_level(&u
.uz
, &astral_level
))
1499 final_level(); /* guardian angel,&c */
1500 else if (newdungeon
&& u
.uhave
.amulet
)
1501 resurrect(); /* force confrontation with Wizard */
1502 } else if (In_quest(&u
.uz
)) {
1503 onquest(); /* might be reaching locate|goal level */
1504 } else if (In_V_tower(&u
.uz
)) {
1505 if (newdungeon
&& In_hell(&u
.uz0
))
1506 pline_The("heat and smoke are gone.");
1507 } else if (Is_knox(&u
.uz
)) {
1508 /* alarm stops working once Croesus has died */
1509 if (new || !mvitals
[PM_CROESUS
].died
) {
1510 You("have penetrated a high security area!");
1511 pline("An alarm sounds!");
1512 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
) {
1513 if (DEADMONSTER(mtmp
))
1515 mtmp
->msleeping
= 0;
1519 if (new && Is_rogue_level(&u
.uz
))
1520 You("enter what seems to be an older, more primitive world.");
1521 /* main dungeon message from your quest leader */
1522 if (!In_quest(&u
.uz0
) && at_dgn_entrance("The Quest")
1523 && !(u
.uevent
.qcompleted
|| u
.uevent
.qexpelled
1524 || quest_status
.leader_is_dead
)) {
1525 if (!u
.uevent
.qcalled
) {
1526 u
.uevent
.qcalled
= 1;
1527 com_pager(2); /* main "leader needs help" message */
1528 } else { /* reminder message */
1529 com_pager(Role_if(PM_ROGUE
) ? 4 : 3);
1534 assign_level(&u
.uz0
, &u
.uz
); /* reset u.uz0 */
1536 save_currentstate();
1539 if ((annotation
= get_annotation(&u
.uz
)) != 0)
1540 You("remember this level as %s.", annotation
);
1542 /* assume this will always return TRUE when changing level */
1543 (void) in_out_region(u
.ux
, u
.uy
);
1546 /* discard context which applied to previous level */
1547 maybe_reset_pick(); /* for door or for box not accompanying hero */
1548 reset_trapset(); /* even if to-be-armed trap obj is accompanying hero */
1549 iflags
.travelcc
.x
= iflags
.travelcc
.y
= -1; /* travel destination cache */
1550 context
.polearm
.hitmon
= (struct monst
*) 0; /* polearm target */
1551 /* digging context is level-aware and can actually be resumed if
1552 hero returns to the previous level without any intervening dig */
1560 /* reset monster hostility relative to player */
1561 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
) {
1562 if (DEADMONSTER(mtmp
))
1564 reset_hostility(mtmp
);
1567 /* create some player-monsters */
1568 create_mplayers(rn1(4, 3), TRUE
);
1570 /* create a guardian angel next to player, if worthy */
1571 gain_guardian_angel();
1574 static char *dfr_pre_msg
= 0, /* pline() before level change */
1575 *dfr_post_msg
= 0; /* pline() after level change */
1577 /* change levels at the end of this turn, after monsters finish moving */
1579 schedule_goto(tolev
, at_stairs
, falling
, portal_flag
, pre_msg
, post_msg
)
1581 boolean at_stairs
, falling
;
1583 const char *pre_msg
, *post_msg
;
1585 int typmask
= 0100; /* non-zero triggers `deferred_goto' */
1587 /* destination flags (`goto_level' args) */
1594 if (portal_flag
< 0)
1595 typmask
|= 0200; /* flag for portal removal */
1596 u
.utotype
= typmask
;
1597 /* destination level */
1598 assign_level(&u
.utolev
, tolev
);
1601 dfr_pre_msg
= dupstr(pre_msg
);
1603 dfr_post_msg
= dupstr(post_msg
);
1606 /* handle something like portal ejection */
1610 if (!on_level(&u
.uz
, &u
.utolev
)) {
1612 int typmask
= u
.utotype
; /* save it; goto_level zeroes u.utotype */
1614 assign_level(&dest
, &u
.utolev
);
1616 pline1(dfr_pre_msg
);
1617 goto_level(&dest
, !!(typmask
& 1), !!(typmask
& 2), !!(typmask
& 4));
1618 if (typmask
& 0200) { /* remove portal */
1619 struct trap
*t
= t_at(u
.ux
, u
.uy
);
1627 pline1(dfr_post_msg
);
1629 u
.utotype
= 0; /* our caller keys off of this */
1631 free((genericptr_t
) dfr_pre_msg
), dfr_pre_msg
= 0;
1633 free((genericptr_t
) dfr_post_msg
), dfr_post_msg
= 0;
1637 * Return TRUE if we created a monster for the corpse. If successful, the
1641 revive_corpse(corpse
)
1644 struct monst
*mtmp
, *mcarry
;
1645 boolean is_uwep
, chewed
;
1648 struct obj
*container
= (struct obj
*) 0;
1649 int container_where
= 0;
1651 where
= corpse
->where
;
1652 is_uwep
= (corpse
== uwep
);
1653 chewed
= (corpse
->oeaten
!= 0);
1655 corpse_xname(corpse
, chewed
? "bite-covered" : (const char *) 0,
1657 mcarry
= (where
== OBJ_MINVENT
) ? corpse
->ocarry
: 0;
1659 if (where
== OBJ_CONTAINED
) {
1660 struct monst
*mtmp2
;
1662 container
= corpse
->ocontainer
;
1664 get_container_location(container
, &container_where
, (int *) 0);
1665 /* container_where is the outermost container's location even if
1667 if (container_where
== OBJ_MINVENT
&& mtmp2
)
1670 mtmp
= revive(corpse
, FALSE
); /* corpse is gone if successful */
1676 pline_The("%s writhes out of your grasp!", cname
);
1678 You_feel("squirming in your backpack!");
1682 if (cansee(mtmp
->mx
, mtmp
->my
))
1683 pline("%s rises from the dead!",
1684 chewed
? Adjmonnam(mtmp
, "bite-covered")
1688 case OBJ_MINVENT
: /* probably a nymph's */
1689 if (cansee(mtmp
->mx
, mtmp
->my
)) {
1690 if (canseemon(mcarry
))
1691 pline("Startled, %s drops %s as it revives!",
1692 mon_nam(mcarry
), an(cname
));
1694 pline("%s suddenly appears!",
1695 chewed
? Adjmonnam(mtmp
, "bite-covered")
1699 case OBJ_CONTAINED
: {
1700 char sackname
[BUFSZ
];
1702 if (container_where
== OBJ_MINVENT
&& cansee(mtmp
->mx
, mtmp
->my
)
1703 && mcarry
&& canseemon(mcarry
) && container
) {
1704 pline("%s writhes out of %s!", Amonnam(mtmp
),
1706 } else if (container_where
== OBJ_INVENT
&& container
) {
1707 Strcpy(sackname
, an(xname(container
)));
1708 pline("%s %s out of %s in your pack!",
1709 Blind
? Something
: Amonnam(mtmp
),
1710 locomotion(mtmp
->data
, "writhes"), sackname
);
1711 } else if (container_where
== OBJ_FLOOR
&& container
1712 && cansee(mtmp
->mx
, mtmp
->my
)) {
1713 Strcpy(sackname
, an(xname(container
)));
1714 pline("%s escapes from %s!", Amonnam(mtmp
), sackname
);
1719 /* we should be able to handle the other cases... */
1720 impossible("revive_corpse: lost corpse @ %d", where
);
1728 /* Revive the corpse via a timeout. */
1731 revive_mon(arg
, timeout
)
1733 long timeout UNUSED
;
1735 struct obj
*body
= arg
->a_obj
;
1736 struct permonst
*mptr
= &mons
[body
->corpsenm
];
1740 /* corpse will revive somewhere else if there is a monster in the way;
1741 Riders get a chance to try to bump the obstacle out of their way */
1742 if ((mptr
->mflags3
& M3_DISPLACES
) != 0 && body
->where
== OBJ_FLOOR
1743 && get_obj_location(body
, &x
, &y
, 0) && (mtmp
= m_at(x
, y
)) != 0) {
1744 boolean notice_it
= canseemon(mtmp
); /* before rloc() */
1745 char *monname
= Monnam(mtmp
);
1747 if (rloc(mtmp
, TRUE
)) {
1748 if (notice_it
&& !canseemon(mtmp
))
1749 pline("%s vanishes.", monname
);
1750 else if (!notice_it
&& canseemon(mtmp
))
1751 pline("%s appears.", Monnam(mtmp
)); /* not pre-rloc monname */
1752 else if (notice_it
&& dist2(mtmp
->mx
, mtmp
->my
, x
, y
) > 2)
1753 pline("%s teleports.", monname
); /* saw it and still see it */
1757 /* if we succeed, the corpse is gone */
1758 if (!revive_corpse(body
)) {
1762 if (is_rider(mptr
) && rn2(99)) { /* Rider usually tries again */
1763 action
= REVIVE_MON
;
1764 for (when
= 3L; when
< 67L; when
++)
1767 } else { /* rot this corpse away */
1768 You_feel("%sless hassled.", is_rider(mptr
) ? "much " : "");
1769 action
= ROT_CORPSE
;
1770 when
= 250L - (monstermoves
- body
->age
);
1774 (void) start_timer(when
, TIMER_OBJECT
, action
, arg
);
1781 return 1; /* Do nothing, but let other things happen */
1796 pline("You've got the glop off.");
1798 if (!gulp_blnd_check()) {
1800 make_blinded(0L, TRUE
);
1803 } else if (!u
.ucreamed
) {
1804 Your("%s feels clean now.", body_part(FACE
));
1807 return 1; /* still busy */
1814 static NEARDATA
char buf
[39];
1816 Sprintf(buf
, "wiping off your %s", body_part(FACE
));
1817 set_occupation(wipeoff
, buf
, 0);
1818 /* Not totally correct; what if they change back after now
1819 * but before they're finished wiping?
1823 Your("%s is already clean.", body_part(FACE
));
1828 set_wounded_legs(side
, timex
)
1833 * If you are riding, your steed gets the wounded legs instead.
1834 * You still call this function, but don't lose hp.
1835 * Caller is also responsible for adjusting messages.
1838 if (!Wounded_legs
) {
1843 if (!Wounded_legs
|| (HWounded_legs
& TIMEOUT
))
1844 HWounded_legs
= timex
;
1845 EWounded_legs
= side
;
1846 (void) encumber_msg();
1853 if (ATEMP(A_DEX
) < 0) {
1859 const char *legs
= body_part(LEG
);
1861 if ((EWounded_legs
& BOTH_SIDES
) == BOTH_SIDES
)
1862 legs
= makeplural(legs
);
1863 /* this used to say "somewhat better" but that was
1864 misleading since legs are being fully healed */
1865 Your("%s %s better.", legs
, vtense(legs
, "feel"));
1868 HWounded_legs
= EWounded_legs
= 0;
1870 /* Wounded_legs reduces carrying capacity, so we want
1871 an encumbrance check when they're healed. However,
1872 while dismounting, first steed's legs get healed,
1873 then hero is dropped to floor and a new encumbrance
1874 check is made [in dismount_steed()]. So don't give
1875 encumbrance feedback during the dismount stage
1876 because it could seem to be shown out of order and
1877 it might be immediately contradicted [able to carry
1878 more when steed becomes healthy, then possible floor
1879 feedback, then able to carry less when back on foot]. */
1880 if (!in_steed_dismounting
)
1881 (void) encumber_msg();