Skip to content

Commit

Permalink
Fixed pet AI and actual eating disagreeing on what is tainted and not.
Browse files Browse the repository at this point in the history
This was fixed by creating a new function that address corpse rot status.
The intention is to also use this for the "This corpse smells too old ...",
and to allow for Grunthack-style reporting of corpses as being "slightly rotten", etc,
but addressing this now is a non-bugfix that impacts gameplay, and thus is postponed until after Junethack.
  • Loading branch information
FredrIQ committed Jun 8, 2016
1 parent 6de2d4c commit 7bd8ba3
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 17 deletions.
1 change: 1 addition & 0 deletions libnethack/include/extern.h
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,7 @@ extern int dooverview(const struct nh_cmd_arg *);
extern boolean is_edible(const struct obj *, boolean);
extern void init_uhunger(void);
extern int doeat(const struct nh_cmd_arg *);
extern enum corpserot corpse_rot_status(struct obj *, boolean);
extern int eatcorpse(struct monst *, struct obj *);
extern void eatspecial(struct monst *, int, struct obj *);
extern void gethungry(void);
Expand Down
12 changes: 11 additions & 1 deletion libnethack/include/hungerstatus.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,15 @@
# define FAINTING 4
# define FAINTED 5
# define STARVED 6
#endif

/* Corpse rotness */
enum corpserot {
corpserot_maybe_tainted,
corpserot_tainted,
corpserot_maybe_sick,
corpserot_sick,
corpserot_ok,
corpserot_last_harmful = corpserot_sick,
};

#endif /* HUNGER_STATUS_H */
4 changes: 2 additions & 2 deletions libnethack/src/dog.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
/* NetHack may be freely redistributed. See license for details. */

#include "hack.h"
#include "hungerstatus.h"

static int pet_type(struct newgame_options *);

Expand Down Expand Up @@ -704,8 +705,7 @@ dogfood(const struct monst *mon, struct obj *obj)
return df_harmful;
return carni ? df_good : df_manfood;
case CORPSE:
if ((peek_at_iced_corpse_age(obj) + 50L <= moves &&
obj->corpsenm != PM_LIZARD && obj->corpsenm != PM_LICHEN &&
if ((corpse_rot_status(obj, TRUE) <= corpserot_last_harmful &&
!resists_sick(mon)) ||
(acidic(&mons[obj->corpsenm]) && !resists_acid(mon)) ||
(poisonous(&mons[obj->corpsenm]) && !resists_poison(mon)))
Expand Down
57 changes: 43 additions & 14 deletions libnethack/src/eat.c
Original file line number Diff line number Diff line change
Expand Up @@ -1061,14 +1061,53 @@ rottenfood(struct obj *obj)
return 0;
}

/* Returns rotness status. If test is true, return
corpserot_tainted|sick|ok. Otherwise, return
the worst possible case. This is for
pet/interface purposes to try to stop you and
pets from eating *potentially* tainted corpses. */
enum corpserot
corpse_rot_status(struct obj *obj, boolean test)
{
int min = 19; /* best case */
if (!test)
min = rn2(20);
boolean allow_sick = TRUE;
if (!test && !rn2(5))
allow_sick = FALSE;

if (obj->corpsenm == PM_LICHEN ||
obj->corpsenm == PM_LIZARD)
return corpserot_ok; /* always safe */

long rot = 0L;
long maxrot = 0L;
long age = peek_at_iced_corpse_age(obj);
rot = (moves - age) / (10L + min);
maxrot = (moves - age) / 10L;
rot += bcsign(obj) * 2;
maxrot += bcsign(obj) * 2;
if (obj->corpsenm != PM_ACID_BLOB) {
if (rot > 5L)
return corpserot_tainted;
else if (maxrot > 5L && test)
return corpserot_maybe_tainted;
}
if (rot > 3L && allow_sick)
return corpserot_sick;
else if (maxrot > 3L && test && allow_sick)
return corpserot_maybe_sick;
return corpserot_ok;
}

/* called when a corpse is selected as food */
int
eatcorpse(struct monst *mon, struct obj *otmp)
{
boolean you = (mon == &youmonst);
boolean vis = canseemon(mon);
int tp = 0, mnum = otmp->corpsenm;
long rotted = 0L;
enum corpserot rot = corpse_rot_status(otmp, FALSE);
boolean uniq = ! !(mons[mnum].geno & G_UNIQ);
int retcode = 0;
boolean stoneable = (touch_petrifies(&mons[mnum]) &&
Expand All @@ -1083,17 +1122,8 @@ eatcorpse(struct monst *mon, struct obj *otmp)
break_conduct(conduct_vegetarian);
}

if (mnum != PM_LIZARD && mnum != PM_LICHEN) {
long age = peek_at_iced_corpse_age(otmp);

rotted = (moves - age) / (10L + rn2(20));
if (otmp->cursed)
rotted += 2L;
else if (otmp->blessed)
rotted -= 2L;
}

if (mnum != PM_ACID_BLOB && !stoneable && rotted > 5L) {
if (mnum != PM_ACID_BLOB && !stoneable &&
rot == corpserot_tainted) {
boolean cannibal = FALSE;
if (you)
cannibal = maybe_cannibal(mnum, FALSE);
Expand Down Expand Up @@ -1170,8 +1200,7 @@ eatcorpse(struct monst *mon, struct obj *otmp)
you ? "You" : Monnam(mon),
you ? "" : "s");
/* now any corpse left too long will make you mildly ill */
} else if ((rotted > 5L || (rotted > 3L && rn2(5)))
&& !resists_sick(mon)) {
} else if (rot == corpserot_sick && !resists_sick(mon)) {
tp++;
if (you || vis)
pline(you ? msgc_statusbad : msgc_monneutral,
Expand Down

0 comments on commit 7bd8ba3

Please sign in to comment.