xref: /netbsd-src/games/hack/hack.do.c (revision 8e73b3ad763e92a803658f492d224264534c3d17)
1*8e73b3adSdholland /*	$NetBSD: hack.do.c,v 1.11 2011/08/06 20:29:37 dholland Exp $	*/
23ea4a95cSchristos 
302ded532Smycroft /*
41c7f94e5Sjsm  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
51c7f94e5Sjsm  * Amsterdam
61c7f94e5Sjsm  * All rights reserved.
71c7f94e5Sjsm  *
81c7f94e5Sjsm  * Redistribution and use in source and binary forms, with or without
91c7f94e5Sjsm  * modification, are permitted provided that the following conditions are
101c7f94e5Sjsm  * met:
111c7f94e5Sjsm  *
121c7f94e5Sjsm  * - Redistributions of source code must retain the above copyright notice,
131c7f94e5Sjsm  * this list of conditions and the following disclaimer.
141c7f94e5Sjsm  *
151c7f94e5Sjsm  * - Redistributions in binary form must reproduce the above copyright
161c7f94e5Sjsm  * notice, this list of conditions and the following disclaimer in the
171c7f94e5Sjsm  * documentation and/or other materials provided with the distribution.
181c7f94e5Sjsm  *
191c7f94e5Sjsm  * - Neither the name of the Stichting Centrum voor Wiskunde en
201c7f94e5Sjsm  * Informatica, nor the names of its contributors may be used to endorse or
211c7f94e5Sjsm  * promote products derived from this software without specific prior
221c7f94e5Sjsm  * written permission.
231c7f94e5Sjsm  *
241c7f94e5Sjsm  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
251c7f94e5Sjsm  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
261c7f94e5Sjsm  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
271c7f94e5Sjsm  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
281c7f94e5Sjsm  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
291c7f94e5Sjsm  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
301c7f94e5Sjsm  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
311c7f94e5Sjsm  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
321c7f94e5Sjsm  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
331c7f94e5Sjsm  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
341c7f94e5Sjsm  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
351c7f94e5Sjsm  */
361c7f94e5Sjsm 
371c7f94e5Sjsm /*
381c7f94e5Sjsm  * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
391c7f94e5Sjsm  * All rights reserved.
401c7f94e5Sjsm  *
411c7f94e5Sjsm  * Redistribution and use in source and binary forms, with or without
421c7f94e5Sjsm  * modification, are permitted provided that the following conditions
431c7f94e5Sjsm  * are met:
441c7f94e5Sjsm  * 1. Redistributions of source code must retain the above copyright
451c7f94e5Sjsm  *    notice, this list of conditions and the following disclaimer.
461c7f94e5Sjsm  * 2. Redistributions in binary form must reproduce the above copyright
471c7f94e5Sjsm  *    notice, this list of conditions and the following disclaimer in the
481c7f94e5Sjsm  *    documentation and/or other materials provided with the distribution.
491c7f94e5Sjsm  * 3. The name of the author may not be used to endorse or promote products
501c7f94e5Sjsm  *    derived from this software without specific prior written permission.
511c7f94e5Sjsm  *
521c7f94e5Sjsm  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
531c7f94e5Sjsm  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
541c7f94e5Sjsm  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
551c7f94e5Sjsm  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
561c7f94e5Sjsm  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
571c7f94e5Sjsm  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
581c7f94e5Sjsm  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
591c7f94e5Sjsm  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
601c7f94e5Sjsm  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
611c7f94e5Sjsm  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6202ded532Smycroft  */
6302ded532Smycroft 
643ea4a95cSchristos #include <sys/cdefs.h>
6502ded532Smycroft #ifndef lint
66*8e73b3adSdholland __RCSID("$NetBSD: hack.do.c,v 1.11 2011/08/06 20:29:37 dholland Exp $");
6702ded532Smycroft #endif				/* not lint */
6861f28255Scgd 
6961f28255Scgd /* Contains code for 'd', 'D' (drop), '>', '<' (up, down) and 't' (throw) */
7061f28255Scgd 
713ea4a95cSchristos #include <fcntl.h>
723ea4a95cSchristos #include <unistd.h>
733ea4a95cSchristos #include <stdlib.h>
74fcfbc606Sdholland #include "hack.h"
75fcfbc606Sdholland #include "extern.h"
7661f28255Scgd 
7761f28255Scgd 
78cb5fd834Sjsm static int drop(struct obj *);
799b92b189Sdholland static void dropy(struct obj *);
8061f28255Scgd 
813ea4a95cSchristos int
dodrop(void)821fa8a9a6Sdholland dodrop(void)
833ea4a95cSchristos {
8461f28255Scgd 	return (drop(getobj("0$#", "drop")));
8561f28255Scgd }
8661f28255Scgd 
8761f28255Scgd static int
drop(struct obj * obj)881fa8a9a6Sdholland drop(struct obj *obj)
893ea4a95cSchristos {
903ea4a95cSchristos 	if (!obj)
913ea4a95cSchristos 		return (0);
9261f28255Scgd 	if (obj->olet == '$') {	/* pseudo object */
933ea4a95cSchristos 		long            amount = OGOLD(obj);
9461f28255Scgd 
9561f28255Scgd 		if (amount == 0)
9661f28255Scgd 			pline("You didn't drop any gold pieces.");
9761f28255Scgd 		else {
9861f28255Scgd 			mkgold(amount, u.ux, u.uy);
9961f28255Scgd 			pline("You dropped %ld gold piece%s.",
10061f28255Scgd 			      amount, plur(amount));
1013ea4a95cSchristos 			if (Invisible)
1023ea4a95cSchristos 				newsym(u.ux, u.uy);
10361f28255Scgd 		}
104*8e73b3adSdholland 		free(obj);
10561f28255Scgd 		return (1);
10661f28255Scgd 	}
10761f28255Scgd 	if (obj->owornmask & (W_ARMOR | W_RING)) {
10861f28255Scgd 		pline("You cannot drop something you are wearing.");
10961f28255Scgd 		return (0);
11061f28255Scgd 	}
11161f28255Scgd 	if (obj == uwep) {
11261f28255Scgd 		if (uwep->cursed) {
11361f28255Scgd 			pline("Your weapon is welded to your hand!");
11461f28255Scgd 			return (0);
11561f28255Scgd 		}
11661f28255Scgd 		setuwep((struct obj *) 0);
11761f28255Scgd 	}
11861f28255Scgd 	pline("You dropped %s.", doname(obj));
11961f28255Scgd 	dropx(obj);
12061f28255Scgd 	return (1);
12161f28255Scgd }
12261f28255Scgd 
12361f28255Scgd /* Called in several places - should not produce texts */
1243ea4a95cSchristos void
dropx(struct obj * obj)1251fa8a9a6Sdholland dropx(struct obj *obj)
12661f28255Scgd {
12761f28255Scgd 	freeinv(obj);
12861f28255Scgd 	dropy(obj);
12961f28255Scgd }
13061f28255Scgd 
1319b92b189Sdholland static void
dropy(struct obj * obj)1321fa8a9a6Sdholland dropy(struct obj *obj)
13361f28255Scgd {
13461f28255Scgd 	if (obj->otyp == CRYSKNIFE)
13561f28255Scgd 		obj->otyp = WORM_TOOTH;
13661f28255Scgd 	obj->ox = u.ux;
13761f28255Scgd 	obj->oy = u.uy;
13861f28255Scgd 	obj->nobj = fobj;
13961f28255Scgd 	fobj = obj;
1403ea4a95cSchristos 	if (Invisible)
1413ea4a95cSchristos 		newsym(u.ux, u.uy);
14261f28255Scgd 	subfrombill(obj);
14361f28255Scgd 	stackobj(obj);
14461f28255Scgd }
14561f28255Scgd 
14661f28255Scgd /* drop several things */
1473ea4a95cSchristos int
doddrop(void)1481fa8a9a6Sdholland doddrop(void)
1493ea4a95cSchristos {
15061f28255Scgd 	return (ggetobj("drop", drop, 0));
15161f28255Scgd }
15261f28255Scgd 
1533ea4a95cSchristos int
dodown(void)1541fa8a9a6Sdholland dodown(void)
15561f28255Scgd {
15661f28255Scgd 	if (u.ux != xdnstair || u.uy != ydnstair) {
15761f28255Scgd 		pline("You can't go down here.");
15861f28255Scgd 		return (0);
15961f28255Scgd 	}
16061f28255Scgd 	if (u.ustuck) {
16161f28255Scgd 		pline("You are being held, and cannot go down.");
16261f28255Scgd 		return (1);
16361f28255Scgd 	}
16461f28255Scgd 	if (Levitation) {
16561f28255Scgd 		pline("You're floating high above the stairs.");
16661f28255Scgd 		return (0);
16761f28255Scgd 	}
16861f28255Scgd 	goto_level(dlevel + 1, TRUE);
16961f28255Scgd 	return (1);
17061f28255Scgd }
17161f28255Scgd 
1723ea4a95cSchristos int
doup(void)1731fa8a9a6Sdholland doup(void)
17461f28255Scgd {
17561f28255Scgd 	if (u.ux != xupstair || u.uy != yupstair) {
17661f28255Scgd 		pline("You can't go up here.");
17761f28255Scgd 		return (0);
17861f28255Scgd 	}
17961f28255Scgd 	if (u.ustuck) {
18061f28255Scgd 		pline("You are being held, and cannot go up.");
18161f28255Scgd 		return (1);
18261f28255Scgd 	}
18361f28255Scgd 	if (!Levitation && inv_weight() + 5 > 0) {
18461f28255Scgd 		pline("Your load is too heavy to climb the stairs.");
18561f28255Scgd 		return (1);
18661f28255Scgd 	}
18761f28255Scgd 	goto_level(dlevel - 1, TRUE);
18861f28255Scgd 	return (1);
18961f28255Scgd }
19061f28255Scgd 
1913ea4a95cSchristos void
goto_level(int newlevel,boolean at_stairs)1921fa8a9a6Sdholland goto_level(int newlevel, boolean at_stairs)
19361f28255Scgd {
1943ea4a95cSchristos 	int fd;
1953ea4a95cSchristos 	boolean         up = (newlevel < dlevel);
19661f28255Scgd 
1973ea4a95cSchristos 	if (newlevel <= 0)
1983ea4a95cSchristos 		done("escaped");/* in fact < 0 is impossible */
1993ea4a95cSchristos 	if (newlevel > MAXLEVEL)
2003ea4a95cSchristos 		newlevel = MAXLEVEL;	/* strange ... */
2013ea4a95cSchristos 	if (newlevel == dlevel)
2023ea4a95cSchristos 		return;		/* this can happen */
20361f28255Scgd 
20461f28255Scgd 	glo(dlevel);
20561f28255Scgd 	fd = creat(lock, FMASK);
20661f28255Scgd 	if (fd < 0) {
20761f28255Scgd 		/*
20861f28255Scgd 		 * This is not quite impossible: e.g., we may have
20961f28255Scgd 		 * exceeded our quota. If that is the case then we
21061f28255Scgd 		 * cannot leave this level, and cannot save either.
21161f28255Scgd 		 * Another possibility is that the directory was not
21261f28255Scgd 		 * writable.
21361f28255Scgd 		 */
21461f28255Scgd 		pline("A mysterious force prevents you from going %s.",
21561f28255Scgd 		      up ? "up" : "down");
21661f28255Scgd 		return;
21761f28255Scgd 	}
2183ea4a95cSchristos 	if (Punished)
2193ea4a95cSchristos 		unplacebc();
22061f28255Scgd 	u.utrap = 0;		/* needed in level_tele */
22161f28255Scgd 	u.ustuck = 0;		/* idem */
22261f28255Scgd 	keepdogs();
22361f28255Scgd 	seeoff(1);
22461f28255Scgd 	if (u.uswallow)		/* idem */
22561f28255Scgd 		u.uswldtim = u.uswallow = 0;
22661f28255Scgd 	flags.nscrinh = 1;
22761f28255Scgd 	u.ux = FAR;		/* hack */
22861f28255Scgd 	(void) inshop();	/* probably was a trapdoor */
22961f28255Scgd 
23061f28255Scgd 	savelev(fd, dlevel);
23161f28255Scgd 	(void) close(fd);
23261f28255Scgd 
23361f28255Scgd 	dlevel = newlevel;
23461f28255Scgd 	if (maxdlevel < dlevel)
23561f28255Scgd 		maxdlevel = dlevel;
23661f28255Scgd 	glo(dlevel);
23761f28255Scgd 
23861f28255Scgd 	if (!level_exists[dlevel])
23961f28255Scgd 		mklev();
24061f28255Scgd 	else {
241ab8b6343Sjsm 		if ((fd = open(lock, O_RDONLY)) < 0) {
24261f28255Scgd 			pline("Cannot open %s .", lock);
24361f28255Scgd 			pline("Probably someone removed it.");
24461f28255Scgd 			done("tricked");
24561f28255Scgd 		}
24661f28255Scgd 		getlev(fd, hackpid, dlevel);
24761f28255Scgd 		(void) close(fd);
24861f28255Scgd 	}
24961f28255Scgd 
25061f28255Scgd 	if (at_stairs) {
25161f28255Scgd 		if (up) {
25261f28255Scgd 			u.ux = xdnstair;
25361f28255Scgd 			u.uy = ydnstair;
25461f28255Scgd 			if (!u.ux) {	/* entering a maze from below? */
2553ea4a95cSchristos 				u.ux = xupstair;	/* this will confuse the
2563ea4a95cSchristos 							 * player! */
25761f28255Scgd 				u.uy = yupstair;
25861f28255Scgd 			}
25961f28255Scgd 			if (Punished && !Levitation) {
26061f28255Scgd 				pline("With great effort you climb the stairs.");
26161f28255Scgd 				placebc(1);
26261f28255Scgd 			}
26361f28255Scgd 		} else {
26461f28255Scgd 			u.ux = xupstair;
26561f28255Scgd 			u.uy = yupstair;
26661f28255Scgd 			if (inv_weight() + 5 > 0 || Punished) {
26761f28255Scgd 				pline("You fall down the stairs.");	/* %% */
26861f28255Scgd 				losehp(rnd(3), "fall");
26961f28255Scgd 				if (Punished) {
27061f28255Scgd 					if (uwep != uball && rn2(3)) {
27161f28255Scgd 						pline("... and are hit by the iron ball.");
27261f28255Scgd 						losehp(rnd(20), "iron ball");
27361f28255Scgd 					}
27461f28255Scgd 					placebc(1);
27561f28255Scgd 				}
27661f28255Scgd 				selftouch("Falling, you");
27761f28255Scgd 			}
27861f28255Scgd 		}
2793ea4a95cSchristos 		{
2803ea4a95cSchristos 			struct monst   *mtmp = m_at(u.ux, u.uy);
28161f28255Scgd 			if (mtmp)
28261f28255Scgd 				mnexto(mtmp);
28361f28255Scgd 		}
28461f28255Scgd 	} else {		/* trapdoor or level_tele */
28561f28255Scgd 		do {
28661f28255Scgd 			u.ux = rnd(COLNO - 1);
28761f28255Scgd 			u.uy = rn2(ROWNO);
28861f28255Scgd 		} while (levl[u.ux][u.uy].typ != ROOM ||
28961f28255Scgd 			 m_at(u.ux, u.uy));
29061f28255Scgd 		if (Punished) {
29161f28255Scgd 			if (uwep != uball && !up /* %% */ && rn2(5)) {
29261f28255Scgd 				pline("The iron ball falls on your head.");
29361f28255Scgd 				losehp(rnd(25), "iron ball");
29461f28255Scgd 			}
29561f28255Scgd 			placebc(1);
29661f28255Scgd 		}
29761f28255Scgd 		selftouch("Falling, you");
29861f28255Scgd 	}
29961f28255Scgd 	(void) inshop();
30061f28255Scgd 	initrack();
30161f28255Scgd 
30261f28255Scgd 	losedogs();
3033ea4a95cSchristos 	{
3043ea4a95cSchristos 		struct monst   *mtmp;
3053ea4a95cSchristos 		if ((mtmp = m_at(u.ux, u.uy)) != NULL)
3063ea4a95cSchristos 			mnexto(mtmp);	/* riv05!a3 */
30761f28255Scgd 	}
30861f28255Scgd 	flags.nscrinh = 0;
30961f28255Scgd 	setsee();
31061f28255Scgd 	seeobjs();		/* make old cadavers disappear - riv05!a3 */
31161f28255Scgd 	docrt();
31261f28255Scgd 	pickup(1);
31361f28255Scgd 	read_engr_at(u.ux, u.uy);
31461f28255Scgd }
31561f28255Scgd 
3163ea4a95cSchristos int
donull(void)3171fa8a9a6Sdholland donull(void)
3183ea4a95cSchristos {
31961f28255Scgd 	return (1);		/* Do nothing, but let other things happen */
32061f28255Scgd }
32161f28255Scgd 
3223ea4a95cSchristos int
dopray(void)3231fa8a9a6Sdholland dopray(void)
3243ea4a95cSchristos {
32561f28255Scgd 	nomovemsg = "You finished your prayer.";
32661f28255Scgd 	nomul(-3);
32761f28255Scgd 	return (1);
32861f28255Scgd }
32961f28255Scgd 
3303ea4a95cSchristos int
dothrow(void)3311fa8a9a6Sdholland dothrow(void)
33261f28255Scgd {
3333ea4a95cSchristos 	struct obj     *obj;
3343ea4a95cSchristos 	struct monst   *mon;
3353ea4a95cSchristos 	int tmp;
33661f28255Scgd 
33761f28255Scgd 	obj = getobj("#)", "throw");	/* it is also possible to throw food */
33861f28255Scgd 	/* (or jewels, or iron balls ... ) */
33961f28255Scgd 	if (!obj || !getdir(1))	/* ask "in what direction?" */
34061f28255Scgd 		return (0);
34161f28255Scgd 	if (obj->owornmask & (W_ARMOR | W_RING)) {
34261f28255Scgd 		pline("You can't throw something you are wearing.");
34361f28255Scgd 		return (0);
34461f28255Scgd 	}
34561f28255Scgd 	u_wipe_engr(2);
34661f28255Scgd 
34761f28255Scgd 	if (obj == uwep) {
34861f28255Scgd 		if (obj->cursed) {
34961f28255Scgd 			pline("Your weapon is welded to your hand.");
35061f28255Scgd 			return (1);
35161f28255Scgd 		}
35261f28255Scgd 		if (obj->quan > 1)
35361f28255Scgd 			setuwep(splitobj(obj, 1));
35461f28255Scgd 		else
35561f28255Scgd 			setuwep((struct obj *) 0);
3563ea4a95cSchristos 	} else if (obj->quan > 1)
35761f28255Scgd 		(void) splitobj(obj, 1);
35861f28255Scgd 	freeinv(obj);
35961f28255Scgd 	if (u.uswallow) {
36061f28255Scgd 		mon = u.ustuck;
36161f28255Scgd 		bhitpos.x = mon->mx;
36261f28255Scgd 		bhitpos.y = mon->my;
36361f28255Scgd 	} else if (u.dz) {
36461f28255Scgd 		if (u.dz < 0) {
36561f28255Scgd 			pline("%s hits the ceiling, then falls back on top of your head.",
36661f28255Scgd 			      Doname(obj));	/* note: obj->quan == 1 */
36761f28255Scgd 			if (obj->olet == POTION_SYM)
36861f28255Scgd 				potionhit(&youmonst, obj);
36961f28255Scgd 			else {
3703ea4a95cSchristos 				if (uarmh)
3713ea4a95cSchristos 					pline("Fortunately, you are wearing a helmet!");
37261f28255Scgd 				losehp(uarmh ? 1 : rnd((int) (obj->owt)), "falling object");
37361f28255Scgd 				dropy(obj);
37461f28255Scgd 			}
37561f28255Scgd 		} else {
37661f28255Scgd 			pline("%s hits the floor.", Doname(obj));
37761f28255Scgd 			if (obj->otyp == EXPENSIVE_CAMERA) {
37861f28255Scgd 				pline("It is shattered in a thousand pieces!");
37961f28255Scgd 				obfree(obj, Null(obj));
38061f28255Scgd 			} else if (obj->otyp == EGG) {
38161f28255Scgd 				pline("\"Splash!\"");
38261f28255Scgd 				obfree(obj, Null(obj));
38361f28255Scgd 			} else if (obj->olet == POTION_SYM) {
38461f28255Scgd 				pline("The flask breaks, and you smell a peculiar odor ...");
38561f28255Scgd 				potionbreathe(obj);
38661f28255Scgd 				obfree(obj, Null(obj));
38761f28255Scgd 			} else {
38861f28255Scgd 				dropy(obj);
38961f28255Scgd 			}
39061f28255Scgd 		}
39161f28255Scgd 		return (1);
39261f28255Scgd 	} else if (obj->otyp == BOOMERANG) {
39361f28255Scgd 		mon = boomhit(u.dx, u.dy);
39461f28255Scgd 		if (mon == &youmonst) {	/* the thing was caught */
39561f28255Scgd 			(void) addinv(obj);
39661f28255Scgd 			return (1);
39761f28255Scgd 		}
39861f28255Scgd 	} else {
39961f28255Scgd 		if (obj->otyp == PICK_AXE && shkcatch(obj))
40061f28255Scgd 			return (1);
40161f28255Scgd 
40261f28255Scgd 		mon = bhit(u.dx, u.dy, (obj->otyp == ICE_BOX) ? 1 :
40361f28255Scgd 			(!Punished || obj != uball) ? 8 : !u.ustuck ? 5 : 1,
40461f28255Scgd 			   obj->olet,
405cb5fd834Sjsm 			   (void (*)(struct monst *, struct obj *)) 0,
406cb5fd834Sjsm 			   (int (*)(struct obj *, struct obj *)) 0, obj);
40761f28255Scgd 	}
40861f28255Scgd 	if (mon) {
40961f28255Scgd 		/* awake monster if sleeping */
41061f28255Scgd 		wakeup(mon);
41161f28255Scgd 
41261f28255Scgd 		if (obj->olet == WEAPON_SYM) {
41361f28255Scgd 			tmp = -1 + u.ulevel + mon->data->ac + abon();
41461f28255Scgd 			if (obj->otyp < ROCK) {
41561f28255Scgd 				if (!uwep ||
41661f28255Scgd 				    uwep->otyp != obj->otyp + (BOW - ARROW))
41761f28255Scgd 					tmp -= 4;
41861f28255Scgd 				else {
41961f28255Scgd 					tmp += uwep->spe;
42061f28255Scgd 				}
4213ea4a95cSchristos 			} else if (obj->otyp == BOOMERANG)
4223ea4a95cSchristos 				tmp += 4;
42361f28255Scgd 			tmp += obj->spe;
42461f28255Scgd 			if (u.uswallow || tmp >= rnd(20)) {
42561f28255Scgd 				if (hmon(mon, obj, 1) == TRUE) {
42661f28255Scgd 					/* mon still alive */
42761f28255Scgd #ifndef NOWORM
42861f28255Scgd 					cutworm(mon, bhitpos.x, bhitpos.y, obj->otyp);
4293ea4a95cSchristos #endif	/* NOWORM */
4303ea4a95cSchristos 				} else
4313ea4a95cSchristos 					mon = 0;
43261f28255Scgd 				/* weapons thrown disappear sometimes */
43361f28255Scgd 				if (obj->otyp < BOOMERANG && rn2(3)) {
43461f28255Scgd 					/* check bill; free */
43561f28255Scgd 					obfree(obj, (struct obj *) 0);
43661f28255Scgd 					return (1);
43761f28255Scgd 				}
4383ea4a95cSchristos 			} else
4393ea4a95cSchristos 				miss(objects[obj->otyp].oc_name, mon);
44061f28255Scgd 		} else if (obj->otyp == HEAVY_IRON_BALL) {
44161f28255Scgd 			tmp = -1 + u.ulevel + mon->data->ac + abon();
4423ea4a95cSchristos 			if (!Punished || obj != uball)
4433ea4a95cSchristos 				tmp += 2;
4443ea4a95cSchristos 			if (u.utrap)
4453ea4a95cSchristos 				tmp -= 2;
44661f28255Scgd 			if (u.uswallow || tmp >= rnd(20)) {
44761f28255Scgd 				if (hmon(mon, obj, 1) == FALSE)
44861f28255Scgd 					mon = 0;	/* he died */
4493ea4a95cSchristos 			} else
4503ea4a95cSchristos 				miss("iron ball", mon);
45161f28255Scgd 		} else if (obj->olet == POTION_SYM && u.ulevel > rn2(15)) {
45261f28255Scgd 			potionhit(mon, obj);
45361f28255Scgd 			return (1);
45461f28255Scgd 		} else {
45561f28255Scgd 			if (cansee(bhitpos.x, bhitpos.y))
45661f28255Scgd 				pline("You miss %s.", monnam(mon));
4573ea4a95cSchristos 			else
4583ea4a95cSchristos 				pline("You miss it.");
45961f28255Scgd 			if (obj->olet == FOOD_SYM && mon->data->mlet == 'd')
4603ea4a95cSchristos 				if (tamedog(mon, obj))
4613ea4a95cSchristos 					return (1);
46261f28255Scgd 			if (obj->olet == GEM_SYM && mon->data->mlet == 'u' &&
46361f28255Scgd 			    !mon->mtame) {
46461f28255Scgd 				if (obj->dknown && objects[obj->otyp].oc_name_known) {
46561f28255Scgd 					if (objects[obj->otyp].g_val > 0) {
46661f28255Scgd 						u.uluck += 5;
46761f28255Scgd 						goto valuable;
46861f28255Scgd 					} else {
46961f28255Scgd 						pline("%s is not interested in your junk.",
47061f28255Scgd 						      Monnam(mon));
47161f28255Scgd 					}
47261f28255Scgd 				} else {	/* value unknown to @ */
47361f28255Scgd 					u.uluck++;
47461f28255Scgd 			valuable:
47561f28255Scgd 					if (u.uluck > LUCKMAX)	/* dan@ut-ngp */
47661f28255Scgd 						u.uluck = LUCKMAX;
47761f28255Scgd 					pline("%s graciously accepts your gift.",
47861f28255Scgd 					      Monnam(mon));
47961f28255Scgd 					mpickobj(mon, obj);
48061f28255Scgd 					rloc(mon);
48161f28255Scgd 					return (1);
48261f28255Scgd 				}
48361f28255Scgd 			}
48461f28255Scgd 		}
48561f28255Scgd 	}
48661f28255Scgd 	/* the code following might become part of dropy() */
48761f28255Scgd 	if (obj->otyp == CRYSKNIFE)
48861f28255Scgd 		obj->otyp = WORM_TOOTH;
48961f28255Scgd 	obj->ox = bhitpos.x;
49061f28255Scgd 	obj->oy = bhitpos.y;
49161f28255Scgd 	obj->nobj = fobj;
49261f28255Scgd 	fobj = obj;
49361f28255Scgd 	/* prevent him from throwing articles to the exit and escaping */
49461f28255Scgd 	/* subfrombill(obj); */
49561f28255Scgd 	stackobj(obj);
49661f28255Scgd 	if (Punished && obj == uball &&
49761f28255Scgd 	    (bhitpos.x != u.ux || bhitpos.y != u.uy)) {
49861f28255Scgd 		freeobj(uchain);
49961f28255Scgd 		unpobj(uchain);
50061f28255Scgd 		if (u.utrap) {
50161f28255Scgd 			if (u.utraptype == TT_PIT)
50261f28255Scgd 				pline("The ball pulls you out of the pit!");
50361f28255Scgd 			else {
5043ea4a95cSchristos 				long            side =
50561f28255Scgd 				rn2(3) ? LEFT_SIDE : RIGHT_SIDE;
50661f28255Scgd 				pline("The ball pulls you out of the bear trap.");
50761f28255Scgd 				pline("Your %s leg is severely damaged.",
50861f28255Scgd 				    (side == LEFT_SIDE) ? "left" : "right");
50961f28255Scgd 				set_wounded_legs(side, 500 + rn2(1000));
51061f28255Scgd 				losehp(2, "thrown ball");
51161f28255Scgd 			}
51261f28255Scgd 			u.utrap = 0;
51361f28255Scgd 		}
51461f28255Scgd 		unsee();
51561f28255Scgd 		uchain->nobj = fobj;
51661f28255Scgd 		fobj = uchain;
51761f28255Scgd 		u.ux = uchain->ox = bhitpos.x - u.dx;
51861f28255Scgd 		u.uy = uchain->oy = bhitpos.y - u.dy;
51961f28255Scgd 		setsee();
52061f28255Scgd 		(void) inshop();
52161f28255Scgd 	}
5223ea4a95cSchristos 	if (cansee(bhitpos.x, bhitpos.y))
5233ea4a95cSchristos 		prl(bhitpos.x, bhitpos.y);
52461f28255Scgd 	return (1);
52561f28255Scgd }
52661f28255Scgd 
52761f28255Scgd /* split obj so that it gets size num */
52861f28255Scgd /* remainder is put in the object structure delivered by this call */
52961f28255Scgd struct obj     *
splitobj(struct obj * obj,int num)5301fa8a9a6Sdholland splitobj(struct obj *obj, int num)
5313ea4a95cSchristos {
5323ea4a95cSchristos 	struct obj     *otmp;
53361f28255Scgd 	otmp = newobj(0);
53461f28255Scgd 	*otmp = *obj;		/* copies whole structure */
53561f28255Scgd 	otmp->o_id = flags.ident++;
53661f28255Scgd 	otmp->onamelth = 0;
53761f28255Scgd 	obj->quan = num;
53861f28255Scgd 	obj->owt = weight(obj);
53961f28255Scgd 	otmp->quan -= num;
54061f28255Scgd 	otmp->owt = weight(otmp);	/* -= obj->owt ? */
54161f28255Scgd 	obj->nobj = otmp;
5423ea4a95cSchristos 	if (obj->unpaid)
5433ea4a95cSchristos 		splitbill(obj, otmp);
54461f28255Scgd 	return (otmp);
54561f28255Scgd }
54661f28255Scgd 
5473ea4a95cSchristos void
more_experienced(int exp,int rexp)5481fa8a9a6Sdholland more_experienced(int exp, int rexp)
54961f28255Scgd {
55061f28255Scgd 	u.uexp += exp;
55161f28255Scgd 	u.urexp += 4 * exp + rexp;
5523ea4a95cSchristos 	if (exp)
5533ea4a95cSchristos 		flags.botl = 1;
55461f28255Scgd 	if (u.urexp >= ((pl_character[0] == 'W') ? 1000 : 2000))
55561f28255Scgd 		flags.beginner = 0;
55661f28255Scgd }
55761f28255Scgd 
5583ea4a95cSchristos void
set_wounded_legs(long side,int timex)5591fa8a9a6Sdholland set_wounded_legs(long side, int timex)
56061f28255Scgd {
56161f28255Scgd 	if (!Wounded_legs || (Wounded_legs & TIMEOUT))
56261f28255Scgd 		Wounded_legs |= side + timex;
56361f28255Scgd 	else
56461f28255Scgd 		Wounded_legs |= side;
56561f28255Scgd }
56661f28255Scgd 
5673ea4a95cSchristos void
heal_legs(void)5681fa8a9a6Sdholland heal_legs(void)
56961f28255Scgd {
57061f28255Scgd 	if (Wounded_legs) {
57161f28255Scgd 		if ((Wounded_legs & BOTH_SIDES) == BOTH_SIDES)
57261f28255Scgd 			pline("Your legs feel somewhat better.");
57361f28255Scgd 		else
57461f28255Scgd 			pline("Your leg feels somewhat better.");
57561f28255Scgd 		Wounded_legs = 0;
57661f28255Scgd 	}
57761f28255Scgd }
578