Home | History | Annotate | Line # | Download | only in hack
      1  1.11  dholland /*	$NetBSD: hack.do.c,v 1.11 2011/08/06 20:29:37 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.11  dholland __RCSID("$NetBSD: hack.do.c,v 1.11 2011/08/06 20:29:37 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.4  christos #include <fcntl.h>
     72   1.4  christos #include <unistd.h>
     73   1.4  christos #include <stdlib.h>
     74  1.10  dholland #include "hack.h"
     75  1.10  dholland #include "extern.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.11  dholland 		free(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