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