home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #3 / NN_1993_3.iso / spool / comp / sources / games / 320 < prev    next >
Encoding:
Internet Message Format  |  1993-01-28  |  57.4 KB

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