Source:NetHack 2.3e/do.c

From NetHackWiki
(Redirected from NetHack 2.3e/do.c)
Jump to navigation Jump to search

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

Warning! This is the source code from an old release. For the latest release, see Source code

Screenshots and source code from Hack are used under the CWI license.

1.    /*	SCCS Id: @(#)do.c	2.3	88/02/11
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    
4.    /* Contains code for 'd', 'D' (drop), '>', '<' (up, down) and 't' (throw) */
5.    
6.    #include "hack.h"
7.    
8.    extern struct obj *splitobj(), *addinv();
9.    extern boolean hmon();
10.   extern boolean level_exists[];
11.   extern struct monst youmonst;
12.   extern char *Doname();
13.   extern char *nomovemsg;
14.   int	identify();
15.   #ifdef KAA
16.   extern char *xname();
17.   #endif
18.   
19.   dodrop() {
20.   	if(u.ugold)	return(drop(getobj("0$#", "drop")));
21.   	else		return(drop(getobj("0#", "drop")));
22.   }
23.   
24.   static
25.   drop(obj) register struct obj *obj; {
26.   	if(!obj) return(0);
27.   	if(obj->olet == GOLD_SYM) {		/* pseudo object */
28.   		register long amount = OGOLD(obj);
29.   
30.   		if(amount == 0)
31.   			pline("You didn't drop any gold pieces.");
32.   /* Fix bug with dropping huge amounts of gold read as negative    KAA */
33.   		else if(amount < 0) {
34.   			u.ugold += amount;
35.   	pline("The LRS would be very interested to know you have that much.");
36.   		} else {
37.   			/* uswallow test added by GAN 01/29/87 */
38.   			pline("You dropped %ld gold piece%s.",
39.   				 amount, plur(amount));
40.   			if(u.uswallow)
41.   				(u.ustuck)->mgold += amount;
42.   			else {
43.   				mkgold(amount, u.ux, u.uy);
44.   				if(Invisible) newsym(u.ux, u.uy);
45.   			}
46.   		}
47.   		free((char *) obj);
48.   		return(1);
49.   	}
50.   	if(obj->owornmask & (W_ARMOR | W_RING | W_TOOL)){
51.   		pline("You cannot drop something you are wearing.");
52.   		return(0);
53.   	}
54.   	if(obj == uwep) {
55.   		if(uwep->cursed) {
56.   			pline("Your weapon is welded to your hand!");
57.   			return(0);
58.   		}
59.   		setuwep((struct obj *) 0);
60.   	}
61.   #ifdef WALKIES
62.           if (obj->otyp == LEASH) {
63.               register struct monst *mtmp = fmon;
64.               while (mtmp && !mtmp->mleashed) mtmp = mtmp->nmon;
65.               if (mtmp) {
66.                   pline ("Your leash is tied around your hand.");
67.                   return (0);
68.               }
69.           }
70.   #endif
71.   #ifdef SINKS
72.   	if((obj->olet == RING_SYM) && IS_SINK(levl[u.ux][u.uy].typ))
73.   	    if (u.uswallow) {
74.   		freeinv(obj);
75.   		mpickobj(u.ustuck,obj);
76.   		return(1);
77.   	    }
78.   	    else {
79.   		dosinkring(obj);
80.   		return(1);
81.   	    }
82.   #endif
83.   	pline("You dropped %s.", doname(obj));
84.   	dropx(obj);
85.   	return(1);
86.   }
87.   
88.   /* Called in several places - should not produce texts */
89.   dropx(obj)
90.   register struct obj *obj;
91.   {
92.   	freeinv(obj);
93.   	dropy(obj);
94.   }
95.   
96.   dropy(obj)
97.   register struct obj *obj;
98.   {
99.   	if(obj->otyp == CRYSKNIFE)
100.  		obj->otyp = WORM_TOOTH;
101.  	/* uswallow check done by GAN 01/29/87 */
102.  	if(u.uswallow)
103.  		mpickobj(u.ustuck,obj);
104.  	else  {
105.  		obj->ox = u.ux;
106.  		obj->oy = u.uy;
107.  		/* Blind check added by GAN 02/18/87 */
108.  		if(Blind)  {
109.  #ifdef KAA
110.  			if(obj->olet != ')')
111.  #endif
112.  			    obj->dknown = index("/=!?*",obj->olet) ? 0 : 1;
113.  			obj->known = 0;
114.  		}
115.  		obj->nobj = fobj;
116.  		fobj = obj;
117.  		if(Invisible) newsym(u.ux,u.uy);
118.  		subfrombill(obj);
119.  		stackobj(obj);
120.  	}
121.  }
122.  
123.  /* drop several things */
124.  doddrop() {
125.  	return(ggetobj("drop", drop, 0));
126.  }
127.  
128.  dodown()
129.  {
130.  	if(u.ux != xdnstair || u.uy != ydnstair) {
131.  		pline("You can't go down here.");
132.  		return(0);
133.  	}
134.  	if(u.ustuck) {
135.  		pline("You are being held, and cannot go down.");
136.  		return(1);
137.  	}
138.  	if(Levitation) {
139.  		pline("Your floating high above the stairs.");
140.  		return(0);
141.  	}
142.  
143.  	goto_level(dlevel+1, TRUE);
144.  	return(1);
145.  }
146.  
147.  doup()
148.  {
149.  	if(u.ux != xupstair || u.uy != yupstair) {
150.  		pline("You can't go up here.");
151.  		return(0);
152.  	}
153.  	if(u.ustuck) {
154.  		pline("You are being held, and cannot go up.");
155.  		return(1);
156.  	}
157.  	if(!Levitation && inv_weight() + 5 > 0) {
158.  		pline("Your load is too heavy to climb the stairs.");
159.  		return(1);
160.  	}
161.  
162.  	goto_level(dlevel-1, TRUE);
163.  	return(1);
164.  }
165.  
166.  goto_level(newlevel, at_stairs)
167.  register int newlevel;
168.  register boolean at_stairs;
169.  {
170.  	register fd;
171.  	register boolean up = (newlevel < dlevel);
172.  
173.  	if(newlevel <= 0) done("escaped");    /* in fact < 0 is impossible */
174.  	if(newlevel > MAXLEVEL) newlevel = MAXLEVEL;	/* strange ... */
175.  	if(newlevel == dlevel) return;	      /* this can happen */
176.  
177.  	glo(dlevel);
178.  #ifdef DGK
179.  	/* Use O_TRUNC to force the file to be shortened if it already
180.  	 * exists and is currently longer.
181.  	 */
182.  	fd = open(lock, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FMASK);
183.  #else
184.  	fd = creat(lock, FMASK);
185.  #endif
186.  	if(fd < 0) {
187.  		/*
188.  		 * This is not quite impossible: e.g., we may have
189.  		 * exceeded our quota. If that is the case then we
190.  		 * cannot leave this level, and cannot save either.
191.  		 * Another possibility is that the directory was not
192.  		 * writable.
193.  		 */
194.  #ifdef DGK
195.  		pline("Cannot create level file '%s'.", lock);
196.  #else
197.  		pline("A mysterious force prevents you from going %s.",
198.  			up ? "up" : "down");
199.  #endif
200.  		return;
201.  	}
202.  
203.  #ifdef DGK
204.  	if (!savelev(fd, dlevel, COUNT)) {
205.  		(void) close(fd);
206.  		(void) unlink(lock);
207.  		pline("HACK is out of disk space for making levels!");
208.  		pline("You can save, quit, or continue playing.");
209.  		return;
210.  	}
211.  #endif
212.  	if(Punished) unplacebc();
213.  	u.utrap = 0;				/* needed in level_tele */
214.  	u.ustuck = 0;				/* idem */
215.  	keepdogs();
216.  	seeoff(1);
217.  	if(u.uswallow)				/* idem */
218.  		u.uswldtim = u.uswallow = 0;
219.  	flags.nscrinh = 1;
220.  	u.ux = FAR;				/* hack */
221.  	(void) inshop();			/* probably was a trapdoor */
222.  
223.  #ifdef DGK
224.  	savelev(fd,dlevel, WRITE);
225.  #else
226.  	savelev(fd,dlevel);
227.  #endif
228.  	(void) close(fd);
229.  
230.  	dlevel = newlevel;
231.  	if(maxdlevel < dlevel)
232.  		maxdlevel = dlevel;
233.  	glo(dlevel);
234.  #ifdef MSDOS
235.  	/* If the level has no where yet, it hasn't been made
236.  	 */
237.  	if(!fileinfo[dlevel].where)
238.  #else
239.  	if(!level_exists[dlevel])
240.  #endif
241.  		mklev();
242.  	else {
243.  		extern int hackpid;
244.  #ifdef DGK
245.  		/* If not currently accessible, swap it in.
246.  		 */
247.  		if (fileinfo[dlevel].where != ACTIVE)
248.  			swapin_file(dlevel);
249.  
250.  		if((fd = open(lock, O_RDONLY | O_BINARY)) < 0) {
251.  #else
252.  		if((fd = open(lock,0)) < 0) {
253.  #endif
254.  			pline("Cannot open %s .", lock);
255.  			pline("Probably someone removed it.");
256.  			done("tricked");
257.  		}
258.  		getlev(fd, hackpid, dlevel);
259.  		(void) close(fd);
260.  	}
261.  
262.  	if(at_stairs) {
263.  	    if(up) {
264.  		u.ux = xdnstair;
265.  		u.uy = ydnstair;
266.  		if(!u.ux) {		/* entering a maze from below? */
267.  		    u.ux = xupstair;	/* this will confuse the player! */
268.  		    u.uy = yupstair;
269.  		}
270.  /* Remove bug which crashes with levitation/punishment  KAA */
271.  		if(Punished) {
272.  		    if(!Levitation) 
273.  			pline("With great effort you climb the stairs.");
274.  		    placebc(1);
275.  		}
276.  	    } else {
277.  		u.ux = xupstair;
278.  		u.uy = yupstair;
279.  		if(inv_weight() + 5 > 0 || Punished){
280.  			pline("You fall down the stairs.");	/* %% */
281.  			losehp(rnd(3), "fall");
282.  			if(Punished) {
283.  			    if(uwep != uball && rn2(3)){
284.  				pline("... and are hit by the iron ball.");
285.  				losehp(rnd(20), "iron ball");
286.  			    }
287.  			    placebc(1);
288.  			}
289.  			selftouch("Falling, you");
290.  		}
291.  	    }
292.  	    { register struct monst *mtmp = m_at(u.ux, u.uy);
293.  	      if(mtmp)
294.  		mnexto(mtmp);
295.  	    }
296.  	} else {	/* trapdoor or level_tele */
297.  	    do {
298.  		u.ux = rnd(COLNO-1);
299.  		u.uy = rn2(ROWNO);
300.  	    } while(levl[u.ux][u.uy].typ != ROOM ||
301.  			m_at(u.ux,u.uy));
302.  	    if(Punished){
303.  		if(uwep != uball && !up /* %% */ && rn2(5)){
304.  			pline("The iron ball falls on your head.");
305.  			losehp(rnd(25), "iron ball");
306.  		}
307.  		placebc(1);
308.  	    }
309.  	    selftouch("Falling, you");
310.  	}
311.  	(void) inshop();
312.  	initrack();
313.  
314.  	losedogs();
315.  	{ register struct monst *mtmp;
316.  	  if(mtmp = m_at(u.ux, u.uy)) mnexto(mtmp);	/* riv05!a3 */
317.  	}
318.  	flags.nscrinh = 0;
319.  	setsee();
320.  	seeobjs();	/* make old cadavers disappear - riv05!a3 */
321.  	docrt();
322.  	pickup(1);
323.  	read_engr_at(u.ux,u.uy);
324.  }
325.  
326.  donull() {
327.  	return(1);	/* Do nothing, but let other things happen */
328.  }
329.  
330.  #if defined(KAA) && defined(KOPS)
331.  wipeoff()
332.  {
333.  	if(u.ucreamed < 4)	u.ucreamed = 0;
334.  	else			u.ucreamed -= 4;
335.  	if(u.ucreamed > 0)  {
336.  		Blinded -= 4;
337.  		if(Blind <= 1) {
338.  			pline("You've got the glop off.");
339.  			u.ucreamed = 0;
340.  			Blinded = 1;
341.  			return(0);
342.  		}
343.  		return(1);		/* still busy */
344.  	}
345.  	pline("Your face feels clean now.");
346.  	u.ucreamed = 0;
347.  	return(0);
348.  }
349.  	
350.  dowipe()
351.  {
352.  	if(u.ucreamed)  {
353.  #ifdef DGKMOD
354.  		set_occupation(wipeoff, "wiping off your face", 0);
355.  #else
356.  		occupation = wipeoff;
357.  		occtxt = "wiping off your face";
358.  #endif
359.  		return(1);
360.  	}
361.  	pline("Your face is already clean.");
362.  	return(1);
363.  }
364.  #endif
365.  
366.  /* split obj so that it gets size num */
367.  /* remainder is put in the object structure delivered by this call */
368.  struct obj *
369.  splitobj(obj, num) register struct obj *obj; register int num; {
370.  register struct obj *otmp;
371.  	otmp = newobj(0);
372.  	*otmp = *obj;		/* copies whole structure */
373.  	otmp->o_id = flags.ident++;
374.  	otmp->onamelth = 0;
375.  	obj->quan = num;
376.  	obj->owt = weight(obj);
377.  	otmp->quan -= num;
378.  	otmp->owt = weight(otmp);	/* -= obj->owt ? */
379.  	obj->nobj = otmp;
380.  	if(obj->unpaid) splitbill(obj,otmp);
381.  	return(otmp);
382.  }
383.  
384.  more_experienced(exp,rexp)
385.  register int exp, rexp;
386.  {
387.  	extern char pl_character[];
388.  
389.  	u.uexp += exp;
390.  	u.urexp += 4*exp + rexp;
391.  	if(exp) flags.botl = 1;
392.  	if(u.urexp >= ((pl_character[0] == 'W') ? 1000 : 2000))
393.  		flags.beginner = 0;
394.  }
395.  
396.  set_wounded_legs(side, timex)
397.  register long side;
398.  register int timex;
399.  {
400.  	if(!Wounded_legs || (Wounded_legs & TIMEOUT))
401.  		Wounded_legs |= side + timex;
402.  	else
403.  		Wounded_legs |= side;
404.  }
405.  
406.  heal_legs()
407.  {
408.  	if(Wounded_legs) {
409.  		if((Wounded_legs & BOTH_SIDES) == BOTH_SIDES)
410.  			pline("Your legs feel somewhat better.");
411.  		else
412.  			pline("Your leg feels somewhat better.");
413.  		Wounded_legs = 0;
414.  	}
415.  }
416.  
417.  #ifdef SINKS
418.  trycall(obj)
419.  register struct obj *obj;
420.  {
421.  	if(!objects[obj->otyp].oc_name_known &&
422.  	   !objects[obj->otyp].oc_uname)
423.  	   docall(obj);
424.  }
425.  
426.  dosinkring(obj)  /* obj is a ring being dropped over a kitchen sink */
427.  register struct obj *obj;
428.  {
429.  register struct obj *otmp,*otmp2;
430.  register short eaten;
431.  	pline("You drop %s down the drain.", doname(obj));
432.  	switch(obj->otyp) {
433.  	    case RIN_ADORNMENT:  {
434.  		pline("The faucets flash brightly for a moment.");
435.  		trycall(obj);
436.  		break;
437.  		}
438.  	    case RIN_REGENERATION:  {
439.  		pline("The sink looks as good as new.");
440.  		trycall(obj);
441.  		break;
442.  		}
443.  	    case RIN_SEARCHING:
444.  		break;
445.  	    case RIN_SEE_INVISIBLE:
446.  		break;
447.  	    case RIN_STEALTH:  {
448.  		pline("The sink seems to blend into the floor for a moment.");
449.  		trycall(obj);
450.  		break;
451.  		}
452.  	    case RIN_LEVITATION:  {
453.  		pline("The sink quivers upward for a moment.");
454.  		trycall(obj);
455.  		break;
456.  		}
457.  	    case RIN_POISON_RESISTANCE:
458.  		break;
459.  	    case RIN_AGGRAVATE_MONSTER:
460.  		break;
461.  	    case RIN_HUNGER:  {
462.  		eaten = 0;
463.  		for(otmp=fobj; otmp; otmp=otmp2) {
464.  		    otmp2 = otmp->nobj;
465.  		    if(otmp->ox == u.ux && otmp->oy == u.uy)
466.  			if(!Punished ||
467.  			    (otmp->otyp != HEAVY_IRON_BALL && otmp->otyp != IRON_CHAIN)) {
468.  			    eaten++;
469.  			    pline("Suddenly, %s vanishes from the sink!",doname(otmp));
470.  			    delobj(otmp);
471.  			}
472.  		}
473.  		if(eaten)
474.  		    trycall(obj);
475.  		break;
476.  		}
477.  	    case RIN_FIRE_RESISTANCE:  {
478.  		pline("The hot water faucet flashes brightly for a moment.");
479.  		trycall(obj);
480.  		break;
481.  		}
482.  	    case RIN_COLD_RESISTANCE:  {
483.  		pline("The cold water faucet flashes brightly for a moment.");
484.  		trycall(obj);
485.  		break;
486.  		}
487.  	    case RIN_PROTECTION_FROM_SHAPE_CHAN:  {
488.  		pline("The sink momentarily looks nothing like a fountain.");
489.  		trycall(obj);
490.  		break;
491.  		}
492.  	    case RIN_CONFLICT:
493.  		break;
494.  	    case RIN_GAIN_STRENGTH:
495.  		break;
496.  	    case RIN_INCREASE_DAMAGE:
497.  		break;
498.  	    case RIN_PROTECTION:
499.  		break;
500.  	    case RIN_WARNING:  {
501.  		pline("The sink glows white for a moment.");
502.  		trycall(obj);
503.  		break;
504.  		}
505.  	    case RIN_TELEPORTATION:	/* fall through */
506.  	    case RIN_TELEPORT_CONTROL:  {
507.  		pline("The sink momentarily vanishes.");
508.  		trycall(obj);
509.  		break;
510.  		}
511.  	    case RIN_POLYMORPH:		/* fall through */
512.  	    case RIN_POLYMORPH_CONTROL:  {
513.  		pline("The sink momentarily looks like a fountain.");
514.  		trycall(obj);
515.  		break;
516.  		}
517.  	}
518.  	if (!rn2(20)) {
519.  		pline("The sink backs up, leaving %s.", doname(obj));
520.  		dropx(obj);
521.  	}
522.  	else
523.  		useup(obj);
524.  }
525.  #endif