home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / games / volume16 / nethack31 / part19 < prev    next >
Internet Message Format  |  1993-02-01  |  58KB

  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: v16i019:  nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part19/108
  5. Message-ID: <4302@master.CNA.TEK.COM>
  6. Date: 28 Jan 93 19:14:34 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 2079
  9. Approved: billr@saab.CNA.TEK.COM
  10. Xref: uunet comp.sources.games:1575
  11.  
  12. Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
  13. Posting-number: Volume 16, Issue 19
  14. Archive-name: nethack31/Part19
  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 19 (of 108)."
  27. # Contents:  src/sit.c src/uhitm.c
  28. # Wrapped by billr@saab on Wed Jan 27 16:08:53 1993
  29. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  30. if test -f 'src/sit.c' -a "${1}" != "-c" ; then 
  31.   echo shar: Will not clobber existing file \"'src/sit.c'\"
  32. else
  33. echo shar: Extracting \"'src/sit.c'\" \(8661 characters\)
  34. sed "s/^X//" >'src/sit.c' <<'END_OF_FILE'
  35. X/*    SCCS Id: @(#)sit.c    3.1    92/10/24    */
  36. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  37. X/* NetHack may be freely redistributed.  See license for details. */
  38. X
  39. X#include "hack.h"
  40. X#include "artifact.h"
  41. X
  42. Xvoid
  43. Xtake_gold()
  44. X{
  45. X    if (u.ugold <= 0)  {
  46. X        You("feel a strange sensation.");
  47. X    } else {
  48. X        You("notice you have no gold!");
  49. X        u.ugold = 0;
  50. X        flags.botl = 1;
  51. X    }
  52. X}
  53. X
  54. Xint
  55. Xdosit()
  56. X{
  57. X    char pbuf[BUFSZ];
  58. X    register struct trap *trap;
  59. X    register int typ = levl[u.ux][u.uy].typ;
  60. X
  61. X    if(Levitation)  {
  62. X        pline("There's nothing to sit on up here.");
  63. X        return 0;
  64. X    } 
  65. X
  66. X    Strcpy(pbuf, "You sit on the %s.");
  67. X
  68. X    if(OBJ_AT(u.ux, u.uy)) { 
  69. X        register struct obj *obj;
  70. X
  71. X        obj = level.objects[u.ux][u.uy];
  72. X        You("sit on %s.", the(xname(obj)));
  73. X        if(!Is_box(obj)) pline("It is not very comfortable...");
  74. X
  75. X    } else if(trap = t_at(u.ux, u.uy)) {
  76. X
  77. X        if(u.utrap) {
  78. X            if(u.utraptype == TT_BEARTRAP) {
  79. X            You("can't sit down!");
  80. X            u.utrap++;
  81. X            } else if(u.utraptype == TT_PIT) {
  82. X            You("sit in the bottom of the pit.");
  83. X            if(trap->ttyp == SPIKED_PIT) pline("This hurts!");
  84. X            u.utrap += rn2(5);
  85. X        } else if(u.utraptype == TT_WEB) {
  86. X            pline(pbuf, "giant spider's web");
  87. X            You("are further entangled!");
  88. X            u.utrap += rn1(10, 5);
  89. X        } else if(u.utraptype == TT_LAVA) {
  90. X            /* Must have fire resistance or they'd be dead already */
  91. X            You("sit in the lava!");
  92. X            u.utrap += rnd(4);
  93. X            losehp(d(2,10), "sitting in lava", KILLED_BY);
  94. X        } else if(u.utraptype == TT_INFLOOR) {
  95. X            You("can't maneuver to sit!");
  96. X            u.utrap++;
  97. X        }
  98. X        } else {
  99. X            You("sit down.");
  100. X        dotrap(trap);
  101. X        }
  102. X    } else if(Underwater || Is_waterlevel(&u.uz)) {
  103. X        if (Is_waterlevel(&u.uz))
  104. X        pline("There are no seats floating in the neighborhood.");
  105. X        else
  106. X        You("sit down in the muddy bottom.");
  107. X    } else if(is_pool(u.ux, u.uy)) {
  108. X
  109. X        You("sit in the water.");
  110. X        if (!rn2(10) && uarm)
  111. X        (void) rust_dmg(uarm, "armor", 1, TRUE);
  112. X#ifdef POLYSELF
  113. X        /* Note: without POLYSELF, this can't _happen_ without */
  114. X        /* water walking boots.... */
  115. X        if (!rn2(10) && uarmf && uarmf->otyp != WATER_WALKING_BOOTS)
  116. X        (void) rust_dmg(uarm, "armor", 1, TRUE);
  117. X#endif
  118. X#ifdef SINKS
  119. X    } else if(IS_SINK(typ)) {
  120. X
  121. X        pline(pbuf, defsyms[S_sink].explanation);
  122. X        Your("%s gets wet.", humanoid(uasmon) ? "rump" : "underside");
  123. X#endif
  124. X    } else if(IS_ALTAR(typ)) {
  125. X
  126. X        pline(pbuf, defsyms[S_altar].explanation);
  127. X        altar_wrath(u.ux, u.uy);
  128. X
  129. X    } else if(typ == STAIRS) {
  130. X
  131. X        pline(pbuf, "stairs");
  132. X
  133. X    } else if(typ == LADDER) {
  134. X
  135. X        pline(pbuf, "ladder");
  136. X
  137. X    } else if (is_lava(u.ux, u.uy)) {
  138. X
  139. X        /* must be WWalking */
  140. X        pline(pbuf, "lava");
  141. X        pline("It burns you!");
  142. X        losehp(d((Fire_resistance ? 2 : 10), 10),
  143. X           "sitting on lava", KILLED_BY);
  144. X
  145. X    } else if (is_ice(u.ux, u.uy)) {
  146. X
  147. X        pline(pbuf, defsyms[S_ice].explanation);
  148. X        if (!Cold_resistance) pline("It's very cold...");
  149. X
  150. X    } else if (typ == DRAWBRIDGE_DOWN) {
  151. X
  152. X        pline(pbuf, "drawbridge");
  153. X
  154. X    } else if(IS_THRONE(typ)) {
  155. X
  156. X        pline(pbuf, defsyms[S_throne].explanation);
  157. X        if (rnd(6) > 4)  {
  158. X        switch (rnd(13))  {
  159. X            case 1:
  160. X            (void) adjattrib(rn2(A_MAX), -rn1(4,3), FALSE);
  161. X            losehp(rnd(10), "cursed throne", KILLED_BY_AN);
  162. X            break;
  163. X            case 2:
  164. X            (void) adjattrib(rn2(A_MAX), 1, FALSE);
  165. X            break;
  166. X            case 3:
  167. X        pline("A%s charge of electricity shoots through your body!",
  168. X                  (Shock_resistance) ? "" : " massive");
  169. X            if(Shock_resistance)
  170. X                losehp(rnd(6), "electric chair", KILLED_BY_AN);
  171. X            else    losehp(rnd(30), "electric chair", KILLED_BY_AN);
  172. X            exercise(A_CON, FALSE);
  173. X            break;
  174. X            case 4:
  175. X            You("feel much, much better!");
  176. X            if(u.uhp >= (u.uhpmax - 5))  u.uhpmax += 4;
  177. X            u.uhp = u.uhpmax;
  178. X            make_blinded(0L,TRUE);
  179. X            make_sick(0L,FALSE);
  180. X            heal_legs();
  181. X            flags.botl = 1;
  182. X            break;
  183. X            case 5:
  184. X            take_gold();
  185. X            break;
  186. X            case 6:
  187. X            if(u.uluck + rn2(5) < 0) {
  188. X                You("feel your luck is changing.");
  189. X                change_luck(1);
  190. X            } else        makewish();
  191. X            break;
  192. X            case 7:
  193. X            {
  194. X            register int cnt = rnd(10);
  195. X
  196. X            You("hear a voice echo:");
  197. X            verbalize("Thy audience hath been summoned, %s!",
  198. X                  flags.female ? "Dame" : "Sire");
  199. X            while(cnt--)
  200. X                (void) makemon(courtmon(), u.ux, u.uy);
  201. X            break;
  202. X            }
  203. X            case 8:
  204. X            You("hear a voice echo:");
  205. X            verbalize("By thy Imperious order, %s...",
  206. X                  flags.female ? "Dame" : "Sire");
  207. X            do_genocide(1);
  208. X            break;
  209. X            case 9:
  210. X            You("hear a voice echo:");
  211. X    verbalize("A curse upon thee for sitting upon this most holy throne!");
  212. X            if (Luck > 0)  {
  213. X                make_blinded(Blinded + rn1(100,250),TRUE);
  214. X            } else        rndcurse();
  215. X            break;
  216. X            case 10:
  217. X            if (Luck < 0 || (HSee_invisible & INTRINSIC))  {
  218. X                if (level.flags.nommap) {
  219. X                    pline(
  220. X                    "A terrible drone fills your head!");
  221. X                    make_confused(HConfusion + rnd(30),
  222. X                                    FALSE);
  223. X                } else {
  224. X                    pline("An image forms in your mind.");
  225. X                    do_mapping();
  226. X                }
  227. X            } else  {
  228. X                Your("vision clarifies.");
  229. X                HSee_invisible |= FROMOUTSIDE;
  230. X                newsym(u.ux, u.uy);
  231. X            }
  232. X            break;
  233. X            case 11:
  234. X            if (Luck < 0)  {
  235. X                You("feel threatened.");
  236. X                aggravate();
  237. X            } else  {
  238. X
  239. X                You("feel a wrenching sensation.");
  240. X                tele();        /* teleport him */
  241. X            }
  242. X            break;
  243. X            case 12:
  244. X            You("are granted a gift of insight!");
  245. X            if (invent) {
  246. X                int ret, cval = rn2(5); /* agrees w/seffects() */
  247. X                do {
  248. X                ret = ggetobj("identify", identify, cval);
  249. X                } while (cval && (cval -= ret));
  250. X            }
  251. X            break;
  252. X            case 13:
  253. X            Your("mind turns into a pretzel!");
  254. X            make_confused(HConfusion + rn1(7,16),FALSE);
  255. X            break;
  256. X            default:    impossible("throne effect");
  257. X                break;
  258. X        }
  259. X        } else    You("feel somehow out of place...");
  260. X
  261. X        if (!rn2(3) && IS_THRONE(levl[u.ux][u.uy].typ)) {
  262. X        /* may have teleported */
  263. X        pline("The throne vanishes in a puff of logic.");
  264. X        levl[u.ux][u.uy].typ = ROOM;
  265. X        if(Invisible) newsym(u.ux,u.uy);
  266. X        }
  267. X
  268. X#ifdef POLYSELF
  269. X    } else if (lays_eggs(uasmon) || u.umonnum == PM_QUEEN_BEE) {
  270. X        struct obj *uegg;
  271. X
  272. X        if (!flags.female) {
  273. X            pline("Males can't lay eggs!");
  274. X            return 0;
  275. X        }
  276. X
  277. X        if (u.uhunger < (int)objects[EGG].oc_nutrition) {
  278. X            You("are too weak to lay an egg.");
  279. X            return 0;
  280. X        }
  281. X
  282. X        uegg = mksobj(EGG, FALSE, FALSE);
  283. X        uegg->spe = 1;
  284. X        uegg->quan = 1;
  285. X        uegg->owt = weight(uegg);
  286. X        uegg->corpsenm =
  287. X            (u.umonnum==PM_QUEEN_BEE ? PM_KILLER_BEE : monsndx(uasmon));
  288. X        uegg->known = uegg->dknown = 1;
  289. X        You("lay an egg.");
  290. X        dropy(uegg);
  291. X        stackobj(uegg);
  292. X        morehungry((int)objects[EGG].oc_nutrition);
  293. X#endif
  294. X    } else if (u.uswallow)
  295. X        pline("There are no seats in here!");
  296. X    else
  297. X        pline("Having fun sitting on the floor?");
  298. X    return(1);
  299. X}
  300. X
  301. Xvoid
  302. Xrndcurse()            /* curse a few inventory items at random! */
  303. X{
  304. X    int    nobj = 0;
  305. X    int    cnt, onum;
  306. X    struct    obj    *otmp;
  307. X
  308. X    if(Antimagic) {
  309. X        shieldeff(u.ux, u.uy);
  310. X        You("feel a malignant aura surround you.");
  311. X    }
  312. X
  313. X    for (otmp = invent; otmp; otmp = otmp->nobj)  nobj++;
  314. X
  315. X    if (nobj)
  316. X        for (cnt = rnd(6/((!!Antimagic) + (!!Half_spell_damage) + 1));
  317. X         cnt > 0; cnt--)  {
  318. X        onum = rn2(nobj);
  319. X        for(otmp = invent; onum != 0; onum--)
  320. X            otmp = otmp->nobj;
  321. X
  322. X        if(otmp->oartifact && spec_ability(otmp, SPFX_INTEL) &&
  323. X           rn2(10) < 8) {
  324. X            pline("%s resists!", The(xname(otmp)));
  325. X            continue;
  326. X        }
  327. X
  328. X        if(otmp->blessed)
  329. X            unbless(otmp);
  330. X        else
  331. X            curse(otmp);
  332. X        }
  333. X}
  334. X
  335. Xvoid
  336. Xattrcurse()            /* remove a random INTRINSIC ability */
  337. X{
  338. X    switch(rnd(10)) {
  339. X    case 1 : if (HFire_resistance & INTRINSIC) {
  340. X            HFire_resistance &= ~INTRINSIC;
  341. X            You("feel warmer.");
  342. X            break;
  343. X        }
  344. X    case 2 : if (HTeleportation & INTRINSIC) {
  345. X            HTeleportation &= ~INTRINSIC;
  346. X            You("feel less jumpy.");
  347. X            break;
  348. X        }
  349. X    case 3 : if (HPoison_resistance & INTRINSIC) {
  350. X            HPoison_resistance &= ~INTRINSIC;
  351. X            You("feel a little sick!");
  352. X            break;
  353. X        }
  354. X    case 4 : if (HTelepat & INTRINSIC) {
  355. X            HTelepat &= ~INTRINSIC;
  356. X            if (Blind && !Telepat)
  357. X                see_monsters();    /* Can't sense mons anymore! */
  358. X            Your("senses fail!");
  359. X            break;
  360. X        }
  361. X    case 5 : if (HCold_resistance & INTRINSIC) {
  362. X            HCold_resistance &= ~INTRINSIC;
  363. X            You("feel cooler.");
  364. X            break;
  365. X        }
  366. X    case 6 : if (HInvis & INTRINSIC) {
  367. X            HInvis &= ~INTRINSIC;
  368. X            You("feel paranoid.");
  369. X            break;
  370. X        }
  371. X    case 7 : if (HSee_invisible & INTRINSIC) {
  372. X            HSee_invisible &= ~INTRINSIC;
  373. X            You("thought you saw something!");
  374. X            break;
  375. X        }
  376. X    case 8 : if (Fast & INTRINSIC) {
  377. X            Fast &= ~INTRINSIC;
  378. X            You("feel slower.");
  379. X            break;
  380. X        }
  381. X    case 9 : if (Stealth & INTRINSIC) {
  382. X            Stealth &= ~INTRINSIC;
  383. X            You("feel clumsy.");
  384. X            break;
  385. X        }
  386. X    case 10: if (Protection & INTRINSIC) {
  387. X            Protection &= ~INTRINSIC;
  388. X            You("feel vulnerable.");
  389. X            break;
  390. X        }
  391. X    default: break;
  392. X    }
  393. X}
  394. X
  395. X/*sit.c*/
  396. END_OF_FILE
  397. if test 8661 -ne `wc -c <'src/sit.c'`; then
  398.     echo shar: \"'src/sit.c'\" unpacked with wrong size!
  399. fi
  400. # end of 'src/sit.c'
  401. fi
  402. if test -f 'src/uhitm.c' -a "${1}" != "-c" ; then 
  403.   echo shar: Will not clobber existing file \"'src/uhitm.c'\"
  404. else
  405. echo shar: Extracting \"'src/uhitm.c'\" \(44975 characters\)
  406. sed "s/^X//" >'src/uhitm.c' <<'END_OF_FILE'
  407. X/*    SCCS Id: @(#)uhitm.c    3.1    92/12/10    */
  408. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  409. X/* NetHack may be freely redistributed.  See license for details. */
  410. X
  411. X#include "hack.h"
  412. X
  413. Xstatic boolean FDECL(known_hitum, (struct monst *,int));
  414. Xstatic boolean FDECL(hitum, (struct monst *,int));
  415. X#ifdef POLYSELF
  416. Xstatic int FDECL(explum, (struct monst *,struct attack *));
  417. Xstatic int FDECL(gulpum, (struct monst *,struct attack *));
  418. Xstatic boolean FDECL(hmonas, (struct monst *,int));
  419. X#endif
  420. Xstatic void FDECL(nohandglow, (struct monst *));
  421. X
  422. Xextern boolean notonhead;    /* for long worms */
  423. X/* The below might become a parameter instead if we use it a lot */
  424. Xstatic int dieroll;
  425. X
  426. Xstruct monst *
  427. Xclone_mon(mon)
  428. Xstruct monst *mon;
  429. X{
  430. X    coord mm;
  431. X    struct monst *m2;
  432. X
  433. X    mm.x = mon->mx;
  434. X    mm.y = mon->my;
  435. X    if (!enexto(&mm, mm.x, mm.y, mon->data)) return (struct monst *)0;
  436. X    if (MON_AT(mm.x, mm.y) || mon->mhp <= 1) return (struct monst *)0;
  437. X    /* may have been extinguished for population control */
  438. X    if(mon->data->geno & G_EXTINCT) return((struct monst *) 0);
  439. X    m2 = newmonst(0);
  440. X    *m2 = *mon;            /* copy condition of old monster */
  441. X    m2->nmon = fmon;
  442. X    fmon = m2;
  443. X    m2->m_id = flags.ident++;
  444. X    m2->mx = mm.x;
  445. X    m2->my = mm.y;
  446. X
  447. X    m2->minvent = (struct obj *) 0; /* objects don't clone */
  448. X    m2->mleashed = FALSE;
  449. X    m2->mgold = 0L;
  450. X    /* Max HP the same, but current HP halved for both.  The caller
  451. X     * might want to override this by halving the max HP also.
  452. X     */
  453. X    m2->mhpmax = mon->mhpmax;
  454. X    m2->mhp = mon->mhp /= 2;
  455. X
  456. X    /* since shopkeepers and guards will only be cloned if they've been
  457. X     * polymorphed away from their original forms, the clone doesn't have
  458. X     * room for the extra information.  we also don't want two shopkeepers
  459. X     * around for the same shop.
  460. X     * similarly, clones of named monsters don't have room for the name,
  461. X     * so we just make the clone unnamed instead of bothering to create
  462. X     * a clone with room and copying over the name from the right place
  463. X     * (which changes if the original was a shopkeeper or guard).
  464. X     */
  465. X    if (mon->isshk) m2->isshk = FALSE;
  466. X    if (mon->isgd) m2->isgd = FALSE;
  467. X    if (mon->ispriest) m2->ispriest = FALSE;
  468. X    m2->mxlth = 0;
  469. X    m2->mnamelth = 0;
  470. X    place_monster(m2, m2->mx, m2->my);
  471. X    newsym(m2->mx,m2->my);    /* display the new monster */
  472. X    if (mon->mtame) {
  473. X        struct monst *m3;
  474. X
  475. X        /* because m2 is a copy of mon it is tame but not init'ed.
  476. X         * however, tamedog will not re-tame a tame dog, so m2
  477. X         * must be made non-tame to get initialized properly.
  478. X         */
  479. X        m2->mtame = 0;
  480. X        if ((m3 = tamedog(m2, (struct obj *)0)) != 0)
  481. X        m2 = m3;
  482. X    }
  483. X    return m2;
  484. X}
  485. X
  486. Xboolean
  487. Xspecial_case(mtmp)
  488. X/* Moved this code from attack() in order to     */
  489. X/* avoid having to duplicate it in dokick.    */
  490. Xregister struct monst *mtmp;
  491. X{
  492. X    char qbuf[QBUFSZ];
  493. X
  494. X    if(mtmp->m_ap_type && !Protection_from_shape_changers
  495. X                        && !sensemon(mtmp)) {
  496. X        stumble_onto_mimic(mtmp);
  497. X        mtmp->data->mflags3 &= ~M3_WAITMASK;
  498. X        return(1);
  499. X    }
  500. X
  501. X    if(mtmp->mundetected && hides_under(mtmp->data) && !canseemon(mtmp)) {
  502. X        mtmp->mundetected = 0;
  503. X        if (!(Blind ? Telepat : (HTelepat & (W_ARMH|W_AMUL|W_ART)))) {
  504. X            register struct obj *obj;
  505. X
  506. X            if(Blind)
  507. X                pline("Wait!  There's a hidden monster there!");
  508. X            else if ((obj = level.objects[mtmp->mx][mtmp->my]) != 0)
  509. X                pline("Wait!  There's %s hiding under %s!",
  510. X                    an(l_monnam(mtmp)), doname(obj));
  511. X            wakeup(mtmp);
  512. X            mtmp->data->mflags3 &= ~M3_WAITMASK;
  513. X            return(TRUE);
  514. X        }
  515. X    }
  516. X
  517. X    if (flags.confirm && mtmp->mpeaceful
  518. X        && !Confusion && !Hallucination && !Stunned) {
  519. X        /* Intelligent chaotic weapons (Stormbringer) want blood */
  520. X        if (uwep && uwep->oartifact == ART_STORMBRINGER)
  521. X            return(FALSE);
  522. X
  523. X        if (canspotmon(mtmp)) {
  524. X            Sprintf(qbuf, "Really attack %s?", mon_nam(mtmp));
  525. X            if (yn(qbuf) != 'y') {
  526. X                flags.move = 0;
  527. X                mtmp->data->mflags3 &= ~M3_WAITMASK;
  528. X                return(TRUE);
  529. X            }
  530. X        }
  531. X    }
  532. X
  533. X    return(FALSE);
  534. X}
  535. X
  536. Xschar
  537. Xfind_roll_to_hit(mtmp)
  538. Xregister struct monst *mtmp;
  539. X{
  540. X    schar tmp;
  541. X    int tmp2;
  542. X    struct permonst *mdat = mtmp->data;
  543. X
  544. X    tmp = 1 + Luck + abon() +
  545. X        find_mac(mtmp) +
  546. X#ifdef POLYSELF
  547. X        ((u.umonnum >= 0) ? uasmon->mlevel : u.ulevel);
  548. X#else
  549. X        u.ulevel;
  550. X#endif
  551. X
  552. X/*    it is unchivalrous to attack the defenseless or from behind */
  553. X    if (pl_character[0] == 'K' && u.ualign.type == A_LAWFUL &&
  554. X        (!mtmp->mcanmove || mtmp->msleep || mtmp->mflee) &&
  555. X        u.ualign.record > -10) adjalign(-1);
  556. X
  557. X/*    attacking peaceful creatures is bad for the samurai's giri */
  558. X    if (pl_character[0] == 'S' && mtmp->mpeaceful &&
  559. X        u.ualign.record > -10) adjalign(-1);
  560. X
  561. X/*    Adjust vs. (and possibly modify) monster state.        */
  562. X
  563. X    if(mtmp->mstun) tmp += 2;
  564. X    if(mtmp->mflee) tmp += 2;
  565. X
  566. X    if(mtmp->msleep) {
  567. X        mtmp->msleep = 0;
  568. X        tmp += 2;
  569. X    }
  570. X    if(!mtmp->mcanmove) {
  571. X        tmp += 4;
  572. X        if(!rn2(10)) {
  573. X            mtmp->mcanmove = 1;
  574. X            mtmp->mfrozen = 0;
  575. X        }
  576. X    }
  577. X    if (is_orc(mtmp->data) && pl_character[0]=='E') tmp++;
  578. X
  579. X/*    with a lot of luggage, your agility diminishes */
  580. X    if(tmp2 = near_capacity()) tmp -= (tmp2*2) - 1;
  581. X    if(u.utrap) tmp -= 3;
  582. X#ifdef POLYSELF
  583. X/*    Some monsters have a combination of weapon attacks and non-weapon
  584. X *    attacks.  It is therefore wrong to add hitval to tmp; we must add it
  585. X *    only for the specific attack (in hmonas()).
  586. X */
  587. X    if(uwep && u.umonnum == -1) tmp += hitval(uwep, mdat);
  588. X#else
  589. X    if(uwep) tmp += hitval(uwep, mdat);
  590. X#endif
  591. X    return tmp;
  592. X}
  593. X
  594. X/* try to attack; return FALSE if monster evaded */
  595. X/* u.dx and u.dy must be set */
  596. Xboolean
  597. Xattack(mtmp)
  598. Xregister struct monst *mtmp;
  599. X{
  600. X    schar tmp;
  601. X    register struct permonst *mdat = mtmp->data;
  602. X
  603. X    /* This section of code provides protection against accidentally
  604. X     * hitting peaceful (like '@') and tame (like 'd') monsters.
  605. X     * Protection is provided as long as player is not: blind, confused,
  606. X     * hallucinating or stunned.
  607. X     * changes by wwp 5/16/85
  608. X     * More changes 12/90, -dkh-. if its tame and safepet, (and protected
  609. X     * 07/92) then we assume that you're not trying to attack. Instead,
  610. X     * you'll usually just swap places if this is a movement command
  611. X     */
  612. X    /* Intelligent chaotic weapons (Stormbringer) want blood */
  613. X    if (is_safepet(mtmp) &&
  614. X        (!uwep || uwep->oartifact != ART_STORMBRINGER)) {
  615. X        /* there are some additional considerations: this won't work
  616. X         * if in a shop or Punished or you miss a random roll or
  617. X         * if you can walk thru walls and your pet cannot (KAA) or
  618. X         * if your pet is a long worm (unless someone does better).
  619. X         * there's also a chance of displacing a "frozen" monster.
  620. X         * sleeping monsters might magically walk in their sleep.
  621. X         */
  622. X        unsigned int foo = (Punished ||
  623. X                    !rn2(7) || is_longworm(mtmp->data));
  624. X
  625. X        if (*in_rooms(mtmp->mx, mtmp->my, SHOPBASE) || foo
  626. X#ifdef POLYSELF
  627. X            || (IS_ROCK(levl[u.ux][u.uy].typ) &&
  628. X                    !passes_walls(mtmp->data))
  629. X#endif
  630. X            ) {
  631. X            mtmp->mflee = 1;
  632. X            mtmp->mfleetim = rnd(6);
  633. X            You("stop.  %s is in your way!",
  634. X            (mtmp->mnamelth ? NAME(mtmp) : Monnam(mtmp)));
  635. X            return(TRUE);
  636. X        } else if ((mtmp->mfrozen || (! mtmp->mcanmove)
  637. X                || (mtmp->data->mmove == 0)) && rn2(6)) {
  638. X            pline("%s doesn't seem to move!", Monnam(mtmp));
  639. X            return(TRUE);
  640. X        } else return(FALSE);
  641. X    }
  642. X
  643. X    /* moved code to a separate function to share with dokick */
  644. X    if(special_case(mtmp)) return(TRUE);
  645. X
  646. X#ifdef POLYSELF
  647. X    if(u.umonnum >= 0) {    /* certain "pacifist" monsters don't attack */
  648. X        set_uasmon();
  649. X        if(noattacks(uasmon)) {
  650. X            You("have no way to attack monsters physically.");
  651. X            mtmp->data->mflags3 &= ~M3_WAITMASK;
  652. X            return(TRUE);
  653. X        }
  654. X    }
  655. X#endif
  656. X
  657. X    if(check_capacity("You cannot fight while so heavily loaded."))
  658. X        return (TRUE);
  659. X
  660. X    if(unweapon) {
  661. X        unweapon=FALSE;
  662. X        if(flags.verbose)
  663. X        if(uwep)
  664. X            You("begin bashing monsters with your %s.",
  665. X            aobjnam(uwep, NULL));
  666. X        else
  667. X#ifdef POLYSELF
  668. X            if (!cantwield(uasmon))
  669. X#endif
  670. X            You("begin bashing monsters with your %s hands.",
  671. X            uarmg ? "gloved" : "bare");        /* Del Lamb */
  672. X    }
  673. X    exercise(A_STR, TRUE);        /* you're exercising muscles */
  674. X    /* andrew@orca: prevent unlimited pick-axe attacks */
  675. X    u_wipe_engr(3);
  676. X
  677. X    if(mdat->mlet == S_LEPRECHAUN && mtmp->mfrozen && !mtmp->msleep &&
  678. X       !mtmp->mconf && mtmp->mcansee && !rn2(7) &&
  679. X       (m_move(mtmp, 0) == 2 ||                /* it died */
  680. X       mtmp->mx != u.ux+u.dx || mtmp->my != u.uy+u.dy)) /* it moved */
  681. X        return(FALSE);
  682. X
  683. X    tmp = find_roll_to_hit(mtmp);
  684. X#ifdef POLYSELF
  685. X    if (u.umonnum >= 0) (void) hmonas(mtmp, tmp);
  686. X    else
  687. X#endif
  688. X        (void) hitum(mtmp, tmp);
  689. X
  690. X    mtmp->data->mflags3 &= ~M3_WAITMASK;
  691. X    return(TRUE);
  692. X}
  693. X
  694. Xstatic boolean
  695. Xknown_hitum(mon, mhit)    /* returns TRUE if monster still lives */
  696. X/* Made into a separate function because in some cases we want to know
  697. X * in the calling function whether we hit.
  698. X */
  699. Xregister struct monst *mon;
  700. Xregister int mhit;
  701. X{
  702. X    register boolean malive = TRUE, special;
  703. X
  704. X    /* we need to know whether the special monster was peaceful */
  705. X    /* before the attack, to save idle calls to angry_guards()  */
  706. X    special = (mon->mpeaceful && (mon->data == &mons[PM_WATCHMAN] ||
  707. X                mon->data == &mons[PM_WATCH_CAPTAIN] ||
  708. X                      mon->ispriest || mon->isshk));
  709. X
  710. X    if(!mhit) {
  711. X        if(flags.verbose) You("miss %s.", mon_nam(mon));
  712. X        else            You("miss it.");
  713. X        if(!mon->msleep && mon->mcanmove)
  714. X        wakeup(mon);
  715. X#ifdef MUSE
  716. X        else if (uwep && uwep->otyp == TSURUGI &&
  717. X             MON_WEP(mon) && !rn2(20)) {
  718. X        /* 1/20 chance of shattering defender's weapon */
  719. X        struct obj *obj = MON_WEP(mon);
  720. X
  721. X        MON_NOWEP(mon);
  722. X        m_useup(mon, obj);
  723. X        pline("%s weapon shatters!", s_suffix(Monnam(mon)));
  724. X        /* perhaps this will freak out the monster */
  725. X        if (!rn2(3)) {
  726. X            mon->mflee = 1;
  727. X            mon->mfleetim += rnd(20);
  728. X        }
  729. X        }
  730. X#endif
  731. X    } else {
  732. X        /* we hit the monster; be careful: it might die! */
  733. X        notonhead = (mon->mx != u.ux+u.dx || mon->my != u.uy+u.dy);
  734. X        if((malive = hmon(mon, uwep, 0)) == TRUE) {
  735. X        /* monster still alive */
  736. X        if(!rn2(25) && mon->mhp < mon->mhpmax/2) {
  737. X            mon->mflee = 1;
  738. X            if(!rn2(3)) mon->mfleetim = rnd(100);
  739. X            if(u.ustuck == mon && !u.uswallow
  740. X#ifdef POLYSELF
  741. X                        && !sticks(uasmon)
  742. X#endif
  743. X                                )
  744. X                u.ustuck = 0;
  745. X        }
  746. X        if (mon->wormno) cutworm(mon, u.ux+u.dx, u.uy+u.dy, uwep);
  747. X        }
  748. X        if(mon->ispriest && !rn2(2)) ghod_hitsu(mon);
  749. X        if(special) (void) angry_guards(!flags.soundok);
  750. X    }
  751. X    return(malive);
  752. X}
  753. X
  754. Xstatic boolean
  755. Xhitum(mon, tmp)        /* returns TRUE if monster still lives */
  756. Xstruct monst *mon;
  757. Xint tmp;
  758. X{
  759. X    static int NEARDATA malive;
  760. X    boolean mhit = (tmp > (dieroll = rnd(20)) || u.uswallow);
  761. X
  762. X    if(tmp > dieroll) exercise(A_DEX, TRUE);
  763. X    malive = known_hitum(mon, mhit);
  764. X    (void) passive(mon, mhit, malive, FALSE);
  765. X    return(malive);
  766. X}
  767. X
  768. Xboolean            /* general "damage monster" routine */
  769. Xhmon(mon, obj, thrown)        /* return TRUE if mon still alive */
  770. Xregister struct monst *mon;
  771. Xregister struct obj *obj;
  772. Xregister int thrown;
  773. X{
  774. X    int tmp;
  775. X    struct permonst *mdat = mon->data;
  776. X    /* Why all these booleans?  This stuff has to be done in the
  777. X     *      following order:
  778. X     * 1) Know what we're attacking with, and print special hittxt for
  779. X     *    unusual cases.
  780. X     * 2a) Know whether we did damage (depends on 1)
  781. X     * 2b) Know if it's poisoned (depends on 1)
  782. X     * 2c) Know whether we get a normal damage bonus or not (depends on 1)
  783. X     * 3a) Know what the value of the damage bonus is (depends on 2c)
  784. X     * 3b) Know how much poison damage was taken (depends on 2b) and if the
  785. X     *    poison instant-killed it
  786. X     * 4) Know if it was killed (requires knowing 3a, 3b) except by instant-
  787. X     *    kill poison
  788. X     * 5) Print hit message (depends on 1 and 4)
  789. X     * 6a) Print poison message (must be done after 5)
  790. X#if 0
  791. X     * 6b) Rust weapon (must be done after 5)
  792. X#endif
  793. X     * 7) Possibly kill monster (must be done after 6a, 6b)
  794. X     * 8) Instant-kill from poison (can happen anywhere between 5 and 9)
  795. X     * 9) Hands not glowing (must be done after 7 and 8)
  796. X     * The major problem is that since we don't want a "hit" message
  797. X     * when the monster dies, we have to know how much damage it did
  798. X     * _before_ outputting a hit message, but any messages associated with
  799. X     * the damage don't come out until _after_ outputting a hit message.
  800. X     */
  801. X    boolean hittxt = FALSE, destroyed = FALSE;
  802. X    boolean get_dmg_bonus = TRUE;
  803. X    boolean ispoisoned = FALSE, needpoismsg = FALSE, poiskilled = FALSE;
  804. X    boolean silvermsg = FALSE;
  805. X
  806. X    wakeup(mon);
  807. X    if(!obj) {    /* attack with bare hands */
  808. X        if (mdat == &mons[PM_SHADE])
  809. X        tmp = 0;
  810. X        else
  811. X        tmp = rnd(2);
  812. X#if 0
  813. X        if(mdat == &mons[PM_COCKATRICE] && !uarmg
  814. X#ifdef POLYSELF
  815. X        && !resists_ston(uasmon)
  816. X#endif
  817. X        ) {
  818. X
  819. X        You("hit %s with your bare %s.",
  820. X            mon_nam(mon), makeplural(body_part(HAND)));
  821. X# ifdef POLYSELF
  822. X        if(poly_when_stoned(uasmon) && polymon(PM_STONE_GOLEM))
  823. X            return TRUE;
  824. X# endif
  825. X        You("turn to stone...");
  826. X        done_in_by(mon);
  827. X        hittxt = TRUE; /* maybe lifesaved */
  828. X        }
  829. X#endif
  830. X    } else {
  831. X        if(obj->oclass == WEAPON_CLASS || obj->otyp == PICK_AXE ||
  832. X           obj->otyp == UNICORN_HORN || obj->oclass == ROCK_CLASS) {
  833. X
  834. X        /* If not a melee weapon, and either not thrown, or thrown */
  835. X        /* and a bow (bows are >BOOMERANG), or thrown and a missile */
  836. X        /* without a propellor (missiles are <DART), do 1-2 points */
  837. X        if((obj->otyp >= BOW || obj->otyp < DART)
  838. X            && obj->otyp != PICK_AXE && obj->otyp != UNICORN_HORN
  839. X            && (!thrown ||
  840. X                (obj->oclass != ROCK_CLASS &&
  841. X                (obj->otyp > BOOMERANG ||
  842. X                (obj->otyp < DART &&
  843. X                    (!uwep ||
  844. X                    objects[obj->otyp].w_propellor !=
  845. X                    -objects[uwep->otyp].w_propellor)
  846. X                ))))) {
  847. X            if (mdat == &mons[PM_SHADE] && obj->otyp != SILVER_ARROW)
  848. X            tmp = 0;
  849. X            else
  850. X            tmp = rnd(2);
  851. X        } else {
  852. X            tmp = dmgval(obj, mdat);
  853. X            if (obj->oartifact &&
  854. X            artifact_hit(&youmonst, mon, obj, &tmp, dieroll)) {
  855. X            if(mon->mhp <= 0) /* artifact killed monster */
  856. X                return FALSE;
  857. X            hittxt = TRUE;
  858. X            }
  859. X            if (objects[obj->otyp].oc_material == SILVER
  860. X                && hates_silver(mdat))
  861. X            silvermsg = TRUE;
  862. X            if(!thrown && obj == uwep && obj->otyp == BOOMERANG &&
  863. X               !rnl(3)) {
  864. X            pline("As you hit %s, %s breaks into splinters.",
  865. X                  mon_nam(mon), the(xname(obj)));
  866. X            useup(obj);
  867. X            obj = (struct obj *) 0;
  868. X            hittxt = TRUE;
  869. X            if (mdat != &mons[PM_SHADE])
  870. X                tmp++;
  871. X            } else if(thrown &&
  872. X                  (obj->otyp >= ARROW && obj->otyp <= SHURIKEN)) {
  873. X            if(uwep && obj->otyp < DART &&
  874. X               objects[obj->otyp].w_propellor ==
  875. X               -objects[uwep->otyp].w_propellor) {
  876. X                /* Elves and Samurai do extra damage using
  877. X                 * their bows&arrows; they're highly trained.
  878. X                 */
  879. X                if (pl_character[0] == 'S' &&
  880. X                obj->otyp == YA && uwep->otyp == YUMI)
  881. X                tmp++;
  882. X                else if (pl_character[0] == 'E' &&
  883. X                     obj->otyp == ELVEN_ARROW &&
  884. X                     uwep->otyp == ELVEN_BOW)
  885. X                tmp++;
  886. X            }
  887. X            if(((uwep && objects[obj->otyp].w_propellor ==
  888. X                -objects[uwep->otyp].w_propellor)
  889. X                || obj->otyp==DART || obj->otyp==SHURIKEN) &&
  890. X                obj->opoisoned)
  891. X                ispoisoned = TRUE;
  892. X            }
  893. X        }
  894. X        } else if(obj->oclass == POTION_CLASS) {
  895. X            if (obj->quan > 1L) setuwep(splitobj(obj, 1L));
  896. X            else setuwep((struct obj *)0);
  897. X            freeinv(obj);
  898. X            potionhit(mon,obj);
  899. X            hittxt = TRUE;
  900. X            if (mdat == &mons[PM_SHADE])
  901. X                tmp = 0;
  902. X            else
  903. X                tmp = 1;
  904. X        } else {
  905. X        switch(obj->otyp) {
  906. X            case HEAVY_IRON_BALL:
  907. X            tmp = rnd(25); break;
  908. X            case BOULDER:
  909. X            tmp = rnd(20); break;
  910. X            case MIRROR:
  911. X            You("break your mirror.  That's bad luck!");
  912. X            change_luck(-2);
  913. X            useup(obj);
  914. X            obj = (struct obj *) 0;
  915. X            hittxt = TRUE;
  916. X            tmp = 1;
  917. X            break;
  918. X#ifdef TOURIST
  919. X            case EXPENSIVE_CAMERA:
  920. X    You("succeed in destroying your camera.  Congratulations!");
  921. X            useup(obj);
  922. X            return(TRUE);
  923. X#endif
  924. X            case CORPSE:        /* fixed by polder@cs.vu.nl */
  925. X            if(obj->corpsenm == PM_COCKATRICE) {
  926. X                You("hit %s with the cockatrice corpse.",
  927. X                  mon_nam(mon));
  928. X                if(resists_ston(mdat)) {
  929. X                tmp = 1;
  930. X                hittxt = TRUE;
  931. X                break;
  932. X                }
  933. X                if(poly_when_stoned(mdat)) {
  934. X                mon_to_stone(mon);
  935. X                tmp = 1;
  936. X                hittxt = TRUE;
  937. X                break;
  938. X                }
  939. X                pline("%s turns to stone.", Monnam(mon));
  940. X                stoned = TRUE;
  941. X                xkilled(mon,0);
  942. X                return(FALSE);
  943. X            }
  944. X            tmp = mons[obj->corpsenm].msize + 1;
  945. X            break;
  946. X            case EGG: /* only possible if hand-to-hand */
  947. X            if(obj->corpsenm > -1
  948. X                    && obj->corpsenm != PM_COCKATRICE
  949. X                    && mdat == &mons[PM_COCKATRICE]) {
  950. X                You("hit %s with the %s egg%s.",
  951. X                    mon_nam(mon),
  952. X                    mons[obj->corpsenm].mname,
  953. X                    plur(obj->quan));
  954. X                hittxt = TRUE;
  955. X                pline("The egg%sn't live any more...",
  956. X                    (obj->quan == 1L) ? " is" : "s are");
  957. X                obj->otyp = ROCK;
  958. X                obj->oclass = GEM_CLASS;
  959. X                obj->known = obj->dknown = 0;
  960. X                obj->owt = weight(obj);
  961. X            }
  962. X            tmp = 1;
  963. X            break;
  964. X            case CLOVE_OF_GARLIC:    /* no effect against demons */
  965. X            if(is_undead(mdat)) mon->mflee = 1;
  966. X            tmp = 1;
  967. X            break;
  968. X            case CREAM_PIE:
  969. X#ifdef POLYSELF
  970. X            case BLINDING_VENOM:
  971. X            if(Blind || !haseyes(mon->data))
  972. X                pline(obj->otyp==CREAM_PIE ? "Splat!" : "Splash!");
  973. X            else if (obj->otyp == BLINDING_VENOM)
  974. X                pline("The venom blinds %s%s!", mon_nam(mon),
  975. X                    mon->mcansee ? "" : " further");
  976. X#else
  977. X            if(Blind) pline("Splat!");
  978. X#endif
  979. X            else
  980. X                pline("The cream pie splashes over %s%s!",
  981. X                mon_nam(mon),
  982. X                (haseyes(mdat) &&
  983. X                    mdat != &mons[PM_FLOATING_EYE])
  984. X                ? (*(eos(mon_nam(mon))-1) == 's' ? "' face" :
  985. X                     "'s face") : "");
  986. X            if(mon->msleep) mon->msleep = 0;
  987. X            setmangry(mon);
  988. X            if(haseyes(mon->data)) {
  989. X                mon->mcansee = 0;
  990. X                tmp = rn1(25, 21);
  991. X                if(((int) mon->mblinded + tmp) > 127)
  992. X                mon->mblinded = 127;
  993. X                else mon->mblinded += tmp;
  994. X            }
  995. X            hittxt = TRUE;
  996. X            get_dmg_bonus = FALSE;
  997. X            tmp = 0;
  998. X            break;
  999. X#ifdef POLYSELF
  1000. X            case ACID_VENOM: /* only possible if thrown */
  1001. X            if(resists_acid(mdat)) {
  1002. X                Your("venom hits %s harmlessly.",
  1003. X                    mon_nam(mon));
  1004. X                tmp = 0;
  1005. X            } else {
  1006. X                Your("venom burns %s!", mon_nam(mon));
  1007. X                tmp = dmgval(obj, mdat);
  1008. X            }
  1009. X            hittxt = TRUE;
  1010. X            get_dmg_bonus = FALSE;
  1011. X            break;
  1012. X#endif
  1013. X            default:
  1014. X            /* non-weapons can damage because of their weight */
  1015. X            /* (but not too much) */
  1016. X            tmp = obj->owt/100;
  1017. X            if(tmp < 1) tmp = 1;
  1018. X            else tmp = rnd(tmp);
  1019. X            if(tmp > 6) tmp = 6;
  1020. X        }
  1021. X        if (mdat == &mons[PM_SHADE] && obj &&
  1022. X                objects[obj->otyp].oc_material != SILVER)
  1023. X            tmp = 0;
  1024. X        }
  1025. X    }
  1026. X
  1027. X    /****** NOTE: perhaps obj is undefined!! (if !thrown && BOOMERANG)
  1028. X     *      *OR* if attacking bare-handed!! */
  1029. X
  1030. X    if (get_dmg_bonus && tmp) {
  1031. X        tmp += u.udaminc;
  1032. X        /* If you throw using a propellor, you don't get a strength
  1033. X         * bonus but you do get an increase-damage bonus.
  1034. X         */
  1035. X        if(!thrown || !obj || !uwep ||
  1036. X           (obj->oclass != GEM_CLASS && obj->oclass != WEAPON_CLASS) ||
  1037. X           !objects[obj->otyp].w_propellor ||
  1038. X           (objects[obj->otyp].w_propellor !=
  1039. X                -objects[uwep->otyp].w_propellor))
  1040. X            tmp += dbon();
  1041. X    }
  1042. X
  1043. X/* TODO:    Fix this up.  multiple engulf attacks now exist.
  1044. X    if(u.uswallow) {
  1045. X        if((tmp -= u.uswldtim) <= 0) {
  1046. X        Your("%s are no longer able to hit.",
  1047. X            makeplural(body_part(ARM)));
  1048. X        return(TRUE);
  1049. X        }
  1050. X    }
  1051. X */
  1052. X    if (ispoisoned) {
  1053. X        if(resists_poison(mdat))
  1054. X        needpoismsg = TRUE;
  1055. X        else if (rn2(10))
  1056. X        tmp += rnd(6);
  1057. X        else poiskilled = TRUE;
  1058. X    }
  1059. X    if(tmp < 1)
  1060. X        if (mdat == &mons[PM_SHADE]) {
  1061. X        Your("attack passes harmlessly through %s.",
  1062. X            mon_nam(mon));
  1063. X        hittxt = TRUE;
  1064. X        } else
  1065. X        tmp = 1;
  1066. X
  1067. X    mon->mhp -= tmp;
  1068. X    if(mon->mhp < 1)
  1069. X        destroyed = TRUE;
  1070. X    if(mon->mtame && (!mon->mflee || mon->mfleetim)) {
  1071. X#ifdef SOUNDS
  1072. X        if (rn2(8)) yelp(mon);
  1073. X        else growl(mon); /* give them a moment's worry */
  1074. X#endif
  1075. X        mon->mtame--;
  1076. X        if(!mon->mtame) newsym(mon->mx, mon->my);
  1077. X        mon->mflee = TRUE;        /* Rick Richardson */
  1078. X        mon->mfleetim += 10*rnd(tmp);
  1079. X    }
  1080. X    if((mdat == &mons[PM_BLACK_PUDDING] || mdat == &mons[PM_BROWN_PUDDING])
  1081. X           && obj && obj == uwep
  1082. X           && objects[obj->otyp].oc_material == IRON
  1083. X           && mon->mhp > 1 && !thrown && !mon->mcan
  1084. X           /* && !destroyed  -- guaranteed by mhp > 1 */ ) {
  1085. X
  1086. X        if (clone_mon(mon)) {
  1087. X            pline("%s divides as you hit it!", Monnam(mon));
  1088. X            hittxt = TRUE;
  1089. X        }
  1090. X    }
  1091. X
  1092. X    if(!hittxt && !destroyed) {
  1093. X        if(thrown)
  1094. X            /* thrown => obj exists */
  1095. X            hit(xname(obj), mon, exclam(tmp) );
  1096. X        else if(!flags.verbose) You("hit it.");
  1097. X        else    You("hit %s%s", mon_nam(mon), canseemon(mon)
  1098. X            ? exclam(tmp) : ".");
  1099. X    }
  1100. X
  1101. X    if (silvermsg) {
  1102. X        if (canseemon(mon) || sensemon(mon))
  1103. X            pline("The silver sears %s%s!",
  1104. X                mon_nam(mon),
  1105. X                noncorporeal(mdat) ? "" : 
  1106. X                      (*(eos(mon_nam(mon))-1) == 's' ?
  1107. X                       "' flesh" : "'s flesh"));
  1108. X        else
  1109. X            pline("It%s is seared!",
  1110. X                noncorporeal(mdat) ? "" : "s flesh");
  1111. X    }
  1112. X
  1113. X    if (needpoismsg)
  1114. X        pline("The poison doesn't seem to affect %s.", mon_nam(mon));
  1115. X    if (poiskilled) {
  1116. X        pline("The poison was deadly...");
  1117. X        xkilled(mon, 0);
  1118. X        return FALSE;
  1119. X    } else if (destroyed) {
  1120. X        killed(mon);    /* takes care of most messages */
  1121. X    } else if(u.umconf && !thrown) {
  1122. X        nohandglow(mon);
  1123. X        if(!mon->mconf && !resist(mon, '+', 0, NOTELL)) {
  1124. X            mon->mconf = 1;
  1125. X            if(!mon->mstun && mon->mcanmove && !mon->msleep &&
  1126. X               !Blind)
  1127. X                pline("%s appears confused.", Monnam(mon));
  1128. X        }
  1129. X    }
  1130. X
  1131. X#if 0
  1132. X    if(mdat == &mons[PM_RUST_MONSTER] && obj && obj == uwep &&
  1133. X        is_rustprone(obj) && obj->oeroded < MAX_ERODE) {
  1134. X        if (obj->greased)
  1135. X        grease_protect(obj,NULL,FALSE);
  1136. X        else if (obj->oerodeproof || (obj->blessed && !rnl(4))) {
  1137. X            if (flags.verbose)
  1138. X            pline("Somehow, your %s is not affected.",
  1139. X                  is_sword(obj) ? "sword" : "weapon");
  1140. X        } else {
  1141. X        Your("%s%s!", aobjnam(obj, "rust"),
  1142. X             obj->oeroded+1 == MAX_ERODE ? " completely" :
  1143. X             obj->oeroded ? " further" : "");
  1144. X        obj->oeroded++;
  1145. X        }
  1146. X    }
  1147. X#endif
  1148. X
  1149. X    return(destroyed ? FALSE : TRUE);
  1150. X}
  1151. X
  1152. X#ifdef POLYSELF
  1153. X
  1154. Xint
  1155. Xdamageum(mdef, mattk)
  1156. Xregister struct monst *mdef;
  1157. Xregister struct attack *mattk;
  1158. X{
  1159. X    register struct permonst *pd = mdef->data;
  1160. X    register int    tmp = d((int)mattk->damn, (int)mattk->damd);
  1161. X
  1162. X    if (is_demon(uasmon) && !rn2(13) && !uwep
  1163. X        && u.umonnum != PM_SUCCUBUS && u.umonnum != PM_INCUBUS
  1164. X        && u.umonnum != PM_BALROG) {
  1165. X        struct monst *dtmp;
  1166. X        pline("Some hell-p has arrived!");
  1167. X        if((dtmp = makemon(!rn2(6) ? &mons[ndemon()] : uasmon, u.ux, u.uy)))
  1168. X        (void)tamedog(dtmp, (struct obj *)0);
  1169. X        exercise(A_WIS, TRUE);
  1170. X        return(0);
  1171. X    }
  1172. X
  1173. X    switch(mattk->adtyp) {
  1174. X        case AD_STUN:
  1175. X        if(!Blind)
  1176. X            pline("%s staggers for a moment.", Monnam(mdef));
  1177. X        mdef->mstun = 1;
  1178. X        /* fall through to next case */
  1179. X        case AD_WERE:        /* no effect on monsters */
  1180. X        case AD_HEAL:
  1181. X        case AD_LEGS:
  1182. X        case AD_PHYS:
  1183. X        if(mattk->aatyp == AT_WEAP) {
  1184. X            if(uwep) tmp = 0;
  1185. X        } else if(mattk->aatyp == AT_KICK)
  1186. X            if(thick_skinned(mdef->data)) tmp = 0;
  1187. X        break;
  1188. X        case AD_FIRE:
  1189. X        if(!Blind) pline("%s is on fire!", Monnam(mdef));
  1190. X        tmp += destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE);
  1191. X        tmp += destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE);
  1192. X        if(resists_fire(pd)) {
  1193. X            if (!Blind)
  1194. X            pline("The fire doesn't heat %s!", mon_nam(mdef));
  1195. X            golemeffects(mdef, AD_FIRE, tmp);
  1196. X            shieldeff(mdef->mx, mdef->my);
  1197. X            tmp = 0;
  1198. X        }
  1199. X        /* only potions damage resistant players in destroy_item */
  1200. X        tmp += destroy_mitem(mdef, POTION_CLASS, AD_FIRE);
  1201. X        break;
  1202. X        case AD_COLD:
  1203. X        if(!Blind) pline("%s is covered in frost!", Monnam(mdef));
  1204. X        if(resists_cold(pd)) {
  1205. X            shieldeff(mdef->mx, mdef->my);
  1206. X            if (!Blind)
  1207. X            pline("The frost doesn't chill %s!", mon_nam(mdef));
  1208. X            golemeffects(mdef, AD_COLD, tmp);
  1209. X            tmp = 0;
  1210. X        }
  1211. X        tmp += destroy_mitem(mdef, POTION_CLASS, AD_COLD);
  1212. X        break;
  1213. X        case AD_ELEC:
  1214. X        if (!Blind) pline("%s is zapped!", Monnam(mdef));
  1215. X        tmp += destroy_mitem(mdef, WAND_CLASS, AD_ELEC);
  1216. X        if(resists_elec(pd)) {
  1217. X            if (!Blind)
  1218. X            pline("The zap doesn't shock %s!", mon_nam(mdef));
  1219. X            golemeffects(mdef, AD_ELEC, tmp);
  1220. X            shieldeff(mdef->mx, mdef->my);
  1221. X            tmp = 0;
  1222. X        }
  1223. X        /* only rings damage resistant players in destroy_item */
  1224. X        tmp += destroy_mitem(mdef, RING_CLASS, AD_ELEC);
  1225. X        break;
  1226. X        case AD_ACID:
  1227. X        if(resists_acid(pd)) tmp = 0;
  1228. X        break;
  1229. X        case AD_STON:
  1230. X        if(poly_when_stoned(pd))
  1231. X           mon_to_stone(mdef);
  1232. X        else if(!resists_ston(pd)) {
  1233. X            stoned = TRUE;
  1234. X            if(!Blind) pline("%s turns to stone.", Monnam(mdef));
  1235. X            xkilled(mdef, 0);
  1236. X            return(2);
  1237. X        }
  1238. X        tmp = 0;    /* no damage if this fails */
  1239. X        break;
  1240. X# ifdef SEDUCE
  1241. X        case AD_SSEX:
  1242. X# endif
  1243. X        case AD_SEDU:
  1244. X        case AD_SITM:
  1245. X        if(mdef->minvent) {
  1246. X            struct obj *otmp, *stealoid;
  1247. X
  1248. X            stealoid = (struct obj *)0;
  1249. X        /* Without MUSE we can only change a monster's AC by stealing
  1250. X         * armor with the "unarmored soldier" kludge.  With it there
  1251. X         * are many monsters which wear armor, and all can be stripped.
  1252. X         */
  1253. X            if(
  1254. X#ifndef MUSE
  1255. X            is_mercenary(pd) &&
  1256. X#endif
  1257. X                    could_seduce(&youmonst,mdef,mattk)){
  1258. X            for(otmp = mdef->minvent; otmp; otmp=otmp->nobj)
  1259. X#ifdef MUSE
  1260. X                if (otmp->owornmask & W_ARM) stealoid = otmp;
  1261. X#else
  1262. X                if (otmp->otyp >= PLATE_MAIL && otmp->otyp
  1263. X                <= ELVEN_CLOAK) stealoid = otmp;
  1264. X#endif
  1265. X            }
  1266. X            if (stealoid) {
  1267. X            boolean stolen = FALSE;
  1268. X            /* Is "he"/"his" always correct? */
  1269. X            if (gender(mdef) == u.mfemale &&
  1270. X                        uasmon->mlet == S_NYMPH)
  1271. X    You("charm %s.  She gladly hands over her possessions.", mon_nam(mdef));
  1272. X            else
  1273. X        You("seduce %s and %s starts to take off %s clothes.",
  1274. X                mon_nam(mdef),
  1275. X                gender(mdef) ? "she" : "he",
  1276. X                gender(mdef) ? "her" : "his");
  1277. X            while(mdef->minvent) {
  1278. X                otmp = mdef->minvent;
  1279. X                mdef->minvent = otmp->nobj;
  1280. X                /* set dknown to insure proper merge */
  1281. X                if (!Blind) otmp->dknown = 1;
  1282. X#ifdef MUSE
  1283. X                otmp->owornmask = 0L;
  1284. X#endif
  1285. X                if (!stolen && otmp==stealoid) {
  1286. X                    otmp = hold_another_object(otmp,
  1287. X                          (const char *)0, (const char *)0,
  1288. X                                  (const char *)0);
  1289. X                    stealoid = otmp;
  1290. X                    stolen = TRUE;
  1291. X                } else {
  1292. X                    otmp = hold_another_object(otmp,
  1293. X                         "You steal %s.", doname(otmp),
  1294. X                                "You steal: ");
  1295. X                }
  1296. X            }
  1297. X            if (!stolen)
  1298. X                impossible("Player steal fails!");
  1299. X            else {
  1300. X                pline("%s finishes taking off %s suit.",
  1301. X                   Monnam(mdef), gender(mdef) ? "her" : "his");
  1302. X                You("steal %s!", doname(stealoid));
  1303. X# if defined(ARMY) && !defined(MUSE)
  1304. X                mdef->data = &mons[PM_UNARMORED_SOLDIER];
  1305. X# endif
  1306. X            }
  1307. X#ifdef MUSE
  1308. X            possibly_unwield(mdef);
  1309. X            mdef->misc_worn_check = 0L;
  1310. X#endif
  1311. X           } else {
  1312. X            otmp = mdef->minvent;
  1313. X            mdef->minvent = otmp->nobj;
  1314. X            otmp = hold_another_object(otmp, "You steal %s.",
  1315. X                          doname(otmp), "You steal: ");
  1316. X#ifdef MUSE
  1317. X            possibly_unwield(mdef);
  1318. X            otmp->owornmask = 0L;
  1319. X#endif
  1320. X           }
  1321. X        }
  1322. X        tmp = 0;
  1323. X        break;
  1324. X        case AD_SGLD:
  1325. X        if (mdef->mgold) {
  1326. X            u.ugold += mdef->mgold;
  1327. X            mdef->mgold = 0;
  1328. X            Your("purse feels heavier.");
  1329. X        }
  1330. X        exercise(A_DEX, TRUE);
  1331. X        tmp = 0;
  1332. X        break;
  1333. X        case AD_TLPT:
  1334. X        if(tmp <= 0) tmp = 1;
  1335. X        if(tmp < mdef->mhp) {
  1336. X            rloc(mdef);
  1337. X            if(!Blind) pline("%s suddenly disappears!", Monnam(mdef));
  1338. X        }
  1339. X        break;
  1340. X        case AD_BLND:
  1341. X        if(haseyes(pd)) {
  1342. X
  1343. X            if(!Blind) pline("%s is blinded.", Monnam(mdef));
  1344. X            mdef->mcansee = 0;
  1345. X            mdef->mblinded += tmp;
  1346. X        }
  1347. X        tmp = 0;
  1348. X        break;
  1349. X        case AD_CURS:
  1350. X        if (night() && !rn2(10) && !mdef->mcan) {
  1351. X            if (mdef->data == &mons[PM_CLAY_GOLEM]) {
  1352. X            if (!Blind)
  1353. X                pline("Some writing vanishes from %s head!",
  1354. X                s_suffix(mon_nam(mdef)));
  1355. X            xkilled(mdef, 0);
  1356. X            return 2;
  1357. X            }
  1358. X            mdef->mcan = 1;
  1359. X            You("chuckle.");
  1360. X        }
  1361. X        tmp = 0;
  1362. X        break;
  1363. X        case AD_DRLI:
  1364. X        if(rn2(2) && !resists_drli(pd)) {
  1365. X            int xtmp = d(2,6);
  1366. X            pline("%s suddenly seems weaker!", Monnam(mdef));
  1367. X            mdef->mhpmax -= xtmp;
  1368. X            if ((mdef->mhp -= xtmp) <= 0 || !mdef->m_lev--) {
  1369. X                pline("%s dies!", Monnam(mdef));
  1370. X                xkilled(mdef,0);
  1371. X                return(2);
  1372. X            }
  1373. X        }
  1374. X        tmp = 0;
  1375. X        break;
  1376. X        case AD_RUST:
  1377. X        if (pd == &mons[PM_IRON_GOLEM]) {
  1378. X            pline("%s falls to pieces!", Monnam(mdef));
  1379. X            xkilled(mdef,0);
  1380. X            return(2);
  1381. X        }
  1382. X        tmp = 0;
  1383. X        break;
  1384. X        case AD_DCAY:
  1385. X        if (pd == &mons[PM_WOOD_GOLEM] ||
  1386. X            pd == &mons[PM_LEATHER_GOLEM]) {
  1387. X            pline("%s falls to pieces!", Monnam(mdef));
  1388. X            xkilled(mdef,0);
  1389. X            return(2);
  1390. X        }
  1391. X        case AD_DRST:
  1392. X        case AD_DRDX:
  1393. X        case AD_DRCO:
  1394. X        if (!rn2(8)) {
  1395. X            Your("%s was poisoned!", mattk->aatyp==AT_BITE ?
  1396. X            "bite" : "sting");
  1397. X            if (resists_poison(mdef->data))
  1398. X            pline("The poison doesn't seem to affect %s.",
  1399. X                mon_nam(mdef));
  1400. X            else {
  1401. X            if (!rn2(10)) {
  1402. X                Your("poison was deadly...");
  1403. X                tmp = mdef->mhp;
  1404. X            } else tmp += rn1(10,6);
  1405. X            }
  1406. X        }
  1407. X        break;
  1408. X        case AD_DRIN:
  1409. X        if (!has_head(mdef->data)) {
  1410. X            pline("%s doesn't seem harmed.", Monnam(mdef));
  1411. X            tmp = 0;
  1412. X            break;
  1413. X        }
  1414. X#ifdef MUSE
  1415. X        if ((mdef->misc_worn_check & W_ARMH) && rn2(8)) {
  1416. X            pline("%s helmet blocks your attack to %s head.",
  1417. X              s_suffix(Monnam(mdef)),
  1418. X              (Blind || !humanoid(mdef->data)) ? "its" :
  1419. X                (mdef->female ? "her" : "his"));
  1420. X            break;
  1421. X        }
  1422. X#endif
  1423. X        You("eat %s brain!", s_suffix(mon_nam(mdef)));
  1424. X        if (mindless(mdef->data)) {
  1425. X            pline("%s doesn't notice.", Monnam(mdef));
  1426. X            break;
  1427. X        }
  1428. X        tmp += rnd(10);
  1429. X        morehungry(-rnd(30)); /* cannot choke */
  1430. X        if (ABASE(A_INT) < AMAX(A_INT)) {
  1431. X            ABASE(A_INT) += rnd(4);
  1432. X            if (ABASE(A_INT) > AMAX(A_INT))
  1433. X                ABASE(A_INT) = AMAX(A_INT);
  1434. X            flags.botl = 1;
  1435. X        }
  1436. X        exercise(A_WIS, TRUE);
  1437. X        break;
  1438. X        case AD_WRAP:
  1439. X        case AD_STCK:
  1440. X        if (!sticks(mdef->data))
  1441. X            u.ustuck = mdef; /* it's now stuck to you */
  1442. X        break;
  1443. X        case AD_PLYS:
  1444. X        if (mdef->mcanmove && !rn2(3) && tmp < mdef->mhp) {
  1445. X            if (!Blind) pline("%s is frozen by you!", Monnam(mdef));
  1446. X            mdef->mcanmove = 0;
  1447. X            mdef->mfrozen = rnd(10);
  1448. X        }
  1449. X        break;
  1450. X        case AD_SLEE:
  1451. X        if (!resists_sleep(mdef->data) && !mdef->msleep &&
  1452. X                            mdef->mcanmove) {
  1453. X            if (!Blind)
  1454. X            pline("%s suddenly falls asleep!", Monnam(mdef));
  1455. X            mdef->mcanmove = 0;
  1456. X            mdef->mfrozen = rnd(10);
  1457. X        }
  1458. X        break;
  1459. X        default:    tmp = 0;
  1460. X            break;
  1461. X    }
  1462. X    if(!tmp) return(1);
  1463. X
  1464. X    if((mdef->mhp -= tmp) < 1) {
  1465. X
  1466. X        if (mdef->mtame && !cansee(mdef->mx,mdef->my)) {
  1467. X        You("feel embarrassed for a moment.");
  1468. X        xkilled(mdef, 0);
  1469. X        } else if (!flags.verbose) {
  1470. X        You("destroy it!");
  1471. X        xkilled(mdef, 0);
  1472. X        } else
  1473. X        killed(mdef);
  1474. X        return(2);
  1475. X    }
  1476. X    return(1);
  1477. X}
  1478. X
  1479. Xstatic int
  1480. Xexplum(mdef, mattk)
  1481. Xregister struct monst *mdef;
  1482. Xregister struct attack *mattk;
  1483. X{
  1484. X    register int tmp = d((int)mattk->damn, (int)mattk->damd);
  1485. X
  1486. X    You("explode!");
  1487. X    switch(mattk->adtyp) {
  1488. X        case AD_BLND:
  1489. X        if (haseyes(mdef->data)) {
  1490. X            pline("%s is blinded by your flash of light!", Monnam(mdef));
  1491. X            if (mdef->mcansee) {
  1492. X            mdef->mblinded += tmp;
  1493. X            mdef->mcansee = 0;
  1494. X            }
  1495. X        }
  1496. X        break;
  1497. X        case AD_COLD:
  1498. X        if (!resists_cold(mdef->data)) {
  1499. X            pline("%s gets blasted!", Monnam(mdef));
  1500. X            mdef->mhp -= tmp;
  1501. X            if (mdef->mhp <= 0) {
  1502. X             killed(mdef);
  1503. X             return(2);
  1504. X            }
  1505. X        } else {
  1506. X            shieldeff(mdef->mx, mdef->my);
  1507. X            if (is_golem(mdef->data))
  1508. X            golemeffects(mdef, AD_COLD, tmp);
  1509. X            else
  1510. X            pline("The blast doesn't seem to affect %s.",
  1511. X                mon_nam(mdef));
  1512. X        }
  1513. X        break;
  1514. X        default:
  1515. X        break;
  1516. X    }
  1517. X    return(1);
  1518. X}
  1519. X
  1520. Xstatic int
  1521. Xgulpum(mdef,mattk)
  1522. Xregister struct monst *mdef;
  1523. Xregister struct attack *mattk;
  1524. X{
  1525. X    register int tmp;
  1526. X    register int dam = d((int)mattk->damn, (int)mattk->damd);
  1527. X    /* Not totally the same as for real monsters.  Specifically, these
  1528. X     * don't take multiple moves.  (It's just too hard, for too little
  1529. X     * result, to program monsters which attack from inside you, which
  1530. X     * would be necessary if done accurately.)  Instead, we arbitrarily
  1531. X     * kill the monster immediately for AD_DGST and we regurgitate them
  1532. X     * after exactly 1 round of attack otherwise.  -KAA
  1533. X     */
  1534. X
  1535. X    if(mdef->data->msize >= MZ_HUGE) return 0;
  1536. X
  1537. X    if(u.uhunger < 1500 && !u.uswallow) {
  1538. X
  1539. X        if(mdef->data->mlet != S_COCKATRICE) {
  1540. X# ifdef LINT    /* static char msgbuf[BUFSZ]; */
  1541. X        char msgbuf[BUFSZ];
  1542. X# else
  1543. X        static char msgbuf[BUFSZ];
  1544. X# endif
  1545. X/* TODO: get the symbol display also to work (monster symbol is removed from
  1546. X * the screen and you moved onto it, then you get moved back and it gets
  1547. X * moved back if the monster survives--just like when monsters swallow you.
  1548. X */
  1549. X        You("engulf %s!", mon_nam(mdef));
  1550. X        switch(mattk->adtyp) {
  1551. X            case AD_DGST:
  1552. X            u.uhunger += mdef->data->cnutrit;
  1553. X            newuhs(FALSE);
  1554. X            xkilled(mdef,2);
  1555. X            Sprintf(msgbuf, "You totally digest %s.",
  1556. X                    mon_nam(mdef));
  1557. X            if ((tmp = 3 + (mdef->data->cwt >> 6)) != 0) {
  1558. X                You("digest %s.", mon_nam(mdef));
  1559. X                nomul(-tmp);
  1560. X                nomovemsg = msgbuf;
  1561. X            } else pline(msgbuf);
  1562. X            exercise(A_CON, TRUE);
  1563. X            return(2);
  1564. X            case AD_PHYS:
  1565. X            pline("%s is pummeled with your debris!",Monnam(mdef));
  1566. X            break;
  1567. X            case AD_ACID:
  1568. X            pline("%s is covered with your goo!", Monnam(mdef));
  1569. X            if (resists_acid(mdef->data)) {
  1570. X                pline("It seems harmless to %s.", mon_nam(mdef));
  1571. X                dam = 0;
  1572. X            }
  1573. X            break;
  1574. X            case AD_BLND:
  1575. X            if(haseyes(mdef->data)) {
  1576. X                if (mdef->mcansee)
  1577. X                pline("%s can't see in there!", Monnam(mdef));
  1578. X                mdef->mcansee = 0;
  1579. X                dam += mdef->mblinded;
  1580. X                if (dam > 127) dam = 127;
  1581. X                mdef->mblinded = dam;
  1582. X            }
  1583. X            dam = 0;
  1584. X            break;
  1585. X            case AD_ELEC:
  1586. X            if (rn2(2)) {
  1587. X                pline("The air around %s crackles with electricity.", mon_nam(mdef));
  1588. X                if (resists_elec(mdef->data)) {
  1589. X                pline("%s seems unhurt.", Monnam(mdef));
  1590. X                dam = 0;
  1591. X                }
  1592. X                golemeffects(mdef,(int)mattk->adtyp,dam);
  1593. X            } else dam = 0;
  1594. X            break;
  1595. X            case AD_COLD:
  1596. X            if (rn2(2)) {
  1597. X                if (resists_cold(mdef->data)) {
  1598. X                pline("%s seems mildly chilly.", Monnam(mdef));
  1599. X                dam = 0;
  1600. X                } else
  1601. X                pline("%s is freezing to death!",Monnam(mdef));
  1602. X                golemeffects(mdef,(int)mattk->adtyp,dam);
  1603. X            } else dam = 0;
  1604. X            break;
  1605. X            case AD_FIRE:
  1606. X            if (rn2(2)) {
  1607. X                if (resists_fire(mdef->data)) {
  1608. X                pline("%s seems mildly hot.", Monnam(mdef));
  1609. X                dam = 0;
  1610. X                } else
  1611. X                pline("%s is burning to a crisp!",Monnam(mdef));
  1612. X                golemeffects(mdef,(int)mattk->adtyp,dam);
  1613. X            } else dam = 0;
  1614. X            break;
  1615. X        }
  1616. X        if ((mdef->mhp -= dam) <= 0) {
  1617. X            killed(mdef);
  1618. X            return(2);
  1619. X        }
  1620. X        You("%s %s!", is_animal(uasmon) ? "regurgitate"
  1621. X            : "expel", mon_nam(mdef));
  1622. X        if (is_animal(uasmon)) {
  1623. X            pline("Obviously, you didn't like %s taste.",
  1624. X              s_suffix(mon_nam(mdef)));
  1625. X        }
  1626. X        } else {
  1627. X        You("bite into %s", mon_nam(mdef));
  1628. X        You("turn to stone...");
  1629. X        killer_format = KILLED_BY;
  1630. X        killer = "swallowing a cockatrice whole";
  1631. X        done(STONING);
  1632. X        }
  1633. X    }
  1634. X    return(0);
  1635. X}
  1636. X
  1637. Xvoid
  1638. Xmissum(mdef,mattk)
  1639. Xregister struct monst *mdef;
  1640. Xregister struct attack *mattk;
  1641. X{
  1642. X    if (could_seduce(&youmonst, mdef, mattk))
  1643. X        You("pretend to be friendly to %s.", mon_nam(mdef));
  1644. X    else if(!Blind && flags.verbose)
  1645. X        You("miss %s.", mon_nam(mdef));
  1646. X    else
  1647. X        You("miss it.");
  1648. X    wakeup(mdef);
  1649. X}
  1650. X
  1651. Xstatic boolean
  1652. Xhmonas(mon, tmp)        /* attack monster as a monster. */
  1653. Xregister struct monst *mon;
  1654. Xregister int tmp;
  1655. X{
  1656. X    register struct attack *mattk;
  1657. X    int    i, sum[NATTK];
  1658. X    int    nsum = 0;
  1659. X    schar    dhit;
  1660. X
  1661. X#ifdef GCC_WARN
  1662. X    dhit = 0;
  1663. X#endif
  1664. X
  1665. X    for(i = 0; i < NATTK; i++) {
  1666. X
  1667. X        sum[i] = 0;
  1668. X        mattk = &(uasmon->mattk[i]);
  1669. X        switch(mattk->aatyp) {
  1670. X        case AT_WEAP:
  1671. Xuse_weapon:
  1672. X    /* Certain monsters don't use weapons when encountered as enemies,
  1673. X     * but players who polymorph into them have hands or claws and thus
  1674. X     * should be able to use weapons.  This shouldn't prohibit the use
  1675. X     * of most special abilities, either.
  1676. X     */
  1677. X    /* Potential problem: if the monster gets multiple weapon attacks,
  1678. X     * we currently allow the player to get each of these as a weapon
  1679. X     * attack.  Is this really desirable?
  1680. X     */
  1681. X            if(uwep) tmp += hitval(uwep, mon->data);
  1682. X            dhit = (tmp > (dieroll = rnd(20)) || u.uswallow);
  1683. X            /* Enemy dead, before any special abilities used */
  1684. X            if (!known_hitum(mon,dhit)) return 0;
  1685. X            /* might be a worm that gets cut in half */
  1686. X            if (m_at(u.ux+u.dx, u.uy+u.dy) != mon) return(nsum);
  1687. X            /* Do not print "You hit" message, since known_hitum
  1688. X             * already did it.
  1689. X             */
  1690. X            if (dhit && mattk->adtyp != AD_SPEL
  1691. X                && mattk->adtyp != AD_PHYS)
  1692. X                sum[i] = damageum(mon,mattk);
  1693. X            break;
  1694. X        case AT_CLAW:
  1695. X            if (i==0 && uwep && !cantwield(uasmon)) goto use_weapon;
  1696. X# ifdef SEDUCE
  1697. X            /* succubi/incubi are humanoid, but their _second_
  1698. X             * attack is AT_CLAW, not their first...
  1699. X             */
  1700. X            if (i==1 && uwep && (u.umonnum == PM_SUCCUBUS ||
  1701. X                u.umonnum == PM_INCUBUS)) goto use_weapon;
  1702. X# endif
  1703. X        case AT_KICK:
  1704. X        case AT_BITE:
  1705. X        case AT_STNG:
  1706. X        case AT_TUCH:
  1707. X        case AT_BUTT:
  1708. X        case AT_TENT:
  1709. X            if (i==0 && uwep && (u.usym==S_LICH)) goto use_weapon;
  1710. X            if ((dhit = (tmp > rnd(20) || u.uswallow)) != 0) {
  1711. X                int compat;
  1712. X
  1713. X                if (!u.uswallow &&
  1714. X                (compat=could_seduce(&youmonst, mon, mattk))) {
  1715. X                You("%s %s %s.",
  1716. X                    mon->mcansee && haseyes(mon->data)
  1717. X                    ? "smile at" : "talk to",
  1718. X                    mon_nam(mon),
  1719. X                    compat == 2 ? "engagingly":"seductively");
  1720. X                /* doesn't anger it; no wakeup() */
  1721. X                sum[i] = damageum(mon, mattk);
  1722. X                break;
  1723. X                }
  1724. X                wakeup(mon);
  1725. X                if (mon->data == &mons[PM_SHADE]) {
  1726. X                Your("attack passes harmlessly through %s.",
  1727. X                    mon_nam(mon));
  1728. X                break;
  1729. X                }
  1730. X                if (mattk->aatyp == AT_KICK)
  1731. X                    You("kick %s.", mon_nam(mon));
  1732. X                else if (mattk->aatyp == AT_BITE)
  1733. X                    You("bite %s.", mon_nam(mon));
  1734. X                else if (mattk->aatyp == AT_STNG)
  1735. X                    You("sting %s.", mon_nam(mon));
  1736. X                else if (mattk->aatyp == AT_BUTT)
  1737. X                    You("butt %s.", mon_nam(mon));
  1738. X                else if (mattk->aatyp == AT_TUCH)
  1739. X                    You("touch %s.", mon_nam(mon));
  1740. X                else if (mattk->aatyp == AT_TENT)
  1741. X                    Your("tentacles suck %s.", mon_nam(mon));
  1742. X                else You("hit %s.", mon_nam(mon));
  1743. X                sum[i] = damageum(mon, mattk);
  1744. X            } else
  1745. X                missum(mon, mattk);
  1746. X            break;
  1747. X
  1748. X        case AT_HUGS:
  1749. X            /* automatic if prev two attacks succeed, or if
  1750. X             * already grabbed in a previous attack
  1751. X             */
  1752. X            dhit = 1;
  1753. X            wakeup(mon);
  1754. X            if (mon->data == &mons[PM_SHADE])
  1755. X                Your("hug passes harmlessly through %s.",
  1756. X                mon_nam(mon));
  1757. X            else if (!sticks(mon->data))
  1758. X                if (mon==u.ustuck) {
  1759. X                pline("%s is being %s.", Monnam(mon),
  1760. X                    u.umonnum==PM_ROPE_GOLEM ? "choked":
  1761. X                    "crushed");
  1762. X                sum[i] = damageum(mon, mattk);
  1763. X                } else if(sum[i-1] && sum[i-2]) {
  1764. X                You("grab %s!", mon_nam(mon));
  1765. X                u.ustuck = mon;
  1766. X                sum[i] = damageum(mon, mattk);
  1767. X                }
  1768. X            break;
  1769. X
  1770. X        case AT_EXPL:    /* automatic hit if next to */
  1771. X            dhit = -1;
  1772. X            wakeup(mon);
  1773. X            sum[i] = explum(mon, mattk);
  1774. X            break;
  1775. X
  1776. X        case AT_ENGL:
  1777. X            if((dhit = (tmp > rnd(20+i)))) {
  1778. X                wakeup(mon);
  1779. X                if (mon->data == &mons[PM_SHADE])
  1780. X                    Your("attempt to surround %s is harmless.",
  1781. X                    mon_nam(mon));
  1782. X                else
  1783. X                    sum[i]= gulpum(mon,mattk);
  1784. X            } else
  1785. X                missum(mon, mattk);
  1786. X            break;
  1787. X
  1788. X        case AT_MAGC:
  1789. X            /* No check for uwep; if wielding nothing we want to
  1790. X             * do the normal 1-2 points bare hand damage...
  1791. X             */
  1792. X            if (i==0 && (u.usym==S_KOBOLD
  1793. X                || u.usym==S_ORC
  1794. X                || u.usym==S_GNOME
  1795. X                )) goto use_weapon;
  1796. X
  1797. X        case AT_NONE:
  1798. X            continue;
  1799. X            /* Not break--avoid passive attacks from enemy */
  1800. X
  1801. X        case AT_BREA:
  1802. X        case AT_SPIT:
  1803. X        case AT_GAZE:    /* all done using #monster command */
  1804. X            dhit = 0;
  1805. X            break;
  1806. X
  1807. X        default: /* Strange... */
  1808. X            impossible("strange attack of yours (%d)",
  1809. X                 mattk->aatyp);
  1810. X        }
  1811. X        if (dhit == -1)
  1812. X        rehumanize();
  1813. X        if(sum[i] == 2) return(passive(mon, 1, 0, (mattk->aatyp==AT_KICK)));
  1814. X                            /* defender dead */
  1815. X        else {
  1816. X        (void) passive(mon, sum[i], 1, (mattk->aatyp==AT_KICK));
  1817. X        nsum |= sum[i];
  1818. X        }
  1819. X        if (uasmon == &playermon)
  1820. X        break; /* No extra attacks if no longer a monster */
  1821. X        if (multi < 0)
  1822. X        break; /* If paralyzed while attacking, i.e. floating eye */
  1823. X    }
  1824. X    return(nsum);
  1825. X}
  1826. X
  1827. X#endif /* POLYSELF */
  1828. X
  1829. X/*    Special (passive) attacks on you by monsters done here.        */
  1830. X
  1831. Xint
  1832. Xpassive(mon, mhit, malive, kicked)
  1833. Xregister struct monst *mon;
  1834. Xregister boolean mhit;
  1835. Xregister int malive;
  1836. Xboolean kicked;
  1837. X{
  1838. X    register struct permonst *ptr = mon->data;
  1839. X    register int i, tmp;
  1840. X
  1841. X    for(i = 0; ; i++) {
  1842. X        if(i >= NATTK) return(malive | mhit);    /* no passive attacks */
  1843. X        if(ptr->mattk[i].aatyp == AT_NONE) break;    /* try this one */
  1844. X    }
  1845. X    /* Note: tmp not always used */
  1846. X    if (ptr->mattk[i].damn)
  1847. X        tmp = d((int)ptr->mattk[i].damn, (int)ptr->mattk[i].damd);
  1848. X    else if(ptr->mattk[i].damd)
  1849. X        tmp = d((int)mon->m_lev+1, (int)ptr->mattk[i].damd);
  1850. X    else
  1851. X        tmp = 0;
  1852. X
  1853. X/*    These affect you even if they just died */
  1854. X
  1855. X    switch(ptr->mattk[i].adtyp) {
  1856. X
  1857. X      case AD_ACID:
  1858. X        if(mhit && rn2(2)) {
  1859. X        if (Blind || !flags.verbose) You("are splashed!");
  1860. X        else    You("are splashed by %s acid!", 
  1861. X                            s_suffix(mon_nam(mon)));
  1862. X
  1863. X#ifdef POLYSELF
  1864. X        if(!resists_acid(uasmon))
  1865. X#endif
  1866. X            mdamageu(mon, tmp);
  1867. X        if(!rn2(30)) erode_armor(TRUE);
  1868. X        }
  1869. X        if(mhit && !rn2(6)) {
  1870. X        if (kicked) {
  1871. X            if (uarmf)
  1872. X            (void) rust_dmg(uarmf, xname(uarmf), 3, TRUE);
  1873. X        } else erode_weapon(TRUE);
  1874. X        }
  1875. X        exercise(A_STR, FALSE);
  1876. X        break;
  1877. X      case AD_STON:
  1878. X        if(mhit)
  1879. X          if (!kicked)
  1880. X        if (!uwep && !uarmg
  1881. X#ifdef POLYSELF
  1882. X            && !resists_ston(uasmon)
  1883. X            && !(poly_when_stoned(uasmon) && polymon(PM_STONE_GOLEM))
  1884. X#endif
  1885. X           ) {
  1886. X            You("turn to stone...");
  1887. X            done_in_by(mon);
  1888. X            return 2;
  1889. X        }
  1890. X        break;
  1891. X      case AD_RUST:
  1892. X        if(mhit && !mon->mcan)
  1893. X          if (kicked) {
  1894. X        if (uarmf)
  1895. X            (void) rust_dmg(uarmf, xname(uarmf), 1, TRUE);
  1896. X          } else
  1897. X        erode_weapon(FALSE);
  1898. X        break;
  1899. X      case AD_MAGM:
  1900. X        /* wrath of gods for attacking Oracle */
  1901. X        if(Antimagic) {
  1902. X        shieldeff(u.ux, u.uy);
  1903. X        pline("A hail of magic missiles narrowly misses you!");
  1904. X        } else {
  1905. X        You("are hit by magic missiles appearing from thin air!");
  1906. X        mdamageu(mon, tmp);
  1907. X        }
  1908. X        break;
  1909. X      default:
  1910. X        break;
  1911. X    }
  1912. X
  1913. X/*    These only affect you if they still live */
  1914. X
  1915. X    if(malive && !mon->mcan && rn2(3)) {
  1916. X
  1917. X        switch(ptr->mattk[i].adtyp) {
  1918. X
  1919. X          case AD_PLYS:
  1920. X        if(ptr == &mons[PM_FLOATING_EYE]) {
  1921. X            if (!canseemon(mon)) {
  1922. X            break;
  1923. X            }
  1924. X            if(mon->mcansee) {
  1925. X            if(Reflecting & W_AMUL) {
  1926. X                makeknown(AMULET_OF_REFLECTION);
  1927. X                pline("%s gaze is reflected by your medallion.",
  1928. X                  s_suffix(Monnam(mon)));
  1929. X            } else if(Reflecting & W_ARMS) {
  1930. X                makeknown(SHIELD_OF_REFLECTION);
  1931. X                pline("%s gaze is reflected by your shield.",
  1932. X                  s_suffix(Monnam(mon)));
  1933. X            } else {
  1934. X                You("are frozen by %s gaze!", 
  1935. X                  s_suffix(mon_nam(mon)));
  1936. X                nomul((ACURR(A_WIS) > 12 || rn2(4)) ? -tmp : -120);
  1937. X            }
  1938. X            } else {
  1939. X            pline("%s cannot defend itself.",
  1940. X                Adjmonnam(mon,"blind"));
  1941. X            if(!rn2(500)) change_luck(-1);
  1942. X            }
  1943. X        } else { /* gelatinous cube */
  1944. X            You("are frozen by %s!", mon_nam(mon));
  1945. X            nomul(-tmp);
  1946. X            exercise(A_DEX, FALSE);
  1947. X        }
  1948. X        break;
  1949. X          case AD_COLD:        /* brown mold or blue jelly */
  1950. X        if(monnear(mon, u.ux, u.uy)) {
  1951. X            if(Cold_resistance) {
  1952. X              shieldeff(u.ux, u.uy);
  1953. X            You("feel a mild chill.");
  1954. X#ifdef POLYSELF
  1955. X            ugolemeffects(AD_COLD, tmp);
  1956. X#endif
  1957. X            break;
  1958. X            }
  1959. X            You("are suddenly very cold!");
  1960. X            mdamageu(mon, tmp);
  1961. X        /* monster gets stronger with your heat! */
  1962. X            mon->mhp += tmp / 2;
  1963. X            if (mon->mhpmax < mon->mhp) mon->mhpmax = mon->mhp;
  1964. X        /* at a certain point, the monster will reproduce! */
  1965. X            if(mon->mhpmax > ((int) (mon->m_lev+1) * 8)) {
  1966. X            register struct monst *mtmp;
  1967. X
  1968. X            if ((mtmp = clone_mon(mon)) != 0) {
  1969. X                mtmp->mhpmax = mon->mhpmax /= 2;
  1970. X                if(!Blind)
  1971. X                pline("%s multiplies from your heat!",
  1972. X                                Monnam(mon));
  1973. X            }
  1974. X            }
  1975. X        }
  1976. X        break;
  1977. X          case AD_STUN:        /* specifically yellow mold */
  1978. X        if(!Stunned)
  1979. X            make_stunned((long)tmp, TRUE);
  1980. X        break;
  1981. X          case AD_FIRE:
  1982. X        if(monnear(mon, u.ux, u.uy)) {
  1983. X            if(Fire_resistance) {
  1984. X            shieldeff(u.ux, u.uy);
  1985. X            You("feel mildly warm.");
  1986. X#ifdef POLYSELF
  1987. X            ugolemeffects(AD_FIRE, tmp);
  1988. X#endif
  1989. X            break;
  1990. X            }
  1991. X            You("are suddenly very hot!");
  1992. X            mdamageu(mon, tmp);
  1993. X        }
  1994. X        break;
  1995. X          case AD_ELEC:
  1996. X        if(Shock_resistance) {
  1997. X            shieldeff(u.ux, u.uy);
  1998. X            You("feel a mild tingle.");
  1999. X#ifdef POLYSELF
  2000. X            ugolemeffects(AD_ELEC, tmp);
  2001. X#endif
  2002. X            break;
  2003. X        }
  2004. X        You("are jolted with electricity!");
  2005. X        mdamageu(mon, tmp);
  2006. X        break;
  2007. X          default:
  2008. X        break;
  2009. X        }
  2010. X    }
  2011. X    return(malive | mhit);
  2012. X}
  2013. X
  2014. X/* Note: caller must ascertain mtmp is mimicing... */
  2015. Xvoid
  2016. Xstumble_onto_mimic(mtmp)
  2017. Xregister struct monst *mtmp;
  2018. X{
  2019. X    if(!u.ustuck && !mtmp->mflee && dmgtype(mtmp->data,AD_STCK))
  2020. X        u.ustuck = mtmp;
  2021. X    if (Blind) {
  2022. X        if(!Telepat)
  2023. X        pline("Wait!  That's a monster!");
  2024. X    } else if (glyph_is_cmap(levl[u.ux+u.dx][u.uy+u.dy].glyph) &&
  2025. X        (glyph_to_cmap(levl[u.ux+u.dx][u.uy+u.dy].glyph) == S_hcdoor ||
  2026. X         glyph_to_cmap(levl[u.ux+u.dx][u.uy+u.dy].glyph) == S_vcdoor))
  2027. X        pline("The door actually was %s!", a_monnam(mtmp));
  2028. X    else if (glyph_is_object(levl[u.ux+u.dx][u.uy+u.dy].glyph) &&
  2029. X        glyph_to_obj(levl[u.ux+u.dx][u.uy+u.dy].glyph) == GOLD_PIECE)
  2030. X        pline("That gold was %s!", a_monnam(mtmp));
  2031. X    else {
  2032. X        pline("Wait!  That's %s!", a_monnam(mtmp));
  2033. X    }
  2034. X
  2035. X    wakeup(mtmp);    /* clears mimicing */
  2036. X}
  2037. X
  2038. Xstatic void
  2039. Xnohandglow(mon)
  2040. Xstruct monst *mon;
  2041. X{
  2042. X    char *hands=makeplural(body_part(HAND));
  2043. X
  2044. X    if (!u.umconf || mon->mconf) return;
  2045. X    if (u.umconf == 1) {
  2046. X        if (Blind)
  2047. X            Your("%s stop tingling.", hands);
  2048. X        else
  2049. X            Your("%s stop glowing %s.", hands,
  2050. X                Hallucination ? hcolor() : red);
  2051. X    } else {
  2052. X        if (Blind)
  2053. X            pline("The tingling in your %s lessens.", hands);
  2054. X        else
  2055. X            Your("%s no longer glow so brightly %s.", hands,
  2056. X                Hallucination ? hcolor() : red);
  2057. X    }
  2058. X    u.umconf--;
  2059. X}
  2060. X
  2061. X/*uhitm.c*/
  2062. END_OF_FILE
  2063. if test 44975 -ne `wc -c <'src/uhitm.c'`; then
  2064.     echo shar: \"'src/uhitm.c'\" unpacked with wrong size!
  2065. fi
  2066. # end of 'src/uhitm.c'
  2067. fi
  2068. echo shar: End of archive 19 \(of 108\).
  2069. cp /dev/null ark19isdone
  2070. MISSING=""
  2071. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
  2072. 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
  2073. 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
  2074. 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
  2075. 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
  2076. 101 102 103 104 105 106 107 108 ; do
  2077.     if test ! -f ark${I}isdone ; then
  2078.     MISSING="${MISSING} ${I}"
  2079.     fi
  2080. done
  2081. if test "${MISSING}" = "" ; then
  2082.     echo You have unpacked all 108 archives.
  2083.     echo "Now execute 'rebuild.sh'"
  2084.     rm -f ark10[0-8]isdone ark[1-9]isdone ark[1-9][0-9]isdone
  2085. else
  2086.     echo You still need to unpack the following archives:
  2087.     echo "        " ${MISSING}
  2088. fi
  2089. ##  End of shell archive.
  2090. exit 0
  2091.