Wikihack
Advertisement

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

Top of file[]

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.    
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
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.   
47.   char msgbuf[BUFSZ];
48.   
49.   #endif /* OVLB */
50.   
51.   /* hunger texts used on bottom line (each 8 chars long) */
52.   #define SATIATED	0
53.   #define NOT_HUNGRY	1
54.   #define HUNGRY		2
55.   #define WEAK		3
56.   #define FAINTING	4
57.   #define FAINTED		5
58.   #define STARVED		6
59.   
60.   /* also used to see if you're allowed to eat cats and dogs */
61.   #define CANNIBAL_ALLOWED() (Role_if(PM_CAVEMAN) || Race_if(PM_ORC))
62.   
63.   #ifndef OVLB
64.   
65.   STATIC_DCL NEARDATA const char comestibles[];
66.   STATIC_DCL NEARDATA const char allobj[];
67.   STATIC_DCL boolean force_save_hs;
68.   
69.   #else
70.   
71.   STATIC_OVL NEARDATA const char comestibles[] = { FOOD_CLASS, 0 };
72.   
73.   /* Gold must come first for getobj(). */
74.   STATIC_OVL NEARDATA const char allobj[] = {
75.   	COIN_CLASS, WEAPON_CLASS, ARMOR_CLASS, POTION_CLASS, SCROLL_CLASS,
76.   	WAND_CLASS, RING_CLASS, AMULET_CLASS, FOOD_CLASS, TOOL_CLASS,
77.   	GEM_CLASS, ROCK_CLASS, BALL_CLASS, CHAIN_CLASS, SPBOOK_CLASS, 0 };
78.   
79.   STATIC_OVL boolean force_save_hs = FALSE;
80.   
81.   const char *hu_stat[] = {
82.   	"Satiated",
83.   	"        ",
84.   	"Hungry  ",
85.   	"Weak    ",
86.   	"Fainting",
87.   	"Fainted ",
88.   	"Starved "
89.   };
90.   
91.   #endif /* OVLB */

is_edible[]

92.   #ifdef OVL1
93.   
94.   /*
95.    * Decide whether a particular object can be eaten by the possibly
96.    * polymorphed character.  Not used for monster checks.
97.    */
98.   boolean
99.   is_edible(obj)
100.  register struct obj *obj;
101.  {
102.  	/* protect invocation tools but not Rider corpses (handled elsewhere)*/
103.       /* if (obj->oclass != FOOD_CLASS && obj_resists(obj, 0, 0)) */
104.  	if (objects[obj->otyp].oc_unique)
105.  		return FALSE;
106.  	/* above also prevents the Amulet from being eaten, so we must never
107.  	   allow fake amulets to be eaten either [which is already the case] */
108.  
109.  	if (metallivorous(youmonst.data) && is_metallic(obj) &&
110.  	    (youmonst.data != &mons[PM_RUST_MONSTER] || is_rustprone(obj)))
111.  		return TRUE;
112.  	if (u.umonnum == PM_GELATINOUS_CUBE && is_organic(obj) &&
113.  		/* [g.cubes can eat containers and retain all contents
114.  		    as engulfed items, but poly'd player can't do that] */
115.  	    !Has_contents(obj))
116.  		return TRUE;
117.  
118.       /* return((boolean)(!!index(comestibles, obj->oclass))); */
119.  	return (boolean)(obj->oclass == FOOD_CLASS);
120.  }
121.  
122.  #endif /* OVL1 */

init_uhunger[]

123.  #ifdef OVLB
124.  
125.  void
126.  init_uhunger()
127.  {
128.  	u.uhunger = 900;
129.  	u.uhs = NOT_HUNGRY;
130.  }
131.  

More definitions[]

132.  static const struct { const char *txt; int nut; } tintxts[] = {
133.  	{"deep fried",	 60},
134.  	{"pickled",	 40},
135.  	{"soup made from", 20},
136.  	{"pureed",	500},
137.  #define ROTTEN_TIN 4
138.  	{"rotten",	-50},
139.  #define HOMEMADE_TIN 5
140.  	{"homemade",	 50},
141.  	{"stir fried",   80},
142.  	{"candied",      100},
143.  	{"boiled",       50},
144.  	{"dried",        55},
145.  	{"szechuan",     70},
146.  #define FRENCH_FRIED_TIN 11
147.  	{"french fried", 40},
148.  	{"sauteed",      95},
149.  	{"broiled",      80},
150.  	{"smoked",       50},
151.  	{"", 0}
152.  };
153.  #define TTSZ	SIZE(tintxts)
154.  
155.  static NEARDATA struct {
156.  	struct	obj *tin;
157.  	int	usedtime, reqtime;
158.  } tin;
159.  
160.  static NEARDATA struct {
161.  	struct	obj *piece;	/* the thing being eaten, or last thing that
162.  				 * was partially eaten, unless that thing was
163.  				 * a tin, which uses the tin structure above,
164.  				 * in which case this should be 0 */
165.  	/* doeat() initializes these when piece is valid */
166.  	int	usedtime,	/* turns spent eating */
167.  		reqtime;	/* turns required to eat */
168.  	int	nmod;		/* coded nutrition per turn */
169.  	Bitfield(canchoke,1);	/* was satiated at beginning */
170.  
171.  	/* start_eating() initializes these */
172.  	Bitfield(fullwarn,1);	/* have warned about being full */
173.  	Bitfield(eating,1);	/* victual currently being eaten */
174.  	Bitfield(doreset,1);	/* stop eating at end of turn */
175.  } victual;
176.  
177.  static char *eatmbuf = 0;	/* set by cpostfx() */
178.  

eatmdone[]

179.  STATIC_PTR
180.  int
181.  eatmdone()		/* called after mimicing is over */
182.  {
183.  	/* release `eatmbuf' */
184.  	if (eatmbuf) {
185.  	    if (nomovemsg == eatmbuf) nomovemsg = 0;
186.  	    free((genericptr_t)eatmbuf),  eatmbuf = 0;
187.  	}
188.  	/* update display */
189.  	if (youmonst.m_ap_type) {
190.  	    youmonst.m_ap_type = M_AP_NOTHING;
191.  	    newsym(u.ux,u.uy);
192.  	}
193.  	return 0;
194.  }
195.  

food_xname[]

196.  /* ``[the(] singular(food, xname) [)] with awareness of unique monsters */
197.  STATIC_OVL const char *
198.  food_xname(food, the_pfx)
199.  struct obj *food;
200.  boolean the_pfx;
201.  {
202.  	const char *result;
203.  	int mnum = food->corpsenm;
204.  
205.  	if (food->otyp == CORPSE && (mons[mnum].geno & G_UNIQ)) {
206.  	    /* grab xname()'s modifiable return buffer for our own use */
207.  	    char *bufp = xname(food);
208.  	    Sprintf(bufp, "%s%s corpse",
209.  		    (the_pfx && !type_is_pname(&mons[mnum])) ? "the " : "",
210.  		    s_suffix(mons[mnum].mname));
211.  	    result = bufp;
212.  	} else {
213.  	    /* the ordinary case */
214.  	    result = singular(food, xname);
215.  	    if (the_pfx) result = the(result);
216.  	}
217.  	return result;
218.  }
219.  

choke[]

220.  /* Created by GAN 01/28/87
221.   * Amended by AKP 09/22/87: if not hard, don't choke, just vomit.
222.   * Amended by 3.  06/12/89: if not hard, sometimes choke anyway, to keep risk.
223.   *		  11/10/89: if hard, rarely vomit anyway, for slim chance.
224.   */
225.  STATIC_OVL void
226.  choke(food)	/* To a full belly all food is bad. (It.) */
227.  	register struct obj *food;
228.  {
229.  	/* only happens if you were satiated */
230.  	if (u.uhs != SATIATED) {
231.  		if (!food || food->otyp != AMULET_OF_STRANGULATION)
232.  			return;
233.  	} else if (Role_if(PM_KNIGHT) && u.ualign.type == A_LAWFUL) {
234.  			adjalign(-1);		/* gluttony is unchivalrous */
235.  			You_feel("like a glutton!");
236.  	}
237.  
238.  	exercise(A_CON, FALSE);
239.  
240.  	if (Breathless || (!Strangled && !rn2(20))) {
241.  		/* choking by eating AoS doesn't involve stuffing yourself */
242.  		if (food && food->otyp == AMULET_OF_STRANGULATION) {
243.  			You("choke, but recover your composure.");
244.  			return;
245.  		}
246.  		You("stuff yourself and then vomit voluminously.");
247.  		morehungry(1000);	/* you just got *very* sick! */
248.  		nomovemsg = 0;
249.  		vomit();
250.  	} else {
251.  		killer_format = KILLED_BY_AN;
252.  		/*
253.  		 * Note all "killer"s below read "Choked on %s" on the
254.  		 * high score list & tombstone.  So plan accordingly.
255.  		 */
256.  		if(food) {
257.  			You("choke over your %s.", foodword(food));
258.  			if (food->oclass == COIN_CLASS) {
259.  				killer = "a very rich meal";
260.  			} else {
261.  				killer = food_xname(food, FALSE);
262.  				if (food->otyp == CORPSE &&
263.  				    (mons[food->corpsenm].geno & G_UNIQ)) {
264.  				    if (!type_is_pname(&mons[food->corpsenm]))
265.  					killer = the(killer);
266.  				    killer_format = KILLED_BY;
267.  				}
268.  			}
269.  		} else {
270.  			You("choke over it.");
271.  			killer = "quick snack";
272.  		}
273.  		You("die...");
274.  		done(CHOKING);
275.  	}
276.  }
277.  

recalc_wt[]

278.  /* modify object wt. depending on time spent consuming it */
279.  STATIC_OVL void
280.  recalc_wt()
281.  {
282.  	struct obj *piece = victual.piece;
283.  
284.  #ifdef DEBUG
285.  	debugpline("Old weight = %d", piece->owt);
286.  	debugpline("Used time = %d, Req'd time = %d",
287.  		victual.usedtime, victual.reqtime);
288.  #endif
289.  	piece->owt = weight(piece);
290.  #ifdef DEBUG
291.  	debugpline("New weight = %d", piece->owt);
292.  #endif
293.  }
294.  

reset_eat[]

295.  void
296.  reset_eat()		/* called when eating interrupted by an event */
297.  {
298.      /* we only set a flag here - the actual reset process is done after
299.       * the round is spent eating.
300.       */
301.  	if(victual.eating && !victual.doreset) {
302.  #ifdef DEBUG
303.  	    debugpline("reset_eat...");
304.  #endif
305.  	    victual.doreset = TRUE;
306.  	}
307.  	return;
308.  }
309.  

touchfood[]

310.  STATIC_OVL struct obj *
311.  touchfood(otmp)
312.  register struct obj *otmp;
313.  {
314.  	if (otmp->quan > 1L) {
315.  	    if(!carried(otmp))
316.  		(void) splitobj(otmp, otmp->quan - 1L);
317.  	    else
318.  		otmp = splitobj(otmp, 1L);
319.  #ifdef DEBUG
320.  	    debugpline("split object,");
321.  #endif
322.  	}
323.  
324.  	if (!otmp->oeaten) {
325.  	    if(((!carried(otmp) && costly_spot(otmp->ox, otmp->oy) &&
326.  		 !otmp->no_charge)
327.  		 || otmp->unpaid)) {
328.  		/* create a dummy duplicate to put on bill */
329.  		verbalize("You bit it, you bought it!");
330.  		bill_dummy_object(otmp);
331.  	    }
332.  	    otmp->oeaten = (otmp->otyp == CORPSE ?
333.  				mons[otmp->corpsenm].cnutrit :
334.  				objects[otmp->otyp].oc_nutrition);
335.  	}
336.  
337.  	if (carried(otmp)) {
338.  	    freeinv(otmp);
339.  	    if (inv_cnt() >= 52) {
340.  		sellobj_state(SELL_DONTSELL);
341.  		dropy(otmp);
342.  		sellobj_state(SELL_NORMAL);
343.  	    } else {
344.  		otmp->oxlth++;		/* hack to prevent merge */
345.  		otmp = addinv(otmp);
346.  		otmp->oxlth--;
347.  	    }
348.  	}
349.  	return(otmp);
350.  }
351.  

food_disappears[]

352.  /* When food decays, in the middle of your meal, we don't want to dereference
353.   * any dangling pointers, so set it to null (which should still trigger
354.   * do_reset_eat() at the beginning of eatfood()) and check for null pointers
355.   * in do_reset_eat().
356.   */
357.  void
358.  food_disappears(obj)
359.  register struct obj *obj;
360.  {
361.  	if (obj == victual.piece) victual.piece = (struct obj *)0;
362.  	if (obj->timed) obj_stop_timers(obj);
363.  }
364.  

food_substitution[]

365.  /* renaming an object usually results in it having a different address;
366.     so the sequence start eating/opening, get interrupted, name the food,
367.     resume eating/opening would restart from scratch */
368.  void
369.  food_substitution(old_obj, new_obj)
370.  struct obj *old_obj, *new_obj;
371.  {
372.  	if (old_obj == victual.piece) victual.piece = new_obj;
373.  	if (old_obj == tin.tin) tin.tin = new_obj;
374.  }
375.  

do_reset_eat[]

376.  STATIC_OVL void
377.  do_reset_eat()
378.  {
379.  #ifdef DEBUG
380.  	debugpline("do_reset_eat...");
381.  #endif
382.  	if (victual.piece) {
383.  		victual.piece = touchfood(victual.piece);
384.  		recalc_wt();
385.  	}
386.  	victual.fullwarn = victual.eating = victual.doreset = FALSE;
387.  	/* Do not set canchoke to FALSE; if we continue eating the same object
388.  	 * we need to know if canchoke was set when they started eating it the
389.  	 * previous time.  And if we don't continue eating the same object
390.  	 * canchoke always gets recalculated anyway.
391.  	 */
392.  	stop_occupation();
393.  	newuhs(FALSE);
394.  }
395.  

