OSDN Git Service

86453d5a5ed61158ffc9c7d8c097668a17cab4ed
[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-2021            */
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%s%s\81I", Monnam(mtmp),
334               onm,
335               trgbuf,
336               mtarg ? "\82É" : "",
337               m_shot.s ? "\8c\82\82Á\82½" : "\93\8a\82°\82½");
338 #endif
339         m_shot.o = otmp->otyp;
340     } else {
341         m_shot.o = STRANGE_OBJECT; /* don't give multishot feedback */
342     }
343     m_shot.n = multishot;
344     for (m_shot.i = 1; m_shot.i <= m_shot.n; m_shot.i++) {
345         m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), dm, otmp);
346         /* conceptually all N missiles are in flight at once, but
347            if mtmp gets killed (shot kills adjacent gas spore and
348            triggers explosion, perhaps), inventory will be dropped
349            and otmp might go away via merging into another stack */
350         if (DEADMONSTER(mtmp) && m_shot.i < m_shot.n)
351             /* cancel pending shots (perhaps ought to give a message here
352                since we gave one above about throwing/shooting N missiles) */
353             break; /* endmultishot(FALSE); */
354     }
355     /* reset 'm_shot' */
356     m_shot.n = m_shot.i = 0;
357     m_shot.o = STRANGE_OBJECT;
358     m_shot.s = FALSE;
359 }
360
361 /* an object launched by someone/thing other than player attacks a monster;
362    return 1 if the object has stopped moving (hit or its range used up) */
363 int
364 ohitmon(mtmp, otmp, range, verbose)
365 struct monst *mtmp; /* accidental target, located at <bhitpos.x,.y> */
366 struct obj *otmp;   /* missile; might be destroyed by drop_throw */
367 int range;          /* how much farther will object travel if it misses;
368                        use -1 to signify to keep going even after hit,
369                        unless it's gone (used for rolling_boulder_traps) */
370 boolean verbose;    /* give message(s) even when you can't see what happened */
371 {
372     int damage, tmp;
373     boolean vis, ismimic;
374     int objgone = 1;
375     struct obj *mon_launcher = archer ? MON_WEP(archer) : NULL;
376
377     notonhead = (bhitpos.x != mtmp->mx || bhitpos.y != mtmp->my);
378     ismimic = M_AP_TYPE(mtmp) && M_AP_TYPE(mtmp) != M_AP_MONSTER;
379     vis = cansee(bhitpos.x, bhitpos.y);
380
381     tmp = 5 + find_mac(mtmp) + omon_adj(mtmp, otmp, FALSE);
382     /* High level monsters will be more likely to hit */
383     /* This check applies only if this monster is the target
384      * the archer was aiming at. */
385     if (archer && target == mtmp) {
386         if (archer->m_lev > 5)
387             tmp += archer->m_lev - 5;
388         if (mon_launcher && mon_launcher->oartifact)
389             tmp += spec_abon(mon_launcher, mtmp);
390     }
391     if (tmp < rnd(20)) {
392         if (!ismimic) {
393             if (vis)
394                 miss(distant_name(otmp, mshot_xname), mtmp);
395             else if (verbose && !target)
396 /*JP
397                 pline("It is missed.");
398 */
399                 pline("\89½\82©\82ª\82©\82·\82ß\82½\81D");
400         }
401         if (!range) { /* Last position; object drops */
402             (void) drop_throw(otmp, 0, mtmp->mx, mtmp->my);
403             return 1;
404         }
405     } else if (otmp->oclass == POTION_CLASS) {
406         if (ismimic)
407             seemimic(mtmp);
408         mtmp->msleeping = 0;
409         if (vis)
410             otmp->dknown = 1;
411         /* probably thrown by a monster rather than 'other', but the
412            distinction only matters when hitting the hero */
413         potionhit(mtmp, otmp, POTHIT_OTHER_THROW);
414         return 1;
415     } else {
416         damage = dmgval(otmp, mtmp);
417         if (otmp->otyp == ACID_VENOM && resists_acid(mtmp))
418             damage = 0;
419 #if 0 /* can't use this because we don't have the attacker */
420         if (is_orc(mtmp->data) && is_elf(?magr?))
421             damage++;
422 #endif
423         if (ismimic)
424             seemimic(mtmp);
425         mtmp->msleeping = 0;
426         if (vis) {
427             if (otmp->otyp == EGG)
428 #if 0 /*JP:T*/
429                 pline("Splat!  %s is hit with %s egg!", Monnam(mtmp),
430                       otmp->known ? an(mons[otmp->corpsenm].mname) : "an");
431 #else
432                 pline("\83r\83`\83\83\83b\81I%s\82Í%s\97\91\82É\93\96\82½\82Á\82½\81I", Monnam(mtmp),
433                       otmp->known ? s_suffix(mons[otmp->corpsenm].mname) : "");
434 #endif
435             else
436                 hit(distant_name(otmp, mshot_xname), mtmp, exclam(damage));
437         } else if (verbose && !target)
438 #if 0 /*JP:T*/
439             pline("%s%s is hit%s", (otmp->otyp == EGG) ? "Splat!  " : "",
440                   Monnam(mtmp), exclam(damage));
441 #else
442             pline("%s%s\82É\96½\92\86\82µ\82½%s", (otmp->otyp == EGG) ? "\83r\83`\83\83\83b\81I" : "",
443                   Monnam(mtmp), exclam(damage));
444 #endif
445
446         if (otmp->opoisoned && is_poisonable(otmp)) {
447             if (resists_poison(mtmp)) {
448                 if (vis)
449 /*JP
450                     pline_The("poison doesn't seem to affect %s.",
451 */
452                     pline("%s\82Í\93Å\82Ì\89e\8b¿\82ð\8eó\82¯\82È\82¢\82æ\82¤\82¾\81D",
453                               mon_nam(mtmp));
454             } else {
455                 if (rn2(30)) {
456                     damage += rnd(6);
457                 } else {
458                     if (vis)
459 /*JP
460                         pline_The("poison was deadly...");
461 */
462                         pline("\93Å\82Í\92v\8e\80\97Ê\82¾\82Á\82½\81D\81D\81D");
463                     damage = mtmp->mhp;
464                 }
465             }
466         }
467         if (objects[otmp->otyp].oc_material == SILVER
468             && mon_hates_silver(mtmp)) {
469             boolean flesh = (!noncorporeal(mtmp->data)
470                              && !amorphous(mtmp->data));
471
472             /* note: extra silver damage is handled by dmgval() */
473             if (vis) {
474                 char *m_name = mon_nam(mtmp);
475
476                 if (flesh) /* s_suffix returns a modifiable buffer */
477 /*JP
478                     m_name = strcat(s_suffix(m_name), " flesh");
479 */
480                     m_name = strcat(s_suffix(m_name), "\82Ì\91Ì");
481 /*JP
482                 pline_The("silver sears %s!", m_name);
483 */
484                 pline("%s\82Í\8bâ\82Å\8fÄ\82©\82ê\82½\81I", m_name);
485             } else if (verbose && !target) {
486 /*JP
487                 pline("%s is seared!", flesh ? "Its flesh" : "It");
488 */
489                 pline("\89½%s\82Í\8fÄ\82©\82ê\82½\81I", flesh ? "\8eÒ\82©\82Ì\91Ì" : "\82©");
490             }
491         }
492         if (otmp->otyp == ACID_VENOM && cansee(mtmp->mx, mtmp->my)) {
493             if (resists_acid(mtmp)) {
494                 if (vis || (verbose && !target))
495 /*JP
496                     pline("%s is unaffected.", Monnam(mtmp));
497 */
498                     pline("%s\82Í\89e\8b¿\82ð\8eó\82¯\82È\82¢\81D", Monnam(mtmp));
499             } else {
500                 if (vis)
501 /*JP
502                     pline_The("%s burns %s!", hliquid("acid"), mon_nam(mtmp));
503 */
504                     pline_The("%s\82Í%s\82Å\8fÄ\82©\82ê\82½\81I", mon_nam(mtmp), hliquid("\8e_"));
505                 else if (verbose && !target)
506 /*JP
507                     pline("It is burned!");
508 */
509                     pline("\89½\82©\82Í\8fÄ\82©\82ê\82½\81I");
510             }
511         }
512         if (otmp->otyp == EGG && touch_petrifies(&mons[otmp->corpsenm])) {
513             if (!munstone(mtmp, TRUE))
514                 minstapetrify(mtmp, TRUE);
515             if (resists_ston(mtmp))
516                 damage = 0;
517         }
518
519         if (!DEADMONSTER(mtmp)) { /* might already be dead (if petrified) */
520             mtmp->mhp -= damage;
521             if (DEADMONSTER(mtmp)) {
522                 if (vis || (verbose && !target))
523 #if 0 /*JP:T*/
524                     pline("%s is %s!", Monnam(mtmp),
525                           (nonliving(mtmp->data) || is_vampshifter(mtmp)
526                            || !canspotmon(mtmp)) ? "destroyed" : "killed");
527 #else
528                     pline("%s\82Í%s\81I", Monnam(mtmp),
529                           (nonliving(mtmp->data) || is_vampshifter(mtmp)
530                            || !canspotmon(mtmp)) ? "\93|\82³\82ê\82½" : "\8e\80\82ñ\82¾");
531 #endif
532                 /* don't blame hero for unknown rolling boulder trap */
533                 if (!context.mon_moving && (otmp->otyp != BOULDER
534                                             || range >= 0 || otmp->otrapped))
535                     xkilled(mtmp, XKILL_NOMSG);
536                 else
537                     mondied(mtmp);
538             }
539         }
540
541         /* blinding venom and cream pie do 0 damage, but verify
542            that the target is still alive anyway */
543         if (!DEADMONSTER(mtmp)
544             && can_blnd((struct monst *) 0, mtmp,
545                         (uchar) ((otmp->otyp == BLINDING_VENOM) ? AT_SPIT
546                                                                 : AT_WEAP),
547                         otmp)) {
548             if (vis && mtmp->mcansee)
549 /*JP
550                 pline("%s is blinded by %s.", Monnam(mtmp), the(xname(otmp)));
551 */
552                 pline("%s\82Í%s\82É\82æ\82Á\82Ä\96Ú\82ª\8c©\82¦\82È\82­\82È\82Á\82½\81D", Monnam(mtmp), the(xname(otmp)));
553             mtmp->mcansee = 0;
554             tmp = (int) mtmp->mblinded + rnd(25) + 20;
555             if (tmp > 127)
556                 tmp = 127;
557             mtmp->mblinded = tmp;
558         }
559
560         objgone = drop_throw(otmp, 1, bhitpos.x, bhitpos.y);
561         if (!objgone && range == -1) { /* special case */
562             obj_extract_self(otmp);    /* free it for motion again */
563             return 0;
564         }
565         return 1;
566     }
567     return 0;
568 }
569
570 #define MT_FLIGHTCHECK(pre)                                             \
571     (/* missile hits edge of screen */                                  \
572      !isok(bhitpos.x + dx, bhitpos.y + dy)                              \
573      /* missile hits the wall */                                        \
574      || IS_ROCK(levl[bhitpos.x + dx][bhitpos.y + dy].typ)               \
575      /* missile hit closed door */                                      \
576      || closed_door(bhitpos.x + dx, bhitpos.y + dy)                     \
577      /* missile might hit iron bars */                                  \
578      /* the random chance for small objects hitting bars is */          \
579      /* skipped when reaching them at point blank range */              \
580      || (levl[bhitpos.x + dx][bhitpos.y + dy].typ == IRONBARS           \
581          && hits_bars(&singleobj,                                       \
582                       bhitpos.x, bhitpos.y,                             \
583                       bhitpos.x + dx, bhitpos.y + dy,                   \
584                       ((pre) ? 0 : !rn2(5)), 0))                        \
585      /* Thrown objects "sink" */                                        \
586      || (!(pre) && IS_SINK(levl[bhitpos.x][bhitpos.y].typ)))
587
588 void
589 m_throw(mon, x, y, dx, dy, range, obj)
590 struct monst *mon;       /* launching monster */
591 int x, y, dx, dy, range; /* launch point, direction, and range */
592 struct obj *obj;         /* missile (or stack providing it) */
593 {
594     struct monst *mtmp;
595     struct obj *singleobj;
596     char sym = obj->oclass;
597     int hitu = 0, oldumort, blindinc = 0;
598
599     bhitpos.x = x;
600     bhitpos.y = y;
601     notonhead = FALSE; /* reset potentially stale value */
602
603     if (obj->quan == 1L) {
604         /*
605          * Remove object from minvent.  This cannot be done later on;
606          * what if the player dies before then, leaving the monster
607          * with 0 daggers?  (This caused the infamous 2^32-1 orcish
608          * dagger bug).
609          *
610          * VENOM is not in minvent - it should already be OBJ_FREE.
611          * The extract below does nothing.
612          */
613
614         /* not possibly_unwield, which checks the object's */
615         /* location, not its existence */
616         if (MON_WEP(mon) == obj)
617             setmnotwielded(mon, obj);
618         obj_extract_self(obj);
619         singleobj = obj;
620         obj = (struct obj *) 0;
621     } else {
622         singleobj = splitobj(obj, 1L);
623         obj_extract_self(singleobj);
624     }
625
626     singleobj->owornmask = 0; /* threw one of multiple weapons in hand? */
627
628     if ((singleobj->cursed || singleobj->greased) && (dx || dy) && !rn2(7)) {
629         if (canseemon(mon) && flags.verbose) {
630             if (is_ammo(singleobj))
631 /*JP
632                 pline("%s misfires!", Monnam(mon));
633 */
634                 pline("%s\82Í\82Í\82¸\82µ\82½\81I", Monnam(mon));
635             else
636 #if 0 /*JP:T*/
637                 pline("%s as %s throws it!", Tobjnam(singleobj, "slip"),
638                       mon_nam(mon));
639 #else
640                 pline("%s\82ª\93\8a\82°\82æ\82¤\82Æ\82µ\82½\82Æ\82½\82ñ%s\82ª\8a\8a\82Á\82½\81I",
641                           mon_nam(mon), xname(singleobj));
642 #endif
643         }
644         dx = rn2(3) - 1;
645         dy = rn2(3) - 1;
646         /* check validity of new direction */
647         if (!dx && !dy) {
648             (void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
649             return;
650         }
651     }
652
653     if (MT_FLIGHTCHECK(TRUE)) {
654         (void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
655         return;
656     }
657     mesg_given = 0; /* a 'missile misses' message has not yet been shown */
658
659     /* Note: drop_throw may destroy singleobj.  Since obj must be destroyed
660      * early to avoid the dagger bug, anyone who modifies this code should
661      * be careful not to use either one after it's been freed.
662      */
663     if (sym)
664         tmp_at(DISP_FLASH, obj_to_glyph(singleobj, rn2_on_display_rng));
665     while (range-- > 0) { /* Actually the loop is always exited by break */
666         bhitpos.x += dx;
667         bhitpos.y += dy;
668         mtmp = m_at(bhitpos.x, bhitpos.y);
669         if (mtmp && shade_miss(mon, mtmp, singleobj, TRUE, TRUE)) {
670             /* if mtmp is a shade and missile passes harmlessly through it,
671                give message and skip it in order to keep going */
672             mtmp = (struct monst *) 0;
673         } else if (mtmp) {
674             if (ohitmon(mtmp, singleobj, range, TRUE))
675                 break;
676         } else if (bhitpos.x == u.ux && bhitpos.y == u.uy) {
677             if (multi)
678                 nomul(0);
679
680             if (singleobj->oclass == GEM_CLASS
681                 && singleobj->otyp <= LAST_GEM + 9 /* 9 glass colors */
682                 && is_unicorn(youmonst.data)) {
683                 if (singleobj->otyp > LAST_GEM) {
684 /*JP
685                     You("catch the %s.", xname(singleobj));
686 */
687                     You("%s\82ð\82Â\82©\82Ü\82¦\82½\81D", xname(singleobj));
688 #if 0 /*JP:T*/
689                     You("are not interested in %s junk.",
690                         s_suffix(mon_nam(mon)));
691 #else
692                     You("%s\82Ì\83K\83\89\83N\83^\82É\8b»\96¡\82Í\82È\82¢\81D",
693                         mon_nam(mon));
694 #endif
695                     makeknown(singleobj->otyp);
696                     dropy(singleobj);
697                 } else {
698                     You(
699 /*JP
700                      "accept %s gift in the spirit in which it was intended.",
701 */
702                      "\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",
703                         s_suffix(mon_nam(mon)));
704 #if 0 /*JP:T*/
705                     (void) hold_another_object(singleobj,
706                                                "You catch, but drop, %s.",
707                                                xname(singleobj),
708                                                "You catch:");
709 #else
710                     (void) hold_another_object(singleobj,
711                                      "\82 \82È\82½\82Í%s\82ð\82Â\82©\82Ü\82¦\82½\82ª\81C\97\8e\82µ\82½\81D",
712                                                xname(singleobj),
713                                                "\82ð\82Â\82©\82Ü\82¦\82½\81D");
714 #endif
715                 }
716                 break;
717             }
718             if (singleobj->oclass == POTION_CLASS) {
719                 if (!Blind)
720                     singleobj->dknown = 1;
721                 potionhit(&youmonst, singleobj, POTHIT_MONST_THROW);
722                 break;
723             }
724             oldumort = u.umortality;
725             switch (singleobj->otyp) {
726                 int dam, hitv;
727             case EGG:
728                 if (!touch_petrifies(&mons[singleobj->corpsenm])) {
729                     impossible("monster throwing egg type %d",
730                                singleobj->corpsenm);
731                     hitu = 0;
732                     break;
733                 }
734             /* fall through */
735             case CREAM_PIE:
736             case BLINDING_VENOM:
737                 hitu = thitu(8, 0, &singleobj, (char *) 0);
738                 break;
739             default:
740                 dam = dmgval(singleobj, &youmonst);
741                 hitv = 3 - distmin(u.ux, u.uy, mon->mx, mon->my);
742                 if (hitv < -4)
743                     hitv = -4;
744                 if (is_elf(mon->data)
745                     && objects[singleobj->otyp].oc_skill == P_BOW) {
746                     hitv++;
747                     if (MON_WEP(mon) && MON_WEP(mon)->otyp == ELVEN_BOW)
748                         hitv++;
749                     if (singleobj->otyp == ELVEN_ARROW)
750                         dam++;
751                 }
752                 if (bigmonst(youmonst.data))
753                     hitv++;
754                 hitv += 8 + singleobj->spe;
755                 if (dam < 1)
756                     dam = 1;
757                 hitu = thitu(hitv, dam, &singleobj, (char *) 0);
758             }
759             if (hitu && singleobj->opoisoned && is_poisonable(singleobj)) {
760                 char onmbuf[BUFSZ], knmbuf[BUFSZ];
761
762                 Strcpy(onmbuf, xname(singleobj));
763                 Strcpy(knmbuf, killer_xname(singleobj));
764                 poisoned(onmbuf, A_STR, knmbuf,
765                          /* if damage triggered life-saving,
766                             poison is limited to attrib loss */
767                          (u.umortality > oldumort) ? 0 : 10, TRUE);
768             }
769             if (hitu && can_blnd((struct monst *) 0, &youmonst,
770                                  (uchar) ((singleobj->otyp == BLINDING_VENOM)
771                                              ? AT_SPIT
772                                              : AT_WEAP),
773                                  singleobj)) {
774                 blindinc = rnd(25);
775                 if (singleobj->otyp == CREAM_PIE) {
776                     if (!Blind)
777 /*JP
778                         pline("Yecch!  You've been creamed.");
779 */
780                         pline("\83E\83F\81[\81D\83N\83\8a\81[\83\80\82ð\82©\82Ô\82Á\82½\81D");
781                     else
782 #if 0 /*JP:T*/
783                         pline("There's %s sticky all over your %s.",
784                               something, body_part(FACE));
785 #else
786                         pline("\82 \82È\82½\82Í%s\82É\82×\82Æ\82Â\82­\82à\82Ì\82ð\8a´\82\82½\81D",
787                               body_part(FACE));
788 #endif
789                 } else if (singleobj->otyp == BLINDING_VENOM) {
790 #if 0 /*JP*/
791                     const char *eyes = body_part(EYE);
792
793                     if (eyecount(youmonst.data) != 1)
794                         eyes = makeplural(eyes);
795                     /* venom in the eyes */
796                     if (!Blind)
797                         pline_The("venom blinds you.");
798                     else
799                         Your("%s %s.", eyes, vtense(eyes, "sting"));
800 #else
801                     if(!Blind)
802                         pline("\93Å\82Å\96Ú\82ª\8c©\82¦\82È\82­\82È\82Á\82½\81D");
803                     else
804                         Your("%s\82Í\82¿\82­\82¿\82­\82µ\82½\81D", body_part(EYE));
805 #endif
806                 }
807             }
808             if (hitu && singleobj->otyp == EGG) {
809                 if (!Stoned && !Stone_resistance
810                     && !(poly_when_stoned(youmonst.data)
811                          && polymon(PM_STONE_GOLEM))) {
812                     make_stoned(5L, (char *) 0, KILLED_BY, "");
813                 }
814             }
815             stop_occupation();
816             if (hitu) {
817                 (void) drop_throw(singleobj, hitu, u.ux, u.uy);
818                 break;
819             }
820         }
821         if (!range /* reached end of path */
822             || MT_FLIGHTCHECK(FALSE)) {
823             if (singleobj) { /* hits_bars might have destroyed it */
824                 if (m_shot.n > 1
825                     && (!mesg_given || bhitpos.x != u.ux || bhitpos.y != u.uy)
826                     && (cansee(bhitpos.x, bhitpos.y)
827                         || (archer && canseemon(archer))))
828 /*JP
829                     pline("%s misses.", The(mshot_xname(singleobj)));
830 */
831                     pline("%s\82Í\82Í\82¸\82ê\82½\81D", mshot_xname(singleobj));
832                 (void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
833             }
834             break;
835         }
836         tmp_at(bhitpos.x, bhitpos.y);
837         delay_output();
838     }
839     tmp_at(bhitpos.x, bhitpos.y);
840     delay_output();
841     tmp_at(DISP_END, 0);
842     mesg_given = 0; /* reset */
843
844     if (blindinc) {
845         u.ucreamed += blindinc;
846         make_blinded(Blinded + (long) blindinc, FALSE);
847         if (!Blind)
848             Your1(vision_clears);
849     }
850 }
851
852 #undef MT_FLIGHTCHECK
853
854 /* Monster throws item at another monster */
855 int
856 thrwmm(mtmp, mtarg)
857 struct monst *mtmp, *mtarg;
858 {
859     struct obj *otmp, *mwep;
860     register xchar x, y;
861     boolean ispole;
862
863     /* Polearms won't be applied by monsters against other monsters */
864     if (mtmp->weapon_check == NEED_WEAPON || !MON_WEP(mtmp)) {
865         mtmp->weapon_check = NEED_RANGED_WEAPON;
866         /* mon_wield_item resets weapon_check as appropriate */
867         if (mon_wield_item(mtmp) != 0)
868             return 0;
869     }
870
871     /* Pick a weapon */
872     otmp = select_rwep(mtmp);
873     if (!otmp)
874         return 0;
875     ispole = is_pole(otmp);
876
877     x = mtmp->mx;
878     y = mtmp->my;
879
880     mwep = MON_WEP(mtmp); /* wielded weapon */
881
882     if (!ispole && m_lined_up(mtarg, mtmp)) {
883         int chance = max(BOLT_LIM - distmin(x, y, mtarg->mx, mtarg->my), 1);
884
885         if (!mtarg->mflee || !rn2(chance)) {
886             if (ammo_and_launcher(otmp, mwep)
887                 && dist2(mtmp->mx, mtmp->my, mtarg->mx, mtarg->my)
888                    > PET_MISSILE_RANGE2)
889                 return 0; /* Out of range */
890             /* Set target monster */
891             target = mtarg;
892             archer = mtmp;
893             monshoot(mtmp, otmp, mwep); /* multishot shooting or throwing */
894             archer = target = (struct monst *) 0;
895             nomul(0);
896             return 1;
897         }
898     }
899     return 0;
900 }
901
902 /* monster spits substance at monster */
903 int
904 spitmm(mtmp, mattk, mtarg)
905 struct monst *mtmp, *mtarg;
906 struct attack *mattk;
907 {
908     struct obj *otmp;
909
910     if (mtmp->mcan) {
911         if (!Deaf)
912 #if 0 /*JP:T*/
913             pline("A dry rattle comes from %s throat.",
914                   s_suffix(mon_nam(mtmp)));
915 #else
916             pline("%s\82Ì\8dA\82ª\83K\83\89\83K\83\89\82Æ\96Â\82Á\82½\81D",
917                   mon_nam(mtmp));
918 #endif
919         return 0;
920     }
921     if (m_lined_up(mtarg, mtmp)) {
922         switch (mattk->adtyp) {
923         case AD_BLND:
924         case AD_DRST:
925             otmp = mksobj(BLINDING_VENOM, TRUE, FALSE);
926             break;
927         default:
928             impossible("bad attack type in spitmu");
929             /*FALLTHRU*/
930         case AD_ACID:
931             otmp = mksobj(ACID_VENOM, TRUE, FALSE);
932             break;
933         }
934         if (!rn2(BOLT_LIM-distmin(mtmp->mx,mtmp->my,mtarg->mx,mtarg->my))) {
935             if (canseemon(mtmp))
936 /*JP
937                 pline("%s spits venom!", Monnam(mtmp));
938 */
939                 pline("%s\82Í\93Å\82ð\93f\82¢\82½\81I", Monnam(mtmp));
940             target = mtarg;
941             m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby),
942                     distmin(mtmp->mx,mtmp->my,mtarg->mx,mtarg->my), otmp);
943             target = (struct monst *)0;
944             nomul(0);
945
946             /* If this is a pet, it'll get hungry. Minions and
947              * spell beings won't hunger */
948             if (mtmp->mtame && !mtmp->isminion) {
949                 struct edog *dog = EDOG(mtmp);
950
951                 /* Hunger effects will catch up next move */
952                 if (dog->hungrytime > 1)
953                     dog->hungrytime -= 5;
954             }
955
956             return 1;
957         }
958     }
959     return 0;
960 }
961
962 /* monster breathes at monster (ranged) */
963 int
964 breamm(mtmp, mattk, mtarg)
965 struct monst *mtmp, *mtarg;
966 struct attack  *mattk;
967 {
968     /* if new breath types are added, change AD_ACID to max type */
969     int typ = (mattk->adtyp == AD_RBRE) ? rnd(AD_ACID) : mattk->adtyp ;
970
971     if (m_lined_up(mtarg, mtmp)) {
972         if (mtmp->mcan) {
973             if (!Deaf) {
974                 if (canseemon(mtmp))
975 /*JP
976                     pline("%s coughs.", Monnam(mtmp));
977 */
978                     pline("%s\82Í\82¹\82«\82ð\82µ\82½\81D", Monnam(mtmp));
979                 else
980 /*JP
981                     You_hear("a cough.");
982 */
983                     You_hear("\82¹\82«\82Ì\89¹\82ð\95·\82¢\82½\81D");
984             }
985             return 0;
986         }
987         if (!mtmp->mspec_used && rn2(3)) {
988             if ((typ >= AD_MAGM) && (typ <= AD_ACID)) {
989                 if (canseemon(mtmp))
990 /*JP
991                     pline("%s breathes %s!", Monnam(mtmp), breathwep[typ - 1]);
992 */
993                     pline("%s\82Í%s\82ð\82Í\82¢\82½\81I", Monnam(mtmp), breathwep[typ - 1]);
994                 dobuzz((int) (-20 - (typ - 1)), (int) mattk->damn,
995                        mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), FALSE);
996                 nomul(0);
997                 /* breath runs out sometimes. Also, give monster some
998                  * cunning; don't breath if the target fell asleep.
999                  */
1000                 mtmp->mspec_used = 6 + rn2(18);
1001
1002                 /* If this is a pet, it'll get hungry. Minions and
1003                  * spell beings won't hunger */
1004                 if (mtmp->mtame && !mtmp->isminion) {
1005                     struct edog *dog = EDOG(mtmp);
1006
1007                     /* Hunger effects will catch up next move */
1008                     if (dog->hungrytime >= 10)
1009                         dog->hungrytime -= 10;
1010                 }
1011             } else impossible("Breath weapon %d used", typ-1);
1012         } else
1013             return 0;
1014     }
1015     return 1;
1016 }
1017
1018
1019
1020 /* remove an entire item from a monster's inventory; destroy that item */
1021 void
1022 m_useupall(mon, obj)
1023 struct monst *mon;
1024 struct obj *obj;
1025 {
1026     obj_extract_self(obj);
1027     if (obj->owornmask) {
1028         if (obj == MON_WEP(mon))
1029             mwepgone(mon);
1030         mon->misc_worn_check &= ~obj->owornmask;
1031         update_mon_intrinsics(mon, obj, FALSE, FALSE);
1032         obj->owornmask = 0L;
1033     }
1034     obfree(obj, (struct obj *) 0);
1035 }
1036
1037 /* remove one instance of an item from a monster's inventory */
1038 void
1039 m_useup(mon, obj)
1040 struct monst *mon;
1041 struct obj *obj;
1042 {
1043     if (obj->quan > 1L) {
1044         obj->quan--;
1045         obj->owt = weight(obj);
1046     } else {
1047         m_useupall(mon, obj);
1048     }
1049 }
1050
1051 /* monster attempts ranged weapon attack against player */
1052 void
1053 thrwmu(mtmp)
1054 struct monst *mtmp;
1055 {
1056     struct obj *otmp, *mwep;
1057     xchar x, y;
1058     const char *onm;
1059
1060     /* Rearranged beginning so monsters can use polearms not in a line */
1061     if (mtmp->weapon_check == NEED_WEAPON || !MON_WEP(mtmp)) {
1062         mtmp->weapon_check = NEED_RANGED_WEAPON;
1063         /* mon_wield_item resets weapon_check as appropriate */
1064         if (mon_wield_item(mtmp) != 0)
1065             return;
1066     }
1067
1068     /* Pick a weapon */
1069     otmp = select_rwep(mtmp);
1070     if (!otmp)
1071         return;
1072
1073     if (is_pole(otmp)) {
1074         int dam, hitv;
1075
1076         if (otmp != MON_WEP(mtmp))
1077             return; /* polearm must be wielded */
1078         if (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) > POLE_LIM
1079             || !couldsee(mtmp->mx, mtmp->my))
1080             return; /* Out of range, or intervening wall */
1081
1082         if (canseemon(mtmp)) {
1083             onm = xname(otmp);
1084 #if 0 /*JP:T*/
1085             pline("%s thrusts %s.", Monnam(mtmp),
1086                   obj_is_pname(otmp) ? the(onm) : an(onm));
1087 #else
1088             pline("%s\82Í%s\82ð\93Ë\82«\8eh\82µ\82½\81D", Monnam(mtmp), onm);
1089 #endif
1090         }
1091
1092         dam = dmgval(otmp, &youmonst);
1093         hitv = 3 - distmin(u.ux, u.uy, mtmp->mx, mtmp->my);
1094         if (hitv < -4)
1095             hitv = -4;
1096         if (bigmonst(youmonst.data))
1097             hitv++;
1098         hitv += 8 + otmp->spe;
1099         if (dam < 1)
1100             dam = 1;
1101
1102         (void) thitu(hitv, dam, &otmp, (char *) 0);
1103         stop_occupation();
1104         return;
1105     }
1106
1107     x = mtmp->mx;
1108     y = mtmp->my;
1109     /* If you are coming toward the monster, the monster
1110      * should try to soften you up with missiles.  If you are
1111      * going away, you are probably hurt or running.  Give
1112      * chase, but if you are getting too far away, throw.
1113      */
1114     if (!lined_up(mtmp)
1115         || (URETREATING(x, y)
1116             && rn2(BOLT_LIM - distmin(x, y, mtmp->mux, mtmp->muy))))
1117         return;
1118
1119     mwep = MON_WEP(mtmp); /* wielded weapon */
1120     monshoot(mtmp, otmp, mwep); /* multishot shooting or throwing */
1121     nomul(0);
1122 }
1123
1124 /* monster spits substance at you */
1125 int
1126 spitmu(mtmp, mattk)
1127 struct monst *mtmp;
1128 struct attack *mattk;
1129 {
1130     struct obj *otmp;
1131
1132     if (mtmp->mcan) {
1133         if (!Deaf)
1134 #if 0 /*JP:T*/
1135             pline("A dry rattle comes from %s throat.",
1136                   s_suffix(mon_nam(mtmp)));
1137 #else
1138             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",
1139                   mon_nam(mtmp));
1140 #endif
1141         return 0;
1142     }
1143     if (lined_up(mtmp)) {
1144         switch (mattk->adtyp) {
1145         case AD_BLND:
1146         case AD_DRST:
1147             otmp = mksobj(BLINDING_VENOM, TRUE, FALSE);
1148             break;
1149         default:
1150             impossible("bad attack type in spitmu");
1151         /* fall through */
1152         case AD_ACID:
1153             otmp = mksobj(ACID_VENOM, TRUE, FALSE);
1154             break;
1155         }
1156         if (!rn2(BOLT_LIM
1157                  - distmin(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy))) {
1158             if (canseemon(mtmp))
1159 /*JP
1160                 pline("%s spits venom!", Monnam(mtmp));
1161 */
1162                 pline("%s\82Í\93Å\89t\82ð\93f\82¢\82½\81I", Monnam(mtmp));
1163             m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby),
1164                     distmin(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy), otmp);
1165             nomul(0);
1166             return 0;
1167         } else {
1168             obj_extract_self(otmp);
1169             obfree(otmp, (struct obj *) 0);
1170         }
1171     }
1172     return 0;
1173 }
1174
1175 /* monster breathes at you (ranged) */
1176 int
1177 breamu(mtmp, mattk)
1178 struct monst *mtmp;
1179 struct attack *mattk;
1180 {
1181     /* if new breath types are added, change AD_ACID to max type */
1182     int typ = (mattk->adtyp == AD_RBRE) ? rnd(AD_ACID) : mattk->adtyp;
1183
1184     if (lined_up(mtmp)) {
1185         if (mtmp->mcan) {
1186             if (!Deaf) {
1187                 if (canseemon(mtmp))
1188 /*JP
1189                     pline("%s coughs.", Monnam(mtmp));
1190 */
1191                     pline("%s\82Í\82¹\82«\82ð\82µ\82½\81D", Monnam(mtmp));
1192                 else
1193 /*JP
1194                     You_hear("a cough.");
1195 */
1196                     You_hear("\82¹\82«\82Ì\89¹\82ð\95·\82¢\82½\81D");
1197             }
1198             return 0;
1199         }
1200         if (!mtmp->mspec_used && rn2(3)) {
1201             if ((typ >= AD_MAGM) && (typ <= AD_ACID)) {
1202                 if (canseemon(mtmp))
1203 #if 0 /*JP:T*/
1204                     pline("%s breathes %s!", Monnam(mtmp),
1205                           breathwep[typ - 1]);
1206 #else
1207                     pline("%s\82Í%s\82ð\93f\82¢\82½\81I", Monnam(mtmp),
1208                           breathwep[typ - 1]);
1209 #endif
1210                 buzz((int) (-20 - (typ - 1)), (int) mattk->damn, mtmp->mx,
1211                      mtmp->my, sgn(tbx), sgn(tby));
1212                 nomul(0);
1213                 /* breath runs out sometimes. Also, give monster some
1214                  * cunning; don't breath if the player fell asleep.
1215                  */
1216                 if (!rn2(3))
1217                     mtmp->mspec_used = 10 + rn2(20);
1218                 if (typ == AD_SLEE && !Sleep_resistance)
1219                     mtmp->mspec_used += rnd(20);
1220             } else
1221                 impossible("Breath weapon %d used", typ - 1);
1222         }
1223     }
1224     return 1;
1225 }
1226
1227 boolean
1228 linedup(ax, ay, bx, by, boulderhandling)
1229 register xchar ax, ay, bx, by;
1230 int boulderhandling; /* 0=block, 1=ignore, 2=conditionally block */
1231 {
1232     int dx, dy, boulderspots;
1233
1234     /* These two values are set for use after successful return. */
1235     tbx = ax - bx;
1236     tby = ay - by;
1237
1238     /* sometimes displacement makes a monster think that you're at its
1239        own location; prevent it from throwing and zapping in that case */
1240     if (!tbx && !tby)
1241         return FALSE;
1242
1243     if ((!tbx || !tby || abs(tbx) == abs(tby)) /* straight line or diagonal */
1244         && distmin(tbx, tby, 0, 0) < BOLT_LIM) {
1245         if ((ax == u.ux && ay == u.uy) ? (boolean) couldsee(bx, by)
1246                                        : clear_path(ax, ay, bx, by))
1247             return TRUE;
1248         /* don't have line of sight, but might still be lined up
1249            if that lack of sight is due solely to boulders */
1250         if (boulderhandling == 0)
1251             return FALSE;
1252         dx = sgn(ax - bx), dy = sgn(ay - by);
1253         boulderspots = 0;
1254         do {
1255             /* <bx,by> is guaranteed to eventually converge with <ax,ay> */
1256             bx += dx, by += dy;
1257             if (IS_ROCK(levl[bx][by].typ) || closed_door(bx, by))
1258                 return FALSE;
1259             if (sobj_at(BOULDER, bx, by))
1260                 ++boulderspots;
1261         } while (bx != ax || by != ay);
1262         /* reached target position without encountering obstacle */
1263         if (boulderhandling == 1 || rn2(2 + boulderspots) < 2)
1264             return TRUE;
1265     }
1266     return FALSE;
1267 }
1268
1269 STATIC_OVL boolean
1270 m_lined_up(mtarg, mtmp)
1271 struct monst *mtarg, *mtmp;
1272 {
1273     return (linedup(mtarg->mx, mtarg->my, mtmp->mx, mtmp->my, 0));
1274 }
1275
1276
1277 /* is mtmp in position to use ranged attack? */
1278 boolean
1279 lined_up(mtmp)
1280 register struct monst *mtmp;
1281 {
1282     boolean ignore_boulders;
1283
1284     /* hero concealment usually trumps monst awareness of being lined up */
1285     if (Upolyd && rn2(25)
1286         && (u.uundetected || (U_AP_TYPE != M_AP_NOTHING
1287                               && U_AP_TYPE != M_AP_MONSTER)))
1288         return FALSE;
1289
1290     ignore_boulders = (throws_rocks(mtmp->data)
1291                        || m_carrying(mtmp, WAN_STRIKING));
1292     return linedup(mtmp->mux, mtmp->muy, mtmp->mx, mtmp->my,
1293                    ignore_boulders ? 1 : 2);
1294 }
1295
1296 /* check if a monster is carrying a particular item */
1297 struct obj *
1298 m_carrying(mtmp, type)
1299 struct monst *mtmp;
1300 int type;
1301 {
1302     register struct obj *otmp;
1303
1304     for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
1305         if (otmp->otyp == type)
1306             return otmp;
1307     return (struct obj *) 0;
1308 }
1309
1310 void
1311 hit_bars(objp, objx, objy, barsx, barsy, your_fault, from_invent)
1312 struct obj **objp;      /* *objp will be set to NULL if object breaks */
1313 int objx, objy, barsx, barsy;
1314 boolean your_fault, from_invent;
1315 {
1316     struct obj *otmp = *objp;
1317     int obj_type = otmp->otyp;
1318     boolean unbreakable = (levl[barsx][barsy].wall_info & W_NONDIGGABLE) != 0;
1319
1320     if (your_fault
1321         ? hero_breaks(otmp, objx, objy, from_invent)
1322         : breaks(otmp, objx, objy)) {
1323         *objp = 0; /* object is now gone */
1324         /* breakage makes its own noises */
1325         if (obj_type == POT_ACID) {
1326             if (cansee(barsx, barsy) && !unbreakable)
1327 /*JP
1328                 pline_The("iron bars are dissolved!");
1329 */
1330                 pline_The("\93S\82Ì\96_\82Í\97Z\82¯\82½\81I");
1331             else
1332 /*JP
1333                 You_hear(Hallucination ? "angry snakes!" : "a hissing noise.");
1334 */
1335                 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");
1336             if (!unbreakable)
1337                 dissolve_bars(barsx, barsy);
1338         }
1339     }
1340     else if (obj_type == BOULDER || obj_type == HEAVY_IRON_BALL)
1341 /*JP
1342         pline("Whang!");
1343 */
1344         pline("\82®\82í\81[\82ñ\81I");
1345     else if (otmp->oclass == COIN_CLASS
1346              || objects[obj_type].oc_material == GOLD
1347              || objects[obj_type].oc_material == SILVER)
1348 /*JP
1349         pline("Clink!");
1350 */
1351         pline("\83`\83\83\83\8a\83\93\81I");
1352     else
1353 /*JP
1354         pline("Clonk!");
1355 */
1356         pline("\83S\83c\83\93\81I");
1357 }
1358
1359 /* TRUE iff thrown/kicked/rolled object doesn't pass through iron bars */
1360 boolean
1361 hits_bars(obj_p, x, y, barsx, barsy, always_hit, whodidit)
1362 struct obj **obj_p; /* *obj_p will be set to NULL if object breaks */
1363 int x, y, barsx, barsy;
1364 int always_hit; /* caller can force a hit for items which would fit through */
1365 int whodidit;   /* 1==hero, 0=other, -1==just check whether it'll pass thru */
1366 {
1367     struct obj *otmp = *obj_p;
1368     int obj_type = otmp->otyp;
1369     boolean hits = always_hit;
1370
1371     if (!hits)
1372         switch (otmp->oclass) {
1373         case WEAPON_CLASS: {
1374             int oskill = objects[obj_type].oc_skill;
1375
1376             hits = (oskill != -P_BOW && oskill != -P_CROSSBOW
1377                     && oskill != -P_DART && oskill != -P_SHURIKEN
1378                     && oskill != P_SPEAR
1379                     && oskill != P_KNIFE); /* but not dagger */
1380             break;
1381         }
1382         case ARMOR_CLASS:
1383             hits = (objects[obj_type].oc_armcat != ARM_GLOVES);
1384             break;
1385         case TOOL_CLASS:
1386             hits = (obj_type != SKELETON_KEY && obj_type != LOCK_PICK
1387                     && obj_type != CREDIT_CARD && obj_type != TALLOW_CANDLE
1388                     && obj_type != WAX_CANDLE && obj_type != LENSES
1389                     && obj_type != TIN_WHISTLE && obj_type != MAGIC_WHISTLE);
1390             break;
1391         case ROCK_CLASS: /* includes boulder */
1392             if (obj_type != STATUE || mons[otmp->corpsenm].msize > MZ_TINY)
1393                 hits = TRUE;
1394             break;
1395         case FOOD_CLASS:
1396             if (obj_type == CORPSE && mons[otmp->corpsenm].msize > MZ_TINY)
1397                 hits = TRUE;
1398             else
1399                 hits = (obj_type == MEAT_STICK
1400                         || obj_type == HUGE_CHUNK_OF_MEAT);
1401             break;
1402         case SPBOOK_CLASS:
1403         case WAND_CLASS:
1404         case BALL_CLASS:
1405         case CHAIN_CLASS:
1406             hits = TRUE;
1407             break;
1408         default:
1409             break;
1410         }
1411
1412     if (hits && whodidit != -1) {
1413         hit_bars(obj_p, x,y, barsx,barsy, whodidit, FALSE);
1414     }
1415
1416     return hits;
1417 }
1418
1419 /*mthrowu.c*/