1*d5b021c7Sdholland /* $NetBSD: hack.dog.c,v 1.12 2011/08/07 06:03:45 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*d5b021c7Sdholland __RCSID("$NetBSD: hack.dog.c,v 1.12 2011/08/07 06:03:45 dholland Exp $");
6702ded532Smycroft #endif /* not lint */
6861f28255Scgd
6961f28255Scgd #include "hack.h"
703ea4a95cSchristos #include "extern.h"
7161f28255Scgd #include "hack.mfndpos.h"
7261f28255Scgd #include "def.edog.h"
7361f28255Scgd #include "def.mkroom.h"
7461f28255Scgd
75ab8b6343Sjsm const struct permonst li_dog =
7661f28255Scgd {"little dog", 'd', 2, 18, 6, 1, 6, sizeof(struct edog)};
77ab8b6343Sjsm const struct permonst dog =
7861f28255Scgd {"dog", 'd', 4, 16, 5, 1, 6, sizeof(struct edog)};
79ab8b6343Sjsm const struct permonst la_dog =
8061f28255Scgd {"large dog", 'd', 6, 15, 4, 2, 4, sizeof(struct edog)};
8161f28255Scgd
829b92b189Sdholland static void initedog(struct monst *);
839b92b189Sdholland static int dogfood(struct obj *);
8461f28255Scgd
853ea4a95cSchristos void
makedog(void)861fa8a9a6Sdholland makedog(void)
873ea4a95cSchristos {
883ea4a95cSchristos struct monst *mtmp = makemon(&li_dog, u.ux, u.uy);
893ea4a95cSchristos if (!mtmp)
903ea4a95cSchristos return; /* dogs were genocided */
9161f28255Scgd initedog(mtmp);
9261f28255Scgd }
9361f28255Scgd
949b92b189Sdholland static void
initedog(struct monst * mtmp)951fa8a9a6Sdholland initedog(struct monst *mtmp)
963ea4a95cSchristos {
9761f28255Scgd mtmp->mtame = mtmp->mpeaceful = 1;
9861f28255Scgd EDOG(mtmp)->hungrytime = 1000 + moves;
9961f28255Scgd EDOG(mtmp)->eattime = 0;
10061f28255Scgd EDOG(mtmp)->droptime = 0;
10161f28255Scgd EDOG(mtmp)->dropdist = 10000;
10261f28255Scgd EDOG(mtmp)->apport = 10;
10361f28255Scgd EDOG(mtmp)->whistletime = 0;
10461f28255Scgd }
10561f28255Scgd
10661f28255Scgd /* attach the monsters that went down (or up) together with @ */
10761f28255Scgd struct monst *mydogs = 0;
10861f28255Scgd struct monst *fallen_down = 0;/* monsters that fell through a trapdoor */
10961f28255Scgd /* they will appear on the next level @ goes to, even if he goes up! */
11061f28255Scgd
1113ea4a95cSchristos void
losedogs(void)1121fa8a9a6Sdholland losedogs(void)
1133ea4a95cSchristos {
1143ea4a95cSchristos struct monst *mtmp;
1153ea4a95cSchristos while ((mtmp = mydogs) != NULL) {
11661f28255Scgd mydogs = mtmp->nmon;
11761f28255Scgd mtmp->nmon = fmon;
11861f28255Scgd fmon = mtmp;
11961f28255Scgd mnexto(mtmp);
12061f28255Scgd }
1213ea4a95cSchristos while ((mtmp = fallen_down) != NULL) {
12261f28255Scgd fallen_down = mtmp->nmon;
12361f28255Scgd mtmp->nmon = fmon;
12461f28255Scgd fmon = mtmp;
12561f28255Scgd rloc(mtmp);
12661f28255Scgd }
12761f28255Scgd }
12861f28255Scgd
1293ea4a95cSchristos void
keepdogs(void)1301fa8a9a6Sdholland keepdogs(void)
1313ea4a95cSchristos {
1323ea4a95cSchristos struct monst *mtmp;
13361f28255Scgd for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
13461f28255Scgd if (dist(mtmp->mx, mtmp->my) < 3 && follower(mtmp)
13561f28255Scgd && !mtmp->msleep && !mtmp->mfroz) {
13661f28255Scgd relmon(mtmp);
13761f28255Scgd mtmp->nmon = mydogs;
13861f28255Scgd mydogs = mtmp;
13961f28255Scgd unpmon(mtmp);
1403ea4a95cSchristos keepdogs(); /* we destroyed the link, so use
1413ea4a95cSchristos * recursion */
14261f28255Scgd return; /* (admittedly somewhat primitive) */
14361f28255Scgd }
14461f28255Scgd }
14561f28255Scgd
1463ea4a95cSchristos void
fall_down(struct monst * mtmp)1471fa8a9a6Sdholland fall_down(struct monst *mtmp)
1483ea4a95cSchristos {
14961f28255Scgd relmon(mtmp);
15061f28255Scgd mtmp->nmon = fallen_down;
15161f28255Scgd fallen_down = mtmp;
15261f28255Scgd unpmon(mtmp);
15361f28255Scgd mtmp->mtame = 0;
15461f28255Scgd }
15561f28255Scgd
15661f28255Scgd /* return quality of food; the lower the better */
15761f28255Scgd #define DOGFOOD 0
15861f28255Scgd #define CADAVER 1
15961f28255Scgd #define ACCFOOD 2
16061f28255Scgd #define MANFOOD 3
16161f28255Scgd #define APPORT 4
16261f28255Scgd #define POISON 5
16361f28255Scgd #define UNDEF 6
1649b92b189Sdholland static int
dogfood(struct obj * obj)1651fa8a9a6Sdholland dogfood(struct obj *obj)
1663ea4a95cSchristos {
16761f28255Scgd switch (obj->olet) {
16861f28255Scgd case FOOD_SYM:
16961f28255Scgd return (
17061f28255Scgd (obj->otyp == TRIPE_RATION) ? DOGFOOD :
17161f28255Scgd (obj->otyp < CARROT) ? ACCFOOD :
17261f28255Scgd (obj->otyp < CORPSE) ? MANFOOD :
17361f28255Scgd (poisonous(obj) || obj->age + 50 <= moves ||
17461f28255Scgd obj->otyp == DEAD_COCKATRICE)
17561f28255Scgd ? POISON : CADAVER
17661f28255Scgd );
17761f28255Scgd default:
1783ea4a95cSchristos if (!obj->cursed)
1793ea4a95cSchristos return (APPORT);
180*d5b021c7Sdholland /* FALLTHROUGH */
18161f28255Scgd case BALL_SYM:
18261f28255Scgd case CHAIN_SYM:
18361f28255Scgd case ROCK_SYM:
18461f28255Scgd return (UNDEF);
18561f28255Scgd }
18661f28255Scgd }
18761f28255Scgd
18861f28255Scgd /* return 0 (no move), 1 (move) or 2 (dead) */
1893ea4a95cSchristos int
dog_move(struct monst * mtmp,int after)190ab8b6343Sjsm dog_move(struct monst *mtmp, int after)
1913ea4a95cSchristos {
1923ea4a95cSchristos int nx, ny, omx, omy, appr, nearer, j;
1933ea4a95cSchristos int udist, chi = 0, i, whappr;
1943ea4a95cSchristos struct monst *mtmp2;
195ab8b6343Sjsm const struct permonst *mdat = mtmp->data;
1963ea4a95cSchristos struct edog *edog = EDOG(mtmp);
19761f28255Scgd struct obj *obj;
19861f28255Scgd struct trap *trap;
19961f28255Scgd xchar cnt, chcnt, nix, niy;
20061f28255Scgd schar dogroom, uroom;
2013ea4a95cSchristos xchar gx = 0, gy = 0, gtyp, otyp; /* current goal */
20261f28255Scgd coord poss[9];
20361f28255Scgd int info[9];
20461f28255Scgd #define GDIST(x,y) ((x-gx)*(x-gx) + (y-gy)*(y-gy))
20561f28255Scgd #define DDIST(x,y) ((x-omx)*(x-omx) + (y-omy)*(y-omy))
20661f28255Scgd
2073ea4a95cSchristos if (moves <= edog->eattime)
2083ea4a95cSchristos return (0); /* dog is still eating */
20961f28255Scgd omx = mtmp->mx;
21061f28255Scgd omy = mtmp->my;
21161f28255Scgd whappr = (moves - EDOG(mtmp)->whistletime < 5);
21261f28255Scgd if (moves > edog->hungrytime + 500 && !mtmp->mconf) {
21361f28255Scgd mtmp->mconf = 1;
21461f28255Scgd mtmp->mhpmax /= 3;
21561f28255Scgd if (mtmp->mhp > mtmp->mhpmax)
21661f28255Scgd mtmp->mhp = mtmp->mhpmax;
21761f28255Scgd if (cansee(omx, omy))
21861f28255Scgd pline("%s is confused from hunger.", Monnam(mtmp));
2193ea4a95cSchristos else
2203ea4a95cSchristos pline("You feel worried about %s.", monnam(mtmp));
2213ea4a95cSchristos } else if (moves > edog->hungrytime + 750 || mtmp->mhp < 1) {
22261f28255Scgd if (cansee(omx, omy))
22361f28255Scgd pline("%s dies from hunger.", Monnam(mtmp));
22461f28255Scgd else
22561f28255Scgd pline("You have a sad feeling for a moment, then it passes.");
22661f28255Scgd mondied(mtmp);
22761f28255Scgd return (2);
22861f28255Scgd }
22961f28255Scgd dogroom = inroom(omx, omy);
23061f28255Scgd uroom = inroom(u.ux, u.uy);
23161f28255Scgd udist = dist(omx, omy);
23261f28255Scgd
23361f28255Scgd /* maybe we tamed him while being swallowed --jgm */
2343ea4a95cSchristos if (!udist)
2353ea4a95cSchristos return (0);
23661f28255Scgd
23761f28255Scgd /* if we are carrying sth then we drop it (perhaps near @) */
23861f28255Scgd /* Note: if apport == 1 then our behaviour is independent of udist */
23961f28255Scgd if (mtmp->minvent) {
24061f28255Scgd if (!rn2(udist) || !rn2((int) edog->apport))
2413c439f43Sdholland if ((unsigned) rn2(10) < edog->apport) {
24261f28255Scgd relobj(mtmp, (int) mtmp->minvis);
2433ea4a95cSchristos if (edog->apport > 1)
2443ea4a95cSchristos edog->apport--;
24561f28255Scgd edog->dropdist = udist; /* hpscdi!jon */
24661f28255Scgd edog->droptime = moves;
24761f28255Scgd }
24861f28255Scgd } else {
2493ea4a95cSchristos if ((obj = o_at(omx, omy)) != NULL)
2503ea4a95cSchristos if (!strchr("0_", obj->olet)) {
25161f28255Scgd if ((otyp = dogfood(obj)) <= CADAVER) {
25261f28255Scgd nix = omx;
25361f28255Scgd niy = omy;
25461f28255Scgd goto eatobj;
25561f28255Scgd }
25661f28255Scgd if (obj->owt < 10 * mtmp->data->mlevel)
2573c439f43Sdholland if ((unsigned) rn2(20) < edog->apport + 3)
25861f28255Scgd if (rn2(udist) || !rn2((int) edog->apport)) {
25961f28255Scgd freeobj(obj);
26061f28255Scgd unpobj(obj);
2613ea4a95cSchristos /*
2623ea4a95cSchristos * if(levl[omx][omy].s
2633ea4a95cSchristos * crsym ==
2643ea4a95cSchristos * obj->olet)
2653ea4a95cSchristos * newsym(omx,omy);
2663ea4a95cSchristos */
26761f28255Scgd mpickobj(mtmp, obj);
26861f28255Scgd }
26961f28255Scgd }
27061f28255Scgd }
27161f28255Scgd
27261f28255Scgd /* first we look for food */
27361f28255Scgd gtyp = UNDEF; /* no goal as yet */
27461f28255Scgd #ifdef LINT
27561f28255Scgd gx = gy = 0; /* suppress 'used before set' message */
2763ea4a95cSchristos #endif /* LINT */
27761f28255Scgd for (obj = fobj; obj; obj = obj->nobj) {
27861f28255Scgd otyp = dogfood(obj);
2793ea4a95cSchristos if (otyp > gtyp || otyp == UNDEF)
2803ea4a95cSchristos continue;
2813ea4a95cSchristos if (inroom(obj->ox, obj->oy) != dogroom)
2823ea4a95cSchristos continue;
28361f28255Scgd if (otyp < MANFOOD &&
28461f28255Scgd (dogroom >= 0 || DDIST(obj->ox, obj->oy) < 10)) {
28561f28255Scgd if (otyp < gtyp || (otyp == gtyp &&
28661f28255Scgd DDIST(obj->ox, obj->oy) < DDIST(gx, gy))) {
28761f28255Scgd gx = obj->ox;
28861f28255Scgd gy = obj->oy;
28961f28255Scgd gtyp = otyp;
29061f28255Scgd }
2913ea4a95cSchristos } else if (gtyp == UNDEF && dogroom >= 0 &&
29261f28255Scgd uroom == dogroom &&
2933c439f43Sdholland !mtmp->minvent && edog->apport > (unsigned)rn2(8)) {
29461f28255Scgd gx = obj->ox;
29561f28255Scgd gy = obj->oy;
29661f28255Scgd gtyp = APPORT;
29761f28255Scgd }
29861f28255Scgd }
29961f28255Scgd if (gtyp == UNDEF ||
30061f28255Scgd (gtyp != DOGFOOD && gtyp != APPORT && moves < edog->hungrytime)) {
30161f28255Scgd if (dogroom < 0 || dogroom == uroom) {
30261f28255Scgd gx = u.ux;
30361f28255Scgd gy = u.uy;
30461f28255Scgd #ifndef QUEST
30561f28255Scgd } else {
30661f28255Scgd int tmp = rooms[dogroom].fdoor;
30761f28255Scgd cnt = rooms[dogroom].doorct;
30861f28255Scgd
30961f28255Scgd gx = gy = FAR; /* random, far away */
31061f28255Scgd while (cnt--) {
31161f28255Scgd if (dist(gx, gy) >
31261f28255Scgd dist(doors[tmp].x, doors[tmp].y)) {
31361f28255Scgd gx = doors[tmp].x;
31461f28255Scgd gy = doors[tmp].y;
31561f28255Scgd }
31661f28255Scgd tmp++;
31761f28255Scgd }
31861f28255Scgd /* here gx == FAR e.g. when dog is in a vault */
31961f28255Scgd if (gx == FAR || (gx == omx && gy == omy)) {
32061f28255Scgd gx = u.ux;
32161f28255Scgd gy = u.uy;
32261f28255Scgd }
3233ea4a95cSchristos #endif /* QUEST */
32461f28255Scgd }
32561f28255Scgd appr = (udist >= 9) ? 1 : (mtmp->mflee) ? -1 : 0;
32661f28255Scgd if (after && udist <= 4 && gx == u.ux && gy == u.uy)
32761f28255Scgd return (0);
32861f28255Scgd if (udist > 1) {
32961f28255Scgd if (!IS_ROOM(levl[u.ux][u.uy].typ) || !rn2(4) ||
33061f28255Scgd whappr ||
33161f28255Scgd (mtmp->minvent && rn2((int) edog->apport)))
33261f28255Scgd appr = 1;
33361f28255Scgd }
33461f28255Scgd /* if you have dog food he'll follow you more closely */
33561f28255Scgd if (appr == 0) {
33661f28255Scgd obj = invent;
33761f28255Scgd while (obj) {
33861f28255Scgd if (obj->otyp == TRIPE_RATION) {
33961f28255Scgd appr = 1;
34061f28255Scgd break;
34161f28255Scgd }
34261f28255Scgd obj = obj->nobj;
34361f28255Scgd }
34461f28255Scgd }
3453ea4a95cSchristos } else
3463ea4a95cSchristos appr = 1; /* gtyp != UNDEF */
3473ea4a95cSchristos if (mtmp->mconf)
3483ea4a95cSchristos appr = 0;
34961f28255Scgd
35061f28255Scgd if (gx == u.ux && gy == u.uy && (dogroom != uroom || dogroom < 0)) {
3513ea4a95cSchristos coord *cp;
35261f28255Scgd cp = gettrack(omx, omy);
35361f28255Scgd if (cp) {
35461f28255Scgd gx = cp->x;
35561f28255Scgd gy = cp->y;
35661f28255Scgd }
35761f28255Scgd }
35861f28255Scgd nix = omx;
35961f28255Scgd niy = omy;
36061f28255Scgd cnt = mfndpos(mtmp, poss, info, ALLOW_M | ALLOW_TRAPS);
36161f28255Scgd chcnt = 0;
36261f28255Scgd chi = -1;
36361f28255Scgd for (i = 0; i < cnt; i++) {
36461f28255Scgd nx = poss[i].x;
36561f28255Scgd ny = poss[i].y;
36661f28255Scgd if (info[i] & ALLOW_M) {
36761f28255Scgd mtmp2 = m_at(nx, ny);
368a3fb5aa7Sjnemeth if (mtmp2 == NULL)
369f413c2baSjnemeth panic("error in dog_move");
37061f28255Scgd if (mtmp2->data->mlevel >= mdat->mlevel + 2 ||
37161f28255Scgd mtmp2->data->mlet == 'c')
37261f28255Scgd continue;
3733ea4a95cSchristos if (after)
3743ea4a95cSchristos return (0); /* hit only once each move */
37561f28255Scgd
37661f28255Scgd if (hitmm(mtmp, mtmp2) == 1 && rn2(4) &&
37761f28255Scgd mtmp2->mlstmv != moves &&
3783ea4a95cSchristos hitmm(mtmp2, mtmp) == 2)
3793ea4a95cSchristos return (2);
38061f28255Scgd return (0);
38161f28255Scgd }
38261f28255Scgd /* dog avoids traps */
38361f28255Scgd /* but perhaps we have to pass a trap in order to follow @ */
38461f28255Scgd if ((info[i] & ALLOW_TRAPS) && (trap = t_at(nx, ny))) {
3853ea4a95cSchristos if (!trap->tseen && rn2(40))
3863ea4a95cSchristos continue;
3873ea4a95cSchristos if (rn2(10))
3883ea4a95cSchristos continue;
38961f28255Scgd }
39061f28255Scgd /* dog eschewes cursed objects */
39161f28255Scgd /* but likes dog food */
39261f28255Scgd obj = fobj;
39361f28255Scgd while (obj) {
39461f28255Scgd if (obj->ox != nx || obj->oy != ny)
39561f28255Scgd goto nextobj;
3963ea4a95cSchristos if (obj->cursed)
3973ea4a95cSchristos goto nxti;
39861f28255Scgd if (obj->olet == FOOD_SYM &&
39961f28255Scgd (otyp = dogfood(obj)) < MANFOOD &&
40061f28255Scgd (otyp < ACCFOOD || edog->hungrytime <= moves)) {
4013ea4a95cSchristos /*
4023ea4a95cSchristos * Note: our dog likes the food so much that
4033ea4a95cSchristos * he might eat it even when it conceals a
4043ea4a95cSchristos * cursed object
4053ea4a95cSchristos */
40661f28255Scgd nix = nx;
40761f28255Scgd niy = ny;
40861f28255Scgd chi = i;
40961f28255Scgd eatobj:
41061f28255Scgd edog->eattime =
41161f28255Scgd moves + obj->quan * objects[obj->otyp].oc_delay;
41261f28255Scgd if (edog->hungrytime < moves)
41361f28255Scgd edog->hungrytime = moves;
41461f28255Scgd edog->hungrytime +=
41561f28255Scgd 5 * obj->quan * objects[obj->otyp].nutrition;
41661f28255Scgd mtmp->mconf = 0;
41761f28255Scgd if (cansee(nix, niy))
41861f28255Scgd pline("%s ate %s.", Monnam(mtmp), doname(obj));
41961f28255Scgd /* perhaps this was a reward */
42061f28255Scgd if (otyp != CADAVER)
42161f28255Scgd edog->apport += 200 / (edog->dropdist + moves - edog->droptime);
42261f28255Scgd delobj(obj);
42361f28255Scgd goto newdogpos;
42461f28255Scgd }
42561f28255Scgd nextobj:
42661f28255Scgd obj = obj->nobj;
42761f28255Scgd }
42861f28255Scgd
42961f28255Scgd for (j = 0; j < MTSZ && j < cnt - 1; j++)
43061f28255Scgd if (nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y)
4313ea4a95cSchristos if (rn2(4 * (cnt - j)))
4323ea4a95cSchristos goto nxti;
43361f28255Scgd
4343ea4a95cSchristos /*
4353ea4a95cSchristos * Some stupid C compilers cannot compute the whole
4363ea4a95cSchristos * expression at once.
4373ea4a95cSchristos */
43861f28255Scgd nearer = GDIST(nx, ny);
43961f28255Scgd nearer -= GDIST(nix, niy);
44061f28255Scgd nearer *= appr;
44161f28255Scgd if ((nearer == 0 && !rn2(++chcnt)) || nearer < 0 ||
44261f28255Scgd (nearer > 0 && !whappr &&
44361f28255Scgd ((omx == nix && omy == niy && !rn2(3))
44461f28255Scgd || !rn2(12))
44561f28255Scgd )) {
44661f28255Scgd nix = nx;
44761f28255Scgd niy = ny;
4483ea4a95cSchristos if (nearer < 0)
4493ea4a95cSchristos chcnt = 0;
45061f28255Scgd chi = i;
45161f28255Scgd }
45261f28255Scgd nxti: ;
45361f28255Scgd }
45461f28255Scgd newdogpos:
45561f28255Scgd if (nix != omx || niy != omy) {
45661f28255Scgd if (info[chi] & ALLOW_U) {
45761f28255Scgd (void) hitu(mtmp, d(mdat->damn, mdat->damd) + 1);
45861f28255Scgd return (0);
45961f28255Scgd }
46061f28255Scgd mtmp->mx = nix;
46161f28255Scgd mtmp->my = niy;
4623ea4a95cSchristos for (j = MTSZ - 1; j > 0; j--)
4633ea4a95cSchristos mtmp->mtrack[j] = mtmp->mtrack[j - 1];
46461f28255Scgd mtmp->mtrack[0].x = omx;
46561f28255Scgd mtmp->mtrack[0].y = omy;
46661f28255Scgd }
46761f28255Scgd if (mintrap(mtmp) == 2) /* he died */
46861f28255Scgd return (2);
46961f28255Scgd pmon(mtmp);
47061f28255Scgd return (1);
47161f28255Scgd }
47261f28255Scgd
47361f28255Scgd /* return roomnumber or -1 */
4743ea4a95cSchristos int
inroom(xchar x,xchar y)4751fa8a9a6Sdholland inroom(xchar x, xchar y)
4763ea4a95cSchristos {
47761f28255Scgd #ifndef QUEST
478*d5b021c7Sdholland int pos = 0;
479*d5b021c7Sdholland
480*d5b021c7Sdholland while (rooms[pos].hx >= 0) {
481*d5b021c7Sdholland if (rooms[pos].hx >= x - 1 && rooms[pos].lx <= x + 1 &&
482*d5b021c7Sdholland rooms[pos].hy >= y - 1 && rooms[pos].ly <= y + 1)
483*d5b021c7Sdholland return pos;
484*d5b021c7Sdholland pos++;
48561f28255Scgd }
4863ea4a95cSchristos #endif /* QUEST */
48761f28255Scgd return (-1); /* not in room or on door */
48861f28255Scgd }
48961f28255Scgd
4903ea4a95cSchristos int
tamedog(struct monst * mtmp,struct obj * obj)4911fa8a9a6Sdholland tamedog(struct monst *mtmp, struct obj *obj)
49261f28255Scgd {
4933ea4a95cSchristos struct monst *mtmp2;
49461f28255Scgd
49561f28255Scgd if (flags.moonphase == FULL_MOON && night() && rn2(6))
49661f28255Scgd return (0);
49761f28255Scgd
49861f28255Scgd /* If we cannot tame him, at least he's no longer afraid. */
49961f28255Scgd mtmp->mflee = 0;
50061f28255Scgd mtmp->mfleetim = 0;
50161f28255Scgd if (mtmp->mtame || mtmp->mfroz ||
50261f28255Scgd #ifndef NOWORM
50361f28255Scgd mtmp->wormno ||
5043ea4a95cSchristos #endif /* NOWORM */
5053ea4a95cSchristos mtmp->isshk || mtmp->isgd || strchr(" &@12", mtmp->data->mlet))
50661f28255Scgd return (0); /* no tame long worms? */
50761f28255Scgd if (obj) {
5083ea4a95cSchristos if (dogfood(obj) >= MANFOOD)
5093ea4a95cSchristos return (0);
51061f28255Scgd if (cansee(mtmp->mx, mtmp->my)) {
51161f28255Scgd pline("%s devours the %s.", Monnam(mtmp),
51261f28255Scgd objects[obj->otyp].oc_name);
51361f28255Scgd }
51461f28255Scgd obfree(obj, (struct obj *) 0);
51561f28255Scgd }
51661f28255Scgd mtmp2 = newmonst(sizeof(struct edog) + mtmp->mnamelth);
51761f28255Scgd *mtmp2 = *mtmp;
51861f28255Scgd mtmp2->mxlth = sizeof(struct edog);
5193ea4a95cSchristos if (mtmp->mnamelth)
5203ea4a95cSchristos (void) strcpy(NAME(mtmp2), NAME(mtmp));
52161f28255Scgd initedog(mtmp2);
52261f28255Scgd replmon(mtmp, mtmp2);
52361f28255Scgd return (1);
52461f28255Scgd }
525