1*8e73b3adSdholland /* $NetBSD: hack.do.c,v 1.11 2011/08/06 20:29:37 dholland Exp $ */
23ea4a95cSchristos
302ded532Smycroft /*
41c7f94e5Sjsm * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
51c7f94e5Sjsm * Amsterdam
61c7f94e5Sjsm * All rights reserved.
71c7f94e5Sjsm *
81c7f94e5Sjsm * Redistribution and use in source and binary forms, with or without
91c7f94e5Sjsm * modification, are permitted provided that the following conditions are
101c7f94e5Sjsm * met:
111c7f94e5Sjsm *
121c7f94e5Sjsm * - Redistributions of source code must retain the above copyright notice,
131c7f94e5Sjsm * this list of conditions and the following disclaimer.
141c7f94e5Sjsm *
151c7f94e5Sjsm * - Redistributions in binary form must reproduce the above copyright
161c7f94e5Sjsm * notice, this list of conditions and the following disclaimer in the
171c7f94e5Sjsm * documentation and/or other materials provided with the distribution.
181c7f94e5Sjsm *
191c7f94e5Sjsm * - Neither the name of the Stichting Centrum voor Wiskunde en
201c7f94e5Sjsm * Informatica, nor the names of its contributors may be used to endorse or
211c7f94e5Sjsm * promote products derived from this software without specific prior
221c7f94e5Sjsm * written permission.
231c7f94e5Sjsm *
241c7f94e5Sjsm * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
251c7f94e5Sjsm * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
261c7f94e5Sjsm * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
271c7f94e5Sjsm * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
281c7f94e5Sjsm * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
291c7f94e5Sjsm * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
301c7f94e5Sjsm * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
311c7f94e5Sjsm * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
321c7f94e5Sjsm * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
331c7f94e5Sjsm * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
341c7f94e5Sjsm * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
351c7f94e5Sjsm */
361c7f94e5Sjsm
371c7f94e5Sjsm /*
381c7f94e5Sjsm * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
391c7f94e5Sjsm * All rights reserved.
401c7f94e5Sjsm *
411c7f94e5Sjsm * Redistribution and use in source and binary forms, with or without
421c7f94e5Sjsm * modification, are permitted provided that the following conditions
431c7f94e5Sjsm * are met:
441c7f94e5Sjsm * 1. Redistributions of source code must retain the above copyright
451c7f94e5Sjsm * notice, this list of conditions and the following disclaimer.
461c7f94e5Sjsm * 2. Redistributions in binary form must reproduce the above copyright
471c7f94e5Sjsm * notice, this list of conditions and the following disclaimer in the
481c7f94e5Sjsm * documentation and/or other materials provided with the distribution.
491c7f94e5Sjsm * 3. The name of the author may not be used to endorse or promote products
501c7f94e5Sjsm * derived from this software without specific prior written permission.
511c7f94e5Sjsm *
521c7f94e5Sjsm * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
531c7f94e5Sjsm * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
541c7f94e5Sjsm * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
551c7f94e5Sjsm * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
561c7f94e5Sjsm * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
571c7f94e5Sjsm * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
581c7f94e5Sjsm * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
591c7f94e5Sjsm * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
601c7f94e5Sjsm * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
611c7f94e5Sjsm * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6202ded532Smycroft */
6302ded532Smycroft
643ea4a95cSchristos #include <sys/cdefs.h>
6502ded532Smycroft #ifndef lint
66*8e73b3adSdholland __RCSID("$NetBSD: hack.do.c,v 1.11 2011/08/06 20:29:37 dholland Exp $");
6702ded532Smycroft #endif /* not lint */
6861f28255Scgd
6961f28255Scgd /* Contains code for 'd', 'D' (drop), '>', '<' (up, down) and 't' (throw) */
7061f28255Scgd
713ea4a95cSchristos #include <fcntl.h>
723ea4a95cSchristos #include <unistd.h>
733ea4a95cSchristos #include <stdlib.h>
74fcfbc606Sdholland #include "hack.h"
75fcfbc606Sdholland #include "extern.h"
7661f28255Scgd
7761f28255Scgd
78cb5fd834Sjsm static int drop(struct obj *);
799b92b189Sdholland static void dropy(struct obj *);
8061f28255Scgd
813ea4a95cSchristos int
dodrop(void)821fa8a9a6Sdholland dodrop(void)
833ea4a95cSchristos {
8461f28255Scgd return (drop(getobj("0$#", "drop")));
8561f28255Scgd }
8661f28255Scgd
8761f28255Scgd static int
drop(struct obj * obj)881fa8a9a6Sdholland drop(struct obj *obj)
893ea4a95cSchristos {
903ea4a95cSchristos if (!obj)
913ea4a95cSchristos return (0);
9261f28255Scgd if (obj->olet == '$') { /* pseudo object */
933ea4a95cSchristos long amount = OGOLD(obj);
9461f28255Scgd
9561f28255Scgd if (amount == 0)
9661f28255Scgd pline("You didn't drop any gold pieces.");
9761f28255Scgd else {
9861f28255Scgd mkgold(amount, u.ux, u.uy);
9961f28255Scgd pline("You dropped %ld gold piece%s.",
10061f28255Scgd amount, plur(amount));
1013ea4a95cSchristos if (Invisible)
1023ea4a95cSchristos newsym(u.ux, u.uy);
10361f28255Scgd }
104*8e73b3adSdholland free(obj);
10561f28255Scgd return (1);
10661f28255Scgd }
10761f28255Scgd if (obj->owornmask & (W_ARMOR | W_RING)) {
10861f28255Scgd pline("You cannot drop something you are wearing.");
10961f28255Scgd return (0);
11061f28255Scgd }
11161f28255Scgd if (obj == uwep) {
11261f28255Scgd if (uwep->cursed) {
11361f28255Scgd pline("Your weapon is welded to your hand!");
11461f28255Scgd return (0);
11561f28255Scgd }
11661f28255Scgd setuwep((struct obj *) 0);
11761f28255Scgd }
11861f28255Scgd pline("You dropped %s.", doname(obj));
11961f28255Scgd dropx(obj);
12061f28255Scgd return (1);
12161f28255Scgd }
12261f28255Scgd
12361f28255Scgd /* Called in several places - should not produce texts */
1243ea4a95cSchristos void
dropx(struct obj * obj)1251fa8a9a6Sdholland dropx(struct obj *obj)
12661f28255Scgd {
12761f28255Scgd freeinv(obj);
12861f28255Scgd dropy(obj);
12961f28255Scgd }
13061f28255Scgd
1319b92b189Sdholland static void
dropy(struct obj * obj)1321fa8a9a6Sdholland dropy(struct obj *obj)
13361f28255Scgd {
13461f28255Scgd if (obj->otyp == CRYSKNIFE)
13561f28255Scgd obj->otyp = WORM_TOOTH;
13661f28255Scgd obj->ox = u.ux;
13761f28255Scgd obj->oy = u.uy;
13861f28255Scgd obj->nobj = fobj;
13961f28255Scgd fobj = obj;
1403ea4a95cSchristos if (Invisible)
1413ea4a95cSchristos newsym(u.ux, u.uy);
14261f28255Scgd subfrombill(obj);
14361f28255Scgd stackobj(obj);
14461f28255Scgd }
14561f28255Scgd
14661f28255Scgd /* drop several things */
1473ea4a95cSchristos int
doddrop(void)1481fa8a9a6Sdholland doddrop(void)
1493ea4a95cSchristos {
15061f28255Scgd return (ggetobj("drop", drop, 0));
15161f28255Scgd }
15261f28255Scgd
1533ea4a95cSchristos int
dodown(void)1541fa8a9a6Sdholland dodown(void)
15561f28255Scgd {
15661f28255Scgd if (u.ux != xdnstair || u.uy != ydnstair) {
15761f28255Scgd pline("You can't go down here.");
15861f28255Scgd return (0);
15961f28255Scgd }
16061f28255Scgd if (u.ustuck) {
16161f28255Scgd pline("You are being held, and cannot go down.");
16261f28255Scgd return (1);
16361f28255Scgd }
16461f28255Scgd if (Levitation) {
16561f28255Scgd pline("You're floating high above the stairs.");
16661f28255Scgd return (0);
16761f28255Scgd }
16861f28255Scgd goto_level(dlevel + 1, TRUE);
16961f28255Scgd return (1);
17061f28255Scgd }
17161f28255Scgd
1723ea4a95cSchristos int
doup(void)1731fa8a9a6Sdholland doup(void)
17461f28255Scgd {
17561f28255Scgd if (u.ux != xupstair || u.uy != yupstair) {
17661f28255Scgd pline("You can't go up here.");
17761f28255Scgd return (0);
17861f28255Scgd }
17961f28255Scgd if (u.ustuck) {
18061f28255Scgd pline("You are being held, and cannot go up.");
18161f28255Scgd return (1);
18261f28255Scgd }
18361f28255Scgd if (!Levitation && inv_weight() + 5 > 0) {
18461f28255Scgd pline("Your load is too heavy to climb the stairs.");
18561f28255Scgd return (1);
18661f28255Scgd }
18761f28255Scgd goto_level(dlevel - 1, TRUE);
18861f28255Scgd return (1);
18961f28255Scgd }
19061f28255Scgd
1913ea4a95cSchristos void
goto_level(int newlevel,boolean at_stairs)1921fa8a9a6Sdholland goto_level(int newlevel, boolean at_stairs)
19361f28255Scgd {
1943ea4a95cSchristos int fd;
1953ea4a95cSchristos boolean up = (newlevel < dlevel);
19661f28255Scgd
1973ea4a95cSchristos if (newlevel <= 0)
1983ea4a95cSchristos done("escaped");/* in fact < 0 is impossible */
1993ea4a95cSchristos if (newlevel > MAXLEVEL)
2003ea4a95cSchristos newlevel = MAXLEVEL; /* strange ... */
2013ea4a95cSchristos if (newlevel == dlevel)
2023ea4a95cSchristos return; /* this can happen */
20361f28255Scgd
20461f28255Scgd glo(dlevel);
20561f28255Scgd fd = creat(lock, FMASK);
20661f28255Scgd if (fd < 0) {
20761f28255Scgd /*
20861f28255Scgd * This is not quite impossible: e.g., we may have
20961f28255Scgd * exceeded our quota. If that is the case then we
21061f28255Scgd * cannot leave this level, and cannot save either.
21161f28255Scgd * Another possibility is that the directory was not
21261f28255Scgd * writable.
21361f28255Scgd */
21461f28255Scgd pline("A mysterious force prevents you from going %s.",
21561f28255Scgd up ? "up" : "down");
21661f28255Scgd return;
21761f28255Scgd }
2183ea4a95cSchristos if (Punished)
2193ea4a95cSchristos unplacebc();
22061f28255Scgd u.utrap = 0; /* needed in level_tele */
22161f28255Scgd u.ustuck = 0; /* idem */
22261f28255Scgd keepdogs();
22361f28255Scgd seeoff(1);
22461f28255Scgd if (u.uswallow) /* idem */
22561f28255Scgd u.uswldtim = u.uswallow = 0;
22661f28255Scgd flags.nscrinh = 1;
22761f28255Scgd u.ux = FAR; /* hack */
22861f28255Scgd (void) inshop(); /* probably was a trapdoor */
22961f28255Scgd
23061f28255Scgd savelev(fd, dlevel);
23161f28255Scgd (void) close(fd);
23261f28255Scgd
23361f28255Scgd dlevel = newlevel;
23461f28255Scgd if (maxdlevel < dlevel)
23561f28255Scgd maxdlevel = dlevel;
23661f28255Scgd glo(dlevel);
23761f28255Scgd
23861f28255Scgd if (!level_exists[dlevel])
23961f28255Scgd mklev();
24061f28255Scgd else {
241ab8b6343Sjsm if ((fd = open(lock, O_RDONLY)) < 0) {
24261f28255Scgd pline("Cannot open %s .", lock);
24361f28255Scgd pline("Probably someone removed it.");
24461f28255Scgd done("tricked");
24561f28255Scgd }
24661f28255Scgd getlev(fd, hackpid, dlevel);
24761f28255Scgd (void) close(fd);
24861f28255Scgd }
24961f28255Scgd
25061f28255Scgd if (at_stairs) {
25161f28255Scgd if (up) {
25261f28255Scgd u.ux = xdnstair;
25361f28255Scgd u.uy = ydnstair;
25461f28255Scgd if (!u.ux) { /* entering a maze from below? */
2553ea4a95cSchristos u.ux = xupstair; /* this will confuse the
2563ea4a95cSchristos * player! */
25761f28255Scgd u.uy = yupstair;
25861f28255Scgd }
25961f28255Scgd if (Punished && !Levitation) {
26061f28255Scgd pline("With great effort you climb the stairs.");
26161f28255Scgd placebc(1);
26261f28255Scgd }
26361f28255Scgd } else {
26461f28255Scgd u.ux = xupstair;
26561f28255Scgd u.uy = yupstair;
26661f28255Scgd if (inv_weight() + 5 > 0 || Punished) {
26761f28255Scgd pline("You fall down the stairs."); /* %% */
26861f28255Scgd losehp(rnd(3), "fall");
26961f28255Scgd if (Punished) {
27061f28255Scgd if (uwep != uball && rn2(3)) {
27161f28255Scgd pline("... and are hit by the iron ball.");
27261f28255Scgd losehp(rnd(20), "iron ball");
27361f28255Scgd }
27461f28255Scgd placebc(1);
27561f28255Scgd }
27661f28255Scgd selftouch("Falling, you");
27761f28255Scgd }
27861f28255Scgd }
2793ea4a95cSchristos {
2803ea4a95cSchristos struct monst *mtmp = m_at(u.ux, u.uy);
28161f28255Scgd if (mtmp)
28261f28255Scgd mnexto(mtmp);
28361f28255Scgd }
28461f28255Scgd } else { /* trapdoor or level_tele */
28561f28255Scgd do {
28661f28255Scgd u.ux = rnd(COLNO - 1);
28761f28255Scgd u.uy = rn2(ROWNO);
28861f28255Scgd } while (levl[u.ux][u.uy].typ != ROOM ||
28961f28255Scgd m_at(u.ux, u.uy));
29061f28255Scgd if (Punished) {
29161f28255Scgd if (uwep != uball && !up /* %% */ && rn2(5)) {
29261f28255Scgd pline("The iron ball falls on your head.");
29361f28255Scgd losehp(rnd(25), "iron ball");
29461f28255Scgd }
29561f28255Scgd placebc(1);
29661f28255Scgd }
29761f28255Scgd selftouch("Falling, you");
29861f28255Scgd }
29961f28255Scgd (void) inshop();
30061f28255Scgd initrack();
30161f28255Scgd
30261f28255Scgd losedogs();
3033ea4a95cSchristos {
3043ea4a95cSchristos struct monst *mtmp;
3053ea4a95cSchristos if ((mtmp = m_at(u.ux, u.uy)) != NULL)
3063ea4a95cSchristos mnexto(mtmp); /* riv05!a3 */
30761f28255Scgd }
30861f28255Scgd flags.nscrinh = 0;
30961f28255Scgd setsee();
31061f28255Scgd seeobjs(); /* make old cadavers disappear - riv05!a3 */
31161f28255Scgd docrt();
31261f28255Scgd pickup(1);
31361f28255Scgd read_engr_at(u.ux, u.uy);
31461f28255Scgd }
31561f28255Scgd
3163ea4a95cSchristos int
donull(void)3171fa8a9a6Sdholland donull(void)
3183ea4a95cSchristos {
31961f28255Scgd return (1); /* Do nothing, but let other things happen */
32061f28255Scgd }
32161f28255Scgd
3223ea4a95cSchristos int
dopray(void)3231fa8a9a6Sdholland dopray(void)
3243ea4a95cSchristos {
32561f28255Scgd nomovemsg = "You finished your prayer.";
32661f28255Scgd nomul(-3);
32761f28255Scgd return (1);
32861f28255Scgd }
32961f28255Scgd
3303ea4a95cSchristos int
dothrow(void)3311fa8a9a6Sdholland dothrow(void)
33261f28255Scgd {
3333ea4a95cSchristos struct obj *obj;
3343ea4a95cSchristos struct monst *mon;
3353ea4a95cSchristos int tmp;
33661f28255Scgd
33761f28255Scgd obj = getobj("#)", "throw"); /* it is also possible to throw food */
33861f28255Scgd /* (or jewels, or iron balls ... ) */
33961f28255Scgd if (!obj || !getdir(1)) /* ask "in what direction?" */
34061f28255Scgd return (0);
34161f28255Scgd if (obj->owornmask & (W_ARMOR | W_RING)) {
34261f28255Scgd pline("You can't throw something you are wearing.");
34361f28255Scgd return (0);
34461f28255Scgd }
34561f28255Scgd u_wipe_engr(2);
34661f28255Scgd
34761f28255Scgd if (obj == uwep) {
34861f28255Scgd if (obj->cursed) {
34961f28255Scgd pline("Your weapon is welded to your hand.");
35061f28255Scgd return (1);
35161f28255Scgd }
35261f28255Scgd if (obj->quan > 1)
35361f28255Scgd setuwep(splitobj(obj, 1));
35461f28255Scgd else
35561f28255Scgd setuwep((struct obj *) 0);
3563ea4a95cSchristos } else if (obj->quan > 1)
35761f28255Scgd (void) splitobj(obj, 1);
35861f28255Scgd freeinv(obj);
35961f28255Scgd if (u.uswallow) {
36061f28255Scgd mon = u.ustuck;
36161f28255Scgd bhitpos.x = mon->mx;
36261f28255Scgd bhitpos.y = mon->my;
36361f28255Scgd } else if (u.dz) {
36461f28255Scgd if (u.dz < 0) {
36561f28255Scgd pline("%s hits the ceiling, then falls back on top of your head.",
36661f28255Scgd Doname(obj)); /* note: obj->quan == 1 */
36761f28255Scgd if (obj->olet == POTION_SYM)
36861f28255Scgd potionhit(&youmonst, obj);
36961f28255Scgd else {
3703ea4a95cSchristos if (uarmh)
3713ea4a95cSchristos pline("Fortunately, you are wearing a helmet!");
37261f28255Scgd losehp(uarmh ? 1 : rnd((int) (obj->owt)), "falling object");
37361f28255Scgd dropy(obj);
37461f28255Scgd }
37561f28255Scgd } else {
37661f28255Scgd pline("%s hits the floor.", Doname(obj));
37761f28255Scgd if (obj->otyp == EXPENSIVE_CAMERA) {
37861f28255Scgd pline("It is shattered in a thousand pieces!");
37961f28255Scgd obfree(obj, Null(obj));
38061f28255Scgd } else if (obj->otyp == EGG) {
38161f28255Scgd pline("\"Splash!\"");
38261f28255Scgd obfree(obj, Null(obj));
38361f28255Scgd } else if (obj->olet == POTION_SYM) {
38461f28255Scgd pline("The flask breaks, and you smell a peculiar odor ...");
38561f28255Scgd potionbreathe(obj);
38661f28255Scgd obfree(obj, Null(obj));
38761f28255Scgd } else {
38861f28255Scgd dropy(obj);
38961f28255Scgd }
39061f28255Scgd }
39161f28255Scgd return (1);
39261f28255Scgd } else if (obj->otyp == BOOMERANG) {
39361f28255Scgd mon = boomhit(u.dx, u.dy);
39461f28255Scgd if (mon == &youmonst) { /* the thing was caught */
39561f28255Scgd (void) addinv(obj);
39661f28255Scgd return (1);
39761f28255Scgd }
39861f28255Scgd } else {
39961f28255Scgd if (obj->otyp == PICK_AXE && shkcatch(obj))
40061f28255Scgd return (1);
40161f28255Scgd
40261f28255Scgd mon = bhit(u.dx, u.dy, (obj->otyp == ICE_BOX) ? 1 :
40361f28255Scgd (!Punished || obj != uball) ? 8 : !u.ustuck ? 5 : 1,
40461f28255Scgd obj->olet,
405cb5fd834Sjsm (void (*)(struct monst *, struct obj *)) 0,
406cb5fd834Sjsm (int (*)(struct obj *, struct obj *)) 0, obj);
40761f28255Scgd }
40861f28255Scgd if (mon) {
40961f28255Scgd /* awake monster if sleeping */
41061f28255Scgd wakeup(mon);
41161f28255Scgd
41261f28255Scgd if (obj->olet == WEAPON_SYM) {
41361f28255Scgd tmp = -1 + u.ulevel + mon->data->ac + abon();
41461f28255Scgd if (obj->otyp < ROCK) {
41561f28255Scgd if (!uwep ||
41661f28255Scgd uwep->otyp != obj->otyp + (BOW - ARROW))
41761f28255Scgd tmp -= 4;
41861f28255Scgd else {
41961f28255Scgd tmp += uwep->spe;
42061f28255Scgd }
4213ea4a95cSchristos } else if (obj->otyp == BOOMERANG)
4223ea4a95cSchristos tmp += 4;
42361f28255Scgd tmp += obj->spe;
42461f28255Scgd if (u.uswallow || tmp >= rnd(20)) {
42561f28255Scgd if (hmon(mon, obj, 1) == TRUE) {
42661f28255Scgd /* mon still alive */
42761f28255Scgd #ifndef NOWORM
42861f28255Scgd cutworm(mon, bhitpos.x, bhitpos.y, obj->otyp);
4293ea4a95cSchristos #endif /* NOWORM */
4303ea4a95cSchristos } else
4313ea4a95cSchristos mon = 0;
43261f28255Scgd /* weapons thrown disappear sometimes */
43361f28255Scgd if (obj->otyp < BOOMERANG && rn2(3)) {
43461f28255Scgd /* check bill; free */
43561f28255Scgd obfree(obj, (struct obj *) 0);
43661f28255Scgd return (1);
43761f28255Scgd }
4383ea4a95cSchristos } else
4393ea4a95cSchristos miss(objects[obj->otyp].oc_name, mon);
44061f28255Scgd } else if (obj->otyp == HEAVY_IRON_BALL) {
44161f28255Scgd tmp = -1 + u.ulevel + mon->data->ac + abon();
4423ea4a95cSchristos if (!Punished || obj != uball)
4433ea4a95cSchristos tmp += 2;
4443ea4a95cSchristos if (u.utrap)
4453ea4a95cSchristos tmp -= 2;
44661f28255Scgd if (u.uswallow || tmp >= rnd(20)) {
44761f28255Scgd if (hmon(mon, obj, 1) == FALSE)
44861f28255Scgd mon = 0; /* he died */
4493ea4a95cSchristos } else
4503ea4a95cSchristos miss("iron ball", mon);
45161f28255Scgd } else if (obj->olet == POTION_SYM && u.ulevel > rn2(15)) {
45261f28255Scgd potionhit(mon, obj);
45361f28255Scgd return (1);
45461f28255Scgd } else {
45561f28255Scgd if (cansee(bhitpos.x, bhitpos.y))
45661f28255Scgd pline("You miss %s.", monnam(mon));
4573ea4a95cSchristos else
4583ea4a95cSchristos pline("You miss it.");
45961f28255Scgd if (obj->olet == FOOD_SYM && mon->data->mlet == 'd')
4603ea4a95cSchristos if (tamedog(mon, obj))
4613ea4a95cSchristos return (1);
46261f28255Scgd if (obj->olet == GEM_SYM && mon->data->mlet == 'u' &&
46361f28255Scgd !mon->mtame) {
46461f28255Scgd if (obj->dknown && objects[obj->otyp].oc_name_known) {
46561f28255Scgd if (objects[obj->otyp].g_val > 0) {
46661f28255Scgd u.uluck += 5;
46761f28255Scgd goto valuable;
46861f28255Scgd } else {
46961f28255Scgd pline("%s is not interested in your junk.",
47061f28255Scgd Monnam(mon));
47161f28255Scgd }
47261f28255Scgd } else { /* value unknown to @ */
47361f28255Scgd u.uluck++;
47461f28255Scgd valuable:
47561f28255Scgd if (u.uluck > LUCKMAX) /* dan@ut-ngp */
47661f28255Scgd u.uluck = LUCKMAX;
47761f28255Scgd pline("%s graciously accepts your gift.",
47861f28255Scgd Monnam(mon));
47961f28255Scgd mpickobj(mon, obj);
48061f28255Scgd rloc(mon);
48161f28255Scgd return (1);
48261f28255Scgd }
48361f28255Scgd }
48461f28255Scgd }
48561f28255Scgd }
48661f28255Scgd /* the code following might become part of dropy() */
48761f28255Scgd if (obj->otyp == CRYSKNIFE)
48861f28255Scgd obj->otyp = WORM_TOOTH;
48961f28255Scgd obj->ox = bhitpos.x;
49061f28255Scgd obj->oy = bhitpos.y;
49161f28255Scgd obj->nobj = fobj;
49261f28255Scgd fobj = obj;
49361f28255Scgd /* prevent him from throwing articles to the exit and escaping */
49461f28255Scgd /* subfrombill(obj); */
49561f28255Scgd stackobj(obj);
49661f28255Scgd if (Punished && obj == uball &&
49761f28255Scgd (bhitpos.x != u.ux || bhitpos.y != u.uy)) {
49861f28255Scgd freeobj(uchain);
49961f28255Scgd unpobj(uchain);
50061f28255Scgd if (u.utrap) {
50161f28255Scgd if (u.utraptype == TT_PIT)
50261f28255Scgd pline("The ball pulls you out of the pit!");
50361f28255Scgd else {
5043ea4a95cSchristos long side =
50561f28255Scgd rn2(3) ? LEFT_SIDE : RIGHT_SIDE;
50661f28255Scgd pline("The ball pulls you out of the bear trap.");
50761f28255Scgd pline("Your %s leg is severely damaged.",
50861f28255Scgd (side == LEFT_SIDE) ? "left" : "right");
50961f28255Scgd set_wounded_legs(side, 500 + rn2(1000));
51061f28255Scgd losehp(2, "thrown ball");
51161f28255Scgd }
51261f28255Scgd u.utrap = 0;
51361f28255Scgd }
51461f28255Scgd unsee();
51561f28255Scgd uchain->nobj = fobj;
51661f28255Scgd fobj = uchain;
51761f28255Scgd u.ux = uchain->ox = bhitpos.x - u.dx;
51861f28255Scgd u.uy = uchain->oy = bhitpos.y - u.dy;
51961f28255Scgd setsee();
52061f28255Scgd (void) inshop();
52161f28255Scgd }
5223ea4a95cSchristos if (cansee(bhitpos.x, bhitpos.y))
5233ea4a95cSchristos prl(bhitpos.x, bhitpos.y);
52461f28255Scgd return (1);
52561f28255Scgd }
52661f28255Scgd
52761f28255Scgd /* split obj so that it gets size num */
52861f28255Scgd /* remainder is put in the object structure delivered by this call */
52961f28255Scgd struct obj *
splitobj(struct obj * obj,int num)5301fa8a9a6Sdholland splitobj(struct obj *obj, int num)
5313ea4a95cSchristos {
5323ea4a95cSchristos struct obj *otmp;
53361f28255Scgd otmp = newobj(0);
53461f28255Scgd *otmp = *obj; /* copies whole structure */
53561f28255Scgd otmp->o_id = flags.ident++;
53661f28255Scgd otmp->onamelth = 0;
53761f28255Scgd obj->quan = num;
53861f28255Scgd obj->owt = weight(obj);
53961f28255Scgd otmp->quan -= num;
54061f28255Scgd otmp->owt = weight(otmp); /* -= obj->owt ? */
54161f28255Scgd obj->nobj = otmp;
5423ea4a95cSchristos if (obj->unpaid)
5433ea4a95cSchristos splitbill(obj, otmp);
54461f28255Scgd return (otmp);
54561f28255Scgd }
54661f28255Scgd
5473ea4a95cSchristos void
more_experienced(int exp,int rexp)5481fa8a9a6Sdholland more_experienced(int exp, int rexp)
54961f28255Scgd {
55061f28255Scgd u.uexp += exp;
55161f28255Scgd u.urexp += 4 * exp + rexp;
5523ea4a95cSchristos if (exp)
5533ea4a95cSchristos flags.botl = 1;
55461f28255Scgd if (u.urexp >= ((pl_character[0] == 'W') ? 1000 : 2000))
55561f28255Scgd flags.beginner = 0;
55661f28255Scgd }
55761f28255Scgd
5583ea4a95cSchristos void
set_wounded_legs(long side,int timex)5591fa8a9a6Sdholland set_wounded_legs(long side, int timex)
56061f28255Scgd {
56161f28255Scgd if (!Wounded_legs || (Wounded_legs & TIMEOUT))
56261f28255Scgd Wounded_legs |= side + timex;
56361f28255Scgd else
56461f28255Scgd Wounded_legs |= side;
56561f28255Scgd }
56661f28255Scgd
5673ea4a95cSchristos void
heal_legs(void)5681fa8a9a6Sdholland heal_legs(void)
56961f28255Scgd {
57061f28255Scgd if (Wounded_legs) {
57161f28255Scgd if ((Wounded_legs & BOTH_SIDES) == BOTH_SIDES)
57261f28255Scgd pline("Your legs feel somewhat better.");
57361f28255Scgd else
57461f28255Scgd pline("Your leg feels somewhat better.");
57561f28255Scgd Wounded_legs = 0;
57661f28255Scgd }
57761f28255Scgd }
578