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