Source:NetHack 3.6.1/src/eat.c
(Redirected from Eat.c)
Jump to navigation
Jump to search
Below is the full text to eat.c from the source code of NetHack 3.6.1. To link to a particular line, write [[Source:NetHack 3.6.1/src/eat.c#line123]], for example.
Contents
- 1 Top of file
- 2 is_edible
- 3 init_uhunger
- 4 eatmdone
- 5 eatmupdate
- 6 food_xname
- 7 choke
- 8 recalc_wt
- 9 reset_eat
- 10 obj_nutrition
- 11 touchfood
- 12 food_disappears
- 13 food_substitution
- 14 do_reset_eat
- 15 eatfood
- 16 done_eating
- 17 eating_conducts
- 18 eat_brains
- 19 maybe_cannibal
- 20 cprefx
- 21 fix_petrification
- 22 intrinsic_possible
- 23 givit
- 24 cpostfx
- 25 violated_vegetarian
- 26 costly_tin
- 27 tin_variety_txt
- 28 tin_details
- 29 set_tin_variety
- 30 tin_variety
- 31 consume_tin
- 32 opentin
- 33 start_tin
- 34 Hear_again
- 35 rottenfood
- 36 eatcorpse
- 37 start_eating
- 38 fprefx
- 39 bounded_increase
- 40 accessory_has_effect
- 41 eataccessory
- 42 eatspecial
- 43 foodword
- 44 fpostfx
- 45 leather_cover
- 46 edibility_prompts
- 47 doeat
- 48 use_tin_opener
- 49 bite
- 50 gethungry
- 51 morehungry
- 52 lesshungry
- 53 unfaint
- 54 is_fainted
- 55 reset_faint
- 56 newuhs
- 57 floorfood
- 58 vomit
- 59 eaten_stat
- 60 consume_oeaten
- 61 maybe_finished_meal
- 62 Popeye
Top of file
1. /* NetHack 3.6 eat.c $NHDT-Date: 1502754159 2017/08/14 23:42:39 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.179 $ */ 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /*-Copyright (c) Robert Patrick Rankin, 2012. */ 4. /* NetHack may be freely redistributed. See license for details. */
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.
5. 6. #include "hack.h" 7. 8. STATIC_PTR int NDECL(eatmdone); 9. STATIC_PTR int NDECL(eatfood); 10. STATIC_PTR struct obj *FDECL(costly_tin, (int)); 11. STATIC_PTR int NDECL(opentin); 12. STATIC_PTR int NDECL(unfaint); 13. 14. STATIC_DCL const char *FDECL(food_xname, (struct obj *, BOOLEAN_P)); 15. STATIC_DCL void FDECL(choke, (struct obj *)); 16. STATIC_DCL void NDECL(recalc_wt); 17. STATIC_DCL unsigned FDECL(obj_nutrition, (struct obj *)); 18. STATIC_DCL struct obj *FDECL(touchfood, (struct obj *)); 19. STATIC_DCL void NDECL(do_reset_eat); 20. STATIC_DCL void FDECL(done_eating, (BOOLEAN_P)); 21. STATIC_DCL void FDECL(cprefx, (int)); 22. STATIC_DCL int FDECL(intrinsic_possible, (int, struct permonst *)); 23. STATIC_DCL void FDECL(givit, (int, struct permonst *)); 24. STATIC_DCL void FDECL(cpostfx, (int)); 25. STATIC_DCL void FDECL(consume_tin, (const char *)); 26. STATIC_DCL void FDECL(start_tin, (struct obj *)); 27. STATIC_DCL int FDECL(eatcorpse, (struct obj *)); 28. STATIC_DCL void FDECL(start_eating, (struct obj *)); 29. STATIC_DCL void FDECL(fprefx, (struct obj *)); 30. STATIC_DCL void FDECL(fpostfx, (struct obj *)); 31. STATIC_DCL int NDECL(bite); 32. STATIC_DCL int FDECL(edibility_prompts, (struct obj *)); 33. STATIC_DCL int FDECL(rottenfood, (struct obj *)); 34. STATIC_DCL void NDECL(eatspecial); 35. STATIC_DCL int FDECL(bounded_increase, (int, int, int)); 36. STATIC_DCL void FDECL(accessory_has_effect, (struct obj *)); 37. STATIC_DCL void FDECL(eataccessory, (struct obj *)); 38. STATIC_DCL const char *FDECL(foodword, (struct obj *)); 39. STATIC_DCL int FDECL(tin_variety, (struct obj *, BOOLEAN_P)); 40. STATIC_DCL boolean FDECL(maybe_cannibal, (int, BOOLEAN_P)); 41. 42. char msgbuf[BUFSZ]; 43. 44. /* also used to see if you're allowed to eat cats and dogs */ 45. #define CANNIBAL_ALLOWED() (Role_if(PM_CAVEMAN) || Race_if(PM_ORC)) 46. 47. /* monster types that cause hero to be turned into stone if eaten */ 48. #define flesh_petrifies(pm) (touch_petrifies(pm) || (pm) == &mons[PM_MEDUSA]) 49. 50. /* Rider corpses are treated as non-rotting so that attempting to eat one 51. will be sure to reach the stage of eating where that meal is fatal */ 52. #define nonrotting_corpse(mnum) \ 53. ((mnum) == PM_LIZARD || (mnum) == PM_LICHEN || is_rider(&mons[mnum])) 54. 55. /* non-rotting non-corpses; unlike lizard corpses, these items will behave 56. as if rotten if they are cursed (fortune cookies handled elsewhere) */ 57. #define nonrotting_food(otyp) \ 58. ((otyp) == LEMBAS_WAFER || (otyp) == CRAM_RATION) 59. 60. STATIC_OVL NEARDATA const char comestibles[] = { FOOD_CLASS, 0 }; 61. STATIC_OVL NEARDATA const char offerfodder[] = { FOOD_CLASS, AMULET_CLASS, 62. 0 }; 63. 64. /* Gold must come first for getobj(). */ 65. STATIC_OVL NEARDATA const char allobj[] = { 66. COIN_CLASS, WEAPON_CLASS, ARMOR_CLASS, POTION_CLASS, 67. SCROLL_CLASS, WAND_CLASS, RING_CLASS, AMULET_CLASS, 68. FOOD_CLASS, TOOL_CLASS, GEM_CLASS, ROCK_CLASS, 69. BALL_CLASS, CHAIN_CLASS, SPBOOK_CLASS, 0 70. }; 71. 72. STATIC_OVL boolean force_save_hs = FALSE; 73. 74. /* see hunger states in hack.h - texts used on bottom line */ 75. const char *hu_stat[] = { "Satiated", " ", "Hungry ", "Weak ", 76. "Fainting", "Fainted ", "Starved " }; 77.
is_edible
78. /* 79. * Decide whether a particular object can be eaten by the possibly 80. * polymorphed character. Not used for monster checks. 81. */ 82. boolean 83. is_edible(obj) 84. register struct obj *obj; 85. { 86. /* protect invocation tools but not Rider corpses (handled elsewhere)*/ 87. /* if (obj->oclass != FOOD_CLASS && obj_resists(obj, 0, 0)) */ 88. if (objects[obj->otyp].oc_unique) 89. return FALSE; 90. /* above also prevents the Amulet from being eaten, so we must never 91. allow fake amulets to be eaten either [which is already the case] */ 92. 93. if (metallivorous(youmonst.data) && is_metallic(obj) 94. && (youmonst.data != &mons[PM_RUST_MONSTER] || is_rustprone(obj))) 95. return TRUE; 96. 97. /* Ghouls only eat non-veggy corpses or eggs (see dogfood()) */ 98. if (u.umonnum == PM_GHOUL) 99. return (boolean)((obj->otyp == CORPSE 100. && !vegan(&mons[obj->corpsenm])) 101. || (obj->otyp == EGG)); 102. 103. if (u.umonnum == PM_GELATINOUS_CUBE && is_organic(obj) 104. /* [g.cubes can eat containers and retain all contents 105. as engulfed items, but poly'd player can't do that] */ 106. && !Has_contents(obj)) 107. return TRUE; 108. 109. /* return (boolean) !!index(comestibles, obj->oclass); */ 110. return (boolean) (obj->oclass == FOOD_CLASS); 111. } 112.
init_uhunger
113. void 114. init_uhunger() 115. { 116. context.botl = (u.uhs != NOT_HUNGRY || ATEMP(A_STR) < 0); 117. u.uhunger = 900; 118. u.uhs = NOT_HUNGRY; 119. if (ATEMP(A_STR) < 0) 120. ATEMP(A_STR) = 0; 121. } 122. 123. /* tin types [SPINACH_TIN = -1, overrides corpsenm, nut==600] */ 124. static const struct { 125. const char *txt; /* description */ 126. int nut; /* nutrition */ 127. Bitfield(fodder, 1); /* stocked by health food shops */ 128. Bitfield(greasy, 1); /* causes slippery fingers */ 129. } tintxts[] = { { "rotten", -50, 0, 0 }, /* ROTTEN_TIN = 0 */ 130. { "homemade", 50, 1, 0 }, /* HOMEMADE_TIN = 1 */ 131. { "soup made from", 20, 1, 0 }, 132. { "french fried", 40, 0, 1 }, 133. { "pickled", 40, 1, 0 }, 134. { "boiled", 50, 1, 0 }, 135. { "smoked", 50, 1, 0 }, 136. { "dried", 55, 1, 0 }, 137. { "deep fried", 60, 0, 1 }, 138. { "szechuan", 70, 1, 0 }, 139. { "broiled", 80, 0, 0 }, 140. { "stir fried", 80, 0, 1 }, 141. { "sauteed", 95, 0, 0 }, 142. { "candied", 100, 1, 0 }, 143. { "pureed", 500, 1, 0 }, 144. { "", 0, 0, 0 } }; 145. #define TTSZ SIZE(tintxts) 146. 147. static char *eatmbuf = 0; /* set by cpostfx() */ 148.
eatmdone
149. /* called after mimicing is over */ 150. STATIC_PTR int 151. eatmdone(VOID_ARGS) 152. { 153. /* release `eatmbuf' */ 154. if (eatmbuf) { 155. if (nomovemsg == eatmbuf) 156. nomovemsg = 0; 157. free((genericptr_t) eatmbuf), eatmbuf = 0; 158. } 159. /* update display */ 160. if (youmonst.m_ap_type) { 161. youmonst.m_ap_type = M_AP_NOTHING; 162. newsym(u.ux, u.uy); 163. } 164. return 0; 165. } 166.
eatmupdate
167. /* called when hallucination is toggled */ 168. void 169. eatmupdate() 170. { 171. const char *altmsg = 0; 172. int altapp = 0; /* lint suppression */ 173. 174. if (!eatmbuf || nomovemsg != eatmbuf) 175. return; 176. 177. if (is_obj_mappear(&youmonst,ORANGE) && !Hallucination) { 178. /* revert from hallucinatory to "normal" mimicking */ 179. altmsg = "You now prefer mimicking yourself."; 180. altapp = GOLD_PIECE; 181. } else if (is_obj_mappear(&youmonst,GOLD_PIECE) && Hallucination) { 182. /* won't happen; anything which might make immobilized 183. hero begin hallucinating (black light attack, theft 184. of Grayswandir) will terminate the mimicry first */ 185. altmsg = "Your rind escaped intact."; 186. altapp = ORANGE; 187. } 188. 189. if (altmsg) { 190. /* replace end-of-mimicking message */ 191. if (strlen(altmsg) > strlen(eatmbuf)) { 192. free((genericptr_t) eatmbuf); 193. eatmbuf = (char *) alloc(strlen(altmsg) + 1); 194. } 195. nomovemsg = strcpy(eatmbuf, altmsg); 196. /* update current image */ 197. youmonst.mappearance = altapp; 198. newsym(u.ux, u.uy); 199. } 200. } 201.
food_xname
202. /* ``[the(] singular(food, xname) [)] */ 203. STATIC_OVL const char * 204. food_xname(food, the_pfx) 205. struct obj *food; 206. boolean the_pfx; 207. { 208. const char *result; 209. 210. if (food->otyp == CORPSE) { 211. result = corpse_xname(food, (const char *) 0, 212. CXN_SINGULAR | (the_pfx ? CXN_PFX_THE : 0)); 213. /* not strictly needed since pname values are capitalized 214. and the() is a no-op for them */ 215. if (type_is_pname(&mons[food->corpsenm])) 216. the_pfx = FALSE; 217. } else { 218. /* the ordinary case */ 219. result = singular(food, xname); 220. } 221. if (the_pfx) 222. result = the(result); 223. return result; 224. } 225.
choke
226. /* Created by GAN 01/28/87 227. * Amended by AKP 09/22/87: if not hard, don't choke, just vomit. 228. * Amended by 3. 06/12/89: if not hard, sometimes choke anyway, to keep risk. 229. * 11/10/89: if hard, rarely vomit anyway, for slim chance. 230. * 231. * To a full belly all food is bad. (It.) 232. */ 233. STATIC_OVL void 234. choke(food) 235. struct obj *food; 236. { 237. /* only happens if you were satiated */ 238. if (u.uhs != SATIATED) { 239. if (!food || food->otyp != AMULET_OF_STRANGULATION) 240. return; 241. } else if (Role_if(PM_KNIGHT) && u.ualign.type == A_LAWFUL) { 242. adjalign(-1); /* gluttony is unchivalrous */ 243. You_feel("like a glutton!"); 244. } 245. 246. exercise(A_CON, FALSE); 247. 248. if (Breathless || (!Strangled && !rn2(20))) { 249. /* choking by eating AoS doesn't involve stuffing yourself */ 250. if (food && food->otyp == AMULET_OF_STRANGULATION) { 251. You("choke, but recover your composure."); 252. return; 253. } 254. You("stuff yourself and then vomit voluminously."); 255. morehungry(1000); /* you just got *very* sick! */ 256. vomit(); 257. } else { 258. killer.format = KILLED_BY_AN; 259. /* 260. * Note all "killer"s below read "Choked on %s" on the 261. * high score list & tombstone. So plan accordingly. 262. */ 263. if (food) { 264. You("choke over your %s.", foodword(food)); 265. if (food->oclass == COIN_CLASS) { 266. Strcpy(killer.name, "very rich meal"); 267. } else { 268. killer.format = KILLED_BY; 269. Strcpy(killer.name, killer_xname(food)); 270. } 271. } else { 272. You("choke over it."); 273. Strcpy(killer.name, "quick snack"); 274. } 275. You("die..."); 276. done(CHOKING); 277. } 278. } 279.
recalc_wt
280. /* modify object wt. depending on time spent consuming it */ 281. STATIC_OVL void 282. recalc_wt() 283. { 284. struct obj *piece = context.victual.piece; 285. if (!piece) { 286. impossible("recalc_wt without piece"); 287. return; 288. } 289. debugpline1("Old weight = %d", piece->owt); 290. debugpline2("Used time = %d, Req'd time = %d", context.victual.usedtime, 291. context.victual.reqtime); 292. piece->owt = weight(piece); 293. debugpline1("New weight = %d", piece->owt); 294. } 295.
reset_eat
296. /* called when eating interrupted by an event */ 297. void 298. reset_eat() 299. { 300. /* we only set a flag here - the actual reset process is done after 301. * the round is spent eating. 302. */ 303. if (context.victual.eating && !context.victual.doreset) { 304. debugpline0("reset_eat..."); 305. context.victual.doreset = TRUE; 306. } 307. return; 308. } 309.
obj_nutrition
310. /* base nutrition of a food-class object */ 311. STATIC_OVL unsigned 312. obj_nutrition(otmp) 313. struct obj *otmp; 314. { 315. unsigned nut = (otmp->otyp == CORPSE) ? mons[otmp->corpsenm].cnutrit 316. : otmp->globby ? otmp->owt 317. : (unsigned) objects[otmp->otyp].oc_nutrition; 318. 319. if (otmp->otyp == LEMBAS_WAFER) { 320. if (maybe_polyd(is_elf(youmonst.data), Race_if(PM_ELF))) 321. nut += nut / 4; /* 800 -> 1000 */ 322. else if (maybe_polyd(is_orc(youmonst.data), Race_if(PM_ORC))) 323. nut -= nut / 4; /* 800 -> 600 */ 324. /* prevent polymorph making a partly eaten wafer 325. become more nutritious than an untouched one */ 326. if (otmp->oeaten >= nut) 327. otmp->oeaten = (otmp->oeaten < objects[LEMBAS_WAFER].oc_nutrition) 328. ? (nut - 1) : nut; 329. } else if (otmp->otyp == CRAM_RATION) { 330. if (maybe_polyd(is_dwarf(youmonst.data), Race_if(PM_DWARF))) 331. nut += nut / 6; /* 600 -> 700 */ 332. } 333. return nut; 334. } 335.
touchfood
336. STATIC_OVL struct obj * 337. touchfood(otmp) 338. struct obj *otmp; 339. { 340. if (otmp->quan > 1L) { 341. if (!carried(otmp)) 342. (void) splitobj(otmp, otmp->quan - 1L); 343. else 344. otmp = splitobj(otmp, 1L); 345. debugpline0("split object,"); 346. } 347. 348. if (!otmp->oeaten) { 349. costly_alteration(otmp, COST_BITE); 350. otmp->oeaten = obj_nutrition(otmp); 351. } 352. 353. if (carried(otmp)) { 354. freeinv(otmp); 355. if (inv_cnt(FALSE) >= 52) { 356. sellobj_state(SELL_DONTSELL); 357. dropy(otmp); 358. sellobj_state(SELL_NORMAL); 359. } else { 360. otmp->nomerge = 1; /* used to prevent merge */ 361. otmp = addinv(otmp); 362. otmp->nomerge = 0; 363. } 364. } 365. return otmp; 366. } 367.
food_disappears
368. /* When food decays, in the middle of your meal, we don't want to dereference 369. * any dangling pointers, so set it to null (which should still trigger 370. * do_reset_eat() at the beginning of eatfood()) and check for null pointers 371. * in do_reset_eat(). 372. */ 373. void 374. food_disappears(obj) 375. struct obj *obj; 376. { 377. if (obj == context.victual.piece) { 378. context.victual.piece = (struct obj *) 0; 379. context.victual.o_id = 0; 380. } 381. if (obj->timed) 382. obj_stop_timers(obj); 383. } 384.
food_substitution
385. /* renaming an object used to result in it having a different address, 386. so the sequence start eating/opening, get interrupted, name the food, 387. resume eating/opening would restart from scratch */ 388. void 389. food_substitution(old_obj, new_obj) 390. struct obj *old_obj, *new_obj; 391. { 392. if (old_obj == context.victual.piece) { 393. context.victual.piece = new_obj; 394. context.victual.o_id = new_obj->o_id; 395. } 396. if (old_obj == context.tin.tin) { 397. context.tin.tin = new_obj; 398. context.tin.o_id = new_obj->o_id; 399. } 400. } 401.
do_reset_eat
402. STATIC_OVL void 403. do_reset_eat() 404. { 405. debugpline0("do_reset_eat..."); 406. if (context.victual.piece) { 407. context.victual.o_id = 0; 408. context.victual.piece = touchfood(context.victual.piece); 409. if (context.victual.piece) 410. context.victual.o_id = context.victual.piece->o_id; 411. recalc_wt(); 412. } 413. context.victual.fullwarn = context.victual.eating = 414. context.victual.doreset = FALSE; 415. /* Do not set canchoke to FALSE; if we continue eating the same object 416. * we need to know if canchoke was set when they started eating it the 417. * previous time. And if we don't continue eating the same object 418. * canchoke always gets recalculated anyway. 419. */ 420. stop_occupation(); 421. newuhs(FALSE); 422. } 423.
eatfood
424. /* called each move during eating process */ 425. STATIC_PTR int 426. eatfood(VOID_ARGS) 427. { 428. if (!context.victual.piece 429. || (!carried(context.victual.piece) 430. && !obj_here(context.victual.piece, u.ux, u.uy))) { 431. /* maybe it was stolen? */ 432. do_reset_eat(); 433. return 0; 434. } 435. if (!context.victual.eating) 436. return 0; 437. 438. if (++context.victual.usedtime <= context.victual.reqtime) { 439. if (bite()) 440. return 0; 441. return 1; /* still busy */ 442. } else { /* done */ 443. done_eating(TRUE); 444. return 0; 445. } 446. } 447.
done_eating
448. STATIC_OVL void 449. done_eating(message) 450. boolean message; 451. { 452. struct obj *piece = context.victual.piece; 453. 454. piece->in_use = TRUE; 455. occupation = 0; /* do this early, so newuhs() knows we're done */ 456. newuhs(FALSE); 457. if (nomovemsg) { 458. if (message) 459. pline1(nomovemsg); 460. nomovemsg = 0; 461. } else if (message) 462. You("finish eating %s.", food_xname(piece, TRUE)); 463. 464. if (piece->otyp == CORPSE || piece->globby) 465. cpostfx(piece->corpsenm); 466. else 467. fpostfx(piece); 468. 469. if (carried(piece)) 470. useup(piece); 471. else 472. useupf(piece, 1L); 473. context.victual.piece = (struct obj *) 0; 474. context.victual.o_id = 0; 475. context.victual.fullwarn = context.victual.eating = 476. context.victual.doreset = FALSE; 477. } 478.
eating_conducts
479. void 480. eating_conducts(pd) 481. struct permonst *pd; 482. { 483. u.uconduct.food++; 484. if (!vegan(pd)) 485. u.uconduct.unvegan++; 486. if (!vegetarian(pd)) 487. violated_vegetarian(); 488. } 489.
eat_brains
490. /* handle side-effects of mind flayer's tentacle attack */ 491. int 492. eat_brains(magr, mdef, visflag, dmg_p) 493. struct monst *magr, *mdef; 494. boolean visflag; 495. int *dmg_p; /* for dishing out extra damage in lieu of Int loss */ 496. { 497. struct permonst *pd = mdef->data; 498. boolean give_nutrit = FALSE; 499. int result = MM_HIT, xtra_dmg = rnd(10); 500. 501. if (noncorporeal(pd)) { 502. if (visflag) 503. pline("%s brain is unharmed.", 504. (mdef == &youmonst) ? "Your" : s_suffix(Monnam(mdef))); 505. return MM_MISS; /* side-effects can't occur */ 506. } else if (magr == &youmonst) { 507. You("eat %s brain!", s_suffix(mon_nam(mdef))); 508. } else if (mdef == &youmonst) { 509. Your("brain is eaten!"); 510. } else { /* monster against monster */ 511. if (visflag && canspotmon(mdef)) 512. pline("%s brain is eaten!", s_suffix(Monnam(mdef))); 513. } 514. 515. if (flesh_petrifies(pd)) { 516. /* mind flayer has attempted to eat the brains of a petrification 517. inducing critter (most likely Medusa; attacking a cockatrice via 518. tentacle-touch should have been caught before reaching this far) */ 519. if (magr == &youmonst) { 520. if (!Stone_resistance && !Stoned) 521. make_stoned(5L, (char *) 0, KILLED_BY_AN, pd->mname); 522. } else { 523. /* no need to check for poly_when_stoned or Stone_resistance; 524. mind flayers don't have those capabilities */ 525. if (visflag && canseemon(magr)) 526. pline("%s turns to stone!", Monnam(magr)); 527. monstone(magr); 528. if (magr->mhp > 0) { 529. /* life-saved; don't continue eating the brains */ 530. return MM_MISS; 531. } else { 532. if (magr->mtame && !visflag) 533. /* parallels mhitm.c's brief_feeling */ 534. You("have a sad thought for a moment, then it passes."); 535. return MM_AGR_DIED; 536. } 537. } 538. } 539. 540. if (magr == &youmonst) { 541. /* 542. * player mind flayer is eating something's brain 543. */ 544. eating_conducts(pd); 545. if (mindless(pd)) { /* (cannibalism not possible here) */ 546. pline("%s doesn't notice.", Monnam(mdef)); 547. /* all done; no extra harm inflicted upon target */ 548. return MM_MISS; 549. } else if (is_rider(pd)) { 550. pline("Ingesting that is fatal."); 551. Sprintf(killer.name, "unwisely ate the brain of %s", pd->mname); 552. killer.format = NO_KILLER_PREFIX; 553. done(DIED); 554. /* life-saving needed to reach here */ 555. exercise(A_WIS, FALSE); 556. *dmg_p += xtra_dmg; /* Rider takes extra damage */ 557. } else { 558. morehungry(-rnd(30)); /* cannot choke */ 559. if (ABASE(A_INT) < AMAX(A_INT)) { 560. /* recover lost Int; won't increase current max */ 561. ABASE(A_INT) += rnd(4); 562. if (ABASE(A_INT) > AMAX(A_INT)) 563. ABASE(A_INT) = AMAX(A_INT); 564. context.botl = 1; 565. } 566. exercise(A_WIS, TRUE); 567. *dmg_p += xtra_dmg; 568. } 569. /* targetting another mind flayer or your own underlying species 570. is cannibalism */ 571. (void) maybe_cannibal(monsndx(pd), TRUE); 572. 573. } else if (mdef == &youmonst) { 574. /* 575. * monster mind flayer is eating hero's brain 576. */ 577. /* no such thing as mindless players */ 578. if (ABASE(A_INT) <= ATTRMIN(A_INT)) { 579. static NEARDATA const char brainlessness[] = "brainlessness"; 580. 581. if (Lifesaved) { 582. Strcpy(killer.name, brainlessness); 583. killer.format = KILLED_BY; 584. done(DIED); 585. /* amulet of life saving has now been used up */ 586. pline("Unfortunately your brain is still gone."); 587. /* sanity check against adding other forms of life-saving */ 588. u.uprops[LIFESAVED].extrinsic = 589. u.uprops[LIFESAVED].intrinsic = 0L; 590. } else { 591. Your("last thought fades away."); 592. } 593. Strcpy(killer.name, brainlessness); 594. killer.format = KILLED_BY; 595. done(DIED); 596. /* can only get here when in wizard or explore mode and user has 597. explicitly chosen not to die; arbitrarily boost intelligence */ 598. ABASE(A_INT) = ATTRMIN(A_INT) + 2; 599. You_feel("like a scarecrow."); 600. } 601. give_nutrit = TRUE; /* in case a conflicted pet is doing this */ 602. exercise(A_WIS, FALSE); 603. /* caller handles Int and memory loss */ 604. 605. } else { /* mhitm */ 606. /* 607. * monster mind flayer is eating another monster's brain 608. */ 609. if (mindless(pd)) { 610. if (visflag && canspotmon(mdef)) 611. pline("%s doesn't notice.", Monnam(mdef)); 612. return MM_MISS; 613. } else if (is_rider(pd)) { 614. mondied(magr); 615. if (magr->mhp <= 0) 616. result = MM_AGR_DIED; 617. /* Rider takes extra damage regardless of whether attacker dies */ 618. *dmg_p += xtra_dmg; 619. } else { 620. *dmg_p += xtra_dmg; 621. give_nutrit = TRUE; 622. if (*dmg_p >= mdef->mhp && visflag && canspotmon(mdef)) 623. pline("%s last thought fades away...", 624. s_suffix(Monnam(mdef))); 625. } 626. } 627. 628. if (give_nutrit && magr->mtame && !magr->isminion) { 629. EDOG(magr)->hungrytime += rnd(60); 630. magr->mconf = 0; 631. } 632. 633. return result; 634. } 635.
maybe_cannibal
636. /* eating a corpse or egg of one's own species is usually naughty */ 637. STATIC_OVL boolean 638. maybe_cannibal(pm, allowmsg) 639. int pm; 640. boolean allowmsg; 641. { 642. static NEARDATA long ate_brains = 0L; 643. struct permonst *fptr = &mons[pm]; /* food type */ 644. 645. /* when poly'd into a mind flayer, multiple tentacle hits in one 646. turn cause multiple digestion checks to occur; avoid giving 647. multiple luck penalties for the same attack */ 648. if (moves == ate_brains) 649. return FALSE; 650. ate_brains = moves; /* ate_anything, not just brains... */ 651. 652. if (!CANNIBAL_ALLOWED() 653. /* non-cannibalistic heroes shouldn't eat own species ever 654. and also shouldn't eat current species when polymorphed 655. (even if having the form of something which doesn't care 656. about cannibalism--hero's innate traits aren't altered) */ 657. && (your_race(fptr) 658. || (Upolyd && same_race(youmonst.data, fptr)) 659. || (u.ulycn >= LOW_PM && were_beastie(pm) == u.ulycn))) { 660. if (allowmsg) { 661. if (Upolyd && your_race(fptr)) 662. You("have a bad feeling deep inside."); 663. You("cannibal! You will regret this!"); 664. } 665. HAggravate_monster |= FROMOUTSIDE; 666. change_luck(-rn1(4, 2)); /* -5..-2 */ 667. return TRUE; 668. } 669. return FALSE; 670. } 671.
cprefx
672. STATIC_OVL void 673. cprefx(pm) 674. register int pm; 675. { 676. (void) maybe_cannibal(pm, TRUE); 677. if (flesh_petrifies(&mons[pm])) { 678. if (!Stone_resistance 679. && !(poly_when_stoned(youmonst.data) 680. && polymon(PM_STONE_GOLEM))) { 681. Sprintf(killer.name, "tasting %s meat", mons[pm].mname); 682. killer.format = KILLED_BY; 683. You("turn to stone."); 684. done(STONING); 685. if (context.victual.piece) 686. context.victual.eating = FALSE; 687. return; /* lifesaved */ 688. } 689. } 690. 691. switch (pm) { 692. case PM_LITTLE_DOG: 693. case PM_DOG: 694. case PM_LARGE_DOG: 695. case PM_KITTEN: 696. case PM_HOUSECAT: 697. case PM_LARGE_CAT: 698. /* cannibals are allowed to eat domestic animals without penalty */ 699. if (!CANNIBAL_ALLOWED()) { 700. You_feel("that eating the %s was a bad idea.", mons[pm].mname); 701. HAggravate_monster |= FROMOUTSIDE; 702. } 703. break; 704. case PM_LIZARD: 705. if (Stoned) 706. fix_petrification(); 707. break; 708. case PM_DEATH: 709. case PM_PESTILENCE: 710. case PM_FAMINE: { 711. pline("Eating that is instantly fatal."); 712. Sprintf(killer.name, "unwisely ate the body of %s", mons[pm].mname); 713. killer.format = NO_KILLER_PREFIX; 714. done(DIED); 715. /* life-saving needed to reach here */ 716. exercise(A_WIS, FALSE); 717. /* It so happens that since we know these monsters */ 718. /* cannot appear in tins, context.victual.piece will always */ 719. /* be what we want, which is not generally true. */ 720. if (revive_corpse(context.victual.piece)) { 721. context.victual.piece = (struct obj *) 0; 722. context.victual.o_id = 0; 723. } 724. return; 725. } 726. case PM_GREEN_SLIME: 727. if (!Slimed && !Unchanging && !slimeproof(youmonst.data)) { 728. You("don't feel very well."); 729. make_slimed(10L, (char *) 0); 730. delayed_killer(SLIMED, KILLED_BY_AN, ""); 731. } 732. /* Fall through */ 733. default: 734. if (acidic(&mons[pm]) && Stoned) 735. fix_petrification(); 736. break; 737. } 738. } 739.
fix_petrification
740. void 741. fix_petrification() 742. { 743. char buf[BUFSZ]; 744. 745. if (Hallucination) 746. Sprintf(buf, "What a pity--you just ruined a future piece of %sart!", 747. ACURR(A_CHA) > 15 ? "fine " : ""); 748. else 749. Strcpy(buf, "You feel limber!"); 750. make_stoned(0L, buf, 0, (char *) 0); 751. } 752. 753. /* 754. * If you add an intrinsic that can be gotten by eating a monster, add it 755. * to intrinsic_possible() and givit(). (It must already be in prop.h to 756. * be an intrinsic property.) 757. * It would be very easy to make the intrinsics not try to give you one 758. * that you already had by checking to see if you have it in 759. * intrinsic_possible() instead of givit(), but we're not that nice. 760. */ 761.
intrinsic_possible
762. /* intrinsic_possible() returns TRUE iff a monster can give an intrinsic. */ 763. STATIC_OVL int 764. intrinsic_possible(type, ptr) 765. int type; 766. register struct permonst *ptr; 767. { 768. int res = 0; 769. 770. #ifdef DEBUG 771. #define ifdebugresist(Msg) \ 772. do { \ 773. if (res) \ 774. debugpline0(Msg); \ 775. } while (0) 776. #else 777. #define ifdebugresist(Msg) /*empty*/ 778. #endif 779. switch (type) { 780. case FIRE_RES: 781. res = (ptr->mconveys & MR_FIRE) != 0; 782. ifdebugresist("can get fire resistance"); 783. break; 784. case SLEEP_RES: 785. res = (ptr->mconveys & MR_SLEEP) != 0; 786. ifdebugresist("can get sleep resistance"); 787. break; 788. case COLD_RES: 789. res = (ptr->mconveys & MR_COLD) != 0; 790. ifdebugresist("can get cold resistance"); 791. break; 792. case DISINT_RES: 793. res = (ptr->mconveys & MR_DISINT) != 0; 794. ifdebugresist("can get disintegration resistance"); 795. break; 796. case SHOCK_RES: /* shock (electricity) resistance */ 797. res = (ptr->mconveys & MR_ELEC) != 0; 798. ifdebugresist("can get shock resistance"); 799. break; 800. case POISON_RES: 801. res = (ptr->mconveys & MR_POISON) != 0; 802. ifdebugresist("can get poison resistance"); 803. break; 804. case TELEPORT: 805. res = can_teleport(ptr); 806. ifdebugresist("can get teleport"); 807. break; 808. case TELEPORT_CONTROL: 809. res = control_teleport(ptr); 810. ifdebugresist("can get teleport control"); 811. break; 812. case TELEPAT: 813. res = telepathic(ptr); 814. ifdebugresist("can get telepathy"); 815. break; 816. default: 817. /* res stays 0 */ 818. break; 819. } 820. #undef ifdebugresist 821. return res; 822. } 823.
givit
824. /* givit() tries to give you an intrinsic based on the monster's level 825. * and what type of intrinsic it is trying to give you. 826. */ 827. STATIC_OVL void 828. givit(type, ptr) 829. int type; 830. register struct permonst *ptr; 831. { 832. register int chance; 833. 834. debugpline1("Attempting to give intrinsic %d", type); 835. /* some intrinsics are easier to get than others */ 836. switch (type) { 837. case POISON_RES: 838. if ((ptr == &mons[PM_KILLER_BEE] || ptr == &mons[PM_SCORPION]) 839. && !rn2(4)) 840. chance = 1; 841. else 842. chance = 15; 843. break; 844. case TELEPORT: 845. chance = 10; 846. break; 847. case TELEPORT_CONTROL: 848. chance = 12; 849. break; 850. case TELEPAT: 851. chance = 1; 852. break; 853. default: 854. chance = 15; 855. break; 856. } 857. 858. if (ptr->mlevel <= rn2(chance)) 859. return; /* failed die roll */ 860. 861. switch (type) { 862. case FIRE_RES: 863. debugpline0("Trying to give fire resistance"); 864. if (!(HFire_resistance & FROMOUTSIDE)) { 865. You(Hallucination ? "be chillin'." : "feel a momentary chill."); 866. HFire_resistance |= FROMOUTSIDE; 867. } 868. break; 869. case SLEEP_RES: 870. debugpline0("Trying to give sleep resistance"); 871. if (!(HSleep_resistance & FROMOUTSIDE)) { 872. You_feel("wide awake."); 873. HSleep_resistance |= FROMOUTSIDE; 874. } 875. break; 876. case COLD_RES: 877. debugpline0("Trying to give cold resistance"); 878. if (!(HCold_resistance & FROMOUTSIDE)) { 879. You_feel("full of hot air."); 880. HCold_resistance |= FROMOUTSIDE; 881. } 882. break; 883. case DISINT_RES: 884. debugpline0("Trying to give disintegration resistance"); 885. if (!(HDisint_resistance & FROMOUTSIDE)) { 886. You_feel(Hallucination ? "totally together, man." : "very firm."); 887. HDisint_resistance |= FROMOUTSIDE; 888. } 889. break; 890. case SHOCK_RES: /* shock (electricity) resistance */ 891. debugpline0("Trying to give shock resistance"); 892. if (!(HShock_resistance & FROMOUTSIDE)) { 893. if (Hallucination) 894. You_feel("grounded in reality."); 895. else 896. Your("health currently feels amplified!"); 897. HShock_resistance |= FROMOUTSIDE; 898. } 899. break; 900. case POISON_RES: 901. debugpline0("Trying to give poison resistance"); 902. if (!(HPoison_resistance & FROMOUTSIDE)) { 903. You_feel(Poison_resistance ? "especially healthy." : "healthy."); 904. HPoison_resistance |= FROMOUTSIDE; 905. } 906. break; 907. case TELEPORT: 908. debugpline0("Trying to give teleport"); 909. if (!(HTeleportation & FROMOUTSIDE)) { 910. You_feel(Hallucination ? "diffuse." : "very jumpy."); 911. HTeleportation |= FROMOUTSIDE; 912. } 913. break; 914. case TELEPORT_CONTROL: 915. debugpline0("Trying to give teleport control"); 916. if (!(HTeleport_control & FROMOUTSIDE)) { 917. You_feel(Hallucination ? "centered in your personal space." 918. : "in control of yourself."); 919. HTeleport_control |= FROMOUTSIDE; 920. } 921. break; 922. case TELEPAT: 923. debugpline0("Trying to give telepathy"); 924. if (!(HTelepat & FROMOUTSIDE)) { 925. You_feel(Hallucination ? "in touch with the cosmos." 926. : "a strange mental acuity."); 927. HTelepat |= FROMOUTSIDE; 928. /* If blind, make sure monsters show up. */ 929. if (Blind) 930. see_monsters(); 931. } 932. break; 933. default: 934. debugpline0("Tried to give an impossible intrinsic"); 935. break; 936. } 937. } 938.
cpostfx
939. /* called after completely consuming a corpse */ 940. STATIC_OVL void 941. cpostfx(pm) 942. register int pm; 943. { 944. register int tmp = 0; 945. int catch_lycanthropy = NON_PM; 946. 947. /* in case `afternmv' didn't get called for previously mimicking 948. gold, clean up now to avoid `eatmbuf' memory leak */ 949. if (eatmbuf) 950. (void) eatmdone(); 951. 952. switch (pm) { 953. case PM_NEWT: 954. /* MRKR: "eye of newt" may give small magical energy boost */ 955. if (rn2(3) || 3 * u.uen <= 2 * u.uenmax) { 956. int old_uen = u.uen; 957. u.uen += rnd(3); 958. if (u.uen > u.uenmax) { 959. if (!rn2(3)) 960. u.uenmax++; 961. u.uen = u.uenmax; 962. } 963. if (old_uen != u.uen) { 964. You_feel("a mild buzz."); 965. context.botl = 1; 966. } 967. } 968. break; 969. case PM_WRAITH: 970. pluslvl(FALSE); 971. break; 972. case PM_HUMAN_WERERAT: 973. catch_lycanthropy = PM_WERERAT; 974. break; 975. case PM_HUMAN_WEREJACKAL: 976. catch_lycanthropy = PM_WEREJACKAL; 977. break; 978. case PM_HUMAN_WEREWOLF: 979. catch_lycanthropy = PM_WEREWOLF; 980. break; 981. case PM_NURSE: 982. if (Upolyd) 983. u.mh = u.mhmax; 984. else 985. u.uhp = u.uhpmax; 986. make_blinded(0L, !u.ucreamed); 987. context.botl = 1; 988. break; 989. case PM_STALKER: 990. if (!Invis) { 991. set_itimeout(&HInvis, (long) rn1(100, 50)); 992. if (!Blind && !BInvis) 993. self_invis_message(); 994. } else { 995. if (!(HInvis & INTRINSIC)) 996. You_feel("hidden!"); 997. HInvis |= FROMOUTSIDE; 998. HSee_invisible |= FROMOUTSIDE; 999. } 1000. newsym(u.ux, u.uy); 1001. /*FALLTHRU*/ 1002. case PM_YELLOW_LIGHT: 1003. case PM_GIANT_BAT: 1004. make_stunned((HStun & TIMEOUT) + 30L, FALSE); 1005. /*FALLTHRU*/ 1006. case PM_BAT: 1007. make_stunned((HStun & TIMEOUT) + 30L, FALSE); 1008. break; 1009. case PM_GIANT_MIMIC: 1010. tmp += 10; 1011. /*FALLTHRU*/ 1012. case PM_LARGE_MIMIC: 1013. tmp += 20; 1014. /*FALLTHRU*/ 1015. case PM_SMALL_MIMIC: 1016. tmp += 20; 1017. if (youmonst.data->mlet != S_MIMIC && !Unchanging) { 1018. char buf[BUFSZ]; 1019. 1020. u.uconduct.polyselfs++; /* you're changing form */ 1021. You_cant("resist the temptation to mimic %s.", 1022. Hallucination ? "an orange" : "a pile of gold"); 1023. /* A pile of gold can't ride. */ 1024. if (u.usteed) 1025. dismount_steed(DISMOUNT_FELL); 1026. nomul(-tmp); 1027. multi_reason = "pretending to be a pile of gold"; 1028. Sprintf(buf, 1029. Hallucination 1030. ? "You suddenly dread being peeled and mimic %s again!" 1031. : "You now prefer mimicking %s again.", 1032. an(Upolyd ? youmonst.data->mname : urace.noun)); 1033. eatmbuf = dupstr(buf); 1034. nomovemsg = eatmbuf; 1035. afternmv = eatmdone; 1036. /* ??? what if this was set before? */ 1037. youmonst.m_ap_type = M_AP_OBJECT; 1038. youmonst.mappearance = Hallucination ? ORANGE : GOLD_PIECE; 1039. newsym(u.ux, u.uy); 1040. curs_on_u(); 1041. /* make gold symbol show up now */ 1042. display_nhwindow(WIN_MAP, TRUE); 1043. } 1044. break; 1045. case PM_QUANTUM_MECHANIC: 1046. Your("velocity suddenly seems very uncertain!"); 1047. if (HFast & INTRINSIC) { 1048. HFast &= ~INTRINSIC; 1049. You("seem slower."); 1050. } else { 1051. HFast |= FROMOUTSIDE; 1052. You("seem faster."); 1053. } 1054. break; 1055. case PM_LIZARD: 1056. if ((HStun & TIMEOUT) > 2) 1057. make_stunned(2L, FALSE); 1058. if ((HConfusion & TIMEOUT) > 2) 1059. make_confused(2L, FALSE); 1060. break; 1061. case PM_CHAMELEON: 1062. case PM_DOPPELGANGER: 1063. case PM_SANDESTIN: /* moot--they don't leave corpses */ 1064. if (Unchanging) { 1065. You_feel("momentarily different."); /* same as poly trap */ 1066. } else { 1067. You_feel("a change coming over you."); 1068. polyself(0); 1069. } 1070. break; 1071. case PM_DISENCHANTER: 1072. /* picks an intrinsic at random and removes it; there's 1073. no feedback if hero already lacks the chosen ability */ 1074. debugpline0("using attrcurse to strip an intrinsic"); 1075. attrcurse(); 1076. break; 1077. case PM_MIND_FLAYER: 1078. case PM_MASTER_MIND_FLAYER: 1079. if (ABASE(A_INT) < ATTRMAX(A_INT)) { 1080. if (!rn2(2)) { 1081. pline("Yum! That was real brain food!"); 1082. (void) adjattrib(A_INT, 1, FALSE); 1083. break; /* don't give them telepathy, too */ 1084. } 1085. } else { 1086. pline("For some reason, that tasted bland."); 1087. } 1088. /*FALLTHRU*/ 1089. default: { 1090. struct permonst *ptr = &mons[pm]; 1091. boolean conveys_STR = is_giant(ptr); 1092. int i, count; 1093. 1094. if (dmgtype(ptr, AD_STUN) || dmgtype(ptr, AD_HALU) 1095. || pm == PM_VIOLET_FUNGUS) { 1096. pline("Oh wow! Great stuff!"); 1097. (void) make_hallucinated((HHallucination & TIMEOUT) + 200L, FALSE, 1098. 0L); 1099. } 1100. 1101. /* Check the monster for all of the intrinsics. If this 1102. * monster can give more than one, pick one to try to give 1103. * from among all it can give. 1104. * 1105. * Strength from giants is now treated like an intrinsic 1106. * rather than being given unconditionally. 1107. */ 1108. count = 0; /* number of possible intrinsics */ 1109. tmp = 0; /* which one we will try to give */ 1110. if (conveys_STR) { 1111. count = 1; 1112. tmp = -1; /* use -1 as fake prop index for STR */ 1113. debugpline1("\"Intrinsic\" strength, %d", tmp); 1114. } 1115. for (i = 1; i <= LAST_PROP; i++) { 1116. if (!intrinsic_possible(i, ptr)) 1117. continue; 1118. ++count; 1119. /* a 1 in count chance of replacing the old choice 1120. with this one, and a count-1 in count chance 1121. of keeping the old choice (note that 1 in 1 and 1122. 0 in 1 are what we want for the first candidate) */ 1123. if (!rn2(count)) { 1124. debugpline2("Intrinsic %d replacing %d", i, tmp); 1125. tmp = i; 1126. } 1127. } 1128. /* if strength is the only candidate, give it 50% chance */ 1129. if (conveys_STR && count == 1 && !rn2(2)) 1130. tmp = 0; 1131. /* if something was chosen, give it now (givit() might fail) */ 1132. if (tmp == -1) 1133. gainstr((struct obj *) 0, 0, TRUE); 1134. else if (tmp > 0) 1135. givit(tmp, ptr); 1136. break; 1137. } /* default case */ 1138. } /* switch */ 1139. 1140. if (catch_lycanthropy >= LOW_PM) { 1141. set_ulycn(catch_lycanthropy); 1142. retouch_equipment(2); 1143. } 1144. return; 1145. } 1146.
violated_vegetarian
1147. void 1148. violated_vegetarian() 1149. { 1150. u.uconduct.unvegetarian++; 1151. if (Role_if(PM_MONK)) { 1152. You_feel("guilty."); 1153. adjalign(-1); 1154. } 1155. return; 1156. } 1157.
costly_tin
1158. /* common code to check and possibly charge for 1 context.tin.tin, 1159. * will split() context.tin.tin if necessary */ 1160. STATIC_PTR struct obj * 1161. costly_tin(alter_type) 1162. int alter_type; /* COST_xxx */ 1163. { 1164. struct obj *tin = context.tin.tin; 1165. 1166. if (carried(tin) ? tin->unpaid 1167. : (costly_spot(tin->ox, tin->oy) && !tin->no_charge)) { 1168. if (tin->quan > 1L) { 1169. tin = context.tin.tin = splitobj(tin, 1L); 1170. context.tin.o_id = tin->o_id; 1171. } 1172. costly_alteration(tin, alter_type); 1173. } 1174. return tin; 1175. } 1176.
tin_variety_txt
1177. int 1178. tin_variety_txt(s, tinvariety) 1179. char *s; 1180. int *tinvariety; 1181. { 1182. int k, l; 1183. 1184. if (s && tinvariety) { 1185. *tinvariety = -1; 1186. for (k = 0; k < TTSZ - 1; ++k) { 1187. l = (int) strlen(tintxts[k].txt); 1188. if (!strncmpi(s, tintxts[k].txt, l) && ((int) strlen(s) > l) 1189. && s[l] == ' ') { 1190. *tinvariety = k; 1191. return (l + 1); 1192. } 1193. } 1194. } 1195. return 0; 1196. } 1197.
tin_details
1198. /* 1199. * This assumes that buf already contains the word "tin", 1200. * as is the case with caller xname(). 1201. */ 1202. void 1203. tin_details(obj, mnum, buf) 1204. struct obj *obj; 1205. int mnum; 1206. char *buf; 1207. { 1208. char buf2[BUFSZ]; 1209. int r = tin_variety(obj, TRUE); 1210. 1211. if (obj && buf) { 1212. if (r == SPINACH_TIN) 1213. Strcat(buf, " of spinach"); 1214. else if (mnum == NON_PM) 1215. Strcpy(buf, "empty tin"); 1216. else { 1217. if ((obj->cknown || iflags.override_ID) && obj->spe < 0) { 1218. if (r == ROTTEN_TIN || r == HOMEMADE_TIN) { 1219. /* put these before the word tin */ 1220. Sprintf(buf2, "%s %s of ", tintxts[r].txt, buf); 1221. Strcpy(buf, buf2); 1222. } else { 1223. Sprintf(eos(buf), " of %s ", tintxts[r].txt); 1224. } 1225. } else { 1226. Strcpy(eos(buf), " of "); 1227. } 1228. if (vegetarian(&mons[mnum])) 1229. Sprintf(eos(buf), "%s", mons[mnum].mname); 1230. else 1231. Sprintf(eos(buf), "%s meat", mons[mnum].mname); 1232. } 1233. } 1234. } 1235.
set_tin_variety
1236. void 1237. set_tin_variety(obj, forcetype) 1238. struct obj *obj; 1239. int forcetype; 1240. { 1241. register int r; 1242. 1243. if (forcetype == SPINACH_TIN 1244. || (forcetype == HEALTHY_TIN 1245. && (obj->corpsenm == NON_PM /* empty or already spinach */ 1246. || !vegetarian(&mons[obj->corpsenm])))) { /* replace meat */ 1247. obj->corpsenm = NON_PM; /* not based on any monster */ 1248. obj->spe = 1; /* spinach */ 1249. return; 1250. } else if (forcetype == HEALTHY_TIN) { 1251. r = tin_variety(obj, FALSE); 1252. if (r < 0 || r >= TTSZ) 1253. r = ROTTEN_TIN; /* shouldn't happen */ 1254. while ((r == ROTTEN_TIN && !obj->cursed) || !tintxts[r].fodder) 1255. r = rn2(TTSZ - 1); 1256. } else if (forcetype >= 0 && forcetype < TTSZ - 1) { 1257. r = forcetype; 1258. } else { /* RANDOM_TIN */ 1259. r = rn2(TTSZ - 1); /* take your pick */ 1260. if (r == ROTTEN_TIN && nonrotting_corpse(obj->corpsenm)) 1261. r = HOMEMADE_TIN; /* lizards don't rot */ 1262. } 1263. obj->spe = -(r + 1); /* offset by 1 to allow index 0 */ 1264. } 1265.
tin_variety
1266. STATIC_OVL int 1267. tin_variety(obj, disp) 1268. struct obj *obj; 1269. boolean disp; /* we're just displaying so leave things alone */ 1270. { 1271. register int r; 1272. 1273. if (obj->spe == 1) { 1274. r = SPINACH_TIN; 1275. } else if (obj->cursed) { 1276. r = ROTTEN_TIN; /* always rotten if cursed */ 1277. } else if (obj->spe < 0) { 1278. r = -(obj->spe); 1279. --r; /* get rid of the offset */ 1280. } else 1281. r = rn2(TTSZ - 1); 1282. 1283. if (!disp && r == HOMEMADE_TIN && !obj->blessed && !rn2(7)) 1284. r = ROTTEN_TIN; /* some homemade tins go bad */ 1285. 1286. if (r == ROTTEN_TIN && nonrotting_corpse(obj->corpsenm)) 1287. r = HOMEMADE_TIN; /* lizards don't rot */ 1288. return r; 1289. } 1290.
consume_tin
1291. STATIC_OVL void 1292. consume_tin(mesg) 1293. const char *mesg; 1294. { 1295. const char *what; 1296. int which, mnum, r; 1297. struct obj *tin = context.tin.tin; 1298. 1299. r = tin_variety(tin, FALSE); 1300. if (tin->otrapped || (tin->cursed && r != HOMEMADE_TIN && !rn2(8))) { 1301. b_trapped("tin", 0); 1302. tin = costly_tin(COST_DSTROY); 1303. goto use_up_tin; 1304. } 1305. 1306. pline1(mesg); /* "You succeed in opening the tin." */ 1307. 1308. if (r != SPINACH_TIN) { 1309. mnum = tin->corpsenm; 1310. if (mnum == NON_PM) { 1311. pline("It turns out to be empty."); 1312. tin->dknown = tin->known = 1; 1313. tin = costly_tin(COST_OPEN); 1314. goto use_up_tin; 1315. } 1316. 1317. which = 0; /* 0=>plural, 1=>as-is, 2=>"the" prefix */ 1318. if ((mnum == PM_COCKATRICE || mnum == PM_CHICKATRICE) 1319. && (Stone_resistance || Hallucination)) { 1320. what = "chicken"; 1321. which = 1; /* suppress pluralization */ 1322. } else if (Hallucination) { 1323. what = rndmonnam(NULL); 1324. } else { 1325. what = mons[mnum].mname; 1326. if (the_unique_pm(&mons[mnum])) 1327. which = 2; 1328. else if (type_is_pname(&mons[mnum])) 1329. which = 1; 1330. } 1331. if (which == 0) 1332. what = makeplural(what); 1333. else if (which == 2) 1334. what = the(what); 1335. 1336. pline("It smells like %s.", what); 1337. if (yn("Eat it?") == 'n') { 1338. if (flags.verbose) 1339. You("discard the open tin."); 1340. if (!Hallucination) 1341. tin->dknown = tin->known = 1; 1342. tin = costly_tin(COST_OPEN); 1343. goto use_up_tin; 1344. } 1345. 1346. /* in case stop_occupation() was called on previous meal */ 1347. context.victual.piece = (struct obj *) 0; 1348. context.victual.o_id = 0; 1349. context.victual.fullwarn = context.victual.eating = 1350. context.victual.doreset = FALSE; 1351. 1352. You("consume %s %s.", tintxts[r].txt, mons[mnum].mname); 1353. 1354. eating_conducts(&mons[mnum]); 1355. 1356. tin->dknown = tin->known = 1; 1357. cprefx(mnum); 1358. cpostfx(mnum); 1359. 1360. /* charge for one at pre-eating cost */ 1361. tin = costly_tin(COST_OPEN); 1362. 1363. if (tintxts[r].nut < 0) /* rotten */ 1364. make_vomiting((long) rn1(15, 10), FALSE); 1365. else 1366. lesshungry(tintxts[r].nut); 1367. 1368. if (tintxts[r].greasy) { 1369. /* Assume !Glib, because you can't open tins when Glib. */ 1370. incr_itimeout(&Glib, rnd(15)); 1371. pline("Eating %s food made your %s very slippery.", 1372. tintxts[r].txt, makeplural(body_part(FINGER))); 1373. } 1374. 1375. } else { /* spinach... */ 1376. if (tin->cursed) { 1377. pline("It contains some decaying%s%s substance.", 1378. Blind ? "" : " ", Blind ? "" : hcolor(NH_GREEN)); 1379. } else { 1380. pline("It contains spinach."); 1381. tin->dknown = tin->known = 1; 1382. } 1383. 1384. if (yn("Eat it?") == 'n') { 1385. if (flags.verbose) 1386. You("discard the open tin."); 1387. tin = costly_tin(COST_OPEN); 1388. goto use_up_tin; 1389. } 1390. 1391. /* 1392. * Same order as with non-spinach above: 1393. * conduct update, side-effects, shop handling, and nutrition. 1394. */ 1395. u.uconduct.food++; /* don't need vegetarian checks for spinach */ 1396. if (!tin->cursed) 1397. pline("This makes you feel like %s!", 1398. Hallucination ? "Swee'pea" : "Popeye"); 1399. gainstr(tin, 0, FALSE); 1400. 1401. tin = costly_tin(COST_OPEN); 1402. 1403. lesshungry(tin->blessed 1404. ? 600 /* blessed */ 1405. : !tin->cursed 1406. ? (400 + rnd(200)) /* uncursed */ 1407. : (200 + rnd(400))); /* cursed */ 1408. } 1409. 1410. use_up_tin: 1411. if (carried(tin)) 1412. useup(tin); 1413. else 1414. useupf(tin, 1L); 1415. context.tin.tin = (struct obj *) 0; 1416. context.tin.o_id = 0; 1417. } 1418.
opentin
1419. /* called during each move whilst opening a tin */ 1420. STATIC_PTR int 1421. opentin(VOID_ARGS) 1422. { 1423. /* perhaps it was stolen (although that should cause interruption) */ 1424. if (!carried(context.tin.tin) 1425. && (!obj_here(context.tin.tin, u.ux, u.uy) || !can_reach_floor(TRUE))) 1426. return 0; /* %% probably we should use tinoid */ 1427. if (context.tin.usedtime++ >= 50) { 1428. You("give up your attempt to open the tin."); 1429. return 0; 1430. } 1431. if (context.tin.usedtime < context.tin.reqtime) 1432. return 1; /* still busy */ 1433. 1434. consume_tin("You succeed in opening the tin."); 1435. return 0; 1436. } 1437.
start_tin
1438. /* called when starting to open a tin */ 1439. STATIC_OVL void 1440. start_tin(otmp) 1441. struct obj *otmp; 1442. { 1443. const char *mesg = 0; 1444. register int tmp; 1445. 1446. if (metallivorous(youmonst.data)) { 1447. mesg = "You bite right into the metal tin..."; 1448. tmp = 0; 1449. } else if (cantwield(youmonst.data)) { /* nohands || verysmall */ 1450. You("cannot handle the tin properly to open it."); 1451. return; 1452. } else if (otmp->blessed) { 1453. /* 50/50 chance for immediate access vs 1 turn delay (unless 1454. wielding blessed tin opener which always yields immediate 1455. access); 1 turn delay case is non-deterministic: getting 1456. interrupted and retrying might yield another 1 turn delay 1457. or might open immediately on 2nd (or 3rd, 4th, ...) try */ 1458. tmp = (uwep && uwep->blessed && uwep->otyp == TIN_OPENER) ? 0 : rn2(2); 1459. if (!tmp) 1460. mesg = "The tin opens like magic!"; 1461. else 1462. pline_The("tin seems easy to open."); 1463. } else if (uwep) { 1464. switch (uwep->otyp) { 1465. case TIN_OPENER: 1466. mesg = "You easily open the tin."; /* iff tmp==0 */ 1467. tmp = rn2(uwep->cursed ? 3 : !uwep->blessed ? 2 : 1); 1468. break; 1469. case DAGGER: 1470. case SILVER_DAGGER: 1471. case ELVEN_DAGGER: 1472. case ORCISH_DAGGER: 1473. case ATHAME: 1474. case KNIFE: 1475. case STILETTO: 1476. case CRYSKNIFE: 1477. tmp = 3; 1478. break; 1479. case PICK_AXE: 1480. case AXE: 1481. tmp = 6; 1482. break; 1483. default: 1484. goto no_opener; 1485. } 1486. pline("Using %s you try to open the tin.", yobjnam(uwep, (char *) 0)); 1487. } else { 1488. no_opener: 1489. pline("It is not so easy to open this tin."); 1490. if (Glib) { 1491. pline_The("tin slips from your %s.", 1492. makeplural(body_part(FINGER))); 1493. if (otmp->quan > 1L) { 1494. otmp = splitobj(otmp, 1L); 1495. } 1496. if (carried(otmp)) 1497. dropx(otmp); 1498. else 1499. stackobj(otmp); 1500. return; 1501. } 1502. tmp = rn1(1 + 500 / ((int) (ACURR(A_DEX) + ACURRSTR)), 10); 1503. } 1504. 1505. context.tin.tin = otmp; 1506. context.tin.o_id = otmp->o_id; 1507. if (!tmp) { 1508. consume_tin(mesg); /* begin immediately */ 1509. } else { 1510. context.tin.reqtime = tmp; 1511. context.tin.usedtime = 0; 1512. set_occupation(opentin, "opening the tin", 0); 1513. } 1514. return; 1515. } 1516.
Hear_again
1517. /* called when waking up after fainting */ 1518. int 1519. Hear_again(VOID_ARGS) 1520. { 1521. /* Chance of deafness going away while fainted/sleeping/etc. */ 1522. if (!rn2(2)) { 1523. make_deaf(0L, FALSE); 1524. context.botl = TRUE; 1525. } 1526. return 0; 1527. } 1528.
rottenfood
1529. /* called on the "first bite" of rotten food */ 1530. STATIC_OVL int 1531. rottenfood(obj) 1532. struct obj *obj; 1533. { 1534. pline("Blecch! Rotten %s!", foodword(obj)); 1535. if (!rn2(4)) { 1536. if (Hallucination) 1537. You_feel("rather trippy."); 1538. else 1539. You_feel("rather %s.", body_part(LIGHT_HEADED)); 1540. make_confused(HConfusion + d(2, 4), FALSE); 1541. } else if (!rn2(4) && !Blind) { 1542. pline("Everything suddenly goes dark."); 1543. /* hero is not Blind, but Blinded timer might be nonzero if 1544. blindness is being overridden by the Eyes of the Overworld */ 1545. make_blinded((Blinded & TIMEOUT) + (long) d(2, 10), FALSE); 1546. if (!Blind) 1547. Your1(vision_clears); 1548. } else if (!rn2(3)) { 1549. const char *what, *where; 1550. int duration = rnd(10); 1551. 1552. if (!Blind) 1553. what = "goes", where = "dark"; 1554. else if (Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)) 1555. what = "you lose control of", where = "yourself"; 1556. else 1557. what = "you slap against the", 1558. where = (u.usteed) ? "saddle" : surface(u.ux, u.uy); 1559. pline_The("world spins and %s %s.", what, where); 1560. incr_itimeout(&HDeaf, duration); 1561. context.botl = TRUE; 1562. nomul(-duration); 1563. multi_reason = "unconscious from rotten food"; 1564. nomovemsg = "You are conscious again."; 1565. afternmv = Hear_again; 1566. return 1; 1567. } 1568. return 0; 1569. } 1570.
eatcorpse
1571. /* called when a corpse is selected as food */ 1572. STATIC_OVL int 1573. eatcorpse(otmp) 1574. struct obj *otmp; 1575. { 1576. int retcode = 0, tp = 0, mnum = otmp->corpsenm; 1577. long rotted = 0L; 1578. boolean stoneable = (flesh_petrifies(&mons[mnum]) && !Stone_resistance 1579. && !poly_when_stoned(youmonst.data)), 1580. slimeable = (mnum == PM_GREEN_SLIME && !Slimed && !Unchanging 1581. && !slimeproof(youmonst.data)), 1582. glob = otmp->globby ? TRUE : FALSE; 1583. 1584. /* KMH, conduct */ 1585. if (!vegan(&mons[mnum])) 1586. u.uconduct.unvegan++; 1587. if (!vegetarian(&mons[mnum])) 1588. violated_vegetarian(); 1589. 1590. if (!nonrotting_corpse(mnum)) { 1591. long age = peek_at_iced_corpse_age(otmp); 1592. 1593. rotted = (monstermoves - age) / (10L + rn2(20)); 1594. if (otmp->cursed) 1595. rotted += 2L; 1596. else if (otmp->blessed) 1597. rotted -= 2L; 1598. } 1599. 1600. if (mnum != PM_ACID_BLOB && !stoneable && !slimeable && rotted > 5L) { 1601. boolean cannibal = maybe_cannibal(mnum, FALSE); 1602. 1603. pline("Ulch - that %s was tainted%s!", 1604. (mons[mnum].mlet == S_FUNGUS) ? "fungoid vegetation" 1605. : glob ? "glob" 1606. : vegetarian(&mons[mnum]) ? "protoplasm" 1607. : "meat", 1608. cannibal ? ", you cannibal" : ""); 1609. if (Sick_resistance) { 1610. pline("It doesn't seem at all sickening, though..."); 1611. } else { 1612. long sick_time; 1613. 1614. sick_time = (long) rn1(10, 10); 1615. /* make sure new ill doesn't result in improvement */ 1616. if (Sick && (sick_time > Sick)) 1617. sick_time = (Sick > 1L) ? Sick - 1L : 1L; 1618. make_sick(sick_time, corpse_xname(otmp, "rotted", CXN_NORMAL), 1619. TRUE, SICK_VOMITABLE); 1620. 1621. pline("(It must have died too long ago to be safe to eat.)"); 1622. } 1623. if (carried(otmp)) 1624. useup(otmp); 1625. else 1626. useupf(otmp, 1L); 1627. return 2; 1628. } else if (acidic(&mons[mnum]) && !Acid_resistance) { 1629. tp++; 1630. You("have a very bad case of stomach acid."); /* not body_part() */ 1631. losehp(rnd(15), !glob ? "acidic corpse" : "acidic glob", 1632. KILLED_BY_AN); /* acid damage */ 1633. } else if (poisonous(&mons[mnum]) && rn2(5)) { 1634. tp++; 1635. pline("Ecch - that must have been poisonous!"); 1636. if (!Poison_resistance) { 1637. losestr(rnd(4)); 1638. losehp(rnd(15), !glob ? "poisonous corpse" : "poisonous glob", 1639. KILLED_BY_AN); 1640. } else 1641. You("seem unaffected by the poison."); 1642. /* now any corpse left too long will make you mildly ill */ 1643. } else if ((rotted > 5L || (rotted > 3L && rn2(5))) && !Sick_resistance) { 1644. tp++; 1645. You_feel("%ssick.", (Sick) ? "very " : ""); 1646. losehp(rnd(8), !glob ? "cadaver" : "rotted glob", KILLED_BY_AN); 1647. } 1648. 1649. /* delay is weight dependent */ 1650. context.victual.reqtime = 3 + ((!glob ? mons[mnum].cwt : otmp->owt) >> 6); 1651. 1652. if (!tp && !nonrotting_corpse(mnum) && (otmp->orotten || !rn2(7))) { 1653. if (rottenfood(otmp)) { 1654. otmp->orotten = TRUE; 1655. (void) touchfood(otmp); 1656. retcode = 1; 1657. } 1658. 1659. if (!mons[otmp->corpsenm].cnutrit) { 1660. /* no nutrition: rots away, no message if you passed out */ 1661. if (!retcode) 1662. pline_The("corpse rots away completely."); 1663. if (carried(otmp)) 1664. useup(otmp); 1665. else 1666. useupf(otmp, 1L); 1667. retcode = 2; 1668. } 1669. 1670. if (!retcode) 1671. consume_oeaten(otmp, 2); /* oeaten >>= 2 */ 1672. } else if ((mnum == PM_COCKATRICE || mnum == PM_CHICKATRICE) 1673. && (Stone_resistance || Hallucination)) { 1674. pline("This tastes just like chicken!"); 1675. } else if (mnum == PM_FLOATING_EYE && u.umonnum == PM_RAVEN) { 1676. You("peck the eyeball with delight."); 1677. } else { 1678. /* yummy is always False for omnivores, palatable always True */ 1679. boolean yummy = (vegan(&mons[mnum]) 1680. ? (!carnivorous(youmonst.data) 1681. && herbivorous(youmonst.data)) 1682. : (carnivorous(youmonst.data) 1683. && !herbivorous(youmonst.data))), 1684. palatable = ((vegetarian(&mons[mnum]) 1685. ? herbivorous(youmonst.data) 1686. : carnivorous(youmonst.data)) 1687. && rn2(10) 1688. && ((rotted < 1) ? TRUE : !rn2(rotted+1))); 1689. const char *pmxnam = food_xname(otmp, FALSE); 1690. 1691. if (!strncmpi(pmxnam, "the ", 4)) 1692. pmxnam += 4; 1693. pline("%s%s %s %s%c", 1694. type_is_pname(&mons[mnum]) 1695. ? "" : the_unique_pm(&mons[mnum]) ? "The " : "This ", 1696. pmxnam, 1697. Hallucination ? "is" : "tastes", 1698. /* tiger reference is to TV ads for "Frosted Flakes", 1699. breakfast cereal targeted at kids by "Tony the tiger" */ 1700. Hallucination 1701. ? (yummy ? ((u.umonnum == PM_TIGER) ? "gr-r-reat" : "gnarly") 1702. : palatable ? "copacetic" : "grody") 1703. : (yummy ? "delicious" : palatable ? "okay" : "terrible"), 1704. (yummy || !palatable) ? '!' : '.'); 1705. } 1706. 1707. return retcode; 1708. } 1709.
start_eating
1710. /* called as you start to eat */ 1711. STATIC_OVL void 1712. start_eating(otmp) 1713. struct obj *otmp; 1714. { 1715. const char *old_nomovemsg, *save_nomovemsg; 1716. 1717. debugpline2("start_eating: %s (victual = %s)", 1718. /* note: fmt_ptr() returns a static buffer but supports 1719. several such so we don't need to copy the first result 1720. before calling it a second time */ 1721. fmt_ptr((genericptr_t) otmp), 1722. fmt_ptr((genericptr_t) context.victual.piece)); 1723. debugpline1("reqtime = %d", context.victual.reqtime); 1724. debugpline1("(original reqtime = %d)", objects[otmp->otyp].oc_delay); 1725. debugpline1("nmod = %d", context.victual.nmod); 1726. debugpline1("oeaten = %d", otmp->oeaten); 1727. context.victual.fullwarn = context.victual.doreset = FALSE; 1728. context.victual.eating = TRUE; 1729. 1730. if (otmp->otyp == CORPSE || otmp->globby) { 1731. cprefx(context.victual.piece->corpsenm); 1732. if (!context.victual.piece || !context.victual.eating) { 1733. /* rider revived, or died and lifesaved */ 1734. return; 1735. } 1736. } 1737. 1738. old_nomovemsg = nomovemsg; 1739. if (bite()) { 1740. /* survived choking, finish off food that's nearly done; 1741. need this to handle cockatrice eggs, fortune cookies, etc */ 1742. if (++context.victual.usedtime >= context.victual.reqtime) { 1743. /* don't want done_eating() to issue nomovemsg if it 1744. is due to vomit() called by bite() */ 1745. save_nomovemsg = nomovemsg; 1746. if (!old_nomovemsg) 1747. nomovemsg = 0; 1748. done_eating(FALSE); 1749. if (!old_nomovemsg) 1750. nomovemsg = save_nomovemsg; 1751. } 1752. return; 1753. } 1754. 1755. if (++context.victual.usedtime >= context.victual.reqtime) { 1756. /* print "finish eating" message if they just resumed -dlc */ 1757. done_eating(context.victual.reqtime > 1 ? TRUE : FALSE); 1758. return; 1759. } 1760. 1761. Sprintf(msgbuf, "eating %s", food_xname(otmp, TRUE)); 1762. set_occupation(eatfood, msgbuf, 0); 1763. } 1764.
fprefx
1765. /* 1766. * called on "first bite" of (non-corpse) food. 1767. * used for non-rotten non-tin non-corpse food 1768. */ 1769. STATIC_OVL void 1770. fprefx(otmp) 1771. struct obj *otmp; 1772. { 1773. switch (otmp->otyp) { 1774. case FOOD_RATION: 1775. if (u.uhunger <= 200) 1776. pline(Hallucination ? "Oh wow, like, superior, man!" 1777. : "That food really hit the spot!"); 1778. else if (u.uhunger <= 700) 1779. pline("That satiated your %s!", body_part(STOMACH)); 1780. break; 1781. case TRIPE_RATION: 1782. if (carnivorous(youmonst.data) && !humanoid(youmonst.data)) 1783. pline("That tripe ration was surprisingly good!"); 1784. else if (maybe_polyd(is_orc(youmonst.data), Race_if(PM_ORC))) 1785. pline(Hallucination ? "Tastes great! Less filling!" 1786. : "Mmm, tripe... not bad!"); 1787. else { 1788. pline("Yak - dog food!"); 1789. more_experienced(1, 0); 1790. newexplevel(); 1791. /* not cannibalism, but we use similar criteria 1792. for deciding whether to be sickened by this meal */ 1793. if (rn2(2) && !CANNIBAL_ALLOWED()) 1794. make_vomiting((long) rn1(context.victual.reqtime, 14), FALSE); 1795. } 1796. break; 1797. case LEMBAS_WAFER: 1798. if (maybe_polyd(is_orc(youmonst.data), Race_if(PM_ORC))) { 1799. pline("%s", "!#?&* elf kibble!"); 1800. break; 1801. } else if (maybe_polyd(is_elf(youmonst.data), Race_if(PM_ELF))) { 1802. pline("A little goes a long way."); 1803. break; 1804. } 1805. goto give_feedback; 1806. case MEATBALL: 1807. case MEAT_STICK: 1808. case HUGE_CHUNK_OF_MEAT: 1809. case MEAT_RING: 1810. goto give_feedback; 1811. case CLOVE_OF_GARLIC: 1812. if (is_undead(youmonst.data)) { 1813. make_vomiting((long) rn1(context.victual.reqtime, 5), FALSE); 1814. break; 1815. } 1816. /*FALLTHRU*/ 1817. default: 1818. if (otmp->otyp == SLIME_MOLD && !otmp->cursed 1819. && otmp->spe == context.current_fruit) { 1820. pline("My, that was a %s %s!", 1821. Hallucination ? "primo" : "yummy", 1822. singular(otmp, xname)); 1823. } else if (otmp->otyp == APPLE && otmp->cursed && !Sleep_resistance) { 1824. ; /* skip core joke; feedback deferred til fpostfx() */ 1825. 1826. #if defined(MAC) || defined(MACOSX) 1827. /* KMH -- Why should Unix have all the fun? 1828. We check MACOSX before UNIX to get the Apple-specific apple 1829. message; the '#if UNIX' code will still kick in for pear. */ 1830. } else if (otmp->otyp == APPLE) { 1831. pline("Delicious! Must be a Macintosh!"); 1832. #endif 1833. 1834. #ifdef UNIX 1835. } else if (otmp->otyp == APPLE || otmp->otyp == PEAR) { 1836. if (!Hallucination) { 1837. pline("Core dumped."); 1838. } else { 1839. /* This is based on an old Usenet joke, a fake a.out manual 1840. * page 1841. */ 1842. int x = rnd(100); 1843. 1844. pline("%s -- core dumped.", 1845. (x <= 75) 1846. ? "Segmentation fault" 1847. : (x <= 99) 1848. ? "Bus error" 1849. : "Yo' mama"); 1850. } 1851. #endif 1852. } else if (otmp->otyp == EGG && stale_egg(otmp)) { 1853. pline("Ugh. Rotten egg."); /* perhaps others like it */ 1854. /* increasing existing nausea means that it will take longer 1855. before eventual vomit, but also means that constitution 1856. will be abused more times before illness completes */ 1857. make_vomiting((Vomiting & TIMEOUT) + (long) d(10, 4), TRUE); 1858. } else { 1859. give_feedback: 1860. pline("This %s is %s", singular(otmp, xname), 1861. otmp->cursed 1862. ? (Hallucination ? "grody!" : "terrible!") 1863. : (otmp->otyp == CRAM_RATION 1864. || otmp->otyp == K_RATION 1865. || otmp->otyp == C_RATION) 1866. ? "bland." 1867. : Hallucination ? "gnarly!" : "delicious!"); 1868. } 1869. break; /* default */ 1870. } /* switch */ 1871. } 1872.
bounded_increase
1873. /* increment a combat intrinsic with limits on its growth */ 1874. STATIC_OVL int 1875. bounded_increase(old, inc, typ) 1876. int old, inc, typ; 1877. { 1878. int absold, absinc, sgnold, sgninc; 1879. 1880. /* don't include any amount coming from worn rings */ 1881. if (uright && uright->otyp == typ) 1882. old -= uright->spe; 1883. if (uleft && uleft->otyp == typ) 1884. old -= uleft->spe; 1885. absold = abs(old), absinc = abs(inc); 1886. sgnold = sgn(old), sgninc = sgn(inc); 1887. 1888. if (absinc == 0 || sgnold != sgninc || absold + absinc < 10) { 1889. ; /* use inc as-is */ 1890. } else if (absold + absinc < 20) { 1891. absinc = rnd(absinc); /* 1..n */ 1892. if (absold + absinc < 10) 1893. absinc = 10 - absold; 1894. inc = sgninc * absinc; 1895. } else if (absold + absinc < 40) { 1896. absinc = rn2(absinc) ? 1 : 0; 1897. if (absold + absinc < 20) 1898. absinc = rnd(20 - absold); 1899. inc = sgninc * absinc; 1900. } else { 1901. inc = 0; /* no further increase allowed via this method */ 1902. } 1903. return old + inc; 1904. } 1905.
accessory_has_effect
1906. STATIC_OVL void 1907. accessory_has_effect(otmp) 1908. struct obj *otmp; 1909. { 1910. pline("Magic spreads through your body as you digest the %s.", 1911. otmp->oclass == RING_CLASS ? "ring" : "amulet"); 1912. } 1913.
eataccessory
1914. STATIC_OVL void 1915. eataccessory(otmp) 1916. struct obj *otmp; 1917. { 1918. int typ = otmp->otyp; 1919. long oldprop; 1920. 1921. /* Note: rings are not so common that this is unbalancing. */ 1922. /* (How often do you even _find_ 3 rings of polymorph in a game?) */ 1923. oldprop = u.uprops[objects[typ].oc_oprop].intrinsic; 1924. if (otmp == uleft || otmp == uright) { 1925. Ring_gone(otmp); 1926. if (u.uhp <= 0) 1927. return; /* died from sink fall */ 1928. } 1929. otmp->known = otmp->dknown = 1; /* by taste */ 1930. if (!rn2(otmp->oclass == RING_CLASS ? 3 : 5)) { 1931. switch (otmp->otyp) { 1932. default: 1933. if (!objects[typ].oc_oprop) 1934. break; /* should never happen */ 1935. 1936. if (!(u.uprops[objects[typ].oc_oprop].intrinsic & FROMOUTSIDE)) 1937. accessory_has_effect(otmp); 1938. 1939. u.uprops[objects[typ].oc_oprop].intrinsic |= FROMOUTSIDE; 1940. 1941. switch (typ) { 1942. case RIN_SEE_INVISIBLE: 1943. set_mimic_blocking(); 1944. see_monsters(); 1945. if (Invis && !oldprop && !ESee_invisible 1946. && !perceives(youmonst.data) && !Blind) { 1947. newsym(u.ux, u.uy); 1948. pline("Suddenly you can see yourself."); 1949. makeknown(typ); 1950. } 1951. break; 1952. case RIN_INVISIBILITY: 1953. if (!oldprop && !EInvis && !BInvis && !See_invisible 1954. && !Blind) { 1955. newsym(u.ux, u.uy); 1956. Your("body takes on a %s transparency...", 1957. Hallucination ? "normal" : "strange"); 1958. makeknown(typ); 1959. } 1960. break; 1961. case RIN_PROTECTION_FROM_SHAPE_CHAN: 1962. rescham(); 1963. break; 1964. case RIN_LEVITATION: 1965. /* undo the `.intrinsic |= FROMOUTSIDE' done above */ 1966. u.uprops[LEVITATION].intrinsic = oldprop; 1967. if (!Levitation) { 1968. float_up(); 1969. incr_itimeout(&HLevitation, d(10, 20)); 1970. makeknown(typ); 1971. } 1972. break; 1973. } /* inner switch */ 1974. break; /* default case of outer switch */ 1975. 1976. case RIN_ADORNMENT: 1977. accessory_has_effect(otmp); 1978. if (adjattrib(A_CHA, otmp->spe, -1)) 1979. makeknown(typ); 1980. break; 1981. case RIN_GAIN_STRENGTH: 1982. accessory_has_effect(otmp); 1983. if (adjattrib(A_STR, otmp->spe, -1)) 1984. makeknown(typ); 1985. break; 1986. case RIN_GAIN_CONSTITUTION: 1987. accessory_has_effect(otmp); 1988. if (adjattrib(A_CON, otmp->spe, -1)) 1989. makeknown(typ); 1990. break; 1991. case RIN_INCREASE_ACCURACY: 1992. accessory_has_effect(otmp); 1993. u.uhitinc = (schar) bounded_increase((int) u.uhitinc, otmp->spe, 1994. RIN_INCREASE_ACCURACY); 1995. break; 1996. case RIN_INCREASE_DAMAGE: 1997. accessory_has_effect(otmp); 1998. u.udaminc = (schar) bounded_increase((int) u.udaminc, otmp->spe, 1999. RIN_INCREASE_DAMAGE); 2000. break; 2001. case RIN_PROTECTION: 2002. accessory_has_effect(otmp); 2003. HProtection |= FROMOUTSIDE; 2004. u.ublessed = bounded_increase(u.ublessed, otmp->spe, 2005. RIN_PROTECTION); 2006. context.botl = 1; 2007. break; 2008. case RIN_FREE_ACTION: 2009. /* Give sleep resistance instead */ 2010. if (!(HSleep_resistance & FROMOUTSIDE)) 2011. accessory_has_effect(otmp); 2012. if (!Sleep_resistance) 2013. You_feel("wide awake."); 2014. HSleep_resistance |= FROMOUTSIDE; 2015. break; 2016. case AMULET_OF_CHANGE: 2017. accessory_has_effect(otmp); 2018. makeknown(typ); 2019. change_sex(); 2020. You("are suddenly very %s!", 2021. flags.female ? "feminine" : "masculine"); 2022. context.botl = 1; 2023. break; 2024. case AMULET_OF_UNCHANGING: 2025. /* un-change: it's a pun */ 2026. if (!Unchanging && Upolyd) { 2027. accessory_has_effect(otmp); 2028. makeknown(typ); 2029. rehumanize(); 2030. } 2031. break; 2032. case AMULET_OF_STRANGULATION: /* bad idea! */ 2033. /* no message--this gives no permanent effect */ 2034. choke(otmp); 2035. break; 2036. case AMULET_OF_RESTFUL_SLEEP: { /* another bad idea! */ 2037. long newnap = (long) rnd(100), oldnap = (HSleepy & TIMEOUT); 2038. 2039. if (!(HSleepy & FROMOUTSIDE)) 2040. accessory_has_effect(otmp); 2041. HSleepy |= FROMOUTSIDE; 2042. /* might also be wearing one; use shorter of two timeouts */ 2043. if (newnap < oldnap || oldnap == 0L) 2044. HSleepy = (HSleepy & ~TIMEOUT) | newnap; 2045. break; 2046. } 2047. case RIN_SUSTAIN_ABILITY: 2048. case AMULET_OF_LIFE_SAVING: 2049. case AMULET_OF_REFLECTION: /* nice try */ 2050. /* can't eat Amulet of Yendor or fakes, 2051. * and no oc_prop even if you could -3. 2052. */ 2053. break; 2054. } 2055. } 2056. } 2057.
eatspecial
2058. /* called after eating non-food */ 2059. STATIC_OVL void 2060. eatspecial() 2061. { 2062. struct obj *otmp = context.victual.piece; 2063. 2064. /* lesshungry wants an occupation to handle choke messages correctly */ 2065. set_occupation(eatfood, "eating non-food", 0); 2066. lesshungry(context.victual.nmod); 2067. occupation = 0; 2068. context.victual.piece = (struct obj *) 0; 2069. context.victual.o_id = 0; 2070. context.victual.eating = 0; 2071. if (otmp->oclass == COIN_CLASS) { 2072. if (carried(otmp)) 2073. useupall(otmp); 2074. else 2075. useupf(otmp, otmp->quan); 2076. vault_gd_watching(GD_EATGOLD); 2077. return; 2078. } 2079. if (objects[otmp->otyp].oc_material == PAPER) { 2080. #ifdef MAIL 2081. if (otmp->otyp == SCR_MAIL) 2082. /* no nutrition */ 2083. pline("This junk mail is less than satisfying."); 2084. else 2085. #endif 2086. if (otmp->otyp == SCR_SCARE_MONSTER) 2087. /* to eat scroll, hero is currently polymorphed into a monster */ 2088. pline("Yuck%c", otmp->blessed ? '!' : '.'); 2089. else if (otmp->oclass == SCROLL_CLASS 2090. /* check description after checking for specific scrolls */ 2091. && !strcmpi(OBJ_DESCR(objects[otmp->otyp]), "YUM YUM")) 2092. pline("Yum%c", otmp->blessed ? '!' : '.'); 2093. else 2094. pline("Needs salt..."); 2095. } 2096. if (otmp->oclass == POTION_CLASS) { 2097. otmp->quan++; /* dopotion() does a useup() */ 2098. (void) dopotion(otmp); 2099. } else if (otmp->oclass == RING_CLASS || otmp->oclass == AMULET_CLASS) { 2100. eataccessory(otmp); 2101. } else if (otmp->otyp == LEASH && otmp->leashmon) { 2102. o_unleash(otmp); 2103. } 2104. 2105. /* KMH -- idea by "Tommy the Terrorist" */ 2106. if (otmp->otyp == TRIDENT && !otmp->cursed) { 2107. /* sugarless chewing gum which used to be heavily advertised on TV */ 2108. pline(Hallucination ? "Four out of five dentists agree." 2109. : "That was pure chewing satisfaction!"); 2110. exercise(A_WIS, TRUE); 2111. } 2112. if (otmp->otyp == FLINT && !otmp->cursed) { 2113. /* chewable vitamin for kids based on "The Flintstones" TV cartoon */ 2114. pline("Yabba-dabba delicious!"); 2115. exercise(A_CON, TRUE); 2116. } 2117. 2118. if (otmp == uwep && otmp->quan == 1L) 2119. uwepgone(); 2120. if (otmp == uquiver && otmp->quan == 1L) 2121. uqwepgone(); 2122. if (otmp == uswapwep && otmp->quan == 1L) 2123. uswapwepgone(); 2124. 2125. if (otmp == uball) 2126. unpunish(); 2127. if (otmp == uchain) 2128. unpunish(); /* but no useup() */ 2129. else if (carried(otmp)) 2130. useup(otmp); 2131. else 2132. useupf(otmp, 1L); 2133. } 2134. 2135. /* NOTE: the order of these words exactly corresponds to the 2136. order of oc_material values #define'd in objclass.h. */ 2137. static const char *foodwords[] = { 2138. "meal", "liquid", "wax", "food", "meat", "paper", 2139. "cloth", "leather", "wood", "bone", "scale", "metal", 2140. "metal", "metal", "silver", "gold", "platinum", "mithril", 2141. "plastic", "glass", "rich food", "stone" 2142. }; 2143.
foodword
2144. STATIC_OVL const char * 2145. foodword(otmp) 2146. struct obj *otmp; 2147. { 2148. if (otmp->oclass == FOOD_CLASS) 2149. return "food"; 2150. if (otmp->oclass == GEM_CLASS && objects[otmp->otyp].oc_material == GLASS 2151. && otmp->dknown) 2152. makeknown(otmp->otyp); 2153. return foodwords[objects[otmp->otyp].oc_material]; 2154. } 2155.
fpostfx
2156. /* called after consuming (non-corpse) food */ 2157. STATIC_OVL void 2158. fpostfx(otmp) 2159. struct obj *otmp; 2160. { 2161. switch (otmp->otyp) { 2162. case SPRIG_OF_WOLFSBANE: 2163. if (u.ulycn >= LOW_PM || is_were(youmonst.data)) 2164. you_unwere(TRUE); 2165. break; 2166. case CARROT: 2167. if (!u.uswallow 2168. || !attacktype_fordmg(u.ustuck->data, AT_ENGL, AD_BLND)) 2169. make_blinded((long) u.ucreamed, TRUE); 2170. break; 2171. case FORTUNE_COOKIE: 2172. outrumor(bcsign(otmp), BY_COOKIE); 2173. if (!Blind) 2174. u.uconduct.literate++; 2175. break; 2176. case LUMP_OF_ROYAL_JELLY: 2177. /* This stuff seems to be VERY healthy! */ 2178. gainstr(otmp, 1, TRUE); 2179. if (Upolyd) { 2180. u.mh += otmp->cursed ? -rnd(20) : rnd(20); 2181. if (u.mh > u.mhmax) { 2182. if (!rn2(17)) 2183. u.mhmax++; 2184. u.mh = u.mhmax; 2185. } else if (u.mh <= 0) { 2186. rehumanize(); 2187. } 2188. } else { 2189. u.uhp += otmp->cursed ? -rnd(20) : rnd(20); 2190. if (u.uhp > u.uhpmax) { 2191. if (!rn2(17)) 2192. u.uhpmax++; 2193. u.uhp = u.uhpmax; 2194. } else if (u.uhp <= 0) { 2195. killer.format = KILLED_BY_AN; 2196. Strcpy(killer.name, "rotten lump of royal jelly"); 2197. done(POISONING); 2198. } 2199. } 2200. if (!otmp->cursed) 2201. heal_legs(); 2202. break; 2203. case EGG: 2204. if (flesh_petrifies(&mons[otmp->corpsenm])) { 2205. if (!Stone_resistance 2206. && !(poly_when_stoned(youmonst.data) 2207. && polymon(PM_STONE_GOLEM))) { 2208. if (!Stoned) { 2209. Sprintf(killer.name, "%s egg", 2210. mons[otmp->corpsenm].mname); 2211. make_stoned(5L, (char *) 0, KILLED_BY_AN, killer.name); 2212. } 2213. } 2214. /* note: no "tastes like chicken" message for eggs */ 2215. } 2216. break; 2217. case EUCALYPTUS_LEAF: 2218. if (Sick && !otmp->cursed) 2219. make_sick(0L, (char *) 0, TRUE, SICK_ALL); 2220. if (Vomiting && !otmp->cursed) 2221. make_vomiting(0L, TRUE); 2222. break; 2223. case APPLE: 2224. if (otmp->cursed && !Sleep_resistance) { 2225. /* Snow White; 'poisoned' applies to [a subset of] weapons, 2226. not food, so we substitute cursed; fortunately our hero 2227. won't have to wait for a prince to be rescued/revived */ 2228. if (Race_if(PM_DWARF) && Hallucination) 2229. verbalize("Heigh-ho, ho-hum, I think I'll skip work today."); 2230. else if (Deaf || !flags.acoustics) 2231. You("fall asleep."); 2232. else 2233. You_hear("sinister laughter as you fall asleep..."); 2234. fall_asleep(-rn1(11, 20), TRUE); 2235. } 2236. break; 2237. } 2238. return; 2239. } 2240.
leather_cover
2241. #if 0 2242. /* intended for eating a spellbook while polymorphed, but not used; 2243. "leather" applied to appearance, not composition, and has been 2244. changed to "leathery" to reflect that */ 2245. STATIC_DCL boolean FDECL(leather_cover, (struct obj *)); 2246. 2247. STATIC_OVL boolean 2248. leather_cover(otmp) 2249. struct obj *otmp; 2250. { 2251. const char *odesc = OBJ_DESCR(objects[otmp->otyp]); 2252. 2253. if (odesc && (otmp->oclass == SPBOOK_CLASS)) { 2254. if (!strcmp(odesc, "leather")) 2255. return TRUE; 2256. } 2257. return FALSE; 2258. } 2259. #endif 2260.
edibility_prompts
2261. /* 2262. * return 0 if the food was not dangerous. 2263. * return 1 if the food was dangerous and you chose to stop. 2264. * return 2 if the food was dangerous and you chose to eat it anyway. 2265. */ 2266. STATIC_OVL int 2267. edibility_prompts(otmp) 2268. struct obj *otmp; 2269. { 2270. /* Blessed food detection grants hero a one-use 2271. * ability to detect food that is unfit for consumption 2272. * or dangerous and avoid it. 2273. */ 2274. char buf[BUFSZ], foodsmell[BUFSZ], 2275. it_or_they[QBUFSZ], eat_it_anyway[QBUFSZ]; 2276. boolean cadaver = (otmp->otyp == CORPSE || otmp->globby), 2277. stoneorslime = FALSE; 2278. int material = objects[otmp->otyp].oc_material, mnum = otmp->corpsenm; 2279. long rotted = 0L; 2280. 2281. Strcpy(foodsmell, Tobjnam(otmp, "smell")); 2282. Strcpy(it_or_they, (otmp->quan == 1L) ? "it" : "they"); 2283. Sprintf(eat_it_anyway, "Eat %s anyway?", 2284. (otmp->quan == 1L) ? "it" : "one"); 2285. 2286. if (cadaver || otmp->otyp == EGG || otmp->otyp == TIN) { 2287. /* These checks must match those in eatcorpse() */ 2288. stoneorslime = (flesh_petrifies(&mons[mnum]) && !Stone_resistance 2289. && !poly_when_stoned(youmonst.data)); 2290. 2291. if (mnum == PM_GREEN_SLIME || otmp->otyp == GLOB_OF_GREEN_SLIME) 2292. stoneorslime = (!Unchanging && !slimeproof(youmonst.data)); 2293. 2294. if (cadaver && !nonrotting_corpse(mnum)) { 2295. long age = peek_at_iced_corpse_age(otmp); 2296. 2297. /* worst case rather than random 2298. in this calculation to force prompt */ 2299. rotted = (monstermoves - age) / (10L + 0 /* was rn2(20) */); 2300. if (otmp->cursed) 2301. rotted += 2L; 2302. else if (otmp->blessed) 2303. rotted -= 2L; 2304. } 2305. } 2306. 2307. /* 2308. * These problems with food should be checked in 2309. * order from most detrimental to least detrimental. 2310. */ 2311. if (cadaver && mnum != PM_ACID_BLOB && rotted > 5L && !Sick_resistance) { 2312. /* Tainted meat */ 2313. Sprintf(buf, "%s like %s could be tainted! %s", foodsmell, it_or_they, 2314. eat_it_anyway); 2315. if (yn_function(buf, ynchars, 'n') == 'n') 2316. return 1; 2317. else 2318. return 2; 2319. } 2320. if (stoneorslime) { 2321. Sprintf(buf, "%s like %s could be something very dangerous! %s", 2322. foodsmell, it_or_they, eat_it_anyway); 2323. if (yn_function(buf, ynchars, 'n') == 'n') 2324. return 1; 2325. else 2326. return 2; 2327. } 2328. if (otmp->orotten || (cadaver && rotted > 3L)) { 2329. /* Rotten */ 2330. Sprintf(buf, "%s like %s could be rotten! %s", foodsmell, it_or_they, 2331. eat_it_anyway); 2332. if (yn_function(buf, ynchars, 'n') == 'n') 2333. return 1; 2334. else 2335. return 2; 2336. } 2337. if (cadaver && poisonous(&mons[mnum]) && !Poison_resistance) { 2338. /* poisonous */ 2339. Sprintf(buf, "%s like %s might be poisonous! %s", foodsmell, 2340. it_or_they, eat_it_anyway); 2341. if (yn_function(buf, ynchars, 'n') == 'n') 2342. return 1; 2343. else 2344. return 2; 2345. } 2346. if (otmp->otyp == APPLE && otmp->cursed && !Sleep_resistance) { 2347. /* causes sleep, for long enough to be dangerous */ 2348. Sprintf(buf, "%s like %s might have been poisoned. %s", foodsmell, 2349. it_or_they, eat_it_anyway); 2350. return (yn_function(buf, ynchars, 'n') == 'n') ? 1 : 2; 2351. } 2352. if (cadaver && !vegetarian(&mons[mnum]) && !u.uconduct.unvegetarian 2353. && Role_if(PM_MONK)) { 2354. Sprintf(buf, "%s unhealthy. %s", foodsmell, eat_it_anyway); 2355. if (yn_function(buf, ynchars, 'n') == 'n') 2356. return 1; 2357. else 2358. return 2; 2359. } 2360. if (cadaver && acidic(&mons[mnum]) && !Acid_resistance) { 2361. Sprintf(buf, "%s rather acidic. %s", foodsmell, eat_it_anyway); 2362. if (yn_function(buf, ynchars, 'n') == 'n') 2363. return 1; 2364. else 2365. return 2; 2366. } 2367. if (Upolyd && u.umonnum == PM_RUST_MONSTER && is_metallic(otmp) 2368. && otmp->oerodeproof) { 2369. Sprintf(buf, "%s disgusting to you right now. %s", foodsmell, 2370. eat_it_anyway); 2371. if (yn_function(buf, ynchars, 'n') == 'n') 2372. return 1; 2373. else 2374. return 2; 2375. } 2376. 2377. /* 2378. * Breaks conduct, but otherwise safe. 2379. */ 2380. if (!u.uconduct.unvegan 2381. && ((material == LEATHER || material == BONE 2382. || material == DRAGON_HIDE || material == WAX) 2383. || (cadaver && !vegan(&mons[mnum])))) { 2384. Sprintf(buf, "%s foul and unfamiliar to you. %s", foodsmell, 2385. eat_it_anyway); 2386. if (yn_function(buf, ynchars, 'n') == 'n') 2387. return 1; 2388. else 2389. return 2; 2390. } 2391. if (!u.uconduct.unvegetarian 2392. && ((material == LEATHER || material == BONE 2393. || material == DRAGON_HIDE) 2394. || (cadaver && !vegetarian(&mons[mnum])))) { 2395. Sprintf(buf, "%s unfamiliar to you. %s", foodsmell, eat_it_anyway); 2396. if (yn_function(buf, ynchars, 'n') == 'n') 2397. return 1; 2398. else 2399. return 2; 2400. } 2401. 2402. if (cadaver && mnum != PM_ACID_BLOB && rotted > 5L && Sick_resistance) { 2403. /* Tainted meat with Sick_resistance */ 2404. Sprintf(buf, "%s like %s could be tainted! %s", foodsmell, it_or_they, 2405. eat_it_anyway); 2406. if (yn_function(buf, ynchars, 'n') == 'n') 2407. return 1; 2408. else 2409. return 2; 2410. } 2411. return 0; 2412. } 2413.
doeat
2414. /* 'e' command */ 2415. int 2416. doeat() 2417. { 2418. struct obj *otmp; 2419. int basenutrit; /* nutrition of full item */ 2420. boolean dont_start = FALSE, nodelicious = FALSE; 2421. 2422. if (Strangled) { 2423. pline("If you can't breathe air, how can you consume solids?"); 2424. return 0; 2425. } 2426. if (!(otmp = floorfood("eat", 0))) 2427. return 0; 2428. if (check_capacity((char *) 0)) 2429. return 0; 2430. 2431. if (u.uedibility) { 2432. int res = edibility_prompts(otmp); 2433. 2434. if (res) { 2435. Your( 2436. "%s stops tingling and your sense of smell returns to normal.", 2437. body_part(NOSE)); 2438. u.uedibility = 0; 2439. if (res == 1) 2440. return 0; 2441. } 2442. } 2443. 2444. /* We have to make non-foods take 1 move to eat, unless we want to 2445. * do ridiculous amounts of coding to deal with partly eaten plate 2446. * mails, players who polymorph back to human in the middle of their 2447. * metallic meal, etc.... 2448. */ 2449. if (!is_edible(otmp)) { 2450. You("cannot eat that!"); 2451. return 0; 2452. } else if ((otmp->owornmask & (W_ARMOR | W_TOOL | W_AMUL | W_SADDLE)) 2453. != 0) { 2454. /* let them eat rings */ 2455. You_cant("eat %s you're wearing.", something); 2456. return 0; 2457. } else if (!(carried(otmp) ? retouch_object(&otmp, FALSE) 2458. : touch_artifact(otmp, &youmonst))) { 2459. return 1; /* got blasted so use a turn */ 2460. } 2461. if (is_metallic(otmp) && u.umonnum == PM_RUST_MONSTER 2462. && otmp->oerodeproof) { 2463. otmp->rknown = TRUE; 2464. if (otmp->quan > 1L) { 2465. if (!carried(otmp)) 2466. (void) splitobj(otmp, otmp->quan - 1L); 2467. else 2468. otmp = splitobj(otmp, 1L); 2469. } 2470. pline("Ulch - that %s was rustproofed!", xname(otmp)); 2471. /* The regurgitated object's rustproofing is gone now */ 2472. otmp->oerodeproof = 0; 2473. make_stunned((HStun & TIMEOUT) + (long) rn2(10), TRUE); 2474. /* 2475. * We don't expect rust monsters to be wielding welded weapons 2476. * or wearing cursed rings which were rustproofed, but guard 2477. * against the possibility just in case. 2478. */ 2479. if (welded(otmp) || (otmp->cursed && (otmp->owornmask & W_RING))) { 2480. otmp->bknown = 1; /* for ring; welded() does this for weapon */ 2481. You("spit out %s.", the(xname(otmp))); 2482. } else { 2483. You("spit %s out onto the %s.", the(xname(otmp)), 2484. surface(u.ux, u.uy)); 2485. if (carried(otmp)) { 2486. /* no need to check for leash in use; it's not metallic */ 2487. if (otmp->owornmask) 2488. remove_worn_item(otmp, FALSE); 2489. freeinv(otmp); 2490. dropy(otmp); 2491. } 2492. stackobj(otmp); 2493. } 2494. return 1; 2495. } 2496. /* KMH -- Slow digestion is... indigestible */ 2497. if (otmp->otyp == RIN_SLOW_DIGESTION) { 2498. pline("This ring is indigestible!"); 2499. (void) rottenfood(otmp); 2500. if (otmp->dknown && !objects[otmp->otyp].oc_name_known 2501. && !objects[otmp->otyp].oc_uname) 2502. docall(otmp); 2503. return 1; 2504. } 2505. if (otmp->oclass != FOOD_CLASS) { 2506. int material; 2507. 2508. context.victual.reqtime = 1; 2509. context.victual.piece = otmp; 2510. context.victual.o_id = otmp->o_id; 2511. /* Don't split it, we don't need to if it's 1 move */ 2512. context.victual.usedtime = 0; 2513. context.victual.canchoke = (u.uhs == SATIATED); 2514. /* Note: gold weighs 1 pt. for each 1000 pieces (see 2515. pickup.c) so gold and non-gold is consistent. */ 2516. if (otmp->oclass == COIN_CLASS) 2517. basenutrit = ((otmp->quan > 200000L) 2518. ? 2000 2519. : (int) (otmp->quan / 100L)); 2520. else if (otmp->oclass == BALL_CLASS || otmp->oclass == CHAIN_CLASS) 2521. basenutrit = weight(otmp); 2522. /* oc_nutrition is usually weight anyway */ 2523. else 2524. basenutrit = objects[otmp->otyp].oc_nutrition; 2525. #ifdef MAIL 2526. if (otmp->otyp == SCR_MAIL) { 2527. basenutrit = 0; 2528. nodelicious = TRUE; 2529. } 2530. #endif 2531. context.victual.nmod = basenutrit; 2532. context.victual.eating = TRUE; /* needed for lesshungry() */ 2533. 2534. material = objects[otmp->otyp].oc_material; 2535. if (material == LEATHER || material == BONE 2536. || material == DRAGON_HIDE) { 2537. u.uconduct.unvegan++; 2538. violated_vegetarian(); 2539. } else if (material == WAX) 2540. u.uconduct.unvegan++; 2541. u.uconduct.food++; 2542. 2543. if (otmp->cursed) { 2544. (void) rottenfood(otmp); 2545. nodelicious = TRUE; 2546. } else if (objects[otmp->otyp].oc_material == PAPER) 2547. nodelicious = TRUE; 2548. 2549. if (otmp->oclass == WEAPON_CLASS && otmp->opoisoned) { 2550. pline("Ecch - that must have been poisonous!"); 2551. if (!Poison_resistance) { 2552. losestr(rnd(4)); 2553. losehp(rnd(15), xname(otmp), KILLED_BY_AN); 2554. } else 2555. You("seem unaffected by the poison."); 2556. } else if (!nodelicious) { 2557. pline("%s%s is delicious!", 2558. (obj_is_pname(otmp) 2559. && otmp->oartifact < ART_ORB_OF_DETECTION) 2560. ? "" 2561. : "This ", 2562. (otmp->oclass == COIN_CLASS) 2563. ? foodword(otmp) 2564. : singular(otmp, xname)); 2565. } 2566. eatspecial(); 2567. return 1; 2568. } 2569. 2570. if (otmp == context.victual.piece) { 2571. /* If they weren't able to choke, they don't suddenly become able to 2572. * choke just because they were interrupted. On the other hand, if 2573. * they were able to choke before, if they lost food it's possible 2574. * they shouldn't be able to choke now. 2575. */ 2576. if (u.uhs != SATIATED) 2577. context.victual.canchoke = FALSE; 2578. context.victual.o_id = 0; 2579. context.victual.piece = touchfood(otmp); 2580. if (context.victual.piece) 2581. context.victual.o_id = context.victual.piece->o_id; 2582. You("resume your meal."); 2583. start_eating(context.victual.piece); 2584. return 1; 2585. } 2586. 2587. /* nothing in progress - so try to find something. */ 2588. /* tins are a special case */ 2589. /* tins must also check conduct separately in case they're discarded */ 2590. if (otmp->otyp == TIN) { 2591. start_tin(otmp); 2592. return 1; 2593. } 2594. 2595. /* KMH, conduct */ 2596. u.uconduct.food++; 2597. 2598. context.victual.o_id = 0; 2599. context.victual.piece = otmp = touchfood(otmp); 2600. if (context.victual.piece) 2601. context.victual.o_id = context.victual.piece->o_id; 2602. context.victual.usedtime = 0; 2603. 2604. /* Now we need to calculate delay and nutritional info. 2605. * The base nutrition calculated here and in eatcorpse() accounts 2606. * for normal vs. rotten food. The reqtime and nutrit values are 2607. * then adjusted in accordance with the amount of food left. 2608. */ 2609. if (otmp->otyp == CORPSE || otmp->globby) { 2610. int tmp = eatcorpse(otmp); 2611. 2612. if (tmp == 2) { 2613. /* used up */ 2614. context.victual.piece = (struct obj *) 0; 2615. context.victual.o_id = 0; 2616. return 1; 2617. } else if (tmp) 2618. dont_start = TRUE; 2619. /* if not used up, eatcorpse sets up reqtime and may modify oeaten */ 2620. } else { 2621. /* No checks for WAX, LEATHER, BONE, DRAGON_HIDE. These are 2622. * all handled in the != FOOD_CLASS case, above. 2623. */ 2624. switch (objects[otmp->otyp].oc_material) { 2625. case FLESH: 2626. u.uconduct.unvegan++; 2627. if (otmp->otyp != EGG) { 2628. violated_vegetarian(); 2629. } 2630. break; 2631. 2632. default: 2633. if (otmp->otyp == PANCAKE || otmp->otyp == FORTUNE_COOKIE /*eggs*/ 2634. || otmp->otyp == CREAM_PIE || otmp->otyp == CANDY_BAR /*milk*/ 2635. || otmp->otyp == LUMP_OF_ROYAL_JELLY) 2636. u.uconduct.unvegan++; 2637. break; 2638. } 2639. 2640. context.victual.reqtime = objects[otmp->otyp].oc_delay; 2641. if (otmp->otyp != FORTUNE_COOKIE 2642. && (otmp->cursed || (!nonrotting_food(otmp->otyp) 2643. && (monstermoves - otmp->age) 2644. > (otmp->blessed ? 50L : 30L) 2645. && (otmp->orotten || !rn2(7))))) { 2646. if (rottenfood(otmp)) { 2647. otmp->orotten = TRUE; 2648. dont_start = TRUE; 2649. } 2650. consume_oeaten(otmp, 1); /* oeaten >>= 1 */ 2651. } else 2652. fprefx(otmp); 2653. } 2654. 2655. /* re-calc the nutrition */ 2656. basenutrit = (int) obj_nutrition(otmp); 2657. 2658. debugpline3( 2659. "before rounddiv: victual.reqtime == %d, oeaten == %d, basenutrit == %d", 2660. context.victual.reqtime, otmp->oeaten, basenutrit); 2661. 2662. context.victual.reqtime = (basenutrit == 0) ? 0 2663. : rounddiv(context.victual.reqtime * (long) otmp->oeaten, basenutrit); 2664. 2665. debugpline1("after rounddiv: victual.reqtime == %d", 2666. context.victual.reqtime); 2667. /* 2668. * calculate the modulo value (nutrit. units per round eating) 2669. * note: this isn't exact - you actually lose a little nutrition due 2670. * to this method. 2671. * TODO: add in a "remainder" value to be given at the end of the meal. 2672. */ 2673. if (context.victual.reqtime == 0 || otmp->oeaten == 0) 2674. /* possible if most has been eaten before */ 2675. context.victual.nmod = 0; 2676. else if ((int) otmp->oeaten >= context.victual.reqtime) 2677. context.victual.nmod = -((int) otmp->oeaten 2678. / context.victual.reqtime); 2679. else 2680. context.victual.nmod = context.victual.reqtime % otmp->oeaten; 2681. context.victual.canchoke = (u.uhs == SATIATED); 2682. 2683. if (!dont_start) 2684. start_eating(otmp); 2685. return 1; 2686. } 2687.
use_tin_opener
2688. int 2689. use_tin_opener(obj) 2690. struct obj *obj; 2691. { 2692. struct obj *otmp; 2693. int res = 0; 2694. 2695. if (!carrying(TIN)) { 2696. You("have no tin to open."); 2697. return 0; 2698. } 2699. 2700. if (obj != uwep) { 2701. if (obj->cursed && obj->bknown) { 2702. char qbuf[QBUFSZ]; 2703. 2704. if (ynq(safe_qbuf(qbuf, "Really wield ", "?", 2705. obj, doname, thesimpleoname, "that")) != 'y') 2706. return 0; 2707. } 2708. if (!wield_tool(obj, "use")) 2709. return 0; 2710. res = 1; 2711. } 2712. 2713. otmp = getobj(comestibles, "open"); 2714. if (!otmp) 2715. return res; 2716. 2717. start_tin(otmp); 2718. return 1; 2719. } 2720.
bite
2721. /* Take a single bite from a piece of food, checking for choking and 2722. * modifying usedtime. Returns 1 if they choked and survived, 0 otherwise. 2723. */ 2724. STATIC_OVL int 2725. bite() 2726. { 2727. if (context.victual.canchoke && u.uhunger >= 2000) { 2728. choke(context.victual.piece); 2729. return 1; 2730. } 2731. if (context.victual.doreset) { 2732. do_reset_eat(); 2733. return 0; 2734. } 2735. force_save_hs = TRUE; 2736. if (context.victual.nmod < 0) { 2737. lesshungry(-context.victual.nmod); 2738. consume_oeaten(context.victual.piece, 2739. context.victual.nmod); /* -= -nmod */ 2740. } else if (context.victual.nmod > 0 2741. && (context.victual.usedtime % context.victual.nmod)) { 2742. lesshungry(1); 2743. consume_oeaten(context.victual.piece, -1); /* -= 1 */ 2744. } 2745. force_save_hs = FALSE; 2746. recalc_wt(); 2747. return 0; 2748. } 2749.
gethungry
2750. /* as time goes by - called by moveloop(every move) & domove(melee attack) */ 2751. void 2752. gethungry() 2753. { 2754. if (u.uinvulnerable) 2755. return; /* you don't feel hungrier */ 2756. 2757. /* being polymorphed into a creature which doesn't eat prevents 2758. this first uhunger decrement, but to stay in such form the hero 2759. will need to wear an Amulet of Unchanging so still burn a small 2760. amount of nutrition in the 'moves % 20' ring/amulet check below */ 2761. if ((!Unaware || !rn2(10)) /* slow metabolic rate while asleep */ 2762. && (carnivorous(youmonst.data) 2763. || herbivorous(youmonst.data) 2764. || metallivorous(youmonst.data)) 2765. && !Slow_digestion) 2766. u.uhunger--; /* ordinary food consumption */ 2767. 2768. if (moves % 2) { /* odd turns */ 2769. /* Regeneration uses up food, unless due to an artifact */ 2770. if ((HRegeneration & ~FROMFORM) 2771. || (ERegeneration & ~(W_ARTI | W_WEP))) 2772. u.uhunger--; 2773. if (near_capacity() > SLT_ENCUMBER) 2774. u.uhunger--; 2775. } else { /* even turns */ 2776. if (Hunger) 2777. u.uhunger--; 2778. /* Conflict uses up food too */ 2779. if (HConflict || (EConflict & (~W_ARTI))) 2780. u.uhunger--; 2781. /* +0 charged rings don't do anything, so don't affect hunger. 2782. Slow digestion cancels move hunger but still causes ring hunger. */ 2783. switch ((int) (moves % 20)) { /* note: use even cases only */ 2784. case 4: 2785. if (uleft && (uleft->spe || !objects[uleft->otyp].oc_charged)) 2786. u.uhunger--; 2787. break; 2788. case 8: 2789. if (uamul) 2790. u.uhunger--; 2791. break; 2792. case 12: 2793. if (uright && (uright->spe || !objects[uright->otyp].oc_charged)) 2794. u.uhunger--; 2795. break; 2796. case 16: 2797. if (u.uhave.amulet) 2798. u.uhunger--; 2799. break; 2800. default: 2801. break; 2802. } 2803. } 2804. newuhs(TRUE); 2805. } 2806.
morehungry
2807. /* called after vomiting and after performing feats of magic */ 2808. void 2809. morehungry(num) 2810. int num; 2811. { 2812. u.uhunger -= num; 2813. newuhs(TRUE); 2814. } 2815.
lesshungry
2816. /* called after eating (and after drinking fruit juice) */ 2817. void 2818. lesshungry(num) 2819. int num; 2820. { 2821. /* See comments in newuhs() for discussion on force_save_hs */ 2822. boolean iseating = (occupation == eatfood) || force_save_hs; 2823. 2824. debugpline1("lesshungry(%d)", num); 2825. u.uhunger += num; 2826. if (u.uhunger >= 2000) { 2827. if (!iseating || context.victual.canchoke) { 2828. if (iseating) { 2829. choke(context.victual.piece); 2830. reset_eat(); 2831. } else 2832. choke(occupation == opentin ? context.tin.tin 2833. : (struct obj *) 0); 2834. /* no reset_eat() */ 2835. } 2836. } else { 2837. /* Have lesshungry() report when you're nearly full so all eating 2838. * warns when you're about to choke. 2839. */ 2840. if (u.uhunger >= 1500) { 2841. if (!context.victual.eating 2842. || (context.victual.eating && !context.victual.fullwarn)) { 2843. pline("You're having a hard time getting all of it down."); 2844. nomovemsg = "You're finally finished."; 2845. if (!context.victual.eating) { 2846. multi = -2; 2847. } else { 2848. context.victual.fullwarn = TRUE; 2849. if (context.victual.canchoke 2850. && context.victual.reqtime > 1) { 2851. /* a one-gulp food will not survive a stop */ 2852. if (yn_function("Continue eating?", ynchars, 'n') 2853. != 'y') { 2854. reset_eat(); 2855. nomovemsg = (char *) 0; 2856. } 2857. } 2858. } 2859. } 2860. } 2861. } 2862. newuhs(FALSE); 2863. } 2864.
unfaint
2865. STATIC_PTR 2866. int 2867. unfaint(VOID_ARGS) 2868. { 2869. (void) Hear_again(); 2870. if (u.uhs > FAINTING) 2871. u.uhs = FAINTING; 2872. stop_occupation(); 2873. context.botl = 1; 2874. return 0; 2875. } 2876.
is_fainted
2877. boolean 2878. is_fainted() 2879. { 2880. return (boolean) (u.uhs == FAINTED); 2881. } 2882.
reset_faint
2883. /* call when a faint must be prematurely terminated */ 2884. void 2885. reset_faint() 2886. { 2887. if (afternmv == unfaint) 2888. unmul("You revive."); 2889. } 2890.
newuhs
2891. /* compute and comment on your (new?) hunger status */ 2892. void 2893. newuhs(incr) 2894. boolean incr; 2895. { 2896. unsigned newhs; 2897. static unsigned save_hs; 2898. static boolean saved_hs = FALSE; 2899. int h = u.uhunger; 2900. 2901. newhs = (h > 1000) 2902. ? SATIATED 2903. : (h > 150) ? NOT_HUNGRY 2904. : (h > 50) ? HUNGRY : (h > 0) ? WEAK : FAINTING; 2905. 2906. /* While you're eating, you may pass from WEAK to HUNGRY to NOT_HUNGRY. 2907. * This should not produce the message "you only feel hungry now"; 2908. * that message should only appear if HUNGRY is an endpoint. Therefore 2909. * we check to see if we're in the middle of eating. If so, we save 2910. * the first hunger status, and at the end of eating we decide what 2911. * message to print based on the _entire_ meal, not on each little bit. 2912. */ 2913. /* It is normally possible to check if you are in the middle of a meal 2914. * by checking occupation == eatfood, but there is one special case: 2915. * start_eating() can call bite() for your first bite before it 2916. * sets the occupation. 2917. * Anyone who wants to get that case to work _without_ an ugly static 2918. * force_save_hs variable, feel free. 2919. */ 2920. /* Note: If you become a certain hunger status in the middle of the 2921. * meal, and still have that same status at the end of the meal, 2922. * this will incorrectly print the associated message at the end of 2923. * the meal instead of the middle. Such a case is currently 2924. * impossible, but could become possible if a message for SATIATED 2925. * were added or if HUNGRY and WEAK were separated by a big enough 2926. * gap to fit two bites. 2927. */ 2928. if (occupation == eatfood || force_save_hs) { 2929. if (!saved_hs) { 2930. save_hs = u.uhs; 2931. saved_hs = TRUE; 2932. } 2933. u.uhs = newhs; 2934. return; 2935. } else { 2936. if (saved_hs) { 2937. u.uhs = save_hs; 2938. saved_hs = FALSE; 2939. } 2940. } 2941. 2942. if (newhs == FAINTING) { 2943. /* u,uhunger is likely to be negative at this point */ 2944. int uhunger_div_by_10 = sgn(u.uhunger) * ((abs(u.uhunger) + 5) / 10); 2945. 2946. if (is_fainted()) 2947. newhs = FAINTED; 2948. if (u.uhs <= WEAK || rn2(20 - uhunger_div_by_10) >= 19) { 2949. if (!is_fainted() && multi >= 0 /* %% */) { 2950. int duration = 10 - uhunger_div_by_10; 2951. 2952. /* stop what you're doing, then faint */ 2953. stop_occupation(); 2954. You("faint from lack of food."); 2955. incr_itimeout(&HDeaf, duration); 2956. context.botl = TRUE; 2957. nomul(-duration); 2958. multi_reason = "fainted from lack of food"; 2959. nomovemsg = "You regain consciousness."; 2960. afternmv = unfaint; 2961. newhs = FAINTED; 2962. if (!Levitation) 2963. selftouch("Falling, you"); 2964. } 2965. 2966. /* this used to be -(200 + 20 * Con) but that was when being asleep 2967. suppressed per-turn uhunger decrement but being fainted didn't; 2968. now uhunger becomes more negative at a slower rate */ 2969. } else if (u.uhunger < -(100 + 10 * (int) ACURR(A_CON))) { 2970. u.uhs = STARVED; 2971. context.botl = 1; 2972. bot(); 2973. You("die from starvation."); 2974. killer.format = KILLED_BY; 2975. Strcpy(killer.name, "starvation"); 2976. done(STARVING); 2977. /* if we return, we lifesaved, and that calls newuhs */ 2978. return; 2979. } 2980. } 2981. 2982. if (newhs != u.uhs) { 2983. if (newhs >= WEAK && u.uhs < WEAK) { 2984. /* this used to be losestr(1) which had the potential to 2985. be fatal (still handled below) by reducing HP if it 2986. tried to take base strength below minimum of 3 */ 2987. ATEMP(A_STR) = -1; /* temporary loss overrides Fixed_abil */ 2988. /* defer context.botl status update until after hunger message */ 2989. } else if (newhs < WEAK && u.uhs >= WEAK) { 2990. /* this used to be losestr(-1) which could be abused by 2991. becoming weak while wearing ring of sustain ability, 2992. removing ring, eating to 'restore' strength which boosted 2993. strength by a point each time the cycle was performed; 2994. substituting "while polymorphed" for sustain ability and 2995. "rehumanize" for ring removal might have done that too */ 2996. ATEMP(A_STR) = 0; /* repair of loss also overrides Fixed_abil */ 2997. /* defer context.botl status update until after hunger message */ 2998. } 2999. 3000. switch (newhs) { 3001. case HUNGRY: 3002. if (Hallucination) { 3003. You((!incr) ? "now have a lesser case of the munchies." 3004. : "are getting the munchies."); 3005. } else 3006. You((!incr) ? "only feel hungry now." 3007. : (u.uhunger < 145) 3008. ? "feel hungry." 3009. : "are beginning to feel hungry."); 3010. if (incr && occupation 3011. && (occupation != eatfood && occupation != opentin)) 3012. stop_occupation(); 3013. context.travel = context.travel1 = context.mv = context.run = 0; 3014. break; 3015. case WEAK: 3016. if (Hallucination) 3017. pline((!incr) ? "You still have the munchies." 3018. : "The munchies are interfering with your motor capabilities."); 3019. else if (incr && (Role_if(PM_WIZARD) || Race_if(PM_ELF) 3020. || Role_if(PM_VALKYRIE))) 3021. pline("%s needs food, badly!", 3022. (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) 3023. ? urole.name.m 3024. : "Elf"); 3025. else 3026. You((!incr) 3027. ? "feel weak now." 3028. : (u.uhunger < 45) ? "feel weak." 3029. : "are beginning to feel weak."); 3030. if (incr && occupation 3031. && (occupation != eatfood && occupation != opentin)) 3032. stop_occupation(); 3033. context.travel = context.travel1 = context.mv = context.run = 0; 3034. break; 3035. } 3036. u.uhs = newhs; 3037. context.botl = 1; 3038. bot(); 3039. if ((Upolyd ? u.mh : u.uhp) < 1) { 3040. You("die from hunger and exhaustion."); 3041. killer.format = KILLED_BY; 3042. Strcpy(killer.name, "exhaustion"); 3043. done(STARVING); 3044. return; 3045. } 3046. } 3047. } 3048.
floorfood
3049. /* Returns an object representing food. 3050. * Object may be either on floor or in inventory. 3051. */ 3052. struct obj * 3053. floorfood(verb, corpsecheck) 3054. const char *verb; 3055. int corpsecheck; /* 0, no check, 1, corpses, 2, tinnable corpses */ 3056. { 3057. register struct obj *otmp; 3058. char qbuf[QBUFSZ]; 3059. char c; 3060. boolean feeding = !strcmp(verb, "eat"), /* corpsecheck==0 */ 3061. offering = !strcmp(verb, "sacrifice"); /* corpsecheck==1 */ 3062. 3063. /* if we can't touch floor objects then use invent food only */ 3064. if (iflags.menu_requested /* command was preceded by 'm' prefix */ 3065. || !can_reach_floor(TRUE) || (feeding && u.usteed) 3066. || (is_pool_or_lava(u.ux, u.uy) 3067. && (Wwalking || is_clinger(youmonst.data) 3068. || (Flying && !Breathless)))) 3069. goto skipfloor; 3070. 3071. if (feeding && metallivorous(youmonst.data)) { 3072. struct obj *gold; 3073. struct trap *ttmp = t_at(u.ux, u.uy); 3074. 3075. if (ttmp && ttmp->tseen && ttmp->ttyp == BEAR_TRAP) { 3076. /* If not already stuck in the trap, perhaps there should 3077. be a chance to becoming trapped? Probably not, because 3078. then the trap would just get eaten on the _next_ turn... */ 3079. Sprintf(qbuf, "There is a bear trap here (%s); eat it?", 3080. (u.utrap && u.utraptype == TT_BEARTRAP) ? "holding you" 3081. : "armed"); 3082. if ((c = yn_function(qbuf, ynqchars, 'n')) == 'y') { 3083. u.utrap = u.utraptype = 0; 3084. deltrap(ttmp); 3085. return mksobj(BEARTRAP, TRUE, FALSE); 3086. } else if (c == 'q') { 3087. return (struct obj *) 0; 3088. } 3089. } 3090. 3091. if (youmonst.data != &mons[PM_RUST_MONSTER] 3092. && (gold = g_at(u.ux, u.uy)) != 0) { 3093. if (gold->quan == 1L) 3094. Sprintf(qbuf, "There is 1 gold piece here; eat it?"); 3095. else 3096. Sprintf(qbuf, "There are %ld gold pieces here; eat them?", 3097. gold->quan); 3098. if ((c = yn_function(qbuf, ynqchars, 'n')) == 'y') { 3099. return gold; 3100. } else if (c == 'q') { 3101. return (struct obj *) 0; 3102. } 3103. } 3104. } 3105. 3106. /* Is there some food (probably a heavy corpse) here on the ground? */ 3107. for (otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp->nexthere) { 3108. if (corpsecheck 3109. ? (otmp->otyp == CORPSE 3110. && (corpsecheck == 1 || tinnable(otmp))) 3111. : feeding ? (otmp->oclass != COIN_CLASS && is_edible(otmp)) 3112. : otmp->oclass == FOOD_CLASS) { 3113. char qsfx[QBUFSZ]; 3114. boolean one = (otmp->quan == 1L); 3115. 3116. /* if blind and without gloves, attempting to eat (or tin or 3117. offer) a cockatrice corpse is fatal before asking whether 3118. or not to use it; otherwise, 'm<dir>' followed by 'e' could 3119. be used to locate cockatrice corpses without touching them */ 3120. if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) { 3121. feel_cockatrice(otmp, FALSE); 3122. /* if life-saved (or poly'd into stone golem), terminate 3123. attempt to eat off floor */ 3124. return (struct obj *) 0; 3125. } 3126. /* "There is <an object> here; <verb> it?" or 3127. "There are <N objects> here; <verb> one?" */ 3128. Sprintf(qbuf, "There %s ", otense(otmp, "are")); 3129. Sprintf(qsfx, " here; %s %s?", verb, one ? "it" : "one"); 3130. (void) safe_qbuf(qbuf, qbuf, qsfx, otmp, doname, ansimpleoname, 3131. one ? something : (const char *) "things"); 3132. if ((c = yn_function(qbuf, ynqchars, 'n')) == 'y') 3133. return otmp; 3134. else if (c == 'q') 3135. return (struct obj *) 0; 3136. } 3137. } 3138. 3139. skipfloor: 3140. /* We cannot use ALL_CLASSES since that causes getobj() to skip its 3141. * "ugly checks" and we need to check for inedible items. 3142. */ 3143. otmp = getobj(feeding ? allobj : offering ? offerfodder : comestibles, 3144. verb); 3145. if (corpsecheck && otmp && !(offering && otmp->oclass == AMULET_CLASS)) 3146. if (otmp->otyp != CORPSE || (corpsecheck == 2 && !tinnable(otmp))) { 3147. You_cant("%s that!", verb); 3148. return (struct obj *) 0; 3149. } 3150. return otmp; 3151. } 3152.
vomit
3153. /* Side effects of vomiting */ 3154. /* added nomul (MRS) - it makes sense, you're too busy being sick! */ 3155. void 3156. vomit() /* A good idea from David Neves */ 3157. { 3158. if (cantvomit(youmonst.data)) { 3159. /* doesn't cure food poisoning; message assumes that we aren't 3160. dealing with some esoteric body_part() */ 3161. Your("jaw gapes convulsively."); 3162. } else { 3163. make_sick(0L, (char *) 0, TRUE, SICK_VOMITABLE); 3164. /* if not enough in stomach to actually vomit then dry heave; 3165. vomiting_dialog() gives a vomit message when its countdown 3166. reaches 0, but only if u.uhs < FAINTING (and !cantvomit()) */ 3167. if (u.uhs >= FAINTING) 3168. Your("%s heaves convulsively!", body_part(STOMACH)); 3169. } 3170. 3171. /* nomul()/You_can_move_again used to be unconditional, which was 3172. viable while eating but not for Vomiting countdown where hero might 3173. be immobilized for some other reason at the time vomit() is called */ 3174. if (multi >= -2) { 3175. nomul(-2); 3176. multi_reason = "vomiting"; 3177. nomovemsg = You_can_move_again; 3178. } 3179. } 3180.
eaten_stat
3181. int 3182. eaten_stat(base, obj) 3183. int base; 3184. struct obj *obj; 3185. { 3186. long uneaten_amt, full_amount; 3187. 3188. /* get full_amount first; obj_nutrition() might modify obj->oeaten */ 3189. full_amount = (long) obj_nutrition(obj); 3190. uneaten_amt = (long) obj->oeaten; 3191. if (uneaten_amt > full_amount) { 3192. impossible( 3193. "partly eaten food (%ld) more nutritious than untouched food (%ld)", 3194. uneaten_amt, full_amount); 3195. uneaten_amt = full_amount; 3196. } 3197. 3198. base = (int) (full_amount ? (long) base * uneaten_amt / full_amount : 0L); 3199. return (base < 1) ? 1 : base; 3200. } 3201.
consume_oeaten
3202. /* reduce obj's oeaten field, making sure it never hits or passes 0 */ 3203. void 3204. consume_oeaten(obj, amt) 3205. struct obj *obj; 3206. int amt; 3207. { 3208. /* 3209. * This is a hack to try to squelch several long standing mystery 3210. * food bugs. A better solution would be to rewrite the entire 3211. * victual handling mechanism from scratch using a less complex 3212. * model. Alternatively, this routine could call done_eating() 3213. * or food_disappears() but its callers would need revisions to 3214. * cope with context.victual.piece unexpectedly going away. 3215. * 3216. * Multi-turn eating operates by setting the food's oeaten field 3217. * to its full nutritional value and then running a counter which 3218. * independently keeps track of whether there is any food left. 3219. * The oeaten field can reach exactly zero on the last turn, and 3220. * the object isn't removed from inventory until the next turn 3221. * when the "you finish eating" message gets delivered, so the 3222. * food would be restored to the status of untouched during that 3223. * interval. This resulted in unexpected encumbrance messages 3224. * at the end of a meal (if near enough to a threshold) and would 3225. * yield full food if there was an interruption on the critical 3226. * turn. Also, there have been reports over the years of food 3227. * becoming massively heavy or producing unlimited satiation; 3228. * this would occur if reducing oeaten via subtraction attempted 3229. * to drop it below 0 since its unsigned type would produce a 3230. * huge positive value instead. So far, no one has figured out 3231. * _why_ that inappropriate subtraction might sometimes happen. 3232. */ 3233. 3234. if (amt > 0) { 3235. /* bit shift to divide the remaining amount of food */ 3236. obj->oeaten >>= amt; 3237. } else { 3238. /* simple decrement; value is negative so we actually add it */ 3239. if ((int) obj->oeaten > -amt) 3240. obj->oeaten += amt; 3241. else 3242. obj->oeaten = 0; 3243. } 3244. 3245. if (obj->oeaten == 0) { 3246. if (obj == context.victual.piece) /* always true unless wishing... */ 3247. context.victual.reqtime = 3248. context.victual.usedtime; /* no bites left */ 3249. obj->oeaten = 1; /* smallest possible positive value */ 3250. } 3251. } 3252.
maybe_finished_meal
3253. /* called when eatfood occupation has been interrupted, 3254. or in the case of theft, is about to be interrupted */ 3255. boolean 3256. maybe_finished_meal(stopping) 3257. boolean stopping; 3258. { 3259. /* in case consume_oeaten() has decided that the food is all gone */ 3260. if (occupation == eatfood 3261. && context.victual.usedtime >= context.victual.reqtime) { 3262. if (stopping) 3263. occupation = 0; /* for do_reset_eat */ 3264. (void) eatfood(); /* calls done_eating() to use up 3265. context.victual.piece */ 3266. return TRUE; 3267. } 3268. return FALSE; 3269. } 3270.
Popeye
3271. /* Tin of <something> to the rescue? Decide whether current occupation 3272. is an attempt to eat a tin of something capable of saving hero's life. 3273. We don't care about consumption of non-tinned food here because special 3274. effects there take place on first bite rather than at end of occupation. 3275. [Popeye the Sailor gets out of trouble by eating tins of spinach. :-] */ 3276. boolean 3277. Popeye(threat) 3278. int threat; 3279. { 3280. struct obj *otin; 3281. int mndx; 3282. 3283. if (occupation != opentin) 3284. return FALSE; 3285. otin = context.tin.tin; 3286. /* make sure hero still has access to tin */ 3287. if (!carried(otin) 3288. && (!obj_here(otin, u.ux, u.uy) || !can_reach_floor(TRUE))) 3289. return FALSE; 3290. /* unknown tin is assumed to be helpful */ 3291. if (!otin->known) 3292. return TRUE; 3293. /* known tin is helpful if it will stop life-threatening problem */ 3294. mndx = otin->corpsenm; 3295. switch (threat) { 3296. /* note: not used; hunger code bypasses stop_occupation() when eating */ 3297. case HUNGER: 3298. return (boolean) (mndx != NON_PM || otin->spe == 1); 3299. /* flesh from lizards and acidic critters stops petrification */ 3300. case STONED: 3301. return (boolean) (mndx >= LOW_PM 3302. && (mndx == PM_LIZARD || acidic(&mons[mndx]))); 3303. /* no tins can cure these (yet?) */ 3304. case SLIMED: 3305. case SICK: 3306. case VOMITING: 3307. break; 3308. default: 3309. break; 3310. } 3311. return FALSE; 3312. } 3313. 3314. /*eat.c*/