aboutsummaryrefslogtreecommitdiff
path: root/hack/hack.eat.c
diff options
context:
space:
mode:
Diffstat (limited to 'hack/hack.eat.c')
-rw-r--r--hack/hack.eat.c492
1 files changed, 492 insertions, 0 deletions
diff --git a/hack/hack.eat.c b/hack/hack.eat.c
new file mode 100644
index 0000000..6373bc5
--- /dev/null
+++ b/hack/hack.eat.c
@@ -0,0 +1,492 @@
+/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/* hack.eat.c - version 1.0.3 */
+/* $FreeBSD: src/games/hack/hack.eat.c,v 1.4 1999/11/16 10:26:36 marcel Exp $ */
+
+#include "hack.h"
+char POISONOUS[] = "ADKSVabhks";
+
+static bool opentin(void);
+static void Meatdone(void);
+static void unfaint(void);
+static void newuhs(bool);
+static int eatcorpse(struct obj *);
+
+/* hunger texts used on bottom line (each 8 chars long) */
+#define SATIATED 0
+#define NOT_HUNGRY 1
+#define HUNGRY 2
+#define WEAK 3
+#define FAINTING 4
+#define FAINTED 5
+#define STARVED 6
+
+const char *hu_stat[] = {
+ "Satiated",
+ " ",
+ "Hungry ",
+ "Weak ",
+ "Fainting",
+ "Fainted ",
+ "Starved "
+};
+
+void
+init_uhunger(void)
+{
+ u.uhunger = 900;
+ u.uhs = NOT_HUNGRY;
+}
+
+#define TTSZ SIZE(tintxts)
+struct { const char *txt; int nut; } tintxts[] = {
+ { "It contains first quality peaches - what a surprise!", 40 },
+ { "It contains salmon - not bad!", 60 },
+ { "It contains apple juice - perhaps not what you hoped for.", 20 },
+ { "It contains some nondescript substance, tasting awfully.", 500 },
+ { "It contains rotten meat. You vomit.", -50 },
+ { "It turns out to be empty.", 0 }
+};
+
+static struct {
+ struct obj *tin;
+ int usedtime, reqtime;
+} tin;
+
+static bool
+opentin(void)
+{
+ int r;
+
+ if (!carried(tin.tin)) /* perhaps it was stolen? */
+ return (0); /* %% probably we should use tinoid */
+ if (tin.usedtime++ >= 50) {
+ pline("You give up your attempt to open the tin.");
+ return (0);
+ }
+ if (tin.usedtime < tin.reqtime)
+ return (1); /* still busy */
+
+ pline("You succeed in opening the tin.");
+ useup(tin.tin);
+ r = rn2(2 * TTSZ);
+ if (r < TTSZ) {
+ pline("%s", tintxts[r].txt);
+ lesshungry(tintxts[r].nut);
+ if (r == 1) { /* SALMON */
+ Glib = rnd(15);
+ pline("Eating salmon made your fingers very slippery.");
+ }
+ } else {
+ pline("It contains spinach - this makes you feel like Popeye!");
+ lesshungry(600);
+ if (u.ustr < 118)
+ u.ustr += rnd(((u.ustr < 17) ? 19 : 118) - u.ustr);
+ if (u.ustr > u.ustrmax)
+ u.ustrmax = u.ustr;
+ flags.botl = 1;
+ }
+ return (0);
+}
+
+static void
+Meatdone(void)
+{
+ u.usym = '@';
+ prme();
+}
+
+int
+doeat(void)
+{
+ struct obj *otmp;
+ struct objclass *ftmp;
+ int tmp;
+
+ /* Is there some food (probably a heavy corpse) here on the ground? */
+ if (!Levitation)
+ for (otmp = fobj; otmp; otmp = otmp->nobj) {
+ if (otmp->ox == u.ux && otmp->oy == u.uy &&
+ otmp->olet == FOOD_SYM) {
+ pline("There %s %s here; eat %s? [ny] ",
+ (otmp->quan == 1) ? "is" : "are",
+ doname(otmp),
+ (otmp->quan == 1) ? "it" : "one");
+ if (readchar() == 'y') {
+ if (otmp->quan != 1)
+ splitobj(otmp, 1);
+ freeobj(otmp);
+ otmp = addinv(otmp);
+ addtobill(otmp);
+ goto gotit;
+ }
+ }
+ }
+
+ otmp = getobj("%", "eat");
+ if (!otmp)
+ return (0);
+gotit:
+ if (otmp->otyp == TIN) {
+ if (uwep) {
+ switch (uwep->otyp) {
+ case CAN_OPENER:
+ tmp = 1;
+ break;
+ case DAGGER:
+ case CRYSKNIFE:
+ tmp = 3;
+ break;
+ case PICK_AXE:
+ case AXE:
+ tmp = 6;
+ break;
+ default:
+ goto no_opener;
+ }
+ pline("Using your %s you try to open the tin.",
+ aobjnam(uwep, NULL));
+ } else {
+no_opener:
+ pline("It is not so easy to open this tin.");
+ if (Glib) {
+ pline("The tin slips out of your hands.");
+ if (otmp->quan > 1) {
+ struct obj *obj;
+
+ obj = splitobj(otmp, 1);
+ if (otmp == uwep)
+ setuwep(obj);
+ }
+ dropx(otmp);
+ return (1);
+ }
+ tmp = 10 + rn2(1 + 500 / ((int)(u.ulevel + u.ustr)));
+ }
+ tin.reqtime = tmp;
+ tin.usedtime = 0;
+ tin.tin = otmp;
+ occupation = opentin;
+ occtxt = "opening the tin";
+ return (1);
+ }
+ ftmp = &objects[otmp->otyp];
+ multi = -ftmp->oc_delay;
+ if (otmp->otyp >= CORPSE && eatcorpse(otmp))
+ goto eatx;
+ if (!rn2(7) && otmp->otyp != FORTUNE_COOKIE) {
+ pline("Blecch! Rotten food!");
+ if (!rn2(4)) {
+ pline("You feel rather light headed.");
+ Confusion += d(2, 4);
+ } else if (!rn2(4) && !Blind) {
+ pline("Everything suddenly goes dark.");
+ Blind = d(2, 10);
+ seeoff(0);
+ } else if (!rn2(3)) {
+ if (Blind)
+ pline("The world spins and you slap against the floor.");
+ else
+ pline("The world spins and goes dark.");
+ nomul(-rnd(10));
+ nomovemsg = "You are conscious again.";
+ }
+ lesshungry(ftmp->nutrition / 4);
+ } else {
+ if (u.uhunger >= 1500) {
+ pline("You choke over your food.");
+ pline("You die...");
+ killer = ftmp->oc_name;
+ done("choked");
+ }
+ switch (otmp->otyp) {
+ case FOOD_RATION:
+ if (u.uhunger <= 200)
+ pline("That food really hit the spot!");
+ else if (u.uhunger <= 700)
+ pline("That satiated your stomach!");
+ else {
+ pline("You're having a hard time getting all that food down.");
+ multi -= 2;
+ }
+ lesshungry(ftmp->nutrition);
+ if (multi < 0)
+ nomovemsg = "You finished your meal.";
+ break;
+ case TRIPE_RATION:
+ pline("Yak - dog food!");
+ more_experienced(1, 0);
+ flags.botl = 1;
+ if (rn2(2)) {
+ pline("You vomit.");
+ morehungry(20);
+ if (Sick) {
+ Sick = 0; /* David Neves */
+ pline("What a relief!");
+ }
+ } else
+ lesshungry(ftmp->nutrition);
+ break;
+ default:
+ if (otmp->otyp >= CORPSE)
+ pline("That %s tasted terrible!", ftmp->oc_name);
+ else
+ pline("That %s was delicious!", ftmp->oc_name);
+ lesshungry(ftmp->nutrition);
+ if (otmp->otyp == DEAD_LIZARD && (Confusion > 2))
+ Confusion = 2;
+ else
+#ifdef QUEST
+ if (otmp->otyp == CARROT && !Blind) {
+ u.uhorizon++;
+ setsee();
+ pline("Your vision improves.");
+ } else
+#endif /* QUEST */
+ if (otmp->otyp == FORTUNE_COOKIE) {
+ if (Blind) {
+ pline("This cookie has a scrap of paper inside!");
+ pline("What a pity, that you cannot read it!");
+ } else
+ outrumor();
+ } else if (otmp->otyp == LUMP_OF_ROYAL_JELLY) {
+ /* This stuff seems to be VERY healthy! */
+ if (u.ustrmax < 118)
+ u.ustrmax++;
+ if (u.ustr < u.ustrmax)
+ u.ustr++;
+ u.uhp += rnd(20);
+ if (u.uhp > u.uhpmax) {
+ if (!rn2(17))
+ u.uhpmax++;
+ u.uhp = u.uhpmax;
+ }
+ heal_legs();
+ }
+ break;
+ }
+ }
+eatx:
+ if (multi < 0 && !nomovemsg) {
+ static char msgbuf[BUFSZ];
+ sprintf(msgbuf, "You finished eating the %s.", ftmp->oc_name);
+ nomovemsg = msgbuf;
+ }
+ useup(otmp);
+ return (1);
+}
+
+/* called in hack.main.c */
+void
+gethungry(void)
+{
+ --u.uhunger;
+ if (moves % 2) {
+ if (Regeneration)
+ u.uhunger--;
+ if (Hunger)
+ u.uhunger--;
+ /* a3: if (Hunger & LEFT_RING) u.uhunger--;
+ * if (Hunger & RIGHT_RING) u.uhunger--;
+ * etc.
+ */
+ }
+ if (moves % 20 == 0) { /* jimt@asgb */
+ if (uleft)
+ u.uhunger--;
+ if (uright)
+ u.uhunger--;
+ }
+ newuhs(TRUE);
+}
+
+/* called after vomiting and after performing feats of magic */
+void
+morehungry(int num)
+{
+ u.uhunger -= num;
+ newuhs(TRUE);
+}
+
+/* called after eating something (and after drinking fruit juice) */
+void
+lesshungry(int num)
+{
+ u.uhunger += num;
+ newuhs(FALSE);
+}
+
+static void
+unfaint(void)
+{
+ u.uhs = FAINTING;
+ flags.botl = 1;
+}
+
+static void
+newuhs(bool incr)
+{
+ int newhs, h = u.uhunger;
+
+ newhs = (h > 1000) ? SATIATED :
+ (h > 150) ? NOT_HUNGRY :
+ (h > 50) ? HUNGRY :
+ (h > 0) ? WEAK : FAINTING;
+
+ if (newhs == FAINTING) {
+ if (u.uhs == FAINTED)
+ newhs = FAINTED;
+ if (u.uhs <= WEAK || rn2(20 - u.uhunger / 10) >= 19) {
+ if (u.uhs != FAINTED && multi >= 0 /* %% */) {
+ pline("You faint from lack of food.");
+ nomul(-10 + (u.uhunger / 10));
+ nomovemsg = "You regain consciousness.";
+ afternmv = unfaint;
+ newhs = FAINTED;
+ }
+ } else if (u.uhunger < -(int)(200 + 25 * u.ulevel)) {
+ u.uhs = STARVED;
+ flags.botl = 1;
+ bot();
+ pline("You die from starvation.");
+ done("starved");
+ }
+ }
+
+ 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 && u.ustr < u.ustrmax)
+ losestr(-1);
+ switch (newhs) {
+ case HUNGRY:
+ pline((!incr) ? "You only feel hungry now." :
+ (u.uhunger < 145) ? "You feel hungry." :
+ "You are beginning to feel hungry.");
+ break;
+ case WEAK:
+ pline((!incr) ? "You feel weak now." :
+ (u.uhunger < 45) ? "You feel weak." :
+ "You are beginning to feel weak.");
+ break;
+ }
+ u.uhs = newhs;
+ flags.botl = 1;
+ if (u.uhp < 1) {
+ pline("You die from hunger and exhaustion.");
+ killer = "exhaustion";
+ done("starved");
+ }
+ }
+}
+
+#define CORPSE_I_TO_C(otyp) (char)((otyp >= DEAD_ACID_BLOB)\
+ ? 'a' + (otyp - DEAD_ACID_BLOB)\
+ : '@' + (otyp - DEAD_HUMAN))
+bool
+poisonous(struct obj *otmp)
+{
+ return (strchr(POISONOUS, CORPSE_I_TO_C(otmp->otyp)) != 0);
+}
+
+/* returns 1 if some text was printed */
+static int
+eatcorpse(struct obj *otmp)
+{
+ char let = CORPSE_I_TO_C(otmp->otyp);
+ int tp = 0;
+
+ if (let != 'a' && moves > otmp->age + 50 + rn2(100)) {
+ tp++;
+ pline("Ulch -- that meat was tainted!");
+ pline("You get very sick.");
+ Sick = 10 + rn2(10);
+ u.usick_cause = objects[otmp->otyp].oc_name;
+ } else if (strchr(POISONOUS, let) && rn2(5)) {
+ tp++;
+ pline("Ecch -- that must have been poisonous!");
+ if (!Poison_resistance) {
+ losestr(rnd(4));
+ losehp(rnd(15), "poisonous corpse");
+ } else
+ pline("You don't seem affected by the poison.");
+ } else if (strchr("ELNOPQRUuxz", let) && rn2(5)) {
+ tp++;
+ pline("You feel sick.");
+ losehp(rnd(8), "cadaver");
+ }
+ switch (let) {
+ case 'L':
+ case 'N':
+ case 't':
+ Teleportation |= INTRINSIC;
+ break;
+ case 'W':
+ pluslvl();
+ break;
+ case 'n':
+ u.uhp = u.uhpmax;
+ flags.botl = 1;
+ /* fall into next case */
+ case '@':
+ pline("You cannibal! You will be sorry for this!");
+ /* not tp++; */
+ /* fall into next case */
+ case 'd':
+ Aggravate_monster |= INTRINSIC;
+ break;
+ case 'I':
+ if (!Invis) {
+ Invis = 50 + rn2(100);
+ if (!See_invisible)
+ newsym(u.ux, u.uy);
+ } else {
+ Invis |= INTRINSIC;
+ See_invisible |= INTRINSIC;
+ }
+ /* fall into next case */
+ case 'y':
+#ifdef QUEST
+ u.uhorizon++;
+#endif /* QUEST */
+ /* fall into next case */
+ case 'B':
+ Confusion = 50;
+ break;
+ case 'D':
+ Fire_resistance |= INTRINSIC;
+ break;
+ case 'E':
+ Telepat |= INTRINSIC;
+ break;
+ case 'F':
+ case 'Y':
+ Cold_resistance |= INTRINSIC;
+ break;
+ case 'k':
+ case 's':
+ Poison_resistance |= INTRINSIC;
+ break;
+ case 'c':
+ pline("You turn to stone.");
+ killer = "dead cockatrice";
+ done("died");
+ /* NOTREACHED */
+ case 'a':
+ if (Stoned) {
+ pline("What a pity - you just destroyed a future piece of art!");
+ tp++;
+ Stoned = 0;
+ }
+ break;
+ case 'M':
+ pline("You cannot resist the temptation to mimic a treasure chest.");
+ tp++;
+ nomul(-30);
+ afternmv = Meatdone;
+ nomovemsg = "You now again prefer mimicking a human.";
+ u.usym = '$';
+ prme();
+ break;
+ }
+ return (tp);
+}