eatfood[]

396.  STATIC_PTR
397.  int
398.  eatfood()		/* called each move during eating process */
399.  {
400.  	if(!victual.piece ||
401.  	 (!carried(victual.piece) && !obj_here(victual.piece, u.ux, u.uy))) {
402.  		/* maybe it was stolen? */
403.  		do_reset_eat();
404.  		return(0);
405.  	}
406.  	if(!victual.eating) return(0);
407.  
408.  	if(++victual.usedtime <= victual.reqtime) {
409.  	    if(bite()) return(0);
410.  	    return(1);	/* still busy */
411.  	} else {	/* done */
412.  	    done_eating(TRUE);
413.  	    return(0);
414.  	}
415.  }
416.  

done_eating[]

417.  STATIC_OVL void
418.  done_eating(message)
419.  boolean message;
420.  {
421.  	victual.piece->in_use = TRUE;
422.  	occupation = 0; /* do this early, so newuhs() knows we're done */
423.  	newuhs(FALSE);
424.  	if (nomovemsg) {
425.  		if (message) pline(nomovemsg);
426.  		nomovemsg = 0;
427.  	} else if (message)
428.  		You("finish eating %s.", food_xname(victual.piece, TRUE));
429.  
430.  	if(victual.piece->otyp == CORPSE)
431.  		cpostfx(victual.piece->corpsenm);
432.  	else
433.  		fpostfx(victual.piece);
434.  
435.  	if (carried(victual.piece)) useup(victual.piece);
436.  	else useupf(victual.piece, 1L);
437.  	victual.piece = (struct obj *) 0;
438.  	victual.fullwarn = victual.eating = victual.doreset = FALSE;
439.  }
440.  

maybe_cannibal[]

441.  STATIC_OVL boolean
442.  maybe_cannibal(pm, allowmsg)
443.  int pm;
444.  boolean allowmsg;
445.  {
446.  	if (!CANNIBAL_ALLOWED() && your_race(&mons[pm])) {
447.  		if (allowmsg) {
448.  			if (Upolyd)
449.  				You("have a bad feeling deep inside.");
450.  			You("cannibal!  You will regret this!");
451.  		}
452.  		HAggravate_monster |= FROMOUTSIDE;
453.  		change_luck(-rn1(4,2));		/* -5..-2 */
454.  		return TRUE;
455.  	}
456.  	return FALSE;
457.  }
458.  

cprefx[]

459.  STATIC_OVL void
460.  cprefx(pm)
461.  register int pm;
462.  {
463.  	(void) maybe_cannibal(pm,TRUE);
464.  	if (touch_petrifies(&mons[pm]) || pm == PM_MEDUSA) {
465.  	    if (!Stone_resistance &&
466.  		!(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))) {
467.  		Sprintf(killer_buf, "tasting %s meat", mons[pm].mname);
468.  		killer_format = KILLED_BY;
469.  		killer = killer_buf;
470.  		You("turn to stone.");
471.  		done(STONING);
472.  		if (victual.piece)
473.  		    victual.eating = FALSE;
474.  		return; /* lifesaved */
475.  	    }
476.  	}
477.  
478.  	switch(pm) {
479.  	    case PM_LITTLE_DOG:
480.  	    case PM_DOG:
481.  	    case PM_LARGE_DOG:
482.  	    case PM_KITTEN:
483.  	    case PM_HOUSECAT:
484.  	    case PM_LARGE_CAT:
485.  		if (!CANNIBAL_ALLOWED()) {
486.  		    You_feel("that eating the %s was a bad idea.", mons[pm].mname);
487.  		    HAggravate_monster |= FROMOUTSIDE;
488.  		}
489.  		break;
490.  	    case PM_LIZARD:
491.  		if (Stoned) fix_petrification();
492.  		break;
493.  	    case PM_DEATH:
494.  	    case PM_PESTILENCE:
495.  	    case PM_FAMINE:
496.  		{ char buf[BUFSZ];
497.  		    pline("Eating that is instantly fatal.");
498.  		    Sprintf(buf, "unwisely ate the body of %s",
499.  			    mons[pm].mname);
500.  		    killer = buf;
501.  		    killer_format = NO_KILLER_PREFIX;
502.  		    done(DIED);
503.  		    /* It so happens that since we know these monsters */
504.  		    /* cannot appear in tins, victual.piece will always */
505.  		    /* be what we want, which is not generally true. */
506.  		    if (revive_corpse(victual.piece))
507.  			victual.piece = (struct obj *)0;
508.  		    return;
509.  		}
510.  	    case PM_GREEN_SLIME:
511.  		if (!Slimed && !Unchanging && !flaming(youmonst.data) &&
512.  			youmonst.data != &mons[PM_GREEN_SLIME]) {
513.  		    You("don't feel very well.");
514.  		    Slimed = 10L;
515.  		    flags.botl = 1;
516.  		}
517.  		/* Fall through */
518.  	    default:
519.  		if (acidic(&mons[pm]) && Stoned)
520.  		    fix_petrification();
521.  		break;
522.  	}
523.  }
524.  

fix_petrification[]

525.  void
526.  fix_petrification()
527.  {
528.  	Stoned = 0;
529.  	delayed_killer = 0;
530.  	if (Hallucination)
531.  	    pline("What a pity - you just ruined a future piece of %sart!",
532.  		  ACURR(A_CHA) > 15 ? "fine " : "");
533.  	else
534.  	    You_feel("limber!");
535.  }
536.  

intrinsic_possible[]

537.  /*
538.   * If you add an intrinsic that can be gotten by eating a monster, add it
539.   * to intrinsic_possible() and givit().  (It must already be in prop.h to
540.   * be an intrinsic property.)
541.   * It would be very easy to make the intrinsics not try to give you one
542.   * that you already had by checking to see if you have it in
543.   * intrinsic_possible() instead of givit().
544.   */
545.  
546.  /* intrinsic_possible() returns TRUE iff a monster can give an intrinsic. */
547.  STATIC_OVL int
548.  intrinsic_possible(type, ptr)
549.  int type;
550.  register struct permonst *ptr;
551.  {
552.  	switch (type) {
553.  	    case FIRE_RES:
554.  #ifdef DEBUG
555.  		if (ptr->mconveys & MR_FIRE) {
556.  			debugpline("can get fire resistance");
557.  			return(TRUE);
558.  		} else  return(FALSE);
559.  #else
560.  		return(ptr->mconveys & MR_FIRE);
561.  #endif
562.  	    case SLEEP_RES:
563.  #ifdef DEBUG
564.  		if (ptr->mconveys & MR_SLEEP) {
565.  			debugpline("can get sleep resistance");
566.  			return(TRUE);
567.  		} else  return(FALSE);
568.  #else
569.  		return(ptr->mconveys & MR_SLEEP);
570.  #endif
571.  	    case COLD_RES:
572.  #ifdef DEBUG
573.  		if (ptr->mconveys & MR_COLD) {
574.  			debugpline("can get cold resistance");
575.  			return(TRUE);
576.  		} else  return(FALSE);
577.  #else
578.  		return(ptr->mconveys & MR_COLD);
579.  #endif
580.  	    case DISINT_RES:
581.  #ifdef DEBUG
582.  		if (ptr->mconveys & MR_DISINT) {
583.  			debugpline("can get disintegration resistance");
584.  			return(TRUE);
585.  		} else  return(FALSE);
586.  #else
587.  		return(ptr->mconveys & MR_DISINT);
588.  #endif
589.  	    case SHOCK_RES:	/* shock (electricity) resistance */
590.  #ifdef DEBUG
591.  		if (ptr->mconveys & MR_ELEC) {
592.  			debugpline("can get shock resistance");
593.  			return(TRUE);
594.  		} else  return(FALSE);
595.  #else
596.  		return(ptr->mconveys & MR_ELEC);
597.  #endif
598.  	    case POISON_RES:
599.  #ifdef DEBUG
600.  		if (ptr->mconveys & MR_POISON) {
601.  			debugpline("can get poison resistance");
602.  			return(TRUE);
603.  		} else  return(FALSE);
604.  #else
605.  		return(ptr->mconveys & MR_POISON);
606.  #endif
607.  	    case TELEPORT:
608.  #ifdef DEBUG
609.  		if (can_teleport(ptr)) {
610.  			debugpline("can get teleport");
611.  			return(TRUE);
612.  		} else  return(FALSE);
613.  #else
614.  		return(can_teleport(ptr));
615.  #endif
616.  	    case TELEPORT_CONTROL:
617.  #ifdef DEBUG
618.  		if (control_teleport(ptr)) {
619.  			debugpline("can get teleport control");
620.  			return(TRUE);
621.  		} else  return(FALSE);
622.  #else
623.  		return(control_teleport(ptr));
624.  #endif
625.  	    case TELEPAT:
626.  #ifdef DEBUG
627.  		if (telepathic(ptr)) {
628.  			debugpline("can get telepathy");
629.  			return(TRUE);
630.  		} else  return(FALSE);
631.  #else
632.  		return(telepathic(ptr));
633.  #endif
634.  	    default:
635.  		return(FALSE);
636.  	}
637.  	/*NOTREACHED*/
638.  }
639.  

givit[]

640.  /* givit() tries to give you an intrinsic based on the monster's level
641.   * and what type of intrinsic it is trying to give you.
642.   */
643.  STATIC_OVL void
644.  givit(type, ptr)
645.  int type;
646.  register struct permonst *ptr;
647.  {
648.  	register int chance;
649.  
650.  #ifdef DEBUG
651.  	debugpline("Attempting to give intrinsic %d", type);
652.  #endif
653.  	/* some intrinsics are easier to get than others */
654.  	switch (type) {
655.  		case POISON_RES:
656.  			if ((ptr == &mons[PM_KILLER_BEE] ||
657.  					ptr == &mons[PM_SCORPION]) && !rn2(4))
658.  				chance = 1;
659.  			else
660.  				chance = 15;
661.  			break;
662.  		case TELEPORT:
663.  			chance = 10;
664.  			break;
665.  		case TELEPORT_CONTROL:
666.  			chance = 12;
667.  			break;
668.  		case TELEPAT:
669.  			chance = 1;
670.  			break;
671.  		default:
672.  			chance = 15;
673.  			break;
674.  	}
675.  
676.  	if (ptr->mlevel <= rn2(chance))
677.  		return;		/* failed die roll */
678.  
679.  	switch (type) {
680.  	    case FIRE_RES:
681.  #ifdef DEBUG
682.  		debugpline("Trying to give fire resistance");
683.  #endif
684.  		if(!(HFire_resistance & FROMOUTSIDE)) {
685.  			You(Hallucination ? "be chillin'." :
686.  			    "feel a momentary chill.");
687.  			HFire_resistance |= FROMOUTSIDE;
688.  		}
689.  		break;
690.  	    case SLEEP_RES:
691.  #ifdef DEBUG
692.  		debugpline("Trying to give sleep resistance");
693.  #endif
694.  		if(!(HSleep_resistance & FROMOUTSIDE)) {
695.  			You_feel("wide awake.");
696.  			HSleep_resistance |= FROMOUTSIDE;
697.  		}
698.  		break;
699.  	    case COLD_RES:
700.  #ifdef DEBUG
701.  		debugpline("Trying to give cold resistance");
702.  #endif
703.  		if(!(HCold_resistance & FROMOUTSIDE)) {
704.  			You_feel("full of hot air.");
705.  			HCold_resistance |= FROMOUTSIDE;
706.  		}
707.  		break;
708.  	    case DISINT_RES:
709.  #ifdef DEBUG
710.  		debugpline("Trying to give disintegration resistance");
711.  #endif
712.  		if(!(HDisint_resistance & FROMOUTSIDE)) {
713.  			You_feel(Hallucination ?
714.  			    "totally together, man." :
715.  			    "very firm.");
716.  			HDisint_resistance |= FROMOUTSIDE;
717.  		}
718.  		break;
719.  	    case SHOCK_RES:	/* shock (electricity) resistance */
720.  #ifdef DEBUG
721.  		debugpline("Trying to give shock resistance");
722.  #endif
723.  		if(!(HShock_resistance & FROMOUTSIDE)) {
724.  			if (Hallucination)
725.  				You_feel("grounded in reality.");
726.  			else
727.  				Your("health currently feels amplified!");
728.  			HShock_resistance |= FROMOUTSIDE;
729.  		}
730.  		break;
731.  	    case POISON_RES:
732.  #ifdef DEBUG
733.  		debugpline("Trying to give poison resistance");
734.  #endif
735.  		if(!(HPoison_resistance & FROMOUTSIDE)) {
736.  			You_feel(Poison_resistance ?
737.  				 "especially healthy." : "healthy.");
738.  			HPoison_resistance |= FROMOUTSIDE;
739.  		}
740.  		break;
741.  	    case TELEPORT:
742.  #ifdef DEBUG
743.  		debugpline("Trying to give teleport");
744.  #endif
745.  		if(!(HTeleportation & FROMOUTSIDE)) {
746.  			You_feel(Hallucination ? "diffuse." :
747.  			    "very jumpy.");
748.  			HTeleportation |= FROMOUTSIDE;
749.  		}
750.  		break;
751.  	    case TELEPORT_CONTROL:
752.  #ifdef DEBUG
753.  		debugpline("Trying to give teleport control");
754.  #endif
755.  		if(!(HTeleport_control & FROMOUTSIDE)) {
756.  			You_feel(Hallucination ?
757.  			    "centered in your personal space." :
758.  			    "in control of yourself.");
759.  			HTeleport_control |= FROMOUTSIDE;
760.  		}
761.  		break;
762.  	    case TELEPAT:
763.  #ifdef DEBUG
764.  		debugpline("Trying to give telepathy");
765.  #endif
766.  		if(!(HTelepat & FROMOUTSIDE)) {
767.  			You_feel(Hallucination ?
768.  			    "in touch with the cosmos." :
769.  			    "a strange mental acuity.");
770.  			HTelepat |= FROMOUTSIDE;
771.  			/* If blind, make sure monsters show up. */
772.  			if (Blind) see_monsters();
773.  		}
774.  		break;
775.  	    default:
776.  #ifdef DEBUG
777.  		debugpline("Tried to give an impossible intrinsic");
778.  #endif
779.  		break;
780.  	}
781.  }
782.  

