Wikia

Wikihack

Source:SLASH'EM 0.0.7E7F2/eat.c

2,032pages on
this wiki
Talk0

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.
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. 

Around Wikia's network

Random Wiki