Fandom

Wikihack

Source:Eat.c

2,034pages on
this wiki
Add New Page
Talk0

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.

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 Edit

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 Edit

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 Edit

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

More definitions Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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

rottenfood Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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

reset_faint Edit

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

sync_hunger Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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 Edit

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*/

Also on Fandom

Random Wiki