From 6f63f81b86baca4060e3bb0bbb1862b971a061e7 Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Fri, 13 Sep 2002 05:31:54 +0000 Subject: [PATCH] pet fodder 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 " dies" whenever it starved with hit points left. --- doc/fixes34.1 | 2 ++ src/dog.c | 23 +++++++++++++++-------- src/dogmove.c | 28 +++++++++++++++++----------- 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/doc/fixes34.1 b/doc/fixes34.1 index 04d9ea10b..0259499ec 100644 --- a/doc/fixes34.1 +++ b/doc/fixes34.1 @@ -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 diff --git a/src/dog.c b/src/dog.c index 29a749ab0..e482cdff8 100644 --- 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); diff --git a/src/dogmove.c b/src/dogmove.c index b6d688fe0..2670da118 100644 --- a/src/dogmove.c +++ b/src/dogmove.c @@ -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 */ -- 2.40.0