Home | History | Annotate | Line # | Download | only in hack
hack.eat.c revision 1.1
      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 }
    460