cmdhelp revamp
[aNetHack.git] / src / do.c
blob94ef36ee3bc917cfea2019a201ef5429e4a3de09
1 /* NetHack 3.6 do.c $NHDT-Date: 1464487100 2016/05/29 01:58:20 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.156 $ */
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) */
7 #include "hack.h"
8 #include "lev.h"
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,
24 ALL_CLASSES, 0 };
26 /* 'd' command: drop one inventory item */
27 int
28 dodrop()
30 int result, i = (invent) ? 0 : (SIZE(drop_types) - 1);
32 if (*u.ushops)
33 sellobj_state(SELL_DELIBERATE);
34 result = drop(getobj(&drop_types[i], "drop"));
35 if (*u.ushops)
36 sellobj_state(SELL_NORMAL);
37 reset_occupations();
39 return result;
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.
46 boolean
47 boulder_hits_pool(otmp, rx, ry, pushing)
48 struct obj *otmp;
49 register int rx, ry;
50 boolean 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;
61 if (fills_up) {
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;
67 } else
68 levl[rx][ry].typ = ROOM;
70 if (ttmp)
71 (void) delfloortrap(ttmp);
72 bury_objs(rx, ry);
74 newsym(rx, ry);
75 if (pushing) {
76 char whobuf[BUFSZ];
78 Strcpy(whobuf, "you");
79 if (u.usteed)
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 */
89 if (!u.uinwater) {
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",
93 what);
94 } else if (!Deaf)
95 You_hear("a%s splash.", lava ? " sizzling" : "");
96 wake_nearto(rx, ry, 40);
99 if (fills_up && u.uinwater && distu(rx, ry) == 0) {
100 u.uinwater = 0;
101 docrt();
102 vision_full_recalc = 1;
103 You("find yourself on dry land again!");
104 } else if (lava && distu(rx, ry) <= 2) {
105 int dmg;
106 You("are hit by molten %s%c",
107 hliquid("lava"), Fire_resistance ? '.' : '!');
108 burn_away_slime();
109 dmg = d((Fire_resistance ? 1 : 3), 6);
110 losehp(Maybe_Half_Phys(dmg), /* lava damage */
111 "molten lava", KILLED_BY);
112 } else if (!fills_up && flags.verbose
113 && (pushing ? !Blind : cansee(rx, ry)))
114 pline("It sinks without a trace!");
117 /* boulder is now gone */
118 if (pushing)
119 delobj(otmp);
120 else
121 obfree(otmp, (struct obj *) 0);
122 return TRUE;
124 return FALSE;
127 /* Used for objects which sometimes do special things when dropped; must be
128 * called with the object not in any chain. Returns TRUE if the object goes
129 * away.
131 boolean
132 flooreffects(obj, x, y, verb)
133 struct obj *obj;
134 int x, y;
135 const char *verb;
137 struct trap *t;
138 struct monst *mtmp;
139 struct obj *otmp;
141 if (obj->where != OBJ_FREE)
142 panic("flooreffects: obj not free");
144 /* make sure things like water_damage() have no pointers to follow */
145 obj->nobj = obj->nexthere = (struct obj *) 0;
147 if (obj->otyp == BOULDER && boulder_hits_pool(obj, x, y, FALSE)) {
148 return TRUE;
149 } else if (obj->otyp == BOULDER && (t = t_at(x, y)) != 0
150 && (t->ttyp == PIT || t->ttyp == SPIKED_PIT
151 || t->ttyp == TRAPDOOR || t->ttyp == HOLE)) {
152 if (((mtmp = m_at(x, y)) && mtmp->mtrapped)
153 || (u.utrap && u.ux == x && u.uy == y)) {
154 if (*verb)
155 pline_The("boulder %s into the pit%s.",
156 vtense((const char *) 0, verb),
157 (mtmp) ? "" : " with you");
158 if (mtmp) {
159 if (!passes_walls(mtmp->data) && !throws_rocks(mtmp->data)) {
160 if (hmon(mtmp, obj, TRUE) && !is_whirly(mtmp->data))
161 return FALSE; /* still alive */
163 mtmp->mtrapped = 0;
164 } else {
165 if (!Passes_walls && !throws_rocks(youmonst.data)) {
166 losehp(Maybe_Half_Phys(rnd(15)),
167 "squished under a boulder", NO_KILLER_PREFIX);
168 return FALSE; /* player remains trapped */
169 } else
170 u.utrap = 0;
173 if (*verb) {
174 if (Blind && (x == u.ux) && (y == u.uy)) {
175 You_hear("a CRASH! beneath you.");
176 } else if (!Blind && cansee(x, y)) {
177 pline_The("boulder %s%s.", t->tseen ? "" : "triggers and ",
178 t->ttyp == TRAPDOOR
179 ? "plugs a trap door"
180 : t->ttyp == HOLE ? "plugs a hole"
181 : "fills a pit");
182 } else {
183 You_hear("a boulder %s.", verb);
186 deltrap(t);
187 useupf(obj, 1L);
188 bury_objs(x, y);
189 newsym(x, y);
190 return TRUE;
191 } else if (is_lava(x, y)) {
192 return fire_damage(obj, FALSE, x, y);
193 } else if (is_pool(x, y)) {
194 /* Reasonably bulky objects (arbitrary) splash when dropped.
195 * If you're floating above the water even small things make
196 * noise. Stuff dropped near fountains always misses */
197 if ((Blind || (Levitation || Flying)) && !Deaf
198 && ((x == u.ux) && (y == u.uy))) {
199 if (!Underwater) {
200 if (weight(obj) > 9) {
201 pline("Splash!");
202 } else if (Levitation || Flying) {
203 pline("Plop!");
206 map_background(x, y, 0);
207 newsym(x, y);
209 return water_damage(obj, NULL, FALSE) == ER_DESTROYED;
210 } else if (u.ux == x && u.uy == y && (t = t_at(x, y)) != 0
211 && uteetering_at_seen_pit(t)) {
212 if (Blind && !Deaf)
213 You_hear("%s tumble downwards.", the(xname(obj)));
214 else
215 pline("%s %s into %s pit.", The(xname(obj)),
216 otense(obj, "tumble"), the_your[t->madeby_u]);
217 } else if (obj->globby) {
218 /* Globby things like puddings might stick together */
219 while (obj && (otmp = obj_nexto_xy(obj, x, y, TRUE)) != 0) {
220 pudding_merge_message(obj, otmp);
221 /* intentionally not getting the melded object; obj_meld may set
222 * obj to null. */
223 (void) obj_meld(&obj, &otmp);
225 return (boolean) !obj;
227 return FALSE;
230 /* obj is an object dropped on an altar */
231 void
232 doaltarobj(obj)
233 register struct obj *obj;
235 if (Blind)
236 return;
238 if (obj->oclass != COIN_CLASS) {
239 /* KMH, conduct */
240 u.uconduct.gnostic++;
241 } else {
242 /* coins don't have bless/curse status */
243 obj->blessed = obj->cursed = 0;
246 if (obj->blessed || obj->cursed) {
247 There("is %s flash as %s %s the altar.",
248 an(hcolor(obj->blessed ? NH_AMBER : NH_BLACK)), doname(obj),
249 otense(obj, "hit"));
250 if (!Hallucination)
251 obj->bknown = 1;
252 } else {
253 pline("%s %s on the altar.", Doname2(obj), otense(obj, "land"));
254 if (obj->oclass != COIN_CLASS)
255 obj->bknown = 1;
259 STATIC_OVL void
260 trycall(obj)
261 register struct obj *obj;
263 if (!objects[obj->otyp].oc_name_known && !objects[obj->otyp].oc_uname)
264 docall(obj);
267 /* Transforms the sink at the player's position into
268 a fountain, throne, altar or grave. */
269 STATIC_DCL void
270 polymorph_sink()
272 uchar sym = S_sink;
274 if (levl[u.ux][u.uy].typ != SINK)
275 return;
277 level.flags.nsinks--;
278 levl[u.ux][u.uy].doormask = 0;
279 switch (rn2(4)) {
280 default:
281 case 0:
282 sym = S_fountain;
283 levl[u.ux][u.uy].typ = FOUNTAIN;
284 level.flags.nfountains++;
285 break;
286 case 1:
287 sym = S_throne;
288 levl[u.ux][u.uy].typ = THRONE;
289 break;
290 case 2:
291 sym = S_altar;
292 levl[u.ux][u.uy].typ = ALTAR;
293 levl[u.ux][u.uy].altarmask = Align2amask(rn2((int) A_LAWFUL + 2) - 1);
294 break;
295 case 3:
296 sym = S_room;
297 levl[u.ux][u.uy].typ = ROOM;
298 make_grave(u.ux, u.uy, (char *) 0);
299 if (levl[u.ux][u.uy].typ == GRAVE)
300 sym = S_grave;
301 break;
303 /* give message even if blind; we know we're not levitating,
304 so can feel the outcome even if we can't directly see it */
305 if (levl[u.ux][u.uy].typ != ROOM)
306 pline_The("sink transforms into %s!", an(defsyms[sym].explanation));
307 else
308 pline_The("sink vanishes.");
309 newsym(u.ux, u.uy);
312 /* Teleports the sink at the player's position;
313 return True if sink teleported. */
314 STATIC_DCL boolean
315 teleport_sink()
317 int cx, cy;
318 int cnt = 0;
319 struct trap *trp;
320 struct engr *eng;
322 do {
323 cx = rnd(COLNO - 1);
324 cy = rn2(ROWNO);
325 trp = t_at(cx, cy);
326 eng = engr_at(cx, cy);
327 } while ((levl[cx][cy].typ != ROOM || trp || eng || cansee(cx, cy))
328 && cnt++ < 200);
330 if (levl[cx][cy].typ == ROOM && !trp && !eng) {
331 /* create sink at new position */
332 levl[cx][cy].typ = SINK;
333 levl[cx][cy].looted = levl[u.ux][u.uy].looted;
334 newsym(cx, cy);
335 /* remove old sink */
336 levl[u.ux][u.uy].typ = ROOM;
337 levl[u.ux][u.uy].looted = 0;
338 newsym(u.ux, u.uy);
339 return TRUE;
341 return FALSE;
344 /* obj is a ring being dropped over a kitchen sink */
345 STATIC_OVL void
346 dosinkring(obj)
347 register struct obj *obj;
349 struct obj *otmp, *otmp2;
350 boolean ideed = TRUE;
351 boolean nosink = FALSE;
353 You("drop %s down the drain.", doname(obj));
354 obj->in_use = TRUE; /* block free identification via interrupt */
355 switch (obj->otyp) { /* effects that can be noticed without eyes */
356 case RIN_SEARCHING:
357 You("thought %s got lost in the sink, but there it is!", yname(obj));
358 goto giveback;
359 case RIN_SLOW_DIGESTION:
360 pline_The("ring is regurgitated!");
361 giveback:
362 obj->in_use = FALSE;
363 dropx(obj);
364 trycall(obj);
365 return;
366 case RIN_LEVITATION:
367 pline_The("sink quivers upward for a moment.");
368 break;
369 case RIN_POISON_RESISTANCE:
370 You("smell rotten %s.", makeplural(fruitname(FALSE)));
371 break;
372 case RIN_AGGRAVATE_MONSTER:
373 pline("Several %s buzz angrily around the sink.",
374 Hallucination ? makeplural(rndmonnam(NULL)) : "flies");
375 break;
376 case RIN_SHOCK_RESISTANCE:
377 pline("Static electricity surrounds the sink.");
378 break;
379 case RIN_CONFLICT:
380 You_hear("loud noises coming from the drain.");
381 break;
382 case RIN_SUSTAIN_ABILITY: /* KMH */
383 pline_The("%s flow seems fixed.", hliquid("water"));
384 break;
385 case RIN_GAIN_STRENGTH:
386 pline_The("%s flow seems %ser now.",
387 hliquid("water"),
388 (obj->spe < 0) ? "weak" : "strong");
389 break;
390 case RIN_GAIN_CONSTITUTION:
391 pline_The("%s flow seems %ser now.",
392 hliquid("water"),
393 (obj->spe < 0) ? "less" : "great");
394 break;
395 case RIN_INCREASE_ACCURACY: /* KMH */
396 pline_The("%s flow %s the drain.",
397 hliquid("water"),
398 (obj->spe < 0) ? "misses" : "hits");
399 break;
400 case RIN_INCREASE_DAMAGE:
401 pline_The("water's force seems %ser now.",
402 (obj->spe < 0) ? "small" : "great");
403 break;
404 case RIN_HUNGER:
405 ideed = FALSE;
406 for (otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp2) {
407 otmp2 = otmp->nexthere;
408 if (otmp != uball && otmp != uchain
409 && !obj_resists(otmp, 1, 99)) {
410 if (!Blind) {
411 pline("Suddenly, %s %s from the sink!", doname(otmp),
412 otense(otmp, "vanish"));
413 ideed = TRUE;
415 delobj(otmp);
418 break;
419 case MEAT_RING:
420 /* Not the same as aggravate monster; besides, it's obvious. */
421 pline("Several flies buzz around the sink.");
422 break;
423 case RIN_TELEPORTATION:
424 nosink = teleport_sink();
425 /* give message even if blind; we know we're not levitating,
426 so can feel the outcome even if we can't directly see it */
427 pline_The("sink %svanishes.", nosink ? "" : "momentarily ");
428 ideed = FALSE;
429 break;
430 case RIN_POLYMORPH:
431 polymorph_sink();
432 nosink = TRUE;
433 /* for S_room case, same message as for teleportation is given */
434 ideed = (levl[u.ux][u.uy].typ != ROOM);
435 break;
436 default:
437 ideed = FALSE;
438 break;
440 if (!Blind && !ideed) {
441 ideed = TRUE;
442 switch (obj->otyp) { /* effects that need eyes */
443 case RIN_ADORNMENT:
444 pline_The("faucets flash brightly for a moment.");
445 break;
446 case RIN_REGENERATION:
447 pline_The("sink looks as good as new.");
448 break;
449 case RIN_INVISIBILITY:
450 You("don't see anything happen to the sink.");
451 break;
452 case RIN_FREE_ACTION:
453 You_see("the ring slide right down the drain!");
454 break;
455 case RIN_SEE_INVISIBLE:
456 You_see("some %s in the sink.",
457 Hallucination ? "oxygen molecules" : "air");
458 break;
459 case RIN_STEALTH:
460 pline_The("sink seems to blend into the floor for a moment.");
461 break;
462 case RIN_FIRE_RESISTANCE:
463 pline_The("hot %s faucet flashes brightly for a moment.",
464 hliquid("water"));
465 break;
466 case RIN_COLD_RESISTANCE:
467 pline_The("cold %s faucet flashes brightly for a moment.",
468 hliquid("water"));
469 break;
470 case RIN_PROTECTION_FROM_SHAPE_CHAN:
471 pline_The("sink looks nothing like a fountain.");
472 break;
473 case RIN_PROTECTION:
474 pline_The("sink glows %s for a moment.",
475 hcolor((obj->spe < 0) ? NH_BLACK : NH_SILVER));
476 break;
477 case RIN_WARNING:
478 pline_The("sink glows %s for a moment.", hcolor(NH_WHITE));
479 break;
480 case RIN_TELEPORT_CONTROL:
481 pline_The("sink looks like it is being beamed aboard somewhere.");
482 break;
483 case RIN_POLYMORPH_CONTROL:
484 pline_The(
485 "sink momentarily looks like a regularly erupting geyser.");
486 break;
487 default:
488 break;
491 if (ideed)
492 trycall(obj);
493 else if (!nosink)
494 You_hear("the ring bouncing down the drainpipe.");
496 if (!rn2(20) && !nosink) {
497 pline_The("sink backs up, leaving %s.", doname(obj));
498 obj->in_use = FALSE;
499 dropx(obj);
500 } else
501 useup(obj);
504 /* some common tests when trying to drop or throw items */
505 boolean
506 canletgo(obj, word)
507 struct obj *obj;
508 const char *word;
510 if (obj->owornmask & (W_ARMOR | W_ACCESSORY)) {
511 if (*word)
512 Norep("You cannot %s %s you are wearing.", word, something);
513 return FALSE;
515 if (obj->otyp == LOADSTONE && obj->cursed) {
516 /* getobj() kludge sets corpsenm to user's specified count
517 when refusing to split a stack of cursed loadstones */
518 if (*word) {
519 /* getobj() ignores a count for throwing since that is
520 implicitly forced to be 1; replicate its kludge... */
521 if (!strcmp(word, "throw") && obj->quan > 1L)
522 obj->corpsenm = 1;
523 pline("For some reason, you cannot %s%s the stone%s!", word,
524 obj->corpsenm ? " any of" : "", plur(obj->quan));
526 obj->corpsenm = 0; /* reset */
527 obj->bknown = 1;
528 return FALSE;
530 if (obj->otyp == LEASH && obj->leashmon != 0) {
531 if (*word)
532 pline_The("leash is tied around your %s.", body_part(HAND));
533 return FALSE;
535 if (obj->owornmask & W_SADDLE) {
536 if (*word)
537 You("cannot %s %s you are sitting on.", word, something);
538 return FALSE;
540 return TRUE;
543 STATIC_PTR int
544 drop(obj)
545 register struct obj *obj;
547 if (!obj)
548 return 0;
549 if (!canletgo(obj, "drop"))
550 return 0;
551 if (obj == uwep) {
552 if (welded(uwep)) {
553 weldmsg(obj);
554 return 0;
556 setuwep((struct obj *) 0);
558 if (obj == uquiver) {
559 setuqwep((struct obj *) 0);
561 if (obj == uswapwep) {
562 setuswapwep((struct obj *) 0);
565 if (u.uswallow) {
566 /* barrier between you and the floor */
567 if (flags.verbose) {
568 char buf[BUFSZ];
570 /* doname can call s_suffix, reusing its buffer */
571 Strcpy(buf, s_suffix(mon_nam(u.ustuck)));
572 You("drop %s into %s %s.", doname(obj), buf,
573 mbodypart(u.ustuck, STOMACH));
575 } else {
576 if ((obj->oclass == RING_CLASS || obj->otyp == MEAT_RING)
577 && IS_SINK(levl[u.ux][u.uy].typ)) {
578 dosinkring(obj);
579 return 1;
581 if (!can_reach_floor(TRUE)) {
582 /* we might be levitating due to #invoke Heart of Ahriman;
583 if so, levitation would end during call to freeinv()
584 and we want hitfloor() to happen before float_down() */
585 boolean levhack = finesse_ahriman(obj);
587 if (levhack)
588 ELevitation = W_ART; /* other than W_ARTI */
589 if (flags.verbose)
590 You("drop %s.", doname(obj));
591 /* Ensure update when we drop gold objects */
592 if (obj->oclass == COIN_CLASS)
593 context.botl = 1;
594 freeinv(obj);
595 hitfloor(obj);
596 if (levhack)
597 float_down(I_SPECIAL | TIMEOUT, W_ARTI | W_ART);
598 return 1;
600 if (!IS_ALTAR(levl[u.ux][u.uy].typ) && flags.verbose)
601 You("drop %s.", doname(obj));
603 dropx(obj);
604 return 1;
607 /* dropx - take dropped item out of inventory;
608 called in several places - may produce output
609 (eg ship_object() and dropy() -> sellobj() both produce output) */
610 void
611 dropx(obj)
612 register struct obj *obj;
614 /* Ensure update when we drop gold objects */
615 if (obj->oclass == COIN_CLASS)
616 context.botl = 1;
617 freeinv(obj);
618 if (!u.uswallow) {
619 if (ship_object(obj, u.ux, u.uy, FALSE))
620 return;
621 if (IS_ALTAR(levl[u.ux][u.uy].typ))
622 doaltarobj(obj); /* set bknown */
624 dropy(obj);
627 /* dropy - put dropped object at destination; called from lots of places */
628 void
629 dropy(obj)
630 struct obj *obj;
632 dropz(obj, FALSE);
635 /* dropz - really put dropped object at its destination... */
636 void
637 dropz(obj, with_impact)
638 struct obj *obj;
639 boolean with_impact;
641 if (obj == uwep)
642 setuwep((struct obj *) 0);
643 if (obj == uquiver)
644 setuqwep((struct obj *) 0);
645 if (obj == uswapwep)
646 setuswapwep((struct obj *) 0);
648 if (!u.uswallow && flooreffects(obj, u.ux, u.uy, "drop"))
649 return;
650 /* uswallow check done by GAN 01/29/87 */
651 if (u.uswallow) {
652 boolean could_petrify = FALSE;
653 boolean could_poly = FALSE;
654 boolean could_slime = FALSE;
655 boolean could_grow = FALSE;
656 boolean could_heal = FALSE;
658 if (obj != uball) { /* mon doesn't pick up ball */
659 if (obj->otyp == CORPSE) {
660 could_petrify = touch_petrifies(&mons[obj->corpsenm]);
661 could_poly = polyfodder(obj);
662 could_slime = (obj->corpsenm == PM_GREEN_SLIME);
663 could_grow = (obj->corpsenm == PM_WRAITH);
664 could_heal = (obj->corpsenm == PM_NURSE);
666 (void) mpickobj(u.ustuck, obj);
667 if (is_animal(u.ustuck->data)) {
668 if (could_poly || could_slime) {
669 (void) newcham(u.ustuck,
670 could_poly ? (struct permonst *) 0
671 : &mons[PM_GREEN_SLIME],
672 FALSE, could_slime);
673 delobj(obj); /* corpse is digested */
674 } else if (could_petrify) {
675 minstapetrify(u.ustuck, TRUE);
676 /* Don't leave a cockatrice corpse in a statue */
677 if (!u.uswallow)
678 delobj(obj);
679 } else if (could_grow) {
680 (void) grow_up(u.ustuck, (struct monst *) 0);
681 delobj(obj); /* corpse is digested */
682 } else if (could_heal) {
683 u.ustuck->mhp = u.ustuck->mhpmax;
684 delobj(obj); /* corpse is digested */
688 } else {
689 place_object(obj, u.ux, u.uy);
690 if (with_impact)
691 container_impact_dmg(obj, u.ux, u.uy);
692 if (obj == uball)
693 drop_ball(u.ux, u.uy);
694 else if (level.flags.has_shop)
695 sellobj(obj, u.ux, u.uy);
696 stackobj(obj);
697 if (Blind && Levitation)
698 map_object(obj, 0);
699 newsym(u.ux, u.uy); /* remap location under self */
703 /* things that must change when not held; recurse into containers.
704 Called for both player and monsters */
705 void
706 obj_no_longer_held(obj)
707 struct obj *obj;
709 if (!obj) {
710 return;
711 } else if (Has_contents(obj)) {
712 struct obj *contents;
714 for (contents = obj->cobj; contents; contents = contents->nobj)
715 obj_no_longer_held(contents);
717 switch (obj->otyp) {
718 case CRYSKNIFE:
719 /* Normal crysknife reverts to worm tooth when not held by hero
720 * or monster; fixed crysknife has only 10% chance of reverting.
721 * When a stack of the latter is involved, it could be worthwhile
722 * to give each individual crysknife its own separate 10% chance,
723 * but we aren't in any position to handle stack splitting here.
725 if (!obj->oerodeproof || !rn2(10)) {
726 /* if monsters aren't moving, assume player is responsible */
727 if (!context.mon_moving && !program_state.gameover)
728 costly_alteration(obj, COST_DEGRD);
729 obj->otyp = WORM_TOOTH;
730 obj->oerodeproof = 0;
732 break;
736 /* 'D' command: drop several things */
738 doddrop()
740 int result = 0;
742 add_valid_menu_class(0); /* clear any classes already there */
743 if (*u.ushops)
744 sellobj_state(SELL_DELIBERATE);
745 if (flags.menu_style != MENU_TRADITIONAL
746 || (result = ggetobj("drop", drop, 0, FALSE, (unsigned *) 0)) < -1)
747 result = menu_drop(result);
748 if (*u.ushops)
749 sellobj_state(SELL_NORMAL);
750 reset_occupations();
752 return result;
755 /* Drop things from the hero's inventory, using a menu. */
756 STATIC_OVL int
757 menu_drop(retry)
758 int retry;
760 int n, i, n_dropped = 0;
761 long cnt;
762 struct obj *otmp, *otmp2;
763 menu_item *pick_list;
764 boolean all_categories = TRUE;
765 boolean drop_everything = FALSE;
767 if (retry) {
768 all_categories = (retry == -2);
769 } else if (flags.menu_style == MENU_FULL) {
770 all_categories = FALSE;
771 n = query_category("Drop what type of items?", invent,
772 UNPAID_TYPES | ALL_TYPES | CHOOSE_ALL | BUC_BLESSED
773 | BUC_CURSED | BUC_UNCURSED | BUC_UNKNOWN,
774 &pick_list, PICK_ANY);
775 if (!n)
776 goto drop_done;
777 for (i = 0; i < n; i++) {
778 if (pick_list[i].item.a_int == ALL_TYPES_SELECTED)
779 all_categories = TRUE;
780 else if (pick_list[i].item.a_int == 'A')
781 drop_everything = TRUE;
782 else
783 add_valid_menu_class(pick_list[i].item.a_int);
785 free((genericptr_t) pick_list);
786 } else if (flags.menu_style == MENU_COMBINATION) {
787 unsigned ggoresults = 0;
788 all_categories = FALSE;
789 /* Gather valid classes via traditional NetHack method */
790 i = ggetobj("drop", drop, 0, TRUE, &ggoresults);
791 if (i == -2)
792 all_categories = TRUE;
793 if (ggoresults & ALL_FINISHED) {
794 n_dropped = i;
795 goto drop_done;
799 if (drop_everything) {
801 * Dropping a burning potion of oil while levitating can cause
802 * an explosion which might destroy some of hero's inventory,
803 * so the old code
804 * for (otmp = invent; otmp; otmp = otmp2) {
805 * otmp2 = otmp->nobj;
806 * n_dropped += drop(otmp);
808 * was unreliable and could lead to an "object lost" panic.
810 * Use the bypass bit to mark items already processed (hence
811 * not droppable) and rescan inventory until no unbypassed
812 * items remain.
814 bypass_objlist(invent, FALSE); /* clear bypass bit for invent */
815 while ((otmp = nxt_unbypassed_obj(invent)) != 0)
816 n_dropped += drop(otmp);
817 /* we might not have dropped everything (worn armor, welded weapon,
818 cursed loadstones), so reset any remaining inventory to normal */
819 bypass_objlist(invent, FALSE);
820 } else {
821 /* should coordinate with perm invent, maybe not show worn items */
822 n = query_objlist("What would you like to drop?", &invent,
823 (USE_INVLET | INVORDER_SORT), &pick_list, PICK_ANY,
824 all_categories ? allow_all : allow_category);
825 if (n > 0) {
827 * picklist[] contains a set of pointers into inventory, but
828 * as soon as something gets dropped, they might become stale
829 * (see the drop_everything code above for an explanation).
830 * Just checking to see whether one is still in the invent
831 * chain is not sufficient validation since destroyed items
832 * will be freed and items we've split here might have already
833 * reused that memory and put the same pointer value back into
834 * invent. Ditto for using invlet to validate. So we start
835 * by setting bypass on all of invent, then check each pointer
836 * to verify that it is in invent and has that bit set.
838 bypass_objlist(invent, TRUE);
839 for (i = 0; i < n; i++) {
840 otmp = pick_list[i].item.a_obj;
841 for (otmp2 = invent; otmp2; otmp2 = otmp2->nobj)
842 if (otmp2 == otmp)
843 break;
844 if (!otmp2 || !otmp2->bypass)
845 continue;
846 /* found next selected invent item */
847 cnt = pick_list[i].count;
848 if (cnt < otmp->quan) {
849 if (welded(otmp)) {
850 ; /* don't split */
851 } else if (otmp->otyp == LOADSTONE && otmp->cursed) {
852 /* same kludge as getobj(), for canletgo()'s use */
853 otmp->corpsenm = (int) cnt; /* don't split */
854 } else {
855 otmp = splitobj(otmp, cnt);
858 n_dropped += drop(otmp);
860 bypass_objlist(invent, FALSE); /* reset invent to normal */
861 free((genericptr_t) pick_list);
865 drop_done:
866 return n_dropped;
869 /* on a ladder, used in goto_level */
870 static NEARDATA boolean at_ladder = FALSE;
872 /* the '>' command */
874 dodown()
876 struct trap *trap = 0;
877 boolean stairs_down = ((u.ux == xdnstair && u.uy == ydnstair)
878 || (u.ux == sstairs.sx && u.uy == sstairs.sy
879 && !sstairs.up)),
880 ladder_down = (u.ux == xdnladder && u.uy == ydnladder);
882 if (u_rooted())
883 return 1;
885 if (stucksteed(TRUE)) {
886 return 0;
888 /* Levitation might be blocked, but player can still use '>' to
889 turn off controlled levitation */
890 if (HLevitation || ELevitation) {
891 if ((HLevitation & I_SPECIAL) || (ELevitation & W_ARTI)) {
892 /* end controlled levitation */
893 if (ELevitation & W_ARTI) {
894 struct obj *obj;
896 for (obj = invent; obj; obj = obj->nobj) {
897 if (obj->oartifact
898 && artifact_has_invprop(obj, LEVITATION)) {
899 if (obj->age < monstermoves)
900 obj->age = monstermoves;
901 obj->age += rnz(100);
905 if (float_down(I_SPECIAL | TIMEOUT, W_ARTI)) {
906 return 1; /* came down, so moved */
907 } else if (!HLevitation && !ELevitation) {
908 Your("latent levitation ceases.");
909 return 1; /* did something, effectively moved */
912 if (BLevitation) {
913 ; /* weren't actually floating after all */
914 } else if (Blind) {
915 /* Avoid alerting player to an unknown stair or ladder.
916 * Changes the message for a covered, known staircase
917 * too; staircase knowledge is not stored anywhere.
919 if (stairs_down)
920 stairs_down =
921 (glyph_to_cmap(levl[u.ux][u.uy].glyph) == S_dnstair);
922 else if (ladder_down)
923 ladder_down =
924 (glyph_to_cmap(levl[u.ux][u.uy].glyph) == S_dnladder);
926 if (Is_airlevel(&u.uz))
927 You("are floating in the %s.", surface(u.ux, u.uy));
928 else if (Is_waterlevel(&u.uz))
929 You("are floating in %s.",
930 is_pool(u.ux, u.uy) ? "the water" : "a bubble of air");
931 else
932 floating_above(stairs_down ? "stairs" : ladder_down
933 ? "ladder"
934 : surface(u.ux, u.uy));
935 return 0; /* didn't move */
937 if (!stairs_down && !ladder_down) {
938 trap = t_at(u.ux, u.uy);
939 if (trap && uteetering_at_seen_pit(trap)) {
940 dotrap(trap, TOOKPLUNGE);
941 return 1;
942 } else if (!trap || (trap->ttyp != TRAPDOOR && trap->ttyp != HOLE)
943 || !Can_fall_thru(&u.uz) || !trap->tseen) {
944 if (flags.autodig && !context.nopick && uwep && is_pick(uwep)) {
945 return use_pick_axe2(uwep);
946 } else {
947 You_cant("go down here.");
948 return 0;
952 if (u.ustuck) {
953 You("are %s, and cannot go down.",
954 !u.uswallow ? "being held" : is_animal(u.ustuck->data)
955 ? "swallowed"
956 : "engulfed");
957 return 1;
959 if (on_level(&valley_level, &u.uz) && !u.uevent.gehennom_entered) {
960 You("are standing at the gate to Gehennom.");
961 pline("Unspeakable cruelty and harm lurk down there.");
962 if (yn("Are you sure you want to enter?") != 'y')
963 return 0;
964 else
965 pline("So be it.");
966 u.uevent.gehennom_entered = 1; /* don't ask again */
969 if (!next_to_u()) {
970 You("are held back by your pet!");
971 return 0;
974 if (trap)
975 You("%s %s.", Flying ? "fly" : locomotion(youmonst.data, "jump"),
976 trap->ttyp == HOLE ? "down the hole" : "through the trap door");
978 if (trap && Is_stronghold(&u.uz)) {
979 goto_hell(FALSE, TRUE);
980 } else {
981 at_ladder = (boolean) (levl[u.ux][u.uy].typ == LADDER);
982 next_level(!trap);
983 at_ladder = FALSE;
985 return 1;
988 /* the '<' command */
990 doup()
992 if (u_rooted())
993 return 1;
995 /* "up" to get out of a pit... */
996 if (u.utrap && u.utraptype == TT_PIT) {
997 climb_pit();
998 return 1;
1001 if ((u.ux != xupstair || u.uy != yupstair)
1002 && (!xupladder || u.ux != xupladder || u.uy != yupladder)
1003 && (!sstairs.sx || u.ux != sstairs.sx || u.uy != sstairs.sy
1004 || !sstairs.up)) {
1005 You_cant("go up here.");
1006 return 0;
1008 if (stucksteed(TRUE)) {
1009 return 0;
1011 if (u.ustuck) {
1012 You("are %s, and cannot go up.",
1013 !u.uswallow ? "being held" : is_animal(u.ustuck->data)
1014 ? "swallowed"
1015 : "engulfed");
1016 return 1;
1018 if (near_capacity() > SLT_ENCUMBER) {
1019 /* No levitation check; inv_weight() already allows for it */
1020 Your("load is too heavy to climb the %s.",
1021 levl[u.ux][u.uy].typ == STAIRS ? "stairs" : "ladder");
1022 return 1;
1024 if (ledger_no(&u.uz) == 1) {
1025 if (yn("Beware, there will be no return! Still climb?") != 'y')
1026 return 0;
1028 if (!next_to_u()) {
1029 You("are held back by your pet!");
1030 return 0;
1032 at_ladder = (boolean) (levl[u.ux][u.uy].typ == LADDER);
1033 prev_level(TRUE);
1034 at_ladder = FALSE;
1035 return 1;
1038 d_level save_dlevel = { 0, 0 };
1040 /* check that we can write out the current level */
1041 STATIC_OVL int
1042 currentlevel_rewrite()
1044 register int fd;
1045 char whynot[BUFSZ];
1047 /* since level change might be a bit slow, flush any buffered screen
1048 * output (like "you fall through a trap door") */
1049 mark_synch();
1051 fd = create_levelfile(ledger_no(&u.uz), whynot);
1052 if (fd < 0) {
1054 * This is not quite impossible: e.g., we may have
1055 * exceeded our quota. If that is the case then we
1056 * cannot leave this level, and cannot save either.
1057 * Another possibility is that the directory was not
1058 * writable.
1060 pline1(whynot);
1061 return -1;
1064 #ifdef MFLOPPY
1065 if (!savelev(fd, ledger_no(&u.uz), COUNT_SAVE)) {
1066 (void) nhclose(fd);
1067 delete_levelfile(ledger_no(&u.uz));
1068 pline("NetHack is out of disk space for making levels!");
1069 You("can save, quit, or continue playing.");
1070 return -1;
1072 #endif
1073 return fd;
1076 #ifdef INSURANCE
1077 void
1078 save_currentstate()
1080 int fd;
1082 if (flags.ins_chkpt) {
1083 /* write out just-attained level, with pets and everything */
1084 fd = currentlevel_rewrite();
1085 if (fd < 0)
1086 return;
1087 bufon(fd);
1088 savelev(fd, ledger_no(&u.uz), WRITE_SAVE);
1089 bclose(fd);
1092 /* write out non-level state */
1093 savestateinlock();
1095 #endif
1098 static boolean
1099 badspot(x, y)
1100 register xchar x, y;
1102 return (boolean) ((levl[x][y].typ != ROOM
1103 && levl[x][y].typ != AIR
1104 && levl[x][y].typ != CORR)
1105 || MON_AT(x, y));
1109 void
1110 goto_level(newlevel, at_stairs, falling, portal)
1111 d_level *newlevel;
1112 boolean at_stairs, falling, portal;
1114 int fd, l_idx;
1115 xchar new_ledger;
1116 boolean cant_go_back, great_effort,
1117 up = (depth(newlevel) < depth(&u.uz)),
1118 newdungeon = (u.uz.dnum != newlevel->dnum),
1119 was_in_W_tower = In_W_tower(u.ux, u.uy, &u.uz),
1120 familiar = FALSE,
1121 new = FALSE; /* made a new level? */
1122 struct monst *mtmp;
1123 char whynot[BUFSZ];
1124 char *annotation;
1126 if (dunlev(newlevel) > dunlevs_in_dungeon(newlevel))
1127 newlevel->dlevel = dunlevs_in_dungeon(newlevel);
1128 if (newdungeon && In_endgame(newlevel)) { /* 1st Endgame Level !!! */
1129 if (!u.uhave.amulet)
1130 return; /* must have the Amulet */
1131 if (!wizard) /* wizard ^V can bypass Earth level */
1132 assign_level(newlevel, &earth_level); /* (redundant) */
1134 new_ledger = ledger_no(newlevel);
1135 if (new_ledger <= 0)
1136 done(ESCAPED); /* in fact < 0 is impossible */
1138 /* If you have the amulet and are trying to get out of Gehennom,
1139 * going up a set of stairs sometimes does some very strange things!
1140 * Biased against law and towards chaos. (The chance to be sent
1141 * down multiple levels when attempting to go up are significantly
1142 * less than the corresponding comment in older versions indicated
1143 * due to overlooking the effect of the call to assign_rnd_lvl().)
1145 * Odds for making it to the next level up, or of being sent down:
1146 * "up" L N C
1147 * +1 75.0 75.0 75.0
1148 * 0 6.25 8.33 12.5
1149 * -1 11.46 12.50 12.5
1150 * -2 5.21 4.17 0.0
1151 * -3 2.08 0.0 0.0
1153 if (Inhell && up && u.uhave.amulet && !newdungeon && !portal
1154 && (dunlev(&u.uz) < dunlevs_in_dungeon(&u.uz) - 3)) {
1155 if (!rn2(4)) {
1156 int odds = 3 + (int) u.ualign.type, /* 2..4 */
1157 diff = odds <= 1 ? 0 : rn2(odds); /* paranoia */
1159 if (diff != 0) {
1160 assign_rnd_level(newlevel, &u.uz, diff);
1161 /* if inside the tower, stay inside */
1162 if (was_in_W_tower && !On_W_tower_level(newlevel))
1163 diff = 0;
1165 if (diff == 0)
1166 assign_level(newlevel, &u.uz);
1168 new_ledger = ledger_no(newlevel);
1170 pline("A mysterious force momentarily surrounds you...");
1171 if (on_level(newlevel, &u.uz)) {
1172 (void) safe_teleds(FALSE);
1173 (void) next_to_u();
1174 return;
1175 } else
1176 at_stairs = at_ladder = FALSE;
1180 /* Prevent the player from going past the first quest level unless
1181 * (s)he has been given the go-ahead by the leader.
1183 if (on_level(&u.uz, &qstart_level) && !newdungeon && !ok_to_quest()) {
1184 pline("A mysterious force prevents you from descending.");
1185 return;
1188 if (on_level(newlevel, &u.uz))
1189 return; /* this can happen */
1191 /* tethered movement makes level change while trapped feasible */
1192 if (u.utrap && u.utraptype == TT_BURIEDBALL)
1193 buried_ball_to_punishment(); /* (before we save/leave old level) */
1195 fd = currentlevel_rewrite();
1196 if (fd < 0)
1197 return;
1199 if (falling) /* assuming this is only trap door or hole */
1200 impact_drop((struct obj *) 0, u.ux, u.uy, newlevel->dlevel);
1202 check_special_room(TRUE); /* probably was a trap door */
1203 if (Punished)
1204 unplacebc();
1205 u.utrap = 0; /* needed in level_tele */
1206 fill_pit(u.ux, u.uy);
1207 u.ustuck = 0; /* idem */
1208 u.uinwater = 0;
1209 u.uundetected = 0; /* not hidden, even if means are available */
1210 keepdogs(FALSE);
1211 if (u.uswallow) /* idem */
1212 u.uswldtim = u.uswallow = 0;
1213 recalc_mapseen(); /* recalculate map overview before we leave the level */
1215 * We no longer see anything on the level. Make sure that this
1216 * follows u.uswallow set to null since uswallow overrides all
1217 * normal vision.
1219 vision_recalc(2);
1222 * Save the level we're leaving. If we're entering the endgame,
1223 * we can get rid of all existing levels because they cannot be
1224 * reached any more. We still need to use savelev()'s cleanup
1225 * for the level being left, to recover dynamic memory in use and
1226 * to avoid dangling timers and light sources.
1228 cant_go_back = (newdungeon && In_endgame(newlevel));
1229 if (!cant_go_back) {
1230 update_mlstmv(); /* current monsters are becoming inactive */
1231 bufon(fd); /* use buffered output */
1233 savelev(fd, ledger_no(&u.uz),
1234 cant_go_back ? FREE_SAVE : (WRITE_SAVE | FREE_SAVE));
1235 bclose(fd);
1236 if (cant_go_back) {
1237 /* discard unreachable levels; keep #0 */
1238 for (l_idx = maxledgerno(); l_idx > 0; --l_idx)
1239 delete_levelfile(l_idx);
1240 /* mark #overview data for all dungeon branches as uninteresting */
1241 for (l_idx = 0; l_idx < n_dgns; ++l_idx)
1242 remdun_mapseen(l_idx);
1245 if (Is_rogue_level(newlevel) || Is_rogue_level(&u.uz))
1246 assign_graphics(Is_rogue_level(newlevel) ? ROGUESET : PRIMARY);
1247 #ifdef USE_TILES
1248 substitute_tiles(newlevel);
1249 #endif
1250 /* record this level transition as a potential seen branch unless using
1251 * some non-standard means of transportation (level teleport).
1253 if ((at_stairs || falling || portal) && (u.uz.dnum != newlevel->dnum))
1254 recbranch_mapseen(&u.uz, newlevel);
1255 assign_level(&u.uz0, &u.uz);
1256 assign_level(&u.uz, newlevel);
1257 assign_level(&u.utolev, newlevel);
1258 u.utotype = 0;
1259 if (!builds_up(&u.uz)) { /* usual case */
1260 if (dunlev(&u.uz) > dunlev_reached(&u.uz))
1261 dunlev_reached(&u.uz) = dunlev(&u.uz);
1262 } else {
1263 if (dunlev_reached(&u.uz) == 0
1264 || dunlev(&u.uz) < dunlev_reached(&u.uz))
1265 dunlev_reached(&u.uz) = dunlev(&u.uz);
1267 reset_rndmonst(NON_PM); /* u.uz change affects monster generation */
1269 /* set default level change destination areas */
1270 /* the special level code may override these */
1271 (void) memset((genericptr_t) &updest, 0, sizeof updest);
1272 (void) memset((genericptr_t) &dndest, 0, sizeof dndest);
1274 if (!(level_info[new_ledger].flags & LFILE_EXISTS)) {
1275 /* entering this level for first time; make it now */
1276 if (level_info[new_ledger].flags & (FORGOTTEN | VISITED)) {
1277 impossible("goto_level: returning to discarded level?");
1278 level_info[new_ledger].flags &= ~(FORGOTTEN | VISITED);
1280 mklev();
1281 new = TRUE; /* made the level */
1282 } else {
1283 /* returning to previously visited level; reload it */
1284 fd = open_levelfile(new_ledger, whynot);
1285 if (tricked_fileremoved(fd, whynot)) {
1286 /* we'll reach here if running in wizard mode */
1287 error("Cannot continue this game.");
1289 minit(); /* ZEROCOMP */
1290 getlev(fd, hackpid, new_ledger, FALSE);
1291 (void) nhclose(fd);
1292 oinit(); /* reassign level dependent obj probabilities */
1294 reglyph_darkroom();
1295 /* do this prior to level-change pline messages */
1296 vision_reset(); /* clear old level's line-of-sight */
1297 vision_full_recalc = 0; /* don't let that reenable vision yet */
1298 flush_screen(-1); /* ensure all map flushes are postponed */
1300 if (portal && !In_endgame(&u.uz)) {
1301 /* find the portal on the new level */
1302 register struct trap *ttrap;
1304 for (ttrap = ftrap; ttrap; ttrap = ttrap->ntrap)
1305 if (ttrap->ttyp == MAGIC_PORTAL)
1306 break;
1308 if (!ttrap)
1309 panic("goto_level: no corresponding portal!");
1310 seetrap(ttrap);
1311 u_on_newpos(ttrap->tx, ttrap->ty);
1312 } else if (at_stairs && !In_endgame(&u.uz)) {
1313 if (up) {
1314 if (at_ladder)
1315 u_on_newpos(xdnladder, ydnladder);
1316 else if (newdungeon)
1317 u_on_sstairs(1);
1318 else
1319 u_on_dnstairs();
1320 /* you climb up the {stairs|ladder};
1321 fly up the stairs; fly up along the ladder */
1322 great_effort = (Punished && !Levitation);
1323 if (flags.verbose || great_effort)
1324 pline("%s %s up%s the %s.",
1325 great_effort ? "With great effort, you" : "You",
1326 Levitation ? "float" : Flying ? "fly" : "climb",
1327 (Flying && at_ladder) ? " along" : "",
1328 at_ladder ? "ladder" : "stairs");
1329 } else { /* down */
1330 if (at_ladder)
1331 u_on_newpos(xupladder, yupladder);
1332 else if (newdungeon)
1333 u_on_sstairs(0);
1334 else
1335 u_on_upstairs();
1336 if (!u.dz) {
1337 ; /* stayed on same level? (no transit effects) */
1338 } else if (Flying) {
1339 if (flags.verbose)
1340 You("fly down %s.",
1341 at_ladder ? "along the ladder" : "the stairs");
1342 } else if (near_capacity() > UNENCUMBERED
1343 || Punished || Fumbling) {
1344 You("fall down the %s.", at_ladder ? "ladder" : "stairs");
1345 if (Punished) {
1346 drag_down();
1347 ballrelease(FALSE);
1349 /* falling off steed has its own losehp() call */
1350 if (u.usteed)
1351 dismount_steed(DISMOUNT_FELL);
1352 else
1353 losehp(Maybe_Half_Phys(rnd(3)),
1354 at_ladder ? "falling off a ladder"
1355 : "tumbling down a flight of stairs",
1356 KILLED_BY);
1357 selftouch("Falling, you");
1358 } else { /* ordinary descent */
1359 if (flags.verbose)
1360 You("%s.", at_ladder ? "climb down the ladder"
1361 : "descend the stairs");
1364 } else { /* trap door or level_tele or In_endgame */
1365 u_on_rndspot((up ? 1 : 0) | (was_in_W_tower ? 2 : 0));
1366 if (falling) {
1367 if (Punished)
1368 ballfall();
1369 selftouch("Falling, you");
1373 if (Punished)
1374 placebc();
1375 obj_delivery(FALSE);
1376 losedogs();
1377 kill_genocided_monsters(); /* for those wiped out while in limbo */
1379 * Expire all timers that have gone off while away. Must be
1380 * after migrating monsters and objects are delivered
1381 * (losedogs and obj_delivery).
1383 run_timers();
1385 initrack();
1387 if ((mtmp = m_at(u.ux, u.uy)) != 0 && mtmp != u.usteed) {
1388 /* There's a monster at your target destination; it might be one
1389 which accompanied you--see mon_arrive(dogmove.c)--or perhaps
1390 it was already here. Randomly move you to an adjacent spot
1391 or else the monster to any nearby location. Prior to 3.3.0
1392 the latter was done unconditionally. */
1393 coord cc;
1395 if (!rn2(2) && enexto(&cc, u.ux, u.uy, youmonst.data)
1396 && distu(cc.x, cc.y) <= 2)
1397 u_on_newpos(cc.x, cc.y); /*[maybe give message here?]*/
1398 else
1399 mnexto(mtmp);
1401 if ((mtmp = m_at(u.ux, u.uy)) != 0) {
1402 /* there was an unconditional impossible("mnearto failed")
1403 here, but it's not impossible and we're prepared to cope
1404 with the situation, so only say something when debugging */
1405 if (wizard)
1406 pline("(monster in hero's way)");
1407 if (!rloc(mtmp, TRUE))
1408 /* no room to move it; send it away, to return later */
1409 migrate_to_level(mtmp, ledger_no(&u.uz), MIGR_RANDOM,
1410 (coord *) 0);
1414 /* initial movement of bubbles just before vision_recalc */
1415 if (Is_waterlevel(&u.uz) || Is_airlevel(&u.uz))
1416 movebubbles();
1417 else if (Is_firelevel(&u.uz))
1418 fumaroles();
1420 if (level_info[new_ledger].flags & FORGOTTEN) {
1421 forget_map(ALL_MAP); /* forget the map */
1422 forget_traps(); /* forget all traps too */
1423 familiar = TRUE;
1424 level_info[new_ledger].flags &= ~FORGOTTEN;
1427 /* Reset the screen. */
1428 vision_reset(); /* reset the blockages */
1429 docrt(); /* does a full vision recalc */
1430 flush_screen(-1);
1433 * Move all plines beyond the screen reset.
1436 /* special levels can have a custom arrival message */
1437 deliver_splev_message();
1439 /* give room entrance message, if any */
1440 check_special_room(FALSE);
1442 /* deliver objects traveling with player */
1443 obj_delivery(TRUE);
1445 /* Check whether we just entered Gehennom. */
1446 if (!In_hell(&u.uz0) && Inhell) {
1447 if (Is_valley(&u.uz)) {
1448 You("arrive at the Valley of the Dead...");
1449 pline_The("odor of burnt flesh and decay pervades the air.");
1450 #ifdef MICRO
1451 display_nhwindow(WIN_MESSAGE, FALSE);
1452 #endif
1453 You_hear("groans and moans everywhere.");
1454 } else
1455 pline("It is hot here. You smell smoke...");
1456 u.uachieve.enter_gehennom = 1;
1458 /* in case we've managed to bypass the Valley's stairway down */
1459 if (Inhell && !Is_valley(&u.uz))
1460 u.uevent.gehennom_entered = 1;
1462 if (familiar) {
1463 static const char *const fam_msgs[4] = {
1464 "You have a sense of deja vu.",
1465 "You feel like you've been here before.",
1466 "This place %s familiar...", 0 /* no message */
1468 static const char *const halu_fam_msgs[4] = {
1469 "Whoa! Everything %s different.",
1470 "You are surrounded by twisty little passages, all alike.",
1471 "Gee, this %s like uncle Conan's place...", 0 /* no message */
1473 const char *mesg;
1474 char buf[BUFSZ];
1475 int which = rn2(4);
1477 if (Hallucination)
1478 mesg = halu_fam_msgs[which];
1479 else
1480 mesg = fam_msgs[which];
1481 if (mesg && index(mesg, '%')) {
1482 Sprintf(buf, mesg, !Blind ? "looks" : "seems");
1483 mesg = buf;
1485 if (mesg)
1486 pline1(mesg);
1489 /* special location arrival messages/events */
1490 if (In_endgame(&u.uz)) {
1491 if (new &&on_level(&u.uz, &astral_level))
1492 final_level(); /* guardian angel,&c */
1493 else if (newdungeon && u.uhave.amulet)
1494 resurrect(); /* force confrontation with Wizard */
1495 } else if (In_quest(&u.uz)) {
1496 onquest(); /* might be reaching locate|goal level */
1497 } else if (In_V_tower(&u.uz)) {
1498 if (newdungeon && In_hell(&u.uz0))
1499 pline_The("heat and smoke are gone.");
1500 } else if (Is_knox(&u.uz)) {
1501 /* alarm stops working once Croesus has died */
1502 if (new || !mvitals[PM_CROESUS].died) {
1503 You("have penetrated a high security area!");
1504 pline("An alarm sounds!");
1505 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
1506 if (DEADMONSTER(mtmp))
1507 continue;
1508 mtmp->msleeping = 0;
1511 } else {
1512 if (new && Is_rogue_level(&u.uz))
1513 You("enter what seems to be an older, more primitive world.");
1514 /* main dungeon message from your quest leader */
1515 if (!In_quest(&u.uz0) && at_dgn_entrance("The Quest")
1516 && !(u.uevent.qcompleted || u.uevent.qexpelled
1517 || quest_status.leader_is_dead)) {
1518 if (!u.uevent.qcalled) {
1519 u.uevent.qcalled = 1;
1520 com_pager(2); /* main "leader needs help" message */
1521 } else { /* reminder message */
1522 com_pager(Role_if(PM_ROGUE) ? 4 : 3);
1527 assign_level(&u.uz0, &u.uz); /* reset u.uz0 */
1528 #ifdef INSURANCE
1529 save_currentstate();
1530 #endif
1532 if ((annotation = get_annotation(&u.uz)) != 0)
1533 You("remember this level as %s.", annotation);
1535 /* assume this will always return TRUE when changing level */
1536 (void) in_out_region(u.ux, u.uy);
1537 (void) pickup(1);
1539 /* discard context which applied to previous level */
1540 maybe_reset_pick(); /* for door or for box not accompanying hero */
1541 reset_trapset(); /* even if to-be-armed trap obj is accompanying hero */
1542 iflags.travelcc.x = iflags.travelcc.y = -1; /* travel destination cache */
1543 context.polearm.hitmon = (struct monst *) 0; /* polearm target */
1544 /* digging context is level-aware and can actually be resumed if
1545 hero returns to the previous level without any intervening dig */
1548 STATIC_OVL void
1549 final_level()
1551 struct monst *mtmp;
1553 /* reset monster hostility relative to player */
1554 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
1555 if (DEADMONSTER(mtmp))
1556 continue;
1557 reset_hostility(mtmp);
1560 /* create some player-monsters */
1561 create_mplayers(rn1(4, 3), TRUE);
1563 /* create a guardian angel next to player, if worthy */
1564 gain_guardian_angel();
1567 static char *dfr_pre_msg = 0, /* pline() before level change */
1568 *dfr_post_msg = 0; /* pline() after level change */
1570 /* change levels at the end of this turn, after monsters finish moving */
1571 void
1572 schedule_goto(tolev, at_stairs, falling, portal_flag, pre_msg, post_msg)
1573 d_level *tolev;
1574 boolean at_stairs, falling;
1575 int portal_flag;
1576 const char *pre_msg, *post_msg;
1578 int typmask = 0100; /* non-zero triggers `deferred_goto' */
1580 /* destination flags (`goto_level' args) */
1581 if (at_stairs)
1582 typmask |= 1;
1583 if (falling)
1584 typmask |= 2;
1585 if (portal_flag)
1586 typmask |= 4;
1587 if (portal_flag < 0)
1588 typmask |= 0200; /* flag for portal removal */
1589 u.utotype = typmask;
1590 /* destination level */
1591 assign_level(&u.utolev, tolev);
1593 if (pre_msg)
1594 dfr_pre_msg = dupstr(pre_msg);
1595 if (post_msg)
1596 dfr_post_msg = dupstr(post_msg);
1599 /* handle something like portal ejection */
1600 void
1601 deferred_goto()
1603 if (!on_level(&u.uz, &u.utolev)) {
1604 d_level dest;
1605 int typmask = u.utotype; /* save it; goto_level zeroes u.utotype */
1607 assign_level(&dest, &u.utolev);
1608 if (dfr_pre_msg)
1609 pline1(dfr_pre_msg);
1610 goto_level(&dest, !!(typmask & 1), !!(typmask & 2), !!(typmask & 4));
1611 if (typmask & 0200) { /* remove portal */
1612 struct trap *t = t_at(u.ux, u.uy);
1614 if (t) {
1615 deltrap(t);
1616 newsym(u.ux, u.uy);
1619 if (dfr_post_msg)
1620 pline1(dfr_post_msg);
1622 u.utotype = 0; /* our caller keys off of this */
1623 if (dfr_pre_msg)
1624 free((genericptr_t) dfr_pre_msg), dfr_pre_msg = 0;
1625 if (dfr_post_msg)
1626 free((genericptr_t) dfr_post_msg), dfr_post_msg = 0;
1630 * Return TRUE if we created a monster for the corpse. If successful, the
1631 * corpse is gone.
1633 boolean
1634 revive_corpse(corpse)
1635 struct obj *corpse;
1637 struct monst *mtmp, *mcarry;
1638 boolean is_uwep, chewed;
1639 xchar where;
1640 char cname[BUFSZ];
1641 struct obj *container = (struct obj *) 0;
1642 int container_where = 0;
1644 where = corpse->where;
1645 is_uwep = (corpse == uwep);
1646 chewed = (corpse->oeaten != 0);
1647 Strcpy(cname,
1648 corpse_xname(corpse, chewed ? "bite-covered" : (const char *) 0,
1649 CXN_SINGULAR));
1650 mcarry = (where == OBJ_MINVENT) ? corpse->ocarry : 0;
1652 if (where == OBJ_CONTAINED) {
1653 struct monst *mtmp2;
1655 container = corpse->ocontainer;
1656 mtmp2 =
1657 get_container_location(container, &container_where, (int *) 0);
1658 /* container_where is the outermost container's location even if
1659 * nested */
1660 if (container_where == OBJ_MINVENT && mtmp2)
1661 mcarry = mtmp2;
1663 mtmp = revive(corpse, FALSE); /* corpse is gone if successful */
1665 if (mtmp) {
1666 switch (where) {
1667 case OBJ_INVENT:
1668 if (is_uwep)
1669 pline_The("%s writhes out of your grasp!", cname);
1670 else
1671 You_feel("squirming in your backpack!");
1672 break;
1674 case OBJ_FLOOR:
1675 if (cansee(mtmp->mx, mtmp->my))
1676 pline("%s rises from the dead!",
1677 chewed ? Adjmonnam(mtmp, "bite-covered")
1678 : Monnam(mtmp));
1679 break;
1681 case OBJ_MINVENT: /* probably a nymph's */
1682 if (cansee(mtmp->mx, mtmp->my)) {
1683 if (canseemon(mcarry))
1684 pline("Startled, %s drops %s as it revives!",
1685 mon_nam(mcarry), an(cname));
1686 else
1687 pline("%s suddenly appears!",
1688 chewed ? Adjmonnam(mtmp, "bite-covered")
1689 : Monnam(mtmp));
1691 break;
1692 case OBJ_CONTAINED: {
1693 char sackname[BUFSZ];
1695 if (container_where == OBJ_MINVENT && cansee(mtmp->mx, mtmp->my)
1696 && mcarry && canseemon(mcarry) && container) {
1697 pline("%s writhes out of %s!", Amonnam(mtmp),
1698 yname(container));
1699 } else if (container_where == OBJ_INVENT && container) {
1700 Strcpy(sackname, an(xname(container)));
1701 pline("%s %s out of %s in your pack!",
1702 Blind ? Something : Amonnam(mtmp),
1703 locomotion(mtmp->data, "writhes"), sackname);
1704 } else if (container_where == OBJ_FLOOR && container
1705 && cansee(mtmp->mx, mtmp->my)) {
1706 Strcpy(sackname, an(xname(container)));
1707 pline("%s escapes from %s!", Amonnam(mtmp), sackname);
1709 break;
1711 default:
1712 /* we should be able to handle the other cases... */
1713 impossible("revive_corpse: lost corpse @ %d", where);
1714 break;
1716 return TRUE;
1718 return FALSE;
1721 /* Revive the corpse via a timeout. */
1722 /*ARGSUSED*/
1723 void
1724 revive_mon(arg, timeout)
1725 anything *arg;
1726 long timeout UNUSED;
1728 struct obj *body = arg->a_obj;
1729 struct permonst *mptr = &mons[body->corpsenm];
1730 struct monst *mtmp;
1731 xchar x, y;
1733 /* corpse will revive somewhere else if there is a monster in the way;
1734 Riders get a chance to try to bump the obstacle out of their way */
1735 if ((mptr->mflags3 & M3_DISPLACES) != 0 && body->where == OBJ_FLOOR
1736 && get_obj_location(body, &x, &y, 0) && (mtmp = m_at(x, y)) != 0) {
1737 boolean notice_it = canseemon(mtmp); /* before rloc() */
1738 char *monname = Monnam(mtmp);
1740 if (rloc(mtmp, TRUE)) {
1741 if (notice_it && !canseemon(mtmp))
1742 pline("%s vanishes.", monname);
1743 else if (!notice_it && canseemon(mtmp))
1744 pline("%s appears.", Monnam(mtmp)); /* not pre-rloc monname */
1745 else if (notice_it && dist2(mtmp->mx, mtmp->my, x, y) > 2)
1746 pline("%s teleports.", monname); /* saw it and still see it */
1750 /* if we succeed, the corpse is gone */
1751 if (!revive_corpse(body)) {
1752 long when;
1753 int action;
1755 if (is_rider(mptr) && rn2(99)) { /* Rider usually tries again */
1756 action = REVIVE_MON;
1757 for (when = 3L; when < 67L; when++)
1758 if (!rn2(3))
1759 break;
1760 } else { /* rot this corpse away */
1761 You_feel("%sless hassled.", is_rider(mptr) ? "much " : "");
1762 action = ROT_CORPSE;
1763 when = 250L - (monstermoves - body->age);
1764 if (when < 1L)
1765 when = 1L;
1767 (void) start_timer(when, TIMER_OBJECT, action, arg);
1772 donull()
1774 return 1; /* Do nothing, but let other things happen */
1777 STATIC_PTR int
1778 wipeoff(VOID_ARGS)
1780 if (u.ucreamed < 4)
1781 u.ucreamed = 0;
1782 else
1783 u.ucreamed -= 4;
1784 if (Blinded < 4)
1785 Blinded = 0;
1786 else
1787 Blinded -= 4;
1788 if (!Blinded) {
1789 pline("You've got the glop off.");
1790 u.ucreamed = 0;
1791 if (!gulp_blnd_check()) {
1792 Blinded = 1;
1793 make_blinded(0L, TRUE);
1795 return 0;
1796 } else if (!u.ucreamed) {
1797 Your("%s feels clean now.", body_part(FACE));
1798 return 0;
1800 return 1; /* still busy */
1804 dowipe()
1806 if (u.ucreamed) {
1807 static NEARDATA char buf[39];
1809 Sprintf(buf, "wiping off your %s", body_part(FACE));
1810 set_occupation(wipeoff, buf, 0);
1811 /* Not totally correct; what if they change back after now
1812 * but before they're finished wiping?
1814 return 1;
1816 Your("%s is already clean.", body_part(FACE));
1817 return 1;
1820 void
1821 set_wounded_legs(side, timex)
1822 register long side;
1823 register int timex;
1825 /* KMH -- STEED
1826 * If you are riding, your steed gets the wounded legs instead.
1827 * You still call this function, but don't lose hp.
1828 * Caller is also responsible for adjusting messages.
1831 if (!Wounded_legs) {
1832 ATEMP(A_DEX)--;
1833 context.botl = 1;
1836 if (!Wounded_legs || (HWounded_legs & TIMEOUT))
1837 HWounded_legs = timex;
1838 EWounded_legs = side;
1839 (void) encumber_msg();
1842 void
1843 heal_legs()
1845 if (Wounded_legs) {
1846 if (ATEMP(A_DEX) < 0) {
1847 ATEMP(A_DEX)++;
1848 context.botl = 1;
1851 if (!u.usteed) {
1852 const char *legs = body_part(LEG);
1854 if ((EWounded_legs & BOTH_SIDES) == BOTH_SIDES)
1855 legs = makeplural(legs);
1856 /* this used to say "somewhat better" but that was
1857 misleading since legs are being fully healed */
1858 Your("%s %s better.", legs, vtense(legs, "feel"));
1861 HWounded_legs = EWounded_legs = 0;
1863 /* Wounded_legs reduces carrying capacity, so we want
1864 an encumbrance check when they're healed. However,
1865 while dismounting, first steed's legs get healed,
1866 then hero is dropped to floor and a new encumbrance
1867 check is made [in dismount_steed()]. So don't give
1868 encumbrance feedback during the dismount stage
1869 because it could seem to be shown out of order and
1870 it might be immediately contradicted [able to carry
1871 more when steed becomes healthy, then possible floor
1872 feedback, then able to carry less when back on foot]. */
1873 if (!in_steed_dismounting)
1874 (void) encumber_msg();
1878 /*do.c*/