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