Home | History | Annotate | Line # | Download | only in hack
hack.do.c revision 1.9
      1  1.9  dholland /*	$NetBSD: hack.do.c,v 1.9 2009/08/12 07:28:40 dholland Exp $	*/
      2  1.4  christos 
      3  1.2   mycroft /*
      4  1.6       jsm  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
      5  1.6       jsm  * Amsterdam
      6  1.6       jsm  * All rights reserved.
      7  1.6       jsm  *
      8  1.6       jsm  * Redistribution and use in source and binary forms, with or without
      9  1.6       jsm  * modification, are permitted provided that the following conditions are
     10  1.6       jsm  * met:
     11  1.6       jsm  *
     12  1.6       jsm  * - Redistributions of source code must retain the above copyright notice,
     13  1.6       jsm  * this list of conditions and the following disclaimer.
     14  1.6       jsm  *
     15  1.6       jsm  * - Redistributions in binary form must reproduce the above copyright
     16  1.6       jsm  * notice, this list of conditions and the following disclaimer in the
     17  1.6       jsm  * documentation and/or other materials provided with the distribution.
     18  1.6       jsm  *
     19  1.6       jsm  * - Neither the name of the Stichting Centrum voor Wiskunde en
     20  1.6       jsm  * Informatica, nor the names of its contributors may be used to endorse or
     21  1.6       jsm  * promote products derived from this software without specific prior
     22  1.6       jsm  * written permission.
     23  1.6       jsm  *
     24  1.6       jsm  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
     25  1.6       jsm  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     26  1.6       jsm  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
     27  1.6       jsm  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
     28  1.6       jsm  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     29  1.6       jsm  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     30  1.6       jsm  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     31  1.6       jsm  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     32  1.6       jsm  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     33  1.6       jsm  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     34  1.6       jsm  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     35  1.6       jsm  */
     36  1.6       jsm 
     37  1.6       jsm /*
     38  1.6       jsm  * Copyright (c) 1982 Jay Fenlason <hack (at) gnu.org>
     39  1.6       jsm  * All rights reserved.
     40  1.6       jsm  *
     41  1.6       jsm  * Redistribution and use in source and binary forms, with or without
     42  1.6       jsm  * modification, are permitted provided that the following conditions
     43  1.6       jsm  * are met:
     44  1.6       jsm  * 1. Redistributions of source code must retain the above copyright
     45  1.6       jsm  *    notice, this list of conditions and the following disclaimer.
     46  1.6       jsm  * 2. Redistributions in binary form must reproduce the above copyright
     47  1.6       jsm  *    notice, this list of conditions and the following disclaimer in the
     48  1.6       jsm  *    documentation and/or other materials provided with the distribution.
     49  1.6       jsm  * 3. The name of the author may not be used to endorse or promote products
     50  1.6       jsm  *    derived from this software without specific prior written permission.
     51  1.6       jsm  *
     52  1.6       jsm  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
     53  1.6       jsm  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
     54  1.6       jsm  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
     55  1.6       jsm  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     56  1.6       jsm  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     57  1.6       jsm  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     58  1.6       jsm  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     59  1.6       jsm  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     60  1.6       jsm  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     61  1.6       jsm  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     62  1.2   mycroft  */
     63  1.2   mycroft 
     64  1.4  christos #include <sys/cdefs.h>
     65  1.2   mycroft #ifndef lint
     66  1.9  dholland __RCSID("$NetBSD: hack.do.c,v 1.9 2009/08/12 07:28:40 dholland Exp $");
     67  1.4  christos #endif				/* not lint */
     68  1.1       cgd 
     69  1.1       cgd /* Contains code for 'd', 'D' (drop), '>', '<' (up, down) and 't' (throw) */
     70  1.1       cgd 
     71  1.1       cgd #include "hack.h"
     72  1.4  christos #include "extern.h"
     73  1.4  christos #include <fcntl.h>
     74  1.4  christos #include <unistd.h>
     75  1.4  christos #include <stdlib.h>
     76  1.1       cgd 
     77  1.1       cgd 
     78  1.7       jsm static int drop(struct obj *);
     79  1.9  dholland static void dropy(struct obj *);
     80  1.1       cgd 
     81  1.4  christos int
     82  1.8  dholland dodrop(void)
     83  1.4  christos {
     84  1.4  christos 	return (drop(getobj("0$#", "drop")));
     85  1.1       cgd }
     86  1.1       cgd 
     87  1.1       cgd static int
     88  1.8  dholland drop(struct obj *obj)
     89  1.4  christos {
     90  1.4  christos 	if (!obj)
     91  1.4  christos 		return (0);
     92  1.4  christos 	if (obj->olet == '$') {	/* pseudo object */
     93  1.4  christos 		long            amount = OGOLD(obj);
     94  1.1       cgd 
     95  1.4  christos 		if (amount == 0)
     96  1.1       cgd 			pline("You didn't drop any gold pieces.");
     97  1.1       cgd 		else {
     98  1.1       cgd 			mkgold(amount, u.ux, u.uy);
     99  1.1       cgd 			pline("You dropped %ld gold piece%s.",
    100  1.4  christos 			      amount, plur(amount));
    101  1.4  christos 			if (Invisible)
    102  1.4  christos 				newsym(u.ux, u.uy);
    103  1.1       cgd 		}
    104  1.1       cgd 		free((char *) obj);
    105  1.4  christos 		return (1);
    106  1.1       cgd 	}
    107  1.4  christos 	if (obj->owornmask & (W_ARMOR | W_RING)) {
    108  1.1       cgd 		pline("You cannot drop something you are wearing.");
    109  1.4  christos 		return (0);
    110  1.1       cgd 	}
    111  1.4  christos 	if (obj == uwep) {
    112  1.4  christos 		if (uwep->cursed) {
    113  1.1       cgd 			pline("Your weapon is welded to your hand!");
    114  1.4  christos 			return (0);
    115  1.1       cgd 		}
    116  1.1       cgd 		setuwep((struct obj *) 0);
    117  1.1       cgd 	}
    118  1.1       cgd 	pline("You dropped %s.", doname(obj));
    119  1.1       cgd 	dropx(obj);
    120  1.4  christos 	return (1);
    121  1.1       cgd }
    122  1.1       cgd 
    123  1.1       cgd /* Called in several places - should not produce texts */
    124  1.4  christos void
    125  1.8  dholland dropx(struct obj *obj)
    126  1.1       cgd {
    127  1.1       cgd 	freeinv(obj);
    128  1.1       cgd 	dropy(obj);
    129  1.1       cgd }
    130  1.1       cgd 
    131  1.9  dholland static void
    132  1.8  dholland dropy(struct obj *obj)
    133  1.1       cgd {
    134  1.4  christos 	if (obj->otyp == CRYSKNIFE)
    135  1.1       cgd 		obj->otyp = WORM_TOOTH;
    136  1.1       cgd 	obj->ox = u.ux;
    137  1.1       cgd 	obj->oy = u.uy;
    138  1.1       cgd 	obj->nobj = fobj;
    139  1.1       cgd 	fobj = obj;
    140  1.4  christos 	if (Invisible)
    141  1.4  christos 		newsym(u.ux, u.uy);
    142  1.1       cgd 	subfrombill(obj);
    143  1.1       cgd 	stackobj(obj);
    144  1.1       cgd }
    145  1.1       cgd 
    146  1.1       cgd /* drop several things */
    147  1.4  christos int
    148  1.8  dholland doddrop(void)
    149  1.4  christos {
    150  1.4  christos 	return (ggetobj("drop", drop, 0));
    151  1.1       cgd }
    152  1.1       cgd 
    153  1.4  christos int
    154  1.8  dholland dodown(void)
    155  1.1       cgd {
    156  1.4  christos 	if (u.ux != xdnstair || u.uy != ydnstair) {
    157  1.1       cgd 		pline("You can't go down here.");
    158  1.4  christos 		return (0);
    159  1.1       cgd 	}
    160  1.4  christos 	if (u.ustuck) {
    161  1.1       cgd 		pline("You are being held, and cannot go down.");
    162  1.4  christos 		return (1);
    163  1.1       cgd 	}
    164  1.4  christos 	if (Levitation) {
    165  1.1       cgd 		pline("You're floating high above the stairs.");
    166  1.4  christos 		return (0);
    167  1.1       cgd 	}
    168  1.4  christos 	goto_level(dlevel + 1, TRUE);
    169  1.4  christos 	return (1);
    170  1.1       cgd }
    171  1.1       cgd 
    172  1.4  christos int
    173  1.8  dholland doup(void)
    174  1.1       cgd {
    175  1.4  christos 	if (u.ux != xupstair || u.uy != yupstair) {
    176  1.1       cgd 		pline("You can't go up here.");
    177  1.4  christos 		return (0);
    178  1.1       cgd 	}
    179  1.4  christos 	if (u.ustuck) {
    180  1.1       cgd 		pline("You are being held, and cannot go up.");
    181  1.4  christos 		return (1);
    182  1.1       cgd 	}
    183  1.4  christos 	if (!Levitation && inv_weight() + 5 > 0) {
    184  1.1       cgd 		pline("Your load is too heavy to climb the stairs.");
    185  1.4  christos 		return (1);
    186  1.1       cgd 	}
    187  1.4  christos 	goto_level(dlevel - 1, TRUE);
    188  1.4  christos 	return (1);
    189  1.1       cgd }
    190  1.1       cgd 
    191  1.4  christos void
    192  1.8  dholland goto_level(int newlevel, boolean at_stairs)
    193  1.1       cgd {
    194  1.4  christos 	int fd;
    195  1.4  christos 	boolean         up = (newlevel < dlevel);
    196  1.1       cgd 
    197  1.4  christos 	if (newlevel <= 0)
    198  1.4  christos 		done("escaped");/* in fact < 0 is impossible */
    199  1.4  christos 	if (newlevel > MAXLEVEL)
    200  1.4  christos 		newlevel = MAXLEVEL;	/* strange ... */
    201  1.4  christos 	if (newlevel == dlevel)
    202  1.4  christos 		return;		/* this can happen */
    203  1.1       cgd 
    204  1.1       cgd 	glo(dlevel);
    205  1.1       cgd 	fd = creat(lock, FMASK);
    206  1.4  christos 	if (fd < 0) {
    207  1.1       cgd 		/*
    208  1.1       cgd 		 * This is not quite impossible: e.g., we may have
    209  1.1       cgd 		 * exceeded our quota. If that is the case then we
    210  1.1       cgd 		 * cannot leave this level, and cannot save either.
    211  1.1       cgd 		 * Another possibility is that the directory was not
    212  1.1       cgd 		 * writable.
    213  1.1       cgd 		 */
    214  1.1       cgd 		pline("A mysterious force prevents you from going %s.",
    215  1.4  christos 		      up ? "up" : "down");
    216  1.1       cgd 		return;
    217  1.1       cgd 	}
    218  1.4  christos 	if (Punished)
    219  1.4  christos 		unplacebc();
    220  1.4  christos 	u.utrap = 0;		/* needed in level_tele */
    221  1.4  christos 	u.ustuck = 0;		/* idem */
    222  1.1       cgd 	keepdogs();
    223  1.1       cgd 	seeoff(1);
    224  1.4  christos 	if (u.uswallow)		/* idem */
    225  1.1       cgd 		u.uswldtim = u.uswallow = 0;
    226  1.1       cgd 	flags.nscrinh = 1;
    227  1.4  christos 	u.ux = FAR;		/* hack */
    228  1.4  christos 	(void) inshop();	/* probably was a trapdoor */
    229  1.1       cgd 
    230  1.4  christos 	savelev(fd, dlevel);
    231  1.1       cgd 	(void) close(fd);
    232  1.1       cgd 
    233  1.1       cgd 	dlevel = newlevel;
    234  1.4  christos 	if (maxdlevel < dlevel)
    235  1.1       cgd 		maxdlevel = dlevel;
    236  1.1       cgd 	glo(dlevel);
    237  1.1       cgd 
    238  1.4  christos 	if (!level_exists[dlevel])
    239  1.1       cgd 		mklev();
    240  1.1       cgd 	else {
    241  1.5       jsm 		if ((fd = open(lock, O_RDONLY)) < 0) {
    242  1.1       cgd 			pline("Cannot open %s .", lock);
    243  1.1       cgd 			pline("Probably someone removed it.");
    244  1.1       cgd 			done("tricked");
    245  1.1       cgd 		}
    246  1.1       cgd 		getlev(fd, hackpid, dlevel);
    247  1.1       cgd 		(void) close(fd);
    248  1.1       cgd 	}
    249  1.1       cgd 
    250  1.4  christos 	if (at_stairs) {
    251  1.4  christos 		if (up) {
    252  1.4  christos 			u.ux = xdnstair;
    253  1.4  christos 			u.uy = ydnstair;
    254  1.4  christos 			if (!u.ux) {	/* entering a maze from below? */
    255  1.4  christos 				u.ux = xupstair;	/* this will confuse the
    256  1.4  christos 							 * player! */
    257  1.4  christos 				u.uy = yupstair;
    258  1.4  christos 			}
    259  1.4  christos 			if (Punished && !Levitation) {
    260  1.4  christos 				pline("With great effort you climb the stairs.");
    261  1.4  christos 				placebc(1);
    262  1.4  christos 			}
    263  1.4  christos 		} else {
    264  1.4  christos 			u.ux = xupstair;
    265  1.4  christos 			u.uy = yupstair;
    266  1.4  christos 			if (inv_weight() + 5 > 0 || Punished) {
    267  1.4  christos 				pline("You fall down the stairs.");	/* %% */
    268  1.4  christos 				losehp(rnd(3), "fall");
    269  1.4  christos 				if (Punished) {
    270  1.4  christos 					if (uwep != uball && rn2(3)) {
    271  1.4  christos 						pline("... and are hit by the iron ball.");
    272  1.4  christos 						losehp(rnd(20), "iron ball");
    273  1.4  christos 					}
    274  1.4  christos 					placebc(1);
    275  1.4  christos 				}
    276  1.4  christos 				selftouch("Falling, you");
    277  1.4  christos 			}
    278  1.1       cgd 		}
    279  1.4  christos 		{
    280  1.4  christos 			struct monst   *mtmp = m_at(u.ux, u.uy);
    281  1.4  christos 			if (mtmp)
    282  1.4  christos 				mnexto(mtmp);
    283  1.4  christos 		}
    284  1.4  christos 	} else {		/* trapdoor or level_tele */
    285  1.4  christos 		do {
    286  1.4  christos 			u.ux = rnd(COLNO - 1);
    287  1.4  christos 			u.uy = rn2(ROWNO);
    288  1.4  christos 		} while (levl[u.ux][u.uy].typ != ROOM ||
    289  1.4  christos 			 m_at(u.ux, u.uy));
    290  1.4  christos 		if (Punished) {
    291  1.4  christos 			if (uwep != uball && !up /* %% */ && rn2(5)) {
    292  1.4  christos 				pline("The iron ball falls on your head.");
    293  1.4  christos 				losehp(rnd(25), "iron ball");
    294  1.4  christos 			}
    295  1.1       cgd 			placebc(1);
    296  1.1       cgd 		}
    297  1.4  christos 		selftouch("Falling, you");
    298  1.1       cgd 	}
    299  1.1       cgd 	(void) inshop();
    300  1.1       cgd 	initrack();
    301  1.1       cgd 
    302  1.1       cgd 	losedogs();
    303  1.4  christos 	{
    304  1.4  christos 		struct monst   *mtmp;
    305  1.4  christos 		if ((mtmp = m_at(u.ux, u.uy)) != NULL)
    306  1.4  christos 			mnexto(mtmp);	/* riv05!a3 */
    307  1.1       cgd 	}
    308  1.1       cgd 	flags.nscrinh = 0;
    309  1.1       cgd 	setsee();
    310  1.4  christos 	seeobjs();		/* make old cadavers disappear - riv05!a3 */
    311  1.1       cgd 	docrt();
    312  1.1       cgd 	pickup(1);
    313  1.4  christos 	read_engr_at(u.ux, u.uy);
    314  1.1       cgd }
    315  1.1       cgd 
    316  1.4  christos int
    317  1.8  dholland donull(void)
    318  1.4  christos {
    319  1.4  christos 	return (1);		/* Do nothing, but let other things happen */
    320  1.1       cgd }
    321  1.1       cgd 
    322  1.4  christos int
    323  1.8  dholland dopray(void)
    324  1.4  christos {
    325  1.1       cgd 	nomovemsg = "You finished your prayer.";
    326  1.1       cgd 	nomul(-3);
    327  1.4  christos 	return (1);
    328  1.1       cgd }
    329  1.1       cgd 
    330  1.4  christos int
    331  1.8  dholland dothrow(void)
    332  1.1       cgd {
    333  1.4  christos 	struct obj     *obj;
    334  1.4  christos 	struct monst   *mon;
    335  1.4  christos 	int tmp;
    336  1.4  christos 
    337  1.4  christos 	obj = getobj("#)", "throw");	/* it is also possible to throw food */
    338  1.4  christos 	/* (or jewels, or iron balls ... ) */
    339  1.4  christos 	if (!obj || !getdir(1))	/* ask "in what direction?" */
    340  1.4  christos 		return (0);
    341  1.4  christos 	if (obj->owornmask & (W_ARMOR | W_RING)) {
    342  1.1       cgd 		pline("You can't throw something you are wearing.");
    343  1.4  christos 		return (0);
    344  1.1       cgd 	}
    345  1.1       cgd 	u_wipe_engr(2);
    346  1.1       cgd 
    347  1.4  christos 	if (obj == uwep) {
    348  1.4  christos 		if (obj->cursed) {
    349  1.1       cgd 			pline("Your weapon is welded to your hand.");
    350  1.4  christos 			return (1);
    351  1.1       cgd 		}
    352  1.4  christos 		if (obj->quan > 1)
    353  1.1       cgd 			setuwep(splitobj(obj, 1));
    354  1.1       cgd 		else
    355  1.1       cgd 			setuwep((struct obj *) 0);
    356  1.4  christos 	} else if (obj->quan > 1)
    357  1.1       cgd 		(void) splitobj(obj, 1);
    358  1.1       cgd 	freeinv(obj);
    359  1.4  christos 	if (u.uswallow) {
    360  1.1       cgd 		mon = u.ustuck;
    361  1.1       cgd 		bhitpos.x = mon->mx;
    362  1.1       cgd 		bhitpos.y = mon->my;
    363  1.4  christos 	} else if (u.dz) {
    364  1.4  christos 		if (u.dz < 0) {
    365  1.4  christos 			pline("%s hits the ceiling, then falls back on top of your head.",
    366  1.4  christos 			      Doname(obj));	/* note: obj->quan == 1 */
    367  1.4  christos 			if (obj->olet == POTION_SYM)
    368  1.4  christos 				potionhit(&youmonst, obj);
    369  1.4  christos 			else {
    370  1.4  christos 				if (uarmh)
    371  1.4  christos 					pline("Fortunately, you are wearing a helmet!");
    372  1.4  christos 				losehp(uarmh ? 1 : rnd((int) (obj->owt)), "falling object");
    373  1.4  christos 				dropy(obj);
    374  1.4  christos 			}
    375  1.4  christos 		} else {
    376  1.4  christos 			pline("%s hits the floor.", Doname(obj));
    377  1.4  christos 			if (obj->otyp == EXPENSIVE_CAMERA) {
    378  1.4  christos 				pline("It is shattered in a thousand pieces!");
    379  1.4  christos 				obfree(obj, Null(obj));
    380  1.4  christos 			} else if (obj->otyp == EGG) {
    381  1.4  christos 				pline("\"Splash!\"");
    382  1.4  christos 				obfree(obj, Null(obj));
    383  1.4  christos 			} else if (obj->olet == POTION_SYM) {
    384  1.4  christos 				pline("The flask breaks, and you smell a peculiar odor ...");
    385  1.4  christos 				potionbreathe(obj);
    386  1.4  christos 				obfree(obj, Null(obj));
    387  1.4  christos 			} else {
    388  1.4  christos 				dropy(obj);
    389  1.4  christos 			}
    390  1.4  christos 		}
    391  1.4  christos 		return (1);
    392  1.4  christos 	} else if (obj->otyp == BOOMERANG) {
    393  1.1       cgd 		mon = boomhit(u.dx, u.dy);
    394  1.4  christos 		if (mon == &youmonst) {	/* the thing was caught */
    395  1.1       cgd 			(void) addinv(obj);
    396  1.4  christos 			return (1);
    397  1.1       cgd 		}
    398  1.1       cgd 	} else {
    399  1.4  christos 		if (obj->otyp == PICK_AXE && shkcatch(obj))
    400  1.4  christos 			return (1);
    401  1.1       cgd 
    402  1.1       cgd 		mon = bhit(u.dx, u.dy, (obj->otyp == ICE_BOX) ? 1 :
    403  1.1       cgd 			(!Punished || obj != uball) ? 8 : !u.ustuck ? 5 : 1,
    404  1.4  christos 			   obj->olet,
    405  1.7       jsm 			   (void (*)(struct monst *, struct obj *)) 0,
    406  1.7       jsm 			   (int (*)(struct obj *, struct obj *)) 0, obj);
    407  1.1       cgd 	}
    408  1.4  christos 	if (mon) {
    409  1.1       cgd 		/* awake monster if sleeping */
    410  1.1       cgd 		wakeup(mon);
    411  1.1       cgd 
    412  1.4  christos 		if (obj->olet == WEAPON_SYM) {
    413  1.4  christos 			tmp = -1 + u.ulevel + mon->data->ac + abon();
    414  1.4  christos 			if (obj->otyp < ROCK) {
    415  1.4  christos 				if (!uwep ||
    416  1.4  christos 				    uwep->otyp != obj->otyp + (BOW - ARROW))
    417  1.1       cgd 					tmp -= 4;
    418  1.1       cgd 				else {
    419  1.1       cgd 					tmp += uwep->spe;
    420  1.1       cgd 				}
    421  1.4  christos 			} else if (obj->otyp == BOOMERANG)
    422  1.4  christos 				tmp += 4;
    423  1.1       cgd 			tmp += obj->spe;
    424  1.4  christos 			if (u.uswallow || tmp >= rnd(20)) {
    425  1.4  christos 				if (hmon(mon, obj, 1) == TRUE) {
    426  1.4  christos 					/* mon still alive */
    427  1.1       cgd #ifndef NOWORM
    428  1.4  christos 					cutworm(mon, bhitpos.x, bhitpos.y, obj->otyp);
    429  1.4  christos #endif	/* NOWORM */
    430  1.4  christos 				} else
    431  1.4  christos 					mon = 0;
    432  1.1       cgd 				/* weapons thrown disappear sometimes */
    433  1.4  christos 				if (obj->otyp < BOOMERANG && rn2(3)) {
    434  1.1       cgd 					/* check bill; free */
    435  1.1       cgd 					obfree(obj, (struct obj *) 0);
    436  1.4  christos 					return (1);
    437  1.1       cgd 				}
    438  1.4  christos 			} else
    439  1.4  christos 				miss(objects[obj->otyp].oc_name, mon);
    440  1.4  christos 		} else if (obj->otyp == HEAVY_IRON_BALL) {
    441  1.4  christos 			tmp = -1 + u.ulevel + mon->data->ac + abon();
    442  1.4  christos 			if (!Punished || obj != uball)
    443  1.4  christos 				tmp += 2;
    444  1.4  christos 			if (u.utrap)
    445  1.4  christos 				tmp -= 2;
    446  1.4  christos 			if (u.uswallow || tmp >= rnd(20)) {
    447  1.4  christos 				if (hmon(mon, obj, 1) == FALSE)
    448  1.1       cgd 					mon = 0;	/* he died */
    449  1.4  christos 			} else
    450  1.4  christos 				miss("iron ball", mon);
    451  1.4  christos 		} else if (obj->olet == POTION_SYM && u.ulevel > rn2(15)) {
    452  1.1       cgd 			potionhit(mon, obj);
    453  1.4  christos 			return (1);
    454  1.1       cgd 		} else {
    455  1.4  christos 			if (cansee(bhitpos.x, bhitpos.y))
    456  1.4  christos 				pline("You miss %s.", monnam(mon));
    457  1.4  christos 			else
    458  1.4  christos 				pline("You miss it.");
    459  1.4  christos 			if (obj->olet == FOOD_SYM && mon->data->mlet == 'd')
    460  1.4  christos 				if (tamedog(mon, obj))
    461  1.4  christos 					return (1);
    462  1.4  christos 			if (obj->olet == GEM_SYM && mon->data->mlet == 'u' &&
    463  1.4  christos 			    !mon->mtame) {
    464  1.4  christos 				if (obj->dknown && objects[obj->otyp].oc_name_known) {
    465  1.4  christos 					if (objects[obj->otyp].g_val > 0) {
    466  1.4  christos 						u.uluck += 5;
    467  1.4  christos 						goto valuable;
    468  1.4  christos 					} else {
    469  1.4  christos 						pline("%s is not interested in your junk.",
    470  1.4  christos 						      Monnam(mon));
    471  1.4  christos 					}
    472  1.4  christos 				} else {	/* value unknown to @ */
    473  1.4  christos 					u.uluck++;
    474  1.1       cgd 			valuable:
    475  1.4  christos 					if (u.uluck > LUCKMAX)	/* dan@ut-ngp */
    476  1.4  christos 						u.uluck = LUCKMAX;
    477  1.4  christos 					pline("%s graciously accepts your gift.",
    478  1.4  christos 					      Monnam(mon));
    479  1.4  christos 					mpickobj(mon, obj);
    480  1.4  christos 					rloc(mon);
    481  1.4  christos 					return (1);
    482  1.4  christos 				}
    483  1.1       cgd 			}
    484  1.1       cgd 		}
    485  1.1       cgd 	}
    486  1.4  christos 	/* the code following might become part of dropy() */
    487  1.4  christos 	if (obj->otyp == CRYSKNIFE)
    488  1.1       cgd 		obj->otyp = WORM_TOOTH;
    489  1.1       cgd 	obj->ox = bhitpos.x;
    490  1.1       cgd 	obj->oy = bhitpos.y;
    491  1.1       cgd 	obj->nobj = fobj;
    492  1.1       cgd 	fobj = obj;
    493  1.1       cgd 	/* prevent him from throwing articles to the exit and escaping */
    494  1.1       cgd 	/* subfrombill(obj); */
    495  1.1       cgd 	stackobj(obj);
    496  1.4  christos 	if (Punished && obj == uball &&
    497  1.4  christos 	    (bhitpos.x != u.ux || bhitpos.y != u.uy)) {
    498  1.1       cgd 		freeobj(uchain);
    499  1.1       cgd 		unpobj(uchain);
    500  1.4  christos 		if (u.utrap) {
    501  1.4  christos 			if (u.utraptype == TT_PIT)
    502  1.1       cgd 				pline("The ball pulls you out of the pit!");
    503  1.1       cgd 			else {
    504  1.4  christos 				long            side =
    505  1.1       cgd 				rn2(3) ? LEFT_SIDE : RIGHT_SIDE;
    506  1.4  christos 				pline("The ball pulls you out of the bear trap.");
    507  1.4  christos 				pline("Your %s leg is severely damaged.",
    508  1.4  christos 				    (side == LEFT_SIDE) ? "left" : "right");
    509  1.4  christos 				set_wounded_legs(side, 500 + rn2(1000));
    510  1.4  christos 				losehp(2, "thrown ball");
    511  1.1       cgd 			}
    512  1.1       cgd 			u.utrap = 0;
    513  1.1       cgd 		}
    514  1.1       cgd 		unsee();
    515  1.1       cgd 		uchain->nobj = fobj;
    516  1.1       cgd 		fobj = uchain;
    517  1.1       cgd 		u.ux = uchain->ox = bhitpos.x - u.dx;
    518  1.1       cgd 		u.uy = uchain->oy = bhitpos.y - u.dy;
    519  1.1       cgd 		setsee();
    520  1.1       cgd 		(void) inshop();
    521  1.1       cgd 	}
    522  1.4  christos 	if (cansee(bhitpos.x, bhitpos.y))
    523  1.4  christos 		prl(bhitpos.x, bhitpos.y);
    524  1.4  christos 	return (1);
    525  1.1       cgd }
    526  1.1       cgd 
    527  1.1       cgd /* split obj so that it gets size num */
    528  1.1       cgd /* remainder is put in the object structure delivered by this call */
    529  1.4  christos struct obj     *
    530  1.8  dholland splitobj(struct obj *obj, int num)
    531  1.4  christos {
    532  1.4  christos 	struct obj     *otmp;
    533  1.1       cgd 	otmp = newobj(0);
    534  1.1       cgd 	*otmp = *obj;		/* copies whole structure */
    535  1.1       cgd 	otmp->o_id = flags.ident++;
    536  1.1       cgd 	otmp->onamelth = 0;
    537  1.1       cgd 	obj->quan = num;
    538  1.1       cgd 	obj->owt = weight(obj);
    539  1.1       cgd 	otmp->quan -= num;
    540  1.1       cgd 	otmp->owt = weight(otmp);	/* -= obj->owt ? */
    541  1.1       cgd 	obj->nobj = otmp;
    542  1.4  christos 	if (obj->unpaid)
    543  1.4  christos 		splitbill(obj, otmp);
    544  1.4  christos 	return (otmp);
    545  1.1       cgd }
    546  1.1       cgd 
    547  1.4  christos void
    548  1.8  dholland more_experienced(int exp, int rexp)
    549  1.1       cgd {
    550  1.1       cgd 	u.uexp += exp;
    551  1.4  christos 	u.urexp += 4 * exp + rexp;
    552  1.4  christos 	if (exp)
    553  1.4  christos 		flags.botl = 1;
    554  1.4  christos 	if (u.urexp >= ((pl_character[0] == 'W') ? 1000 : 2000))
    555  1.1       cgd 		flags.beginner = 0;
    556  1.1       cgd }
    557  1.1       cgd 
    558  1.4  christos void
    559  1.8  dholland set_wounded_legs(long side, int timex)
    560  1.1       cgd {
    561  1.4  christos 	if (!Wounded_legs || (Wounded_legs & TIMEOUT))
    562  1.1       cgd 		Wounded_legs |= side + timex;
    563  1.1       cgd 	else
    564  1.1       cgd 		Wounded_legs |= side;
    565  1.1       cgd }
    566  1.1       cgd 
    567  1.4  christos void
    568  1.8  dholland heal_legs(void)
    569  1.1       cgd {
    570  1.4  christos 	if (Wounded_legs) {
    571  1.4  christos 		if ((Wounded_legs & BOTH_SIDES) == BOTH_SIDES)
    572  1.1       cgd 			pline("Your legs feel somewhat better.");
    573  1.1       cgd 		else
    574  1.1       cgd 			pline("Your leg feels somewhat better.");
    575  1.1       cgd 		Wounded_legs = 0;
    576  1.1       cgd 	}
    577  1.1       cgd }
    578