1 /* NetHack 3.6 do.c $NHDT-Date: 1454033599 2016/01/29 02:13:19 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.153 $ */
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
);
42 /* Called when a boulder is dropped, thrown, or pushed. If it ends up
43 * in a pool, it either fills the pool up or sinks away. In either case,
44 * it's gone for good... If the destination is not a pool, returns FALSE.
47 boulder_hits_pool(otmp
, rx
, ry
, pushing
)
52 if (!otmp
|| otmp
->otyp
!= BOULDER
) {
53 impossible("Not a boulder?");
54 } else if (!Is_waterlevel(&u
.uz
) && is_pool_or_lava(rx
, ry
)) {
55 boolean lava
= is_lava(rx
, ry
), fills_up
;
56 const char *what
= waterbody_name(rx
, ry
);
57 schar ltyp
= levl
[rx
][ry
].typ
;
58 int chance
= rn2(10); /* water: 90%; lava: 10% */
59 fills_up
= lava
? chance
== 0 : chance
!= 0;
62 struct trap
*ttmp
= t_at(rx
, ry
);
64 if (ltyp
== DRAWBRIDGE_UP
) {
65 levl
[rx
][ry
].drawbridgemask
&= ~DB_UNDER
; /* clear lava */
66 levl
[rx
][ry
].drawbridgemask
|= DB_FLOOR
;
68 levl
[rx
][ry
].typ
= ROOM
;
71 (void) delfloortrap(ttmp
);
78 Strcpy(whobuf
, "you");
80 Strcpy(whobuf
, y_monnam(u
.usteed
));
81 pline("%s %s %s into the %s.", upstart(whobuf
),
82 vtense(whobuf
, "push"), the(xname(otmp
)), what
);
83 if (flags
.verbose
&& !Blind
)
84 pline("Now you can cross it!");
85 /* no splashing in this case */
88 if (!fills_up
|| !pushing
) { /* splashing occurs */
90 if (pushing
? !Blind
: cansee(rx
, ry
)) {
91 There("is a large splash as %s %s the %s.",
92 the(xname(otmp
)), fills_up
? "fills" : "falls into",
95 You_hear("a%s splash.", lava
? " sizzling" : "");
96 wake_nearto(rx
, ry
, 40);
99 if (fills_up
&& u
.uinwater
&& distu(rx
, ry
) == 0) {
102 vision_full_recalc
= 1;
103 You("find yourself on dry land again!");
104 } else if (lava
&& distu(rx
, ry
) <= 2) {
106 You("are hit by molten lava%c", Fire_resistance
? '.' : '!');
108 dmg
= d((Fire_resistance
? 1 : 3), 6);
109 losehp(Maybe_Half_Phys(dmg
), /* lava damage */
110 "molten lava", KILLED_BY
);
111 } else if (!fills_up
&& flags
.verbose
112 && (pushing
? !Blind
: cansee(rx
, ry
)))
113 pline("It sinks without a trace!");
116 /* boulder is now gone */
120 obfree(otmp
, (struct obj
*) 0);
126 /* Used for objects which sometimes do special things when dropped; must be
127 * called with the object not in any chain. Returns TRUE if the object goes
131 flooreffects(obj
, x
, y
, verb
)
140 if (obj
->where
!= OBJ_FREE
)
141 panic("flooreffects: obj not free");
143 /* make sure things like water_damage() have no pointers to follow */
144 obj
->nobj
= obj
->nexthere
= (struct obj
*) 0;
146 if (obj
->otyp
== BOULDER
&& boulder_hits_pool(obj
, x
, y
, FALSE
)) {
148 } else if (obj
->otyp
== BOULDER
&& (t
= t_at(x
, y
)) != 0
149 && (t
->ttyp
== PIT
|| t
->ttyp
== SPIKED_PIT
150 || t
->ttyp
== TRAPDOOR
|| t
->ttyp
== HOLE
)) {
151 if (((mtmp
= m_at(x
, y
)) && mtmp
->mtrapped
)
152 || (u
.utrap
&& u
.ux
== x
&& u
.uy
== y
)) {
154 pline_The("boulder %s into the pit%s.",
155 vtense((const char *) 0, verb
),
156 (mtmp
) ? "" : " with you");
158 if (!passes_walls(mtmp
->data
) && !throws_rocks(mtmp
->data
)) {
159 if (hmon(mtmp
, obj
, TRUE
) && !is_whirly(mtmp
->data
))
160 return FALSE
; /* still alive */
164 if (!Passes_walls
&& !throws_rocks(youmonst
.data
)) {
165 losehp(Maybe_Half_Phys(rnd(15)),
166 "squished under a boulder", NO_KILLER_PREFIX
);
167 return FALSE
; /* player remains trapped */
173 if (Blind
&& (x
== u
.ux
) && (y
== u
.uy
)) {
174 You_hear("a CRASH! beneath you.");
175 } else if (!Blind
&& cansee(x
, y
)) {
176 pline_The("boulder %s%s.", t
->tseen
? "" : "triggers and ",
178 ? "plugs a trap door"
179 : t
->ttyp
== HOLE
? "plugs a hole"
182 You_hear("a boulder %s.", verb
);
190 } else if (is_lava(x
, y
)) {
191 return fire_damage(obj
, FALSE
, x
, y
);
192 } else if (is_pool(x
, y
)) {
193 /* Reasonably bulky objects (arbitrary) splash when dropped.
194 * If you're floating above the water even small things make
195 * noise. Stuff dropped near fountains always misses */
196 if ((Blind
|| (Levitation
|| Flying
)) && !Deaf
197 && ((x
== u
.ux
) && (y
== u
.uy
))) {
199 if (weight(obj
) > 9) {
201 } else if (Levitation
|| Flying
) {
205 map_background(x
, y
, 0);
208 return water_damage(obj
, NULL
, FALSE
) == ER_DESTROYED
;
209 } else if (u
.ux
== x
&& u
.uy
== y
&& (t
= t_at(x
, y
)) != 0
210 && uteetering_at_seen_pit(t
)) {
212 You_hear("%s tumble downwards.", the(xname(obj
)));
214 pline("%s %s into %s pit.", The(xname(obj
)),
215 otense(obj
, "tumble"), the_your
[t
->madeby_u
]);
216 } else if (obj
->globby
) {
217 /* Globby things like puddings might stick together */
218 while (obj
&& (otmp
= obj_nexto_xy(obj
, x
, y
, TRUE
)) != 0) {
219 pudding_merge_message(obj
, otmp
);
220 /* intentionally not getting the melded object; obj_meld may set
222 (void) obj_meld(&obj
, &otmp
);
224 return (boolean
) !obj
;
229 /* obj is an object dropped on an altar */
232 register struct obj
*obj
;
237 if (obj
->oclass
!= COIN_CLASS
) {
239 u
.uconduct
.gnostic
++;
241 /* coins don't have bless/curse status */
242 obj
->blessed
= obj
->cursed
= 0;
245 if (obj
->blessed
|| obj
->cursed
) {
246 There("is %s flash as %s %s the altar.",
247 an(hcolor(obj
->blessed
? NH_AMBER
: NH_BLACK
)), doname(obj
),
252 pline("%s %s on the altar.", Doname2(obj
), otense(obj
, "land"));
253 if (obj
->oclass
!= COIN_CLASS
)
260 register struct obj
*obj
;
262 if (!objects
[obj
->otyp
].oc_name_known
&& !objects
[obj
->otyp
].oc_uname
)
266 /* Transforms the sink at the player's position into
267 a fountain, throne, altar or grave. */
273 if (levl
[u
.ux
][u
.uy
].typ
!= SINK
)
276 level
.flags
.nsinks
--;
277 levl
[u
.ux
][u
.uy
].doormask
= 0;
282 levl
[u
.ux
][u
.uy
].typ
= FOUNTAIN
;
283 level
.flags
.nfountains
++;
287 levl
[u
.ux
][u
.uy
].typ
= THRONE
;
291 levl
[u
.ux
][u
.uy
].typ
= ALTAR
;
292 levl
[u
.ux
][u
.uy
].altarmask
= Align2amask(rn2((int) A_LAWFUL
+ 2) - 1);
296 levl
[u
.ux
][u
.uy
].typ
= ROOM
;
297 make_grave(u
.ux
, u
.uy
, (char *) 0);
298 if (levl
[u
.ux
][u
.uy
].typ
== GRAVE
)
302 /* give message even if blind; we know we're not levitating,
303 so can feel the outcome even if we can't directly see it */
304 if (levl
[u
.ux
][u
.uy
].typ
!= ROOM
)
305 pline_The("sink transforms into %s!", an(defsyms
[sym
].explanation
));
307 pline_The("sink vanishes.");
311 /* Teleports the sink at the player's position;
312 return True if sink teleported. */
325 eng
= engr_at(cx
, cy
);
326 } while ((levl
[cx
][cy
].typ
!= ROOM
|| trp
|| eng
|| cansee(cx
, cy
))
329 if (levl
[cx
][cy
].typ
== ROOM
&& !trp
&& !eng
) {
330 /* create sink at new position */
331 levl
[cx
][cy
].typ
= SINK
;
332 levl
[cx
][cy
].looted
= levl
[u
.ux
][u
.uy
].looted
;
334 /* remove old sink */
335 levl
[u
.ux
][u
.uy
].typ
= ROOM
;
336 levl
[u
.ux
][u
.uy
].looted
= 0;
343 /* obj is a ring being dropped over a kitchen sink */
346 register struct obj
*obj
;
348 struct obj
*otmp
, *otmp2
;
349 boolean ideed
= TRUE
;
350 boolean nosink
= FALSE
;
352 You("drop %s down the drain.", doname(obj
));
353 obj
->in_use
= TRUE
; /* block free identification via interrupt */
354 switch (obj
->otyp
) { /* effects that can be noticed without eyes */
356 You("thought %s got lost in the sink, but there it is!", yname(obj
));
358 case RIN_SLOW_DIGESTION
:
359 pline_The("ring is regurgitated!");
366 pline_The("sink quivers upward for a moment.");
368 case RIN_POISON_RESISTANCE
:
369 You("smell rotten %s.", makeplural(fruitname(FALSE
)));
371 case RIN_AGGRAVATE_MONSTER
:
372 pline("Several %s buzz angrily around the sink.",
373 Hallucination
? makeplural(rndmonnam(NULL
)) : "flies");
375 case RIN_SHOCK_RESISTANCE
:
376 pline("Static electricity surrounds the sink.");
379 You_hear("loud noises coming from the drain.");
381 case RIN_SUSTAIN_ABILITY
: /* KMH */
382 pline_The("water flow seems fixed.");
384 case RIN_GAIN_STRENGTH
:
385 pline_The("water flow seems %ser now.",
386 (obj
->spe
< 0) ? "weak" : "strong");
388 case RIN_GAIN_CONSTITUTION
:
389 pline_The("water flow seems %ser now.",
390 (obj
->spe
< 0) ? "less" : "great");
392 case RIN_INCREASE_ACCURACY
: /* KMH */
393 pline_The("water flow %s the drain.",
394 (obj
->spe
< 0) ? "misses" : "hits");
396 case RIN_INCREASE_DAMAGE
:
397 pline_The("water's force seems %ser now.",
398 (obj
->spe
< 0) ? "small" : "great");
402 for (otmp
= level
.objects
[u
.ux
][u
.uy
]; otmp
; otmp
= otmp2
) {
403 otmp2
= otmp
->nexthere
;
404 if (otmp
!= uball
&& otmp
!= uchain
405 && !obj_resists(otmp
, 1, 99)) {
407 pline("Suddenly, %s %s from the sink!", doname(otmp
),
408 otense(otmp
, "vanish"));
416 /* Not the same as aggravate monster; besides, it's obvious. */
417 pline("Several flies buzz around the sink.");
419 case RIN_TELEPORTATION
:
420 nosink
= teleport_sink();
421 /* give message even if blind; we know we're not levitating,
422 so can feel the outcome even if we can't directly see it */
423 pline_The("sink %svanishes.", nosink
? "" : "momentarily ");
429 /* for S_room case, same message as for teleportation is given */
430 ideed
= (levl
[u
.ux
][u
.uy
].typ
!= ROOM
);
436 if (!Blind
&& !ideed
) {
438 switch (obj
->otyp
) { /* effects that need eyes */
440 pline_The("faucets flash brightly for a moment.");
442 case RIN_REGENERATION
:
443 pline_The("sink looks as good as new.");
445 case RIN_INVISIBILITY
:
446 You("don't see anything happen to the sink.");
448 case RIN_FREE_ACTION
:
449 You_see("the ring slide right down the drain!");
451 case RIN_SEE_INVISIBLE
:
452 You_see("some %s in the sink.",
453 Hallucination
? "oxygen molecules" : "air");
456 pline_The("sink seems to blend into the floor for a moment.");
458 case RIN_FIRE_RESISTANCE
:
459 pline_The("hot water faucet flashes brightly for a moment.");
461 case RIN_COLD_RESISTANCE
:
462 pline_The("cold water faucet flashes brightly for a moment.");
464 case RIN_PROTECTION_FROM_SHAPE_CHAN
:
465 pline_The("sink looks nothing like a fountain.");
468 pline_The("sink glows %s for a moment.",
469 hcolor((obj
->spe
< 0) ? NH_BLACK
: NH_SILVER
));
472 pline_The("sink glows %s for a moment.", hcolor(NH_WHITE
));
474 case RIN_TELEPORT_CONTROL
:
475 pline_The("sink looks like it is being beamed aboard somewhere.");
477 case RIN_POLYMORPH_CONTROL
:
479 "sink momentarily looks like a regularly erupting geyser.");
488 You_hear("the ring bouncing down the drainpipe.");
490 if (!rn2(20) && !nosink
) {
491 pline_The("sink backs up, leaving %s.", doname(obj
));
498 /* some common tests when trying to drop or throw items */
504 if (obj
->owornmask
& (W_ARMOR
| W_ACCESSORY
)) {
506 Norep("You cannot %s %s you are wearing.", word
, something
);
509 if (obj
->otyp
== LOADSTONE
&& obj
->cursed
) {
510 /* getobj() kludge sets corpsenm to user's specified count
511 when refusing to split a stack of cursed loadstones */
513 /* getobj() ignores a count for throwing since that is
514 implicitly forced to be 1; replicate its kludge... */
515 if (!strcmp(word
, "throw") && obj
->quan
> 1L)
517 pline("For some reason, you cannot %s%s the stone%s!", word
,
518 obj
->corpsenm
? " any of" : "", plur(obj
->quan
));
520 obj
->corpsenm
= 0; /* reset */
524 if (obj
->otyp
== LEASH
&& obj
->leashmon
!= 0) {
526 pline_The("leash is tied around your %s.", body_part(HAND
));
529 if (obj
->owornmask
& W_SADDLE
) {
531 You("cannot %s %s you are sitting on.", word
, something
);
539 register struct obj
*obj
;
543 if (!canletgo(obj
, "drop"))
550 setuwep((struct obj
*) 0);
552 if (obj
== uquiver
) {
553 setuqwep((struct obj
*) 0);
555 if (obj
== uswapwep
) {
556 setuswapwep((struct obj
*) 0);
560 /* barrier between you and the floor */
564 /* doname can call s_suffix, reusing its buffer */
565 Strcpy(buf
, s_suffix(mon_nam(u
.ustuck
)));
566 You("drop %s into %s %s.", doname(obj
), buf
,
567 mbodypart(u
.ustuck
, STOMACH
));
570 if ((obj
->oclass
== RING_CLASS
|| obj
->otyp
== MEAT_RING
)
571 && IS_SINK(levl
[u
.ux
][u
.uy
].typ
)) {
575 if (!can_reach_floor(TRUE
)) {
576 /* we might be levitating due to #invoke Heart of Ahriman;
577 if so, levitation would end during call to freeinv()
578 and we want hitfloor() to happen before float_down() */
579 boolean levhack
= finesse_ahriman(obj
);
582 ELevitation
= W_ART
; /* other than W_ARTI */
584 You("drop %s.", doname(obj
));
585 /* Ensure update when we drop gold objects */
586 if (obj
->oclass
== COIN_CLASS
)
591 float_down(I_SPECIAL
| TIMEOUT
, W_ARTI
| W_ART
);
594 if (!IS_ALTAR(levl
[u
.ux
][u
.uy
].typ
) && flags
.verbose
)
595 You("drop %s.", doname(obj
));
601 /* dropx - take dropped item out of inventory;
602 called in several places - may produce output
603 (eg ship_object() and dropy() -> sellobj() both produce output) */
606 register struct obj
*obj
;
608 /* Ensure update when we drop gold objects */
609 if (obj
->oclass
== COIN_CLASS
)
613 if (ship_object(obj
, u
.ux
, u
.uy
, FALSE
))
615 if (IS_ALTAR(levl
[u
.ux
][u
.uy
].typ
))
616 doaltarobj(obj
); /* set bknown */
621 /* dropy - put dropped object at destination; called from lots of places */
629 /* dropz - really put dropped object at its destination... */
631 dropz(obj
, with_impact
)
636 setuwep((struct obj
*) 0);
638 setuqwep((struct obj
*) 0);
640 setuswapwep((struct obj
*) 0);
642 if (!u
.uswallow
&& flooreffects(obj
, u
.ux
, u
.uy
, "drop"))
644 /* uswallow check done by GAN 01/29/87 */
646 boolean could_petrify
= FALSE
;
647 boolean could_poly
= FALSE
;
648 boolean could_slime
= FALSE
;
649 boolean could_grow
= FALSE
;
650 boolean could_heal
= FALSE
;
652 if (obj
!= uball
) { /* mon doesn't pick up ball */
653 if (obj
->otyp
== CORPSE
) {
654 could_petrify
= touch_petrifies(&mons
[obj
->corpsenm
]);
655 could_poly
= polyfodder(obj
);
656 could_slime
= (obj
->corpsenm
== PM_GREEN_SLIME
);
657 could_grow
= (obj
->corpsenm
== PM_WRAITH
);
658 could_heal
= (obj
->corpsenm
== PM_NURSE
);
660 (void) mpickobj(u
.ustuck
, obj
);
661 if (is_animal(u
.ustuck
->data
)) {
662 if (could_poly
|| could_slime
) {
663 (void) newcham(u
.ustuck
,
664 could_poly
? (struct permonst
*) 0
665 : &mons
[PM_GREEN_SLIME
],
667 delobj(obj
); /* corpse is digested */
668 } else if (could_petrify
) {
669 minstapetrify(u
.ustuck
, TRUE
);
670 /* Don't leave a cockatrice corpse in a statue */
673 } else if (could_grow
) {
674 (void) grow_up(u
.ustuck
, (struct monst
*) 0);
675 delobj(obj
); /* corpse is digested */
676 } else if (could_heal
) {
677 u
.ustuck
->mhp
= u
.ustuck
->mhpmax
;
678 delobj(obj
); /* corpse is digested */
683 place_object(obj
, u
.ux
, u
.uy
);
685 container_impact_dmg(obj
, u
.ux
, u
.uy
);
687 drop_ball(u
.ux
, u
.uy
);
688 else if (level
.flags
.has_shop
)
689 sellobj(obj
, u
.ux
, u
.uy
);
691 if (Blind
&& Levitation
)
693 newsym(u
.ux
, u
.uy
); /* remap location under self */
697 /* things that must change when not held; recurse into containers.
698 Called for both player and monsters */
700 obj_no_longer_held(obj
)
705 } else if (Has_contents(obj
)) {
706 struct obj
*contents
;
708 for (contents
= obj
->cobj
; contents
; contents
= contents
->nobj
)
709 obj_no_longer_held(contents
);
713 /* Normal crysknife reverts to worm tooth when not held by hero
714 * or monster; fixed crysknife has only 10% chance of reverting.
715 * When a stack of the latter is involved, it could be worthwhile
716 * to give each individual crysknife its own separate 10% chance,
717 * but we aren't in any position to handle stack splitting here.
719 if (!obj
->oerodeproof
|| !rn2(10)) {
720 /* if monsters aren't moving, assume player is responsible */
721 if (!context
.mon_moving
&& !program_state
.gameover
)
722 costly_alteration(obj
, COST_DEGRD
);
723 obj
->otyp
= WORM_TOOTH
;
724 obj
->oerodeproof
= 0;
730 /* 'D' command: drop several things */
736 add_valid_menu_class(0); /* clear any classes already there */
738 sellobj_state(SELL_DELIBERATE
);
739 if (flags
.menu_style
!= MENU_TRADITIONAL
740 || (result
= ggetobj("drop", drop
, 0, FALSE
, (unsigned *) 0)) < -1)
741 result
= menu_drop(result
);
743 sellobj_state(SELL_NORMAL
);
749 /* Drop things from the hero's inventory, using a menu. */
754 int n
, i
, n_dropped
= 0;
756 struct obj
*otmp
, *otmp2
;
757 menu_item
*pick_list
;
758 boolean all_categories
= TRUE
;
759 boolean drop_everything
= FALSE
;
762 all_categories
= (retry
== -2);
763 } else if (flags
.menu_style
== MENU_FULL
) {
764 all_categories
= FALSE
;
765 n
= query_category("Drop what type of items?", invent
,
766 UNPAID_TYPES
| ALL_TYPES
| CHOOSE_ALL
| BUC_BLESSED
767 | BUC_CURSED
| BUC_UNCURSED
| BUC_UNKNOWN
,
768 &pick_list
, PICK_ANY
);
771 for (i
= 0; i
< n
; i
++) {
772 if (pick_list
[i
].item
.a_int
== ALL_TYPES_SELECTED
)
773 all_categories
= TRUE
;
774 else if (pick_list
[i
].item
.a_int
== 'A')
775 drop_everything
= TRUE
;
777 add_valid_menu_class(pick_list
[i
].item
.a_int
);
779 free((genericptr_t
) pick_list
);
780 } else if (flags
.menu_style
== MENU_COMBINATION
) {
781 unsigned ggoresults
= 0;
782 all_categories
= FALSE
;
783 /* Gather valid classes via traditional NetHack method */
784 i
= ggetobj("drop", drop
, 0, TRUE
, &ggoresults
);
786 all_categories
= TRUE
;
787 if (ggoresults
& ALL_FINISHED
) {
793 if (drop_everything
) {
795 * Dropping a burning potion of oil while levitating can cause
796 * an explosion which might destroy some of hero's inventory,
798 * for (otmp = invent; otmp; otmp = otmp2) {
799 * otmp2 = otmp->nobj;
800 * n_dropped += drop(otmp);
802 * was unreliable and could lead to an "object lost" panic.
804 * Use the bypass bit to mark items already processed (hence
805 * not droppable) and rescan inventory until no unbypassed
808 bypass_objlist(invent
, FALSE
); /* clear bypass bit for invent */
809 while ((otmp
= nxt_unbypassed_obj(invent
)) != 0)
810 n_dropped
+= drop(otmp
);
811 /* we might not have dropped everything (worn armor, welded weapon,
812 cursed loadstones), so reset any remaining inventory to normal */
813 bypass_objlist(invent
, FALSE
);
815 /* should coordinate with perm invent, maybe not show worn items */
816 n
= query_objlist("What would you like to drop?", &invent
,
817 (USE_INVLET
| INVORDER_SORT
), &pick_list
, PICK_ANY
,
818 all_categories
? allow_all
: allow_category
);
821 * picklist[] contains a set of pointers into inventory, but
822 * as soon as something gets dropped, they might become stale
823 * (see the drop_everything code above for an explanation).
824 * Just checking to see whether one is still in the invent
825 * chain is not sufficient validation since destroyed items
826 * will be freed and items we've split here might have already
827 * reused that memory and put the same pointer value back into
828 * invent. Ditto for using invlet to validate. So we start
829 * by setting bypass on all of invent, then check each pointer
830 * to verify that it is in invent and has that bit set.
832 bypass_objlist(invent
, TRUE
);
833 for (i
= 0; i
< n
; i
++) {
834 otmp
= pick_list
[i
].item
.a_obj
;
835 for (otmp2
= invent
; otmp2
; otmp2
= otmp2
->nobj
)
838 if (!otmp2
|| !otmp2
->bypass
)
840 /* found next selected invent item */
841 cnt
= pick_list
[i
].count
;
842 if (cnt
< otmp
->quan
) {
845 } else if (otmp
->otyp
== LOADSTONE
&& otmp
->cursed
) {
846 /* same kludge as getobj(), for canletgo()'s use */
847 otmp
->corpsenm
= (int) cnt
; /* don't split */
849 otmp
= splitobj(otmp
, cnt
);
852 n_dropped
+= drop(otmp
);
854 bypass_objlist(invent
, FALSE
); /* reset invent to normal */
855 free((genericptr_t
) pick_list
);
863 /* on a ladder, used in goto_level */
864 static NEARDATA boolean at_ladder
= FALSE
;
866 /* the '>' command */
870 struct trap
*trap
= 0;
871 boolean stairs_down
= ((u
.ux
== xdnstair
&& u
.uy
== ydnstair
)
872 || (u
.ux
== sstairs
.sx
&& u
.uy
== sstairs
.sy
874 ladder_down
= (u
.ux
== xdnladder
&& u
.uy
== ydnladder
);
879 if (stucksteed(TRUE
)) {
882 /* Levitation might be blocked, but player can still use '>' to
883 turn off controlled levitation */
884 if (HLevitation
|| ELevitation
) {
885 if ((HLevitation
& I_SPECIAL
) || (ELevitation
& W_ARTI
)) {
886 /* end controlled levitation */
887 if (ELevitation
& W_ARTI
) {
890 for (obj
= invent
; obj
; obj
= obj
->nobj
) {
892 && artifact_has_invprop(obj
, LEVITATION
)) {
893 if (obj
->age
< monstermoves
)
894 obj
->age
= monstermoves
;
895 obj
->age
+= rnz(100);
899 if (float_down(I_SPECIAL
| TIMEOUT
, W_ARTI
)) {
900 return 1; /* came down, so moved */
901 } else if (!HLevitation
&& !ELevitation
) {
902 Your("latent levitation ceases.");
903 return 1; /* did something, effectively moved */
907 ; /* weren't actually floating after all */
909 /* Avoid alerting player to an unknown stair or ladder.
910 * Changes the message for a covered, known staircase
911 * too; staircase knowledge is not stored anywhere.
915 (glyph_to_cmap(levl
[u
.ux
][u
.uy
].glyph
) == S_dnstair
);
916 else if (ladder_down
)
918 (glyph_to_cmap(levl
[u
.ux
][u
.uy
].glyph
) == S_dnladder
);
920 if (Is_airlevel(&u
.uz
))
921 You("are floating in the %s.", surface(u
.ux
, u
.uy
));
922 else if (Is_waterlevel(&u
.uz
))
923 You("are floating in %s.",
924 is_pool(u
.ux
, u
.uy
) ? "the water" : "a bubble of air");
926 floating_above(stairs_down
? "stairs" : ladder_down
928 : surface(u
.ux
, u
.uy
));
929 return 0; /* didn't move */
931 if (!stairs_down
&& !ladder_down
) {
932 trap
= t_at(u
.ux
, u
.uy
);
933 if (trap
&& uteetering_at_seen_pit(trap
)) {
934 dotrap(trap
, TOOKPLUNGE
);
936 } else if (!trap
|| (trap
->ttyp
!= TRAPDOOR
&& trap
->ttyp
!= HOLE
)
937 || !Can_fall_thru(&u
.uz
) || !trap
->tseen
) {
938 if (flags
.autodig
&& !context
.nopick
&& uwep
&& is_pick(uwep
)) {
939 return use_pick_axe2(uwep
);
941 You_cant("go down here.");
947 You("are %s, and cannot go down.",
948 !u
.uswallow
? "being held" : is_animal(u
.ustuck
->data
)
953 if (on_level(&valley_level
, &u
.uz
) && !u
.uevent
.gehennom_entered
) {
954 You("are standing at the gate to Gehennom.");
955 pline("Unspeakable cruelty and harm lurk down there.");
956 if (yn("Are you sure you want to enter?") != 'y')
960 u
.uevent
.gehennom_entered
= 1; /* don't ask again */
964 You("are held back by your pet!");
969 You("%s %s.", Flying
? "fly" : locomotion(youmonst
.data
, "jump"),
970 trap
->ttyp
== HOLE
? "down the hole" : "through the trap door");
972 if (trap
&& Is_stronghold(&u
.uz
)) {
973 goto_hell(FALSE
, TRUE
);
975 at_ladder
= (boolean
) (levl
[u
.ux
][u
.uy
].typ
== LADDER
);
982 /* the '<' command */
989 /* "up" to get out of a pit... */
990 if (u
.utrap
&& u
.utraptype
== TT_PIT
) {
995 if ((u
.ux
!= xupstair
|| u
.uy
!= yupstair
)
996 && (!xupladder
|| u
.ux
!= xupladder
|| u
.uy
!= yupladder
)
997 && (!sstairs
.sx
|| u
.ux
!= sstairs
.sx
|| u
.uy
!= sstairs
.sy
999 You_cant("go up here.");
1002 if (stucksteed(TRUE
)) {
1006 You("are %s, and cannot go up.",
1007 !u
.uswallow
? "being held" : is_animal(u
.ustuck
->data
)
1012 if (near_capacity() > SLT_ENCUMBER
) {
1013 /* No levitation check; inv_weight() already allows for it */
1014 Your("load is too heavy to climb the %s.",
1015 levl
[u
.ux
][u
.uy
].typ
== STAIRS
? "stairs" : "ladder");
1018 if (ledger_no(&u
.uz
) == 1) {
1019 if (yn("Beware, there will be no return! Still climb?") != 'y')
1023 You("are held back by your pet!");
1026 at_ladder
= (boolean
) (levl
[u
.ux
][u
.uy
].typ
== LADDER
);
1032 d_level save_dlevel
= { 0, 0 };
1034 /* check that we can write out the current level */
1036 currentlevel_rewrite()
1041 /* since level change might be a bit slow, flush any buffered screen
1042 * output (like "you fall through a trap door") */
1045 fd
= create_levelfile(ledger_no(&u
.uz
), whynot
);
1048 * This is not quite impossible: e.g., we may have
1049 * exceeded our quota. If that is the case then we
1050 * cannot leave this level, and cannot save either.
1051 * Another possibility is that the directory was not
1059 if (!savelev(fd
, ledger_no(&u
.uz
), COUNT_SAVE
)) {
1061 delete_levelfile(ledger_no(&u
.uz
));
1062 pline("NetHack is out of disk space for making levels!");
1063 You("can save, quit, or continue playing.");
1076 if (flags
.ins_chkpt
) {
1077 /* write out just-attained level, with pets and everything */
1078 fd
= currentlevel_rewrite();
1082 savelev(fd
, ledger_no(&u
.uz
), WRITE_SAVE
);
1086 /* write out non-level state */
1094 register xchar x, y;
1096 return (boolean) ((levl[x][y].typ != ROOM
1097 && levl[x][y].typ != AIR
1098 && levl[x][y].typ != CORR)
1104 goto_level(newlevel
, at_stairs
, falling
, portal
)
1106 boolean at_stairs
, falling
, portal
;
1110 boolean cant_go_back
, great_effort
,
1111 up
= (depth(newlevel
) < depth(&u
.uz
)),
1112 newdungeon
= (u
.uz
.dnum
!= newlevel
->dnum
),
1113 was_in_W_tower
= In_W_tower(u
.ux
, u
.uy
, &u
.uz
),
1115 new = FALSE
; /* made a new level? */
1120 if (dunlev(newlevel
) > dunlevs_in_dungeon(newlevel
))
1121 newlevel
->dlevel
= dunlevs_in_dungeon(newlevel
);
1122 if (newdungeon
&& In_endgame(newlevel
)) { /* 1st Endgame Level !!! */
1123 if (!u
.uhave
.amulet
)
1124 return; /* must have the Amulet */
1125 if (!wizard
) /* wizard ^V can bypass Earth level */
1126 assign_level(newlevel
, &earth_level
); /* (redundant) */
1128 new_ledger
= ledger_no(newlevel
);
1129 if (new_ledger
<= 0)
1130 done(ESCAPED
); /* in fact < 0 is impossible */
1132 /* If you have the amulet and are trying to get out of Gehennom,
1133 * going up a set of stairs sometimes does some very strange things!
1134 * Biased against law and towards chaos. (The chance to be sent
1135 * down multiple levels when attempting to go up are significantly
1136 * less than the corresponding comment in older versions indicated
1137 * due to overlooking the effect of the call to assign_rnd_lvl().)
1139 * Odds for making it to the next level up, or of being sent down:
1143 * -1 11.46 12.50 12.5
1147 if (Inhell
&& up
&& u
.uhave
.amulet
&& !newdungeon
&& !portal
1148 && (dunlev(&u
.uz
) < dunlevs_in_dungeon(&u
.uz
) - 3)) {
1150 int odds
= 3 + (int) u
.ualign
.type
, /* 2..4 */
1151 diff
= odds
<= 1 ? 0 : rn2(odds
); /* paranoia */
1154 assign_rnd_level(newlevel
, &u
.uz
, diff
);
1155 /* if inside the tower, stay inside */
1156 if (was_in_W_tower
&& !On_W_tower_level(newlevel
))
1160 assign_level(newlevel
, &u
.uz
);
1162 new_ledger
= ledger_no(newlevel
);
1164 pline("A mysterious force momentarily surrounds you...");
1165 if (on_level(newlevel
, &u
.uz
)) {
1166 (void) safe_teleds(FALSE
);
1170 at_stairs
= at_ladder
= FALSE
;
1174 /* Prevent the player from going past the first quest level unless
1175 * (s)he has been given the go-ahead by the leader.
1177 if (on_level(&u
.uz
, &qstart_level
) && !newdungeon
&& !ok_to_quest()) {
1178 pline("A mysterious force prevents you from descending.");
1182 if (on_level(newlevel
, &u
.uz
))
1183 return; /* this can happen */
1185 /* tethered movement makes level change while trapped feasible */
1186 if (u
.utrap
&& u
.utraptype
== TT_BURIEDBALL
)
1187 buried_ball_to_punishment(); /* (before we save/leave old level) */
1189 fd
= currentlevel_rewrite();
1193 if (falling
) /* assuming this is only trap door or hole */
1194 impact_drop((struct obj
*) 0, u
.ux
, u
.uy
, newlevel
->dlevel
);
1196 check_special_room(TRUE
); /* probably was a trap door */
1199 u
.utrap
= 0; /* needed in level_tele */
1200 fill_pit(u
.ux
, u
.uy
);
1201 u
.ustuck
= 0; /* idem */
1203 u
.uundetected
= 0; /* not hidden, even if means are available */
1205 if (u
.uswallow
) /* idem */
1206 u
.uswldtim
= u
.uswallow
= 0;
1207 recalc_mapseen(); /* recalculate map overview before we leave the level */
1209 * We no longer see anything on the level. Make sure that this
1210 * follows u.uswallow set to null since uswallow overrides all
1216 * Save the level we're leaving. If we're entering the endgame,
1217 * we can get rid of all existing levels because they cannot be
1218 * reached any more. We still need to use savelev()'s cleanup
1219 * for the level being left, to recover dynamic memory in use and
1220 * to avoid dangling timers and light sources.
1222 cant_go_back
= (newdungeon
&& In_endgame(newlevel
));
1223 if (!cant_go_back
) {
1224 update_mlstmv(); /* current monsters are becoming inactive */
1225 bufon(fd
); /* use buffered output */
1227 savelev(fd
, ledger_no(&u
.uz
),
1228 cant_go_back
? FREE_SAVE
: (WRITE_SAVE
| FREE_SAVE
));
1231 /* discard unreachable levels; keep #0 */
1232 for (l_idx
= maxledgerno(); l_idx
> 0; --l_idx
)
1233 delete_levelfile(l_idx
);
1234 /* mark #overview data for all dungeon branches as uninteresting */
1235 for (l_idx
= 0; l_idx
< n_dgns
; ++l_idx
)
1236 remdun_mapseen(l_idx
);
1239 if (Is_rogue_level(newlevel
) || Is_rogue_level(&u
.uz
))
1240 assign_graphics(Is_rogue_level(newlevel
) ? ROGUESET
: PRIMARY
);
1242 substitute_tiles(newlevel
);
1244 /* record this level transition as a potential seen branch unless using
1245 * some non-standard means of transportation (level teleport).
1247 if ((at_stairs
|| falling
|| portal
) && (u
.uz
.dnum
!= newlevel
->dnum
))
1248 recbranch_mapseen(&u
.uz
, newlevel
);
1249 assign_level(&u
.uz0
, &u
.uz
);
1250 assign_level(&u
.uz
, newlevel
);
1251 assign_level(&u
.utolev
, newlevel
);
1253 if (!builds_up(&u
.uz
)) { /* usual case */
1254 if (dunlev(&u
.uz
) > dunlev_reached(&u
.uz
))
1255 dunlev_reached(&u
.uz
) = dunlev(&u
.uz
);
1257 if (dunlev_reached(&u
.uz
) == 0
1258 || dunlev(&u
.uz
) < dunlev_reached(&u
.uz
))
1259 dunlev_reached(&u
.uz
) = dunlev(&u
.uz
);
1261 reset_rndmonst(NON_PM
); /* u.uz change affects monster generation */
1263 /* set default level change destination areas */
1264 /* the special level code may override these */
1265 (void) memset((genericptr_t
) &updest
, 0, sizeof updest
);
1266 (void) memset((genericptr_t
) &dndest
, 0, sizeof dndest
);
1268 if (!(level_info
[new_ledger
].flags
& LFILE_EXISTS
)) {
1269 /* entering this level for first time; make it now */
1270 if (level_info
[new_ledger
].flags
& (FORGOTTEN
| VISITED
)) {
1271 impossible("goto_level: returning to discarded level?");
1272 level_info
[new_ledger
].flags
&= ~(FORGOTTEN
| VISITED
);
1275 new = TRUE
; /* made the level */
1277 /* returning to previously visited level; reload it */
1278 fd
= open_levelfile(new_ledger
, whynot
);
1279 if (tricked_fileremoved(fd
, whynot
)) {
1280 /* we'll reach here if running in wizard mode */
1281 error("Cannot continue this game.");
1283 minit(); /* ZEROCOMP */
1284 getlev(fd
, hackpid
, new_ledger
, FALSE
);
1286 oinit(); /* reassign level dependent obj probabilities */
1289 /* do this prior to level-change pline messages */
1290 vision_reset(); /* clear old level's line-of-sight */
1291 vision_full_recalc
= 0; /* don't let that reenable vision yet */
1292 flush_screen(-1); /* ensure all map flushes are postponed */
1294 if (portal
&& !In_endgame(&u
.uz
)) {
1295 /* find the portal on the new level */
1296 register struct trap
*ttrap
;
1298 for (ttrap
= ftrap
; ttrap
; ttrap
= ttrap
->ntrap
)
1299 if (ttrap
->ttyp
== MAGIC_PORTAL
)
1303 panic("goto_level: no corresponding portal!");
1305 u_on_newpos(ttrap
->tx
, ttrap
->ty
);
1306 } else if (at_stairs
&& !In_endgame(&u
.uz
)) {
1309 u_on_newpos(xdnladder
, ydnladder
);
1310 else if (newdungeon
)
1314 /* you climb up the {stairs|ladder};
1315 fly up the stairs; fly up along the ladder */
1316 great_effort
= (Punished
&& !Levitation
);
1317 if (flags
.verbose
|| great_effort
)
1318 pline("%s %s up%s the %s.",
1319 great_effort
? "With great effort, you" : "You",
1320 Flying
? "fly" : "climb",
1321 (Flying
&& at_ladder
) ? " along" : "",
1322 at_ladder
? "ladder" : "stairs");
1325 u_on_newpos(xupladder
, yupladder
);
1326 else if (newdungeon
)
1331 ; /* stayed on same level? (no transit effects) */
1332 } else if (Flying
) {
1335 at_ladder
? "along the ladder" : "the stairs");
1336 } else if (near_capacity() > UNENCUMBERED
1337 || Punished
|| Fumbling
) {
1338 You("fall down the %s.", at_ladder
? "ladder" : "stairs");
1343 /* falling off steed has its own losehp() call */
1345 dismount_steed(DISMOUNT_FELL
);
1347 losehp(Maybe_Half_Phys(rnd(3)),
1348 at_ladder
? "falling off a ladder"
1349 : "tumbling down a flight of stairs",
1351 selftouch("Falling, you");
1352 } else { /* ordinary descent */
1354 You("%s.", at_ladder
? "climb down the ladder"
1355 : "descend the stairs");
1358 } else { /* trap door or level_tele or In_endgame */
1359 u_on_rndspot((up
? 1 : 0) | (was_in_W_tower
? 2 : 0));
1363 selftouch("Falling, you");
1369 obj_delivery(FALSE
);
1371 kill_genocided_monsters(); /* for those wiped out while in limbo */
1373 * Expire all timers that have gone off while away. Must be
1374 * after migrating monsters and objects are delivered
1375 * (losedogs and obj_delivery).
1381 if ((mtmp
= m_at(u
.ux
, u
.uy
)) != 0 && mtmp
!= u
.usteed
) {
1382 /* There's a monster at your target destination; it might be one
1383 which accompanied you--see mon_arrive(dogmove.c)--or perhaps
1384 it was already here. Randomly move you to an adjacent spot
1385 or else the monster to any nearby location. Prior to 3.3.0
1386 the latter was done unconditionally. */
1389 if (!rn2(2) && enexto(&cc
, u
.ux
, u
.uy
, youmonst
.data
)
1390 && distu(cc
.x
, cc
.y
) <= 2)
1391 u_on_newpos(cc
.x
, cc
.y
); /*[maybe give message here?]*/
1395 if ((mtmp
= m_at(u
.ux
, u
.uy
)) != 0) {
1396 /* there was an unconditional impossible("mnearto failed")
1397 here, but it's not impossible and we're prepared to cope
1398 with the situation, so only say something when debugging */
1400 pline("(monster in hero's way)");
1401 if (!rloc(mtmp
, TRUE
))
1402 /* no room to move it; send it away, to return later */
1403 migrate_to_level(mtmp
, ledger_no(&u
.uz
), MIGR_RANDOM
,
1408 /* initial movement of bubbles just before vision_recalc */
1409 if (Is_waterlevel(&u
.uz
) || Is_airlevel(&u
.uz
))
1411 else if (Is_firelevel(&u
.uz
))
1414 if (level_info
[new_ledger
].flags
& FORGOTTEN
) {
1415 forget_map(ALL_MAP
); /* forget the map */
1416 forget_traps(); /* forget all traps too */
1418 level_info
[new_ledger
].flags
&= ~FORGOTTEN
;
1421 /* Reset the screen. */
1422 vision_reset(); /* reset the blockages */
1423 docrt(); /* does a full vision recalc */
1427 * Move all plines beyond the screen reset.
1430 /* special levels can have a custom arrival message */
1431 deliver_splev_message();
1433 /* give room entrance message, if any */
1434 check_special_room(FALSE
);
1436 /* deliver objects traveling with player */
1439 /* Check whether we just entered Gehennom. */
1440 if (!In_hell(&u
.uz0
) && Inhell
) {
1441 if (Is_valley(&u
.uz
)) {
1442 You("arrive at the Valley of the Dead...");
1443 pline_The("odor of burnt flesh and decay pervades the air.");
1445 display_nhwindow(WIN_MESSAGE
, FALSE
);
1447 You_hear("groans and moans everywhere.");
1449 pline("It is hot here. You smell smoke...");
1450 u
.uachieve
.enter_gehennom
= 1;
1452 /* in case we've managed to bypass the Valley's stairway down */
1453 if (Inhell
&& !Is_valley(&u
.uz
))
1454 u
.uevent
.gehennom_entered
= 1;
1457 static const char *const fam_msgs
[4] = {
1458 "You have a sense of deja vu.",
1459 "You feel like you've been here before.",
1460 "This place %s familiar...", 0 /* no message */
1462 static const char *const halu_fam_msgs
[4] = {
1463 "Whoa! Everything %s different.",
1464 "You are surrounded by twisty little passages, all alike.",
1465 "Gee, this %s like uncle Conan's place...", 0 /* no message */
1472 mesg
= halu_fam_msgs
[which
];
1474 mesg
= fam_msgs
[which
];
1475 if (mesg
&& index(mesg
, '%')) {
1476 Sprintf(buf
, mesg
, !Blind
? "looks" : "seems");
1483 /* special location arrival messages/events */
1484 if (In_endgame(&u
.uz
)) {
1485 if (new &&on_level(&u
.uz
, &astral_level
))
1486 final_level(); /* guardian angel,&c */
1487 else if (newdungeon
&& u
.uhave
.amulet
)
1488 resurrect(); /* force confrontation with Wizard */
1489 } else if (In_quest(&u
.uz
)) {
1490 onquest(); /* might be reaching locate|goal level */
1491 } else if (In_V_tower(&u
.uz
)) {
1492 if (newdungeon
&& In_hell(&u
.uz0
))
1493 pline_The("heat and smoke are gone.");
1494 } else if (Is_knox(&u
.uz
)) {
1495 /* alarm stops working once Croesus has died */
1496 if (new || !mvitals
[PM_CROESUS
].died
) {
1497 You("have penetrated a high security area!");
1498 pline("An alarm sounds!");
1499 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
) {
1500 if (DEADMONSTER(mtmp
))
1502 mtmp
->msleeping
= 0;
1506 if (new && Is_rogue_level(&u
.uz
))
1507 You("enter what seems to be an older, more primitive world.");
1508 /* main dungeon message from your quest leader */
1509 if (!In_quest(&u
.uz0
) && at_dgn_entrance("The Quest")
1510 && !(u
.uevent
.qcompleted
|| u
.uevent
.qexpelled
1511 || quest_status
.leader_is_dead
)) {
1512 if (!u
.uevent
.qcalled
) {
1513 u
.uevent
.qcalled
= 1;
1514 com_pager(2); /* main "leader needs help" message */
1515 } else { /* reminder message */
1516 com_pager(Role_if(PM_ROGUE
) ? 4 : 3);
1521 assign_level(&u
.uz0
, &u
.uz
); /* reset u.uz0 */
1523 save_currentstate();
1526 if ((annotation
= get_annotation(&u
.uz
)))
1527 You("remember this level as %s.", annotation
);
1529 /* assume this will always return TRUE when changing level */
1530 (void) in_out_region(u
.ux
, u
.uy
);
1532 context
.polearm
.hitmon
= NULL
;
1540 /* reset monster hostility relative to player */
1541 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
) {
1542 if (DEADMONSTER(mtmp
))
1544 reset_hostility(mtmp
);
1547 /* create some player-monsters */
1548 create_mplayers(rn1(4, 3), TRUE
);
1550 /* create a guardian angel next to player, if worthy */
1551 gain_guardian_angel();
1554 static char *dfr_pre_msg
= 0, /* pline() before level change */
1555 *dfr_post_msg
= 0; /* pline() after level change */
1557 /* change levels at the end of this turn, after monsters finish moving */
1559 schedule_goto(tolev
, at_stairs
, falling
, portal_flag
, pre_msg
, post_msg
)
1561 boolean at_stairs
, falling
;
1563 const char *pre_msg
, *post_msg
;
1565 int typmask
= 0100; /* non-zero triggers `deferred_goto' */
1567 /* destination flags (`goto_level' args) */
1574 if (portal_flag
< 0)
1575 typmask
|= 0200; /* flag for portal removal */
1576 u
.utotype
= typmask
;
1577 /* destination level */
1578 assign_level(&u
.utolev
, tolev
);
1581 dfr_pre_msg
= dupstr(pre_msg
);
1583 dfr_post_msg
= dupstr(post_msg
);
1586 /* handle something like portal ejection */
1590 if (!on_level(&u
.uz
, &u
.utolev
)) {
1592 int typmask
= u
.utotype
; /* save it; goto_level zeroes u.utotype */
1594 assign_level(&dest
, &u
.utolev
);
1596 pline1(dfr_pre_msg
);
1597 goto_level(&dest
, !!(typmask
& 1), !!(typmask
& 2), !!(typmask
& 4));
1598 if (typmask
& 0200) { /* remove portal */
1599 struct trap
*t
= t_at(u
.ux
, u
.uy
);
1607 pline1(dfr_post_msg
);
1609 u
.utotype
= 0; /* our caller keys off of this */
1611 free((genericptr_t
) dfr_pre_msg
), dfr_pre_msg
= 0;
1613 free((genericptr_t
) dfr_post_msg
), dfr_post_msg
= 0;
1617 * Return TRUE if we created a monster for the corpse. If successful, the
1621 revive_corpse(corpse
)
1624 struct monst
*mtmp
, *mcarry
;
1625 boolean is_uwep
, chewed
;
1628 struct obj
*container
= (struct obj
*) 0;
1629 int container_where
= 0;
1631 where
= corpse
->where
;
1632 is_uwep
= (corpse
== uwep
);
1633 chewed
= (corpse
->oeaten
!= 0);
1635 corpse_xname(corpse
, chewed
? "bite-covered" : (const char *) 0,
1637 mcarry
= (where
== OBJ_MINVENT
) ? corpse
->ocarry
: 0;
1639 if (where
== OBJ_CONTAINED
) {
1640 struct monst
*mtmp2
;
1642 container
= corpse
->ocontainer
;
1644 get_container_location(container
, &container_where
, (int *) 0);
1645 /* container_where is the outermost container's location even if
1647 if (container_where
== OBJ_MINVENT
&& mtmp2
)
1650 mtmp
= revive(corpse
, FALSE
); /* corpse is gone if successful */
1656 pline_The("%s writhes out of your grasp!", cname
);
1658 You_feel("squirming in your backpack!");
1662 if (cansee(mtmp
->mx
, mtmp
->my
))
1663 pline("%s rises from the dead!",
1664 chewed
? Adjmonnam(mtmp
, "bite-covered")
1668 case OBJ_MINVENT
: /* probably a nymph's */
1669 if (cansee(mtmp
->mx
, mtmp
->my
)) {
1670 if (canseemon(mcarry
))
1671 pline("Startled, %s drops %s as it revives!",
1672 mon_nam(mcarry
), an(cname
));
1674 pline("%s suddenly appears!",
1675 chewed
? Adjmonnam(mtmp
, "bite-covered")
1679 case OBJ_CONTAINED
: {
1680 char sackname
[BUFSZ
];
1682 if (container_where
== OBJ_MINVENT
&& cansee(mtmp
->mx
, mtmp
->my
)
1683 && mcarry
&& canseemon(mcarry
) && container
) {
1684 pline("%s writhes out of %s!", Amonnam(mtmp
),
1686 } else if (container_where
== OBJ_INVENT
&& container
) {
1687 Strcpy(sackname
, an(xname(container
)));
1688 pline("%s %s out of %s in your pack!",
1689 Blind
? Something
: Amonnam(mtmp
),
1690 locomotion(mtmp
->data
, "writhes"), sackname
);
1691 } else if (container_where
== OBJ_FLOOR
&& container
1692 && cansee(mtmp
->mx
, mtmp
->my
)) {
1693 Strcpy(sackname
, an(xname(container
)));
1694 pline("%s escapes from %s!", Amonnam(mtmp
), sackname
);
1699 /* we should be able to handle the other cases... */
1700 impossible("revive_corpse: lost corpse @ %d", where
);
1708 /* Revive the corpse via a timeout. */
1711 revive_mon(arg
, timeout
)
1713 long timeout UNUSED
;
1715 struct obj
*body
= arg
->a_obj
;
1716 struct permonst
*mptr
= &mons
[body
->corpsenm
];
1720 /* corpse will revive somewhere else if there is a monster in the way;
1721 Riders get a chance to try to bump the obstacle out of their way */
1722 if ((mptr
->mflags3
& M3_DISPLACES
) != 0 && body
->where
== OBJ_FLOOR
1723 && get_obj_location(body
, &x
, &y
, 0) && (mtmp
= m_at(x
, y
)) != 0) {
1724 boolean notice_it
= canseemon(mtmp
); /* before rloc() */
1725 char *monname
= Monnam(mtmp
);
1727 if (rloc(mtmp
, TRUE
)) {
1728 if (notice_it
&& !canseemon(mtmp
))
1729 pline("%s vanishes.", monname
);
1730 else if (!notice_it
&& canseemon(mtmp
))
1731 pline("%s appears.", Monnam(mtmp
)); /* not pre-rloc monname */
1732 else if (notice_it
&& dist2(mtmp
->mx
, mtmp
->my
, x
, y
) > 2)
1733 pline("%s teleports.", monname
); /* saw it and still see it */
1737 /* if we succeed, the corpse is gone */
1738 if (!revive_corpse(body
)) {
1742 if (is_rider(mptr
) && rn2(99)) { /* Rider usually tries again */
1743 action
= REVIVE_MON
;
1744 for (when
= 3L; when
< 67L; when
++)
1747 } else { /* rot this corpse away */
1748 You_feel("%sless hassled.", is_rider(mptr
) ? "much " : "");
1749 action
= ROT_CORPSE
;
1750 when
= 250L - (monstermoves
- body
->age
);
1754 (void) start_timer(when
, TIMER_OBJECT
, action
, arg
);
1761 return 1; /* Do nothing, but let other things happen */
1776 pline("You've got the glop off.");
1778 if (!gulp_blnd_check()) {
1780 make_blinded(0L, TRUE
);
1783 } else if (!u
.ucreamed
) {
1784 Your("%s feels clean now.", body_part(FACE
));
1787 return 1; /* still busy */
1794 static NEARDATA
char buf
[39];
1796 Sprintf(buf
, "wiping off your %s", body_part(FACE
));
1797 set_occupation(wipeoff
, buf
, 0);
1798 /* Not totally correct; what if they change back after now
1799 * but before they're finished wiping?
1803 Your("%s is already clean.", body_part(FACE
));
1808 set_wounded_legs(side
, timex
)
1813 * If you are riding, your steed gets the wounded legs instead.
1814 * You still call this function, but don't lose hp.
1815 * Caller is also responsible for adjusting messages.
1818 if (!Wounded_legs
) {
1823 if (!Wounded_legs
|| (HWounded_legs
& TIMEOUT
))
1824 HWounded_legs
= timex
;
1825 EWounded_legs
= side
;
1826 (void) encumber_msg();
1833 if (ATEMP(A_DEX
) < 0) {
1839 const char *legs
= body_part(LEG
);
1841 if ((EWounded_legs
& BOTH_SIDES
) == BOTH_SIDES
)
1842 legs
= makeplural(legs
);
1843 /* this used to say "somewhat better" but that was
1844 misleading since legs are being fully healed */
1845 Your("%s %s better.", legs
, vtense(legs
, "feel"));
1848 HWounded_legs
= EWounded_legs
= 0;
1850 /* Wounded_legs reduces carrying capacity, so we want
1851 an encumbrance check when they're healed. However,
1852 while dismounting, first steed's legs get healed,
1853 then hero is dropped to floor and a new encumbrance
1854 check is made [in dismount_steed()]. So don't give
1855 encumbrance feedback during the dismount stage
1856 because it could seem to be shown out of order and
1857 it might be immediately contradicted [able to carry
1858 more when steed becomes healthy, then possible floor
1859 feedback, then able to carry less when back on foot]. */
1860 if (!in_steed_dismounting
)
1861 (void) encumber_msg();