1/*	SCCS Id: @(#)do.c	3.4	2003/12/02	*/
2/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3/* NetHack may be freely redistributed.  See license for details. */
4
5/* Contains code for 'd', 'D' (drop), '>', '<' (up, down) */
6
7#include "hack.h"
8#include "lev.h"
9
10#ifdef SINKS
11# ifdef OVLB
12STATIC_DCL void FDECL(trycall, (struct obj *));
13# endif /* OVLB */
14STATIC_DCL void FDECL(dosinkring, (struct obj *));
15#endif /* SINKS */
16
17STATIC_PTR int FDECL(drop, (struct obj *));
18STATIC_PTR int NDECL(wipeoff);
19
20#ifdef OVL0
21STATIC_DCL int FDECL(menu_drop, (int));
22#endif
23#ifdef OVL2
24STATIC_DCL int NDECL(currentlevel_rewrite);
25STATIC_DCL void NDECL(final_level);
26/* static boolean FDECL(badspot, (XCHAR_P,XCHAR_P)); */
27#endif
28
29#ifdef OVLB
30
31static NEARDATA const char drop_types[] =
32	{ ALLOW_COUNT, COIN_CLASS, ALL_CLASSES, 0 };
33
34/* 'd' command: drop one inventory item */
35int
36dodrop()
37{
38#ifndef GOLDOBJ
39	int result, i = (invent || u.ugold) ? 0 : (SIZE(drop_types) - 1);
40#else
41	int result, i = (invent) ? 0 : (SIZE(drop_types) - 1);
42#endif
43
44	if (*u.ushops) sellobj_state(SELL_DELIBERATE);
45	result = drop(getobj(&drop_types[i], "drop"));
46	if (*u.ushops) sellobj_state(SELL_NORMAL);
47	reset_occupations();
48
49	return result;
50}
51
52#endif /* OVLB */
53#ifdef OVL0
54
55/* Called when a boulder is dropped, thrown, or pushed.  If it ends up
56 * in a pool, it either fills the pool up or sinks away.  In either case,
57 * it's gone for good...  If the destination is not a pool, returns FALSE.
58 */
59boolean
60boulder_hits_pool(otmp, rx, ry, pushing)
61struct obj *otmp;
62register int rx, ry;
63boolean pushing;
64{
65	if (!otmp || otmp->otyp != BOULDER)
66	    impossible("Not a boulder?");
67	else if (!Is_waterlevel(&u.uz) && (is_pool(rx,ry) || is_lava(rx,ry))) {
68	    boolean lava = is_lava(rx,ry), fills_up;
69	    const char *what = waterbody_name(rx,ry);
70	    schar ltyp = levl[rx][ry].typ;
71	    int chance = rn2(10);		/* water: 90%; lava: 10% */
72	    fills_up = lava ? chance == 0 : chance != 0;
73
74	    if (fills_up) {
75		struct trap *ttmp = t_at(rx, ry);
76
77		if (ltyp == DRAWBRIDGE_UP) {
78		    levl[rx][ry].drawbridgemask &= ~DB_UNDER; /* clear lava */
79		    levl[rx][ry].drawbridgemask |= DB_FLOOR;
80		} else
81		    levl[rx][ry].typ = ROOM;
82
83		if (ttmp) (void) delfloortrap(ttmp);
84		bury_objs(rx, ry);
85
86		newsym(rx,ry);
87		if (pushing) {
88		    You("push %s into the %s.", the(xname(otmp)), what);
89		    if (flags.verbose && !Blind)
90			pline("Now you can cross it!");
91		    /* no splashing in this case */
92		}
93	    }
94	    if (!fills_up || !pushing) {	/* splashing occurs */
95		if (!u.uinwater) {
96		    if (pushing ? !Blind : cansee(rx,ry)) {
97			There("is a large splash as %s %s the %s.",
98			      the(xname(otmp)), fills_up? "fills":"falls into",
99			      what);
100		    } else if (flags.soundok)
101			You_hear("a%s splash.", lava ? " sizzling" : "");
102		    wake_nearto(rx, ry, 40);
103		}
104
105		if (fills_up && u.uinwater && distu(rx,ry) == 0) {
106		    u.uinwater = 0;
107		    docrt();
108		    vision_full_recalc = 1;
109		    You("find yourself on dry land again!");
110		} else if (lava && distu(rx,ry) <= 2) {
111		    You("are hit by molten lava%c",
112			Fire_resistance ? '.' : '!');
113			burn_away_slime();
114		    losehp(d((Fire_resistance ? 1 : 3), 6),
115			   "molten lava", KILLED_BY);
116		} else if (!fills_up && flags.verbose &&
117			   (pushing ? !Blind : cansee(rx,ry)))
118		    pline("It sinks without a trace!");
119	    }
120
121	    /* boulder is now gone */
122	    if (pushing) delobj(otmp);
123	    else obfree(otmp, (struct obj *)0);
124	    return TRUE;
125	}
126	return FALSE;
127}
128
129/* Used for objects which sometimes do special things when dropped; must be
130 * called with the object not in any chain.  Returns TRUE if the object goes
131 * away.
132 */
133boolean
134flooreffects(obj,x,y,verb)
135struct obj *obj;
136int x,y;
137const char *verb;
138{
139	struct trap *t;
140	struct monst *mtmp;
141
142	if (obj->where != OBJ_FREE)
143	    panic("flooreffects: obj not free");
144
145	/* make sure things like water_damage() have no pointers to follow */
146	obj->nobj = obj->nexthere = (struct obj *)0;
147
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) &&
161				!throws_rocks(mtmp->data)) {
162			    if (hmon(mtmp, obj, TRUE) && !is_whirly(mtmp->data))
163				return FALSE;	/* still alive */
164			}
165			mtmp->mtrapped = 0;
166		    } else {
167			if (!Passes_walls && !throws_rocks(youmonst.data)) {
168			    losehp(rnd(15), "squished under a boulder",
169				   NO_KILLER_PREFIX);
170			    return FALSE;	/* player remains trapped */
171			} else u.utrap = 0;
172		    }
173		}
174		if (*verb) {
175			if (Blind) {
176				if ((x == u.ux) && (y == u.uy))
177					You_hear("a CRASH! beneath you.");
178				else
179					You_hear("the boulder %s.", verb);
180			} else if (cansee(x, y)) {
181				pline_The("boulder %s%s.",
182				    t->tseen ? "" : "triggers and ",
183				    t->ttyp == TRAPDOOR ? "plugs a trap door" :
184				    t->ttyp == HOLE ? "plugs a hole" :
185				    "fills a pit");
186			}
187		}
188		deltrap(t);
189		obfree(obj, (struct obj *)0);
190		bury_objs(x, y);
191		newsym(x,y);
192		return TRUE;
193	} else if (is_lava(x, y)) {
194		return fire_damage(obj, FALSE, FALSE, x, y);
195	} else if (is_pool(x, y)) {
196		/* Reasonably bulky objects (arbitrary) splash when dropped.
197		 * If you're floating above the water even small things make noise.
198		 * Stuff dropped near fountains always misses */
199		if ((Blind || (Levitation || Flying)) && flags.soundok &&
200		    ((x == u.ux) && (y == u.uy))) {
201		    if (!Underwater) {
202			if (weight(obj) > 9) {
203				pline("Splash!");
204		        } else if (Levitation || Flying) {
205				pline("Plop!");
206		        }
207		    }
208		    map_background(x, y, 0);
209		    newsym(x, y);
210		}
211		water_damage(obj, FALSE, FALSE);
212	} else if (u.ux == x && u.uy == y &&
213		(!u.utrap || u.utraptype != TT_PIT) &&
214		(t = t_at(x,y)) != 0 && t->tseen &&
215			(t->ttyp==PIT || t->ttyp==SPIKED_PIT)) {
216		/* you escaped a pit and are standing on the precipice */
217		if (Blind && flags.soundok)
218			You_hear("%s %s downwards.",
219				The(xname(obj)), otense(obj, "tumble"));
220		else
221			pline("%s %s into %s pit.",
222				The(xname(obj)), otense(obj, "tumble"),
223				the_your[t->madeby_u]);
224	}
225	return FALSE;
226}
227
228#endif /* OVL0 */
229#ifdef OVLB
230
231void
232doaltarobj(obj)  /* obj is an object dropped on an altar */
233	register struct obj *obj;
234{
235	if (Blind)
236		return;
237
238	/* KMH, conduct */
239	u.uconduct.gnostic++;
240
241	if ((obj->blessed || obj->cursed) && obj->oclass != COIN_CLASS) {
242		There("is %s flash as %s %s the altar.",
243			an(hcolor(obj->blessed ? NH_AMBER : NH_BLACK)),
244			doname(obj), otense(obj, "hit"));
245		if (!Hallucination) obj->bknown = 1;
246	} else {
247		pline("%s %s on the altar.", Doname2(obj),
248			otense(obj, "land"));
249		obj->bknown = 1;
250	}
251}
252
253#ifdef SINKS
254STATIC_OVL
255void
256trycall(obj)
257register struct obj *obj;
258{
259	if(!objects[obj->otyp].oc_name_known &&
260	   !objects[obj->otyp].oc_uname)
261	   docall(obj);
262}
263
264STATIC_OVL
265void
266dosinkring(obj)  /* obj is a ring being dropped over a kitchen sink */
267register struct obj *obj;
268{
269	register struct obj *otmp,*otmp2;
270	register boolean ideed = TRUE;
271
272	You("drop %s down the drain.", doname(obj));
273	obj->in_use = TRUE;	/* block free identification via interrupt */
274	switch(obj->otyp) {	/* effects that can be noticed without eyes */
275	    case RIN_SEARCHING:
276		You("thought your %s got lost in the sink, but there it is!",
277			xname(obj));
278		goto giveback;
279	    case RIN_SLOW_DIGESTION:
280		pline_The("ring is regurgitated!");
281giveback:
282		obj->in_use = FALSE;
283		dropx(obj);
284		trycall(obj);
285		return;
286	    case RIN_LEVITATION:
287		pline_The("sink quivers upward for a moment.");
288		break;
289	    case RIN_POISON_RESISTANCE:
290		You("smell rotten %s.", makeplural(fruitname(FALSE)));
291		break;
292	    case RIN_AGGRAVATE_MONSTER:
293		pline("Several flies buzz angrily around the sink.");
294		break;
295	    case RIN_SHOCK_RESISTANCE:
296		pline("Static electricity surrounds the sink.");
297		break;
298	    case RIN_CONFLICT:
299		You_hear("loud noises coming from the drain.");
300		break;
301	    case RIN_SUSTAIN_ABILITY:	/* KMH */
302		pline_The("water flow seems fixed.");
303		break;
304	    case RIN_GAIN_STRENGTH:
305		pline_The("water flow seems %ser now.",
306			(obj->spe<0) ? "weak" : "strong");
307		break;
308	    case RIN_GAIN_CONSTITUTION:
309		pline_The("water flow seems %ser now.",
310			(obj->spe<0) ? "less" : "great");
311		break;
312	    case RIN_INCREASE_ACCURACY:	/* KMH */
313		pline_The("water flow %s the drain.",
314			(obj->spe<0) ? "misses" : "hits");
315		break;
316	    case RIN_INCREASE_DAMAGE:
317		pline_The("water's force seems %ser now.",
318			(obj->spe<0) ? "small" : "great");
319		break;
320	    case RIN_HUNGER:
321		ideed = FALSE;
322		for(otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp2) {
323		    otmp2 = otmp->nexthere;
324		    if (otmp != uball && otmp != uchain &&
325			    !obj_resists(otmp, 1, 99)) {
326			if (!Blind) {
327			    pline("Suddenly, %s %s from the sink!",
328				  doname(otmp), otense(otmp, "vanish"));
329			    ideed = TRUE;
330			}
331			delobj(otmp);
332		    }
333		}
334		break;
335	    case MEAT_RING:
336		/* Not the same as aggravate monster; besides, it's obvious. */
337		pline("Several flies buzz around the sink.");
338		break;
339	    default:
340		ideed = FALSE;
341		break;
342	}
343	if(!Blind && !ideed && obj->otyp != RIN_HUNGER) {
344	    ideed = TRUE;
345	    switch(obj->otyp) {		/* effects that need eyes */
346		case RIN_ADORNMENT:
347		    pline_The("faucets flash brightly for a moment.");
348		    break;
349		case RIN_REGENERATION:
350		    pline_The("sink looks as good as new.");
351		    break;
352		case RIN_INVISIBILITY:
353		    You("don't see anything happen to the sink.");
354		    break;
355		case RIN_FREE_ACTION:
356		    You("see the ring slide right down the drain!");
357		    break;
358		case RIN_SEE_INVISIBLE:
359		    You("see some air in the sink.");
360		    break;
361		case RIN_STEALTH:
362		pline_The("sink seems to blend into the floor for a moment.");
363		    break;
364		case RIN_FIRE_RESISTANCE:
365		pline_The("hot water faucet flashes brightly for a moment.");
366		    break;
367		case RIN_COLD_RESISTANCE:
368		pline_The("cold water faucet flashes brightly for a moment.");
369		    break;
370		case RIN_PROTECTION_FROM_SHAPE_CHAN:
371		    pline_The("sink looks nothing like a fountain.");
372		    break;
373		case RIN_PROTECTION:
374		    pline_The("sink glows %s for a moment.",
375			    hcolor((obj->spe<0) ? NH_BLACK : NH_SILVER));
376		    break;
377		case RIN_WARNING:
378		    pline_The("sink glows %s for a moment.", hcolor(NH_WHITE));
379		    break;
380		case RIN_TELEPORTATION:
381		    pline_The("sink momentarily vanishes.");
382		    break;
383		case RIN_TELEPORT_CONTROL:
384	    pline_The("sink looks like it is being beamed aboard somewhere.");
385		    break;
386		case RIN_POLYMORPH:
387		    pline_The("sink momentarily looks like a fountain.");
388		    break;
389		case RIN_POLYMORPH_CONTROL:
390	pline_The("sink momentarily looks like a regularly erupting geyser.");
391		    break;
392	    }
393	}
394	if(ideed)
395	    trycall(obj);
396	else
397	    You_hear("the ring bouncing down the drainpipe.");
398	if (!rn2(20)) {
399		pline_The("sink backs up, leaving %s.", doname(obj));
400		obj->in_use = FALSE;
401		dropx(obj);
402	} else
403		useup(obj);
404}
405#endif
406
407#endif /* OVLB */
408#ifdef OVL0
409
410/* some common tests when trying to drop or throw items */
411boolean
412canletgo(obj,word)
413register struct obj *obj;
414register const char *word;
415{
416	if(obj->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)){
417		if (*word)
418			Norep("You cannot %s %s you are wearing.",word,
419				something);
420		return(FALSE);
421	}
422	if (obj->otyp == LOADSTONE && obj->cursed) {
423		/* getobj() kludge sets corpsenm to user's specified count
424		   when refusing to split a stack of cursed loadstones */
425		if (*word) {
426			/* getobj() ignores a count for throwing since that is
427			   implicitly forced to be 1; replicate its kludge... */
428			if (!strcmp(word, "throw") && obj->quan > 1L)
429			    obj->corpsenm = 1;
430			pline("For some reason, you cannot %s%s the stone%s!",
431			      word, obj->corpsenm ? " any of" : "",
432			      plur(obj->quan));
433		}
434		obj->corpsenm = 0;		/* reset */
435		obj->bknown = 1;
436		return(FALSE);
437	}
438	if (obj->otyp == LEASH && obj->leashmon != 0) {
439		if (*word)
440			pline_The("leash is tied around your %s.",
441					body_part(HAND));
442		return(FALSE);
443	}
444#ifdef STEED
445	if (obj->owornmask & W_SADDLE) {
446		if (*word)
447			You("cannot %s %s you are sitting on.", word,
448				something);
449		return (FALSE);
450	}
451#endif
452	return(TRUE);
453}
454
455STATIC_PTR
456int
457drop(obj)
458register struct obj *obj;
459{
460	if(!obj) return(0);
461	if(!canletgo(obj,"drop"))
462		return(0);
463	if(obj == uwep) {
464		if(welded(uwep)) {
465			weldmsg(obj);
466			return(0);
467		}
468		setuwep((struct obj *)0);
469	}
470	if(obj == uquiver) {
471		setuqwep((struct obj *)0);
472	}
473	if (obj == uswapwep) {
474		setuswapwep((struct obj *)0);
475	}
476
477	if (u.uswallow) {
478		/* barrier between you and the floor */
479		if(flags.verbose)
480		{
481			char buf[BUFSZ];
482
483			/* doname can call s_suffix, reusing its buffer */
484			Strcpy(buf, s_suffix(mon_nam(u.ustuck)));
485			You("drop %s into %s %s.", doname(obj), buf,
486				mbodypart(u.ustuck, STOMACH));
487		}
488	} else {
489#ifdef SINKS
490	    if((obj->oclass == RING_CLASS || obj->otyp == MEAT_RING) &&
491			IS_SINK(levl[u.ux][u.uy].typ)) {
492		dosinkring(obj);
493		return(1);
494	    }
495#endif
496	    if (!can_reach_floor()) {
497		if(flags.verbose) You("drop %s.", doname(obj));
498#ifndef GOLDOBJ
499		if (obj->oclass != COIN_CLASS || obj == invent) freeinv(obj);
500#else
501		/* Ensure update when we drop gold objects */
502		if (obj->oclass == COIN_CLASS) flags.botl = 1;
503		freeinv(obj);
504#endif
505		hitfloor(obj);
506		return(1);
507	    }
508	    if (!IS_ALTAR(levl[u.ux][u.uy].typ) && flags.verbose)
509		You("drop %s.", doname(obj));
510	}
511	dropx(obj);
512	return(1);
513}
514
515/* Called in several places - may produce output */
516/* eg ship_object() and dropy() -> sellobj() both produce output */
517void
518dropx(obj)
519register struct obj *obj;
520{
521#ifndef GOLDOBJ
522	if (obj->oclass != COIN_CLASS || obj == invent) freeinv(obj);
523#else
524        /* Ensure update when we drop gold objects */
525        if (obj->oclass == COIN_CLASS) flags.botl = 1;
526        freeinv(obj);
527#endif
528	if (!u.uswallow) {
529	    if (ship_object(obj, u.ux, u.uy, FALSE)) return;
530	    if (IS_ALTAR(levl[u.ux][u.uy].typ))
531		doaltarobj(obj); /* set bknown */
532	}
533	dropy(obj);
534}
535
536void
537dropy(obj)
538register struct obj *obj;
539{
540	if (obj == uwep) setuwep((struct obj *)0);
541	if (obj == uquiver) setuqwep((struct obj *)0);
542	if (obj == uswapwep) setuswapwep((struct obj *)0);
543
544	if (!u.uswallow && flooreffects(obj,u.ux,u.uy,"drop")) return;
545	/* uswallow check done by GAN 01/29/87 */
546	if(u.uswallow) {
547	    boolean could_petrify = FALSE;
548	    boolean could_poly = FALSE;
549	    boolean could_slime = FALSE;
550	    boolean could_grow = FALSE;
551	    boolean could_heal = FALSE;
552
553	    if (obj != uball) {		/* mon doesn't pick up ball */
554		if (obj->otyp == CORPSE) {
555		    could_petrify = touch_petrifies(&mons[obj->corpsenm]);
556		    could_poly = polyfodder(obj);
557		    could_slime = (obj->corpsenm == PM_GREEN_SLIME);
558		    could_grow = (obj->corpsenm == PM_WRAITH);
559		    could_heal = (obj->corpsenm == PM_NURSE);
560		}
561		(void) mpickobj(u.ustuck,obj);
562		if (is_animal(u.ustuck->data)) {
563		    if (could_poly || could_slime) {
564			(void) newcham(u.ustuck,
565				       could_poly ? (struct permonst *)0 :
566				       &mons[PM_GREEN_SLIME],
567				       FALSE, could_slime);
568			delobj(obj);	/* corpse is digested */
569		    } else if (could_petrify) {
570			minstapetrify(u.ustuck, TRUE);
571			/* Don't leave a cockatrice corpse in a statue */
572			if (!u.uswallow) delobj(obj);
573		    } else if (could_grow) {
574			(void) grow_up(u.ustuck, (struct monst *)0);
575			delobj(obj);	/* corpse is digested */
576		    } else if (could_heal) {
577			u.ustuck->mhp = u.ustuck->mhpmax;
578			delobj(obj);	/* corpse is digested */
579		    }
580		}
581	    }
582	} else  {
583	    place_object(obj, u.ux, u.uy);
584	    if (obj == uball)
585		drop_ball(u.ux,u.uy);
586	    else
587		sellobj(obj, u.ux, u.uy);
588	    stackobj(obj);
589	    if(Blind && Levitation)
590		map_object(obj, 0);
591	    newsym(u.ux,u.uy);	/* remap location under self */
592	}
593}
594
595/* things that must change when not held; recurse into containers.
596   Called for both player and monsters */
597void
598obj_no_longer_held(obj)
599struct obj *obj;
600{
601	if (!obj) {
602	    return;
603	} else if ((Is_container(obj) || obj->otyp == STATUE) && obj->cobj) {
604	    struct obj *contents;
605	    for(contents=obj->cobj; contents; contents=contents->nobj)
606		obj_no_longer_held(contents);
607	}
608	switch(obj->otyp) {
609	case CRYSKNIFE:
610	    /* KMH -- Fixed crysknives have only 10% chance of reverting */
611	    /* only changes when not held by player or monster */
612	    if (!obj->oerodeproof || !rn2(10)) {
613		obj->otyp = WORM_TOOTH;
614		obj->oerodeproof = 0;
615	    }
616	    break;
617	}
618}
619
620/* 'D' command: drop several things */
621int
622doddrop()
623{
624	int result = 0;
625
626	add_valid_menu_class(0); /* clear any classes already there */
627	if (*u.ushops) sellobj_state(SELL_DELIBERATE);
628	if (flags.menu_style != MENU_TRADITIONAL ||
629		(result = ggetobj("drop", drop, 0, FALSE, (unsigned *)0)) < -1)
630	    result = menu_drop(result);
631	if (*u.ushops) sellobj_state(SELL_NORMAL);
632	reset_occupations();
633
634	return result;
635}
636
637/* Drop things from the hero's inventory, using a menu. */
638STATIC_OVL int
639menu_drop(retry)
640int retry;
641{
642    int n, i, n_dropped = 0;
643    long cnt;
644    struct obj *otmp, *otmp2;
645#ifndef GOLDOBJ
646    struct obj *u_gold = 0;
647#endif
648    menu_item *pick_list;
649    boolean all_categories = TRUE;
650    boolean drop_everything = FALSE;
651
652#ifndef GOLDOBJ
653    if (u.ugold) {
654	/* Hack: gold is not in the inventory, so make a gold object
655	   and put it at the head of the inventory list. */
656	u_gold = mkgoldobj(u.ugold);	/* removes from u.ugold */
657	u_gold->in_use = TRUE;
658	u.ugold = u_gold->quan;		/* put the gold back */
659	assigninvlet(u_gold);		/* might end up as NOINVSYM */
660	u_gold->nobj = invent;
661	invent = u_gold;
662    }
663#endif
664    if (retry) {
665	all_categories = (retry == -2);
666    } else if (flags.menu_style == MENU_FULL) {
667	all_categories = FALSE;
668	n = query_category("Drop what type of items?",
669			invent,
670			UNPAID_TYPES | ALL_TYPES | CHOOSE_ALL |
671			BUC_BLESSED | BUC_CURSED | BUC_UNCURSED | BUC_UNKNOWN,
672			&pick_list, PICK_ANY);
673	if (!n) goto drop_done;
674	for (i = 0; i < n; i++) {
675	    if (pick_list[i].item.a_int == ALL_TYPES_SELECTED)
676		all_categories = TRUE;
677	    else if (pick_list[i].item.a_int == 'A')
678		drop_everything = TRUE;
679	    else
680		add_valid_menu_class(pick_list[i].item.a_int);
681	}
682	free((genericptr_t) pick_list);
683    } else if (flags.menu_style == MENU_COMBINATION) {
684	unsigned ggoresults = 0;
685	all_categories = FALSE;
686	/* Gather valid classes via traditional NetHack method */
687	i = ggetobj("drop", drop, 0, TRUE, &ggoresults);
688	if (i == -2) all_categories = TRUE;
689	if (ggoresults & ALL_FINISHED) {
690		n_dropped = i;
691		goto drop_done;
692	}
693    }
694
695    if (drop_everything) {
696	for(otmp = invent; otmp; otmp = otmp2) {
697	    otmp2 = otmp->nobj;
698	    n_dropped += drop(otmp);
699	}
700    } else {
701	/* should coordinate with perm invent, maybe not show worn items */
702	n = query_objlist("What would you like to drop?", invent,
703			USE_INVLET|INVORDER_SORT, &pick_list,
704			PICK_ANY, all_categories ? allow_all : allow_category);
705	if (n > 0) {
706	    for (i = 0; i < n; i++) {
707		otmp = pick_list[i].item.a_obj;
708		cnt = pick_list[i].count;
709		if (cnt < otmp->quan) {
710		    if (welded(otmp)) {
711			;	/* don't split */
712		    } else if (otmp->otyp == LOADSTONE && otmp->cursed) {
713			/* same kludge as getobj(), for canletgo()'s use */
714			otmp->corpsenm = (int) cnt;	/* don't split */
715		    } else {
716#ifndef GOLDOBJ
717			if (otmp->oclass == COIN_CLASS)
718			    (void) splitobj(otmp, otmp->quan - cnt);
719			else
720#endif
721			    otmp = splitobj(otmp, cnt);
722		    }
723		}
724		n_dropped += drop(otmp);
725	    }
726	    free((genericptr_t) pick_list);
727	}
728    }
729
730 drop_done:
731#ifndef GOLDOBJ
732    if (u_gold && invent && invent->oclass == COIN_CLASS) {
733	/* didn't drop [all of] it */
734	u_gold = invent;
735	invent = u_gold->nobj;
736	u_gold->in_use = FALSE;
737	dealloc_obj(u_gold);
738	update_inventory();
739    }
740#endif
741    return n_dropped;
742}
743
744#endif /* OVL0 */
745#ifdef OVL2
746
747/* on a ladder, used in goto_level */
748static NEARDATA boolean at_ladder = FALSE;
749
750int
751dodown()
752{
753	struct trap *trap = 0;
754	boolean stairs_down = ((u.ux == xdnstair && u.uy == ydnstair) ||
755		    (u.ux == sstairs.sx && u.uy == sstairs.sy && !sstairs.up)),
756		ladder_down = (u.ux == xdnladder && u.uy == ydnladder);
757
758#ifdef STEED
759	if (u.usteed && !u.usteed->mcanmove) {
760		pline("%s won't move!", Monnam(u.usteed));
761		return(0);
762	} else if (u.usteed && u.usteed->meating) {
763		pline("%s is still eating.", Monnam(u.usteed));
764		return(0);
765	} else
766#endif
767	if (Levitation) {
768	    if ((HLevitation & I_SPECIAL) || (ELevitation & W_ARTI)) {
769		/* end controlled levitation */
770		if (ELevitation & W_ARTI) {
771		    struct obj *obj;
772
773		    for(obj = invent; obj; obj = obj->nobj) {
774			if (obj->oartifact &&
775					artifact_has_invprop(obj,LEVITATION)) {
776			    if (obj->age < monstermoves)
777				obj->age = monstermoves + rnz(100);
778			    else
779				obj->age += rnz(100);
780			}
781		    }
782		}
783		if (float_down(I_SPECIAL|TIMEOUT, W_ARTI))
784		    return (1);   /* came down, so moved */
785	    }
786	    floating_above(stairs_down ? "stairs" : ladder_down ?
787			   "ladder" : surface(u.ux, u.uy));
788	    return (0);   /* didn't move */
789	}
790	if (!stairs_down && !ladder_down) {
791		if (!(trap = t_at(u.ux,u.uy)) ||
792			(trap->ttyp != TRAPDOOR && trap->ttyp != HOLE)
793			|| !Can_fall_thru(&u.uz) || !trap->tseen) {
794
795			if (flags.autodig && !flags.nopick &&
796				uwep && is_pick(uwep)) {
797				return use_pick_axe2(uwep);
798			} else {
799				You_cant("go down here.");
800				return(0);
801			}
802		}
803	}
804	if(u.ustuck) {
805		You("are %s, and cannot go down.",
806			!u.uswallow ? "being held" : is_animal(u.ustuck->data) ?
807			"swallowed" : "engulfed");
808		return(1);
809	}
810	if (on_level(&valley_level, &u.uz) && !u.uevent.gehennom_entered) {
811		You("are standing at the gate to Gehennom.");
812		pline("Unspeakable cruelty and harm lurk down there.");
813		if (yn("Are you sure you want to enter?") != 'y')
814			return(0);
815		else pline("So be it.");
816		u.uevent.gehennom_entered = 1;	/* don't ask again */
817	}
818
819	if(!next_to_u()) {
820		You("are held back by your pet!");
821		return(0);
822	}
823
824	if (trap)
825	    You("%s %s.", locomotion(youmonst.data, "jump"),
826		trap->ttyp == HOLE ? "down the hole" : "through the trap door");
827
828	if (trap && Is_stronghold(&u.uz)) {
829		goto_hell(FALSE, TRUE);
830	} else {
831		at_ladder = (boolean) (levl[u.ux][u.uy].typ == LADDER);
832		next_level(!trap);
833		at_ladder = FALSE;
834	}
835	return(1);
836}
837
838int
839doup()
840{
841	if( (u.ux != xupstair || u.uy != yupstair)
842	     && (!xupladder || u.ux != xupladder || u.uy != yupladder)
843	     && (!sstairs.sx || u.ux != sstairs.sx || u.uy != sstairs.sy
844			|| !sstairs.up)
845	  ) {
846		You_cant("go up here.");
847		return(0);
848	}
849#ifdef STEED
850	if (u.usteed && !u.usteed->mcanmove) {
851		pline("%s won't move!", Monnam(u.usteed));
852		return(0);
853	} else if (u.usteed && u.usteed->meating) {
854		pline("%s is still eating.", Monnam(u.usteed));
855		return(0);
856	} else
857#endif
858	if(u.ustuck) {
859		You("are %s, and cannot go up.",
860			!u.uswallow ? "being held" : is_animal(u.ustuck->data) ?
861			"swallowed" : "engulfed");
862		return(1);
863	}
864	if(near_capacity() > SLT_ENCUMBER) {
865		/* No levitation check; inv_weight() already allows for it */
866		Your("load is too heavy to climb the %s.",
867			levl[u.ux][u.uy].typ == STAIRS ? "stairs" : "ladder");
868		return(1);
869	}
870	if(ledger_no(&u.uz) == 1) {
871		if (yn("Beware, there will be no return! Still climb?") != 'y')
872			return(0);
873	}
874	if(!next_to_u()) {
875		You("are held back by your pet!");
876		return(0);
877	}
878	at_ladder = (boolean) (levl[u.ux][u.uy].typ == LADDER);
879	prev_level(TRUE);
880	at_ladder = FALSE;
881	return(1);
882}
883
884d_level save_dlevel = {0, 0};
885
886/* check that we can write out the current level */
887STATIC_OVL int
888currentlevel_rewrite()
889{
890	register int fd;
891	char whynot[BUFSZ];
892
893	/* since level change might be a bit slow, flush any buffered screen
894	 *  output (like "you fall through a trap door") */
895	mark_synch();
896
897	fd = create_levelfile(ledger_no(&u.uz), whynot);
898	if (fd < 0) {
899		/*
900		 * This is not quite impossible: e.g., we may have
901		 * exceeded our quota. If that is the case then we
902		 * cannot leave this level, and cannot save either.
903		 * Another possibility is that the directory was not
904		 * writable.
905		 */
906		pline("%s", whynot);
907		return -1;
908	}
909
910#ifdef MFLOPPY
911	if (!savelev(fd, ledger_no(&u.uz), COUNT_SAVE)) {
912		(void) close(fd);
913		delete_levelfile(ledger_no(&u.uz));
914		pline("NetHack is out of disk space for making levels!");
915		You("can save, quit, or continue playing.");
916		return -1;
917	}
918#endif
919	return fd;
920}
921
922#ifdef INSURANCE
923void
924save_currentstate()
925{
926	int fd;
927
928	if (flags.ins_chkpt) {
929		/* write out just-attained level, with pets and everything */
930		fd = currentlevel_rewrite();
931		if(fd < 0) return;
932		bufon(fd);
933		savelev(fd,ledger_no(&u.uz), WRITE_SAVE);
934		bclose(fd);
935	}
936
937	/* write out non-level state */
938	savestateinlock();
939}
940#endif
941
942/*
943static boolean
944badspot(x, y)
945register xchar x, y;
946{
947	return((levl[x][y].typ != ROOM && levl[x][y].typ != AIR &&
948			 levl[x][y].typ != CORR) || MON_AT(x, y));
949}
950*/
951
952void
953goto_level(newlevel, at_stairs, falling, portal)
954d_level *newlevel;
955boolean at_stairs, falling, portal;
956{
957	int fd, l_idx;
958	xchar new_ledger;
959	boolean cant_go_back,
960		up = (depth(newlevel) < depth(&u.uz)),
961		newdungeon = (u.uz.dnum != newlevel->dnum),
962		was_in_W_tower = In_W_tower(u.ux, u.uy, &u.uz),
963		familiar = FALSE;
964	boolean new = FALSE;	/* made a new level? */
965	struct monst *mtmp;
966	char whynot[BUFSZ];
967
968	if (dunlev(newlevel) > dunlevs_in_dungeon(newlevel))
969		newlevel->dlevel = dunlevs_in_dungeon(newlevel);
970	if (newdungeon && In_endgame(newlevel)) { /* 1st Endgame Level !!! */
971		if (u.uhave.amulet)
972		    assign_level(newlevel, &earth_level);
973		else return;
974	}
975	new_ledger = ledger_no(newlevel);
976	if (new_ledger <= 0)
977		done(ESCAPED);	/* in fact < 0 is impossible */
978
979	/* If you have the amulet and are trying to get out of Gehennom, going
980	 * up a set of stairs sometimes does some very strange things!
981	 * Biased against law and towards chaos, but not nearly as strongly
982	 * as it used to be (prior to 3.2.0).
983	 * Odds:	    old				    new
984	 *	"up"    L      N      C		"up"    L      N      C
985	 *	 +1   75.0   75.0   75.0	 +1   75.0   75.0   75.0
986	 *	  0    0.0   12.5   25.0	  0    6.25   8.33  12.5
987	 *	 -1    8.33   4.17   0.0	 -1    6.25   8.33  12.5
988	 *	 -2    8.33   4.17   0.0	 -2    6.25   8.33   0.0
989	 *	 -3    8.33   4.17   0.0	 -3    6.25   0.0    0.0
990	 */
991	if (Inhell && up && u.uhave.amulet && !newdungeon && !portal &&
992				(dunlev(&u.uz) < dunlevs_in_dungeon(&u.uz)-3)) {
993		if (!rn2(4)) {
994		    int odds = 3 + (int)u.ualign.type,		/* 2..4 */
995			diff = odds <= 1 ? 0 : rn2(odds);	/* paranoia */
996
997		    if (diff != 0) {
998			assign_rnd_level(newlevel, &u.uz, diff);
999			/* if inside the tower, stay inside */
1000			if (was_in_W_tower &&
1001			    !On_W_tower_level(newlevel)) diff = 0;
1002		    }
1003		    if (diff == 0)
1004			assign_level(newlevel, &u.uz);
1005
1006		    new_ledger = ledger_no(newlevel);
1007
1008		    pline("A mysterious force momentarily surrounds you...");
1009		    if (on_level(newlevel, &u.uz)) {
1010			(void) safe_teleds(FALSE);
1011			(void) next_to_u();
1012			return;
1013		    } else
1014			at_stairs = at_ladder = FALSE;
1015		}
1016	}
1017
1018	/* Prevent the player from going past the first quest level unless
1019	 * (s)he has been given the go-ahead by the leader.
1020	 */
1021	if (on_level(&u.uz, &qstart_level) && !newdungeon && !ok_to_quest()) {
1022		pline("A mysterious force prevents you from descending.");
1023		return;
1024	}
1025
1026	if (on_level(newlevel, &u.uz)) return;		/* this can happen */
1027
1028	fd = currentlevel_rewrite();
1029	if (fd < 0) return;
1030
1031	if (falling) /* assuming this is only trap door or hole */
1032	    impact_drop((struct obj *)0, u.ux, u.uy, newlevel->dlevel);
1033
1034	check_special_room(TRUE);		/* probably was a trap door */
1035	if (Punished) unplacebc();
1036	u.utrap = 0;				/* needed in level_tele */
1037	fill_pit(u.ux, u.uy);
1038	u.ustuck = 0;				/* idem */
1039	u.uinwater = 0;
1040	u.uundetected = 0;	/* not hidden, even if means are available */
1041	keepdogs(FALSE);
1042	if (u.uswallow)				/* idem */
1043		u.uswldtim = u.uswallow = 0;
1044	/*
1045	 *  We no longer see anything on the level.  Make sure that this
1046	 *  follows u.uswallow set to null since uswallow overrides all
1047	 *  normal vision.
1048	 */
1049	vision_recalc(2);
1050
1051	/*
1052	 * Save the level we're leaving.  If we're entering the endgame,
1053	 * we can get rid of all existing levels because they cannot be
1054	 * reached any more.  We still need to use savelev()'s cleanup
1055	 * for the level being left, to recover dynamic memory in use and
1056	 * to avoid dangling timers and light sources.
1057	 */
1058	cant_go_back = (newdungeon && In_endgame(newlevel));
1059	if (!cant_go_back) {
1060	    update_mlstmv();	/* current monsters are becoming inactive */
1061	    bufon(fd);		/* use buffered output */
1062	}
1063	savelev(fd, ledger_no(&u.uz),
1064		cant_go_back ? FREE_SAVE : (WRITE_SAVE | FREE_SAVE));
1065	bclose(fd);
1066	if (cant_go_back) {
1067	    /* discard unreachable levels; keep #0 */
1068	    for (l_idx = maxledgerno(); l_idx > 0; --l_idx)
1069		delete_levelfile(l_idx);
1070	}
1071
1072#ifdef REINCARNATION
1073	if (Is_rogue_level(newlevel) || Is_rogue_level(&u.uz))
1074		assign_rogue_graphics(Is_rogue_level(newlevel));
1075#endif
1076#ifdef USE_TILES
1077	substitute_tiles(newlevel);
1078#endif
1079	assign_level(&u.uz0, &u.uz);
1080	assign_level(&u.uz, newlevel);
1081	assign_level(&u.utolev, newlevel);
1082	u.utotype = 0;
1083	if (dunlev_reached(&u.uz) < dunlev(&u.uz))
1084		dunlev_reached(&u.uz) = dunlev(&u.uz);
1085	reset_rndmonst(NON_PM);   /* u.uz change affects monster generation */
1086
1087	/* set default level change destination areas */
1088	/* the special level code may override these */
1089	(void) memset((genericptr_t) &updest, 0, sizeof updest);
1090	(void) memset((genericptr_t) &dndest, 0, sizeof dndest);
1091
1092	if (!(level_info[new_ledger].flags & LFILE_EXISTS)) {
1093		/* entering this level for first time; make it now */
1094		if (level_info[new_ledger].flags & (FORGOTTEN|VISITED)) {
1095		    impossible("goto_level: returning to discarded level?");
1096		    level_info[new_ledger].flags &= ~(FORGOTTEN|VISITED);
1097		}
1098		mklev();
1099		new = TRUE;	/* made the level */
1100	} else {
1101		/* returning to previously visited level; reload it */
1102		fd = open_levelfile(new_ledger, whynot);
1103		if (fd < 0) {
1104			pline("%s", whynot);
1105			pline("Probably someone removed it.");
1106			killer = whynot;
1107			done(TRICKED);
1108			/* we'll reach here if running in wizard mode */
1109			error("Cannot continue this game.");
1110		}
1111		minit();	/* ZEROCOMP */
1112		getlev(fd, hackpid, new_ledger, FALSE);
1113		(void) close(fd);
1114	}
1115	/* do this prior to level-change pline messages */
1116	vision_reset();		/* clear old level's line-of-sight */
1117	vision_full_recalc = 0;	/* don't let that reenable vision yet */
1118	flush_screen(-1);	/* ensure all map flushes are postponed */
1119
1120	if (portal && !In_endgame(&u.uz)) {
1121	    /* find the portal on the new level */
1122	    register struct trap *ttrap;
1123
1124	    for (ttrap = ftrap; ttrap; ttrap = ttrap->ntrap)
1125		if (ttrap->ttyp == MAGIC_PORTAL) break;
1126
1127	    if (!ttrap) panic("goto_level: no corresponding portal!");
1128	    seetrap(ttrap);
1129	    u_on_newpos(ttrap->tx, ttrap->ty);
1130	} else if (at_stairs && !In_endgame(&u.uz)) {
1131	    if (up) {
1132		if (at_ladder) {
1133		    u_on_newpos(xdnladder, ydnladder);
1134		} else {
1135		    if (newdungeon) {
1136			if (Is_stronghold(&u.uz)) {
1137			    register xchar x, y;
1138
1139			    do {
1140				x = (COLNO - 2 - rnd(5));
1141				y = rn1(ROWNO - 4, 3);
1142			    } while(occupied(x, y) ||
1143				    IS_WALL(levl[x][y].typ));
1144			    u_on_newpos(x, y);
1145			} else u_on_sstairs();
1146		    } else u_on_dnstairs();
1147		}
1148		/* Remove bug which crashes with levitation/punishment  KAA */
1149		if (Punished && !Levitation) {
1150			pline("With great effort you climb the %s.",
1151				at_ladder ? "ladder" : "stairs");
1152		} else if (at_ladder)
1153		    You("climb up the ladder.");
1154	    } else {	/* down */
1155		if (at_ladder) {
1156		    u_on_newpos(xupladder, yupladder);
1157		} else {
1158		    if (newdungeon) u_on_sstairs();
1159		    else u_on_upstairs();
1160		}
1161		if (u.dz && Flying)
1162		    You("fly down along the %s.",
1163			at_ladder ? "ladder" : "stairs");
1164		else if (u.dz &&
1165		    (near_capacity() > UNENCUMBERED || Punished || Fumbling)) {
1166		    You("fall down the %s.", at_ladder ? "ladder" : "stairs");
1167		    if (Punished) {
1168			drag_down();
1169			if (carried(uball)) {
1170			    if (uwep == uball)
1171				setuwep((struct obj *)0);
1172			    if (uswapwep == uball)
1173				setuswapwep((struct obj *)0);
1174			    if (uquiver == uball)
1175				setuqwep((struct obj *)0);
1176			    freeinv(uball);
1177			}
1178		    }
1179#ifdef STEED
1180		    /* falling off steed has its own losehp() call */
1181		    if (u.usteed)
1182			dismount_steed(DISMOUNT_FELL);
1183		    else
1184#endif
1185			losehp(rnd(3), "falling downstairs", KILLED_BY);
1186		    selftouch("Falling, you");
1187		} else if (u.dz && at_ladder)
1188		    You("climb down the ladder.");
1189	    }
1190	} else {	/* trap door or level_tele or In_endgame */
1191	    if (was_in_W_tower && On_W_tower_level(&u.uz))
1192		/* Stay inside the Wizard's tower when feasible.	*/
1193		/* Note: up vs down doesn't really matter in this case. */
1194		place_lregion(dndest.nlx, dndest.nly,
1195				dndest.nhx, dndest.nhy,
1196				0,0, 0,0, LR_DOWNTELE, (d_level *) 0);
1197	    else if (up)
1198		place_lregion(updest.lx, updest.ly,
1199				updest.hx, updest.hy,
1200				updest.nlx, updest.nly,
1201				updest.nhx, updest.nhy,
1202				LR_UPTELE, (d_level *) 0);
1203	    else
1204		place_lregion(dndest.lx, dndest.ly,
1205				dndest.hx, dndest.hy,
1206				dndest.nlx, dndest.nly,
1207				dndest.nhx, dndest.nhy,
1208				LR_DOWNTELE, (d_level *) 0);
1209	    if (falling) {
1210		if (Punished) ballfall();
1211		selftouch("Falling, you");
1212	    }
1213	}
1214
1215	if (Punished) placebc();
1216	obj_delivery();		/* before killing geno'd monsters' eggs */
1217	losedogs();
1218	kill_genocided_monsters();  /* for those wiped out while in limbo */
1219	/*
1220	 * Expire all timers that have gone off while away.  Must be
1221	 * after migrating monsters and objects are delivered
1222	 * (losedogs and obj_delivery).
1223	 */
1224	run_timers();
1225
1226	initrack();
1227
1228	if ((mtmp = m_at(u.ux, u.uy)) != 0
1229#ifdef STEED
1230		&& mtmp != u.usteed
1231#endif
1232		) {
1233	    /* There's a monster at your target destination; it might be one
1234	       which accompanied you--see mon_arrive(dogmove.c)--or perhaps
1235	       it was already here.  Randomly move you to an adjacent spot
1236	       or else the monster to any nearby location.  Prior to 3.3.0
1237	       the latter was done unconditionally. */
1238	    coord cc;
1239
1240	    if (!rn2(2) &&
1241		    enexto(&cc, u.ux, u.uy, youmonst.data) &&
1242		    distu(cc.x, cc.y) <= 2)
1243		u_on_newpos(cc.x, cc.y);	/*[maybe give message here?]*/
1244	    else
1245		mnexto(mtmp);
1246
1247	    if ((mtmp = m_at(u.ux, u.uy)) != 0) {
1248		impossible("mnexto failed (do.c)?");
1249		(void) rloc(mtmp, FALSE);
1250	    }
1251	}
1252
1253	/* initial movement of bubbles just before vision_recalc */
1254	if (Is_waterlevel(&u.uz))
1255		movebubbles();
1256
1257	if (level_info[new_ledger].flags & FORGOTTEN) {
1258	    forget_map(ALL_MAP);	/* forget the map */
1259	    forget_traps();		/* forget all traps too */
1260	    familiar = TRUE;
1261	    level_info[new_ledger].flags &= ~FORGOTTEN;
1262	}
1263
1264	/* Reset the screen. */
1265	vision_reset();		/* reset the blockages */
1266	docrt();		/* does a full vision recalc */
1267	flush_screen(-1);
1268
1269	/*
1270	 *  Move all plines beyond the screen reset.
1271	 */
1272
1273	/* give room entrance message, if any */
1274	check_special_room(FALSE);
1275
1276	/* Check whether we just entered Gehennom. */
1277	if (!In_hell(&u.uz0) && Inhell) {
1278	    if (Is_valley(&u.uz)) {
1279		You("arrive at the Valley of the Dead...");
1280		pline_The("odor of burnt flesh and decay pervades the air.");
1281#ifdef MICRO
1282		display_nhwindow(WIN_MESSAGE, FALSE);
1283#endif
1284		You_hear("groans and moans everywhere.");
1285	    } else pline("It is hot here.  You smell smoke...");
1286	}
1287
1288	if (familiar) {
1289	    static const char * const fam_msgs[4] = {
1290		"You have a sense of deja vu.",
1291		"You feel like you've been here before.",
1292		"This place %s familiar...",
1293		0	/* no message */
1294	    };
1295	    static const char * const halu_fam_msgs[4] = {
1296		"Whoa!  Everything %s different.",
1297		"You are surrounded by twisty little passages, all alike.",
1298		"Gee, this %s like uncle Conan's place...",
1299		0	/* no message */
1300	    };
1301	    const char *mesg;
1302	    char buf[BUFSZ];
1303	    int which = rn2(4);
1304
1305	    if (Hallucination)
1306		mesg = halu_fam_msgs[which];
1307	    else
1308		mesg = fam_msgs[which];
1309	    if (mesg && index(mesg, '%')) {
1310		Sprintf(buf, mesg, !Blind ? "looks" : "seems");
1311		mesg = buf;
1312	    }
1313	    if (mesg) pline(mesg);
1314	}
1315
1316#ifdef REINCARNATION
1317	if (new && Is_rogue_level(&u.uz))
1318	    You("enter what seems to be an older, more primitive world.");
1319#endif
1320	/* Final confrontation */
1321	if (In_endgame(&u.uz) && newdungeon && u.uhave.amulet)
1322		resurrect();
1323	if (newdungeon && In_V_tower(&u.uz) && In_hell(&u.uz0))
1324		pline_The("heat and smoke are gone.");
1325
1326	/* the message from your quest leader */
1327	if (!In_quest(&u.uz0) && at_dgn_entrance("The Quest") &&
1328		!(u.uevent.qexpelled || u.uevent.qcompleted || quest_status.leader_is_dead)) {
1329
1330		if (u.uevent.qcalled) {
1331			com_pager(Role_if(PM_ROGUE) ? 4 : 3);
1332		} else {
1333			com_pager(2);
1334			u.uevent.qcalled = TRUE;
1335		}
1336	}
1337
1338	/* once Croesus is dead, his alarm doesn't work any more */
1339	if (Is_knox(&u.uz) && (new || !mvitals[PM_CROESUS].died)) {
1340		You("penetrated a high security area!");
1341		pline("An alarm sounds!");
1342		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
1343		    if (!DEADMONSTER(mtmp) && mtmp->msleeping) mtmp->msleeping = 0;
1344	}
1345
1346	if (on_level(&u.uz, &astral_level))
1347	    final_level();
1348	else
1349	    onquest();
1350	assign_level(&u.uz0, &u.uz); /* reset u.uz0 */
1351
1352#ifdef INSURANCE
1353	save_currentstate();
1354#endif
1355
1356	/* assume this will always return TRUE when changing level */
1357	(void) in_out_region(u.ux, u.uy);
1358	(void) pickup(1);
1359}
1360
1361STATIC_OVL void
1362final_level()
1363{
1364	struct monst *mtmp;
1365	struct obj *otmp;
1366	coord mm;
1367	int i;
1368
1369	/* reset monster hostility relative to player */
1370	for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
1371	    if (!DEADMONSTER(mtmp)) reset_hostility(mtmp);
1372
1373	/* create some player-monsters */
1374	create_mplayers(rn1(4, 3), TRUE);
1375
1376	/* create a guardian angel next to player, if worthy */
1377	if (Conflict) {
1378	    pline(
1379	     "A voice booms: \"Thy desire for conflict shall be fulfilled!\"");
1380	    for (i = rnd(4); i > 0; --i) {
1381		mm.x = u.ux;
1382		mm.y = u.uy;
1383		if (enexto(&mm, mm.x, mm.y, &mons[PM_ANGEL]))
1384		    (void) mk_roamer(&mons[PM_ANGEL], u.ualign.type,
1385				     mm.x, mm.y, FALSE);
1386	    }
1387
1388	} else if (u.ualign.record > 8) {	/* fervent */
1389	    pline("A voice whispers: \"Thou hast been worthy of me!\"");
1390	    mm.x = u.ux;
1391	    mm.y = u.uy;
1392	    if (enexto(&mm, mm.x, mm.y, &mons[PM_ANGEL])) {
1393		if ((mtmp = mk_roamer(&mons[PM_ANGEL], u.ualign.type,
1394				      mm.x, mm.y, TRUE)) != 0) {
1395		    if (!Blind)
1396			pline("An angel appears near you.");
1397		    else
1398			You_feel("the presence of a friendly angel near you.");
1399		    /* guardian angel -- the one case mtame doesn't
1400		     * imply an edog structure, so we don't want to
1401		     * call tamedog().
1402		     */
1403		    mtmp->mtame = 10;
1404		    /* make him strong enough vs. endgame foes */
1405		    mtmp->m_lev = rn1(8,15);
1406		    mtmp->mhp = mtmp->mhpmax =
1407					d((int)mtmp->m_lev,10) + 30 + rnd(30);
1408		    if ((otmp = select_hwep(mtmp)) == 0) {
1409			otmp = mksobj(SILVER_SABER, FALSE, FALSE);
1410			if (mpickobj(mtmp, otmp))
1411			    panic("merged weapon?");
1412		    }
1413		    bless(otmp);
1414		    if (otmp->spe < 4) otmp->spe += rnd(4);
1415		    if ((otmp = which_armor(mtmp, W_ARMS)) == 0 ||
1416			    otmp->otyp != SHIELD_OF_REFLECTION) {
1417			(void) mongets(mtmp, AMULET_OF_REFLECTION);
1418			m_dowear(mtmp, TRUE);
1419		    }
1420		}
1421	    }
1422	}
1423}
1424
1425static char *dfr_pre_msg = 0,	/* pline() before level change */
1426	    *dfr_post_msg = 0;	/* pline() after level change */
1427
1428/* change levels at the end of this turn, after monsters finish moving */
1429void
1430schedule_goto(tolev, at_stairs, falling, portal_flag, pre_msg, post_msg)
1431d_level *tolev;
1432boolean at_stairs, falling;
1433int portal_flag;
1434const char *pre_msg, *post_msg;
1435{
1436	int typmask = 0100;		/* non-zero triggers `deferred_goto' */
1437
1438	/* destination flags (`goto_level' args) */
1439	if (at_stairs)	 typmask |= 1;
1440	if (falling)	 typmask |= 2;
1441	if (portal_flag) typmask |= 4;
1442	if (portal_flag < 0) typmask |= 0200;	/* flag for portal removal */
1443	u.utotype = typmask;
1444	/* destination level */
1445	assign_level(&u.utolev, tolev);
1446
1447	if (pre_msg)
1448	    dfr_pre_msg = strcpy((char *)alloc(strlen(pre_msg) + 1), pre_msg);
1449	if (post_msg)
1450	    dfr_post_msg = strcpy((char *)alloc(strlen(post_msg)+1), post_msg);
1451}
1452
1453/* handle something like portal ejection */
1454void
1455deferred_goto()
1456{
1457	if (!on_level(&u.uz, &u.utolev)) {
1458	    d_level dest;
1459	    int typmask = u.utotype; /* save it; goto_level zeroes u.utotype */
1460
1461	    assign_level(&dest, &u.utolev);
1462	    if (dfr_pre_msg) pline(dfr_pre_msg);
1463	    goto_level(&dest, !!(typmask&1), !!(typmask&2), !!(typmask&4));
1464	    if (typmask & 0200) {	/* remove portal */
1465		struct trap *t = t_at(u.ux, u.uy);
1466
1467		if (t) {
1468		    deltrap(t);
1469		    newsym(u.ux, u.uy);
1470		}
1471	    }
1472	    if (dfr_post_msg) pline(dfr_post_msg);
1473	}
1474	u.utotype = 0;		/* our caller keys off of this */
1475	if (dfr_pre_msg)
1476	    free((genericptr_t)dfr_pre_msg),  dfr_pre_msg = 0;
1477	if (dfr_post_msg)
1478	    free((genericptr_t)dfr_post_msg),  dfr_post_msg = 0;
1479}
1480
1481#endif /* OVL2 */
1482#ifdef OVL3
1483
1484/*
1485 * Return TRUE if we created a monster for the corpse.  If successful, the
1486 * corpse is gone.
1487 */
1488boolean
1489revive_corpse(corpse)
1490struct obj *corpse;
1491{
1492    struct monst *mtmp, *mcarry;
1493    boolean is_uwep, chewed;
1494    xchar where;
1495    char *cname, cname_buf[BUFSZ];
1496    struct obj *container = (struct obj *)0;
1497    int container_where = 0;
1498
1499    where = corpse->where;
1500    is_uwep = corpse == uwep;
1501    cname = eos(strcpy(cname_buf, "bite-covered "));
1502    Strcpy(cname, corpse_xname(corpse, TRUE));
1503    mcarry = (where == OBJ_MINVENT) ? corpse->ocarry : 0;
1504
1505    if (where == OBJ_CONTAINED) {
1506    	struct monst *mtmp2 = (struct monst *)0;
1507	container = corpse->ocontainer;
1508    	mtmp2 = get_container_location(container, &container_where, (int *)0);
1509	/* container_where is the outermost container's location even if nested */
1510	if (container_where == OBJ_MINVENT && mtmp2) mcarry = mtmp2;
1511    }
1512    mtmp = revive(corpse);	/* corpse is gone if successful */
1513
1514    if (mtmp) {
1515	chewed = (mtmp->mhp < mtmp->mhpmax);
1516	if (chewed) cname = cname_buf;	/* include "bite-covered" prefix */
1517	switch (where) {
1518	    case OBJ_INVENT:
1519		if (is_uwep)
1520		    pline_The("%s writhes out of your grasp!", cname);
1521		else
1522		    You_feel("squirming in your backpack!");
1523		break;
1524
1525	    case OBJ_FLOOR:
1526		if (cansee(mtmp->mx, mtmp->my))
1527		    pline("%s rises from the dead!", chewed ?
1528			  Adjmonnam(mtmp, "bite-covered") : Monnam(mtmp));
1529		break;
1530
1531	    case OBJ_MINVENT:		/* probably a nymph's */
1532		if (cansee(mtmp->mx, mtmp->my)) {
1533		    if (canseemon(mcarry))
1534			pline("Startled, %s drops %s as it revives!",
1535			      mon_nam(mcarry), an(cname));
1536		    else
1537			pline("%s suddenly appears!", chewed ?
1538			      Adjmonnam(mtmp, "bite-covered") : Monnam(mtmp));
1539		}
1540		break;
1541	   case OBJ_CONTAINED:
1542	   	if (container_where == OBJ_MINVENT && cansee(mtmp->mx, mtmp->my) &&
1543		    mcarry && canseemon(mcarry) && container) {
1544		        char sackname[BUFSZ];
1545		        Sprintf(sackname, "%s %s", s_suffix(mon_nam(mcarry)),
1546				xname(container));
1547	   		pline("%s writhes out of %s!", Amonnam(mtmp), sackname);
1548	   	} else if (container_where == OBJ_INVENT && container) {
1549		        char sackname[BUFSZ];
1550		        Strcpy(sackname, an(xname(container)));
1551	   		pline("%s %s out of %s in your pack!",
1552	   			Blind ? Something : Amonnam(mtmp),
1553				locomotion(mtmp->data,"writhes"),
1554	   			sackname);
1555	   	} else if (container_where == OBJ_FLOOR && container &&
1556		            cansee(mtmp->mx, mtmp->my)) {
1557		        char sackname[BUFSZ];
1558		        Strcpy(sackname, an(xname(container)));
1559			pline("%s escapes from %s!", Amonnam(mtmp), sackname);
1560		}
1561		break;
1562	    default:
1563		/* we should be able to handle the other cases... */
1564		impossible("revive_corpse: lost corpse @ %d", where);
1565		break;
1566	}
1567	return TRUE;
1568    }
1569    return FALSE;
1570}
1571
1572/* Revive the corpse via a timeout. */
1573/*ARGSUSED*/
1574void
1575revive_mon(arg, timeout)
1576genericptr_t arg;
1577long timeout;
1578{
1579    struct obj *body = (struct obj *) arg;
1580
1581    /* if we succeed, the corpse is gone, otherwise, rot it away */
1582    if (!revive_corpse(body)) {
1583	if (is_rider(&mons[body->corpsenm]))
1584	    You_feel("less hassled.");
1585	(void) start_timer(250L - (monstermoves-body->age),
1586					TIMER_OBJECT, ROT_CORPSE, arg);
1587    }
1588}
1589
1590int
1591donull()
1592{
1593	return(1);	/* Do nothing, but let other things happen */
1594}
1595
1596#endif /* OVL3 */
1597#ifdef OVLB
1598
1599STATIC_PTR int
1600wipeoff()
1601{
1602	if(u.ucreamed < 4)	u.ucreamed = 0;
1603	else			u.ucreamed -= 4;
1604	if (Blinded < 4)	Blinded = 0;
1605	else			Blinded -= 4;
1606	if (!Blinded) {
1607		pline("You've got the glop off.");
1608		u.ucreamed = 0;
1609		Blinded = 1;
1610		make_blinded(0L,TRUE);
1611		return(0);
1612	} else if (!u.ucreamed) {
1613		Your("%s feels clean now.", body_part(FACE));
1614		return(0);
1615	}
1616	return(1);		/* still busy */
1617}
1618
1619int
1620dowipe()
1621{
1622	if(u.ucreamed)  {
1623		static NEARDATA char buf[39];
1624
1625		Sprintf(buf, "wiping off your %s", body_part(FACE));
1626		set_occupation(wipeoff, buf, 0);
1627		/* Not totally correct; what if they change back after now
1628		 * but before they're finished wiping?
1629		 */
1630		return(1);
1631	}
1632	Your("%s is already clean.", body_part(FACE));
1633	return(1);
1634}
1635
1636void
1637set_wounded_legs(side, timex)
1638register long side;
1639register int timex;
1640{
1641	/* KMH -- STEED
1642	 * If you are riding, your steed gets the wounded legs instead.
1643	 * You still call this function, but don't lose hp.
1644	 * Caller is also responsible for adjusting messages.
1645	 */
1646
1647	if(!Wounded_legs) {
1648		ATEMP(A_DEX)--;
1649		flags.botl = 1;
1650	}
1651
1652	if(!Wounded_legs || (HWounded_legs & TIMEOUT))
1653		HWounded_legs = timex;
1654	EWounded_legs = side;
1655	(void)encumber_msg();
1656}
1657
1658void
1659heal_legs()
1660{
1661	if(Wounded_legs) {
1662		if (ATEMP(A_DEX) < 0) {
1663			ATEMP(A_DEX)++;
1664			flags.botl = 1;
1665		}
1666
1667#ifdef STEED
1668		if (!u.usteed)
1669#endif
1670		{
1671			/* KMH, intrinsics patch */
1672			if((EWounded_legs & BOTH_SIDES) == BOTH_SIDES) {
1673			Your("%s feel somewhat better.",
1674				makeplural(body_part(LEG)));
1675		} else {
1676			Your("%s feels somewhat better.",
1677				body_part(LEG));
1678		}
1679		}
1680		HWounded_legs = EWounded_legs = 0;
1681	}
1682	(void)encumber_msg();
1683}
1684
1685#endif /* OVLB */
1686
1687/*do.c*/
1688