]> granicus.if.org Git - nethack/commitdiff
pet fodder
authornethack.rankin <nethack.rankin>
Fri, 13 Sep 2002 05:31:54 +0000 (05:31 +0000)
committernethack.rankin <nethack.rankin>
Fri, 13 Sep 2002 05:31:54 +0000 (05:31 +0000)
     Allow starving pets to consume items they wouldn't ordinarily
eat.  Carnivores will eat fruits and vegetables--such as they are--
and herbivores will eat assorted rations.  Even though eating such
rations doesn't violate vegetarian conduct for the character, horses
would never eat them.

     This change should allow players to keep mundane steeds alive
much longer.  The new behavior doesn't kick in until the pet has
been classified as starving though; it doesn't affect ones who are
merely hungry.

     This also gives the reason why a starving pet has died instead
of just saying "<pet> dies" whenever it starved with hit points left.

doc/fixes34.1
src/dog.c
src/dogmove.c

index 04d9ea10b33f9d14d2e421453c707f8a077554c6..0259499ec7d3d56cd88e379613feee99be850915 100644 (file)
@@ -242,6 +242,8 @@ make sure corpses and statues which remember monster attributes don't keep
        ones that were conferred by no longer worn items (mainly speed boots)
 elevate the trouble priority of any cursed item which is preventing removal
        of a ring of levitation
+starving pets will eat more aggressively
+when a pet starves to death, say so instead of just "Fido dies."
 
 
 Platform- and/or Interface-Specific Fixes
index 29a749ab06cd0df53c9158217ff9db5ffc78dab5..e482cdff8493d8f3b62c5ae16eef35b4faddce52 100644 (file)
--- a/src/dog.c
+++ b/src/dog.c
@@ -596,6 +596,7 @@ register struct obj *obj;
        boolean carni = carnivorous(mon->data);
        boolean herbi = herbivorous(mon->data);
        struct permonst *fptr = &mons[obj->corpsenm];
+       boolean starving;
 
        if (is_quest_artifact(obj) || obj_resists(obj, 0, 95))
            return (obj->cursed ? TABU : APPORT);
@@ -609,12 +610,17 @@ register struct obj *obj;
 
            /* Ghouls only eat old corpses... yum! */
            if (mon->data == &mons[PM_GHOUL])
-               return (obj->otyp == CORPSE && obj->age+50 <= monstermoves) ?
-                               DOGFOOD : TABU;
+               return (obj->otyp == CORPSE &&
+                       peek_at_iced_corpse_age(obj) + 50L <= monstermoves) ?
+                               DOGFOOD : TABU;
 
            if (!carni && !herbi)
                    return (obj->cursed ? UNDEF : APPORT);
 
+           /* a starving pet will eat almost anything */
+           starving = (mon->mtame && !mon->isminion &&
+                       EDOG(mon)->mhpmax_penalty);
+
            switch (obj->otyp) {
                case TRIPE_RATION:
                case MEATBALL:
@@ -627,7 +633,7 @@ register struct obj *obj;
                        return POISON;
                    return (carni ? CADAVER : MANFOOD);
                case CORPSE:
-                  if ((peek_at_iced_corpse_age(obj)+50 <= monstermoves
+                  if ((peek_at_iced_corpse_age(obj) + 50L <= monstermoves
                                            && obj->corpsenm != PM_LIZARD
                                            && obj->corpsenm != PM_LICHEN
                                            && mon->data->mlet != S_FUNGUS) ||
@@ -640,24 +646,25 @@ register struct obj *obj;
                    else return (carni ? CADAVER : MANFOOD);
                case CLOVE_OF_GARLIC:
                    return (is_undead(mon->data) ? TABU :
-                           (herbi ? ACCFOOD : MANFOOD));
+                           ((herbi || starving) ? ACCFOOD : MANFOOD));
                case TIN:
                    return (metallivorous(mon->data) ? ACCFOOD : MANFOOD);
                case APPLE:
                case CARROT:
-                   return (herbi ? DOGFOOD : MANFOOD);
+                   return (herbi ? DOGFOOD : starving ? ACCFOOD : MANFOOD);
                case BANANA:
                    return ((mon->data->mlet == S_YETI) ? DOGFOOD :
-                           (herbi ? ACCFOOD : MANFOOD));
+                           ((herbi || starving) ? ACCFOOD : MANFOOD));
                default:
+                   if (starving) return ACCFOOD;
                    return (obj->otyp > SLIME_MOLD ?
                            (carni ? ACCFOOD : MANFOOD) :
                            (herbi ? ACCFOOD : MANFOOD));
            }
        default:
            if (obj->otyp == AMULET_OF_STRANGULATION ||
-                       obj->otyp == RIN_SLOW_DIGESTION)
-               return (TABU);
+                       obj->otyp == RIN_SLOW_DIGESTION)
+               return TABU;
            if (hates_silver(mon->data) &&
                objects[obj->otyp].oc_material == SILVER)
                return(TABU);
