periodic(8): Sync with FreeBSD current
[dragonfly.git] / games / hack / hack.eat.c
blob62f2155b4265cf709ae0e76e671b65ca668d96f2
1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
2 /* hack.eat.c - version 1.0.3 */
3 /* $FreeBSD: src/games/hack/hack.eat.c,v 1.4 1999/11/16 10:26:36 marcel Exp $ */
5 #include "hack.h"
6 char POISONOUS[] = "ADKSVabhks";
8 static bool opentin(void);
9 static void Meatdone(void);
10 static void unfaint(void);
11 static void newuhs(bool);
12 static int eatcorpse(struct obj *);
14 /* hunger texts used on bottom line (each 8 chars long) */
15 #define SATIATED 0
16 #define NOT_HUNGRY 1
17 #define HUNGRY 2
18 #define WEAK 3
19 #define FAINTING 4
20 #define FAINTED 5
21 #define STARVED 6
23 const char *hu_stat[] = {
24 "Satiated",
25 " ",
26 "Hungry ",
27 "Weak ",
28 "Fainting",
29 "Fainted ",
30 "Starved "
33 void
34 init_uhunger(void)
36 u.uhunger = 900;
37 u.uhs = NOT_HUNGRY;
40 #define TTSZ SIZE(tintxts)
41 struct { const char *txt; int nut; } tintxts[] = {
42 { "It contains first quality peaches - what a surprise!", 40 },
43 { "It contains salmon - not bad!", 60 },
44 { "It contains apple juice - perhaps not what you hoped for.", 20 },
45 { "It contains some nondescript substance, tasting awfully.", 500 },
46 { "It contains rotten meat. You vomit.", -50 },
47 { "It turns out to be empty.", 0 }
50 static struct {
51 struct obj *tin;
52 int usedtime, reqtime;
53 } tin;
55 static bool
56 opentin(void)
58 int r;
60 if (!carried(tin.tin)) /* perhaps it was stolen? */
61 return (0); /* %% probably we should use tinoid */
62 if (tin.usedtime++ >= 50) {
63 pline("You give up your attempt to open the tin.");
64 return (0);
66 if (tin.usedtime < tin.reqtime)
67 return (1); /* still busy */
69 pline("You succeed in opening the tin.");
70 useup(tin.tin);
71 r = rn2(2 * TTSZ);
72 if (r < TTSZ) {
73 pline("%s", tintxts[r].txt);
74 lesshungry(tintxts[r].nut);
75 if (r == 1) { /* SALMON */
76 Glib = rnd(15);
77 pline("Eating salmon made your fingers very slippery.");
79 } else {
80 pline("It contains spinach - this makes you feel like Popeye!");
81 lesshungry(600);
82 if (u.ustr < 118)
83 u.ustr += rnd(((u.ustr < 17) ? 19 : 118) - u.ustr);
84 if (u.ustr > u.ustrmax)
85 u.ustrmax = u.ustr;
86 flags.botl = 1;
88 return (0);
91 static void
92 Meatdone(void)
94 u.usym = '@';
95 prme();
98 int
99 doeat(void)
101 struct obj *otmp;
102 struct objclass *ftmp;
103 int tmp;
105 /* Is there some food (probably a heavy corpse) here on the ground? */
106 if (!Levitation)
107 for (otmp = fobj; otmp; otmp = otmp->nobj) {
108 if (otmp->ox == u.ux && otmp->oy == u.uy &&
109 otmp->olet == FOOD_SYM) {
110 pline("There %s %s here; eat %s? [ny] ",
111 (otmp->quan == 1) ? "is" : "are",
112 doname(otmp),
113 (otmp->quan == 1) ? "it" : "one");
114 if (readchar() == 'y') {
115 if (otmp->quan != 1)
116 splitobj(otmp, 1);
117 freeobj(otmp);
118 otmp = addinv(otmp);
119 addtobill(otmp);
120 goto gotit;
125 otmp = getobj("%", "eat");
126 if (!otmp)
127 return (0);
128 gotit:
129 if (otmp->otyp == TIN) {
130 if (uwep) {
131 switch (uwep->otyp) {
132 case CAN_OPENER:
133 tmp = 1;
134 break;
135 case DAGGER:
136 case CRYSKNIFE:
137 tmp = 3;
138 break;
139 case PICK_AXE:
140 case AXE:
141 tmp = 6;
142 break;
143 default:
144 goto no_opener;
146 pline("Using your %s you try to open the tin.",
147 aobjnam(uwep, NULL));
148 } else {
149 no_opener:
150 pline("It is not so easy to open this tin.");
151 if (Glib) {
152 pline("The tin slips out of your hands.");
153 if (otmp->quan > 1) {
154 struct obj *obj;
156 obj = splitobj(otmp, 1);
157 if (otmp == uwep)
158 setuwep(obj);
160 dropx(otmp);
161 return (1);
163 tmp = 10 + rn2(1 + 500 / ((int)(u.ulevel + u.ustr)));
165 tin.reqtime = tmp;
166 tin.usedtime = 0;
167 tin.tin = otmp;
168 occupation = opentin;
169 occtxt = "opening the tin";
170 return (1);
172 ftmp = &objects[otmp->otyp];
173 multi = -ftmp->oc_delay;
174 if (otmp->otyp >= CORPSE && eatcorpse(otmp))
175 goto eatx;
176 if (!rn2(7) && otmp->otyp != FORTUNE_COOKIE) {
177 pline("Blecch! Rotten food!");
178 if (!rn2(4)) {
179 pline("You feel rather light headed.");
180 Confusion += d(2, 4);
181 } else if (!rn2(4) && !Blind) {
182 pline("Everything suddenly goes dark.");
183 Blind = d(2, 10);
184 seeoff(0);
185 } else if (!rn2(3)) {
186 if (Blind)
187 pline("The world spins and you slap against the floor.");
188 else
189 pline("The world spins and goes dark.");
190 nomul(-rnd(10));
191 nomovemsg = "You are conscious again.";
193 lesshungry(ftmp->nutrition / 4);
194 } else {
195 if (u.uhunger >= 1500) {
196 pline("You choke over your food.");
197 pline("You die...");
198 killer = ftmp->oc_name;
199 done("choked");
201 switch (otmp->otyp) {
202 case FOOD_RATION:
203 if (u.uhunger <= 200)
204 pline("That food really hit the spot!");
205 else if (u.uhunger <= 700)
206 pline("That satiated your stomach!");
207 else {
208 pline("You're having a hard time getting all that food down.");
209 multi -= 2;
211 lesshungry(ftmp->nutrition);
212 if (multi < 0)
213 nomovemsg = "You finished your meal.";
214 break;
215 case TRIPE_RATION:
216 pline("Yak - dog food!");
217 more_experienced(1, 0);
218 flags.botl = 1;
219 if (rn2(2)) {
220 pline("You vomit.");
221 morehungry(20);
222 if (Sick) {
223 Sick = 0; /* David Neves */
224 pline("What a relief!");
226 } else
227 lesshungry(ftmp->nutrition);
228 break;
229 default:
230 if (otmp->otyp >= CORPSE)
231 pline("That %s tasted terrible!", ftmp->oc_name);
232 else
233 pline("That %s was delicious!", ftmp->oc_name);
234 lesshungry(ftmp->nutrition);
235 if (otmp->otyp == DEAD_LIZARD && (Confusion > 2))
236 Confusion = 2;
237 else
238 #ifdef QUEST
239 if (otmp->otyp == CARROT && !Blind) {
240 u.uhorizon++;
241 setsee();
242 pline("Your vision improves.");
243 } else
244 #endif /* QUEST */
245 if (otmp->otyp == FORTUNE_COOKIE) {
246 if (Blind) {
247 pline("This cookie has a scrap of paper inside!");
248 pline("What a pity, that you cannot read it!");
249 } else
250 outrumor();
251 } else if (otmp->otyp == LUMP_OF_ROYAL_JELLY) {
252 /* This stuff seems to be VERY healthy! */
253 if (u.ustrmax < 118)
254 u.ustrmax++;
255 if (u.ustr < u.ustrmax)
256 u.ustr++;
257 u.uhp += rnd(20);
258 if (u.uhp > u.uhpmax) {
259 if (!rn2(17))
260 u.uhpmax++;
261 u.uhp = u.uhpmax;
263 heal_legs();
265 break;
268 eatx:
269 if (multi < 0 && !nomovemsg) {
270 static char msgbuf[BUFSZ];
271 sprintf(msgbuf, "You finished eating the %s.", ftmp->oc_name);
272 nomovemsg = msgbuf;
274 useup(otmp);
275 return (1);
278 /* called in hack.main.c */
279 void
280 gethungry(void)
282 --u.uhunger;
283 if (moves % 2) {
284 if (Regeneration)
285 u.uhunger--;
286 if (Hunger)
287 u.uhunger--;
288 /* a3: if (Hunger & LEFT_RING) u.uhunger--;
289 * if (Hunger & RIGHT_RING) u.uhunger--;
290 * etc.
293 if (moves % 20 == 0) { /* jimt@asgb */
294 if (uleft)
295 u.uhunger--;
296 if (uright)
297 u.uhunger--;
299 newuhs(TRUE);
302 /* called after vomiting and after performing feats of magic */
303 void
304 morehungry(int num)
306 u.uhunger -= num;
307 newuhs(TRUE);
310 /* called after eating something (and after drinking fruit juice) */
311 void
312 lesshungry(int num)
314 u.uhunger += num;
315 newuhs(FALSE);
318 static void
319 unfaint(void)
321 u.uhs = FAINTING;
322 flags.botl = 1;
325 static void
326 newuhs(bool incr)
328 int newhs, h = u.uhunger;
330 newhs = (h > 1000) ? SATIATED :
331 (h > 150) ? NOT_HUNGRY :
332 (h > 50) ? HUNGRY :
333 (h > 0) ? WEAK : FAINTING;
335 if (newhs == FAINTING) {
336 if (u.uhs == FAINTED)
337 newhs = FAINTED;
338 if (u.uhs <= WEAK || rn2(20 - u.uhunger / 10) >= 19) {
339 if (u.uhs != FAINTED && multi >= 0 /* %% */) {
340 pline("You faint from lack of food.");
341 nomul(-10 + (u.uhunger / 10));
342 nomovemsg = "You regain consciousness.";
343 afternmv = unfaint;
344 newhs = FAINTED;
346 } else if (u.uhunger < -(int)(200 + 25 * u.ulevel)) {
347 u.uhs = STARVED;
348 flags.botl = 1;
349 bot();
350 pline("You die from starvation.");
351 done("starved");
355 if (newhs != u.uhs) {
356 if (newhs >= WEAK && u.uhs < WEAK)
357 losestr(1); /* this may kill you -- see below */
358 else if (newhs < WEAK && u.uhs >= WEAK && u.ustr < u.ustrmax)
359 losestr(-1);
360 switch (newhs) {
361 case HUNGRY:
362 pline((!incr) ? "You only feel hungry now." :
363 (u.uhunger < 145) ? "You feel hungry." :
364 "You are beginning to feel hungry.");
365 break;
366 case WEAK:
367 pline((!incr) ? "You feel weak now." :
368 (u.uhunger < 45) ? "You feel weak." :
369 "You are beginning to feel weak.");
370 break;
372 u.uhs = newhs;
373 flags.botl = 1;
374 if (u.uhp < 1) {
375 pline("You die from hunger and exhaustion.");
376 killer = "exhaustion";
377 done("starved");
382 #define CORPSE_I_TO_C(otyp) (char)((otyp >= DEAD_ACID_BLOB)\
383 ? 'a' + (otyp - DEAD_ACID_BLOB)\
384 : '@' + (otyp - DEAD_HUMAN))
385 bool
386 poisonous(struct obj *otmp)
388 return (strchr(POISONOUS, CORPSE_I_TO_C(otmp->otyp)) != 0);
391 /* returns 1 if some text was printed */
392 static int
393 eatcorpse(struct obj *otmp)
395 char let = CORPSE_I_TO_C(otmp->otyp);
396 int tp = 0;
398 if (let != 'a' && moves > otmp->age + 50 + rn2(100)) {
399 tp++;
400 pline("Ulch -- that meat was tainted!");
401 pline("You get very sick.");
402 Sick = 10 + rn2(10);
403 u.usick_cause = objects[otmp->otyp].oc_name;
404 } else if (strchr(POISONOUS, let) && rn2(5)) {
405 tp++;
406 pline("Ecch -- that must have been poisonous!");
407 if (!Poison_resistance) {
408 losestr(rnd(4));
409 losehp(rnd(15), "poisonous corpse");
410 } else
411 pline("You don't seem affected by the poison.");
412 } else if (strchr("ELNOPQRUuxz", let) && rn2(5)) {
413 tp++;
414 pline("You feel sick.");
415 losehp(rnd(8), "cadaver");
417 switch (let) {
418 case 'L':
419 case 'N':
420 case 't':
421 Teleportation |= INTRINSIC;
422 break;
423 case 'W':
424 pluslvl();
425 break;
426 case 'n':
427 u.uhp = u.uhpmax;
428 flags.botl = 1;
429 /* FALLTHROUGH */
430 case '@':
431 pline("You cannibal! You will be sorry for this!");
432 /* not tp++; */
433 /* FALLTHROUGH */
434 case 'd':
435 Aggravate_monster |= INTRINSIC;
436 break;
437 case 'I':
438 if (!Invis) {
439 Invis = 50 + rn2(100);
440 if (!See_invisible)
441 newsym(u.ux, u.uy);
442 } else {
443 Invis |= INTRINSIC;
444 See_invisible |= INTRINSIC;
446 /* FALLTHROUGH */
447 case 'y':
448 #ifdef QUEST
449 u.uhorizon++;
450 #endif /* QUEST */
451 /* FALLTHROUGH */
452 case 'B':
453 Confusion = 50;
454 break;
455 case 'D':
456 Fire_resistance |= INTRINSIC;
457 break;
458 case 'E':
459 Telepat |= INTRINSIC;
460 break;
461 case 'F':
462 case 'Y':
463 Cold_resistance |= INTRINSIC;
464 break;
465 case 'k':
466 case 's':
467 Poison_resistance |= INTRINSIC;
468 break;
469 case 'c':
470 pline("You turn to stone.");
471 killer = "dead cockatrice";
472 done("died");
473 /* NOTREACHED */
474 exit(1); /* hint for a compiler */
475 case 'a':
476 if (Stoned) {
477 pline("What a pity - you just destroyed a future piece of art!");
478 tp++;
479 Stoned = 0;
481 break;
482 case 'M':
483 pline("You cannot resist the temptation to mimic a treasure chest.");
484 tp++;
485 nomul(-30);
486 afternmv = Meatdone;
487 nomovemsg = "You now again prefer mimicking a human.";
488 u.usym = '$';
489 prme();
490 break;
492 return (tp);