cpostfx[]

783.  STATIC_OVL void
784.  cpostfx(pm)		/* called after completely consuming a corpse */
785.  register int pm;
786.  {
787.  	register int tmp = 0;
788.  	boolean catch_lycanthropy = FALSE;
789.  
790.  	/* in case `afternmv' didn't get called for previously mimicking
791.  	   gold, clean up now to avoid `eatmbuf' memory leak */
792.  	if (eatmbuf) (void)eatmdone();
793.  
794.  	switch(pm) {
795.  	    case PM_NEWT:
796.  		/* MRKR: "eye of newt" may give small magical energy boost */
797.  		if (rn2(3) || 3 * u.uen <= 2 * u.uenmax) {
798.  		    int old_uen = u.uen;
799.  		    u.uen += rnd(3);
800.  		    if (u.uen > u.uenmax) {
801.  			if (!rn2(3)) u.uenmax++;
802.  			u.uen = u.uenmax;
803.  		    }
804.  		    if (old_uen != u.uen) {
805.  			    You_feel("a mild buzz.");
806.  			    flags.botl = 1;
807.  		    }
808.  		}
809.  		break;
810.  	    case PM_WRAITH:
811.  		pluslvl(FALSE);
812.  		break;
813.  	    case PM_HUMAN_WERERAT:
814.  		catch_lycanthropy = TRUE;
815.  		u.ulycn = PM_WERERAT;
816.  		break;
817.  	    case PM_HUMAN_WEREJACKAL:
818.  		catch_lycanthropy = TRUE;
819.  		u.ulycn = PM_WEREJACKAL;
820.  		break;
821.  	    case PM_HUMAN_WEREWOLF:
822.  		catch_lycanthropy = TRUE;
823.  		u.ulycn = PM_WEREWOLF;
824.  		break;
825.  	    case PM_NURSE:
826.  		if (Upolyd) u.mh = u.mhmax;
827.  		else u.uhp = u.uhpmax;
828.  		flags.botl = 1;
829.  		break;
830.  	    case PM_STALKER:
831.  		if(!Invis) {
832.  			set_itimeout(&HInvis, (long)rn1(100, 50));
833.  			if (!Blind && !BInvis) self_invis_message();
834.  		} else {
835.  			if (!(HInvis & INTRINSIC)) You_feel("hidden!");
836.  			HInvis |= FROMOUTSIDE;
837.  			HSee_invisible |= FROMOUTSIDE;
838.  		}
839.  		newsym(u.ux, u.uy);
840.  		/* fall into next case */
841.  	    case PM_YELLOW_LIGHT:
842.  		/* fall into next case */
843.  	    case PM_GIANT_BAT:
844.  		make_stunned(HStun + 30,FALSE);
845.  		/* fall into next case */
846.  	    case PM_BAT:
847.  		make_stunned(HStun + 30,FALSE);
848.  		break;
849.  	    case PM_GIANT_MIMIC:
850.  		tmp += 10;
851.  		/* fall into next case */
852.  	    case PM_LARGE_MIMIC:
853.  		tmp += 20;
854.  		/* fall into next case */
855.  	    case PM_SMALL_MIMIC:
856.  		tmp += 20;
857.  		if (youmonst.data->mlet != S_MIMIC && !Unchanging) {
858.  		    char buf[BUFSZ];
859.  		    You_cant("resist the temptation to mimic %s.",
860.  			Hallucination ? "an orange" : "a pile of gold");
861.  #ifdef STEED
862.                      /* A pile of gold can't ride. */
863.  		    if (u.usteed) dismount_steed(DISMOUNT_FELL);
864.  #endif
865.  		    nomul(-tmp);
866.  		    Sprintf(buf, Hallucination ?
867.  			"You suddenly dread being peeled and mimic %s again!" :
868.  			"You now prefer mimicking %s again.",
869.  			an(Upolyd ? youmonst.data->mname : urace.noun));
870.  		    eatmbuf = strcpy((char *) alloc(strlen(buf) + 1), buf);
871.  		    nomovemsg = eatmbuf;
872.  		    afternmv = eatmdone;
873.  		    /* ??? what if this was set before? */
874.  		    youmonst.m_ap_type = M_AP_OBJECT;
875.  		    youmonst.mappearance = Hallucination ? ORANGE : GOLD_PIECE;
876.  		    newsym(u.ux,u.uy);
877.  		    curs_on_u();
878.  		    /* make gold symbol show up now */
879.  		    display_nhwindow(WIN_MAP, TRUE);
880.  		}
881.  		break;
882.  	    case PM_QUANTUM_MECHANIC:
883.  		Your("velocity suddenly seems very uncertain!");
884.  		if (HFast & INTRINSIC) {
885.  			HFast &= ~INTRINSIC;
886.  			You("seem slower.");
887.  		} else {
888.  			HFast |= FROMOUTSIDE;
889.  			You("seem faster.");
890.  		}
891.  		break;
892.  	    case PM_LIZARD:
893.  		if (HStun > 2)  make_stunned(2L,FALSE);
894.  		if (HConfusion > 2)  make_confused(2L,FALSE);
895.  		break;
896.  	    case PM_CHAMELEON:
897.  	    case PM_DOPPELGANGER:
898.  	 /* case PM_SANDESTIN: */
899.  		if (!Unchanging) {
900.  		    You_feel("a change coming over you.");
901.  		    polyself(FALSE);
902.  		}
903.  		break;
904.  	    case PM_MIND_FLAYER:
905.  	    case PM_MASTER_MIND_FLAYER:
906.  		if (ABASE(A_INT) < ATTRMAX(A_INT)) {
907.  			if (!rn2(2)) {
908.  				pline("Yum! That was real brain food!");
909.  				(void) adjattrib(A_INT, 1, FALSE);
910.  				break;	/* don't give them telepathy, too */
911.  			}
912.  		}
913.  		else {
914.  			pline("For some reason, that tasted bland.");
915.  		}
916.  		/* fall through to default case */
917.  	    default: {
918.  		register struct permonst *ptr = &mons[pm];
919.  		int i, count;
920.  
921.  		if (dmgtype(ptr, AD_STUN) || dmgtype(ptr, AD_HALU) ||
922.  		    pm == PM_VIOLET_FUNGUS) {
923.  			pline ("Oh wow!  Great stuff!");
924.  			make_hallucinated(HHallucination + 200,FALSE,0L);
925.  		}
926.  		if(is_giant(ptr)) gainstr((struct obj *)0, 0);
927.  
928.  		/* Check the monster for all of the intrinsics.  If this
929.  		 * monster can give more than one, pick one to try to give
930.  		 * from among all it can give.
931.  		 *
932.  		 * If a monster can give 4 intrinsics then you have
933.  		 * a 1/1 * 1/2 * 2/3 * 3/4 = 1/4 chance of getting the first,
934.  		 * a 1/2 * 2/3 * 3/4 = 1/4 chance of getting the second,
935.  		 * a 1/3 * 3/4 = 1/4 chance of getting the third,
936.  		 * and a 1/4 chance of getting the fourth.
937.  		 *
938.  		 * And now a proof by induction:
939.  		 * it works for 1 intrinsic (1 in 1 of getting it)
940.  		 * for 2 you have a 1 in 2 chance of getting the second,
941.  		 *	otherwise you keep the first
942.  		 * for 3 you have a 1 in 3 chance of getting the third,
943.  		 *	otherwise you keep the first or the second
944.  		 * for n+1 you have a 1 in n+1 chance of getting the (n+1)st,
945.  		 *	otherwise you keep the previous one.
946.  		 * Elliott Kleinrock, October 5, 1990
947.  		 */
948.  
949.  		 count = 0;	/* number of possible intrinsics */
950.  		 tmp = 0;	/* which one we will try to give */
951.  		 for (i = 1; i <= LAST_PROP; i++) {
952.  			if (intrinsic_possible(i, ptr)) {
953.  				count++;
954.  				/* a 1 in count chance of replacing the old
955.  				 * one with this one, and a count-1 in count
956.  				 * chance of keeping the old one.  (note
957.  				 * that 1 in 1 and 0 in 1 are what we want
958.  				 * for the first one
959.  				 */
960.  				if (!rn2(count)) {
961.  #ifdef DEBUG
962.  					debugpline("Intrinsic %d replacing %d",
963.  								i, tmp);
964.  #endif
965.  					tmp = i;
966.  				}
967.  			}
968.  		 }
969.  
970.  		 /* if any found try to give them one */
971.  		 if (count) givit(tmp, ptr);
972.  	    }
973.  	    break;
974.  	}
975.  
976.  	if (catch_lycanthropy && defends(AD_WERE, uwep)) {
977.  	    if (!touch_artifact(uwep, &youmonst)) {
978.  		dropx(uwep);
979.  		uwepgone();
980.  	    }
981.  	}
982.  
983.  	return;
984.  }
985.  

violated_vegetarian[]

986.  void
987.  violated_vegetarian()
988.  {
989.      u.uconduct.unvegetarian++;
990.      if (Role_if(PM_MONK)) {
991.  	You_feel("guilty.");
992.  	adjalign(-1);
993.      }
994.      return;
995.  }
996.  

costly_tin[]

997.  /* common code to check and possibly charge for 1 context.tin.tin,
998.   * will split() context.tin.tin if necessary */
999.  STATIC_PTR
1000. void
1001. costly_tin(verb)
1002. 	const char* verb;		/* if 0, the verb is "open" */
1003. {
1004. 	if(((!carried(tin.tin) &&
1005. 	     costly_spot(tin.tin->ox, tin.tin->oy) &&
1006. 	     !tin.tin->no_charge)
1007. 	    || tin.tin->unpaid)) {
1008. 	    verbalize("You %s it, you bought it!", verb ? verb : "open");
1009. 	    if(tin.tin->quan > 1L) tin.tin = splitobj(tin.tin, 1L);
1010. 	    bill_dummy_object(tin.tin);
1011. 	}
1012. }
1013. 

opentin[]

1014. STATIC_PTR
1015. int
1016. opentin()		/* called during each move whilst opening a tin */
1017. {
1018. 	register int r;
1019. 	const char *what;
1020. 	int which;
1021. 
1022. 	if(!carried(tin.tin) && !obj_here(tin.tin, u.ux, u.uy))
1023. 					/* perhaps it was stolen? */
1024. 		return(0);		/* %% probably we should use tinoid */
1025. 	if(tin.usedtime++ >= 50) {
1026. 		You("give up your attempt to open the tin.");
1027. 		return(0);
1028. 	}
1029. 	if(tin.usedtime < tin.reqtime)
1030. 		return(1);		/* still busy */
1031. 	if(tin.tin->otrapped ||
1032. 	   (tin.tin->cursed && tin.tin->spe != -1 && !rn2(8))) {
1033. 		b_trapped("tin", 0);
1034. 		costly_tin("destroyed");
1035. 		goto use_me;
1036. 	}
1037. 	You("succeed in opening the tin.");
1038. 	if(tin.tin->spe != 1) {
1039. 	    if (tin.tin->corpsenm == NON_PM) {
1040. 		pline("It turns out to be empty.");
1041. 		tin.tin->dknown = tin.tin->known = TRUE;
1042. 		costly_tin((const char*)0);
1043. 		goto use_me;
1044. 	    }
1045. 	    r = tin.tin->cursed ? ROTTEN_TIN :	/* always rotten if cursed */
1046. 		    (tin.tin->spe == -1) ? HOMEMADE_TIN :  /* player made it */
1047. 			rn2(TTSZ-1);		/* else take your pick */
1048. 	    if (r == ROTTEN_TIN && (tin.tin->corpsenm == PM_LIZARD ||
1049. 			tin.tin->corpsenm == PM_LICHEN))
1050. 		r = HOMEMADE_TIN;		/* lizards don't rot */
1051. 	    else if (tin.tin->spe == -1 && !tin.tin->blessed && !rn2(7))
1052. 		r = ROTTEN_TIN;			/* some homemade tins go bad */
1053. 	    which = 0;	/* 0=>plural, 1=>as-is, 2=>"the" prefix */
1054. 	    if (Hallucination) {
1055. 		what = rndmonnam();
1056. 	    } else {
1057. 		what = mons[tin.tin->corpsenm].mname;
1058. 		if (mons[tin.tin->corpsenm].geno & G_UNIQ)
1059. 		    which = type_is_pname(&mons[tin.tin->corpsenm]) ? 1 : 2;
1060. 	    }
1061. 	    if (which == 0) what = makeplural(what);
1062. 	    pline("It smells like %s%s.", (which == 2) ? "the " : "", what);
1063. 	    if (yn("Eat it?") == 'n') {
1064. 		if (!Hallucination) tin.tin->dknown = tin.tin->known = TRUE;
1065. 		if (flags.verbose) You("discard the open tin.");
1066. 		costly_tin((const char*)0);
1067. 		goto use_me;
1068. 	    }
1069. 	    /* in case stop_occupation() was called on previous meal */
1070. 	    victual.piece = (struct obj *)0;
1071. 	    victual.fullwarn = victual.eating = victual.doreset = FALSE;
1072. 
1073. 	    You("consume %s %s.", tintxts[r].txt,
1074. 			mons[tin.tin->corpsenm].mname);
1075. 
1076. 	    /* KMH, conduct */
1077. 	    u.uconduct.food++;
1078. 	    if (!vegan(&mons[tin.tin->corpsenm]))
1079. 		u.uconduct.unvegan++;
1080. 	    if (!vegetarian(&mons[tin.tin->corpsenm]))
1081. 		violated_vegetarian();
1082. 
1083. 	    tin.tin->dknown = tin.tin->known = TRUE;
1084. 	    cprefx(tin.tin->corpsenm); cpostfx(tin.tin->corpsenm);
1085. 
1086. 	    /* charge for one at pre-eating cost */
1087. 	    costly_tin((const char*)0);
1088. 
1089. 	    /* check for vomiting added by GAN 01/16/87 */
1090. 	    if(tintxts[r].nut < 0) make_vomiting((long)rn1(15,10), FALSE);
1091. 	    else lesshungry(tintxts[r].nut);
1092. 
1093. 	    if(r == 0 || r == FRENCH_FRIED_TIN) {
1094. 	        /* Assume !Glib, because you can't open tins when Glib. */
1095. 		incr_itimeout(&Glib, rnd(15));
1096. 		pline("Eating deep fried food made your %s very slippery.",
1097. 		      makeplural(body_part(FINGER)));
1098. 	    }
1099. 	} else {
1100. 	    if (tin.tin->cursed)
1101. 		pline("It contains some decaying%s%s substance.",
1102. 			Blind ? "" : " ", Blind ? "" : hcolor(NH_GREEN));
1103. 	    else
1104. 		pline("It contains spinach.");
1105. 
1106. 	    if (yn("Eat it?") == 'n') {
1107. 		if (!Hallucination && !tin.tin->cursed)
1108. 		    tin.tin->dknown = tin.tin->known = TRUE;
1109. 		if (flags.verbose)
1110. 		    You("discard the open tin.");
1111. 		costly_tin((const char*)0);
1112. 		goto use_me;
1113. 	    }
1114. 
1115. 	    tin.tin->dknown = tin.tin->known = TRUE;
1116. 	    costly_tin((const char*)0);
1117. 
1118. 	    if (!tin.tin->cursed)
1119. 		pline("This makes you feel like %s!",
1120. 		      Hallucination ? "Swee'pea" : "Popeye");
1121. 	    lesshungry(600);
1122. 	    gainstr(tin.tin, 0);
1123. 	    u.uconduct.food++;
1124. 	}
1125. use_me:
1126. 	if (carried(tin.tin)) useup(tin.tin);
1127. 	else useupf(tin.tin, 1L);
1128. 	tin.tin = (struct obj *) 0;
1129. 	return(0);
1130. }
1131. 

