home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / HACKSRC.ZIP / DOG.C < prev    next >
C/C++ Source or Header  |  1985-10-16  |  11KB  |  418 lines

  1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  2. /* dog.c - version 1.0.3 */
  3.  
  4. #include    "hack.h"
  5. #include    "mfndpos.h"
  6. extern struct monst *makemon();
  7. #include "edog.h"
  8. #include "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. #ifdef REGBUG
  109. int nx,ny,omx,omy,appr,nearer,j;
  110. #else
  111. register int nx,ny,omx,omy,appr,nearer,j;
  112. #endif REGBUG
  113. int udist,chi,i,whappr;
  114. register struct monst *mtmp2;
  115. register struct permonst *mdat = mtmp->data;
  116. register struct edog *edog = EDOG(mtmp);
  117. struct obj *obj;
  118. struct trap *trap;
  119. xchar cnt,chcnt,nix,niy;
  120. schar dogroom,uroom;
  121. xchar gx,gy,gtyp,otyp;    /* current goal */
  122. coord poss[9];
  123. int info[9];
  124. #define GDIST(x,y) ((x-gx)*(x-gx) + (y-gy)*(y-gy))
  125. #define DDIST(x,y) ((x-omx)*(x-omx) + (y-omy)*(y-omy))
  126.  
  127.     if(moves <= edog->eattime) return(0);    /* dog is still eating */
  128.     omx = mtmp->mx;
  129.     omy = mtmp->my;
  130.     whappr = (moves - EDOG(mtmp)->whistletime < 5);
  131.     if(moves > edog->hungrytime + 500 && !mtmp->mconf){
  132.         mtmp->mconf = 1;
  133.         mtmp->mhpmax /= 3;
  134.         if(mtmp->mhp > mtmp->mhpmax)
  135.             mtmp->mhp = mtmp->mhpmax;
  136.         if(cansee(omx,omy))
  137.             pline("%s is confused from hunger.", Monnam(mtmp));
  138.         else    pline("You feel worried about %s.", monnam(mtmp));
  139.     } else
  140.     if(moves > edog->hungrytime + 750 || mtmp->mhp < 1){
  141.         if(cansee(omx,omy))
  142.             pline("%s dies from hunger.", Monnam(mtmp));
  143.         else
  144.         pline("You have a sad feeling for a moment, then it passes.");
  145.         mondied(mtmp);
  146.         return(2);
  147.     }
  148.     dogroom = inroom(omx,omy);
  149.     uroom = inroom(u.ux,u.uy);
  150.     udist = dist(omx,omy);
  151.  
  152.     /* maybe we tamed him while being swallowed --jgm */
  153.     if(!udist) return(0);
  154.  
  155.     /* if we are carrying sth then we drop it (perhaps near @) */
  156.     /* Note: if apport == 1 then our behaviour is independent of udist */
  157.     if(mtmp->minvent){
  158.         if(!rn2(udist) || !rn2((int) edog->apport))
  159.         if(rn2(10) < edog->apport){
  160.             relobj(mtmp, (int) mtmp->minvis);
  161.             if(edog->apport > 1) edog->apport--;
  162.             edog->dropdist = udist;        /* hpscdi!jon */
  163.             edog->droptime = moves;
  164.         }
  165.     } else {
  166.         if(obj = o_at(omx,omy)) if(!index("0_", obj->olet)){
  167.             if((otyp = dogfood(obj)) <= CADAVER){
  168.             nix = omx;
  169.             niy = omy;
  170.             goto eatobj;
  171.             }
  172.             if(obj->owt < 10*mtmp->data->mlevel)
  173.             if(rn2(20) < edog->apport+3)
  174.             if(rn2(udist) || !rn2((int) edog->apport)){
  175.             freeobj(obj);
  176.             unpobj(obj);
  177.             /* if(levl[omx][omy].scrsym == obj->olet)
  178.                 newsym(omx,omy); */
  179.             mpickobj(mtmp,obj);
  180.             }
  181.         }
  182.     }
  183.  
  184.     /* first we look for food */
  185.     gtyp = UNDEF;    /* no goal as yet */
  186. #ifdef LINT
  187.     gx = gy = 0;    /* suppress 'used before set' message */
  188. #endif LINT
  189.     for(obj = fobj; obj; obj = obj->nobj) {
  190.         otyp = dogfood(obj);
  191.         if(otyp > gtyp || otyp == UNDEF) continue;
  192.         if(inroom(obj->ox,obj->oy) != dogroom) continue;
  193.         if(otyp < MANFOOD &&
  194.          (dogroom >= 0 || DDIST(obj->ox,obj->oy) < 10)) {
  195.             if(otyp < gtyp || (otyp == gtyp &&
  196.                 DDIST(obj->ox,obj->oy) < DDIST(gx,gy))){
  197.                 gx = obj->ox;
  198.                 gy = obj->oy;
  199.                 gtyp = otyp;
  200.             }
  201.         } else
  202.         if(gtyp == UNDEF && dogroom >= 0 &&
  203.            uroom == dogroom &&
  204.            !mtmp->minvent && edog->apport > rn2(8)){
  205.             gx = obj->ox;
  206.             gy = obj->oy;
  207.             gtyp = APPORT;
  208.         }
  209.     }
  210.     if(gtyp == UNDEF ||
  211.       (gtyp != DOGFOOD && gtyp != APPORT && moves < edog->hungrytime)){
  212.         if(dogroom < 0 || dogroom == uroom){
  213.             gx = u.ux;
  214.             gy = u.uy;
  215. #ifndef QUEST
  216.         } else {
  217.             int tmp = rooms[dogroom].fdoor;
  218.                 cnt = rooms[dogroom].doorct;
  219.  
  220.             gx = gy = FAR;    /* random, far away */
  221.             while(cnt--){
  222.                 if(dist(gx,gy) >
  223.                 dist(doors[tmp].x, doors[tmp].y)){
  224.                     gx = doors[tmp].x;
  225.                     gy = doors[tmp].y;
  226.                 }
  227.                 tmp++;
  228.             }
  229.             /* here gx == FAR e.g. when dog is in a vault */
  230.             if(gx == FAR || (gx == omx && gy == omy)){
  231.                 gx = u.ux;
  232.                 gy = u.uy;
  233.             }
  234. #endif QUEST
  235.         }
  236.         appr = (udist >= 9) ? 1 : (mtmp->mflee) ? -1 : 0;
  237.         if(after && udist <= 4 && gx == u.ux && gy == u.uy)
  238.             return(0);
  239.         if(udist > 1){
  240.             if(!IS_ROOM(levl[u.ux][u.uy].typ) || !rn2(4) ||
  241.                whappr ||
  242.                (mtmp->minvent && rn2((int) edog->apport)))
  243.                 appr = 1;
  244.         }
  245.         /* if you have dog food he'll follow you more closely */
  246.         if(appr == 0){
  247.             obj = invent;
  248.             while(obj){
  249.                 if(obj->otyp == TRIPE_RATION){
  250.                     appr = 1;
  251.                     break;
  252.                 }
  253.                 obj = obj->nobj;
  254.             }
  255.         }
  256.     } else    appr = 1;    /* gtyp != UNDEF */
  257.     if(mtmp->mconf) appr = 0;
  258.  
  259.     if(gx == u.ux && gy == u.uy && (dogroom != uroom || dogroom < 0)){
  260.     extern coord *gettrack();
  261.     register coord *cp;
  262.         cp = gettrack(omx,omy);
  263.         if(cp){
  264.             gx = cp->x;
  265.             gy = cp->y;
  266.         }
  267.     }
  268.  
  269.     nix = omx;
  270.     niy = omy;
  271.     cnt = mfndpos(mtmp,poss,info,ALLOW_M | ALLOW_TRAPS);
  272.     chcnt = 0;
  273.     chi = -1;
  274.     for(i=0; i<cnt; i++){
  275.         nx = poss[i].x;
  276.         ny = poss[i].y;
  277.         if(info[i] & ALLOW_M){
  278.             mtmp2 = m_at(nx,ny);
  279.             if(mtmp2->data->mlevel >= mdat->mlevel+2 ||
  280.               mtmp2->data->mlet == 'c')
  281.                 continue;
  282.             if(after) return(0); /* hit only once each move */
  283.  
  284.             if(hitmm(mtmp, mtmp2) == 1 && rn2(4) &&
  285.               mtmp2->mlstmv != moves &&
  286.               hitmm(mtmp2,mtmp) == 2) return(2);
  287.             return(0);
  288.         }
  289.  
  290.         /* dog avoids traps */
  291.         /* but perhaps we have to pass a trap in order to follow @ */
  292.         if((info[i] & ALLOW_TRAPS) && (trap = t_at(nx,ny))){
  293.             if(!trap->tseen && rn2(40)) continue;
  294.             if(rn2(10)) continue;
  295.         }
  296.  
  297.         /* dog eschewes cursed objects */
  298.         /* but likes dog food */
  299.         obj = fobj;
  300.         while(obj){
  301.             if(obj->ox != nx || obj->oy != ny)
  302.             goto nextobj;
  303.             if(obj->cursed) goto nxti;
  304.             if(obj->olet == FOOD_SYM &&
  305.             (otyp = dogfood(obj)) < MANFOOD &&
  306.             (otyp < ACCFOOD || edog->hungrytime <= moves)){
  307.             /* Note: our dog likes the food so much that he
  308.             might eat it even when it conceals a cursed object */
  309.             nix = nx;
  310.             niy = ny;
  311.             chi = i;
  312.              eatobj:
  313.             edog->eattime =
  314.                 moves + obj->quan * objects[obj->otyp].oc_delay;
  315.             if(edog->hungrytime < moves)
  316.                 edog->hungrytime = moves;
  317.             edog->hungrytime +=
  318.                 5*obj->quan * objects[obj->otyp].nutrition;
  319.             mtmp->mconf = 0;
  320.             if(cansee(nix,niy))
  321.                 pline("%s ate %s.", Monnam(mtmp), doname(obj));
  322.             /* perhaps this was a reward */
  323.             if(otyp != CADAVER)
  324.             edog->apport += 200/(edog->dropdist+moves-edog->droptime);
  325.             delobj(obj);
  326.             goto newdogpos;
  327.             }
  328.         nextobj:
  329.             obj = obj->nobj;
  330.         }
  331.  
  332.         for(j=0; j<MTSZ && j<cnt-1; j++)
  333.             if(nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y)
  334.                 if(rn2(4*(cnt-j))) goto nxti;
  335.  
  336. /* Some stupid C compilers cannot compute the whole expression at once. */
  337.         nearer = GDIST(nx,ny);
  338.         nearer -= GDIST(nix,niy);
  339.         nearer *= appr;
  340.         if((nearer == 0 && !rn2(++chcnt)) || nearer<0 ||
  341.             (nearer > 0 && !whappr &&
  342.                 ((omx == nix && omy == niy && !rn2(3))
  343.                 || !rn2(12))
  344.             )){
  345.             nix = nx;
  346.             niy = ny;
  347.             if(nearer < 0) chcnt = 0;
  348.             chi = i;
  349.         }
  350.     nxti:    ;
  351.     }
  352. newdogpos:
  353.     if(nix != omx || niy != omy){
  354.         if(info[chi] & ALLOW_U){
  355.             (void) hitu(mtmp, d(mdat->damn, mdat->damd)+1);
  356.             return(0);
  357.         }
  358.         mtmp->mx = nix;
  359.         mtmp->my = niy;
  360.         for(j=MTSZ-1; j>0; j--) mtmp->mtrack[j] = mtmp->mtrack[j-1];
  361.         mtmp->mtrack[0].x = omx;
  362.         mtmp->mtrack[0].y = omy;
  363.     }
  364.     if(mintrap(mtmp) == 2)    /* he died */
  365.         return(2);
  366.     pmon(mtmp);
  367.     return(1);
  368. }
  369.  
  370. /* return roomnumber or -1 */
  371. inroom(x,y) xchar x,y; {
  372. #ifndef QUEST
  373.     register struct mkroom *croom = &rooms[0];
  374.     while(croom->hx >= 0){
  375.         if(croom->hx >= x-1 && croom->lx <= x+1 &&
  376.            croom->hy >= y-1 && croom->ly <= y+1)
  377.             return(croom - rooms);
  378.         croom++;
  379.     }
  380. #endif QUEST
  381.     return(-1);    /* not in room or on door */
  382. }
  383.  
  384. tamedog(mtmp, obj)
  385. register struct monst *mtmp;
  386. register struct obj *obj;
  387. {
  388.     register struct monst *mtmp2;
  389.  
  390.     if(flags.moonphase == FULL_MOON && night() && rn2(6))
  391.         return(0);
  392.  
  393.     /* If we cannot tame him, at least he's no longer afraid. */
  394.     mtmp->mflee = 0;
  395.     mtmp->mfleetim = 0;
  396.     if(mtmp->mtame || mtmp->mfroz ||
  397. #ifndef NOWORM
  398.         mtmp->wormno ||
  399. #endif NOWORM
  400.         mtmp->isshk || mtmp->isgd || index(" &@12", mtmp->data->mlet))
  401.         return(0); /* no tame long worms? */
  402.     if(obj) {
  403.         if(dogfood(obj) >= MANFOOD) return(0);
  404.         if(cansee(mtmp->mx,mtmp->my)){
  405.             pline("%s devours the %s.", Monnam(mtmp),
  406.                 objects[obj->otyp].oc_name);
  407.         }
  408.         obfree(obj, (struct obj *) 0);
  409.     }
  410.     mtmp2 = newmonst(sizeof(struct edog) + mtmp->mnamelth);
  411.     *mtmp2 = *mtmp;
  412.     mtmp2->mxlth = sizeof(struct edog);
  413.     if(mtmp->mnamelth) (void) strcpy(NAME(mtmp2), NAME(mtmp));
  414.     initedog(mtmp2);
  415.     replmon(mtmp,mtmp2);
  416.     return(1);
  417. }
  418.