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

  1. /*    SCCS Id: @(#)uhitm.c    3.1    93/02/18    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6.  
  7. static boolean FDECL(known_hitum, (struct monst *,int));
  8. static boolean FDECL(hitum, (struct monst *,int));
  9. #ifdef POLYSELF
  10. static int FDECL(explum, (struct monst *,struct attack *));
  11. static int FDECL(gulpum, (struct monst *,struct attack *));
  12. static boolean FDECL(hmonas, (struct monst *,int));
  13. #endif
  14. static void FDECL(nohandglow, (struct monst *));
  15.  
  16. extern boolean notonhead;    /* for long worms */
  17. /* The below might become a parameter instead if we use it a lot */
  18. static int dieroll;
  19.  
  20. struct monst *
  21. clone_mon(mon)
  22. struct monst *mon;
  23. {
  24.     coord mm;
  25.     struct monst *m2;
  26.  
  27.     mm.x = mon->mx;
  28.     mm.y = mon->my;
  29.     if (!enexto(&mm, mm.x, mm.y, mon->data)) return (struct monst *)0;
  30.     if (MON_AT(mm.x, mm.y) || mon->mhp <= 1) return (struct monst *)0;
  31.     /* may have been extinguished for population control */
  32.     if(mon->data->geno & G_EXTINCT) return((struct monst *) 0);
  33.     m2 = newmonst(0);
  34.     *m2 = *mon;            /* copy condition of old monster */
  35.     m2->nmon = fmon;
  36.     fmon = m2;
  37.     m2->m_id = flags.ident++;
  38.     m2->mx = mm.x;
  39.     m2->my = mm.y;
  40.  
  41.     m2->minvent = (struct obj *) 0; /* objects don't clone */
  42.     m2->mleashed = FALSE;
  43.     m2->mgold = 0L;
  44.     /* Max HP the same, but current HP halved for both.  The caller
  45.      * might want to override this by halving the max HP also.
  46.      */
  47.     m2->mhpmax = mon->mhpmax;
  48.     m2->mhp = mon->mhp /= 2;
  49.  
  50.     /* since shopkeepers and guards will only be cloned if they've been
  51.      * polymorphed away from their original forms, the clone doesn't have
  52.      * room for the extra information.  we also don't want two shopkeepers
  53.      * around for the same shop.
  54.      * similarly, clones of named monsters don't have room for the name,
  55.      * so we just make the clone unnamed instead of bothering to create
  56.      * a clone with room and copying over the name from the right place
  57.      * (which changes if the original was a shopkeeper or guard).
  58.      */
  59.     if (mon->isshk) m2->isshk = FALSE;
  60.     if (mon->isgd) m2->isgd = FALSE;
  61.     if (mon->ispriest) m2->ispriest = FALSE;
  62.     m2->mxlth = 0;
  63.     m2->mnamelth = 0;
  64.     place_monster(m2, m2->mx, m2->my);
  65.     newsym(m2->mx,m2->my);    /* display the new monster */
  66.     if (mon->mtame) {
  67.         struct monst *m3;
  68.  
  69.         /* because m2 is a copy of mon it is tame but not init'ed.
  70.          * however, tamedog will not re-tame a tame dog, so m2
  71.          * must be made non-tame to get initialized properly.
  72.          */
  73.         m2->mtame = 0;
  74.         if ((m3 = tamedog(m2, (struct obj *)0)) != 0)
  75.         m2 = m3;
  76.     }
  77.     return m2;
  78. }
  79.  
  80. boolean
  81. special_case(mtmp)
  82. /* Moved this code from attack() in order to     */
  83. /* avoid having to duplicate it in dokick.    */
  84. register struct monst *mtmp;
  85. {
  86.     char qbuf[QBUFSZ];
  87.  
  88.     if(mtmp->m_ap_type && !Protection_from_shape_changers
  89.                         && !sensemon(mtmp)) {
  90.         stumble_onto_mimic(mtmp);
  91.         mtmp->data->mflags3 &= ~M3_WAITMASK;
  92.         return(1);
  93.     }
  94.  
  95.     if(mtmp->mundetected && hides_under(mtmp->data) && !canseemon(mtmp)) {
  96.         mtmp->mundetected = 0;
  97.         if (!(Blind ? Telepat : (HTelepat & (W_ARMH|W_AMUL|W_ART)))) {
  98.             register struct obj *obj;
  99.  
  100.             if(Blind)
  101.                 pline("Wait!  There's a hidden monster there!");
  102.             else if ((obj = level.objects[mtmp->mx][mtmp->my]) != 0)
  103.                 pline("Wait!  There's %s hiding under %s!",
  104.                     an(l_monnam(mtmp)), doname(obj));
  105.             mtmp->msleep = 0;
  106.             mtmp->data->mflags3 &= ~M3_WAITMASK;
  107.             return(TRUE);
  108.         }
  109.     }
  110.  
  111.     if (flags.confirm && mtmp->mpeaceful
  112.         && !Confusion && !Hallucination && !Stunned) {
  113.         /* Intelligent chaotic weapons (Stormbringer) want blood */
  114.         if (uwep && uwep->oartifact == ART_STORMBRINGER)
  115.             return(FALSE);
  116.  
  117.         if (canspotmon(mtmp)) {
  118.             Sprintf(qbuf, "Really attack %s?", mon_nam(mtmp));
  119.             if (yn(qbuf) != 'y') {
  120.                 flags.move = 0;
  121.                 mtmp->data->mflags3 &= ~M3_WAITMASK;
  122.                 return(TRUE);
  123.             }
  124.         }
  125.     }
  126.  
  127.     return(FALSE);
  128. }
  129.  
  130. schar
  131. find_roll_to_hit(mtmp)
  132. register struct monst *mtmp;
  133. {
  134.     schar tmp;
  135.     int tmp2;
  136.     struct permonst *mdat = mtmp->data;
  137.  
  138.     tmp = 1 + Luck + abon() +
  139.         find_mac(mtmp) +
  140. #ifdef POLYSELF
  141.         ((u.umonnum >= 0) ? uasmon->mlevel : u.ulevel);
  142. #else
  143.         u.ulevel;
  144. #endif
  145.  
  146. /*    it is unchivalrous to attack the defenseless or from behind */
  147.     if (pl_character[0] == 'K' && u.ualign.type == A_LAWFUL &&
  148.         (!mtmp->mcanmove || mtmp->msleep || mtmp->mflee) &&
  149.         u.ualign.record > -10) adjalign(-1);
  150.  
  151. /*    attacking peaceful creatures is bad for the samurai's giri */
  152.     if (pl_character[0] == 'S' && mtmp->mpeaceful &&
  153.         u.ualign.record > -10) adjalign(-1);
  154.  
  155. /*    Adjust vs. (and possibly modify) monster state.        */
  156.  
  157.     if(mtmp->mstun) tmp += 2;
  158.     if(mtmp->mflee) tmp += 2;
  159.  
  160.     if(mtmp->msleep) {
  161.         mtmp->msleep = 0;
  162.         tmp += 2;
  163.     }
  164.     if(!mtmp->mcanmove) {
  165.         tmp += 4;
  166.         if(!rn2(10)) {
  167.             mtmp->mcanmove = 1;
  168.             mtmp->mfrozen = 0;
  169.         }
  170.     }
  171.     if (is_orc(mtmp->data) && pl_character[0]=='E') tmp++;
  172.  
  173. /*    with a lot of luggage, your agility diminishes */
  174.     if ((tmp2 = near_capacity()) != 0) tmp -= (tmp2*2) - 1;
  175.     if(u.utrap) tmp -= 3;
  176. #ifdef POLYSELF
  177. /*    Some monsters have a combination of weapon attacks and non-weapon
  178.  *    attacks.  It is therefore wrong to add hitval to tmp; we must add it
  179.  *    only for the specific attack (in hmonas()).
  180.  */
  181.     if(uwep && u.umonnum == -1) tmp += hitval(uwep, mdat);
  182. #else
  183.     if(uwep) tmp += hitval(uwep, mdat);
  184. #endif
  185.     return tmp;
  186. }
  187.  
  188. /* try to attack; return FALSE if monster evaded */
  189. /* u.dx and u.dy must be set */
  190. boolean
  191. attack(mtmp)
  192. register struct monst *mtmp;
  193. {
  194.     schar tmp;
  195.     register struct permonst *mdat = mtmp->data;
  196.  
  197.     /* This section of code provides protection against accidentally
  198.      * hitting peaceful (like '@') and tame (like 'd') monsters.
  199.      * Protection is provided as long as player is not: blind, confused,
  200.      * hallucinating or stunned.
  201.      * changes by wwp 5/16/85
  202.      * More changes 12/90, -dkh-. if its tame and safepet, (and protected
  203.      * 07/92) then we assume that you're not trying to attack. Instead,
  204.      * you'll usually just swap places if this is a movement command
  205.      */
  206.     /* Intelligent chaotic weapons (Stormbringer) want blood */
  207.     if (is_safepet(mtmp) &&
  208.         (!uwep || uwep->oartifact != ART_STORMBRINGER)) {
  209.         /* there are some additional considerations: this won't work
  210.          * if in a shop or Punished or you miss a random roll or
  211.          * if you can walk thru walls and your pet cannot (KAA) or
  212.          * if your pet is a long worm (unless someone does better).
  213.          * there's also a chance of displacing a "frozen" monster.
  214.          * sleeping monsters might magically walk in their sleep.
  215.          */
  216.         unsigned int foo = (Punished ||
  217.                     !rn2(7) || is_longworm(mtmp->data));
  218.  
  219.         if (*in_rooms(mtmp->mx, mtmp->my, SHOPBASE) || foo
  220. #ifdef POLYSELF
  221.             || (IS_ROCK(levl[u.ux][u.uy].typ) &&
  222.                     !passes_walls(mtmp->data))
  223. #endif
  224.             ) {
  225.             mtmp->mflee = 1;
  226.             mtmp->mfleetim = rnd(6);
  227.             You("stop.  %s is in your way!",
  228.             (mtmp->mnamelth ? NAME(mtmp) : Monnam(mtmp)));
  229.             return(TRUE);
  230.         } else if ((mtmp->mfrozen || (! mtmp->mcanmove)
  231.                 || (mtmp->data->mmove == 0)) && rn2(6)) {
  232.             pline("%s doesn't seem to move!", Monnam(mtmp));
  233.             return(TRUE);
  234.         } else return(FALSE);
  235.     }
  236.  
  237.     /* moved code to a separate function to share with dokick */
  238.     if(special_case(mtmp)) return(TRUE);
  239.  
  240. #ifdef POLYSELF
  241.     if(u.umonnum >= 0) {    /* certain "pacifist" monsters don't attack */
  242.         set_uasmon();
  243.         if(noattacks(uasmon)) {
  244.             You("have no way to attack monsters physically.");
  245.             mtmp->data->mflags3 &= ~M3_WAITMASK;
  246.             return(TRUE);
  247.         }
  248.     }
  249. #endif
  250.  
  251.     if(check_capacity("You cannot fight while so heavily loaded."))
  252.         return (TRUE);
  253.  
  254.     if(unweapon) {
  255.         unweapon=FALSE;
  256.         if(flags.verbose)
  257.         if(uwep)
  258.             You("begin bashing monsters with your %s.",
  259.             aobjnam(uwep, NULL));
  260.         else
  261. #ifdef POLYSELF
  262.             if (!cantwield(uasmon))
  263. #endif
  264.             You("begin bashing monsters with your %s hands.",
  265.             uarmg ? "gloved" : "bare");        /* Del Lamb */
  266.     }
  267.     exercise(A_STR, TRUE);        /* you're exercising muscles */
  268.     /* andrew@orca: prevent unlimited pick-axe attacks */
  269.     u_wipe_engr(3);
  270.  
  271.     if(mdat->mlet == S_LEPRECHAUN && mtmp->mfrozen && !mtmp->msleep &&
  272.        !mtmp->mconf && mtmp->mcansee && !rn2(7) &&
  273.        (m_move(mtmp, 0) == 2 ||                /* it died */
  274.        mtmp->mx != u.ux+u.dx || mtmp->my != u.uy+u.dy)) /* it moved */
  275.         return(FALSE);
  276.  
  277.     tmp = find_roll_to_hit(mtmp);
  278. #ifdef POLYSELF
  279.     if (u.umonnum >= 0) (void) hmonas(mtmp, tmp);
  280.     else
  281. #endif
  282.         (void) hitum(mtmp, tmp);
  283.  
  284.     mtmp->data->mflags3 &= ~M3_WAITMASK;
  285.     return(TRUE);
  286. }
  287.  
  288. static boolean
  289. known_hitum(mon, mhit)    /* returns TRUE if monster still lives */
  290. /* Made into a separate function because in some cases we want to know
  291.  * in the calling function whether we hit.
  292.  */
  293. register struct monst *mon;
  294. register int mhit;
  295. {
  296.     register boolean malive = TRUE, special;
  297.  
  298.     /* we need to know whether the special monster was peaceful */
  299.     /* before the attack, to save idle calls to angry_guards()  */
  300.     special = (mon->mpeaceful && (mon->data == &mons[PM_WATCHMAN] ||
  301.                 mon->data == &mons[PM_WATCH_CAPTAIN] ||
  302.                       mon->ispriest || mon->isshk));
  303.  
  304.     if(!mhit) {
  305.         if(flags.verbose) You("miss %s.", mon_nam(mon));
  306.         else            You("miss it.");
  307.         if(!mon->msleep && mon->mcanmove)
  308.         wakeup(mon);
  309. #ifdef MUSE
  310.         else if (uwep && uwep->otyp == TSURUGI &&
  311.              MON_WEP(mon) && !rn2(20)) {
  312.         /* 1/20 chance of shattering defender's weapon */
  313.         struct obj *obj = MON_WEP(mon);
  314.  
  315.         obj->owornmask &= ~W_WEP;
  316.         MON_NOWEP(mon);
  317.         m_useup(mon, obj);
  318.         pline("%s weapon shatters!", s_suffix(Monnam(mon)));
  319.         /* perhaps this will freak out the monster */
  320.         if (!rn2(3)) {
  321.             mon->mflee = 1;
  322.             mon->mfleetim += rnd(20);
  323.         }
  324.         }
  325. #endif
  326.     } else {
  327.         int oldhp = mon->mhp;
  328.  
  329.         /* we hit the monster; be careful: it might die! */
  330.         notonhead = (mon->mx != u.ux+u.dx || mon->my != u.uy+u.dy);
  331.         if((malive = hmon(mon, uwep, 0)) == TRUE) {
  332.         /* monster still alive */
  333.         if(!rn2(25) && mon->mhp < mon->mhpmax/2) {
  334.             mon->mflee = 1;
  335.             if(!rn2(3)) mon->mfleetim = rnd(100);
  336.             if(u.ustuck == mon && !u.uswallow
  337. #ifdef POLYSELF
  338.                         && !sticks(uasmon)
  339. #endif
  340.                                 )
  341.                 u.ustuck = 0;
  342.         }
  343.         /* If no damage was done (Vorpal Blade and not on head)
  344.          * do not cut the worm.  We lost the information long ago, so
  345.          * we must do this by checking the hit points.
  346.          */
  347.         if (mon->wormno && mon->mhp < oldhp)
  348.             cutworm(mon, u.ux+u.dx, u.uy+u.dy, uwep);
  349.         }
  350.         if(mon->ispriest && !rn2(2)) ghod_hitsu(mon);
  351.         if(special) (void) angry_guards(!flags.soundok);
  352.     }
  353.     return(malive);
  354. }
  355.  
  356. static boolean
  357. hitum(mon, tmp)        /* returns TRUE if monster still lives */
  358. struct monst *mon;
  359. int tmp;
  360. {
  361.     static NEARDATA boolean malive;
  362.     boolean mhit = (tmp > (dieroll = rnd(20)) || u.uswallow);
  363.  
  364.     if(tmp > dieroll) exercise(A_DEX, TRUE);
  365.     malive = known_hitum(mon, mhit);
  366.     (void) passive(mon, mhit, malive, FALSE);
  367.     return(malive);
  368. }
  369.  
  370. boolean            /* general "damage monster" routine */
  371. hmon(mon, obj, thrown)        /* return TRUE if mon still alive */
  372. register struct monst *mon;
  373. register struct obj *obj;
  374. register int thrown;
  375. {
  376.     int tmp;
  377.     struct permonst *mdat = mon->data;
  378.     /* Why all these booleans?  This stuff has to be done in the
  379.      *      following order:
  380.      * 1) Know what we're attacking with, and print special hittxt for
  381.      *    unusual cases.
  382.      * 2a) Know whether we did damage (depends on 1)
  383.      * 2b) Know if it's poisoned (depends on 1)
  384.      * 2c) Know whether we get a normal damage bonus or not (depends on 1)
  385.      * 3a) Know what the value of the damage bonus is (depends on 2c)
  386.      * 3b) Know how much poison damage was taken (depends on 2b) and if the
  387.      *    poison instant-killed it
  388.      * 4) Know if it was killed (requires knowing 3a, 3b) except by instant-
  389.      *    kill poison
  390.      * 5) Print hit message (depends on 1 and 4)
  391.      * 6a) Print poison message (must be done after 5)
  392. #if 0
  393.      * 6b) Rust weapon (must be done after 5)
  394. #endif
  395.      * 7) Possibly kill monster (must be done after 6a, 6b)
  396.      * 8) Instant-kill from poison (can happen anywhere between 5 and 9)
  397.      * 9) Hands not glowing (must be done after 7 and 8)
  398.      * The major problem is that since we don't want a "hit" message
  399.      * when the monster dies, we have to know how much damage it did
  400.      * _before_ outputting a hit message, but any messages associated with
  401.      * the damage don't come out until _after_ outputting a hit message.
  402.      */
  403.     boolean hittxt = FALSE, destroyed = FALSE;
  404.     boolean get_dmg_bonus = TRUE;
  405.     boolean ispoisoned = FALSE, needpoismsg = FALSE, poiskilled = FALSE;
  406.     boolean silvermsg = FALSE;
  407.  
  408.     wakeup(mon);
  409.     if(!obj) {    /* attack with bare hands */
  410.         if (mdat == &mons[PM_SHADE])
  411.         tmp = 0;
  412.         else
  413.         tmp = rnd(2);
  414. #if 0
  415.         if(mdat == &mons[PM_COCKATRICE] && !uarmg
  416. #ifdef POLYSELF
  417.         && !resists_ston(uasmon)
  418. #endif
  419.         ) {
  420.  
  421.         You("hit %s with your bare %s.",
  422.             mon_nam(mon), makeplural(body_part(HAND)));
  423. # ifdef POLYSELF
  424.         if(poly_when_stoned(uasmon) && polymon(PM_STONE_GOLEM))
  425.             return TRUE;
  426. # endif
  427.         You("turn to stone...");
  428.         done_in_by(mon);
  429.         hittxt = TRUE; /* maybe lifesaved */
  430.         }
  431. #endif
  432.     } else {
  433.         if(obj->oclass == WEAPON_CLASS || obj->otyp == PICK_AXE ||
  434.            obj->otyp == UNICORN_HORN || obj->oclass == ROCK_CLASS) {
  435.  
  436.         /* If not a melee weapon, and either not thrown, or thrown */
  437.         /* and a bow (bows are >= BOW), or thrown and a missile */
  438.         /* without a propellor (which means <DART), do 1-2 points */
  439.         if((obj->otyp >= BOW || obj->otyp < BOOMERANG)
  440.             && obj->otyp != PICK_AXE && obj->otyp != UNICORN_HORN
  441.             && (!thrown ||
  442.                 (obj->oclass != ROCK_CLASS &&
  443.                 (obj->otyp >= BOW ||
  444.                 (obj->otyp < DART &&
  445.                     (!uwep ||
  446.                     objects[obj->otyp].w_propellor !=
  447.                     -objects[uwep->otyp].w_propellor)
  448.                 ))))) {
  449.             if (mdat == &mons[PM_SHADE] && obj->otyp != SILVER_ARROW)
  450.             tmp = 0;
  451.             else
  452.             tmp = rnd(2);
  453.         } else {
  454.             tmp = dmgval(obj, mdat);
  455.             if (obj->oartifact &&
  456.             artifact_hit(&youmonst, mon, obj, &tmp, dieroll)) {
  457.             if(mon->mhp <= 0) /* artifact killed monster */
  458.                 return FALSE;
  459.             if (tmp == 0) return TRUE;
  460.             hittxt = TRUE;
  461.             }
  462.             if (objects[obj->otyp].oc_material == SILVER
  463.                 && hates_silver(mdat))
  464.             silvermsg = TRUE;
  465.             if(!thrown && obj == uwep && obj->otyp == BOOMERANG &&
  466.                !rnl(3)) {
  467.             pline("As you hit %s, %s breaks into splinters.",
  468.                   mon_nam(mon), the(xname(obj)));
  469.             useup(obj);
  470.             obj = (struct obj *) 0;
  471.             hittxt = TRUE;
  472.             if (mdat != &mons[PM_SHADE])
  473.                 tmp++;
  474.             } else if(thrown &&
  475.                   (obj->otyp >= ARROW && obj->otyp <= SHURIKEN)) {
  476.             if(uwep && obj->otyp < DART &&
  477.                objects[obj->otyp].w_propellor ==
  478.                -objects[uwep->otyp].w_propellor) {
  479.                 /* Elves and Samurai do extra damage using
  480.                  * their bows&arrows; they're highly trained.
  481.                  */
  482.                 if (pl_character[0] == 'S' &&
  483.                 obj->otyp == YA && uwep->otyp == YUMI)
  484.                 tmp++;
  485.                 else if (pl_character[0] == 'E' &&
  486.                      obj->otyp == ELVEN_ARROW &&
  487.                      uwep->otyp == ELVEN_BOW)
  488.                 tmp++;
  489.             }
  490.             if(((uwep && objects[obj->otyp].w_propellor ==
  491.                 -objects[uwep->otyp].w_propellor)
  492.                 || obj->otyp==DART || obj->otyp==SHURIKEN) &&
  493.                 obj->opoisoned)
  494.                 ispoisoned = TRUE;
  495.             }
  496.         }
  497.         } else if(obj->oclass == POTION_CLASS) {
  498.             if (obj->quan > 1L) setuwep(splitobj(obj, 1L));
  499.             else setuwep((struct obj *)0);
  500.             freeinv(obj);
  501.             potionhit(mon,obj);
  502.             hittxt = TRUE;
  503.             if (mdat == &mons[PM_SHADE])
  504.                 tmp = 0;
  505.             else
  506.                 tmp = 1;
  507.         } else {
  508.         switch(obj->otyp) {
  509.             case HEAVY_IRON_BALL:
  510.             tmp = rnd(25); break;
  511.             case BOULDER:
  512.             tmp = rnd(20); break;
  513.             case MIRROR:
  514.             You("break your mirror.  That's bad luck!");
  515.             change_luck(-2);
  516.             useup(obj);
  517.             obj = (struct obj *) 0;
  518.             hittxt = TRUE;
  519.             tmp = 1;
  520.             break;
  521. #ifdef TOURIST
  522.             case EXPENSIVE_CAMERA:
  523.     You("succeed in destroying your camera.  Congratulations!");
  524.             useup(obj);
  525.             return(TRUE);
  526. #endif
  527.             case CORPSE:        /* fixed by polder@cs.vu.nl */
  528.             if(obj->corpsenm == PM_COCKATRICE) {
  529.                 You("hit %s with the cockatrice corpse.",
  530.                   mon_nam(mon));
  531.                 if(resists_ston(mdat)) {
  532.                 tmp = 1;
  533.                 hittxt = TRUE;
  534.                 break;
  535.                 }
  536.                 if(poly_when_stoned(mdat)) {
  537.                 mon_to_stone(mon);
  538.                 tmp = 1;
  539.                 hittxt = TRUE;
  540.                 break;
  541.                 }
  542.                 pline("%s turns to stone.", Monnam(mon));
  543.                 stoned = TRUE;
  544.                 xkilled(mon,0);
  545.                 return(FALSE);
  546.             }
  547.             tmp = mons[obj->corpsenm].msize + 1;
  548.             break;
  549.             case EGG: /* only possible if hand-to-hand */
  550.             if(obj->corpsenm > -1
  551.                     && obj->corpsenm != PM_COCKATRICE
  552.                     && mdat == &mons[PM_COCKATRICE]) {
  553.                 You("hit %s with the %s egg%s.",
  554.                     mon_nam(mon),
  555.                     mons[obj->corpsenm].mname,
  556.                     plur(obj->quan));
  557.                 hittxt = TRUE;
  558.                 pline("The egg%sn't live any more...",
  559.                     (obj->quan == 1L) ? " is" : "s are");
  560.                 obj->otyp = ROCK;
  561.                 obj->oclass = GEM_CLASS;
  562.                 obj->known = obj->dknown = 0;
  563.                 obj->owt = weight(obj);
  564.             }
  565.             tmp = 1;
  566.             break;
  567.             case CLOVE_OF_GARLIC:    /* no effect against demons */
  568.             if(is_undead(mdat)) mon->mflee = 1;
  569.             tmp = 1;
  570.             break;
  571.             case CREAM_PIE:
  572. #ifdef POLYSELF
  573.             case BLINDING_VENOM:
  574.             if(Blind || !haseyes(mon->data))
  575.                 pline(obj->otyp==CREAM_PIE ? "Splat!" : "Splash!");
  576.             else if (obj->otyp == BLINDING_VENOM)
  577.                 pline("The venom blinds %s%s!", mon_nam(mon),
  578.                     mon->mcansee ? "" : " further");
  579. #else
  580.             if(Blind) pline("Splat!");
  581. #endif
  582.             else
  583.                 pline("The cream pie splashes over %s%s!",
  584.                 mon_nam(mon),
  585.                 (haseyes(mdat) &&
  586.                     mdat != &mons[PM_FLOATING_EYE])
  587.                 ? (*(eos(mon_nam(mon))-1) == 's' ? "' face" :
  588.                      "'s face") : "");
  589.             if(mon->msleep) mon->msleep = 0;
  590.             setmangry(mon);
  591.             if(haseyes(mon->data)) {
  592.                 mon->mcansee = 0;
  593.                 tmp = rn1(25, 21);
  594.                 if(((int) mon->mblinded + tmp) > 127)
  595.                 mon->mblinded = 127;
  596.                 else mon->mblinded += tmp;
  597.             }
  598.             hittxt = TRUE;
  599.             get_dmg_bonus = FALSE;
  600.             tmp = 0;
  601.             break;
  602. #ifdef POLYSELF
  603.             case ACID_VENOM: /* only possible if thrown */
  604.             if(resists_acid(mdat)) {
  605.                 Your("venom hits %s harmlessly.",
  606.                     mon_nam(mon));
  607.                 tmp = 0;
  608.             } else {
  609.                 Your("venom burns %s!", mon_nam(mon));
  610.                 tmp = dmgval(obj, mdat);
  611.             }
  612.             hittxt = TRUE;
  613.             get_dmg_bonus = FALSE;
  614.             break;
  615. #endif
  616.             default:
  617.             /* non-weapons can damage because of their weight */
  618.             /* (but not too much) */
  619.             tmp = obj->owt/100;
  620.             if(tmp < 1) tmp = 1;
  621.             else tmp = rnd(tmp);
  622.             if(tmp > 6) tmp = 6;
  623.         }
  624.         if (mdat == &mons[PM_SHADE] && obj &&
  625.                 objects[obj->otyp].oc_material != SILVER)
  626.             tmp = 0;
  627.         }
  628.     }
  629.  
  630.     /****** NOTE: perhaps obj is undefined!! (if !thrown && BOOMERANG)
  631.      *      *OR* if attacking bare-handed!! */
  632.  
  633.     if (get_dmg_bonus && tmp) {
  634.         tmp += u.udaminc;
  635.         /* If you throw using a propellor, you don't get a strength
  636.          * bonus but you do get an increase-damage bonus.
  637.          */
  638.         if(!thrown || !obj || !uwep ||
  639.            (obj->oclass != GEM_CLASS && obj->oclass != WEAPON_CLASS) ||
  640.            !objects[obj->otyp].w_propellor ||
  641.            (objects[obj->otyp].w_propellor !=
  642.                 -objects[uwep->otyp].w_propellor))
  643.             tmp += dbon();
  644.     }
  645.  
  646. /* TODO:    Fix this up.  multiple engulf attacks now exist.
  647.     if(u.uswallow) {
  648.         if((tmp -= u.uswldtim) <= 0) {
  649.         Your("%s are no longer able to hit.",
  650.             makeplural(body_part(ARM)));
  651.         return(TRUE);
  652.         }
  653.     }
  654.  */
  655.     if (ispoisoned) {
  656.         if(resists_poison(mdat))
  657.         needpoismsg = TRUE;
  658.         else if (rn2(10))
  659.         tmp += rnd(6);
  660.         else poiskilled = TRUE;
  661.     }
  662.     if(tmp < 1)
  663.         if (mdat == &mons[PM_SHADE]) {
  664.         Your("attack passes harmlessly through %s.",
  665.             mon_nam(mon));
  666.         hittxt = TRUE;
  667.         } else
  668.         tmp = 1;
  669.  
  670.     mon->mhp -= tmp;
  671.     if(mon->mhp < 1)
  672.         destroyed = TRUE;
  673.     if(mon->mtame && (!mon->mflee || mon->mfleetim)) {
  674.         abuse_dog(mon);
  675.         mon->mflee = TRUE;        /* Rick Richardson */
  676.         mon->mfleetim += 10*rnd(tmp);
  677.     }
  678.     if((mdat == &mons[PM_BLACK_PUDDING] || mdat == &mons[PM_BROWN_PUDDING])
  679.            && obj && obj == uwep
  680.            && objects[obj->otyp].oc_material == IRON
  681.            && mon->mhp > 1 && !thrown && !mon->mcan
  682.            /* && !destroyed  -- guaranteed by mhp > 1 */ ) {
  683.  
  684.         if (clone_mon(mon)) {
  685.             pline("%s divides as you hit it!", Monnam(mon));
  686.             hittxt = TRUE;
  687.         }
  688.     }
  689.  
  690.     if(!hittxt && !destroyed) {
  691.         if(thrown)
  692.             /* thrown => obj exists */
  693.             hit(xname(obj), mon, exclam(tmp) );
  694.         else if(!flags.verbose) You("hit it.");
  695.         else    You("hit %s%s", mon_nam(mon), canseemon(mon)
  696.             ? exclam(tmp) : ".");
  697.     }
  698.  
  699.     if (silvermsg) {
  700.         if (canseemon(mon) || sensemon(mon))
  701.             pline("The silver sears %s%s!",
  702.                 mon_nam(mon),
  703.                 noncorporeal(mdat) ? "" : 
  704.                       (*(eos(mon_nam(mon))-1) == 's' ?
  705.                        "' flesh" : "'s flesh"));
  706.         else
  707.             pline("It%s is seared!",
  708.                 noncorporeal(mdat) ? "" : "s flesh");
  709.     }
  710.  
  711.     if (needpoismsg)
  712.         pline("The poison doesn't seem to affect %s.", mon_nam(mon));
  713.     if (poiskilled) {
  714.         pline("The poison was deadly...");
  715.         xkilled(mon, 0);
  716.         return FALSE;
  717.     } else if (destroyed) {
  718.         killed(mon);    /* takes care of most messages */
  719.     } else if(u.umconf && !thrown) {
  720.         nohandglow(mon);
  721.         if(!mon->mconf && !resist(mon, '+', 0, NOTELL)) {
  722.             mon->mconf = 1;
  723.             if(!mon->mstun && mon->mcanmove && !mon->msleep &&
  724.                !Blind)
  725.                 pline("%s appears confused.", Monnam(mon));
  726.         }
  727.     }
  728.  
  729. #if 0
  730.     if(mdat == &mons[PM_RUST_MONSTER] && obj && obj == uwep &&
  731.         is_rustprone(obj) && obj->oeroded < MAX_ERODE) {
  732.         if (obj->greased)
  733.         grease_protect(obj,NULL,FALSE);
  734.         else if (obj->oerodeproof || (obj->blessed && !rnl(4))) {
  735.             if (flags.verbose)
  736.             pline("Somehow, your %s is not affected.",
  737.                   is_sword(obj) ? "sword" : "weapon");
  738.         } else {
  739.         Your("%s%s!", aobjnam(obj, "rust"),
  740.              obj->oeroded+1 == MAX_ERODE ? " completely" :
  741.              obj->oeroded ? " further" : "");
  742.         obj->oeroded++;
  743.         }
  744.     }
  745. #endif
  746.  
  747.     return((boolean)(destroyed ? FALSE : TRUE));
  748. }
  749.  
  750. #ifdef POLYSELF
  751.  
  752. int
  753. damageum(mdef, mattk)
  754. register struct monst *mdef;
  755. register struct attack *mattk;
  756. {
  757.     register struct permonst *pd = mdef->data;
  758.     register int    tmp = d((int)mattk->damn, (int)mattk->damd);
  759.  
  760.     if (is_demon(uasmon) && !rn2(13) && !uwep
  761.         && u.umonnum != PM_SUCCUBUS && u.umonnum != PM_INCUBUS
  762.         && u.umonnum != PM_BALROG) {
  763.         struct monst *dtmp;
  764.         pline("Some hell-p has arrived!");
  765.         if((dtmp = makemon(!rn2(6) ? &mons[ndemon(u.ualign.type)] :
  766.                      uasmon, u.ux, u.uy)))
  767.         (void)tamedog(dtmp, (struct obj *)0);
  768.         exercise(A_WIS, TRUE);
  769.         return(0);
  770.     }
  771.  
  772.     switch(mattk->adtyp) {
  773.         case AD_STUN:
  774.         if(!Blind)
  775.             pline("%s staggers for a moment.", Monnam(mdef));
  776.         mdef->mstun = 1;
  777.         /* fall through to next case */
  778.         case AD_WERE:        /* no effect on monsters */
  779.         case AD_HEAL:
  780.         case AD_LEGS:
  781.         case AD_PHYS:
  782.         if(mattk->aatyp == AT_WEAP) {
  783.             if(uwep) tmp = 0;
  784.         } else if(mattk->aatyp == AT_KICK)
  785.             if(thick_skinned(mdef->data)) tmp = 0;
  786.         break;
  787.         case AD_FIRE:
  788.         if(!Blind) pline("%s is on fire!", Monnam(mdef));
  789.         tmp += destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE);
  790.         tmp += destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE);
  791.         if(resists_fire(pd)) {
  792.             if (!Blind)
  793.             pline("The fire doesn't heat %s!", mon_nam(mdef));
  794.             golemeffects(mdef, AD_FIRE, tmp);
  795.             shieldeff(mdef->mx, mdef->my);
  796.             tmp = 0;
  797.         }
  798.         /* only potions damage resistant players in destroy_item */
  799.         tmp += destroy_mitem(mdef, POTION_CLASS, AD_FIRE);
  800.         break;
  801.         case AD_COLD:
  802.         if(!Blind) pline("%s is covered in frost!", Monnam(mdef));
  803.         if(resists_cold(pd)) {
  804.             shieldeff(mdef->mx, mdef->my);
  805.             if (!Blind)
  806.             pline("The frost doesn't chill %s!", mon_nam(mdef));
  807.             golemeffects(mdef, AD_COLD, tmp);
  808.             tmp = 0;
  809.         }
  810.         tmp += destroy_mitem(mdef, POTION_CLASS, AD_COLD);
  811.         break;
  812.         case AD_ELEC:
  813.         if (!Blind) pline("%s is zapped!", Monnam(mdef));
  814.         tmp += destroy_mitem(mdef, WAND_CLASS, AD_ELEC);
  815.         if(resists_elec(pd)) {
  816.             if (!Blind)
  817.             pline("The zap doesn't shock %s!", mon_nam(mdef));
  818.             golemeffects(mdef, AD_ELEC, tmp);
  819.             shieldeff(mdef->mx, mdef->my);
  820.             tmp = 0;
  821.         }
  822.         /* only rings damage resistant players in destroy_item */
  823.         tmp += destroy_mitem(mdef, RING_CLASS, AD_ELEC);
  824.         break;
  825.         case AD_ACID:
  826.         if(resists_acid(pd)) tmp = 0;
  827.         break;
  828.         case AD_STON:
  829.         if(poly_when_stoned(pd))
  830.            mon_to_stone(mdef);
  831.         else if(!resists_ston(pd)) {
  832.             stoned = TRUE;
  833.             if(!Blind) pline("%s turns to stone.", Monnam(mdef));
  834.             xkilled(mdef, 0);
  835.             return(2);
  836.         }
  837.         tmp = 0;    /* no damage if this fails */
  838.         break;
  839. # ifdef SEDUCE
  840.         case AD_SSEX:
  841. # endif
  842.         case AD_SEDU:
  843.         case AD_SITM:
  844.         if(mdef->minvent) {
  845.             struct obj *otmp, *stealoid;
  846.  
  847.             stealoid = (struct obj *)0;
  848.         /* Without MUSE we can only change a monster's AC by stealing
  849.          * armor with the "unarmored soldier" kludge.  With it there
  850.          * are many monsters which wear armor, and all can be stripped.
  851.          */
  852.             if(
  853. #ifndef MUSE
  854.             is_mercenary(pd) &&
  855. #endif
  856.                     could_seduce(&youmonst,mdef,mattk)){
  857.             for(otmp = mdef->minvent; otmp; otmp=otmp->nobj)
  858. #ifdef MUSE
  859.                 if (otmp->owornmask & W_ARM) stealoid = otmp;
  860. #else
  861.                 if (otmp->otyp >= PLATE_MAIL && otmp->otyp
  862.                 <= ELVEN_CLOAK) stealoid = otmp;
  863. #endif
  864.             }
  865.             if (stealoid) {
  866.             boolean stolen = FALSE;
  867.             if (gender(mdef) == u.mfemale &&
  868.                         uasmon->mlet == S_NYMPH)
  869.     You("charm %s.  She gladly hands over her possessions.", mon_nam(mdef));
  870.             else
  871.             You("seduce %s and %s starts to take off %s clothes.",
  872.                 mon_nam(mdef), he[pronoun_gender(mdef)],
  873.                 his[pronoun_gender(mdef)]);
  874.             while(mdef->minvent) {
  875.                 otmp = mdef->minvent;
  876.                 mdef->minvent = otmp->nobj;
  877.                 /* set dknown to insure proper merge */
  878.                 if (!Blind) otmp->dknown = 1;
  879. #ifdef MUSE
  880.                 otmp->owornmask = 0L;
  881. #endif
  882.                 if (!stolen && otmp==stealoid) {
  883.                     otmp = hold_another_object(otmp,
  884.                           (const char *)0, (const char *)0,
  885.                                   (const char *)0);
  886.                     stealoid = otmp;
  887.                     stolen = TRUE;
  888.                 } else {
  889.                     otmp = hold_another_object(otmp,
  890.                          "You steal %s.", doname(otmp),
  891.                                 "You steal: ");
  892.                 }
  893.             }
  894.             if (!stolen)
  895.                 impossible("Player steal fails!");
  896.             else {
  897.                 pline("%s finishes taking off %s suit.",
  898.                       Monnam(mdef), his[pronoun_gender(mdef)]);
  899.                 You("steal %s!", doname(stealoid));
  900. # if defined(ARMY) && !defined(MUSE)
  901.                 mdef->data = &mons[PM_UNARMORED_SOLDIER];
  902. # endif
  903.             }
  904. #ifdef MUSE
  905.             possibly_unwield(mdef);
  906.             mdef->misc_worn_check = 0L;
  907. #endif
  908.            } else {
  909.             otmp = mdef->minvent;
  910.             mdef->minvent = otmp->nobj;
  911.             otmp = hold_another_object(otmp, "You steal %s.",
  912.                           doname(otmp), "You steal: ");
  913. #ifdef MUSE
  914.             possibly_unwield(mdef);
  915.             otmp->owornmask = 0L;
  916.             mselftouch(mdef, (const char *)0, TRUE);
  917.             if (mdef->mhp <= 0) {
  918.                 tmp = 1; /* avoid early return from damageum */
  919.                 break;
  920.             }
  921. #endif
  922.            }
  923.         }
  924.         tmp = 0;
  925.         break;
  926.         case AD_SGLD:
  927.         if (mdef->mgold) {
  928.             u.ugold += mdef->mgold;
  929.             mdef->mgold = 0;
  930.             Your("purse feels heavier.");
  931.         }
  932.         exercise(A_DEX, TRUE);
  933.         tmp = 0;
  934.         break;
  935.         case AD_TLPT:
  936.         if(tmp <= 0) tmp = 1;
  937.         if(tmp < mdef->mhp) {
  938.             rloc(mdef);
  939.             if(!Blind) pline("%s suddenly disappears!", Monnam(mdef));
  940.         }
  941.         break;
  942.         case AD_BLND:
  943.         if(haseyes(pd)) {
  944.  
  945.             if(!Blind) pline("%s is blinded.", Monnam(mdef));
  946.             mdef->mcansee = 0;
  947.             mdef->mblinded += tmp;
  948.         }
  949.         tmp = 0;
  950.         break;
  951.         case AD_CURS:
  952.         if (night() && !rn2(10) && !mdef->mcan) {
  953.             if (mdef->data == &mons[PM_CLAY_GOLEM]) {
  954.             if (!Blind)
  955.                 pline("Some writing vanishes from %s head!",
  956.                 s_suffix(mon_nam(mdef)));
  957.             xkilled(mdef, 0);
  958.             return 2;
  959.             }
  960.             mdef->mcan = 1;
  961.             You("chuckle.");
  962.         }
  963.         tmp = 0;
  964.         break;
  965.         case AD_DRLI:
  966.         if(rn2(2) && !resists_drli(pd)) {
  967.             int xtmp = d(2,6);
  968.             pline("%s suddenly seems weaker!", Monnam(mdef));
  969.             mdef->mhpmax -= xtmp;
  970.             if ((mdef->mhp -= xtmp) <= 0 || !mdef->m_lev) {
  971.                 pline("%s dies!", Monnam(mdef));
  972.                 xkilled(mdef,0);
  973.                 return(2);
  974.             }
  975.             mdef->m_lev--;
  976.         }
  977.         tmp = 0;
  978.         break;
  979.         case AD_RUST:
  980.         if (pd == &mons[PM_IRON_GOLEM]) {
  981.             pline("%s falls to pieces!", Monnam(mdef));
  982.             xkilled(mdef,0);
  983.             return(2);
  984.         }
  985.         tmp = 0;
  986.         break;
  987.         case AD_DCAY:
  988.         if (pd == &mons[PM_WOOD_GOLEM] ||
  989.             pd == &mons[PM_LEATHER_GOLEM]) {
  990.             pline("%s falls to pieces!", Monnam(mdef));
  991.             xkilled(mdef,0);
  992.             return(2);
  993.         }
  994.         case AD_DRST:
  995.         case AD_DRDX:
  996.         case AD_DRCO:
  997.         if (!rn2(8)) {
  998.             Your("%s was poisoned!", mattk->aatyp==AT_BITE ?
  999.             "bite" : "sting");
  1000.             if (resists_poison(mdef->data))
  1001.             pline("The poison doesn't seem to affect %s.",
  1002.                 mon_nam(mdef));
  1003.             else {
  1004.             if (!rn2(10)) {
  1005.                 Your("poison was deadly...");
  1006.                 tmp = mdef->mhp;
  1007.             } else tmp += rn1(10,6);
  1008.             }
  1009.         }
  1010.         break;
  1011.         case AD_DRIN:
  1012.         if (!has_head(mdef->data)) {
  1013.             pline("%s doesn't seem harmed.", Monnam(mdef));
  1014.             tmp = 0;
  1015.             break;
  1016.         }
  1017. #ifdef MUSE
  1018.         if ((mdef->misc_worn_check & W_ARMH) && rn2(8)) {
  1019.             pline("%s helmet blocks your attack to %s head.",
  1020.               s_suffix(Monnam(mdef)), his[pronoun_gender(mdef)]);
  1021.             break;
  1022.         }
  1023. #endif
  1024.         You("eat %s brain!", s_suffix(mon_nam(mdef)));
  1025.         if (mindless(mdef->data)) {
  1026.             pline("%s doesn't notice.", Monnam(mdef));
  1027.             break;
  1028.         }
  1029.         tmp += rnd(10);
  1030.         morehungry(-rnd(30)); /* cannot choke */
  1031.         if (ABASE(A_INT) < AMAX(A_INT)) {
  1032.             ABASE(A_INT) += rnd(4);
  1033.             if (ABASE(A_INT) > AMAX(A_INT))
  1034.                 ABASE(A_INT) = AMAX(A_INT);
  1035.             flags.botl = 1;
  1036.         }
  1037.         exercise(A_WIS, TRUE);
  1038.         break;
  1039.         case AD_WRAP:
  1040.         case AD_STCK:
  1041.         if (!sticks(mdef->data))
  1042.             u.ustuck = mdef; /* it's now stuck to you */
  1043.         break;
  1044.         case AD_PLYS:
  1045.         if (mdef->mcanmove && !rn2(3) && tmp < mdef->mhp) {
  1046.             if (!Blind) pline("%s is frozen by you!", Monnam(mdef));
  1047.             mdef->mcanmove = 0;
  1048.             mdef->mfrozen = rnd(10);
  1049.         }
  1050.         break;
  1051.         case AD_SLEE:
  1052.         if (!resists_sleep(mdef->data) && !mdef->msleep &&
  1053.                             mdef->mcanmove) {
  1054.             if (!Blind)
  1055.             pline("%s suddenly falls asleep!", Monnam(mdef));
  1056.             mdef->mcanmove = 0;
  1057.             mdef->mfrozen = rnd(10);
  1058.         }
  1059.         break;
  1060.         default:    tmp = 0;
  1061.             break;
  1062.     }
  1063.     if(!tmp) return(1);
  1064.  
  1065.     if((mdef->mhp -= tmp) < 1) {
  1066.  
  1067.         if (mdef->mtame && !cansee(mdef->mx,mdef->my)) {
  1068.         You("feel embarrassed for a moment.");
  1069.         xkilled(mdef, 0);
  1070.         } else if (!flags.verbose) {
  1071.         You("destroy it!");
  1072.         xkilled(mdef, 0);
  1073.         } else
  1074.         killed(mdef);
  1075.         return(2);
  1076.     }
  1077.     return(1);
  1078. }
  1079.  
  1080. static int
  1081. explum(mdef, mattk)
  1082. register struct monst *mdef;
  1083. register struct attack *mattk;
  1084. {
  1085.     register int tmp = d((int)mattk->damn, (int)mattk->damd);
  1086.  
  1087.     You("explode!");
  1088.     switch(mattk->adtyp) {
  1089.         case AD_BLND:
  1090.         if (haseyes(mdef->data)) {
  1091.             pline("%s is blinded by your flash of light!", Monnam(mdef));
  1092.             if (mdef->mcansee) {
  1093.             mdef->mblinded += tmp;
  1094.             mdef->mcansee = 0;
  1095.             }
  1096.         }
  1097.         break;
  1098.         case AD_COLD:
  1099.         if (!resists_cold(mdef->data)) {
  1100.             pline("%s gets blasted!", Monnam(mdef));
  1101.             mdef->mhp -= tmp;
  1102.             if (mdef->mhp <= 0) {
  1103.              killed(mdef);
  1104.              return(2);
  1105.             }
  1106.         } else {
  1107.             shieldeff(mdef->mx, mdef->my);
  1108.             if (is_golem(mdef->data))
  1109.             golemeffects(mdef, AD_COLD, tmp);
  1110.             else
  1111.             pline("The blast doesn't seem to affect %s.",
  1112.                 mon_nam(mdef));
  1113.         }
  1114.         break;
  1115.         default:
  1116.         break;
  1117.     }
  1118.     return(1);
  1119. }
  1120.  
  1121. static int
  1122. gulpum(mdef,mattk)
  1123. register struct monst *mdef;
  1124. register struct attack *mattk;
  1125. {
  1126.     register int tmp;
  1127.     register int dam = d((int)mattk->damn, (int)mattk->damd);
  1128.     /* Not totally the same as for real monsters.  Specifically, these
  1129.      * don't take multiple moves.  (It's just too hard, for too little
  1130.      * result, to program monsters which attack from inside you, which
  1131.      * would be necessary if done accurately.)  Instead, we arbitrarily
  1132.      * kill the monster immediately for AD_DGST and we regurgitate them
  1133.      * after exactly 1 round of attack otherwise.  -KAA
  1134.      */
  1135.  
  1136.     if(mdef->data->msize >= MZ_HUGE) return 0;
  1137.  
  1138.     if(u.uhunger < 1500 && !u.uswallow) {
  1139.  
  1140.         if(mdef->data->mlet != S_COCKATRICE) {
  1141. # ifdef LINT    /* static char msgbuf[BUFSZ]; */
  1142.         char msgbuf[BUFSZ];
  1143. # else
  1144.         static char msgbuf[BUFSZ];
  1145. # endif
  1146. /* TODO: get the symbol display also to work (monster symbol is removed from
  1147.  * the screen and you moved onto it, then you get moved back and it gets
  1148.  * moved back if the monster survives--just like when monsters swallow you.
  1149.  */
  1150.         You("engulf %s!", mon_nam(mdef));
  1151.         switch(mattk->adtyp) {
  1152.             case AD_DGST:
  1153.             u.uhunger += mdef->data->cnutrit;
  1154.             newuhs(FALSE);
  1155.             xkilled(mdef,2);
  1156.             Sprintf(msgbuf, "You totally digest %s.",
  1157.                     mon_nam(mdef));
  1158.             if ((tmp = 3 + (mdef->data->cwt >> 6)) != 0) {
  1159.                 You("digest %s.", mon_nam(mdef));
  1160.                 nomul(-tmp);
  1161.                 nomovemsg = msgbuf;
  1162.             } else pline(msgbuf);
  1163.             exercise(A_CON, TRUE);
  1164.             return(2);
  1165.             case AD_PHYS:
  1166.             pline("%s is pummeled with your debris!",Monnam(mdef));
  1167.             break;
  1168.             case AD_ACID:
  1169.             pline("%s is covered with your goo!", Monnam(mdef));
  1170.             if (resists_acid(mdef->data)) {
  1171.                 pline("It seems harmless to %s.", mon_nam(mdef));
  1172.                 dam = 0;
  1173.             }
  1174.             break;
  1175.             case AD_BLND:
  1176.             if(haseyes(mdef->data)) {
  1177.                 if (mdef->mcansee)
  1178.                 pline("%s can't see in there!", Monnam(mdef));
  1179.                 mdef->mcansee = 0;
  1180.                 dam += mdef->mblinded;
  1181.                 if (dam > 127) dam = 127;
  1182.                 mdef->mblinded = dam;
  1183.             }
  1184.             dam = 0;
  1185.             break;
  1186.             case AD_ELEC:
  1187.             if (rn2(2)) {
  1188.                 pline("The air around %s crackles with electricity.", mon_nam(mdef));
  1189.                 if (resists_elec(mdef->data)) {
  1190.                 pline("%s seems unhurt.", Monnam(mdef));
  1191.                 dam = 0;
  1192.                 }
  1193.                 golemeffects(mdef,(int)mattk->adtyp,dam);
  1194.             } else dam = 0;
  1195.             break;
  1196.             case AD_COLD:
  1197.             if (rn2(2)) {
  1198.                 if (resists_cold(mdef->data)) {
  1199.                 pline("%s seems mildly chilly.", Monnam(mdef));
  1200.                 dam = 0;
  1201.                 } else
  1202.                 pline("%s is freezing to death!",Monnam(mdef));
  1203.                 golemeffects(mdef,(int)mattk->adtyp,dam);
  1204.             } else dam = 0;
  1205.             break;
  1206.             case AD_FIRE:
  1207.             if (rn2(2)) {
  1208.                 if (resists_fire(mdef->data)) {
  1209.                 pline("%s seems mildly hot.", Monnam(mdef));
  1210.                 dam = 0;
  1211.                 } else
  1212.                 pline("%s is burning to a crisp!",Monnam(mdef));
  1213.                 golemeffects(mdef,(int)mattk->adtyp,dam);
  1214.             } else dam = 0;
  1215.             break;
  1216.         }
  1217.         if ((mdef->mhp -= dam) <= 0) {
  1218.             killed(mdef);
  1219.             return(2);
  1220.         }
  1221.         You("%s %s!", is_animal(uasmon) ? "regurgitate"
  1222.             : "expel", mon_nam(mdef));
  1223.         if (is_animal(uasmon)) {
  1224.             pline("Obviously, you didn't like %s taste.",
  1225.               s_suffix(mon_nam(mdef)));
  1226.         }
  1227.         } else {
  1228.         You("bite into %s", mon_nam(mdef));
  1229.         You("turn to stone...");
  1230.         killer_format = KILLED_BY;
  1231.         killer = "swallowing a cockatrice whole";
  1232.         done(STONING);
  1233.         }
  1234.     }
  1235.     return(0);
  1236. }
  1237.  
  1238. void
  1239. missum(mdef,mattk)
  1240. register struct monst *mdef;
  1241. register struct attack *mattk;
  1242. {
  1243.     if (could_seduce(&youmonst, mdef, mattk))
  1244.         You("pretend to be friendly to %s.", mon_nam(mdef));
  1245.     else if(!Blind && flags.verbose)
  1246.         You("miss %s.", mon_nam(mdef));
  1247.     else
  1248.         You("miss it.");
  1249.     wakeup(mdef);
  1250. }
  1251.  
  1252. static boolean
  1253. hmonas(mon, tmp)        /* attack monster as a monster. */
  1254. register struct monst *mon;
  1255. register int tmp;
  1256. {
  1257.     register struct attack *mattk;
  1258.     int    i, sum[NATTK];
  1259.     int    nsum = 0;
  1260.     schar    dhit;
  1261.  
  1262. #ifdef GCC_WARN
  1263.     dhit = 0;
  1264. #endif
  1265.  
  1266.     for(i = 0; i < NATTK; i++) {
  1267.  
  1268.         sum[i] = 0;
  1269.         mattk = &(uasmon->mattk[i]);
  1270.         switch(mattk->aatyp) {
  1271.         case AT_WEAP:
  1272. use_weapon:
  1273.     /* Certain monsters don't use weapons when encountered as enemies,
  1274.      * but players who polymorph into them have hands or claws and thus
  1275.      * should be able to use weapons.  This shouldn't prohibit the use
  1276.      * of most special abilities, either.
  1277.      */
  1278.     /* Potential problem: if the monster gets multiple weapon attacks,
  1279.      * we currently allow the player to get each of these as a weapon
  1280.      * attack.  Is this really desirable?
  1281.      */
  1282.             if(uwep) tmp += hitval(uwep, mon->data);
  1283.             dhit = (tmp > (dieroll = rnd(20)) || u.uswallow);
  1284.             /* Enemy dead, before any special abilities used */
  1285.             if (!known_hitum(mon,dhit)) return 0;
  1286.             /* might be a worm that gets cut in half */
  1287.             if (m_at(u.ux+u.dx, u.uy+u.dy) != mon) return((boolean)(nsum != 0));
  1288.             /* Do not print "You hit" message, since known_hitum
  1289.              * already did it.
  1290.              */
  1291.             if (dhit && mattk->adtyp != AD_SPEL
  1292.                 && mattk->adtyp != AD_PHYS)
  1293.                 sum[i] = damageum(mon,mattk);
  1294.             break;
  1295.         case AT_CLAW:
  1296.             if (i==0 && uwep && !cantwield(uasmon)) goto use_weapon;
  1297. # ifdef SEDUCE
  1298.             /* succubi/incubi are humanoid, but their _second_
  1299.              * attack is AT_CLAW, not their first...
  1300.              */
  1301.             if (i==1 && uwep && (u.umonnum == PM_SUCCUBUS ||
  1302.                 u.umonnum == PM_INCUBUS)) goto use_weapon;
  1303. # endif
  1304.         case AT_KICK:
  1305.         case AT_BITE:
  1306.         case AT_STNG:
  1307.         case AT_TUCH:
  1308.         case AT_BUTT:
  1309.         case AT_TENT:
  1310.             if (i==0 && uwep && (u.usym==S_LICH)) goto use_weapon;
  1311.             if ((dhit = (tmp > rnd(20) || u.uswallow)) != 0) {
  1312.                 int compat;
  1313.  
  1314.                 if (!u.uswallow &&
  1315.                 (compat=could_seduce(&youmonst, mon, mattk))) {
  1316.                 You("%s %s %s.",
  1317.                     mon->mcansee && haseyes(mon->data)
  1318.                     ? "smile at" : "talk to",
  1319.                     mon_nam(mon),
  1320.                     compat == 2 ? "engagingly":"seductively");
  1321.                 /* doesn't anger it; no wakeup() */
  1322.                 sum[i] = damageum(mon, mattk);
  1323.                 break;
  1324.                 }
  1325.                 wakeup(mon);
  1326.                 if (mon->data == &mons[PM_SHADE]) {
  1327.                 Your("attack passes harmlessly through %s.",
  1328.                     mon_nam(mon));
  1329.                 break;
  1330.                 }
  1331.                 if (mattk->aatyp == AT_KICK)
  1332.                     You("kick %s.", mon_nam(mon));
  1333.                 else if (mattk->aatyp == AT_BITE)
  1334.                     You("bite %s.", mon_nam(mon));
  1335.                 else if (mattk->aatyp == AT_STNG)
  1336.                     You("sting %s.", mon_nam(mon));
  1337.                 else if (mattk->aatyp == AT_BUTT)
  1338.                     You("butt %s.", mon_nam(mon));
  1339.                 else if (mattk->aatyp == AT_TUCH)
  1340.                     You("touch %s.", mon_nam(mon));
  1341.                 else if (mattk->aatyp == AT_TENT)
  1342.                     Your("tentacles suck %s.", mon_nam(mon));
  1343.                 else You("hit %s.", mon_nam(mon));
  1344.                 sum[i] = damageum(mon, mattk);
  1345.             } else
  1346.                 missum(mon, mattk);
  1347.             break;
  1348.  
  1349.         case AT_HUGS:
  1350.             /* automatic if prev two attacks succeed, or if
  1351.              * already grabbed in a previous attack
  1352.              */
  1353.             dhit = 1;
  1354.             wakeup(mon);
  1355.             if (mon->data == &mons[PM_SHADE])
  1356.                 Your("hug passes harmlessly through %s.",
  1357.                 mon_nam(mon));
  1358.             else if (!sticks(mon->data) && !u.uswallow)
  1359.                 if (mon==u.ustuck) {
  1360.                 pline("%s is being %s.", Monnam(mon),
  1361.                     u.umonnum==PM_ROPE_GOLEM ? "choked":
  1362.                     "crushed");
  1363.                 sum[i] = damageum(mon, mattk);
  1364.                 } else if(i >= 2 && sum[i-1] && sum[i-2]) {
  1365.                 You("grab %s!", mon_nam(mon));
  1366.                 u.ustuck = mon;
  1367.                 sum[i] = damageum(mon, mattk);
  1368.                 }
  1369.             break;
  1370.  
  1371.         case AT_EXPL:    /* automatic hit if next to */
  1372.             dhit = -1;
  1373.             wakeup(mon);
  1374.             sum[i] = explum(mon, mattk);
  1375.             break;
  1376.  
  1377.         case AT_ENGL:
  1378.             if((dhit = (tmp > rnd(20+i)))) {
  1379.                 wakeup(mon);
  1380.                 if (mon->data == &mons[PM_SHADE])
  1381.                     Your("attempt to surround %s is harmless.",
  1382.                     mon_nam(mon));
  1383.                 else
  1384.                     sum[i]= gulpum(mon,mattk);
  1385.             } else
  1386.                 missum(mon, mattk);
  1387.             break;
  1388.  
  1389.         case AT_MAGC:
  1390.             /* No check for uwep; if wielding nothing we want to
  1391.              * do the normal 1-2 points bare hand damage...
  1392.              */
  1393.             if (i==0 && (u.usym==S_KOBOLD
  1394.                 || u.usym==S_ORC
  1395.                 || u.usym==S_GNOME
  1396.                 )) goto use_weapon;
  1397.  
  1398.         case AT_NONE:
  1399.             continue;
  1400.             /* Not break--avoid passive attacks from enemy */
  1401.  
  1402.         case AT_BREA:
  1403.         case AT_SPIT:
  1404.         case AT_GAZE:    /* all done using #monster command */
  1405.             dhit = 0;
  1406.             break;
  1407.  
  1408.         default: /* Strange... */
  1409.             impossible("strange attack of yours (%d)",
  1410.                  mattk->aatyp);
  1411.         }
  1412.         if (dhit == -1)
  1413.         rehumanize();
  1414.         if(sum[i] == 2) return((boolean)passive(mon, 1, 0, (mattk->aatyp==AT_KICK)));
  1415.                             /* defender dead */
  1416.         else {
  1417.         (void) passive(mon, sum[i], 1, (mattk->aatyp==AT_KICK));
  1418.         nsum |= sum[i];
  1419.         }
  1420.         if (uasmon == &playermon)
  1421.         break; /* No extra attacks if no longer a monster */
  1422.         if (multi < 0)
  1423.         break; /* If paralyzed while attacking, i.e. floating eye */
  1424.     }
  1425.     return((boolean)(nsum != 0));
  1426. }
  1427.  
  1428. #endif /* POLYSELF */
  1429.  
  1430. /*    Special (passive) attacks on you by monsters done here.        */
  1431.  
  1432. int
  1433. passive(mon, mhit, malive, kicked)
  1434. register struct monst *mon;
  1435. register boolean mhit;
  1436. register int malive;
  1437. boolean kicked;
  1438. {
  1439.     register struct permonst *ptr = mon->data;
  1440.     register int i, tmp;
  1441.  
  1442.     for(i = 0; ; i++) {
  1443.         if(i >= NATTK) return(malive | mhit);    /* no passive attacks */
  1444.         if(ptr->mattk[i].aatyp == AT_NONE) break;    /* try this one */
  1445.     }
  1446.     /* Note: tmp not always used */
  1447.     if (ptr->mattk[i].damn)
  1448.         tmp = d((int)ptr->mattk[i].damn, (int)ptr->mattk[i].damd);
  1449.     else if(ptr->mattk[i].damd)
  1450.         tmp = d((int)mon->m_lev+1, (int)ptr->mattk[i].damd);
  1451.     else
  1452.         tmp = 0;
  1453.  
  1454. /*    These affect you even if they just died */
  1455.  
  1456.     switch(ptr->mattk[i].adtyp) {
  1457.  
  1458.       case AD_ACID:
  1459.         if(mhit && rn2(2)) {
  1460.         if (Blind || !flags.verbose) You("are splashed!");
  1461.         else    You("are splashed by %s acid!", 
  1462.                             s_suffix(mon_nam(mon)));
  1463.  
  1464. #ifdef POLYSELF
  1465.         if(!resists_acid(uasmon))
  1466. #endif
  1467.             mdamageu(mon, tmp);
  1468.         if(!rn2(30)) erode_armor(TRUE);
  1469.         }
  1470.         if(mhit && !rn2(6)) {
  1471.         if (kicked) {
  1472.             if (uarmf)
  1473.             (void) rust_dmg(uarmf, xname(uarmf), 3, TRUE);
  1474.         } else erode_weapon(TRUE);
  1475.         }
  1476.         exercise(A_STR, FALSE);
  1477.         break;
  1478.       case AD_STON:
  1479.         if(mhit)
  1480.           if (!kicked)
  1481.         if (!uwep && !uarmg
  1482. #ifdef POLYSELF
  1483.             && !resists_ston(uasmon)
  1484.             && !(poly_when_stoned(uasmon) && polymon(PM_STONE_GOLEM))
  1485. #endif
  1486.            ) {
  1487.             You("turn to stone...");
  1488.             done_in_by(mon);
  1489.             return 2;
  1490.         }
  1491.         break;
  1492.       case AD_RUST:
  1493.         if(mhit && !mon->mcan)
  1494.           if (kicked) {
  1495.         if (uarmf)
  1496.             (void) rust_dmg(uarmf, xname(uarmf), 1, TRUE);
  1497.           } else
  1498.         erode_weapon(FALSE);
  1499.         break;
  1500.       case AD_MAGM:
  1501.         /* wrath of gods for attacking Oracle */
  1502.         if(Antimagic) {
  1503.         shieldeff(u.ux, u.uy);
  1504.         pline("A hail of magic missiles narrowly misses you!");
  1505.         } else {
  1506.         You("are hit by magic missiles appearing from thin air!");
  1507.         mdamageu(mon, tmp);
  1508.         }
  1509.         break;
  1510.       default:
  1511.         break;
  1512.     }
  1513.  
  1514. /*    These only affect you if they still live */
  1515.  
  1516.     if(malive && !mon->mcan && rn2(3)) {
  1517.  
  1518.         switch(ptr->mattk[i].adtyp) {
  1519.  
  1520.           case AD_PLYS:
  1521.         if(ptr == &mons[PM_FLOATING_EYE]) {
  1522.             if (!canseemon(mon)) {
  1523.             break;
  1524.             }
  1525.             if(mon->mcansee) {
  1526.             if(Reflecting & W_AMUL) {
  1527.                 makeknown(AMULET_OF_REFLECTION);
  1528.                 pline("%s gaze is reflected by your medallion.",
  1529.                   s_suffix(Monnam(mon)));
  1530.             } else if(Reflecting & W_ARMS) {
  1531.                 makeknown(SHIELD_OF_REFLECTION);
  1532.                 pline("%s gaze is reflected by your shield.",
  1533.                   s_suffix(Monnam(mon)));
  1534.             } else {
  1535.                 You("are frozen by %s gaze!", 
  1536.                   s_suffix(mon_nam(mon)));
  1537.                 nomul((ACURR(A_WIS) > 12 || rn2(4)) ? -tmp : -127);
  1538.             }
  1539.             } else {
  1540.             pline("%s cannot defend itself.",
  1541.                 Adjmonnam(mon,"blind"));
  1542.             if(!rn2(500)) change_luck(-1);
  1543.             }
  1544.         } else { /* gelatinous cube */
  1545.             You("are frozen by %s!", mon_nam(mon));
  1546.             nomul(-tmp);
  1547.             exercise(A_DEX, FALSE);
  1548.         }
  1549.         break;
  1550.           case AD_COLD:        /* brown mold or blue jelly */
  1551.         if(monnear(mon, u.ux, u.uy)) {
  1552.             if(Cold_resistance) {
  1553.               shieldeff(u.ux, u.uy);
  1554.             You("feel a mild chill.");
  1555. #ifdef POLYSELF
  1556.             ugolemeffects(AD_COLD, tmp);
  1557. #endif
  1558.             break;
  1559.             }
  1560.             You("are suddenly very cold!");
  1561.             mdamageu(mon, tmp);
  1562.         /* monster gets stronger with your heat! */
  1563.             mon->mhp += tmp / 2;
  1564.             if (mon->mhpmax < mon->mhp) mon->mhpmax = mon->mhp;
  1565.         /* at a certain point, the monster will reproduce! */
  1566.             if(mon->mhpmax > ((int) (mon->m_lev+1) * 8)) {
  1567.             register struct monst *mtmp;
  1568.  
  1569.             if ((mtmp = clone_mon(mon)) != 0) {
  1570.                 mtmp->mhpmax = mon->mhpmax /= 2;
  1571.                 if(!Blind)
  1572.                 pline("%s multiplies from your heat!",
  1573.                                 Monnam(mon));
  1574.             }
  1575.             }
  1576.         }
  1577.         break;
  1578.           case AD_STUN:        /* specifically yellow mold */
  1579.         if(!Stunned)
  1580.             make_stunned((long)tmp, TRUE);
  1581.         break;
  1582.           case AD_FIRE:
  1583.         if(monnear(mon, u.ux, u.uy)) {
  1584.             if(Fire_resistance) {
  1585.             shieldeff(u.ux, u.uy);
  1586.             You("feel mildly warm.");
  1587. #ifdef POLYSELF
  1588.             ugolemeffects(AD_FIRE, tmp);
  1589. #endif
  1590.             break;
  1591.             }
  1592.             You("are suddenly very hot!");
  1593.             mdamageu(mon, tmp);
  1594.         }
  1595.         break;
  1596.           case AD_ELEC:
  1597.         if(Shock_resistance) {
  1598.             shieldeff(u.ux, u.uy);
  1599.             You("feel a mild tingle.");
  1600. #ifdef POLYSELF
  1601.             ugolemeffects(AD_ELEC, tmp);
  1602. #endif
  1603.             break;
  1604.         }
  1605.         You("are jolted with electricity!");
  1606.         mdamageu(mon, tmp);
  1607.         break;
  1608.           default:
  1609.         break;
  1610.         }
  1611.     }
  1612.     return(malive | mhit);
  1613. }
  1614.  
  1615. /* Note: caller must ascertain mtmp is mimicing... */
  1616. void
  1617. stumble_onto_mimic(mtmp)
  1618. register struct monst *mtmp;
  1619. {
  1620.     if(!u.ustuck && !mtmp->mflee && dmgtype(mtmp->data,AD_STCK))
  1621.         u.ustuck = mtmp;
  1622.     if (Blind) {
  1623.         if(!Telepat)
  1624.         pline("Wait!  That's a monster!");
  1625.     } else if (glyph_is_cmap(levl[u.ux+u.dx][u.uy+u.dy].glyph) &&
  1626.         (glyph_to_cmap(levl[u.ux+u.dx][u.uy+u.dy].glyph) == S_hcdoor ||
  1627.          glyph_to_cmap(levl[u.ux+u.dx][u.uy+u.dy].glyph) == S_vcdoor))
  1628.         pline("The door actually was %s!", a_monnam(mtmp));
  1629.     else if (glyph_is_object(levl[u.ux+u.dx][u.uy+u.dy].glyph) &&
  1630.         glyph_to_obj(levl[u.ux+u.dx][u.uy+u.dy].glyph) == GOLD_PIECE)
  1631.         pline("That gold was %s!", a_monnam(mtmp));
  1632.     else {
  1633.         pline("Wait!  That's %s!", a_monnam(mtmp));
  1634.     }
  1635.  
  1636.     wakeup(mtmp);    /* clears mimicing */
  1637. }
  1638.  
  1639. static void
  1640. nohandglow(mon)
  1641. struct monst *mon;
  1642. {
  1643.     char *hands=makeplural(body_part(HAND));
  1644.  
  1645.     if (!u.umconf || mon->mconf) return;
  1646.     if (u.umconf == 1) {
  1647.         if (Blind)
  1648.             Your("%s stop tingling.", hands);
  1649.         else
  1650.             Your("%s stop glowing %s.", hands,
  1651.                 Hallucination ? hcolor() : red);
  1652.     } else {
  1653.         if (Blind)
  1654.             pline("The tingling in your %s lessens.", hands);
  1655.         else
  1656.             Your("%s no longer glow so brightly %s.", hands,
  1657.                 Hallucination ? hcolor() : red);
  1658.     }
  1659.     u.umconf--;
  1660. }
  1661.  
  1662. /*uhitm.c*/
  1663.