start_tin[]

1132. STATIC_OVL void
1133. start_tin(otmp)		/* called when starting to open a tin */
1134. 	register struct obj *otmp;
1135. {
1136. 	register int tmp;
1137. 
1138. 	if (metallivorous(youmonst.data)) {
1139. 		You("bite right into the metal tin...");
1140. 		tmp = 1;
1141. 	} else if (nolimbs(youmonst.data)) {
1142. 		You("cannot handle the tin properly to open it.");
1143. 		return;
1144. 	} else if (otmp->blessed) {
1145. 		pline_The("tin opens like magic!");
1146. 		tmp = 1;
1147. 	} else if(uwep) {
1148. 		switch(uwep->otyp) {
1149. 		case TIN_OPENER:
1150. 			tmp = 1;
1151. 			break;
1152. 		case DAGGER:
1153. 		case SILVER_DAGGER:
1154. 		case ELVEN_DAGGER:
1155. 		case ORCISH_DAGGER:
1156. 		case ATHAME:
1157. 		case CRYSKNIFE:
1158. 			tmp = 3;
1159. 			break;
1160. 		case PICK_AXE:
1161. 		case AXE:
1162. 			tmp = 6;
1163. 			break;
1164. 		default:
1165. 			goto no_opener;
1166. 		}
1167. 		pline("Using your %s you try to open the tin.",
1168. 			aobjnam(uwep, (char *)0));
1169. 	} else {
1170. no_opener:
1171. 		pline("It is not so easy to open this tin.");
1172. 		if(Glib) {
1173. 			pline_The("tin slips from your %s.",
1174. 			      makeplural(body_part(FINGER)));
1175. 			if(otmp->quan > 1L) {
1176. 			    otmp = splitobj(otmp, 1L);
1177. 			}
1178. 			if (carried(otmp)) dropx(otmp);
1179. 			else stackobj(otmp);
1180. 			return;
1181. 		}
1182. 		tmp = rn1(1 + 500/((int)(ACURR(A_DEX) + ACURRSTR)), 10);
1183. 	}
1184. 	tin.reqtime = tmp;
1185. 	tin.usedtime = 0;
1186. 	tin.tin = otmp;
1187. 	set_occupation(opentin, "opening the tin", 0);
1188. 	return;
1189. }
1190. 

Hear_again[]

1191. int
1192. Hear_again()		/* called when waking up after fainting */
1193. {
1194. 	flags.soundok = 1;
1195. 	return 0;
1196. }
1197. 

rottenfood[]

1198. /* called on the "first bite" of rotten food */
1199. STATIC_OVL int
1200. rottenfood(obj)
1201. struct obj *obj;
1202. {
1203. 	pline("Blecch!  Rotten %s!", foodword(obj));
1204. 	if(!rn2(4)) {
1205. 		if (Hallucination) You_feel("rather trippy.");
1206. 		else You_feel("rather %s.", body_part(LIGHT_HEADED));
1207. 		make_confused(HConfusion + d(2,4),FALSE);
1208. 	} else if(!rn2(4) && !Blind) {
1209. 		pline("Everything suddenly goes dark.");
1210. 		make_blinded((long)d(2,10),FALSE);
1211. 		if (!Blind) Your(vision_clears);
1212. 	} else if(!rn2(3)) {
1213. 		const char *what, *where;
1214. 		if (!Blind)
1215. 		    what = "goes",  where = "dark";
1216. 		else if (Levitation || Is_airlevel(&u.uz) ||
1217. 			 Is_waterlevel(&u.uz))
1218. 		    what = "you lose control of",  where = "yourself";
1219. 		else
1220. 		    what = "you slap against the", where =
1221. #ifdef STEED
1222. 			   (u.usteed) ? "saddle" :
1223. #endif
1224. 			   surface(u.ux,u.uy);
1225. 		pline_The("world spins and %s %s.", what, where);
1226. 		flags.soundok = 0;
1227. 		nomul(-rnd(10));
1228. 		nomovemsg = "You are conscious again.";
1229. 		afternmv = Hear_again;
1230. 		return(1);
1231. 	}
1232. 	return(0);
1233. }
1234. 

eatcorpse[]

1235. STATIC_OVL int
1236. eatcorpse(otmp)		/* called when a corpse is selected as food */
1237. 	register struct obj *otmp;
1238. {
1239. 	int tp = 0, mnum = otmp->corpsenm;
1240. 	long rotted = 0L;
1241. 	boolean uniq = !!(mons[mnum].geno & G_UNIQ);
1242. 	int retcode = 0;
1243. 	boolean stoneable = (touch_petrifies(&mons[mnum]) && !Stone_resistance &&
1244. 				!poly_when_stoned(youmonst.data));
1245. 
1246. 	/* KMH, conduct */
1247. 	if (!vegan(&mons[mnum])) u.uconduct.unvegan++;
1248. 	if (!vegetarian(&mons[mnum])) violated_vegetarian();
1249. 
1250. 	if (mnum != PM_LIZARD && mnum != PM_LICHEN) {
1251. 		long age = peek_at_iced_corpse_age(otmp);
1252. 
1253. 		rotted = (monstermoves - age)/(10L + rn2(20));
1254. 		if (otmp->cursed) rotted += 2L;
1255. 		else if (otmp->blessed) rotted -= 2L;
1256. 	}
1257. 
1258. 	if (mnum != PM_ACID_BLOB && !stoneable && rotted > 5L) {
1259. 		boolean cannibal = maybe_cannibal(mnum, FALSE);
1260. 		pline("Ulch - that %s was tainted%s!",
1261. 		      mons[mnum].mlet == S_FUNGUS ? "fungoid vegetation" :
1262. 		      !vegetarian(&mons[mnum]) ? "meat" : "protoplasm",
1263. 		      cannibal ? " cannibal" : "");
1264. 		if (Sick_resistance) {
1265. 			pline("It doesn't seem at all sickening, though...");
1266. 		} else {
1267. 			char buf[BUFSZ];
1268. 			long sick_time;
1269. 
1270. 			sick_time = (long) rn1(10, 10);
1271. 			/* make sure new ill doesn't result in improvement */
1272. 			if (Sick && (sick_time > Sick))
1273. 			    sick_time = (Sick > 1L) ? Sick - 1L : 1L;
1274. 			if (!uniq)
1275. 			    Sprintf(buf, "rotted %s", corpse_xname(otmp,TRUE));
1276. 			else
1277. 			    Sprintf(buf, "%s%s rotted corpse",
1278. 				    !type_is_pname(&mons[mnum]) ? "the " : "",
1279. 				    s_suffix(mons[mnum].mname));
1280. 			make_sick(sick_time, buf, TRUE, SICK_VOMITABLE);
1281. 		}
1282. 		if (carried(otmp)) useup(otmp);
1283. 		else useupf(otmp, 1L);
1284. 		return(2);
1285. 	} else if (acidic(&mons[mnum]) && !Acid_resistance) {
1286. 		tp++;
1287. 		You("have a very bad case of stomach acid."); /* not body_part() */
1288. 		losehp(rnd(15), "acidic corpse", KILLED_BY_AN);
1289. 	} else if (poisonous(&mons[mnum]) && rn2(5)) {
1290. 		tp++;
1291. 		pline("Ecch - that must have been poisonous!");
1292. 		if(!Poison_resistance) {
1293. 			losestr(rnd(4));
1294. 			losehp(rnd(15), "poisonous corpse", KILLED_BY_AN);
1295. 		} else	You("seem unaffected by the poison.");
1296. 	/* now any corpse left too long will make you mildly ill */
1297. 	} else if ((rotted > 5L || (rotted > 3L && rn2(5)))
1298. 					&& !Sick_resistance) {
1299. 		tp++;
1300. 		You_feel("%ssick.", (Sick) ? "very " : "");
1301. 		losehp(rnd(8), "cadaver", KILLED_BY_AN);
1302. 	}
1303. 
1304. 	/* delay is weight dependent */
1305. 	victual.reqtime = 3 + (mons[mnum].cwt >> 6);
1306. 
1307. 	if (!tp && mnum != PM_LIZARD && mnum != PM_LICHEN &&
1308. 			(otmp->orotten || !rn2(7))) {
1309. 	    if (rottenfood(otmp)) {
1310. 		otmp->orotten = TRUE;
1311. 		(void)touchfood(otmp);
1312. 		retcode = 1;
1313. 	    }
1314. 
1315. 	    if (!mons[otmp->corpsenm].cnutrit) {
1316. 		/* no nutrution: rots away, no message if you passed out */
1317. 		if (!retcode) pline_The("corpse rots away completely.");
1318. 		if (carried(otmp)) useup(otmp);
1319. 		else useupf(otmp, 1L);
1320. 		retcode = 2;
1321. 	    }
1322. 		    
1323. 	    if (!retcode) consume_oeaten(otmp, 2);	/* oeaten >>= 2 */
1324. 	} else {
1325. 	    pline("%s%s %s!",
1326. 		  !uniq ? "This " : !type_is_pname(&mons[mnum]) ? "The " : "",
1327. 		  food_xname(otmp, FALSE),
1328. 		  (vegan(&mons[mnum]) ?
1329. 		   (!carnivorous(youmonst.data) && herbivorous(youmonst.data)) :
1330. 		   (carnivorous(youmonst.data) && !herbivorous(youmonst.data)))
1331. 		  ? "is delicious" : "tastes terrible");
1332. 	}
1333. 
1334. 	return(retcode);
1335. }
1336. 

start_eating[]

1337. STATIC_OVL void
1338. start_eating(otmp)		/* called as you start to eat */
1339. 	register struct obj *otmp;
1340. {
1341. #ifdef DEBUG
1342. 	debugpline("start_eating: %lx (victual = %lx)", otmp, victual.piece);
1343. 	debugpline("reqtime = %d", victual.reqtime);
1344. 	debugpline("(original reqtime = %d)", objects[otmp->otyp].oc_delay);
1345. 	debugpline("nmod = %d", victual.nmod);
1346. 	debugpline("oeaten = %d", otmp->oeaten);
1347. #endif
1348. 	victual.fullwarn = victual.doreset = FALSE;
1349. 	victual.eating = TRUE;
1350. 
1351. 	if (otmp->otyp == CORPSE) {
1352. 	    cprefx(victual.piece->corpsenm);
1353. 	    if (!victual.piece || !victual.eating) {
1354. 		/* rider revived, or died and lifesaved */
1355. 		return;
1356. 	    }
1357. 	}
1358. 
1359. 	if (bite()) return;
1360. 
1361. 	if (++victual.usedtime >= victual.reqtime) {
1362. 	    /* print "finish eating" message if they just resumed -dlc */
1363. 	    done_eating(victual.reqtime > 1 ? TRUE : FALSE);
1364. 	    return;
1365. 	}
1366. 
1367. 	Sprintf(msgbuf, "eating %s", food_xname(otmp, TRUE));
1368. 	set_occupation(eatfood, msgbuf, 0);
1369. }
1370. 
1371. 

fprefx[]

