OSDN Git Service

update year to 2020
[jnethack/source.git] / src / mthrowu.c
1 /* NetHack 3.6  mthrowu.c       $NHDT-Date: 1573688695 2019/11/13 23:44:55 $  $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.86 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Pasi Kallinen, 2016. */
4 /* NetHack may be freely redistributed.  See license for details. */
5
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000  */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2020            */
9 /* JNetHack may be freely redistributed.  See license for details. */
10
11 #include "hack.h"
12
13 STATIC_DCL int FDECL(monmulti, (struct monst *, struct obj *, struct obj *));
14 STATIC_DCL void FDECL(monshoot, (struct monst *, struct obj *, struct obj *));
15 STATIC_DCL int FDECL(drop_throw, (struct obj *, BOOLEAN_P, int, int));
16 STATIC_DCL boolean FDECL(m_lined_up, (struct monst *, struct monst *));
17
18 #define URETREATING(x, y) \
19     (distmin(u.ux, u.uy, x, y) > distmin(u.ux0, u.uy0, x, y))
20
21 #define POLE_LIM 5 /* How far monsters can use pole-weapons */
22
23 #define PET_MISSILE_RANGE2 36 /* Square of distance within which pets shoot */
24
25 /*
26  * Keep consistent with breath weapons in zap.c, and AD_* in monattk.h.
27  */
28 STATIC_OVL NEARDATA const char *breathwep[] = {
29 #if 0 /*JP:T*/
30     "fragments", "fire", "frost", "sleep gas", "a disintegration blast",
31     "lightning", "poison gas", "acid", "strange breath #8",
32     "strange breath #9"
33 #else
34     "\94j\95Ð", "\89\8a", "\97â\8bC", "\90\87\96°\83K\83X", "\95ª\89ð\82Ì\91§",
35     "\88î\8dÈ", "\93Å\82Ì\91§", "\8e_", "strange breath #8",
36     "strange breath #9"
37 #endif
38 };
39
40 extern boolean notonhead; /* for long worms */
41 STATIC_VAR int mesg_given; /* for m_throw()/thitu() 'miss' message */
42
43 /* hero is hit by something other than a monster */
44 int
45 thitu(tlev, dam, objp, name)
46 int tlev, dam;
47 struct obj **objp;
48 const char *name; /* if null, then format `*objp' */
49 {
50     struct obj *obj = objp ? *objp : 0;
51     const char *onm, *knm;
52     boolean is_acid;
53     int kprefix = KILLED_BY_AN, dieroll;
54     char onmbuf[BUFSZ], knmbuf[BUFSZ];
55
56     if (!name) {
57         if (!obj)
58             panic("thitu: name & obj both null?");
59         name = strcpy(onmbuf,
60                       (obj->quan > 1L) ? doname(obj) : mshot_xname(obj));
61         knm = strcpy(knmbuf, killer_xname(obj));
62         kprefix = KILLED_BY; /* killer_name supplies "an" if warranted */
63     } else {
64         knm = name;
65 #if 0 /*JP*/
66         /* [perhaps ought to check for plural here to] */
67         if (!strncmpi(name, "the ", 4) || !strncmpi(name, "an ", 3)
68             || !strncmpi(name, "a ", 2))
69             kprefix = KILLED_BY;
70 #else /* \93ú\96{\8cê\82Å\82Í\82»\82Ì\82Ü\82Ü */
71         knm = strcpy(knmbuf, name);
72 #endif
73     }
74 #if 1 /*JP*/
75     strcat(knmbuf, "\82É\93\96\82½\82Á\82Ä");
76 #endif
77     onm = (obj && obj_is_pname(obj)) ? the(name)
78           : (obj && obj->quan > 1L) ? name
79             : an(name);
80     is_acid = (obj && obj->otyp == ACID_VENOM);
81
82     if (u.uac + tlev <= (dieroll = rnd(20))) {
83         ++mesg_given;
84         if (Blind || !flags.verbose) {
85 /*JP
86             pline("It misses.");
87 */
88             pline("\82»\82ê\82Í\82Í\82¸\82ê\82½\81D");
89         } else if (u.uac + tlev <= dieroll - 2) {
90             if (onm != onmbuf)
91                 Strcpy(onmbuf, onm); /* [modifiable buffer for upstart()] */
92 /*JP
93             pline("%s %s you.", upstart(onmbuf), vtense(onmbuf, "miss"));
94 */
95             pline("%s\82Í\8dU\8c\82\82ð\82Í\82¸\82µ\82½\81D", upstart(onmbuf));
96         } else
97 /*JP
98             You("are almost hit by %s.", onm);
99 */
100             pline("\82à\82¤\8f­\82µ\82Å%s\82É\96½\92\86\82·\82é\82Æ\82±\82ë\82¾\82Á\82½\81I",onm);
101         return 0;
102     } else {
103         if (Blind || !flags.verbose)
104 /*JP
105             You("are hit%s", exclam(dam));
106 */
107             pline("\89½\82©\82ª\82 \82È\82½\82É\96½\92\86\82µ\82½\81I");
108         else
109 /*JP
110             You("are hit by %s%s", onm, exclam(dam));
111 */
112             pline("%s\82ª\82 \82È\82½\82É\96½\92\86\82µ\82½\81I", onm);
113
114         if (is_acid && Acid_resistance) {
115 /*JP
116             pline("It doesn't seem to hurt you.");
117 */
118             pline("\82 \82È\82½\82Í\8f\9d\82Â\82©\82È\82©\82Á\82½\81D");
119         } else if (obj && obj->oclass == POTION_CLASS) {
120             /* an explosion which scatters objects might hit hero with one
121                (potions deliberately thrown at hero are handled by m_throw) */
122             potionhit(&youmonst, obj, POTHIT_OTHER_THROW);
123             *objp = obj = 0; /* potionhit() uses up the potion */
124         } else {
125             if (obj && objects[obj->otyp].oc_material == SILVER
126                 && Hate_silver) {
127                 /* extra damage already applied by dmgval() */
128 /*JP
129                 pline_The("silver sears your flesh!");
130 */
131                 pline("\82 \82È\82½\82Ì\91Ì\82Í\8bâ\82Å\8fÄ\82©\82ê\82½\81I");
132                 exercise(A_CON, FALSE);
133             }
134             if (is_acid)
135 /*JP
136                 pline("It burns!");
137 */
138                 pline("\8e_\82Å\8fÄ\82©\82ê\82½\81I");
139             losehp(dam, knm, kprefix); /* acid damage */
140             exercise(A_STR, FALSE);
141         }
142         return 1;
143     }
144 }
145
146 /* Be sure this corresponds with what happens to player-thrown objects in
147  * dothrow.c (for consistency). --KAA
148  * Returns 0 if object still exists (not destroyed).
149  */
150 STATIC_OVL int
151 drop_throw(obj, ohit, x, y)
152 register struct obj *obj;
153 boolean ohit;
154 int x, y;
155 {
156     int retvalu = 1;
157     int create;
158     struct monst *mtmp;
159     struct trap *t;
160
161     if (obj->otyp == CREAM_PIE || obj->oclass == VENOM_CLASS
162         || (ohit && obj->otyp == EGG))
163         create = 0;
164     else if (ohit && (is_multigen(obj) || obj->otyp == ROCK))
165         create = !rn2(3);
166     else
167         create = 1;
168
169     if (create && !((mtmp = m_at(x, y)) != 0 && mtmp->mtrapped
170                     && (t = t_at(x, y)) != 0
171                     && is_pit(t->ttyp))) {
172         int objgone = 0;
173
174         if (down_gate(x, y) != -1)
175             objgone = ship_object(obj, x, y, FALSE);
176         if (!objgone) {
177 #if 0 /*JP:T*/
178             if (!flooreffects(obj, x, y, "fall")) {
179 #else
180             if (!flooreffects(obj, x, y, "\97\8e\82¿\82é")) {
181 #endif
182                 place_object(obj, x, y);
183                 if (!mtmp && x == u.ux && y == u.uy)
184                     mtmp = &youmonst;
185                 if (mtmp && ohit)
186                     passive_obj(mtmp, obj, (struct attack *) 0);
187                 stackobj(obj);
188                 retvalu = 0;
189             }
190         }
191     } else
192         obfree(obj, (struct obj *) 0);
193     return retvalu;
194 }
195
196 /* The monster that's being shot at when one monster shoots at another */
197 STATIC_OVL struct monst *target = 0;
198 /* The monster that's doing the shooting/throwing */
199 STATIC_OVL struct monst *archer = 0;
200
201 /* calculate multishot volley count for mtmp throwing otmp (if not ammo) or
202    shooting otmp with mwep (if otmp is ammo and mwep appropriate launcher) */
203 STATIC_OVL int
204 monmulti(mtmp, otmp, mwep)
205 struct monst *mtmp;
206 struct obj *otmp, *mwep;
207 {
208     int skill = (int) objects[otmp->otyp].oc_skill;
209     int multishot = 1;
210
211     if (otmp->quan > 1L /* no point checking if there's only 1 */
212         /* ammo requires corresponding launcher be wielded */
213         && (is_ammo(otmp)
214                ? matching_launcher(otmp, mwep)
215                /* otherwise any stackable (non-ammo) weapon */
216                : otmp->oclass == WEAPON_CLASS)
217         && !mtmp->mconf) {
218         /* Assumes lords are skilled, princes are expert */
219         if (is_prince(mtmp->data))
220             multishot += 2;
221         else if (is_lord(mtmp->data))
222             multishot++;
223         /* fake players treated as skilled (regardless of role limits) */
224         else if (is_mplayer(mtmp->data))
225             multishot++;
226
227         /* this portion is different from hero multishot; from slash'em?
228          */
229         /* Elven Craftsmanship makes for light, quick bows */
230         if (otmp->otyp == ELVEN_ARROW && !otmp->cursed)
231             multishot++;
232         /* for arrow, we checked bow&arrow when entering block, but for
233            bow, so far we've only validated that otmp is a weapon stack;
234            need to verify that it's a stack of arrows rather than darts */
235         if (mwep && mwep->otyp == ELVEN_BOW && ammo_and_launcher(otmp, mwep)
236             && !mwep->cursed)
237             multishot++;
238         /* 1/3 of launcher enchantment */
239         if (ammo_and_launcher(otmp, mwep) && mwep->spe > 1)
240             multishot += (long) rounddiv(mwep->spe, 3);
241         /* Some randomness */
242         multishot = (long) rnd((int) multishot);
243
244         /* class bonus */
245         switch (monsndx(mtmp->data)) {
246         case PM_CAVEMAN: /* give bonus for low-tech gear */
247             if (skill == -P_SLING || skill == P_SPEAR)
248                 multishot++;
249             break;
250         case PM_MONK: /* allow higher volley count */
251             if (skill == -P_SHURIKEN)
252                 multishot++;
253             break;
254         case PM_RANGER:
255             if (skill != P_DAGGER)
256                 multishot++;
257             break;
258         case PM_ROGUE:
259             if (skill == P_DAGGER)
260                 multishot++;
261             break;
262         case PM_NINJA:
263             if (skill == -P_SHURIKEN || skill == -P_DART)
264                 multishot++;
265             /*FALLTHRU*/
266         case PM_SAMURAI:
267             if (otmp->otyp == YA && mwep->otyp == YUMI)
268                 multishot++;
269             break;
270         default:
271             break;
272         }
273         /* racial bonus */
274         if ((is_elf(mtmp->data) && otmp->otyp == ELVEN_ARROW
275             && mwep->otyp == ELVEN_BOW)
276             || (is_orc(mtmp->data) && otmp->otyp == ORCISH_ARROW
277                 && mwep->otyp == ORCISH_BOW)
278             || (is_gnome(mtmp->data) && otmp->otyp == CROSSBOW_BOLT
279                 && mwep->otyp == CROSSBOW))
280             multishot++;
281     }
282
283     if (otmp->quan < multishot)
284         multishot = (int) otmp->quan;
285     if (multishot < 1)
286         multishot = 1;
287     return multishot;
288 }
289
290 /* mtmp throws otmp, or shoots otmp with mwep, at hero or at monster mtarg */
291 STATIC_OVL void
292 monshoot(mtmp, otmp, mwep)
293 struct monst *mtmp;
294 struct obj *otmp, *mwep;
295 {
296     struct monst *mtarg = target;
297     int dm = distmin(mtmp->mx, mtmp->my,
298                      mtarg ? mtarg->mx : mtmp->mux,
299                      mtarg ? mtarg->my : mtmp->muy),
300         multishot = monmulti(mtmp, otmp, mwep);
301         /*
302          * Caller must have called linedup() to set up tbx, tby.
303          */
304
305     if (canseemon(mtmp)) {
306         const char *onm;
307         char onmbuf[BUFSZ], trgbuf[BUFSZ];
308
309         if (multishot > 1) {
310             /* "N arrows"; multishot > 1 implies otmp->quan > 1, so
311                xname()'s result will already be pluralized */
312 /*JP
313             Sprintf(onmbuf, "%d %s", multishot, xname(otmp));
314 */
315             Sprintf(onmbuf, "%d%s\82Ì%s", multishot, numeral(otmp), xname(otmp));
316             onm = onmbuf;
317         } else {
318             /* "an arrow" */
319             onm = singular(otmp, xname);
320             onm = obj_is_pname(otmp) ? the(onm) : an(onm);
321         }
322         m_shot.s = ammo_and_launcher(otmp, mwep) ? TRUE : FALSE;
323         Strcpy(trgbuf, mtarg ? mon_nam(mtarg) : "");
324 #if 0 /*JP*//*\93ú\96{\8cê\82Å\82Ímon_nam\82Í\81u\89½\8eÒ\82©\81v\82ð\95Ô\82·\82Ì\82Å\95Ï\8dX\95s\97v*/
325         if (!strcmp(trgbuf, "it"))
326             Strcpy(trgbuf, humanoid(mtmp->data) ? "someone" : something);
327 #endif
328 #if 0 /*JP:T*/
329         pline("%s %s %s%s%s!", Monnam(mtmp),
330               m_shot.s ? "shoots" : "throws", onm,
331               mtarg ? " at " : "", trgbuf);
332 #else
333         pline("%s\82Í%s\82ð%s\82É%s\81I", Monnam(mtmp),
334               onm,
335               trgbuf,
336               m_shot.s ? "\8c\82\82Á\82½" : "\93\8a\82°\82½");
337 #endif
338         m_shot.o = otmp->otyp;
339     } else {
340         m_shot.o = STRANGE_OBJECT; /* don't give multishot feedback */
341     }
342     m_shot.n = multishot;
343     for (m_shot.i = 1; m_shot.i <= m_shot.n; m_shot.i++) {
344         m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), dm, otmp);
345         /* conceptually all N missiles are in flight at once, but
346            if mtmp gets killed (shot kills adjacent gas spore and
347            triggers explosion, perhaps), inventory will be dropped
348            and otmp might go away via merging into another stack */
349         if (DEADMONSTER(mtmp) && m_shot.i < m_shot.n)
350             /* cancel pending shots (perhaps ought to give a message here
351                since we gave one above about throwing/shooting N missiles) */
352             break; /* endmultishot(FALSE); */
353     }
354     /* reset 'm_shot' */
355     m_shot.n = m_shot.i = 0;
356     m_shot.o = STRANGE_OBJECT;
357     m_shot.s = FALSE;
358 }
359
360 /* an object launched by someone/thing other than player attacks a monster;
361    return 1 if the object has stopped moving (hit or its range used up) */
362 int
363 ohitmon(mtmp, otmp, range, verbose)
364 struct monst *mtmp; /* accidental target, located at <bhitpos.x,.y> */
365 struct obj *otmp;   /* missile; might be destroyed by drop_throw */
366 int range;          /* how much farther will object travel if it misses;
367                        use -1 to signify to keep going even after hit,
368                        unless it's gone (used for rolling_boulder_traps) */
369 boolean verbose;    /* give message(s) even when you can't see what happened */
370 {
371     int damage, tmp;
372     boolean vis, ismimic;
373     int objgone = 1;
374     struct obj *mon_launcher = archer ? MON_WEP(archer) : NULL;
375
376     notonhead = (bhitpos.x != mtmp->mx || bhitpos.y != mtmp->my);
377     ismimic = M_AP_TYPE(mtmp) && M_AP_TYPE(mtmp) != M_AP_MONSTER;
378     vis = cansee(bhitpos.x, bhitpos.y);
379
380     tmp = 5 + find_mac(mtmp) + omon_adj(mtmp, otmp, FALSE);
381     /* High level monsters will be more likely to hit */
382     /* This check applies only if this monster is the target
383      * the archer was aiming at. */
384     if (archer && target == mtmp) {
385         if (archer->m_lev > 5)
386             tmp += archer->m_lev - 5;
387         if (mon_launcher && mon_launcher->oartifact)
388             tmp += spec_abon(mon_launcher, mtmp);
389     }
390     if (tmp < rnd(20)) {
391         if (!ismimic) {
392             if (vis)
393                 miss(distant_name(otmp, mshot_xname), mtmp);
394             else if (verbose && !target)
395 /*JP
396                 pline("It is missed.");
397 */
398                 pline("\89½\82©\82ª\82©\82·\82ß\82½\81D");
399         }
400         if (!range) { /* Last position; object drops */
401             (void) drop_throw(otmp, 0, mtmp->mx, mtmp->my);
402             return 1;
403         }
404     } else if (otmp->oclass == POTION_CLASS) {
405         if (ismimic)
406             seemimic(mtmp);
407         mtmp->msleeping = 0;
408         if (vis)
409             otmp->dknown = 1;
410         /* probably thrown by a monster rather than 'other', but the
411            distinction only matters when hitting the hero */
412         potionhit(mtmp, otmp, POTHIT_OTHER_THROW);
413         return 1;
414     } else {
415         damage = dmgval(otmp, mtmp);
416         if (otmp->otyp == ACID_VENOM && resists_acid(mtmp))
417             damage = 0;
418 #if 0 /* can't use this because we don't have the attacker */
419         if (is_orc(mtmp->data) && is_elf(?magr?))
420             damage++;
421 #endif
422         if (ismimic)
423             seemimic(mtmp);
424         mtmp->msleeping = 0;
425         if (vis) {
426             if (otmp->otyp == EGG)
427 #if 0 /*JP:T*/
428                 pline("Splat!  %s is hit with %s egg!", Monnam(mtmp),
429                       otmp->known ? an(mons[otmp->corpsenm].mname) : "an");
430 #else
431                 pline("\83r\83`\83\83\83b\81I%s\82Í%s\97\91\82É\93\96\82½\82Á\82½\81I", Monnam(mtmp),
432                       otmp->known ? s_suffix(mons[otmp->corpsenm].mname) : "");
433 #endif
434             else
435                 hit(distant_name(otmp, mshot_xname), mtmp, exclam(damage));
436         } else if (verbose && !target)
437 #if 0 /*JP:T*/
438             pline("%s%s is hit%s", (otmp->otyp == EGG) ? "Splat!  " : "",
439                   Monnam(mtmp), exclam(damage));
440 #else
441             pline("%s%s\82É\96½\92\86\82µ\82½%s", (otmp->otyp == EGG) ? "\83r\83`\83\83\83b\81I" : "",
442                   Monnam(mtmp), exclam(damage));
443 #endif
444
445         if (otmp->opoisoned && is_poisonable(otmp)) {
446             if (resists_poison(mtmp)) {
447                 if (vis)
448 /*JP
449                     pline_The("poison doesn't seem to affect %s.",
450 */
451                     pline("%s\82Í\93Å\82Ì\89e\8b¿\82ð\8eó\82¯\82È\82¢\82æ\82¤\82¾\81D",
452                               mon_nam(mtmp));
453             } else {
454                 if (rn2(30)) {
455                     damage += rnd(6);
456                 } else {
457                     if (vis)
458 /*JP
459                         pline_The("poison was deadly...");
460 */
461                         pline("\93Å\82Í\92v\8e\80\97Ê\82¾\82Á\82½\81D\81D\81D");
462                     damage = mtmp->mhp;
463                 }
464             }
465         }
466         if (objects[otmp->otyp].oc_material == SILVER
467             && mon_hates_silver(mtmp)) {
468             boolean flesh = (!noncorporeal(mtmp->data)
469                              && !amorphous(mtmp->data));
470
471             /* note: extra silver damage is handled by dmgval() */
472             if (vis) {
473                 char *m_name = mon_nam(mtmp);
474
475                 if (flesh) /* s_suffix returns a modifiable buffer */
476 /*JP
477                     m_name = strcat(s_suffix(m_name), " flesh");
478 */
479                     m_name = strcat(s_suffix(m_name), "\82Ì\91Ì");
480 /*JP
481                 pline_The("silver sears %s!", m_name);
482 */
483                 pline("%s\82Í\8bâ\82Å\8fÄ\82©\82ê\82½\81I", m_name);
484             } else if (verbose && !target) {
485 /*JP
486                 pline("%s is seared!", flesh ? "Its flesh" : "It");
487 */
488                 pline("\89½%s\82Í\8fÄ\82©\82ê\82½\81I", flesh ? "\8eÒ\82©\82Ì\91Ì" : "\82©");
489             }
490         }
491         if (otmp->otyp == ACID_VENOM && cansee(mtmp->mx, mtmp->my)) {
492             if (resists_acid(mtmp)) {
493                 if (vis || (verbose && !target))
494 /*JP
495                     pline("%s is unaffected.", Monnam(mtmp));
496 */
497                     pline("%s\82Í\89e\8b¿\82ð\8eó\82¯\82È\82¢\81D", Monnam(mtmp));
498             } else {
499                 if (vis)
500 /*JP
501                     pline_The("%s burns %s!", hliquid("acid"), mon_nam(mtmp));
502 */
503                     pline_The("%s\82Í%s\82Å\8fÄ\82©\82ê\82½\81I", mon_nam(mtmp), hliquid("\8e_"));
504                 else if (verbose && !target)
505 /*JP
506                     pline("It is burned!");
507 */
508                     pline("\89½\82©\82Í\8fÄ\82©\82ê\82½\81I");
509             }
510         }
511         if (otmp->otyp == EGG && touch_petrifies(&mons[otmp->corpsenm])) {
512             if (!munstone(mtmp, TRUE))
513                 minstapetrify(mtmp, TRUE);
514             if (resists_ston(mtmp))
515                 damage = 0;
516         }
517
518         if (!DEADMONSTER(mtmp)) { /* might already be dead (if petrified) */
519             mtmp->mhp -= damage;
520             if (DEADMONSTER(mtmp)) {
521                 if (vis || (verbose && !target))
522 #if 0 /*JP:T*/
523                     pline("%s is %s!", Monnam(mtmp),
524                           (nonliving(mtmp->data) || is_vampshifter(mtmp)
525                            || !canspotmon(mtmp)) ? "destroyed" : "killed");
526 #else
527                     pline("%s\82Í%s\81I", Monnam(mtmp),
528                           (nonliving(mtmp->data) || is_vampshifter(mtmp)
529                            || !canspotmon(mtmp)) ? "\93|\82³\82ê\82½" : "\8e\80\82ñ\82¾");
530 #endif
531                 /* don't blame hero for unknown rolling boulder trap */
532                 if (!context.mon_moving && (otmp->otyp != BOULDER
533                                             || range >= 0 || otmp->otrapped))
534                     xkilled(mtmp, XKILL_NOMSG);
535                 else
536                     mondied(mtmp);
537             }
538         }
539
540         /* blinding venom and cream pie do 0 damage, but verify
541            that the target is still alive anyway */
542         if (!DEADMONSTER(mtmp)
543             && can_blnd((struct monst *) 0, mtmp,
544                         (uchar) ((otmp->otyp == BLINDING_VENOM) ? AT_SPIT
545                                                                 : AT_WEAP),
546                         otmp)) {
547             if (vis && mtmp->mcansee)
548 /*JP
549                 pline("%s is blinded by %s.", Monnam(mtmp), the(xname(otmp)));
550 */
551                 pline("%s\82Í%s\82É\82æ\82Á\82Ä\96Ú\82ª\8c©\82¦\82È\82­\82È\82Á\82½\81D", Monnam(mtmp), the(xname(otmp)));
552             mtmp->mcansee = 0;
553             tmp = (int) mtmp->mblinded + rnd(25) + 20;
554             if (tmp > 127)
555                 tmp = 127;
556             mtmp->mblinded = tmp;
557         }
558
559         objgone = drop_throw(otmp, 1, bhitpos.x, bhitpos.y);
560         if (!objgone && range == -1) { /* special case */
561             obj_extract_self(otmp);    /* free it for motion again */
562             return 0;
563         }
564         return 1;
565     }
566     return 0;
567 }
568
569 #define MT_FLIGHTCHECK(pre)                                             \
570     (/* missile hits edge of screen */                                  \
571      !isok(bhitpos.x + dx, bhitpos.y + dy)                              \
572      /* missile hits the wall */                                        \
573      || IS_ROCK(levl[bhitpos.x + dx][bhitpos.y + dy].typ)               \
574      /* missile hit closed door */                                      \
575      || closed_door(bhitpos.x + dx, bhitpos.y + dy)                     \
576      /* missile might hit iron bars */                                  \
577      /* the random chance for small objects hitting bars is */          \
578      /* skipped when reaching them at point blank range */              \
579      || (levl[bhitpos.x + dx][bhitpos.y + dy].typ == IRONBARS           \
580          && hits_bars(&singleobj,                                       \
581                       bhitpos.x, bhitpos.y,                             \
582                       bhitpos.x + dx, bhitpos.y + dy,                   \
583                       ((pre) ? 0 : !rn2(5)), 0))                        \
584      /* Thrown objects "sink" */                                        \
585      || (!(pre) && IS_SINK(levl[bhitpos.x][bhitpos.y].typ)))
586
587 void
588 m_throw(mon, x, y, dx, dy, range, obj)
589 struct monst *mon;       /* launching monster */
590 int x, y, dx, dy, range; /* launch point, direction, and range */
591 struct obj *obj;         /* missile (or stack providing it) */
592 {
593     struct monst *mtmp;
594     struct obj *singleobj;
595     char sym = obj->oclass;
596     int hitu = 0, oldumort, blindinc = 0;
597
598     bhitpos.x = x;
599     bhitpos.y = y;
600     notonhead = FALSE; /* reset potentially stale value */
601
602     if (obj->quan == 1L) {
603         /*
604          * Remove object from minvent.  This cannot be done later on;
605          * what if the player dies before then, leaving the monster
606          * with 0 daggers?  (This caused the infamous 2^32-1 orcish
607          * dagger bug).
608          *
609          * VENOM is not in minvent - it should already be OBJ_FREE.
610          * The extract below does nothing.
611          */
612
613         /* not possibly_unwield, which checks the object's */
614         /* location, not its existence */
615         if (MON_WEP(mon) == obj)
616             setmnotwielded(mon, obj);
617         obj_extract_self(obj);
618         singleobj = obj;
619         obj = (struct obj *) 0;
620     } else {
621         singleobj = splitobj(obj, 1L);
622         obj_extract_self(singleobj);
623     }
624
625     singleobj->owornmask = 0; /* threw one of multiple weapons in hand? */
626
627     if ((singleobj->cursed || singleobj->greased) && (dx || dy) && !rn2(7)) {
628         if (canseemon(mon) && flags.verbose) {
629             if (is_ammo(singleobj))
630 /*JP
631                 pline("%s misfires!", Monnam(mon));
632 */
633                 pline("%s\82Í\82Í\82¸\82µ\82½\81I", Monnam(mon));
634             else
635 #if 0 /*JP:T*/
636                 pline("%s as %s throws it!", Tobjnam(singleobj, "slip"),
637                       mon_nam(mon));
638 #else
639                 pline("%s\82ª\93\8a\82°\82æ\82¤\82Æ\82µ\82½\82Æ\82½\82ñ%s\82ª\8a\8a\82Á\82½\81I",
640                           mon_nam(mon), xname(singleobj));
641 #endif
642         }
643         dx = rn2(3) - 1;
644         dy = rn2(3) - 1;
645         /* check validity of new direction */
646         if (!dx && !dy) {
647             (void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
648             return;
649         }
650     }
651
652     if (MT_FLIGHTCHECK(TRUE)) {
653         (void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
654         return;
655     }
656     mesg_given = 0; /* a 'missile misses' message has not yet been shown */
657
658     /* Note: drop_throw may destroy singleobj.  Since obj must be destroyed
659      * early to avoid the dagger bug, anyone who modifies this code should
660      * be careful not to use either one after it's been freed.
661      */
662     if (sym)
663         tmp_at(DISP_FLASH, obj_to_glyph(singleobj, rn2_on_display_rng));
664     while (range-- > 0) { /* Actually the loop is always exited by break */
665         bhitpos.x += dx;
666         bhitpos.y += dy;
667         mtmp = m_at(bhitpos.x, bhitpos.y);
668         if (mtmp && shade_miss(mon, mtmp, singleobj, TRUE, TRUE)) {
669             /* if mtmp is a shade and missile passes harmlessly through it,
670                give message and skip it in order to keep going */
671             mtmp = (struct monst *) 0;
672         } else if (mtmp) {
673             if (ohitmon(mtmp, singleobj, range, TRUE))
674                 break;
675         } else if (bhitpos.x == u.ux && bhitpos.y == u.uy) {
676             if (multi)
677                 nomul(0);
678
679             if (singleobj->oclass == GEM_CLASS
680                 && singleobj->otyp <= LAST_GEM + 9 /* 9 glass colors */
681                 && is_unicorn(youmonst.data)) {
682                 if (singleobj->otyp > LAST_GEM) {
683 /*JP
684                     You("catch the %s.", xname(singleobj));
685 */
686                     You("%s\82ð\82Â\82©\82Ü\82¦\82½\81D", xname(singleobj));
687 #if 0 /*JP:T*/
688                     You("are not interested in %s junk.",
689                         s_suffix(mon_nam(mon)));
690 #else
691                     You("%s\82Ì\83K\83\89\83N\83^\82É\8b»\96¡\82Í\82È\82¢\81D",
692                         mon_nam(mon));
693 #endif
694                     makeknown(singleobj->otyp);
695                     dropy(singleobj);
696                 } else {
697                     You(
698 /*JP
699                      "accept %s gift in the spirit in which it was intended.",
700 */
701                      "\82±\82ê\82ª\97~\82µ\82©\82Á\82½\82ñ\82¾\82Æ\8ev\82¢\82È\82ª\82ç%s\82Ì\91¡\82è\95¨\82ð\8eó\82¯\82Æ\82Á\82½\81D",
702                         s_suffix(mon_nam(mon)));
703 #if 0 /*JP:T*/
704                     (void) hold_another_object(singleobj,
705                                                "You catch, but drop, %s.",
706                                                xname(singleobj),
707                                                "You catch:");
708 #else
709                     (void) hold_another_object(singleobj,
710                                      "\82 \82È\82½\82Í%s\82ð\82Â\82©\82Ü\82¦\82½\82ª\81C\97\8e\82µ\82½\81D",
711                                                xname(singleobj),
712                                                "\82ð\82Â\82©\82Ü\82¦\82½\81D");
713 #endif
714                 }
715                 break;
716             }
717             if (singleobj->oclass == POTION_CLASS) {
718                 if (!Blind)
719                     singleobj->dknown = 1;
720                 potionhit(&youmonst, singleobj, POTHIT_MONST_THROW);
721                 break;
722             }
723             oldumort = u.umortality;
724             switch (singleobj->otyp) {
725                 int dam, hitv;
726             case EGG:
727                 if (!touch_petrifies(&mons[singleobj->corpsenm])) {
728                     impossible("monster throwing egg type %d",
729                                singleobj->corpsenm);
730                     hitu = 0;
731                     break;
732                 }
733             /* fall through */
734             case CREAM_PIE:
735             case BLINDING_VENOM:
736                 hitu = thitu(8, 0, &singleobj, (char *) 0);
737                 break;
738             default:
739                 dam = dmgval(singleobj, &youmonst);
740                 hitv = 3 - distmin(u.ux, u.uy, mon->mx, mon->my);
741                 if (hitv < -4)
742                     hitv = -4;
743                 if (is_elf(mon->data)
744                     && objects[singleobj->otyp].oc_skill == P_BOW) {
745                     hitv++;
746                     if (MON_WEP(mon) && MON_WEP(mon)->otyp == ELVEN_BOW)
747                         hitv++;
748                     if (singleobj->otyp == ELVEN_ARROW)
749                         dam++;
750                 }
751                 if (bigmonst(youmonst.data))
752                     hitv++;
753                 hitv += 8 + singleobj->spe;
754                 if (dam < 1)
755                     dam = 1;
756                 hitu = thitu(hitv, dam, &singleobj, (char *) 0);
757             }
758             if (hitu && singleobj->opoisoned && is_poisonable(singleobj)) {
759                 char onmbuf[BUFSZ], knmbuf[BUFSZ];
760
761                 Strcpy(onmbuf, xname(singleobj));
762                 Strcpy(knmbuf, killer_xname(singleobj));
763                 poisoned(onmbuf, A_STR, knmbuf,
764                          /* if damage triggered life-saving,
765                             poison is limited to attrib loss */
766                          (u.umortality > oldumort) ? 0 : 10, TRUE);
767             }
768             if (hitu && can_blnd((struct monst *) 0, &youmonst,
769                                  (uchar) ((singleobj->otyp == BLINDING_VENOM)
770                                              ? AT_SPIT
771                                              : AT_WEAP),
772                                  singleobj)) {
773                 blindinc = rnd(25);
774                 if (singleobj->otyp == CREAM_PIE) {
775                     if (!Blind)
776 /*JP
777                         pline("Yecch!  You've been creamed.");
778 */
779                         pline("\83E\83F\81[\81D\83N\83\8a\81[\83\80\82ð\82©\82Ô\82Á\82½\81D");
780                     else
781 #if 0 /*JP:T*/
782                         pline("There's %s sticky all over your %s.",
783                               something, body_part(FACE));
784 #else
785                         pline("\82 \82È\82½\82Í%s\82É\82×\82Æ\82Â\82­\82à\82Ì\82ð\8a´\82\82½\81D",
786                               body_part(FACE));
787 #endif
788                 } else if (singleobj->otyp == BLINDING_VENOM) {
789 #if 0 /*JP*/
790                     const char *eyes = body_part(EYE);
791
792                     if (eyecount(youmonst.data) != 1)
793                         eyes = makeplural(eyes);
794                     /* venom in the eyes */
795                     if (!Blind)
796                         pline_The("venom blinds you.");
797                     else
798                         Your("%s %s.", eyes, vtense(eyes, "sting"));
799 #else
800                     if(!Blind)
801                         pline("\93Å\82Å\96Ú\82ª\8c©\82¦\82È\82­\82È\82Á\82½\81D");
802                     else
803                         Your("%s\82Í\82¿\82­\82¿\82­\82µ\82½\81D", body_part(EYE));
804 #endif
805                 }
806             }
807             if (hitu && singleobj->otyp == EGG) {
808                 if (!Stoned && !Stone_resistance
809                     && !(poly_when_stoned(youmonst.data)
810                          && polymon(PM_STONE_GOLEM))) {
811                     make_stoned(5L, (char *) 0, KILLED_BY, "");
812                 }
813             }
814             stop_occupation();
815             if (hitu) {
816                 (void) drop_throw(singleobj, hitu, u.ux, u.uy);
817                 break;
818             }
819         }
820         if (!range /* reached end of path */
821             || MT_FLIGHTCHECK(FALSE)) {
822             if (singleobj) { /* hits_bars might have destroyed it */
823                 if (m_shot.n > 1
824                     && (!mesg_given || bhitpos.x != u.ux || bhitpos.y != u.uy)
825                     && (cansee(bhitpos.x, bhitpos.y)
826                         || (archer && canseemon(archer))))
827 /*JP
828                     pline("%s misses.", The(mshot_xname(singleobj)));
829 */
830                     pline("%s\82Í\82Í\82¸\82ê\82½\81D", mshot_xname(singleobj));
831                 (void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
832             }
833             break;
834         }
835         tmp_at(bhitpos.x, bhitpos.y);
836         delay_output();
837     }
838     tmp_at(bhitpos.x, bhitpos.y);
839     delay_output();
840     tmp_at(DISP_END, 0);
841     mesg_given = 0; /* reset */
842
843     if (blindinc) {
844         u.ucreamed += blindinc;
845         make_blinded(Blinded + (long) blindinc, FALSE);
846         if (!Blind)
847             Your1(vision_clears);
848     }
849 }
850
851 #undef MT_FLIGHTCHECK
852
853 /* Monster throws item at another monster */
854 int
855 thrwmm(mtmp, mtarg)
856 struct monst *mtmp, *mtarg;
857 {
858     struct obj *otmp, *mwep;
859     register xchar x, y;
860     boolean ispole;
861
862     /* Polearms won't be applied by monsters against other monsters */
863     if (mtmp->weapon_check == NEED_WEAPON || !MON_WEP(mtmp)) {
864         mtmp->weapon_check = NEED_RANGED_WEAPON;
865         /* mon_wield_item resets weapon_check as appropriate */
866         if (mon_wield_item(mtmp) != 0)
867             return 0;
868     }
869
870     /* Pick a weapon */
871     otmp = select_rwep(mtmp);
872     if (!otmp)
873         return 0;
874     ispole = is_pole(otmp);
875
876     x = mtmp->mx;
877     y = mtmp->my;
878
879     mwep = MON_WEP(mtmp); /* wielded weapon */
880
881     if (!ispole && m_lined_up(mtarg, mtmp)) {
882         int chance = max(BOLT_LIM - distmin(x, y, mtarg->mx, mtarg->my), 1);
883
884         if (!mtarg->mflee || !rn2(chance)) {
885             if (ammo_and_launcher(otmp, mwep)
886                 && dist2(mtmp->mx, mtmp->my, mtarg->mx, mtarg->my)
887                    > PET_MISSILE_RANGE2)
888                 return 0; /* Out of range */
889             /* Set target monster */
890             target = mtarg;
891             archer = mtmp;
892             monshoot(mtmp, otmp, mwep); /* multishot shooting or throwing */
893             archer = target = (struct monst *) 0;
894             nomul(0);
895             return 1;
896         }
897     }
898     return 0;
899 }
900
901 /* monster spits substance at monster */
902 int
903 spitmm(mtmp, mattk, mtarg)
904 struct monst *mtmp, *mtarg;
905 struct attack *mattk;
906 {
907     struct obj *otmp;
908
909     if (mtmp->mcan) {
910         if (!Deaf)
911 #if 0 /*JP:T*/
912             pline("A dry rattle comes from %s throat.",
913                   s_suffix(mon_nam(mtmp)));
914 #else
915             pline("%s\82Ì\8dA\82ª\83K\83\89\83K\83\89\82Æ\96Â\82Á\82½\81D",
916                   mon_nam(mtmp));
917 #endif
918         return 0;
919     }
920     if (m_lined_up(mtarg, mtmp)) {
921         switch (mattk->adtyp) {
922         case AD_BLND:
923         case AD_DRST:
924             otmp = mksobj(BLINDING_VENOM, TRUE, FALSE);
925             break;
926         default:
927             impossible("bad attack type in spitmu");
928             /*FALLTHRU*/
929         case AD_ACID:
930             otmp = mksobj(ACID_VENOM, TRUE, FALSE);
931             break;
932         }
933         if (!rn2(BOLT_LIM-distmin(mtmp->mx,mtmp->my,mtarg->mx,mtarg->my))) {
934             if (canseemon(mtmp))
935 /*JP
936                 pline("%s spits venom!", Monnam(mtmp));
937 */
938                 pline("%s\82Í\93Å\82ð\93f\82¢\82½\81I", Monnam(mtmp));
939             target = mtarg;
940             m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby),
941                     distmin(mtmp->mx,mtmp->my,mtarg->mx,mtarg->my), otmp);
942             target = (struct monst *)0;
943             nomul(0);
944
945             /* If this is a pet, it'll get hungry. Minions and
946              * spell beings won't hunger */
947             if (mtmp->mtame && !mtmp->isminion) {
948                 struct edog *dog = EDOG(mtmp);
949
950                 /* Hunger effects will catch up next move */
951                 if (dog->hungrytime > 1)
952                     dog->hungrytime -= 5;
953             }
954
955             return 1;
956         }
957     }
958     return 0;
959 }
960
961 /* monster breathes at monster (ranged) */
962 int
963 breamm(mtmp, mattk, mtarg)
964 struct monst *mtmp, *mtarg;
965 struct attack  *mattk;
966 {
967     /* if new breath types are added, change AD_ACID to max type */
968     int typ = (mattk->adtyp == AD_RBRE) ? rnd(AD_ACID) : mattk->adtyp ;
969
970     if (m_lined_up(mtarg, mtmp)) {
971         if (mtmp->mcan) {
972             if (!Deaf) {
973                 if (canseemon(mtmp))
974 /*JP
975                     pline("%s coughs.", Monnam(mtmp));
976 */
977                     pline("%s\82Í\82¹\82«\82ð\82µ\82½\81D", Monnam(mtmp));
978                 else
979 /*JP
980                     You_hear("a cough.");
981 */
982                     You_hear("\82¹\82«\82Ì\89¹\82ð\95·\82¢\82½\81D");
983             }
984             return 0;
985         }
986         if (!mtmp->mspec_used && rn2(3)) {
987             if ((typ >= AD_MAGM) && (typ <= AD_ACID)) {
988                 if (canseemon(mtmp))
989 /*JP
990                     pline("%s breathes %s!", Monnam(mtmp), breathwep[typ - 1]);
991 */
992                     pline("%s\82Í%s\82ð\82Í\82¢\82½\81I", Monnam(mtmp), breathwep[typ - 1]);
993                 dobuzz((int) (-20 - (typ - 1)), (int) mattk->damn,
994                        mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), FALSE);
995                 nomul(0);
996                 /* breath runs out sometimes. Also, give monster some
997                  * cunning; don't breath if the target fell asleep.
998                  */
999                 mtmp->mspec_used = 6 + rn2(18);
1000
1001                 /* If this is a pet, it'll get hungry. Minions and
1002                  * spell beings won't hunger */
1003                 if (mtmp->mtame && !mtmp->isminion) {
1004                     struct edog *dog = EDOG(mtmp);
1005
1006                     /* Hunger effects will catch up next move */
1007                     if (dog->hungrytime >= 10)
1008                         dog->hungrytime -= 10;
1009                 }
1010             } else impossible("Breath weapon %d used", typ-1);
1011         } else
1012             return 0;
1013     }
1014     return 1;
1015 }
1016
1017
1018
1019 /* remove an entire item from a monster's inventory; destroy that item */
1020 void
1021 m_useupall(mon, obj)
1022 struct monst *mon;
1023 struct obj *obj;
1024 {
1025     obj_extract_self(obj);
1026     if (obj->owornmask) {
1027         if (obj == MON_WEP(mon))
1028             mwepgone(mon);
1029         mon->misc_worn_check &= ~obj->owornmask;
1030         update_mon_intrinsics(mon, obj, FALSE, FALSE);
1031         obj->owornmask = 0L;
1032     }
1033     obfree(obj, (struct obj *) 0);
1034 }
1035
1036 /* remove one instance of an item from a monster's inventory */
1037 void
1038 m_useup(mon, obj)
1039 struct monst *mon;
1040 struct obj *obj;
1041 {
1042     if (obj->quan > 1L) {
1043         obj->quan--;
1044         obj->owt = weight(obj);
1045     } else {
1046         m_useupall(mon, obj);
1047     }
1048 }
1049
1050 /* monster attempts ranged weapon attack against player */
1051 void
1052 thrwmu(mtmp)
1053 struct monst *mtmp;
1054 {
1055     struct obj *otmp, *mwep;
1056     xchar x, y;
1057     const char *onm;
1058
1059     /* Rearranged beginning so monsters can use polearms not in a line */
1060     if (mtmp->weapon_check == NEED_WEAPON || !MON_WEP(mtmp)) {
1061         mtmp->weapon_check = NEED_RANGED_WEAPON;
1062         /* mon_wield_item resets weapon_check as appropriate */
1063         if (mon_wield_item(mtmp) != 0)
1064             return;
1065     }
1066
1067     /* Pick a weapon */
1068     otmp = select_rwep(mtmp);
1069     if (!otmp)
1070         return;
1071
1072     if (is_pole(otmp)) {
1073         int dam, hitv;
1074
1075         if (otmp != MON_WEP(mtmp))
1076             return; /* polearm must be wielded */
1077         if (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) > POLE_LIM
1078             || !couldsee(mtmp->mx, mtmp->my))
1079             return; /* Out of range, or intervening wall */
1080
1081         if (canseemon(mtmp)) {
1082             onm = xname(otmp);
1083 #if 0 /*JP:T*/
1084             pline("%s thrusts %s.", Monnam(mtmp),
1085                   obj_is_pname(otmp) ? the(onm) : an(onm));
1086 #else
1087             pline("%s\82Í%s\82ð\93Ë\82«\8eh\82µ\82½\81D", Monnam(mtmp), onm);
1088 #endif
1089         }
1090
1091         dam = dmgval(otmp, &youmonst);
1092         hitv = 3 - distmin(u.ux, u.uy, mtmp->mx, mtmp->my);
1093         if (hitv < -4)
1094             hitv = -4;
1095         if (bigmonst(youmonst.data))
1096             hitv++;
1097         hitv += 8 + otmp->spe;
1098         if (dam < 1)
1099             dam = 1;
1100
1101         (void) thitu(hitv, dam, &otmp, (char *) 0);
1102         stop_occupation();
1103         return;
1104     }
1105
1106     x = mtmp->mx;
1107     y = mtmp->my;
1108     /* If you are coming toward the monster, the monster
1109      * should try to soften you up with missiles.  If you are
1110      * going away, you are probably hurt or running.  Give
1111      * chase, but if you are getting too far away, throw.
1112      */
1113     if (!lined_up(mtmp)
1114         || (URETREATING(x, y)
1115             && rn2(BOLT_LIM - distmin(x, y, mtmp->mux, mtmp->muy))))
1116         return;
1117
1118     mwep = MON_WEP(mtmp); /* wielded weapon */
1119     monshoot(mtmp, otmp, mwep); /* multishot shooting or throwing */
1120     nomul(0);
1121 }
1122
1123 /* monster spits substance at you */
1124 int
1125 spitmu(mtmp, mattk)
1126 struct monst *mtmp;
1127 struct attack *mattk;
1128 {
1129     struct obj *otmp;
1130
1131     if (mtmp->mcan) {
1132         if (!Deaf)
1133 #if 0 /*JP:T*/
1134             pline("A dry rattle comes from %s throat.",
1135                   s_suffix(mon_nam(mtmp)));
1136 #else
1137             pline("\8a£\82¢\82½\83K\83\89\83K\83\89\89¹\82ª%s\82Ì\82Ì\82Ç\82©\82ç\95·\82±\82¦\82Ä\82«\82½\81D",
1138                   mon_nam(mtmp));
1139 #endif
1140         return 0;
1141     }
1142     if (lined_up(mtmp)) {
1143         switch (mattk->adtyp) {
1144         case AD_BLND:
1145         case AD_DRST:
1146             otmp = mksobj(BLINDING_VENOM, TRUE, FALSE);
1147             break;
1148         default:
1149             impossible("bad attack type in spitmu");
1150         /* fall through */
1151         case AD_ACID:
1152             otmp = mksobj(ACID_VENOM, TRUE, FALSE);
1153             break;
1154         }
1155         if (!rn2(BOLT_LIM
1156                  - distmin(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy))) {
1157             if (canseemon(mtmp))
1158 /*JP
1159                 pline("%s spits venom!", Monnam(mtmp));
1160 */
1161                 pline("%s\82Í\93Å\89t\82ð\93f\82¢\82½\81I", Monnam(mtmp));
1162             m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby),
1163                     distmin(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy), otmp);
1164             nomul(0);
1165             return 0;
1166         } else {
1167             obj_extract_self(otmp);
1168             obfree(otmp, (struct obj *) 0);
1169         }
1170     }
1171     return 0;
1172 }
1173
1174 /* monster breathes at you (ranged) */
1175 int
1176 breamu(mtmp, mattk)
1177 struct monst *mtmp;
1178 struct attack *mattk;
1179 {
1180     /* if new breath types are added, change AD_ACID to max type */
1181     int typ = (mattk->adtyp == AD_RBRE) ? rnd(AD_ACID) : mattk->adtyp;
1182
1183     if (lined_up(mtmp)) {
1184         if (mtmp->mcan) {
1185             if (!Deaf) {
1186                 if (canseemon(mtmp))
1187 /*JP
1188                     pline("%s coughs.", Monnam(mtmp));
1189 */
1190                     pline("%s\82Í\82¹\82«\82ð\82µ\82½\81D", Monnam(mtmp));
1191                 else
1192 /*JP
1193                     You_hear("a cough.");
1194 */
1195                     You_hear("\82¹\82«\82Ì\89¹\82ð\95·\82¢\82½\81D");
1196             }
1197             return 0;
1198         }
1199         if (!mtmp->mspec_used && rn2(3)) {
1200             if ((typ >= AD_MAGM) && (typ <= AD_ACID)) {
1201                 if (canseemon(mtmp))
1202 #if 0 /*JP:T*/
1203                     pline("%s breathes %s!", Monnam(mtmp),
1204                           breathwep[typ - 1]);
1205 #else
1206                     pline("%s\82Í%s\82ð\93f\82¢\82½\81I", Monnam(mtmp),
1207                           breathwep[typ - 1]);
1208 #endif
1209                 buzz((int) (-20 - (typ - 1)), (int) mattk->damn, mtmp->mx,
1210                      mtmp->my, sgn(tbx), sgn(tby));
1211                 nomul(0);
1212                 /* breath runs out sometimes. Also, give monster some
1213                  * cunning; don't breath if the player fell asleep.
1214                  */
1215                 if (!rn2(3))
1216                     mtmp->mspec_used = 10 + rn2(20);
1217                 if (typ == AD_SLEE && !Sleep_resistance)
1218                     mtmp->mspec_used += rnd(20);
1219             } else
1220                 impossible("Breath weapon %d used", typ - 1);
1221         }
1222     }
1223     return 1;
1224 }
1225
1226 boolean
1227 linedup(ax, ay, bx, by, boulderhandling)
1228 register xchar ax, ay, bx, by;
1229 int boulderhandling; /* 0=block, 1=ignore, 2=conditionally block */
1230 {
1231     int dx, dy, boulderspots;
1232
1233     /* These two values are set for use after successful return. */
1234     tbx = ax - bx;
1235     tby = ay - by;
1236
1237     /* sometimes displacement makes a monster think that you're at its
1238        own location; prevent it from throwing and zapping in that case */
1239     if (!tbx && !tby)
1240         return FALSE;
1241
1242     if ((!tbx || !tby || abs(tbx) == abs(tby)) /* straight line or diagonal */
1243         && distmin(tbx, tby, 0, 0) < BOLT_LIM) {
1244         if ((ax == u.ux && ay == u.uy) ? (boolean) couldsee(bx, by)
1245                                        : clear_path(ax, ay, bx, by))
1246             return TRUE;
1247         /* don't have line of sight, but might still be lined up
1248            if that lack of sight is due solely to boulders */
1249         if (boulderhandling == 0)
1250             return FALSE;
1251         dx = sgn(ax - bx), dy = sgn(ay - by);
1252         boulderspots = 0;
1253         do {
1254             /* <bx,by> is guaranteed to eventually converge with <ax,ay> */
1255             bx += dx, by += dy;
1256             if (IS_ROCK(levl[bx][by].typ) || closed_door(bx, by))
1257                 return FALSE;
1258             if (sobj_at(BOULDER, bx, by))
1259                 ++boulderspots;
1260         } while (bx != ax || by != ay);
1261         /* reached target position without encountering obstacle */
1262         if (boulderhandling == 1 || rn2(2 + boulderspots) < 2)
1263             return TRUE;
1264     }
1265     return FALSE;
1266 }
1267
1268 STATIC_OVL boolean
1269 m_lined_up(mtarg, mtmp)
1270 struct monst *mtarg, *mtmp;
1271 {
1272     return (linedup(mtarg->mx, mtarg->my, mtmp->mx, mtmp->my, 0));
1273 }
1274
1275
1276 /* is mtmp in position to use ranged attack? */
1277 boolean
1278 lined_up(mtmp)
1279 register struct monst *mtmp;
1280 {
1281     boolean ignore_boulders;
1282
1283     /* hero concealment usually trumps monst awareness of being lined up */
1284     if (Upolyd && rn2(25)
1285         && (u.uundetected || (U_AP_TYPE != M_AP_NOTHING
1286                               && U_AP_TYPE != M_AP_MONSTER)))
1287         return FALSE;
1288
1289     ignore_boulders = (throws_rocks(mtmp->data)
1290                        || m_carrying(mtmp, WAN_STRIKING));
1291     return linedup(mtmp->mux, mtmp->muy, mtmp->mx, mtmp->my,
1292                    ignore_boulders ? 1 : 2);
1293 }
1294
1295 /* check if a monster is carrying a particular item */
1296 struct obj *
1297 m_carrying(mtmp, type)
1298 struct monst *mtmp;
1299 int type;
1300 {
1301     register struct obj *otmp;
1302
1303     for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
1304         if (otmp->otyp == type)
1305             return otmp;
1306     return (struct obj *) 0;
1307 }
1308
1309 void
1310 hit_bars(objp, objx, objy, barsx, barsy, your_fault, from_invent)
1311 struct obj **objp;      /* *objp will be set to NULL if object breaks */
1312 int objx, objy, barsx, barsy;
1313 boolean your_fault, from_invent;
1314 {
1315     struct obj *otmp = *objp;
1316     int obj_type = otmp->otyp;
1317     boolean unbreakable = (levl[barsx][barsy].wall_info & W_NONDIGGABLE) != 0;
1318
1319     if (your_fault
1320         ? hero_breaks(otmp, objx, objy, from_invent)
1321         : breaks(otmp, objx, objy)) {
1322         *objp = 0; /* object is now gone */
1323         /* breakage makes its own noises */
1324         if (obj_type == POT_ACID) {
1325             if (cansee(barsx, barsy) && !unbreakable)
1326 /*JP
1327                 pline_The("iron bars are dissolved!");
1328 */
1329                 pline_The("\93S\82Ì\96_\82Í\97Z\82¯\82½\81I");
1330             else
1331 /*JP
1332                 You_hear(Hallucination ? "angry snakes!" : "a hissing noise.");
1333 */
1334                 You_hear(Hallucination ? "\93{\82Á\82½\82Ö\82Ñ\82Ì\90º\82ð\95·\82¢\82½\81I" : "\83V\81[\83b\82Æ\82¢\82¤\89¹\82ð\95·\82¢\82½\81D");
1335             if (!unbreakable)
1336                 dissolve_bars(barsx, barsy);
1337         }
1338     }
1339     else if (obj_type == BOULDER || obj_type == HEAVY_IRON_BALL)
1340 /*JP
1341         pline("Whang!");
1342 */
1343         pline("\82®\82í\81[\82ñ\81I");
1344     else if (otmp->oclass == COIN_CLASS
1345              || objects[obj_type].oc_material == GOLD
1346              || objects[obj_type].oc_material == SILVER)
1347 /*JP
1348         pline("Clink!");
1349 */
1350         pline("\83`\83\83\83\8a\83\93\81I");
1351     else
1352 /*JP
1353         pline("Clonk!");
1354 */
1355         pline("\83S\83c\83\93\81I");
1356 }
1357
1358 /* TRUE iff thrown/kicked/rolled object doesn't pass through iron bars */
1359 boolean
1360 hits_bars(obj_p, x, y, barsx, barsy, always_hit, whodidit)
1361 struct obj **obj_p; /* *obj_p will be set to NULL if object breaks */
1362 int x, y, barsx, barsy;
1363 int always_hit; /* caller can force a hit for items which would fit through */
1364 int whodidit;   /* 1==hero, 0=other, -1==just check whether it'll pass thru */
1365 {
1366     struct obj *otmp = *obj_p;
1367     int obj_type = otmp->otyp;
1368     boolean hits = always_hit;
1369
1370     if (!hits)
1371         switch (otmp->oclass) {
1372         case WEAPON_CLASS: {
1373             int oskill = objects[obj_type].oc_skill;
1374
1375             hits = (oskill != -P_BOW && oskill != -P_CROSSBOW
1376                     && oskill != -P_DART && oskill != -P_SHURIKEN
1377                     && oskill != P_SPEAR
1378                     && oskill != P_KNIFE); /* but not dagger */
1379             break;
1380         }
1381         case ARMOR_CLASS:
1382             hits = (objects[obj_type].oc_armcat != ARM_GLOVES);
1383             break;
1384         case TOOL_CLASS:
1385             hits = (obj_type != SKELETON_KEY && obj_type != LOCK_PICK
1386                     && obj_type != CREDIT_CARD && obj_type != TALLOW_CANDLE
1387                     && obj_type != WAX_CANDLE && obj_type != LENSES
1388                     && obj_type != TIN_WHISTLE && obj_type != MAGIC_WHISTLE);
1389             break;
1390         case ROCK_CLASS: /* includes boulder */
1391             if (obj_type != STATUE || mons[otmp->corpsenm].msize > MZ_TINY)
1392                 hits = TRUE;
1393             break;
1394         case FOOD_CLASS:
1395             if (obj_type == CORPSE && mons[otmp->corpsenm].msize > MZ_TINY)
1396                 hits = TRUE;
1397             else
1398                 hits = (obj_type == MEAT_STICK
1399                         || obj_type == HUGE_CHUNK_OF_MEAT);
1400             break;
1401         case SPBOOK_CLASS:
1402         case WAND_CLASS:
1403         case BALL_CLASS:
1404         case CHAIN_CLASS:
1405             hits = TRUE;
1406             break;
1407         default:
1408             break;
1409         }
1410
1411     if (hits && whodidit != -1) {
1412         hit_bars(obj_p, x,y, barsx,barsy, whodidit, FALSE);
1413     }
1414
1415     return hits;
1416 }
1417
1418 /*mthrowu.c*/