pc-hack

PC HACK 3.61 source code (archival)
git clone http://frotz.net/git/pc-hack.git
Log | Files | Refs

eat.c (11887B)


      1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
      2 /* 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 				addtobill(otmp);
    108 				otmp = addinv(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 #ifdef DGK
    156 		set_occupation(opentin, "opening the tin", 0);
    157 #else
    158 		occupation = opentin;
    159 		occtxt = "opening the tin";
    160 #endif
    161 		return(1);
    162 	}
    163 	ftmp = &objects[otmp->otyp];
    164 	multi = -ftmp->oc_delay;
    165 	if(otmp->otyp >= CORPSE && eatcorpse(otmp)) goto eatx;
    166 #ifdef DGK
    167 	if(!rn2(7) && otmp->otyp != FORTUNE_COOKIE && otmp->otyp != DEAD_LIZARD) {
    168 #else
    169 	if(!rn2(7) && otmp->otyp != FORTUNE_COOKIE) {
    170 #endif /* DGK /**/
    171 		pline("Blecch!  Rotten food!");
    172 		if(!rn2(4)) {
    173 			pline("You feel rather light headed.");
    174 			Confusion += d(2,4);
    175 		} else if(!rn2(4)&& !Blind) {
    176 			pline("Everything suddenly goes dark.");
    177 			Blind = d(2,10);
    178 			seeoff(0);
    179 		} else if(!rn2(3)) {
    180 			if(Blind)
    181 			  pline("The world spins and you slap against the floor.");
    182 			else
    183 			  pline("The world spins and goes dark.");
    184 			nomul(-rnd(10));
    185 			nomovemsg = "You are conscious again.";
    186 		}
    187 		lesshungry(ftmp->nutrition / 4);
    188 	} else {
    189 		if(u.uhunger >= 1500) {
    190 			pline("You choke over your food.");
    191 			pline("You die...");
    192 			killer = ftmp->oc_name;
    193 			done("choked");
    194 		}
    195 		switch(otmp->otyp){
    196 		case FOOD_RATION:
    197 			if(u.uhunger <= 200)
    198 				pline("That food really hit the spot!");
    199 			else if(u.uhunger <= 700)
    200 				pline("That satiated your stomach!");
    201 #ifdef DGK
    202 	/* Have lesshungry() report when you're nearly full so all eating
    203 	 * warns when you're about to choke.
    204 	 */
    205 			lesshungry(ftmp->nutrition);
    206 #else
    207 			else {
    208 	pline("You're having a hard time getting all that food down.");
    209 				multi -= 2;
    210 			}
    211 			lesshungry(ftmp->nutrition);
    212 			if(multi < 0) nomovemsg = "You finished your meal.";
    213 #endif /* DGK /**/
    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!");
    225 				}
    226 			} else	lesshungry(ftmp->nutrition);
    227 			break;
    228 		default:
    229 			if(otmp->otyp >= CORPSE)
    230 			pline("That %s tasted terrible!",ftmp->oc_name);
    231 			else
    232 			pline("That %s was delicious!",ftmp->oc_name);
    233 			lesshungry(ftmp->nutrition);
    234 #ifdef DGK
    235 			/* Relief from cockatrices -dgk */
    236 			if (otmp->otyp == DEAD_LIZARD) {
    237 				if (Stoned) {
    238 					Stoned = 0;
    239 					pline("You feel more limber!");
    240 				}
    241 				if (Confusion > 2)
    242 					Confusion = 2;
    243 			}
    244 #else
    245 			if(otmp->otyp == DEAD_LIZARD && (Confusion > 2))
    246 				Confusion = 2;
    247 #endif /* DGK /**/
    248 			else
    249 #ifdef QUEST
    250 			if(otmp->otyp == CARROT && !Blind){
    251 				u.uhorizon++;
    252 				setsee();
    253 				pline("Your vision improves.");
    254 			} else
    255 #endif /* QUEST /**/
    256 			if(otmp->otyp == FORTUNE_COOKIE) {
    257 			  if(Blind) {
    258 			    pline("This cookie has a scrap of paper inside!");
    259 			    pline("What a pity, that you cannot read it!");
    260 			  } else
    261 			    outrumor();
    262 			} else
    263 			if(otmp->otyp == LUMP_OF_ROYAL_JELLY) {
    264 				/* This stuff seems to be VERY healthy! */
    265 				if(u.ustrmax < 118) u.ustrmax++;
    266 				if(u.ustr < u.ustrmax) u.ustr++;
    267 				u.uhp += rnd(20);
    268 				if(u.uhp > u.uhpmax) {
    269 					if(!rn2(17)) u.uhpmax++;
    270 					u.uhp = u.uhpmax;
    271 				}
    272 				heal_legs();
    273 			}
    274 			break;
    275 		}
    276 	}
    277 eatx:
    278 	if(multi<0 && !nomovemsg){
    279 		static char msgbuf[BUFSZ];
    280 		(void) sprintf(msgbuf, "You finished eating the %s.",
    281 				ftmp->oc_name);
    282 		nomovemsg = msgbuf;
    283 	}
    284 	useup(otmp);
    285 	return(1);
    286 }
    287 
    288 /* called in main.c */
    289 gethungry(){
    290 	--u.uhunger;
    291 	if(moves % 2) {
    292 		if(Regeneration) u.uhunger--;
    293 		if(Hunger) u.uhunger--;
    294 		/* a3:  if(Hunger & LEFT_RING) u.uhunger--;
    295 			if(Hunger & RIGHT_RING) u.uhunger--;
    296 		   etc. */
    297 	}
    298 	if(moves % 20 == 0) {			/* jimt@asgb */
    299 		if(uleft) u.uhunger--;
    300 		if(uright) u.uhunger--;
    301 	}
    302 	newuhs(TRUE);
    303 }
    304 
    305 /* called after vomiting and after performing feats of magic */
    306 morehungry(num) register num; {
    307 	u.uhunger -= num;
    308 	newuhs(TRUE);
    309 }
    310 
    311 /* called after eating something (and after drinking fruit juice) */
    312 lesshungry(num) register num; {
    313 	u.uhunger += num;
    314 #ifdef DGK
    315 	/* Have lesshungry() report when you're nearly full so all eating
    316 	 * warns when you're about to choke.
    317 	 */
    318 	if (u.uhunger >= 1500) {
    319 		pline("You're having a hard time getting all of it down.");
    320 		multi -= 2;
    321 		nomovemsg = "You're finally finished.";
    322 	}
    323 #endif /* DGK /**/
    324 	newuhs(FALSE);
    325 }
    326 
    327 unfaint(){
    328 	u.uhs = FAINTING;
    329 	flags.botl = 1;
    330 }
    331 
    332 newuhs(incr) boolean incr; {
    333 	register int newhs, h = u.uhunger;
    334 
    335 	newhs = (h > 1000) ? SATIATED :
    336 		(h > 150) ? NOT_HUNGRY :
    337 		(h > 50) ? HUNGRY :
    338 		(h > 0) ? WEAK : FAINTING;
    339 
    340 	if(newhs == FAINTING) {
    341 		if(u.uhs == FAINTED)
    342 			newhs = FAINTED;
    343 		if(u.uhs <= WEAK || rn2(20-u.uhunger/10) >= 19) {
    344 			if(u.uhs != FAINTED && multi >= 0 /* %% */) {
    345 				pline("You faint from lack of food.");
    346 				nomul(-10+(u.uhunger/10));
    347 				nomovemsg = "You regain consciousness.";
    348 				afternmv = unfaint;
    349 				newhs = FAINTED;
    350 			}
    351 		} else
    352 		if(u.uhunger < -(int)(200 + 25*u.ulevel)) {
    353 			u.uhs = STARVED;
    354 			flags.botl = 1;
    355 			bot();
    356 			pline("You die from starvation.");
    357 			done("starved");
    358 		}
    359 	}
    360 
    361 	if(newhs != u.uhs) {
    362 		if(newhs >= WEAK && u.uhs < WEAK)
    363 			losestr(1);	/* this may kill you -- see below */
    364 		else
    365 		if(newhs < WEAK && u.uhs >= WEAK && u.ustr < u.ustrmax)
    366 			losestr(-1);
    367 		switch(newhs){
    368 		case HUNGRY:
    369 			pline((!incr) ? "You only feel hungry now." :
    370 			      (u.uhunger < 145) ? "You feel hungry." :
    371 				"You are beginning to feel hungry.");
    372 			break;
    373 		case WEAK:
    374 			pline((!incr) ? "You feel weak now." :
    375 			      (u.uhunger < 45) ? "You feel weak." :
    376 				"You are beginning to feel weak.");
    377 			break;
    378 		}
    379 		u.uhs = newhs;
    380 		flags.botl = 1;
    381 		if(u.uhp < 1) {
    382 			pline("You die from hunger and exhaustion.");
    383 			killer = "exhaustion";
    384 			done("starved");
    385 		}
    386 	}
    387 }
    388 
    389 #define	CORPSE_I_TO_C(otyp)	(char) ((otyp >= DEAD_ACID_BLOB)\
    390 		     ?  'a' + (otyp - DEAD_ACID_BLOB)\
    391 		     :	'@' + (otyp - DEAD_HUMAN))
    392 poisonous(otmp)
    393 register struct obj *otmp;
    394 {
    395 	return(index(POISONOUS, CORPSE_I_TO_C(otmp->otyp)) != 0);
    396 }
    397 
    398 /* returns 1 if some text was printed */
    399 eatcorpse(otmp) register struct obj *otmp; {
    400 register char let = CORPSE_I_TO_C(otmp->otyp);
    401 register tp = 0;
    402 	if(let != 'a' && moves > otmp->age + 50 + rn2(100)) {
    403 		tp++;
    404 		pline("Ulch -- that meat was tainted!");
    405 		pline("You get very sick.");
    406 		Sick = 10 + rn2(10);
    407 		u.usick_cause = objects[otmp->otyp].oc_name;
    408 	} else if(index(POISONOUS, let) && rn2(5)){
    409 		tp++;
    410 		pline("Ecch -- that must have been poisonous!");
    411 		if(!Poison_resistance){
    412 			losestr(rnd(4));
    413 			losehp(rnd(15), "poisonous corpse");
    414 		} else
    415 			pline("You don't seem affected by the poison.");
    416 	} else if(index("ELNOPQRUuxz", let) && rn2(5)){
    417 		tp++;
    418 		pline("You feel sick.");
    419 		losehp(rnd(8), "cadaver");
    420 	}
    421 	switch(let) {
    422 	case 'L':
    423 	case 'N':
    424 	case 't':
    425 		Teleportation |= INTRINSIC;
    426 		break;
    427 	case 'W':
    428 		pluslvl();
    429 		break;
    430 	case 'n':
    431 		u.uhp = u.uhpmax;
    432 		flags.botl = 1;
    433 		/* fall into next case */
    434 	case '@':
    435 		pline("You cannibal! You will be sorry for this!");
    436 		/* not tp++; */
    437 		/* fall into next case */
    438 	case 'd':
    439 		Aggravate_monster |= INTRINSIC;
    440 		break;
    441 	case 'I':
    442 		if(!Invis) {
    443 			Invis = 50+rn2(100);
    444 			if(!See_invisible)
    445 				newsym(u.ux, u.uy);
    446 		} else {
    447 			Invis |= INTRINSIC;
    448 			See_invisible |= INTRINSIC;
    449 		}
    450 		/* fall into next case */
    451 	case 'y':
    452 #ifdef QUEST
    453 		u.uhorizon++;
    454 #endif /* QUEST /**/
    455 		/* fall into next case */
    456 	case 'B':
    457 		Confusion = 50;
    458 		break;
    459 	case 'D':
    460 		Fire_resistance |= INTRINSIC;
    461 		break;
    462 	case 'E':
    463 		Telepat |= INTRINSIC;
    464 		break;
    465 	case 'F':
    466 	case 'Y':
    467 		Cold_resistance |= INTRINSIC;
    468 		break;
    469 	case 'k':
    470 	case 's':
    471 		Poison_resistance |= INTRINSIC;
    472 		break;
    473 	case 'c':
    474 		pline("You turn to stone.");
    475 		killer = "dead cockatrice";
    476 		done("died");
    477 		/* NOTREACHED */
    478 	case 'a':
    479 	  if(Stoned) {
    480 	      pline("What a pity - you just destroyed a future piece of art!");
    481 	      tp++;
    482 	      Stoned = 0;
    483 	  }
    484 	  break;
    485 	case 'M':
    486 	  pline("You cannot resist the temptation to mimic a treasure chest.");
    487 	  tp++;
    488 	  nomul(-30);
    489 	  afternmv = Meatdone;
    490 	  nomovemsg = "You now again prefer mimicking a human.";
    491 	  u.usym = '$';
    492 	  prme();
    493 	  break;
    494 	}
    495 	return(tp);
    496 }