1372. /*
1373.  * called on "first bite" of (non-corpse) food.
1374.  * used for non-rotten non-tin non-corpse food
1375.  */
1376. STATIC_OVL void
1377. fprefx(otmp)
1378. struct obj *otmp;
1379. {
1380. 	switch(otmp->otyp) {
1381. 	    case FOOD_RATION:
1382. 		if(u.uhunger <= 200)
1383. 		    pline(Hallucination ? "Oh wow, like, superior, man!" :
1384. 			  "That food really hit the spot!");
1385. 		else if(u.uhunger <= 700) pline("That satiated your %s!",
1386. 						body_part(STOMACH));
1387. 		break;
1388. 	    case TRIPE_RATION:
1389. 		if (carnivorous(youmonst.data) && !humanoid(youmonst.data))
1390. 		    pline("That tripe ration was surprisingly good!");
1391. 		else if (maybe_polyd(is_orc(youmonst.data), Race_if(PM_ORC)))
1392. 		    pline(Hallucination ? "Tastes great! Less filling!" :
1393. 			  "Mmm, tripe... not bad!");
1394. 		else {
1395. 		    pline("Yak - dog food!");
1396. 		    more_experienced(1,0);
1397. 		    newexplevel();
1398. 		    /* not cannibalism, but we use similar criteria
1399. 		       for deciding whether to be sickened by this meal */
1400. 		    if (rn2(2) && !CANNIBAL_ALLOWED())
1401. 			make_vomiting((long)rn1(victual.reqtime, 14), FALSE);
1402. 		}
1403. 		break;
1404. 	    case MEATBALL:
1405. 	    case MEAT_STICK:
1406. 	    case HUGE_CHUNK_OF_MEAT:
1407. 	    case MEAT_RING:
1408. 		goto give_feedback;
1409. 	     /* break; */
1410. 	    case CLOVE_OF_GARLIC:
1411. 		if (is_undead(youmonst.data)) {
1412. 			make_vomiting((long)rn1(victual.reqtime, 5), FALSE);
1413. 			break;
1414. 		}
1415. 		/* Fall through otherwise */
1416. 	    default:
1417. 		if (otmp->otyp==SLIME_MOLD && !otmp->cursed
1418. 			&& otmp->spe == current_fruit)
1419. 		    pline("My, that was a %s %s!",
1420. 			  Hallucination ? "primo" : "yummy",
1421. 			  singular(otmp, xname));
1422. 		else
1423. #ifdef UNIX
1424. 		if (otmp->otyp == APPLE || otmp->otyp == PEAR) {
1425. 		    if (!Hallucination) pline("Core dumped.");
1426. 		    else {
1427. /* This is based on an old Usenet joke, a fake a.out manual page */
1428. 			int x = rnd(100);
1429. 			if (x <= 75)
1430. 			    pline("Segmentation fault -- core dumped.");
1431. 			else if (x <= 99)
1432. 			    pline("Bus error -- core dumped.");
1433. 			else pline("Yo' mama -- core dumped.");
1434. 		    }
1435. 		} else
1436. #endif
1437. #ifdef MAC	/* KMH -- Why should Unix have all the fun? */
1438. 		if (otmp->otyp == APPLE) {
1439. 			pline("Delicious!  Must be a Macintosh!");
1440. 		} else
1441. #endif
1442. 		if (otmp->otyp == EGG && stale_egg(otmp)) {
1443. 		    pline("Ugh.  Rotten egg.");	/* perhaps others like it */
1444. 		    make_vomiting(Vomiting+d(10,4), TRUE);
1445. 		} else
1446.  give_feedback:
1447. 		    pline("This %s is %s", singular(otmp, xname),
1448. 		      otmp->cursed ? (Hallucination ? "grody!" : "terrible!") :
1449. 		      (otmp->otyp == CRAM_RATION
1450. 		      || otmp->otyp == K_RATION
1451. 		      || otmp->otyp == C_RATION)
1452. 		      ? "bland." :
1453. 		      Hallucination ? "gnarly!" : "delicious!");
1454. 		break;
1455. 	}
1456. }
1457. 

accessory_has_effect[]

1458. STATIC_OVL void
1459. accessory_has_effect(otmp)
1460. struct obj *otmp;
1461. {
1462. 	pline("Magic spreads through your body as you digest the %s.",
1463. 	    otmp->oclass == RING_CLASS ? "ring" : "amulet");
1464. }
1465. 

eataccessory[]

1466. STATIC_OVL void
1467. eataccessory(otmp)
1468. struct obj *otmp;
1469. {
1470. 	int typ = otmp->otyp;
1471. 	long oldprop;
1472. 
1473. 	/* Note: rings are not so common that this is unbalancing. */
1474. 	/* (How often do you even _find_ 3 rings of polymorph in a game?) */
1475. 	oldprop = u.uprops[objects[typ].oc_oprop].intrinsic;
1476. 	if (otmp == uleft || otmp == uright) {
1477. 	    Ring_gone(otmp);
1478. 	    if (u.uhp <= 0) return; /* died from sink fall */
1479. 	}
1480. 	otmp->known = otmp->dknown = 1; /* by taste */
1481. 	if (!rn2(otmp->oclass == RING_CLASS ? 3 : 5)) {
1482. 	  switch (otmp->otyp) {
1483. 	    default:
1484. 	        if (!objects[typ].oc_oprop) break; /* should never happen */
1485. 
1486. 		if (!(u.uprops[objects[typ].oc_oprop].intrinsic & FROMOUTSIDE))
1487. 		    accessory_has_effect(otmp);
1488. 
1489. 		u.uprops[objects[typ].oc_oprop].intrinsic |= FROMOUTSIDE;
1490. 
1491. 		switch (typ) {
1492. 		  case RIN_SEE_INVISIBLE:
1493. 		    set_mimic_blocking();
1494. 		    see_monsters();
1495. 		    if (Invis && !oldprop && !ESee_invisible &&
1496. 				!perceives(youmonst.data) && !Blind) {
1497. 			newsym(u.ux,u.uy);
1498. 			pline("Suddenly you can see yourself.");
1499. 			makeknown(typ);
1500. 		    }
1501. 		    break;
1502. 		  case RIN_INVISIBILITY:
1503. 		    if (!oldprop && !EInvis && !BInvis &&
1504. 					!See_invisible && !Blind) {
1505. 			newsym(u.ux,u.uy);
1506. 			Your("body takes on a %s transparency...",
1507. 				Hallucination ? "normal" : "strange");
1508. 			makeknown(typ);
1509. 		    }
1510. 		    break;
1511. 		  case RIN_PROTECTION_FROM_SHAPE_CHAN:
1512. 		    rescham();
1513. 		    break;
1514. 		  case RIN_LEVITATION:
1515. 		    /* undo the `.intrinsic |= FROMOUTSIDE' done above */
1516. 		    u.uprops[LEVITATION].intrinsic = oldprop;
1517. 		    if (!Levitation) {
1518. 			float_up();
1519. 			incr_itimeout(&HLevitation, d(10,20));
1520. 			makeknown(typ);
1521. 		    }
1522. 		    break;
1523. 		}
1524. 		break;
1525. 	    case RIN_ADORNMENT:
1526. 		accessory_has_effect(otmp);
1527. 		if (adjattrib(A_CHA, otmp->spe, -1))
1528. 		    makeknown(typ);
1529. 		break;
1530. 	    case RIN_GAIN_STRENGTH:
1531. 		accessory_has_effect(otmp);
1532. 		if (adjattrib(A_STR, otmp->spe, -1))
1533. 		    makeknown(typ);
1534. 		break;
1535. 	    case RIN_GAIN_CONSTITUTION:
1536. 		accessory_has_effect(otmp);
1537. 		if (adjattrib(A_CON, otmp->spe, -1))
1538. 		    makeknown(typ);
1539. 		break;
1540. 	    case RIN_INCREASE_ACCURACY:
1541. 		accessory_has_effect(otmp);
1542. 		u.uhitinc += otmp->spe;
1543. 		break;
1544. 	    case RIN_INCREASE_DAMAGE:
1545. 		accessory_has_effect(otmp);
1546. 		u.udaminc += otmp->spe;
1547. 		break;
1548. 	    case RIN_PROTECTION:
1549. 		accessory_has_effect(otmp);
1550. 		HProtection |= FROMOUTSIDE;
1551. 		u.ublessed += otmp->spe;
1552. 		flags.botl = 1;
1553. 		break;
1554. 	    case RIN_FREE_ACTION:
1555. 		/* Give sleep resistance instead */
1556. 		if (!(HSleep_resistance & FROMOUTSIDE))
1557. 		    accessory_has_effect(otmp);
1558. 		if (!Sleep_resistance)
1559. 		    You_feel("wide awake.");
1560. 		HSleep_resistance |= FROMOUTSIDE;
1561. 		break;
1562. 	    case AMULET_OF_CHANGE:
1563. 		accessory_has_effect(otmp);
1564. 		makeknown(typ);
1565. 		change_sex();
1566. 		You("are suddenly very %s!",
1567. 		    flags.female ? "feminine" : "masculine");
1568. 		flags.botl = 1;
1569. 		break;
1570. 	    case AMULET_OF_UNCHANGING:
1571. 		/* un-change: it's a pun */
1572. 		if (!Unchanging && Upolyd) {
1573. 		    accessory_has_effect(otmp);
1574. 		    makeknown(typ);
1575. 		    rehumanize();
1576. 		}
1577. 		break;
1578. 	    case AMULET_OF_STRANGULATION: /* bad idea! */
1579. 		/* no message--this gives no permanent effect */
1580. 		choke(otmp);
1581. 		break;
1582. 	    case AMULET_OF_RESTFUL_SLEEP: /* another bad idea! */
1583. 		if (!(HSleeping & FROMOUTSIDE))
1584. 		    accessory_has_effect(otmp);
1585. 		HSleeping = FROMOUTSIDE | rnd(100);
1586. 		break;
1587. 	    case RIN_SUSTAIN_ABILITY:
1588. 	    case AMULET_OF_LIFE_SAVING:
1589. 	    case AMULET_OF_REFLECTION: /* nice try */
1590. 	    /* can't eat Amulet of Yendor or fakes,
1591. 	     * and no oc_prop even if you could -3.
1592. 	     */
1593. 		break;
1594. 	  }
1595. 	}
1596. }
1597. 

eatspecial[]

1598. STATIC_OVL void
1599. eatspecial() /* called after eating non-food */
1600. {
1601. 	register struct obj *otmp = victual.piece;
1602. 
1603. 	/* lesshungry wants an occupation to handle choke messages correctly */
1604. 	set_occupation(eatfood, "eating non-food", 0);
1605. 	lesshungry(victual.nmod);
1606. 	occupation = 0;
1607. 	victual.piece = (struct obj *)0;
1608. 	victual.eating = 0;
1609. 	if (otmp->oclass == COIN_CLASS) {
1610. #ifdef GOLDOBJ
1611. 		if (carried(otmp))
1612. 		    useupall(otmp);
1613. #else
1614. 		if (otmp->where == OBJ_FREE)
1615. 		    dealloc_obj(otmp);
1616. #endif
1617. 		else
1618. 		    useupf(otmp, otmp->quan);
1619. 		return;
1620. 	}
1621. 	if (otmp->oclass == POTION_CLASS) {
1622. 		otmp->quan++; /* dopotion() does a useup() */
1623. 		(void)dopotion(otmp);
1624. 	}
1625. 	if (otmp->oclass == RING_CLASS || otmp->oclass == AMULET_CLASS)
1626. 		eataccessory(otmp);
1627. 	else if (otmp->otyp == LEASH && otmp->leashmon)
1628. 		o_unleash(otmp);
1629. 
1630. 	/* KMH -- idea by "Tommy the Terrorist" */
1631. 	if ((otmp->otyp == TRIDENT) && !otmp->cursed)
1632. 	{
1633. 		pline(Hallucination ? "Four out of five dentists agree." :
1634. 				"That was pure chewing satisfaction!");
1635. 		exercise(A_WIS, TRUE);
1636. 	}
1637. 	if ((otmp->otyp == FLINT) && !otmp->cursed)
1638. 	{
1639. 		pline("Yabba-dabba delicious!");
1640. 		exercise(A_CON, TRUE);
1641. 	}
1642. 
1643. 	if (otmp == uwep && otmp->quan == 1L) uwepgone();
1644. 	if (otmp == uquiver && otmp->quan == 1L) uqwepgone();
1645. 	if (otmp == uswapwep && otmp->quan == 1L) uswapwepgone();
1646. 
1647. 	if (otmp == uball) unpunish();
1648. 	if (otmp == uchain) unpunish(); /* but no useup() */
1649. 	else if (carried(otmp)) useup(otmp);
1650. 	else useupf(otmp, 1L);
1651. }
1652. 

foodword[]

1653. /* NOTE: the order of these words exactly corresponds to the
1654.    order of oc_material values #define'd in objclass.h. */
1655. static const char *foodwords[] = {
1656. 	"meal", "liquid", "wax", "food", "meat",
1657. 	"paper", "cloth", "leather", "wood", "bone", "scale",
1658. 	"metal", "metal", "metal", "silver", "gold", "platinum", "mithril",
1659. 	"plastic", "glass", "rich food", "stone"
1660. };
1661. 
1662. STATIC_OVL const char *
1663. foodword(otmp)
1664. register struct obj *otmp;
1665. {
1666. 	if (otmp->oclass == FOOD_CLASS) return "food";
1667. 	if (otmp->oclass == GEM_CLASS &&
1668. 	    objects[otmp->otyp].oc_material == GLASS &&
1669. 	    otmp->dknown)
1670. 		makeknown(otmp->otyp);
1671. 	return foodwords[objects[otmp->otyp].oc_material];
1672. }
1673. 

fpostfx[]

