OSDN Git Service

upgrade to 3.6.1
[jnethack/source.git] / src / monmove.c
1 /* NetHack 3.6  monmove.c       $NHDT-Date: 1517877380 2018/02/06 00:36:20 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.96 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Michael Allison, 2006. */
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-2016            */
9 /* JNetHack may be freely redistributed.  See license for details. */
10
11 #include "hack.h"
12 #include "mfndpos.h"
13 #include "artifact.h"
14
15 extern boolean notonhead;
16
17 STATIC_DCL void FDECL(watch_on_duty, (struct monst *));
18 STATIC_DCL int FDECL(disturb, (struct monst *));
19 STATIC_DCL void FDECL(release_hero, (struct monst *));
20 STATIC_DCL void FDECL(distfleeck, (struct monst *, int *, int *, int *));
21 STATIC_DCL int FDECL(m_arrival, (struct monst *));
22 STATIC_DCL boolean FDECL(stuff_prevents_passage, (struct monst *));
23 STATIC_DCL int FDECL(vamp_shift, (struct monst *, struct permonst *, BOOLEAN_P));
24
25 /* True if mtmp died */
26 boolean
27 mb_trapped(mtmp)
28 struct monst *mtmp;
29 {
30     if (flags.verbose) {
31         if (cansee(mtmp->mx, mtmp->my) && !Unaware)
32 /*JP
33             pline("KABOOM!!  You see a door explode.");
34 */
35             pline("\82¿\82ã\82Ç\81[\82ñ\81I\83h\83A\82ª\94\9a\94­\82·\82é\82Ì\82ð\8c©\82½\81D");
36         else if (!Deaf)
37 /*JP
38             You_hear("a distant explosion.");
39 */
40             You_hear("\89\93\95û\82Å\94\9a\94­\82·\82é\89¹\82ð\95·\82¢\82½\81D");
41     }
42     wake_nearto(mtmp->mx, mtmp->my, 7 * 7);
43     mtmp->mstun = 1;
44     mtmp->mhp -= rnd(15);
45     if (mtmp->mhp <= 0) {
46         mondied(mtmp);
47         if (mtmp->mhp > 0) /* lifesaved */
48             return FALSE;
49         else
50             return TRUE;
51     }
52     return FALSE;
53 }
54
55 /* check whether a monster is carrying a locking/unlocking tool */
56 boolean
57 monhaskey(mon, for_unlocking)
58 struct monst *mon;
59 boolean for_unlocking; /* true => credit card ok, false => not ok */
60 {
61     if (for_unlocking && m_carrying(mon, CREDIT_CARD))
62         return TRUE;
63     return m_carrying(mon, SKELETON_KEY) || m_carrying(mon, LOCK_PICK);
64 }
65
66 void
67 mon_yells(mon, shout)
68 struct monst *mon;
69 const char *shout;
70 {
71     if (Deaf) {
72         if (canspotmon(mon))
73             /* Sidenote on "A watchman angrily waves her arms!"
74              * Female being called watchman is correct (career name).
75              */
76             pline("%s angrily %s %s %s!",
77                 Amonnam(mon),
78                 nolimbs(mon->data) ? "shakes" : "waves",
79                 mhis(mon),
80                 nolimbs(mon->data) ? mbodypart(mon, HEAD)
81                                    : makeplural(mbodypart(mon, ARM)));
82     } else {
83         if (canspotmon(mon))
84 /*JP
85         pline("%s yells:", Amonnam(mon));
86 */
87         pline("%s\82Í\8b©\82ñ\82¾\81F", Amonnam(mon));
88         else
89 /*JP
90         You_hear("someone yell:");
91 */
92         pline("\89½\8eÒ\82©\82Í\8b©\82ñ\82¾\81F");
93         verbalize1(shout);
94     }
95 }
96
97 STATIC_OVL void
98 watch_on_duty(mtmp)
99 register struct monst *mtmp;
100 {
101     int x, y;
102
103     if (mtmp->mpeaceful && in_town(u.ux + u.dx, u.uy + u.dy)
104         && mtmp->mcansee && m_canseeu(mtmp) && !rn2(3)) {
105         if (picking_lock(&x, &y) && IS_DOOR(levl[x][y].typ)
106             && (levl[x][y].doormask & D_LOCKED)) {
107             if (couldsee(mtmp->mx, mtmp->my)) {
108                 if (levl[x][y].looted & D_WARNED) {
109 /*JP
110                     mon_yells(mtmp, "Halt, thief!  You're under arrest!");
111 */
112                     verbalize("\91Ò\82Ä\81I\82Ê\82·\82Á\82Æ\81I\82¨\82Ü\82¦\82ð\91ß\95ß\82·\82é\81I");
113                     (void) angry_guards(!!Deaf);
114                 } else {
115 /*JP
116                     mon_yells(mtmp, "Hey, stop picking that lock!");
117 */
118                     verbalize("\82¨\82¢\81C\8c®\82ð\8f\9f\8eè\82É\8aJ\82¯\82é\82ñ\82\82á\82È\82¢\81I");
119                     levl[x][y].looted |= D_WARNED;
120                 }
121                 stop_occupation();
122             }
123         } else if (is_digging()) {
124             /* chewing, wand/spell of digging are checked elsewhere */
125             watch_dig(mtmp, context.digging.pos.x, context.digging.pos.y,
126                       FALSE);
127         }
128     }
129 }
130
131 int
132 dochugw(mtmp)
133 register struct monst *mtmp;
134 {
135     int x = mtmp->mx, y = mtmp->my;
136     boolean already_saw_mon = !occupation ? 0 : canspotmon(mtmp);
137     int rd = dochug(mtmp);
138
139     /* a similar check is in monster_nearby() in hack.c */
140     /* check whether hero notices monster and stops current activity */
141     if (occupation && !rd && !Confusion && (!mtmp->mpeaceful || Hallucination)
142         /* it's close enough to be a threat */
143         && distu(x, y) <= (BOLT_LIM + 1) * (BOLT_LIM + 1)
144         /* and either couldn't see it before, or it was too far away */
145         && (!already_saw_mon || !couldsee(x, y)
146             || distu(x, y) > (BOLT_LIM + 1) * (BOLT_LIM + 1))
147         /* can see it now, or sense it and would normally see it */
148         && (canseemon(mtmp) || (sensemon(mtmp) && couldsee(x, y)))
149         && mtmp->mcanmove && !noattacks(mtmp->data)
150         && !onscary(u.ux, u.uy, mtmp))
151         stop_occupation();
152
153     return rd;
154 }
155
156 boolean
157 onscary(x, y, mtmp)
158 int x, y;
159 struct monst *mtmp;
160 {
161     /* creatures who are directly resistant to magical scaring:
162      * Rodney, lawful minions, Angels, the Riders, shopkeepers
163      * inside their own shop, priests inside their own temple */
164     if (mtmp->iswiz || is_lminion(mtmp) || mtmp->data == &mons[PM_ANGEL]
165         || is_rider(mtmp->data)
166         || (mtmp->isshk && inhishop(mtmp))
167         || (mtmp->ispriest && inhistemple(mtmp)))
168         return FALSE;
169
170     /* <0,0> is used by musical scaring to check for the above;
171      * it doesn't care about scrolls or engravings or dungeon branch */
172     if (x == 0 && y == 0)
173         return TRUE;
174
175     /* should this still be true for defiled/molochian altars? */
176     if (IS_ALTAR(levl[x][y].typ)
177         && (mtmp->data->mlet == S_VAMPIRE || is_vampshifter(mtmp)))
178         return TRUE;
179
180     /* the scare monster scroll doesn't have any of the below
181      * restrictions, being its own source of power */
182     if (sobj_at(SCR_SCARE_MONSTER, x, y))
183         return TRUE;
184
185     /*
186      * Creatures who don't (or can't) fear a written Elbereth:
187      * all the above plus shopkeepers (even if poly'd into non-human),
188      * vault guards (also even if poly'd), blind or peaceful monsters,
189      * humans and elves, and minotaurs.
190      *
191      * If the player isn't actually on the square OR the player's image
192      * isn't displaced to the square, no protection is being granted.
193      *
194      * Elbereth doesn't work in Gehennom, the Elemental Planes, or the
195      * Astral Plane; the influence of the Valar only reaches so far.
196      */
197     return (sengr_at("Elbereth", x, y, TRUE)
198             && ((u.ux == x && u.uy == y)
199                 || (Displaced && mtmp->mux == x && mtmp->muy == y))
200             && !(mtmp->isshk || mtmp->isgd || !mtmp->mcansee
201                  || mtmp->mpeaceful || mtmp->data->mlet == S_HUMAN
202                  || mtmp->data == &mons[PM_MINOTAUR]
203                  || Inhell || In_endgame(&u.uz)));
204 }
205
206
207 /* regenerate lost hit points */
208 void
209 mon_regen(mon, digest_meal)
210 struct monst *mon;
211 boolean digest_meal;
212 {
213     if (mon->mhp < mon->mhpmax && (moves % 20 == 0 || regenerates(mon->data)))
214         mon->mhp++;
215     if (mon->mspec_used)
216         mon->mspec_used--;
217     if (digest_meal) {
218         if (mon->meating) {
219             mon->meating--;
220             if (mon->meating <= 0)
221                 finish_meating(mon);
222         }
223     }
224 }
225
226 /*
227  * Possibly awaken the given monster.  Return a 1 if the monster has been
228  * jolted awake.
229  */
230 STATIC_OVL int
231 disturb(mtmp)
232 register struct monst *mtmp;
233 {
234     /*
235      * + Ettins are hard to surprise.
236      * + Nymphs, jabberwocks, and leprechauns do not easily wake up.
237      *
238      * Wake up if:
239      *  in direct LOS                                           AND
240      *  within 10 squares                                       AND
241      *  not stealthy or (mon is an ettin and 9/10)              AND
242      *  (mon is not a nymph, jabberwock, or leprechaun) or 1/50 AND
243      *  Aggravate or mon is (dog or human) or
244      *      (1/7 and mon is not mimicing furniture or object)
245      */
246     if (couldsee(mtmp->mx, mtmp->my) && distu(mtmp->mx, mtmp->my) <= 100
247         && (!Stealth || (mtmp->data == &mons[PM_ETTIN] && rn2(10)))
248         && (!(mtmp->data->mlet == S_NYMPH
249               || mtmp->data == &mons[PM_JABBERWOCK]
250 #if 0 /* DEFERRED */
251               || mtmp->data == &mons[PM_VORPAL_JABBERWOCK]
252 #endif
253               || mtmp->data->mlet == S_LEPRECHAUN) || !rn2(50))
254         && (Aggravate_monster
255             || (mtmp->data->mlet == S_DOG || mtmp->data->mlet == S_HUMAN)
256             || (!rn2(7) && mtmp->m_ap_type != M_AP_FURNITURE
257                 && mtmp->m_ap_type != M_AP_OBJECT))) {
258         mtmp->msleeping = 0;
259         return 1;
260     }
261     return 0;
262 }
263
264 /* ungrab/expel held/swallowed hero */
265 STATIC_OVL void
266 release_hero(mon)
267 struct monst *mon;
268 {
269     if (mon == u.ustuck) {
270         if (u.uswallow) {
271             expels(mon, mon->data, TRUE);
272         } else if (!sticks(youmonst.data)) {
273             unstuck(mon); /* let go */
274 /*JP
275             You("get released!");
276 */
277             You("\89ð\95ú\82³\82ê\82½\81I");
278         }
279     }
280 }
281
282 /* monster begins fleeing for the specified time, 0 means untimed flee
283  * if first, only adds fleetime if monster isn't already fleeing
284  * if fleemsg, prints a message about new flight, otherwise, caller should */
285 void
286 monflee(mtmp, fleetime, first, fleemsg)
287 struct monst *mtmp;
288 int fleetime;
289 boolean first;
290 boolean fleemsg;
291 {
292     /* shouldn't happen; maybe warrants impossible()? */
293     if (DEADMONSTER(mtmp))
294         return;
295
296     if (mtmp == u.ustuck)
297         release_hero(mtmp); /* expels/unstuck */
298
299     if (!first || !mtmp->mflee) {
300         /* don't lose untimed scare */
301         if (!fleetime)
302             mtmp->mfleetim = 0;
303         else if (!mtmp->mflee || mtmp->mfleetim) {
304             fleetime += (int) mtmp->mfleetim;
305             /* ensure monster flees long enough to visibly stop fighting */
306             if (fleetime == 1)
307                 fleetime++;
308             mtmp->mfleetim = (unsigned) min(fleetime, 127);
309         }
310         if (!mtmp->mflee && fleemsg && canseemon(mtmp)
311             && mtmp->m_ap_type != M_AP_FURNITURE
312             && mtmp->m_ap_type != M_AP_OBJECT) {
313             /* unfortunately we can't distinguish between temporary
314                sleep and temporary paralysis, so both conditions
315                receive the same alternate message */
316             if (!mtmp->mcanmove || !mtmp->data->mmove)
317 /*JP
318                 pline("%s seems to flinch.", Adjmonnam(mtmp, "immobile"));
319 */
320                 pline("%s\82Í\82µ\82è\82²\82Ý\82µ\82Ä\82¢\82é\82æ\82¤\82¾\81D", Monnam(mtmp));
321             else
322 /*JP
323                 pline("%s turns to flee.", Monnam(mtmp));
324 */
325                 pline("%s\82Í\82¨\82Ñ\82¦\82Ä\93¦\82°\8fo\82µ\82½\81I", Monnam(mtmp));
326         }
327         mtmp->mflee = 1;
328     }
329     /* ignore recently-stepped spaces when made to flee */
330     memset(mtmp->mtrack, 0, sizeof(mtmp->mtrack));
331 }
332
333 STATIC_OVL void
334 distfleeck(mtmp, inrange, nearby, scared)
335 register struct monst *mtmp;
336 int *inrange, *nearby, *scared;
337 {
338     int seescaryx, seescaryy;
339     boolean sawscary = FALSE;
340
341     *inrange = (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy)
342                 <= (BOLT_LIM * BOLT_LIM));
343     *nearby = *inrange && monnear(mtmp, mtmp->mux, mtmp->muy);
344
345     /* Note: if your image is displaced, the monster sees the Elbereth
346      * at your displaced position, thus never attacking your displaced
347      * position, but possibly attacking you by accident.  If you are
348      * invisible, it sees the Elbereth at your real position, thus never
349      * running into you by accident but possibly attacking the spot
350      * where it guesses you are.
351      */
352     if (!mtmp->mcansee || (Invis && !perceives(mtmp->data))) {
353         seescaryx = mtmp->mux;
354         seescaryy = mtmp->muy;
355     } else {
356         seescaryx = u.ux;
357         seescaryy = u.uy;
358     }
359
360     sawscary = onscary(seescaryx, seescaryy, mtmp);
361     if (*nearby && (sawscary
362                     || (!mtmp->mpeaceful && in_your_sanctuary(mtmp, 0, 0)))) {
363         *scared = 1;
364         monflee(mtmp, rnd(rn2(7) ? 10 : 100), TRUE, TRUE);
365     } else
366         *scared = 0;
367 }
368
369 /* perform a special one-time action for a monster; returns -1 if nothing
370    special happened, 0 if monster uses up its turn, 1 if monster is killed */
371 STATIC_OVL int
372 m_arrival(mon)
373 struct monst *mon;
374 {
375     mon->mstrategy &= ~STRAT_ARRIVE; /* always reset */
376
377     return -1;
378 }
379
380 /* returns 1 if monster died moving, 0 otherwise */
381 /* The whole dochugw/m_move/distfleeck/mfndpos section is serious spaghetti
382  * code. --KAA
383  */
384 int
385 dochug(mtmp)
386 register struct monst *mtmp;
387 {
388     register struct permonst *mdat;
389     register int tmp = 0;
390     int inrange, nearby, scared;
391
392     /*  Pre-movement adjustments
393      */
394
395     mdat = mtmp->data;
396
397     if (mtmp->mstrategy & STRAT_ARRIVE) {
398         int res = m_arrival(mtmp);
399         if (res >= 0)
400             return res;
401     }
402
403     /* check for waitmask status change */
404     if ((mtmp->mstrategy & STRAT_WAITFORU)
405         && (m_canseeu(mtmp) || mtmp->mhp < mtmp->mhpmax))
406         mtmp->mstrategy &= ~STRAT_WAITFORU;
407
408     /* update quest status flags */
409     quest_stat_check(mtmp);
410
411     if (!mtmp->mcanmove || (mtmp->mstrategy & STRAT_WAITMASK)) {
412         if (Hallucination)
413             newsym(mtmp->mx, mtmp->my);
414         if (mtmp->mcanmove && (mtmp->mstrategy & STRAT_CLOSE)
415             && !mtmp->msleeping && monnear(mtmp, u.ux, u.uy))
416             quest_talk(mtmp); /* give the leaders a chance to speak */
417         return 0;             /* other frozen monsters can't do anything */
418     }
419
420     /* there is a chance we will wake it */
421     if (mtmp->msleeping && !disturb(mtmp)) {
422         if (Hallucination)
423             newsym(mtmp->mx, mtmp->my);
424         return 0;
425     }
426
427     /* not frozen or sleeping: wipe out texts written in the dust */
428     wipe_engr_at(mtmp->mx, mtmp->my, 1, FALSE);
429
430     /* confused monsters get unconfused with small probability */
431     if (mtmp->mconf && !rn2(50))
432         mtmp->mconf = 0;
433
434     /* stunned monsters get un-stunned with larger probability */
435     if (mtmp->mstun && !rn2(10))
436         mtmp->mstun = 0;
437
438     /* some monsters teleport */
439     if (mtmp->mflee && !rn2(40) && can_teleport(mdat) && !mtmp->iswiz
440         && !level.flags.noteleport) {
441         (void) rloc(mtmp, TRUE);
442         return 0;
443     }
444     if (mdat->msound == MS_SHRIEK && !um_dist(mtmp->mx, mtmp->my, 1))
445         m_respond(mtmp);
446     if (mdat == &mons[PM_MEDUSA] && couldsee(mtmp->mx, mtmp->my))
447         m_respond(mtmp);
448     if (mtmp->mhp <= 0)
449         return 1; /* m_respond gaze can kill medusa */
450
451     /* fleeing monsters might regain courage */
452     if (mtmp->mflee && !mtmp->mfleetim && mtmp->mhp == mtmp->mhpmax
453         && !rn2(25))
454         mtmp->mflee = 0;
455
456     /* cease conflict-induced swallow/grab if conflict has ended */
457     if (mtmp == u.ustuck && mtmp->mpeaceful && !mtmp->mconf && !Conflict) {
458         release_hero(mtmp);
459         return 0; /* uses up monster's turn */
460     }
461
462     set_apparxy(mtmp);
463     /* Must be done after you move and before the monster does.  The
464      * set_apparxy() call in m_move() doesn't suffice since the variables
465      * inrange, etc. all depend on stuff set by set_apparxy().
466      */
467
468     /* Monsters that want to acquire things */
469     /* may teleport, so do it before inrange is set */
470     if (is_covetous(mdat))
471         (void) tactics(mtmp);
472
473     /* check distance and scariness of attacks */
474     distfleeck(mtmp, &inrange, &nearby, &scared);
475
476     if (find_defensive(mtmp)) {
477         if (use_defensive(mtmp) != 0)
478             return 1;
479     } else if (find_misc(mtmp)) {
480         if (use_misc(mtmp) != 0)
481             return 1;
482     }
483
484     /* Demonic Blackmail! */
485     if (nearby && mdat->msound == MS_BRIBE && mtmp->mpeaceful && !mtmp->mtame
486         && !u.uswallow) {
487         if (mtmp->mux != u.ux || mtmp->muy != u.uy) {
488 #if 0 /*JP*/
489             pline("%s whispers at thin air.",
490                   cansee(mtmp->mux, mtmp->muy) ? Monnam(mtmp) : "It");
491 #else
492             pline("%s\82ª\82³\82³\82â\82¢\82½\81D",
493                   cansee(mtmp->mux, mtmp->muy) ? Monnam(mtmp) : "\89½\82©");
494 #endif
495
496             if (is_demon(youmonst.data)) {
497                 /* "Good hunting, brother" */
498                 if (!tele_restrict(mtmp))
499                     (void) rloc(mtmp, TRUE);
500             } else {
501                 mtmp->minvis = mtmp->perminvis = 0;
502                 /* Why?  For the same reason in real demon talk */
503 /*JP
504                 pline("%s gets angry!", Amonnam(mtmp));
505 */
506                 pline("%s\82Í\93{\82Á\82½\81I", Amonnam(mtmp));
507                 mtmp->mpeaceful = 0;
508                 set_malign(mtmp);
509                 /* since no way is an image going to pay it off */
510             }
511         } else if (demon_talk(mtmp))
512             return 1; /* you paid it off */
513     }
514
515     /* the watch will look around and see if you are up to no good :-) */
516     if (is_watch(mdat)) {
517         watch_on_duty(mtmp);
518
519     } else if (is_mind_flayer(mdat) && !rn2(20)) {
520         struct monst *m2, *nmon = (struct monst *) 0;
521
522         if (canseemon(mtmp))
523 /*JP
524             pline("%s concentrates.", Monnam(mtmp));
525 */
526             pline("%s\82Í\90¸\90_\82ð\8fW\92\86\82µ\82Ä\82¢\82é\81D", Monnam(mtmp));
527         if (distu(mtmp->mx, mtmp->my) > BOLT_LIM * BOLT_LIM) {
528 /*JP
529             You("sense a faint wave of psychic energy.");
530 */
531             You("\83T\83C\83R\83G\83l\83\8b\83M\81[\82Ì\94g\93®\82ð\8a´\82\82½\81D");
532             goto toofar;
533         }
534 /*JP
535         pline("A wave of psychic energy pours over you!");
536 */
537         pline("\82 \82È\82½\82Í\83T\83C\83R\83G\83l\83\8b\83M\81[\82Ì\94g\93®\82ð\97\81\82Ñ\82½\81I");
538         if (mtmp->mpeaceful
539             && (!Conflict || resist(mtmp, RING_CLASS, 0, 0))) {
540 /*JP
541             pline("It feels quite soothing.");
542 */
543             pline("\90S\82ª\82È\82²\82ñ\82¾\81D");
544         } else if (!u.uinvulnerable) {
545             register boolean m_sen = sensemon(mtmp);
546
547             if (m_sen || (Blind_telepat && rn2(2)) || !rn2(10)) {
548                 int dmg;
549 #if 0 /*JP*/
550                 pline("It locks on to your %s!",
551                       m_sen ? "telepathy" : Blind_telepat ? "latent telepathy"
552                                                           : "mind");
553 #else
554                 pline("\82»\82ê\82Í\82 \82È\82½\82Ì%s\82ð\92¼\8c\82\82µ\82½\81I",
555                       m_sen ? "\83e\83\8c\83p\83V\81[\94\\97Í" : Blind_telepat ? "\90ö\8dÝ\94\\97Í"
556                                                                : "\90¸\90_");
557 #endif
558                 dmg = rnd(15);
559                 if (Half_spell_damage)
560                     dmg = (dmg + 1) / 2;
561 /*JP
562                 losehp(dmg, "psychic blast", KILLED_BY_AN);
563 */
564                 losehp(dmg, "\83T\83C\83R\8dU\8c\82\82Å", KILLED_BY_AN);
565             }
566         }
567         for (m2 = fmon; m2; m2 = nmon) {
568             nmon = m2->nmon;
569             if (DEADMONSTER(m2))
570                 continue;
571             if (m2->mpeaceful == mtmp->mpeaceful)
572                 continue;
573             if (mindless(m2->data))
574                 continue;
575             if (m2 == mtmp)
576                 continue;
577             if ((telepathic(m2->data) && (rn2(2) || m2->mblinded))
578                 || !rn2(10)) {
579                 if (cansee(m2->mx, m2->my))
580 /*JP
581                     pline("It locks on to %s.", mon_nam(m2));
582 */
583                     pline("%s\82ð\92¼\8c\82\82µ\82½\81D", mon_nam(m2));
584                 m2->mhp -= rnd(15);
585                 if (m2->mhp <= 0)
586                     monkilled(m2, "", AD_DRIN);
587                 else
588                     m2->msleeping = 0;
589             }
590         }
591     }
592 toofar:
593
594     /* If monster is nearby you, and has to wield a weapon, do so.   This
595      * costs the monster a move, of course.
596      */
597     if ((!mtmp->mpeaceful || Conflict) && inrange
598         && dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= 8
599         && attacktype(mdat, AT_WEAP)) {
600         struct obj *mw_tmp;
601
602         /* The scared check is necessary.  Otherwise a monster that is
603          * one square near the player but fleeing into a wall would keep
604          * switching between pick-axe and weapon.  If monster is stuck
605          * in a trap, prefer ranged weapon (wielding is done in thrwmu).
606          * This may cost the monster an attack, but keeps the monster
607          * from switching back and forth if carrying both.
608          */
609         mw_tmp = MON_WEP(mtmp);
610         if (!(scared && mw_tmp && is_pick(mw_tmp))
611             && mtmp->weapon_check == NEED_WEAPON
612             && !(mtmp->mtrapped && !nearby && select_rwep(mtmp))) {
613             mtmp->weapon_check = NEED_HTH_WEAPON;
614             if (mon_wield_item(mtmp) != 0)
615                 return 0;
616         }
617     }
618
619     /*  Now the actual movement phase
620      */
621
622     if (!nearby || mtmp->mflee || scared || mtmp->mconf || mtmp->mstun
623         || (mtmp->minvis && !rn2(3))
624         || (mdat->mlet == S_LEPRECHAUN && !findgold(invent)
625             && (findgold(mtmp->minvent) || rn2(2)))
626         || (is_wanderer(mdat) && !rn2(4)) || (Conflict && !mtmp->iswiz)
627         || (!mtmp->mcansee && !rn2(4)) || mtmp->mpeaceful) {
628         /* Possibly cast an undirected spell if not attacking you */
629         /* note that most of the time castmu() will pick a directed
630            spell and do nothing, so the monster moves normally */
631         /* arbitrary distance restriction to keep monster far away
632            from you from having cast dozens of sticks-to-snakes
633            or similar spells by the time you reach it */
634         if (dist2(mtmp->mx, mtmp->my, u.ux, u.uy) <= 49
635             && !mtmp->mspec_used) {
636             struct attack *a;
637
638             for (a = &mdat->mattk[0]; a < &mdat->mattk[NATTK]; a++) {
639                 if (a->aatyp == AT_MAGC
640                     && (a->adtyp == AD_SPEL || a->adtyp == AD_CLRC)) {
641                     if (castmu(mtmp, a, FALSE, FALSE)) {
642                         tmp = 3;
643                         break;
644                     }
645                 }
646             }
647         }
648
649         tmp = m_move(mtmp, 0);
650         if (tmp != 2)
651             distfleeck(mtmp, &inrange, &nearby, &scared); /* recalc */
652
653         switch (tmp) { /* for pets, cases 0 and 3 are equivalent */
654         case 0: /* no movement, but it can still attack you */
655         case 3: /* absolutely no movement */
656             /* vault guard might have vanished */
657             if (mtmp->isgd && (mtmp->mhp < 1 || mtmp->mx == 0))
658                 return 1; /* behave as if it died */
659             /* During hallucination, monster appearance should
660              * still change - even if it doesn't move.
661              */
662             if (Hallucination)
663                 newsym(mtmp->mx, mtmp->my);
664             break;
665         case 1: /* monster moved */
666             /* Maybe it stepped on a trap and fell asleep... */
667             if (mtmp->msleeping || !mtmp->mcanmove)
668                 return 0;
669             /* Monsters can move and then shoot on same turn;
670                our hero can't.  Is that fair? */
671             if (!nearby && (ranged_attk(mdat) || find_offensive(mtmp)))
672                 break;
673             /* engulfer/grabber checks */
674             if (mtmp == u.ustuck) {
675                 /* a monster that's digesting you can move at the
676                  * same time -dlc
677                  */
678                 if (u.uswallow)
679                     return mattacku(mtmp);
680                 /* if confused grabber has wandered off, let go */
681                 if (distu(mtmp->mx, mtmp->my) > 2)
682                     unstuck(mtmp);
683             }
684             return 0;
685         case 2: /* monster died */
686             return 1;
687         }
688     }
689
690     /*  Now, attack the player if possible - one attack set per monst
691      */
692
693     if (!mtmp->mpeaceful || (Conflict && !resist(mtmp, RING_CLASS, 0, 0))) {
694         if (inrange && !noattacks(mdat)
695             && (Upolyd ? u.mh : u.uhp) > 0 && !scared && tmp != 3)
696             if (mattacku(mtmp))
697                 return 1; /* monster died (e.g. exploded) */
698
699         if (mtmp->wormno)
700             wormhitu(mtmp);
701     }
702     /* special speeches for quest monsters */
703     if (!mtmp->msleeping && mtmp->mcanmove && nearby)
704         quest_talk(mtmp);
705     /* extra emotional attack for vile monsters */
706     if (inrange && mtmp->data->msound == MS_CUSS && !mtmp->mpeaceful
707         && couldsee(mtmp->mx, mtmp->my) && !mtmp->minvis && !rn2(5))
708         cuss(mtmp);
709
710     return (tmp == 2);
711 }
712
713 static NEARDATA const char practical[] = { WEAPON_CLASS, ARMOR_CLASS,
714                                            GEM_CLASS, FOOD_CLASS, 0 };
715 static NEARDATA const char magical[] = { AMULET_CLASS, POTION_CLASS,
716                                          SCROLL_CLASS, WAND_CLASS,
717                                          RING_CLASS,   SPBOOK_CLASS, 0 };
718 static NEARDATA const char indigestion[] = { BALL_CLASS, ROCK_CLASS, 0 };
719 static NEARDATA const char boulder_class[] = { ROCK_CLASS, 0 };
720 static NEARDATA const char gem_class[] = { GEM_CLASS, 0 };
721
722 boolean
723 itsstuck(mtmp)
724 register struct monst *mtmp;
725 {
726     if (sticks(youmonst.data) && mtmp == u.ustuck && !u.uswallow) {
727 /*JP
728         pline("%s cannot escape from you!", Monnam(mtmp));
729 */
730         pline("%s\82Í\82 \82È\82½\82©\82ç\93¦\82°\82ç\82ê\82È\82¢\81I", Monnam(mtmp));
731         return TRUE;
732     }
733     return FALSE;
734 }
735
736 /*
737  * should_displace()
738  *
739  * Displacement of another monster is a last resort and only
740  * used on approach. If there are better ways to get to target,
741  * those should be used instead. This function does that evaluation.
742  */
743 boolean
744 should_displace(mtmp, poss, info, cnt, gx, gy)
745 struct monst *mtmp;
746 coord *poss; /* coord poss[9] */
747 long *info;  /* long info[9] */
748 int cnt;
749 xchar gx, gy;
750 {
751     int shortest_with_displacing = -1;
752     int shortest_without_displacing = -1;
753     int count_without_displacing = 0;
754     register int i, nx, ny;
755     int ndist;
756
757     for (i = 0; i < cnt; i++) {
758         nx = poss[i].x;
759         ny = poss[i].y;
760         ndist = dist2(nx, ny, gx, gy);
761         if (MON_AT(nx, ny) && (info[i] & ALLOW_MDISP) && !(info[i] & ALLOW_M)
762             && !undesirable_disp(mtmp, nx, ny)) {
763             if (shortest_with_displacing == -1
764                 || (ndist < shortest_with_displacing))
765                 shortest_with_displacing = ndist;
766         } else {
767             if ((shortest_without_displacing == -1)
768                 || (ndist < shortest_without_displacing))
769                 shortest_without_displacing = ndist;
770             count_without_displacing++;
771         }
772     }
773     if (shortest_with_displacing > -1
774         && (shortest_with_displacing < shortest_without_displacing
775             || !count_without_displacing))
776         return TRUE;
777     return FALSE;
778 }
779
780 boolean
781 m_digweapon_check(mtmp, nix, niy)
782 struct monst *mtmp;
783 xchar nix,niy;
784 {
785     boolean can_tunnel = 0;
786     struct obj *mw_tmp;
787
788     if (!Is_rogue_level(&u.uz))
789         can_tunnel = tunnels(mtmp->data);
790
791     if (can_tunnel && needspick(mtmp->data)
792         && mtmp->weapon_check != NO_WEAPON_WANTED
793         && ((IS_ROCK(levl[nix][niy].typ) && may_dig(nix, niy))
794             || closed_door(nix, niy))) {
795         if (closed_door(nix, niy)) {
796             if (!(mw_tmp = MON_WEP(mtmp))
797                 || !is_pick(mw_tmp)
798                 || !is_axe(mw_tmp))
799                 mtmp->weapon_check = NEED_PICK_OR_AXE;
800         } else if (IS_TREE(levl[nix][niy].typ)) {
801             if (!(mw_tmp = MON_WEP(mtmp)) || !is_axe(mw_tmp))
802                 mtmp->weapon_check = NEED_AXE;
803         } else if (!(mw_tmp = MON_WEP(mtmp)) || !is_pick(mw_tmp)) {
804             mtmp->weapon_check = NEED_PICK_AXE;
805         }
806         if (mtmp->weapon_check >= NEED_PICK_AXE && mon_wield_item(mtmp))
807             return TRUE;
808     }
809     return FALSE;
810 }
811
812 /* Return values:
813  * 0: did not move, but can still attack and do other stuff.
814  * 1: moved, possibly can attack.
815  * 2: monster died.
816  * 3: did not move, and can't do anything else either.
817  */
818 int
819 m_move(mtmp, after)
820 register struct monst *mtmp;
821 register int after;
822 {
823     register int appr;
824     xchar gx, gy, nix, niy, chcnt;
825     int chi; /* could be schar except for stupid Sun-2 compiler */
826     boolean likegold = 0, likegems = 0, likeobjs = 0, likemagic = 0,
827             conceals = 0;
828     boolean likerock = 0, can_tunnel = 0;
829     boolean can_open = 0, can_unlock = 0, doorbuster = 0;
830     boolean uses_items = 0, setlikes = 0;
831     boolean avoid = FALSE;
832     boolean better_with_displacing = FALSE;
833     boolean sawmon = canspotmon(mtmp); /* before it moved */
834     struct permonst *ptr;
835     struct monst *mtoo;
836     schar mmoved = 0; /* not strictly nec.: chi >= 0 will do */
837     long info[9];
838     long flag;
839     int omx = mtmp->mx, omy = mtmp->my;
840
841     if (mtmp->mtrapped) {
842         int i = mintrap(mtmp);
843
844         if (i >= 2) {
845             newsym(mtmp->mx, mtmp->my);
846             return 2;
847         } /* it died */
848         if (i == 1)
849             return 0; /* still in trap, so didn't move */
850     }
851     ptr = mtmp->data; /* mintrap() can change mtmp->data -dlc */
852
853     if (mtmp->meating) {
854         mtmp->meating--;
855         if (mtmp->meating <= 0)
856             finish_meating(mtmp);
857         return 3; /* still eating */
858     }
859     if (hides_under(ptr) && OBJ_AT(mtmp->mx, mtmp->my) && rn2(10))
860         return 0; /* do not leave hiding place */
861
862     set_apparxy(mtmp);
863     /* where does mtmp think you are? */
864     /* Not necessary if m_move called from this file, but necessary in
865      * other calls of m_move (ex. leprechauns dodging)
866      */
867     if (!Is_rogue_level(&u.uz))
868         can_tunnel = tunnels(ptr);
869     can_open = !(nohands(ptr) || verysmall(ptr));
870     can_unlock =
871         ((can_open && monhaskey(mtmp, TRUE)) || mtmp->iswiz || is_rider(ptr));
872     doorbuster = is_giant(ptr);
873     if (mtmp->wormno)
874         goto not_special;
875     /* my dog gets special treatment */
876     if (mtmp->mtame) {
877         mmoved = dog_move(mtmp, after);
878         goto postmov;
879     }
880
881     /* likewise for shopkeeper */
882     if (mtmp->isshk) {
883         mmoved = shk_move(mtmp);
884         if (mmoved == -2)
885             return 2;
886         if (mmoved >= 0)
887             goto postmov;
888         mmoved = 0; /* follow player outside shop */
889     }
890
891     /* and for the guard */
892     if (mtmp->isgd) {
893         mmoved = gd_move(mtmp);
894         if (mmoved == -2)
895             return 2;
896         if (mmoved >= 0)
897             goto postmov;
898         mmoved = 0;
899     }
900
901     /* and the acquisitive monsters get special treatment */
902     if (is_covetous(ptr)) {
903         xchar tx = STRAT_GOALX(mtmp->mstrategy),
904               ty = STRAT_GOALY(mtmp->mstrategy);
905         struct monst *intruder = m_at(tx, ty);
906         /*
907          * if there's a monster on the object or in possession of it,
908          * attack it.
909          */
910         if ((dist2(mtmp->mx, mtmp->my, tx, ty) < 2) && intruder
911             && (intruder != mtmp)) {
912             notonhead = (intruder->mx != tx || intruder->my != ty);
913             if (mattackm(mtmp, intruder) == 2)
914                 return 2;
915             mmoved = 1;
916         } else
917             mmoved = 0;
918         goto postmov;
919     }
920
921     /* and for the priest */
922     if (mtmp->ispriest) {
923         mmoved = pri_move(mtmp);
924         if (mmoved == -2)
925             return 2;
926         if (mmoved >= 0)
927             goto postmov;
928         mmoved = 0;
929     }
930
931 #ifdef MAIL
932     if (ptr == &mons[PM_MAIL_DAEMON]) {
933         if (!Deaf && canseemon(mtmp))
934 /*JP
935             verbalize("I'm late!");
936 */
937             verbalize("\92x\82­\82È\82Á\82Ä\82·\82Ü\82È\82¢\81I");
938         mongone(mtmp);
939         return 2;
940     }
941 #endif
942
943     /* teleport if that lies in our nature */
944     if (ptr == &mons[PM_TENGU] && !rn2(5) && !mtmp->mcan
945         && !tele_restrict(mtmp)) {
946         if (mtmp->mhp < 7 || mtmp->mpeaceful || rn2(2))
947             (void) rloc(mtmp, TRUE);
948         else
949             mnexto(mtmp);
950         mmoved = 1;
951         goto postmov;
952     }
953 not_special:
954     if (u.uswallow && !mtmp->mflee && u.ustuck != mtmp)
955         return 1;
956     omx = mtmp->mx;
957     omy = mtmp->my;
958     gx = mtmp->mux;
959     gy = mtmp->muy;
960     appr = mtmp->mflee ? -1 : 1;
961     if (mtmp->mconf || (u.uswallow && mtmp == u.ustuck)) {
962         appr = 0;
963     } else {
964         struct obj *lepgold, *ygold;
965         boolean should_see = (couldsee(omx, omy)
966                               && (levl[gx][gy].lit || !levl[omx][omy].lit)
967                               && (dist2(omx, omy, gx, gy) <= 36));
968
969         if (!mtmp->mcansee
970             || (should_see && Invis && !perceives(ptr) && rn2(11))
971             || is_obj_mappear(&youmonst,STRANGE_OBJECT) || u.uundetected
972             || (is_obj_mappear(&youmonst,GOLD_PIECE) && !likes_gold(ptr))
973             || (mtmp->mpeaceful && !mtmp->isshk) /* allow shks to follow */
974             || ((monsndx(ptr) == PM_STALKER || ptr->mlet == S_BAT
975                  || ptr->mlet == S_LIGHT) && !rn2(3)))
976             appr = 0;
977
978         if (monsndx(ptr) == PM_LEPRECHAUN && (appr == 1)
979             && ((lepgold = findgold(mtmp->minvent))
980                 && (lepgold->quan
981                     > ((ygold = findgold(invent)) ? ygold->quan : 0L))))
982             appr = -1;
983
984         if (!should_see && can_track(ptr)) {
985             register coord *cp;
986
987             cp = gettrack(omx, omy);
988             if (cp) {
989                 gx = cp->x;
990                 gy = cp->y;
991             }
992         }
993     }
994
995     if ((!mtmp->mpeaceful || !rn2(10)) && (!Is_rogue_level(&u.uz))) {
996         boolean in_line = (lined_up(mtmp)
997                && (distmin(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy)
998                    <= (throws_rocks(youmonst.data) ? 20 : ACURRSTR / 2 + 1)));
999
1000         if (appr != 1 || !in_line) {
1001             /* Monsters in combat won't pick stuff up, avoiding the
1002              * situation where you toss arrows at it and it has nothing
1003              * better to do than pick the arrows up.
1004              */
1005             register int pctload =
1006                 (curr_mon_load(mtmp) * 100) / max_mon_load(mtmp);
1007
1008             /* look for gold or jewels nearby */
1009             likegold = (likes_gold(ptr) && pctload < 95);
1010             likegems = (likes_gems(ptr) && pctload < 85);
1011             uses_items = (!mindless(ptr) && !is_animal(ptr) && pctload < 75);
1012             likeobjs = (likes_objs(ptr) && pctload < 75);
1013             likemagic = (likes_magic(ptr) && pctload < 85);
1014             likerock = (throws_rocks(ptr) && pctload < 50 && !Sokoban);
1015             conceals = hides_under(ptr);
1016             setlikes = TRUE;
1017         }
1018     }
1019
1020 #define SQSRCHRADIUS 5
1021
1022     {
1023         register int minr = SQSRCHRADIUS; /* not too far away */
1024         register struct obj *otmp;
1025         register int xx, yy;
1026         int oomx, oomy, lmx, lmy;
1027
1028         /* cut down the search radius if it thinks character is closer. */
1029         if (distmin(mtmp->mux, mtmp->muy, omx, omy) < SQSRCHRADIUS
1030             && !mtmp->mpeaceful)
1031             minr--;
1032         /* guards shouldn't get too distracted */
1033         if (!mtmp->mpeaceful && is_mercenary(ptr))
1034             minr = 1;
1035
1036         if ((likegold || likegems || likeobjs || likemagic || likerock
1037              || conceals) && (!*in_rooms(omx, omy, SHOPBASE)
1038                               || (!rn2(25) && !mtmp->isshk))) {
1039         look_for_obj:
1040             oomx = min(COLNO - 1, omx + minr);
1041             oomy = min(ROWNO - 1, omy + minr);
1042             lmx = max(1, omx - minr);
1043             lmy = max(0, omy - minr);
1044             for (otmp = fobj; otmp; otmp = otmp->nobj) {
1045                 /* monsters may pick rocks up, but won't go out of their way
1046                    to grab them; this might hamper sling wielders, but it cuts
1047                    down on move overhead by filtering out most common item */
1048                 if (otmp->otyp == ROCK)
1049                     continue;
1050                 xx = otmp->ox;
1051                 yy = otmp->oy;
1052                 /* Nymphs take everything.  Most other creatures should not
1053                  * pick up corpses except as a special case like in
1054                  * searches_for_item().  We need to do this check in
1055                  * mpickstuff() as well.
1056                  */
1057                 if (xx >= lmx && xx <= oomx && yy >= lmy && yy <= oomy) {
1058                     /* don't get stuck circling around object that's
1059                        underneath an immobile or hidden monster;
1060                        paralysis victims excluded */
1061                     if ((mtoo = m_at(xx, yy)) != 0
1062                         && (mtoo->msleeping || mtoo->mundetected
1063                             || (mtoo->mappearance && !mtoo->iswiz)
1064                             || !mtoo->data->mmove))
1065                         continue;
1066                     /* the mfndpos() test for whether to allow a move to a
1067                        water location accepts flyers, but they can't reach
1068                        underwater objects, so being able to move to a spot
1069                        is insufficient for deciding whether to do so */
1070                     if ((is_pool(xx, yy) && !is_swimmer(ptr))
1071                         || (is_lava(xx, yy) && !likes_lava(ptr)))
1072                         continue;
1073
1074                     if (((likegold && otmp->oclass == COIN_CLASS)
1075                          || (likeobjs && index(practical, otmp->oclass)
1076                              && (otmp->otyp != CORPSE
1077                                  || (ptr->mlet == S_NYMPH
1078                                      && !is_rider(&mons[otmp->corpsenm]))))
1079                          || (likemagic && index(magical, otmp->oclass))
1080                          || (uses_items && searches_for_item(mtmp, otmp))
1081                          || (likerock && otmp->otyp == BOULDER)
1082                          || (likegems && otmp->oclass == GEM_CLASS
1083                              && objects[otmp->otyp].oc_material != MINERAL)
1084                          || (conceals && !cansee(otmp->ox, otmp->oy))
1085                          || (ptr == &mons[PM_GELATINOUS_CUBE]
1086                              && !index(indigestion, otmp->oclass)
1087                              && !(otmp->otyp == CORPSE
1088                                   && touch_petrifies(&mons[otmp->corpsenm]))))
1089                         && touch_artifact(otmp, mtmp)) {
1090                         if (can_carry(mtmp, otmp) > 0
1091                             && (throws_rocks(ptr) || !sobj_at(BOULDER, xx, yy))
1092                             && (!is_unicorn(ptr)
1093                                 || objects[otmp->otyp].oc_material == GEMSTONE)
1094                             /* Don't get stuck circling an Elbereth */
1095                             && !onscary(xx, yy, mtmp)) {
1096                             minr = distmin(omx, omy, xx, yy);
1097                             oomx = min(COLNO - 1, omx + minr);
1098                             oomy = min(ROWNO - 1, omy + minr);
1099                             lmx = max(1, omx - minr);
1100                             lmy = max(0, omy - minr);
1101                             gx = otmp->ox;
1102                             gy = otmp->oy;
1103                             if (gx == omx && gy == omy) {
1104                                 mmoved = 3; /* actually unnecessary */
1105                                 goto postmov;
1106                             }
1107                         }
1108                     }
1109                 }
1110             }
1111         } else if (likegold) {
1112             /* don't try to pick up anything else, but use the same loop */
1113             uses_items = 0;
1114             likegems = likeobjs = likemagic = likerock = conceals = 0;
1115             goto look_for_obj;
1116         }
1117
1118         if (minr < SQSRCHRADIUS && appr == -1) {
1119             if (distmin(omx, omy, mtmp->mux, mtmp->muy) <= 3) {
1120                 gx = mtmp->mux;
1121                 gy = mtmp->muy;
1122             } else
1123                 appr = 1;
1124         }
1125     }
1126
1127     /* don't tunnel if hostile and close enough to prefer a weapon */
1128     if (can_tunnel && needspick(ptr)
1129         && ((!mtmp->mpeaceful || Conflict)
1130             && dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= 8))
1131         can_tunnel = FALSE;
1132
1133     nix = omx;
1134     niy = omy;
1135     flag = 0L;
1136     if (mtmp->mpeaceful && (!Conflict || resist(mtmp, RING_CLASS, 0, 0)))
1137         flag |= (ALLOW_SANCT | ALLOW_SSM);
1138     else
1139         flag |= ALLOW_U;
1140     if (is_minion(ptr) || is_rider(ptr))
1141         flag |= ALLOW_SANCT;
1142     /* unicorn may not be able to avoid hero on a noteleport level */
1143     if (is_unicorn(ptr) && !level.flags.noteleport)
1144         flag |= NOTONL;
1145     if (passes_walls(ptr))
1146         flag |= (ALLOW_WALL | ALLOW_ROCK);
1147     if (passes_bars(ptr))
1148         flag |= ALLOW_BARS;
1149     if (can_tunnel)
1150         flag |= ALLOW_DIG;
1151     if (is_human(ptr) || ptr == &mons[PM_MINOTAUR])
1152         flag |= ALLOW_SSM;
1153     if ((is_undead(ptr) && ptr->mlet != S_GHOST) || is_vampshifter(mtmp))
1154         flag |= NOGARLIC;
1155     if (throws_rocks(ptr))
1156         flag |= ALLOW_ROCK;
1157     if (can_open)
1158         flag |= OPENDOOR;
1159     if (can_unlock)
1160         flag |= UNLOCKDOOR;
1161     if (doorbuster)
1162         flag |= BUSTDOOR;
1163     {
1164         register int i, j, nx, ny, nearer;
1165         int jcnt, cnt;
1166         int ndist, nidist;
1167         register coord *mtrk;
1168         coord poss[9];
1169
1170         cnt = mfndpos(mtmp, poss, info, flag);
1171         chcnt = 0;
1172         jcnt = min(MTSZ, cnt - 1);
1173         chi = -1;
1174         nidist = dist2(nix, niy, gx, gy);
1175         /* allow monsters be shortsighted on some levels for balance */
1176         if (!mtmp->mpeaceful && level.flags.shortsighted
1177             && nidist > (couldsee(nix, niy) ? 144 : 36) && appr == 1)
1178             appr = 0;
1179         if (is_unicorn(ptr) && level.flags.noteleport) {
1180             /* on noteleport levels, perhaps we cannot avoid hero */
1181             for (i = 0; i < cnt; i++)
1182                 if (!(info[i] & NOTONL))
1183                     avoid = TRUE;
1184         }
1185         better_with_displacing =
1186             should_displace(mtmp, poss, info, cnt, gx, gy);
1187         for (i = 0; i < cnt; i++) {
1188             if (avoid && (info[i] & NOTONL))
1189                 continue;
1190             nx = poss[i].x;
1191             ny = poss[i].y;
1192
1193             if (MON_AT(nx, ny) && (info[i] & ALLOW_MDISP)
1194                 && !(info[i] & ALLOW_M) && !better_with_displacing)
1195                 continue;
1196             if (appr != 0) {
1197                 mtrk = &mtmp->mtrack[0];
1198                 for (j = 0; j < jcnt; mtrk++, j++)
1199                     if (nx == mtrk->x && ny == mtrk->y)
1200                         if (rn2(4 * (cnt - j)))
1201                             goto nxti;
1202             }
1203
1204             nearer = ((ndist = dist2(nx, ny, gx, gy)) < nidist);
1205
1206             if ((appr == 1 && nearer) || (appr == -1 && !nearer)
1207                 || (!appr && !rn2(++chcnt)) || !mmoved) {
1208                 nix = nx;
1209                 niy = ny;
1210                 nidist = ndist;
1211                 chi = i;
1212                 mmoved = 1;
1213             }
1214         nxti:
1215             ;
1216         }
1217     }
1218
1219     if (mmoved) {
1220         register int j;
1221
1222         if (mmoved == 1 && (u.ux != nix || u.uy != niy) && itsstuck(mtmp))
1223             return 3;
1224
1225         if (mmoved == 1 && m_digweapon_check(mtmp, nix,niy))
1226             return 3;
1227
1228         /* If ALLOW_U is set, either it's trying to attack you, or it
1229          * thinks it is.  In either case, attack this spot in preference to
1230          * all others.
1231          */
1232         /* Actually, this whole section of code doesn't work as you'd expect.
1233          * Most attacks are handled in dochug().  It calls distfleeck(), which
1234          * among other things sets nearby if the monster is near you--and if
1235          * nearby is set, we never call m_move unless it is a special case
1236          * (confused, stun, etc.)  The effect is that this ALLOW_U (and
1237          * mfndpos) has no effect for normal attacks, though it lets a
1238          * confused monster attack you by accident.
1239          */
1240         if (info[chi] & ALLOW_U) {
1241             nix = mtmp->mux;
1242             niy = mtmp->muy;
1243         }
1244         if (nix == u.ux && niy == u.uy) {
1245             mtmp->mux = u.ux;
1246             mtmp->muy = u.uy;
1247             return 0;
1248         }
1249         /* The monster may attack another based on 1 of 2 conditions:
1250          * 1 - It may be confused.
1251          * 2 - It may mistake the monster for your (displaced) image.
1252          * Pets get taken care of above and shouldn't reach this code.
1253          * Conflict gets handled even farther away (movemon()).
1254          */
1255         if ((info[chi] & ALLOW_M) || (nix == mtmp->mux && niy == mtmp->muy)) {
1256             struct monst *mtmp2;
1257             int mstatus;
1258             mtmp2 = m_at(nix, niy);
1259
1260             notonhead = mtmp2 && (nix != mtmp2->mx || niy != mtmp2->my);
1261             /* note: mstatus returns 0 if mtmp2 is nonexistent */
1262             mstatus = mattackm(mtmp, mtmp2);
1263
1264             if (mstatus & MM_AGR_DIED) /* aggressor died */
1265                 return 2;
1266
1267             if ((mstatus & MM_HIT) && !(mstatus & MM_DEF_DIED) && rn2(4)
1268                 && mtmp2->movement >= NORMAL_SPEED) {
1269                 mtmp2->movement -= NORMAL_SPEED;
1270                 notonhead = 0;
1271                 mstatus = mattackm(mtmp2, mtmp); /* return attack */
1272                 if (mstatus & MM_DEF_DIED)
1273                     return 2;
1274             }
1275             return 3;
1276         }
1277
1278         if ((info[chi] & ALLOW_MDISP)) {
1279             struct monst *mtmp2;
1280             int mstatus;
1281             mtmp2 = m_at(nix, niy);
1282             mstatus = mdisplacem(mtmp, mtmp2, FALSE);
1283             if ((mstatus & MM_AGR_DIED) || (mstatus & MM_DEF_DIED))
1284                 return 2;
1285             if (mstatus & MM_HIT)
1286                 return 1;
1287             return 3;
1288         }
1289
1290         if (!m_in_out_region(mtmp, nix, niy))
1291             return 3;
1292         remove_monster(omx, omy);
1293         place_monster(mtmp, nix, niy);
1294         for (j = MTSZ - 1; j > 0; j--)
1295             mtmp->mtrack[j] = mtmp->mtrack[j - 1];
1296         mtmp->mtrack[0].x = omx;
1297         mtmp->mtrack[0].y = omy;
1298         /* Place a segment at the old position. */
1299         if (mtmp->wormno)
1300             worm_move(mtmp);
1301     } else {
1302         if (is_unicorn(ptr) && rn2(2) && !tele_restrict(mtmp)) {
1303             (void) rloc(mtmp, TRUE);
1304             return 1;
1305         }
1306         if (mtmp->wormno)
1307             worm_nomove(mtmp);
1308     }
1309 postmov:
1310     if (mmoved == 1 || mmoved == 3) {
1311         boolean canseeit = cansee(mtmp->mx, mtmp->my);
1312
1313         if (mmoved == 1) {
1314             newsym(omx, omy); /* update the old position */
1315             if (mintrap(mtmp) >= 2) {
1316                 if (mtmp->mx)
1317                     newsym(mtmp->mx, mtmp->my);
1318                 return 2; /* it died */
1319             }
1320             ptr = mtmp->data;
1321
1322             /* open a door, or crash through it, if 'mtmp' can */
1323             if (IS_DOOR(levl[mtmp->mx][mtmp->my].typ)
1324                 && !passes_walls(ptr) /* doesn't need to open doors */
1325                 && !can_tunnel) {     /* taken care of below */
1326                 struct rm *here = &levl[mtmp->mx][mtmp->my];
1327                 boolean btrapped = (here->doormask & D_TRAPPED) != 0,
1328                         observeit = canseeit && canspotmon(mtmp);
1329
1330                 /* if mon has MKoT, disarm door trap; no message given */
1331                 if (btrapped && has_magic_key(mtmp)) {
1332                     /* BUG: this lets a vampire or blob or a doorbuster
1333                        holding the Key disarm the trap even though it isn't
1334                        using that Key when squeezing under or smashing the
1335                        door.  Not significant enough to worry about; perhaps
1336                        the Key's magic is more powerful for monsters? */
1337                     here->doormask &= ~D_TRAPPED;
1338                     btrapped = FALSE;
1339                 }
1340                 if ((here->doormask & (D_LOCKED | D_CLOSED)) != 0
1341                     && (amorphous(ptr)
1342                         || (can_fog(mtmp)
1343                             && vamp_shift(mtmp, &mons[PM_FOG_CLOUD],
1344                                           sawmon)))) {
1345                     /* update cached value for vamp_shift() case */
1346                     ptr = mtmp->data;
1347                     if (flags.verbose && canseemon(mtmp))
1348 #if 0 /*JP*/
1349                         pline("%s %s under the door.", Monnam(mtmp),
1350                               (ptr == &mons[PM_FOG_CLOUD]
1351                                || ptr->mlet == S_LIGHT)
1352                                   ? "flows"
1353                                   : "oozes");
1354 #else
1355                         pline("%s\82Í\94à\82Ì\89º\82©\82ç%s\81D", Monnam(mtmp),
1356                               (ptr == &mons[PM_FOG_CLOUD]
1357                                || ptr->mlet == S_LIGHT)
1358                                   ? "\97¬\82ê\82Å\82½"
1359                                   : "\82É\82\82Ý\82Å\82½");
1360 #endif
1361                 } else if (here->doormask & D_LOCKED && can_unlock) {
1362                     if (btrapped) {
1363                         here->doormask = D_NODOOR;
1364                         newsym(mtmp->mx, mtmp->my);
1365                         unblock_point(mtmp->mx, mtmp->my); /* vision */
1366                         if (mb_trapped(mtmp))
1367                             return 2;
1368                     } else {
1369                         if (flags.verbose) {
1370                             if (observeit)
1371 /*JP
1372                                 pline("%s unlocks and opens a door.",
1373 */
1374                                 pline("%s\82Í\8c®\82ð\82Í\82¸\82µ\82Ä\94à\82ð\8aJ\82¯\82½\81D",
1375                                       Monnam(mtmp));
1376                             else if (canseeit)
1377 /*JP
1378                                 You_see("a door unlock and open.");
1379 */
1380                                 You("\94à\82Ì\8c®\82ª\82Í\82¸\82ê\81C\8aJ\82­\82Ì\82ð\8c©\82½\81D");
1381                             else if (!Deaf)
1382 /*JP
1383                                 You_hear("a door unlock and open.");
1384 */
1385                                 You_hear("\94à\82Ì\8c®\82ª\82Í\82¸\82ê\81C\8aJ\82­\89¹\82ð\95·\82¢\82½\81D");
1386                         }
1387                         here->doormask = D_ISOPEN;
1388                         /* newsym(mtmp->mx, mtmp->my); */
1389                         unblock_point(mtmp->mx, mtmp->my); /* vision */
1390                     }
1391                 } else if (here->doormask == D_CLOSED && can_open) {
1392                     if (btrapped) {
1393                         here->doormask = D_NODOOR;
1394                         newsym(mtmp->mx, mtmp->my);
1395                         unblock_point(mtmp->mx, mtmp->my); /* vision */
1396                         if (mb_trapped(mtmp))
1397                             return 2;
1398                     } else {
1399                         if (flags.verbose) {
1400                             if (observeit)
1401 /*JP
1402                                 pline("%s opens a door.", Monnam(mtmp));
1403 */
1404                                 pline("%s\82Í\94à\82ð\8aJ\82¯\82½\81D", Monnam(mtmp));
1405                             else if (canseeit)
1406 /*JP
1407                                 You_see("a door open.");
1408 */
1409                                 You("\94à\82ª\8aJ\82­\82Ì\82ð\8c©\82½\81D");
1410                             else if (!Deaf)
1411 /*JP
1412                                 You_hear("a door open.");
1413 */
1414                                 You_hear("\94à\82ª\8aJ\82­\89¹\82ð\95·\82¢\82½\81D");
1415                         }
1416                         here->doormask = D_ISOPEN;
1417                         /* newsym(mtmp->mx, mtmp->my); */  /* done below */
1418                         unblock_point(mtmp->mx, mtmp->my); /* vision */
1419                     }
1420                 } else if (here->doormask & (D_LOCKED | D_CLOSED)) {
1421                     /* mfndpos guarantees this must be a doorbuster */
1422                     if (btrapped) {
1423                         here->doormask = D_NODOOR;
1424                         newsym(mtmp->mx, mtmp->my);
1425                         unblock_point(mtmp->mx, mtmp->my); /* vision */
1426                         if (mb_trapped(mtmp))
1427                             return 2;
1428                     } else {
1429                         if (flags.verbose) {
1430                             if (observeit)
1431 /*JP
1432                                 pline("%s smashes down a door.",
1433 */
1434                                 pline("%s\82Í\94à\82ð\94j\89ó\82µ\82½\81D",
1435                                       Monnam(mtmp));
1436                             else if (canseeit)
1437 /*JP
1438                                 You_see("a door crash open.");
1439 */
1440                                 You("\94à\82ª\94j\89ó\82³\82ê\82é\82Ì\82ð\8c©\82½\81D");
1441                             else if (!Deaf)
1442 /*JP
1443                                 You_hear("a door crash open.");
1444 */
1445                                 You_hear("\94à\82ª\94j\89ó\82³\82ê\82é\89¹\82ð\95·\82¢\82½\81D");
1446                         }
1447                         if ((here->doormask & D_LOCKED) != 0 && !rn2(2))
1448                             here->doormask = D_NODOOR;
1449                         else
1450                             here->doormask = D_BROKEN;
1451                         /* newsym(mtmp->mx, mtmp->my); */  /* done below */
1452                         unblock_point(mtmp->mx, mtmp->my); /* vision */
1453                     }
1454                     /* if it's a shop door, schedule repair */
1455                     if (*in_rooms(mtmp->mx, mtmp->my, SHOPBASE))
1456                         add_damage(mtmp->mx, mtmp->my, 0L);
1457                 }
1458             } else if (levl[mtmp->mx][mtmp->my].typ == IRONBARS) {
1459                 if (may_dig(mtmp->mx, mtmp->my)
1460                     && (dmgtype(ptr, AD_RUST) || dmgtype(ptr, AD_CORR))) {
1461                     if (canseemon(mtmp))
1462 /*JP
1463                         pline("%s eats through the iron bars.", Monnam(mtmp));
1464 */
1465                         pline("%s\82Í\93S\82Ì\96_\82ð\90H\82×\82Ä\92Ê\82è\94²\82¯\82½\81D", Monnam(mtmp));
1466                     dissolve_bars(mtmp->mx, mtmp->my);
1467                     return 3;
1468                 } else if (flags.verbose && canseemon(mtmp))
1469 #if 0 /*JP*/
1470                     Norep("%s %s %s the iron bars.", Monnam(mtmp),
1471                           /* pluralization fakes verb conjugation */
1472                           makeplural(locomotion(ptr, "pass")),
1473                           passes_walls(ptr) ? "through" : "between");
1474 #else
1475                     Norep("%s\82Í\93S\82Ì\96_%s\82ð\82·\82è\94²\82¯\82½\81D", Monnam(mtmp),
1476                           passes_walls(ptr) ? "" : "\82Ì\8aÔ");
1477 #endif
1478             }
1479
1480             /* possibly dig */
1481             if (can_tunnel && mdig_tunnel(mtmp))
1482                 return 2; /* mon died (position already updated) */
1483
1484             /* set also in domove(), hack.c */
1485             if (u.uswallow && mtmp == u.ustuck
1486                 && (mtmp->mx != omx || mtmp->my != omy)) {
1487                 /* If the monster moved, then update */
1488                 u.ux0 = u.ux;
1489                 u.uy0 = u.uy;
1490                 u.ux = mtmp->mx;
1491                 u.uy = mtmp->my;
1492                 swallowed(0);
1493             } else
1494                 newsym(mtmp->mx, mtmp->my);
1495         }
1496         if (OBJ_AT(mtmp->mx, mtmp->my) && mtmp->mcanmove) {
1497             /* recompute the likes tests, in case we polymorphed
1498              * or if the "likegold" case got taken above */
1499             if (setlikes) {
1500                 int pctload = (curr_mon_load(mtmp) * 100) / max_mon_load(mtmp);
1501
1502                 /* look for gold or jewels nearby */
1503                 likegold = (likes_gold(ptr) && pctload < 95);
1504                 likegems = (likes_gems(ptr) && pctload < 85);
1505                 uses_items =
1506                     (!mindless(ptr) && !is_animal(ptr) && pctload < 75);
1507                 likeobjs = (likes_objs(ptr) && pctload < 75);
1508                 likemagic = (likes_magic(ptr) && pctload < 85);
1509                 likerock = (throws_rocks(ptr) && pctload < 50 && !Sokoban);
1510                 conceals = hides_under(ptr);
1511             }
1512
1513             /* Maybe a rock mole just ate some metal object */
1514             if (metallivorous(ptr)) {
1515                 if (meatmetal(mtmp) == 2)
1516                     return 2; /* it died */
1517             }
1518
1519             if (g_at(mtmp->mx, mtmp->my) && likegold)
1520                 mpickgold(mtmp);
1521
1522             /* Maybe a cube ate just about anything */
1523             if (ptr == &mons[PM_GELATINOUS_CUBE]) {
1524                 if (meatobj(mtmp) == 2)
1525                     return 2; /* it died */
1526             }
1527
1528             if (!*in_rooms(mtmp->mx, mtmp->my, SHOPBASE) || !rn2(25)) {
1529                 boolean picked = FALSE;
1530
1531                 if (likeobjs)
1532                     picked |= mpickstuff(mtmp, practical);
1533                 if (likemagic)
1534                     picked |= mpickstuff(mtmp, magical);
1535                 if (likerock)
1536                     picked |= mpickstuff(mtmp, boulder_class);
1537                 if (likegems)
1538                     picked |= mpickstuff(mtmp, gem_class);
1539                 if (uses_items)
1540                     picked |= mpickstuff(mtmp, (char *) 0);
1541                 if (picked)
1542                     mmoved = 3;
1543             }
1544
1545             if (mtmp->minvis) {
1546                 newsym(mtmp->mx, mtmp->my);
1547                 if (mtmp->wormno)
1548                     see_wsegs(mtmp);
1549             }
1550         }
1551
1552         if (hides_under(ptr) || ptr->mlet == S_EEL) {
1553             /* Always set--or reset--mundetected if it's already hidden
1554                (just in case the object it was hiding under went away);
1555                usually set mundetected unless monster can't move.  */
1556             if (mtmp->mundetected
1557                 || (mtmp->mcanmove && !mtmp->msleeping && rn2(5)))
1558                 (void) hideunder(mtmp);
1559             newsym(mtmp->mx, mtmp->my);
1560         }
1561         if (mtmp->isshk) {
1562             after_shk_move(mtmp);
1563         }
1564     }
1565     return mmoved;
1566 }
1567
1568 void
1569 dissolve_bars(x, y)
1570 register int x, y;
1571 {
1572     levl[x][y].typ = (Is_special(&u.uz) || *in_rooms(x, y, 0)) ? ROOM : CORR;
1573     newsym(x, y);
1574 }
1575
1576 boolean
1577 closed_door(x, y)
1578 register int x, y;
1579 {
1580     return (boolean) (IS_DOOR(levl[x][y].typ)
1581                       && (levl[x][y].doormask & (D_LOCKED | D_CLOSED)));
1582 }
1583
1584 boolean
1585 accessible(x, y)
1586 register int x, y;
1587 {
1588     int levtyp = levl[x][y].typ;
1589
1590     /* use underlying terrain in front of closed drawbridge */
1591     if (levtyp == DRAWBRIDGE_UP)
1592         levtyp = db_under_typ(levl[x][y].drawbridgemask);
1593
1594     return (boolean) (ACCESSIBLE(levtyp) && !closed_door(x, y));
1595 }
1596
1597 /* decide where the monster thinks you are standing */
1598 void
1599 set_apparxy(mtmp)
1600 register struct monst *mtmp;
1601 {
1602     boolean notseen, gotu;
1603     register int disp, mx = mtmp->mux, my = mtmp->muy;
1604     long umoney = money_cnt(invent);
1605
1606     /*
1607      * do cheapest and/or most likely tests first
1608      */
1609
1610     /* pet knows your smell; grabber still has hold of you */
1611     if (mtmp->mtame || mtmp == u.ustuck)
1612         goto found_you;
1613
1614     /* monsters which know where you are don't suddenly forget,
1615        if you haven't moved away */
1616     if (mx == u.ux && my == u.uy)
1617         goto found_you;
1618
1619     notseen = (!mtmp->mcansee || (Invis && !perceives(mtmp->data)));
1620     /* add cases as required.  eg. Displacement ... */
1621     if (notseen || Underwater) {
1622         /* Xorns can smell quantities of valuable metal
1623             like that in solid gold coins, treat as seen */
1624         if ((mtmp->data == &mons[PM_XORN]) && umoney && !Underwater)
1625             disp = 0;
1626         else
1627             disp = 1;
1628     } else if (Displaced) {
1629         disp = couldsee(mx, my) ? 2 : 1;
1630     } else
1631         disp = 0;
1632     if (!disp)
1633         goto found_you;
1634
1635     /* without something like the following, invisibility and displacement
1636        are too powerful */
1637     gotu = notseen ? !rn2(3) : Displaced ? !rn2(4) : FALSE;
1638
1639     if (!gotu) {
1640         register int try_cnt = 0;
1641         do {
1642             if (++try_cnt > 200)
1643                 goto found_you; /* punt */
1644             mx = u.ux - disp + rn2(2 * disp + 1);
1645             my = u.uy - disp + rn2(2 * disp + 1);
1646         } while (!isok(mx, my)
1647                  || (disp != 2 && mx == mtmp->mx && my == mtmp->my)
1648                  || ((mx != u.ux || my != u.uy) && !passes_walls(mtmp->data)
1649                      && !(accessible(mx, my)
1650                           || (closed_door(mx, my)
1651                               && (can_ooze(mtmp) || can_fog(mtmp)))))
1652                  || !couldsee(mx, my));
1653     } else {
1654     found_you:
1655         mx = u.ux;
1656         my = u.uy;
1657     }
1658
1659     mtmp->mux = mx;
1660     mtmp->muy = my;
1661 }
1662
1663 /*
1664  * mon-to-mon displacement is a deliberate "get out of my way" act,
1665  * not an accidental bump, so we don't consider mstun or mconf in
1666  * undesired_disp().
1667  *
1668  * We do consider many other things about the target and its
1669  * location however.
1670  */
1671 boolean
1672 undesirable_disp(mtmp, x, y)
1673 struct monst *mtmp;
1674 xchar x, y;
1675 {
1676     boolean is_pet = (mtmp && mtmp->mtame && !mtmp->isminion);
1677     struct trap *trap = t_at(x, y);
1678
1679     if (is_pet) {
1680         /* Pets avoid a trap if you've seen it usually. */
1681         if (trap && trap->tseen && rn2(40))
1682             return TRUE;
1683         /* Pets avoid cursed locations */
1684         if (cursed_object_at(x, y))
1685             return TRUE;
1686
1687     /* Monsters avoid a trap if they've seen that type before */
1688     } else if (trap && rn2(40)
1689                && (mtmp->mtrapseen & (1 << (trap->ttyp - 1))) != 0) {
1690         return TRUE;
1691     }
1692
1693     return FALSE;
1694 }
1695
1696 /*
1697  * Inventory prevents passage under door.
1698  * Used by can_ooze() and can_fog().
1699  */
1700 STATIC_OVL boolean
1701 stuff_prevents_passage(mtmp)
1702 struct monst *mtmp;
1703 {
1704     struct obj *chain, *obj;
1705
1706     if (mtmp == &youmonst) {
1707         chain = invent;
1708     } else {
1709         chain = mtmp->minvent;
1710     }
1711     for (obj = chain; obj; obj = obj->nobj) {
1712         int typ = obj->otyp;
1713
1714         if (typ == COIN_CLASS && obj->quan > 100L)
1715             return TRUE;
1716         if (obj->oclass != GEM_CLASS && !(typ >= ARROW && typ <= BOOMERANG)
1717             && !(typ >= DAGGER && typ <= CRYSKNIFE) && typ != SLING
1718             && !is_cloak(obj) && typ != FEDORA && !is_gloves(obj)
1719             && typ != LEATHER_JACKET && typ != CREDIT_CARD && !is_shirt(obj)
1720             && !(typ == CORPSE && verysmall(&mons[obj->corpsenm]))
1721             && typ != FORTUNE_COOKIE && typ != CANDY_BAR && typ != PANCAKE
1722             && typ != LEMBAS_WAFER && typ != LUMP_OF_ROYAL_JELLY
1723             && obj->oclass != AMULET_CLASS && obj->oclass != RING_CLASS
1724             && obj->oclass != VENOM_CLASS && typ != SACK
1725             && typ != BAG_OF_HOLDING && typ != BAG_OF_TRICKS
1726             && !Is_candle(obj) && typ != OILSKIN_SACK && typ != LEASH
1727             && typ != STETHOSCOPE && typ != BLINDFOLD && typ != TOWEL
1728             && typ != TIN_WHISTLE && typ != MAGIC_WHISTLE
1729             && typ != MAGIC_MARKER && typ != TIN_OPENER && typ != SKELETON_KEY
1730             && typ != LOCK_PICK)
1731             return TRUE;
1732         if (Is_container(obj) && obj->cobj)
1733             return TRUE;
1734     }
1735     return FALSE;
1736 }
1737
1738 boolean
1739 can_ooze(mtmp)
1740 struct monst *mtmp;
1741 {
1742     if (!amorphous(mtmp->data) || stuff_prevents_passage(mtmp))
1743         return FALSE;
1744     return TRUE;
1745 }
1746
1747 /* monster can change form into a fog if necessary */
1748 boolean
1749 can_fog(mtmp)
1750 struct monst *mtmp;
1751 {
1752     if (!(mvitals[PM_FOG_CLOUD].mvflags & G_GENOD) && is_vampshifter(mtmp)
1753         && !Protection_from_shape_changers && !stuff_prevents_passage(mtmp))
1754         return TRUE;
1755     return FALSE;
1756 }
1757
1758 STATIC_OVL int
1759 vamp_shift(mon, ptr, domsg)
1760 struct monst *mon;
1761 struct permonst *ptr;
1762 boolean domsg;
1763 {
1764     int reslt = 0;
1765     char oldmtype[BUFSZ];
1766
1767     /* remember current monster type before shapechange */
1768     Strcpy(oldmtype, domsg ? noname_monnam(mon, ARTICLE_THE) : "");
1769
1770     if (mon->data == ptr) {
1771         /* already right shape */
1772         reslt = 1;
1773         domsg = FALSE;
1774     } else if (is_vampshifter(mon)) {
1775         reslt = newcham(mon, ptr, FALSE, FALSE);
1776     }
1777
1778     if (reslt && domsg) {
1779         pline("You %s %s where %s was.",
1780               !canseemon(mon) ? "now detect" : "observe",
1781               noname_monnam(mon, ARTICLE_A), oldmtype);
1782     }
1783
1784     return reslt;
1785 }
1786
1787 /*monmove.c*/