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
12 STATIC_DCL void FDECL(trycall, (struct obj *));
13 # endif /* OVLB */
14 STATIC_DCL void FDECL(dosinkring, (struct obj *));
15 #endif /* SINKS */
16 
17 STATIC_PTR int FDECL(drop, (struct obj *));
18 STATIC_PTR int NDECL(wipeoff);
19 
20 #ifdef OVL0
21 STATIC_DCL int FDECL(menu_drop, (int));
22 #endif
23 #ifdef OVL2
24 STATIC_DCL int NDECL(currentlevel_rewrite);
25 STATIC_DCL void NDECL(final_level);
26 /* static boolean FDECL(badspot, (XCHAR_P,XCHAR_P)); */
27 #endif
28 
29 #ifdef OVLB
30 
31 static NEARDATA const char drop_types[] =
32 	{ ALLOW_COUNT, COIN_CLASS, ALL_CLASSES, 0 };
33 
34 /* 'd' command: drop one inventory item */
35 int
dodrop()36 dodrop()
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  */
59 boolean
boulder_hits_pool(otmp,rx,ry,pushing)60 boulder_hits_pool(otmp, rx, ry, pushing)
61 struct obj *otmp;
62 register int rx, ry;
63 boolean 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  */
133 boolean
flooreffects(obj,x,y,verb)134 flooreffects(obj,x,y,verb)
135 struct obj *obj;
136 int x,y;
137 const 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 
231 void
doaltarobj(obj)232 doaltarobj(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
254 STATIC_OVL
255 void
trycall(obj)256 trycall(obj)
257 register struct obj *obj;
258 {
259 	if(!objects[obj->otyp].oc_name_known &&
260 	   !objects[obj->otyp].oc_uname)
261 	   docall(obj);
262 }
263 
264 STATIC_OVL
265 void
dosinkring(obj)266 dosinkring(obj)  /* obj is a ring being dropped over a kitchen sink */
267 register 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!");
281 giveback:
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 */
411 boolean
canletgo(obj,word)412 canletgo(obj,word)
413 register struct obj *obj;
414 register 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 
455 STATIC_PTR
456 int
drop(obj)457 drop(obj)
458 register 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 */
517 void
dropx(obj)518 dropx(obj)
519 register 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 
536 void
dropy(obj)537 dropy(obj)
538 register 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 */
597 void
obj_no_longer_held(obj)598 obj_no_longer_held(obj)
599 struct 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 */
621 int
doddrop()622 doddrop()
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. */
638 STATIC_OVL int
menu_drop(retry)639 menu_drop(retry)
640 int 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 */
748 static NEARDATA boolean at_ladder = FALSE;
749 
750 int
dodown()751 dodown()
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 
838 int
doup()839 doup()
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 
884 d_level save_dlevel = {0, 0};
885 
886 /* check that we can write out the current level */
887 STATIC_OVL int
currentlevel_rewrite()888 currentlevel_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
923 void
save_currentstate()924 save_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 /*
943 static boolean
944 badspot(x, y)
945 register 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 
952 void
goto_level(newlevel,at_stairs,falling,portal)953 goto_level(newlevel, at_stairs, falling, portal)
954 d_level *newlevel;
955 boolean 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 
1361 STATIC_OVL void
final_level()1362 final_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 
1425 static 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 */
1429 void
schedule_goto(tolev,at_stairs,falling,portal_flag,pre_msg,post_msg)1430 schedule_goto(tolev, at_stairs, falling, portal_flag, pre_msg, post_msg)
1431 d_level *tolev;
1432 boolean at_stairs, falling;
1433 int portal_flag;
1434 const 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 */
1454 void
deferred_goto()1455 deferred_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  */
1488 boolean
revive_corpse(corpse)1489 revive_corpse(corpse)
1490 struct 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*/
1574 void
revive_mon(arg,timeout)1575 revive_mon(arg, timeout)
1576 genericptr_t arg;
1577 long 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 
1590 int
donull()1591 donull()
1592 {
1593 	return(1);	/* Do nothing, but let other things happen */
1594 }
1595 
1596 #endif /* OVL3 */
1597 #ifdef OVLB
1598 
1599 STATIC_PTR int
wipeoff()1600 wipeoff()
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 
1619 int
dowipe()1620 dowipe()
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 
1636 void
set_wounded_legs(side,timex)1637 set_wounded_legs(side, timex)
1638 register long side;
1639 register 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 
1658 void
heal_legs()1659 heal_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