1674. STATIC_OVL void
1675. fpostfx(otmp)		/* called after consuming (non-corpse) food */
1676. register struct obj *otmp;
1677. {
1678. 	switch(otmp->otyp) {
1679. 	    case SPRIG_OF_WOLFSBANE:
1680. 		if (u.ulycn >= LOW_PM || is_were(youmonst.data))
1681. 		    you_unwere(TRUE);
1682. 		break;
1683. 	    case CARROT:
1684. 		make_blinded((long)u.ucreamed,TRUE);
1685. 		break;
1686. 	    case FORTUNE_COOKIE:
1687. 		outrumor(bcsign(otmp), BY_COOKIE);
1688. 		if (!Blind) u.uconduct.literate++;
1689. 		break;
1690. 	    case LUMP_OF_ROYAL_JELLY:
1691. 		/* This stuff seems to be VERY healthy! */
1692. 		gainstr(otmp, 1);
1693. 		if (Upolyd) {
1694. 		    u.mh += otmp->cursed ? -rnd(20) : rnd(20);
1695. 		    if (u.mh > u.mhmax) {
1696. 			if (!rn2(17)) u.mhmax++;
1697. 			u.mh = u.mhmax;
1698. 		    } else if (u.mh <= 0) {
1699. 			rehumanize();
1700. 		    }
1701. 		} else {
1702. 		    u.uhp += otmp->cursed ? -rnd(20) : rnd(20);
1703. 		    if (u.uhp > u.uhpmax) {
1704. 			if(!rn2(17)) u.uhpmax++;
1705. 			u.uhp = u.uhpmax;
1706. 		    } else if (u.uhp <= 0) {
1707. 			killer_format = KILLED_BY_AN;
1708. 			killer = "rotten lump of royal jelly";
1709. 			done(POISONING);
1710. 		    }
1711. 		}
1712. 		if(!otmp->cursed) heal_legs();
1713. 		break;
1714. 	    case EGG:
1715. 		if (touch_petrifies(&mons[otmp->corpsenm])) {
1716. 		    if (!Stone_resistance &&
1717. 			!(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))) {
1718. 			if (!Stoned) Stoned = 5;
1719. 			killer_format = KILLED_BY_AN;
1720. 			Sprintf(killer_buf, "%s egg", mons[otmp->corpsenm].mname);
1721. 			delayed_killer = killer_buf;
1722. 		    }
1723. 		}
1724. 		break;
1725. 	    case EUCALYPTUS_LEAF:
1726. 		if (Sick && !otmp->cursed)
1727. 		    make_sick(0L, (char *)0, TRUE, SICK_ALL);
1728. 		if (Vomiting && !otmp->cursed)
1729. 		    make_vomiting(0L, TRUE);
1730. 		break;
1731. 	}
1732. 	return;
1733. }
1734. 

edibility_prompts[]

1735. /*
1736.  * return 0 if the food was not dangerous.
1737.  * return 1 if the food was dangerous and you chose to stop.
1738.  * return 2 if the food was dangerous and you chose to eat it anyway.
1739.  */
1740. STATIC_OVL int
1741. edibility_prompts(otmp)
1742. struct obj *otmp;
1743. {
1744. 	/* blessed food detection granted you a one-use
1745. 	   ability to detect food that is unfit for consumption
1746. 	   or dangerous and avoid it. */
1747. 
1748. 	char buf[BUFSZ], foodsmell[BUFSZ],
1749. 	     it_or_they[QBUFSZ], eat_it_anyway[QBUFSZ];
1750. 	boolean cadaver = (otmp->otyp == CORPSE),
1751. 		stoneorslime = FALSE;
1752. 	int material = objects[otmp->otyp].oc_material,
1753. 	    mnum = otmp->corpsenm;
1754. 	long rotted = 0L;
1755. 
1756. 	Strcpy(foodsmell, Tobjnam(otmp, "smell"));
1757. 	Strcpy(it_or_they, (otmp->quan == 1L) ? "it" : "they");
1758. 	Sprintf(eat_it_anyway, "Eat %s anyway?",
1759. 		(otmp->quan == 1L) ? "it" : "one");
1760. 
1761. 	if (cadaver || otmp->otyp == EGG || otmp->otyp == TIN) {
1762. 		/* These checks must match those in eatcorpse() */
1763. 		stoneorslime = (touch_petrifies(&mons[mnum]) &&
1764. 				!Stone_resistance &&
1765. 				!poly_when_stoned(youmonst.data));
1766. 
1767. 		if (mnum == PM_GREEN_SLIME)
1768. 		    stoneorslime = (!Unchanging && !flaming(youmonst.data) &&
1769. 			youmonst.data != &mons[PM_GREEN_SLIME]);
1770. 
1771. 		if (cadaver && mnum != PM_LIZARD && mnum != PM_LICHEN) {
1772. 			long age = peek_at_iced_corpse_age(otmp);
1773. 			/* worst case rather than random
1774. 			   in this calculation to force prompt */
1775. 			rotted = (monstermoves - age)/(10L + 0 /* was rn2(20) */);
1776. 			if (otmp->cursed) rotted += 2L;
1777. 			else if (otmp->blessed) rotted -= 2L;
1778. 		}
1779. 	}
1780. 
1781. 	/*
1782. 	 * These problems with food should be checked in
1783. 	 * order from most detrimental to least detrimental.
1784. 	 */
1785. 
1786. 	if (cadaver && mnum != PM_ACID_BLOB && rotted > 5L && !Sick_resistance) {
1787. 		/* Tainted meat */
1788. 		Sprintf(buf, "%s like %s could be tainted! %s",
1789. 			foodsmell, it_or_they, eat_it_anyway);
1790. 		if (yn_function(buf,ynchars,'n')=='n') return 1;
1791. 		else return 2;
1792. 	}
1793. 	if (stoneorslime) {
1794. 		Sprintf(buf, "%s like %s could be something very dangerous! %s",
1795. 			foodsmell, it_or_they, eat_it_anyway);
1796. 		if (yn_function(buf,ynchars,'n')=='n') return 1;
1797. 		else return 2;
1798. 	}
1799. 	if (otmp->orotten || (cadaver && rotted > 3L)) {
1800. 		/* Rotten */
1801. 		Sprintf(buf, "%s like %s could be rotten! %s",
1802. 			foodsmell, it_or_they, eat_it_anyway);
1803. 		if (yn_function(buf,ynchars,'n')=='n') return 1;
1804. 		else return 2;
1805. 	}
1806. 	if (cadaver && poisonous(&mons[mnum]) && !Poison_resistance) {
1807. 		/* poisonous */
1808. 		Sprintf(buf, "%s like %s might be poisonous! %s",
1809. 			foodsmell, it_or_they, eat_it_anyway);
1810. 		if (yn_function(buf,ynchars,'n')=='n') return 1;
1811. 		else return 2;
1812. 	}
1813. 	if (cadaver && !vegetarian(&mons[mnum]) &&
1814. 	    !u.uconduct.unvegetarian && Role_if(PM_MONK)) {
1815. 		Sprintf(buf, "%s unhealthy. %s",
1816. 			foodsmell, eat_it_anyway);
1817. 		if (yn_function(buf,ynchars,'n')=='n') return 1;
1818. 		else return 2;
1819. 	}
1820. 	if (cadaver && acidic(&mons[mnum]) && !Acid_resistance) {
1821. 		Sprintf(buf, "%s rather acidic. %s",
1822. 			foodsmell, eat_it_anyway);
1823. 		if (yn_function(buf,ynchars,'n')=='n') return 1;
1824. 		else return 2;
1825. 	}
1826. 	if (Upolyd && u.umonnum == PM_RUST_MONSTER &&
1827. 	    is_metallic(otmp) && otmp->oerodeproof) {
1828. 		Sprintf(buf, "%s disgusting to you right now. %s",
1829. 			foodsmell, eat_it_anyway);
1830. 		if (yn_function(buf,ynchars,'n')=='n') return 1;
1831. 		else return 2;
1832. 	}
1833. 
1834. 	/*
1835. 	 * Breaks conduct, but otherwise safe.
1836. 	 */
1837. 	 
1838. 	if (!u.uconduct.unvegan &&
1839. 	    ((material == LEATHER || material == BONE ||
1840. 	      material == DRAGON_HIDE || material == WAX) ||
1841. 	     (cadaver && !vegan(&mons[mnum])))) {
1842. 		Sprintf(buf, "%s foul and unfamiliar to you. %s",
1843. 			foodsmell, eat_it_anyway);
1844. 		if (yn_function(buf,ynchars,'n')=='n') return 1;
1845. 		else return 2;
1846. 	}
1847. 	if (!u.uconduct.unvegetarian &&
1848. 	    ((material == LEATHER || material == BONE ||
1849. 	      material == DRAGON_HIDE) ||
1850. 	     (cadaver && !vegetarian(&mons[mnum])))) {
1851. 		Sprintf(buf, "%s unfamiliar to you. %s",
1852. 			foodsmell, eat_it_anyway);
1853. 		if (yn_function(buf,ynchars,'n')=='n') return 1;
1854. 		else return 2;
1855. 	}
1856. 
1857. 	if (cadaver && mnum != PM_ACID_BLOB && rotted > 5L && Sick_resistance) {
1858. 		/* Tainted meat with Sick_resistance */
1859. 		Sprintf(buf, "%s like %s could be tainted! %s",
1860. 			foodsmell, it_or_they, eat_it_anyway);
1861. 		if (yn_function(buf,ynchars,'n')=='n') return 1;
1862. 		else return 2;
1863. 	}
1864. 	return 0;
1865. }
1866. 

doeat[]

