Source:NetHack 3.1.0/do.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to do.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.0/do.c#line123]], for example.

Warning! This is the source code from an old release. For the latest release, see 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.1	92/11/11	*/
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.   #include <errno.h>
11.   #ifdef _MSC_VER	/* MSC 6.0 defines errno quite differently */
12.   # if (_MSC_VER >= 600)
13.   #  define SKIP_ERRNO
14.   # endif
15.   #endif
16.   #ifndef SKIP_ERRNO
17.   extern int errno;
18.   #endif
19.   
20.   #ifdef MFLOPPY
21.   extern struct finfo fileinfo[];
22.   #else
23.   extern boolean level_exists[];
24.   #endif
25.   
26.   #ifdef SINKS
27.   # ifdef OVLB
28.   static void FDECL(trycall, (struct obj *));
29.   # endif /* OVLB */
30.   STATIC_DCL void FDECL(dosinkring, (struct obj *));
31.   #endif /* SINKS */
32.   
33.   STATIC_PTR int FDECL(drop, (struct obj *));
34.   STATIC_PTR int NDECL(wipeoff);
35.   
36.   #ifdef OVL2
37.   static int NDECL(currentlevel_rewrite);
38.   /* static boolean FDECL(badspot, (XCHAR_P,XCHAR_P)); */
39.   #endif
40.   
41.   #ifdef OVLB
42.   
43.   static const char NEARDATA drop_types[] =
44.   	{ ALLOW_COUNT, GOLD_CLASS, ALL_CLASSES, 0 };
45.   
46.   int
47.   dodrop()
48.   {
49.   	int result;
50.   
51.   	if (*u.ushops) sellobj_state(TRUE);
52.   	result = drop(getobj(drop_types, "drop"));
53.   	if (*u.ushops) sellobj_state(FALSE);
54.   	reset_occupations();
55.   
56.   	return result;
57.   }
58.   
59.   #endif /* OVLB */
60.   #ifdef OVL0
61.   
62.   /* Called when a boulder is dropped, thrown, or pushed.  If it ends up
63.    * in a pool, it either fills the pool up or sinks away.  In either case, 
64.    * it's gone for good...  If the destination is not a pool, returns FALSE.
65.    */
66.   boolean
67.   boulder_hits_pool(otmp, rx, ry, pushing)
68.   struct obj *otmp;
69.   register int rx, ry;
70.   boolean pushing;
71.   {
72.   	if (!otmp || otmp->otyp != BOULDER)
73.   	    impossible("Not a boulder?");
74.   	else if (!Is_waterlevel(&u.uz) && (is_pool(rx,ry) || is_lava(rx,ry))) {
75.   	    boolean lava = is_lava(rx,ry), fills_up;
76.   	    const char *what = lava ? "lava" : "water";
77.   	    schar ltyp = levl[rx][ry].typ;
78.   	    int chance = rn2(10);		/* water: 90%; lava: 10% */
79.   	    fills_up = lava ? chance == 0 : chance != 0;
80.   
81.   	    if (fills_up) {
82.   		if (ltyp == DRAWBRIDGE_UP) {
83.   		    levl[rx][ry].drawbridgemask &= ~DB_UNDER; /* clear lava */
84.   		    levl[rx][ry].drawbridgemask |= DB_FLOOR;
85.   		} else
86.   		    levl[rx][ry].typ = ROOM;
87.   
88.   		delallobj(rx, ry);
89.   		newsym(rx,ry);
90.   		if (pushing) {
91.   		    You("push %s into the %s.", the(xname(otmp)), what);
92.   		    if (flags.verbose && !Blind)
93.   			pline("Now you can cross it!");
94.   		    /* no splashing in this case */
95.   		}
96.   	    }
97.   	    if (!fills_up || !pushing) {	/* splashing occurs */
98.   		if (pushing ? !Blind : cansee(rx,ry))
99.   		    pline("There is a large splash as %s %s the %s.",
100.  			the(xname(otmp)), fills_up ? "fills" : "falls into",
101.  			lava ? "lava" : ltyp==POOL ? "pool" : "moat");
102.  		else if (flags.soundok)
103.  		    You("hear a%s splash.", lava ? " sizzling" : "");
104.  		wake_nearby();
105.  
106.  		if (fills_up && u.uinwater && distu(rx,ry) == 0) {
107.  		    You("find yourself on dry land again!");
108.  		    u.uinwater = 0;
109.  		} else if (lava && distu(rx,ry) <= 2) {
110.  		    You("are hit by molten lava%c",
111.  			Fire_resistance ? '.' : '!');
112.  		    losehp(d((Fire_resistance ? 1 : 3), 6),
113.  			   "molten lava", KILLED_BY);
114.  		} else if (!fills_up && flags.verbose &&
115.  			   (pushing ? !Blind : cansee(rx,ry)))
116.  		    pline("It sinks without a trace!");
117.  	    }
118.  
119.  	    /* boulder is now gone */
120.  	    if (pushing) delobj(otmp);
121.  	    else obfree(otmp, (struct obj *)0);
122.  	    return TRUE;
123.  	}
124.  	return FALSE;
125.  }
126.  
127.  /* Used for objects which sometimes do special things when dropped; must be
128.   * called with the object not in any chain.  Returns 1 if the object is
129.   * gone.
130.   */
131.  boolean
132.  flooreffects(obj,x,y,verb)
133.  struct obj *obj;
134.  int x,y;
135.  const char *verb;
136.  {
137.  	struct trap *t;
138.  
139.  	if (obj->otyp == BOULDER && boulder_hits_pool(obj, x, y, FALSE))
140.  		return TRUE;
141.  	else if (obj->otyp == BOULDER && (t = t_at(x,y)) != 0 &&
142.  		 (t->ttyp==PIT || t->ttyp==SPIKED_PIT || t->ttyp==TRAPDOOR)) {
143.  		struct monst *mtmp;
144.  
145.  		delallobj(x, y);
146.  		if(!Can_fall_thru(&u.uz) && t->ttyp == TRAPDOOR)
147.  			return FALSE;
148.  		if (((mtmp = m_at(x, y)) && mtmp->mtrapped) ||
149.  		    (u.utrap && x==u.ux && y==u.uy)) {
150.  		    /* u.utrap = 0;     /* player remains trapped. See trap.c */
151.  		    if (*verb)
152.  			pline("The boulder %ss into the pit%s.", verb, 
153.  			      (mtmp)? "" : " with you");
154.  		    if (mtmp) {
155.  			if (!passes_walls(mtmp->data) && !throws_rocks(mtmp->data))
156.  				if (hmon(mtmp, obj, TRUE))
157.  					return FALSE; 	       /* still alive */
158.  				else
159.  					delallobj(x, y);  /* treasure, corpse */
160.  		    } else
161.  #ifdef POLYSELF
162.  		    	if (!passes_walls(uasmon) && !throws_rocks(uasmon))
163.  #endif
164.  			{
165.  			       losehp(rnd(15), "squished under a boulder",
166.  			       	      NO_KILLER_PREFIX);
167.  		    	       return FALSE;
168.  			}
169.  		}
170.  		if (*verb) {
171.  			if (Blind) {
172.  				if ((x == u.ux) && (y == u.uy))
173.  					You("hear a CRASH! beneath you.");
174.  				else
175.  					You("hear the boulder %s.", verb);
176.  			} else if (cansee(x, y)) {
177.  				pline("The boulder %sfills a %s.",
178.  				      t->tseen ? "" : "triggers and ",
179.  				      t->ttyp == TRAPDOOR ? 
180.  				      "trap door" : "pit");
181.  			}
182.  		}
183.  		deltrap(t);
184.  		obfree(obj, (struct obj *)0);
185.  		newsym(x,y);
186.  		return TRUE;
187.  	}
188.  	return FALSE;
189.  }
190.  
191.  #endif /* OVL0 */
192.  #ifdef OVLB
193.  
194.  void
195.  doaltarobj(obj)  /* obj is an object dropped on an altar */
196.  	register struct obj *obj;
197.  {
198.  	if (Blind) return;
199.  	if (obj->blessed || obj->cursed) {
200.  		pline("There is %s flash as %s hit%s the altar.",
201.  		      an(Hallucination ? hcolor() :
202.  			 obj->blessed ? amber : Black),
203.  		      doname(obj),
204.  		      (obj->quan == 1L) ? "s" : "");
205.  		if (!Hallucination) obj->bknown = 1;
206.  	} else {
207.  		pline("%s land%s on the altar.", Doname2(obj),
208.  			(obj->quan == 1L) ? "s" : "");
209.  		if (obj->otyp != GOLD_PIECE)
210.  			obj->bknown = 1;
211.  	}
212.  }
213.  
214.  #ifdef SINKS
215.  static
216.  void
217.  trycall(obj)
218.  register struct obj *obj;
219.  {
220.  	if(!objects[obj->otyp].oc_name_known &&
221.  	   !objects[obj->otyp].oc_uname)
222.  	   docall(obj);
223.  }
224.  
225.  STATIC_OVL
226.  void
227.  dosinkring(obj)  /* obj is a ring being dropped over a kitchen sink */
228.  register struct obj *obj;
229.  {
230.  	register struct obj *otmp,*otmp2;
231.  	register boolean ideed = TRUE;
232.  
233.  	You("drop %s down the drain.", doname(obj));
234.  	switch(obj->otyp) {	/* effects that can be noticed without eyes */
235.  	    case RIN_SEARCHING:
236.  		You("thought your %s got lost in the sink, but there it is!",
237.  			xname(obj));
238.  		dropx(obj);
239.  		trycall(obj);
240.  		return;
241.  	    case RIN_LEVITATION:
242.  		pline("The sink quivers upward for a moment.");
243.  		break;
244.  	    case RIN_POISON_RESISTANCE:
245.  #ifdef TUTTI_FRUTTI
246.  		You("smell rotten %s.", makeplural(pl_fruit));
247.  #else
248.  		You("smell rotten fruit.");
249.  #endif
250.  		break;
251.  	    case RIN_AGGRAVATE_MONSTER:
252.  		pline("Several flies buzz angrily around the sink.");
253.  		break;
254.  	    case RIN_SHOCK_RESISTANCE:
255.  		pline("Static electricity surrounds the sink.");
256.  		break;
257.  	    case RIN_CONFLICT:
258.  		You("hear loud noises coming from the drain.");
259.  		break;
260.  	    case RIN_GAIN_STRENGTH:
261.  		pline("The water flow seems %ser now.",
262.  			(obj->spe<0) ? "weak" : "strong");
263.  		break;
264.  	    case RIN_INCREASE_DAMAGE:
265.  		pline("The water's force seems %ser now.",
266.  			(obj->spe<0) ? "small" : "great");
267.  		break;
268.  	    default:
269.  		ideed = FALSE;
270.  		break;
271.  	}
272.  	if(!Blind && !ideed) {
273.  	    ideed = TRUE;
274.  	    switch(obj->otyp) {		/* effects that need eyes */
275.  		case RIN_ADORNMENT:
276.  		    pline("The faucets flash brightly for a moment.");
277.  		    break;
278.  		case RIN_REGENERATION:
279.  		    pline("The sink looks as good as new.");
280.  		    break;
281.  		case RIN_INVISIBILITY:
282.  		    You("don't see anything happen to the sink.");
283.  		    break;
284.  		case RIN_SEE_INVISIBLE:
285.  		    You("see some air in the sink.");
286.  		    break;
287.  		case RIN_STEALTH:
288.  		pline("The sink seems to blend into the floor for a moment.");
289.  		    break;
290.  		case RIN_HUNGER:
291.  		    ideed = FALSE;
292.  		    for(otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp2) {
293.  			otmp2 = otmp->nexthere;
294.  			if(otmp != uball && otmp != uchain) {
295.  			    pline("Suddenly, %s vanishes from the sink!",
296.  							doname(otmp));
297.  			    delobj(otmp);
298.  			    ideed = TRUE;
299.  			}
300.  		    }
301.  		    break;
302.  		case RIN_FIRE_RESISTANCE:
303.  		pline("The hot water faucet flashes brightly for a moment.");
304.  		    break;
305.  		case RIN_COLD_RESISTANCE:
306.  		pline("The cold water faucet flashes brightly for a moment.");
307.  		    break;
308.  		case RIN_PROTECTION_FROM_SHAPE_CHAN:
309.  		    pline("The sink looks nothing like a fountain.");
310.  		    break;
311.  		case RIN_PROTECTION:
312.  		    pline("The sink glows %s for a moment.",
313.  			    Hallucination ? hcolor() :
314.  			    (obj->spe<0) ? Black : silver);
315.  		    break;
316.  		case RIN_WARNING:
317.  		    pline("The sink glows %s for a moment.",
318.  			    Hallucination ? hcolor() : White);
319.  		    break;
320.  		case RIN_TELEPORTATION:
321.  		    pline("The sink momentarily vanishes.");
322.  		    break;
323.  		case RIN_TELEPORT_CONTROL:
324.  	    pline("The sink looks like it is being beamed aboard somewhere.");
325.  		    break;
326.  #ifdef POLYSELF
327.  		case RIN_POLYMORPH:
328.  		    pline("The sink momentarily looks like a fountain.");
329.  		    break;
330.  		case RIN_POLYMORPH_CONTROL:
331.  	pline("The sink momentarily looks like a regularly erupting geyser.");
332.  		    break;
333.  #endif
334.  	    }
335.  	}
336.  	if(ideed)
337.  	    trycall(obj);
338.  	else
339.  	    You("hear the ring bouncing down the drainpipe.");
340.  	if (!rn2(20)) {
341.  		pline("The sink backs up, leaving %s.", doname(obj));
342.  		dropx(obj);
343.  	}
344.  	else
345.  		useup(obj);
346.  }
347.  #endif
348.  
349.  #endif /* OVLB */
350.  #ifdef OVL0
351.  
352.  /* some common tests when trying to drop or throw items */
353.  boolean
354.  canletgo(obj,word)
355.  register struct obj *obj;
356.  register const char *word;
357.  {
358.  	if(obj->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)){
359.  	       if (*word)
360.  			Norep("You cannot %s something you are wearing.",word);
361.  		return(FALSE);
362.  	}
363.  	if (obj->otyp == LOADSTONE && obj->cursed) {
364.  		if (*word)
365.  			pline("For some reason, you cannot %s the stone%s!",
366.  				word, plur(obj->quan));
367.  		/* Kludge -- see invent.c */
368.  		if (obj->corpsenm) {
369.  			struct obj *otmp;
370.  
371.  			otmp = obj;
372.  			obj = obj->nobj;
373.  			obj->quan += otmp->quan;
374.  			obj->owt = weight(obj);
375.  			freeinv(otmp);
376.  			obfree(otmp, obj);
377.  		}
378.  		obj->bknown = 1;
379.  		return(FALSE);
380.  	}
381.  #ifdef WALKIES
382.  	if (obj->otyp == LEASH && obj->leashmon != 0) {
383.  	       if (*word)
384.  			pline ("The leash is tied around your %s.",
385.  					body_part(HAND));
386.  		return(FALSE);
387.  	}
388.  #endif
389.  	return(TRUE);
390.  }
391.  
392.  STATIC_PTR
393.  int
394.  drop(obj)
395.  register struct obj *obj;
396.  {
397.  	if(!obj) return(0);
398.  	if(!canletgo(obj,"drop"))
399.  		return(0);
400.  	if(obj == uwep) {
401.  		if(welded(uwep)) {
402.  			weldmsg(obj, FALSE);
403.  			return(0);
404.  		}
405.  		setuwep((struct obj *)0);
406.  		if(uwep) return 0; /* lifesaved and rewielded */
407.  	}
408.  #ifdef SINKS
409.  	if((obj->oclass == RING_CLASS) && IS_SINK(levl[u.ux][u.uy].typ)
410.  							&& !u.uswallow) {
411.  		dosinkring(obj);
412.  		return(1);
413.  	}
414.  #endif
415.  	if (IS_ALTAR(levl[u.ux][u.uy].typ) && !u.uswallow) {
416.  		doaltarobj(obj);	/* set bknown */
417.  	} else
418.  		if(flags.verbose) You("drop %s.", doname(obj));
419.  	dropx(obj);
420.  	return(1);
421.  }
422.  
423.  /* Called in several places - should not produce texts */
424.  void
425.  dropx(obj)
426.  register struct obj *obj;
427.  {
428.  	/* Money is *not* in our inventory */
429.  	if (obj->otyp != GOLD_PIECE) freeinv(obj);
430.  	(void) snuff_candle(obj);
431.  	if(!u.uswallow && obj != uball &&
432.  		          ship_object(obj, u.ux, u.uy, FALSE)) return;
433.  	dropy(obj);
434.  }
435.  
436.  void
437.  dropy(obj)
438.  register struct obj *obj;
439.  {
440.  	if (!u.uswallow && flooreffects(obj,u.ux,u.uy,"drop")) return;
441.  	if(obj->otyp == CRYSKNIFE)
442.  		obj->otyp = WORM_TOOTH;
443.  	/* uswallow check done by GAN 01/29/87 */
444.  	if(u.uswallow) {
445.  		if (obj->otyp == GOLD_PIECE) {
446.  		    u.ustuck->mgold += obj->quan;
447.  		    delobj(obj);
448.  		} else if (obj != uball) {	/* mon doesn't pick up ball */
449.  		    (void) snuff_candle(obj);   /* security. it's never lit */
450.  		    mpickobj(u.ustuck,obj);
451.  		}
452.  	} else  {
453.  		(void) snuff_candle(obj);
454.  		obj->nobj = fobj;
455.  		fobj = obj;
456.  		place_object(obj, u.ux, u.uy);
457.  		if (obj == uball)
458.  		    drop_ball(u.ux,u.uy);
459.  		else
460.  		    sellobj(obj, u.ux, u.uy);
461.  		stackobj(obj);
462.  		if(Blind && Levitation)
463.  		    map_object(obj, 0);
464.  		newsym(u.ux,u.uy);	/* remap location under self */
465.  	}
466.  }
467.  
468.  /* drop several things */
469.  int
470.  doddrop()
471.  {
472.  	int result;
473.  
474.  	if (*u.ushops) sellobj_state(TRUE);
475.  	result = ggetobj("drop", drop, 0);
476.  	if (*u.ushops) sellobj_state(FALSE);
477.  	reset_occupations();
478.  
479.  	return result;
480.  }
481.  
482.  #endif /* OVL0 */
483.  #ifdef OVL2
484.  
485.  /* on a ladder, used in goto_level */
486.  static boolean NEARDATA at_ladder = FALSE;
487.  
488.  int
489.  dodown()
490.  {
491.  	struct trap *trap = 0;
492.  
493.  	if( (u.ux != xdnstair || u.uy != ydnstair)
494.  	     && (!xdnladder || u.ux != xdnladder || u.uy != ydnladder)
495.  	     && (!sstairs.sx || u.ux != sstairs.sx || u.uy != sstairs.sy
496.  			|| sstairs.up)
497.  	  ) {
498.  		if (!(trap = t_at(u.ux,u.uy)) || trap->ttyp != TRAPDOOR
499.  			|| !Can_fall_thru(&u.uz) || !trap->tseen) {
500.  			You("can't go down here.");
501.  			return(0);
502.  		}
503.  	}
504.  	if(u.ustuck) {
505.  		You("are being held, and cannot go down.");
506.  		return(1);
507.  	}
508.  	if(Levitation) {
509.  		pline("You're floating high above the %s.",
510.  			levl[u.ux][u.uy].typ == STAIRS ? "stairs" :
511.  			levl[u.ux][u.uy].typ == LADDER ? "ladder" :
512.  			"trap door");
513.  		return(0);
514.  	}
515.  	if (on_level(&valley_level, &u.uz) && !u.uevent.gehennom_entered) {
516.  		You("are standing at the gate to Gehennom.");
517.  		pline("Unspeakable cruelty and harm lurk down there.");
518.  		if (yn("Are you sure you want to enter?") != 'y')
519.  		     return(0);
520.  		else pline("So be it.");
521.  		u.uevent.gehennom_entered = 1;	/* don't ask again */
522.  	}
523.  
524.  #ifdef WALKIES
525.  	if(!next_to_u()) {
526.  		You("are held back by your pet!");
527.  		return(0);
528.  	}
529.  #endif
530.  	if (trap)
531.  #ifdef POLYSELF
532.  		You("%s into the trap door.", locomotion(uasmon, "jump"));
533.  #else
534.  		You("jump into the trap door.");
535.  #endif
536.  	if (levl[u.ux][u.uy].typ == LADDER) at_ladder = TRUE;
537.  	next_level(!trap);
538.  	at_ladder = FALSE;
539.  	return(1);
540.  }
541.  
542.  int
543.  doup()
544.  {
545.  	if( (u.ux != xupstair || u.uy != yupstair)
546.  	     && (!xupladder || u.ux != xupladder || u.uy != yupladder)
547.  	     && (!sstairs.sx || u.ux != sstairs.sx || u.uy != sstairs.sy
548.  			|| !sstairs.up)
549.   	  ) {
550.  		You("can't go up here.");
551.  		return(0);
552.  	}
553.  	if(u.ustuck) {
554.  		You("are being held, and cannot go up.");
555.  		return(1);
556.  	}
557.  	if(near_capacity() > SLT_ENCUMBER) {
558.  		/* No levitation check; inv_weight() already allows for it */
559.  		Your("load is too heavy to climb the %s.",
560.  		      levl[u.ux][u.uy].typ == STAIRS ? "stairs" : "ladder");
561.  		return(1);
562.  	}
563.  	if(ledger_no(&u.uz) == 1) {
564.  		if (yn("Beware, there will be no return! Still climb?") != 'y')
565.  			return(0);
566.  	}
567.  #ifdef WALKIES
568.  	if(!next_to_u()) {
569.  		You("are held back by your pet!");
570.  		return(0);
571.  	}
572.  #endif
573.  	if (levl[u.ux][u.uy].typ == LADDER) at_ladder = TRUE;
574.  	prev_level(TRUE);
575.  	at_ladder = FALSE;
576.  	return(1);
577.  }
578.  
579.  d_level save_dlevel = {0, 0};
580.  
581.  /* check that we can write out the current level */
582.  static int
583.  currentlevel_rewrite()
584.  {
585.  	register int fd;
586.  
587.  	fd = create_levelfile(ledger_no(&u.uz));
588.  
589.  	if(fd < 0) {
590.  		/*
591.  		 * This is not quite impossible: e.g., we may have
592.  		 * exceeded our quota. If that is the case then we
593.  		 * cannot leave this level, and cannot save either.
594.  		 * Another possibility is that the directory was not
595.  		 * writable.
596.  		 */
597.  		pline("Cannot create level file for level %d.",
598.  						ledger_no(&u.uz));
599.  		return -1;
600.  	}
601.  
602.  #ifdef MFLOPPY
603.  	if (!savelev(fd, ledger_no(&u.uz), COUNT_SAVE)) {
604.  		(void) close(fd);
605.  		delete_levelfile(ledger_no(&u.uz));
606.  		pline("NetHack is out of disk space for making levels!");
607.  		You("can save, quit, or continue playing.");
608.  		return -1;
609.  	}
610.  #endif
611.  	return fd;
612.  }
613.  
614.  #ifdef INSURANCE
615.  void
616.  save_currentstate()
617.  {
618.  	int fd;
619.  
620.  	if (flags.ins_chkpt) {
621.  		/* write out just-attained level, with pets and everything */
622.  		fd = currentlevel_rewrite();
623.  		if(fd < 0) return;
624.  		bufon(fd);
625.  		savelev(fd,ledger_no(&u.uz), WRITE_SAVE);
626.  		bclose(fd);
627.  	}
628.  
629.  	/* write out non-level state */
630.  	savestateinlock();
631.  }
632.  #endif
633.  
634.  /*
635.  static boolean
636.  badspot(x, y)
637.  register xchar x, y;
638.  {
639.          return((levl[x][y].typ != ROOM && levl[x][y].typ != AIR &&
640.  		         levl[x][y].typ != CORR) || MON_AT(x, y));
641.  }
642.  */
643.  
644.  void
645.  goto_level(newlevel, at_stairs, falling, portal)
646.  d_level *newlevel;
647.  register boolean at_stairs, falling, portal;
648.  {
649.  	register int fd;
650.  	register boolean up = (depth(newlevel) < depth(&u.uz));
651.  	register boolean newdungeon = (u.uz.dnum != newlevel->dnum);
652.  #ifdef REINCARNATION
653.  	int new = 0;	/* made a new level? */
654.  #endif
655.  
656.  	if(dunlev(newlevel) > dunlevs_in_dungeon(newlevel))
657.  	    	newlevel->dlevel = dunlevs_in_dungeon(newlevel);
658.  	if(newdungeon && In_endgame(newlevel)) { /* 1st Endgame Level !!! */
659.  	    	if(u.uhave.amulet) 
660.  		    assign_level(newlevel, &earth_level);
661.  	    	else return;
662.  	}
663.  	if(ledger_no(newlevel) <= 0)
664.  	    	done(ESCAPED);	/* in fact < 0 is impossible */
665.  	/* If you have the amulet and are trying to get out of Hell, going
666.  	 * up a set of stairs sometimes does some very strange things!
667.  	 */
668.  	if(Inhell && up && !newdungeon && u.uhave.amulet &&
669.  	   			(dunlev(&u.uz) < dunlevs_in_dungeon(&u.uz)-3)) {
670.  	    	if(!rn2(4)) {
671.  		    if(!u.ualign.type) {		    /* neutral */
672.  		        if(rn2(2)) assign_level(newlevel, &u.uz);
673.  		        else assign_rnd_level(newlevel, &u.uz, rnd(3));
674.  		    } else if(u.ualign.type == A_LAWFUL) {    /* lawful */
675.  			assign_rnd_level(newlevel, &u.uz, rnd(3));
676.  		    } else assign_level(newlevel, &u.uz); /* chaotic */
677.  	        }
678.  		pline("A mysterious force momentarily surrounds you...");
679.  	    	if(ledger_no(newlevel) < 1) assign_level(newlevel, &u.uz);
680.  	    	if(on_level(newlevel, &u.uz)) {
681.  		    (void) safe_teleds();
682.  #ifdef WALKIES
683.  		    (void) next_to_u();
684.  #endif
685.  		    return;
686.  		}
687.  	}
688.  #ifdef MULDGN
689.  /*	Prevent the player from going past the first quest level unless
690.   *	(s)he has been given the go-ahead by the leader.
691.   */
692.  	if(on_level(&u.uz, &qstart_level) && !newdungeon && !ok_to_quest()) {
693.  
694.  		pline("A mysterious force prevents you from descending.");
695.  		return;
696.  	}
697.  #endif
698.  	if(on_level(newlevel, &u.uz)) return;	      /* this can happen */
699.  
700.  	fd = currentlevel_rewrite();
701.  	if(fd < 0) return;
702.  
703.  	if (falling) /* assuming this is only trapdoor */
704.  	    impact_drop((struct obj *)0, u.ux, u.uy, newlevel->dlevel);
705.  
706.  	check_special_room(TRUE);		/* probably was a trap door */
707.  	if(Punished) unplacebc();
708.  	u.utrap = 0;				/* needed in level_tele */
709.  	fill_pit(u.ux, u.uy);
710.  	u.ustuck = 0;				/* idem */
711.  	u.uinwater = 0;
712.  	keepdogs();
713.  	if(u.uswallow)				/* idem */
714.  		u.uswldtim = u.uswallow = 0;
715.  	/*
716.  	 *  We no longer see anything on the level.  Make sure that this
717.  	 *  follows u.uswallow set to null since uswallow overrides all
718.  	 *  normal vision.
719.  	 */
720.  	vision_recalc(2);
721.  	bufon(fd);
722.  	savelev(fd,ledger_no(&u.uz), WRITE_SAVE | FREE_SAVE);
723.  	bclose(fd);
724.  
725.  #ifdef REINCARNATION
726.  	if (Is_rogue_level(newlevel) || Is_rogue_level(&u.uz))
727.  		assign_rogue_graphics(Is_rogue_level(newlevel));
728.  #endif
729.  	assign_level(&u.uz0, &u.uz);
730.  	assign_level(&u.uz, newlevel);
731.  	assign_level(&u.utolev, newlevel);
732.  	u.utotype = 0;
733.  	if(dunlev_reached(&u.uz) < dunlev(&u.uz))
734.  		dunlev_reached(&u.uz) = dunlev(&u.uz);
735.  
736.  	/* set default level change destination areas */
737.  	/* the special level code may override these */
738.  	(void) memset((genericptr_t) &updest, 0, sizeof updest);
739.  	(void) memset((genericptr_t) &dndest, 0, sizeof dndest);
740.  
741.  	if(In_endgame(&u.uz) ||
742.  #ifdef MFLOPPY
743.  	    /* If the level has no .where yet, it hasn't been made */
744.  	    !fileinfo[ledger_no(&u.uz)].where) {
745.  #else
746.  	    !level_exists[ledger_no(&u.uz)]) {
747.  #endif
748.  		mklev();
749.  #ifdef REINCARNATION
750.  		new = 1;	/* made the level */
751.  #endif
752.  	} else {
753.  		fd = open_levelfile(ledger_no(&u.uz));
754.  		if (fd < 0) {
755.  			pline("Cannot open file (#%d) for level %d (errno %d).",
756.  					ledger_no(&u.uz), depth(&u.uz), errno);
757.  			pline("Probably someone removed it.");
758.  			done(TRICKED);
759.  		}
760.  #ifdef ZEROCOMP
761.  		minit();
762.  #endif
763.  		getlev(fd, hackpid, ledger_no(&u.uz), FALSE);
764.  		(void) close(fd);
765.  	}
766.  #ifdef MULDGN
767.  	quest_init();	/* re-initialize */
768.  #endif
769.  
770.  	if(portal && !In_endgame(&u.uz)) {
771.  	    /* find the portal on the new level */
772.  	    register struct trap *ttrap;
773.  
774.  	    for(ttrap = ftrap; ttrap; ttrap = ttrap->ntrap)
775.  		if(ttrap->ttyp == MAGIC_PORTAL) break;
776.  
777.  	    if(ttrap) {
778.  		u.ux = ttrap->tx;
779.  		u.uy = ttrap->ty;
780.  	    } else panic("goto_level: no corresponding portal!");
781.  	} else if(at_stairs && !In_endgame(&u.uz)) {
782.  	    if(up) {
783.  		if(at_ladder) {
784.  		    u.ux = xdnladder;
785.  		    u.uy = ydnladder;
786.  		} else {
787.  		    if(newdungeon) {
788.  			if(Is_stronghold(&u.uz)) {
789.  			    register xchar x, y;
790.  
791.  			    do {
792.  				x = (COLNO - 2 - rnd(5));
793.  				y = rn1(ROWNO - 4, 3);
794.  			    } while(occupied(x, y) ||
795.  				    IS_WALL(levl[x][y].typ));
796.  			    u.ux = x;
797.  			    u.uy = y;
798.  			} else u_on_sstairs();
799.  		    } else u_on_dnstairs();
800.  		} 
801.  		/* Remove bug which crashes with */ 
802.  		/* levitation/punishment  KAA    */
803.  		if(Punished) {
804.  		    if(!Levitation)
805.  			pline("With great effort you climb the %s.",
806.  			      !at_ladder ? "stairs" : "ladder");
807.  		    placebc();
808.  		} 
809.  		if(at_ladder && (!Punished || Levitation))
810.  		    You("climb up the ladder.");
811.  	    } else { /* down */
812.  		if(at_ladder) {
813.  		    u.ux = xupladder;
814.  		    u.uy = yupladder;
815.  		} else {
816.  		    if(newdungeon) u_on_sstairs();
817.  		    else u_on_upstairs();
818.  		}
819.  		if(at_stairs && u.dz && !up &&
820.  		   ((near_capacity()>UNENCUMBERED) || Punished || Fumbling)) {
821.  		    You("fall down the %s.",
822.  			!at_ladder ? "stairs" : "ladder");
823.  		    if(Punished) {
824.  			drag_down();
825.  			if(carried(uball)) {
826.  			    if (uwep == uball)
827.  				setuwep((struct obj *)0);
828.  			    if (uwep != uball)
829.  				freeinv(uball);
830.  			}
831.  			placebc();
832.  		    } 
833.  		    losehp(rnd(3), "falling downstairs", KILLED_BY);
834.  		    selftouch("Falling, you");
835.  		} 
836.  		else if(at_ladder && u.dz)
837.  		    You("climb down the ladder.");
838.  	    }
839.  	} else { /* trap door or level_tele or In_endgame */
840.  	    if(up)
841.  		place_lregion(updest.lx, updest.ly,
842.  			      updest.hx, updest.hy,
843.  			      updest.nlx, updest.nly,
844.  			      updest.nhx, updest.nhy,
845.  			      LR_UPTELE, (d_level *) 0);
846.  	    else
847.  		place_lregion(dndest.lx, dndest.ly,
848.  			      dndest.hx, dndest.hy,
849.  			      dndest.nlx, dndest.nly,
850.  			      dndest.nhx, dndest.nhy,
851.  			      LR_DOWNTELE, (d_level *) 0);
852.  	    if(Punished) {
853.  		if(falling) ballfall();
854.  		placebc();
855.  	    }
856.  	    if(falling)
857.  		selftouch("Falling, you");
858.  	}
859.  
860.  	losedogs();
861.  	obj_delivery();
862.  	check_special_room(FALSE);
863.  
864.  	initrack();
865.  
866.  	if(MON_AT(u.ux, u.uy)) mnexto(m_at(u.ux, u.uy));
867.  	if(MON_AT(u.ux, u.uy)) {
868.  		impossible("mnexto failed (do.c)?");
869.  		rloc(m_at(u.ux, u.uy));
870.  	}
871.  	remove_cadavers(&fobj);	/* remove rotted meat (before seen) */
872.  
873.  	/* initial movement of bubbles just before vision_recalc */
874.  	if (Is_waterlevel(&u.uz))
875.  		movebubbles();
876.  
877.  	/* Reset the screen. */
878.  	vision_reset();		/* reset the blockages */
879.  	docrt();		/* does a full vision recalc */
880.  
881.  	/* In Nethack 3.1, Gehennom starts after the stronghold.  Moreover,
882.  	 * there are traps in the stronghold, that can send the player
883.  	 * to Gehennom (gnark, gnark)!  So we have to test here:
884.  	 */
885.  	if(!In_hell(&u.uz0) && Inhell) {
886.              if(Is_valley(newlevel)) {
887.  		You("arrive at the Valley of the Dead...");
888.  	    	pline("There is a smell of burnt flesh and decay here.");
889.  #ifdef MICRO
890.  	    	display_nhwindow(WIN_MESSAGE, FALSE);
891.  #endif
892.  		pline("The sounds of groans and moans fill the air.");
893.  	    } else pline("It is hot here.  You smell smoke...");
894.  	}
895.  
896.  #ifdef REINCARNATION
897.  	/*
898.  	 *  Move all plines beyond the screen reset.
899.  	 */
900.  	if (new && Is_rogue_level(&u.uz))
901.  	 You("have entered what appears to be an older, more primitive world.");
902.  #endif
903.  	/* Final confrontation */
904.  	if (In_endgame(&u.uz) && newdungeon && u.uhave.amulet &&
905.  						   flags.no_of_wizards == 0)
906.  		resurrect();
907.  	if (newdungeon && In_tower(&u.uz))
908.  		pline("The heat and smoke are gone.");
909.  #ifdef MULDGN
910.  	if(!In_quest(&u.uz0) && at_dgn_entrance("The Quest") &&
911.  		!(u.uevent.qexpelled || u.uevent.qcompleted || leaderless()))
912.  	    com_pager(2);	/* the message from the leader */
913.  
914.  	if(Is_knox(&u.uz)) {
915.  	        register struct monst *mtmp;
916.  
917.  	        You("penetrated a high security area!");
918.  		pline("An alarm sounds!");
919.  		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 
920.  		    if(mtmp->msleep) mtmp->msleep = 0;
921.  	}
922.  #endif /* MULDGN */
923.  	if(on_level(&u.uz, &astral_level)) {
924.  	        register struct monst *mtmp;
925.  
926.  	        /* reset monster hostility relative to player */
927.  		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 
928.  		    reset_hostility(mtmp);
929.  
930.  		/* create some player-monsters */
931.  		create_mplayers(rn1(4, 3), TRUE);
932.  
933.  		/* create a guardian angel next to player, if worthy */
934.  		if (Conflict) {
935.  		    coord mm;
936.  		    int i = rnd(4);
937.  	pline("A voice booms: \"Thy desire for conflict shall be rewarded!\"");
938.  		    while(i--) {
939.  			mm.x = u.ux;
940.  			mm.y = u.uy;
941.  			if(enexto(&mm, mm.x, mm.y, &mons[PM_ANGEL]))
942.  			    (void) mk_roamer(&mons[PM_ANGEL], u.ualign.type,
943.  					     mm.x, mm.y, FALSE);
944.  		    }
945.  
946.  		} else if(u.ualign.record > 3) {
947.  		    coord mm;
948.  
949.  		pline("A voice whispers: \"Thou hast been worthy of me!\"");
950.  		    mm.x = u.ux;
951.  		    mm.y = u.uy;
952.  		    if(enexto(&mm, mm.x, mm.y, &mons[PM_ANGEL])) {
953.  			if((mtmp = mk_roamer(&mons[PM_ANGEL], u.ualign.type,
954.  					   mm.x, mm.y, TRUE)) != 0) {
955.  			     register struct obj *otmp =
956.  			                   mksobj(SILVER_SABER, FALSE, FALSE);
957.  
958.  			     if(!Blind)
959.  		                 pline("An angel appears near you.");
960.  			     else 
961.  		       You("feel the presence of a friendly angel near you.");
962.  			    /* guardian angel -- the one case mtame doesn't
963.  			     * imply an edog structure, so we don't want to
964.  			     * call tamedog().
965.  			     */
966.  			     mtmp->mtame = 10;
967.  			     /* make him strong enough vs. endgame foes */
968.  			     mtmp->m_lev = rn1(8,15);
969.  			     mtmp->mhp = mtmp->mhpmax = 
970.  				       d((int)mtmp->m_lev,10) + 30 + rnd(30);
971.  			     bless(otmp);
972.  			     otmp->spe = 7;
973.  			     mpickobj(mtmp, otmp);
974.  		        }
975.  		    }
976.  		}
977.          }
978.  
979.  #ifdef MULDGN
980.  	onquest();
981.  #endif
982.  	assign_level(&u.uz0, &u.uz); /* reset u.uz0 */
983.  
984.  #ifdef INSURANCE
985.  	save_currentstate();
986.  #endif
987.  
988.  	if(!flags.nopick && OBJ_AT(u.ux, u.uy) &&
989.  	   (!is_pool(u.ux,u.uy) || Underwater))
990.  		pickup(1);
991.  	else read_engr_at(u.ux,u.uy);
992.  }
993.  
994.  /* handle something like portal ejection */
995.  void
996.  deferred_goto()
997.  {
998.  	if (!on_level(&u.uz, &u.utolev)) {
999.  	    d_level dest;
1000. 	    int typmask = u.utotype; /* save it; goto_level zeroes u.utotype */
1001. 
1002. 	    assign_level(&dest, &u.utolev);
1003. 	    goto_level(&dest, !!(typmask&4), !!(typmask&2), !!(typmask&1));
1004. 	    if (typmask & 0200) {	/* remove portal */
1005. 		deltrap(t_at(u.ux, u.uy));
1006. 		newsym(u.ux, u.uy);
1007. 	    }
1008. 	}
1009. }
1010. 
1011. #endif /* OVL2 */
1012. #ifdef OVL3
1013. 
1014. void
1015. revive_corpse(corpse, odds, mark_as_old)    /* see remove_cadavers() */
1016. register struct obj *corpse;
1017. int odds;
1018. boolean mark_as_old;
1019. {
1020.     register struct monst *mtmp;
1021. 
1022.     corpse->oldcorpse = mark_as_old;
1023. 
1024.     /* odds == 0 is a special case meaning 'always revive' */
1025.     if (!odds || !rn2(odds)) {
1026. 	if (carried(corpse)) {
1027. 	    if (corpse == uwep) {
1028. 		if ((mtmp = revive(corpse,TRUE)) != 0)
1029. 		    pline("The %s%s %s writhes out of your grasp!",
1030. 			(mtmp->mhp < mtmp->mhpmax) ? "bite-covered ":"",
1031. 				mtmp->data->mname, xname(corpse));
1032. 	    } else if ((mtmp = revive(corpse,TRUE)) != 0)
1033. 		You("feel squirming in your backpack!");
1034. 	} else {
1035. 	    if ((mtmp = revive(corpse,FALSE)) && cansee(mtmp->mx,mtmp->my))
1036. 		pline("%s rises from the dead!",
1037. 		    (mtmp->mhp==mtmp->mhpmax) ? Monnam(mtmp)
1038. 			: Adjmonnam(mtmp, "bite-covered"));
1039. 	}
1040.     }
1041. }
1042. 
1043. /*
1044.  *  Remove old cadavers from any object chain.  Regenerate trolls
1045.  *  thanks to KAA.  Follows containers (except ice boxes).
1046.  */
1047. #define TAINT_AGE	50	/* min. limit for tainting.  see eat.c */
1048. #define ODDS_RV1	37	/* 1/37 odds for 50 moves = 75% revive */
1049. #define ODDS_RV2	2	/* special case 1/2 odds of reviving */
1050. 
1051. void
1052. remove_cadavers(chain)
1053. struct obj **chain;
1054. {
1055.     register struct obj *obj, *nobj, *pobj = (struct obj *)0;
1056.     register long corpse_age;
1057.     boolean ininv = (*chain == invent);
1058.     boolean onfloor = (*chain == fobj);
1059. 
1060.     for (obj = *chain; obj; obj = nobj) {
1061. 	nobj = obj->nobj;
1062. 
1063. 	if (obj->otyp == CORPSE) {
1064. 	    /* corpses laying on ice deteriorate more slowly */
1065. 	    if (onfloor && obj->age < monstermoves &&
1066. 		rn2(3) && is_ice(obj->ox, obj->oy)) obj->age++;
1067. 	    corpse_age = monstermoves - obj->age;
1068. 
1069. 	    if (is_rider(&mons[obj->corpsenm]) && corpse_age >= 12) {
1070. 		/* these always come back eventually */
1071. 		/* riders can't be picked up, so no need to check onfloor */
1072. 		revive_corpse(obj, 3, FALSE);
1073. 	    } else if (mons[obj->corpsenm].mlet == S_TROLL && !obj->oldcorpse
1074. 		       && !(mons[obj->corpsenm].geno & (G_GENOD | G_EXTINCT))
1075. 		       && (onfloor || ininv)) {
1076. 
1077. 		/* the corpse has 50 moves, the lower limit for tainting,
1078. 		 * to attempt re-animation.  if it is unsuccessful it is
1079. 		 * marked to prevent further attempts.  if we leave the
1080. 		 * level and return to old corpses that haven't been marked
1081. 		 * they're given a one-shot chance to re-animate.
1082. 		 */
1083. 		if (corpse_age < TAINT_AGE)
1084. 		    revive_corpse(obj, ODDS_RV1, FALSE);
1085. 		else if (corpse_age == TAINT_AGE)
1086. 		    revive_corpse(obj, ODDS_RV1, TRUE);
1087. 		else revive_corpse(obj, ODDS_RV2, TRUE);
1088. 
1089. 	    } else if (obj->corpsenm != PM_LIZARD && (250 < corpse_age)) {
1090. 		if(ininv)
1091. 		    useup(obj);
1092. 		else if(onfloor)
1093. 		    delobj(obj);
1094. 		else { /* in a container */
1095. 		    if(pobj) pobj->nobj = nobj;
1096. 		    else *chain = nobj;
1097. 		    obfree(obj, (struct obj *) 0);
1098. 		    obj = 0;
1099. 		}
1100. 	    }
1101. 	} else if(obj->cobj && Is_container(obj) && obj->otyp != ICE_BOX)
1102. 	    remove_cadavers(&obj->cobj);
1103. 	/* pobj is only used for containers, which don't allow revive() -dlc */
1104. 	if (obj) pobj = obj;
1105.     }
1106. }
1107. 
1108. int
1109. donull() {
1110. 	return(1);	/* Do nothing, but let other things happen */
1111. }
1112. 
1113. #endif /* OVL3 */
1114. #ifdef OVLB
1115. 
1116. STATIC_PTR int
1117. wipeoff() {
1118. 	if(u.ucreamed < 4)	u.ucreamed = 0;
1119. 	else			u.ucreamed -= 4;
1120. 	if (Blinded < 4)	Blinded = 0;
1121. 	else			Blinded -= 4;
1122. 	if (!Blinded) {
1123. 		pline("You've got the glop off.");
1124. 		u.ucreamed = 0;
1125. 		Blinded = 1;
1126. 		make_blinded(0L,TRUE);
1127. 		return(0);
1128. 	} else if (!u.ucreamed) {
1129. 		Your("%s feels clean now.", body_part(FACE));
1130. 		return(0);
1131. 	}
1132. 	return(1);		/* still busy */
1133. }
1134. 
1135. int
1136. dowipe()
1137. {
1138. 	if(u.ucreamed)  {
1139. 		static char NEARDATA buf[39];
1140. 
1141. 		Sprintf(buf, "wiping off your %s", body_part(FACE));
1142. 		set_occupation(wipeoff, buf, 0);
1143. 		/* Not totally correct; what if they change back after now
1144. 		 * but before they're finished wiping?
1145. 		 */
1146. 		return(1);
1147. 	}
1148. 	Your("%s is already clean.", body_part(FACE));
1149. 	return(1);
1150. }
1151. 
1152. #endif /* OVLB */
1153. #ifdef OVL1
1154. 
1155. /* split obj so that it gets size num */
1156. /* remainder is put in the object structure delivered by this call */
1157. struct obj *
1158. splitobj(obj, num)
1159. register struct obj *obj;
1160. register long num;
1161. {
1162. register struct obj *otmp;
1163. 	/* assert(0 < num && num < obj->quan); */
1164. 	otmp = newobj(obj->onamelth);
1165. 	*otmp = *obj;		/* copies whole structure */
1166. 	otmp->o_id = flags.ident++;
1167. 	obj->quan = num;
1168. 	obj->owt = weight(obj);
1169. 	otmp->quan -= num;
1170. 	otmp->owt = weight(otmp);	/* -= obj->owt ? */
1171. 	obj->nobj = obj->nexthere = otmp;
1172. 	if (obj->onamelth)
1173. 		(void)strncpy(ONAME(otmp), ONAME(obj), (int)obj->onamelth);
1174. 	if(obj->unpaid) splitbill(obj,otmp);
1175. 	return(otmp);
1176. }
1177. 
1178. #endif /* OVL1 */
1179. #ifdef OVLB
1180. 
1181. void
1182. set_wounded_legs(side, timex)
1183. register long side;
1184. register int timex;
1185. {
1186. 	if(!Wounded_legs) {
1187. 		ATEMP(A_DEX)--;
1188. 		flags.botl = 1;
1189. 	}
1190. 
1191. 	if(!Wounded_legs || (Wounded_legs & TIMEOUT))
1192. 		Wounded_legs |= side + timex;
1193. 	else
1194. 		Wounded_legs |= side;
1195. }
1196. 
1197. void
1198. heal_legs()
1199. {
1200. 	if(Wounded_legs) {
1201. 		if (ATEMP(A_DEX) < 0) {
1202. 			ATEMP(A_DEX)++;
1203. 			flags.botl = 1;
1204. 		}
1205. 
1206. 		if((Wounded_legs & BOTH_SIDES) == BOTH_SIDES) {
1207. 			Your("%s feel somewhat better.",
1208. 				makeplural(body_part(LEG)));
1209. 		} else {
1210. 			Your("%s feels somewhat better.",
1211. 				body_part(LEG));
1212. 		}
1213. 		Wounded_legs = 0;
1214. 	}
1215. }
1216. 
1217. #endif /* OVLB */
1218. 
1219. /*do.c*/