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