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