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