# 2.11BSD#431 - /usr/src/games/hack/hack.dog.c

##### Functions

    dog_move          X
    dogfood           X
    fall_down         X
    initedog          X
    inroom            X
    keepdogs          X
    losedogs          X
    makedog           X
    tamedog           X

##### Variables

    dog               X
    fallen_down       X
    la_dog            X
    li_dog            X
    mydogs            X

##### Macros

    ACCFOOD           X
    APPORT            X
    CADAVER           X
    DDIST             X
    DOGFOOD           X
    GDIST             X
    MANFOOD           X
    POISON            X
    UNDEF             X

       1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
       2: /* hack.dog.c - version 1.0.3 */
       3:
       4: #include    "hack.h"
       5: #include    "hack.mfndpos.h"
       6: extern struct monst *makemon();
       7: #include "def.edog.h"
       8: #include "def.mkroom.h"
       9:
      10: struct permonst li_dog =
      11:     { "little dog", 'd',2,18,6,1,6,sizeof(struct edog) };
      12: struct permonst dog =
      13:     { "dog", 'd',4,16,5,1,6,sizeof(struct edog) };
      14: struct permonst la_dog =
      15:     { "large dog", 'd',6,15,4,2,4,sizeof(struct edog) };
      16:
      17:
      18: makedog(){
      19: register struct monst *mtmp = makemon(&li_dog,u.ux,u.uy);
      20:     if(!mtmp) return; /* dogs were genocided */
      21:     initedog(mtmp);
      22: }
      23:
      24: initedog(mtmp) register struct monst *mtmp; {
      25:     mtmp->mtame = mtmp->mpeaceful = 1;
      26:     EDOG(mtmp)->hungrytime = 1000 + moves;
      27:     EDOG(mtmp)->eattime = 0;
      28:     EDOG(mtmp)->droptime = 0;
      29:     EDOG(mtmp)->dropdist = 10000;
      30:     EDOG(mtmp)->apport = 10;
      31:     EDOG(mtmp)->whistletime = 0;
      32: }
      33:
      34: /* attach the monsters that went down (or up) together with @ */
      35: struct monst *mydogs = 0;
      36: struct monst *fallen_down = 0;  /* monsters that fell through a trapdoor */
      37:     /* they will appear on the next level @ goes to, even if he goes up! */
      38:
      39: losedogs(){
      40: register struct monst *mtmp;
      41:     while(mtmp = mydogs){
      42:         mydogs = mtmp->nmon;
      43:         mtmp->nmon = fmon;
      44:         fmon = mtmp;
      45:         mnexto(mtmp);
      46:     }
      47:     while(mtmp = fallen_down){
      48:         fallen_down = mtmp->nmon;
      49:         mtmp->nmon = fmon;
      50:         fmon = mtmp;
      51:         rloc(mtmp);
      52:     }
      53: }
      54:
      55: keepdogs(){
      56: register struct monst *mtmp;
      57:     for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
      58:         if(dist(mtmp->mx,mtmp->my) < 3 && follower(mtmp)
      59:         && !mtmp->msleep && !mtmp->mfroz) {
      60:         relmon(mtmp);
      61:         mtmp->nmon = mydogs;
      62:         mydogs = mtmp;
      63:         unpmon(mtmp);
      64:         keepdogs(); /* we destroyed the link, so use recursion */
      65:         return;     /* (admittedly somewhat primitive) */
      66:     }
      67: }
      68:
      69: fall_down(mtmp) register struct monst *mtmp; {
      70:     relmon(mtmp);
      71:     mtmp->nmon = fallen_down;
      72:     fallen_down = mtmp;
      73:     unpmon(mtmp);
      74:     mtmp->mtame = 0;
      75: }
      76:
      77: /* return quality of food; the lower the better */
      78: #define DOGFOOD 0
      79: #define CADAVER 1
      80: #define ACCFOOD 2
      81: #define MANFOOD 3
      82: #define APPORT  4
      83: #define POISON  5
      84: #define UNDEF   6
      85: dogfood(obj) register struct obj *obj; {
      86:     switch(obj->olet) {
      87:     case FOOD_SYM:
      88:         return(
      89:         (obj->otyp == TRIPE_RATION) ? DOGFOOD :
      90:         (obj->otyp < CARROT) ? ACCFOOD :
      91:         (obj->otyp < CORPSE) ? MANFOOD :
      92:         (poisonous(obj) || obj->age + 50 <= moves ||
      93:             obj->otyp == DEAD_COCKATRICE)
      94:             ? POISON : CADAVER
      95:         );
      96:     default:
      97:         if(!obj->cursed) return(APPORT);
      98:         /* fall into next case */
      99:     case BALL_SYM:
     100:     case CHAIN_SYM:
     101:     case ROCK_SYM:
     102:         return(UNDEF);
     103:     }
     104: }
     105:
     106: /* return 0 (no move), 1 (move) or 2 (dead) */
     107: dog_move(mtmp, after) register struct monst *mtmp; {
     108: register int nx,ny,omx,omy,appr,nearer,j;
     109: int udist,chi,i,whappr;
     110: register struct monst *mtmp2;
     111: register struct permonst *mdat = mtmp->data;
     112: register struct edog *edog = EDOG(mtmp);
     113: struct obj *obj;
     114: struct trap *trap;
     115: xchar cnt,chcnt,nix,niy;
     116: schar dogroom,uroom;
     117: xchar gx,gy,gtyp,otyp;  /* current goal */
     118: coord poss[9];
     119: int info[9];
     120: #define GDIST(x,y) ((x-gx)*(x-gx) + (y-gy)*(y-gy))
     121: #define DDIST(x,y) ((x-omx)*(x-omx) + (y-omy)*(y-omy))
     122:
     123:     if(moves <= edog->eattime) return(0);   /* dog is still eating */
     124:     omx = mtmp->mx;
     125:     omy = mtmp->my;
     126:     whappr = (moves - EDOG(mtmp)->whistletime < 5);
     127:     if(moves > edog->hungrytime + 500 && !mtmp->mconf){
     128:         mtmp->mconf = 1;
     129:         mtmp->mhpmax /= 3;
     130:         if(mtmp->mhp > mtmp->mhpmax)
     131:             mtmp->mhp = mtmp->mhpmax;
     132:         if(cansee(omx,omy))
     133:             pline("%s is confused from hunger.", Monnam(mtmp));
     134:         else    pline("You feel worried about %s.", monnam(mtmp));
     135:     } else
     136:     if(moves > edog->hungrytime + 750 || mtmp->mhp < 1){
     137:         if(cansee(omx,omy))
     138:             pline("%s dies from hunger.", Monnam(mtmp));
     139:         else
     140:         pline("You have a sad feeling for a moment, then it passes.");
     141:         mondied(mtmp);
     142:         return(2);
     143:     }
     144:     dogroom = inroom(omx,omy);
     145:     uroom = inroom(u.ux,u.uy);
     146:     udist = dist(omx,omy);
     147:
     148:     /* maybe we tamed him while being swallowed --jgm */
     149:     if(!udist) return(0);
     150:
     151:     /* if we are carrying sth then we drop it (perhaps near @) */
     152:     /* Note: if apport == 1 then our behaviour is independent of udist */
     153:     if(mtmp->minvent){
     154:         if(!rn2(udist) || !rn2((int) edog->apport))
     155:         if(rn2(10) < edog->apport){
     156:             relobj(mtmp, (int) mtmp->minvis);
     157:             if(edog->apport > 1) edog->apport--;
     158:             edog->dropdist = udist;     /* hpscdi!jon */
     159:             edog->droptime = moves;
     160:         }
     161:     } else {
     162:         if(obj = o_at(omx,omy)) if(!index("0_", obj->olet)){
     163:             if((otyp = dogfood(obj)) <= CADAVER){
     164:             nix = omx;
     165:             niy = omy;
     166:             goto eatobj;
     167:             }
     168:             if(obj->owt < 10*mtmp->data->mlevel)
     169:             if(rn2(20) < edog->apport+3)
     170:             if(rn2(udist) || !rn2((int) edog->apport)){
     171:             freeobj(obj);
     172:             unpobj(obj);
     173:             /* if(levl[omx][omy].scrsym == obj->olet)
     174: 				newsym(omx,omy); */
     175:             mpickobj(mtmp,obj);
     176:             }
     177:         }
     178:     }
     179:
     180:     /* first we look for food */
     181:     gtyp = UNDEF;   /* no goal as yet */
     182: #ifdef LINT
     183:     gx = gy = 0;    /* suppress 'used before set' message */
     184: #endif LINT
     185:     for(obj = fobj; obj; obj = obj->nobj) {
     186:         otyp = dogfood(obj);
     187:         if(otyp > gtyp || otyp == UNDEF) continue;
     188:         if(inroom(obj->ox,obj->oy) != dogroom) continue;
     189:         if(otyp < MANFOOD &&
     190:          (dogroom >= 0 || DDIST(obj->ox,obj->oy) < 10)) {
     191:             if(otyp < gtyp || (otyp == gtyp &&
     192:                 DDIST(obj->ox,obj->oy) < DDIST(gx,gy))){
     193:                 gx = obj->ox;
     194:                 gy = obj->oy;
     195:                 gtyp = otyp;
     196:             }
     197:         } else
     198:         if(gtyp == UNDEF && dogroom >= 0 &&
     199:            uroom == dogroom &&
     200:            !mtmp->minvent && edog->apport > rn2(8)){
     201:             gx = obj->ox;
     202:             gy = obj->oy;
     203:             gtyp = APPORT;
     204:         }
     205:     }
     206:     if(gtyp == UNDEF ||
     207:       (gtyp != DOGFOOD && gtyp != APPORT && moves < edog->hungrytime)){
     208:         if(dogroom < 0 || dogroom == uroom){
     209:             gx = u.ux;
     210:             gy = u.uy;
     211: #ifndef QUEST
     212:         } else {
     213:             int tmp = rooms[dogroom].fdoor;
     214:                 cnt = rooms[dogroom].doorct;
     215:
     216:             gx = gy = FAR;  /* random, far away */
     217:             while(cnt--){
     218:                 if(dist(gx,gy) >
     219:                 dist(doors[tmp].x, doors[tmp].y)){
     220:                     gx = doors[tmp].x;
     221:                     gy = doors[tmp].y;
     222:                 }
     223:                 tmp++;
     224:             }
     225:             /* here gx == FAR e.g. when dog is in a vault */
     226:             if(gx == FAR || (gx == omx && gy == omy)){
     227:                 gx = u.ux;
     228:                 gy = u.uy;
     229:             }
     230: #endif QUEST
     231:         }
     232:         appr = (udist >= 9) ? 1 : (mtmp->mflee) ? -1 : 0;
     233:         if(after && udist <= 4 && gx == u.ux && gy == u.uy)
     234:             return(0);
     235:         if(udist > 1){
     236:             if(!IS_ROOM(levl[u.ux][u.uy].typ) || !rn2(4) ||
     237:                whappr ||
     238:                (mtmp->minvent && rn2((int) edog->apport)))
     239:                 appr = 1;
     240:         }
     241:         /* if you have dog food he'll follow you more closely */
     242:         if(appr == 0){
     243:             obj = invent;
     244:             while(obj){
     245:                 if(obj->otyp == TRIPE_RATION){
     246:                     appr = 1;
     247:                     break;
     248:                 }
     249:                 obj = obj->nobj;
     250:             }
     251:         }
     252:     } else  appr = 1;   /* gtyp != UNDEF */
     253:     if(mtmp->mconf) appr = 0;
     254:
     255:     if(gx == u.ux && gy == u.uy && (dogroom != uroom || dogroom < 0)){
     256:     extern coord *gettrack();
     257:     register coord *cp;
     258:         cp = gettrack(omx,omy);
     259:         if(cp){
     260:             gx = cp->x;
     261:             gy = cp->y;
     262:         }
     263:     }
     264:
     265:     nix = omx;
     266:     niy = omy;
     267:     cnt = mfndpos(mtmp,poss,info,ALLOW_M | ALLOW_TRAPS);
     268:     chcnt = 0;
     269:     chi = -1;
     270:     for(i=0; i<cnt; i++){
     271:         nx = poss[i].x;
     272:         ny = poss[i].y;
     273:         if(info[i] & ALLOW_M){
     274:             mtmp2 = m_at(nx,ny);
     275:             if(mtmp2->data->mlevel >= mdat->mlevel+2 ||
     276:               mtmp2->data->mlet == 'c')
     277:                 continue;
     278:             if(after) return(0); /* hit only once each move */
     279:
     280:             if(hitmm(mtmp, mtmp2) == 1 && rn2(4) &&
     281:               mtmp2->mlstmv != moves &&
     282:               hitmm(mtmp2,mtmp) == 2) return(2);
     283:             return(0);
     284:         }
     285:
     286:         /* dog avoids traps */
     287:         /* but perhaps we have to pass a trap in order to follow @ */
     288:         if((info[i] & ALLOW_TRAPS) && (trap = t_at(nx,ny))){
     289:             if(!trap->tseen && rn2(40)) continue;
     290:             if(rn2(10)) continue;
     291:         }
     292:
     293:         /* dog eschewes cursed objects */
     294:         /* but likes dog food */
     295:         obj = fobj;
     296:         while(obj){
     297:             if(obj->ox != nx || obj->oy != ny)
     298:             goto nextobj;
     299:             if(obj->cursed) goto nxti;
     300:             if(obj->olet == FOOD_SYM &&
     301:             (otyp = dogfood(obj)) < MANFOOD &&
     302:             (otyp < ACCFOOD || edog->hungrytime <= moves)){
     303:             /* Note: our dog likes the food so much that he
     304: 			might eat it even when it conceals a cursed object */
     305:             nix = nx;
     306:             niy = ny;
     307:             chi = i;
     308:              eatobj:
     309:             edog->eattime =
     310:                 moves + obj->quan * objects[obj->otyp].oc_delay;
     311:             if(edog->hungrytime < moves)
     312:                 edog->hungrytime = moves;
     313:             edog->hungrytime +=
     314:                 5*obj->quan * objects[obj->otyp].nutrition;
     315:             mtmp->mconf = 0;
     316:             if(cansee(nix,niy))
     317:                 pline("%s ate %s.", Monnam(mtmp), doname(obj));
     318:             /* perhaps this was a reward */
     319:             if(otyp != CADAVER)
     320:             edog->apport += 200/(edog->dropdist+moves-edog->droptime);
     321:             delobj(obj);
     322:             goto newdogpos;
     323:             }
     324:         nextobj:
     325:             obj = obj->nobj;
     326:         }
     327:
     328:         for(j=0; j<MTSZ && j<cnt-1; j++)
     329:             if(nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y)
     330:                 if(rn2(4*(cnt-j))) goto nxti;
     331:
     332: /* Some stupid C compilers cannot compute the whole expression at once. */
     333:         nearer = GDIST(nx,ny);
     334:         nearer -= GDIST(nix,niy);
     335:         nearer *= appr;
     336:         if((nearer == 0 && !rn2(++chcnt)) || nearer<0 ||
     337:             (nearer > 0 && !whappr &&
     338:                 ((omx == nix && omy == niy && !rn2(3))
     339:                 || !rn2(12))
     340:             )){
     341:             nix = nx;
     342:             niy = ny;
     343:             if(nearer < 0) chcnt = 0;
     344:             chi = i;
     345:         }
     346:     nxti:   ;
     347:     }
     348: newdogpos:
     349:     if(nix != omx || niy != omy){
     350:         if(info[chi] & ALLOW_U){
     351:             (void) hitu(mtmp, d(mdat->damn, mdat->damd)+1);
     352:             return(0);
     353:         }
     354:         mtmp->mx = nix;
     355:         mtmp->my = niy;
     356:         for(j=MTSZ-1; j>0; j--) mtmp->mtrack[j] = mtmp->mtrack[j-1];
     357:         mtmp->mtrack[0].x = omx;
     358:         mtmp->mtrack[0].y = omy;
     359:     }
     360:     if(mintrap(mtmp) == 2)  /* he died */
     361:         return(2);
     362:     pmon(mtmp);
     363:     return(1);
     364: }
     365:
     366: /* return roomnumber or -1 */
     367: inroom(x,y) xchar x,y; {
     368: #ifndef QUEST
     369:     register struct mkroom *croom = &rooms[0];
     370:     while(croom->hx >= 0){
     371:         if(croom->hx >= x-1 && croom->lx <= x+1 &&
     372:            croom->hy >= y-1 && croom->ly <= y+1)
     373:             return(croom - rooms);
     374:         croom++;
     375:     }
     376: #endif QUEST
     377:     return(-1); /* not in room or on door */
     378: }
     379:
     380: tamedog(mtmp, obj)
     381: register struct monst *mtmp;
     382: register struct obj *obj;
     383: {
     384:     register struct monst *mtmp2;
     385:
     386:     if(flags.moonphase == FULL_MOON && night() && rn2(6))
     387:         return(0);
     388:
     389:     /* If we cannot tame him, at least he's no longer afraid. */
     390:     mtmp->mflee = 0;
     391:     mtmp->mfleetim = 0;
     392:     if(mtmp->mtame || mtmp->mfroz ||
     393: #ifndef NOWORM
     394:         mtmp->wormno ||
     395: #endif NOWORM
     396:         mtmp->isshk || mtmp->isgd || index(" &@12", mtmp->data->mlet))
     397:         return(0); /* no tame long worms? */
     398:     if(obj) {
     399:         if(dogfood(obj) >= MANFOOD) return(0);
     400:         if(cansee(mtmp->mx,mtmp->my)){
     401:             pline("%s devours the %s.", Monnam(mtmp),
     402:                 objects[obj->otyp].oc_name);
     403:         }
     404:         obfree(obj, (struct obj *) 0);
     405:     }
     406:     mtmp2 = newmonst(sizeof(struct edog) + mtmp->mnamelth);
     407:     *mtmp2 = *mtmp;
     408:     mtmp2->mxlth = sizeof(struct edog);
     409:     if(mtmp->mnamelth) (void) strcpy(NAME(mtmp2), NAME(mtmp));
     410:     initedog(mtmp2);
     411:     replmon(mtmp,mtmp2);
     412:     return(1);
     413: }

