-/* NetHack 3.6 eat.c $NHDT-Date: 1449269916 2015/12/04 22:58:36 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.154 $ */
+/* NetHack 3.6 eat.c $NHDT-Date: 1502754159 2017/08/14 23:42:39 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.179 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
/* JNetHack Copyright */
STATIC_PTR int NDECL(eatmdone);
STATIC_PTR int NDECL(eatfood);
-STATIC_PTR void FDECL(costly_tin, (int));
+STATIC_PTR struct obj *FDECL(costly_tin, (int));
STATIC_PTR int NDECL(opentin);
STATIC_PTR int NDECL(unfaint);
STATIC_DCL const char *FDECL(food_xname, (struct obj *, BOOLEAN_P));
STATIC_DCL void FDECL(choke, (struct obj *));
STATIC_DCL void NDECL(recalc_wt);
+STATIC_DCL unsigned FDECL(obj_nutrition, (struct obj *));
STATIC_DCL struct obj *FDECL(touchfood, (struct obj *));
STATIC_DCL void NDECL(do_reset_eat);
STATIC_DCL void FDECL(done_eating, (BOOLEAN_P));
&& (youmonst.data != &mons[PM_RUST_MONSTER] || is_rustprone(obj)))
return TRUE;
+ /* Ghouls only eat non-veggy corpses or eggs (see dogfood()) */
+ if (u.umonnum == PM_GHOUL)
+ return (boolean)((obj->otyp == CORPSE
+ && !vegan(&mons[obj->corpsenm]))
+ || (obj->otyp == EGG));
+
if (u.umonnum == PM_GELATINOUS_CUBE && is_organic(obj)
/* [g.cubes can eat containers and retain all contents
as engulfed items, but poly'd player can't do that] */
void
init_uhunger()
{
+ context.botl = (u.uhs != NOT_HUNGRY || ATEMP(A_STR) < 0);
u.uhunger = 900;
u.uhs = NOT_HUNGRY;
+ if (ATEMP(A_STR) < 0)
+ ATEMP(A_STR) = 0;
}
/* tin types [SPINACH_TIN = -1, overrides corpsenm, nut==600] */
return;
}
+/* base nutrition of a food-class object */
+STATIC_OVL unsigned
+obj_nutrition(otmp)
+struct obj *otmp;
+{
+ unsigned nut = (otmp->otyp == CORPSE) ? mons[otmp->corpsenm].cnutrit
+ : otmp->globby ? otmp->owt
+ : (unsigned) objects[otmp->otyp].oc_nutrition;
+
+ if (otmp->otyp == LEMBAS_WAFER) {
+ if (maybe_polyd(is_elf(youmonst.data), Race_if(PM_ELF)))
+ nut += nut / 4; /* 800 -> 1000 */
+ else if (maybe_polyd(is_orc(youmonst.data), Race_if(PM_ORC)))
+ nut -= nut / 4; /* 800 -> 600 */
+ /* prevent polymorph making a partly eaten wafer
+ become more nutritious than an untouched one */
+ if (otmp->oeaten >= nut)
+ otmp->oeaten = (otmp->oeaten < objects[LEMBAS_WAFER].oc_nutrition)
+ ? (nut - 1) : nut;
+ } else if (otmp->otyp == CRAM_RATION) {
+ if (maybe_polyd(is_dwarf(youmonst.data), Race_if(PM_DWARF)))
+ nut += nut / 6; /* 600 -> 700 */
+ }
+ return nut;
+}
+
STATIC_OVL struct obj *
touchfood(otmp)
struct obj *otmp;
if (!otmp->oeaten) {
costly_alteration(otmp, COST_BITE);
- otmp->oeaten =
- (otmp->otyp == CORPSE ? mons[otmp->corpsenm].cnutrit
- : objects[otmp->otyp].oc_nutrition);
+ otmp->oeaten = obj_nutrition(otmp);
}
if (carried(otmp)) {
done_eating(message)
boolean message;
{
- context.victual.piece->in_use = TRUE;
+ struct obj *piece = context.victual.piece;
+
+ piece->in_use = TRUE;
occupation = 0; /* do this early, so newuhs() knows we're done */
newuhs(FALSE);
if (nomovemsg) {
nomovemsg = 0;
} else if (message)
/*JP
- You("finish eating %s.", food_xname(context.victual.piece, TRUE));
+ You("finish eating %s.", food_xname(piece, TRUE));
*/
- You("%s\82ð\90H\82×\8fI\82¦\82½\81D", food_xname(context.victual.piece, TRUE));
+ You("%s\82ð\90H\82×\8fI\82¦\82½\81D", food_xname(piece, TRUE));
- if (context.victual.piece->otyp == CORPSE)
- cpostfx(context.victual.piece->corpsenm);
+ if (piece->otyp == CORPSE || piece->globby)
+ cpostfx(piece->corpsenm);
else
- fpostfx(context.victual.piece);
+ fpostfx(piece);
- if (carried(context.victual.piece))
- useup(context.victual.piece);
+ if (carried(piece))
+ useup(piece);
else
- useupf(context.victual.piece, 1L);
+ useupf(piece, 1L);
context.victual.piece = (struct obj *) 0;
context.victual.o_id = 0;
context.victual.fullwarn = context.victual.eating =
*/
Your("\94]\82Í\90H\82×\82ç\82ê\82½\81I");
} else { /* monster against monster */
- if (visflag)
+ if (visflag && canspotmon(mdef))
/*JP
pline("%s brain is eaten!", s_suffix(Monnam(mdef)));
*/
} else {
/* no need to check for poly_when_stoned or Stone_resistance;
mind flayers don't have those capabilities */
- if (visflag)
+ if (visflag && canseemon(magr))
/*JP
pline("%s turns to stone!", Monnam(magr));
*/
if (magr->mtame && !visflag)
/* parallels mhitm.c's brief_feeling */
/*JP
- You("have a sad thought for a moment, then is passes.");
+ You("have a sad thought for a moment, then it passes.");
*/
You("\94ß\82µ\82¢\8dl\82¦\82É\82¨\82»\82í\82ê\82½\82ª\81A\82·\82®\82É\89ß\82¬\82³\82Á\82½\81D");
return MM_AGR_DIED;
* monster mind flayer is eating another monster's brain
*/
if (mindless(pd)) {
- if (visflag)
+ if (visflag && canspotmon(mdef))
/*JP
pline("%s doesn't notice.", Monnam(mdef));
*/
} else {
*dmg_p += xtra_dmg;
give_nutrit = TRUE;
- if (*dmg_p >= mdef->mhp && visflag)
-/*JP
+ if (*dmg_p >= mdef->mhp && visflag && canspotmon(mdef))
+#if 0 /*JP*/
pline("%s last thought fades away...",
-*/
- pline("%s\82Ì\8dÅ\8cã\82Ì\8ev\82¢\82ª\82æ\82¬\82é\81D\81D\81D",
s_suffix(Monnam(mdef)));
+#else
+ pline("%s\82Ì\8dÅ\8cã\82Ì\8ev\82¢\82ª\82æ\82¬\82é\81D\81D\81D",
+ Monnam(mdef));
+#endif
}
}
and also shouldn't eat current species when polymorphed
(even if having the form of something which doesn't care
about cannibalism--hero's innate traits aren't altered) */
- && (your_race(fptr) || (Upolyd && same_race(youmonst.data, fptr)))) {
+ && (your_race(fptr)
+ || (Upolyd && same_race(youmonst.data, fptr))
+ || (u.ulycn >= LOW_PM && were_beastie(pm) == u.ulycn))) {
if (allowmsg) {
if (Upolyd && your_race(fptr))
/*JP
register int pm;
{
register int tmp = 0;
- boolean catch_lycanthropy = FALSE;
+ int catch_lycanthropy = NON_PM;
/* in case `afternmv' didn't get called for previously mimicking
gold, clean up now to avoid `eatmbuf' memory leak */
pluslvl(FALSE);
break;
case PM_HUMAN_WERERAT:
- catch_lycanthropy = TRUE;
- u.ulycn = PM_WERERAT;
+ catch_lycanthropy = PM_WERERAT;
break;
case PM_HUMAN_WEREJACKAL:
- catch_lycanthropy = TRUE;
- u.ulycn = PM_WEREJACKAL;
+ catch_lycanthropy = PM_WEREJACKAL;
break;
case PM_HUMAN_WEREWOLF:
- catch_lycanthropy = TRUE;
- u.ulycn = PM_WEREWOLF;
+ catch_lycanthropy = PM_WEREWOLF;
break;
case PM_NURSE:
if (Upolyd)
u.mh = u.mhmax;
else
u.uhp = u.uhpmax;
+ make_blinded(0L, !u.ucreamed);
context.botl = 1;
break;
case PM_STALKER:
gainstr((struct obj *) 0, 0, TRUE);
else if (tmp > 0)
givit(tmp, ptr);
- } break;
- }
+ break;
+ } /* default case */
+ } /* switch */
- if (catch_lycanthropy)
+ if (catch_lycanthropy >= LOW_PM) {
+ set_ulycn(catch_lycanthropy);
retouch_equipment(2);
-
+ }
return;
}
/* common code to check and possibly charge for 1 context.tin.tin,
* will split() context.tin.tin if necessary */
-STATIC_PTR void
+STATIC_PTR struct obj *
costly_tin(alter_type)
int alter_type; /* COST_xxx */
{
}
costly_alteration(tin, alter_type);
}
+ return tin;
}
int
b_trapped("tin", 0);
*/
b_trapped("\8aÊ", 0);
- costly_tin(COST_DSTROY);
+ tin = costly_tin(COST_DSTROY);
goto use_up_tin;
}
*/
pline("\8aÊ\82Í\8bó\82Á\82Û\82¾\82Á\82½\81D");
tin->dknown = tin->known = 1;
- costly_tin(COST_OPEN);
+ tin = costly_tin(COST_OPEN);
goto use_up_tin;
}
You("\8aJ\82¯\82½\8aÊ\82ð\8eÌ\82Ä\82½\81D");
if (!Hallucination)
tin->dknown = tin->known = 1;
- costly_tin(COST_OPEN);
+ tin = costly_tin(COST_OPEN);
goto use_up_tin;
}
cpostfx(mnum);
/* charge for one at pre-eating cost */
- costly_tin(COST_OPEN);
+ tin = costly_tin(COST_OPEN);
if (tintxts[r].nut < 0) /* rotten */
make_vomiting((long) rn1(15, 10), FALSE);
You("discard the open tin.");
*/
You("\8aJ\82¯\82½\8aÊ\82ð\8eÌ\82Ä\82½\81D");
- costly_tin(COST_OPEN);
+ tin = costly_tin(COST_OPEN);
goto use_up_tin;
}
* Same order as with non-spinach above:
* conduct update, side-effects, shop handling, and nutrition.
*/
- u.uconduct
- .food++; /* don't need vegan/vegetarian checks for spinach */
+ u.uconduct.food++; /* don't need vegetarian checks for spinach */
if (!tin->cursed)
#if 0 /*JP:T*/
pline("This makes you feel like %s!",
#endif
gainstr(tin, 0, FALSE);
- costly_tin(COST_OPEN);
+ tin = costly_tin(COST_OPEN);
lesshungry(tin->blessed
? 600 /* blessed */
case ELVEN_DAGGER:
case ORCISH_DAGGER:
case ATHAME:
+ case KNIFE:
+ case STILETTO:
case CRYSKNIFE:
tmp = 3;
break;
Hear_again(VOID_ARGS)
{
/* Chance of deafness going away while fainted/sleeping/etc. */
- if (!rn2(2))
+ if (!rn2(2)) {
make_deaf(0L, FALSE);
+ context.botl = TRUE;
+ }
return 0;
}
pline("Everything suddenly goes dark.");
*/
pline("\93Ë\91R\91S\82Ä\82ª\88Ã\82\82È\82Á\82½\81D");
- make_blinded((long) d(2, 10), FALSE);
+ /* hero is not Blind, but Blinded timer might be nonzero if
+ blindness is being overridden by the Eyes of the Overworld */
+ make_blinded((Blinded & TIMEOUT) + (long) d(2, 10), FALSE);
if (!Blind)
Your1(vision_clears);
} else if (!rn2(3)) {
*/
pline("\90¢\8aE\82ª\89ñ\93]\82µ\81C%s%s\81D", where, what);
incr_itimeout(&HDeaf, duration);
+ context.botl = TRUE;
nomul(-duration);
/*JP
multi_reason = "unconscious from rotten food";
eatcorpse(otmp)
struct obj *otmp;
{
- int tp = 0, mnum = otmp->corpsenm;
+ int retcode = 0, tp = 0, mnum = otmp->corpsenm;
long rotted = 0L;
- int retcode = 0;
boolean stoneable = (flesh_petrifies(&mons[mnum]) && !Stone_resistance
- && !poly_when_stoned(youmonst.data));
+ && !poly_when_stoned(youmonst.data)),
+ slimeable = (mnum == PM_GREEN_SLIME && !Slimed && !Unchanging
+ && !slimeproof(youmonst.data)),
+ glob = otmp->globby ? TRUE : FALSE;
/* KMH, conduct */
if (!vegan(&mons[mnum]))
rotted -= 2L;
}
- if (mnum != PM_ACID_BLOB && !stoneable && rotted > 5L) {
+ if (mnum != PM_ACID_BLOB && !stoneable && !slimeable && rotted > 5L) {
boolean cannibal = maybe_cannibal(mnum, FALSE);
#if 0 /*JP*/
pline("Ulch - that %s was tainted%s!",
- mons[mnum].mlet == S_FUNGUS
- ? "fungoid vegetation"
- : !vegetarian(&mons[mnum]) ? "meat" : "protoplasm",
+ (mons[mnum].mlet == S_FUNGUS) ? "fungoid vegetation"
+ : glob ? "glob"
+ : vegetarian(&mons[mnum]) ? "protoplasm"
+ : "meat",
cannibal ? ", you cannibal" : "");
-#else
- pline("\83I\83F\81I\82±\82Ì%s\82Í\95\85\82Á\82Ä\82¢\82é%s\81I",
- mons[mnum].mlet == S_FUNGUS
- ? "\8d×\8bÛ\82É\89\98\90õ\82³\82ê\82½\90A\95¨"
- : !vegetarian(&mons[mnum]) ? "\93÷" : "\90¶\95¨",
- cannibal ? "\81D\82µ\82©\82à\8b¤\90H\82¢\82¾" : "");
+#else /* \93ú\96{\8cê\82Å\82Í\92P\8f\83\82É */
+ pline("\83I\83F\81I\82±\82ê\82Í\95\85\82Á\82Ä\82¢\82é\81I%s",
+ cannibal ? "\82µ\82©\82à\8b¤\90H\82¢\82¾\81I" : "");
#endif
if (Sick_resistance) {
/*JP
/* make sure new ill doesn't result in improvement */
if (Sick && (sick_time > Sick))
sick_time = (Sick > 1L) ? Sick - 1L : 1L;
-#if 0 /*JP*/
+#if 0 /*JP:T*/
make_sick(sick_time, corpse_xname(otmp, "rotted", CXN_NORMAL),
TRUE, SICK_VOMITABLE);
#else
make_sick(sick_time, corpse_xname(otmp, "\95\85\82Á\82½", CXN_NORMAL),
TRUE, SICK_VOMITABLE);
#endif
+
+ pline("(It must have died too long ago to be safe to eat.)");
}
if (carried(otmp))
useup(otmp);
#else
pline("\88Ý\8e_\82Ì\92²\8eq\82ª\82Æ\82Ä\82à\88«\82¢\81D");
#endif
-#if 0 /*JP*/
- losehp(rnd(15), "acidic corpse", KILLED_BY_AN); /* acid damage */
-#else
+#if 0 /*JP:T*/
+ losehp(rnd(15), !glob ? "acidic corpse" : "acidic glob",
+ KILLED_BY_AN); /* acid damage */
+#else /* \93ú\96{\8cê\82Å\82Í\8bæ\95Ê\82µ\82È\82¢ */
losehp(rnd(15), "\8e_\82Ì\8e\80\91Ì\82Å", KILLED_BY_AN);
#endif
} else if (poisonous(&mons[mnum]) && rn2(5)) {
pline("\83E\83Q\83F\81[\81C\97L\93Å\82¾\82Á\82½\82É\82¿\82ª\82¢\82È\82¢\81I");
if (!Poison_resistance) {
losestr(rnd(4));
-/*JP
- losehp(rnd(15), "poisonous corpse", KILLED_BY_AN);
-*/
+#if 0 /*JP*/
+ losehp(rnd(15), !glob ? "poisonous corpse" : "poisonous glob",
+ KILLED_BY_AN);
+#else
losehp(rnd(15), "\93Å\82Ì\8e\80\91Ì\82Å", KILLED_BY_AN);
+#endif
} else
/*JP
You("seem unaffected by the poison.");
*/
You("\93Å\82Ì\89e\8b¿\82ð\8eó\82¯\82È\82¢\82æ\82¤\82¾\81D");
- /* now any corpse left too long will make you mildly ill */
+ /* now any corpse left too long will make you mildly ill */
} else if ((rotted > 5L || (rotted > 3L && rn2(5))) && !Sick_resistance) {
tp++;
/*JP
*/
You("%s\8bC\95ª\82ª\88«\82¢\81D", (Sick) ? "\82Æ\82Ä\82à" : "");
/*JP
- losehp(rnd(8), "cadaver", KILLED_BY_AN);
+ losehp(rnd(8), !glob ? "cadaver" : "rotted glob", KILLED_BY_AN);
*/
losehp(rnd(8), "\95\85\97\90\8e\80\91Ì\82Å", KILLED_BY_AN);
}
/* delay is weight dependent */
- context.victual.reqtime = 3 + (mons[mnum].cwt >> 6);
+ context.victual.reqtime = 3 + ((!glob ? mons[mnum].cwt : otmp->owt) >> 6);
if (!tp && !nonrotting_corpse(mnum) && (otmp->orotten || !rn2(7))) {
if (rottenfood(otmp)) {
*/
You("\96Ú\8bÊ\82ð\82Â\82ñ\82Â\82ñ\82Â\82Â\82¢\82½\81D");
} else {
- /* [is this right? omnivores end up always disliking the taste] */
- boolean yummy = vegan(&mons[mnum])
- ? (!carnivorous(youmonst.data)
- && herbivorous(youmonst.data))
- : (carnivorous(youmonst.data)
- && !herbivorous(youmonst.data));
+ /* yummy is always False for omnivores, palatable always True */
+ boolean yummy = (vegan(&mons[mnum])
+ ? (!carnivorous(youmonst.data)
+ && herbivorous(youmonst.data))
+ : (carnivorous(youmonst.data)
+ && !herbivorous(youmonst.data))),
+ palatable = ((vegetarian(&mons[mnum])
+ ? herbivorous(youmonst.data)
+ : carnivorous(youmonst.data))
+ && rn2(10)
+ && ((rotted < 1) ? TRUE : !rn2(rotted+1)));
+ const char *pmxnam = food_xname(otmp, FALSE);
#if 0 /*JP*/
- pline("%s%s %s!",
+ if (!strncmpi(pmxnam, "the ", 4))
+ pmxnam += 4;
+ pline("%s%s %s %s%c",
type_is_pname(&mons[mnum])
? "" : the_unique_pm(&mons[mnum]) ? "The " : "This ",
- food_xname(otmp, FALSE),
+ pmxnam,
+ Hallucination ? "is" : "tastes",
+ /* tiger reference is to TV ads for "Frosted Flakes",
+ breakfast cereal targeted at kids by "Tony the tiger" */
Hallucination
- ? (yummy ? ((u.umonnum == PM_TIGER) ? "is gr-r-reat"
- : "is gnarly")
- : "is grody")
- : (yummy ? "is delicious" : "tastes terrible"));
+ ? (yummy ? ((u.umonnum == PM_TIGER) ? "gr-r-reat" : "gnarly")
+ : palatable ? "copacetic" : "grody")
+ : (yummy ? "delicious" : palatable ? "okay" : "terrible"),
+ (yummy || !palatable) ? '!' : '.');
#else
- pline("\82±\82Ì%s\82Í%s\81I",
- food_xname(otmp, FALSE),
+ pline("\82±\82Ì%s\82Í%s%s",
+ pmxnam,
Hallucination
- ? (yummy ? ((u.umonnum == PM_TIGER) ? "\83O\83D\83\8c\83C\83g\83D"
- : "\83C\83P\82Ä\82é")
- : "\83C\83P\82Ä\82È\82¢")
- : (yummy ? "\82Æ\82Ä\82à\8e|\82¢" : "\82Ð\82Ç\82¢\96¡\82¾"));
+ ? (yummy ? ((u.umonnum == PM_TIGER) ? "\83O\83D\83\8c\83C\83g\83D"
+ : "\83C\83P\82Ä\82é")
+ : palatable ? "\82Ü\82 \82 \82è\82¾" : "\83C\83P\82Ä\82È\82¢")
+ : (yummy ? "\82Æ\82Ä\82à\8e|\82¢" : palatable ? "\82Ü\82 \82Ü\82 \82¾"
+ : "\82Ð\82Ç\82¢\96¡\82¾"),
+ (yummy || !palatable) ? "\81I" : "\81D");
#endif
}
{
const char *old_nomovemsg, *save_nomovemsg;
- debugpline2("start_eating: %lx (victual = %lx)", (unsigned long) otmp,
- (unsigned long) context.victual.piece);
+ debugpline2("start_eating: %s (victual = %s)",
+ /* note: fmt_ptr() returns a static buffer but supports
+ several such so we don't need to copy the first result
+ before calling it a second time */
+ fmt_ptr((genericptr_t) otmp),
+ fmt_ptr((genericptr_t) context.victual.piece));
debugpline1("reqtime = %d", context.victual.reqtime);
debugpline1("(original reqtime = %d)", objects[otmp->otyp].oc_delay);
debugpline1("nmod = %d", context.victual.nmod);
make_vomiting((long) rn1(context.victual.reqtime, 14), FALSE);
}
break;
+ case LEMBAS_WAFER:
+ if (maybe_polyd(is_orc(youmonst.data), Race_if(PM_ORC))) {
+ pline("%s", "!#?&* elf kibble!");
+ break;
+ } else if (maybe_polyd(is_elf(youmonst.data), Race_if(PM_ELF))) {
+ pline("A little goes a long way.");
+ break;
+ }
+ goto give_feedback;
case MEATBALL:
case MEAT_STICK:
case HUGE_CHUNK_OF_MEAT:
make_vomiting((long) rn1(context.victual.reqtime, 5), FALSE);
break;
}
- /* else FALLTHRU */
+ /*FALLTHRU*/
default:
if (otmp->otyp == SLIME_MOLD && !otmp->cursed
&& otmp->spe == context.current_fruit) {
#else
pline("\83E\83Q\83F\81[\95\85\82Á\82½\97\91\82¾\81D");
#endif
+ /* increasing existing nausea means that it will take longer
+ before eventual vomit, but also means that constitution
+ will be abused more times before illness completes */
make_vomiting((Vomiting & TIMEOUT) + (long) d(10, 4), TRUE);
} else {
give_feedback:
vault_gd_watching(GD_EATGOLD);
return;
}
+ if (objects[otmp->otyp].oc_material == PAPER) {
#ifdef MAIL
- if (otmp->otyp == SCR_MAIL) {
- /* no nutrition */
- pline("This junk mail is less than satisfying.");
- }
+ if (otmp->otyp == SCR_MAIL)
+ /* no nutrition */
+ pline("This junk mail is less than satisfying.");
+ else
#endif
+ if (otmp->otyp == SCR_SCARE_MONSTER)
+ /* to eat scroll, hero is currently polymorphed into a monster */
+ pline("Yuck%c", otmp->blessed ? '!' : '.');
+ else if (otmp->oclass == SCROLL_CLASS
+ /* check description after checking for specific scrolls */
+ && !strcmpi(OBJ_DESCR(objects[otmp->otyp]), "YUM YUM"))
+ pline("Yum%c", otmp->blessed ? '!' : '.');
+ else
+ pline("Needs salt...");
+ }
if (otmp->oclass == POTION_CLASS) {
otmp->quan++; /* dopotion() does a useup() */
(void) dopotion(otmp);
*/
char buf[BUFSZ], foodsmell[BUFSZ],
it_or_they[QBUFSZ], eat_it_anyway[QBUFSZ];
- boolean cadaver = (otmp->otyp == CORPSE), stoneorslime = FALSE;
+ boolean cadaver = (otmp->otyp == CORPSE || otmp->globby),
+ stoneorslime = FALSE;
int material = objects[otmp->otyp].oc_material, mnum = otmp->corpsenm;
long rotted = 0L;
if (cadaver && !nonrotting_corpse(mnum)) {
long age = peek_at_iced_corpse_age(otmp);
+
/* worst case rather than random
in this calculation to force prompt */
rotted = (monstermoves - age) / (10L + 0 /* was rn2(20) */);
if (u.uedibility) {
int res = edibility_prompts(otmp);
+
if (res) {
#if 0 /*JP*/
Your(
* mails, players who polymorph back to human in the middle of their
* metallic meal, etc....
*/
- if (!(carried(otmp) ? retouch_object(&otmp, FALSE)
- : touch_artifact(otmp, &youmonst))) {
- return 1;
- } else if (!is_edible(otmp)) {
+ if (!is_edible(otmp)) {
/*JP
You("cannot eat that!");
*/
*/
You("\90g\82É\82Â\82¯\82Ä\82¢\82é\8aÔ\82Í\90H\82×\82ê\82È\82¢\81D");
return 0;
+ } else if (!(carried(otmp) ? retouch_object(&otmp, FALSE)
+ : touch_artifact(otmp, &youmonst))) {
+ return 1; /* got blasted so use a turn */
}
if (is_metallic(otmp) && u.umonnum == PM_RUST_MONSTER
&& otmp->oerodeproof) {
/* The regurgitated object's rustproofing is gone now */
otmp->oerodeproof = 0;
make_stunned((HStun & TIMEOUT) + (long) rn2(10), TRUE);
+ /*
+ * We don't expect rust monsters to be wielding welded weapons
+ * or wearing cursed rings which were rustproofed, but guard
+ * against the possibility just in case.
+ */
+ if (welded(otmp) || (otmp->cursed && (otmp->owornmask & W_RING))) {
+ otmp->bknown = 1; /* for ring; welded() does this for weapon */
+ You("spit out %s.", the(xname(otmp)));
+ } else {
#if 0 /*JP*/
- You("spit %s out onto the %s.", the(xname(otmp)),
- surface(u.ux, u.uy));
+ You("spit %s out onto the %s.", the(xname(otmp)),
+ surface(u.ux, u.uy));
#else
- You("%s\82ð%s\82É\93f\82«\8fo\82µ\82½\81D", the(xname(otmp)),
- surface(u.ux, u.uy));
+ You("%s\82ð%s\82É\93f\82«\8fo\82µ\82½\81D", the(xname(otmp)),
+ surface(u.ux, u.uy));
#endif
- if (carried(otmp)) {
- freeinv(otmp);
- dropy(otmp);
+ if (carried(otmp)) {
+ /* no need to check for leash in use; it's not metallic */
+ if (otmp->owornmask)
+ remove_worn_item(otmp, FALSE);
+ freeinv(otmp);
+ dropy(otmp);
+ }
+ stackobj(otmp);
}
- stackobj(otmp);
return 1;
}
/* KMH -- Slow digestion is... indigestible */
u.uconduct.unvegan++;
u.uconduct.food++;
- if (otmp->cursed)
+ if (otmp->cursed) {
(void) rottenfood(otmp);
+ nodelicious = TRUE;
+ } else if (objects[otmp->otyp].oc_material == PAPER)
+ nodelicious = TRUE;
if (otmp->oclass == WEAPON_CLASS && otmp->opoisoned) {
/*JP
You("seem unaffected by the poison.");
*/
You("\93Å\82Ì\89e\8b¿\82ð\8eó\82¯\82È\82¢\82æ\82¤\82¾\81D");
- } else if (!otmp->cursed && !nodelicious) {
+ } else if (!nodelicious) {
#if 0 /*JP*/
pline("%s%s is delicious!",
(obj_is_pname(otmp)
}
/* re-calc the nutrition */
- if (otmp->otyp == CORPSE)
- basenutrit = mons[otmp->corpsenm].cnutrit;
- else
- basenutrit = objects[otmp->otyp].oc_nutrition;
+ basenutrit = (int) obj_nutrition(otmp);
- debugpline1("before rounddiv: context.victual.reqtime == %d",
- context.victual.reqtime);
- debugpline2("oeaten == %d, basenutrit == %d", otmp->oeaten, basenutrit);
- context.victual.reqtime = (basenutrit == 0)
- ? 0
- : rounddiv(context.victual.reqtime
- * (long) otmp->oeaten,
- basenutrit);
- debugpline1("after rounddiv: context.victual.reqtime == %d",
+ debugpline3(
+ "before rounddiv: victual.reqtime == %d, oeaten == %d, basenutrit == %d",
+ context.victual.reqtime, otmp->oeaten, basenutrit);
+
+ context.victual.reqtime = (basenutrit == 0) ? 0
+ : rounddiv(context.victual.reqtime * (long) otmp->oeaten, basenutrit);
+
+ debugpline1("after rounddiv: victual.reqtime == %d",
context.victual.reqtime);
/*
* calculate the modulo value (nutrit. units per round eating)
return 1;
}
+int
+use_tin_opener(obj)
+struct obj *obj;
+{
+ struct obj *otmp;
+ int res = 0;
+
+ if (!carrying(TIN)) {
+/*JP
+ You("have no tin to open.");
+*/
+ You("\8aÊ\82ð\8e\9d\82Á\82Ä\82¢\82È\82¢\81D");
+ return 0;
+ }
+
+ if (obj != uwep) {
+ if (obj->cursed && obj->bknown) {
+ char qbuf[QBUFSZ];
+
+ if (ynq(safe_qbuf(qbuf, "Really wield ", "?",
+ obj, doname, thesimpleoname, "that")) != 'y')
+ return 0;
+ }
+ if (!wield_tool(obj, "use"))
+ return 0;
+ res = 1;
+ }
+
+ otmp = getobj(comestibles, "open");
+ if (!otmp)
+ return res;
+
+ start_tin(otmp);
+ return 1;
+}
+
/* Take a single bite from a piece of food, checking for choking and
* modifying usedtime. Returns 1 if they choked and survived, 0 otherwise.
*/
return 0;
}
-/* as time goes by - called by moveloop() and domove() */
+/* as time goes by - called by moveloop(every move) & domove(melee attack) */
void
gethungry()
{
if (u.uinvulnerable)
return; /* you don't feel hungrier */
- if ((!u.usleep || !rn2(10)) /* slow metabolic rate while asleep */
- && (carnivorous(youmonst.data) || herbivorous(youmonst.data))
+ /* being polymorphed into a creature which doesn't eat prevents
+ this first uhunger decrement, but to stay in such form the hero
+ will need to wear an Amulet of Unchanging so still burn a small
+ amount of nutrition in the 'moves % 20' ring/amulet check below */
+ if ((!Unaware || !rn2(10)) /* slow metabolic rate while asleep */
+ && (carnivorous(youmonst.data)
+ || herbivorous(youmonst.data)
+ || metallivorous(youmonst.data))
&& !Slow_digestion)
u.uhunger--; /* ordinary food consumption */
/* Conflict uses up food too */
if (HConflict || (EConflict & (~W_ARTI)))
u.uhunger--;
- /* +0 charged rings don't do anything, so don't affect hunger */
- /* Slow digestion still uses ring hunger */
+ /* +0 charged rings don't do anything, so don't affect hunger.
+ Slow digestion cancels move hunger but still causes ring hunger. */
switch ((int) (moves % 20)) { /* note: use even cases only */
case 4:
if (uleft && (uleft->spe || !objects[uleft->otyp].oc_charged))
}
if (newhs == FAINTING) {
+ /* u,uhunger is likely to be negative at this point */
+ int uhunger_div_by_10 = sgn(u.uhunger) * ((abs(u.uhunger) + 5) / 10);
+
if (is_fainted())
newhs = FAINTED;
- if (u.uhs <= WEAK || rn2(20 - u.uhunger / 10) >= 19) {
+ if (u.uhs <= WEAK || rn2(20 - uhunger_div_by_10) >= 19) {
if (!is_fainted() && multi >= 0 /* %% */) {
- int duration = 10 - (u.uhunger / 10);
+ int duration = 10 - uhunger_div_by_10;
/* stop what you're doing, then faint */
stop_occupation();
You("faint from lack of food.");
*/
You("\95 \82ª\8c¸\82Á\82Ä\93|\82ê\82½\81D");
- if (!Levitation)
-/*JP
- selftouch("Falling, you");
-*/
- selftouch("\97\8e\82¿\82È\82ª\82ç\81C\82 \82È\82½\82Í");
incr_itimeout(&HDeaf, duration);
+ context.botl = TRUE;
nomul(-duration);
/*JP
multi_reason = "fainted from lack of food";
nomovemsg = "\82 \82È\82½\82Í\90³\8bC\82Ã\82¢\82½\81D";
afternmv = unfaint;
newhs = FAINTED;
+ if (!Levitation)
+/*JP
+ selftouch("Falling, you");
+*/
+ selftouch("\97\8e\82¿\82È\82ª\82ç\81C\82 \82È\82½\82Í");
}
- } else if (u.uhunger < -(int) (200 + 20 * ACURR(A_CON))) {
+
+ /* this used to be -(200 + 20 * Con) but that was when being asleep
+ suppressed per-turn uhunger decrement but being fainted didn't;
+ now uhunger becomes more negative at a slower rate */
+ } else if (u.uhunger < -(100 + 10 * (int) ACURR(A_CON))) {
u.uhs = STARVED;
context.botl = 1;
bot();
}
if (newhs != u.uhs) {
- if (newhs >= WEAK && u.uhs < WEAK)
- losestr(1); /* this may kill you -- see below */
- else if (newhs < WEAK && u.uhs >= WEAK)
- losestr(-1);
+ if (newhs >= WEAK && u.uhs < WEAK) {
+ /* this used to be losestr(1) which had the potential to
+ be fatal (still handled below) by reducing HP if it
+ tried to take base strength below minimum of 3 */
+ ATEMP(A_STR) = -1; /* temporary loss overrides Fixed_abil */
+ /* defer context.botl status update until after hunger message */
+ } else if (newhs < WEAK && u.uhs >= WEAK) {
+ /* this used to be losestr(-1) which could be abused by
+ becoming weak while wearing ring of sustain ability,
+ removing ring, eating to 'restore' strength which boosted
+ strength by a point each time the cycle was performed;
+ substituting "while polymorphed" for sustain ability and
+ "rehumanize" for ring removal might have done that too */
+ ATEMP(A_STR) = 0; /* repair of loss also overrides Fixed_abil */
+ /* defer context.botl status update until after hunger message */
+ }
+
switch (newhs) {
case HUNGRY:
if (Hallucination) {
#endif
/* if we can't touch floor objects then use invent food only */
- if (!can_reach_floor(TRUE) || (feeding && u.usteed)
+ if (iflags.menu_requested /* command was preceded by 'm' prefix */
+ || !can_reach_floor(TRUE) || (feeding && u.usteed)
|| (is_pool_or_lava(u.ux, u.uy)
&& (Wwalking || is_clinger(youmonst.data)
|| (Flying && !Breathless))))
char qsfx[QBUFSZ];
boolean one = (otmp->quan == 1L);
+ /* if blind and without gloves, attempting to eat (or tin or
+ offer) a cockatrice corpse is fatal before asking whether
+ or not to use it; otherwise, 'm<dir>' followed by 'e' could
+ be used to locate cockatrice corpses without touching them */
+ if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
+ feel_cockatrice(otmp, FALSE);
+ /* if life-saved (or poly'd into stone golem), terminate
+ attempt to eat off floor */
+ return (struct obj *) 0;
+ }
/* "There is <an object> here; <verb> it?" or
"There are <N objects> here; <verb> one?" */
#if 0 /*JP*/
/* We cannot use ALL_CLASSES since that causes getobj() to skip its
* "ugly checks" and we need to check for inedible items.
*/
- otmp =
- getobj(feeding ? allobj : offering ? offerfodder : comestibles, verb);
+ otmp = getobj(feeding ? allobj : offering ? offerfodder : comestibles,
+ verb);
if (corpsecheck && otmp && !(offering && otmp->oclass == AMULET_CLASS))
if (otmp->otyp != CORPSE || (corpsecheck == 2 && !tinnable(otmp))) {
/*JP
void
vomit() /* A good idea from David Neves */
{
- if (cantvomit(youmonst.data))
+ if (cantvomit(youmonst.data)) {
/* doesn't cure food poisoning; message assumes that we aren't
dealing with some esoteric body_part() */
/*JP
Your("jaw gapes convulsively.");
*/
Your("\82 \82²\82Í\94\8dì\93I\82É\91å\82«\82\8aJ\82¢\82½\81D");
- else
+ } else {
make_sick(0L, (char *) 0, TRUE, SICK_VOMITABLE);
- nomul(-2);
+ /* if not enough in stomach to actually vomit then dry heave;
+ vomiting_dialog() gives a vomit message when its countdown
+ reaches 0, but only if u.uhs < FAINTING (and !cantvomit()) */
+ if (u.uhs >= FAINTING)
+ Your("%s heaves convulsively!", body_part(STOMACH));
+ }
+
+ /* nomul()/You_can_move_again used to be unconditional, which was
+ viable while eating but not for Vomiting countdown where hero might
+ be immobilized for some other reason at the time vomit() is called */
+ if (multi >= -2) {
+ nomul(-2);
/*JP
multi_reason = "vomiting";
*/
multi_reason = "\9aq\93f\82µ\82Ä\82¢\82é\8dÅ\92\86\82É";
- nomovemsg = You_can_move_again;
+ nomovemsg = You_can_move_again;
+ }
}
int
{
long uneaten_amt, full_amount;
+ /* get full_amount first; obj_nutrition() might modify obj->oeaten */
+ full_amount = (long) obj_nutrition(obj);
uneaten_amt = (long) obj->oeaten;
- full_amount = (obj->otyp == CORPSE)
- ? (long) mons[obj->corpsenm].cnutrit
- : (long) objects[obj->otyp].oc_nutrition;
if (uneaten_amt > full_amount) {
impossible(
"partly eaten food (%ld) more nutritious than untouched food (%ld)",