Source:SLASH'EM 0.0.7E7F2/do.c

From NetHackWiki
Revision as of 18:56, 7 March 2008 by Kernigh bot (talk | contribs) (SLASH'EM 0.0.7E7F2/do.c moved to Source:SLASH'EM 0.0.7E7F2/do.c: Robot: moved page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Below is the full text to do.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/do.c#line123]], for example.

The latest source code for vanilla NetHack is at Source code.


The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

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