Source:SLASH'EM 0.0.7E7F2/eat.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to eat.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/eat.c#line123]], for example.

The latest source code for vanilla NetHack is at 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.4	2003/02/13	*/
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 void FDECL(costly_tin, (const char*));
19.   STATIC_PTR int NDECL(opentin);
20.   STATIC_PTR int NDECL(unfaint);
21.   
22.   #ifdef OVLB
23.   STATIC_DCL const char *FDECL(food_xname, (struct obj *,BOOLEAN_P));
24.   STATIC_DCL void FDECL(choke, (struct obj *));
25.   STATIC_DCL void NDECL(recalc_wt);
26.   STATIC_DCL struct obj *FDECL(touchfood, (struct obj *));
27.   STATIC_DCL void NDECL(do_reset_eat);
28.   STATIC_DCL void FDECL(done_eating, (BOOLEAN_P));
29.   STATIC_DCL void FDECL(cprefx, (int));
30.   STATIC_DCL int FDECL(intrinsic_possible, (int,struct permonst *));
31.   STATIC_DCL void FDECL(givit, (int,struct permonst *));
32.   STATIC_DCL void FDECL(cpostfx, (int));
33.   STATIC_DCL void FDECL(start_tin, (struct obj *));
34.   STATIC_DCL int FDECL(eatcorpse, (struct obj *));
35.   STATIC_DCL void FDECL(start_eating, (struct obj *));
36.   STATIC_DCL void FDECL(fprefx, (struct obj *));
37.   STATIC_DCL void FDECL(accessory_has_effect, (struct obj *));
38.   STATIC_DCL void FDECL(fpostfx, (struct obj *));
39.   STATIC_DCL int NDECL(bite);
40.   STATIC_DCL int FDECL(edibility_prompts, (struct obj *));
41.   STATIC_DCL int FDECL(rottenfood, (struct obj *));
42.   STATIC_DCL void NDECL(eatspecial);
43.   STATIC_DCL void FDECL(eataccessory, (struct obj *));
44.   STATIC_DCL const char *FDECL(foodword, (struct obj *));
45.   STATIC_DCL boolean FDECL(maybe_cannibal, (int,BOOLEAN_P));
46.   STATIC_DCL struct obj *FDECL(floorfood, (const char *));
47.   
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.   /* also used to see if you're allowed to eat cats and dogs */
62.   #define CANNIBAL_ALLOWED() (Role_if(PM_CAVEMAN) || Race_if(PM_ORC) || \
63.   			    Race_if(PM_HUMAN_WEREWOLF) || Race_if(PM_VAMPIRE))
64.   
65.   #ifndef OVLB
66.   
67.   STATIC_DCL NEARDATA const char comestibles[];
68.   STATIC_DCL NEARDATA const char allobj[];
69.   STATIC_DCL boolean force_save_hs;
70.   
71.   #else
72.   
73.   STATIC_OVL NEARDATA const char comestibles[] = { FOOD_CLASS, 0 };
74.   
75.   /* Gold must come first for getobj(). */
76.   STATIC_OVL NEARDATA const char allobj[] = { COIN_CLASS, ALLOW_FLOOROBJ,
77.   	WEAPON_CLASS, ARMOR_CLASS, POTION_CLASS, SCROLL_CLASS,
78.   	WAND_CLASS, RING_CLASS, AMULET_CLASS, FOOD_CLASS, TOOL_CLASS,
79.   	GEM_CLASS, ROCK_CLASS, BALL_CLASS, CHAIN_CLASS, SPBOOK_CLASS, 0 };
80.   
81.   STATIC_OVL boolean force_save_hs = FALSE;
82.   
83.   const char *hu_stat[] = {
84.   	"Satiated",
85.   	"        ",
86.   	"Hungry  ",
87.   	"Weak    ",
88.   	"Fainting",
89.   	"Fainted ",
90.   	"Starved "
91.   };
92.   
93.   #endif /* OVLB */
94.   #ifdef OVL1
95.   
96.   /*
97.    * Decide whether a particular object can be eaten by the possibly
98.    * polymorphed character.  Not used for monster checks.
99.    */
100.  boolean
101.  is_edible(obj)
102.  register struct obj *obj;
103.  {
104.  	/* protect invocation tools but not Rider corpses (handled elsewhere)*/
105.       /* if (obj->oclass != FOOD_CLASS && obj_resists(obj, 0, 0)) */
106.  	if (evades_destruction(obj))
107.  		return FALSE;
108.  	if (objects[obj->otyp].oc_unique)
109.  		return FALSE;
110.  	/* above also prevents the Amulet from being eaten, so we must never
111.  	   allow fake amulets to be eaten either [which is already the case] */
112.  
113.  	if (metallivorous(youmonst.data) && is_metallic(obj) &&
114.  	    (youmonst.data != &mons[PM_RUST_MONSTER] || is_rustprone(obj)))
115.  		return TRUE;
116.  	/* KMH -- Taz likes organics, too! */
117.  	if ((u.umonnum == PM_GELATINOUS_CUBE ||
118.  			u.umonnum == PM_TASMANIAN_DEVIL) && is_organic(obj) &&
119.  		/* [g.cubes can eat containers and retain all contents
120.  		    as engulfed items, but poly'd player can't do that] */
121.  	    !Has_contents(obj))
122.  		return TRUE;
123.  
124.  	/* Koalas only eat Eucalyptus leaves */
125.  	if (u.umonnum == PM_KOALA)
126.  		return (boolean)(obj->otyp == EUCALYPTUS_LEAF);
127.  	
128.  	/* Ghouls, ghasts only eat corpses */
129.  	if (u.umonnum == PM_GHOUL || u.umonnum == PM_GHAST)
130.  	   	return (boolean)(obj->otyp == CORPSE);
131.  	/* Vampires drink the blood of meaty corpses */
132.  	/* [ALI] (fully) drained food is not presented as an option,
133.  	 * but partly eaten food is (even though you can't drain it).
134.  	 */
135.  	if (is_vampire(youmonst.data))
136.  		return (boolean)(obj->otyp == CORPSE &&
137.  		  has_blood(&mons[obj->corpsenm]) && (!obj->odrained ||
138.  		  obj->oeaten > drainlevel(obj)));
139.  
140.       /* return((boolean)(!!index(comestibles, obj->oclass))); */
141.  	return (boolean)(obj->oclass == FOOD_CLASS);
142.  }
143.  
144.  #endif /* OVL1 */
145.  #ifdef OVLB
146.  
147.  void
148.  init_uhunger()
149.  {
150.  	u.uhunger = 900;
151.  	u.uhs = NOT_HUNGRY;
152.  }
153.  
154.  static const struct { const char *txt; int nut; } tintxts[] = {
155.  	{"deep fried",	 60},
156.  	{"pickled",	 40},
157.  	{"soup made from", 20},
158.  	{"pureed",	500},
159.  #define ROTTEN_TIN 4
160.  	{"rotten",	-50},
161.  #define HOMEMADE_TIN 5
162.  	{"homemade",	 50},
163.  	{"stir fried",   80},
164.  	{"candied",      100},
165.  	{"boiled",       50},
166.  	{"dried",        55},
167.  	{"szechuan",     70},
168.  #define FRENCH_FRIED_TIN 11
169.  	{"french fried", 40},
170.  	{"sauteed",      95},
171.  	{"broiled",      80},
172.  	{"smoked",       50},
173.  	/* [Tom] added a few new styles */        
174.  	{"stir fried",   80},
175.  	{"candied",      100},
176.  	{"boiled",       50},
177.  	{"dried",        55},
178.  	{"szechuan",     70},
179.  	{"french fried", 40},
180.  	{"sauteed",      95},
181.  	{"broiled",      80},
182.  	{"smoked",       50},
183.  	{"", 0}
184.  };
185.  #define TTSZ	SIZE(tintxts)
186.  
187.  static NEARDATA struct {
188.  	struct	obj *tin;
189.  	int	usedtime, reqtime;
190.  } tin;
191.  
192.  static NEARDATA struct {
193.  	struct	obj *piece;	/* the thing being eaten, or last thing that
194.  				 * was partially eaten, unless that thing was
195.  				 * a tin, which uses the tin structure above,
196.  				 * in which case this should be 0 */
197.  	/* doeat() initializes these when piece is valid */
198.  	int	usedtime,	/* turns spent eating */
199.  		reqtime;	/* turns required to eat */
200.  	int	nmod;		/* coded nutrition per turn */
201.  	Bitfield(canchoke,1);	/* was satiated at beginning */
202.  
203.  	/* start_eating() initializes these */
204.  	Bitfield(fullwarn,1);	/* have warned about being full */
205.  	Bitfield(eating,1);	/* victual currently being eaten */
206.  	Bitfield(doreset,1);	/* stop eating at end of turn */
207.  } victual;
208.  
209.  static char *eatmbuf = 0;	/* set by cpostfx() */
210.  
211.  STATIC_PTR
212.  int
213.  eatmdone()		/* called after mimicing is over */
214.  {
215.  	/* release `eatmbuf' */
216.  	if (eatmbuf) {
217.  	    if (nomovemsg == eatmbuf) nomovemsg = 0;
218.  	    free((genericptr_t)eatmbuf),  eatmbuf = 0;
219.  	}
220.  	/* update display */
221.  	if (youmonst.m_ap_type) {
222.  	    youmonst.m_ap_type = M_AP_NOTHING;
223.  	    newsym(u.ux,u.uy);
224.  	}
225.  	return 0;
226.  }
227.  
228.  /* ``[the(] singular(food, xname) [)] with awareness of unique monsters */
229.  STATIC_OVL const char *
230.  food_xname(food, the_pfx)
231.  struct obj *food;
232.  boolean the_pfx;
233.  {
234.  	const char *result;
235.  	int mnum = food->corpsenm;
236.  
237.  	if (food->otyp == CORPSE && (mons[mnum].geno & G_UNIQ) && !Hallucination) {
238.  	    /* grab xname()'s modifiable return buffer for our own use */
239.  	    char *bufp = xname(food);
240.  
241.  	    Sprintf(bufp, "%s%s corpse",
242.  		    (the_pfx && !type_is_pname(&mons[mnum])) ? "the " : "",
243.  		    s_suffix(mons[mnum].mname));
244.  	    result = bufp;
245.  	} else {
246.  	    /* the ordinary case */
247.  	    result = singular(food, xname);
248.  	    if (the_pfx) result = the(result);
249.  	}
250.  	return result;
251.  }
252.  
253.  
254.  /* Created by GAN 01/28/87
255.   * Amended by AKP 09/22/87: if not hard, don't choke, just vomit.
256.   * Amended by 3.  06/12/89: if not hard, sometimes choke anyway, to keep risk.
257.   *		  11/10/89: if hard, rarely vomit anyway, for slim chance.
258.   */
259.  STATIC_OVL void
260.  choke(food)	/* To a full belly all food is bad. (It.) */
261.  register struct obj *food;
262.  {
263.  	/* only happens if you were satiated */
264.  	if (u.uhs != SATIATED) {
265.  		if (!food || food->otyp != AMULET_OF_STRANGULATION)
266.  			return;
267.  	} else if (Role_if(PM_KNIGHT) && u.ualign.type == A_LAWFUL) {
268.  			adjalign(-1);		/* gluttony is unchivalrous */
269.  		You("feel like a glutton!");        
270.  	}
271.  
272.  	exercise(A_CON, FALSE);
273.  
274.  	if (Breathless || (!Strangled && !rn2(20))) {
275.  		/* choking by eating AoS doesn't involve stuffing yourself */
276.  		/* ALI - nor does other non-food nutrition (eg., life-blood) */
277.  		if (!food || food->otyp == AMULET_OF_STRANGULATION) {
278.  			nomovemsg = "You recover your composure.";
279.  			You("choke over it.");
280.  			nomul(-2);
281.  			return;
282.  		}
283.  		You("stuff yourself and then vomit voluminously.");
284.  		morehungry(1000);	/* you just got *very* sick! */
285.  		nomovemsg = 0;
286.  		vomit();
287.  	} else {
288.  		killer_format = KILLED_BY_AN;
289.  		/*
290.  		 * Note all "killer"s below read "Choked on %s" on the
291.  		 * high score list & tombstone.  So plan accordingly.
292.  		 */
293.  		if(food) {
294.  			You("choke over your %s.", foodword(food));
295.  			if (food->oclass == COIN_CLASS) {
296.  				killer = "a very rich meal";
297.  			} else {
298.  				killer = food_xname(food, FALSE);
299.  				if (food->otyp == CORPSE &&
300.  				    (mons[food->corpsenm].geno & G_UNIQ)) {
301.  				    if (!type_is_pname(&mons[food->corpsenm]))
302.  					killer = the(killer);
303.  				    killer_format = KILLED_BY;
304.  				}
305.  			}
306.  		} else {
307.  			You("choke over it.");
308.  			killer = "quick snack";
309.  		}
310.  		You("die...");
311.  		done(CHOKING);
312.  	}
313.  }
314.  
315.  /* modify object wt. depending on time spent consuming it */
316.  STATIC_OVL void
317.  recalc_wt()
318.  {
319.  	struct obj *piece = victual.piece;
320.  
321.  #ifdef DEBUG
322.  	debugpline("Old weight = %d", piece->owt);
323.  	debugpline("Used time = %d, Req'd time = %d",
324.  		victual.usedtime, victual.reqtime);
325.  #endif
326.  	piece->owt = weight(piece);
327.  #ifdef DEBUG
328.  	debugpline("New weight = %d", piece->owt);
329.  #endif
330.  }
331.  
332.  void
333.  reset_eat()		/* called when eating interrupted by an event */
334.  {
335.      /* we only set a flag here - the actual reset process is done after
336.       * the round is spent eating.
337.       */
338.  	if(victual.eating && !victual.doreset) {
339.  #ifdef DEBUG
340.  	    debugpline("reset_eat...");
341.  #endif
342.  	    victual.doreset = TRUE;
343.  	}
344.  	return;
345.  }
346.  
347.  STATIC_OVL struct obj *
348.  touchfood(otmp)
349.  register struct obj *otmp;
350.  {
351.  	if (otmp->quan > 1L) {
352.  	    if(!carried(otmp))
353.  		(void) splitobj(otmp, otmp->quan - 1L);
354.  	    else
355.  		otmp = splitobj(otmp, 1L);
356.  
357.  #ifdef DEBUG
358.  	    debugpline("split object,");
359.  #endif
360.  	}
361.  
362.  	if (!otmp->oeaten) {
363.  	    if(((!carried(otmp) && costly_spot(otmp->ox, otmp->oy) &&
364.  		 !otmp->no_charge)
365.  		 || otmp->unpaid)) {
366.  		/* create a dummy duplicate to put on bill */
367.  		verbalize("You bit it, you bought it!");
368.  		bill_dummy_object(otmp);
369.  	    }
370.  	    otmp->oeaten = (otmp->otyp == CORPSE ?
371.  				mons[otmp->corpsenm].cnutrit :
372.  				objects[otmp->otyp].oc_nutrition);
373.  	}
374.  
375.  	if (carried(otmp)) {
376.  	    freeinv(otmp);
377.  	    if (inv_cnt() >= 52) {
378.  		sellobj_state(SELL_DONTSELL);
379.  		dropy(otmp);
380.  		sellobj_state(SELL_NORMAL);
381.  	    } else {
382.  		otmp->oxlth++;		/* hack to prevent merge */
383.  		otmp = addinv(otmp);
384.  		otmp->oxlth--;
385.  	    }
386.  	}
387.  	return(otmp);
388.  }
389.  
390.  /* When food decays, in the middle of your meal, we don't want to dereference
391.   * any dangling pointers, so set it to null (which should still trigger
392.   * do_reset_eat() at the beginning of eatfood()) and check for null pointers
393.   * in do_reset_eat().
394.   */
395.  void
396.  food_disappears(obj)
397.  register struct obj *obj;
398.  {
399.  	if (obj == victual.piece) victual.piece = (struct obj *)0;
400.  	if (obj->timed) obj_stop_timers(obj);
401.  }
402.  
403.  /* renaming an object usually results in it having a different address;
404.     so the sequence start eating/opening, get interrupted, name the food,
405.     resume eating/opening would restart from scratch */
406.  void
407.  food_substitution(old_obj, new_obj)
408.  struct obj *old_obj, *new_obj;
409.  {
410.  	if (old_obj == victual.piece) victual.piece = new_obj;
411.  	if (old_obj == tin.tin) tin.tin = new_obj;
412.  }
413.  
414.  STATIC_OVL void
415.  do_reset_eat()
416.  {
417.  #ifdef DEBUG
418.  	debugpline("do_reset_eat...");
419.  #endif
420.  	if (victual.piece) {
421.  		victual.piece = touchfood(victual.piece);
422.  		recalc_wt();
423.  	}
424.  	victual.fullwarn = victual.eating = victual.doreset = FALSE;
425.  	/* Do not set canchoke to FALSE; if we continue eating the same object
426.  	 * we need to know if canchoke was set when they started eating it the
427.  	 * previous time.  And if we don't continue eating the same object
428.  	 * canchoke always gets recalculated anyway.
429.  	 */
430.  	stop_occupation();
431.  	newuhs(FALSE);
432.  }
433.  
434.  STATIC_PTR
435.  int
436.  eatfood()		/* called each move during eating process */
437.  {
438.  	if(!victual.piece ||
439.  	 (!carried(victual.piece) && !obj_here(victual.piece, u.ux, u.uy))) {
440.  		/* maybe it was stolen? */
441.  		do_reset_eat();
442.  		return(0);
443.  	}
444.  	if (is_vampire(youmonst.data) != victual.piece->odrained) {
445.  	    /* Polymorphed while eating/draining */
446.  	    do_reset_eat();
447.  	    return(0);
448.  	}
449.  	if(!victual.eating) return(0);
450.  
451.  	if(++victual.usedtime <= victual.reqtime) {
452.  	    if(bite()) return(0);
453.  	    return(1);	/* still busy */
454.  	} else {	/* done */
455.  	    int crumbs = victual.piece->oeaten;		/* The last crumbs */
456.  	    if (victual.piece->odrained) crumbs -= drainlevel(victual.piece);
457.  	    if (crumbs > 0) {
458.  		lesshungry(crumbs);
459.  		victual.piece->oeaten -= crumbs;
460.  	    }
461.  	    done_eating(TRUE);
462.  	    return(0);
463.  	}
464.  }
465.  
466.  STATIC_OVL void
467.  done_eating(message)
468.  boolean message;
469.  {
470.  	victual.piece->in_use = TRUE;
471.  	occupation = 0; /* do this early, so newuhs() knows we're done */
472.  	newuhs(FALSE);
473.  	if (nomovemsg) {
474.  		if (message) pline(nomovemsg);
475.  		nomovemsg = 0;
476.  	} else if (message)
477.  		You("finish %s %s.", victual.piece->odrained ? "draining" :
478.  		  "eating", food_xname(victual.piece, TRUE));
479.  
480.  	if(victual.piece->otyp == CORPSE) {
481.  		if (!victual.piece->odrained || Race_if(PM_VAMPIRE) && !rn2(5))
482.  		cpostfx(victual.piece->corpsenm);
483.  	} else
484.  		fpostfx(victual.piece);
485.  
486.  	if (victual.piece->odrained)
487.  		victual.piece->in_use = FALSE;
488.  	else
489.  	if (carried(victual.piece)) useup(victual.piece);
490.  	else useupf(victual.piece, 1L);
491.  	victual.piece = (struct obj *) 0;
492.  	victual.fullwarn = victual.eating = victual.doreset = FALSE;
493.  }
494.  
495.  STATIC_OVL boolean
496.  maybe_cannibal(pm, allowmsg)
497.  int pm;
498.  boolean allowmsg;
499.  {
500.  	if (your_race(&mons[pm])) {
501.  	    if (!CANNIBAL_ALLOWED()) {
502.  		if (allowmsg) {
503.  		    if (Upolyd)
504.  			You("have a bad feeling deep inside.");
505.  		    You("cannibal!  You will regret this!");
506.  		}
507.  		HAggravate_monster |= FROMOUTSIDE;
508.  		change_luck(-rn1(4,2));		/* -5..-2 */
509.  	    } else if (Role_if(PM_CAVEMAN)) {
510.  		adjalign(sgn(u.ualign.type));
511.  		You("honour the dead.");
512.  	    } else {
513.  		adjalign(-sgn(u.ualign.type));
514.  		You_feel("evil and fiendish!");
515.  	    }
516.  	    return TRUE;
517.  	}
518.  	return FALSE;
519.  }
520.  
521.  STATIC_OVL void
522.  cprefx(pm)
523.  register int pm;
524.  {
525.  	(void) maybe_cannibal(pm,TRUE);
526.  	if (touch_petrifies(&mons[pm]) || pm == PM_MEDUSA) {
527.  	    if (!Stone_resistance &&
528.  		!(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))) {
529.  		Sprintf(killer_buf, "tasting %s meat", mons[pm].mname);
530.  		killer_format = KILLED_BY;
531.  		killer = killer_buf;
532.  		You("turn to stone.");
533.  		done(STONING);
534.  		if (victual.piece)
535.  		    victual.eating = FALSE;
536.  		return; /* lifesaved */
537.  	    }
538.  	}
539.  
540.  	switch(pm) {
541.  	    case PM_LITTLE_DOG:
542.  	    case PM_DOG:
543.  	    case PM_LARGE_DOG:
544.  	    case PM_KITTEN:
545.  	    case PM_HOUSECAT:
546.  	    case PM_LARGE_CAT:
547.  		if (!CANNIBAL_ALLOWED()) {
548.  		    You_feel("that %s the %s%s was a bad idea.",
549.  		      victual.eating ? "eating" : "biting",
550.  		      occupation == opentin ? "tinned " : "", mons[pm].mname);
551.  		    HAggravate_monster |= FROMOUTSIDE;
552.  		}
553.  		break;
554.  	    case PM_LIZARD:
555.  		if (Stoned) fix_petrification();
556.  		break;
557.  	    case PM_DEATH:
558.  	    case PM_PESTILENCE:
559.  	    case PM_FAMINE:
560.  		{ char buf[BUFSZ];
561.  		    pline("Eating that is instantly fatal.");
562.  		    Sprintf(buf, "unwisely ate the body of %s",
563.  			    mons[pm].mname);
564.  		    killer = buf;
565.  		    killer_format = NO_KILLER_PREFIX;
566.  		    done(DIED);
567.  		    /* It so happens that since we know these monsters */
568.  		    /* cannot appear in tins, victual.piece will always */
569.  		    /* be what we want, which is not generally true. */
570.  		    if (revive_corpse(victual.piece, FALSE))
571.  			victual.piece = (struct obj *)0;
572.  		    return;
573.  		}
574.  	    case PM_GREEN_SLIME:
575.  		if (!Slimed && !Unchanging && !flaming(youmonst.data) &&
576.  			youmonst.data != &mons[PM_GREEN_SLIME]) {
577.  		    You("don't feel very well.");
578.  		    Slimed = 10L;
579.  		    flags.botl = 1;
580.  		}
581.  		/* Fall through */
582.  	    default:
583.  		if (acidic(&mons[pm]) && Stoned)
584.  		    fix_petrification();
585.  		break;
586.  	}
587.  }
588.  
589.  /*
590.   * Called when a vampire bites a monster.
591.   * Returns TRUE if hero died and was lifesaved.
592.   */
593.  
594.  boolean
595.  bite_monster(mon)
596.  struct monst *mon;
597.  {
598.      switch(monsndx(mon->data)) {
599.  	case PM_LIZARD:
600.  	    if (Stoned) fix_petrification();
601.  	    break;
602.  	case PM_DEATH:
603.  	case PM_PESTILENCE:
604.  	case PM_FAMINE:
605.  	    pline("Unfortunately, eating any of it is fatal.");
606.  	    done_in_by(mon);
607.  	    return TRUE;		/* lifesaved */
608.  
609.  	case PM_GREEN_SLIME:
610.  	    if (!Unchanging && youmonst.data != &mons[PM_FIRE_VORTEX] &&
611.  			    youmonst.data != &mons[PM_FIRE_ELEMENTAL] &&
612.  			    youmonst.data != &mons[PM_GREEN_SLIME]) {
613.  		You("don't feel very well.");
614.  		Slimed = 10L;
615.  	    }
616.  	    /* Fall through */
617.  	default:
618.  	    if (acidic(mon->data) && Stoned)
619.  		fix_petrification();
620.  	    break;
621.      }
622.      return FALSE;
623.  }
624.  
625.  void
626.  fix_petrification()
627.  {
628.  	Stoned = 0;
629.  	delayed_killer = 0;
630.  	if (Hallucination)
631.  	    pline("What a pity - you just ruined a future piece of %sart!",
632.  		  ACURR(A_CHA) > 15 ? "fine " : "");
633.  	else
634.  	    You_feel("limber!");
635.  }
636.  
637.  /*
638.   * If you add an intrinsic that can be gotten by eating a monster, add it
639.   * to intrinsic_possible() and givit().  (It must already be in prop.h to
640.   * be an intrinsic property.)
641.   * It would be very easy to make the intrinsics not try to give you one
642.   * that you already had by checking to see if you have it in
643.   * intrinsic_possible() instead of givit().
644.   */
645.  
646.  /* intrinsic_possible() returns TRUE if a monster can give an intrinsic. */
647.  STATIC_OVL int
648.  intrinsic_possible(type, ptr)
649.  int type;
650.  register struct permonst *ptr;
651.  {
652.  	switch (type) {
653.  	    case FIRE_RES:
654.  #ifdef DEBUG
655.  		if (ptr->mconveys & MR_FIRE) {
656.  			debugpline("can get fire resistance");
657.  			return(TRUE);
658.  		} else  return(FALSE);
659.  #else
660.  		return(ptr->mconveys & MR_FIRE);
661.  #endif
662.  	    case SLEEP_RES:
663.  #ifdef DEBUG
664.  		if (ptr->mconveys & MR_SLEEP) {
665.  			debugpline("can get sleep resistance");
666.  			return(TRUE);
667.  		} else  return(FALSE);
668.  #else
669.  		return(ptr->mconveys & MR_SLEEP);
670.  #endif
671.  	    case COLD_RES:
672.  #ifdef DEBUG
673.  		if (ptr->mconveys & MR_COLD) {
674.  			debugpline("can get cold resistance");
675.  			return(TRUE);
676.  		} else  return(FALSE);
677.  #else
678.  		return(ptr->mconveys & MR_COLD);
679.  #endif
680.  	    case DISINT_RES:
681.  #ifdef DEBUG
682.  		if (ptr->mconveys & MR_DISINT) {
683.  			debugpline("can get disintegration resistance");
684.  			return(TRUE);
685.  		} else  return(FALSE);
686.  #else
687.  		return(ptr->mconveys & MR_DISINT);
688.  #endif
689.  	    case SHOCK_RES:	/* shock (electricity) resistance */
690.  #ifdef DEBUG
691.  		if (ptr->mconveys & MR_ELEC) {
692.  			debugpline("can get shock resistance");
693.  			return(TRUE);
694.  		} else  return(FALSE);
695.  #else
696.  		return(ptr->mconveys & MR_ELEC);
697.  #endif
698.  	    case POISON_RES:
699.  #ifdef DEBUG
700.  		if (ptr->mconveys & MR_POISON) {
701.  			debugpline("can get poison resistance");
702.  			return(TRUE);
703.  		} else  return(FALSE);
704.  #else
705.  		return(ptr->mconveys & MR_POISON);
706.  #endif
707.  	    case TELEPORT:
708.  #ifdef DEBUG
709.  		if (can_teleport(ptr)) {
710.  			debugpline("can get teleport");
711.  			return(TRUE);
712.  		} else  return(FALSE);
713.  #else
714.  		return(can_teleport(ptr));
715.  #endif
716.  	    case TELEPORT_CONTROL:
717.  #ifdef DEBUG
718.  		if (control_teleport(ptr)) {
719.  			debugpline("can get teleport control");
720.  			return(TRUE);
721.  		} else  return(FALSE);
722.  #else
723.  		return(control_teleport(ptr));
724.  #endif
725.  	    case TELEPAT:
726.  #ifdef DEBUG
727.  		if (telepathic(ptr)) {
728.  			debugpline("can get telepathy");
729.  			return(TRUE);
730.  		} else  return(FALSE);
731.  #else
732.  		return(telepathic(ptr));
733.  #endif
734.  	    default:
735.  		return(FALSE);
736.  	}
737.  	/*NOTREACHED*/
738.  }
739.  
740.  /* givit() tries to give you an intrinsic based on the monster's level
741.   * and what type of intrinsic it is trying to give you.
742.   */
743.  /* KMH, balance patch -- eliminated temporary intrinsics from
744.   * corpses, and restored probabilities to NetHack levels.
745.   *
746.   * There were several ways to deal with this issue:
747.   * 1.  Let corpses convey permanent intrisics (as implemented in
748.   *     vanilla NetHack).  This is the easiest method for players
749.   *     to understand and has the least player frustration.
750.   * 2.  Provide a temporary intrinsic if you don't already have it,
751.   *     a give the permanent intrinsic if you do have it (Slash's
752.   *     method).  This is probably the most realistic solution,
753.   *     but players were extremely annoyed by it.
754.   * 3.  Let certain intrinsics be conveyed one way and the rest
755.   *     conveyed the other.  However, there would certainly be
756.   *     arguments about which should be which, and it would
757.   *     certainly become yet another FAQ.
758.   * 4.  Increase the timeouts.  This is limited by the number of
759.   *     bits reserved for the timeout.
760.   * 5.  Convey a permanent intrinsic if you have _ever_ been
761.   *     given the temporary intrinsic.  This is a nice solution,
762.   *     but it would use another bit, and probably isn't worth
763.   *     the effort.
764.   * 6.  Give the player better notice when the timeout expires,
765.   *     and/or some method to check on intrinsics that is not as
766.   *     revealing as enlightenment.
767.   * 7.  Some combination of the above.
768.   *
769.   * In the end, I decided that the simplest solution would be the
770.   * best solution.
771.   */
772.  STATIC_OVL void
773.  givit(type, ptr)
774.  int type;
775.  register struct permonst *ptr;
776.  {
777.  	register int chance;
778.  
779.  #ifdef DEBUG
780.  	debugpline("Attempting to give intrinsic %d", type);
781.  #endif
782.  	/* some intrinsics are easier to get than others */
783.  	switch (type) {
784.  		case POISON_RES:
785.  			if ((ptr == &mons[PM_KILLER_BEE] ||
786.  					ptr == &mons[PM_SCORPION]) && !rn2(4))
787.  				chance = 1;
788.  			else
789.  				chance = 15;
790.  			break;
791.  		case TELEPORT:
792.  			chance = 10;
793.  			break;
794.  		case TELEPORT_CONTROL:
795.  			chance = 12;
796.  			break;
797.  		case TELEPAT:
798.  			chance = 1;
799.  			break;
800.  		default:
801.  			chance = 15;
802.  			break;
803.  	}
804.  
805.  	if (ptr->mlevel <= rn2(chance))
806.  		return;		/* failed die roll */
807.  
808.  	switch (type) {
809.  	    case FIRE_RES:
810.  #ifdef DEBUG
811.  		debugpline("Trying to give fire resistance");
812.  #endif
813.  		if(!(HFire_resistance & FROMOUTSIDE)) {
814.  			You(Hallucination ? "be chillin'." :
815.  			    "feel a momentary chill.");
816.  			HFire_resistance |= FROMOUTSIDE;
817.  		}
818.  		break;
819.  	    case SLEEP_RES:
820.  #ifdef DEBUG
821.  		debugpline("Trying to give sleep resistance");
822.  #endif
823.  		if(!(HSleep_resistance & FROMOUTSIDE)) {
824.  			You_feel("wide awake.");
825.  			HSleep_resistance |= FROMOUTSIDE;
826.  		}
827.  		break;
828.  	    case COLD_RES:
829.  #ifdef DEBUG
830.  		debugpline("Trying to give cold resistance");
831.  #endif
832.  		if(!(HCold_resistance & FROMOUTSIDE)) {
833.  			You_feel("full of hot air.");
834.  			HCold_resistance |= FROMOUTSIDE;
835.  		}
836.  		break;
837.  	    case DISINT_RES:
838.  #ifdef DEBUG
839.  		debugpline("Trying to give disintegration resistance");
840.  #endif
841.  		if(!(HDisint_resistance & FROMOUTSIDE)) {
842.  			You_feel(Hallucination ?
843.  			    "totally together, man." :
844.  			    "very firm.");
845.  			HDisint_resistance |= FROMOUTSIDE;
846.  		}
847.  		break;
848.  	    case SHOCK_RES:	/* shock (electricity) resistance */
849.  #ifdef DEBUG
850.  		debugpline("Trying to give shock resistance");
851.  #endif
852.  		if(!(HShock_resistance & FROMOUTSIDE)) {
853.  			if (Hallucination)
854.  				You_feel("grounded in reality.");
855.  			else
856.  				Your("health currently feels amplified!");
857.  			HShock_resistance |= FROMOUTSIDE;
858.  		}
859.  		break;
860.  	    case POISON_RES:
861.  #ifdef DEBUG
862.  		debugpline("Trying to give poison resistance");
863.  #endif
864.  		if(!(HPoison_resistance & FROMOUTSIDE)) {
865.  			You_feel(Poison_resistance ?
866.  				 "especially healthy." : "healthy.");
867.  			HPoison_resistance |= FROMOUTSIDE;
868.  		}
869.  		break;
870.  	    case TELEPORT:
871.  #ifdef DEBUG
872.  		debugpline("Trying to give teleport");
873.  #endif
874.  		if(!(HTeleportation & FROMOUTSIDE)) {
875.  			You_feel(Hallucination ? "diffuse." :
876.  			    "very jumpy.");
877.  			HTeleportation |= FROMOUTSIDE;
878.  		}
879.  		break;
880.  	    case TELEPORT_CONTROL:
881.  #ifdef DEBUG
882.  		debugpline("Trying to give teleport control");
883.  #endif
884.  		if(!(HTeleport_control & FROMOUTSIDE)) {
885.  			You_feel(Hallucination ?
886.  			    "centered in your personal space." :
887.  			    "in control of yourself.");
888.  			HTeleport_control |= FROMOUTSIDE;
889.  		}
890.  		break;
891.  	    case TELEPAT:
892.  #ifdef DEBUG
893.  		debugpline("Trying to give telepathy");
894.  #endif
895.  		if(!(HTelepat & FROMOUTSIDE)) {
896.  			You_feel(Hallucination ?
897.  			    "in touch with the cosmos." :
898.  			    "a strange mental acuity.");
899.  			HTelepat |= FROMOUTSIDE;
900.  			/* If blind, make sure monsters show up. */
901.  			if (Blind) see_monsters();
902.  		}
903.  		break;
904.  	    default:
905.  #ifdef DEBUG
906.  		debugpline("Tried to give an impossible intrinsic");
907.  #endif
908.  		break;
909.  	}
910.  }
911.  
912.  STATIC_OVL void
913.  cpostfx(pm)		/* called after completely consuming a corpse */
914.  register int pm;
915.  {
916.  	register int tmp = 0;
917.  	boolean catch_lycanthropy = FALSE;
918.  
919.  	/* in case `afternmv' didn't get called for previously mimicking
920.  	   gold, clean up now to avoid `eatmbuf' memory leak */
921.  	if (eatmbuf) (void)eatmdone();
922.  
923.  	switch(pm) {
924.  	    case PM_NEWT:
925.  		/* MRKR: "eye of newt" may give small magical energy boost */
926.  		if (rn2(3) || 3 * u.uen <= 2 * u.uenmax) {
927.  		    int old_uen = u.uen;
928.  		    u.uen += rnd(3);
929.  		    if (u.uen > u.uenmax) {
930.  			if (!rn2(3)) u.uenmax++;
931.  			u.uen = u.uenmax;
932.  		    }
933.  		    if (old_uen != u.uen) {
934.  			    You_feel("a mild buzz.");
935.  			    flags.botl = 1;
936.  		    }
937.  		}
938.  		break;
939.  	    case PM_WRAITH:
940.  		switch(rnd(10)) {                
941.  		case 1:
942.  		    You("feel that was a bad idea.");
943.  		    losexp("eating a wraith corpse", FALSE);
944.  		    break;
945.  		case 2:                        
946.  		    You("don't feel so good ...");
947.  		    if (Upolyd) {
948.  			u.mhmax -= 4;
949.  			if (u.mhmax < 1) u.mhmax = 1;
950.  		    } else {
951.  			u.uhpmax -= 4;
952.  			if (u.uhpmax < 1) u.uhpmax = 1;
953.  		    }
954.  		    u.uenmax -= 8;
955.  		    if (u.uenmax < 1) u.uenmax = 1;
956.  		    u.uen -= 8;
957.  		    if (u.uen < 0) u.uen = 0;
958.  		    losehp(4, "eating a wraith corpse", KILLED_BY);
959.  		    break;
960.  		case 3:                        
961.  		case 4: 
962.  		    You("feel something strange for a moment.");
963.  		    break;
964.  		case 5: 
965.  		    You("feel physically and mentally stronger!");
966.  		    if (Upolyd) {
967.  			u.mhmax += 4;
968.  			u.mh = u.mhmax;
969.  		    } else {
970.  			u.uhpmax += 4;
971.  			u.uhp = u.uhpmax;
972.  		    }
973.  		    u.uenmax += 8;
974.  		    u.uen = u.uenmax;
975.  		    break;
976.  		case 6:                        
977.  		case 7: 
978.  		case 8:
979.  		case 9:                        
980.  		case 10:                
981.  		    You("feel that was a smart thing to do.");
982.  		pluslvl(FALSE);
983.  		break;
984.  		default:            
985.  		    break;
986.  		}
987.  		flags.botl = 1;
988.  		break;
989.  	    case PM_HUMAN_WERERAT:
990.  		catch_lycanthropy = TRUE;
991.  		if (!Race_if(PM_HUMAN_WEREWOLF)) u.ulycn = PM_WERERAT;
992.  		break;
993.  	    case PM_HUMAN_WEREJACKAL:
994.  		catch_lycanthropy = TRUE;
995.  		if (!Race_if(PM_HUMAN_WEREWOLF)) u.ulycn = PM_WEREJACKAL;
996.  		break;
997.  	    case PM_HUMAN_WEREWOLF:
998.  		catch_lycanthropy = TRUE;
999.  		if (!Race_if(PM_HUMAN_WEREWOLF)) u.ulycn = PM_WEREWOLF;
1000. 		break;
1001. 	    case PM_HUMAN_WEREPANTHER:            
1002. 		catch_lycanthropy = TRUE;
1003. 		if (!Race_if(PM_HUMAN_WEREWOLF)) u.ulycn = PM_WEREPANTHER;
1004. 		break;
1005. 	    case PM_HUMAN_WERETIGER:
1006. 		catch_lycanthropy = TRUE;
1007. 		if (!Race_if(PM_HUMAN_WEREWOLF)) u.ulycn = PM_WERETIGER;
1008. 		break;
1009. 	    case PM_HUMAN_WERESNAKE:
1010. 		catch_lycanthropy = TRUE;
1011. 		if (!Race_if(PM_HUMAN_WEREWOLF)) u.ulycn = PM_WERESNAKE;
1012. 		break;
1013. 	    case PM_HUMAN_WERESPIDER:
1014. 		catch_lycanthropy = TRUE;
1015. 		if (!Race_if(PM_HUMAN_WEREWOLF)) u.ulycn = PM_WERESPIDER;
1016. 		break;
1017. 	    case PM_NURSE:
1018. 		if (Upolyd) u.mh = u.mhmax;
1019. 		else u.uhp = u.uhpmax;
1020. 		flags.botl = 1;
1021. 		break;
1022. 	    case PM_STALKER:
1023. 		if(!Invis) {
1024. 			set_itimeout(&HInvis, (long)rn1(100, 50));
1025. 			if (!Blind && !BInvis) self_invis_message();
1026. 		} else {
1027. 			if (!(HInvis & INTRINSIC)) You_feel("hidden!");
1028. 			HInvis |= FROMOUTSIDE;
1029. 			HSee_invisible |= FROMOUTSIDE;
1030. 		}
1031. 		newsym(u.ux, u.uy);
1032. 		/* fall into next case */
1033. 	    case PM_YELLOW_LIGHT:
1034. 		/* fall into next case */
1035. 	    case PM_GIANT_BAT:
1036. 		make_stunned(HStun + 30,FALSE);
1037. 		/* fall into next case */
1038. 	    case PM_BAT:
1039. 		make_stunned(HStun + 30,FALSE);
1040. 		break;
1041. 	    case PM_GIANT_MIMIC:
1042. 		tmp += 10;
1043. 		/* fall into next case */
1044. 	    case PM_LARGE_MIMIC:
1045. 		tmp += 20;
1046. 		/* fall into next case */
1047. 	    case PM_SMALL_MIMIC:
1048. 		tmp += 20;
1049. 		if (youmonst.data->mlet != S_MIMIC && !Unchanging) {
1050. 		    char buf[BUFSZ];
1051. 		    You_cant("resist the temptation to mimic %s.",
1052. 			Hallucination ? "an orange" : "a pile of gold");
1053. #ifdef STEED
1054.                     /* A pile of gold can't ride. */
1055. 		    if (u.usteed) dismount_steed(DISMOUNT_FELL);
1056. #endif
1057. 		    nomul(-tmp);
1058. 		    Sprintf(buf, Hallucination ?
1059. 			"You suddenly dread being peeled and mimic %s again!" :
1060. 			"You now prefer mimicking %s again.",
1061. 			an(Upolyd ? youmonst.data->mname : urace.noun));
1062. 		    eatmbuf = strcpy((char *) alloc(strlen(buf) + 1), buf);
1063. 		    nomovemsg = eatmbuf;
1064. 		    afternmv = eatmdone;
1065. 		    /* ??? what if this was set before? */
1066. 		    youmonst.m_ap_type = M_AP_OBJECT;
1067. 		    youmonst.mappearance = Hallucination ? ORANGE : GOLD_PIECE;
1068. 		    newsym(u.ux,u.uy);
1069. 		    curs_on_u();
1070. 		    /* make gold symbol show up now */
1071. 		    display_nhwindow(WIN_MAP, TRUE);
1072. 		}
1073. 		break;
1074. 	    case PM_QUANTUM_MECHANIC:
1075. 		Your("velocity suddenly seems very uncertain!");
1076. 		if (HFast & INTRINSIC) {
1077. 			HFast &= ~INTRINSIC;
1078. 			You("seem slower.");
1079. 		} else {
1080. 			HFast |= FROMOUTSIDE;
1081. 			You("seem faster.");
1082. 		}
1083. 		break;
1084. 	    case PM_LIZARD:
1085. 		if (HStun > 2)  make_stunned(2L,FALSE);
1086. 		if (HConfusion > 2)  make_confused(2L,FALSE);
1087. 		break;
1088. 	    case PM_CHAMELEON:
1089. 	    case PM_DOPPELGANGER:
1090. 	 /* case PM_SANDESTIN: */
1091. 		if (!Unchanging) {
1092. 		    You_feel("a change coming over you.");
1093. 		    polyself(FALSE);
1094. 		}
1095. 		break;
1096. 	    case PM_GENETIC_ENGINEER: /* Robin Johnson -- special msg */
1097. 		if (!Unchanging) {
1098. 		    You("undergo a freakish metamorphosis!");
1099. 		    polyself(FALSE);
1100. 		}
1101. 		break;
1102. 		/* WAC all mind flayers as per mondata.h have to be here */
1103. 	    case PM_MASTER_MIND_FLAYER:
1104. 	    case PM_MIND_FLAYER: {
1105. #if 0
1106. 		int     temp;
1107. 		temp = urole.attrmax[A_INT];
1108. #endif
1109. 		if (ABASE(A_INT) < ATTRMAX(A_INT)) {
1110. 			if (!rn2(2)) {
1111. 				pline("Yum! That was real brain food!");
1112. 				(void) adjattrib(A_INT, 1, FALSE);
1113. 				break;	/* don't give them telepathy, too */
1114. 			}
1115. 		}
1116. 		else {
1117. 			pline("For some reason, that tasted bland.");
1118. 		}
1119. 		}
1120. 		/* fall through to default case */
1121. 	    default: {
1122. 		register struct permonst *ptr = &mons[pm];
1123. 		int i, count;
1124. 
1125. 		if (dmgtype(ptr, AD_STUN) || dmgtype(ptr, AD_HALU) ||
1126. 		    pm == PM_VIOLET_FUNGUS) {
1127. 			pline ("Oh wow!  Great stuff!");
1128. 			make_hallucinated(HHallucination + 200,FALSE,0L);
1129. 		}
1130. 		if(is_giant(ptr) && !rn2(4)) gainstr((struct obj *)0, 0);
1131. 
1132. 		/* Check the monster for all of the intrinsics.  If this
1133. 		 * monster can give more than one, pick one to try to give
1134. 		 * from among all it can give.
1135. 		 *
1136. 		 * If a monster can give 4 intrinsics then you have
1137. 		 * a 1/1 * 1/2 * 2/3 * 3/4 = 1/4 chance of getting the first,
1138. 		 * a 1/2 * 2/3 * 3/4 = 1/4 chance of getting the second,
1139. 		 * a 1/3 * 3/4 = 1/4 chance of getting the third,
1140. 		 * and a 1/4 chance of getting the fourth.
1141. 		 *
1142. 		 * And now a proof by induction:
1143. 		 * it works for 1 intrinsic (1 in 1 of getting it)
1144. 		 * for 2 you have a 1 in 2 chance of getting the second,
1145. 		 *	otherwise you keep the first
1146. 		 * for 3 you have a 1 in 3 chance of getting the third,
1147. 		 *	otherwise you keep the first or the second
1148. 		 * for n+1 you have a 1 in n+1 chance of getting the (n+1)st,
1149. 		 *	otherwise you keep the previous one.
1150. 		 * Elliott Kleinrock, October 5, 1990
1151. 		 */
1152. 
1153. 		 count = 0;	/* number of possible intrinsics */
1154. 		 tmp = 0;	/* which one we will try to give */
1155. 		 for (i = 1; i <= LAST_PROP; i++) {
1156. 			if (intrinsic_possible(i, ptr)) {
1157. 				count++;
1158. 				/* a 1 in count chance of replacing the old
1159. 				 * one with this one, and a count-1 in count
1160. 				 * chance of keeping the old one.  (note
1161. 				 * that 1 in 1 and 0 in 1 are what we want
1162. 				 * for the first one
1163. 				 */
1164. 				if (!rn2(count)) {
1165. #ifdef DEBUG
1166. 					debugpline("Intrinsic %d replacing %d",
1167. 								i, tmp);
1168. #endif
1169. 					tmp = i;
1170. 				}
1171. 			}
1172. 		 }
1173. 
1174. 		 /* if any found try to give them one */
1175. 		 if (count) givit(tmp, ptr);
1176. 	    }
1177. 	    break;
1178. 	}
1179. 
1180. 	if (!Race_if(PM_HUMAN_WEREWOLF) &&
1181. 		catch_lycanthropy && defends(AD_WERE, uwep)) {
1182. 	    if (!touch_artifact(uwep, &youmonst)) {
1183. 		dropx(uwep);
1184. 		uwepgone();
1185. 	    }
1186. 	}
1187. 
1188. 	return;
1189. }
1190. 
1191. void
1192. violated_vegetarian()
1193. {
1194.     u.uconduct.unvegetarian++;
1195.     if (Role_if(PM_MONK)) {
1196. 	You_feel("guilty.");
1197. 	adjalign(-1);
1198.     }
1199.     return;
1200. }
1201. 
1202. /* common code to check and possibly charge for 1 context.tin.tin,
1203.  * will split() context.tin.tin if necessary */
1204. STATIC_PTR
1205. void
1206. costly_tin(verb)
1207. 	const char* verb;		/* if 0, the verb is "open" */
1208. {
1209. 	if(((!carried(tin.tin) &&
1210. 	     costly_spot(tin.tin->ox, tin.tin->oy) &&
1211. 	     !tin.tin->no_charge)
1212. 	    || tin.tin->unpaid)) {
1213. 	    verbalize("You %s it, you bought it!", verb ? verb : "open");
1214. 	    if(tin.tin->quan > 1L) tin.tin = splitobj(tin.tin, 1L);
1215. 	    bill_dummy_object(tin.tin);
1216. 	}
1217. }
1218. 
1219. STATIC_PTR
1220. int
1221. opentin()		/* called during each move whilst opening a tin */
1222. {
1223. 	register int r;
1224. 	const char *what;
1225. 	int which;
1226. 
1227. 	if(!carried(tin.tin) && !obj_here(tin.tin, u.ux, u.uy))
1228. 					/* perhaps it was stolen? */
1229. 		return(0);		/* %% probably we should use tinoid */
1230. 	if(tin.usedtime++ >= 50) {
1231. 		You("give up your attempt to open the tin.");
1232. 		return(0);
1233. 	}
1234. 	if(tin.usedtime < tin.reqtime)
1235. 		return(1);		/* still busy */
1236. 	if(tin.tin->otrapped ||
1237. 	   (tin.tin->cursed && tin.tin->spe != -1 && !rn2(8))) {
1238. 		b_trapped("tin", 0);
1239. 		costly_tin("destroyed");
1240. 		goto use_me;
1241. 	}
1242. 	You("succeed in opening the tin.");
1243. 	if(tin.tin->spe != 1) {
1244. 	    if (tin.tin->corpsenm == NON_PM) {
1245. 		pline("It turns out to be empty.");
1246. 		tin.tin->dknown = tin.tin->known = TRUE;
1247. 		costly_tin((const char*)0);
1248. 		goto use_me;
1249. 	    }
1250. 	    r = tin.tin->cursed ? ROTTEN_TIN :	/* always rotten if cursed */
1251. 		    (tin.tin->spe == -1) ? HOMEMADE_TIN :  /* player made it */
1252. 			rn2(TTSZ-1);		/* else take your pick */
1253. 	    if (r == ROTTEN_TIN && (tin.tin->corpsenm == PM_LIZARD ||
1254. 			tin.tin->corpsenm == PM_LICHEN))
1255. 		r = HOMEMADE_TIN;		/* lizards don't rot */
1256. 	    else if (tin.tin->spe == -1 && !tin.tin->blessed && !rn2(7))
1257. 		r = ROTTEN_TIN;			/* some homemade tins go bad */
1258. 	    which = 0;	/* 0=>plural, 1=>as-is, 2=>"the" prefix */
1259. 	    if (Hallucination) {
1260. 		what = rndmonnam();
1261. 	    } else {
1262. 		what = mons[tin.tin->corpsenm].mname;
1263. 		if (mons[tin.tin->corpsenm].geno & G_UNIQ)
1264. 		    which = type_is_pname(&mons[tin.tin->corpsenm]) ? 1 : 2;
1265. 	    }
1266. 	    if (which == 0) what = makeplural(what);
1267. #ifdef EATEN_MEMORY
1268. 	    /* ALI - you already know the type of the tinned meat */
1269. 	    if (tin.tin->known && mvitals[tin.tin->corpsenm].eaten < 255)
1270. 		mvitals[tin.tin->corpsenm].eaten++;
1271. 	    /* WAC - you only recognize if you've eaten this before */
1272. 	    if (!mvitals[tin.tin->corpsenm].eaten && !Hallucination) {
1273. 		if (rn2(2))
1274. 			pline ("It smells kind of like %s.",
1275. 				monexplain[mons[tin.tin->corpsenm].mlet]);
1276. 		else 
1277. 			pline_The("smell is unfamiliar.");
1278. 	    } else
1279. #endif
1280. 	    pline("It smells like %s%s.", (which == 2) ? "the " : "", what);
1281. 
1282. 	    if (yn("Eat it?") == 'n') {
1283. #ifdef EATEN_MEMORY
1284. 	    	/* ALI - you know the tin iff you recognized the contents */
1285. 		if (mvitals[tin.tin->corpsenm].eaten)
1286. #endif
1287. 		if (!Hallucination) tin.tin->dknown = tin.tin->known = TRUE;
1288. 		if (flags.verbose) You("discard the open tin.");
1289. 		costly_tin((const char*)0);
1290. 		goto use_me;
1291. 	    }
1292. 	    /* in case stop_occupation() was called on previous meal */
1293. 	    victual.piece = (struct obj *)0;
1294. 	    victual.fullwarn = victual.eating = victual.doreset = FALSE;
1295. 
1296. #ifdef EATEN_MEMORY
1297. 	    /* WAC - you only recognize if you've eaten this before */
1298. 	    You("consume %s %s.", tintxts[r].txt,
1299. 				mvitals[tin.tin->corpsenm].eaten ?
1300. 				mons[tin.tin->corpsenm].mname : "food");
1301. #else
1302. 	    You("consume %s %s.", tintxts[r].txt,
1303. 			mons[tin.tin->corpsenm].mname);
1304. #endif
1305. 
1306. 	    /* KMH, conduct */
1307. 	    u.uconduct.food++;
1308. 	    if (!vegan(&mons[tin.tin->corpsenm]))
1309. 		u.uconduct.unvegan++;
1310. 	    if (!vegetarian(&mons[tin.tin->corpsenm]))
1311. 		violated_vegetarian();
1312. 
1313. #ifdef EATEN_MEMORY
1314. 	    if (mvitals[tin.tin->corpsenm].eaten)
1315. #endif
1316. 	    tin.tin->dknown = tin.tin->known = TRUE;
1317. 	    cprefx(tin.tin->corpsenm); cpostfx(tin.tin->corpsenm);
1318. 
1319. 	    /* charge for one at pre-eating cost */
1320. 	    costly_tin((const char*)0);
1321. 
1322. 	    /* check for vomiting added by GAN 01/16/87 */
1323. 	    if(tintxts[r].nut < 0) make_vomiting((long)rn1(15,10), FALSE);
1324. 	    else lesshungry(tintxts[r].nut);
1325. 
1326. 	    if(r == 0 || r == FRENCH_FRIED_TIN) {
1327. 	        /* Assume !Glib, because you can't open tins when Glib. */
1328. 		incr_itimeout(&Glib, rnd(15));
1329. 		pline("Eating deep fried food made your %s very slippery.",
1330. 		      makeplural(body_part(FINGER)));
1331. 	    }
1332. 	} else {
1333. 	    if (tin.tin->cursed)
1334. 		pline("It contains some decaying%s%s substance.",
1335. 			Blind ? "" : " ", Blind ? "" : hcolor(NH_GREEN));
1336. 	    else
1337. 		pline("It contains spinach.");
1338. 
1339. 	    if (yn("Eat it?") == 'n') {
1340. 		if (!Hallucination && !tin.tin->cursed)
1341. 		    tin.tin->dknown = tin.tin->known = TRUE;
1342. 		if (flags.verbose)
1343. 		    You("discard the open tin.");
1344. 		costly_tin((const char*)0);
1345. 		goto use_me;
1346. 	    }
1347. 
1348. 	    tin.tin->dknown = tin.tin->known = TRUE;
1349. 	    costly_tin((const char*)0);
1350. 
1351. 	    if (!tin.tin->cursed)
1352. 		pline("This makes you feel like %s!",
1353. 		      Hallucination ? "Swee'pea" : "Popeye");
1354. 	    lesshungry(600);
1355. 	    gainstr(tin.tin, 0);
1356. 	    u.uconduct.food++;
1357. 	}
1358. use_me:
1359. 	if (carried(tin.tin)) useup(tin.tin);
1360. 	else useupf(tin.tin, 1L);
1361. 	tin.tin = (struct obj *) 0;
1362. 	return(0);
1363. }
1364. 
1365. STATIC_OVL void
1366. start_tin(otmp)		/* called when starting to open a tin */
1367. 	register struct obj *otmp;
1368. {
1369. 	register int tmp;
1370. 
1371. 	if (metallivorous(youmonst.data)) {
1372. 		You("bite right into the metal tin...");
1373. 		tmp = 1;
1374. 	} else if (nolimbs(youmonst.data)) {
1375. 		You("cannot handle the tin properly to open it.");
1376. 		return;
1377. 	} else if (otmp->blessed) {
1378. 		pline_The("tin opens like magic!");
1379. 		tmp = 1;
1380. 	} else if(uwep) {
1381. 		switch(uwep->otyp) {
1382. 		case TIN_OPENER:
1383. 			tmp = 1;
1384. 			break;
1385. 		case DAGGER:
1386. 		case SILVER_DAGGER:
1387. 		case ELVEN_DAGGER:
1388. 		case ORCISH_DAGGER:
1389. 		case ATHAME:
1390. 		case CRYSKNIFE:
1391. 		case DARK_ELVEN_DAGGER:
1392. 		case GREAT_DAGGER:
1393. 			tmp = 3;
1394. 			break;
1395. 		case PICK_AXE:
1396. 		case AXE:
1397. 			tmp = 6;
1398. 			break;
1399. 		default:
1400. 			goto no_opener;
1401. 		}
1402. 		pline("Using your %s you try to open the tin.",
1403. 			aobjnam(uwep, (char *)0));
1404. 	} else {
1405. no_opener:
1406. 		pline("It is not so easy to open this tin.");
1407. 		if(Glib) {
1408. 			pline_The("tin slips from your %s.",
1409. 			      makeplural(body_part(FINGER)));
1410. 			if(otmp->quan > 1L) {
1411. 			    otmp = splitobj(otmp, 1L);
1412. 			}
1413. 			if (carried(otmp)) dropx(otmp);
1414. 			else stackobj(otmp);
1415. 			return;
1416. 		}
1417. 		tmp = rn1(1 + 500/((int)(ACURR(A_DEX) + ACURRSTR)), 10);
1418. 	}
1419. 	tin.reqtime = tmp;
1420. 	tin.usedtime = 0;
1421. 	tin.tin = otmp;
1422. 	set_occupation(opentin, "opening the tin", 0);
1423. 	return;
1424. }
1425. 
1426. int
1427. Hear_again()		/* called when waking up after fainting */
1428. {
1429. 	flags.soundok = 1;
1430. 	return 0;
1431. }
1432. 
1433. /* called on the "first bite" of rotten food */
1434. STATIC_OVL int
1435. rottenfood(obj)
1436. struct obj *obj;
1437. {
1438. 	pline("Blecch!  Rotten %s!", foodword(obj));
1439. 	if(!rn2(4)) {
1440. 		if (Hallucination) You_feel("rather trippy.");
1441. 		else You_feel("rather %s.", body_part(LIGHT_HEADED));
1442. 		make_confused(HConfusion + d(2,4),FALSE);
1443. 	} else if(!rn2(4) && !Blind) {
1444. 		pline("Everything suddenly goes dark.");
1445. 		make_blinded((long)d(2,10),FALSE);
1446. 		if (!Blind) Your(vision_clears);
1447. 	} else if(!rn2(3)) {
1448. 		const char *what, *where;
1449. 		if (!Blind)
1450. 		    what = "goes",  where = "dark";
1451. 		else if (Levitation || Is_airlevel(&u.uz) ||
1452. 			 Is_waterlevel(&u.uz))
1453. 		    what = "you lose control of",  where = "yourself";
1454. 		else
1455. 		    what = "you slap against the", where =
1456. #ifdef STEED
1457. 			   (u.usteed) ? "saddle" :
1458. #endif
1459. 			   surface(u.ux,u.uy);
1460. 		pline_The("world spins and %s %s.", what, where);
1461. 		flags.soundok = 0;
1462. 		nomul(-rnd(10));
1463. 		nomovemsg = "You are conscious again.";
1464. 		afternmv = Hear_again;
1465. 		return(1);
1466. 	}
1467. 	return(0);
1468. }
1469. 
1470. /* [ALI] Return codes:
1471.  *
1472.  *	0 - Ready to start eating
1473.  *	1 - Corpse partly eaten, but don't start occupation
1474.  *	2 - Corpse completely consumed, victual.piece left dangling
1475.  *	3 - Corpse was inedible
1476.  */
1477. 
1478. STATIC_OVL int
1479. eatcorpse(otmp)		/* called when a corpse is selected as food */
1480. 	register struct obj *otmp;
1481. {
1482. 	int tp = 0, mnum = otmp->corpsenm;
1483. 	long rotted = 0L;
1484. 	boolean uniq = !!(mons[mnum].geno & G_UNIQ);
1485. 	int retcode = 0;
1486. 	boolean stoneable = (touch_petrifies(&mons[mnum]) && !Stone_resistance &&
1487. 				!poly_when_stoned(youmonst.data));
1488. 
1489. 
1490. 	/* KMH, conduct */
1491. 	if (!vegan(&mons[mnum])) u.uconduct.unvegan++;
1492. 	if (!vegetarian(&mons[mnum])) violated_vegetarian();
1493. 
1494. 	if (mnum != PM_LIZARD && mnum != PM_LICHEN) {
1495. 		long age = peek_at_iced_corpse_age(otmp);
1496. 
1497. 		rotted = (monstermoves - age)/(10L + rn2(20));
1498. 		if (otmp->cursed) rotted += 2L;
1499. 		else if (otmp->blessed) rotted -= 2L;
1500. 	}
1501. 
1502. 	/* Vampires only drink the blood of very young, meaty corpses 
1503. 	 * is_edible only allows meaty corpses here
1504. 	 * Blood is assumed to be 1/5 of the nutrition
1505. 	 * Thus happens before the conduct checks intentionally - should it be after?
1506. 	 * Blood is assumed to be meat and flesh.
1507. 	 */
1508. 	if (is_vampire(youmonst.data)) {
1509. 	    /* oeaten is set up by touchfood */
1510. 	    if (otmp->odrained ? otmp->oeaten <= drainlevel(otmp) :
1511. 	      otmp->oeaten < mons[otmp->corpsenm].cnutrit) {
1512. 	    	pline("There is no blood left in this corpse!");
1513. 	    	return 3;
1514. 	    } else if (rotted <= 0 &&
1515. 	      (peek_at_iced_corpse_age(otmp) + 5) >= monstermoves) {
1516. 		char buf[BUFSZ];
1517. 
1518. 		/* Generate the name for the corpse */
1519. 		if (!uniq || Hallucination)
1520. 		    Sprintf(buf, "%s", the(corpse_xname(otmp,TRUE)));
1521. 		else
1522. 		    Sprintf(buf, "%s%s corpse",
1523. 			    !type_is_pname(&mons[mnum]) ? "the " : "",
1524. 			    s_suffix(mons[mnum].mname));
1525. 
1526. 	    	pline("You drain the blood from %s.", buf);
1527. 		otmp->odrained = 1;
1528. 	    } else {
1529. 	    	pline("The blood in this corpse has coagulated!");
1530. 	    	return 3;
1531. 	    }
1532. 	}
1533. 	else
1534. 	    otmp->odrained = 0;
1535. 
1536. 	/* Very rotten corpse will make you sick unless you are a ghoul or a ghast */
1537. 	if (mnum != PM_ACID_BLOB && !stoneable && rotted > 5L) {
1538. 	    boolean cannibal = maybe_cannibal(mnum, FALSE);
1539. 	    if (u.umonnum == PM_GHOUL || u.umonnum == PM_GHAST) {
1540. 	    	pline("Yum - that %s was well aged%s!",
1541. 		      mons[mnum].mlet == S_FUNGUS ? "fungoid vegetation" :
1542. 		      !vegetarian(&mons[mnum]) ? "meat" : "protoplasm",
1543. 		      cannibal ? ", cannibal" : "");
1544. 	    } else {	    
1545. 		pline("Ulch - that %s was tainted%s!",
1546. 		      mons[mnum].mlet == S_FUNGUS ? "fungoid vegetation" :
1547. 		      !vegetarian(&mons[mnum]) ? "meat" : "protoplasm",
1548. 		      cannibal ? ", cannibal" : "");
1549. 		if (Sick_resistance) {
1550. 			pline("It doesn't seem at all sickening, though...");
1551. 		} else {
1552. 			char buf[BUFSZ];
1553. 			long sick_time;
1554. 
1555. 			sick_time = (long) rn1(10, 10);
1556. 			/* make sure new ill doesn't result in improvement */
1557. 			if (Sick && (sick_time > Sick))
1558. 			    sick_time = (Sick > 1L) ? Sick - 1L : 1L;
1559. 			if (!uniq || Hallucination)
1560. 			    Sprintf(buf, "rotted %s", corpse_xname(otmp,TRUE));
1561. 			else
1562. 			    Sprintf(buf, "%s%s rotted corpse",
1563. 				    !type_is_pname(&mons[mnum]) ? "the " : "",
1564. 				    s_suffix(mons[mnum].mname));
1565. 			make_sick(sick_time, buf, TRUE, SICK_VOMITABLE);
1566. 		}
1567. 		if (carried(otmp)) useup(otmp);
1568. 		else useupf(otmp, 1L);
1569. 		return(2);
1570. 	    }
1571. 	} else if (youmonst.data == &mons[PM_GHOUL] || 
1572. 		   youmonst.data == &mons[PM_GHAST]) {
1573. 		pline ("This corpse is too fresh!");
1574. 		return 3;
1575. 	} else if (acidic(&mons[mnum]) && !Acid_resistance) {
1576. 		tp++;
1577. 		You("have a very bad case of stomach acid."); /* not body_part() */
1578. 		losehp(rnd(15), "acidic corpse", KILLED_BY_AN);
1579. 	} else if (poisonous(&mons[mnum]) && rn2(5)) {
1580. 		tp++;
1581. 		pline("Ecch - that must have been poisonous!");
1582. 		if(!Poison_resistance) {
1583. 			losestr(rnd(4));
1584. 			losehp(rnd(15), "poisonous corpse", KILLED_BY_AN);
1585. 		} else	You("seem unaffected by the poison.");
1586. 	/* now any corpse left too long will make you mildly ill */
1587. 	} else if ((rotted > 5L || (rotted > 3L && rn2(5)))
1588. 					&& !Sick_resistance) {
1589. 		tp++;
1590. 		You_feel("%ssick.", (Sick) ? "very " : "");
1591. 		losehp(rnd(8), "cadaver", KILLED_BY_AN);
1592. 	}
1593. 
1594. 	/* delay is weight dependent */
1595. 	victual.reqtime = 3 + (mons[mnum].cwt >> 6);
1596. 	if (otmp->odrained) victual.reqtime = rounddiv(victual.reqtime, 5);
1597. 
1598. 	if (!tp && mnum != PM_LIZARD && mnum != PM_LICHEN &&
1599. 			(otmp->orotten || !rn2(7))) {
1600. 	    if (rottenfood(otmp)) {
1601. 		otmp->orotten = TRUE;
1602. 		(void)touchfood(otmp);
1603. 		retcode = 1;
1604. 	    }
1605. 
1606. 	    if (!mons[otmp->corpsenm].cnutrit) {
1607. 		/* no nutrution: rots away, no message if you passed out */
1608. 		if (!retcode) pline_The("corpse rots away completely.");
1609. 		if (carried(otmp)) useup(otmp);
1610. 		else useupf(otmp, 1L);
1611. 		retcode = 2;
1612. 	    }
1613. 		    
1614. 	    if (!retcode) consume_oeaten(otmp, 2);	/* oeaten >>= 2 */
1615. 	    if (otmp->odrained && otmp->oeaten < drainlevel(otmp))
1616. 	        otmp->oeaten = drainlevel(otmp);
1617. 	} else if (!is_vampire(youmonst.data)) {
1618. 	    pline("%s%s %s!",
1619. 		  !uniq ? "This " : !type_is_pname(&mons[mnum]) ? "The " : "",
1620. 		  food_xname(otmp, FALSE),
1621. 		  (vegan(&mons[mnum]) ?
1622. 		   (!carnivorous(youmonst.data) && herbivorous(youmonst.data)) :
1623. 		   (carnivorous(youmonst.data) && !herbivorous(youmonst.data)))
1624. 		  ? "is delicious" : "tastes terrible");
1625. 	}
1626. 
1627. #ifdef EATEN_MEMORY
1628. 	/* WAC Track food types eaten */
1629. 	if (mvitals[mnum].eaten < 255) mvitals[mnum].eaten++;
1630. #endif
1631. 
1632. 	return(retcode);
1633. }
1634. 
1635. STATIC_OVL void
1636. start_eating(otmp)		/* called as you start to eat */
1637. 	register struct obj *otmp;
1638. {
1639. #ifdef DEBUG
1640. 	debugpline("start_eating: %lx (victual = %lx)", otmp, victual.piece);
1641. 	debugpline("reqtime = %d", victual.reqtime);
1642. 	debugpline("(original reqtime = %d)", objects[otmp->otyp].oc_delay);
1643. 	debugpline("nmod = %d", victual.nmod);
1644. 	debugpline("oeaten = %d", otmp->oeaten);
1645. #endif
1646. 	victual.fullwarn = victual.doreset = FALSE;
1647. 	victual.eating = TRUE;
1648. 
1649. 	if (otmp->otyp == CORPSE) {
1650. 	    cprefx(victual.piece->corpsenm);
1651. 	    if (!victual.piece || !victual.eating) {
1652. 		/* rider revived, or died and lifesaved */
1653. 		return;
1654. 	    }
1655. 	}
1656. 
1657. 	if (bite()) return;
1658. 
1659. 	if (++victual.usedtime >= victual.reqtime) {
1660. 	    /* print "finish eating" message if they just resumed -dlc */
1661. 	    done_eating(victual.reqtime > 1 ? TRUE : FALSE);
1662. 	    return;
1663. 	}
1664. 
1665. 	Sprintf(msgbuf, "%s %s", otmp->odrained ? "draining" : "eating",
1666. 	  food_xname(otmp, TRUE));
1667. 	set_occupation(eatfood, msgbuf, 0);
1668. }
1669. 
1670. 
1671. /*
1672.  * called on "first bite" of (non-corpse) food.
1673.  * used for non-rotten non-tin non-corpse food
1674.  */
1675. STATIC_OVL void
1676. fprefx(otmp)
1677. struct obj *otmp;
1678. {
1679. 	switch(otmp->otyp) {
1680. 
1681. 	    case FOOD_RATION:
1682. 		if(u.uhunger <= 200)
1683. 		    pline(Hallucination ? "Oh wow, like, superior, man!" :
1684. 			  "That food really hit the spot!");
1685. 		else if(u.uhunger <= 700) pline("That satiated your %s!",
1686. 						body_part(STOMACH));
1687. 		break;
1688. 	    case TRIPE_RATION:
1689. 		if (carnivorous(youmonst.data) && (!humanoid(youmonst.data)) || 
1690. 			u.ulycn != NON_PM && carnivorous(&mons[u.ulycn]) && 
1691. 			!humanoid(&mons[u.ulycn]))
1692. 		    /* Symptom of lycanthropy is starting to like your
1693. 		     * alternative form's food! 
1694. 		     */
1695. 		    pline("That tripe ration was surprisingly good!");
1696. 		else if (maybe_polyd(is_orc(youmonst.data), Race_if(PM_ORC)))
1697. 		    pline(Hallucination ? "Tastes great! Less filling!" :
1698. 			  "Mmm, tripe... not bad!");
1699. 		else {
1700. 		    pline("Yak - dog food!");
1701. 		    more_experienced(1,0);
1702. 		    newexplevel();
1703. 		    /* not cannibalism, but we use similar criteria
1704. 		       for deciding whether to be sickened by this meal */
1705. 		    if (rn2(2) && !CANNIBAL_ALLOWED())
1706. 			make_vomiting((long)rn1(victual.reqtime, 14), FALSE);
1707. 		}
1708. 		break;
1709. 	    case PILL:            
1710. 		You("swallow the little pink pill.");
1711. 		switch(rn2(7))
1712. 		{
1713. 		   case 0:
1714. 			/* [Tom] wishing pills are from the Land of Oz */
1715. 			pline ("The pink sugar coating hid a silver wishing pill!");
1716. 			makewish();
1717. 			break;
1718. 		   case 1:
1719. 			if(!Poison_resistance) {
1720. 				You("feel your stomach twinge.");
1721. 				losestr(rnd(4));
1722. 				losehp(rnd(15), "poisonous pill", KILLED_BY_AN);
1723. 			} else  You("seem unaffected by the poison.");
1724. 			break;
1725. 		   case 2:
1726. 			pline ("Everything begins to get blurry.");
1727. 			make_stunned(HStun + 30,FALSE);
1728. 			break;
1729. 		   case 3:
1730. 			pline ("Oh wow!  Look at the lights!");
1731. 			make_hallucinated(HHallucination + 150,FALSE,0L);
1732. 			break;
1733. 		   case 4:
1734. 			pline("That tasted like vitamins...");
1735. 			lesshungry(600);
1736. 			break;
1737. 		   case 5:
1738. 			if(Sleep_resistance) {
1739. 				pline("Hmm. Nothing happens.");
1740. 			} else {
1741. 				pline("You feel drowsy...");
1742. 				nomul(-rn2(50));
1743. 				u.usleep = 1;
1744. 				nomovemsg = "You wake up.";
1745. 			}
1746. 			break;
1747. 		   case 6:
1748. 			pline("Wow... everything is moving in slow motion...");
1749. 			/* KMH, balance patch -- Use incr_itimeout() instead of += */
1750. 			incr_itimeout(&HFast, rn1(10,200));
1751. 			break;
1752. 		}
1753. 		break;
1754. 	    case MUSHROOM:
1755. 	       pline("This %s is %s", singular(otmp, xname),
1756. 	       otmp->cursed ? (Hallucination ? "far-out!" : "terrible!") :
1757. 		      Hallucination ? "groovy!" : "delicious!");
1758. 		switch(rn2(10))
1759. 		{
1760. 		   case 0:
1761. 		   case 1:
1762. 			if(!Poison_resistance) {
1763. 				You("feel rather ill....");
1764. 				losestr(rnd(4));
1765. 				losehp(rnd(15), "poisonous mushroom", KILLED_BY_AN);
1766. 			} else  You("burp loudly.");
1767. 			break;
1768. 		   case 2:
1769. 			pline ("That mushroom tasted a little funny.");
1770. 			make_stunned(HStun + 30,FALSE);
1771. 			break;
1772. 		   case 3:
1773. 			pline ("Whoa! Everything looks groovy!");
1774. 			make_hallucinated(HHallucination + 150,FALSE,0L);
1775. 			break;
1776. 		   case 4:
1777. 			gainstr(otmp, 1);
1778. 			pline ("You feel stronger!");
1779. 			break;                                           
1780. 		   case 5:
1781. 		   case 6:
1782. 		   case 7:
1783. 		   case 8:
1784. 		   case 9:
1785. 			break;
1786. 		}
1787. 		break;
1788. 	    case MEATBALL:
1789. 	    case MEAT_STICK:
1790. 	    case HUGE_CHUNK_OF_MEAT:
1791. 	    case MEAT_RING:
1792. 		goto give_feedback;
1793. 	     /* break; */
1794. 	    case CLOVE_OF_GARLIC:
1795. 		if (is_undead(youmonst.data)) {
1796. 			make_vomiting((long)rn1(victual.reqtime, 5), FALSE);
1797. 			break;
1798. 		}
1799. 		/* Fall through otherwise */
1800. 	    default:
1801. 		if (otmp->otyp == SLIME_MOLD && !otmp->cursed
1802. 			&& otmp->spe == current_fruit)
1803. 		    pline("My, that was a %s %s!",
1804. 			  Hallucination ? "primo" : "yummy",
1805. 			  singular(otmp, xname));
1806. 		else
1807. #ifdef UNIX
1808. 		if (otmp->otyp == APPLE || otmp->otyp == PEAR) {
1809. 		    if (!Hallucination) pline("Core dumped.");
1810. 		    else {
1811. /* This is based on an old Usenet joke, a fake a.out manual page */
1812. 			int x = rnd(100);
1813. 			if (x <= 75)
1814. 			    pline("Segmentation fault -- core dumped.");
1815. 			else if (x <= 99)
1816. 			    pline("Bus error -- core dumped.");
1817. 			else pline("Yo' mama -- core dumped.");
1818. 		    }
1819. 		} else
1820. #endif
1821. #ifdef MAC	/* KMH -- Why should Unix have all the fun? */
1822. 		if (otmp->otyp == APPLE) {
1823. 			pline("This Macintosh is wonderful!");
1824. 		} else
1825. #endif
1826. 		if (otmp->otyp == EGG && stale_egg(otmp)) {
1827. 		    pline("Ugh.  Rotten egg.");	/* perhaps others like it */
1828. 		    make_vomiting(Vomiting+d(10,4), TRUE);
1829. 		} else {
1830. 		    boolean bad_for_you;
1831.  give_feedback:
1832. 		    bad_for_you = otmp->cursed ||
1833. 		      (Race_if(PM_HUMAN_WEREWOLF) &&
1834. 		      otmp->otyp == SPRIG_OF_WOLFSBANE);
1835. 		    pline("This %s is %s", singular(otmp, xname),
1836. 		      bad_for_you ? (Hallucination ? "grody!" : "terrible!") :
1837. 		      (otmp->otyp == CRAM_RATION
1838. 		      || otmp->otyp == K_RATION
1839. 		      || otmp->otyp == C_RATION)
1840. 		      ? "bland." :
1841. 		      Hallucination ? "gnarly!" : "delicious!");
1842. 		}
1843. 		break;
1844. 	}
1845. }
1846. 
1847. STATIC_OVL void
1848. accessory_has_effect(otmp)
1849. struct obj *otmp;
1850. {
1851. 	pline("Magic spreads through your body as you digest the %s.",
1852. 	    otmp->oclass == RING_CLASS ? "ring" : "amulet");
1853. }
1854. 
1855. STATIC_OVL void
1856. eataccessory(otmp)
1857. struct obj *otmp;
1858. {
1859. 	int typ = otmp->otyp;
1860. 	long oldprop;
1861. 
1862. 	/* Note: rings are not so common that this is unbalancing. */
1863. 	/* (How often do you even _find_ 3 rings of polymorph in a game?) */
1864. 	/* KMH, intrinsic patch -- several changes below */
1865. 	oldprop = u.uprops[objects[typ].oc_oprop].intrinsic;
1866. 	if (otmp == uleft || otmp == uright) {
1867. 	    Ring_gone(otmp);
1868. 	    if (u.uhp <= 0) return; /* died from sink fall */
1869. 	}
1870. 	otmp->known = otmp->dknown = 1; /* by taste */
1871. 	if (!rn2(otmp->oclass == RING_CLASS ? 3 : 5)) {
1872. 	  switch (otmp->otyp) {
1873. 	    default:
1874. 	        if (!objects[typ].oc_oprop) break; /* should never happen */
1875. 
1876. 		if (!(u.uprops[objects[typ].oc_oprop].intrinsic & FROMOUTSIDE))
1877. 		    accessory_has_effect(otmp);
1878. 
1879. 		u.uprops[objects[typ].oc_oprop].intrinsic |= FROMOUTSIDE;
1880. 
1881. 		switch (typ) {
1882. 		  case RIN_SEE_INVISIBLE:
1883. 		    set_mimic_blocking();
1884. 		    see_monsters();
1885. 		    if (Invis && !oldprop && !ESee_invisible &&
1886. 				!perceives(youmonst.data) && !Blind) {
1887. 			newsym(u.ux,u.uy);
1888. 			pline("Suddenly you can see yourself.");
1889. 			makeknown(typ);
1890. 		    }
1891. 		    break;
1892. 		  case RIN_INVISIBILITY:
1893. 		    if (!oldprop && !EInvis && !BInvis &&
1894. 					!See_invisible && !Blind) {
1895. 			newsym(u.ux,u.uy);
1896. 			Your("body takes on a %s transparency...",
1897. 				Hallucination ? "normal" : "strange");
1898. 			makeknown(typ);
1899. 		    }
1900. 		    break;
1901. 		  case RIN_PROTECTION_FROM_SHAPE_CHAN:
1902. 		    rescham();
1903. 		    break;
1904. 		  case RIN_LEVITATION:
1905. 		    /* undo the `.intrinsic |= FROMOUTSIDE' done above */
1906. 		    u.uprops[LEVITATION].intrinsic = oldprop;
1907. 		    if (!Levitation) {
1908. 			float_up();
1909. 			incr_itimeout(&HLevitation, d(10,20));
1910. 			makeknown(typ);
1911. 		    }
1912. 		    break;
1913. 		}
1914. 		break;
1915. 	    case RIN_ADORNMENT:
1916. 		accessory_has_effect(otmp);
1917. 		if (adjattrib(A_CHA, otmp->spe, -1))
1918. 		    makeknown(typ);
1919. 		break;
1920. 	    case RIN_GAIN_STRENGTH:
1921. 		accessory_has_effect(otmp);
1922. 		if (adjattrib(A_STR, otmp->spe, -1))
1923. 		    makeknown(typ);
1924. 		break;
1925. 	    case RIN_GAIN_CONSTITUTION:
1926. 		accessory_has_effect(otmp);
1927. 		if (adjattrib(A_CON, otmp->spe, -1))
1928. 		    makeknown(typ);
1929. 		break;
1930. 	    case RIN_GAIN_INTELLIGENCE:
1931. 		accessory_has_effect(otmp);
1932. 		if (adjattrib(A_INT, otmp->spe, -1))
1933. 		    makeknown(typ);
1934. 		break;
1935. 	    case RIN_GAIN_WISDOM:
1936. 		accessory_has_effect(otmp);
1937. 		if (adjattrib(A_WIS, otmp->spe, -1))
1938. 		    makeknown(typ);
1939. 		break;
1940. 	    case RIN_GAIN_DEXTERITY:
1941. 		accessory_has_effect(otmp);
1942. 		if (adjattrib(A_DEX, otmp->spe, -1))
1943. 		    makeknown(typ);
1944. 		break;
1945. 	    case RIN_INCREASE_ACCURACY:
1946. 		accessory_has_effect(otmp);
1947. 		u.uhitinc += otmp->spe;
1948. 		break;
1949. 	    case RIN_INCREASE_DAMAGE:
1950. 		accessory_has_effect(otmp);
1951. 		u.udaminc += otmp->spe;
1952. 		break;
1953. 	    case RIN_PROTECTION:
1954. 		accessory_has_effect(otmp);
1955. 		HProtection |= FROMOUTSIDE;
1956. 		u.ublessed += otmp->spe;
1957. 		flags.botl = 1;
1958. 		break;
1959. 	    case RIN_FREE_ACTION:
1960. 		/* Give sleep resistance instead */
1961. 		if (!(HSleep_resistance & FROMOUTSIDE))
1962. 		    accessory_has_effect(otmp);
1963. 		if (!Sleep_resistance)
1964. 		    You_feel("wide awake.");
1965. 		HSleep_resistance |= FROMOUTSIDE;
1966. 		break;
1967. 	    case AMULET_OF_CHANGE:
1968. 		accessory_has_effect(otmp);
1969. 		makeknown(typ);
1970. 		change_sex();
1971. 		You("are suddenly very %s!",
1972. 		    flags.female ? "feminine" : "masculine");
1973. 		flags.botl = 1;
1974. 		break;
1975. 	    case AMULET_OF_UNCHANGING:
1976. 		/* un-change: it's a pun */
1977. 		if (!Unchanging && Upolyd) {
1978. 		    accessory_has_effect(otmp);
1979. 		    makeknown(typ);
1980. 		    rehumanize();
1981. 		}
1982. 		break;
1983. 	    case AMULET_OF_STRANGULATION: /* bad idea! */
1984. 		/* no message--this gives no permanent effect */
1985. 		choke(otmp);
1986. 		break;
1987. 	    case AMULET_OF_RESTFUL_SLEEP: /* another bad idea! */
1988. 	    case RIN_SLEEPING:
1989. 		if (!(HSleeping & FROMOUTSIDE))
1990. 		    accessory_has_effect(otmp);
1991. 		HSleeping = FROMOUTSIDE | rnd(100);
1992. 		break;
1993. 	    case AMULET_VERSUS_STONE:
1994. 		/* no message--this gives no permanent effect */
1995. 		(void)uunstone();
1996. 		break;
1997. 	    case RIN_SUSTAIN_ABILITY:
1998. 	    case AMULET_OF_FLYING: /* Intrinsic flying not supported --ALI */
1999. 	    case AMULET_OF_LIFE_SAVING:
2000. 	    case AMULET_OF_REFLECTION: /* nice try */
2001. 	    case AMULET_OF_DRAIN_RESISTANCE:
2002. 	    /* can't eat Amulet of Yendor or fakes,
2003. 	     * and no oc_prop even if you could -3.
2004. 	     */
2005. 		break;
2006. 	  }
2007. 	}
2008. }
2009. 
2010. STATIC_OVL void
2011. eatspecial() /* called after eating non-food */
2012. {
2013. 	register struct obj *otmp = victual.piece;
2014. 
2015. 	/* lesshungry wants an occupation to handle choke messages correctly */
2016. 	set_occupation(eatfood, "eating non-food", 0);
2017. 	lesshungry(victual.nmod);
2018. 	occupation = 0;
2019. 	victual.piece = (struct obj *)0;
2020. 	victual.eating = 0;
2021. 	if (otmp->oclass == COIN_CLASS) {
2022. #ifdef GOLDOBJ
2023. 		if (carried(otmp))
2024. 		    useupall(otmp);
2025. #else
2026. 		if (otmp->where == OBJ_FREE)
2027. 		    dealloc_obj(otmp);
2028. #endif
2029. 		else
2030. 		    useupf(otmp, otmp->quan);
2031. 		return;
2032. 	}
2033. 	if (otmp->oclass == POTION_CLASS) {
2034. 		otmp->quan++; /* dopotion() does a useup() */
2035. 		(void)dopotion(otmp);
2036. 	}
2037. 	if (otmp->oclass == RING_CLASS || otmp->oclass == AMULET_CLASS)
2038. 		eataccessory(otmp);
2039. 	else if (otmp->otyp == LEASH && otmp->leashmon)
2040. 		o_unleash(otmp);
2041. 
2042. 	/* KMH -- idea by "Tommy the Terrorist" */
2043. 	if ((otmp->otyp == TRIDENT) && !otmp->cursed)
2044. 	{
2045. 		pline(Hallucination ? "Four out of five dentists agree." :
2046. 				"That was pure chewing satisfaction!");
2047. 		exercise(A_WIS, TRUE);
2048. 	}
2049. 	if ((otmp->otyp == FLINT) && !otmp->cursed)
2050. 	{
2051. 		pline("Yabba-dabba delicious!");
2052. 		exercise(A_CON, TRUE);
2053. 	}
2054. 
2055. 	if (otmp == uwep && otmp->quan == 1L) uwepgone();
2056. 	if (otmp == uquiver && otmp->quan == 1L) uqwepgone();
2057. 	if (otmp == uswapwep && otmp->quan == 1L) uswapwepgone();
2058. 
2059. 	if (otmp == uball) unpunish();
2060. 	if (otmp == uchain) unpunish(); /* but no useup() */
2061. 	else if (carried(otmp)) useup(otmp);
2062. 	else useupf(otmp, 1L);
2063. }
2064. 
2065. /* NOTE: the order of these words exactly corresponds to the
2066.    order of oc_material values #define'd in objclass.h. */
2067. static const char *foodwords[] = {
2068. 	"meal", "liquid", "wax", "food", "meat",
2069. 	"paper", "cloth", "leather", "wood", "bone", "scale",
2070. 	"metal", "metal", "metal", "silver", "gold", "platinum", "mithril",
2071. 	"plastic", "glass", "rich food", "stone"
2072. };
2073. 
2074. STATIC_OVL const char *
2075. foodword(otmp)
2076. register struct obj *otmp;
2077. {
2078. 	if (otmp->oclass == FOOD_CLASS) return "food";
2079. 	if (otmp->oclass == GEM_CLASS &&
2080. 	    objects[otmp->otyp].oc_material == GLASS &&
2081. 	    otmp->dknown)
2082. 		makeknown(otmp->otyp);
2083. 	return foodwords[objects[otmp->otyp].oc_material];
2084. }
2085. 
2086. STATIC_OVL void
2087. fpostfx(otmp)		/* called after consuming (non-corpse) food */
2088. register struct obj *otmp;
2089. {
2090. 	switch(otmp->otyp) {
2091. 	    case SPRIG_OF_WOLFSBANE:
2092. 		if (u.ulycn >= LOW_PM || is_were(youmonst.data) || Race_if(PM_HUMAN_WEREWOLF))
2093. 		    you_unwere(TRUE);
2094. 		break;
2095. 	    case HOLY_WAFER:            
2096. 		if (u.ualign.type == A_LAWFUL) {
2097. 			if (u.uhp < u.uhpmax) {
2098. 				You("feel warm inside.");
2099. 				u.uhp += rn1(20,20);
2100. 				if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
2101. 			} 
2102. 		}
2103. 		if (Sick) make_sick(0L, (char *)0, TRUE, SICK_ALL);
2104. 		if (u.ulycn != -1) {
2105. 		    you_unwere(TRUE);
2106. 		}
2107. 		if (u.ualign.type == A_CHAOTIC) {
2108. 		    You("feel a burning inside!");
2109. 		    u.uhp -= rn1(10,10);
2110. 		    /* KMH, balance patch 2 -- should not have 0 hp */
2111. 		    if (u.uhp < 1) u.uhp = 1;
2112. 		}
2113. 		break;
2114. 	    case CARROT:
2115. 		make_blinded((long)u.ucreamed,TRUE);
2116. 		break;
2117. 	    /* body parts -- now checks for artifact and name*/
2118. 	    case EYEBALL:
2119. 		if (!otmp->oartifact) break;
2120. 		You("feel a burning inside!");
2121. 		u.uhp -= rn1(50,150);
2122. 		if (u.uhp <= 0) {
2123. 		  killer_format = KILLED_BY;
2124. 		  killer = food_xname(otmp, TRUE);
2125. 		  done(CHOKING);
2126. 		}
2127. 		break;
2128. 	    case SEVERED_HAND:
2129. 		if (!otmp->oartifact) break;
2130. 		You("feel the hand scrabbling around inside of you!");
2131. 		u.uhp -= rn1(50,150);
2132. 		if (u.uhp <= 0) {
2133. 		  killer_format = KILLED_BY;
2134. 		  killer = food_xname(otmp, TRUE);
2135. 		  done(CHOKING);
2136. 		}
2137. 		break;
2138. 	    case FORTUNE_COOKIE:
2139. 	    	if (yn("Read the fortune?") == 'y') {
2140. 		outrumor(bcsign(otmp), BY_COOKIE);
2141. 		if (!Blind) u.uconduct.literate++;
2142. 		}
2143. 		break;
2144. /* STEHPEN WHITE'S NEW CODE */            
2145. 	    case LUMP_OF_ROYAL_JELLY:
2146. 		/* This stuff seems to be VERY healthy! */
2147. 		gainstr(otmp, 1);
2148. 		if (Upolyd) {
2149. 		    u.mh += otmp->cursed ? -rnd(20) : rnd(20);
2150. 		    if (u.mh > u.mhmax) {
2151. 			if (!rn2(17)) u.mhmax++;
2152. 			u.mh = u.mhmax;
2153. 		    } else if (u.mh <= 0) {
2154. 			rehumanize();
2155. 		    }
2156. 		} else {
2157. 		    u.uhp += otmp->cursed ? -rnd(20) : rnd(20);
2158. 		    if (u.uhp > u.uhpmax) {
2159. 			if(!rn2(17)) u.uhpmax++;
2160. 			u.uhp = u.uhpmax;
2161. 		    } else if(u.uhp <= 0) {
2162. 			killer_format = KILLED_BY_AN;
2163. 			killer = "rotten lump of royal jelly";
2164. 			done(POISONING);
2165. 		    }
2166. 		}
2167. 		if(!otmp->cursed) heal_legs();
2168. 		break;
2169. 	    case EGG:
2170. 		if (touch_petrifies(&mons[otmp->corpsenm])) {
2171. 		    if (!Stone_resistance &&
2172. 			!(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))) {
2173. 			if (!Stoned) Stoned = 5;
2174. 			killer_format = KILLED_BY_AN;
2175. 			Sprintf(killer_buf, "%s egg", mons[otmp->corpsenm].mname);
2176. 			delayed_killer = killer_buf;
2177. 		    }
2178. 		}
2179. 		break;
2180. 	    case EUCALYPTUS_LEAF:
2181. 		if (Sick && !otmp->cursed)
2182. 		    make_sick(0L, (char *)0, TRUE, SICK_ALL);
2183. 		if (Vomiting && !otmp->cursed)
2184. 		    make_vomiting(0L, TRUE);
2185. 		break;
2186. 	}
2187. 
2188. 	return;
2189. }
2190. /*
2191.  * return 0 if the food was not dangerous.
2192.  * return 1 if the food was dangerous and you chose to stop.
2193.  * return 2 if the food was dangerous and you chose to eat it anyway.
2194.  */
2195. STATIC_OVL int
2196. edibility_prompts(otmp)
2197. struct obj *otmp;
2198. {
2199. 	/* blessed food detection granted you a one-use
2200. 	   ability to detect food that is unfit for consumption
2201. 	   or dangerous and avoid it. */
2202. 
2203. 	char buf[BUFSZ], foodsmell[BUFSZ],
2204. 	     it_or_they[QBUFSZ], eat_it_anyway[QBUFSZ];
2205. 	boolean cadaver = (otmp->otyp == CORPSE),
2206. 		stoneorslime = FALSE;
2207. 	int material = objects[otmp->otyp].oc_material,
2208. 	    mnum = otmp->corpsenm;
2209. 	long rotted = 0L;
2210. 
2211. 	Strcpy(foodsmell, Tobjnam(otmp, "smell"));
2212. 	Strcpy(it_or_they, (otmp->quan == 1L) ? "it" : "they");
2213. 	Sprintf(eat_it_anyway, "Eat %s anyway?",
2214. 		(otmp->quan == 1L) ? "it" : "one");
2215. 
2216. 	if (cadaver || otmp->otyp == EGG || otmp->otyp == TIN) {
2217. 		/* These checks must match those in eatcorpse() */
2218. 	  	stoneorslime = (touch_petrifies(&mons[mnum]) &&
2219. 				!Stone_resistance &&
2220. 				!poly_when_stoned(youmonst.data));
2221. 
2222. 		if (mnum == PM_GREEN_SLIME)
2223. 		    stoneorslime = (!Unchanging && !flaming(youmonst.data) &&
2224. 			youmonst.data != &mons[PM_GREEN_SLIME]);
2225. 
2226. 		if (cadaver && mnum != PM_LIZARD && mnum != PM_LICHEN) {
2227. 			long age = peek_at_iced_corpse_age(otmp);
2228. 			/* worst case rather than random
2229. 			   in this calculation to force prompt */
2230. 			rotted = (monstermoves - age)/(10L + 0 /* was rn2(20) */);
2231. 			if (otmp->cursed) rotted += 2L;
2232. 			else if (otmp->blessed) rotted -= 2L;
2233. 		}
2234. 	}
2235. 
2236. 	/*
2237. 	 * These problems with food should be checked in
2238. 	 * order from most detrimental to least detrimental.
2239. 	 */
2240. 
2241. 	if (cadaver && mnum != PM_ACID_BLOB && rotted > 5L && !Sick_resistance) {
2242. 		/* Tainted meat */
2243. 		Sprintf(buf, "%s like %s could be tainted! %s",
2244. 			foodsmell, it_or_they, eat_it_anyway);
2245. 		if (yn_function(buf,ynchars,'n')=='n') return 1;
2246. 		else return 2;
2247. 	}
2248. 	if (stoneorslime) {
2249. 		Sprintf(buf, "%s like %s could be something very dangerous! %s",
2250. 			foodsmell, it_or_they, eat_it_anyway);
2251. 		if (yn_function(buf,ynchars,'n')=='n') return 1;
2252. 		else return 2;
2253. 	}
2254. 	if (otmp->orotten || (cadaver && rotted > 3L)) {
2255. 		/* Rotten */
2256. 		Sprintf(buf, "%s like %s could be rotten! %s",
2257. 			foodsmell, it_or_they, eat_it_anyway);
2258. 		if (yn_function(buf,ynchars,'n')=='n') return 1;
2259. 		else return 2;
2260. 	}
2261. 	if (cadaver && poisonous(&mons[mnum]) && !Poison_resistance) {
2262. 		/* poisonous */
2263. 		Sprintf(buf, "%s like %s might be poisonous! %s",
2264. 			foodsmell, it_or_they, eat_it_anyway);
2265. 		if (yn_function(buf,ynchars,'n')=='n') return 1;
2266. 		else return 2;
2267. 	}
2268. 	if (cadaver && !vegetarian(&mons[mnum]) &&
2269. 	    !u.uconduct.unvegetarian && Role_if(PM_MONK)) {
2270. 		Sprintf(buf, "%s unhealthy. %s",
2271. 			foodsmell, eat_it_anyway);
2272. 		if (yn_function(buf,ynchars,'n')=='n') return 1;
2273. 		else return 2;
2274. 	}
2275. 	if (cadaver && acidic(&mons[mnum]) && !Acid_resistance) {
2276. 		Sprintf(buf, "%s rather acidic. %s",
2277. 			foodsmell, eat_it_anyway);
2278. 		if (yn_function(buf,ynchars,'n')=='n') return 1;
2279. 		else return 2;
2280. 	}
2281. 	if (Upolyd && u.umonnum == PM_RUST_MONSTER &&
2282. 	    is_metallic(otmp) && otmp->oerodeproof) {
2283. 		Sprintf(buf, "%s disgusting to you right now. %s",
2284. 			foodsmell, eat_it_anyway);
2285. 		if (yn_function(buf,ynchars,'n')=='n') return 1;
2286. 		else return 2;
2287. 	}
2288. 
2289. 	/*
2290. 	 * Breaks conduct, but otherwise safe.
2291. 	 */
2292. 	 
2293. 	if (!u.uconduct.unvegan &&
2294. 	    ((material == LEATHER || material == BONE ||
2295. 	      material == EYEBALL || material == SEVERED_HAND ||
2296. 	      material == DRAGON_HIDE || material == WAX) ||
2297. 	     (cadaver && !vegan(&mons[mnum])))) {
2298. 		Sprintf(buf, "%s foul and unfamiliar to you. %s",
2299. 			foodsmell, eat_it_anyway);
2300. 		if (yn_function(buf,ynchars,'n')=='n') return 1;
2301. 		else return 2;
2302. 	}
2303. 	if (!u.uconduct.unvegetarian &&
2304. 	    ((material == LEATHER || material == BONE ||
2305. 	      material == EYEBALL || material == SEVERED_HAND ||
2306. 	      material == DRAGON_HIDE) ||
2307. 	     (cadaver && !vegetarian(&mons[mnum])))) {
2308. 		Sprintf(buf, "%s unfamiliar to you. %s",
2309. 			foodsmell, eat_it_anyway);
2310. 		if (yn_function(buf,ynchars,'n')=='n') return 1;
2311. 		else return 2;
2312. 	}
2313. 
2314. 	if (cadaver && mnum != PM_ACID_BLOB && rotted > 5L && Sick_resistance) {
2315. 		/* Tainted meat with Sick_resistance */
2316. 		Sprintf(buf, "%s like %s could be tainted! %s",
2317. 			foodsmell, it_or_they, eat_it_anyway);
2318. 		if (yn_function(buf,ynchars,'n')=='n') return 1;
2319. 		else return 2;
2320. 	}
2321. 	return 0;
2322. }
2323. 
2324. int
2325. doeat()		/* generic "eat" command funtion (see cmd.c) */
2326. {
2327. 	register struct obj *otmp;
2328. 	int basenutrit;			/* nutrition of full item */
2329. 	int nutrit;			/* nutrition available */
2330. 	char qbuf[QBUFSZ];
2331. 	char c;
2332. 	
2333. 	boolean dont_start = FALSE;
2334. 	if (Strangled) {
2335. 		pline("If you can't breathe air, how can you consume solids?");
2336. 		return 0;
2337. 	}
2338. 	if (!(otmp = floorfood("eat"))) return 0;
2339. 	if (check_capacity((char *)0)) return 0;
2340. 
2341. 	if (u.uedibility) {
2342. 		int res = edibility_prompts(otmp);
2343. 		if (res) {
2344. 		    Your("%s stops tingling and your sense of smell returns to normal.",
2345. 			body_part(NOSE));
2346. 		    u.uedibility = 0;
2347. 		    if (res == 1) return 0;
2348. 		}
2349. 	}
2350. 
2351. 	/* We have to make non-foods take 1 move to eat, unless we want to
2352. 	 * do ridiculous amounts of coding to deal with partly eaten plate
2353. 	 * mails, players who polymorph back to human in the middle of their
2354. 	 * metallic meal, etc....
2355. 	 */
2356. 	if (!is_edible(otmp)) {
2357. 	    You("cannot eat that!");
2358. 	    return 0;
2359. 	} else if ((otmp->owornmask & (W_ARMOR|W_TOOL|W_AMUL
2360. #ifdef STEED
2361. 			|W_SADDLE
2362. #endif
2363. 			)) != 0) {
2364. 	    /* let them eat rings */
2365. 	    You_cant("eat %s you're wearing.", something);
2366. 	    return 0;
2367. 	}
2368. 	if (is_metallic(otmp) &&
2369. 	    u.umonnum == PM_RUST_MONSTER && otmp->oerodeproof) {
2370. 	    	otmp->rknown = TRUE;
2371. 		if (otmp->quan > 1L) {
2372. 		    if(!carried(otmp))
2373. 			(void) splitobj(otmp, otmp->quan - 1L);
2374. 		    else
2375. 			otmp = splitobj(otmp, 1L);
2376. 		}
2377. 		pline("Ulch - That %s was rustproofed!", xname(otmp));
2378. 		/* The regurgitated object's rustproofing is gone now */
2379. 		otmp->oerodeproof = 0;
2380. 		make_stunned(HStun + rn2(10), TRUE);
2381. 		You("spit %s out onto the %s.", the(xname(otmp)),
2382. 			surface(u.ux, u.uy));
2383. 		if (carried(otmp)) {
2384. 			freeinv(otmp);
2385. 			dropy(otmp);
2386. 		}
2387. 		stackobj(otmp);
2388. 		return 1;
2389. 	}
2390. 	if (otmp->otyp == EYEBALL || otmp->otyp == SEVERED_HAND) {
2391. 	    Strcpy(qbuf,"Are you sure you want to eat that?");
2392. 	    if ((c = yn_function(qbuf, ynqchars, 'n')) != 'y') return 0;
2393. 	}
2394. 
2395. 	/* KMH -- Slow digestion is... indigestible */
2396. 	if (otmp->otyp == RIN_SLOW_DIGESTION) {
2397. 		pline("This ring is indigestible!");
2398. 		(void) rottenfood(otmp);
2399. 		if (otmp->dknown && !objects[otmp->otyp].oc_name_known
2400. 				&& !objects[otmp->otyp].oc_uname)
2401. 			docall(otmp);
2402. 		return (1);
2403. 	}
2404. 
2405. 	if (otmp->oclass != FOOD_CLASS) {
2406. 	    int material;
2407. 	    victual.reqtime = 1;
2408. 	    victual.piece = otmp;
2409. 		/* Don't split it, we don't need to if it's 1 move */
2410. 	    victual.usedtime = 0;
2411. 	    victual.canchoke = (u.uhs == SATIATED);
2412. 		/* Note: gold weighs 1 pt. for each 1000 pieces (see */
2413. 		/* pickup.c) so gold and non-gold is consistent. */
2414. 	    if (otmp->oclass == COIN_CLASS)
2415. 		basenutrit = ((otmp->quan > 200000L) ? 2000
2416. 			: (int)(otmp->quan/100L));
2417. 	    else if(otmp->oclass == BALL_CLASS || otmp->oclass == CHAIN_CLASS)
2418. 		basenutrit = weight(otmp);
2419. 	    /* oc_nutrition is usually weight anyway */
2420. 	    else basenutrit = objects[otmp->otyp].oc_nutrition;
2421. 	    victual.nmod = basenutrit;
2422. 	    victual.eating = TRUE; /* needed for lesshungry() */
2423. 
2424. 	    material = objects[otmp->otyp].oc_material;
2425. 	    if (material == LEATHER ||
2426. 		material == EYEBALL || material == SEVERED_HAND ||
2427. 		material == BONE || material == DRAGON_HIDE) {
2428. 	 		u.uconduct.unvegan++;
2429. 	    		violated_vegetarian();
2430. 	    } else if (material == WAX)
2431. 			u.uconduct.unvegan++;
2432. 	    u.uconduct.food++;
2433. 	    
2434. 	    if (otmp->cursed)
2435. 		(void) rottenfood(otmp);
2436. 
2437. 	    if (otmp->oclass == WEAPON_CLASS && otmp->opoisoned) {
2438. 		pline("Ecch - that must have been poisonous!");
2439. 		if(!Poison_resistance) {
2440. 		    losestr(rnd(4));
2441. 		    losehp(rnd(15), xname(otmp), KILLED_BY_AN);
2442. 		} else
2443. 		    You("seem unaffected by the poison.");
2444. 	    } else if (!otmp->cursed)
2445. 		pline("This %s is delicious!",
2446. 		      otmp->oclass == COIN_CLASS ? foodword(otmp) :
2447. 		      singular(otmp, xname));
2448. 
2449. 	    eatspecial();
2450. 	    return 1;
2451. 	}
2452. 
2453. 	/* [ALI] Hero polymorphed in the meantime.
2454. 	 */
2455. 	if (otmp == victual.piece &&
2456. 	  is_vampire(youmonst.data) != otmp->odrained)
2457. 	    victual.piece = (struct obj *)0;	/* Can't resume */
2458. 
2459. 	/* [ALI] Blood can coagulate during the interruption
2460. 	 *       but not during the draining process.
2461. 	 */
2462. 	if(otmp == victual.piece && otmp->odrained &&
2463. 	  (peek_at_iced_corpse_age(otmp) + victual.usedtime + 5) < monstermoves)
2464. 	    victual.piece = (struct obj *)0;	/* Can't resume */
2465. 
2466. 	if(otmp == victual.piece) {
2467. 	/* If they weren't able to choke, they don't suddenly become able to
2468. 	 * choke just because they were interrupted.  On the other hand, if
2469. 	 * they were able to choke before, if they lost food it's possible
2470. 	 * they shouldn't be able to choke now.
2471. 	 */
2472. 	    if (u.uhs != SATIATED) victual.canchoke = FALSE;
2473. 	    victual.piece = touchfood(otmp);
2474. 	    You("resume your meal.");
2475. 	    start_eating(victual.piece);
2476. 	    return(1);
2477. 	}
2478. 
2479. 	/* nothing in progress - so try to find something. */
2480. 	/* tins are a special case */
2481. 	/* tins must also check conduct separately in case they're discarded */
2482. 	if(otmp->otyp == TIN) {
2483. 	    start_tin(otmp);
2484. 	    return(1);
2485. 	}
2486. 
2487. 	/* KMH, conduct */
2488. 	u.uconduct.food++;
2489. 
2490. 	victual.piece = otmp = touchfood(otmp);
2491. 	victual.usedtime = 0;
2492. 
2493. 	/* Now we need to calculate delay and nutritional info.
2494. 	 * The base nutrition calculated here and in eatcorpse() accounts
2495. 	 * for normal vs. rotten food.  The reqtime and nutrit values are
2496. 	 * then adjusted in accordance with the amount of food left.
2497. 	 */
2498. 	if(otmp->otyp == CORPSE) {
2499. 	    int tmp = eatcorpse(otmp);
2500. 	    if (tmp == 3) {
2501. 		/* inedible */
2502. 		victual.piece = (struct obj *)0;
2503. 		/*
2504. 		 * The combination of odrained == TRUE and oeaten == cnutrit
2505. 		 * represents the case of starting to drain a corpse but not
2506. 		 * getting any further (eg., loosing consciousness due to
2507. 		 * rotten food). We must preserve this case to avoid corpses
2508. 		 * changing appearance after a failed attempt to eat.
2509. 		 */
2510. 		if (!otmp->odrained &&
2511. 			otmp->oeaten == mons[otmp->corpsenm].cnutrit)
2512. 		    otmp->oeaten = 0;
2513. 		/* ALI, conduct: didn't eat it after all */
2514. 		u.uconduct.food--;
2515. 		return 0;
2516. 	    } else if (tmp == 2) {
2517. 		/* used up */
2518. 		victual.piece = (struct obj *)0;
2519. 		return(1);
2520. 	    } else if (tmp)
2521. 		dont_start = TRUE;
2522. 	    /* if not used up, eatcorpse sets up reqtime and may modify
2523. 	     * oeaten */
2524. 	} else {
2525. 	    /* No checks for WAX, LEATHER, BONE, DRAGON_HIDE.  These are
2526. 	     * all handled in the != FOOD_CLASS case, above */
2527. 	    switch (objects[otmp->otyp].oc_material) {
2528. 	    case FLESH:
2529. 		u.uconduct.unvegan++;
2530. 		if (otmp->otyp != EGG && otmp->otyp != CHEESE) {
2531. 		    violated_vegetarian();
2532. 		}
2533. 		break;
2534. 
2535. 	    default:
2536. 		if (otmp->otyp == PANCAKE ||
2537. 		    otmp->otyp == FORTUNE_COOKIE || /* eggs */
2538. 		    otmp->otyp == CREAM_PIE ||
2539. 		    otmp->otyp == CANDY_BAR || /* milk */
2540. 		    otmp->otyp == LUMP_OF_ROYAL_JELLY)
2541. 		    u.uconduct.unvegan++;
2542. 		break;
2543. 	    }
2544. 
2545. 	    victual.reqtime = objects[otmp->otyp].oc_delay;
2546. 	    if (otmp->otyp != FORTUNE_COOKIE &&
2547. 		(otmp->cursed ||
2548. 		 (((monstermoves - otmp->age) > (int) otmp->blessed ? 50:30) &&
2549. 		(otmp->orotten || !rn2(7))))) {
2550. 
2551. 		if (rottenfood(otmp)) {
2552. 		    otmp->orotten = TRUE;
2553. 		    dont_start = TRUE;
2554. 		}
2555. 		if (otmp->oeaten < 2) {
2556. 		    victual.piece = (struct obj *)0;
2557. 		    if (carried(otmp)) useup(otmp);
2558. 		    else useupf(otmp, 1L);
2559. 		    return 1;
2560. 		} else
2561. 		consume_oeaten(otmp, 1);	/* oeaten >>= 1 */
2562. 	    } else fprefx(otmp);
2563. 	}
2564. 
2565. 	/* re-calc the nutrition */
2566. 	if (otmp->otyp == CORPSE) basenutrit = mons[otmp->corpsenm].cnutrit;
2567. 	else basenutrit = objects[otmp->otyp].oc_nutrition;
2568. 	nutrit = otmp->oeaten;
2569. 	if (otmp->otyp == CORPSE && otmp->odrained) {
2570. 	    nutrit -= drainlevel(otmp);
2571. 	    basenutrit -= drainlevel(otmp);
2572. 	}
2573. 
2574. #ifdef DEBUG
2575. 	debugpline("before rounddiv: victual.reqtime == %d", victual.reqtime);
2576. 	debugpline("oeaten == %d, basenutrit == %d", otmp->oeaten, basenutrit);
2577. 	debugpline("nutrit == %d, cnutrit == %d", nutrit, otmp->otyp == CORPSE ?
2578. 	  mons[otmp->corpsenm].cnutrit : objects[otmp->otyp].oc_nutrition);
2579. #endif
2580. 	victual.reqtime = (basenutrit == 0 ? 0 :
2581. 		rounddiv(victual.reqtime * (long)nutrit, basenutrit));
2582. #ifdef DEBUG
2583. 	debugpline("after rounddiv: victual.reqtime == %d", victual.reqtime);
2584. #endif
2585. 	/* calculate the modulo value (nutrit. units per round eating)
2586. 	 * [ALI] Note: although this is not exact, the remainder is
2587. 	 *       now dealt with in done_eating().
2588. 	 */
2589. 	if (victual.reqtime == 0 || nutrit == 0)
2590. 	    /* possible if most has been eaten before */
2591. 	    victual.nmod = 0;
2592. 	else if (nutrit >= victual.reqtime)
2593. 	    victual.nmod = -(nutrit / victual.reqtime);
2594. 	else
2595. 	    victual.nmod = victual.reqtime % nutrit;
2596. 	victual.canchoke = (u.uhs == SATIATED);
2597. 
2598. 	if (!dont_start) start_eating(otmp);
2599. 	return(1);
2600. }
2601. 
2602. /* Take a single bite from a piece of food, checking for choking and
2603.  * modifying usedtime.  Returns 1 if they choked and survived, 0 otherwise.
2604.  */
2605. STATIC_OVL int
2606. bite()
2607. {
2608. 	if(victual.canchoke && u.uhunger >= 2000) {
2609. 		choke(victual.piece);
2610. 		return 1;
2611. 	}
2612. 	if (victual.doreset) {
2613. 		do_reset_eat();
2614. 		return 0;
2615. 	}
2616. 	force_save_hs = TRUE;
2617. 	if(victual.nmod < 0) {
2618. 		lesshungry(-victual.nmod);
2619. 		consume_oeaten(victual.piece, victual.nmod); /* -= -nmod */
2620. 	} else if(victual.nmod > 0 && (victual.usedtime % victual.nmod)) {
2621. 		lesshungry(1);
2622. 		consume_oeaten(victual.piece, -1);		  /* -= 1 */
2623. 	}
2624. 	force_save_hs = FALSE;
2625. 	recalc_wt();
2626. 	return 0;
2627. }
2628. 
2629. #endif /* OVLB */
2630. #ifdef OVL0
2631. 
2632. void
2633. gethungry()	/* as time goes by - called by moveloop() and domove() */
2634. {
2635. 	if (u.uinvulnerable) return;	/* you don't feel hungrier */
2636. 
2637. 	if ((!u.usleep || !rn2(10))	/* slow metabolic rate while asleep */
2638. 		&& (carnivorous(youmonst.data) || herbivorous(youmonst.data))
2639. 		&& !Slow_digestion)
2640. 	    u.uhunger--;		/* ordinary food consumption */
2641. 
2642. 	if (moves % 2) {	/* odd turns */
2643. 	    /* Regeneration uses up food, unless due to an artifact */
2644. 	    if (HRegeneration || ((ERegeneration & (~W_ART)) &&
2645. 				(ERegeneration != W_WEP || !uwep->oartifact)))
2646. 			u.uhunger--;
2647. 	    if (near_capacity() > SLT_ENCUMBER) u.uhunger--;
2648. 	} else {		/* even turns */
2649. 	    if (Hunger) u.uhunger--;
2650. 	    /* Conflict uses up food too */
2651. 	    if (HConflict || (EConflict & (~W_ARTI))) u.uhunger--;
2652. 	    /* +0 charged rings don't do anything, so don't affect hunger */
2653. 	    /* Slow digestion still uses ring hunger */
2654. 	    switch ((int)(moves % 20)) {	/* note: use even cases only */
2655. 	     case  4: if (uleft &&
2656. 			  (uleft->spe || !objects[uleft->otyp].oc_charged))
2657. 			    u.uhunger--;
2658. 		    break;
2659. 	     case  8: if (uamul) u.uhunger--;
2660. 		    break;
2661. 	     case 12: if (uright &&
2662. 			  (uright->spe || !objects[uright->otyp].oc_charged))
2663. 			    u.uhunger--;
2664. 		    break;
2665. 	     case 16: if (u.uhave.amulet) u.uhunger--;
2666. 		    break;
2667. 	     default: break;
2668. 	    }
2669. 	}
2670. 	newuhs(TRUE);
2671. }
2672. 
2673. #endif /* OVL0 */
2674. #ifdef OVLB
2675. 
2676. void
2677. morehungry(num)	/* called after vomiting and after performing feats of magic */
2678. register int num;
2679. {
2680. 	u.uhunger -= num;
2681. 	newuhs(TRUE);
2682. }
2683. 
2684. 
2685. void
2686. lesshungry(num)	/* called after eating (and after drinking fruit juice) */
2687. register int num;
2688. {
2689. 	/* See comments in newuhs() for discussion on force_save_hs */
2690. 	boolean iseating = occupation == eatfood || force_save_hs;
2691. #ifdef DEBUG
2692. 	debugpline("lesshungry(%d)", num);
2693. #endif
2694. 	u.uhunger += num;
2695. 	if(u.uhunger >= 2000) {
2696. 	    if (!iseating || victual.canchoke) {
2697. 		if (iseating) {
2698. 		    choke(victual.piece);
2699. 		    reset_eat();
2700. 		} else
2701. 		    choke(occupation == opentin ? tin.tin : (struct obj *)0);
2702. 		/* no reset_eat() */
2703. 	    }
2704. 	} else {
2705. 	    /* Have lesshungry() report when you're nearly full so all eating
2706. 	     * warns when you're about to choke.
2707. 	     */
2708. 	    if (u.uhunger >= 1500) {
2709. 		if (!victual.eating || (victual.eating && !victual.fullwarn)) {
2710. 		    pline("You're having a hard time getting all of it down.");
2711. 		    nomovemsg = "You're finally finished.";
2712. 		    if (!victual.eating)
2713. 			multi = -2;
2714. 		    else {
2715. 			victual.fullwarn = TRUE;
2716. 			if (victual.canchoke && victual.reqtime > 1) {
2717. 			    /* a one-gulp food will not survive a stop */
2718. 			    if (yn_function("Stop eating?",ynchars,'y')=='y') {
2719. 				reset_eat();
2720. 				nomovemsg = (char *)0;
2721. 			    }
2722. 			}
2723. 		    }
2724. 		}
2725. 	    }
2726. 	}
2727. 	newuhs(FALSE);
2728. }
2729. 
2730. STATIC_PTR
2731. int
2732. unfaint()
2733. {
2734. 	(void) Hear_again();
2735. 	if(u.uhs > FAINTING)
2736. 		u.uhs = FAINTING;
2737. 	stop_occupation();
2738. 	flags.botl = 1;
2739. 	return 0;
2740. }
2741. 
2742. #endif /* OVLB */
2743. #ifdef OVL0
2744. 
2745. boolean
2746. is_fainted()
2747. {
2748. 	return((boolean)(u.uhs == FAINTED));
2749. }
2750. 
2751. void
2752. reset_faint()	/* call when a faint must be prematurely terminated */
2753. {
2754. 	if(is_fainted()) nomul(0);
2755. }
2756. 
2757. #if 0
2758. void
2759. sync_hunger()
2760. {
2761. 	if(is_fainted()) {
2762. 		flags.soundok = 0;
2763. 		nomul(-10+(u.uhunger/10));
2764. 		nomovemsg = "You regain consciousness.";
2765. 		afternmv = unfaint;
2766. 	}
2767. }
2768. #endif
2769. 
2770. void
2771. newuhs(incr)		/* compute and comment on your (new?) hunger status */
2772. boolean incr;
2773. {
2774. 	unsigned newhs;
2775. 	static unsigned save_hs;
2776. 	static boolean saved_hs = FALSE;
2777. 	int h = u.uhunger;
2778. 
2779. 	newhs = (h > 1000) ? SATIATED :
2780. 		(h > 150) ? NOT_HUNGRY :
2781. 		(h > 50) ? HUNGRY :
2782. 		(h > 0) ? WEAK : FAINTING;
2783. 
2784. 	/* While you're eating, you may pass from WEAK to HUNGRY to NOT_HUNGRY.
2785. 	 * This should not produce the message "you only feel hungry now";
2786. 	 * that message should only appear if HUNGRY is an endpoint.  Therefore
2787. 	 * we check to see if we're in the middle of eating.  If so, we save
2788. 	 * the first hunger status, and at the end of eating we decide what
2789. 	 * message to print based on the _entire_ meal, not on each little bit.
2790. 	 */
2791. 	/* It is normally possible to check if you are in the middle of a meal
2792. 	 * by checking occupation == eatfood, but there is one special case:
2793. 	 * start_eating() can call bite() for your first bite before it
2794. 	 * sets the occupation.
2795. 	 * Anyone who wants to get that case to work _without_ an ugly static
2796. 	 * force_save_hs variable, feel free.
2797. 	 */
2798. 	/* Note: If you become a certain hunger status in the middle of the
2799. 	 * meal, and still have that same status at the end of the meal,
2800. 	 * this will incorrectly print the associated message at the end of
2801. 	 * the meal instead of the middle.  Such a case is currently
2802. 	 * impossible, but could become possible if a message for SATIATED
2803. 	 * were added or if HUNGRY and WEAK were separated by a big enough
2804. 	 * gap to fit two bites.
2805. 	 */
2806. 	if (occupation == eatfood || force_save_hs) {
2807. 		if (!saved_hs) {
2808. 			save_hs = u.uhs;
2809. 			saved_hs = TRUE;
2810. 		}
2811. 		u.uhs = newhs;
2812. 		return;
2813. 	} else {
2814. 		if (saved_hs) {
2815. 			u.uhs = save_hs;
2816. 			saved_hs = FALSE;
2817. 		}
2818. 	}
2819. 
2820. 	if(newhs == FAINTING) {
2821. 		if(is_fainted()) newhs = FAINTED;
2822. 		if(u.uhs <= WEAK || rn2(20-u.uhunger/10) >= 19) {
2823. 			if(!is_fainted() && multi >= 0 /* %% */) {
2824. 				/* stop what you're doing, then faint */
2825. 				stop_occupation();
2826. 				You("faint from lack of food.");
2827. 				flags.soundok = 0;
2828. 				nomul(-10+(u.uhunger/10));
2829. 				nomovemsg = "You regain consciousness.";
2830. 				afternmv = unfaint;
2831. 				newhs = FAINTED;
2832. 			}
2833. 		} else
2834. 		if(u.uhunger < -(int)(200 + 20*ACURR(A_CON))) {
2835. 			u.uhs = STARVED;
2836. 			flags.botl = 1;
2837. 			bot();
2838. 			You("die from starvation.");
2839. 			killer_format = KILLED_BY;
2840. 			killer = "starvation";
2841. 			done(STARVING);
2842. 			/* if we return, we lifesaved, and that calls newuhs */
2843. 			return;
2844. 		}
2845. 	}
2846. 
2847. 	if(newhs != u.uhs) {
2848. 		if(newhs >= WEAK && u.uhs < WEAK)
2849. 			losestr(1);	/* this may kill you -- see below */
2850. 		else if(newhs < WEAK && u.uhs >= WEAK)
2851. 			losestr(-1);
2852. 		switch(newhs){
2853. 		case HUNGRY:
2854. 			if (Hallucination) {
2855. 			    You((!incr) ?
2856. 				"now have a lesser case of the munchies." :
2857. 				"are getting the munchies.");
2858. 			} else
2859. 			    You((!incr) ? "only feel hungry now." :
2860. 				  (u.uhunger < 145) ? "feel hungry." :
2861. 				   "are beginning to feel hungry.");
2862. 			if (incr && occupation &&
2863. 			    (occupation != eatfood && occupation != opentin))
2864. 			    stop_occupation();
2865. 			break;
2866. 		case WEAK:
2867. 			if (Hallucination)
2868. 			    pline((!incr) ?
2869. 				  "You still have the munchies." :
2870.       "The munchies are interfering with your motor capabilities.");
2871. 			else if (incr &&
2872. 				(Role_if(PM_WIZARD) || Race_if(PM_ELF) ||
2873. 				 Role_if(PM_VALKYRIE)))
2874. 			    pline("%s needs food, badly!",
2875. 				  (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ?
2876. 				  urole.name.m : "Elf");
2877. 			else
2878. 			    You((!incr) ? "feel weak now." :
2879. 				  (u.uhunger < 45) ? "feel weak." :
2880. 				   "are beginning to feel weak.");
2881. 			if (incr && occupation &&
2882. 			    (occupation != eatfood && occupation != opentin))
2883. 			    stop_occupation();
2884. 			break;
2885. 		}
2886. 		u.uhs = newhs;
2887. 		flags.botl = 1;
2888. 		bot();
2889. 		if ((Upolyd ? u.mh : u.uhp) < 1) {
2890. 			You("die from hunger and exhaustion.");
2891. 			killer_format = KILLED_BY;
2892. 			killer = "exhaustion";
2893. 			done(STARVING);
2894. 			return;
2895. 		}
2896. 	}
2897. }
2898. 
2899. #endif /* OVL0 */
2900. #ifdef OVLB
2901. 
2902. boolean can_reach_floorobj()
2903. {
2904.     return can_reach_floor() &&
2905. 	  !((is_pool(u.ux, u.uy) || is_lava(u.ux, u.uy)) &&
2906. 	    (Wwalking || is_clinger(youmonst.data) || (Flying && !Breathless)));
2907. }
2908. 
2909. /* Returns an object representing food.  Object may be either on floor or
2910.  * in inventory.
2911.  */
2912. STATIC_OVL struct obj *
2913. floorfood(verb)		/* get food from floor or pack */
2914. 	const char *verb;
2915. {
2916. 	register struct obj *otmp;
2917. 	/* We cannot use ALL_CLASSES since that causes getobj() to skip its
2918. 	 * "ugly checks" and we need to check for inedible items.
2919. 	 */
2920. 	const char *edibles = (const char *)allobj;
2921. 	char qbuf[QBUFSZ];
2922. 	char c;
2923. 
2924. #ifdef STEED
2925. 	if (u.usteed)	/* can't eat off floor while riding */
2926. 	    edibles++;
2927. 	else
2928. #endif
2929. 	if (metallivorous(youmonst.data)) {
2930. 	    struct trap *ttmp = t_at(u.ux, u.uy);
2931. 
2932. 	    if (ttmp && ttmp->tseen && ttmp->ttyp == BEAR_TRAP) {
2933. 		/* If not already stuck in the trap, perhaps there should
2934. 		   be a chance to becoming trapped?  Probably not, because
2935. 		   then the trap would just get eaten on the _next_ turn... */
2936. 		Sprintf(qbuf, "There is a bear trap here (%s); eat it?",
2937. 			(u.utrap && u.utraptype == TT_BEARTRAP) ?
2938. 				"holding you" : "armed");
2939. 		if ((c = yn_function(qbuf, ynqchars, 'n')) == 'y') {
2940. 		    u.utrap = u.utraptype = 0;
2941. 		    deltrap(ttmp);
2942. 		    return mksobj(BEARTRAP, TRUE, FALSE);
2943. 		} else if (c == 'q') {
2944. 		    return (struct obj *)0;
2945. 		}
2946. 	    }
2947. 	}
2948. 
2949. 	otmp = getobj(edibles, verb);
2950. 	if (otmp && otmp->oclass == COIN_CLASS)
2951. 	    obj_extract_self(otmp);
2952. 	return otmp;
2953. }
2954. 
2955. /* Side effects of vomiting */
2956. /* added nomul (MRS) - it makes sense, you're too busy being sick! */
2957. void
2958. vomit()		/* A good idea from David Neves */
2959. {
2960. 	make_sick(0L, (char *) 0, TRUE, SICK_VOMITABLE);
2961. 	nomul(-2);
2962. 	nomovemsg = 0;
2963. }
2964. 
2965. int
2966. eaten_stat(base, obj)
2967. register int base;
2968. register struct obj *obj;
2969. {
2970. 	long uneaten_amt, full_amount;
2971. 
2972. 	uneaten_amt = (long)obj->oeaten;
2973. 	full_amount = (obj->otyp == CORPSE) ? (long)mons[obj->corpsenm].cnutrit
2974. 					: (long)objects[obj->otyp].oc_nutrition;
2975. 	if (uneaten_amt > full_amount) {
2976. 	    impossible(
2977. 	  "partly eaten food (%ld) more nutritious than untouched food (%ld)",
2978. 		       uneaten_amt, full_amount);
2979. 	    uneaten_amt = full_amount;
2980. 	}
2981. 
2982. 	base = (int)(full_amount ? (long)base * uneaten_amt / full_amount : 0L);
2983. 	return (base < 1) ? 1 : base;
2984. }
2985. 
2986. /* reduce obj's oeaten field, making sure it never hits or passes 0 */
2987. void
2988. consume_oeaten(obj, amt)
2989. struct obj *obj;
2990. int amt;
2991. {
2992.     /*
2993.      * This is a hack to try to squelch several long standing mystery
2994.      * food bugs.  A better solution would be to rewrite the entire
2995.      * victual handling mechanism from scratch using a less complex
2996.      * model.  Alternatively, this routine could call done_eating()
2997.      * or food_disappears() but its callers would need revisions to
2998.      * cope with victual.piece unexpectedly going away.
2999.      *
3000.      * Multi-turn eating operates by setting the food's oeaten field
3001.      * to its full nutritional value and then running a counter which
3002.      * independently keeps track of whether there is any food left.
3003.      * The oeaten field can reach exactly zero on the last turn, and
3004.      * the object isn't removed from inventory until the next turn
3005.      * when the "you finish eating" message gets delivered, so the
3006.      * food would be restored to the status of untouched during that
3007.      * interval.  This resulted in unexpected encumbrance messages
3008.      * at the end of a meal (if near enough to a threshold) and would
3009.      * yield full food if there was an interruption on the critical
3010.      * turn.  Also, there have been reports over the years of food
3011.      * becoming massively heavy or producing unlimited satiation;
3012.      * this would occur if reducing oeaten via subtraction attempted
3013.      * to drop it below 0 since its unsigned type would produce a
3014.      * huge positive value instead.  So far, no one has figured out
3015.      * _why_ that inappropriate subtraction might sometimes happen.
3016.      */
3017. 
3018.     if (amt > 0) {
3019. 	/* bit shift to divide the remaining amount of food */
3020. 	obj->oeaten >>= amt;
3021.     } else {
3022. 	/* simple decrement; value is negative so we actually add it */
3023. 	if ((int) obj->oeaten > -amt)
3024. 	    obj->oeaten += amt;
3025. 	else
3026. 	    obj->oeaten = 0;
3027.     }
3028. 
3029.     if (obj->oeaten == 0) {
3030. 	if (obj == victual.piece)	/* always true unless wishing... */
3031. 	    victual.reqtime = victual.usedtime;	/* no bites left */
3032. 	obj->oeaten = 1;	/* smallest possible positive value */
3033.     }
3034. }
3035. 
3036. #endif /* OVLB */
3037. #ifdef OVL1
3038. 
3039. /* called when eatfood occupation has been interrupted,
3040.    or in the case of theft, is about to be interrupted */
3041. boolean
3042. maybe_finished_meal(stopping)
3043. boolean stopping;
3044. {
3045. 	/* in case consume_oeaten() has decided that the food is all gone */
3046. 	if (occupation == eatfood && victual.usedtime >= victual.reqtime) {
3047. 	    if (stopping) occupation = 0;	/* for do_reset_eat */
3048. 	    (void) eatfood(); /* calls done_eating() to use up victual.piece */
3049. 	    return TRUE;
3050. 	}
3051. 	return FALSE;
3052. }
3053. 
3054. #endif /* OVL1 */
3055. 
3056. /*eat.c*/
3057.