#### Defined functions

dog_move defined in line 107; used 1 times

- in /usr/src/games/hack/hack.mon.c line 271

dogfood defined in line 85; used 4 times

- in line 163, 186, 301, 399

fall_down defined in line 69; used 2 times

- in /usr/src/games/hack/hack.trap.c line 213
- in /usr/src/games/hack/hack.wizard.c line 43

initedog defined in line 24; used 2 times

- in line 21, 410

inroom defined in line 367; used 20 times

- in line 144-145(2), 188
- in /usr/src/games/hack/hack.apply.c line 309
- in /usr/src/games/hack/hack.mon.c line 335-336(2)
- in /usr/src/games/hack/hack.read.c line 226-228(2)
- in /usr/src/games/hack/hack.shk.c line 131, 187, 317, 592, 766, 824, 832
- in /usr/src/games/hack/hack.unix.c line 355
- in /usr/src/games/hack/hack.vault.c line 81, 190
- in /usr/src/games/hack/hack.wizard.c line 92(2)

keepdogs defined in line 55; used 3 times

- in line 64
- in /usr/src/games/hack/hack.do.c line 150
- in /usr/src/games/hack/hack.end.c line 126

losedogs defined in line 39; used 1 times

- in /usr/src/games/hack/hack.do.c line 230

