Annotation of 43BSDTahoe/games/hack/hack.dog.c, revision 1.1.1.1

1.1       root        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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.