1867. int
1868. doeat()		/* generic "eat" command funtion (see cmd.c) */
1869. {
1870. 	register struct obj *otmp;
1871. 	int basenutrit;			/* nutrition of full item */
1872. 	boolean dont_start = FALSE;
1873. 	
1874. 	if (Strangled) {
1875. 		pline("If you can't breathe air, how can you consume solids?");
1876. 		return 0;
1877. 	}
1878. 	if (!(otmp = floorfood("eat", 0))) return 0;
1879. 	if (check_capacity((char *)0)) return 0;
1880. 
1881. 	if (u.uedibility) {
1882. 		int res = edibility_prompts(otmp);
1883. 		if (res) {
1884. 		    Your("%s stops tingling and your sense of smell returns to normal.",
1885. 			body_part(NOSE));
1886. 		    u.uedibility = 0;
1887. 		    if (res == 1) return 0;
1888. 		}
1889. 	}
1890. 
1891. 	/* We have to make non-foods take 1 move to eat, unless we want to
1892. 	 * do ridiculous amounts of coding to deal with partly eaten plate
1893. 	 * mails, players who polymorph back to human in the middle of their
1894. 	 * metallic meal, etc....
1895. 	 */
1896. 	if (!is_edible(otmp)) {
1897. 	    You("cannot eat that!");
1898. 	    return 0;
1899. 	} else if ((otmp->owornmask & (W_ARMOR|W_TOOL|W_AMUL
1900. #ifdef STEED
1901. 			|W_SADDLE
1902. #endif
1903. 			)) != 0) {
1904. 	    /* let them eat rings */
1905. 	    You_cant("eat %s you're wearing.", something);
1906. 	    return 0;
1907. 	}
1908. 	if (is_metallic(otmp) &&
1909. 	    u.umonnum == PM_RUST_MONSTER && otmp->oerodeproof) {
1910. 	    	otmp->rknown = TRUE;
1911. 		if (otmp->quan > 1L) {
1912. 		    if(!carried(otmp))
1913. 			(void) splitobj(otmp, otmp->quan - 1L);
1914. 		    else
1915. 			otmp = splitobj(otmp, 1L);
1916. 		}
1917. 		pline("Ulch - That %s was rustproofed!", xname(otmp));
1918. 		/* The regurgitated object's rustproofing is gone now */
1919. 		otmp->oerodeproof = 0;
1920. 		make_stunned(HStun + rn2(10), TRUE);
1921. 		You("spit %s out onto the %s.", the(xname(otmp)),
1922. 			surface(u.ux, u.uy));
1923. 		if (carried(otmp)) {
1924. 			freeinv(otmp);
1925. 			dropy(otmp);
1926. 		}
1927. 		stackobj(otmp);
1928. 		return 1;
1929. 	}
1930. 	/* KMH -- Slow digestion is... indigestible */
1931. 	if (otmp->otyp == RIN_SLOW_DIGESTION) {
1932. 		pline("This ring is indigestible!");
1933. 		(void) rottenfood(otmp);
1934. 		if (otmp->dknown && !objects[otmp->otyp].oc_name_known
1935. 				&& !objects[otmp->otyp].oc_uname)
1936. 			docall(otmp);
1937. 		return (1);
1938. 	}
1939. 	if (otmp->oclass != FOOD_CLASS) {
1940. 	    int material;
1941. 	    victual.reqtime = 1;
1942. 	    victual.piece = otmp;
1943. 		/* Don't split it, we don't need to if it's 1 move */
1944. 	    victual.usedtime = 0;
1945. 	    victual.canchoke = (u.uhs == SATIATED);
1946. 		/* Note: gold weighs 1 pt. for each 1000 pieces (see */
1947. 		/* pickup.c) so gold and non-gold is consistent. */
1948. 	    if (otmp->oclass == COIN_CLASS)
1949. 		basenutrit = ((otmp->quan > 200000L) ? 2000
1950. 			: (int)(otmp->quan/100L));
1951. 	    else if(otmp->oclass == BALL_CLASS || otmp->oclass == CHAIN_CLASS)
1952. 		basenutrit = weight(otmp);
1953. 	    /* oc_nutrition is usually weight anyway */
1954. 	    else basenutrit = objects[otmp->otyp].oc_nutrition;
1955. 	    victual.nmod = basenutrit;
1956. 	    victual.eating = TRUE; /* needed for lesshungry() */
1957. 
1958. 	    material = objects[otmp->otyp].oc_material;
1959. 	    if (material == LEATHER ||
1960. 		material == BONE || material == DRAGON_HIDE) {
1961. 		u.uconduct.unvegan++;
1962. 		violated_vegetarian();
1963. 	    } else if (material == WAX)
1964. 		u.uconduct.unvegan++;
1965. 	    u.uconduct.food++;
1966. 	    
1967. 	    if (otmp->cursed)
1968. 		(void) rottenfood(otmp);
1969. 
1970. 	    if (otmp->oclass == WEAPON_CLASS && otmp->opoisoned) {
1971. 		pline("Ecch - that must have been poisonous!");
1972. 		if(!Poison_resistance) {
1973. 		    losestr(rnd(4));
1974. 		    losehp(rnd(15), xname(otmp), KILLED_BY_AN);
1975. 		} else
1976. 		    You("seem unaffected by the poison.");
1977. 	    } else if (!otmp->cursed)
1978. 		pline("This %s is delicious!",
1979. 		      otmp->oclass == COIN_CLASS ? foodword(otmp) :
1980. 		      singular(otmp, xname));
1981. 
1982. 	    eatspecial();
1983. 	    return 1;
1984. 	}
1985. 
1986. 	if(otmp == victual.piece) {
1987. 	/* If they weren't able to choke, they don't suddenly become able to
1988. 	 * choke just because they were interrupted.  On the other hand, if
1989. 	 * they were able to choke before, if they lost food it's possible
1990. 	 * they shouldn't be able to choke now.
1991. 	 */
1992. 	    if (u.uhs != SATIATED) victual.canchoke = FALSE;
1993. 	    victual.piece = touchfood(otmp);
1994. 	    You("resume your meal.");
1995. 	    start_eating(victual.piece);
1996. 	    return(1);
1997. 	}
1998. 
1999. 	/* nothing in progress - so try to find something. */
2000. 	/* tins are a special case */
2001. 	/* tins must also check conduct separately in case they're discarded */
2002. 	if(otmp->otyp == TIN) {
2003. 	    start_tin(otmp);
2004. 	    return(1);
2005. 	}
2006. 
2007. 	/* KMH, conduct */
2008. 	u.uconduct.food++;
2009. 
2010. 	victual.piece = otmp = touchfood(otmp);
2011. 	victual.usedtime = 0;
2012. 
2013. 	/* Now we need to calculate delay and nutritional info.
2014. 	 * The base nutrition calculated here and in eatcorpse() accounts
2015. 	 * for normal vs. rotten food.  The reqtime and nutrit values are
2016. 	 * then adjusted in accordance with the amount of food left.
2017. 	 */
2018. 	if(otmp->otyp == CORPSE) {
2019. 	    int tmp = eatcorpse(otmp);
2020. 	    if (tmp == 2) {
2021. 		/* used up */
2022. 		victual.piece = (struct obj *)0;
2023. 		return(1);
2024. 	    } else if (tmp)
2025. 		dont_start = TRUE;
2026. 	    /* if not used up, eatcorpse sets up reqtime and may modify
2027. 	     * oeaten */
2028. 	} else {
2029. 	    /* No checks for WAX, LEATHER, BONE, DRAGON_HIDE.  These are
2030. 	     * all handled in the != FOOD_CLASS case, above */
2031. 	    switch (objects[otmp->otyp].oc_material) {
2032. 	    case FLESH:
2033. 		u.uconduct.unvegan++;
2034. 		if (otmp->otyp != EGG) {
2035. 		    violated_vegetarian();
2036. 		}
2037. 		break;
2038. 
2039. 	    default:
2040. 		if (otmp->otyp == PANCAKE ||
2041. 		    otmp->otyp == FORTUNE_COOKIE || /* eggs */
2042. 		    otmp->otyp == CREAM_PIE ||
2043. 		    otmp->otyp == CANDY_BAR || /* milk */
2044. 		    otmp->otyp == LUMP_OF_ROYAL_JELLY)
2045. 		    u.uconduct.unvegan++;
2046. 		break;
2047. 	    }
2048. 
2049. 	    victual.reqtime = objects[otmp->otyp].oc_delay;
2050. 	    if (otmp->otyp != FORTUNE_COOKIE &&
2051. 		(otmp->cursed ||
2052. 		 (((monstermoves - otmp->age) > (int) otmp->blessed ? 50:30) &&
2053. 		(otmp->orotten || !rn2(7))))) {
2054. 
2055. 		if (rottenfood(otmp)) {
2056. 		    otmp->orotten = TRUE;
2057. 		    dont_start = TRUE;
2058. 		}
2059. 		consume_oeaten(otmp, 1);	/* oeaten >>= 1 */
2060. 	    } else fprefx(otmp);
2061. 	}
2062. 
2063. 	/* re-calc the nutrition */
2064. 	if (otmp->otyp == CORPSE) basenutrit = mons[otmp->corpsenm].cnutrit;
2065. 	else basenutrit = objects[otmp->otyp].oc_nutrition;
2066. 
2067. #ifdef DEBUG
2068. 	debugpline("before rounddiv: victual.reqtime == %d", victual.reqtime);
2069. 	debugpline("oeaten == %d, basenutrit == %d", otmp->oeaten, basenutrit);
2070. #endif
2071. 	victual.reqtime = (basenutrit == 0 ? 0 :
2072. 		rounddiv(victual.reqtime * (long)otmp->oeaten, basenutrit));
2073. #ifdef DEBUG
2074. 	debugpline("after rounddiv: victual.reqtime == %d", victual.reqtime);
2075. #endif
2076. 	/* calculate the modulo value (nutrit. units per round eating)
2077. 	 * note: this isn't exact - you actually lose a little nutrition
2078. 	 *	 due to this method.
2079. 	 * TODO: add in a "remainder" value to be given at the end of the
2080. 	 *	 meal.
2081. 	 */
2082. 	if (victual.reqtime == 0 || otmp->oeaten == 0)
2083. 	    /* possible if most has been eaten before */
2084. 	    victual.nmod = 0;
2085. 	else if ((int)otmp->oeaten >= victual.reqtime)
2086. 	    victual.nmod = -((int)otmp->oeaten / victual.reqtime);
2087. 	else
2088. 	    victual.nmod = victual.reqtime % otmp->oeaten;
2089. 	victual.canchoke = (u.uhs == SATIATED);
2090. 
2091. 	if (!dont_start) start_eating(otmp);
2092. 	return(1);
2093. }
2094. 

bite[]

2095. /* Take a single bite from a piece of food, checking for choking and
2096.  * modifying usedtime.  Returns 1 if they choked and survived, 0 otherwise.
2097.  */
2098. STATIC_OVL int
2099. bite()
2100. {
2101. 	if(victual.canchoke && u.uhunger >= 2000) {
2102. 		choke(victual.piece);
2103. 		return 1;
2104. 	}
2105. 	if (victual.doreset) {
2106. 		do_reset_eat();
2107. 		return 0;
2108. 	}
2109. 	force_save_hs = TRUE;
2110. 	if(victual.nmod < 0) {
2111. 		lesshungry(-victual.nmod);
2112. 		consume_oeaten(victual.piece, victual.nmod); /* -= -nmod */
2113. 	} else if(victual.nmod > 0 && (victual.usedtime % victual.nmod)) {
2114. 		lesshungry(1);
2115. 		consume_oeaten(victual.piece, -1);		  /* -= 1 */
2116. 	}
2117. 	force_save_hs = FALSE;
2118. 	recalc_wt();
2119. 	return 0;
2120. }
2121. 
2122. #endif /* OVLB */

gethungry[]

2123. #ifdef OVL0
2124. 
2125. void
2126. gethungry()	/* as time goes by - called by moveloop() and domove() */
2127. {
2128. 	if (u.uinvulnerable) return;	/* you don't feel hungrier */
2129. 
2130. 	if ((!u.usleep || !rn2(10))	/* slow metabolic rate while asleep */
2131. 		&& (carnivorous(youmonst.data) || herbivorous(youmonst.data))
2132. 		&& !Slow_digestion)
2133. 	    u.uhunger--;		/* ordinary food consumption */
2134. 
2135. 	if (moves % 2) {	/* odd turns */
2136. 	    /* Regeneration uses up food, unless due to an artifact */
2137. 	    if (HRegeneration || ((ERegeneration & (~W_ART)) &&
2138. 				(ERegeneration != W_WEP || !uwep->oartifact)))
2139. 			u.uhunger--;
2140. 	    if (near_capacity() > SLT_ENCUMBER) u.uhunger--;
2141. 	} else {		/* even turns */
2142. 	    if (Hunger) u.uhunger--;
2143. 	    /* Conflict uses up food too */
2144. 	    if (HConflict || (EConflict & (~W_ARTI))) u.uhunger--;
2145. 	    /* +0 charged rings don't do anything, so don't affect hunger */
2146. 	    /* Slow digestion still uses ring hunger */
2147. 	    switch ((int)(moves % 20)) {	/* note: use even cases only */
2148. 	     case  4: if (uleft &&
2149. 			  (uleft->spe || !objects[uleft->otyp].oc_charged))
2150. 			    u.uhunger--;
2151. 		    break;
2152. 	     case  8: if (uamul) u.uhunger--;
2153. 		    break;
2154. 	     case 12: if (uright &&
2155. 			  (uright->spe || !objects[uright->otyp].oc_charged))
2156. 			    u.uhunger--;
2157. 		    break;
2158. 	     case 16: if (u.uhave.amulet) u.uhunger--;
2159. 		    break;
2160. 	     default: break;
2161. 	    }
2162. 	}
2163. 	newuhs(TRUE);
2164. }
2165. 
2166. #endif /* OVL0 */

morehungry[]

2167. #ifdef OVLB
2168. 
2169. void
2170. morehungry(num)	/* called after vomiting and after performing feats of magic */
2171. register int num;
2172. {
2173. 	u.uhunger -= num;
2174. 	newuhs(TRUE);
2175. }
2176. 
2177. 

lesshungry[]

2178. void
2179. lesshungry(num)	/* called after eating (and after drinking fruit juice) */
2180. register int num;
2181. {
2182. 	/* See comments in newuhs() for discussion on force_save_hs */
2183. 	boolean iseating = (occupation == eatfood) || force_save_hs;
2184. #ifdef DEBUG
2185. 	debugpline("lesshungry(%d)", num);
2186. #endif
2187. 	u.uhunger += num;
2188. 	if(u.uhunger >= 2000) {
2189. 	    if (!iseating || victual.canchoke) {
2190. 		if (iseating) {
2191. 		    choke(victual.piece);
2192. 		    reset_eat();
2193. 		} else
2194. 		    choke(occupation == opentin ? tin.tin : (struct obj *)0);
2195. 		/* no reset_eat() */
2196. 	    }
2197. 	} else {
2198. 	    /* Have lesshungry() report when you're nearly full so all eating
2199. 	     * warns when you're about to choke.
2200. 	     */
2201. 	    if (u.uhunger >= 1500) {
2202. 		if (!victual.eating || (victual.eating && !victual.fullwarn)) {
2203. 		    pline("You're having a hard time getting all of it down.");
2204. 		    nomovemsg = "You're finally finished.";
2205. 		    if (!victual.eating)
2206. 			multi = -2;
2207. 		    else {
2208. 			victual.fullwarn = TRUE;
2209. 			if (victual.canchoke && victual.reqtime > 1) {
2210. 			    /* a one-gulp food will not survive a stop */
2211. 			    if (yn_function("Stop eating?",ynchars,'y')=='y') {
2212. 				reset_eat();
2213. 				nomovemsg = (char *)0;
2214. 			    }
2215. 			}
2216. 		    }
2217. 		}
2218. 	    }
2219. 	}
2220. 	newuhs(FALSE);
2221. }
2222. 

unfaint[]

2223. STATIC_PTR
2224. int
2225. unfaint()
2226. {
2227. 	(void) Hear_again();
2228. 	if(u.uhs > FAINTING)
2229. 		u.uhs = FAINTING;
2230. 	stop_occupation();
2231. 	flags.botl = 1;
2232. 	return 0;
2233. }
2234. 
2235. #endif /* OVLB */

is_fainted[]

2236. #ifdef OVL0
2237. 
2238. boolean
2239. is_fainted()
2240. {
2241. 	return((boolean)(u.uhs == FAINTED));
2242. }
2243. 

reset_faint[]

2244. void
2245. reset_faint()	/* call when a faint must be prematurely terminated */
2246. {
2247. 	if(is_fainted()) nomul(0);
2248. }
2249. 

sync_hunger[]

2250. #if 0
2251. void
2252. sync_hunger()
2253. {
2254. 
2255. 	if(is_fainted()) {
2256. 
2257. 		flags.soundok = 0;
2258. 		nomul(-10+(u.uhunger/10));
2259. 		nomovemsg = "You regain consciousness.";
2260. 		afternmv = unfaint;
2261. 	}
2262. }
2263. #endif
2264. 

newuhs[]

