home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / src / mhitm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  27.3 KB  |  1,077 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)mhitm.c    3.1    93/05/26    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6. #include "artifact.h"
  7. #include "edog.h"
  8.  
  9. #ifdef OVLB
  10.  
  11. static NEARDATA boolean vis, far_noise;
  12. static NEARDATA long noisetime;
  13. static NEARDATA struct obj *otmp;
  14.  
  15. static void FDECL(mrustm, (struct monst *, struct monst *, struct obj *));
  16. static int FDECL(hitmm, (struct monst *,struct monst *,struct attack *));
  17. static int FDECL(gazemm, (struct monst *,struct monst *,struct attack *));
  18. static int FDECL(gulpmm, (struct monst *,struct monst *,struct attack *));
  19. static int FDECL(explmm, (struct monst *,struct monst *,struct attack *));
  20. static int FDECL(mdamagem, (struct monst *,struct monst *,struct attack *));
  21. static void FDECL(mswingsm, (struct monst *, struct monst *, struct obj *));
  22. static void FDECL(noises,(struct monst *,struct attack *));
  23. static void FDECL(missmm,(struct monst *,struct monst *,struct attack *));
  24. static int FDECL(passivemm, (struct monst *, struct monst *, BOOLEAN_P, int));
  25.  
  26. /* Needed for the special case of monsters wielding vorpal blades (rare).
  27.  * If we use this a lot it should probably be a parameter to mdamagem()
  28.  * instead of a global variable.
  29.  */
  30. static int dieroll;
  31.  
  32. static void
  33. noises(magr, mattk)
  34.     register struct monst *magr;
  35.     register struct    attack *mattk;
  36. {
  37.     boolean farq = (distu(magr->mx, magr->my) > 15);
  38.  
  39.     if(flags.soundok && (farq != far_noise || moves-noisetime > 10)) {
  40.         far_noise = farq;
  41.         noisetime = moves;
  42.         You("hear %s%s.",
  43.             (mattk->aatyp == AT_EXPL) ? "an explosion" : "some noises",
  44.             farq ? " in the distance" : "");
  45.     }
  46. }
  47.  
  48. static
  49. void
  50. missmm(magr, mdef, mattk)
  51.     register struct monst *magr, *mdef;
  52.     struct attack *mattk;
  53. {
  54.     const char *fmt;
  55.     char buf[BUFSZ];
  56.  
  57.     if (vis) {
  58.         if (mdef->m_ap_type) seemimic(mdef);
  59.         if (magr->m_ap_type) seemimic(magr);
  60.         fmt = (could_seduce(magr,mdef,mattk) && !magr->mcan) ?
  61.             "%s pretends to be friendly to" : "%s misses";
  62.         Sprintf(buf, fmt, Monnam(magr));
  63.         pline("%s %s.", buf, mon_nam(mdef));
  64.     } else  noises(magr, mattk);
  65. }
  66.  
  67. /*
  68.  *  fightm()  -- fight some other monster
  69.  *
  70.  *  Returns:
  71.  *    0 - Monster did nothing.
  72.  *    1 - If the monster made an attack.  The monster might have died.
  73.  *
  74.  *  There is an exception to the above.  If mtmp has the hero swallowed,
  75.  *  then we report that the monster did nothing so it will continue to
  76.  *  digest the hero.
  77.  */
  78. int
  79. fightm(mtmp)        /* have monsters fight each other */
  80.     register struct monst *mtmp;
  81. {
  82.     register struct monst *mon, *nmon;
  83.     int result, has_u_swallowed;
  84. #ifdef LINT
  85.     nmon = 0;
  86. #endif
  87.     /* perhaps the monster will resist Conflict */
  88.     if(resist(mtmp, RING_CLASS, 0, 0))
  89.         return(0);
  90. #ifdef POLYSELF
  91.     if(u.ustuck == mtmp) {
  92.         /* perhaps we're holding it... */
  93.         if(itsstuck(mtmp))
  94.         return(0);
  95.     }
  96. #endif
  97.     has_u_swallowed = (u.uswallow && (mtmp == u.ustuck));
  98.  
  99.     for(mon = fmon; mon; mon = nmon) {
  100.         nmon = mon->nmon;
  101.         if(nmon == mtmp) nmon = mtmp->nmon;
  102.         if(mon != mtmp) {
  103.         if(monnear(mtmp,mon->mx,mon->my)) {
  104.             if(!u.uswallow && (mtmp == u.ustuck)) {
  105.             if(!rn2(4)) {
  106.                 pline("%s releases you!", Monnam(mtmp));
  107.                 u.ustuck = 0;
  108.             } else
  109.                 break;
  110.             }
  111.  
  112.             /* mtmp can be killed */
  113.             bhitpos.x = mon->mx;
  114.             bhitpos.y = mon->my;
  115.             result = mattackm(mtmp,mon);
  116.  
  117.             if (result & MM_AGR_DIED) return 1;    /* mtmp died */
  118.             /*
  119.              *  If mtmp has the hero swallowed, lie and say there
  120.              *  was no attack (this allows mtmp to digest the hero).
  121.              */
  122.             if (has_u_swallowed) return 0;
  123.  
  124.             return ((result & MM_HIT) ? 1 : 0);
  125.         }
  126.         }
  127.     }
  128.     return 0;
  129. }
  130.  
  131. /*
  132.  * mattackm() -- a monster attacks another monster.
  133.  *
  134.  * This function returns a result bitfield:
  135.  *       
  136.  *        --------- agressor died
  137.  *       /  ------- defender died
  138.  *      /  /  ----- defender was hit
  139.  *     /  /  /
  140.  *    x  x  x
  141.  *
  142.  *    0x4    MM_AGR_DIED
  143.  *    0x2    MM_DEF_DIED
  144.  *    0x1    MM_HIT
  145.  *    0x0    MM_MISS
  146.  *
  147.  * Each successive attack has a lower probability of hitting.  Some rely on the
  148.  * success of previous attacks.  ** this doen't seem to be implemented -dl **
  149.  *
  150.  * In the case of exploding monsters, the monster dies as well.
  151.  */
  152. int
  153. mattackm(magr, mdef)
  154.     register struct monst *magr,*mdef;
  155. {
  156.     int            i,        /* loop counter */
  157.             tmp,    /* amour class difference */
  158.             strike,    /* hit this attack */
  159.             attk,    /* attack attempted this time */
  160.             struck = 0,    /* hit at least once */
  161.             res[NATTK];    /* results of all attacks */
  162.     struct attack   *mattk;
  163.     struct permonst *pa, *pd;
  164.  
  165.     if (!magr || !mdef) return(MM_MISS);        /* mike@genat */
  166.     pa = magr->data; pd = mdef->data;
  167.     if (!magr->mcanmove) return(MM_MISS);        /* riv05!a3 */
  168.  
  169.     /* Grid bugs cannot attack at an angle. */
  170.     if (pa == &mons[PM_GRID_BUG] && magr->mx != mdef->mx
  171.                         && magr->my != mdef->my)
  172.     return(MM_MISS);
  173.  
  174.     /* Calculate the armour class differential. */
  175.     tmp = find_mac(mdef) + magr->m_lev;
  176.     if (mdef->mconf || !mdef->mcanmove || mdef->msleep){
  177.     tmp += 4;
  178.     if (mdef->msleep) mdef->msleep = 0;
  179.     }
  180.  
  181.     /* undetect monsters become un-hidden if they are attacked */
  182.     if (mdef->mundetected) {
  183.     mdef->mundetected = 0;
  184.     newsym(mdef->mx, mdef->my);
  185.     if(canseemon(mdef))
  186.         pline("Suddenly, you notice %s.", a_monnam(mdef));
  187.     }
  188.  
  189.     /* Elves hate orcs. */
  190.     if (is_elf(pa) && is_orc(pd)) tmp++;
  191.  
  192.  
  193.     /* Set up the visibility of action */
  194.     vis = (cansee(magr->mx,magr->my) && cansee(mdef->mx,mdef->my));
  195.  
  196.     /*    Set flag indicating monster has moved this turn.  Necessary since a
  197.      *    monster might get an attack out of sequence (i.e. before its move) in
  198.      *    some cases, in which case this still counts as its move for the round
  199.      *    and it shouldn't move again.
  200.      */
  201.     magr->mlstmv = monstermoves;
  202.  
  203.     /* Now perform all attacks for the monster. */
  204.     for (i = 0; i < NATTK; i++) {
  205.     res[i] = MM_MISS;
  206.     mattk = &(pa->mattk[i]);
  207.     otmp = (struct obj *)0;
  208.     attk = 1;
  209.     switch (mattk->aatyp) {
  210.         case AT_WEAP:        /* "hand to hand" attacks */
  211. #ifdef MUSE
  212.         if (magr->weapon_check == NEED_WEAPON || !MON_WEP(magr)) {
  213.             magr->weapon_check = NEED_HTH_WEAPON;
  214.             if (mon_wield_item(magr) != 0) return 0;
  215.         }
  216.         remove_cadavers(&magr->minvent);
  217.         possibly_unwield(magr);
  218.         otmp = MON_WEP(magr);
  219. #else
  220.         otmp = select_hwep(magr);
  221. #endif
  222.         if (otmp) {
  223.             if (vis) mswingsm(magr, mdef, otmp);
  224.             tmp += hitval(otmp, pd);
  225.         }
  226.         /* fall through */
  227.         case AT_CLAW:
  228.         case AT_KICK:
  229.         case AT_BITE:
  230.         case AT_STNG:
  231.         case AT_TUCH:
  232.         case AT_BUTT:
  233.         case AT_TENT:
  234.         dieroll = rnd(20 + i);
  235.         strike = (tmp > dieroll);
  236.         if (strike)
  237.             res[i] = hitmm(magr, mdef, mattk);
  238.         else
  239.             missmm(magr, mdef, mattk);
  240.         break;
  241.  
  242.         case AT_HUGS:    /* automatic if prev two attacks succeed */
  243.         strike = (i >= 2 && res[i-1] == MM_HIT && res[i-2] == MM_HIT);
  244.         if (strike)
  245.             res[i] = hitmm(magr, mdef, mattk);
  246.  
  247.         break;
  248.  
  249.         case AT_GAZE:
  250.         strike = 0;    /* will not wake up a sleeper */
  251.         res[i] = gazemm(magr, mdef, mattk);
  252.         break;
  253.  
  254.         case AT_EXPL:
  255.         strike = 1;    /* automatic hit */
  256.         res[i] = explmm(magr, mdef, mattk);
  257.         break;
  258.  
  259.         case AT_ENGL:
  260.         /* Engulfing attacks are directed at the hero if
  261.          * possible. -dlc
  262.          */
  263.         if (u.uswallow && magr == u.ustuck)
  264.             strike = 0;
  265.         else {
  266.             if ((strike = (tmp > rnd(20+i))))
  267.             res[i] = gulpmm(magr, mdef, mattk);
  268.             else
  269.             missmm(magr, mdef, mattk);
  270.         }
  271.         break;
  272.  
  273.         default:        /* no attack */
  274.         strike = 0;
  275.         attk = 0;
  276.         break;
  277.     }
  278.  
  279.     if (attk && !(res[i] & MM_AGR_DIED))
  280.         res[i] = passivemm(magr, mdef, strike, res[i] & MM_DEF_DIED);
  281.  
  282.     if (res[i] & MM_DEF_DIED) return res[i];
  283.  
  284.     /*
  285.      *  Wake up the defender.  NOTE:  this must follow the check
  286.      *  to see if the defender died.  We don't want to modify
  287.      *  unallocated monsters!
  288.      */
  289.     if (strike) mdef->msleep = 0;
  290.  
  291.     if (res[i] & MM_AGR_DIED)  return res[i];
  292.     /* return if aggressor can no longer attack */
  293.     if (!magr->mcanmove || magr->msleep) return res[i];
  294.     if (res[i] & MM_HIT) struck = 1;    /* at least one hit */
  295.     }
  296.  
  297.     return(struck ? MM_HIT : MM_MISS);
  298. }
  299.  
  300. /* Returns the result of mdamagem(). */
  301. static int
  302. hitmm(magr, mdef, mattk)
  303.     register struct monst *magr,*mdef;
  304.     struct    attack *mattk;
  305. {
  306.     if(vis){
  307.         int compat;
  308.         char buf[BUFSZ];
  309.  
  310.         if(mdef->m_ap_type) seemimic(mdef);
  311.         if(magr->m_ap_type) seemimic(magr);
  312.         if((compat = could_seduce(magr,mdef,mattk)) && !magr->mcan) {
  313.             Sprintf(buf, "%s %s", Monnam(magr),
  314.                 mdef->mcansee ? "smiles at" : "talks to");
  315.             pline("%s %s %s.", buf, mon_nam(mdef),
  316.                 compat == 2 ?
  317.                     "engagingly" : "seductively");
  318.         } else {
  319.             char magr_name[BUFSZ];
  320.  
  321.             Strcpy(magr_name, Monnam(magr));
  322.             switch (mattk->aatyp) {
  323.             case AT_BITE:
  324.                 Sprintf(buf,"%s bites", magr_name);
  325.                 break;
  326.             case AT_STNG:
  327.                 Sprintf(buf,"%s stings", magr_name);
  328.                 break;
  329.             case AT_BUTT:
  330.                 Sprintf(buf,"%s butts", magr_name);
  331.                 break;
  332.             case AT_TUCH:
  333.                 Sprintf(buf,"%s touches", magr_name);
  334.                 break;
  335.             case AT_TENT:
  336.                 Sprintf(buf, "%s tentacles suck",
  337.                     s_suffix(magr_name));
  338.                 break;
  339.             case AT_HUGS:
  340.                 if (magr != u.ustuck) {
  341.                     Sprintf(buf,"%s squeezes", magr_name);
  342.                     break;
  343.                 }
  344.             default:
  345.                 Sprintf(buf,"%s hits", magr_name);
  346.             }
  347.         }
  348.         pline("%s %s.", buf, mon_nam(mdef));
  349.     } else  noises(magr, mattk);
  350.     return(mdamagem(magr, mdef, mattk));
  351. }
  352.  
  353. /* Returns the same values as mdamagem(). */
  354. static int
  355. gazemm(magr, mdef, mattk)
  356.     register struct monst *magr, *mdef;
  357.     struct attack *mattk;
  358. {
  359.     char buf[BUFSZ];
  360.  
  361.     if(vis) {
  362.         Sprintf(buf,"%s gazes at", Monnam(magr));
  363.         pline("%s %s...", buf, mon_nam(mdef));
  364.     }
  365.  
  366.     if (!mdef->mcansee || mdef->msleep) {
  367.         if(vis) pline("but nothing happens.");
  368.         return(MM_MISS);
  369.     }
  370.  
  371.     return(mdamagem(magr, mdef, mattk));
  372. }
  373.  
  374. /* Returns the same values as mattackm(). */
  375. static int
  376. gulpmm(magr, mdef, mattk)
  377.     register struct monst *magr, *mdef;
  378.     register struct    attack *mattk;
  379. {
  380.     xchar    ax, ay, dx, dy;
  381.     int    status;
  382.     char buf[BUFSZ];
  383.  
  384.     if (mdef->data->msize >= MZ_HUGE) return MM_MISS;
  385.  
  386.     if (vis) {
  387.         Sprintf(buf,"%s swallows", Monnam(magr));
  388.         pline("%s %s.", buf, mon_nam(mdef));
  389.     }
  390.  
  391.     /*
  392.      *  All of this maniuplation is needed to keep the display correct.
  393.      *  There is a flush at the next pline().
  394.      */
  395.     ax = magr->mx;
  396.     ay = magr->my;
  397.     dx = mdef->mx;
  398.     dy = mdef->my;
  399.     /*
  400.      *  Leave the defender in the monster chain at it's current position,
  401.      *  but don't leave it on the screen.  Move the agressor to the def-
  402.      *  ender's position.
  403.      */
  404.     remove_monster(ax, ay);
  405.     place_monster(magr, dx, dy);
  406.     newsym(ax,ay);            /* erase old position */
  407.     newsym(dx,dy);            /* update new position */
  408.  
  409.     status = mdamagem(magr, mdef, mattk);
  410.  
  411.     if ((status & MM_AGR_DIED) && (status & MM_DEF_DIED)) {
  412.         ;                    /* both died -- do nothing  */
  413.     }
  414.     else if (status & MM_DEF_DIED) {    /* defender died */
  415.         /*
  416.          *  Note:  remove_monster() was called in relmon(), wiping out
  417.          *  magr from level.monsters[mdef->mx][mdef->my].  We need to
  418.          *  put it back and display it.    -kd
  419.          */
  420.         place_monster(magr, dx, dy);
  421.         newsym(dx, dy);
  422.     }
  423.     else if (status & MM_AGR_DIED) {    /* agressor died */
  424.         place_monster(mdef, dx, dy);
  425.         newsym(dx, dy);
  426.     }
  427.     else {                    /* both alive, put them back */
  428.         if (cansee(dx, dy))
  429.         pline("%s is regurgitated!", Monnam(mdef));
  430.  
  431.         place_monster(magr, ax, ay);
  432.         place_monster(mdef, dx, dy);
  433.         newsym(ax, ay);
  434.         newsym(dx, dy);
  435.     }
  436.  
  437.     return status;
  438. }
  439.  
  440. static int
  441. explmm(magr, mdef, mattk)
  442.     register struct monst *magr, *mdef;
  443.     register struct    attack *mattk;
  444. {
  445.     int result, was_tame;
  446.  
  447.     if(cansee(magr->mx, magr->my))
  448.         pline("%s explodes!", Monnam(magr));
  449.     else    noises(magr, mattk);
  450.  
  451.     was_tame = magr->mtame;
  452.     result = mdamagem(magr, mdef, mattk);
  453.  
  454.     /* The attacker could have died . . */
  455.     if (was_tame)
  456.         You("have a sad feeling for a moment, then it passes.");
  457.  
  458.     /* Kill off agressor if it didn't die. */
  459.     if (!(result & MM_AGR_DIED)) {
  460.         mondead(magr);
  461. #ifdef MUSE
  462.         if (magr->mhp <= 0)
  463. #endif
  464.         result |= MM_AGR_DIED;
  465.     }
  466.  
  467.     return result;
  468. }
  469.  
  470. static const char psf[] =
  471.     "have a peculiarly sad feeling for a moment, then it passes.";
  472.  
  473. /*
  474.  *  See comment at top of mattackm(), for return values.
  475.  */
  476. static int
  477. mdamagem(magr, mdef, mattk)
  478.     register struct monst    *magr, *mdef;
  479.     register struct attack    *mattk;
  480. {
  481.     struct    permonst *pa = magr->data, *pd = mdef->data;
  482.     int    tmp = d((int)mattk->damn,(int)mattk->damd);
  483.     char buf[BUFSZ];
  484.  
  485.     if (pd == &mons[PM_COCKATRICE] && !resists_ston(pa) &&
  486.        (mattk->aatyp != AT_WEAP || !otmp) &&
  487.        (mattk->aatyp != AT_GAZE && mattk->aatyp != AT_EXPL) &&
  488. #ifdef MUSE
  489.        (!(magr->misc_worn_check & W_ARMG))) {
  490. #else
  491.        (!is_mercenary(pa) || !m_carrying(magr, LEATHER_GLOVES))) {
  492.        /* Note: other monsters may carry gloves, only soldiers have them */
  493.        /* as their "armor" and can be said to wear them */
  494. #endif
  495.         if (poly_when_stoned(pa)) {
  496.             mon_to_stone(magr);
  497.             return MM_HIT; /* no damage during the polymorph */
  498.         }
  499.         if (vis) pline("%s turns to stone!", Monnam(magr));
  500.         else if (magr->mtame) You(psf);
  501.         monstone(magr);
  502.         return MM_AGR_DIED;
  503.     }
  504.  
  505.     switch(mattk->adtyp) {
  506.         case AD_DGST:
  507.         if(flags.verbose && flags.soundok) verbalize("Burrrrp!");
  508.         tmp = mdef->mhp;
  509.         break;
  510.         case AD_STUN:
  511.         if (magr->mcan) break;
  512.         if(vis) pline("%s staggers for a moment.", Monnam(mdef));
  513.         mdef->mstun = 1;
  514.         /* fall through */
  515.         case AD_WERE:
  516.         case AD_HEAL:
  517.         case AD_LEGS:
  518.         case AD_PHYS:
  519.         if (mattk->aatyp == AT_KICK && thick_skinned(pd))
  520.             tmp = 0;
  521.         else if(mattk->aatyp == AT_WEAP) {
  522.             if(otmp) {
  523. #ifdef MUSE
  524.             if (otmp->otyp == CORPSE &&
  525.                 otmp->corpsenm == PM_COCKATRICE)
  526.                 goto do_stone_goto_label;
  527. #endif
  528.             tmp += dmgval(otmp, pd);
  529.             if (otmp->oartifact) {
  530.                 (void)artifact_hit(magr,mdef, otmp, &tmp, dieroll);
  531.                 if (mdef->mhp <= 0)
  532.                 return (MM_DEF_DIED |
  533.                     (grow_up(magr,mdef) ? 0 : MM_AGR_DIED));
  534.             }
  535.             if (tmp)
  536.                 mrustm(magr, mdef, otmp);
  537.             }
  538.         }
  539.         break;
  540.         case AD_FIRE:
  541.         if (magr->mcan) {
  542.             tmp = 0;
  543.             break;
  544.         }
  545.         if(vis) pline("%s is on fire!", Monnam(mdef));
  546.         tmp += destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE);
  547.         tmp += destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE);
  548.         if(resists_fire(pd)) {
  549.             if (vis)
  550.             pline("The fire doesn't seem to burn %s!",
  551.                                 mon_nam(mdef));
  552.             shieldeff(mdef->mx, mdef->my);
  553.             golemeffects(mdef, AD_FIRE, tmp);
  554.             tmp = 0;
  555.         }
  556.         /* only potions damage resistant players in destroy_item */
  557.         tmp += destroy_mitem(mdef, POTION_CLASS, AD_FIRE);
  558.         break;
  559.         case AD_COLD:
  560.         if (magr->mcan) {
  561.             tmp = 0;
  562.             break;
  563.         }
  564.         if(vis) pline("%s is covered in frost!", Monnam(mdef));
  565.         if(resists_cold(pd)) {
  566.             if (vis)
  567.             pline("The frost doesn't seem to chill %s!",
  568.                                 mon_nam(mdef));
  569.             shieldeff(mdef->mx, mdef->my);
  570.             golemeffects(mdef, AD_COLD, tmp);
  571.             tmp = 0;
  572.         }
  573.         tmp += destroy_mitem(mdef, POTION_CLASS, AD_COLD);
  574.         break;
  575.         case AD_ELEC:
  576.         if (magr->mcan) {
  577.             tmp = 0;
  578.             break;
  579.         }
  580.         if(vis) pline("%s gets zapped!", Monnam(mdef));
  581.         tmp += destroy_mitem(mdef, WAND_CLASS, AD_ELEC);
  582.         if(resists_elec(pd)) {
  583.             if (vis) pline("The zap doesn't shock %s!", mon_nam(mdef));
  584.             shieldeff(mdef->mx, mdef->my);
  585.             golemeffects(mdef, AD_ELEC, tmp);
  586.             tmp = 0;
  587.         }
  588.         /* only rings damage resistant players in destroy_item */
  589.         tmp += destroy_mitem(mdef, RING_CLASS, AD_ELEC);
  590.         break;
  591.         case AD_ACID:
  592.         if (magr->mcan) {
  593.             tmp = 0;
  594.             break;
  595.         }
  596.         if(resists_acid(pd)) {
  597.             if (vis)
  598.             pline("%s is covered in acid, but it seems harmless.",
  599.                             Monnam(mdef));
  600.             tmp = 0;
  601.         } else if (vis) {
  602.             pline("%s is covered in acid!", Monnam(mdef));
  603.             pline("It burns %s!", mon_nam(mdef));
  604.         }
  605.         break;
  606.         case AD_RUST:
  607.         if (!magr->mcan && pd == &mons[PM_IRON_GOLEM]) {
  608.             if (vis) pline("%s falls to pieces!", Monnam(mdef));
  609.             else if(mdef->mtame)
  610.                  pline("May %s rust in peace.", mon_nam(mdef));
  611.             mondied(mdef);
  612. #ifdef MUSE
  613.             if (mdef->mhp > 0) return 0;
  614. #endif
  615.             return (MM_DEF_DIED | (grow_up(magr,mdef) ?
  616.                             0 : MM_AGR_DIED));
  617.         }
  618.         tmp = 0;
  619.         break;
  620.         case AD_DCAY:
  621.         if (!magr->mcan && (pd == &mons[PM_WOOD_GOLEM] ||
  622.             pd == &mons[PM_LEATHER_GOLEM])) {
  623.             if (vis) pline("%s falls to pieces!", Monnam(mdef));
  624.             else if(mdef->mtame)
  625.                  pline("May %s rot in peace.", mon_nam(mdef));
  626.             mondied(mdef);
  627. #ifdef MUSE
  628.             if (mdef->mhp > 0) return 0;
  629. #endif
  630.             return (MM_DEF_DIED | (grow_up(magr,mdef) ?
  631.                             0 : MM_AGR_DIED));
  632.         }
  633.         tmp = 0;
  634.         break;
  635.         case AD_STON:
  636. #ifdef MUSE
  637. do_stone_goto_label:
  638. #endif
  639.         if(poly_when_stoned(pd)) {
  640.             mon_to_stone(mdef);
  641.             tmp = 0;
  642.             break;
  643.         }
  644.         if(!resists_ston(pd)) {
  645.             if(vis) pline("%s turns to stone!", Monnam(mdef));
  646.             else if(mdef->mtame) You(psf);
  647.             monstone(mdef);
  648. #ifdef MUSE
  649.             if (mdef->mhp > 0) return 0;
  650. #endif
  651.             return (MM_DEF_DIED | (grow_up(magr,mdef) ?
  652.                             0 : MM_AGR_DIED));
  653.         }
  654.         tmp = (mattk->adtyp == AD_STON ? 0 : 1);
  655.         break;
  656.         case AD_TLPT:
  657.         if(!magr->mcan && tmp < mdef->mhp) {
  658.             if (!tele_restrict(mdef)) rloc(mdef);
  659.             if(vis && !cansee(mdef->mx, mdef->my))
  660.             pline("%s suddenly disappears!", Monnam(mdef));
  661.         }
  662.         break;
  663.         case AD_SLEE:
  664.         if(!resists_sleep(pd) && !magr->mcan && !mdef->msleep
  665.                             && mdef->mcanmove) {
  666.             if (vis) {
  667.             Strcpy(buf, Monnam(mdef));
  668.             pline("%s is put to sleep by %s.", buf, mon_nam(magr));
  669.             }
  670.             mdef->mcanmove = 0;
  671.             mdef->mfrozen = rnd(10);
  672.         }
  673.         break;
  674.         case AD_PLYS:
  675.         if(!magr->mcan && mdef->mcanmove) {
  676.             if (vis) {
  677.             Strcpy(buf, Monnam(mdef));
  678.             pline("%s is frozen by %s.", buf, mon_nam(magr));
  679.             }
  680.             mdef->mcanmove = 0;
  681.             mdef->mfrozen = rnd(10);
  682.         }
  683.         break;
  684.         case AD_SLOW:
  685.         if(!magr->mcan && vis && mdef->mspeed != MSLOW) {
  686.             if (vis) pline("%s slows down.", Monnam(mdef));
  687.             if (mdef->mspeed == MFAST) mdef->mspeed = 0;
  688.             else mdef->mspeed = MSLOW;
  689.         }
  690.         break;
  691.         case AD_CONF:
  692.         /* Since confusing another monster doesn't have a real time
  693.          * limit, setting spec_used would not really be right (though
  694.          * we still should check for it).
  695.          */
  696.         if (!magr->mcan && vis && !mdef->mconf && !magr->mspec_used) {
  697.             pline("%s looks confused.", Monnam(mdef));
  698.             mdef->mconf = 1;
  699.         }
  700.         break;
  701.         case AD_BLND:
  702.         if (!magr->mcan && haseyes(pd)) {
  703.             register unsigned rnd_tmp;
  704.  
  705.             if (vis && mdef->mcansee)
  706.             pline("%s is blinded.", Monnam(mdef));
  707.             rnd_tmp = d((int)mattk->damn, (int)mattk->damd);
  708.             if ((rnd_tmp += mdef->mblinded) > 127) rnd_tmp = 127;
  709.             mdef->mblinded = rnd_tmp;
  710.             mdef->mcansee = 0;
  711.         }
  712.         tmp = 0;
  713.         break;
  714.         case AD_CURS:
  715.         if (!night() && (pa == &mons[PM_GREMLIN])) break;
  716.         if (!magr->mcan && !rn2(10)) {
  717.             if (is_were(pd) && pd->mlet != S_HUMAN)
  718.             were_change(mdef);
  719.             if (pd == &mons[PM_CLAY_GOLEM]) {
  720.                 if (vis) {
  721.                 pline("Some writing vanishes from %s head!",
  722.                     s_suffix(mon_nam(mdef)));
  723.                 pline("%s dies!", Monnam(mdef));
  724.                 }
  725.                 else if (mdef->mtame)
  726.     You("have a strangely sad feeling for a moment, then it passes.");
  727.                 mondied(mdef);
  728. #ifdef MUSE
  729.                 if (mdef->mhp > 0) return 0;
  730. #endif
  731.                 return (MM_DEF_DIED | (grow_up(magr,mdef) ?
  732.                             0 : MM_AGR_DIED));
  733.               }
  734.             mdef->mcan = 1;
  735.             if (flags.soundok) {
  736.                 if (!vis) You("hear laughter.");
  737.                 else pline("%s chuckles.", Monnam(magr));
  738.             }
  739.         }
  740.         break;
  741.         case AD_SGLD:
  742.         tmp = 0;
  743.         if (magr->mcan || !mdef->mgold) break;
  744.         /* technically incorrect; no check for stealing gold from
  745.          * between mdef's feet...
  746.          */
  747.         magr->mgold += mdef->mgold;
  748.         mdef->mgold = 0;
  749.         if (vis) {
  750.             Strcpy(buf, Monnam(magr));
  751.             pline("%s steals some gold from %s.", buf,
  752.                                 mon_nam(mdef));
  753.         }
  754.         break;
  755.         case AD_DRLI:
  756.         if(rn2(2) && !resists_drli(pd)) {
  757.             tmp = d(2,6);
  758.             if (vis)
  759.                 pline("%s suddenly seems weaker!", Monnam(mdef));
  760.             mdef->mhpmax -= tmp;
  761.             if (mdef->m_lev == 0)
  762.                 tmp = mdef->mhp;
  763.             else mdef->m_lev--;
  764.             /* Automatic kill if drained past level 0 */
  765.         }
  766.         break;
  767. #ifdef SEDUCE
  768.         case AD_SSEX:
  769. #endif
  770.         case AD_SITM:    /* for now these are the same */
  771.         case AD_SEDU:
  772.         if (!magr->mcan && mdef->minvent) {
  773.                otmp = mdef->minvent;
  774.             mdef->minvent = otmp->nobj;
  775.             otmp->nobj = magr->minvent;
  776.             magr->minvent = otmp;
  777.             if (vis) {
  778.                 Strcpy(buf, Monnam(magr));
  779.                 pline("%s steals %s from %s!", buf,
  780.                         doname(otmp), mon_nam(mdef));
  781.             }
  782. #ifdef MUSE
  783.             possibly_unwield(mdef);
  784.             if (otmp->owornmask) {
  785.                 mdef->misc_worn_check &= ~otmp->owornmask;
  786.                 otmp->owornmask = 0;
  787.             }
  788.             mselftouch(mdef, (const char *)0, FALSE);
  789.             if (mdef->mhp <= 0)
  790.                 return (MM_DEF_DIED | (grow_up(magr,mdef) ?
  791.                             0 : MM_AGR_DIED));
  792. #endif
  793.         }
  794.         tmp = 0;
  795.         break;
  796.         case AD_DRST:
  797.         case AD_DRDX:
  798.         case AD_DRCO:
  799.         if (!magr->mcan && !rn2(8)) {
  800.             if (vis)
  801.             pline("%s %s was poisoned!", s_suffix(Monnam(magr)),
  802.                 mattk->aatyp==AT_BITE ? "bite" : "sting");
  803.             if (resists_poison(pd)) {
  804.             if (vis)
  805.                 pline("The poison doesn't seem to affect %s.",
  806.                 mon_nam(mdef));
  807.             } else {
  808.             if (rn2(10)) tmp += rn1(10,6);
  809.             else {
  810.                 if (vis) pline("The poison was deadly...");
  811.                 tmp = mdef->mhp;
  812.             }
  813.             }
  814.         }
  815.         break;
  816.         case AD_DRIN:
  817.         if (!has_head(pd)) {
  818.             if (vis) pline("%s doesn't seem harmed.", Monnam(mdef));
  819.             tmp = 0;
  820.             break;
  821.         }
  822. #ifdef MUSE
  823.         if ((mdef->misc_worn_check & W_ARMH) && rn2(8)) {
  824.             if (vis) {
  825.             Strcpy(buf, s_suffix(Monnam(mdef)));
  826.             pline("%s helmet blocks %s attack to his head.",
  827.                 buf, s_suffix(mon_nam(magr)));
  828.             }
  829.             break;
  830.         }
  831. #endif
  832.         if (vis) pline("%s brain is eaten!", s_suffix(Monnam(mdef)));
  833.         if (mindless(pd)) {
  834.             if (vis) pline("%s doesn't notice.", Monnam(mdef));
  835.             break;
  836.         }
  837.         tmp += rnd(10); /* fakery, since monsters lack INT scores */
  838.         if (magr->mtame && !magr->isminion) {
  839.             EDOG(magr)->hungrytime += rnd(60);
  840.             magr->mconf = 0;
  841.         }
  842.         if (tmp >= mdef->mhp && vis)
  843.             pline("%s last thought fades away...", 
  844.                       s_suffix(Monnam(mdef)));
  845.         break;
  846.         case AD_STCK:
  847.         case AD_WRAP: /* monsters cannot grab one another, it's too hard */
  848.         break;
  849.         default:    tmp = 0;
  850.             break;
  851.     }
  852.     if(!tmp) return(MM_MISS);
  853.  
  854.     if((mdef->mhp -= tmp) < 1) {
  855.         if (m_at(mdef->mx, mdef->my) == magr) {  /* see gulpmm() */
  856.         remove_monster(mdef->mx, mdef->my);
  857.         place_monster(mdef, mdef->mx, mdef->my);
  858.         }
  859.         monkilled(mdef, "", (int)mattk->adtyp);
  860.         if (mdef->mhp > 0) return 0; /* mdef lifesaved */
  861.         return (MM_DEF_DIED | (grow_up(magr,mdef) ? 0 : MM_AGR_DIED));
  862.     }
  863.     return(MM_HIT);
  864. }
  865.  
  866. #endif /* OVLB */
  867.  
  868.  
  869. #ifdef OVL0
  870.  
  871. int
  872. noattacks(ptr)            /* returns 1 if monster doesn't attack */
  873.     struct    permonst *ptr;
  874. {
  875.     int i;
  876.  
  877.     for(i = 0; i < NATTK; i++)
  878.         if(ptr->mattk[i].aatyp) return(0);
  879.  
  880.     return(1);
  881. }
  882.  
  883. #endif /* OVL0 */
  884. #ifdef OVLB
  885.  
  886. static void
  887. mrustm(magr, mdef, obj)
  888. register struct monst *magr, *mdef;
  889. register struct obj *obj;
  890. {
  891.     if (!magr || !mdef || !obj) return; /* just in case */
  892.     if (mdef->data == &mons[PM_RUST_MONSTER] && !mdef->mcan &&
  893.         is_rustprone(obj) && obj->oeroded < MAX_ERODE) {
  894.         if (obj->greased || obj->oerodeproof || (obj->blessed && rn2(3))) {
  895.             if (cansee(mdef->mx, mdef->my) && flags.verbose)
  896.             pline("%s weapon is not affected.", 
  897.                              s_suffix(Monnam(magr)));
  898.             if (obj->greased && !rn2(2)) obj->greased = 0;
  899.         } else {
  900.             if (cansee(mdef->mx, mdef->my)) {
  901.             pline("%s %s%s!", s_suffix(Monnam(magr)),
  902.                   aobjnam(obj, "rust"),
  903.                   obj->oeroded ? " further" : "");
  904.             }
  905.             obj->oeroded++;
  906.         }
  907.     }
  908. }
  909.  
  910. static void
  911. mswingsm(magr, mdef, otemp)
  912. register struct monst *magr, *mdef;
  913. register struct obj *otemp;
  914. {
  915.     char buf[BUFSZ];
  916.     Strcpy(buf, mon_nam(mdef));
  917.     if (!flags.verbose || Blind) return;
  918.     pline("%s %s %s %s at %s.", Monnam(magr),
  919.           ((otemp->otyp >= SPEAR && otemp->otyp <= LANCE) ||
  920.            (otemp->otyp >= PARTISAN && otemp->otyp <= SPETUM) ||
  921.            otemp->otyp == TRIDENT) ? "thrusts" : "swings",
  922.           his[pronoun_gender(magr)], xname(otemp), buf);
  923. }
  924.  
  925. /*
  926.  * Passive responses by defenders.  Does not replicate responses already
  927.  * handled above.  Returns same values as mattackm.
  928.  */
  929. static int
  930. passivemm(magr,mdef,mhit,mdead)
  931. register struct monst *magr, *mdef;
  932. boolean mhit;
  933. int mdead;
  934. {
  935.     register struct permonst *mddat = mdef->data;
  936.     register struct permonst *madat = magr->data;
  937.     char buf[BUFSZ];
  938.     int i, tmp;
  939.  
  940.     for(i = 0; ; i++) {
  941.         if(i >= NATTK) return (mdead | mhit); /* no passive attacks */
  942.         if(mddat->mattk[i].aatyp == AT_NONE) break;
  943.     }
  944.     if (mddat->mattk[i].damn)
  945.         tmp = d((int)mddat->mattk[i].damn, 
  946.                                     (int)mddat->mattk[i].damd);
  947.     else if(mddat->mattk[i].damd)
  948.         tmp = d((int)mddat->mlevel+1, (int)mddat->mattk[i].damd);
  949.     else
  950.         tmp = 0;
  951.  
  952.     /* These affect the enemy even if defender killed */
  953.     switch(mddat->mattk[i].adtyp) {
  954.         case AD_ACID:
  955.         if (mhit && !rn2(2)) {
  956.             Strcpy(buf, Monnam(magr));
  957.             if(canseemon(magr))
  958.             pline("%s is splashed by %s acid!",
  959.                   buf, s_suffix(mon_nam(mdef)));
  960.             if(resists_acid(madat)) {
  961.             if(canseemon(magr))
  962.                 pline("%s is not affected.", Monnam(magr));
  963.             tmp = 0;
  964.             }
  965.         } else tmp = 0;
  966.         goto assess_dmg;
  967.         default:
  968.         break;
  969.     }
  970.     if (mdead || mdef->mcan) return (mdead|mhit);
  971.  
  972.     /* These affect the enemy only if defender is still alive */
  973.     if (rn2(3)) switch(mddat->mattk[i].adtyp) {
  974.         case AD_PLYS: /* Floating eye */
  975.         if (tmp > 127) tmp = 127;
  976.         if (mddat == &mons[PM_FLOATING_EYE]) {
  977.             if (!rn2(4)) tmp = 127;
  978.             if (magr->mcansee && haseyes(madat) && mdef->mcansee &&
  979.             (perceives(madat) || !mdef->minvis)) {
  980. #ifdef MUSE
  981.             Sprintf(buf, "%s gaze is reflected by %%s %%s.",
  982.                 s_suffix(mon_nam(mdef)));
  983.             if (mon_reflects(magr, buf))
  984.                 return(mdead|mhit);
  985. #endif
  986.             Strcpy(buf, Monnam(magr));
  987.             if(canseemon(magr))
  988.                 pline("%s is frozen by %s gaze!",
  989.                   buf, s_suffix(mon_nam(mdef)));
  990.             magr->mcanmove = 0;
  991.             magr->mfrozen = tmp;
  992.             return (mdead|mhit);
  993.             }
  994.         } else { /* gelatinous cube */
  995.             Strcpy(buf, Monnam(magr));
  996.             if(canseemon(magr))
  997.             pline("%s is frozen by %s.", buf, mon_nam(mdef));
  998.             magr->mcanmove = 0;
  999.             magr->mfrozen = tmp;
  1000.             return (mdead|mhit);
  1001.         }
  1002.         return 1;
  1003.         case AD_COLD:
  1004.         if (resists_cold(madat)) {
  1005.             if (canseemon(magr)) {
  1006.             pline("%s is mildly chilly.", Monnam(magr));
  1007.             golemeffects(magr, AD_COLD, tmp);
  1008.             tmp = 0;
  1009.             break;
  1010.             }
  1011.         }
  1012.         if(canseemon(magr))
  1013.             pline("%s is suddenly very cold!", Monnam(magr));
  1014.         mdef->mhp += tmp / 2;
  1015.         if (mdef->mhpmax < mdef->mhp) mdef->mhpmax = mdef->mhp;
  1016.         if (mdef->mhpmax > ((int) (mdef->m_lev+1) * 8)) {
  1017.             register struct monst *mtmp;
  1018.  
  1019.             if ((mtmp = clone_mon(mdef)) != 0) {
  1020.             mtmp->mhpmax = mdef->mhpmax /= 2;
  1021.             if(canseemon(magr)) {
  1022.                 Strcpy(buf, Monnam(mdef));
  1023.                 pline("%s multiplies from %s heat!",
  1024.                     buf, s_suffix(mon_nam(magr)));
  1025.             }
  1026.             }
  1027.         }
  1028.         break;
  1029.         case AD_STUN:
  1030.         if (!magr->mstun) {
  1031.             magr->mstun = 1;
  1032.             if (canseemon(magr))
  1033.             pline("%s staggers...", Monnam(magr));
  1034.         }
  1035.         tmp = 0;
  1036.         break;
  1037.         case AD_FIRE:
  1038.         if (resists_fire(madat)) {
  1039.             if (canseemon(magr)) {
  1040.             pline("%s is mildly warmed.", Monnam(magr));
  1041.             golemeffects(magr, AD_FIRE, tmp);
  1042.             tmp = 0;
  1043.             break;
  1044.             }
  1045.         }
  1046.         if(canseemon(magr))
  1047.             pline("%s is suddenly very hot!", Monnam(magr));
  1048.         break;
  1049.         case AD_ELEC:
  1050.         if (resists_elec(madat)) {
  1051.             if (canseemon(magr)) {
  1052.             pline("%s is mildly tingled.", Monnam(magr));
  1053.             golemeffects(magr, AD_ELEC, tmp);
  1054.             tmp = 0;
  1055.             break;
  1056.             }
  1057.         }
  1058.         if(canseemon(magr))
  1059.             pline("%s is jolted with electricity!", Monnam(magr));
  1060.         break;
  1061.         default: tmp = 0;
  1062.         break;
  1063.     }
  1064.     else tmp = 0;
  1065.  
  1066.     assess_dmg:
  1067.     if((magr->mhp -= tmp) <= 0) {
  1068.         monkilled(magr, "", (int)mddat->mattk[i].adtyp);
  1069.         return (mdead | mhit | MM_AGR_DIED);
  1070.     }
  1071.     return (mdead | mhit);
  1072. }
  1073.  
  1074. #endif /* OVLB */
  1075.  
  1076. /*mhitm.c*/
  1077.