home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / games / volume16 / nethck31 / part12 < prev    next >
Encoding:
Internet Message Format  |  1993-01-31  |  57.4 KB

  1. Path: uunet!news.tek.com!master!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v16i012:  nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part12/108
  5. Message-ID: <4295@master.CNA.TEK.COM>
  6. Date: 28 Jan 93 19:12:46 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 2180
  9. Approved: billr@saab.CNA.TEK.COM
  10. Xref: uunet comp.sources.games:1568
  11.  
  12. Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
  13. Posting-number: Volume 16, Issue 12
  14. Archive-name: nethack31/Part12
  15. Supersedes: nethack3p9: Volume 10, Issue 46-102
  16. Environment: Amiga, Atari, Mac, MS-DOS, OS2, Unix, VMS, X11
  17.  
  18.  
  19.  
  20. #! /bin/sh
  21. # This is a shell archive.  Remove anything before this line, then unpack
  22. # it by saving it into a file and typing "sh file".  To overwrite existing
  23. # files, type "sh file -c".  You can also feed this as standard input via
  24. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  25. # will see the following message at the end:
  26. #        "End of archive 12 (of 108)."
  27. # Contents:  include/global.h src/eat.c sys/mac/mhdump.c
  28. # Wrapped by billr@saab on Wed Jan 27 16:08:49 1993
  29. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  30. if test -f 'include/global.h' -a "${1}" != "-c" ; then 
  31.   echo shar: Will not clobber existing file \"'include/global.h'\"
  32. else
  33. echo shar: Extracting \"'include/global.h'\" \(6136 characters\)
  34. sed "s/^X//" >'include/global.h' <<'END_OF_FILE'
  35. X/*    SCCS Id: @(#)global.h    3.1    92/01/04    */
  36. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  37. X/* NetHack may be freely redistributed.  See license for details. */
  38. X
  39. X#ifndef GLOBAL_H
  40. X#define GLOBAL_H
  41. X
  42. X#include <stdio.h>
  43. X
  44. X
  45. X/*#define BETA        /* if a beta-test copy  [MRS] */
  46. X#define VERSION "3.1"    /* version number. */
  47. X
  48. X/*
  49. X * Files expected to exist in the playground directory.
  50. X */
  51. X
  52. X#define RECORD        "record"  /* a file containing list of topscorers */
  53. X#define HELP        "help"      /* a file containing command descriptions */
  54. X#define SHELP        "hh"        /* abbreviated form of the same */
  55. X#define DEBUGHELP    "wizhelp"    /* a file containing debug mode cmds */
  56. X#define RUMORFILE    "rumors"    /* a file with fortune cookies */
  57. X#define ORACLEFILE    "oracles"    /* a file with oracular information */
  58. X#define DATAFILE    "data"    /* a file giving the meaning of symbols used */
  59. X#define CMDHELPFILE    "cmdhelp"    /* file telling what commands do */
  60. X#define HISTORY        "history"    /* a file giving nethack's history */
  61. X#define LICENSE        "license"    /* file with license information */
  62. X#define OPTIONFILE    "opthelp"    /* a file explaining runtime options */
  63. X#define OPTIONS_USED    "options"    /* compile-time options, for #version */
  64. X
  65. X#define LEV_EXT    ".lev"        /* extension for special level files */
  66. X
  67. X
  68. X/* Assorted definitions that may depend on selections in config.h. */
  69. X
  70. X/*
  71. X * for DUMB preprocessor and compiler, e.g., cpp and pcc supplied
  72. X * with Microport SysV/AT, which have small symbol tables;
  73. X * DUMB if needed is defined in CFLAGS
  74. X */
  75. X#ifdef DUMB
  76. X#ifdef BITFIELDS
  77. X#undef BITFIELDS
  78. X#endif
  79. X#ifndef STUPID
  80. X#define STUPID
  81. X#endif
  82. X#endif    /* DUMB */
  83. X
  84. X/*
  85. X * type xchar: small integers in the range 0 - 127, usually coordinates
  86. X * although they are nonnegative they must not be declared unsigned
  87. X * since otherwise comparisons with signed quantities are done incorrectly
  88. X */
  89. Xtypedef schar    xchar;
  90. Xtypedef xchar    boolean;        /* 0 or 1 */
  91. X
  92. X#ifndef TRUE        /* defined in some systems' native include files */
  93. X#define TRUE    ((boolean)1)
  94. X#define FALSE    ((boolean)0)
  95. X#endif
  96. X
  97. X#ifndef STRNCMPI
  98. X# define strcmpi(a,b) strncmpi((a),(b),-1)
  99. X#endif
  100. X
  101. X/* comment out to test effects of each #define -- these will probably
  102. X * disappear eventually
  103. X */
  104. X#ifdef INTERNAL_COMP
  105. X# define RLECOMP    /* run-length compression of levl array - JLee */
  106. X# define ZEROCOMP    /* zero-run compression of everything - Olaf Seibert */
  107. X#endif
  108. X
  109. X/* #define SPECIALIZATION    /* do "specialized" version of new topology */
  110. X
  111. X
  112. X#ifdef BITFIELDS
  113. X#define Bitfield(x,n)    unsigned x:n
  114. X#else
  115. X#define Bitfield(x,n)    uchar x
  116. X#endif
  117. X
  118. X#ifdef UNWIDENED_PROTOTYPES
  119. X# define CHAR_P char
  120. X# define SCHAR_P schar
  121. X# define UCHAR_P uchar
  122. X# define XCHAR_P xchar
  123. X# define SHORT_P short
  124. X# define BOOLEAN_P boolean
  125. X# define ALIGNTYP_P aligntyp
  126. X#else
  127. X# ifdef WIDENED_PROTOTYPES
  128. X#  define CHAR_P int
  129. X#  define SCHAR_P int
  130. X#  define UCHAR_P int
  131. X#  define XCHAR_P int
  132. X#  define SHORT_P int
  133. X#  define BOOLEAN_P int
  134. X#  define ALIGNTYP_P int
  135. X# endif
  136. X#endif
  137. X#if defined(ULTRIX_PROTO) && !defined(__GNUC__)
  138. X/* The ultrix 2.0 and 2.1 compilers (on Ultrix 4.0 and 4.2 respectively) can't
  139. X * handle "struct obj *" constructs in prototypes.  Their bugs are different,
  140. X * but both seem to work if we put "void*" in the prototype instead.  This
  141. X * gives us minimal prototype checking but avoids the compiler bugs.
  142. X *
  143. X * OBJ_P and MONST_P should _only_ be used for declaring function pointers.
  144. X */
  145. X#define OBJ_P void*
  146. X#define MONST_P void*
  147. X#else
  148. X#define OBJ_P struct obj*
  149. X#define MONST_P struct monst*
  150. X#endif
  151. X
  152. X#define SIZE(x)    (int)(sizeof(x) / sizeof(x[0]))
  153. X
  154. Xtypedef int winid;        /* a window identifier */
  155. X
  156. X/* A limit for some NetHack int variables.  It need not, and for comparable
  157. X * scoring should not, depend on the actual limit on integers for a
  158. X * particular machine, although it is set to the minimum required maximum
  159. X * signed integer for C (2^15 -1).
  160. X */
  161. X#define LARGEST_INT    32767
  162. X
  163. X
  164. X#ifdef REDO
  165. X#define Getchar pgetchar
  166. X#endif
  167. X
  168. X/*
  169. X * Automatic inclusions for the subsidiary files.
  170. X * Please don't change the order.  It does matter.
  171. X */
  172. X
  173. X#ifndef COORD_H
  174. X#include "coord.h"
  175. X#endif
  176. X
  177. X#if defined(VMS) && !defined(VMSCONF_H)
  178. X# include "vmsconf.h"
  179. X#endif
  180. X
  181. X#if defined(UNIX) && !defined(UNIXCONF_H)
  182. X# include "unixconf.h"
  183. X#endif
  184. X
  185. X#if defined(OS2) && !defined(OS2CONF_H)
  186. X# include "os2conf.h"
  187. X#endif
  188. X
  189. X#if defined(MSDOS) && !defined(PCCONF_H)
  190. X# include "pcconf.h"
  191. X#endif
  192. X
  193. X#if defined(TOS) && !defined(TOSCONF_H)
  194. X# include "tosconf.h"
  195. X#endif
  196. X
  197. X#if defined(AMIGA) && !defined(AMICONF_H)
  198. X# include "amiconf.h"
  199. X#endif
  200. X
  201. X#if defined(MAC) && ! defined(MACCONF_H)
  202. X# include "macconf.h"
  203. X#endif
  204. X
  205. X/* Displayable name of this port; don't redefine if defined in *conf.h */
  206. X#ifndef PORT_ID
  207. X# ifdef AMIGA
  208. X#  define PORT_ID    "Amiga"
  209. X# endif
  210. X# ifdef MAC
  211. X#  define PORT_ID    "Mac"
  212. X# endif
  213. X# ifdef MSDOS
  214. X#  define PORT_ID    "PC"
  215. X# endif
  216. X# ifdef OS2
  217. X#  define PORT_ID    "OS/2"
  218. X# endif
  219. X# ifdef TOS
  220. X#  define PORT_ID    "ST"
  221. X# endif
  222. X# ifdef UNIX
  223. X#  define PORT_ID    "Unix"
  224. X# endif
  225. X# ifdef VMS
  226. X#  define PORT_ID    "VMS"
  227. X# endif
  228. X#endif
  229. X
  230. X/*
  231. X * Configurable internal parameters.
  232. X *
  233. X * Please be very careful if you are going to change one of these.  Any
  234. X * changes in these parameters, unless properly done, can render the
  235. X * executable inoperative.
  236. X */
  237. X
  238. X/* size of terminal screen is (at least) (ROWNO+3) by COLNO */
  239. X#define COLNO    80
  240. X#define ROWNO    21
  241. X
  242. X#define MAXNROFROOMS    20    /* max number of rooms per level */
  243. X#define MAX_SUBROOMS    16    /* max # of subrooms in a given room */
  244. X#define DOORMAX        120    /* max number of doors per level */
  245. X
  246. X#define BUFSZ        256    /* for getlin buffers */
  247. X#define QBUFSZ        128    /* for building question text */
  248. X
  249. X#define PL_NSIZ        32    /* name of player, ghost, shopkeeper */
  250. X#define PL_CSIZ        20    /* sizeof pl_character */
  251. X#define PL_FSIZ        32    /* fruit name */
  252. X
  253. X#define MAXDUNGEON    10    /* current maximum number of dungeons */
  254. X#define MAXLEVEL    30    /* max number of levels in one dungeon */
  255. X#define MAXSTAIRS    1    /* max # of special stairways in a dungeon */
  256. X#define ALIGNWEIGHT    4    /* generation weight of alignment */
  257. X
  258. X#define MAXULEV        30    /* max character experience level */
  259. X
  260. X#define MAXMONNO    120    /* geno monst after this number killed */
  261. X#define MHPMAX        500    /* maximum monster hp */
  262. X
  263. X#endif /* GLOBAL_H */
  264. END_OF_FILE
  265. if test 6136 -ne `wc -c <'include/global.h'`; then
  266.     echo shar: \"'include/global.h'\" unpacked with wrong size!
  267. fi
  268. # end of 'include/global.h'
  269. fi
  270. if test -f 'src/eat.c' -a "${1}" != "-c" ; then 
  271.   echo shar: Will not clobber existing file \"'src/eat.c'\"
  272. else
  273. echo shar: Extracting \"'src/eat.c'\" \(47298 characters\)
  274. sed "s/^X//" >'src/eat.c' <<'END_OF_FILE'
  275. X/*    SCCS Id: @(#)eat.c    3.1    92/12/06    */
  276. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  277. X/* NetHack may be freely redistributed.  See license for details. */
  278. X
  279. X#include    "hack.h"
  280. X/*#define DEBUG        /* uncomment to enable new eat code debugging */
  281. X
  282. X#ifdef DEBUG
  283. X# ifdef WIZARD
  284. X#define debugpline    if (wizard) pline
  285. X# else
  286. X#define debugpline    pline
  287. X# endif
  288. X#endif
  289. X
  290. XSTATIC_PTR int NDECL(eatmdone);
  291. XSTATIC_PTR int NDECL(eatfood);
  292. XSTATIC_PTR int NDECL(opentin);
  293. XSTATIC_PTR int NDECL(unfaint);
  294. X
  295. X#ifdef OVLB
  296. Xstatic void FDECL(choke, (struct obj *));
  297. Xstatic void NDECL(recalc_wt);
  298. Xstatic struct obj *FDECL(touchfood, (struct obj *));
  299. Xstatic void NDECL(do_reset_eat);
  300. Xstatic void FDECL(done_eating, (BOOLEAN_P));
  301. Xstatic void FDECL(cprefx, (int));
  302. Xstatic int FDECL(intrinsic_possible, (int,struct permonst *));
  303. Xstatic void FDECL(givit, (int,struct permonst *));
  304. Xstatic void FDECL(cpostfx, (int));
  305. Xstatic void FDECL(start_tin, (struct obj *));
  306. Xstatic int FDECL(eatcorpse, (struct obj *));
  307. Xstatic void FDECL(start_eating, (struct obj *));
  308. Xstatic void FDECL(fprefx, (struct obj *));
  309. Xstatic void FDECL(fpostfx, (struct obj *));
  310. Xstatic int NDECL(bite);
  311. X
  312. X#ifdef POLYSELF
  313. Xstatic int FDECL(rottenfood, (struct obj *));
  314. Xstatic void NDECL(eatspecial);
  315. Xstatic void FDECL(eatring, (struct obj *));
  316. Xstatic const char * FDECL(foodword, (struct obj *));
  317. X#else
  318. Xstatic int NDECL(rottenfood);
  319. X#endif /* POLYSELF */
  320. X
  321. Xchar corpsename[60];
  322. Xchar msgbuf[BUFSZ];
  323. X
  324. X#endif /* OVLB */
  325. X
  326. X/* hunger texts used on bottom line (each 8 chars long) */
  327. X#define SATIATED    0
  328. X#define NOT_HUNGRY    1
  329. X#define HUNGRY        2
  330. X#define WEAK        3
  331. X#define FAINTING    4
  332. X#define FAINTED        5
  333. X#define STARVED        6
  334. X
  335. X#ifdef OVLB
  336. X
  337. Xconst char *hu_stat[] = {
  338. X    "Satiated",
  339. X    "        ",
  340. X    "Hungry  ",
  341. X    "Weak    ",
  342. X    "Fainting",
  343. X    "Fainted ",
  344. X    "Starved "
  345. X};
  346. X
  347. X#endif /* OVLB */
  348. X
  349. X#ifndef OVLB
  350. X
  351. XSTATIC_DCL const char NEARDATA comestibles[];
  352. X#ifdef POLYSELF
  353. XSTATIC_OVL const char NEARDATA allobj[];
  354. X#endif /* POLYSELF */
  355. X
  356. X#else
  357. X
  358. XSTATIC_OVL const char NEARDATA comestibles[] = { FOOD_CLASS, 0 };
  359. X
  360. X#ifdef POLYSELF
  361. X/* Gold must come first for getobj(). */
  362. XSTATIC_OVL const char NEARDATA allobj[] = {
  363. X    GOLD_CLASS, WEAPON_CLASS, ARMOR_CLASS, POTION_CLASS, SCROLL_CLASS,
  364. X    WAND_CLASS, RING_CLASS, AMULET_CLASS, FOOD_CLASS, TOOL_CLASS,
  365. X    GEM_CLASS, ROCK_CLASS, BALL_CLASS, CHAIN_CLASS, SPBOOK_CLASS, 0 };
  366. X#endif /* POLYSELF */
  367. X
  368. X#endif /* OVLB */
  369. X#ifdef OVL1
  370. X# ifdef POLYSELF
  371. X
  372. Xboolean
  373. Xis_edible(obj)
  374. Xregister struct obj *obj;
  375. X{
  376. X    if (metallivorous(uasmon) && is_metallic(obj))
  377. X        return TRUE;
  378. X    if (u.umonnum == PM_GELATINOUS_CUBE && is_organic(obj))
  379. X        return TRUE;
  380. X    return !!index(comestibles, obj->oclass);
  381. X}
  382. X# endif /* POLYSELF */
  383. X#endif /* OVL1 */
  384. X#ifdef OVLB
  385. X
  386. Xvoid
  387. Xinit_uhunger(){
  388. X    u.uhunger = 900;
  389. X    u.uhs = NOT_HUNGRY;
  390. X}
  391. X
  392. Xstatic const struct { const char *txt; int nut; } tintxts[] = {
  393. X    {"deep fried",     60},
  394. X    {"pickled",     40},
  395. X    {"soup made from", 20},
  396. X    {"pureed",    500},
  397. X    {"rotten",    -50},
  398. X    {"homemade",     50},
  399. X    {"", 0}
  400. X};
  401. X#define    TTSZ    SIZE(tintxts)
  402. X
  403. Xstatic struct {
  404. X    struct    obj *tin;
  405. X    int    usedtime, reqtime;
  406. X} NEARDATA tin;
  407. X
  408. Xstatic struct {
  409. X    struct    obj *piece;    /* the thing being eaten, or last thing that
  410. X                 * was partially eaten, unless that thing was
  411. X                 * a tin, which uses the tin structure above */
  412. X    int    usedtime,    /* turns spent eating */
  413. X        reqtime;    /* turns required to eat */
  414. X    int    nmod;        /* coded nutrition per turn */
  415. X    Bitfield(canchoke,1);    /* was satiated at beginning */
  416. X    Bitfield(fullwarn,1);    /* have warned about being full */
  417. X    Bitfield(eating,1);    /* victual currently being eaten */
  418. X    Bitfield(doreset,1);    /* stop eating at end of turn */
  419. X} NEARDATA victual;
  420. X
  421. XSTATIC_PTR
  422. Xint
  423. Xeatmdone() {        /* called after mimicing is over */
  424. X    u.usym =
  425. X#ifdef POLYSELF
  426. X        u.mtimedone ? uasmon->mlet :
  427. X#endif
  428. X        S_HUMAN;
  429. X    newsym(u.ux,u.uy);
  430. X    return 0;
  431. X}
  432. X
  433. X/* Created by GAN 01/28/87
  434. X * Amended by AKP 09/22/87: if not hard, don't choke, just vomit.
  435. X * Amended by 3.  06/12/89: if not hard, sometimes choke anyway, to keep risk.
  436. X *          11/10/89: if hard, rarely vomit anyway, for slim chance.
  437. X */
  438. X/*ARGSUSED*/
  439. Xstatic void
  440. Xchoke(food)    /* To a full belly all food is bad. (It.) */
  441. X    register struct obj *food;
  442. X{
  443. X    /* only happens if you were satiated */
  444. X    if(u.uhs != SATIATED) return;
  445. X
  446. X    if (pl_character[0] == 'K' && u.ualign.type == A_LAWFUL)
  447. X        u.ualign.record--;    /* gluttony is unchivalrous */
  448. X
  449. X    if (!rn2(20)) {
  450. X        You("stuff yourself and then vomit voluminously.");
  451. X        morehungry(1000);    /* you just got *very* sick! */
  452. X        vomit();
  453. X    } else {
  454. X        killer_format = KILLED_BY_AN;
  455. X        /*
  456. X         * Note all "killer"s below read "Choked on %s" on the
  457. X         * high score list & tombstone.  So plan accordingly.
  458. X         */
  459. X        if(food) {
  460. X#ifdef POLYSELF
  461. X            You("choke over your %s.", foodword(food));
  462. X            if (food->oclass == GOLD_CLASS) {
  463. X                killer_format = KILLED_BY;
  464. X                killer = "eating too rich a meal";
  465. X            } else {
  466. X#else
  467. X                You("choke over your food.");
  468. X#endif
  469. X                killer = singular(food, xname);
  470. X#ifdef POLYSELF
  471. X            }
  472. X#endif
  473. X        } else {
  474. X            You("choke over it.");
  475. X            killer = "quick snack";
  476. X        }
  477. X        You("die...");
  478. X        done(CHOKING);
  479. X    }
  480. X}
  481. X
  482. Xstatic void
  483. Xrecalc_wt() {    /* modify object wt. depending on time spent consuming it */
  484. X    register struct obj *piece = victual.piece;
  485. X
  486. X#ifdef DEBUG
  487. X    debugpline("Old weight = %d", piece->owt);
  488. X    debugpline("Used time = %d, Req'd time = %d",
  489. X        victual.usedtime, victual.reqtime);
  490. X#endif
  491. X    /* weight(piece) = weight of full item */
  492. X    if(victual.usedtime)
  493. X        piece->owt = eaten_stat(weight(piece), piece);
  494. X#ifdef DEBUG
  495. X    debugpline("New weight = %d", piece->owt);
  496. X#endif
  497. X}
  498. X
  499. Xvoid
  500. Xreset_eat() {        /* called when eating interrupted by an event */
  501. X
  502. X    /* we only set a flag here - the actual reset process is done after
  503. X     * the round is spent eating.
  504. X     */
  505. X    if(victual.eating && !victual.doreset) {
  506. X#ifdef DEBUG
  507. X        debugpline("reset_eat...");
  508. X#endif
  509. X        victual.doreset = TRUE;
  510. X    }
  511. X    return;
  512. X}
  513. X
  514. Xvoid
  515. Xbill_dummy_object(otmp)
  516. Xregister struct obj *otmp;
  517. X{
  518. X    /* Create a dummy duplicate to put on bill.  The duplicate exists
  519. X     * only in the billobjs chain.  This function is used when a store
  520. X     * object is being altered, and a copy of the original is needed
  521. X     * for billing purposes.
  522. X     */
  523. X    register struct obj *dummy;
  524. X
  525. X    if(otmp->unpaid)
  526. X        subfrombill(otmp, shop_keeper(*u.ushops));
  527. X    dummy = newobj(otmp->onamelth);
  528. X    *dummy = *otmp;
  529. X    dummy->o_id = flags.ident++;
  530. X    dummy->owt = weight(dummy);
  531. X    if(otmp->onamelth)
  532. X        (void)strncpy(ONAME(dummy),ONAME(otmp), (int)otmp->onamelth);
  533. X    if(Is_candle(dummy)) dummy->lamplit = 0;
  534. X    addtobill(dummy, FALSE, TRUE, TRUE);
  535. X}
  536. X
  537. Xstatic struct obj *
  538. Xtouchfood(otmp)
  539. Xregister struct obj *otmp;
  540. X{
  541. X    if (otmp->quan > 1L) {
  542. X        if(!carried(otmp))
  543. X        (void) splitobj(otmp, 1L);
  544. X        else
  545. X        otmp = splitobj(otmp, otmp->quan - 1L);
  546. X#ifdef DEBUG
  547. X        debugpline("split object,");
  548. X#endif
  549. X    }
  550. X
  551. X    if (!otmp->oeaten) {
  552. X        if(((!carried(otmp) && costly_spot(otmp->ox, otmp->oy) &&
  553. X         saleable(rooms[*u.ushops-ROOMOFFSET].rtype-SHOPBASE, otmp))
  554. X         || otmp->unpaid) &&
  555. X         (otmp->otyp == CORPSE || objects[otmp->otyp].oc_delay > 1)) {
  556. X        /* create a dummy duplicate to put on bill */
  557. X        You("bite it, you bought it!");
  558. X        bill_dummy_object(otmp);
  559. X        }
  560. X        otmp->oeaten = (otmp->otyp == CORPSE ?
  561. X                (int)mons[otmp->corpsenm].cnutrit :
  562. X                objects[otmp->otyp].oc_nutrition);
  563. X    }
  564. X
  565. X    if (carried(otmp)) {
  566. X        freeinv(otmp);
  567. X        if(inv_cnt() >= 52)
  568. X        dropy(otmp);
  569. X        else
  570. X        otmp = addinv(otmp); /* unlikely but a merge is possible */
  571. X    }
  572. X    return(otmp);
  573. X}
  574. X
  575. X/* When food decays, in the middle of your meal, we don't want to dereference
  576. X * any dangling pointers, so set it to null (which should still trigger
  577. X * do_reset_eat() at the beginning of eatfood()) and check for null pointers
  578. X * in do_reset_eat().
  579. X */
  580. Xvoid
  581. Xfood_disappears(obj)
  582. Xregister struct obj *obj;
  583. X{
  584. X    if (obj == victual.piece) victual.piece = (struct obj *)0;
  585. X}
  586. X
  587. Xstatic void
  588. Xdo_reset_eat() {
  589. X
  590. X#ifdef DEBUG
  591. X    debugpline("do_reset_eat...");
  592. X#endif
  593. X    if (victual.piece) {
  594. X        victual.piece = touchfood(victual.piece);
  595. X        recalc_wt();
  596. X    }
  597. X    victual.fullwarn = victual.eating = victual.doreset = FALSE;
  598. X    /* Do not set canchoke to FALSE; if we continue eating the same object
  599. X     * we need to know if canchoke was set when they started eating it the
  600. X     * previous time.  And if we don't continue eating the same object
  601. X     * canchoke always gets recalculated anyway.
  602. X     */
  603. X    stop_occupation();
  604. X}
  605. X
  606. XSTATIC_PTR
  607. Xint
  608. Xeatfood() {        /* called each move during eating process */
  609. X    if(!carried(victual.piece) && !obj_here(victual.piece, u.ux, u.uy)) {
  610. X        /* maybe it was stolen? */
  611. X        do_reset_eat();
  612. X        return(0);
  613. X    }
  614. X    if(!victual.eating) return(0);
  615. X
  616. X    if(++victual.usedtime < victual.reqtime) {
  617. X        if(bite()) return(0);
  618. X        return(1);    /* still busy */
  619. X    } else {    /* done */
  620. X        done_eating(TRUE);
  621. X        return(0);
  622. X    }
  623. X}
  624. X
  625. Xstatic void
  626. Xdone_eating(message)
  627. Xboolean message;
  628. X{
  629. X#ifndef NO_SIGNAL
  630. X    victual.piece->in_use = TRUE;
  631. X#endif
  632. X    if (nomovemsg) {
  633. X        if (message) pline(nomovemsg);
  634. X        nomovemsg = 0;
  635. X    } else if (message)
  636. X        You("finish eating %s.", the(singular(victual.piece, xname)));
  637. X
  638. X    if(victual.piece->otyp == CORPSE)
  639. X        cpostfx(victual.piece->corpsenm);
  640. X    else
  641. X        fpostfx(victual.piece);
  642. X
  643. X    if (carried(victual.piece)) useup(victual.piece);
  644. X    else useupf(victual.piece);
  645. X    victual.piece = (struct obj *) 0;
  646. X    victual.fullwarn = victual.eating = victual.doreset = FALSE;
  647. X}
  648. X
  649. Xstatic void
  650. Xcprefx(pm)
  651. Xregister int pm;
  652. X{
  653. X    if ((pl_character[0]=='E') ? is_elf(&mons[pm]) : is_human(&mons[pm])) {
  654. X        You("cannibal!  You will regret this!");
  655. X        Aggravate_monster |= FROMOUTSIDE;
  656. X    }
  657. X
  658. X    switch(pm) {
  659. X        case PM_LITTLE_DOG:
  660. X        case PM_DOG:
  661. X        case PM_LARGE_DOG:
  662. X        case PM_KITTEN:
  663. X        case PM_HOUSECAT:
  664. X        case PM_LARGE_CAT:
  665. X        You("feel that eating the %s was a bad idea.", mons[pm].mname);
  666. X        Aggravate_monster |= FROMOUTSIDE;
  667. X        break;
  668. X        case PM_COCKATRICE:
  669. X        case PM_MEDUSA:
  670. X#ifdef POLYSELF
  671. X        if(!resists_ston(uasmon))
  672. X            if(!(poly_when_stoned(uasmon) && polymon(PM_STONE_GOLEM)))
  673. X#endif
  674. X            {
  675. X            char *cruft;    /* killer is const char * */
  676. X            killer_format = KILLED_BY;
  677. X            killer = cruft = (char *)  /* sizeof "s" includes \0 */
  678. X                    alloc((unsigned) strlen(mons[pm].mname)
  679. X                        + sizeof " meat");
  680. X            Sprintf(cruft, "%s meat", mons[pm].mname);
  681. X            You("turn to stone.");
  682. X            done(STONING);
  683. X            }
  684. X            break;
  685. X        case PM_LIZARD:
  686. X        /* Relief from cockatrices -dgk */
  687. X        if (Stoned) {
  688. X            Stoned = 0;
  689. X            You("feel limber!");
  690. X        }
  691. X        break;
  692. X        case PM_DEATH:
  693. X        case PM_PESTILENCE:
  694. X        case PM_FAMINE:
  695. X        { char buf[BUFSZ];
  696. X            pline("Eating that is instantly fatal.");
  697. X            Sprintf(buf, "unwisely ate the body of %s",
  698. X                mons[pm].mname);
  699. X            killer = buf;
  700. X            killer_format = NO_KILLER_PREFIX;
  701. X            done(DIED);
  702. X            /* It so happens that since we know these monsters */
  703. X            /* cannot appear in tins, victual.piece will always */
  704. X            /* be what we want, which is not generally true. */
  705. X            revive_corpse(victual.piece, 0, FALSE);
  706. X            return;
  707. X        }
  708. X        default:
  709. X        if(acidic(&mons[pm]) && Stoned) {
  710. X            pline("What a pity - you just destroyed a future piece of art!");
  711. X            Stoned = 0;
  712. X        }
  713. X    }
  714. X    return;
  715. X}
  716. X
  717. X
  718. X/*
  719. X * If you add an intrinsic that can be gotten by eating a monster, add it
  720. X * to intrinsic_possible() and givit().  (It must already be in prop.h to
  721. X * be an intrinsic property.)
  722. X * It would be very easy to make the intrinsics not try to give you one
  723. X * that you already had by checking to see if you have it in
  724. X * intrinsic_possible() instead of givit().
  725. X */
  726. X
  727. X/* intrinsic_possible() returns TRUE iff a monster can give an intrinsic. */
  728. Xstatic int
  729. Xintrinsic_possible(type, ptr)
  730. Xint type;
  731. Xregister struct permonst *ptr;
  732. X{
  733. X    switch (type) {
  734. X        case FIRE_RES:
  735. X#ifdef DEBUG
  736. X        if (ptr->mconveys & MR_FIRE) {
  737. X            debugpline("can get fire resistance");
  738. X            return(TRUE);
  739. X        } else  return(FALSE);
  740. X#else
  741. X        return(ptr->mconveys & MR_FIRE);
  742. X#endif
  743. X        case SLEEP_RES:
  744. X#ifdef DEBUG
  745. X        if (ptr->mconveys & MR_SLEEP) {
  746. X            debugpline("can get sleep resistance");
  747. X            return(TRUE);
  748. X        } else  return(FALSE);
  749. X#else
  750. X        return(ptr->mconveys & MR_SLEEP);
  751. X#endif
  752. X        case COLD_RES:
  753. X#ifdef DEBUG
  754. X        if (ptr->mconveys & MR_COLD) {
  755. X            debugpline("can get cold resistance");
  756. X            return(TRUE);
  757. X        } else  return(FALSE);
  758. X#else
  759. X        return(ptr->mconveys & MR_COLD);
  760. X#endif
  761. X        case DISINT_RES:
  762. X#ifdef DEBUG
  763. X        if (ptr->mconveys & MR_DISINT) {
  764. X            debugpline("can get disintegration resistance");
  765. X            return(TRUE);
  766. X        } else  return(FALSE);
  767. X#else
  768. X        return(ptr->mconveys & MR_DISINT);
  769. X#endif
  770. X        case SHOCK_RES:    /* shock (electricity) resistance */
  771. X#ifdef DEBUG
  772. X        if (ptr->mconveys & MR_ELEC) {
  773. X            debugpline("can get shock resistance");
  774. X            return(TRUE);
  775. X        } else  return(FALSE);
  776. X#else
  777. X        return(ptr->mconveys & MR_ELEC);
  778. X#endif
  779. X        case POISON_RES:
  780. X#ifdef DEBUG
  781. X        if (ptr->mconveys & MR_POISON) {
  782. X            debugpline("can get poison resistance");
  783. X            return(TRUE);
  784. X        } else  return(FALSE);
  785. X#else
  786. X        return(ptr->mconveys & MR_POISON);
  787. X#endif
  788. X        case TELEPORT:
  789. X#ifdef DEBUG
  790. X        if (can_teleport(ptr)) {
  791. X            debugpline("can get teleport");
  792. X            return(TRUE);
  793. X        } else  return(FALSE);
  794. X#else
  795. X        return(can_teleport(ptr));
  796. X#endif
  797. X        case TELEPORT_CONTROL:
  798. X#ifdef DEBUG
  799. X        if (control_teleport(ptr)) {
  800. X            debugpline("can get teleport control");
  801. X            return(TRUE);
  802. X        } else  return(FALSE);
  803. X#else
  804. X        return(control_teleport(ptr));
  805. X#endif
  806. X        case TELEPAT:
  807. X#ifdef DEBUG
  808. X        if (telepathic(ptr)) {
  809. X            debugpline("can get telepathy");
  810. X            return(TRUE);
  811. X        } else  return(FALSE);
  812. X#else
  813. X        return(telepathic(ptr));
  814. X#endif
  815. X        default:
  816. X        return(FALSE);
  817. X    }
  818. X    /*NOTREACHED*/
  819. X}
  820. X
  821. X/* givit() tries to give you an intrinsic based on the monster's level
  822. X * and what type of intrinsic it is trying to give you.
  823. X */
  824. Xstatic void
  825. Xgivit(type, ptr)
  826. Xint type;
  827. Xregister struct permonst *ptr;
  828. X{
  829. X    register int chance;
  830. X
  831. X#ifdef DEBUG
  832. X    debugpline("Attempting to give intrinsic %d", type);
  833. X#endif
  834. X    /* some intrinsics are easier to get than others */
  835. X    switch (type) {
  836. X        case POISON_RES:
  837. X            if ((ptr == &mons[PM_KILLER_BEE] ||
  838. X                    ptr == &mons[PM_SCORPION]) && !rn2(4))
  839. X                chance = 1;
  840. X            else
  841. X                chance = 15;
  842. X            break;
  843. X        case TELEPORT:
  844. X            chance = 10;
  845. X            break;
  846. X        case TELEPORT_CONTROL:
  847. X            chance = 12;
  848. X            break;
  849. X        case TELEPAT:
  850. X            chance = 1;
  851. X            break;
  852. X        default:
  853. X            chance = 15;
  854. X            break;
  855. X    }
  856. X
  857. X    if (ptr->mlevel <= rn2(chance))
  858. X        return;        /* failed die roll */
  859. X
  860. X    switch (type) {
  861. X        case FIRE_RES:
  862. X#ifdef DEBUG
  863. X        debugpline("Trying to give fire resistance");
  864. X#endif
  865. X        if(!(HFire_resistance & FROMOUTSIDE)) {
  866. X            You("feel a momentary chill.");
  867. X            HFire_resistance |= FROMOUTSIDE;
  868. X        }
  869. X        break;
  870. X        case SLEEP_RES:
  871. X#ifdef DEBUG
  872. X        debugpline("Trying to give sleep resistance");
  873. X#endif
  874. X        if(!(HSleep_resistance & FROMOUTSIDE)) {
  875. X            You("feel wide awake.");
  876. X            HSleep_resistance |= FROMOUTSIDE;
  877. X        }
  878. X        break;
  879. X        case COLD_RES:
  880. X#ifdef DEBUG
  881. X        debugpline("Trying to give cold resistance");
  882. X#endif
  883. X        if(!(HCold_resistance & FROMOUTSIDE)) {
  884. X            You("feel full of hot air.");
  885. X            HCold_resistance |= FROMOUTSIDE;
  886. X        }
  887. X        break;
  888. X        case DISINT_RES:
  889. X#ifdef DEBUG
  890. X        debugpline("Trying to give disintegration resistance");
  891. X#endif
  892. X        if(!(HDisint_resistance & FROMOUTSIDE)) {
  893. X            You("feel very firm.");
  894. X            HDisint_resistance |= FROMOUTSIDE;
  895. X        }
  896. X        break;
  897. X        case SHOCK_RES:    /* shock (electricity) resistance */
  898. X#ifdef DEBUG
  899. X        debugpline("Trying to give shock resistance");
  900. X#endif
  901. X        if(!(HShock_resistance & FROMOUTSIDE)) {
  902. X            Your("health currently feels amplified!");
  903. X            HShock_resistance |= FROMOUTSIDE;
  904. X        }
  905. X        break;
  906. X        case POISON_RES:
  907. X#ifdef DEBUG
  908. X        debugpline("Trying to give poison resistance");
  909. X#endif
  910. X        if(!(HPoison_resistance & FROMOUTSIDE)) {
  911. X            You("feel healthy.");
  912. X            HPoison_resistance |= FROMOUTSIDE;
  913. X        }
  914. X        break;
  915. X        case TELEPORT:
  916. X#ifdef DEBUG
  917. X        debugpline("Trying to give teleport");
  918. X#endif
  919. X        if(!(HTeleportation & FROMOUTSIDE)) {
  920. X            You("feel very jumpy.");
  921. X            HTeleportation |= FROMOUTSIDE;
  922. X        }
  923. X        break;
  924. X        case TELEPORT_CONTROL:
  925. X#ifdef DEBUG
  926. X        debugpline("Trying to give teleport control");
  927. X#endif
  928. X        if(!(HTeleport_control & FROMOUTSIDE)) {
  929. X            You("feel in control of yourself.");
  930. X            HTeleport_control |= FROMOUTSIDE;
  931. X        }
  932. X        break;
  933. X        case TELEPAT:
  934. X#ifdef DEBUG
  935. X        debugpline("Trying to give telepathy");
  936. X#endif
  937. X        if(!(HTelepat & FROMOUTSIDE)) {
  938. X            You("feel a %s mental acuity.",
  939. X                Hallucination ? "normal" : "strange");
  940. X            HTelepat |= FROMOUTSIDE;
  941. X            /* If blind, make sure monsters show up. */
  942. X            if (Blind) see_monsters();
  943. X        }
  944. X        break;
  945. X        default:
  946. X#ifdef DEBUG
  947. X        debugpline("Tried to give an impossible intrinsic");
  948. X#endif
  949. X        break;
  950. X    }
  951. X}
  952. X
  953. Xstatic void
  954. Xcpostfx(pm)        /* called after completely consuming a corpse */
  955. Xregister int pm;
  956. X{
  957. X    register int tmp = 0;
  958. X
  959. X    switch(pm) {
  960. X        case PM_WRAITH:
  961. X        pluslvl();
  962. X        break;
  963. X#ifdef POLYSELF
  964. X        case PM_HUMAN_WERERAT:
  965. X        u.ulycn = PM_WERERAT;
  966. X        break;
  967. X        case PM_HUMAN_WEREJACKAL:
  968. X        u.ulycn = PM_WEREJACKAL;
  969. X        break;
  970. X        case PM_HUMAN_WEREWOLF:
  971. X        u.ulycn = PM_WEREWOLF;
  972. X        break;
  973. X#endif
  974. X        case PM_NURSE:
  975. X        u.uhp = u.uhpmax;
  976. X        flags.botl = 1;
  977. X        break;
  978. X        case PM_STALKER:
  979. X        if(!Invis) {
  980. X            HInvis = rn1(100, 50);
  981. X            if(!See_invisible)
  982. X                newsym(u.ux, u.uy);
  983. X        } else {
  984. X            register long oldprop = See_invisible;
  985. X            if (!(HInvis & INTRINSIC)) You("feel hidden!");
  986. X            HInvis |= FROMOUTSIDE;
  987. X            HSee_invisible |= FROMOUTSIDE;
  988. X            if (!oldprop)
  989. X                newsym(u.ux, u.uy);
  990. X        }
  991. X        /* fall into next case */
  992. X        case PM_YELLOW_LIGHT:
  993. X        /* fall into next case */
  994. X        case PM_GIANT_BAT:
  995. X        make_stunned(HStun + 30,FALSE);
  996. X        /* fall into next case */
  997. X        case PM_BAT:
  998. X        make_stunned(HStun + 30,FALSE);
  999. X        break;
  1000. X        case PM_GIANT_MIMIC:
  1001. X        tmp += 10;
  1002. X        /* fall into next case */
  1003. X        case PM_LARGE_MIMIC:
  1004. X        tmp += 20;
  1005. X        /* fall into next case */
  1006. X        case PM_SMALL_MIMIC:
  1007. X        tmp += 20;
  1008. X        if(u.usym == S_HUMAN) {
  1009. X            You("cannot resist the temptation to mimic a pile of gold.");
  1010. X            nomul(-tmp);
  1011. X            afternmv = eatmdone;
  1012. X            if (pl_character[0]=='E')
  1013. X            nomovemsg = "You now again prefer mimicking an elf.";
  1014. X            else
  1015. X            nomovemsg = "You now again prefer mimicking a human.";
  1016. X            u.usym = 0; /* hack! no monster sym 0; use for gold */
  1017. X            newsym(u.ux,u.uy);
  1018. X        }
  1019. X        break;
  1020. X        case PM_QUANTUM_MECHANIC:
  1021. X        Your("velocity suddenly seems very uncertain!");
  1022. X        if (Fast & INTRINSIC) {
  1023. X            Fast &= ~INTRINSIC;
  1024. X            You("seem slower.");
  1025. X        } else {
  1026. X            Fast |= FROMOUTSIDE;
  1027. X            You("seem faster.");
  1028. X        }
  1029. X        break;
  1030. X        case PM_LIZARD:
  1031. X        if (HStun > 2)  make_stunned(2L,FALSE);
  1032. X        if (HConfusion > 2)  make_confused(2L,FALSE);
  1033. X        break;
  1034. X        case PM_CHAMELEON:
  1035. X        You("feel a change coming over you.");
  1036. X#ifdef POLYSELF
  1037. X        polyself();
  1038. X#else
  1039. X        newman();
  1040. X#endif
  1041. X        break;
  1042. X        case PM_MIND_FLAYER:
  1043. X        if (ABASE(A_INT) < ATTRMAX(A_INT)) {
  1044. X            if (!rn2(2)) {
  1045. X                pline("Yum! That was real brain food!");
  1046. X                (void) adjattrib(A_INT, 1, FALSE);
  1047. X                break;    /* don't give them telepathy, too */
  1048. X            }
  1049. X        }
  1050. X        else {
  1051. X            pline("For some reason, that tasted bland.");
  1052. X        }
  1053. X        /* fall through to default case */
  1054. X        default: {
  1055. X        register struct permonst *ptr = &mons[pm];
  1056. X        int i, count;
  1057. X
  1058. X        if(dmgtype(ptr, AD_STUN) || pm==PM_VIOLET_FUNGUS) {
  1059. X            pline ("Oh wow!  Great stuff!");
  1060. X            make_hallucinated(HHallucination + 200,FALSE,0L);
  1061. X        }
  1062. X        /* prevent polymorph abuse by killing/eating your offspring */
  1063. X        if(pm >= PM_BABY_GRAY_DRAGON && pm <= PM_BABY_YELLOW_DRAGON)
  1064. X            return;
  1065. X        if(is_giant(ptr)) gainstr((struct obj *)0, 0);
  1066. X
  1067. X        /* Check the monster for all of the intrinsics.  If this
  1068. X         * monster can give more than one, pick one to try to give
  1069. X         * from among all it can give.
  1070. X         *
  1071. X         * If a monster can give 4 intrinsics then you have
  1072. X         * a 1/1 * 1/2 * 2/3 * 3/4 = 1/4 chance of getting the first,
  1073. X         * a 1/2 * 2/3 * 3/4 = 1/4 chance of getting the second,
  1074. X         * a 1/3 * 3/4 = 1/4 chance of getting the third,
  1075. X         * and a 1/4 chance of getting the fourth.
  1076. X         *
  1077. X         * And now a proof by induction:
  1078. X         * it works for 1 intrinsic (1 in 1 of getting it)
  1079. X         * for 2 you have a 1 in 2 chance of getting the second,
  1080. X         *    otherwise you keep the first
  1081. X         * for 3 you have a 1 in 3 chance of getting the third,
  1082. X         *    otherwise you keep the first or the second
  1083. X         * for n+1 you have a 1 in n+1 chance of getting the (n+1)st,
  1084. X         *    otherwise you keep the previous one.
  1085. X         * Elliott Kleinrock, October 5, 1990
  1086. X         */
  1087. X
  1088. X         count = 0;    /* number of possible intrinsics */
  1089. X         tmp = 0;    /* which one we will try to give */
  1090. X         for (i = 1; i <= LAST_PROP; i++) {
  1091. X            if (intrinsic_possible(i, ptr)) {
  1092. X                count++;
  1093. X                /* a 1 in count chance of replacing the old
  1094. X                 * one with this one, and a count-1 in count
  1095. X                 * chance of keeping the old one.  (note
  1096. X                 * that 1 in 1 and 0 in 1 are what we want
  1097. X                 * for the first one
  1098. X                 */
  1099. X                if (!rn2(count)) {
  1100. X#ifdef DEBUG
  1101. X                    debugpline("Intrinsic %d replacing %d",
  1102. X                                i, tmp);
  1103. X#endif
  1104. X                    tmp = i;
  1105. X                }
  1106. X            }
  1107. X         }
  1108. X
  1109. X         /* if any found try to give them one */
  1110. X         if (count) givit(tmp, ptr);
  1111. X        }
  1112. X        break;
  1113. X    }
  1114. X    return;
  1115. X}
  1116. X
  1117. XSTATIC_PTR
  1118. Xint
  1119. Xopentin()        /* called during each move whilst opening a tin */
  1120. X{
  1121. X    register int r;
  1122. X
  1123. X    if(!carried(tin.tin) && !obj_here(tin.tin, u.ux, u.uy))
  1124. X                    /* perhaps it was stolen? */
  1125. X        return(0);        /* %% probably we should use tinoid */
  1126. X    if(tin.usedtime++ >= 50) {
  1127. X        You("give up your attempt to open the tin.");
  1128. X        return(0);
  1129. X    }
  1130. X    if(tin.usedtime < tin.reqtime)
  1131. X        return(1);        /* still busy */
  1132. X    if(tin.tin->cursed && tin.tin->spe != -1 && !rn2(8)) {
  1133. X        b_trapped("tin");
  1134. X        goto use_me;
  1135. X    }
  1136. X    You("succeed in opening the tin.");
  1137. X    if(tin.tin->spe != 1) {
  1138. X        if(tin.tin->corpsenm == -1) {
  1139. X        pline("It turns out to be empty.");
  1140. X        tin.tin->dknown = tin.tin->known = TRUE;
  1141. X        goto use_me;
  1142. X        }
  1143. X        r = tin.tin->cursed ? 4 :        /* Always rotten if cursed */
  1144. X            (tin.tin->spe == -1) ? 5 :    /* "homemade" if player made */
  1145. X            rn2(TTSZ-1);        /* else take your pick */
  1146. X        pline("It smells like %s.", makeplural(
  1147. X          Hallucination ? rndmonnam() : mons[tin.tin->corpsenm].mname));
  1148. X        if (yn("Eat it?") == 'n') {
  1149. X        if (!Hallucination) tin.tin->dknown = tin.tin->known = TRUE;
  1150. X        if (flags.verbose) You("discard the open tin.");
  1151. X        goto use_me;
  1152. X        }
  1153. X        You("consume %s %s.", tintxts[r].txt,
  1154. X            mons[tin.tin->corpsenm].mname);
  1155. X        tin.tin->dknown = tin.tin->known = TRUE;
  1156. X        cprefx(tin.tin->corpsenm); cpostfx(tin.tin->corpsenm);
  1157. X
  1158. X        /* check for vomiting added by GAN 01/16/87 */
  1159. X        if(tintxts[r].nut < 0) make_vomiting((long)rn1(15,10), FALSE);
  1160. X        else lesshungry(tintxts[r].nut);
  1161. X
  1162. X        if(r == 0) {            /* Deep Fried */
  1163. X        Glib = rnd(15);
  1164. X        pline("Eating deep fried food made your %s very slippery.",
  1165. X            makeplural(body_part(FINGER)));
  1166. X        }
  1167. X    } else {
  1168. X        if (tin.tin->cursed)
  1169. X        pline("It contains some decaying %s substance.",
  1170. X            Hallucination ? hcolor() : green);
  1171. X        else
  1172. X        pline("It contains spinach.");
  1173. X
  1174. X        if (yn("Eat it?") == 'n') {
  1175. X        if (!Hallucination && !tin.tin->cursed)
  1176. X            tin.tin->dknown = tin.tin->known = TRUE;
  1177. X        if (flags.verbose)
  1178. X            You("discard the open tin.");
  1179. X        goto use_me;
  1180. X        }
  1181. X        if (!tin.tin->cursed)
  1182. X        pline("This makes you feel like %s!",
  1183. X              Hallucination ? "Swee'pea" : "Popeye");
  1184. X        lesshungry(600);
  1185. X        gainstr(tin.tin, 0);
  1186. X    }
  1187. X    tin.tin->dknown = tin.tin->known = TRUE;
  1188. Xuse_me:
  1189. X    if (carried(tin.tin)) useup(tin.tin);
  1190. X    else useupf(tin.tin);
  1191. X    tin.tin = (struct obj *) 0;
  1192. X    return(0);
  1193. X}
  1194. X
  1195. Xstatic void
  1196. Xstart_tin(otmp)        /* called when starting to open a tin */
  1197. X    register struct obj *otmp;
  1198. X{
  1199. X    register int tmp;
  1200. X
  1201. X#ifdef POLYSELF
  1202. X    if (metallivorous(uasmon)) {
  1203. X        You("bite right into the metal tin....");
  1204. X        tmp = 1;
  1205. X    } else
  1206. X#endif
  1207. X    if (otmp->blessed) {
  1208. X        pline("The tin opens like magic!");
  1209. X        tmp = 1;
  1210. X    } else if(uwep) {
  1211. X        switch(uwep->otyp) {
  1212. X        case TIN_OPENER:
  1213. X            tmp = 1;
  1214. X            break;
  1215. X        case DAGGER:
  1216. X        case ELVEN_DAGGER:
  1217. X        case ORCISH_DAGGER:
  1218. X        case ATHAME:
  1219. X        case CRYSKNIFE:
  1220. X            tmp = 3;
  1221. X            break;
  1222. X        case PICK_AXE:
  1223. X        case AXE:
  1224. X            tmp = 6;
  1225. X            break;
  1226. X        default:
  1227. X            goto no_opener;
  1228. X        }
  1229. X        pline("Using your %s you try to open the tin.",
  1230. X            aobjnam(uwep, NULL));
  1231. X    } else {
  1232. Xno_opener:
  1233. X        pline("It is not so easy to open this tin.");
  1234. X        if(Glib) {
  1235. X            pline("The tin slips out of your hands.");
  1236. X            if(otmp->quan > 1L) {
  1237. X                register struct obj *obj;
  1238. X                obj = splitobj(otmp, 1L);
  1239. X                if(otmp == uwep) setuwep(obj);
  1240. X            }
  1241. X            if (carried(otmp)) dropx(otmp);
  1242. X            else stackobj(otmp);
  1243. X            return;
  1244. X        }
  1245. X        tmp = rn1(1 + 500/((int)(ACURR(A_DEX) + ACURRSTR)), 10);
  1246. X    }
  1247. X    tin.reqtime = tmp;
  1248. X    tin.usedtime = 0;
  1249. X    tin.tin = otmp;
  1250. X    set_occupation(opentin, "opening the tin", 0);
  1251. X    return;
  1252. X}
  1253. X
  1254. Xint
  1255. XHear_again() {        /* called when waking up after fainting */
  1256. X    flags.soundok = 1;
  1257. X    return 0;
  1258. X}
  1259. X
  1260. Xstatic int
  1261. X#ifdef POLYSELF
  1262. Xrottenfood(obj)
  1263. Xstruct obj *obj;
  1264. X#else
  1265. Xrottenfood()
  1266. X#endif
  1267. X{        /* called on the "first bite" of rotten food */
  1268. X#ifdef POLYSELF
  1269. X    pline("Blecch!  Rotten %s!", foodword(obj));
  1270. X#else
  1271. X    pline("Blecch!  Rotten food!");
  1272. X#endif
  1273. X    if(!rn2(4)) {
  1274. X        if (Hallucination) You("feel rather trippy.");
  1275. X        else You("feel rather %s.", body_part(LIGHT_HEADED));
  1276. X        make_confused(HConfusion + d(2,4),FALSE);
  1277. X    } else if(!rn2(4) && !Blind) {
  1278. X        pline("Everything suddenly goes dark.");
  1279. X        make_blinded((long)d(2,10),FALSE);
  1280. X    } else if(!rn2(3)) {
  1281. X        if(Blind)
  1282. X          pline("The world spins and you slap against the floor.");
  1283. X        else
  1284. X          pline("The world spins and goes dark.");
  1285. X        flags.soundok = 0;
  1286. X        nomul(-rnd(10));
  1287. X        nomovemsg = "You are conscious again.";
  1288. X        afternmv = Hear_again;
  1289. X        return(1);
  1290. X    }
  1291. X    return(0);
  1292. X}
  1293. X
  1294. Xstatic int
  1295. Xeatcorpse(otmp)        /* called when a corpse is selected as food */
  1296. X    register struct obj *otmp;
  1297. X{
  1298. X    register const char *cname = mons[otmp->corpsenm].mname;
  1299. X    register int tp, rotted = 0;
  1300. X
  1301. X    tp = 0;
  1302. X
  1303. X    if(otmp->corpsenm != PM_LIZARD) {
  1304. X#ifndef LINT    /* problem if more than 320K moves before try to eat */
  1305. X        rotted = (monstermoves - otmp->age)/((long)(10 + rn2(20)));
  1306. X#endif
  1307. X
  1308. X        if(otmp->cursed) rotted += 2;
  1309. X        else if (otmp->blessed) rotted -= 2;
  1310. X    }
  1311. X
  1312. X    if(otmp->corpsenm != PM_ACID_BLOB && (rotted > 5)) {
  1313. X        pline("Ulch - that %s was tainted!",
  1314. X              mons[otmp->corpsenm].mlet == S_FUNGUS ? "fungoid vegetation" :
  1315. X              is_meaty(&mons[otmp->corpsenm]) ? "meat" : "protoplasm");
  1316. X#ifdef POLYSELF
  1317. X        if (u.usym == S_FUNGUS)
  1318. X            pline("It doesn't seem at all sickening, though...");
  1319. X        else {
  1320. X#endif
  1321. X            make_sick((long) rn1(10, 10),FALSE);
  1322. X            Sprintf(corpsename, "rotted %s corpse", cname);
  1323. X            u.usick_cause = (const char *)corpsename;
  1324. X            flags.botl = 1;
  1325. X#ifdef POLYSELF
  1326. X        }
  1327. X#endif
  1328. X        if (carried(otmp)) useup(otmp);
  1329. X        else useupf(otmp);
  1330. X        return(1);
  1331. X    } else if(acidic(&mons[otmp->corpsenm])
  1332. X#ifdef POLYSELF
  1333. X          && !resists_acid(uasmon)
  1334. X#endif
  1335. X         ) {
  1336. X        tp++;
  1337. X        You("have a very bad case of stomach acid.");
  1338. X        losehp(rnd(15), "acidic corpse", KILLED_BY_AN);
  1339. X    } else if(poisonous(&mons[otmp->corpsenm]) && rn2(5)) {
  1340. X        tp++;
  1341. X        pline("Ecch - that must have been poisonous!");
  1342. X        if(!Poison_resistance) {
  1343. X            losestr(rnd(4));
  1344. X            losehp(rnd(15), "poisonous corpse", KILLED_BY_AN);
  1345. X        } else    You("seem unaffected by the poison.");
  1346. X    /* now any corpse left too long will make you mildly ill */
  1347. X    } else if(((rotted > 5) || ((rotted > 3) && rn2(5)))
  1348. X#ifdef POLYSELF
  1349. X        && u.usym != S_FUNGUS
  1350. X#endif
  1351. X                            ){
  1352. X        tp++;
  1353. X        You("feel%s sick.", (Sick) ? " very" : "");
  1354. X        losehp(rnd(8), "cadaver", KILLED_BY_AN);
  1355. X    }
  1356. X    if(!tp && otmp->corpsenm != PM_LIZARD && (otmp->orotten || !rn2(7))) {
  1357. X#ifdef POLYSELF
  1358. X        if(rottenfood(otmp)) {
  1359. X#else
  1360. X        if(rottenfood()) {
  1361. X#endif
  1362. X        otmp->orotten = TRUE;
  1363. X        (void)touchfood(otmp);
  1364. X        return(1);
  1365. X        }
  1366. X        otmp->oeaten >>= 2;
  1367. X    } else {
  1368. X#ifdef POLYSELF
  1369. X        pline("This %s corpse %s!", cname,
  1370. X        (carnivorous(uasmon) && !herbivorous(uasmon))
  1371. X        ? "is delicious" : "tastes terrible");
  1372. X#else
  1373. X        pline("This %s corpse tastes terrible!", cname);
  1374. X#endif
  1375. X    }
  1376. X
  1377. X    /* delay is weight dependent */
  1378. X    victual.reqtime = 3 + (mons[otmp->corpsenm].cwt >> 6);
  1379. X    return(0);
  1380. X}
  1381. X
  1382. Xstatic void
  1383. Xstart_eating(otmp)        /* called as you start to eat */
  1384. X    register struct obj *otmp;
  1385. X{
  1386. X#ifdef DEBUG
  1387. X    debugpline("start_eating: %lx (victual = %lx)", otmp, victual.piece);
  1388. X    debugpline("reqtime = %d", victual.reqtime);
  1389. X    debugpline("(original reqtime = %d)", objects[otmp->otyp].oc_delay);
  1390. X    debugpline("nmod = %d", victual.nmod);
  1391. X    debugpline("oeaten = %d", otmp->oeaten);
  1392. X#endif
  1393. X    victual.fullwarn = victual.doreset = FALSE;
  1394. X    victual.eating = TRUE;
  1395. X
  1396. X    if (otmp->otyp == CORPSE) {
  1397. X        cprefx(victual.piece->corpsenm);
  1398. X        if (!victual.piece && victual.eating) do_reset_eat();
  1399. X        if (victual.eating == FALSE) return; /* died and lifesaved */
  1400. X    }
  1401. X
  1402. X    if (bite()) return;
  1403. X
  1404. X    if(++victual.usedtime >= victual.reqtime) {
  1405. X        /* print "finish eating" message if they just resumed -dlc */
  1406. X        done_eating(victual.reqtime > 1 ? TRUE : FALSE);
  1407. X        return;
  1408. X    }
  1409. X
  1410. X    Sprintf(msgbuf, "eating %s", the(singular(otmp, xname)));
  1411. X    set_occupation(eatfood, msgbuf, 0);
  1412. X}
  1413. X
  1414. X
  1415. Xstatic void
  1416. Xfprefx(otmp)        /* called on "first bite" of (non-corpse) food */
  1417. X
  1418. X    register struct obj *otmp;
  1419. X{
  1420. X    switch(otmp->otyp) {
  1421. X
  1422. X        case FOOD_RATION:
  1423. X        if(u.uhunger <= 200)
  1424. X            if (Hallucination) pline("Oh wow, like, superior, man!");
  1425. X            else           pline("That food really hit the spot!");
  1426. X        else if(u.uhunger <= 700) pline("That satiated your stomach!");
  1427. X        break;
  1428. X        case TRIPE_RATION:
  1429. X#ifdef POLYSELF
  1430. X        if (carnivorous(uasmon) && !humanoid(uasmon))
  1431. X            pline("That tripe ration was surprisingly good!");
  1432. X        else {
  1433. X#endif
  1434. X            pline("Yak - dog food!");
  1435. X            more_experienced(1,0);
  1436. X            flags.botl = 1;
  1437. X#ifdef POLYSELF
  1438. X        }
  1439. X#endif
  1440. X        if(rn2(2)
  1441. X#ifdef POLYSELF
  1442. X            && (!carnivorous(uasmon) || humanoid(uasmon))
  1443. X#endif
  1444. X                        ) {
  1445. X            make_vomiting((long)rn1(victual.reqtime, 14), FALSE);
  1446. X        }
  1447. X        break;
  1448. X#ifdef POLYSELF
  1449. X        case CLOVE_OF_GARLIC:
  1450. X        if (is_undead(uasmon)) {
  1451. X            make_vomiting((long)rn1(victual.reqtime, 5), FALSE);
  1452. X            break;
  1453. X        }
  1454. X        /* Fall through otherwise */
  1455. X#endif
  1456. X        default:
  1457. X#ifdef TUTTI_FRUTTI
  1458. X        if (otmp->otyp==SLIME_MOLD && !otmp->cursed
  1459. X            && otmp->spe == current_fruit)
  1460. X            pline("My, that was a yummy %s!", singular(otmp, xname));
  1461. X        else
  1462. X#endif
  1463. X#ifdef UNIX
  1464. X        if (otmp->otyp == APPLE || otmp->otyp == PEAR) {
  1465. X            if (!Hallucination) pline("Core dumped.");
  1466. X            else {
  1467. X/* This is based on an old Usenet joke, a fake a.out manual page */
  1468. X            int x = rnd(100);
  1469. X            if (x <= 75)
  1470. X                pline("Segmentation fault -- core dumped.");
  1471. X            else if (x <= 99)
  1472. X                pline("Bus error -- core dumped.");
  1473. X            else pline("Yo' mama -- core dumped.");
  1474. X            }
  1475. X        } else
  1476. X#endif
  1477. X            pline("This %s is %s!", singular(otmp, xname),
  1478. X              otmp->cursed ? (Hallucination ? "grody" : "terrible"):
  1479. X              Hallucination ? "gnarly" :
  1480. X            (otmp->otyp==CRAM_RATION ? "bland" : "delicious"));
  1481. X        break;
  1482. X    }
  1483. X}
  1484. X
  1485. X#ifdef POLYSELF
  1486. Xstatic void
  1487. Xeatring(otmp)
  1488. Xstruct obj *otmp;
  1489. X{
  1490. X    int typ = otmp->otyp;
  1491. X    int oldprop;
  1492. X
  1493. X    /* Note: rings are not so common that this is unbalancing.  (How */
  1494. X    /* often do you even _find_ 3 rings of polymorph in a game? */
  1495. X    oldprop = !!(u.uprops[objects[typ].oc_oprop].p_flgs);
  1496. X    otmp->known = otmp->dknown = 1; /* by taste */
  1497. X    if (!rn2(3)) switch (otmp->otyp) {
  1498. X        case RIN_AGGRAVATE_MONSTER:
  1499. X        case RIN_WARNING:
  1500. X        case RIN_POISON_RESISTANCE:
  1501. X        case RIN_FIRE_RESISTANCE:
  1502. X        case RIN_COLD_RESISTANCE:
  1503. X        case RIN_SHOCK_RESISTANCE:
  1504. X        case RIN_TELEPORTATION:
  1505. X        case RIN_TELEPORT_CONTROL:
  1506. X        case RIN_SEE_INVISIBLE:
  1507. X        case RIN_PROTECTION_FROM_SHAPE_CHAN:
  1508. X        case RIN_SEARCHING:
  1509. X        case RIN_STEALTH:
  1510. X        case RIN_INVISIBILITY:
  1511. X        case RIN_CONFLICT:
  1512. X        case RIN_POLYMORPH:
  1513. X        case RIN_POLYMORPH_CONTROL:
  1514. X        case RIN_REGENERATION: /* Probably stupid. */
  1515. X        case RIN_HUNGER: /* Stupid. */
  1516. X        case RIN_LEVITATION: /* Stupid. */
  1517. X        if (!(u.uprops[objects[typ].oc_oprop].p_flgs & FROMOUTSIDE))
  1518. X            pline("Magic spreads through your body as you digest the ring.");
  1519. X        u.uprops[objects[typ].oc_oprop].p_flgs |= FROMOUTSIDE;
  1520. X        if (typ == RIN_SEE_INVISIBLE) {
  1521. X            set_mimic_blocking();
  1522. X            see_monsters();
  1523. X            if (Invis && !oldprop
  1524. X#ifdef POLYSELF
  1525. X                && !perceives(uasmon)
  1526. X#endif
  1527. X                            && !Blind) {
  1528. X            newsym(u.ux,u.uy);
  1529. X            pline("Suddenly you can see yourself.");
  1530. X            makeknown(typ);
  1531. X            }
  1532. X        } else if (typ == RIN_INVISIBILITY) {
  1533. X            if (!oldprop && !See_invisible && !Blind) {
  1534. X            newsym(u.ux,u.uy);
  1535. X            Your("body takes on a %s transparency...",
  1536. X                Hallucination ? "normal" : "strange");
  1537. X            makeknown(typ);
  1538. X            }
  1539. X        } else if (typ == RIN_PROTECTION_FROM_SHAPE_CHAN)
  1540. X            rescham();
  1541. X        else if (typ == RIN_LEVITATION) {
  1542. X            if (!Levitation) {
  1543. X            float_up();
  1544. X            makeknown(typ);
  1545. X            }
  1546. X        }
  1547. X        break;
  1548. X        case RIN_ADORNMENT:
  1549. X        if (adjattrib(A_CHA, otmp->spe, -1))
  1550. X            makeknown(typ);
  1551. X        break;
  1552. X        case RIN_GAIN_STRENGTH:
  1553. X        case RIN_INCREASE_DAMAGE: /* Any better ideas? */
  1554. X        if (adjattrib(A_STR, otmp->spe, -1))
  1555. X            makeknown(typ);
  1556. X        break;
  1557. X        case RIN_PROTECTION:
  1558. X        Protection |= FROMOUTSIDE;
  1559. X        u.ublessed += otmp->spe;
  1560. X        flags.botl = 1;
  1561. X        break;
  1562. X    }
  1563. X}
  1564. X
  1565. Xstatic void
  1566. Xeatspecial() /* called after eating non-food */
  1567. X{
  1568. X    register struct obj *otmp = victual.piece;
  1569. X
  1570. X    lesshungry(victual.nmod);
  1571. X    victual.piece = (struct obj *)0;
  1572. X    victual.eating = 0;
  1573. X    if (otmp->oclass == GOLD_CLASS) {
  1574. X        dealloc_obj(otmp);
  1575. X        return;
  1576. X    }
  1577. X    if (otmp->oclass == POTION_CLASS) {
  1578. X        otmp->quan++; /* dopotion() does a useup() */
  1579. X        (void)dopotion(otmp);
  1580. X    }
  1581. X    if (otmp->oclass == RING_CLASS)
  1582. X        eatring(otmp);
  1583. X    if (otmp == uball) unpunish();
  1584. X    if (otmp == uchain) unpunish(); /* but no useup() */
  1585. X    else if (carried(otmp)) useup(otmp);
  1586. X    else useupf(otmp);
  1587. X}
  1588. X
  1589. X/* NOTE: the order of these words exactly corresponds to the
  1590. X   order of oc_material values #define'd in objclass.h. */
  1591. Xstatic const char *foodwords[] = {
  1592. X    "meal", "liquid", "wax", "food", "meat",
  1593. X    "paper", "cloth", "leather", "wood", "bone", "scale",
  1594. X    "metal", "metal", "metal", "silver", "gold", "platinum", "mithril",
  1595. X    "plastic", "glass", "rich food", "stone"
  1596. X};
  1597. X
  1598. Xstatic const char *
  1599. Xfoodword(otmp)
  1600. Xregister struct obj *otmp;
  1601. X{
  1602. X    if (otmp->oclass == FOOD_CLASS) return "food";
  1603. X    if (otmp->oclass == GEM_CLASS &&
  1604. X        objects[otmp->otyp].oc_material == GLASS &&
  1605. X        otmp->dknown)
  1606. X        makeknown(otmp->otyp);
  1607. X    return foodwords[objects[otmp->otyp].oc_material];
  1608. X}
  1609. X#endif
  1610. X
  1611. Xstatic void
  1612. Xfpostfx(otmp)        /* called after consuming (non-corpse) food */
  1613. X
  1614. X    register struct obj *otmp;
  1615. X{
  1616. X    switch(otmp->otyp) {
  1617. X#ifdef POLYSELF
  1618. X        case SPRIG_OF_WOLFSBANE:
  1619. X        if (u.ulycn != -1) {
  1620. X            u.ulycn = -1;
  1621. X            You("feel purified.");
  1622. X            if(uasmon == &mons[u.ulycn] && !Polymorph_control)
  1623. X            rehumanize();
  1624. X        }
  1625. X        break;
  1626. X#endif
  1627. X        case CARROT:
  1628. X        make_blinded(0L,TRUE);
  1629. X        break;
  1630. X        case FORTUNE_COOKIE:
  1631. X        outrumor(bcsign(otmp), TRUE);
  1632. X        break;
  1633. X        case LUMP_OF_ROYAL_JELLY:
  1634. X        /* This stuff seems to be VERY healthy! */
  1635. X        gainstr(otmp, 1);
  1636. X        u.uhp += (otmp->cursed) ? -rnd(20) : rnd(20);
  1637. X        if(u.uhp > u.uhpmax) {
  1638. X            if(!rn2(17)) u.uhpmax++;
  1639. X            u.uhp = u.uhpmax;
  1640. X        } else if(u.uhp <= 0) {
  1641. X            killer_format = KILLED_BY_AN;
  1642. X            killer = "rotten lump of royal jelly";
  1643. X            done(POISONING);
  1644. X        }
  1645. X        if(!otmp->cursed) heal_legs();
  1646. X        break;
  1647. X        case EGG:
  1648. X        if(otmp->corpsenm == PM_COCKATRICE) {
  1649. X#ifdef POLYSELF
  1650. X            if(!resists_ston(uasmon))
  1651. X            if(!poly_when_stoned(uasmon) ||
  1652. X               !polymon(PM_STONE_GOLEM))
  1653. X            {
  1654. X#endif
  1655. X            if (!Stoned) Stoned = 5;
  1656. X            killer_format = KILLED_BY_AN;
  1657. X            killer = "cockatrice egg";
  1658. X#ifdef POLYSELF
  1659. X            }
  1660. X#endif
  1661. X        }
  1662. X        break;
  1663. X    }
  1664. X    return;
  1665. X}
  1666. X
  1667. Xint
  1668. Xdoeat()        /* generic "eat" command funtion (see cmd.c) */
  1669. X{
  1670. X    register struct obj *otmp;
  1671. X    int basenutrit;            /* nutrition of full item */
  1672. X
  1673. X    if (Strangled) {
  1674. X        pline("If you can't breathe air, how can you consume solids?");
  1675. X        return 0;
  1676. X    }
  1677. X    if (!(otmp = floorfood("eat", 0))) return 0;
  1678. X    if (check_capacity(NULL)) return 0;
  1679. X#ifdef POLYSELF
  1680. X    /* We have to make non-foods take no time to eat, unless we want to
  1681. X     * do ridiculous amounts of coding to deal with partly eaten plate
  1682. X     * mails, players who polymorph back to human in the middle of their
  1683. X     * metallic meal, etc....
  1684. X     */
  1685. X    if (!is_edible(otmp)) {
  1686. X        You("cannot eat that!");
  1687. X        return 0;
  1688. X    }
  1689. X    if (otmp->oclass != FOOD_CLASS) {
  1690. X        victual.reqtime = 1;
  1691. X        victual.piece = otmp;
  1692. X        /* Don't split it, we don't need to if it's 1 move */
  1693. X        victual.usedtime = 0;
  1694. X        victual.canchoke = (u.uhs == SATIATED);
  1695. X        /* Note: gold weighs 1 pt. for each 1000 pieces (see */
  1696. X        /* pickup.c) so gold and non-gold is consistent. */
  1697. X        if (otmp->oclass == GOLD_CLASS)
  1698. X        basenutrit = ((otmp->quan > 200000L) ? 2000
  1699. X            : (int)(otmp->quan/100L));
  1700. X        else basenutrit = objects[otmp->otyp].oc_nutrition;
  1701. X        victual.nmod = basenutrit;
  1702. X        victual.eating = TRUE; /* needed for lesshungry() */
  1703. X
  1704. X        if (otmp->cursed)
  1705. X        (void) rottenfood(otmp);
  1706. X
  1707. X        if (otmp->oclass == WEAPON_CLASS && otmp->opoisoned) {
  1708. X        pline("Ecch - that must have been poisonous!");
  1709. X        if(!Poison_resistance) {
  1710. X            losestr(rnd(4));
  1711. X            losehp(rnd(15), xname(otmp), KILLED_BY_AN);
  1712. X        } else
  1713. X            You("seem unaffected by the poison.");
  1714. X        } else if (!otmp->cursed)
  1715. X        pline("This %s is delicious!",
  1716. X              otmp->oclass == GOLD_CLASS ? foodword(otmp) :
  1717. X              singular(otmp, xname));
  1718. X        eatspecial();
  1719. X        return 1;
  1720. X    }
  1721. X#endif
  1722. X
  1723. X    if(otmp == victual.piece) {
  1724. X    /* If they weren't able to choke, they don't suddenly become able to
  1725. X     * choke just because they were interrupted.  On the other hand, if
  1726. X     * they were able to choke before, if they lost food it's possible
  1727. X     * they shouldn't be able to choke now.
  1728. X     */
  1729. X        if (u.uhs != SATIATED) victual.canchoke = FALSE;
  1730. X        if(!carried(victual.piece)) {
  1731. X        if(victual.piece->quan > 1L)
  1732. X            (void) splitobj(victual.piece, 1L);
  1733. X        }
  1734. X        You("resume your meal.");
  1735. X        start_eating(victual.piece);
  1736. X        return(1);
  1737. X    }
  1738. X
  1739. X    /* nothing in progress - so try to find something. */
  1740. X    /* tins are a special case */
  1741. X    if(otmp->otyp == TIN) {
  1742. X        start_tin(otmp);
  1743. X        return(1);
  1744. X    }
  1745. X
  1746. X    victual.piece = otmp = touchfood(otmp);
  1747. X    victual.usedtime = 0;
  1748. X
  1749. X    /* Now we need to calculate delay and nutritional info.
  1750. X     * The base nutrition calculated here and in eatcorpse() accounts
  1751. X     * for normal vs. rotten food.  The reqtime and nutrit values are
  1752. X     * then adjusted in accordance with the amount of food left.
  1753. X     */
  1754. X    if(otmp->otyp == CORPSE) {
  1755. X        if(eatcorpse(otmp)) return(1);
  1756. X        /* else eatcorpse sets up reqtime and oeaten */
  1757. X    } else {
  1758. X        victual.reqtime = objects[otmp->otyp].oc_delay;
  1759. X        if (otmp->otyp != FORTUNE_COOKIE &&
  1760. X        (otmp->cursed ||
  1761. X         (((monstermoves - otmp->age) > (int) otmp->blessed ? 50:30) &&
  1762. X        (otmp->orotten || !rn2(7))))) {
  1763. X
  1764. X#ifdef POLYSELF
  1765. X        if(rottenfood(otmp)) {
  1766. X#else
  1767. X        if(rottenfood()) {
  1768. X#endif
  1769. X            otmp->orotten = TRUE;
  1770. X            return(1);
  1771. X        }
  1772. X        otmp->oeaten >>= 1;
  1773. X        } else fprefx(otmp);
  1774. X    }
  1775. X
  1776. X    /* re-calc the nutrition */
  1777. X    if (otmp->otyp == CORPSE) basenutrit = mons[otmp->corpsenm].cnutrit;
  1778. X    else basenutrit = objects[otmp->otyp].oc_nutrition;
  1779. X
  1780. X#ifdef DEBUG
  1781. X    debugpline("before rounddiv: victual.reqtime == %d", victual.reqtime);
  1782. X    debugpline("oeaten == %d, basenutrit == %d", otmp->oeaten, basenutrit);
  1783. X#endif
  1784. X    victual.reqtime = (basenutrit == 0 ? 0 :
  1785. X        rounddiv(victual.reqtime * (long)otmp->oeaten, basenutrit));
  1786. X#ifdef DEBUG
  1787. X    debugpline("after rounddiv: victual.reqtime == %d", victual.reqtime);
  1788. X#endif
  1789. X    /* calculate the modulo value (nutrit. units per round eating)
  1790. X     * note: this isn't exact - you actually lose a little nutrition
  1791. X     *     due to this method.
  1792. X     * TODO: add in a "remainder" value to be given at the end of the
  1793. X     *     meal.
  1794. X     */
  1795. X    if(victual.reqtime == 0)
  1796. X        /* possible if most has been eaten before */
  1797. X        victual.nmod = 0;
  1798. X    else if (otmp->oeaten > victual.reqtime)
  1799. X        victual.nmod = -(otmp->oeaten / victual.reqtime);
  1800. X    else
  1801. X        victual.nmod = victual.reqtime % otmp->oeaten;
  1802. X    victual.canchoke = (u.uhs == SATIATED);
  1803. X
  1804. X    start_eating(otmp);
  1805. X    return(1);
  1806. X}
  1807. X
  1808. X/* Take a single bite from a piece of food, checking for choking and
  1809. X * modifying usedtime.  Returns 1 if they choked and survived, 0 otherwise.
  1810. X */
  1811. Xstatic int
  1812. Xbite()
  1813. X{
  1814. X    if(victual.canchoke && u.uhunger >= 2000) {
  1815. X        choke(victual.piece);
  1816. X        return 1;
  1817. X    }
  1818. X    if (victual.doreset) {
  1819. X        do_reset_eat();
  1820. X        return 0;
  1821. X    }
  1822. X    if(victual.nmod < 0) {
  1823. X        lesshungry(-victual.nmod);
  1824. X        victual.piece->oeaten -= -victual.nmod;
  1825. X    } else if(victual.nmod > 0 && (victual.usedtime % victual.nmod)) {
  1826. X        lesshungry(1);
  1827. X        victual.piece->oeaten--;
  1828. X    }
  1829. X    recalc_wt();
  1830. X    return 0;
  1831. X}
  1832. X
  1833. X#endif /* OVLB */
  1834. X#ifdef OVL0
  1835. X
  1836. Xvoid
  1837. Xgethungry()    /* as time goes by - called by moveloop() and domove() */
  1838. X{
  1839. X    if (u.uinvulnerable) return;    /* you don't feel hungrier */
  1840. X
  1841. X    if ((!u.usleep || !rn2(10))    /* slow metabolic rate while asleep */
  1842. X        && (carnivorous(uasmon) || herbivorous(uasmon)))
  1843. X        u.uhunger--;        /* ordinary food consumption */
  1844. X
  1845. X    if (moves % 2) {    /* odd turns */
  1846. X        /* Regeneration uses up food, unless due to an artifact */
  1847. X        if ((HRegeneration & (~W_ART)) &&
  1848. X        (HRegeneration != W_WEP || !uwep->oartifact)) u.uhunger--;
  1849. X        if (near_capacity() > SLT_ENCUMBER) u.uhunger--;
  1850. X    } else {        /* even turns */
  1851. X        if (Hunger) u.uhunger--;
  1852. X        /* Conflict uses up food too */
  1853. X        if ((Conflict & (~W_ARTI))) u.uhunger--;
  1854. X        /* +0 charged rings don't do anything, so don't affect hunger */
  1855. X        switch (moves % 20) {    /* note: use even cases only */
  1856. X         case  4: if (uleft &&
  1857. X              (uleft->spe || !objects[uleft->otyp].oc_charged))
  1858. X                u.uhunger--;
  1859. X            break;
  1860. X         case  8: if (uamul) u.uhunger--;
  1861. X            break;
  1862. X         case 12: if (uright &&
  1863. X              (uright->spe || !objects[uright->otyp].oc_charged))
  1864. X                u.uhunger--;
  1865. X            break;
  1866. X         case 16: if (u.uhave.amulet) u.uhunger--;
  1867. X            break;
  1868. X         default: break;
  1869. X        }
  1870. X    }
  1871. X    newuhs(TRUE);
  1872. X}
  1873. X
  1874. X#endif /* OVL0 */
  1875. X#ifdef OVLB
  1876. X
  1877. Xvoid
  1878. Xmorehungry(num)    /* called after vomiting and after performing feats of magic */
  1879. Xregister int num;
  1880. X{
  1881. X    u.uhunger -= num;
  1882. X    newuhs(TRUE);
  1883. X}
  1884. X
  1885. X
  1886. Xvoid
  1887. Xlesshungry(num)    /* called after eating (and after drinking fruit juice) */
  1888. Xregister int num;
  1889. X{
  1890. X#ifdef DEBUG
  1891. X    debugpline("lesshungry(%d)", num);
  1892. X#endif
  1893. X    u.uhunger += num;
  1894. X    if(u.uhunger >= 2000) {
  1895. X        if (!victual.eating || victual.canchoke)
  1896. X        if (victual.eating) {
  1897. X            choke(victual.piece);
  1898. X            reset_eat();
  1899. X        } else
  1900. X        if (tin.tin)
  1901. X            choke(tin.tin);
  1902. X        else
  1903. X            choke((struct obj *) 0);
  1904. X        /* no reset_eat(); it was a non-food such as juice */
  1905. X    } else {
  1906. X        /* Have lesshungry() report when you're nearly full so all eating
  1907. X         * warns when you're about to choke.
  1908. X         */
  1909. X        if (u.uhunger >= 1500) {
  1910. X          if(!victual.eating || (victual.eating && !victual.fullwarn)) {
  1911. X        pline("You're having a hard time getting all of it down.");
  1912. X        nomovemsg = "You're finally finished.";
  1913. X        if(!victual.eating)
  1914. X            multi = -2;
  1915. X        else {
  1916. X            victual.fullwarn = TRUE;
  1917. X            if (victual.canchoke &&
  1918. X            /* a one-gulp food will not survive a stop */
  1919. X                objects[victual.piece->otyp].oc_delay > 1) {
  1920. X            if(yn("Stop eating?") == 'y')
  1921. X            {
  1922. X                reset_eat();
  1923. X                nomovemsg = NULL;
  1924. X            }
  1925. X            }
  1926. X        }
  1927. X          }
  1928. X        }
  1929. X    }
  1930. X    newuhs(FALSE);
  1931. X}
  1932. X
  1933. XSTATIC_PTR
  1934. Xint
  1935. Xunfaint() {
  1936. X    (void) Hear_again();
  1937. X    if(u.uhs > FAINTING)
  1938. X        u.uhs = FAINTING;
  1939. X    stop_occupation();
  1940. X    flags.botl = 1;
  1941. X    return 0;
  1942. X}
  1943. X
  1944. X#endif /* OVLB */
  1945. X#ifdef OVL0
  1946. X
  1947. Xboolean
  1948. Xis_fainted() {
  1949. X    return(u.uhs == FAINTED);
  1950. X}
  1951. X
  1952. Xvoid
  1953. Xreset_faint() {    /* call when a faint must be prematurely terminated */
  1954. X    if(is_fainted()) nomul(0);
  1955. X}
  1956. X
  1957. X#if 0
  1958. Xvoid
  1959. Xsync_hunger() {
  1960. X
  1961. X    if(is_fainted()) {
  1962. X
  1963. X        flags.soundok = 0;
  1964. X        nomul(-10+(u.uhunger/10));
  1965. X        nomovemsg = "You regain consciousness.";
  1966. X        afternmv = unfaint;
  1967. X    }
  1968. X}
  1969. X#endif
  1970. X
  1971. Xvoid
  1972. Xnewuhs(incr)        /* compute and comment on your (new?) hunger status */
  1973. X    boolean incr;
  1974. X{
  1975. X    register int newhs, h = u.uhunger;
  1976. X
  1977. X    newhs = (h > 1000) ? SATIATED :
  1978. X        (h > 150) ? NOT_HUNGRY :
  1979. X        (h > 50) ? HUNGRY :
  1980. X        (h > 0) ? WEAK : FAINTING;
  1981. X
  1982. X    if(newhs == FAINTING) {
  1983. X        if(is_fainted()) newhs = FAINTED;
  1984. X        if(u.uhs <= WEAK || rn2(20-u.uhunger/10) >= 19) {
  1985. X            if(!is_fainted() && multi >= 0 /* %% */) {
  1986. X                /* stop what you're doing, then faint */
  1987. X                stop_occupation();
  1988. X                You("faint from lack of food.");
  1989. X                flags.soundok = 0;
  1990. X                nomul(-10+(u.uhunger/10));
  1991. X                nomovemsg = "You regain consciousness.";
  1992. X                afternmv = unfaint;
  1993. X                newhs = FAINTED;
  1994. X            }
  1995. X        } else
  1996. X        if(u.uhunger < -(int)(200 + 20*ACURR(A_CON))) {
  1997. X            u.uhs = STARVED;
  1998. X            flags.botl = 1;
  1999. X            bot();
  2000. X            You("die from starvation.");
  2001. X            killer_format = KILLED_BY;
  2002. X            killer = "starvation";
  2003. X            done(STARVING);
  2004. X            /* if we return, we lifesaved, and that calls newuhs */
  2005. X            return;
  2006. X        }
  2007. X    }
  2008. X
  2009. X    if(newhs != u.uhs) {
  2010. X        if(newhs >= WEAK && u.uhs < WEAK)
  2011. X            losestr(1);    /* this may kill you -- see below */
  2012. X        else if(newhs < WEAK && u.uhs >= WEAK)
  2013. X            losestr(-1);
  2014. X        switch(newhs){
  2015. X        case HUNGRY:
  2016. X            if (Hallucination) {
  2017. X                pline((!incr) ?
  2018. X                "You now have a lesser case of the munchies." :
  2019. X                "You are getting the munchies.");
  2020. X            } else
  2021. X                You((!incr) ? "only feel hungry now." :
  2022. X                  (u.uhunger < 145) ? "feel hungry." :
  2023. X                   "are beginning to feel hungry.");
  2024. X            if (incr && occupation &&
  2025. X                (occupation != eatfood && occupation != opentin))
  2026. X                stop_occupation();
  2027. X            break;
  2028. X        case WEAK:
  2029. X            if (Hallucination)
  2030. X                pline((!incr) ?
  2031. X                  "You still have the munchies." :
  2032. X      "The munchies are interfering with your motor capabilities.");
  2033. X            else
  2034. X                You((!incr) ? "feel weak now." :
  2035. X                  (u.uhunger < 45) ? "feel weak." :
  2036. X                   "are beginning to feel weak.");
  2037. X            if (incr && occupation &&
  2038. X                (occupation != eatfood && occupation != opentin))
  2039. X                stop_occupation();
  2040. X            break;
  2041. X        }
  2042. X        u.uhs = newhs;
  2043. X        flags.botl = 1;
  2044. X        if(u.uhp < 1) {
  2045. X            You("die from hunger and exhaustion.");
  2046. X            killer_format = KILLED_BY;
  2047. X            killer = "exhaustion";
  2048. X            done(STARVING);
  2049. X            return;
  2050. X        }
  2051. X    }
  2052. X}
  2053. X
  2054. X#endif /* OVL0 */
  2055. X#ifdef OVLB
  2056. X
  2057. X/* Returns an object representing food.  Object may be either on floor or
  2058. X * in inventory.
  2059. X */
  2060. Xstruct obj *
  2061. Xfloorfood(verb,corpseonly)    /* get food from floor or pack */
  2062. X    const char *verb;
  2063. X    boolean corpseonly;
  2064. X{
  2065. X    register struct obj *otmp;
  2066. X    char qbuf[QBUFSZ];
  2067. X    char c;
  2068. X#ifdef POLYSELF
  2069. X    struct obj *gold = g_at(u.ux, u.uy);
  2070. X    boolean feeding = (!strcmp(verb, "eat"));
  2071. X
  2072. X    if (feeding && gold && metallivorous(uasmon)) {
  2073. X        if (gold->quan == 1L)
  2074. X        Sprintf(qbuf, "There is 1 gold piece here; eat it?");
  2075. X        else Sprintf(qbuf, "There are %ld gold pieces here; eat them?",
  2076. X                                gold->quan);
  2077. X        if (yn(qbuf) == 'y') {
  2078. X        /* tricky, because gold isn't a real object -dlc */
  2079. X        freeobj(gold);
  2080. X        return gold;
  2081. X        }
  2082. X    }
  2083. X#endif
  2084. X    /* Is there some food (probably a heavy corpse) here on the ground? */
  2085. X    if (!(Levitation && !Is_airlevel(&u.uz)  && !Is_waterlevel(&u.uz))
  2086. X        && !u.uswallow) {
  2087. X        for(otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp->nexthere) {
  2088. X        if(corpseonly ? otmp->otyp==CORPSE :
  2089. X#ifdef POLYSELF
  2090. X            feeding ? (otmp->oclass != GOLD_CLASS && is_edible(otmp)) :
  2091. X#endif
  2092. X                        otmp->oclass==FOOD_CLASS) {
  2093. X            Sprintf(qbuf, "There %s %s here; %s %s?",
  2094. X                (otmp->quan == 1L) ? "is" : "are",
  2095. X                doname(otmp), verb,
  2096. X                (otmp->quan == 1L) ? "it" : "one");
  2097. X            if((c = yn_function(qbuf,ynqchars,'n')) == 'y')
  2098. X                return(otmp);
  2099. X            else if(c == 'q')
  2100. X                return((struct obj *) 0);
  2101. X        }
  2102. X        }
  2103. X    }
  2104. X#ifdef POLYSELF
  2105. X    /* We cannot use ALL_CLASSES since that causes getobj() to skip its
  2106. X     * "ugly checks" and we need to check for inedible items.
  2107. X     */
  2108. X    return getobj(feeding ? (const char *)allobj :
  2109. X                (const char *)comestibles, verb);
  2110. X#else
  2111. X    return getobj(comestibles, verb);
  2112. X#endif
  2113. X}
  2114. X
  2115. X/* Side effects of vomiting */
  2116. X/* added nomul (MRS) - it makes sense, you're too busy being sick! */
  2117. X/* TO DO: regurgitate swallowed monsters when poly'd */
  2118. Xvoid
  2119. Xvomit() {        /* A good idea from David Neves */
  2120. X    make_sick(0L,TRUE);
  2121. X    nomul(-2);
  2122. X}
  2123. X
  2124. Xint
  2125. Xeaten_stat(base, obj)
  2126. Xregister int base;
  2127. Xregister struct obj *obj;
  2128. X{
  2129. X    long uneaten_amt, full_amount;
  2130. X
  2131. X    uneaten_amt = (long)obj->oeaten;
  2132. X    full_amount = (obj->otyp == CORPSE) ? (long)mons[obj->corpsenm].cnutrit
  2133. X                    : (long)objects[obj->otyp].oc_nutrition;
  2134. X
  2135. X    base = (int)(full_amount ? (long)base * uneaten_amt / full_amount : 0L);
  2136. X    return (base < 1) ? 1 : base;
  2137. X}
  2138. X
  2139. X#endif /* OVLB */
  2140. X
  2141. X/*eat.c*/
  2142. END_OF_FILE
  2143. if test 47298 -ne `wc -c <'src/eat.c'`; then
  2144.     echo shar: \"'src/eat.c'\" unpacked with wrong size!
  2145. fi
  2146. # end of 'src/eat.c'
  2147. fi
  2148. if test -f 'sys/mac/mhdump.c' -a "${1}" != "-c" ; then 
  2149.   echo shar: Will not clobber existing file \"'sys/mac/mhdump.c'\"
  2150. else
  2151. echo shar: Extracting \"'sys/mac/mhdump.c'\" \(127 characters\)
  2152. sed "s/^X//" >'sys/mac/mhdump.c' <<'END_OF_FILE'
  2153. X/* Dump file creator for MPW */
  2154. X
  2155. X#define NEED_VARARGS
  2156. X
  2157. X#include ":Include:hack.h"
  2158. X
  2159. X#pragma dump ":Obj:hack.hdump"
  2160. X
  2161. X
  2162. Xdummy() {}
  2163. END_OF_FILE
  2164. if test 127 -ne `wc -c <'sys/mac/mhdump.c'`; then
  2165.     echo shar: \"'sys/mac/mhdump.c'\" unpacked with wrong size!
  2166. fi
  2167. # end of 'sys/mac/mhdump.c'
  2168. fi
  2169. echo shar: End of archive 12 \(of 108\).
  2170. cp /dev/null ark12isdone
  2171. MISSING=""
  2172. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
  2173. 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
  2174. 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
  2175. 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
  2176. 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
  2177. 101 102 103 104 105 106 107 108 ; do
  2178.     if test ! -f ark${I}isdone ; then
  2179.     MISSING="${MISSING} ${I}"
  2180.     fi
  2181. done
  2182. if test "${MISSING}" = "" ; then
  2183.     echo You have unpacked all 108 archives.
  2184.     echo "Now execute 'rebuild.sh'"
  2185.     rm -f ark10[0-8]isdone ark[1-9]isdone ark[1-9][0-9]isdone
  2186. else
  2187.     echo You still need to unpack the following archives:
  2188.     echo "        " ${MISSING}
  2189. fi
  2190. ##  End of shell archive.
  2191. exit 0
  2192.