OSDN Git Service

rearrange main dungeon
[nethackexpress/trunk.git] / src / uhitm.c
1 /*      SCCS Id: @(#)uhitm.c    3.4     2003/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_DCL boolean FDECL(known_hitum, (struct monst *,int *,struct attack *));
8 STATIC_DCL void FDECL(steal_it, (struct monst *, struct attack *));
9 STATIC_DCL boolean FDECL(hitum, (struct monst *,int,struct attack *));
10 STATIC_DCL boolean FDECL(hmon_hitmon, (struct monst *,struct obj *,int));
11 #ifdef STEED
12 STATIC_DCL int FDECL(joust, (struct monst *,struct obj *));
13 #endif
14 STATIC_DCL void NDECL(demonpet);
15 STATIC_DCL boolean FDECL(m_slips_free, (struct monst *mtmp,struct attack *mattk));
16 STATIC_DCL int FDECL(explum, (struct monst *,struct attack *));
17 STATIC_DCL void FDECL(start_engulf, (struct monst *));
18 STATIC_DCL void NDECL(end_engulf);
19 STATIC_DCL int FDECL(gulpum, (struct monst *,struct attack *));
20 STATIC_DCL boolean FDECL(hmonas, (struct monst *,int));
21 STATIC_DCL void FDECL(nohandglow, (struct monst *));
22 STATIC_DCL boolean FDECL(shade_aware, (struct obj *));
23
24 extern boolean notonhead;       /* for long worms */
25 /* The below might become a parameter instead if we use it a lot */
26 static int dieroll;
27 /* Used to flag attacks caused by Stormbringer's maliciousness. */
28 static boolean override_confirmation = FALSE;
29
30 #define PROJECTILE(obj) ((obj) && is_ammo(obj))
31
32 /* modified from hurtarmor() in mhitu.c */
33 /* This is not static because it is also used for monsters rusting monsters */
34 void
35 hurtmarmor(mdef, attk)
36 struct monst *mdef;
37 int attk;
38 {
39         int     hurt;
40         struct obj *target;
41
42         switch(attk) {
43             /* 0 is burning, which we should never be called with */
44             case AD_RUST: hurt = 1; break;
45             case AD_CORR: hurt = 3; break;
46             default: hurt = 2; break;
47         }
48         /* What the following code does: it keeps looping until it
49          * finds a target for the rust monster.
50          * Head, feet, etc... not covered by metal, or covered by
51          * rusty metal, are not targets.  However, your body always
52          * is, no matter what covers it.
53          */
54         while (1) {
55             switch(rn2(5)) {
56             case 0:
57                 target = which_armor(mdef, W_ARMH);
58                 if (!target || !rust_dmg(target, xname(target), hurt, FALSE, mdef))
59                     continue;
60                 break;
61             case 1:
62                 target = which_armor(mdef, W_ARMC);
63                 if (target) {
64                     (void)rust_dmg(target, xname(target), hurt, TRUE, mdef);
65                     break;
66                 }
67                 if ((target = which_armor(mdef, W_ARM)) != (struct obj *)0) {
68                     (void)rust_dmg(target, xname(target), hurt, TRUE, mdef);
69 #ifdef TOURIST
70                 } else if ((target = which_armor(mdef, W_ARMU)) != (struct obj *)0) {
71                     (void)rust_dmg(target, xname(target), hurt, TRUE, mdef);
72 #endif
73                 }
74                 break;
75             case 2:
76                 target = which_armor(mdef, W_ARMS);
77                 if (!target || !rust_dmg(target, xname(target), hurt, FALSE, mdef))
78                     continue;
79                 break;
80             case 3:
81                 target = which_armor(mdef, W_ARMG);
82                 if (!target || !rust_dmg(target, xname(target), hurt, FALSE, mdef))
83                     continue;
84                 break;
85             case 4:
86                 target = which_armor(mdef, W_ARMF);
87                 if (!target || !rust_dmg(target, xname(target), hurt, FALSE, mdef))
88                     continue;
89                 break;
90             }
91             break; /* Out of while loop */
92         }
93 }
94
95 /* FALSE means it's OK to attack */
96 boolean
97 attack_checks(mtmp, wep)
98 register struct monst *mtmp;
99 struct obj *wep;        /* uwep for attack(), null for kick_monster() */
100 {
101         char qbuf[QBUFSZ];
102
103         /* if you're close enough to attack, alert any waiting monster */
104         mtmp->mstrategy &= ~STRAT_WAITMASK;
105
106         if (u.uswallow && mtmp == u.ustuck) return FALSE;
107
108         if (flags.forcefight) {
109                 /* Do this in the caller, after we checked that the monster
110                  * didn't die from the blow.  Reason: putting the 'I' there
111                  * causes the hero to forget the square's contents since
112                  * both 'I' and remembered contents are stored in .glyph.
113                  * If the monster dies immediately from the blow, the 'I' will
114                  * not stay there, so the player will have suddenly forgotten
115                  * the square's contents for no apparent reason.
116                 if (!canspotmon(mtmp) &&
117                     !glyph_is_invisible(levl[u.ux+u.dx][u.uy+u.dy].glyph))
118                         map_invisible(u.ux+u.dx, u.uy+u.dy);
119                  */
120                 return FALSE;
121         }
122
123         /* Put up an invisible monster marker, but with exceptions for
124          * monsters that hide and monsters you've been warned about.
125          * The former already prints a warning message and
126          * prevents you from hitting the monster just via the hidden monster
127          * code below; if we also did that here, similar behavior would be
128          * happening two turns in a row.  The latter shows a glyph on
129          * the screen, so you know something is there.
130          */
131         if (!canspotmon(mtmp) &&
132                     !glyph_is_warning(glyph_at(u.ux+u.dx,u.uy+u.dy)) &&
133                     !glyph_is_invisible(levl[u.ux+u.dx][u.uy+u.dy].glyph) &&
134                     !(!Blind && mtmp->mundetected && hides_under(mtmp->data))) {
135                 pline("Wait!  There's %s there you can't see!",
136                         something);
137                 map_invisible(u.ux+u.dx, u.uy+u.dy);
138                 /* if it was an invisible mimic, treat it as if we stumbled
139                  * onto a visible mimic
140                  */
141                 if(mtmp->m_ap_type && !Protection_from_shape_changers) {
142                     if(!u.ustuck && !mtmp->mflee && dmgtype(mtmp->data,AD_STCK))
143                         u.ustuck = mtmp;
144                 }
145                 wakeup(mtmp); /* always necessary; also un-mimics mimics */
146                 return TRUE;
147         }
148
149         if (mtmp->m_ap_type && !Protection_from_shape_changers &&
150            !sensemon(mtmp) &&
151            !glyph_is_warning(glyph_at(u.ux+u.dx,u.uy+u.dy))) {
152                 /* If a hidden mimic was in a square where a player remembers
153                  * some (probably different) unseen monster, the player is in
154                  * luck--he attacks it even though it's hidden.
155                  */
156                 if (glyph_is_invisible(levl[mtmp->mx][mtmp->my].glyph)) {
157                     seemimic(mtmp);
158                     return(FALSE);
159                 }
160                 stumble_onto_mimic(mtmp);
161                 return TRUE;
162         }
163
164         if (mtmp->mundetected && !canseemon(mtmp) &&
165                 !glyph_is_warning(glyph_at(u.ux+u.dx,u.uy+u.dy)) &&
166                 (hides_under(mtmp->data) || mtmp->data->mlet == S_EEL)) {
167             mtmp->mundetected = mtmp->msleeping = 0;
168             newsym(mtmp->mx, mtmp->my);
169             if (glyph_is_invisible(levl[mtmp->mx][mtmp->my].glyph)) {
170                 seemimic(mtmp);
171                 return(FALSE);
172             }
173             if (!(Blind ? Blind_telepat : Unblind_telepat)) {
174                 struct obj *obj;
175
176                 if (Blind || (is_pool(mtmp->mx,mtmp->my) && !Underwater))
177                     pline("Wait!  There's a hidden monster there!");
178                 else if ((obj = level.objects[mtmp->mx][mtmp->my]) != 0)
179                     pline("Wait!  There's %s hiding under %s!",
180                           an(l_monnam(mtmp)), doname(obj));
181                 return TRUE;
182             }
183         }
184
185         /*
186          * make sure to wake up a monster from the above cases if the
187          * hero can sense that the monster is there.
188          */
189         if ((mtmp->mundetected || mtmp->m_ap_type) && sensemon(mtmp)) {
190             mtmp->mundetected = 0;
191             wakeup(mtmp);
192         }
193
194         if (flags.confirm && mtmp->mpeaceful
195             && !Confusion && !Hallucination && !Stunned) {
196                 /* Intelligent chaotic weapons (Stormbringer) want blood */
197                 if (wep && wep->oartifact == ART_STORMBRINGER) {
198                         override_confirmation = TRUE;
199                         return(FALSE);
200                 }
201                 if (canspotmon(mtmp)) {
202                         Sprintf(qbuf, "Really attack %s?", mon_nam(mtmp));
203                         if (yn(qbuf) != 'y') {
204                                 flags.move = 0;
205                                 return(TRUE);
206                         }
207                 }
208         }
209
210         return(FALSE);
211 }
212
213 /*
214  * It is unchivalrous for a knight to attack the defenseless or from behind.
215  */
216 void
217 check_caitiff(mtmp)
218 struct monst *mtmp;
219 {
220         if (Role_if(PM_KNIGHT) && u.ualign.type == A_LAWFUL &&
221             (!mtmp->mcanmove || mtmp->msleeping ||
222              (mtmp->mflee && !mtmp->mavenge)) &&
223             u.ualign.record > -10) {
224             You("caitiff!");
225             adjalign(-1);
226         }
227 }
228
229 schar
230 find_roll_to_hit(mtmp)
231 register struct monst *mtmp;
232 {
233         schar tmp;
234         int tmp2;
235
236         tmp = 1 + Luck + abon() + find_mac(mtmp) + u.uhitinc +
237                 maybe_polyd(youmonst.data->mlevel, u.ulevel);
238
239         check_caitiff(mtmp);
240
241 /*      attacking peaceful creatures is bad for the samurai's giri */
242         if (Role_if(PM_SAMURAI) && mtmp->mpeaceful &&
243             u.ualign.record > -10) {
244             You("dishonorably attack the innocent!");
245             adjalign(-1);
246         }
247
248 /*      Adjust vs. (and possibly modify) monster state.         */
249
250         if(mtmp->mstun) tmp += 2;
251         if(mtmp->mflee) tmp += 2;
252
253         if (mtmp->msleeping) {
254                 mtmp->msleeping = 0;
255                 tmp += 2;
256         }
257         if(!mtmp->mcanmove) {
258                 tmp += 4;
259                 if(!rn2(10)) {
260                         mtmp->mcanmove = 1;
261                         mtmp->mfrozen = 0;
262                 }
263         }
264         if (is_orc(mtmp->data) && maybe_polyd(is_elf(youmonst.data),
265                         Race_if(PM_ELF)))
266             tmp++;
267         if(Role_if(PM_MONK) && !Upolyd) {
268             if (uarm) {
269                 Your("armor is rather cumbersome...");
270                 tmp -= urole.spelarmr;
271             } else if (!uwep && !uarms) {
272                 tmp += (u.ulevel / 3) + 2;
273             }
274         }
275
276 /*      with a lot of luggage, your agility diminishes */
277         if ((tmp2 = near_capacity()) != 0) tmp -= (tmp2*2) - 1;
278         if (u.utrap) tmp -= 3;
279 /*      Some monsters have a combination of weapon attacks and non-weapon
280  *      attacks.  It is therefore wrong to add hitval to tmp; we must add
281  *      it only for the specific attack (in hmonas()).
282  */
283         if (uwep && !Upolyd) {
284                 tmp += hitval(uwep, mtmp);
285                 tmp += weapon_hit_bonus(uwep);
286         }
287         return tmp;
288 }
289
290 /* try to attack; return FALSE if monster evaded */
291 /* u.dx and u.dy must be set */
292 boolean
293 attack(mtmp)
294 register struct monst *mtmp;
295 {
296         schar tmp;
297         register struct permonst *mdat = mtmp->data;
298
299         /* This section of code provides protection against accidentally
300          * hitting peaceful (like '@') and tame (like 'd') monsters.
301          * Protection is provided as long as player is not: blind, confused,
302          * hallucinating or stunned.
303          * changes by wwp 5/16/85
304          * More changes 12/90, -dkh-. if its tame and safepet, (and protected
305          * 07/92) then we assume that you're not trying to attack. Instead,
306          * you'll usually just swap places if this is a movement command
307          */
308         /* Intelligent chaotic weapons (Stormbringer) want blood */
309         if (is_safepet(mtmp) && !flags.forcefight) {
310             if (!uwep || uwep->oartifact != ART_STORMBRINGER) {
311                 /* there are some additional considerations: this won't work
312                  * if in a shop or Punished or you miss a random roll or
313                  * if you can walk thru walls and your pet cannot (KAA) or
314                  * if your pet is a long worm (unless someone does better).
315                  * there's also a chance of displacing a "frozen" monster.
316                  * sleeping monsters might magically walk in their sleep.
317                  */
318                 boolean foo = (Punished || !rn2(7) || is_longworm(mtmp->data)),
319                         inshop = FALSE;
320                 char *p;
321
322                 for (p = in_rooms(mtmp->mx, mtmp->my, SHOPBASE); *p; p++)
323                     if (tended_shop(&rooms[*p - ROOMOFFSET])) {
324                         inshop = TRUE;
325                         break;
326                     }
327
328                 if (inshop || foo ||
329                         (IS_ROCK(levl[u.ux][u.uy].typ) &&
330                                         !passes_walls(mtmp->data))) {
331                     char buf[BUFSZ];
332
333                     monflee(mtmp, rnd(6), FALSE, FALSE);
334                     Strcpy(buf, y_monnam(mtmp));
335                     buf[0] = highc(buf[0]);
336                     You("stop.  %s is in the way!", buf);
337                     return(TRUE);
338                 } else if ((mtmp->mfrozen || (! mtmp->mcanmove)
339                                 || (mtmp->data->mmove == 0)) && rn2(6)) {
340                     pline("%s doesn't seem to move!", Monnam(mtmp));
341                     return(TRUE);
342                 } else return(FALSE);
343             }
344         }
345
346         /* possibly set in attack_checks;
347            examined in known_hitum, called via hitum or hmonas below */
348         override_confirmation = FALSE;
349         if (attack_checks(mtmp, uwep)) return(TRUE);
350
351         if (Upolyd) {
352                 /* certain "pacifist" monsters don't attack */
353                 if(noattacks(youmonst.data)) {
354                         You("have no way to attack monsters physically.");
355                         mtmp->mstrategy &= ~STRAT_WAITMASK;
356                         goto atk_done;
357                 }
358         }
359
360         if(check_capacity("You cannot fight while so heavily loaded."))
361             goto atk_done;
362
363         if (u.twoweap && !can_twoweapon())
364                 untwoweapon();
365
366         if(unweapon) {
367             unweapon = FALSE;
368             if(flags.verbose) {
369                 if(uwep)
370                     You("begin bashing monsters with your %s.",
371                         aobjnam(uwep, (char *)0));
372                 else if (!cantwield(youmonst.data))
373                     You("begin %sing monsters with your %s %s.",
374                         Role_if(PM_MONK) ? "strik" : "bash",
375                         uarmg ? "gloved" : "bare",      /* Del Lamb */
376                         makeplural(body_part(HAND)));
377             }
378         }
379         exercise(A_STR, TRUE);          /* you're exercising muscles */
380         /* andrew@orca: prevent unlimited pick-axe attacks */
381         u_wipe_engr(3);
382
383         /* Is the "it died" check actually correct? */
384         if(mdat->mlet == S_LEPRECHAUN && !mtmp->mfrozen && !mtmp->msleeping &&
385            !mtmp->mconf && mtmp->mcansee && !rn2(7) &&
386            (m_move(mtmp, 0) == 2 ||                         /* it died */
387            mtmp->mx != u.ux+u.dx || mtmp->my != u.uy+u.dy)) /* it moved */
388                 return(FALSE);
389
390         tmp = find_roll_to_hit(mtmp);
391         if (Upolyd)
392                 (void) hmonas(mtmp, tmp);
393         else
394                 (void) hitum(mtmp, tmp, youmonst.data->mattk);
395         mtmp->mstrategy &= ~STRAT_WAITMASK;
396
397 atk_done:
398         /* see comment in attack_checks() */
399         /* we only need to check for this if we did an attack_checks()
400          * and it returned 0 (it's okay to attack), and the monster didn't
401          * evade.
402          */
403         if (flags.forcefight && mtmp->mhp > 0 && !canspotmon(mtmp) &&
404             !glyph_is_invisible(levl[u.ux+u.dx][u.uy+u.dy].glyph) &&
405             !(u.uswallow && mtmp == u.ustuck))
406                 map_invisible(u.ux+u.dx, u.uy+u.dy);
407
408         return(TRUE);
409 }
410
411 STATIC_OVL boolean
412 known_hitum(mon, mhit, uattk)   /* returns TRUE if monster still lives */
413 register struct monst *mon;
414 register int *mhit;
415 struct attack *uattk;
416 {
417         register boolean malive = TRUE;
418
419         if (override_confirmation) {
420             /* this may need to be generalized if weapons other than
421                Stormbringer acquire similar anti-social behavior... */
422             if (flags.verbose) Your("bloodthirsty blade attacks!");
423         }
424
425         if(!*mhit) {
426             missum(mon, uattk);
427         } else {
428             int oldhp = mon->mhp,
429                 x = u.ux + u.dx, y = u.uy + u.dy;
430
431             /* KMH, conduct */
432             if (uwep && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep)))
433                 u.uconduct.weaphit++;
434
435             /* we hit the monster; be careful: it might die or
436                be knocked into a different location */
437             notonhead = (mon->mx != x || mon->my != y);
438             malive = hmon(mon, uwep, 0);
439             /* this assumes that Stormbringer was uwep not uswapwep */ 
440             if (malive && u.twoweap && !override_confirmation &&
441                     m_at(x, y) == mon)
442                 malive = hmon(mon, uswapwep, 0);
443             if (malive) {
444                 /* monster still alive */
445                 if(!rn2(25) && mon->mhp < mon->mhpmax/2
446                             && !(u.uswallow && mon == u.ustuck)) {
447                     /* maybe should regurgitate if swallowed? */
448                     if(!rn2(3)) {
449                         monflee(mon, rnd(100), FALSE, TRUE);
450                     } else monflee(mon, 0, FALSE, TRUE);
451
452                     if(u.ustuck == mon && !u.uswallow && !sticks(youmonst.data))
453                         u.ustuck = 0;
454                 }
455                 /* Vorpal Blade hit converted to miss */
456                 /* could be headless monster or worm tail */
457                 if (mon->mhp == oldhp) {
458                     *mhit = 0;
459                     /* a miss does not break conduct */
460                     if (uwep &&
461                         (uwep->oclass == WEAPON_CLASS || is_weptool(uwep)))
462                         --u.uconduct.weaphit;
463                 }
464                 if (mon->wormno && *mhit)
465                     cutworm(mon, x, y, uwep);
466             }
467         }
468         return(malive);
469 }
470
471 STATIC_OVL boolean
472 hitum(mon, tmp, uattk)          /* returns TRUE if monster still lives */
473 struct monst *mon;
474 int tmp;
475 struct attack *uattk;
476 {
477         boolean malive;
478         int mhit = (tmp > (dieroll = rnd(20)) || u.uswallow);
479
480         if(tmp > dieroll) exercise(A_DEX, TRUE);
481         malive = known_hitum(mon, &mhit, uattk);
482         (void) passive(mon, mhit, malive, AT_WEAP);
483         return(malive);
484 }
485
486 boolean                 /* general "damage monster" routine */
487 hmon(mon, obj, thrown)          /* return TRUE if mon still alive */
488 struct monst *mon;
489 struct obj *obj;
490 int thrown;
491 {
492         boolean result, anger_guards;
493
494         anger_guards = (mon->mpeaceful &&
495                             (mon->ispriest || mon->isshk ||
496                              mon->data == &mons[PM_WATCHMAN] ||
497                              mon->data == &mons[PM_WATCH_CAPTAIN]));
498         result = hmon_hitmon(mon, obj, thrown);
499         if (mon->ispriest && !rn2(2)) ghod_hitsu(mon);
500         if (anger_guards) (void)angry_guards(!flags.soundok);
501         return result;
502 }
503
504 /* guts of hmon() */
505 STATIC_OVL boolean
506 hmon_hitmon(mon, obj, thrown)
507 struct monst *mon;
508 struct obj *obj;
509 int thrown;
510 {
511         int tmp;
512         struct permonst *mdat = mon->data;
513         int barehand_silver_rings = 0;
514         /* The basic reason we need all these booleans is that we don't want
515          * a "hit" message when a monster dies, so we have to know how much
516          * damage it did _before_ outputting a hit message, but any messages
517          * associated with the damage don't come out until _after_ outputting
518          * a hit message.
519          */
520         boolean hittxt = FALSE, destroyed = FALSE, already_killed = FALSE;
521         boolean get_dmg_bonus = TRUE;
522         boolean ispoisoned = FALSE, needpoismsg = FALSE, poiskilled = FALSE;
523         boolean silvermsg = FALSE, silverobj = FALSE;
524         boolean valid_weapon_attack = FALSE;
525         boolean unarmed = !uwep && !uarm && !uarms;
526 #ifdef STEED
527         int jousting = 0;
528 #endif
529         int wtype;
530         struct obj *monwep;
531         char yourbuf[BUFSZ];
532         char unconventional[BUFSZ];     /* substituted for word "attack" in msg */
533         char saved_oname[BUFSZ];
534
535         unconventional[0] = '\0';
536         saved_oname[0] = '\0';
537
538         wakeup(mon);
539         if(!obj) {      /* attack with bare hands */
540             if (mdat == &mons[PM_SHADE])
541                 tmp = 0;
542             else if (martial_bonus())
543                 tmp = rnd(4);   /* bonus for martial arts */
544             else
545                 tmp = rnd(2);
546             valid_weapon_attack = (tmp > 1);
547             /* blessed gloves give bonuses when fighting 'bare-handed' */
548             if (uarmg && uarmg->blessed && (is_undead(mdat) || is_demon(mdat)))
549                 tmp += rnd(4);
550             /* So do silver rings.  Note: rings are worn under gloves, so you
551              * don't get both bonuses.
552              */
553             if (!uarmg) {
554                 if (uleft && objects[uleft->otyp].oc_material == SILVER)
555                     barehand_silver_rings++;
556                 if (uright && objects[uright->otyp].oc_material == SILVER)
557                     barehand_silver_rings++;
558                 if (barehand_silver_rings && hates_silver(mdat)) {
559                     tmp += rnd(20);
560                     silvermsg = TRUE;
561                 }
562             }
563         } else {
564             Strcpy(saved_oname, cxname(obj));
565             if(obj->oclass == WEAPON_CLASS || is_weptool(obj) ||
566                obj->oclass == GEM_CLASS) {
567
568                 /* is it not a melee weapon? */
569                 if (/* if you strike with a bow... */
570                     is_launcher(obj) ||
571                     /* or strike with a missile in your hand... */
572                     (!thrown && (is_missile(obj) || is_ammo(obj))) ||
573                     /* or use a pole at short range and not mounted... */
574                     (!thrown &&
575 #ifdef STEED
576                      !u.usteed &&
577 #endif
578                      is_pole(obj)) ||
579                     /* or throw a missile without the proper bow... */
580                     (is_ammo(obj) && !ammo_and_launcher(obj, uwep))) {
581                     /* then do only 1-2 points of damage */
582                     if (mdat == &mons[PM_SHADE] && obj->otyp != SILVER_ARROW)
583                         tmp = 0;
584                     else
585                         tmp = rnd(2);
586                     if (!thrown && obj == uwep && obj->otyp == BOOMERANG &&
587                             rnl(4) == 4-1) {
588                         boolean more_than_1 = (obj->quan > 1L);
589
590                         pline("As you hit %s, %s%s %s breaks into splinters.",
591                               mon_nam(mon), more_than_1 ? "one of " : "",
592                               shk_your(yourbuf, obj), xname(obj));
593                         if (!more_than_1) uwepgone();   /* set unweapon */
594                         useup(obj);
595                         if (!more_than_1) obj = (struct obj *) 0;
596                         hittxt = TRUE;
597                         if (mdat != &mons[PM_SHADE])
598                             tmp++;
599                     }
600                 } else {
601                     tmp = dmgval(obj, mon);
602                     /* a minimal hit doesn't exercise proficiency */
603                     valid_weapon_attack = (tmp > 1);
604                     if (!valid_weapon_attack || mon == u.ustuck || u.twoweap) {
605                         ;       /* no special bonuses */
606                     } else if (mon->mflee && Role_if(PM_ROGUE) && !Upolyd) {
607                         You("strike %s from behind!", mon_nam(mon));
608                         tmp += rnd(u.ulevel);
609                         hittxt = TRUE;
610                     } else if (dieroll == 2 && obj == uwep &&
611                           obj->oclass == WEAPON_CLASS &&
612                           (bimanual(obj) ||
613                             (Role_if(PM_SAMURAI) && obj->otyp == KATANA && !uarms)) &&
614                           ((wtype = uwep_skill_type()) != P_NONE &&
615                             P_SKILL(wtype) >= P_SKILLED) &&
616                           ((monwep = MON_WEP(mon)) != 0 &&
617                            !is_flimsy(monwep) &&
618                            !obj_resists(monwep,
619                                  50 + 15 * greatest_erosion(obj), 100))) {
620                         /*
621                          * 2.5% chance of shattering defender's weapon when
622                          * using a two-handed weapon; less if uwep is rusted.
623                          * [dieroll == 2 is most successful non-beheading or
624                          * -bisecting hit, in case of special artifact damage;
625                          * the percentage chance is (1/20)*(50/100).]
626                          */
627                         setmnotwielded(mon,monwep);
628                         MON_NOWEP(mon);
629                         mon->weapon_check = NEED_WEAPON;
630                         pline("%s %s %s from the force of your blow!",
631                               s_suffix(Monnam(mon)), xname(monwep),
632                               otense(monwep, "shatter"));
633                         m_useup(mon, monwep);
634                         /* If someone just shattered MY weapon, I'd flee! */
635                         if (rn2(4)) {
636                             monflee(mon, d(2,3), TRUE, TRUE);
637                         }
638                         hittxt = TRUE;
639                     }
640
641                     if (obj->oartifact &&
642                         artifact_hit(&youmonst, mon, obj, &tmp, dieroll)) {
643                         if(mon->mhp <= 0) /* artifact killed monster */
644                             return FALSE;
645                         if (tmp == 0) return TRUE;
646                         hittxt = TRUE;
647                     }
648                     if (objects[obj->otyp].oc_material == SILVER
649                                 && hates_silver(mdat)) {
650                         silvermsg = TRUE; silverobj = TRUE;
651                     }
652 #ifdef STEED
653                     if (u.usteed && !thrown && tmp > 0 &&
654                             weapon_type(obj) == P_LANCE && mon != u.ustuck) {
655                         jousting = joust(mon, obj);
656                         /* exercise skill even for minimal damage hits */
657                         if (jousting) valid_weapon_attack = TRUE;
658                     }
659 #endif
660                     if (thrown && (is_ammo(obj) || is_missile(obj))) {
661                         if (ammo_and_launcher(obj, uwep)) {
662                             /* Elves and Samurai do extra damage using
663                              * their bows&arrows; they're highly trained.
664                              */
665                             if (Role_if(PM_SAMURAI) &&
666                                 obj->otyp == YA && uwep->otyp == YUMI)
667                                 tmp++;
668                             else if (Race_if(PM_ELF) &&
669                                      obj->otyp == ELVEN_ARROW &&
670                                      uwep->otyp == ELVEN_BOW)
671                                 tmp++;
672                         }
673                         if(obj->opoisoned && is_poisonable(obj))
674                             ispoisoned = TRUE;
675                     }
676                 }
677             } else if(obj->oclass == POTION_CLASS) {
678                 if (obj->quan > 1L)
679                     obj = splitobj(obj, 1L);
680                 else
681                     setuwep((struct obj *)0);
682                 freeinv(obj);
683                 potionhit(mon, obj, TRUE);
684                 if (mon->mhp <= 0) return FALSE;        /* killed */
685                 hittxt = TRUE;
686                 /* in case potion effect causes transformation */
687                 mdat = mon->data;
688                 tmp = (mdat == &mons[PM_SHADE]) ? 0 : 1;
689             } else {
690                 if (mdat == &mons[PM_SHADE] && !shade_aware(obj)) {
691                     tmp = 0;
692                     Strcpy(unconventional, cxname(obj));
693                 } else {
694                     switch(obj->otyp) {
695                     case BOULDER:               /* 1d20 */
696                     case HEAVY_IRON_BALL:       /* 1d25 */
697                     case IRON_CHAIN:            /* 1d4+1 */
698                         tmp = dmgval(obj, mon);
699                         break;
700                     case MIRROR:
701                         if (breaktest(obj)) {
702                             You("break %s mirror.  That's bad luck!",
703                                 shk_your(yourbuf, obj));
704                             change_luck(-2);
705                             useup(obj);
706                             obj = (struct obj *) 0;
707                             unarmed = FALSE;    /* avoid obj==0 confusion */
708                             get_dmg_bonus = FALSE;
709                             hittxt = TRUE;
710                         }
711                         tmp = 1;
712                         break;
713 #ifdef TOURIST
714                     case EXPENSIVE_CAMERA:
715                         You("succeed in destroying %s camera.  Congratulations!",
716                                 shk_your(yourbuf, obj));
717                         useup(obj);
718                         return(TRUE);
719                         /*NOTREACHED*/
720                         break;
721 #endif
722                     case CORPSE:                /* fixed by polder@cs.vu.nl */
723                         if (touch_petrifies(&mons[obj->corpsenm])) {
724                             static const char withwhat[] = "corpse";
725                             tmp = 1;
726                             hittxt = TRUE;
727                             You("hit %s with %s %s.", mon_nam(mon),
728                                 obj->dknown ? the(mons[obj->corpsenm].mname) :
729                                 an(mons[obj->corpsenm].mname),
730                                 (obj->quan > 1) ? makeplural(withwhat) : withwhat);
731                             if (!munstone(mon, TRUE))
732                                 minstapetrify(mon, TRUE);
733                             if (resists_ston(mon)) break;
734                             /* note: hp may be <= 0 even if munstoned==TRUE */
735                             return (boolean) (mon->mhp > 0);
736 #if 0
737                         } else if (touch_petrifies(mdat)) {
738                             /* maybe turn the corpse into a statue? */
739 #endif
740                         }
741                         tmp = (obj->corpsenm >= LOW_PM ?
742                                         mons[obj->corpsenm].msize : 0) + 1;
743                         break;
744                     case EGG:
745                       {
746 #define useup_eggs(o)   { if (thrown) obfree(o,(struct obj *)0); \
747                           else useupall(o); \
748                           o = (struct obj *)0; }        /* now gone */
749                         long cnt = obj->quan;
750
751                         tmp = 1;                /* nominal physical damage */
752                         get_dmg_bonus = FALSE;
753                         hittxt = TRUE;          /* message always given */
754                         /* egg is always either used up or transformed, so next
755                            hand-to-hand attack should yield a "bashing" mesg */
756                         if (obj == uwep) unweapon = TRUE;
757                         if (obj->spe && obj->corpsenm >= LOW_PM) {
758                             if (obj->quan < 5)
759                                 change_luck((schar) -(obj->quan));
760                             else
761                                 change_luck(-5);
762                         }
763
764                         if (touch_petrifies(&mons[obj->corpsenm])) {
765                             /*learn_egg_type(obj->corpsenm);*/
766                             pline("Splat! You hit %s with %s %s egg%s!",
767                                 mon_nam(mon),
768                                 obj->known ? "the" : cnt > 1L ? "some" : "a",
769                                 obj->known ? mons[obj->corpsenm].mname : "petrifying",
770                                 plur(cnt));
771                             obj->known = 1;     /* (not much point...) */
772                             useup_eggs(obj);
773                             if (!munstone(mon, TRUE))
774                                 minstapetrify(mon, TRUE);
775                             if (resists_ston(mon)) break;
776                             return (boolean) (mon->mhp > 0);
777                         } else {        /* ordinary egg(s) */
778                             const char *eggp =
779                                      (obj->corpsenm != NON_PM && obj->known) ?
780                                               the(mons[obj->corpsenm].mname) :
781                                               (cnt > 1L) ? "some" : "an";
782                             You("hit %s with %s egg%s.",
783                                 mon_nam(mon), eggp, plur(cnt));
784                             if (touch_petrifies(mdat) && !stale_egg(obj)) {
785                                 pline_The("egg%s %s alive any more...",
786                                       plur(cnt),
787                                       (cnt == 1L) ? "isn't" : "aren't");
788                                 if (obj->timed) obj_stop_timers(obj);
789                                 obj->otyp = ROCK;
790                                 obj->oclass = GEM_CLASS;
791                                 obj->oartifact = 0;
792                                 obj->spe = 0;
793                                 obj->known = obj->dknown = obj->bknown = 0;
794                                 obj->owt = weight(obj);
795                                 if (thrown) place_object(obj, mon->mx, mon->my);
796                             } else {
797                                 pline("Splat!");
798                                 useup_eggs(obj);
799                                 exercise(A_WIS, FALSE);
800                             }
801                         }
802                         break;
803 #undef useup_eggs
804                       }
805                     case CLOVE_OF_GARLIC:       /* no effect against demons */
806                         if (is_undead(mdat)) {
807                             monflee(mon, d(2, 4), FALSE, TRUE);
808                         }
809                         tmp = 1;
810                         break;
811                     case CREAM_PIE:
812                     case BLINDING_VENOM:
813                         mon->msleeping = 0;
814                         if (can_blnd(&youmonst, mon, (uchar)
815                                     (obj->otyp == BLINDING_VENOM
816                                      ? AT_SPIT : AT_WEAP), obj)) {
817                             if (Blind) {
818                                 pline(obj->otyp == CREAM_PIE ?
819                                       "Splat!" : "Splash!");
820                             } else if (obj->otyp == BLINDING_VENOM) {
821                                 pline_The("venom blinds %s%s!", mon_nam(mon),
822                                           mon->mcansee ? "" : " further");
823                             } else {
824                                 char *whom = mon_nam(mon);
825                                 char *what = The(xname(obj));
826                                 if (!thrown && obj->quan > 1)
827                                     what = An(singular(obj, xname));
828                                 /* note: s_suffix returns a modifiable buffer */
829                                 if (haseyes(mdat)
830                                     && mdat != &mons[PM_FLOATING_EYE])
831                                     whom = strcat(strcat(s_suffix(whom), " "),
832                                                   mbodypart(mon, FACE));
833                                 pline("%s %s over %s!",
834                                       what, vtense(what, "splash"), whom);
835                             }
836                             setmangry(mon);
837                             mon->mcansee = 0;
838                             tmp = rn1(25, 21);
839                             if(((int) mon->mblinded + tmp) > 127)
840                                 mon->mblinded = 127;
841                             else mon->mblinded += tmp;
842                         } else {
843                             pline(obj->otyp==CREAM_PIE ? "Splat!" : "Splash!");
844                             setmangry(mon);
845                         }
846                         if (thrown) obfree(obj, (struct obj *)0);
847                         else useup(obj);
848                         hittxt = TRUE;
849                         get_dmg_bonus = FALSE;
850                         tmp = 0;
851                         break;
852                     case ACID_VENOM: /* thrown (or spit) */
853                         if (resists_acid(mon)) {
854                                 Your("venom hits %s harmlessly.",
855                                         mon_nam(mon));
856                                 tmp = 0;
857                         } else {
858                                 Your("venom burns %s!", mon_nam(mon));
859                                 tmp = dmgval(obj, mon);
860                         }
861                         if (thrown) obfree(obj, (struct obj *)0);
862                         else useup(obj);
863                         hittxt = TRUE;
864                         get_dmg_bonus = FALSE;
865                         break;
866                     default:
867                         /* non-weapons can damage because of their weight */
868                         /* (but not too much) */
869                         tmp = obj->owt/100;
870                         if(tmp < 1) tmp = 1;
871                         else tmp = rnd(tmp);
872                         if(tmp > 6) tmp = 6;
873                         /*
874                          * Things like silver wands can arrive here so
875                          * so we need another silver check.
876                          */
877                         if (objects[obj->otyp].oc_material == SILVER
878                                                 && hates_silver(mdat)) {
879                                 tmp += rnd(20);
880                                 silvermsg = TRUE; silverobj = TRUE;
881                         }
882                     }
883                 }
884             }
885         }
886
887         /****** NOTE: perhaps obj is undefined!! (if !thrown && BOOMERANG)
888          *      *OR* if attacking bare-handed!! */
889
890         if (get_dmg_bonus && tmp > 0) {
891                 tmp += u.udaminc;
892                 /* If you throw using a propellor, you don't get a strength
893                  * bonus but you do get an increase-damage bonus.
894                  */
895                 if(!thrown || !obj || !uwep || !ammo_and_launcher(obj, uwep))
896                     tmp += dbon();
897         }
898
899         if (valid_weapon_attack) {
900             struct obj *wep;
901
902             /* to be valid a projectile must have had the correct projector */
903             wep = PROJECTILE(obj) ? uwep : obj;
904             tmp += weapon_dam_bonus(wep);
905             /* [this assumes that `!thrown' implies wielded...] */
906             wtype = thrown ? weapon_type(wep) : uwep_skill_type();
907             use_skill(wtype, 1);
908         }
909
910         if (ispoisoned) {
911             int nopoison = (10 - (obj->owt/10));            
912             if(nopoison < 2) nopoison = 2;
913             if Role_if(PM_SAMURAI) {
914                 You("dishonorably use a poisoned weapon!");
915                 adjalign(-sgn(u.ualign.type));
916             } else if ((u.ualign.type == A_LAWFUL) && (u.ualign.record > -10)) {
917                 You_feel("like an evil coward for using a poisoned weapon.");
918                 adjalign(-1);
919             }
920             if (obj && !rn2(nopoison)) {
921                 obj->opoisoned = FALSE;
922                 Your("%s %s no longer poisoned.", xname(obj),
923                      otense(obj, "are"));
924             }
925             if (resists_poison(mon))
926                 needpoismsg = TRUE;
927             else if (rn2(10))
928                 tmp += rnd(6);
929             else poiskilled = TRUE;
930         }
931         if (tmp < 1) {
932             /* make sure that negative damage adjustment can't result
933                in inadvertently boosting the victim's hit points */
934             tmp = 0;
935             if (mdat == &mons[PM_SHADE]) {
936                 if (!hittxt) {
937                     const char *what = unconventional[0] ? unconventional : "attack";
938                     Your("%s %s harmlessly through %s.",
939                         what, vtense(what, "pass"),
940                         mon_nam(mon));
941                     hittxt = TRUE;
942                 }
943             } else {
944                 if (get_dmg_bonus) tmp = 1;
945             }
946         }
947
948 #ifdef STEED
949         if (jousting) {
950             tmp += d(2, (obj == uwep) ? 10 : 2);        /* [was in dmgval()] */
951             You("joust %s%s",
952                          mon_nam(mon), canseemon(mon) ? exclam(tmp) : ".");
953             if (jousting < 0) {
954                 Your("%s shatters on impact!", xname(obj));
955                 /* (must be either primary or secondary weapon to get here) */
956                 u.twoweap = FALSE;      /* untwoweapon() is too verbose here */
957                 if (obj == uwep) uwepgone();            /* set unweapon */
958                 /* minor side-effect: broken lance won't split puddings */
959                 useup(obj);
960                 obj = 0;
961             }
962             /* avoid migrating a dead monster */
963             if (mon->mhp > tmp) {
964                 mhurtle(mon, u.dx, u.dy, 1);
965                 mdat = mon->data; /* in case of a polymorph trap */
966                 if (DEADMONSTER(mon)) already_killed = TRUE;
967             }
968             hittxt = TRUE;
969         } else
970 #endif
971
972         /* VERY small chance of stunning opponent if unarmed. */
973         if (unarmed && tmp > 1 && !thrown && !obj && !Upolyd) {
974             if (rnd(100) < P_SKILL(P_BARE_HANDED_COMBAT) &&
975                         !bigmonst(mdat) && !thick_skinned(mdat)) {
976                 if (canspotmon(mon))
977                     pline("%s %s from your powerful strike!", Monnam(mon),
978                           makeplural(stagger(mon->data, "stagger")));
979                 /* avoid migrating a dead monster */
980                 if (mon->mhp > tmp) {
981                     mhurtle(mon, u.dx, u.dy, 1);
982                     mdat = mon->data; /* in case of a polymorph trap */
983                     if (DEADMONSTER(mon)) already_killed = TRUE;
984                 }
985                 hittxt = TRUE;
986             }
987         }
988
989         if (!already_killed) mon->mhp -= tmp;
990         /* adjustments might have made tmp become less than what
991            a level draining artifact has already done to max HP */
992         if (mon->mhp > mon->mhpmax) mon->mhp = mon->mhpmax;
993         if (mon->mhp < 1)
994                 destroyed = TRUE;
995         if (mon->mtame && (!mon->mflee || mon->mfleetim) && tmp > 0) {
996                 abuse_dog(mon);
997                 monflee(mon, 10 * rnd(tmp), FALSE, FALSE);
998         }
999         if((mdat == &mons[PM_BLACK_PUDDING] || mdat == &mons[PM_BROWN_PUDDING])
1000                    && obj && obj == uwep
1001                    && objects[obj->otyp].oc_material == IRON
1002                    && mon->mhp > 1 && !thrown && !mon->mcan
1003                    /* && !destroyed  -- guaranteed by mhp > 1 */ ) {
1004                 if (clone_mon(mon, 0, 0)) {
1005                         pline("%s divides as you hit it!", Monnam(mon));
1006                         hittxt = TRUE;
1007                 }
1008         }
1009
1010         if (!hittxt &&                  /*( thrown => obj exists )*/
1011           (!destroyed || (thrown && m_shot.n > 1 && m_shot.o == obj->otyp))) {
1012                 if (thrown) hit(mshot_xname(obj), mon, exclam(tmp));
1013                 else if (!flags.verbose) You("hit it.");
1014                 else You("%s %s%s", Role_if(PM_BARBARIAN) ? "smite" : "hit",
1015                          mon_nam(mon), canseemon(mon) ? exclam(tmp) : ".");
1016         }
1017
1018         if (silvermsg) {
1019                 const char *fmt;
1020                 char *whom = mon_nam(mon);
1021                 char silverobjbuf[BUFSZ];
1022
1023                 if (canspotmon(mon)) {
1024                     if (barehand_silver_rings == 1)
1025                         fmt = "Your silver ring sears %s!";
1026                     else if (barehand_silver_rings == 2)
1027                         fmt = "Your silver rings sear %s!";
1028                     else if (silverobj && saved_oname[0]) {
1029                         Sprintf(silverobjbuf, "Your %s%s %s %%s!",
1030                                 strstri(saved_oname, "silver") ?
1031                                         "" : "silver ",
1032                                 saved_oname, vtense(saved_oname, "sear"));
1033                         fmt = silverobjbuf;
1034                     } else
1035                         fmt = "The silver sears %s!";
1036                 } else {
1037                     *whom = highc(*whom);       /* "it" -> "It" */
1038                     fmt = "%s is seared!";
1039                 }
1040                 /* note: s_suffix returns a modifiable buffer */
1041                 if (!noncorporeal(mdat))
1042                     whom = strcat(s_suffix(whom), " flesh");
1043                 pline(fmt, whom);
1044         }
1045
1046         if (needpoismsg)
1047                 pline_The("poison doesn't seem to affect %s.", mon_nam(mon));
1048         if (poiskilled) {
1049                 pline_The("poison was deadly...");
1050                 if (!already_killed) xkilled(mon, 0);
1051                 return FALSE;
1052         } else if (destroyed) {
1053                 if (!already_killed)
1054                     killed(mon);        /* takes care of most messages */
1055         } else if(u.umconf && !thrown) {
1056                 nohandglow(mon);
1057                 if (!mon->mconf && !resist(mon, SPBOOK_CLASS, 0, NOTELL)) {
1058                         mon->mconf = 1;
1059                         if (!mon->mstun && mon->mcanmove && !mon->msleeping &&
1060                                 canseemon(mon))
1061                             pline("%s appears confused.", Monnam(mon));
1062                 }
1063         }
1064
1065         return((boolean)(destroyed ? FALSE : TRUE));
1066 }
1067
1068 STATIC_OVL boolean
1069 shade_aware(obj)
1070 struct obj *obj;
1071 {
1072         if (!obj) return FALSE;
1073         /*
1074          * The things in this list either
1075          * 1) affect shades.
1076          *  OR
1077          * 2) are dealt with properly by other routines
1078          *    when it comes to shades.
1079          */
1080         if (obj->otyp == BOULDER || obj->otyp == HEAVY_IRON_BALL
1081             || obj->otyp == IRON_CHAIN          /* dmgval handles those first three */
1082             || obj->otyp == MIRROR              /* silver in the reflective surface */
1083             || obj->otyp == CLOVE_OF_GARLIC     /* causes shades to flee */
1084             || objects[obj->otyp].oc_material == SILVER)
1085                 return TRUE;
1086         return FALSE;
1087 }
1088
1089 /* check whether slippery clothing protects from hug or wrap attack */
1090 /* [currently assumes that you are the attacker] */
1091 STATIC_OVL boolean
1092 m_slips_free(mdef, mattk)
1093 struct monst *mdef;
1094 struct attack *mattk;
1095 {
1096         struct obj *obj;
1097
1098         if (mattk->adtyp == AD_DRIN) {
1099             /* intelligence drain attacks the head */
1100             obj = which_armor(mdef, W_ARMH);
1101         } else {
1102             /* grabbing attacks the body */
1103             obj = which_armor(mdef, W_ARMC);            /* cloak */
1104             if (!obj) obj = which_armor(mdef, W_ARM);   /* suit */
1105 #ifdef TOURIST
1106             if (!obj) obj = which_armor(mdef, W_ARMU);  /* shirt */
1107 #endif
1108         }
1109
1110         /* if your cloak/armor is greased, monster slips off; this
1111            protection might fail (33% chance) when the armor is cursed */
1112         if (obj && (obj->greased || obj->otyp == OILSKIN_CLOAK) &&
1113                 (!obj->cursed || rn2(3))) {
1114             You("%s %s %s %s!",
1115                 mattk->adtyp == AD_WRAP ?
1116                         "slip off of" : "grab, but cannot hold onto",
1117                 s_suffix(mon_nam(mdef)),
1118                 obj->greased ? "greased" : "slippery",
1119                 /* avoid "slippery slippery cloak"
1120                    for undiscovered oilskin cloak */
1121                 (obj->greased || objects[obj->otyp].oc_name_known) ?
1122                         xname(obj) : cloak_simple_name(obj));
1123
1124             if (obj->greased && !rn2(2)) {
1125                 pline_The("grease wears off.");
1126                 obj->greased = 0;
1127             }
1128             return TRUE;
1129         }
1130         return FALSE;
1131 }
1132
1133 /* used when hitting a monster with a lance while mounted */
1134 STATIC_OVL int  /* 1: joust hit; 0: ordinary hit; -1: joust but break lance */
1135 joust(mon, obj)
1136 struct monst *mon;      /* target */
1137 struct obj *obj;        /* weapon */
1138 {
1139     int skill_rating, joust_dieroll;
1140
1141     if (Fumbling || Stunned) return 0;
1142     /* sanity check; lance must be wielded in order to joust */
1143     if (obj != uwep && (obj != uswapwep || !u.twoweap)) return 0;
1144
1145     /* if using two weapons, use worse of lance and two-weapon skills */
1146     skill_rating = P_SKILL(weapon_type(obj));   /* lance skill */
1147     if (u.twoweap && P_SKILL(P_TWO_WEAPON_COMBAT) < skill_rating)
1148         skill_rating = P_SKILL(P_TWO_WEAPON_COMBAT);
1149     if (skill_rating == P_ISRESTRICTED) skill_rating = P_UNSKILLED; /* 0=>1 */
1150
1151     /* odds to joust are expert:80%, skilled:60%, basic:40%, unskilled:20% */
1152     if ((joust_dieroll = rn2(5)) < skill_rating) {
1153         if (joust_dieroll == 0 && rnl(50) == (50-1) &&
1154                 !unsolid(mon->data) && !obj_resists(obj, 0, 100))
1155             return -1;  /* hit that breaks lance */
1156         return 1;       /* successful joust */
1157     }
1158     return 0;   /* no joust bonus; revert to ordinary attack */
1159 }
1160
1161 /*
1162  * Send in a demon pet for the hero.  Exercise wisdom.
1163  *
1164  * This function used to be inline to damageum(), but the Metrowerks compiler
1165  * (DR4 and DR4.5) screws up with an internal error 5 "Expression Too Complex."
1166  * Pulling it out makes it work.
1167  */
1168 STATIC_OVL void
1169 demonpet()
1170 {
1171         int i;
1172         struct permonst *pm;
1173         struct monst *dtmp;
1174
1175         pline("Some hell-p has arrived!");
1176         i = !rn2(6) ? ndemon(u.ualign.type) : NON_PM;
1177         pm = i != NON_PM ? &mons[i] : youmonst.data;
1178         if ((dtmp = makemon(pm, u.ux, u.uy, NO_MM_FLAGS)) != 0)
1179             (void)tamedog(dtmp, (struct obj *)0);
1180         exercise(A_WIS, TRUE);
1181 }
1182
1183 /*
1184  * Player uses theft attack against monster.
1185  *
1186  * If the target is wearing body armor, take all of its possesions;
1187  * otherwise, take one object.  [Is this really the behavior we want?]
1188  *
1189  * This routine implicitly assumes that there is no way to be able to
1190  * resist petfication (ie, be polymorphed into a xorn or golem) at the
1191  * same time as being able to steal (poly'd into nymph or succubus).
1192  * If that ever changes, the check for touching a cockatrice corpse
1193  * will need to be smarter about whether to break out of the theft loop.
1194  */
1195 STATIC_OVL void
1196 steal_it(mdef, mattk)
1197 struct monst *mdef;
1198 struct attack *mattk;
1199 {
1200         struct obj *otmp, *stealoid, **minvent_ptr;
1201         long unwornmask;
1202
1203         if (!mdef->minvent) return;             /* nothing to take */
1204
1205         /* look for worn body armor */
1206         stealoid = (struct obj *)0;
1207         if (could_seduce(&youmonst, mdef, mattk)) {
1208             /* find armor, and move it to end of inventory in the process */
1209             minvent_ptr = &mdef->minvent;
1210             while ((otmp = *minvent_ptr) != 0)
1211                 if (otmp->owornmask & W_ARM) {
1212                     if (stealoid) panic("steal_it: multiple worn suits");
1213                     *minvent_ptr = otmp->nobj;  /* take armor out of minvent */
1214                     stealoid = otmp;
1215                     stealoid->nobj = (struct obj *)0;
1216                 } else {
1217                     minvent_ptr = &otmp->nobj;
1218                 }
1219             *minvent_ptr = stealoid;    /* put armor back into minvent */
1220         }
1221
1222         if (stealoid) {         /* we will be taking everything */
1223             if (gender(mdef) == (int) u.mfemale &&
1224                         youmonst.data->mlet == S_NYMPH)
1225                 You("charm %s.  She gladly hands over her possessions.",
1226                     mon_nam(mdef));
1227             else
1228                 You("seduce %s and %s starts to take off %s clothes.",
1229                     mon_nam(mdef), mhe(mdef), mhis(mdef));
1230         }
1231
1232         while ((otmp = mdef->minvent) != 0) {
1233             if (!Upolyd) break;         /* no longer have ability to steal */
1234             /* take the object away from the monster */
1235             obj_extract_self(otmp);
1236             if ((unwornmask = otmp->owornmask) != 0L) {
1237                 mdef->misc_worn_check &= ~unwornmask;
1238                 if (otmp->owornmask & W_WEP) {
1239                     setmnotwielded(mdef,otmp);
1240                     MON_NOWEP(mdef);
1241                 }
1242                 otmp->owornmask = 0L;
1243                 update_mon_intrinsics(mdef, otmp, FALSE, FALSE);
1244
1245                 if (otmp == stealoid)   /* special message for final item */
1246                     pline("%s finishes taking off %s suit.",
1247                           Monnam(mdef), mhis(mdef));
1248             }
1249             /* give the object to the character */
1250             otmp = hold_another_object(otmp, "You snatched but dropped %s.",
1251                                        doname(otmp), "You steal: ");
1252             if (otmp->where != OBJ_INVENT) continue;
1253             if (otmp->otyp == CORPSE &&
1254                     touch_petrifies(&mons[otmp->corpsenm]) && !uarmg) {
1255                 char kbuf[BUFSZ];
1256
1257                 Sprintf(kbuf, "stolen %s corpse", mons[otmp->corpsenm].mname);
1258                 instapetrify(kbuf);
1259                 break;          /* stop the theft even if hero survives */
1260             }
1261             /* more take-away handling, after theft message */
1262             if (unwornmask & W_WEP) {           /* stole wielded weapon */
1263                 possibly_unwield(mdef, FALSE);
1264             } else if (unwornmask & W_ARMG) {   /* stole worn gloves */
1265                 mselftouch(mdef, (const char *)0, TRUE);
1266                 if (mdef->mhp <= 0)     /* it's now a statue */
1267                     return;             /* can't continue stealing */
1268             }
1269
1270             if (!stealoid) break;       /* only taking one item */
1271         }
1272 }
1273
1274 int
1275 damageum(mdef, mattk)
1276 register struct monst *mdef;
1277 register struct attack *mattk;
1278 {
1279         register struct permonst *pd = mdef->data;
1280         register int    tmp = d((int)mattk->damn, (int)mattk->damd);
1281         int armpro;
1282         boolean negated;
1283
1284         armpro = magic_negation(mdef);
1285         /* since hero can't be cancelled, only defender's armor applies */
1286         negated = !((rn2(3) >= armpro) || !rn2(50));
1287
1288         if (is_demon(youmonst.data) && !rn2(13) && !uwep
1289                 && u.umonnum != PM_SUCCUBUS && u.umonnum != PM_INCUBUS
1290                 && u.umonnum != PM_BALROG) {
1291             demonpet();
1292             return(0);
1293         }
1294         switch(mattk->adtyp) {
1295             case AD_STUN:
1296                 if(!Blind)
1297                     pline("%s %s for a moment.", Monnam(mdef),
1298                           makeplural(stagger(mdef->data, "stagger")));
1299                 mdef->mstun = 1;
1300                 goto physical;
1301             case AD_LEGS:
1302              /* if (u.ucancelled) { */
1303              /*    tmp = 0;         */
1304              /*    break;           */
1305              /* }                   */
1306                 goto physical;
1307             case AD_WERE:           /* no special effect on monsters */
1308             case AD_HEAL:           /* likewise */
1309             case AD_PHYS:
1310  physical:
1311                 if(mattk->aatyp == AT_WEAP) {
1312                     if(uwep) tmp = 0;
1313                 } else if(mattk->aatyp == AT_KICK) {
1314                     if(thick_skinned(mdef->data)) tmp = 0;
1315                     if(mdef->data == &mons[PM_SHADE]) {
1316                         if (!(uarmf && uarmf->blessed)) {
1317                             impossible("bad shade attack function flow?");
1318                             tmp = 0;
1319                         } else
1320                             tmp = rnd(4); /* bless damage */
1321                     }
1322                 }
1323                 break;
1324             case AD_FIRE:
1325                 if (negated) {
1326                     tmp = 0;
1327                     break;
1328                 }
1329                 if (!Blind)
1330                     pline("%s is %s!", Monnam(mdef),
1331                           on_fire(mdef->data, mattk));
1332                 if (pd == &mons[PM_STRAW_GOLEM] ||
1333                     pd == &mons[PM_PAPER_GOLEM]) {
1334                     if (!Blind)
1335                         pline("%s burns completely!", Monnam(mdef));
1336                     xkilled(mdef,2);
1337                     tmp = 0;
1338                     break;
1339                     /* Don't return yet; keep hp<1 and tmp=0 for pet msg */
1340                 }
1341                 tmp += destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE);
1342                 tmp += destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE);
1343                 if (resists_fire(mdef)) {
1344                     if (!Blind)
1345                         pline_The("fire doesn't heat %s!", mon_nam(mdef));
1346                     golemeffects(mdef, AD_FIRE, tmp);
1347                     shieldeff(mdef->mx, mdef->my);
1348                     tmp = 0;
1349                 }
1350                 /* only potions damage resistant players in destroy_item */
1351                 tmp += destroy_mitem(mdef, POTION_CLASS, AD_FIRE);
1352                 break;
1353             case AD_COLD:
1354                 if (negated) {
1355                     tmp = 0;
1356                     break;
1357                 }
1358                 if (!Blind) pline("%s is covered in frost!", Monnam(mdef));
1359                 if (resists_cold(mdef)) {
1360                     shieldeff(mdef->mx, mdef->my);
1361                     if (!Blind)
1362                         pline_The("frost doesn't chill %s!", mon_nam(mdef));
1363                     golemeffects(mdef, AD_COLD, tmp);
1364                     tmp = 0;
1365                 }
1366                 tmp += destroy_mitem(mdef, POTION_CLASS, AD_COLD);
1367                 break;
1368             case AD_ELEC:
1369                 if (negated) {
1370                     tmp = 0;
1371                     break;
1372                 }
1373                 if (!Blind) pline("%s is zapped!", Monnam(mdef));
1374                 tmp += destroy_mitem(mdef, WAND_CLASS, AD_ELEC);
1375                 if (resists_elec(mdef)) {
1376                     if (!Blind)
1377                         pline_The("zap doesn't shock %s!", mon_nam(mdef));
1378                     golemeffects(mdef, AD_ELEC, tmp);
1379                     shieldeff(mdef->mx, mdef->my);
1380                     tmp = 0;
1381                 }
1382                 /* only rings damage resistant players in destroy_item */
1383                 tmp += destroy_mitem(mdef, RING_CLASS, AD_ELEC);
1384                 break;
1385             case AD_ACID:
1386                 if (resists_acid(mdef)) tmp = 0;
1387                 break;
1388             case AD_STON:
1389                 if (!munstone(mdef, TRUE))
1390                     minstapetrify(mdef, TRUE);
1391                 tmp = 0;
1392                 break;
1393 #ifdef SEDUCE
1394             case AD_SSEX:
1395 #endif
1396             case AD_SEDU:
1397             case AD_SITM:
1398                 steal_it(mdef, mattk);
1399                 tmp = 0;
1400                 break;
1401             case AD_SGLD:
1402 #ifndef GOLDOBJ
1403                 if (mdef->mgold) {
1404                     u.ugold += mdef->mgold;
1405                     mdef->mgold = 0;
1406                     Your("purse feels heavier.");
1407                 }
1408 #else
1409                 /* This you as a leprechaun, so steal
1410                    real gold only, no lesser coins */
1411                 {
1412                     struct obj *mongold = findgold(mdef->minvent);
1413                     if (mongold) {
1414                         obj_extract_self(mongold);  
1415                         if (merge_choice(invent, mongold) || inv_cnt() < 52) {
1416                             addinv(mongold);
1417                             Your("purse feels heavier.");
1418                         } else {
1419                             You("grab %s's gold, but find no room in your knapsack.", mon_nam(mdef));
1420                             dropy(mongold);
1421                         }
1422                     }
1423                 }
1424 #endif
1425                 exercise(A_DEX, TRUE);
1426                 tmp = 0;
1427                 break;
1428             case AD_TLPT:
1429                 if (tmp <= 0) tmp = 1;
1430                 if (!negated && tmp < mdef->mhp) {
1431                     char nambuf[BUFSZ];
1432                     boolean u_saw_mon = canseemon(mdef) ||
1433                                         (u.uswallow && u.ustuck == mdef);
1434                     /* record the name before losing sight of monster */
1435                     Strcpy(nambuf, Monnam(mdef));
1436                     if (u_teleport_mon(mdef, FALSE) &&
1437                             u_saw_mon && !canseemon(mdef))
1438                         pline("%s suddenly disappears!", nambuf);
1439                 }
1440                 break;
1441             case AD_BLND:
1442                 if (can_blnd(&youmonst, mdef, mattk->aatyp, (struct obj*)0)) {
1443                     if(!Blind && mdef->mcansee)
1444                         pline("%s is blinded.", Monnam(mdef));
1445                     mdef->mcansee = 0;
1446                     tmp += mdef->mblinded;
1447                     if (tmp > 127) tmp = 127;
1448                     mdef->mblinded = tmp;
1449                 }
1450                 tmp = 0;
1451                 break;
1452             case AD_CURS:
1453                 if (night() && !rn2(10) && !mdef->mcan) {
1454                     if (mdef->data == &mons[PM_CLAY_GOLEM]) {
1455                         if (!Blind)
1456                             pline("Some writing vanishes from %s head!",
1457                                 s_suffix(mon_nam(mdef)));
1458                         xkilled(mdef, 0);
1459                         /* Don't return yet; keep hp<1 and tmp=0 for pet msg */
1460                     } else {
1461                         mdef->mcan = 1;
1462                         You("chuckle.");
1463                     }
1464                 }
1465                 tmp = 0;
1466                 break;
1467             case AD_DRLI:
1468                 if (!negated && !rn2(3) && !resists_drli(mdef)) {
1469                         int xtmp = d(2,6);
1470                         pline("%s suddenly seems weaker!", Monnam(mdef));
1471                         mdef->mhpmax -= xtmp;
1472                         if ((mdef->mhp -= xtmp) <= 0 || !mdef->m_lev) {
1473                                 pline("%s dies!", Monnam(mdef));
1474                                 xkilled(mdef,0);
1475                         } else
1476                                 mdef->m_lev--;
1477                         tmp = 0;
1478                 }
1479                 break;
1480             case AD_RUST:
1481                 if (pd == &mons[PM_IRON_GOLEM]) {
1482                         pline("%s falls to pieces!", Monnam(mdef));
1483                         xkilled(mdef,0);
1484                 }
1485                 hurtmarmor(mdef, AD_RUST);
1486                 tmp = 0;
1487                 break;
1488             case AD_CORR:
1489                 hurtmarmor(mdef, AD_CORR);
1490                 tmp = 0;
1491                 break;
1492             case AD_DCAY:
1493                 if (pd == &mons[PM_WOOD_GOLEM] ||
1494                     pd == &mons[PM_LEATHER_GOLEM]) {
1495                         pline("%s falls to pieces!", Monnam(mdef));
1496                         xkilled(mdef,0);
1497                 }
1498                 hurtmarmor(mdef, AD_DCAY);
1499                 tmp = 0;
1500                 break;
1501             case AD_DRST:
1502             case AD_DRDX:
1503             case AD_DRCO:
1504                 if (!negated && !rn2(8)) {
1505                     Your("%s was poisoned!", mpoisons_subj(&youmonst, mattk));
1506                     if (resists_poison(mdef))
1507                         pline_The("poison doesn't seem to affect %s.",
1508                                 mon_nam(mdef));
1509                     else {
1510                         if (!rn2(10)) {
1511                             Your("poison was deadly...");
1512                             tmp = mdef->mhp;
1513                         } else tmp += rn1(10,6);
1514                     }
1515                 }
1516                 break;
1517             case AD_DRIN:
1518                 if (notonhead || !has_head(mdef->data)) {
1519                     pline("%s doesn't seem harmed.", Monnam(mdef));
1520                     tmp = 0;
1521                     if (!Unchanging && mdef->data == &mons[PM_GREEN_SLIME]) {
1522                         if (!Slimed) {
1523                             You("suck in some slime and don't feel very well.");
1524                             Slimed = 10L;
1525                         }
1526                     }
1527                     break;
1528                 }
1529                 if (m_slips_free(mdef, mattk)) break;
1530
1531                 if ((mdef->misc_worn_check & W_ARMH) && rn2(8)) {
1532                     pline("%s helmet blocks your attack to %s head.",
1533                           s_suffix(Monnam(mdef)), mhis(mdef));
1534                     break;
1535                 }
1536
1537                 You("eat %s brain!", s_suffix(mon_nam(mdef)));
1538                 u.uconduct.food++;
1539                 if (touch_petrifies(mdef->data) && !Stone_resistance && !Stoned) {
1540                     Stoned = 5;
1541                     killer_format = KILLED_BY_AN;
1542                     delayed_killer = mdef->data->mname;
1543                 }
1544                 if (!vegan(mdef->data))
1545                     u.uconduct.unvegan++;
1546                 if (!vegetarian(mdef->data))
1547                     violated_vegetarian();
1548                 if (mindless(mdef->data)) {
1549                     pline("%s doesn't notice.", Monnam(mdef));
1550                     break;
1551                 }
1552                 tmp += rnd(10);
1553                 morehungry(-rnd(30)); /* cannot choke */
1554                 if (ABASE(A_INT) < AMAX(A_INT)) {
1555                         ABASE(A_INT) += rnd(4);
1556                         if (ABASE(A_INT) > AMAX(A_INT))
1557                                 ABASE(A_INT) = AMAX(A_INT);
1558                         flags.botl = 1;
1559                 }
1560                 exercise(A_WIS, TRUE);
1561                 break;
1562             case AD_STCK:
1563                 if (!negated && !sticks(mdef->data))
1564                     u.ustuck = mdef; /* it's now stuck to you */
1565                 break;
1566             case AD_WRAP:
1567                 if (!sticks(mdef->data)) {
1568                     if (!u.ustuck && !rn2(10)) {
1569                         if (m_slips_free(mdef, mattk)) {
1570                             tmp = 0;
1571                         } else {
1572                             You("swing yourself around %s!",
1573                                   mon_nam(mdef));
1574                             u.ustuck = mdef;
1575                         }
1576                     } else if(u.ustuck == mdef) {
1577                         /* Monsters don't wear amulets of magical breathing */
1578                         if (is_pool(u.ux,u.uy) && !is_swimmer(mdef->data) &&
1579                             !amphibious(mdef->data)) {
1580                             You("drown %s...", mon_nam(mdef));
1581                             tmp = mdef->mhp;
1582                         } else if(mattk->aatyp == AT_HUGS)
1583                             pline("%s is being crushed.", Monnam(mdef));
1584                     } else {
1585                         tmp = 0;
1586                         if (flags.verbose)
1587                             You("brush against %s %s.",
1588                                 s_suffix(mon_nam(mdef)),
1589                                 mbodypart(mdef, LEG));
1590                     }
1591                 } else tmp = 0;
1592                 break;
1593             case AD_PLYS:
1594                 if (!negated && mdef->mcanmove && !rn2(3) && tmp < mdef->mhp) {
1595                     if (!Blind) pline("%s is frozen by you!", Monnam(mdef));
1596                     mdef->mcanmove = 0;
1597                     mdef->mfrozen = rnd(10);
1598                 }
1599                 break;
1600             case AD_SLEE:
1601                 if (!negated && !mdef->msleeping &&
1602                             sleep_monst(mdef, rnd(10), -1)) {
1603                     if (!Blind)
1604                         pline("%s is put to sleep by you!", Monnam(mdef));
1605                     slept_monst(mdef);
1606                 }
1607                 break;
1608             case AD_SLIM:
1609                 if (negated) break;     /* physical damage only */
1610                 if (!rn2(4) && !flaming(mdef->data) &&
1611                                 mdef->data != &mons[PM_GREEN_SLIME]) {
1612                     You("turn %s into slime.", mon_nam(mdef));
1613                     (void) newcham(mdef, &mons[PM_GREEN_SLIME], FALSE, FALSE);
1614                     tmp = 0;
1615                 }
1616                 break;
1617             case AD_ENCH:       /* KMH -- remove enchantment (disenchanter) */
1618                 /* there's no msomearmor() function, so just do damage */
1619              /* if (negated) break; */
1620                 break;
1621             case AD_SLOW:
1622                 if (!negated && mdef->mspeed != MSLOW) {
1623                     unsigned int oldspeed = mdef->mspeed;
1624
1625                     mon_adjust_speed(mdef, -1, (struct obj *)0);
1626                     if (mdef->mspeed != oldspeed && canseemon(mdef))
1627                         pline("%s slows down.", Monnam(mdef));
1628                 }
1629                 break;
1630             case AD_CONF:
1631                 if (!mdef->mconf) {
1632                     if (canseemon(mdef))
1633                         pline("%s looks confused.", Monnam(mdef));
1634                     mdef->mconf = 1;
1635                 }
1636                 break;
1637             default:    tmp = 0;
1638                 break;
1639         }
1640
1641         mdef->mstrategy &= ~STRAT_WAITFORU; /* in case player is very fast */
1642         if((mdef->mhp -= tmp) < 1) {
1643             if (mdef->mtame && !cansee(mdef->mx,mdef->my)) {
1644                 You_feel("embarrassed for a moment.");
1645                 if (tmp) xkilled(mdef, 0); /* !tmp but hp<1: already killed */
1646             } else if (!flags.verbose) {
1647                 You("destroy it!");
1648                 if (tmp) xkilled(mdef, 0);
1649             } else
1650                 if (tmp) killed(mdef);
1651             return(2);
1652         }
1653         return(1);
1654 }
1655
1656 STATIC_OVL int
1657 explum(mdef, mattk)
1658 register struct monst *mdef;
1659 register struct attack *mattk;
1660 {
1661         register int tmp = d((int)mattk->damn, (int)mattk->damd);
1662
1663         You("explode!");
1664         switch(mattk->adtyp) {
1665             boolean resistance; /* only for cold/fire/elec */
1666
1667             case AD_BLND:
1668                 if (!resists_blnd(mdef)) {
1669                     pline("%s is blinded by your flash of light!", Monnam(mdef));
1670                     mdef->mblinded = min((int)mdef->mblinded + tmp, 127);
1671                     mdef->mcansee = 0;
1672                 }
1673                 break;
1674             case AD_HALU:
1675                 if (haseyes(mdef->data) && mdef->mcansee) {
1676                     pline("%s is affected by your flash of light!",
1677                           Monnam(mdef));
1678                     mdef->mconf = 1;
1679                 }
1680                 break;
1681             case AD_COLD:
1682                 resistance = resists_cold(mdef);
1683                 goto common;
1684             case AD_FIRE:
1685                 resistance = resists_fire(mdef);
1686                 goto common;
1687             case AD_ELEC:
1688                 resistance = resists_elec(mdef);
1689 common:
1690                 if (!resistance) {
1691                     pline("%s gets blasted!", Monnam(mdef));
1692                     mdef->mhp -= tmp;
1693                     if (mdef->mhp <= 0) {
1694                          killed(mdef);
1695                          return(2);
1696                     }
1697                 } else {
1698                     shieldeff(mdef->mx, mdef->my);
1699                     if (is_golem(mdef->data))
1700                         golemeffects(mdef, (int)mattk->adtyp, tmp);
1701                     else
1702                         pline_The("blast doesn't seem to affect %s.",
1703                                 mon_nam(mdef));
1704                 }
1705                 break;
1706             default:
1707                 break;
1708         }
1709         return(1);
1710 }
1711
1712 STATIC_OVL void
1713 start_engulf(mdef)
1714 struct monst *mdef;
1715 {
1716         if (!Invisible) {
1717                 map_location(u.ux, u.uy, TRUE);
1718                 tmp_at(DISP_ALWAYS, mon_to_glyph(&youmonst));
1719                 tmp_at(mdef->mx, mdef->my);
1720         }
1721         You("engulf %s!", mon_nam(mdef));
1722         delay_output();
1723         delay_output();
1724 }
1725
1726 STATIC_OVL void
1727 end_engulf()
1728 {
1729         if (!Invisible) {
1730                 tmp_at(DISP_END, 0);
1731                 newsym(u.ux, u.uy);
1732         }
1733 }
1734
1735 STATIC_OVL int
1736 gulpum(mdef,mattk)
1737 register struct monst *mdef;
1738 register struct attack *mattk;
1739 {
1740         register int tmp;
1741         register int dam = d((int)mattk->damn, (int)mattk->damd);
1742         struct obj *otmp;
1743         /* Not totally the same as for real monsters.  Specifically, these
1744          * don't take multiple moves.  (It's just too hard, for too little
1745          * result, to program monsters which attack from inside you, which
1746          * would be necessary if done accurately.)  Instead, we arbitrarily
1747          * kill the monster immediately for AD_DGST and we regurgitate them
1748          * after exactly 1 round of attack otherwise.  -KAA
1749          */
1750
1751         if(mdef->data->msize >= MZ_HUGE) return 0;
1752
1753         if(u.uhunger < 1500 && !u.uswallow) {
1754             for (otmp = mdef->minvent; otmp; otmp = otmp->nobj)
1755                 (void) snuff_lit(otmp);
1756
1757             if(!touch_petrifies(mdef->data) || Stone_resistance) {
1758 #ifdef LINT     /* static char msgbuf[BUFSZ]; */
1759                 char msgbuf[BUFSZ];
1760 #else
1761                 static char msgbuf[BUFSZ];
1762 #endif
1763                 start_engulf(mdef);
1764                 switch(mattk->adtyp) {
1765                     case AD_DGST:
1766                         /* eating a Rider or its corpse is fatal */
1767                         if (is_rider(mdef->data)) {
1768                          pline("Unfortunately, digesting any of it is fatal.");
1769                             end_engulf();
1770                             Sprintf(msgbuf, "unwisely tried to eat %s",
1771                                     mdef->data->mname);
1772                             killer = msgbuf;
1773                             killer_format = NO_KILLER_PREFIX;
1774                             done(DIED);
1775                             return 0;           /* lifesaved */
1776                         }
1777
1778                         if (Slow_digestion) {
1779                             dam = 0;
1780                             break;
1781                         }
1782
1783                         /* KMH, conduct */
1784                         u.uconduct.food++;
1785                         if (!vegan(mdef->data))
1786                              u.uconduct.unvegan++;
1787                         if (!vegetarian(mdef->data))
1788                              violated_vegetarian();
1789
1790                         /* Use up amulet of life saving */
1791                         if (!!(otmp = mlifesaver(mdef))) m_useup(mdef, otmp);
1792
1793                         newuhs(FALSE);
1794                         xkilled(mdef,2);
1795                         if (mdef->mhp > 0) { /* monster lifesaved */
1796                             You("hurriedly regurgitate the sizzling in your %s.",
1797                                 body_part(STOMACH));
1798                         } else {
1799                             tmp = 1 + (mdef->data->cwt >> 8);
1800                             if (corpse_chance(mdef, &youmonst, TRUE) &&
1801                                 !(mvitals[monsndx(mdef->data)].mvflags &
1802                                   G_NOCORPSE)) {
1803                                 /* nutrition only if there can be a corpse */
1804                                 u.uhunger += (mdef->data->cnutrit+1) / 2;
1805                             } else tmp = 0;
1806                             Sprintf(msgbuf, "You totally digest %s.",
1807                                             mon_nam(mdef));
1808                             if (tmp != 0) {
1809                                 /* setting afternmv = end_engulf is tempting,
1810                                  * but will cause problems if the player is
1811                                  * attacked (which uses his real location) or
1812                                  * if his See_invisible wears off
1813                                  */
1814                                 You("digest %s.", mon_nam(mdef));
1815                                 if (Slow_digestion) tmp *= 2;
1816                                 nomul(-tmp);
1817                                 nomovemsg = msgbuf;
1818                             } else pline("%s", msgbuf);
1819                             if (mdef->data == &mons[PM_GREEN_SLIME]) {
1820                                 Sprintf(msgbuf, "%s isn't sitting well with you.",
1821                                         The(mdef->data->mname));
1822                                 if (!Unchanging) {
1823                                         Slimed = 5L;
1824                                         flags.botl = 1;
1825                                 }
1826                             } else
1827                             exercise(A_CON, TRUE);
1828                         }
1829                         end_engulf();
1830                         return(2);
1831                     case AD_PHYS:
1832                         if (youmonst.data == &mons[PM_FOG_CLOUD]) {
1833                             pline("%s is laden with your moisture.",
1834                                   Monnam(mdef));
1835                             if (amphibious(mdef->data) &&
1836                                 !flaming(mdef->data)) {
1837                                 dam = 0;
1838                                 pline("%s seems unharmed.", Monnam(mdef));
1839                             }
1840                         } else
1841                             pline("%s is pummeled with your debris!",
1842                                   Monnam(mdef));
1843                         break;
1844                     case AD_ACID:
1845                         pline("%s is covered with your goo!", Monnam(mdef));
1846                         if (resists_acid(mdef)) {
1847                             pline("It seems harmless to %s.", mon_nam(mdef));
1848                             dam = 0;
1849                         }
1850                         break;
1851                     case AD_BLND:
1852                         if (can_blnd(&youmonst, mdef, mattk->aatyp, (struct obj *)0)) {
1853                             if (mdef->mcansee)
1854                                 pline("%s can't see in there!", Monnam(mdef));
1855                             mdef->mcansee = 0;
1856                             dam += mdef->mblinded;
1857                             if (dam > 127) dam = 127;
1858                             mdef->mblinded = dam;
1859                         }
1860                         dam = 0;
1861                         break;
1862                     case AD_ELEC:
1863                         if (rn2(2)) {
1864                             pline_The("air around %s crackles with electricity.", mon_nam(mdef));
1865                             if (resists_elec(mdef)) {
1866                                 pline("%s seems unhurt.", Monnam(mdef));
1867                                 dam = 0;
1868                             }
1869                             golemeffects(mdef,(int)mattk->adtyp,dam);
1870                         } else dam = 0;
1871                         break;
1872                     case AD_COLD:
1873                         if (rn2(2)) {
1874                             if (resists_cold(mdef)) {
1875                                 pline("%s seems mildly chilly.", Monnam(mdef));
1876                                 dam = 0;
1877                             } else
1878                                 pline("%s is freezing to death!",Monnam(mdef));
1879                             golemeffects(mdef,(int)mattk->adtyp,dam);
1880                         } else dam = 0;
1881                         break;
1882                     case AD_FIRE:
1883                         if (rn2(2)) {
1884                             if (resists_fire(mdef)) {
1885                                 pline("%s seems mildly hot.", Monnam(mdef));
1886                                 dam = 0;
1887                             } else
1888                                 pline("%s is burning to a crisp!",Monnam(mdef));
1889                             golemeffects(mdef,(int)mattk->adtyp,dam);
1890                         } else dam = 0;
1891                         break;
1892                 }
1893                 end_engulf();
1894                 if ((mdef->mhp -= dam) <= 0) {
1895                     killed(mdef);
1896                     if (mdef->mhp <= 0) /* not lifesaved */
1897                         return(2);
1898                 }
1899                 You("%s %s!", is_animal(youmonst.data) ? "regurgitate"
1900                         : "expel", mon_nam(mdef));
1901                 if (Slow_digestion || is_animal(youmonst.data)) {
1902                     pline("Obviously, you didn't like %s taste.",
1903                           s_suffix(mon_nam(mdef)));
1904                 }
1905             } else {
1906                 char kbuf[BUFSZ];
1907
1908                 You("bite into %s.", mon_nam(mdef));
1909                 Sprintf(kbuf, "swallowing %s whole", an(mdef->data->mname));
1910                 instapetrify(kbuf);
1911             }
1912         }
1913         return(0);
1914 }
1915
1916 void
1917 missum(mdef,mattk)
1918 register struct monst *mdef;
1919 register struct attack *mattk;
1920 {
1921         if (could_seduce(&youmonst, mdef, mattk))
1922                 You("pretend to be friendly to %s.", mon_nam(mdef));
1923         else if(canspotmon(mdef) && flags.verbose)
1924                 You("miss %s.", mon_nam(mdef));
1925         else
1926                 You("miss it.");
1927         if (!mdef->msleeping && mdef->mcanmove)
1928                 wakeup(mdef);
1929 }
1930
1931 STATIC_OVL boolean
1932 hmonas(mon, tmp)                /* attack monster as a monster. */
1933 register struct monst *mon;
1934 register int tmp;
1935 {
1936         struct attack *mattk, alt_attk;
1937         int     i, sum[NATTK], hittmp = 0;
1938         int     nsum = 0;
1939         int     dhit = 0;
1940
1941         for(i = 0; i < NATTK; i++) {
1942
1943             sum[i] = 0;
1944             mattk = getmattk(youmonst.data, i, sum, &alt_attk);
1945             switch(mattk->aatyp) {
1946                 case AT_WEAP:
1947 use_weapon:
1948         /* Certain monsters don't use weapons when encountered as enemies,
1949          * but players who polymorph into them have hands or claws and thus
1950          * should be able to use weapons.  This shouldn't prohibit the use
1951          * of most special abilities, either.
1952          */
1953         /* Potential problem: if the monster gets multiple weapon attacks,
1954          * we currently allow the player to get each of these as a weapon
1955          * attack.  Is this really desirable?
1956          */
1957                         if (uwep) {
1958                             hittmp = hitval(uwep, mon);
1959                             hittmp += weapon_hit_bonus(uwep);
1960                             tmp += hittmp;
1961                         }
1962                         dhit = (tmp > (dieroll = rnd(20)) || u.uswallow);
1963                         /* KMH -- Don't accumulate to-hit bonuses */
1964                         if (uwep) tmp -= hittmp;
1965                         /* Enemy dead, before any special abilities used */
1966                         if (!known_hitum(mon,&dhit,mattk)) {
1967                             sum[i] = 2;
1968                             break;
1969                         } else sum[i] = dhit;
1970                         /* might be a worm that gets cut in half */
1971                         if (m_at(u.ux+u.dx, u.uy+u.dy) != mon) return((boolean)(nsum != 0));
1972                         /* Do not print "You hit" message, since known_hitum
1973                          * already did it.
1974                          */
1975                         if (dhit && mattk->adtyp != AD_SPEL
1976                                 && mattk->adtyp != AD_PHYS)
1977                                 sum[i] = damageum(mon,mattk);
1978                         break;
1979                 case AT_CLAW:
1980                         if (i==0 && uwep && !cantwield(youmonst.data)) goto use_weapon;
1981 #ifdef SEDUCE
1982                         /* succubi/incubi are humanoid, but their _second_
1983                          * attack is AT_CLAW, not their first...
1984                          */
1985                         if (i==1 && uwep && (u.umonnum == PM_SUCCUBUS ||
1986                                 u.umonnum == PM_INCUBUS)) goto use_weapon;
1987 #endif
1988                 case AT_KICK:
1989                 case AT_BITE:
1990                 case AT_STNG:
1991                 case AT_TUCH:
1992                 case AT_BUTT:
1993                 case AT_TENT:
1994                         if (i==0 && uwep && (youmonst.data->mlet==S_LICH)) goto use_weapon;
1995                         if ((dhit = (tmp > rnd(20) || u.uswallow)) != 0) {
1996                             int compat;
1997
1998                             if (!u.uswallow &&
1999                                 (compat=could_seduce(&youmonst, mon, mattk))) {
2000                                 You("%s %s %s.",
2001                                     mon->mcansee && haseyes(mon->data)
2002                                     ? "smile at" : "talk to",
2003                                     mon_nam(mon),
2004                                     compat == 2 ? "engagingly":"seductively");
2005                                 /* doesn't anger it; no wakeup() */
2006                                 sum[i] = damageum(mon, mattk);
2007                                 break;
2008                             }
2009                             wakeup(mon);
2010                             /* maybe this check should be in damageum()? */
2011                             if (mon->data == &mons[PM_SHADE] &&
2012                                         !(mattk->aatyp == AT_KICK &&
2013                                             uarmf && uarmf->blessed)) {
2014                                 Your("attack passes harmlessly through %s.",
2015                                     mon_nam(mon));
2016                                 break;
2017                             }
2018                             if (mattk->aatyp == AT_KICK)
2019                                     You("kick %s.", mon_nam(mon));
2020                             else if (mattk->aatyp == AT_BITE)
2021                                     You("bite %s.", mon_nam(mon));
2022                             else if (mattk->aatyp == AT_STNG)
2023                                     You("sting %s.", mon_nam(mon));
2024                             else if (mattk->aatyp == AT_BUTT)
2025                                     You("butt %s.", mon_nam(mon));
2026                             else if (mattk->aatyp == AT_TUCH)
2027                                     You("touch %s.", mon_nam(mon));
2028                             else if (mattk->aatyp == AT_TENT)
2029                                     Your("tentacles suck %s.", mon_nam(mon));
2030                             else You("hit %s.", mon_nam(mon));
2031                             sum[i] = damageum(mon, mattk);
2032                         } else
2033                             missum(mon, mattk);
2034                         break;
2035
2036                 case AT_HUGS:
2037                         /* automatic if prev two attacks succeed, or if
2038                          * already grabbed in a previous attack
2039                          */
2040                         dhit = 1;
2041                         wakeup(mon);
2042                         if (mon->data == &mons[PM_SHADE])
2043                             Your("hug passes harmlessly through %s.",
2044                                 mon_nam(mon));
2045                         else if (!sticks(mon->data) && !u.uswallow) {
2046                             if (mon==u.ustuck) {
2047                                 pline("%s is being %s.", Monnam(mon),
2048                                     u.umonnum==PM_ROPE_GOLEM ? "choked":
2049                                     "crushed");
2050                                 sum[i] = damageum(mon, mattk);
2051                             } else if(i >= 2 && sum[i-1] && sum[i-2]) {
2052                                 You("grab %s!", mon_nam(mon));
2053                                 u.ustuck = mon;
2054                                 sum[i] = damageum(mon, mattk);
2055                             }
2056                         }
2057                         break;
2058
2059                 case AT_EXPL:   /* automatic hit if next to */
2060                         dhit = -1;
2061                         wakeup(mon);
2062                         sum[i] = explum(mon, mattk);
2063                         break;
2064
2065                 case AT_ENGL:
2066                         if((dhit = (tmp > rnd(20+i)))) {
2067                                 wakeup(mon);
2068                                 if (mon->data == &mons[PM_SHADE])
2069                                     Your("attempt to surround %s is harmless.",
2070                                         mon_nam(mon));
2071                                 else {
2072                                     sum[i]= gulpum(mon,mattk);
2073                                     if (sum[i] == 2 &&
2074                                             (mon->data->mlet == S_ZOMBIE ||
2075                                                 mon->data->mlet == S_MUMMY) &&
2076                                             rn2(5) &&
2077                                             !Sick_resistance) {
2078                                         You_feel("%ssick.",
2079                                             (Sick) ? "very " : "");
2080                                         mdamageu(mon, rnd(8));
2081                                     }
2082                                 }
2083                         } else
2084                                 missum(mon, mattk);
2085                         break;
2086
2087                 case AT_MAGC:
2088                         /* No check for uwep; if wielding nothing we want to
2089                          * do the normal 1-2 points bare hand damage...
2090                          */
2091                         if (i==0 && (youmonst.data->mlet==S_KOBOLD
2092                                 || youmonst.data->mlet==S_ORC
2093                                 || youmonst.data->mlet==S_GNOME
2094                                 )) goto use_weapon;
2095
2096                 case AT_NONE:
2097                 case AT_BOOM:
2098                         continue;
2099                         /* Not break--avoid passive attacks from enemy */
2100
2101                 case AT_BREA:
2102                 case AT_SPIT:
2103                 case AT_GAZE:   /* all done using #monster command */
2104                         dhit = 0;
2105                         break;
2106
2107                 default: /* Strange... */
2108                         impossible("strange attack of yours (%d)",
2109                                  mattk->aatyp);
2110             }
2111             if (dhit == -1) {
2112                 u.mh = -1;      /* dead in the current form */
2113                 rehumanize();
2114             }
2115             if (sum[i] == 2)
2116                 return((boolean)passive(mon, 1, 0, mattk->aatyp));
2117                                                         /* defender dead */
2118             else {
2119                 (void) passive(mon, sum[i], 1, mattk->aatyp);
2120                 nsum |= sum[i];
2121             }
2122             if (!Upolyd)
2123                 break; /* No extra attacks if no longer a monster */
2124             if (multi < 0)
2125                 break; /* If paralyzed while attacking, i.e. floating eye */
2126         }
2127         return((boolean)(nsum != 0));
2128 }
2129
2130 /*      Special (passive) attacks on you by monsters done here.         */
2131
2132 int
2133 passive(mon, mhit, malive, aatyp)
2134 register struct monst *mon;
2135 register boolean mhit;
2136 register int malive;
2137 uchar aatyp;
2138 {
2139         register struct permonst *ptr = mon->data;
2140         register int i, tmp;
2141
2142         for(i = 0; ; i++) {
2143             if(i >= NATTK) return(malive | mhit);       /* no passive attacks */
2144             if(ptr->mattk[i].aatyp == AT_NONE) break;   /* try this one */
2145         }
2146         /* Note: tmp not always used */
2147         if (ptr->mattk[i].damn)
2148             tmp = d((int)ptr->mattk[i].damn, (int)ptr->mattk[i].damd);
2149         else if(ptr->mattk[i].damd)
2150             tmp = d((int)mon->m_lev+1, (int)ptr->mattk[i].damd);
2151         else
2152             tmp = 0;
2153
2154 /*      These affect you even if they just died */
2155
2156         switch(ptr->mattk[i].adtyp) {
2157
2158           case AD_ACID:
2159             if(mhit && rn2(2)) {
2160                 if (Blind || !flags.verbose) You("are splashed!");
2161                 else    You("are splashed by %s acid!",
2162                                         s_suffix(mon_nam(mon)));
2163
2164                 if (!Acid_resistance)
2165                         mdamageu(mon, tmp);
2166                 if(!rn2(30)) erode_armor(&youmonst, TRUE);
2167             }
2168             if (mhit) {
2169                 if (aatyp == AT_KICK) {
2170                     if (uarmf && !rn2(6))
2171                         (void)rust_dmg(uarmf, xname(uarmf), 3, TRUE, &youmonst);
2172                 } else if (aatyp == AT_WEAP || aatyp == AT_CLAW ||
2173                            aatyp == AT_MAGC || aatyp == AT_TUCH)
2174                     passive_obj(mon, (struct obj*)0, &(ptr->mattk[i]));
2175             }
2176             exercise(A_STR, FALSE);
2177             break;
2178           case AD_STON:
2179             if (mhit) {         /* successful attack */
2180                 long protector = attk_protection((int)aatyp);
2181
2182                 /* hero using monsters' AT_MAGC attack is hitting hand to
2183                    hand rather than casting a spell */
2184                 if (aatyp == AT_MAGC) protector = W_ARMG;
2185
2186                 if (protector == 0L ||          /* no protection */
2187                         (protector == W_ARMG && !uarmg && !uwep) ||
2188                         (protector == W_ARMF && !uarmf) ||
2189                         (protector == W_ARMH && !uarmh) ||
2190                         (protector == (W_ARMC|W_ARMG) && (!uarmc || !uarmg))) {
2191                     if (!Stone_resistance &&
2192                             !(poly_when_stoned(youmonst.data) &&
2193                                 polymon(PM_STONE_GOLEM))) {
2194                         You("turn to stone...");
2195                         done_in_by(mon);
2196                         return 2;
2197                     }
2198                 }
2199             }
2200             break;
2201           case AD_RUST:
2202             if(mhit && !mon->mcan) {
2203                 if (aatyp == AT_KICK) {
2204                     if (uarmf)
2205                         (void)rust_dmg(uarmf, xname(uarmf), 1, TRUE, &youmonst);
2206                 } else if (aatyp == AT_WEAP || aatyp == AT_CLAW ||
2207                            aatyp == AT_MAGC || aatyp == AT_TUCH)
2208                     passive_obj(mon, (struct obj*)0, &(ptr->mattk[i]));
2209             }
2210             break;
2211           case AD_CORR:
2212             if(mhit && !mon->mcan) {
2213                 if (aatyp == AT_KICK) {
2214                     if (uarmf)
2215                         (void)rust_dmg(uarmf, xname(uarmf), 3, TRUE, &youmonst);
2216                 } else if (aatyp == AT_WEAP || aatyp == AT_CLAW ||
2217                            aatyp == AT_MAGC || aatyp == AT_TUCH)
2218                     passive_obj(mon, (struct obj*)0, &(ptr->mattk[i]));
2219             }
2220             break;
2221           case AD_MAGM:
2222             /* wrath of gods for attacking Oracle */
2223             if(Antimagic) {
2224                 shieldeff(u.ux, u.uy);
2225                 pline("A hail of magic missiles narrowly misses you!");
2226             } else {
2227                 You("are hit by magic missiles appearing from thin air!");
2228                 mdamageu(mon, tmp);
2229             }
2230             break;
2231           case AD_ENCH: /* KMH -- remove enchantment (disenchanter) */
2232             if (mhit) {
2233                 struct obj *obj = (struct obj *)0;
2234
2235                 if (aatyp == AT_KICK) {
2236                     obj = uarmf;
2237                     if (!obj) break;
2238                 } else if (aatyp == AT_BITE || aatyp == AT_BUTT ||
2239                            (aatyp >= AT_STNG && aatyp < AT_WEAP)) {
2240                     break;              /* no object involved */
2241                 }
2242                 passive_obj(mon, obj, &(ptr->mattk[i]));
2243             }
2244             break;
2245           default:
2246             break;
2247         }
2248
2249 /*      These only affect you if they still live */
2250
2251         if(malive && !mon->mcan && rn2(3)) {
2252
2253             switch(ptr->mattk[i].adtyp) {
2254
2255               case AD_PLYS:
2256                 if(ptr == &mons[PM_FLOATING_EYE]) {
2257                     if (!canseemon(mon)) {
2258                         break;
2259                     }
2260                     if(mon->mcansee) {
2261                         if (ureflects("%s gaze is reflected by your %s.",
2262                                     s_suffix(Monnam(mon))))
2263                             ;
2264                         else if (Free_action)
2265                             You("momentarily stiffen under %s gaze!",
2266                                     s_suffix(mon_nam(mon)));
2267                         else {
2268                             You("are frozen by %s gaze!",
2269                                   s_suffix(mon_nam(mon)));
2270                             nomul((ACURR(A_WIS) > 12 || rn2(4)) ? -tmp : -127);
2271                         }
2272                     } else {
2273                         pline("%s cannot defend itself.",
2274                                 Adjmonnam(mon,"blind"));
2275                         if(!rn2(500)) change_luck(-1);
2276                     }
2277                 } else if (Free_action) {
2278                     You("momentarily stiffen.");
2279                 } else { /* gelatinous cube */
2280                     You("are frozen by %s!", mon_nam(mon));
2281                     nomovemsg = 0;      /* default: "you can move again" */
2282                     nomul(-tmp);
2283                     exercise(A_DEX, FALSE);
2284                 }
2285                 break;
2286               case AD_COLD:             /* brown mold or blue jelly */
2287                 if(monnear(mon, u.ux, u.uy)) {
2288                     if(Cold_resistance) {
2289                         shieldeff(u.ux, u.uy);
2290                         You_feel("a mild chill.");
2291                         ugolemeffects(AD_COLD, tmp);
2292                         break;
2293                     }
2294                     You("are suddenly very cold!");
2295                     mdamageu(mon, tmp);
2296                 /* monster gets stronger with your heat! */
2297                     mon->mhp += tmp / 2;
2298                     if (mon->mhpmax < mon->mhp) mon->mhpmax = mon->mhp;
2299                 /* at a certain point, the monster will reproduce! */
2300                     if(mon->mhpmax > ((int) (mon->m_lev+1) * 8))
2301                         (void)split_mon(mon, &youmonst);
2302                 }
2303                 break;
2304               case AD_STUN:             /* specifically yellow mold */
2305                 if(!Stunned)
2306                     make_stunned((long)tmp, TRUE);
2307                 break;
2308               case AD_FIRE:
2309                 if(monnear(mon, u.ux, u.uy)) {
2310                     if(Fire_resistance) {
2311                         shieldeff(u.ux, u.uy);
2312                         You_feel("mildly warm.");
2313                         ugolemeffects(AD_FIRE, tmp);
2314                         break;
2315                     }
2316                     You("are suddenly very hot!");
2317                     mdamageu(mon, tmp);
2318                 }
2319                 break;
2320               case AD_ELEC:
2321                 if(Shock_resistance) {
2322                     shieldeff(u.ux, u.uy);
2323                     You_feel("a mild tingle.");
2324                     ugolemeffects(AD_ELEC, tmp);
2325                     break;
2326                 }
2327                 You("are jolted with electricity!");
2328                 mdamageu(mon, tmp);
2329                 break;
2330               default:
2331                 break;
2332             }
2333         }
2334         return(malive | mhit);
2335 }
2336
2337 /*
2338  * Special (passive) attacks on an attacking object by monsters done here.
2339  * Assumes the attack was successful.
2340  */
2341 void
2342 passive_obj(mon, obj, mattk)
2343 register struct monst *mon;
2344 register struct obj *obj;       /* null means pick uwep, uswapwep or uarmg */
2345 struct attack *mattk;           /* null means we find one internally */
2346 {
2347         register struct permonst *ptr = mon->data;
2348         register int i;
2349
2350         /* if caller hasn't specified an object, use uwep, uswapwep or uarmg */
2351         if (!obj) {
2352             obj = (u.twoweap && uswapwep && !rn2(2)) ? uswapwep : uwep;
2353             if (!obj && mattk->adtyp == AD_ENCH)
2354                 obj = uarmg;            /* no weapon? then must be gloves */
2355             if (!obj) return;           /* no object to affect */
2356         }
2357
2358         /* if caller hasn't specified an attack, find one */
2359         if (!mattk) {
2360             for(i = 0; ; i++) {
2361                 if(i >= NATTK) return;  /* no passive attacks */
2362                 if(ptr->mattk[i].aatyp == AT_NONE) break; /* try this one */
2363             }
2364             mattk = &(ptr->mattk[i]);
2365         }
2366
2367         switch(mattk->adtyp) {
2368
2369         case AD_ACID:
2370             if(!rn2(6)) {
2371                 erode_obj(obj, TRUE, FALSE);
2372             }
2373             break;
2374         case AD_RUST:
2375             if(!mon->mcan) {
2376                 erode_obj(obj, FALSE, FALSE);
2377             }
2378             break;
2379         case AD_CORR:
2380             if(!mon->mcan) {
2381                 erode_obj(obj, TRUE, FALSE);
2382             }
2383             break;
2384         case AD_ENCH:
2385             if (!mon->mcan) {
2386                 if (drain_item(obj) && carried(obj) &&
2387                     (obj->known || obj->oclass == ARMOR_CLASS)) {
2388                     Your("%s less effective.", aobjnam(obj, "seem"));
2389                 }
2390                 break;
2391             }
2392           default:
2393             break;
2394         }
2395
2396         if (carried(obj)) update_inventory();
2397 }
2398
2399 /* Note: caller must ascertain mtmp is mimicking... */
2400 void
2401 stumble_onto_mimic(mtmp)
2402 struct monst *mtmp;
2403 {
2404         const char *fmt = "Wait!  That's %s!",
2405                    *generic = "a monster",
2406                    *what = 0;
2407
2408         if(!u.ustuck && !mtmp->mflee && dmgtype(mtmp->data,AD_STCK))
2409             u.ustuck = mtmp;
2410
2411         if (Blind) {
2412             if (!Blind_telepat)
2413                 what = generic;         /* with default fmt */
2414             else if (mtmp->m_ap_type == M_AP_MONSTER)
2415                 what = a_monnam(mtmp);  /* differs from what was sensed */
2416         } else {
2417             int glyph = levl[u.ux+u.dx][u.uy+u.dy].glyph;
2418
2419             if (glyph_is_cmap(glyph) &&
2420                     (glyph_to_cmap(glyph) == S_hcdoor ||
2421                      glyph_to_cmap(glyph) == S_vcdoor))
2422                 fmt = "The door actually was %s!";
2423             else if (glyph_is_object(glyph) &&
2424                     glyph_to_obj(glyph) == GOLD_PIECE)
2425                 fmt = "That gold was %s!";
2426
2427             /* cloned Wiz starts out mimicking some other monster and
2428                might make himself invisible before being revealed */
2429             if (mtmp->minvis && !See_invisible)
2430                 what = generic;
2431             else
2432                 what = a_monnam(mtmp);
2433         }
2434         if (what) pline(fmt, what);
2435
2436         wakeup(mtmp);   /* clears mimicking */
2437 }
2438
2439 STATIC_OVL void
2440 nohandglow(mon)
2441 struct monst *mon;
2442 {
2443         char *hands=makeplural(body_part(HAND));
2444
2445         if (!u.umconf || mon->mconf) return;
2446         if (u.umconf == 1) {
2447                 if (Blind)
2448                         Your("%s stop tingling.", hands);
2449                 else
2450                         Your("%s stop glowing %s.", hands, hcolor(NH_RED));
2451         } else {
2452                 if (Blind)
2453                         pline_The("tingling in your %s lessens.", hands);
2454                 else
2455                         Your("%s no longer glow so brightly %s.", hands,
2456                                 hcolor(NH_RED));
2457         }
2458         u.umconf--;
2459 }
2460
2461 int
2462 flash_hits_mon(mtmp, otmp)
2463 struct monst *mtmp;
2464 struct obj *otmp;       /* source of flash */
2465 {
2466         int tmp, amt, res = 0, useeit = canseemon(mtmp);
2467
2468         if (mtmp->msleeping) {
2469             mtmp->msleeping = 0;
2470             if (useeit) {
2471                 pline_The("flash awakens %s.", mon_nam(mtmp));
2472                 res = 1;
2473             }
2474         } else if (mtmp->data->mlet != S_LIGHT) {
2475             if (!resists_blnd(mtmp)) {
2476                 tmp = dist2(otmp->ox, otmp->oy, mtmp->mx, mtmp->my);
2477                 if (useeit) {
2478                     pline("%s is blinded by the flash!", Monnam(mtmp));
2479                     res = 1;
2480                 }
2481                 if (mtmp->data == &mons[PM_GREMLIN]) {
2482                     /* Rule #1: Keep them out of the light. */
2483                     amt = otmp->otyp == WAN_LIGHT ? d(1 + otmp->spe, 4) :
2484                           rn2(min(mtmp->mhp,4));
2485                     pline("%s %s!", Monnam(mtmp), amt > mtmp->mhp / 2 ?
2486                           "wails in agony" : "cries out in pain");
2487                     if ((mtmp->mhp -= amt) <= 0) {
2488                         if (flags.mon_moving)
2489                             monkilled(mtmp, (char *)0, AD_BLND);
2490                         else
2491                             killed(mtmp);
2492                     } else if (cansee(mtmp->mx,mtmp->my) && !canspotmon(mtmp)){
2493                         map_invisible(mtmp->mx, mtmp->my);
2494                     }
2495                 }
2496                 if (mtmp->mhp > 0) {
2497                     if (!flags.mon_moving) setmangry(mtmp);
2498                     if (tmp < 9 && !mtmp->isshk && rn2(4)) {
2499                         if (rn2(4))
2500                             monflee(mtmp, rnd(100), FALSE, TRUE);
2501                         else
2502                             monflee(mtmp, 0, FALSE, TRUE);
2503                     }
2504                     mtmp->mcansee = 0;
2505                     mtmp->mblinded = (tmp < 3) ? 0 : rnd(1 + 50/tmp);
2506                 }
2507             }
2508         }
2509         return res;
2510 }
2511
2512 /*uhitm.c*/