2265. void
2266. newuhs(incr)		/* compute and comment on your (new?) hunger status */
2267. boolean incr;
2268. {
2269. 	unsigned newhs;
2270. 	static unsigned save_hs;
2271. 	static boolean saved_hs = FALSE;
2272. 	int h = u.uhunger;
2273. 
2274. 	newhs = (h > 1000) ? SATIATED :
2275. 		(h > 150) ? NOT_HUNGRY :
2276. 		(h > 50) ? HUNGRY :
2277. 		(h > 0) ? WEAK : FAINTING;
2278. 
2279. 	/* While you're eating, you may pass from WEAK to HUNGRY to NOT_HUNGRY.
2280. 	 * This should not produce the message "you only feel hungry now";
2281. 	 * that message should only appear if HUNGRY is an endpoint.  Therefore
2282. 	 * we check to see if we're in the middle of eating.  If so, we save
2283. 	 * the first hunger status, and at the end of eating we decide what
2284. 	 * message to print based on the _entire_ meal, not on each little bit.
2285. 	 */
2286. 	/* It is normally possible to check if you are in the middle of a meal
2287. 	 * by checking occupation == eatfood, but there is one special case:
2288. 	 * start_eating() can call bite() for your first bite before it
2289. 	 * sets the occupation.
2290. 	 * Anyone who wants to get that case to work _without_ an ugly static
2291. 	 * force_save_hs variable, feel free.
2292. 	 */
2293. 	/* Note: If you become a certain hunger status in the middle of the
2294. 	 * meal, and still have that same status at the end of the meal,
2295. 	 * this will incorrectly print the associated message at the end of
2296. 	 * the meal instead of the middle.  Such a case is currently
2297. 	 * impossible, but could become possible if a message for SATIATED
2298. 	 * were added or if HUNGRY and WEAK were separated by a big enough
2299. 	 * gap to fit two bites.
2300. 	 */
2301. 	if (occupation == eatfood || force_save_hs) {
2302. 		if (!saved_hs) {
2303. 			save_hs = u.uhs;
2304. 			saved_hs = TRUE;
2305. 		}
2306. 		u.uhs = newhs;
2307. 		return;
2308. 	} else {
2309. 		if (saved_hs) {
2310. 			u.uhs = save_hs;
2311. 			saved_hs = FALSE;
2312. 		}
2313. 	}
2314. 
2315. 	if(newhs == FAINTING) {
2316. 		if(is_fainted()) newhs = FAINTED;
2317. 		if(u.uhs <= WEAK || rn2(20-u.uhunger/10) >= 19) {
2318. 			if(!is_fainted() && multi >= 0 /* %% */) {
2319. 				/* stop what you're doing, then faint */
2320. 				stop_occupation();
2321. 				You("faint from lack of food.");
2322. 				flags.soundok = 0;
2323. 				nomul(-10+(u.uhunger/10));
2324. 				nomovemsg = "You regain consciousness.";
2325. 				afternmv = unfaint;
2326. 				newhs = FAINTED;
2327. 			}
2328. 		} else
2329. 		if(u.uhunger < -(int)(200 + 20*ACURR(A_CON))) {
2330. 			u.uhs = STARVED;
2331. 			flags.botl = 1;
2332. 			bot();
2333. 			You("die from starvation.");
2334. 			killer_format = KILLED_BY;
2335. 			killer = "starvation";
2336. 			done(STARVING);
2337. 			/* if we return, we lifesaved, and that calls newuhs */
2338. 			return;
2339. 		}
2340. 	}
2341. 
2342. 	if(newhs != u.uhs) {
2343. 		if(newhs >= WEAK && u.uhs < WEAK)
2344. 			losestr(1);	/* this may kill you -- see below */
2345. 		else if(newhs < WEAK && u.uhs >= WEAK)
2346. 			losestr(-1);
2347. 		switch(newhs){
2348. 		case HUNGRY:
2349. 			if (Hallucination) {
2350. 			    You((!incr) ?
2351. 				"now have a lesser case of the munchies." :
2352. 				"are getting the munchies.");
2353. 			} else
2354. 			    You((!incr) ? "only feel hungry now." :
2355. 				  (u.uhunger < 145) ? "feel hungry." :
2356. 				   "are beginning to feel hungry.");
2357. 			if (incr && occupation &&
2358. 			    (occupation != eatfood && occupation != opentin))
2359. 			    stop_occupation();
2360. 			break;
2361. 		case WEAK:
2362. 			if (Hallucination)
2363. 			    pline((!incr) ?
2364. 				  "You still have the munchies." :
2365.       "The munchies are interfering with your motor capabilities.");
2366. 			else if (incr &&
2367. 				(Role_if(PM_WIZARD) || Race_if(PM_ELF) ||
2368. 				 Role_if(PM_VALKYRIE)))
2369. 			    pline("%s needs food, badly!",
2370. 				  (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ?
2371. 				  urole.name.m : "Elf");
2372. 			else
2373. 			    You((!incr) ? "feel weak now." :
2374. 				  (u.uhunger < 45) ? "feel weak." :
2375. 				   "are beginning to feel weak.");
2376. 			if (incr && occupation &&
2377. 			    (occupation != eatfood && occupation != opentin))
2378. 			    stop_occupation();
2379. 			break;
2380. 		}
2381. 		u.uhs = newhs;
2382. 		flags.botl = 1;
2383. 		bot();
2384. 		if ((Upolyd ? u.mh : u.uhp) < 1) {
2385. 			You("die from hunger and exhaustion.");
2386. 			killer_format = KILLED_BY;
2387. 			killer = "exhaustion";
2388. 			done(STARVING);
2389. 			return;
2390. 		}
2391. 	}
2392. }
2393. 
2394. #endif /* OVL0 */

floorfood[]

2395. #ifdef OVLB
2396. 
2397. /* Returns an object representing food.  Object may be either on floor or
2398.  * in inventory.
2399.  */
2400. struct obj *
2401. floorfood(verb,corpsecheck)	/* get food from floor or pack */
2402. 	const char *verb;
2403. 	int corpsecheck; /* 0, no check, 1, corpses, 2, tinnable corpses */
2404. {
2405. 	register struct obj *otmp;
2406. 	char qbuf[QBUFSZ];
2407. 	char c;
2408. 	boolean feeding = (!strcmp(verb, "eat"));
2409. 
2410. 	/* if we can't touch floor objects then use invent food only */
2411. 	if (!can_reach_floor() ||
2412. #ifdef STEED
2413. 		(feeding && u.usteed) || /* can't eat off floor while riding */
2414. #endif
2415. 		((is_pool(u.ux, u.uy) || is_lava(u.ux, u.uy)) &&
2416. 		    (Wwalking || is_clinger(youmonst.data) ||
2417. 			(Flying && !Breathless))))
2418. 	    goto skipfloor;
2419. 
2420. 	if (feeding && metallivorous(youmonst.data)) {
2421. 	    struct obj *gold;
2422. 	    struct trap *ttmp = t_at(u.ux, u.uy);
2423. 
2424. 	    if (ttmp && ttmp->tseen && ttmp->ttyp == BEAR_TRAP) {
2425. 		/* If not already stuck in the trap, perhaps there should
2426. 		   be a chance to becoming trapped?  Probably not, because
2427. 		   then the trap would just get eaten on the _next_ turn... */
2428. 		Sprintf(qbuf, "There is a bear trap here (%s); eat it?",
2429. 			(u.utrap && u.utraptype == TT_BEARTRAP) ?
2430. 				"holding you" : "armed");
2431. 		if ((c = yn_function(qbuf, ynqchars, 'n')) == 'y') {
2432. 		    u.utrap = u.utraptype = 0;
2433. 		    deltrap(ttmp);
2434. 		    return mksobj(BEARTRAP, TRUE, FALSE);
2435. 		} else if (c == 'q') {
2436. 		    return (struct obj *)0;
2437. 		}
2438. 	    }
2439. 
2440. 	    if (youmonst.data != &mons[PM_RUST_MONSTER] &&
2441. 		(gold = g_at(u.ux, u.uy)) != 0) {
2442. 		if (gold->quan == 1L)
2443. 		    Sprintf(qbuf, "There is 1 gold piece here; eat it?");
2444. 		else
2445. 		    Sprintf(qbuf, "There are %ld gold pieces here; eat them?",
2446. 			    gold->quan);
2447. 		if ((c = yn_function(qbuf, ynqchars, 'n')) == 'y') {
2448. 		    return gold;
2449. 		} else if (c == 'q') {
2450. 		    return (struct obj *)0;
2451. 		}
2452. 	    }
2453. 	}
2454. 
2455. 	/* Is there some food (probably a heavy corpse) here on the ground? */
2456. 	for (otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp->nexthere) {
2457. 		if(corpsecheck ?
2458. 		(otmp->otyp==CORPSE && (corpsecheck == 1 || tinnable(otmp))) :
2459. 		    feeding ? (otmp->oclass != COIN_CLASS && is_edible(otmp)) :
2460. 						otmp->oclass==FOOD_CLASS) {
2461. 			Sprintf(qbuf, "There %s %s here; %s %s?",
2462. 				otense(otmp, "are"),
2463. 				doname(otmp), verb,
2464. 				(otmp->quan == 1L) ? "it" : "one");
2465. 			if((c = yn_function(qbuf,ynqchars,'n')) == 'y')
2466. 				return(otmp);
2467. 			else if(c == 'q')
2468. 				return((struct obj *) 0);
2469. 		}
2470. 	}
2471. 
2472.  skipfloor:
2473. 	/* We cannot use ALL_CLASSES since that causes getobj() to skip its
2474. 	 * "ugly checks" and we need to check for inedible items.
2475. 	 */
2476. 	otmp = getobj(feeding ? (const char *)allobj :
2477. 				(const char *)comestibles, verb);
2478. 	if (corpsecheck && otmp)
2479. 	    if (otmp->otyp != CORPSE || (corpsecheck == 2 && !tinnable(otmp))) {
2480. 		You_cant("%s that!", verb);
2481. 		return (struct obj *)0;
2482. 	    }
2483. 	return otmp;
2484. }
2485. 

vomit[]

2486. /* Side effects of vomiting */
2487. /* added nomul (MRS) - it makes sense, you're too busy being sick! */
2488. void
2489. vomit()		/* A good idea from David Neves */
2490. {
2491. 	make_sick(0L, (char *) 0, TRUE, SICK_VOMITABLE);
2492. 	nomul(-2);
2493. }
2494. 

eaten_stat[]

2495. int
2496. eaten_stat(base, obj)
2497. register int base;
2498. register struct obj *obj;
2499. {
2500. 	long uneaten_amt, full_amount;
2501. 
2502. 	uneaten_amt = (long)obj->oeaten;
2503. 	full_amount = (obj->otyp == CORPSE) ? (long)mons[obj->corpsenm].cnutrit
2504. 					: (long)objects[obj->otyp].oc_nutrition;
2505. 	if (uneaten_amt > full_amount) {
2506. 	    impossible(
2507. 	  "partly eaten food (%ld) more nutritious than untouched food (%ld)",
2508. 		       uneaten_amt, full_amount);
2509. 	    uneaten_amt = full_amount;
2510. 	}
2511. 
2512. 	base = (int)(full_amount ? (long)base * uneaten_amt / full_amount : 0L);
2513. 	return (base < 1) ? 1 : base;
2514. }
2515. 

consume_oeaten[]

2516. /* reduce obj's oeaten field, making sure it never hits or passes 0 */
2517. void
2518. consume_oeaten(obj, amt)
2519. struct obj *obj;
2520. int amt;
2521. {
2522.     /*
2523.      * This is a hack to try to squelch several long standing mystery
2524.      * food bugs.  A better solution would be to rewrite the entire
2525.      * victual handling mechanism from scratch using a less complex
2526.      * model.  Alternatively, this routine could call done_eating()
2527.      * or food_disappears() but its callers would need revisions to
2528.      * cope with victual.piece unexpectedly going away.
2529.      *
2530.      * Multi-turn eating operates by setting the food's oeaten field
2531.      * to its full nutritional value and then running a counter which
2532.      * independently keeps track of whether there is any food left.
2533.      * The oeaten field can reach exactly zero on the last turn, and
2534.      * the object isn't removed from inventory until the next turn
2535.      * when the "you finish eating" message gets delivered, so the
2536.      * food would be restored to the status of untouched during that
2537.      * interval.  This resulted in unexpected encumbrance messages
2538.      * at the end of a meal (if near enough to a threshold) and would
2539.      * yield full food if there was an interruption on the critical
2540.      * turn.  Also, there have been reports over the years of food
2541.      * becoming massively heavy or producing unlimited satiation;
2542.      * this would occur if reducing oeaten via subtraction attempted
2543.      * to drop it below 0 since its unsigned type would produce a
2544.      * huge positive value instead.  So far, no one has figured out
2545.      * _why_ that inappropriate subtraction might sometimes happen.
2546.      */
2547. 
2548.     if (amt > 0) {
2549. 	/* bit shift to divide the remaining amount of food */
2550. 	obj->oeaten >>= amt;
2551.     } else {
2552. 	/* simple decrement; value is negative so we actually add it */
2553. 	if ((int) obj->oeaten > -amt)
2554. 	    obj->oeaten += amt;
2555. 	else
2556. 	    obj->oeaten = 0;
2557.     }
2558. 
2559.     if (obj->oeaten == 0) {
2560. 	if (obj == victual.piece)	/* always true unless wishing... */
2561. 	    victual.reqtime = victual.usedtime;	/* no bites left */
2562. 	obj->oeaten = 1;	/* smallest possible positive value */
2563.     }
2564. }
2565. 
2566. #endif /* OVLB */

maybe_finished_meal[]

2567. #ifdef OVL1
2568. 
2569. /* called when eatfood occupation has been interrupted,
2570.    or in the case of theft, is about to be interrupted */
2571. boolean
2572. maybe_finished_meal(stopping)
2573. boolean stopping;
2574. {
2575. 	/* in case consume_oeaten() has decided that the food is all gone */
2576. 	if (occupation == eatfood && victual.usedtime >= victual.reqtime) {
2577. 	    if (stopping) occupation = 0;	/* for do_reset_eat */
2578. 	    (void) eatfood(); /* calls done_eating() to use up victual.piece */
2579. 	    return TRUE;
2580. 	}
2581. 	return FALSE;
2582. }
2583. 
2584. #endif /* OVL1 */
2585. 
2586. /*eat.c*/
Advertisement