Source:Hack 1.0/hack.do.c

From NetHackWiki
Revision as of 22:18, 3 March 2008 by Kernigh bot (talk | contribs) (Hack 1.0/hack.do.c moved to Source:Hack 1.0/hack.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 hack.do.c from the source code of Hack 1.0. To link to a particular line, write [[Hack 1.0/hack.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.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
2.    
3.    #include <stdio.h>
4.    #include <signal.h>
5.    #include "hack.h"
6.    #include "def.func_tab.h"
7.    
8.    extern char *getenv(),*parse(),*getlogin(),*lowc(),*unctrl();
9.    extern int float_down();
10.   extern char *nomovemsg, *catmore;
11.   extern struct obj *splitobj(), *addinv();
12.   extern boolean hmon();
13.   
14.   /*	Routines to do various user commands */
15.   
16.   int done1();
17.   
18.   dodrink() {
19.   	register struct obj *otmp,*objs;
20.   	register struct monst *mtmp;
21.   	register int unkn = 0, nothing = 0;
22.   
23.   	otmp = getobj("!", "drink");
24.   	if(!otmp) return(0);
25.   	switch(otmp->otyp){
26.   	case POT_RESTORE_STRENGTH:
27.   		unkn++;
28.   		pline("Wow!  This makes you feel great!");
29.   		if(u.ustr < u.ustrmax) {
30.   			u.ustr = u.ustrmax;
31.   			flags.botl = 1;
32.   		}
33.   		break;
34.   	case POT_BOOZE:
35.   		unkn++;
36.   		pline("Ooph!  This tastes like liquid fire!");
37.   		Confusion += d(3,8);
38.   		/* the whiskey makes us feel better */
39.   		if(u.uhp < u.uhpmax) losehp(-1, "bottle of whiskey");
40.   		if(!rn2(4)) {
41.   			pline("You pass out.");
42.   			multi = -rnd(15);
43.   			nomovemsg = "You awake with a headache.";
44.   		}
45.   		break;
46.   	case POT_INVISIBILITY:
47.   		if(Invis)
48.   		  nothing++;
49.   		else {
50.   		  if(!Blind)
51.   		    pline("Gee!  All of a sudden, you can't see yourself.");
52.   		  else
53.   		    pline("You feel rather airy."), unkn++;
54.   		  newsym(u.ux,u.uy);
55.   		}
56.   		Invis += rn1(15,31);
57.   		break;
58.   	case POT_FRUIT_JUICE:
59.   		pline("This tastes like fruit juice.");
60.   		lesshungry(20);
61.   		break;
62.   	case POT_HEALING:
63.   		pline("You begin to feel better.");
64.   		flags.botl = 1;
65.   		u.uhp += rnd(10);
66.   		if(u.uhp > u.uhpmax)
67.   			u.uhp = ++u.uhpmax;
68.   		if(Blind) Blind = 1;	/* see on next move */
69.   		if(Sick) Sick = 0;
70.   		break;
71.   	case POT_PARALYSIS:
72.   		pline("Your feet are frozen to the floor!");
73.   		nomul(-(rn1(10,25)));
74.   		break;
75.   	case POT_MONSTER_DETECTION:
76.   		if(!fmon) {
77.   			strange_feeling(otmp);
78.   			return(1);
79.   		} else {
80.   			cls();
81.   			for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
82.   				if(mtmp->mx > 0)
83.   				at(mtmp->mx,mtmp->my,mtmp->data->mlet);
84.   			prme();
85.   			pline("You sense the presence of monsters.");
86.   			more();
87.   			docrt();
88.   		}
89.   		break;
90.   	case POT_OBJECT_DETECTION:
91.   		if(!fobj) {
92.   			strange_feeling(otmp);
93.   			return(1);
94.   		} else {
95.   		    for(objs = fobj; objs; objs = objs->nobj)
96.   			if(objs->ox != u.ux || objs->oy != u.uy)
97.   				goto outobjmap;
98.   		    pline("You sense the presence of objects close nearby.");
99.   		    break;
100.  		outobjmap:
101.  			cls();
102.  			for(objs = fobj; objs; objs = objs->nobj)
103.  				at(objs->ox,objs->oy,objs->olet);
104.  			prme();
105.  			pline("You sense the presence of objects.");
106.  			more();
107.  			docrt();
108.  		}
109.  		break;
110.  	case POT_SICKNESS:
111.  		pline("Yech! This stuff tastes like poison.");
112.  		if(Poison_resistance)
113.      pline("(But in fact it was biologically contaminated orange juice.)");
114.  		losestr(rn1(4,3));
115.  		losehp(rnd(10), "poison potion");
116.  		break;
117.  	case POT_CONFUSION:
118.  		if(!Confusion)
119.  			pline("Huh, What?  Where am I?");
120.  		else
121.  			nothing++;
122.  		Confusion += rn1(7,16);
123.  		break;
124.  	case POT_GAIN_STRENGTH:
125.  		pline("Wow do you feel strong!");
126.  		if(u.ustr == 118) break;
127.  		if(u.ustr > 17) u.ustr += rnd(118-u.ustr);
128.  		else u.ustr++;
129.  		if(u.ustr > u.ustrmax) u.ustrmax = u.ustr;
130.  		flags.botl = 1;
131.  		break;
132.  	case POT_SPEED:
133.  		if(Wounded_legs) {
134.  			if((Wounded_legs & BOTH_SIDES) == BOTH_SIDES)
135.  				pline("Your legs feel somewhat better.");
136.  			else
137.  				pline("Your leg feels somewhat better.");
138.  			Wounded_legs = 0;
139.  			unkn++;
140.  			break;
141.  		}
142.  		if(!(Fast & ~INTRINSIC))
143.  			pline("You are suddenly moving much faster.");
144.  		else
145.  			pline("Your legs get new energy."), unkn++;
146.  		Fast += rn1(10,100);
147.  		break;
148.  	case POT_BLINDNESS:
149.  		if(!Blind)
150.  			pline("A cloud of darkness falls upon you.");
151.  		else
152.  			nothing++;
153.  		Blind += rn1(100,250);
154.  		seeoff(0);
155.  		break;
156.  	case POT_GAIN_LEVEL: 
157.  		pluslvl();
158.  		break;
159.  	case POT_EXTRA_HEALING:
160.  		pline("You feel much better.");
161.  		flags.botl = 1;
162.  		u.uhp += d(2,20)+1;
163.  		if(u.uhp > u.uhpmax)
164.  			u.uhp = (u.uhpmax += 2);
165.  		if(Blind) Blind = 1;
166.  		if(Sick) Sick = 0;
167.  		break;
168.  	case POT_LEVITATION:
169.  		if(!Levitation)
170.  			float_up();
171.  		else
172.  			nothing++;
173.  		Levitation += rnd(100);
174.  		u.uprops[PROP(RIN_LEVITATION)].p_tofn = float_down;
175.  		break;
176.  	default:
177.  		pline("What a funny potion! (%d)", otmp->otyp);
178.  		impossible();
179.  		return(0);
180.  	}
181.  	if(nothing) {
182.  	    unkn++;
183.  	    pline("You have a peculiar feeling for a moment, then it passes.");
184.  	}
185.  	if(otmp->dknown && !objects[otmp->otyp].oc_name_known) {
186.  		if(!unkn) {
187.  			objects[otmp->otyp].oc_name_known = 1;
188.  			u.urexp += 10;
189.  		} else if(!objects[otmp->otyp].oc_uname)
190.  			docall(otmp);
191.  	}
192.  	useup(otmp);
193.  	return(1);
194.  }
195.  
196.  pluslvl()
197.  {
198.  	register num;
199.  
200.  	pline("You feel more experienced.");
201.  	num = rnd(10);
202.  	u.uhpmax += num;
203.  	u.uhp += num;
204.  	u.uexp = (10*pow(u.ulevel-1))+1;
205.  	pline("Welcome to level %d.", ++u.ulevel);
206.  	flags.botl = 1;
207.  }
208.  
209.  strange_feeling(obj)
210.  register struct obj *obj;
211.  {
212.  	pline("You have a strange feeling for a moment, then it passes.");
213.  	if(!objects[obj->otyp].oc_name_known && !objects[obj->otyp].oc_uname)
214.  		docall(obj);
215.  	useup(obj);
216.  }
217.  
218.  dodrop() {
219.  	register struct obj *obj;
220.  
221.  	obj = getobj("0$#", "drop");
222.  	if(!obj) return(0);
223.  	if(obj->olet == '$') {
224.  		if(obj->quan == 0)
225.  			pline("You didn't drop any gold pieces.");
226.  		else {
227.  			mkgold((int) obj->quan, u.ux, u.uy);
228.  			pline("You dropped %u gold piece%s.",
229.  				obj->quan, plur(obj->quan));
230.  			if(Invis) newsym(u.ux, u.uy);
231.  		}
232.  		free((char *) obj);
233.  		return(1);
234.  	}
235.  	return(drop(obj));
236.  }
237.  
238.  drop(obj) register struct obj *obj; {
239.  	if(obj->owornmask & (W_ARMOR | W_RING)){
240.  		pline("You cannot drop something you are wearing.");
241.  		return(0);
242.  	}
243.  	if(obj == uwep) {
244.  		if(uwep->cursed) {
245.  			pline("Your weapon is welded to your hand!");
246.  			return(0);
247.  		}
248.  		setuwep((struct obj *) 0);
249.  	}
250.  	pline("You dropped %s.", doname(obj));
251.  	dropx(obj);
252.  	return(1);
253.  }
254.  
255.  dropx(obj) register struct obj *obj; {
256.  	if(obj->otyp == CRYSKNIFE)
257.  		obj->otyp = WORM_TOOTH;
258.  	freeinv(obj);
259.  	obj->ox = u.ux;
260.  	obj->oy = u.uy;
261.  	obj->nobj = fobj;
262.  	fobj = obj;
263.  	if(Invis) newsym(u.ux,u.uy);
264.  	subfrombill(obj);
265.  	stackobj(obj);
266.  }
267.  
268.  /* drop several things */
269.  doddrop() {
270.  	return(ggetobj("drop", drop, 0));
271.  }
272.  
273.  rhack(cmd)
274.  register char *cmd;
275.  {
276.  	register struct func_tab *tlist = list;
277.  	boolean firsttime = FALSE;
278.  	register res;
279.  
280.  	if(!cmd) {
281.  		firsttime = TRUE;
282.  		flags.nopick = 0;
283.  		cmd = parse();
284.  	}
285.  	if(!*cmd || *cmd == 0377)
286.  		return;		/* probably we just had an interrupt */
287.  	if(movecm(cmd)) {
288.  	walk:
289.  		if(multi) flags.mv = 1;
290.  		domove();
291.  		return;
292.  	}
293.  	if(movecm(lowc(cmd))) {
294.  		flags.run = 1;
295.  	rush:
296.  		if(firsttime){
297.  			if(!multi) multi = COLNO;
298.  			u.last_str_turn = 0;
299.  		}
300.  		flags.mv = 1;
301.  #ifdef QUEST
302.  		if(flags.run >= 4) finddir();
303.  		if(firsttime){
304.  			u.ux0 = u.ux + u.dx;
305.  			u.uy0 = u.uy + u.dy;
306.  		}
307.  #endif QUEST
308.  		domove();
309.  		return;
310.  	}
311.  	if((*cmd == 'f' && movecm(cmd+1)) ||
312.  		movecm(unctrl(cmd))) {
313.  		flags.run = 2;
314.  		goto rush;
315.  	}
316.  	if(*cmd == 'F' && movecm(lowc(cmd+1))) {
317.  		flags.run = 3;
318.  		goto rush;
319.  	}
320.  	if(*cmd == 'm' && movecm(cmd+1)) {
321.  		flags.run = 0;
322.  		flags.nopick = 1;
323.  		goto walk;
324.  	}
325.  	if(*cmd == 'M' && movecm(lowc(cmd+1))) {
326.  		flags.run = 1;
327.  		flags.nopick = 1;
328.  		goto rush;
329.  	}
330.  #ifdef QUEST
331.  	if(*cmd == cmd[1] && (*cmd == 'f' || *cmd == 'F')) {
332.  		flags.run = 4;
333.  		if(*cmd == 'F') flags.run += 2;
334.  		if(cmd[2] == '-') flags.run += 1;
335.  		goto rush;
336.  	}
337.  #endif QUEST
338.  	while(tlist->f_char) {
339.  		if(*cmd == tlist->f_char){
340.  			res = (*(tlist->f_funct))(0);
341.  			if(!res) {
342.  				flags.move = 0;
343.  				multi = 0;
344.  			}
345.  			return;
346.  		}
347.  		tlist++;
348.  	}
349.  	pline("Unknown command '%s'",cmd);
350.  	multi = flags.move = 0;
351.  }
352.  
353.  doredraw()
354.  {
355.  	docrt();
356.  	return(0);
357.  }
358.  
359.  dohelp()
360.  {
361.  	if(child(1)){
362.  		execl(catmore,"more","help",(char *)0);
363.  		exit(1);
364.  	}
365.  	return(0);
366.  }
367.  
368.  #ifdef SHELL
369.  dosh(){
370.  register char *str;
371.  	if(child(0)) {
372.  		(void) chdir(getenv("HOME"));
373.  		if(str = getenv("SHELL")) execl(str,str,(char *) 0);
374.  		if(strcmp("player", getlogin()))
375.  			execl("/bin/sh","sh",(char *) 0);
376.  		pline("sh: cannot execute.");
377.  		exit(1);
378.  	}
379.  	return(0);
380.  }
381.  #endif SHELL
382.  
383.  #ifdef BSD
384.  #include	<sys/wait.h>
385.  #else
386.  #include	<wait.h>
387.  #endif BSD
388.  
389.  child(wt) {
390.  register int f = fork();
391.  	if(f == 0){		/* child */
392.  		settty((char *) 0);
393.  		(void) setuid(getuid());
394.  		return(1);
395.  	}
396.  	if(f == -1) {	/* cannot fork */
397.  		pline("Fork failed. Try again.");
398.  		return(0);
399.  	}
400.  	/* fork succeeded; wait for child to exit */
401.  	(void) signal(SIGINT,SIG_IGN);
402.  	(void) signal(SIGQUIT,SIG_IGN);
403.  	(void) wait((union wait *) 0);
404.  	setctty();
405.  	(void) signal(SIGINT,done1);
406.  #ifdef WIZARD
407.  	if(wizard) (void) signal(SIGQUIT,SIG_DFL);
408.  #endif WIZARD
409.  	if(wt) getret();
410.  	docrt();
411.  	return(0);
412.  }
413.  
414.  dodown()
415.  {
416.  	if(u.ux != xdnstair || u.uy != ydnstair) {
417.  		pline("You can't go down here.");
418.  		return(0);
419.  	}
420.  	if(u.ustuck) {
421.  		pline("You are being held, and cannot go down.");
422.  		return(1);
423.  	}
424.  	if(Levitation) {
425.  		pline("You're floating high above the stairs.");
426.  		return(0);
427.  	}
428.  
429.  	goto_level(dlevel+1, TRUE);
430.  	return(1);
431.  }
432.  
433.  doup()
434.  {
435.  	if(u.ux != xupstair || u.uy != yupstair) {
436.  		pline("You can't go up here.");
437.  		return(0);
438.  	}
439.  	if(u.ustuck) {
440.  		pline("You are being held, and cannot go up.");
441.  		return(1);
442.  	}
443.  	if(inv_weight() + 5 > 0) {
444.  		pline("Your load is too heavy to climb the stairs.");
445.  		return(1);
446.  	}
447.  
448.  	goto_level(dlevel-1, TRUE);
449.  	return(1);
450.  }
451.  
452.  goto_level(newlevel, at_stairs)
453.  register int newlevel;
454.  register boolean at_stairs;
455.  {
456.  	register fd;
457.  	register boolean up = (newlevel < dlevel);
458.  
459.  	if(newlevel <= 0) done("escaped");	/* in fact < 0 is impossible */
460.  	if(newlevel == dlevel) return;		/* this cannot happen either */
461.  
462.  	glo(dlevel);
463.  	fd = creat(lock,FMASK);
464.  	if(fd < 0) {
465.  		/*
466.  		 * This is not quite impossible: e.g., we may have
467.  		 * exceeded our quota. If that is the case then we
468.  		 * cannot leave this level, and cannot save either.
469.  		 */
470.  		pline("A mysterious force prevents you from going %d.",
471.  			up ? "up" : "down");
472.  		return;
473.  	}
474.  
475.  	if(Punished) unplacebc();
476.  	keepdogs();
477.  	seeoff(1);
478.  	flags.nscrinh = 1;
479.  	u.ux = FAR;				/* hack */
480.  	(void) inshop();			/* probably was a trapdoor */
481.  
482.  	savelev(fd);
483.  	(void) close(fd);
484.  
485.  	dlevel = newlevel;
486.  	if(maxdlevel < dlevel)
487.  		maxdlevel = dlevel;
488.  	glo(dlevel);
489.  	if((fd = open(lock,0)) < 0)
490.  		mklev();
491.  	else {
492.  		(void) getlev(fd);
493.  		(void) close(fd);
494.  	}
495.  
496.  	if(at_stairs) {
497.  	    if(up) {
498.  		u.ux = xdnstair;
499.  		u.uy = ydnstair;
500.  		if(!u.ux) {		/* entering a maze from below? */
501.  		    u.ux = xupstair;	/* this will confuse the player! */
502.  		    u.uy = yupstair;
503.  		}
504.  		if(Punished){
505.  			pline("With great effort you climb the stairs");
506.  			placebc(1);
507.  		}
508.  	    } else {
509.  		u.ux = xupstair;
510.  		u.uy = yupstair;
511.  		if(inv_weight() + 5 > 0 || Punished){
512.  			pline("You fall down the stairs.");
513.  			losehp(rnd(3), "fall");
514.  			if(Punished) {
515.  			    if(uwep != uball && rn2(3)){
516.  				pline("... and are hit by the iron ball");
517.  				losehp(rnd(20), "iron ball");
518.  			    }
519.  			    placebc(1);
520.  			}
521.  			selftouch("Falling, you");
522.  		}
523.  	    }
524.  	} else {	/* trapdoor or level_tele */
525.  	    do {
526.  		u.ux = rnd(COLNO-1);
527.  		u.uy = rn2(ROWNO);
528.  	    } while(levl[u.ux][u.uy].typ != ROOM ||
529.  			m_at(u.ux,u.uy));
530.  	    if(Punished){
531.  		if(uwep != uball && !up /* %% */ && rn2(5)){
532.  			pline("The iron ball falls on your head.");
533.  			losehp(rnd(25), "iron ball");
534.  		}
535.  		placebc(1);
536.  	    }
537.  	    selftouch("Falling, you");
538.  	}
539.  	(void) inshop();
540.  #ifdef TRACK
541.  	initrack();
542.  #endif TRACK
543.  
544.  	losedogs();
545.  	flags.nscrinh = 0;
546.  	setsee();
547.  	docrt();
548.  	pickup();
549.  	read_engr_at(u.ux,u.uy);
550.  }
551.  
552.  donull() {
553.  	return(1);	/* Do nothing, but let other things happen */
554.  }
555.  
556.  struct monst *bhit(), *boomhit();
557.  dothrow()
558.  {
559.  	register struct obj *obj;
560.  	register struct monst *mon;
561.  	register tmp;
562.  
563.  	obj = getobj("#)", "throw");	/* it is also possible to throw food */
564.  					/* (or jewels, or iron balls ... ) */
565.  	if(!obj || !getdir())
566.  		return(0);
567.  	if(obj->owornmask & (W_ARMOR | W_RING)){
568.  		pline("You can't throw something you are wearing");
569.  		return(0);
570.  	}
571.  	if(obj == uwep){
572.  		if(obj->cursed){
573.  			pline("Your weapon is welded to your hand");
574.  			return(1);
575.  		}
576.  		if(obj->quan > 1)
577.  			setuwep(splitobj(obj, 1));
578.  		else
579.  			setuwep((struct obj *) 0);
580.  	}
581.  	else if(obj->quan > 1)
582.  		(void) splitobj(obj, 1);
583.  	freeinv(obj);
584.  	if(u.uswallow) {
585.  		mon = u.ustuck;
586.  		bhitpos.x = mon->mx;
587.  		bhitpos.y = mon->my;
588.  	} else if(obj->otyp == BOOMERANG) {
589.  		mon = boomhit(u.dx,u.dy);
590.  		/* boomhit delivers -1 if the thing was caught */
591.  		if((int) mon == -1) {
592.  			(void) addinv(obj);
593.  			return(1);
594.  		}
595.  	} else
596.  		mon = bhit(u.dx,u.dy,
597.  			(!Punished || obj != uball) ? 8 :
598.  				!u.ustuck ? 5 : 1,
599.  			obj->olet);
600.  	if(mon) {
601.  		/* awake monster if sleeping */
602.  		wakeup(mon);
603.  
604.  		if(obj->olet == WEAPON_SYM) {
605.  			tmp = -1+u.ulevel+mon->data->ac+abon();
606.  			if(obj->otyp < ROCK) {
607.  				if(!uwep ||
608.  				    uwep->otyp != obj->otyp+(BOW-ARROW))
609.  					tmp -= 4;
610.  				else {
611.  					tmp += uwep->spe;
612.  				}
613.  			} else
614.  			if(obj->otyp == BOOMERANG) tmp += 4;
615.  			tmp += obj->spe;
616.  			if(u.uswallow || tmp >= rnd(20)) {
617.  				if(hmon(mon,obj,1) == TRUE){
618.  				  /* mon still alive */
619.  #ifndef NOWORM
620.  				  cutworm(mon,bhitpos.x,bhitpos.y,obj->otyp);
621.  #endif NOWORM
622.  				} else mon = 0;
623.  				/* weapons thrown disappear sometimes */
624.  				if(obj->otyp < BOOMERANG && rn2(3)) {
625.  					/* check bill; free */
626.  					obfree(obj, (struct obj *) 0);
627.  					return(1);
628.  				}
629.  			} else miss(objects[obj->otyp].oc_name, mon);
630.  		} else if(obj->otyp == HEAVY_IRON_BALL) {
631.  			tmp = -1+u.ulevel+mon->data->ac+abon();
632.  			if(!Punished || obj != uball) tmp += 2;
633.  			if(u.utrap) tmp -= 2;
634.  			if(u.uswallow || tmp >= rnd(20)) {
635.  				if(hmon(mon,obj,1) == FALSE)
636.  					mon = 0;	/* he died */
637.  			} else miss("iron ball", mon);
638.  		} else {
639.  			if(cansee(bhitpos.x,bhitpos.y))
640.  				pline("You miss %s.",monnam(mon));
641.  			else pline("You miss it.");
642.  			if(obj->olet == FOOD_SYM && mon->data->mlet == 'd')
643.  				if(tamedog(mon,obj)) return(1);
644.  			if(obj->olet == GEM_SYM && mon->data->mlet == 'u'){
645.  			 if(obj->dknown && objects[obj->otyp].oc_name_known){
646.  			  if(objects[obj->otyp].g_val > 0){
647.  			    u.uluck += 5;
648.  			    goto valuable;
649.  			  } else {
650.  			    pline("%s is not interested in your junk.",
651.  				Monnam(mon));
652.  			  }
653.  			 } else { /* value unknown to @ */
654.  			    u.uluck++;
655.  			valuable:
656.  			    pline("%s graciously accepts your gift.",
657.  				Monnam(mon));
658.  			    mpickobj(mon, obj);
659.  			    rloc(mon);
660.  			    return(1);
661.  			 }
662.  			}
663.  		}
664.  	}
665.  	obj->ox = bhitpos.x;
666.  	obj->oy = bhitpos.y;
667.  	obj->nobj = fobj;
668.  	fobj = obj;
669.  	/* prevent him from throwing articles to the exit and escaping */
670.  	/* subfrombill(obj); */
671.  	stackobj(obj);
672.  	if(Punished && obj == uball &&
673.  		(bhitpos.x != u.ux || bhitpos.y != u.uy)){
674.  		freeobj(uchain);
675.  		unpobj(uchain);
676.  		if(u.utrap){
677.  			if(u.utraptype == TT_PIT)
678.  				pline("The ball pulls you out of the pit!");
679.  			else {
680.  			    register int side =
681.  				rn2(3) ? LEFT_SIDE : RIGHT_SIDE;
682.  			    pline("The ball pulls you out of the bear trap.");
683.  			    pline("Your %s leg is severely damaged.",
684.  				(side == LEFT_SIDE) ? "left" : "right");
685.  			    Wounded_legs |= side + rnd(1000);
686.  			    losehp(2, "thrown ball");
687.  			}
688.  			u.utrap = 0;
689.  		}
690.  		unsee();
691.  		uchain->nobj = fobj;
692.  		fobj = uchain;
693.  		u.ux = uchain->ox = bhitpos.x - u.dx;
694.  		u.uy = uchain->oy = bhitpos.y - u.dy;
695.  		setsee();
696.  		(void) inshop();
697.  	}
698.  	if(cansee(bhitpos.x, bhitpos.y)) prl(bhitpos.x,bhitpos.y);
699.  	return(1);
700.  }
701.  
702.  getdir()
703.  {
704.  char buf[2];
705.  	pline("What direction?");
706.  	buf[0] = readchar();
707.  	buf[1] = 0;
708.  	return(movecm(buf));
709.  }
710.  
711.  /* split obj so that it gets size num */
712.  /* remainder is put in the object structure delivered by this call */
713.  struct obj *
714.  splitobj(obj, num) register struct obj *obj; register int num; {
715.  register struct obj *otmp;
716.  	otmp = newobj(0);
717.  	*otmp = *obj;		/* copies whole structure */
718.  	otmp->o_id = flags.ident++;
719.  	otmp->onamelth = 0;
720.  	obj->quan = num;
721.  	obj->owt = weight(obj);
722.  	otmp->quan -= num;
723.  	otmp->owt = weight(otmp);	/* -= obj->owt ? */
724.  	obj->nobj = otmp;
725.  	if(obj->unpaid) splitbill(obj,otmp);
726.  	return(otmp);
727.  }
728.  
729.  char *
730.  lowc(str)
731.  register char *str;
732.  {
733.  	static char buf[2];
734.  
735.  	if(*str >= 'A' && *str <= 'Z') *buf = *str+'a'-'A';
736.  	else *buf = *str;
737.  	buf[1] = 0;
738.  	return(buf);
739.  }
740.  
741.  char *
742.  unctrl(str)
743.  register char *str;
744.  {
745.  	static char buf[2];
746.  	if(*str >= ('A' & 037) && *str <= ('Z' & 037))
747.  		*buf = *str + 0140;
748.  	else *buf = *str;
749.  	buf[1] = 0;
750.  	return(buf);
751.  }