index b6d688fe06ac9bddab2e465048f81c3d7eb12b43..2670da118cb70e544353cb03fc195f6a2421bffd 100644 (file)
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)dogmove.c  3.4     2002/04/06      */
+/*     SCCS Id: @(#)dogmove.c  3.4     2002/09/10      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -232,7 +232,7 @@ register struct edog *edog;
                    You_feel("worried about %s.", y_monnam(mtmp));
                stop_occupation();
            } else if (monstermoves > edog->hungrytime + 750 || mtmp->mhp < 1) {
          dog_died:
+ dog_died:
                if (mtmp->mleashed
 #ifdef STEED
                    && mtmp != u.usteed
@@ -240,8 +240,7 @@ register struct edog *edog;
                    )
                    Your("leash goes slack.");
                else if (cansee(mtmp->mx, mtmp->my))
-                   pline("%s dies%s.", Monnam(mtmp),
-                           (mtmp->mhp >= 1) ? "" : " from hunger");
+                   pline("%s starves.", Monnam(mtmp));
                else
                    You_feel("%s for a moment.",
                        Hallucination ? "bummed" : "sad");
@@ -290,7 +289,11 @@ int udist;
                        && obj->otyp != SCR_MAIL
 #endif
                                                                        ){
-               if (dogfood(mtmp, obj) <= CADAVER)
+               int edible = dogfood(mtmp, obj);
+
+               if (edible <= CADAVER ||
+                       /* starving pet is more aggressive about eating */
+                       (edog->mhpmax_penalty && edible == ACCFOOD))
                    return dog_eat(mtmp, obj, omx, omy, FALSE);
 
                if(can_carry(mtmp, obj) && !obj->cursed &&
@@ -327,12 +330,11 @@ struct edog *edog;
 int after, udist, whappr;
 {
        register int omx, omy;
-       boolean in_masters_sight;
+       boolean in_masters_sight, dog_has_minvent;
        register struct obj *obj;
        xchar otyp;
        int appr;
 
-
 #ifdef STEED
        /* Steeds don't move on their own will */
        if (mtmp == u.usteed)
@@ -343,6 +345,7 @@ int after, udist, whappr;
        omy = mtmp->my;
 
        in_masters_sight = couldsee(omx, omy);
+       dog_has_minvent = (DROPPABLES(mtmp) != 0);
 
        if (!edog || mtmp->mleashed) {  /* he's not going anywhere... */
            gtyp = APPORT;
@@ -357,7 +360,7 @@ int after, udist, whappr;
            gtyp = UNDEF;       /* no goal as yet */
            gx = gy = 0;        /* suppress 'used before set' message */
 
-           if ((min_x = omx - SQSRCHRADIUS) < 0) min_x = 0;
+           if ((min_x = omx - SQSRCHRADIUS) < 1) min_x = 1;
            if ((max_x = omx + SQSRCHRADIUS) >= COLNO) max_x = COLNO - 1;
            if ((min_y = omy - SQSRCHRADIUS) < 0) min_y = 0;
            if ((max_y = omy + SQSRCHRADIUS) >= ROWNO) max_y = ROWNO - 1;
@@ -368,9 +371,12 @@ int after, udist, whappr;
                ny = obj->oy;
                if (nx >= min_x && nx <= max_x && ny >= min_y && ny <= max_y) {
                    otyp = dogfood(mtmp, obj);
+                   /* skip inferior goals */
                    if (otyp > gtyp || otyp == UNDEF)
                        continue;
-                   if (cursed_object_at(nx, ny))
+                   /* avoid cursed items unless starving */
+                   if (cursed_object_at(nx, ny) &&
+                           !(edog->mhpmax_penalty && otyp < MANFOOD))
                        continue;
                    if (otyp < MANFOOD &&
                            can_reach_food(mtmp, mtmp->mx, mtmp->my, nx, ny)) {
@@ -380,7 +386,7 @@ int after, udist, whappr;
                            gtyp = otyp;
                        }
                    } else if(gtyp == UNDEF && in_masters_sight &&
-                             !mtmp->minvent &&
+                             !dog_has_minvent &&
                              (!levl[omx][omy].lit || levl[u.ux][u.uy].lit) &&
                              (otyp == MANFOOD || m_cansee(mtmp, nx, ny)) &&
                              edog->apport > rn2(8) &&
@@ -404,7 +410,7 @@ int after, udist, whappr;
                if (udist > 1) {
                        if (!IS_ROOM(levl[u.ux][u.uy].typ) || !rn2(4) ||
                           whappr ||
-                          (mtmp->minvent && rn2(edog->apport)))
+                          (dog_has_minvent && rn2(edog->apport)))
                                appr = 1;
                }
                /* if you have dog food it'll follow you more closely */