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