makedog defined in line 18; used 1 times

- in /usr/src/games/hack/hack.main.c line 269

tamedog defined in line 380; used 2 times

- in /usr/src/games/hack/hack.do.c line 376
- in /usr/src/games/hack/hack.read.c line 177

#### Defined variables

dog defined in line 12; used 2 times

- in /usr/src/games/hack/hack.fight.c line 56-57(2)

fallen_down defined in line 36; used 13 times

- in line 47-48(2), 71-72(2)
- in /usr/src/games/hack/hack.dog.c line 47-48(2), 71-72(2)
- in /usr/src/games/hack/hack.main.c line 255
- in /usr/src/games/hack/hack.save.c line 49, 106
- in /usr/src/games/hack/hack.shk.c line 108, 501

la_dog defined in line 14; used 1 times

- in /usr/src/games/hack/hack.fight.c line 57

li_dog defined in line 10; used 2 times

- in line 19
- in /usr/src/games/hack/hack.fight.c line 56

mydogs defined in line 35; used 4 times

- in line 41-42(2), 61-62(2)

#### Defined macros

ACCFOOD defined in line 80; used 2 times

- in line 90, 302

APPORT defined in line 82; used 3 times

- in line 97, 203-207(2)

CADAVER defined in line 79; used 3 times

- in line 94, 163, 319

DDIST defined in line 121; used 3 times

- in line 190-192(3)

DOGFOOD defined in line 78; used 2 times

- in line 89, 207

GDIST defined in line 120; used 2 times

- in line 333-334(2)

MANFOOD defined in line 81; used 4 times

- in line 91, 189, 301, 399

POISON defined in line 83; used 1 times

- in line 94

UNDEF defined in line 84; used 5 times

- in line 102, 181, 187, 198, 206

Last modified: 1985-10-01 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1276 |