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