Source:NetHack 3.0.0/do.c

From NetHackWiki
Revision as of 04:28, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 3.0.0/do.c moved to Source:NetHack 3.0.0/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 NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.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.0	89/06/12
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.    
9.    #if defined(DGK) && !defined(TOS)
10.   extern struct finfo fileinfo[];
11.   #else
12.   extern boolean level_exists[];
13.   #endif
14.   
15.   static int drop P((struct obj *));
16.   
17.   static const char drop_types[] = { '0', GOLD_SYM, '#', 0 };
18.   
19.   int
20.   dodrop() {
21.   	return(drop(getobj(drop_types, "drop")));
22.   }
23.   
24.   /* Used for objects which sometimes do special things when dropped; must be
25.    * called with the object not in any chain.  Returns 1 if the object is
26.    * gone.
27.    */
28.   boolean
29.   flooreffects(obj,x,y)
30.   struct obj *obj;
31.   int x,y;
32.   {
33.   	if(obj->otyp == BOULDER && IS_POOL(levl[x][y].typ)) {
34.   #ifdef STRONGHOLD
35.   	    if(levl[x][y].typ == DRAWBRIDGE_UP)
36.   		levl[x][y].drawbridgemask |= DB_FLOOR;
37.   	    else
38.   #endif
39.   		levl[x][y].typ = ROOM;
40.   	    if (cansee(x,y))
41.   		pline("There is a large splash as the boulder fills the %s.",
42.   			(levl[x][y].typ==POOL) ? "pool" : "moat");
43.   	    else if (flags.soundok)
44.   		You("hear a splash.");
45.   	    obfree(obj, (struct obj *)0);
46.   	    mnewsym(x,y);
47.   	    if ((x != u.ux || y != u.uy || Invisible) && !Blind)
48.   		newsym(x,y);
49.   	    return TRUE;
50.   	}
51.   	return FALSE;
52.   }
53.   
54.   #ifdef ALTARS
55.   void
56.   doaltarobj(obj)  /* obj is an object dropped on an altar */
57.   	register struct obj *obj;
58.   {
59.   	if (Blind) return;
60.   	if (obj->blessed || obj->cursed) {
61.   		register const char *fcolor = Hallucination ? hcolor() :
62.   					obj->blessed ? amber : black;
63.   
64.   		pline("There is %s %s flash as %s hit%s the altar.",
65.   		      index(vowels, *fcolor) ? "an" : "a",
66.   		      fcolor,
67.   		      doname(obj),
68.   		      (obj->quan==1) ? "s" : "");
69.   		if (!Hallucination) obj->bknown = 1;
70.   	} else {
71.   		pline("%s land%s on the altar.", Doname2(obj),
72.   			(obj->quan==1) ? "s" : "");
73.   		obj->bknown = 1;
74.   	}
75.   }
76.   #endif
77.   
78.   #ifdef SINKS
79.   static
80.   void
81.   trycall(obj)
82.   register struct obj *obj;
83.   {
84.   	if(!objects[obj->otyp].oc_name_known &&
85.   	   !objects[obj->otyp].oc_uname)
86.   	   docall(obj);
87.   }
88.   
89.   static
90.   void
91.   dosinkring(obj)  /* obj is a ring being dropped over a kitchen sink */
92.   register struct obj *obj;
93.   {
94.   	register struct obj *otmp,*otmp2;
95.   	register boolean ideed = TRUE;
96.   
97.   	You("drop %s down the drain.", doname(obj));
98.   	switch(obj->otyp) {	/* effects that can be noticed without eyes */
99.   	    case RIN_SEARCHING:
100.  	You("thought your %s got lost in the sink, but there it is!",
101.  			xname(obj));
102.  		dropx(obj);
103.  		trycall(obj);
104.  		return;
105.  	    case RIN_LEVITATION:
106.  		pline("The sink quivers upward for a moment.");
107.  		break;
108.  	    case RIN_POISON_RESISTANCE:
109.  		You("smell rotten %s.", makeplural(pl_fruit));
110.  		break;
111.  	    case RIN_AGGRAVATE_MONSTER:
112.  		pline("Several flies buzz angrily around the sink.");
113.  		break;
114.  	    case RIN_SHOCK_RESISTANCE:
115.  		pline("Static electricity surrounds the sink.");
116.  		break;
117.  	    case RIN_CONFLICT:
118.  		You("hear loud noises coming from the drain.");
119.  		break;
120.  	    case RIN_GAIN_STRENGTH:
121.  		pline("The water flow seems %ser now.",
122.  			(obj->spe<0) ? "weak" : "strong");
123.  		break;
124.  	    case RIN_INCREASE_DAMAGE:
125.  		pline("The water's force seems %ser now.",
126.  			(obj->spe<0) ? "small" : "great");
127.  		break;
128.  	    default:
129.  		ideed = FALSE;
130.  		break;
131.  	}
132.  	if(!Blind && !ideed) {
133.  	    ideed = TRUE;
134.  	    switch(obj->otyp) {		/* effects that need eyes */
135.  		case RIN_ADORNMENT:
136.  		    pline("The faucets flash brightly for a moment.");
137.  		    break;
138.  		case RIN_REGENERATION:
139.  		    pline("The sink looks as good as new.");
140.  		    break;
141.  		case RIN_INVISIBILITY:
142.  		    You("don't see anything happen to the sink.");
143.  		    break;
144.  		case RIN_SEE_INVISIBLE:
145.  		    You("see some air in the sink.");
146.  		    break;
147.  		case RIN_STEALTH:
148.  		pline("The sink seems to blend into the floor for a moment.");
149.  		    break;
150.  		case RIN_HUNGER:
151.  		    ideed = FALSE;
152.  		    for(otmp=fobj; otmp; otmp=otmp2) {
153.  			otmp2 = otmp->nobj;
154.  			if(otmp->ox == u.ux && otmp->oy == u.uy)
155.  			    if(otmp != uball && otmp != uchain) {
156.  				pline("Suddenly, %s vanishes from the sink!",
157.  							    doname(otmp));
158.  			    delobj(otmp);
159.  			    ideed = TRUE;
160.  			}
161.  		    }
162.  		    break;
163.  		case RIN_FIRE_RESISTANCE:
164.  		pline("The hot water faucet flashes brightly for a moment.");
165.  		    break;
166.  		case RIN_COLD_RESISTANCE:
167.  		pline("The cold water faucet flashes brightly for a moment.");
168.  		    break;
169.  		case RIN_PROTECTION_FROM_SHAPE_CHAN:
170.  		    pline("The sink looks nothing like a fountain.");
171.  		    break;
172.  		case RIN_PROTECTION:
173.  		    pline("The sink glows %s for a moment.",
174.  			    Hallucination ? hcolor() :
175.  			    (obj->spe<0) ? black : silver);
176.  		    break;
177.  		case RIN_WARNING:
178.  		    pline("The sink glows %s for a moment.",
179.  			    Hallucination ? hcolor() : white);
180.  		    break;
181.  		case RIN_TELEPORTATION:
182.  		    pline("The sink momentarily vanishes.");
183.  		    break;
184.  		case RIN_TELEPORT_CONTROL:
185.  	    pline("The sink looks like it is being beamed aboard somewhere.");
186.  		    break;
187.  #ifdef POLYSELF
188.  		case RIN_POLYMORPH:
189.  		    pline("The sink momentarily looks like a fountain.");
190.  		    break;
191.  		case RIN_POLYMORPH_CONTROL:
192.  	pline("The sink momentarily looks like a regularly erupting geyser.");
193.  		    break;
194.  #endif
195.  	    }
196.  	}
197.  	if(ideed)
198.  	    trycall(obj);
199.  	else
200.  	    You("hear the ring bouncing down the drainpipe.");
201.  	if (!rn2(20)) {
202.  		pline("The sink backs up, leaving %s.", doname(obj));
203.  		dropx(obj);
204.  	}
205.  	else
206.  		useup(obj);
207.  }
208.  #endif
209.  
210.  /* some common tests when trying to drop or throw items */
211.  boolean
212.  canletgo(obj,word)
213.  register struct obj *obj;
214.  register char *word;
215.  {
216.  	if(obj->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)){
217.  		You("cannot %s something you are wearing.",word);
218.  		return(FALSE);
219.  	}
220.  	if (obj->otyp == LOADSTONE && obj->cursed) {
221.  		obj->bknown = 1;
222.  		pline("For some reason, you cannot %s the stone%s!",
223.  			word,
224.  			obj->quan==1 ? "" : "s");
225.  		return(FALSE);
226.  	}
227.  #ifdef WALKIES
228.  	if (obj->otyp == LEASH && obj->leashmon != 0) {
229.  		pline ("The leash is tied around your %s.",
230.  			body_part(HAND));
231.  		return(FALSE);
232.  	}
233.  #endif
234.  	return(TRUE);
235.  }
236.  
237.  static int
238.  drop(obj) register struct obj *obj; {
239.  	if(!obj) return(0);
240.  	if(obj->olet == GOLD_SYM) {		/* pseudo object */
241.  		register long amount = OGOLD(obj);
242.  
243.  /* Fix bug with dropping huge amounts of gold read as negative    KAA */
244.  		if(amount < 0) {
245.  			u.ugold += amount;
246.  	pline("The LRS would be very interested to know you have that much.");
247.  		} else {
248.  			/* uswallow test added by GAN 01/29/87 */
249.  			if(flags.verbose)
250.  			    You("drop %ld gold piece%s.",
251.  				   amount, plur(amount));
252.  			if(u.uswallow)
253.  				(u.ustuck)->mgold += amount;
254.  			else {
255.  				mkgold(amount, u.ux, u.uy);
256.  				if(Invisible) newsym(u.ux, u.uy);
257.  			}
258.  		}
259.  		free((genericptr_t) obj);
260.  		return(1);
261.  	}
262.  	if(!canletgo(obj,"drop"))
263.  		return(0);
264.  	if(obj == uwep) {
265.  		if(welded(uwep)) {
266.  			weldmsg(obj, FALSE);
267.  			return(0);
268.  		}
269.  		setuwep((struct obj *)0);
270.  		if(uwep) return 0; /* lifesaved and rewielded */
271.  	}
272.  #ifdef SINKS
273.  	if((obj->olet == RING_SYM) && IS_SINK(levl[u.ux][u.uy].typ)
274.  							&& !u.uswallow) {
275.  		dosinkring(obj);
276.  		return(1);
277.  	}
278.  #endif
279.  #ifdef ALTARS
280.  	if (IS_ALTAR(levl[u.ux][u.uy].typ) && !u.uswallow) {
281.  		/* turn water into [(un)holy] water */
282.  		if (obj->otyp == POT_WATER) {
283.  			obj->blessed = !!(levl[u.ux][u.uy].altarmask & A_LAW);
284.  			obj->cursed = !!(levl[u.ux][u.uy].altarmask & A_CHAOS);
285.  		}
286.  		doaltarobj(obj);	/* set bknown */
287.  	} else
288.  #endif
289.  	if(flags.verbose) You("drop %s.", doname(obj));
290.  	dropx(obj);
291.  	return(1);
292.  }
293.  
294.  /* Called in several places - should not produce texts */
295.  void
296.  dropx(obj)
297.  register struct obj *obj;
298.  {
299.  	freeinv(obj);
300.  	dropy(obj);
301.  }
302.  
303.  void
304.  dropy(obj)
305.  register struct obj *obj;
306.  {
307.  	if (flooreffects(obj,u.ux,u.uy)) return;
308.  #ifdef WORM
309.  	if(obj->otyp == CRYSKNIFE)
310.  		obj->otyp = WORM_TOOTH;
311.  #endif
312.  	/* uswallow check done by GAN 01/29/87 */
313.  	if(u.uswallow)
314.  		mpickobj(u.ustuck,obj);
315.  	else  {
316.  		obj->ox = u.ux;
317.  		obj->oy = u.uy;
318.  		obj->nobj = fobj;
319.  		fobj = obj;
320.  		levl[u.ux][u.uy].omask = 1;
321.  		if(Invisible) newsym(u.ux,u.uy);
322.  		subfrombill(obj);
323.  		stackobj(obj);
324.  	}
325.  }
326.  
327.  /* drop several things */
328.  int
329.  doddrop() {
330.  	return(ggetobj("drop", drop, 0));
331.  }
332.  
333.  #ifdef STRONGHOLD
334.  static boolean at_ladder = FALSE;	/* on a ladder, used in goto_level */
335.  #endif
336.  
337.  int
338.  dodown()
339.  {
340.  	struct trap *trap = 0;
341.  #ifdef STRONGHOLD
342.  	if((u.ux != xdnstair || u.uy != ydnstair) &&
343.  	   (!xdnladder || u.ux != xdnladder || u.uy != ydnladder)) {
344.  #else
345.  	if(u.ux != xdnstair || u.uy != ydnstair) {
346.  #endif /* STRONGHOLD /**/
347.  		if (!(trap = t_at(u.ux,u.uy)) || trap->ttyp != TRAPDOOR
348.  							|| !trap->tseen) {
349.  			You("can't go down here.");
350.  			return(0);
351.  		}
352.  	}
353.  	if(u.ustuck) {
354.  		You("are being held, and cannot go down.");
355.  		return(1);
356.  	}
357.  	if(Levitation) {
358.  #ifdef STRONGHOLD
359.  		pline("You're floating high above the %s.",
360.  		      levl[u.ux][u.uy].typ == STAIRS ? "stairs" : "ladder");
361.  #else
362.  		pline("You're floating high above the stairs.");
363.  #endif /* STRONGHOLD /**/
364.  		return(0);
365.  	}
366.  
367.  #ifdef WALKIES
368.  	if(!next_to_u()) {
369.  		You("are held back by your pet!");
370.  		return(0);
371.  	} else {
372.  #endif
373.  		unsee();
374.  #ifdef STRONGHOLD
375.  		if (levl[u.ux][u.uy].typ == LADDER) at_ladder = TRUE;
376.  #endif
377.  		if (trap)
378.  			pline("You jump into the trapdoor...");
379.  		goto_level(dlevel+1, !trap);
380.  #ifdef STRONGHOLD
381.  		at_ladder = FALSE;
382.  #endif
383.  #ifdef WALKIES
384.  	}
385.  #endif
386.  	return(1);
387.  }
388.  
389.  int
390.  doup()
391.  {
392.  #ifdef STRONGHOLD
393.  	if((u.ux != xupstair || u.uy != yupstair) &&
394.  	   (!xupladder || u.ux != xupladder || u.uy != yupladder)) {
395.  #else
396.  	if(u.ux != xupstair || u.uy != yupstair) {
397.  #endif /* STRONGHOLD /**/
398.  		You("can't go up here.");
399.  		return(0);
400.  	}
401.  	if(u.ustuck) {
402.  		You("are being held, and cannot go up.");
403.  		return(1);
404.  	}
405.  	if(inv_weight() + 5 > 0) {
406.  		/* No levitation check; inv_weight() already allows for it */
407.  #ifdef STRONGHOLD
408.  		Your("load is too heavy to climb the %s.",
409.  		      levl[u.ux][u.uy].typ == STAIRS ? "stairs" : "ladder");
410.  #else
411.  		Your("load is too heavy to climb the stairs.");
412.  #endif /* STRONGHOLD /**/
413.  		return(1);
414.  	}
415.  
416.  #ifdef ENDGAME
417.  	if (dlevel == 1) {
418.  		pline("Beware, there will be no return!  Still climb? ");
419.  		if (yn() != 'y') return(0);
420.  		else more();
421.  	}
422.  #endif
423.  #ifdef WALKIES
424.  	if(!next_to_u()) {
425.  		You("are held back by your pet!");
426.  		return(0);
427.  	} else {
428.  #endif
429.  		unsee();
430.  #ifdef STRONGHOLD
431.  		if (levl[u.ux][u.uy].typ == LADDER) at_ladder = TRUE;
432.  		goto_level(dlevel-1, 
433.  		    (dlevel-1 < stronghold_level || (at_ladder && 
434.  		       dlevel-1 >= tower_level && dlevel-1 < tower_level+2)));
435.  		at_ladder = FALSE;
436.  #else
437.  		goto_level(dlevel-1, (dlevel-1 <= medusa_level));
438.  #endif
439.  #ifdef WALKIES
440.  	}
441.  #endif
442.  	return(1);
443.  }
444.  
445.  void
446.  goto_level(newlevel, at_stairs)
447.  register int newlevel;
448.  register boolean at_stairs;
449.  {
450.  	register int fd;
451.  	register boolean up = (newlevel < dlevel);
452.  
453.  #ifdef ENDGAME
454.  	if(dlevel == ENDLEVEL) return;	/* To be on the safe side.. */
455.  #endif
456.  	if(newlevel > MAXLEVEL) newlevel = MAXLEVEL;
457.  	if(newlevel <= 0)
458.  #ifdef ENDGAME
459.  	    if(u.uhave_amulet)
460.  		newlevel = ENDLEVEL;	/* Endgame Level !!! */
461.  	    else
462.  #endif
463.  		done("escaped");    /* in fact < 0 is impossible */
464.  
465.  /*	If you have the amulet and are trying to get out of Hell, going
466.   *	up a set of stairs sometimes does some very strange things!
467.   */
468.  #ifdef HARD
469.  	if(Inhell && up && at_stairs  &&
470.  	   (dlevel < MAXLEVEL-3) && u.uhave_amulet) {
471.  	    newlevel = (rn2(5) ? newlevel :
472.  /* neutral */	     !u.ualigntyp ? (rn2(2) ? dlevel : dlevel + (rnd(5) - 2)) :
473.  /* lawful */	     (u.ualigntyp == U_LAWFUL) ? dlevel + (rnd(5) - 2) :
474.  /* chaotic */	     dlevel);
475.  	    pline("A mysterious force surrounds you...");
476.  	    if(newlevel < 1) newlevel = dlevel;
477.  	    if(newlevel == dlevel) (void) dotele();
478.  		
479.  	}
480.  #endif /* HARD /* */
481.  	if(newlevel == dlevel) return;	      /* this can happen */
482.  #ifdef STRONGHOLD
483.  	/* In Nethack 3.0, Hell starts after the stronghold.  Moreover,
484.  	 * there are traps in the stronghold, that can send the player
485.  	 * to hell (gnark, gnark)!  So we have to test here:
486.  	 */
487.  	if(!Inhell && newlevel > stronghold_level && !up && !at_ladder
488.  # ifdef ENDGAME
489.  	&& newlevel < ENDLEVEL
490.  # endif
491.  	) {
492.  #else
493.  	if(!Inhell && newlevel >= HELLLEVEL && !up) {
494.  #endif /* STRONGHOLD /**/
495.  	    You("arrive at the center of the earth...");
496.  	    pline("Unfortunately, it is here that hell is located.");
497.  #ifdef MSDOS
498.  	    (void) fflush(stdout);
499.  #endif
500.  	    if(Fire_resistance) {
501.  		pline("But the fire doesn't seem to harm you.");
502.  	    } else {
503.  		int save_dlevel = dlevel;
504.  
505.  		You("burn to a crisp.");
506.  		You("die...");
507.  		dlevel = maxdlevel = newlevel;
508.  		killer = "visit to hell";
509.  		done("burned");
510.  		dlevel = newlevel = save_dlevel; /* in case they survive */
511.  	    }
512.  	}
513.  
514.  	glo(dlevel);
515.  #ifdef MSDOS
516.  	/* Use O_TRUNC to force the file to be shortened if it already
517.  	 * exists and is currently longer.
518.  	 */
519.  	fd = open(lock, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK);
520.  #else
521.  	fd = creat(lock, FCMASK);
522.  #endif
523.  	if(fd < 0) {
524.  		/*
525.  		 * This is not quite impossible: e.g., we may have
526.  		 * exceeded our quota. If that is the case then we
527.  		 * cannot leave this level, and cannot save either.
528.  		 * Another possibility is that the directory was not
529.  		 * writable.
530.  		 */
531.  #ifdef DGK
532.  		pline("Cannot create level file '%s'.", lock);
533.  #else
534.  		pline("A mysterious force prevents you from going %s.",
535.  			up ? "up" : "down");
536.  #endif
537.  		return;
538.  	}
539.  
540.  #ifdef DGK
541.  	if (!savelev(fd, dlevel, COUNT)) {
542.  # ifdef ZEROCOMP
543.  		bflush(fd);
544.  # endif
545.  		(void) close(fd);
546.  		(void) unlink(lock);
547.  		pline("NetHack is out of disk space for making levels!");
548.  		You("can save, quit, or continue playing.");
549.  		return;
550.  	}
551.  #endif
552.  	if(Punished) unplacebc();
553.  	u.utrap = 0;				/* needed in level_tele */
554.  	u.ustuck = 0;				/* idem */
555.  	keepdogs();
556.  	seeoff(1);
557.  	if(u.uswallow)				/* idem */
558.  		u.uswldtim = u.uswallow = 0;
559.  	flags.nscrinh = 1;
560.  	u.ux = FAR;				/* hack */
561.  	(void) inshop();			/* probably was a trapdoor */
562.  
563.  #ifdef DGK
564.  # ifdef ZEROCOMP
565.  	bflush(fd);	/* forget buffer */
566.  # endif
567.  	savelev(fd,dlevel, WRITE);
568.  #else
569.  	savelev(fd,dlevel);
570.  #endif
571.  #ifdef ZEROCOMP
572.  	bflush(fd);	/* flush buffer */
573.  #endif
574.  	(void) close(fd);
575.  #ifdef REINCARNATION
576.  	if (newlevel == rogue_level || dlevel == rogue_level) {
577.  		/* No graphics characters on Rogue levels */
578.  		if (dlevel != rogue_level) {
579.  			savesyms = showsyms;
580.  			showsyms = defsyms;
581.  		}
582.  		if (newlevel != rogue_level)
583.  			showsyms = savesyms;
584.  	}
585.  #endif
586.  	dlevel = newlevel;
587.  	if(maxdlevel < dlevel)
588.  		maxdlevel = dlevel;
589.  	glo(dlevel);
590.  	if(
591.  # ifdef ENDGAME
592.  	   dlevel == ENDLEVEL ||
593.  # endif
594.  #if defined(DGK) && !defined(TOS)
595.  	/* If the level has no .where yet, it hasn't been made */
596.  	   !fileinfo[dlevel].where)
597.  #else
598.  	   !level_exists[dlevel])
599.  #endif
600.  		mklev();
601.  	else {
602.  #if defined(DGK) && !defined(TOS)
603.  		/* If not currently accessible, swap it in. */
604.  		if (fileinfo[dlevel].where != ACTIVE)
605.  			swapin_file(dlevel);
606.  #endif
607.  #if defined(MSDOS) && !defined(TOS)
608.  		if((fd = open(lock, O_RDONLY | O_BINARY)) < 0) {
609.  #else
610.  		if((fd = open(lock,0)) < 0) {
611.  #endif
612.  			pline("Cannot open %s .", lock);
613.  			pline("Probably someone removed it.");
614.  			done("tricked");
615.  		}
616.  #ifdef ZEROCOMP
617.  		minit();
618.  #endif
619.  		getlev(fd, hackpid, dlevel, FALSE);
620.  		(void) close(fd);
621.  	}
622.  
623.  #ifdef ENDGAME
624.  	if(dlevel != ENDLEVEL)
625.  #endif
626.  	if(at_stairs) {
627.  	    if(up) {
628.  #ifdef STRONGHOLD
629.  		if (!at_ladder) {
630.  #endif
631.  		    u.ux = xdnstair;
632.  		    u.uy = ydnstair;
633.  #ifdef STRONGHOLD
634.  		} else {
635.  		    u.ux = xdnladder;
636.  		    u.uy = ydnladder;
637.  		}
638.  #endif
639.  /* Remove bug which crashes with levitation/punishment  KAA */
640.  		if(Punished) {
641.  		    if(!Levitation)
642.  #ifdef STRONGHOLD
643.  			pline("With great effort you climb the %s.",
644.  			      !at_ladder ? "stairs" : "ladder");
645.  #else
646.  			pline("With great effort you climb the stairs.");
647.  #endif
648.  		    placebc(1);
649.  		}
650.  	    } else {
651.  #ifdef STRONGHOLD
652.  		if (!at_ladder) {
653.  #endif
654.  		    u.ux = xupstair;
655.  		    u.uy = yupstair;
656.  #ifdef STRONGHOLD
657.  		} else {
658.  		    u.ux = xupladder;
659.  		    u.uy = yupladder;
660.  		}
661.  #endif
662.  		if(inv_weight() + 5 > 0 || Punished || Fumbling) {
663.  #ifdef STRONGHOLD
664.  			You("fall down the %s.",
665.  			      !at_ladder ? "stairs" : "ladder");
666.  #else
667.  			You("fall down the stairs.");
668.  #endif
669.  			losehp(rnd(3), "fall");
670.  			if(Punished) {
671.  			    if(uwep != uball && rn2(3)) {
672.  				pline("... and are hit by the iron ball.");
673.  				losehp(rnd(20), "iron ball");
674.  			    }
675.  			    placebc(1);
676.  			}
677.  			selftouch("Falling, you");
678.  		}
679.  	    }
680.  	} else {	/* trapdoor or level_tele */
681.  	    register int tryct = 0;
682.  	    do {
683.  #ifdef STRONGHOLD
684.  		/* Prevent teleport-landing inside the castle */
685.  		if(dlevel == stronghold_level) {
686.  			if(up) u.ux = (COLNO - rnd(8));
687.  			else u.ux = rnd(6);
688.  		}
689.  		else
690.  		/* Prevent teleport-landing inside Vlad's tower */
691.  		if(dlevel >= tower_level && dlevel <= tower_level+2) {
692.  			do {
693.  			    u.ux = rnd(COLNO-1);
694.  			} while (u.ux > 29 && u.ux < 47); 
695.  		}
696.  		else
697.  #endif
698.  		u.ux = rnd(COLNO-1);
699.  		u.uy = rn2(ROWNO);
700.  	    } while(tryct++ < 100 && (levl[u.ux][u.uy].typ != ROOM &&
701.  		     levl[u.ux][u.uy].typ != CORR) || levl[u.ux][u.uy].mmask);
702.  	    if(tryct >= 100)
703.  		panic("goto_level: could not relocate player!");
704.  	    if(Punished){
705.  		if(uwep != uball && !up /* %% */ && rn2(5)){
706.  			pline("The iron ball falls on your %s.",
707.  				body_part(HEAD));
708.  			if (uarmh)
709.  				Your("helmet doesn't help too much...");
710.  			losehp(rnd(25), "iron ball");
711.  		}
712.  		placebc(1);
713.  	    }
714.  	    selftouch("Falling, you");
715.  	}
716.  	(void) inshop();
717.  	initrack();
718.  
719.  	losedogs();
720.  	if(levl[u.ux][u.uy].mmask) mnexto(m_at(u.ux, u.uy));
721.  	flags.nscrinh = 0;
722.  	setsee();
723.  	seeobjs();	/* make old cadavers disappear - riv05!a3 */
724.  	docrt();
725.  	if(!flags.nopick && (levl[u.ux][u.uy].omask || levl[u.ux][u.uy].gmask))
726.  	    pickup(1);
727.  	else read_engr_at(u.ux,u.uy);
728.  #ifdef HARD
729.  	/* Final confrontation */
730.  	if (dlevel == 1 && u.uhave_amulet && flags.no_of_wizards == 0)
731.  	    resurrect();
732.  #endif
733.  }
734.  
735.  int
736.  donull() {
737.  	return(1);	/* Do nothing, but let other things happen */
738.  }
739.  
740.  static
741.  int
742.  wipeoff() {
743.  	if(u.ucreamed < 4)	u.ucreamed = 0;
744.  	else			u.ucreamed -= 4;
745.  	if (Blinded < 4)	Blinded = 0;
746.  	else			Blinded -= 4;
747.  	if (!Blinded) {
748.  		pline("You've got the glop off.");
749.  		u.ucreamed = 0;
750.  		make_blinded(0L,TRUE);
751.  		return(0);
752.  	} else if (!u.ucreamed) {
753.  		Your("%s feels clean now.", body_part(FACE));
754.  		return(0);
755.  	}
756.  	return(1);		/* still busy */
757.  }
758.  
759.  int
760.  dowipe()
761.  {
762.  	if(u.ucreamed)  {
763.  		static char buf[39];
764.  
765.  		Sprintf(buf, "wiping off your %s", body_part(FACE));
766.  		set_occupation(wipeoff, buf, 0);
767.  		/* Not totally correct; what if they change back after now
768.  		 * but before they're finished wiping?
769.  		 */
770.  		return(1);
771.  	}
772.  	Your("%s is already clean.", body_part(FACE));
773.  	return(1);
774.  }
775.  
776.  /* split obj so that it gets size num */
777.  /* remainder is put in the object structure delivered by this call */
778.  struct obj *
779.  splitobj(obj, num) register struct obj *obj; register int num; {
780.  register struct obj *otmp;
781.  	otmp = newobj(0);
782.  	*otmp = *obj;		/* copies whole structure */
783.  	otmp->o_id = flags.ident++;
784.  	otmp->onamelth = 0;
785.  	obj->quan = num;
786.  	obj->owt = weight(obj);
787.  	otmp->quan -= num;
788.  	otmp->owt = weight(otmp);	/* -= obj->owt ? */
789.  	obj->nobj = otmp;
790.  	if(obj->unpaid) splitbill(obj,otmp);
791.  	return(otmp);
792.  }
793.  
794.  void
795.  set_wounded_legs(side, timex)
796.  register long side;
797.  register int timex;
798.  {
799.  	if(!Wounded_legs) ATEMP(A_DEX)--;
800.  
801.  	if(!Wounded_legs || (Wounded_legs & TIMEOUT))
802.  		Wounded_legs |= side + timex;
803.  	else
804.  		Wounded_legs |= side;
805.  }
806.  
807.  void
808.  heal_legs()
809.  {
810.  	if(Wounded_legs) {
811.  		if (ATEMP(A_DEX) < 0) ATEMP(A_DEX)++;
812.  
813.  		if((Wounded_legs & BOTH_SIDES) == BOTH_SIDES) {
814.  			Your("%s feel somewhat better.",
815.  				makeplural(body_part(LEG)));
816.  		} else {
817.  			Your("%s feels somewhat better.",
818.  				body_part(LEG));
819.  		}
820.  		Wounded_legs = 0;
821.  	}
822.  }