Source:NetHack 3.1.0/eat.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to eat.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.0/eat.c#line123]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

1.    /*	SCCS Id: @(#)eat.c	3.1	92/12/06	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    #include	"hack.h"
6.    /*#define DEBUG		/* uncomment to enable new eat code debugging */
7.    
8.    #ifdef DEBUG
9.    # ifdef WIZARD
10.   #define debugpline	if (wizard) pline
11.   # else
12.   #define debugpline	pline
13.   # endif
14.   #endif
15.   
16.   STATIC_PTR int NDECL(eatmdone);
17.   STATIC_PTR int NDECL(eatfood);
18.   STATIC_PTR int NDECL(opentin);
19.   STATIC_PTR int NDECL(unfaint);
20.   
21.   #ifdef OVLB
22.   static void FDECL(choke, (struct obj *));
23.   static void NDECL(recalc_wt);
24.   static struct obj *FDECL(touchfood, (struct obj *));
25.   static void NDECL(do_reset_eat);
26.   static void FDECL(done_eating, (BOOLEAN_P));
27.   static void FDECL(cprefx, (int));
28.   static int FDECL(intrinsic_possible, (int,struct permonst *));
29.   static void FDECL(givit, (int,struct permonst *));
30.   static void FDECL(cpostfx, (int));
31.   static void FDECL(start_tin, (struct obj *));
32.   static int FDECL(eatcorpse, (struct obj *));
33.   static void FDECL(start_eating, (struct obj *));
34.   static void FDECL(fprefx, (struct obj *));
35.   static void FDECL(fpostfx, (struct obj *));
36.   static int NDECL(bite);
37.   
38.   #ifdef POLYSELF
39.   static int FDECL(rottenfood, (struct obj *));
40.   static void NDECL(eatspecial);
41.   static void FDECL(eatring, (struct obj *));
42.   static const char * FDECL(foodword, (struct obj *));
43.   #else
44.   static int NDECL(rottenfood);
45.   #endif /* POLYSELF */
46.   
47.   char corpsename[60];
48.   char msgbuf[BUFSZ];
49.   
50.   #endif /* OVLB */
51.   
52.   /* hunger texts used on bottom line (each 8 chars long) */
53.   #define SATIATED	0
54.   #define NOT_HUNGRY	1
55.   #define HUNGRY		2
56.   #define WEAK		3
57.   #define FAINTING	4
58.   #define FAINTED		5
59.   #define STARVED		6
60.   
61.   #ifdef OVLB
62.   
63.   const char *hu_stat[] = {
64.   	"Satiated",
65.   	"        ",
66.   	"Hungry  ",
67.   	"Weak    ",
68.   	"Fainting",
69.   	"Fainted ",
70.   	"Starved "
71.   };
72.   
73.   #endif /* OVLB */
74.   
75.   #ifndef OVLB
76.   
77.   STATIC_DCL const char NEARDATA comestibles[];
78.   #ifdef POLYSELF
79.   STATIC_OVL const char NEARDATA allobj[];
80.   #endif /* POLYSELF */
81.   
82.   #else
83.   
84.   STATIC_OVL const char NEARDATA comestibles[] = { FOOD_CLASS, 0 };
85.   
86.   #ifdef POLYSELF
87.   /* Gold must come first for getobj(). */
88.   STATIC_OVL const char NEARDATA allobj[] = {
89.   	GOLD_CLASS, WEAPON_CLASS, ARMOR_CLASS, POTION_CLASS, SCROLL_CLASS,
90.   	WAND_CLASS, RING_CLASS, AMULET_CLASS, FOOD_CLASS, TOOL_CLASS,
91.   	GEM_CLASS, ROCK_CLASS, BALL_CLASS, CHAIN_CLASS, SPBOOK_CLASS, 0 };
92.   #endif /* POLYSELF */
93.   
94.   #endif /* OVLB */
95.   #ifdef OVL1
96.   # ifdef POLYSELF
97.   
98.   boolean
99.   is_edible(obj)
100.  register struct obj *obj;
101.  {
102.  	if (metallivorous(uasmon) && is_metallic(obj))
103.  		return TRUE;
104.  	if (u.umonnum == PM_GELATINOUS_CUBE && is_organic(obj))
105.  		return TRUE;
106.  	return !!index(comestibles, obj->oclass);
107.  }
108.  # endif /* POLYSELF */
109.  #endif /* OVL1 */
110.  #ifdef OVLB
111.  
112.  void
113.  init_uhunger(){
114.  	u.uhunger = 900;
115.  	u.uhs = NOT_HUNGRY;
116.  }
117.  
118.  static const struct { const char *txt; int nut; } tintxts[] = {
119.  	{"deep fried",	 60},
120.  	{"pickled",	 40},
121.  	{"soup made from", 20},
122.  	{"pureed",	500},
123.  	{"rotten",	-50},
124.  	{"homemade",	 50},
125.  	{"", 0}
126.  };
127.  #define	TTSZ	SIZE(tintxts)
128.  
129.  static struct {
130.  	struct	obj *tin;
131.  	int	usedtime, reqtime;
132.  } NEARDATA tin;
133.  
134.  static struct {
135.  	struct	obj *piece;	/* the thing being eaten, or last thing that
136.  				 * was partially eaten, unless that thing was
137.  				 * a tin, which uses the tin structure above */
138.  	int	usedtime,	/* turns spent eating */
139.  		reqtime;	/* turns required to eat */
140.  	int	nmod;		/* coded nutrition per turn */
141.  	Bitfield(canchoke,1);	/* was satiated at beginning */
142.  	Bitfield(fullwarn,1);	/* have warned about being full */
143.  	Bitfield(eating,1);	/* victual currently being eaten */
144.  	Bitfield(doreset,1);	/* stop eating at end of turn */
145.  } NEARDATA victual;
146.  
147.  STATIC_PTR
148.  int
149.  eatmdone() {		/* called after mimicing is over */
150.  	u.usym =
151.  #ifdef POLYSELF
152.  		u.mtimedone ? uasmon->mlet :
153.  #endif
154.  		S_HUMAN;
155.  	newsym(u.ux,u.uy);
156.  	return 0;
157.  }
158.  
159.  /* Created by GAN 01/28/87
160.   * Amended by AKP 09/22/87: if not hard, don't choke, just vomit.
161.   * Amended by 3.  06/12/89: if not hard, sometimes choke anyway, to keep risk.
162.   *		  11/10/89: if hard, rarely vomit anyway, for slim chance.
163.   */
164.  /*ARGSUSED*/
165.  static void
166.  choke(food)	/* To a full belly all food is bad. (It.) */
167.  	register struct obj *food;
168.  {
169.  	/* only happens if you were satiated */
170.  	if(u.uhs != SATIATED) return;
171.  
172.  	if (pl_character[0] == 'K' && u.ualign.type == A_LAWFUL)
173.  		u.ualign.record--;	/* gluttony is unchivalrous */
174.  
175.  	if (!rn2(20)) {
176.  		You("stuff yourself and then vomit voluminously.");
177.  		morehungry(1000);	/* you just got *very* sick! */
178.  		vomit();
179.  	} else {
180.  		killer_format = KILLED_BY_AN;
181.  		/*
182.  		 * Note all "killer"s below read "Choked on %s" on the
183.  		 * high score list & tombstone.  So plan accordingly.
184.  		 */
185.  		if(food) {
186.  #ifdef POLYSELF
187.  			You("choke over your %s.", foodword(food));
188.  			if (food->oclass == GOLD_CLASS) {
189.  				killer_format = KILLED_BY;
190.  				killer = "eating too rich a meal";
191.  			} else {
192.  #else
193.  				You("choke over your food.");
194.  #endif
195.  				killer = singular(food, xname);
196.  #ifdef POLYSELF
197.  			}
198.  #endif
199.  		} else {
200.  			You("choke over it.");
201.  			killer = "quick snack";
202.  		}
203.  		You("die...");
204.  		done(CHOKING);
205.  	}
206.  }
207.  
208.  static void
209.  recalc_wt() {	/* modify object wt. depending on time spent consuming it */
210.  	register struct obj *piece = victual.piece;
211.  
212.  #ifdef DEBUG
213.  	debugpline("Old weight = %d", piece->owt);
214.  	debugpline("Used time = %d, Req'd time = %d",
215.  		victual.usedtime, victual.reqtime);
216.  #endif
217.  	/* weight(piece) = weight of full item */
218.  	if(victual.usedtime)
219.  	    piece->owt = eaten_stat(weight(piece), piece);
220.  #ifdef DEBUG
221.  	debugpline("New weight = %d", piece->owt);
222.  #endif
223.  }
224.  
225.  void
226.  reset_eat() {		/* called when eating interrupted by an event */
227.  
228.      /* we only set a flag here - the actual reset process is done after
229.       * the round is spent eating.
230.       */
231.  	if(victual.eating && !victual.doreset) {
232.  #ifdef DEBUG
233.  	    debugpline("reset_eat...");
234.  #endif
235.  	    victual.doreset = TRUE;
236.  	}
237.  	return;
238.  }
239.  
240.  void
241.  bill_dummy_object(otmp)
242.  register struct obj *otmp;
243.  {
244.  	/* Create a dummy duplicate to put on bill.  The duplicate exists
245.  	 * only in the billobjs chain.  This function is used when a store
246.  	 * object is being altered, and a copy of the original is needed
247.  	 * for billing purposes.
248.  	 */
249.  	register struct obj *dummy;
250.  
251.  	if(otmp->unpaid)
252.  		subfrombill(otmp, shop_keeper(*u.ushops));
253.  	dummy = newobj(otmp->onamelth);
254.  	*dummy = *otmp;
255.  	dummy->o_id = flags.ident++;
256.  	dummy->owt = weight(dummy);
257.  	if(otmp->onamelth)
258.  		(void)strncpy(ONAME(dummy),ONAME(otmp), (int)otmp->onamelth);
259.  	if(Is_candle(dummy)) dummy->lamplit = 0;
260.  	addtobill(dummy, FALSE, TRUE, TRUE);
261.  }
262.  
263.  static struct obj *
264.  touchfood(otmp)
265.  register struct obj *otmp;
266.  {
267.  	if (otmp->quan > 1L) {
268.  	    if(!carried(otmp))
269.  		(void) splitobj(otmp, 1L);
270.  	    else
271.  		otmp = splitobj(otmp, otmp->quan - 1L);
272.  #ifdef DEBUG
273.  	    debugpline("split object,");
274.  #endif
275.  	}
276.  
277.  	if (!otmp->oeaten) {
278.  	    if(((!carried(otmp) && costly_spot(otmp->ox, otmp->oy) &&
279.  		 saleable(rooms[*u.ushops-ROOMOFFSET].rtype-SHOPBASE, otmp))
280.  		 || otmp->unpaid) &&
281.  		 (otmp->otyp == CORPSE || objects[otmp->otyp].oc_delay > 1)) {
282.  		/* create a dummy duplicate to put on bill */
283.  		You("bite it, you bought it!");
284.  		bill_dummy_object(otmp);
285.  	    }
286.  	    otmp->oeaten = (otmp->otyp == CORPSE ?
287.  				(int)mons[otmp->corpsenm].cnutrit :
288.  				objects[otmp->otyp].oc_nutrition);
289.  	}
290.  
291.  	if (carried(otmp)) {
292.  	    freeinv(otmp);
293.  	    if(inv_cnt() >= 52)
294.  		dropy(otmp);
295.  	    else
296.  		otmp = addinv(otmp); /* unlikely but a merge is possible */
297.  	}
298.  	return(otmp);
299.  }
300.  
301.  /* When food decays, in the middle of your meal, we don't want to dereference
302.   * any dangling pointers, so set it to null (which should still trigger
303.   * do_reset_eat() at the beginning of eatfood()) and check for null pointers
304.   * in do_reset_eat().
305.   */
306.  void
307.  food_disappears(obj)
308.  register struct obj *obj;
309.  {
310.  	if (obj == victual.piece) victual.piece = (struct obj *)0;
311.  }
312.  
313.  static void
314.  do_reset_eat() {
315.  
316.  #ifdef DEBUG
317.  	debugpline("do_reset_eat...");
318.  #endif
319.  	if (victual.piece) {
320.  		victual.piece = touchfood(victual.piece);
321.  		recalc_wt();
322.  	}
323.  	victual.fullwarn = victual.eating = victual.doreset = FALSE;
324.  	/* Do not set canchoke to FALSE; if we continue eating the same object
325.  	 * we need to know if canchoke was set when they started eating it the
326.  	 * previous time.  And if we don't continue eating the same object
327.  	 * canchoke always gets recalculated anyway.
328.  	 */
329.  	stop_occupation();
330.  }
331.  
332.  STATIC_PTR
333.  int
334.  eatfood() {		/* called each move during eating process */
335.  	if(!carried(victual.piece) && !obj_here(victual.piece, u.ux, u.uy)) {
336.  		/* maybe it was stolen? */
337.  		do_reset_eat();
338.  		return(0);
339.  	}
340.  	if(!victual.eating) return(0);
341.  
342.  	if(++victual.usedtime < victual.reqtime) {
343.  	    if(bite()) return(0);
344.  	    return(1);	/* still busy */
345.  	} else {	/* done */
346.  	    done_eating(TRUE);
347.  	    return(0);
348.  	}
349.  }
350.  
351.  static void
352.  done_eating(message)
353.  boolean message;
354.  {
355.  #ifndef NO_SIGNAL
356.  	victual.piece->in_use = TRUE;
357.  #endif
358.  	if (nomovemsg) {
359.  		if (message) pline(nomovemsg);
360.  		nomovemsg = 0;
361.  	} else if (message)
362.  		You("finish eating %s.", the(singular(victual.piece, xname)));
363.  
364.  	if(victual.piece->otyp == CORPSE)
365.  		cpostfx(victual.piece->corpsenm);
366.  	else
367.  		fpostfx(victual.piece);
368.  
369.  	if (carried(victual.piece)) useup(victual.piece);
370.  	else useupf(victual.piece);
371.  	victual.piece = (struct obj *) 0;
372.  	victual.fullwarn = victual.eating = victual.doreset = FALSE;
373.  }
374.  
375.  static void
376.  cprefx(pm)
377.  register int pm;
378.  {
379.  	if ((pl_character[0]=='E') ? is_elf(&mons[pm]) : is_human(&mons[pm])) {
380.  		You("cannibal!  You will regret this!");
381.  		Aggravate_monster |= FROMOUTSIDE;
382.  	}
383.  
384.  	switch(pm) {
385.  	    case PM_LITTLE_DOG:
386.  	    case PM_DOG:
387.  	    case PM_LARGE_DOG:
388.  	    case PM_KITTEN:
389.  	    case PM_HOUSECAT:
390.  	    case PM_LARGE_CAT:
391.  		You("feel that eating the %s was a bad idea.", mons[pm].mname);
392.  		Aggravate_monster |= FROMOUTSIDE;
393.  		break;
394.  	    case PM_COCKATRICE:
395.  	    case PM_MEDUSA:
396.  #ifdef POLYSELF
397.  		if(!resists_ston(uasmon))
398.  		    if(!(poly_when_stoned(uasmon) && polymon(PM_STONE_GOLEM)))
399.  #endif
400.  			{
401.  			char *cruft;	/* killer is const char * */
402.  			killer_format = KILLED_BY;
403.  			killer = cruft = (char *)  /* sizeof "s" includes \0 */
404.  					alloc((unsigned) strlen(mons[pm].mname)
405.  						+ sizeof " meat");
406.  			Sprintf(cruft, "%s meat", mons[pm].mname);
407.  			You("turn to stone.");
408.  			done(STONING);
409.  			}
410.  			break;
411.  	    case PM_LIZARD:
412.  		/* Relief from cockatrices -dgk */
413.  		if (Stoned) {
414.  			Stoned = 0;
415.  			You("feel limber!");
416.  		}
417.  		break;
418.  	    case PM_DEATH:
419.  	    case PM_PESTILENCE:
420.  	    case PM_FAMINE:
421.  		{ char buf[BUFSZ];
422.  		    pline("Eating that is instantly fatal.");
423.  		    Sprintf(buf, "unwisely ate the body of %s",
424.  			    mons[pm].mname);
425.  		    killer = buf;
426.  		    killer_format = NO_KILLER_PREFIX;
427.  		    done(DIED);
428.  		    /* It so happens that since we know these monsters */
429.  		    /* cannot appear in tins, victual.piece will always */
430.  		    /* be what we want, which is not generally true. */
431.  		    revive_corpse(victual.piece, 0, FALSE);
432.  		    return;
433.  		}
434.  	    default:
435.  		if(acidic(&mons[pm]) && Stoned) {
436.  		    pline("What a pity - you just destroyed a future piece of art!");
437.  		    Stoned = 0;
438.  		}
439.  	}
440.  	return;
441.  }
442.  
443.  
444.  /*
445.   * If you add an intrinsic that can be gotten by eating a monster, add it
446.   * to intrinsic_possible() and givit().  (It must already be in prop.h to
447.   * be an intrinsic property.)
448.   * It would be very easy to make the intrinsics not try to give you one
449.   * that you already had by checking to see if you have it in
450.   * intrinsic_possible() instead of givit().
451.   */
452.  
453.  /* intrinsic_possible() returns TRUE iff a monster can give an intrinsic. */
454.  static int
455.  intrinsic_possible(type, ptr)
456.  int type;
457.  register struct permonst *ptr;
458.  {
459.  	switch (type) {
460.  	    case FIRE_RES:
461.  #ifdef DEBUG
462.  		if (ptr->mconveys & MR_FIRE) {
463.  			debugpline("can get fire resistance");
464.  			return(TRUE);
465.  		} else  return(FALSE);
466.  #else
467.  		return(ptr->mconveys & MR_FIRE);
468.  #endif
469.  	    case SLEEP_RES:
470.  #ifdef DEBUG
471.  		if (ptr->mconveys & MR_SLEEP) {
472.  			debugpline("can get sleep resistance");
473.  			return(TRUE);
474.  		} else  return(FALSE);
475.  #else
476.  		return(ptr->mconveys & MR_SLEEP);
477.  #endif
478.  	    case COLD_RES:
479.  #ifdef DEBUG
480.  		if (ptr->mconveys & MR_COLD) {
481.  			debugpline("can get cold resistance");
482.  			return(TRUE);
483.  		} else  return(FALSE);
484.  #else
485.  		return(ptr->mconveys & MR_COLD);
486.  #endif
487.  	    case DISINT_RES:
488.  #ifdef DEBUG
489.  		if (ptr->mconveys & MR_DISINT) {
490.  			debugpline("can get disintegration resistance");
491.  			return(TRUE);
492.  		} else  return(FALSE);
493.  #else
494.  		return(ptr->mconveys & MR_DISINT);
495.  #endif
496.  	    case SHOCK_RES:	/* shock (electricity) resistance */
497.  #ifdef DEBUG
498.  		if (ptr->mconveys & MR_ELEC) {
499.  			debugpline("can get shock resistance");
500.  			return(TRUE);
501.  		} else  return(FALSE);
502.  #else
503.  		return(ptr->mconveys & MR_ELEC);
504.  #endif
505.  	    case POISON_RES:
506.  #ifdef DEBUG
507.  		if (ptr->mconveys & MR_POISON) {
508.  			debugpline("can get poison resistance");
509.  			return(TRUE);
510.  		} else  return(FALSE);
511.  #else
512.  		return(ptr->mconveys & MR_POISON);
513.  #endif
514.  	    case TELEPORT:
515.  #ifdef DEBUG
516.  		if (can_teleport(ptr)) {
517.  			debugpline("can get teleport");
518.  			return(TRUE);
519.  		} else  return(FALSE);
520.  #else
521.  		return(can_teleport(ptr));
522.  #endif
523.  	    case TELEPORT_CONTROL:
524.  #ifdef DEBUG
525.  		if (control_teleport(ptr)) {
526.  			debugpline("can get teleport control");
527.  			return(TRUE);
528.  		} else  return(FALSE);
529.  #else
530.  		return(control_teleport(ptr));
531.  #endif
532.  	    case TELEPAT:
533.  #ifdef DEBUG
534.  		if (telepathic(ptr)) {
535.  			debugpline("can get telepathy");
536.  			return(TRUE);
537.  		} else  return(FALSE);
538.  #else
539.  		return(telepathic(ptr));
540.  #endif
541.  	    default:
542.  		return(FALSE);
543.  	}
544.  	/*NOTREACHED*/
545.  }
546.  
547.  /* givit() tries to give you an intrinsic based on the monster's level
548.   * and what type of intrinsic it is trying to give you.
549.   */
550.  static void
551.  givit(type, ptr)
552.  int type;
553.  register struct permonst *ptr;
554.  {
555.  	register int chance;
556.  
557.  #ifdef DEBUG
558.  	debugpline("Attempting to give intrinsic %d", type);
559.  #endif
560.  	/* some intrinsics are easier to get than others */
561.  	switch (type) {
562.  		case POISON_RES:
563.  			if ((ptr == &mons[PM_KILLER_BEE] ||
564.  					ptr == &mons[PM_SCORPION]) && !rn2(4))
565.  				chance = 1;
566.  			else
567.  				chance = 15;
568.  			break;
569.  		case TELEPORT:
570.  			chance = 10;
571.  			break;
572.  		case TELEPORT_CONTROL:
573.  			chance = 12;
574.  			break;
575.  		case TELEPAT:
576.  			chance = 1;
577.  			break;
578.  		default:
579.  			chance = 15;
580.  			break;
581.  	}
582.  
583.  	if (ptr->mlevel <= rn2(chance))
584.  		return;		/* failed die roll */
585.  
586.  	switch (type) {
587.  	    case FIRE_RES:
588.  #ifdef DEBUG
589.  		debugpline("Trying to give fire resistance");
590.  #endif
591.  		if(!(HFire_resistance & FROMOUTSIDE)) {
592.  			You("feel a momentary chill.");
593.  			HFire_resistance |= FROMOUTSIDE;
594.  		}
595.  		break;
596.  	    case SLEEP_RES:
597.  #ifdef DEBUG
598.  		debugpline("Trying to give sleep resistance");
599.  #endif
600.  		if(!(HSleep_resistance & FROMOUTSIDE)) {
601.  			You("feel wide awake.");
602.  			HSleep_resistance |= FROMOUTSIDE;
603.  		}
604.  		break;
605.  	    case COLD_RES:
606.  #ifdef DEBUG
607.  		debugpline("Trying to give cold resistance");
608.  #endif
609.  		if(!(HCold_resistance & FROMOUTSIDE)) {
610.  			You("feel full of hot air.");
611.  			HCold_resistance |= FROMOUTSIDE;
612.  		}
613.  		break;
614.  	    case DISINT_RES:
615.  #ifdef DEBUG
616.  		debugpline("Trying to give disintegration resistance");
617.  #endif
618.  		if(!(HDisint_resistance & FROMOUTSIDE)) {
619.  			You("feel very firm.");
620.  			HDisint_resistance |= FROMOUTSIDE;
621.  		}
622.  		break;
623.  	    case SHOCK_RES:	/* shock (electricity) resistance */
624.  #ifdef DEBUG
625.  		debugpline("Trying to give shock resistance");
626.  #endif
627.  		if(!(HShock_resistance & FROMOUTSIDE)) {
628.  			Your("health currently feels amplified!");
629.  			HShock_resistance |= FROMOUTSIDE;
630.  		}
631.  		break;
632.  	    case POISON_RES:
633.  #ifdef DEBUG
634.  		debugpline("Trying to give poison resistance");
635.  #endif
636.  		if(!(HPoison_resistance & FROMOUTSIDE)) {
637.  			You("feel healthy.");
638.  			HPoison_resistance |= FROMOUTSIDE;
639.  		}
640.  		break;
641.  	    case TELEPORT:
642.  #ifdef DEBUG
643.  		debugpline("Trying to give teleport");
644.  #endif
645.  		if(!(HTeleportation & FROMOUTSIDE)) {
646.  			You("feel very jumpy.");
647.  			HTeleportation |= FROMOUTSIDE;
648.  		}
649.  		break;
650.  	    case TELEPORT_CONTROL:
651.  #ifdef DEBUG
652.  		debugpline("Trying to give teleport control");
653.  #endif
654.  		if(!(HTeleport_control & FROMOUTSIDE)) {
655.  			You("feel in control of yourself.");
656.  			HTeleport_control |= FROMOUTSIDE;
657.  		}
658.  		break;
659.  	    case TELEPAT:
660.  #ifdef DEBUG
661.  		debugpline("Trying to give telepathy");
662.  #endif
663.  		if(!(HTelepat & FROMOUTSIDE)) {
664.  			You("feel a %s mental acuity.",
665.  				Hallucination ? "normal" : "strange");
666.  			HTelepat |= FROMOUTSIDE;
667.  			/* If blind, make sure monsters show up. */
668.  			if (Blind) see_monsters();
669.  		}
670.  		break;
671.  	    default:
672.  #ifdef DEBUG
673.  		debugpline("Tried to give an impossible intrinsic");
674.  #endif
675.  		break;
676.  	}
677.  }
678.  
679.  static void
680.  cpostfx(pm)		/* called after completely consuming a corpse */
681.  register int pm;
682.  {
683.  	register int tmp = 0;
684.  
685.  	switch(pm) {
686.  	    case PM_WRAITH:
687.  		pluslvl();
688.  		break;
689.  #ifdef POLYSELF
690.  	    case PM_HUMAN_WERERAT:
691.  		u.ulycn = PM_WERERAT;
692.  		break;
693.  	    case PM_HUMAN_WEREJACKAL:
694.  		u.ulycn = PM_WEREJACKAL;
695.  		break;
696.  	    case PM_HUMAN_WEREWOLF:
697.  		u.ulycn = PM_WEREWOLF;
698.  		break;
699.  #endif
700.  	    case PM_NURSE:
701.  		u.uhp = u.uhpmax;
702.  		flags.botl = 1;
703.  		break;
704.  	    case PM_STALKER:
705.  		if(!Invis) {
706.  			HInvis = rn1(100, 50);
707.  			if(!See_invisible)
708.  				newsym(u.ux, u.uy);
709.  		} else {
710.  			register long oldprop = See_invisible;
711.  			if (!(HInvis & INTRINSIC)) You("feel hidden!");
712.  			HInvis |= FROMOUTSIDE;
713.  			HSee_invisible |= FROMOUTSIDE;
714.  			if (!oldprop)
715.  				newsym(u.ux, u.uy);
716.  		}
717.  		/* fall into next case */
718.  	    case PM_YELLOW_LIGHT:
719.  		/* fall into next case */
720.  	    case PM_GIANT_BAT:
721.  		make_stunned(HStun + 30,FALSE);
722.  		/* fall into next case */
723.  	    case PM_BAT:
724.  		make_stunned(HStun + 30,FALSE);
725.  		break;
726.  	    case PM_GIANT_MIMIC:
727.  		tmp += 10;
728.  		/* fall into next case */
729.  	    case PM_LARGE_MIMIC:
730.  		tmp += 20;
731.  		/* fall into next case */
732.  	    case PM_SMALL_MIMIC:
733.  		tmp += 20;
734.  		if(u.usym == S_HUMAN) {
735.  		    You("cannot resist the temptation to mimic a pile of gold.");
736.  		    nomul(-tmp);
737.  		    afternmv = eatmdone;
738.  		    if (pl_character[0]=='E')
739.  			nomovemsg = "You now again prefer mimicking an elf.";
740.  		    else
741.  			nomovemsg = "You now again prefer mimicking a human.";
742.  		    u.usym = 0; /* hack! no monster sym 0; use for gold */
743.  		    newsym(u.ux,u.uy);
744.  		}
745.  		break;
746.  	    case PM_QUANTUM_MECHANIC:
747.  		Your("velocity suddenly seems very uncertain!");
748.  		if (Fast & INTRINSIC) {
749.  			Fast &= ~INTRINSIC;
750.  			You("seem slower.");
751.  		} else {
752.  			Fast |= FROMOUTSIDE;
753.  			You("seem faster.");
754.  		}
755.  		break;
756.  	    case PM_LIZARD:
757.  		if (HStun > 2)  make_stunned(2L,FALSE);
758.  		if (HConfusion > 2)  make_confused(2L,FALSE);
759.  		break;
760.  	    case PM_CHAMELEON:
761.  		You("feel a change coming over you.");
762.  #ifdef POLYSELF
763.  		polyself();
764.  #else
765.  		newman();
766.  #endif
767.  		break;
768.  	    case PM_MIND_FLAYER:
769.  		if (ABASE(A_INT) < ATTRMAX(A_INT)) {
770.  			if (!rn2(2)) {
771.  				pline("Yum! That was real brain food!");
772.  				(void) adjattrib(A_INT, 1, FALSE);
773.  				break;	/* don't give them telepathy, too */
774.  			}
775.  		}
776.  		else {
777.  			pline("For some reason, that tasted bland.");
778.  		}
779.  		/* fall through to default case */
780.  	    default: {
781.  		register struct permonst *ptr = &mons[pm];
782.  		int i, count;
783.  
784.  		if(dmgtype(ptr, AD_STUN) || pm==PM_VIOLET_FUNGUS) {
785.  			pline ("Oh wow!  Great stuff!");
786.  			make_hallucinated(HHallucination + 200,FALSE,0L);
787.  		}
788.  		/* prevent polymorph abuse by killing/eating your offspring */
789.  		if(pm >= PM_BABY_GRAY_DRAGON && pm <= PM_BABY_YELLOW_DRAGON)
790.  			return;
791.  		if(is_giant(ptr)) gainstr((struct obj *)0, 0);
792.  
793.  		/* Check the monster for all of the intrinsics.  If this
794.  		 * monster can give more than one, pick one to try to give
795.  		 * from among all it can give.
796.  		 *
797.  		 * If a monster can give 4 intrinsics then you have
798.  		 * a 1/1 * 1/2 * 2/3 * 3/4 = 1/4 chance of getting the first,
799.  		 * a 1/2 * 2/3 * 3/4 = 1/4 chance of getting the second,
800.  		 * a 1/3 * 3/4 = 1/4 chance of getting the third,
801.  		 * and a 1/4 chance of getting the fourth.
802.  		 *
803.  		 * And now a proof by induction:
804.  		 * it works for 1 intrinsic (1 in 1 of getting it)
805.  		 * for 2 you have a 1 in 2 chance of getting the second,
806.  		 *	otherwise you keep the first
807.  		 * for 3 you have a 1 in 3 chance of getting the third,
808.  		 *	otherwise you keep the first or the second
809.  		 * for n+1 you have a 1 in n+1 chance of getting the (n+1)st,
810.  		 *	otherwise you keep the previous one.
811.  		 * Elliott Kleinrock, October 5, 1990
812.  		 */
813.  
814.  		 count = 0;	/* number of possible intrinsics */
815.  		 tmp = 0;	/* which one we will try to give */
816.  		 for (i = 1; i <= LAST_PROP; i++) {
817.  			if (intrinsic_possible(i, ptr)) {
818.  				count++;
819.  				/* a 1 in count chance of replacing the old
820.  				 * one with this one, and a count-1 in count
821.  				 * chance of keeping the old one.  (note
822.  				 * that 1 in 1 and 0 in 1 are what we want
823.  				 * for the first one
824.  				 */
825.  				if (!rn2(count)) {
826.  #ifdef DEBUG
827.  					debugpline("Intrinsic %d replacing %d",
828.  								i, tmp);
829.  #endif
830.  					tmp = i;
831.  				}
832.  			}
833.  		 }
834.  
835.  		 /* if any found try to give them one */
836.  		 if (count) givit(tmp, ptr);
837.  	    }
838.  	    break;
839.  	}
840.  	return;
841.  }
842.  
843.  STATIC_PTR
844.  int
845.  opentin()		/* called during each move whilst opening a tin */
846.  {
847.  	register int r;
848.  
849.  	if(!carried(tin.tin) && !obj_here(tin.tin, u.ux, u.uy))
850.  					/* perhaps it was stolen? */
851.  		return(0);		/* %% probably we should use tinoid */
852.  	if(tin.usedtime++ >= 50) {
853.  		You("give up your attempt to open the tin.");
854.  		return(0);
855.  	}
856.  	if(tin.usedtime < tin.reqtime)
857.  		return(1);		/* still busy */
858.  	if(tin.tin->cursed && tin.tin->spe != -1 && !rn2(8)) {
859.  		b_trapped("tin");
860.  		goto use_me;
861.  	}
862.  	You("succeed in opening the tin.");
863.  	if(tin.tin->spe != 1) {
864.  	    if(tin.tin->corpsenm == -1) {
865.  		pline("It turns out to be empty.");
866.  		tin.tin->dknown = tin.tin->known = TRUE;
867.  		goto use_me;
868.  	    }
869.  	    r = tin.tin->cursed ? 4 :		/* Always rotten if cursed */
870.  		    (tin.tin->spe == -1) ? 5 :	/* "homemade" if player made */
871.  			rn2(TTSZ-1);		/* else take your pick */
872.  	    pline("It smells like %s.", makeplural(
873.  		  Hallucination ? rndmonnam() : mons[tin.tin->corpsenm].mname));
874.  	    if (yn("Eat it?") == 'n') {
875.  		if (!Hallucination) tin.tin->dknown = tin.tin->known = TRUE;
876.  		if (flags.verbose) You("discard the open tin.");
877.  		goto use_me;
878.  	    }
879.  	    You("consume %s %s.", tintxts[r].txt,
880.  			mons[tin.tin->corpsenm].mname);
881.  	    tin.tin->dknown = tin.tin->known = TRUE;
882.  	    cprefx(tin.tin->corpsenm); cpostfx(tin.tin->corpsenm);
883.  
884.  	    /* check for vomiting added by GAN 01/16/87 */
885.  	    if(tintxts[r].nut < 0) make_vomiting((long)rn1(15,10), FALSE);
886.  	    else lesshungry(tintxts[r].nut);
887.  
888.  	    if(r == 0) {			/* Deep Fried */
889.  		Glib = rnd(15);
890.  		pline("Eating deep fried food made your %s very slippery.",
891.  			makeplural(body_part(FINGER)));
892.  	    }
893.  	} else {
894.  	    if (tin.tin->cursed)
895.  		pline("It contains some decaying %s substance.",
896.  			Hallucination ? hcolor() : green);
897.  	    else
898.  		pline("It contains spinach.");
899.  
900.  	    if (yn("Eat it?") == 'n') {
901.  		if (!Hallucination && !tin.tin->cursed)
902.  		    tin.tin->dknown = tin.tin->known = TRUE;
903.  		if (flags.verbose)
904.  		    You("discard the open tin.");
905.  		goto use_me;
906.  	    }
907.  	    if (!tin.tin->cursed)
908.  		pline("This makes you feel like %s!",
909.  		      Hallucination ? "Swee'pea" : "Popeye");
910.  	    lesshungry(600);
911.  	    gainstr(tin.tin, 0);
912.  	}
913.  	tin.tin->dknown = tin.tin->known = TRUE;
914.  use_me:
915.  	if (carried(tin.tin)) useup(tin.tin);
916.  	else useupf(tin.tin);
917.  	tin.tin = (struct obj *) 0;
918.  	return(0);
919.  }
920.  
921.  static void
922.  start_tin(otmp)		/* called when starting to open a tin */
923.  	register struct obj *otmp;
924.  {
925.  	register int tmp;
926.  
927.  #ifdef POLYSELF
928.  	if (metallivorous(uasmon)) {
929.  		You("bite right into the metal tin....");
930.  		tmp = 1;
931.  	} else
932.  #endif
933.  	if (otmp->blessed) {
934.  		pline("The tin opens like magic!");
935.  		tmp = 1;
936.  	} else if(uwep) {
937.  		switch(uwep->otyp) {
938.  		case TIN_OPENER:
939.  			tmp = 1;
940.  			break;
941.  		case DAGGER:
942.  		case ELVEN_DAGGER:
943.  		case ORCISH_DAGGER:
944.  		case ATHAME:
945.  		case CRYSKNIFE:
946.  			tmp = 3;
947.  			break;
948.  		case PICK_AXE:
949.  		case AXE:
950.  			tmp = 6;
951.  			break;
952.  		default:
953.  			goto no_opener;
954.  		}
955.  		pline("Using your %s you try to open the tin.",
956.  			aobjnam(uwep, NULL));
957.  	} else {
958.  no_opener:
959.  		pline("It is not so easy to open this tin.");
960.  		if(Glib) {
961.  			pline("The tin slips out of your hands.");
962.  			if(otmp->quan > 1L) {
963.  				register struct obj *obj;
964.  				obj = splitobj(otmp, 1L);
965.  				if(otmp == uwep) setuwep(obj);
966.  			}
967.  			if (carried(otmp)) dropx(otmp);
968.  			else stackobj(otmp);
969.  			return;
970.  		}
971.  		tmp = rn1(1 + 500/((int)(ACURR(A_DEX) + ACURRSTR)), 10);
972.  	}
973.  	tin.reqtime = tmp;
974.  	tin.usedtime = 0;
975.  	tin.tin = otmp;
976.  	set_occupation(opentin, "opening the tin", 0);
977.  	return;
978.  }
979.  
980.  int
981.  Hear_again() {		/* called when waking up after fainting */
982.  	flags.soundok = 1;
983.  	return 0;
984.  }
985.  
986.  static int
987.  #ifdef POLYSELF
988.  rottenfood(obj)
989.  struct obj *obj;
990.  #else
991.  rottenfood()
992.  #endif
993.  {		/* called on the "first bite" of rotten food */
994.  #ifdef POLYSELF
995.  	pline("Blecch!  Rotten %s!", foodword(obj));
996.  #else
997.  	pline("Blecch!  Rotten food!");
998.  #endif
999.  	if(!rn2(4)) {
1000. 		if (Hallucination) You("feel rather trippy.");
1001. 		else You("feel rather %s.", body_part(LIGHT_HEADED));
1002. 		make_confused(HConfusion + d(2,4),FALSE);
1003. 	} else if(!rn2(4) && !Blind) {
1004. 		pline("Everything suddenly goes dark.");
1005. 		make_blinded((long)d(2,10),FALSE);
1006. 	} else if(!rn2(3)) {
1007. 		if(Blind)
1008. 		  pline("The world spins and you slap against the floor.");
1009. 		else
1010. 		  pline("The world spins and goes dark.");
1011. 		flags.soundok = 0;
1012. 		nomul(-rnd(10));
1013. 		nomovemsg = "You are conscious again.";
1014. 		afternmv = Hear_again;
1015. 		return(1);
1016. 	}
1017. 	return(0);
1018. }
1019. 
1020. static int
1021. eatcorpse(otmp)		/* called when a corpse is selected as food */
1022. 	register struct obj *otmp;
1023. {
1024. 	register const char *cname = mons[otmp->corpsenm].mname;
1025. 	register int tp, rotted = 0;
1026. 
1027. 	tp = 0;
1028. 
1029. 	if(otmp->corpsenm != PM_LIZARD) {
1030. #ifndef LINT	/* problem if more than 320K moves before try to eat */
1031. 		rotted = (monstermoves - otmp->age)/((long)(10 + rn2(20)));
1032. #endif
1033. 
1034. 		if(otmp->cursed) rotted += 2;
1035. 		else if (otmp->blessed) rotted -= 2;
1036. 	}
1037. 
1038. 	if(otmp->corpsenm != PM_ACID_BLOB && (rotted > 5)) {
1039. 		pline("Ulch - that %s was tainted!",
1040. 		      mons[otmp->corpsenm].mlet == S_FUNGUS ? "fungoid vegetation" :
1041. 		      is_meaty(&mons[otmp->corpsenm]) ? "meat" : "protoplasm");
1042. #ifdef POLYSELF
1043. 		if (u.usym == S_FUNGUS)
1044. 			pline("It doesn't seem at all sickening, though...");
1045. 		else {
1046. #endif
1047. 			make_sick((long) rn1(10, 10),FALSE);
1048. 			Sprintf(corpsename, "rotted %s corpse", cname);
1049. 			u.usick_cause = (const char *)corpsename;
1050. 			flags.botl = 1;
1051. #ifdef POLYSELF
1052. 		}
1053. #endif
1054. 		if (carried(otmp)) useup(otmp);
1055. 		else useupf(otmp);
1056. 		return(1);
1057. 	} else if(acidic(&mons[otmp->corpsenm])
1058. #ifdef POLYSELF
1059. 		  && !resists_acid(uasmon)
1060. #endif
1061. 		 ) {
1062. 		tp++;
1063. 		You("have a very bad case of stomach acid.");
1064. 		losehp(rnd(15), "acidic corpse", KILLED_BY_AN);
1065. 	} else if(poisonous(&mons[otmp->corpsenm]) && rn2(5)) {
1066. 		tp++;
1067. 		pline("Ecch - that must have been poisonous!");
1068. 		if(!Poison_resistance) {
1069. 			losestr(rnd(4));
1070. 			losehp(rnd(15), "poisonous corpse", KILLED_BY_AN);
1071. 		} else	You("seem unaffected by the poison.");
1072. 	/* now any corpse left too long will make you mildly ill */
1073. 	} else if(((rotted > 5) || ((rotted > 3) && rn2(5)))
1074. #ifdef POLYSELF
1075. 		&& u.usym != S_FUNGUS
1076. #endif
1077. 							){
1078. 		tp++;
1079. 		You("feel%s sick.", (Sick) ? " very" : "");
1080. 		losehp(rnd(8), "cadaver", KILLED_BY_AN);
1081. 	}
1082. 	if(!tp && otmp->corpsenm != PM_LIZARD && (otmp->orotten || !rn2(7))) {
1083. #ifdef POLYSELF
1084. 	    if(rottenfood(otmp)) {
1085. #else
1086. 	    if(rottenfood()) {
1087. #endif
1088. 		otmp->orotten = TRUE;
1089. 		(void)touchfood(otmp);
1090. 		return(1);
1091. 	    }
1092. 	    otmp->oeaten >>= 2;
1093. 	} else {
1094. #ifdef POLYSELF
1095. 	    pline("This %s corpse %s!", cname,
1096. 		(carnivorous(uasmon) && !herbivorous(uasmon))
1097. 		? "is delicious" : "tastes terrible");
1098. #else
1099. 	    pline("This %s corpse tastes terrible!", cname);
1100. #endif
1101. 	}
1102. 
1103. 	/* delay is weight dependent */
1104. 	victual.reqtime = 3 + (mons[otmp->corpsenm].cwt >> 6);
1105. 	return(0);
1106. }
1107. 
1108. static void
1109. start_eating(otmp)		/* called as you start to eat */
1110. 	register struct obj *otmp;
1111. {
1112. #ifdef DEBUG
1113. 	debugpline("start_eating: %lx (victual = %lx)", otmp, victual.piece);
1114. 	debugpline("reqtime = %d", victual.reqtime);
1115. 	debugpline("(original reqtime = %d)", objects[otmp->otyp].oc_delay);
1116. 	debugpline("nmod = %d", victual.nmod);
1117. 	debugpline("oeaten = %d", otmp->oeaten);
1118. #endif
1119. 	victual.fullwarn = victual.doreset = FALSE;
1120. 	victual.eating = TRUE;
1121. 
1122. 	if (otmp->otyp == CORPSE) {
1123. 	    cprefx(victual.piece->corpsenm);
1124. 	    if (!victual.piece && victual.eating) do_reset_eat();
1125. 	    if (victual.eating == FALSE) return; /* died and lifesaved */
1126. 	}
1127. 
1128. 	if (bite()) return;
1129. 
1130. 	if(++victual.usedtime >= victual.reqtime) {
1131. 	    /* print "finish eating" message if they just resumed -dlc */
1132. 	    done_eating(victual.reqtime > 1 ? TRUE : FALSE);
1133. 	    return;
1134. 	}
1135. 
1136. 	Sprintf(msgbuf, "eating %s", the(singular(otmp, xname)));
1137. 	set_occupation(eatfood, msgbuf, 0);
1138. }
1139. 
1140. 
1141. static void
1142. fprefx(otmp)		/* called on "first bite" of (non-corpse) food */
1143. 
1144. 	register struct obj *otmp;
1145. {
1146. 	switch(otmp->otyp) {
1147. 
1148. 	    case FOOD_RATION:
1149. 		if(u.uhunger <= 200)
1150. 		    if (Hallucination) pline("Oh wow, like, superior, man!");
1151. 		    else	       pline("That food really hit the spot!");
1152. 		else if(u.uhunger <= 700) pline("That satiated your stomach!");
1153. 		break;
1154. 	    case TRIPE_RATION:
1155. #ifdef POLYSELF
1156. 		if (carnivorous(uasmon) && !humanoid(uasmon))
1157. 		    pline("That tripe ration was surprisingly good!");
1158. 		else {
1159. #endif
1160. 		    pline("Yak - dog food!");
1161. 		    more_experienced(1,0);
1162. 		    flags.botl = 1;
1163. #ifdef POLYSELF
1164. 		}
1165. #endif
1166. 		if(rn2(2)
1167. #ifdef POLYSELF
1168. 			&& (!carnivorous(uasmon) || humanoid(uasmon))
1169. #endif
1170. 						) {
1171. 			make_vomiting((long)rn1(victual.reqtime, 14), FALSE);
1172. 		}
1173. 		break;
1174. #ifdef POLYSELF
1175. 	    case CLOVE_OF_GARLIC:
1176. 		if (is_undead(uasmon)) {
1177. 			make_vomiting((long)rn1(victual.reqtime, 5), FALSE);
1178. 			break;
1179. 		}
1180. 		/* Fall through otherwise */
1181. #endif
1182. 	    default:
1183. #ifdef TUTTI_FRUTTI
1184. 		if (otmp->otyp==SLIME_MOLD && !otmp->cursed
1185. 			&& otmp->spe == current_fruit)
1186. 		    pline("My, that was a yummy %s!", singular(otmp, xname));
1187. 		else
1188. #endif
1189. #ifdef UNIX
1190. 		if (otmp->otyp == APPLE || otmp->otyp == PEAR) {
1191. 		    if (!Hallucination) pline("Core dumped.");
1192. 		    else {
1193. /* This is based on an old Usenet joke, a fake a.out manual page */
1194. 			int x = rnd(100);
1195. 			if (x <= 75)
1196. 			    pline("Segmentation fault -- core dumped.");
1197. 			else if (x <= 99)
1198. 			    pline("Bus error -- core dumped.");
1199. 			else pline("Yo' mama -- core dumped.");
1200. 		    }
1201. 		} else
1202. #endif
1203. 		    pline("This %s is %s!", singular(otmp, xname),
1204. 		      otmp->cursed ? (Hallucination ? "grody" : "terrible"):
1205. 		      Hallucination ? "gnarly" :
1206. 			(otmp->otyp==CRAM_RATION ? "bland" : "delicious"));
1207. 		break;
1208. 	}
1209. }
1210. 
1211. #ifdef POLYSELF
1212. static void
1213. eatring(otmp)
1214. struct obj *otmp;
1215. {
1216. 	int typ = otmp->otyp;
1217. 	int oldprop;
1218. 
1219. 	/* Note: rings are not so common that this is unbalancing.  (How */
1220. 	/* often do you even _find_ 3 rings of polymorph in a game? */
1221. 	oldprop = !!(u.uprops[objects[typ].oc_oprop].p_flgs);
1222. 	otmp->known = otmp->dknown = 1; /* by taste */
1223. 	if (!rn2(3)) switch (otmp->otyp) {
1224. 	    case RIN_AGGRAVATE_MONSTER:
1225. 	    case RIN_WARNING:
1226. 	    case RIN_POISON_RESISTANCE:
1227. 	    case RIN_FIRE_RESISTANCE:
1228. 	    case RIN_COLD_RESISTANCE:
1229. 	    case RIN_SHOCK_RESISTANCE:
1230. 	    case RIN_TELEPORTATION:
1231. 	    case RIN_TELEPORT_CONTROL:
1232. 	    case RIN_SEE_INVISIBLE:
1233. 	    case RIN_PROTECTION_FROM_SHAPE_CHAN:
1234. 	    case RIN_SEARCHING:
1235. 	    case RIN_STEALTH:
1236. 	    case RIN_INVISIBILITY:
1237. 	    case RIN_CONFLICT:
1238. 	    case RIN_POLYMORPH:
1239. 	    case RIN_POLYMORPH_CONTROL:
1240. 	    case RIN_REGENERATION: /* Probably stupid. */
1241. 	    case RIN_HUNGER: /* Stupid. */
1242. 	    case RIN_LEVITATION: /* Stupid. */
1243. 		if (!(u.uprops[objects[typ].oc_oprop].p_flgs & FROMOUTSIDE))
1244. 		    pline("Magic spreads through your body as you digest the ring.");
1245. 		u.uprops[objects[typ].oc_oprop].p_flgs |= FROMOUTSIDE;
1246. 		if (typ == RIN_SEE_INVISIBLE) {
1247. 		    set_mimic_blocking();
1248. 		    see_monsters();
1249. 		    if (Invis && !oldprop
1250. #ifdef POLYSELF
1251. 				&& !perceives(uasmon)
1252. #endif
1253. 							&& !Blind) {
1254. 			newsym(u.ux,u.uy);
1255. 			pline("Suddenly you can see yourself.");
1256. 			makeknown(typ);
1257. 		    }
1258. 		} else if (typ == RIN_INVISIBILITY) {
1259. 		    if (!oldprop && !See_invisible && !Blind) {
1260. 			newsym(u.ux,u.uy);
1261. 			Your("body takes on a %s transparency...",
1262. 				Hallucination ? "normal" : "strange");
1263. 			makeknown(typ);
1264. 		    }
1265. 		} else if (typ == RIN_PROTECTION_FROM_SHAPE_CHAN)
1266. 		    rescham();
1267. 		else if (typ == RIN_LEVITATION) {
1268. 		    if (!Levitation) {
1269. 			float_up();
1270. 			makeknown(typ);
1271. 		    }
1272. 		}
1273. 		break;
1274. 	    case RIN_ADORNMENT:
1275. 		if (adjattrib(A_CHA, otmp->spe, -1))
1276. 		    makeknown(typ);
1277. 		break;
1278. 	    case RIN_GAIN_STRENGTH:
1279. 	    case RIN_INCREASE_DAMAGE: /* Any better ideas? */
1280. 		if (adjattrib(A_STR, otmp->spe, -1))
1281. 		    makeknown(typ);
1282. 		break;
1283. 	    case RIN_PROTECTION:
1284. 		Protection |= FROMOUTSIDE;
1285. 		u.ublessed += otmp->spe;
1286. 		flags.botl = 1;
1287. 		break;
1288. 	}
1289. }
1290. 
1291. static void
1292. eatspecial() /* called after eating non-food */
1293. {
1294. 	register struct obj *otmp = victual.piece;
1295. 
1296. 	lesshungry(victual.nmod);
1297. 	victual.piece = (struct obj *)0;
1298. 	victual.eating = 0;
1299. 	if (otmp->oclass == GOLD_CLASS) {
1300. 		dealloc_obj(otmp);
1301. 		return;
1302. 	}
1303. 	if (otmp->oclass == POTION_CLASS) {
1304. 		otmp->quan++; /* dopotion() does a useup() */
1305. 		(void)dopotion(otmp);
1306. 	}
1307. 	if (otmp->oclass == RING_CLASS)
1308. 		eatring(otmp);
1309. 	if (otmp == uball) unpunish();
1310. 	if (otmp == uchain) unpunish(); /* but no useup() */
1311. 	else if (carried(otmp)) useup(otmp);
1312. 	else useupf(otmp);
1313. }
1314. 
1315. /* NOTE: the order of these words exactly corresponds to the
1316.    order of oc_material values #define'd in objclass.h. */
1317. static const char *foodwords[] = {
1318. 	"meal", "liquid", "wax", "food", "meat",
1319. 	"paper", "cloth", "leather", "wood", "bone", "scale",
1320. 	"metal", "metal", "metal", "silver", "gold", "platinum", "mithril",
1321. 	"plastic", "glass", "rich food", "stone"
1322. };
1323. 
1324. static const char *
1325. foodword(otmp)
1326. register struct obj *otmp;
1327. {
1328. 	if (otmp->oclass == FOOD_CLASS) return "food";
1329. 	if (otmp->oclass == GEM_CLASS &&
1330. 	    objects[otmp->otyp].oc_material == GLASS &&
1331. 	    otmp->dknown)
1332. 		makeknown(otmp->otyp);
1333. 	return foodwords[objects[otmp->otyp].oc_material];
1334. }
1335. #endif
1336. 
1337. static void
1338. fpostfx(otmp)		/* called after consuming (non-corpse) food */
1339. 
1340. 	register struct obj *otmp;
1341. {
1342. 	switch(otmp->otyp) {
1343. #ifdef POLYSELF
1344. 	    case SPRIG_OF_WOLFSBANE:
1345. 		if (u.ulycn != -1) {
1346. 		    u.ulycn = -1;
1347. 		    You("feel purified.");
1348. 		    if(uasmon == &mons[u.ulycn] && !Polymorph_control)
1349. 			rehumanize();
1350. 		}
1351. 		break;
1352. #endif
1353. 	    case CARROT:
1354. 		make_blinded(0L,TRUE);
1355. 		break;
1356. 	    case FORTUNE_COOKIE:
1357. 		outrumor(bcsign(otmp), TRUE);
1358. 		break;
1359. 	    case LUMP_OF_ROYAL_JELLY:
1360. 		/* This stuff seems to be VERY healthy! */
1361. 		gainstr(otmp, 1);
1362. 		u.uhp += (otmp->cursed) ? -rnd(20) : rnd(20);
1363. 		if(u.uhp > u.uhpmax) {
1364. 			if(!rn2(17)) u.uhpmax++;
1365. 			u.uhp = u.uhpmax;
1366. 		} else if(u.uhp <= 0) {
1367. 			killer_format = KILLED_BY_AN;
1368. 			killer = "rotten lump of royal jelly";
1369. 			done(POISONING);
1370. 		}
1371. 		if(!otmp->cursed) heal_legs();
1372. 		break;
1373. 	    case EGG:
1374. 		if(otmp->corpsenm == PM_COCKATRICE) {
1375. #ifdef POLYSELF
1376. 		    if(!resists_ston(uasmon))
1377. 			if(!poly_when_stoned(uasmon) ||
1378. 			   !polymon(PM_STONE_GOLEM))
1379. 		    {
1380. #endif
1381. 			if (!Stoned) Stoned = 5;
1382. 			killer_format = KILLED_BY_AN;
1383. 			killer = "cockatrice egg";
1384. #ifdef POLYSELF
1385. 		    }
1386. #endif
1387. 		}
1388. 		break;
1389. 	}
1390. 	return;
1391. }
1392. 
1393. int
1394. doeat()		/* generic "eat" command funtion (see cmd.c) */
1395. {
1396. 	register struct obj *otmp;
1397. 	int basenutrit;			/* nutrition of full item */
1398. 
1399. 	if (Strangled) {
1400. 		pline("If you can't breathe air, how can you consume solids?");
1401. 		return 0;
1402. 	}
1403. 	if (!(otmp = floorfood("eat", 0))) return 0;
1404. 	if (check_capacity(NULL)) return 0;
1405. #ifdef POLYSELF
1406. 	/* We have to make non-foods take no time to eat, unless we want to
1407. 	 * do ridiculous amounts of coding to deal with partly eaten plate
1408. 	 * mails, players who polymorph back to human in the middle of their
1409. 	 * metallic meal, etc....
1410. 	 */
1411. 	if (!is_edible(otmp)) {
1412. 	    You("cannot eat that!");
1413. 	    return 0;
1414. 	}
1415. 	if (otmp->oclass != FOOD_CLASS) {
1416. 	    victual.reqtime = 1;
1417. 	    victual.piece = otmp;
1418. 		/* Don't split it, we don't need to if it's 1 move */
1419. 	    victual.usedtime = 0;
1420. 	    victual.canchoke = (u.uhs == SATIATED);
1421. 		/* Note: gold weighs 1 pt. for each 1000 pieces (see */
1422. 		/* pickup.c) so gold and non-gold is consistent. */
1423. 	    if (otmp->oclass == GOLD_CLASS)
1424. 		basenutrit = ((otmp->quan > 200000L) ? 2000
1425. 			: (int)(otmp->quan/100L));
1426. 	    else basenutrit = objects[otmp->otyp].oc_nutrition;
1427. 	    victual.nmod = basenutrit;
1428. 	    victual.eating = TRUE; /* needed for lesshungry() */
1429. 
1430. 	    if (otmp->cursed)
1431. 		(void) rottenfood(otmp);
1432. 
1433. 	    if (otmp->oclass == WEAPON_CLASS && otmp->opoisoned) {
1434. 		pline("Ecch - that must have been poisonous!");
1435. 		if(!Poison_resistance) {
1436. 		    losestr(rnd(4));
1437. 		    losehp(rnd(15), xname(otmp), KILLED_BY_AN);
1438. 		} else
1439. 		    You("seem unaffected by the poison.");
1440. 	    } else if (!otmp->cursed)
1441. 		pline("This %s is delicious!",
1442. 		      otmp->oclass == GOLD_CLASS ? foodword(otmp) :
1443. 		      singular(otmp, xname));
1444. 	    eatspecial();
1445. 	    return 1;
1446. 	}
1447. #endif
1448. 
1449. 	if(otmp == victual.piece) {
1450. 	/* If they weren't able to choke, they don't suddenly become able to
1451. 	 * choke just because they were interrupted.  On the other hand, if
1452. 	 * they were able to choke before, if they lost food it's possible
1453. 	 * they shouldn't be able to choke now.
1454. 	 */
1455. 	    if (u.uhs != SATIATED) victual.canchoke = FALSE;
1456. 	    if(!carried(victual.piece)) {
1457. 		if(victual.piece->quan > 1L)
1458. 			(void) splitobj(victual.piece, 1L);
1459. 	    }
1460. 	    You("resume your meal.");
1461. 	    start_eating(victual.piece);
1462. 	    return(1);
1463. 	}
1464. 
1465. 	/* nothing in progress - so try to find something. */
1466. 	/* tins are a special case */
1467. 	if(otmp->otyp == TIN) {
1468. 	    start_tin(otmp);
1469. 	    return(1);
1470. 	}
1471. 
1472. 	victual.piece = otmp = touchfood(otmp);
1473. 	victual.usedtime = 0;
1474. 
1475. 	/* Now we need to calculate delay and nutritional info.
1476. 	 * The base nutrition calculated here and in eatcorpse() accounts
1477. 	 * for normal vs. rotten food.  The reqtime and nutrit values are
1478. 	 * then adjusted in accordance with the amount of food left.
1479. 	 */
1480. 	if(otmp->otyp == CORPSE) {
1481. 	    if(eatcorpse(otmp)) return(1);
1482. 	    /* else eatcorpse sets up reqtime and oeaten */
1483. 	} else {
1484. 	    victual.reqtime = objects[otmp->otyp].oc_delay;
1485. 	    if (otmp->otyp != FORTUNE_COOKIE &&
1486. 		(otmp->cursed ||
1487. 		 (((monstermoves - otmp->age) > (int) otmp->blessed ? 50:30) &&
1488. 		(otmp->orotten || !rn2(7))))) {
1489. 
1490. #ifdef POLYSELF
1491. 		if(rottenfood(otmp)) {
1492. #else
1493. 		if(rottenfood()) {
1494. #endif
1495. 		    otmp->orotten = TRUE;
1496. 		    return(1);
1497. 		}
1498. 		otmp->oeaten >>= 1;
1499. 	    } else fprefx(otmp);
1500. 	}
1501. 
1502. 	/* re-calc the nutrition */
1503. 	if (otmp->otyp == CORPSE) basenutrit = mons[otmp->corpsenm].cnutrit;
1504. 	else basenutrit = objects[otmp->otyp].oc_nutrition;
1505. 
1506. #ifdef DEBUG
1507. 	debugpline("before rounddiv: victual.reqtime == %d", victual.reqtime);
1508. 	debugpline("oeaten == %d, basenutrit == %d", otmp->oeaten, basenutrit);
1509. #endif
1510. 	victual.reqtime = (basenutrit == 0 ? 0 :
1511. 		rounddiv(victual.reqtime * (long)otmp->oeaten, basenutrit));
1512. #ifdef DEBUG
1513. 	debugpline("after rounddiv: victual.reqtime == %d", victual.reqtime);
1514. #endif
1515. 	/* calculate the modulo value (nutrit. units per round eating)
1516. 	 * note: this isn't exact - you actually lose a little nutrition
1517. 	 *	 due to this method.
1518. 	 * TODO: add in a "remainder" value to be given at the end of the
1519. 	 *	 meal.
1520. 	 */
1521. 	if(victual.reqtime == 0)
1522. 	    /* possible if most has been eaten before */
1523. 	    victual.nmod = 0;
1524. 	else if (otmp->oeaten > victual.reqtime)
1525. 	    victual.nmod = -(otmp->oeaten / victual.reqtime);
1526. 	else
1527. 	    victual.nmod = victual.reqtime % otmp->oeaten;
1528. 	victual.canchoke = (u.uhs == SATIATED);
1529. 
1530. 	start_eating(otmp);
1531. 	return(1);
1532. }
1533. 
1534. /* Take a single bite from a piece of food, checking for choking and
1535.  * modifying usedtime.  Returns 1 if they choked and survived, 0 otherwise.
1536.  */
1537. static int
1538. bite()
1539. {
1540. 	if(victual.canchoke && u.uhunger >= 2000) {
1541. 		choke(victual.piece);
1542. 		return 1;
1543. 	}
1544. 	if (victual.doreset) {
1545. 		do_reset_eat();
1546. 		return 0;
1547. 	}
1548. 	if(victual.nmod < 0) {
1549. 		lesshungry(-victual.nmod);
1550. 		victual.piece->oeaten -= -victual.nmod;
1551. 	} else if(victual.nmod > 0 && (victual.usedtime % victual.nmod)) {
1552. 		lesshungry(1);
1553. 		victual.piece->oeaten--;
1554. 	}
1555. 	recalc_wt();
1556. 	return 0;
1557. }
1558. 
1559. #endif /* OVLB */
1560. #ifdef OVL0
1561. 
1562. void
1563. gethungry()	/* as time goes by - called by moveloop() and domove() */
1564. {
1565. 	if (u.uinvulnerable) return;	/* you don't feel hungrier */
1566. 
1567. 	if ((!u.usleep || !rn2(10))	/* slow metabolic rate while asleep */
1568. 		&& (carnivorous(uasmon) || herbivorous(uasmon)))
1569. 	    u.uhunger--;		/* ordinary food consumption */
1570. 
1571. 	if (moves % 2) {	/* odd turns */
1572. 	    /* Regeneration uses up food, unless due to an artifact */
1573. 	    if ((HRegeneration & (~W_ART)) &&
1574. 		(HRegeneration != W_WEP || !uwep->oartifact)) u.uhunger--;
1575. 	    if (near_capacity() > SLT_ENCUMBER) u.uhunger--;
1576. 	} else {		/* even turns */
1577. 	    if (Hunger) u.uhunger--;
1578. 	    /* Conflict uses up food too */
1579. 	    if ((Conflict & (~W_ARTI))) u.uhunger--;
1580. 	    /* +0 charged rings don't do anything, so don't affect hunger */
1581. 	    switch (moves % 20) {	/* note: use even cases only */
1582. 	     case  4: if (uleft &&
1583. 			  (uleft->spe || !objects[uleft->otyp].oc_charged))
1584. 			    u.uhunger--;
1585. 		    break;
1586. 	     case  8: if (uamul) u.uhunger--;
1587. 		    break;
1588. 	     case 12: if (uright &&
1589. 			  (uright->spe || !objects[uright->otyp].oc_charged))
1590. 			    u.uhunger--;
1591. 		    break;
1592. 	     case 16: if (u.uhave.amulet) u.uhunger--;
1593. 		    break;
1594. 	     default: break;
1595. 	    }
1596. 	}
1597. 	newuhs(TRUE);
1598. }
1599. 
1600. #endif /* OVL0 */
1601. #ifdef OVLB
1602. 
1603. void
1604. morehungry(num)	/* called after vomiting and after performing feats of magic */
1605. register int num;
1606. {
1607. 	u.uhunger -= num;
1608. 	newuhs(TRUE);
1609. }
1610. 
1611. 
1612. void
1613. lesshungry(num)	/* called after eating (and after drinking fruit juice) */
1614. register int num;
1615. {
1616. #ifdef DEBUG
1617. 	debugpline("lesshungry(%d)", num);
1618. #endif
1619. 	u.uhunger += num;
1620. 	if(u.uhunger >= 2000) {
1621. 	    if (!victual.eating || victual.canchoke)
1622. 		if (victual.eating) {
1623. 			choke(victual.piece);
1624. 			reset_eat();
1625. 		} else
1626. 		if (tin.tin)
1627. 			choke(tin.tin);
1628. 		else
1629. 			choke((struct obj *) 0);
1630. 		/* no reset_eat(); it was a non-food such as juice */
1631. 	} else {
1632. 	    /* Have lesshungry() report when you're nearly full so all eating
1633. 	     * warns when you're about to choke.
1634. 	     */
1635. 	    if (u.uhunger >= 1500) {
1636. 	      if(!victual.eating || (victual.eating && !victual.fullwarn)) {
1637. 		pline("You're having a hard time getting all of it down.");
1638. 		nomovemsg = "You're finally finished.";
1639. 		if(!victual.eating)
1640. 		    multi = -2;
1641. 		else {
1642. 		    victual.fullwarn = TRUE;
1643. 		    if (victual.canchoke &&
1644. 			/* a one-gulp food will not survive a stop */
1645. 				objects[victual.piece->otyp].oc_delay > 1) {
1646. 			if(yn("Stop eating?") == 'y')
1647. 			{
1648. 				reset_eat();
1649. 				nomovemsg = NULL;
1650. 			}
1651. 		    }
1652. 		}
1653. 	      }
1654. 	    }
1655. 	}
1656. 	newuhs(FALSE);
1657. }
1658. 
1659. STATIC_PTR
1660. int
1661. unfaint() {
1662. 	(void) Hear_again();
1663. 	if(u.uhs > FAINTING)
1664. 		u.uhs = FAINTING;
1665. 	stop_occupation();
1666. 	flags.botl = 1;
1667. 	return 0;
1668. }
1669. 
1670. #endif /* OVLB */
1671. #ifdef OVL0
1672. 
1673. boolean
1674. is_fainted() {
1675. 	return(u.uhs == FAINTED);
1676. }
1677. 
1678. void
1679. reset_faint() {	/* call when a faint must be prematurely terminated */
1680. 	if(is_fainted()) nomul(0);
1681. }
1682. 
1683. #if 0
1684. void
1685. sync_hunger() {
1686. 
1687. 	if(is_fainted()) {
1688. 
1689. 		flags.soundok = 0;
1690. 		nomul(-10+(u.uhunger/10));
1691. 		nomovemsg = "You regain consciousness.";
1692. 		afternmv = unfaint;
1693. 	}
1694. }
1695. #endif
1696. 
1697. void
1698. newuhs(incr)		/* compute and comment on your (new?) hunger status */
1699. 	boolean incr;
1700. {
1701. 	register int newhs, h = u.uhunger;
1702. 
1703. 	newhs = (h > 1000) ? SATIATED :
1704. 		(h > 150) ? NOT_HUNGRY :
1705. 		(h > 50) ? HUNGRY :
1706. 		(h > 0) ? WEAK : FAINTING;
1707. 
1708. 	if(newhs == FAINTING) {
1709. 		if(is_fainted()) newhs = FAINTED;
1710. 		if(u.uhs <= WEAK || rn2(20-u.uhunger/10) >= 19) {
1711. 			if(!is_fainted() && multi >= 0 /* %% */) {
1712. 				/* stop what you're doing, then faint */
1713. 				stop_occupation();
1714. 				You("faint from lack of food.");
1715. 				flags.soundok = 0;
1716. 				nomul(-10+(u.uhunger/10));
1717. 				nomovemsg = "You regain consciousness.";
1718. 				afternmv = unfaint;
1719. 				newhs = FAINTED;
1720. 			}
1721. 		} else
1722. 		if(u.uhunger < -(int)(200 + 20*ACURR(A_CON))) {
1723. 			u.uhs = STARVED;
1724. 			flags.botl = 1;
1725. 			bot();
1726. 			You("die from starvation.");
1727. 			killer_format = KILLED_BY;
1728. 			killer = "starvation";
1729. 			done(STARVING);
1730. 			/* if we return, we lifesaved, and that calls newuhs */
1731. 			return;
1732. 		}
1733. 	}
1734. 
1735. 	if(newhs != u.uhs) {
1736. 		if(newhs >= WEAK && u.uhs < WEAK)
1737. 			losestr(1);	/* this may kill you -- see below */
1738. 		else if(newhs < WEAK && u.uhs >= WEAK)
1739. 			losestr(-1);
1740. 		switch(newhs){
1741. 		case HUNGRY:
1742. 			if (Hallucination) {
1743. 			    pline((!incr) ?
1744. 				"You now have a lesser case of the munchies." :
1745. 				"You are getting the munchies.");
1746. 			} else
1747. 			    You((!incr) ? "only feel hungry now." :
1748. 				  (u.uhunger < 145) ? "feel hungry." :
1749. 				   "are beginning to feel hungry.");
1750. 			if (incr && occupation &&
1751. 			    (occupation != eatfood && occupation != opentin))
1752. 			    stop_occupation();
1753. 			break;
1754. 		case WEAK:
1755. 			if (Hallucination)
1756. 			    pline((!incr) ?
1757. 				  "You still have the munchies." :
1758.       "The munchies are interfering with your motor capabilities.");
1759. 			else
1760. 			    You((!incr) ? "feel weak now." :
1761. 				  (u.uhunger < 45) ? "feel weak." :
1762. 				   "are beginning to feel weak.");
1763. 			if (incr && occupation &&
1764. 			    (occupation != eatfood && occupation != opentin))
1765. 			    stop_occupation();
1766. 			break;
1767. 		}
1768. 		u.uhs = newhs;
1769. 		flags.botl = 1;
1770. 		if(u.uhp < 1) {
1771. 			You("die from hunger and exhaustion.");
1772. 			killer_format = KILLED_BY;
1773. 			killer = "exhaustion";
1774. 			done(STARVING);
1775. 			return;
1776. 		}
1777. 	}
1778. }
1779. 
1780. #endif /* OVL0 */
1781. #ifdef OVLB
1782. 
1783. /* Returns an object representing food.  Object may be either on floor or
1784.  * in inventory.
1785.  */
1786. struct obj *
1787. floorfood(verb,corpseonly)	/* get food from floor or pack */
1788. 	const char *verb;
1789. 	boolean corpseonly;
1790. {
1791. 	register struct obj *otmp;
1792. 	char qbuf[QBUFSZ];
1793. 	char c;
1794. #ifdef POLYSELF
1795. 	struct obj *gold = g_at(u.ux, u.uy);
1796. 	boolean feeding = (!strcmp(verb, "eat"));
1797. 
1798. 	if (feeding && gold && metallivorous(uasmon)) {
1799. 	    if (gold->quan == 1L)
1800. 		Sprintf(qbuf, "There is 1 gold piece here; eat it?");
1801. 	    else Sprintf(qbuf, "There are %ld gold pieces here; eat them?",
1802. 								gold->quan);
1803. 	    if (yn(qbuf) == 'y') {
1804. 		/* tricky, because gold isn't a real object -dlc */
1805. 		freeobj(gold);
1806. 		return gold;
1807. 	    }
1808. 	}
1809. #endif
1810. 	/* Is there some food (probably a heavy corpse) here on the ground? */
1811. 	if (!(Levitation && !Is_airlevel(&u.uz)  && !Is_waterlevel(&u.uz))
1812. 	    && !u.uswallow) {
1813. 	    for(otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp->nexthere) {
1814. 		if(corpseonly ? otmp->otyp==CORPSE :
1815. #ifdef POLYSELF
1816. 		    feeding ? (otmp->oclass != GOLD_CLASS && is_edible(otmp)) :
1817. #endif
1818. 						otmp->oclass==FOOD_CLASS) {
1819. 			Sprintf(qbuf, "There %s %s here; %s %s?",
1820. 				(otmp->quan == 1L) ? "is" : "are",
1821. 				doname(otmp), verb,
1822. 				(otmp->quan == 1L) ? "it" : "one");
1823. 			if((c = yn_function(qbuf,ynqchars,'n')) == 'y')
1824. 				return(otmp);
1825. 			else if(c == 'q')
1826. 				return((struct obj *) 0);
1827. 		}
1828. 	    }
1829. 	}
1830. #ifdef POLYSELF
1831. 	/* We cannot use ALL_CLASSES since that causes getobj() to skip its
1832. 	 * "ugly checks" and we need to check for inedible items.
1833. 	 */
1834. 	return getobj(feeding ? (const char *)allobj :
1835. 				(const char *)comestibles, verb);
1836. #else
1837. 	return getobj(comestibles, verb);
1838. #endif
1839. }
1840. 
1841. /* Side effects of vomiting */
1842. /* added nomul (MRS) - it makes sense, you're too busy being sick! */
1843. /* TO DO: regurgitate swallowed monsters when poly'd */
1844. void
1845. vomit() {		/* A good idea from David Neves */
1846. 	make_sick(0L,TRUE);
1847. 	nomul(-2);
1848. }
1849. 
1850. int
1851. eaten_stat(base, obj)
1852. register int base;
1853. register struct obj *obj;
1854. {
1855. 	long uneaten_amt, full_amount;
1856. 
1857. 	uneaten_amt = (long)obj->oeaten;
1858. 	full_amount = (obj->otyp == CORPSE) ? (long)mons[obj->corpsenm].cnutrit
1859. 					: (long)objects[obj->otyp].oc_nutrition;
1860. 
1861. 	base = (int)(full_amount ? (long)base * uneaten_amt / full_amount : 0L);
1862. 	return (base < 1) ? 1 : base;
1863. }
1864. 
1865. #endif /* OVLB */
1866. 
1867. /*eat.c*/