1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64: #include <sys/cdefs.h>
65: #ifndef lint
66: __RCSID("$NetBSD: hack.eat.c,v 1.6 2003/04/02 18:36:36 jsm Exp $");
67: #endif
68:
69: #include "hack.h"
70: #include "extern.h"
71: char POISONOUS[] = "ADKSVabhks";
72:
73:
74: #define SATIATED 0
75: #define NOT_HUNGRY 1
76: #define HUNGRY 2
77: #define WEAK 3
78: #define FAINTING 4
79: #define FAINTED 5
80: #define STARVED 6
81:
82: const char *const hu_stat[] = {
83: "Satiated",
84: " ",
85: "Hungry ",
86: "Weak ",
87: "Fainting",
88: "Fainted ",
89: "Starved "
90: };
91:
92: void
93: init_uhunger()
94: {
95: u.uhunger = 900;
96: u.uhs = NOT_HUNGRY;
97: }
98:
99: #define TTSZ SIZE(tintxts)
100: const struct {
101: const char *txt;
102: int nut;
103: } tintxts[] = {
104: { "It contains first quality peaches - what a surprise!", 40 },
105: { "It contains salmon - not bad!", 60 },
106: { "It contains apple juice - perhaps not what you hoped for.", 20 },
107: { "It contains some nondescript substance, tasting awfully.", 500 },
108: { "It contains rotten meat. You vomit.", -50 },
109: { "It turns out to be empty.", 0 }
110: };
111:
112: static struct {
113: struct obj *tin;
114: int usedtime, reqtime;
115: } tin;
116:
117: int
118: opentin()
119: {
120: int r;
121:
122: if (!carried(tin.tin))
123: return (0);
124: if (tin.usedtime++ >= 50) {
125: pline("You give up your attempt to open the tin.");
126: return (0);
127: }
128: if (tin.usedtime < tin.reqtime)
129: return (1);
130:
131: pline("You succeed in opening the tin.");
132: useup(tin.tin);
133: r = rn2(2 * TTSZ);
134: if (r < TTSZ) {
135: pline(tintxts[r].txt);
136: lesshungry(tintxts[r].nut);
137: if (r == 1) {
138: Glib = rnd(15);
139: pline("Eating salmon made your fingers very slippery.");
140: }
141: } else {
142: pline("It contains spinach - this makes you feel like Popeye!");
143: lesshungry(600);
144: if (u.ustr < 118)
145: u.ustr += rnd(((u.ustr < 17) ? 19 : 118) - u.ustr);
146: if (u.ustr > u.ustrmax)
147: u.ustrmax = u.ustr;
148: flags.botl = 1;
149: }
150: return (0);
151: }
152:
153: int
154: Meatdone()
155: {
156: u.usym = '@';
157: prme();
158: return 0;
159: }
160:
161: int
162: doeat()
163: {
164: struct obj *otmp;
165: struct objclass *ftmp;
166: int tmp;
167:
168:
169: if (!Levitation)
170: for (otmp = fobj; otmp; otmp = otmp->nobj) {
171: if (otmp->ox == u.ux && otmp->oy == u.uy &&
172: otmp->olet == FOOD_SYM) {
173: pline("There %s %s here; eat %s? [ny] ",
174: (otmp->quan == 1) ? "is" : "are",
175: doname(otmp),
176: (otmp->quan == 1) ? "it" : "one");
177: if (readchar() == 'y') {
178: if (otmp->quan != 1)
179: (void) splitobj(otmp, 1);
180: freeobj(otmp);
181: otmp = addinv(otmp);
182: addtobill(otmp);
183: goto gotit;
184: }
185: }
186: }
187: otmp = getobj("%", "eat");
188: if (!otmp)
189: return (0);
190: gotit:
191: if (otmp->otyp == TIN) {
192: if (uwep) {
193: switch (uwep->otyp) {
194: case CAN_OPENER:
195: tmp = 1;
196: break;
197: case DAGGER:
198: case CRYSKNIFE:
199: tmp = 3;
200: break;
201: case PICK_AXE:
202: case AXE:
203: tmp = 6;
204: break;
205: default:
206: goto no_opener;
207: }
208: pline("Using your %s you try to open the tin.",
209: aobjnam(uwep, (char *) 0));
210: } else {
211: no_opener:
212: pline("It is not so easy to open this tin.");
213: if (Glib) {
214: pline("The tin slips out of your hands.");
215: if (otmp->quan > 1) {
216: struct obj *obj;
217:
218: obj = splitobj(otmp, 1);
219: if (otmp == uwep)
220: setuwep(obj);
221: }
222: dropx(otmp);
223: return (1);
224: }
225: tmp = 10 + rn2(1 + 500 / ((int) (u.ulevel + u.ustr)));
226: }
227: tin.reqtime = tmp;
228: tin.usedtime = 0;
229: tin.tin = otmp;
230: occupation = opentin;
231: occtxt = "opening the tin";
232: return (1);
233: }
234: ftmp = &objects[otmp->otyp];
235: multi = -ftmp->oc_delay;
236: if (otmp->otyp >= CORPSE && eatcorpse(otmp))
237: goto eatx;
238: if (!rn2(7) && otmp->otyp != FORTUNE_COOKIE) {
239: pline("Blecch! Rotten food!");
240: if (!rn2(4)) {
241: pline("You feel rather light headed.");
242: Confusion += d(2, 4);
243: } else if (!rn2(4) && !Blind) {
244: pline("Everything suddenly goes dark.");
245: Blind = d(2, 10);
246: seeoff(0);
247: } else if (!rn2(3)) {
248: if (Blind)
249: pline("The world spins and you slap against the floor.");
250: else
251: pline("The world spins and goes dark.");
252: nomul(-rnd(10));
253: nomovemsg = "You are conscious again.";
254: }
255: lesshungry(ftmp->nutrition / 4);
256: } else {
257: if (u.uhunger >= 1500) {
258: pline("You choke over your food.");
259: pline("You die...");
260: killer = ftmp->oc_name;
261: done("choked");
262: }
263: switch (otmp->otyp) {
264: case FOOD_RATION:
265: if (u.uhunger <= 200)
266: pline("That food really hit the spot!");
267: else if (u.uhunger <= 700)
268: pline("That satiated your stomach!");
269: else {
270: pline("You're having a hard time getting all that food down.");
271: multi -= 2;
272: }
273: lesshungry(ftmp->nutrition);
274: if (multi < 0)
275: nomovemsg = "You finished your meal.";
276: break;
277: case TRIPE_RATION:
278: pline("Yak - dog food!");
279: more_experienced(1, 0);
280: flags.botl = 1;
281: if (rn2(2)) {
282: pline("You vomit.");
283: morehungry(20);
284: if (Sick) {
285: Sick = 0;
286: pline("What a relief!");
287: }
288: } else
289: lesshungry(ftmp->nutrition);
290: break;
291: default:
292: if (otmp->otyp >= CORPSE)
293: pline("That %s tasted terrible!", ftmp->oc_name);
294: else
295: pline("That %s was delicious!", ftmp->oc_name);
296: lesshungry(ftmp->nutrition);
297: if (otmp->otyp == DEAD_LIZARD && (Confusion > 2))
298: Confusion = 2;
299: else
300: #ifdef QUEST
301: if (otmp->otyp == CARROT && !Blind) {
302: u.uhorizon++;
303: setsee();
304: pline("Your vision improves.");
305: } else
306: #endif
307: if (otmp->otyp == FORTUNE_COOKIE) {
308: if (Blind) {
309: pline("This cookie has a scrap of paper inside!");
310: pline("What a pity, that you cannot read it!");
311: } else
312: outrumor();
313: } else if (otmp->otyp == LUMP_OF_ROYAL_JELLY) {
314:
315: if (u.ustrmax < 118)
316: u.ustrmax++;
317: if (u.ustr < u.ustrmax)
318: u.ustr++;
319: u.uhp += rnd(20);
320: if (u.uhp > u.uhpmax) {
321: if (!rn2(17))
322: u.uhpmax++;
323: u.uhp = u.uhpmax;
324: }
325: heal_legs();
326: }
327: break;
328: }
329: }
330: eatx:
331: if (multi < 0 && !nomovemsg) {
332: static char msgbuf[BUFSZ];
333: (void) sprintf(msgbuf, "You finished eating the %s.",
334: ftmp->oc_name);
335: nomovemsg = msgbuf;
336: }
337: useup(otmp);
338: return (1);
339: }
340:
341:
342: void
343: gethungry()
344: {
345: --u.uhunger;
346: if (moves % 2) {
347: if (Regeneration)
348: u.uhunger--;
349: if (Hunger)
350: u.uhunger--;
351:
352:
353:
354:
355: }
356: if (moves % 20 == 0) {
357: if (uleft)
358: u.uhunger--;
359: if (uright)
360: u.uhunger--;
361: }
362: newuhs(TRUE);
363: }
364:
365:
366: void
367: morehungry(num)
368: int num;
369: {
370: u.uhunger -= num;
371: newuhs(TRUE);
372: }
373:
374:
375: void
376: lesshungry(num)
377: int num;
378: {
379: u.uhunger += num;
380: newuhs(FALSE);
381: }
382:
383: int
384: unfaint()
385: {
386: u.uhs = FAINTING;
387: flags.botl = 1;
388: return 0;
389: }
390:
391: void
392: newuhs(incr)
393: boolean incr;
394: {
395: int newhs, h = u.uhunger;
396:
397: newhs = (h > 1000) ? SATIATED :
398: (h > 150) ? NOT_HUNGRY :
399: (h > 50) ? HUNGRY :
400: (h > 0) ? WEAK : FAINTING;
401:
402: if (newhs == FAINTING) {
403: if (u.uhs == FAINTED)
404: newhs = FAINTED;
405: if (u.uhs <= WEAK || rn2(20 - u.uhunger / 10) >= 19) {
406: if (u.uhs != FAINTED && multi >= 0 ) {
407: pline("You faint from lack of food.");
408: nomul(-10 + (u.uhunger / 10));
409: nomovemsg = "You regain consciousness.";
410: afternmv = unfaint;
411: newhs = FAINTED;
412: }
413: } else if (u.uhunger < -(int) (200 + 25 * u.ulevel)) {
414: u.uhs = STARVED;
415: flags.botl = 1;
416: bot();
417: pline("You die from starvation.");
418: done("starved");
419: }
420: }
421: if (newhs != u.uhs) {
422: if (newhs >= WEAK && u.uhs < WEAK)
423: losestr(1);
424: else if (newhs < WEAK && u.uhs >= WEAK && u.ustr < u.ustrmax)
425: losestr(-1);
426: switch (newhs) {
427: case HUNGRY:
428: pline((!incr) ? "You only feel hungry now." :
429: (u.uhunger < 145) ? "You feel hungry." :
430: "You are beginning to feel hungry.");
431: break;
432: case WEAK:
433: pline((!incr) ? "You feel weak now." :
434: (u.uhunger < 45) ? "You feel weak." :
435: "You are beginning to feel weak.");
436: break;
437: }
438: u.uhs = newhs;
439: flags.botl = 1;
440: if (u.uhp < 1) {
441: pline("You die from hunger and exhaustion.");
442: killer = "exhaustion";
443: done("starved");
444: }
445: }
446: }
447:
448: #define CORPSE_I_TO_C(otyp) (char) ((otyp >= DEAD_ACID_BLOB)\
449: ? 'a' + (otyp - DEAD_ACID_BLOB)\
450: : '@' + (otyp - DEAD_HUMAN))
451: int
452: poisonous(otmp)
453: struct obj *otmp;
454: {
455: return (strchr(POISONOUS, CORPSE_I_TO_C(otmp->otyp)) != 0);
456: }
457:
458:
459: int
460: eatcorpse(otmp)
461: struct obj *otmp;
462: {
463: char let = CORPSE_I_TO_C(otmp->otyp);
464: int tp = 0;
465: if (let != 'a' && moves > otmp->age + 50 + rn2(100)) {
466: tp++;
467: pline("Ulch -- that meat was tainted!");
468: pline("You get very sick.");
469: Sick = 10 + rn2(10);
470: u.usick_cause = objects[otmp->otyp].oc_name;
471: } else if (strchr(POISONOUS, let) && rn2(5)) {
472: tp++;
473: pline("Ecch -- that must have been poisonous!");
474: if (!Poison_resistance) {
475: losestr(rnd(4));
476: losehp(rnd(15), "poisonous corpse");
477: } else
478: pline("You don't seem affected by the poison.");
479: } else if (strchr("ELNOPQRUuxz", let) && rn2(5)) {
480: tp++;
481: pline("You feel sick.");
482: losehp(rnd(8), "cadaver");
483: }
484: switch (let) {
485: case 'L':
486: case 'N':
487: case 't':
488: Teleportation |= INTRINSIC;
489: break;
490: case 'W':
491: pluslvl();
492: break;
493: case 'n':
494: u.uhp = u.uhpmax;
495: flags.botl = 1;
496:
497: case '@':
498: pline("You cannibal! You will be sorry for this!");
499:
500:
501: case 'd':
502: Aggravate_monster |= INTRINSIC;
503: break;
504: case 'I':
505: if (!Invis) {
506: Invis = 50 + rn2(100);
507: if (!See_invisible)
508: newsym(u.ux, u.uy);
509: } else {
510: Invis |= INTRINSIC;
511: See_invisible |= INTRINSIC;
512: }
513:
514: case 'y':
515: #ifdef QUEST
516: u.uhorizon++;
517: #endif
518:
519: case 'B':
520: Confusion = 50;
521: break;
522: case 'D':
523: Fire_resistance |= INTRINSIC;
524: break;
525: case 'E':
526: Telepat |= INTRINSIC;
527: break;
528: case 'F':
529: case 'Y':
530: Cold_resistance |= INTRINSIC;
531: break;
532: case 'k':
533: case 's':
534: Poison_resistance |= INTRINSIC;
535: break;
536: case 'c':
537: pline("You turn to stone.");
538: killer = "dead cockatrice";
539: done("died");
540:
541: case 'a':
542: if (Stoned) {
543: pline("What a pity - you just destroyed a future piece of art!");
544: tp++;
545: Stoned = 0;
546: }
547: break;
548: case 'M':
549: pline("You cannot resist the temptation to mimic a treasure chest.");
550: tp++;
551: nomul(-30);
552: afternmv = Meatdone;
553: nomovemsg = "You now again prefer mimicking a human.";
554: u.usym = '$';
555: prme();
556: break;
557: }
558: return (tp);
559: }