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