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