1 /* NetHack 3.6 monmove.c $NHDT-Date: 1463704424 2016/05/20 00:33:44 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.87 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
9 extern boolean notonhead
;
11 STATIC_DCL
void FDECL(watch_on_duty
, (struct monst
*));
12 STATIC_DCL
int FDECL(disturb
, (struct monst
*));
13 STATIC_DCL
void FDECL(release_hero
, (struct monst
*));
14 STATIC_DCL
void FDECL(distfleeck
, (struct monst
*, int *, int *, int *));
15 STATIC_DCL
int FDECL(m_arrival
, (struct monst
*));
16 STATIC_DCL boolean
FDECL(stuff_prevents_passage
, (struct monst
*));
17 STATIC_DCL
int FDECL(vamp_shift
, (struct monst
*, struct permonst
*, BOOLEAN_P
));
19 /* True if mtmp died */
25 if (cansee(mtmp
->mx
, mtmp
->my
) && !Unaware
)
26 pline("KABOOM!! You see a door explode.");
28 You_hear("a distant explosion.");
30 wake_nearto(mtmp
->mx
, mtmp
->my
, 7 * 7);
35 if (mtmp
->mhp
> 0) /* lifesaved */
43 /* check whether a monster is carrying a locking/unlocking tool */
45 monhaskey(mon
, for_unlocking
)
47 boolean for_unlocking
; /* true => credit card ok, false => not ok */
49 if (for_unlocking
&& m_carrying(mon
, CREDIT_CARD
))
51 return m_carrying(mon
, SKELETON_KEY
) || m_carrying(mon
, LOCK_PICK
);
61 /* Sidenote on "A watchman angrily waves her arms!"
62 * Female being called watchman is correct (career name).
64 pline("%s angrily %s %s %s!",
66 nolimbs(mon
->data
) ? "shakes" : "waves",
68 nolimbs(mon
->data
) ? mbodypart(mon
, HEAD
)
69 : makeplural(mbodypart(mon
, ARM
)));
72 pline("%s yells:", Amonnam(mon
));
74 You_hear("someone yell:");
81 register struct monst
*mtmp
;
85 if (mtmp
->mpeaceful
&& in_town(u
.ux
+ u
.dx
, u
.uy
+ u
.dy
)
86 && mtmp
->mcansee
&& m_canseeu(mtmp
) && !rn2(3)) {
87 if (picking_lock(&x
, &y
) && IS_DOOR(levl
[x
][y
].typ
)
88 && (levl
[x
][y
].doormask
& D_LOCKED
)) {
89 if (couldsee(mtmp
->mx
, mtmp
->my
)) {
90 if (levl
[x
][y
].looted
& D_WARNED
) {
91 mon_yells(mtmp
, "Halt, thief! You're under arrest!");
92 (void) angry_guards(!!Deaf
);
94 mon_yells(mtmp
, "Hey, stop picking that lock!");
95 levl
[x
][y
].looted
|= D_WARNED
;
99 } else if (is_digging()) {
100 /* chewing, wand/spell of digging are checked elsewhere */
101 watch_dig(mtmp
, context
.digging
.pos
.x
, context
.digging
.pos
.y
,
109 register struct monst
*mtmp
;
111 int x
= mtmp
->mx
, y
= mtmp
->my
;
112 boolean already_saw_mon
= !occupation
? 0 : canspotmon(mtmp
);
113 int rd
= dochug(mtmp
);
115 /* a similar check is in monster_nearby() in hack.c */
116 /* check whether hero notices monster and stops current activity */
117 if (occupation
&& !rd
&& !Confusion
&& (!mtmp
->mpeaceful
|| Hallucination
)
118 /* it's close enough to be a threat */
119 && distu(x
, y
) <= (BOLT_LIM
+ 1) * (BOLT_LIM
+ 1)
120 /* and either couldn't see it before, or it was too far away */
121 && (!already_saw_mon
|| !couldsee(x
, y
)
122 || distu(x
, y
) > (BOLT_LIM
+ 1) * (BOLT_LIM
+ 1))
123 /* can see it now, or sense it and would normally see it */
124 && (canseemon(mtmp
) || (sensemon(mtmp
) && couldsee(x
, y
)))
125 && mtmp
->mcanmove
&& !noattacks(mtmp
->data
)
126 && !onscary(u
.ux
, u
.uy
, mtmp
))
137 boolean epresent
= sengr_at("Elbereth", x
, y
, TRUE
);
139 /* creatures who are directly resistant to magical scaring:
140 * Rodney, lawful minions, angels, the Riders */
141 if (mtmp
->iswiz
|| is_lminion(mtmp
) || mtmp
->data
== &mons
[PM_ANGEL
]
142 || is_rider(mtmp
->data
))
145 /* should this still be true for defiled/molochian altars? */
146 if (IS_ALTAR(levl
[x
][y
].typ
)
147 && (mtmp
->data
->mlet
== S_VAMPIRE
|| is_vampshifter(mtmp
)))
150 /* the scare monster scroll doesn't have any of the below
151 * restrictions, being its own source of power */
152 if (sobj_at(SCR_SCARE_MONSTER
, x
, y
))
155 /* creatures who don't (or can't) fear a written Elbereth:
156 * all the above plus shopkeepers, guards, blind or
157 * peaceful monsters, humans, and minotaurs.
159 * if the player isn't actually on the square OR the player's image
160 * isn't displaced to the square, no protection is being granted
162 * Elbereth doesn't work in Gehennom, the Elemental Planes, or the
163 * Astral Plane; the influence of the Valar only reaches so far. */
165 && ((u
.ux
== x
&& u
.uy
== y
)
166 || (Displaced
&& mtmp
->mux
== x
&& mtmp
->muy
== y
))
167 && !(mtmp
->isshk
|| mtmp
->isgd
|| !mtmp
->mcansee
168 || mtmp
->mpeaceful
|| mtmp
->data
->mlet
== S_HUMAN
169 || mtmp
->data
== &mons
[PM_MINOTAUR
]
170 || Inhell
|| In_endgame(&u
.uz
)));
174 /* regenerate lost hit points */
176 mon_regen(mon
, digest_meal
)
180 if (mon
->mhp
< mon
->mhpmax
&& (moves
% 20 == 0 || regenerates(mon
->data
)))
187 if (mon
->meating
<= 0)
194 * Possibly awaken the given monster. Return a 1 if the monster has been
199 register struct monst
*mtmp
;
202 * + Ettins are hard to surprise.
203 * + Nymphs, jabberwocks, and leprechauns do not easily wake up.
207 * within 10 squares AND
208 * not stealthy or (mon is an ettin and 9/10) AND
209 * (mon is not a nymph, jabberwock, or leprechaun) or 1/50 AND
210 * Aggravate or mon is (dog or human) or
211 * (1/7 and mon is not mimicing furniture or object)
213 if (couldsee(mtmp
->mx
, mtmp
->my
) && distu(mtmp
->mx
, mtmp
->my
) <= 100
214 && (!Stealth
|| (mtmp
->data
== &mons
[PM_ETTIN
] && rn2(10)))
215 && (!(mtmp
->data
->mlet
== S_NYMPH
216 || mtmp
->data
== &mons
[PM_JABBERWOCK
]
218 || mtmp
->data
== &mons
[PM_VORPAL_JABBERWOCK
]
220 || mtmp
->data
->mlet
== S_LEPRECHAUN
) || !rn2(50))
221 && (Aggravate_monster
222 || (mtmp
->data
->mlet
== S_DOG
|| mtmp
->data
->mlet
== S_HUMAN
)
223 || (!rn2(7) && mtmp
->m_ap_type
!= M_AP_FURNITURE
224 && mtmp
->m_ap_type
!= M_AP_OBJECT
))) {
231 /* ungrab/expel held/swallowed hero */
236 if (mon
== u
.ustuck
) {
238 expels(mon
, mon
->data
, TRUE
);
239 } else if (!sticks(youmonst
.data
)) {
240 unstuck(mon
); /* let go */
241 You("get released!");
246 /* monster begins fleeing for the specified time, 0 means untimed flee
247 * if first, only adds fleetime if monster isn't already fleeing
248 * if fleemsg, prints a message about new flight, otherwise, caller should */
250 monflee(mtmp
, fleetime
, first
, fleemsg
)
256 /* shouldn't happen; maybe warrants impossible()? */
257 if (DEADMONSTER(mtmp
))
260 if (mtmp
== u
.ustuck
)
261 release_hero(mtmp
); /* expels/unstuck */
263 if (!first
|| !mtmp
->mflee
) {
264 /* don't lose untimed scare */
267 else if (!mtmp
->mflee
|| mtmp
->mfleetim
) {
268 fleetime
+= (int) mtmp
->mfleetim
;
269 /* ensure monster flees long enough to visibly stop fighting */
272 mtmp
->mfleetim
= (unsigned) min(fleetime
, 127);
274 if (!mtmp
->mflee
&& fleemsg
&& canseemon(mtmp
)
275 && mtmp
->m_ap_type
!= M_AP_FURNITURE
276 && mtmp
->m_ap_type
!= M_AP_OBJECT
) {
277 /* unfortunately we can't distinguish between temporary
278 sleep and temporary paralysis, so both conditions
279 receive the same alternate message */
280 if (!mtmp
->mcanmove
|| !mtmp
->data
->mmove
)
281 pline("%s seems to flinch.", Adjmonnam(mtmp
, "immobile"));
283 pline("%s turns to flee.", Monnam(mtmp
));
287 /* ignore recently-stepped spaces when made to flee */
288 memset(mtmp
->mtrack
, 0, sizeof(mtmp
->mtrack
));
292 distfleeck(mtmp
, inrange
, nearby
, scared
)
293 register struct monst
*mtmp
;
294 int *inrange
, *nearby
, *scared
;
296 int seescaryx
, seescaryy
;
297 boolean sawscary
= FALSE
;
299 *inrange
= (dist2(mtmp
->mx
, mtmp
->my
, mtmp
->mux
, mtmp
->muy
)
300 <= (BOLT_LIM
* BOLT_LIM
));
301 *nearby
= *inrange
&& monnear(mtmp
, mtmp
->mux
, mtmp
->muy
);
303 /* Note: if your image is displaced, the monster sees the Elbereth
304 * at your displaced position, thus never attacking your displaced
305 * position, but possibly attacking you by accident. If you are
306 * invisible, it sees the Elbereth at your real position, thus never
307 * running into you by accident but possibly attacking the spot
308 * where it guesses you are.
310 if (!mtmp
->mcansee
|| (Invis
&& !perceives(mtmp
->data
))) {
311 seescaryx
= mtmp
->mux
;
312 seescaryy
= mtmp
->muy
;
318 sawscary
= onscary(seescaryx
, seescaryy
, mtmp
);
319 if (*nearby
&& (sawscary
320 || (!mtmp
->mpeaceful
&& in_your_sanctuary(mtmp
, 0, 0)))) {
322 monflee(mtmp
, rnd(rn2(7) ? 10 : 100), TRUE
, TRUE
);
327 /* perform a special one-time action for a monster; returns -1 if nothing
328 special happened, 0 if monster uses up its turn, 1 if monster is killed */
333 mon
->mstrategy
&= ~STRAT_ARRIVE
; /* always reset */
338 /* returns 1 if monster died moving, 0 otherwise */
339 /* The whole dochugw/m_move/distfleeck/mfndpos section is serious spaghetti
344 register struct monst
*mtmp
;
346 register struct permonst
*mdat
;
347 register int tmp
= 0;
348 int inrange
, nearby
, scared
;
350 /* Pre-movement adjustments
355 if (mtmp
->mstrategy
& STRAT_ARRIVE
) {
356 int res
= m_arrival(mtmp
);
361 /* check for waitmask status change */
362 if ((mtmp
->mstrategy
& STRAT_WAITFORU
)
363 && (m_canseeu(mtmp
) || mtmp
->mhp
< mtmp
->mhpmax
))
364 mtmp
->mstrategy
&= ~STRAT_WAITFORU
;
366 /* update quest status flags */
367 quest_stat_check(mtmp
);
369 if (!mtmp
->mcanmove
|| (mtmp
->mstrategy
& STRAT_WAITMASK
)) {
371 newsym(mtmp
->mx
, mtmp
->my
);
372 if (mtmp
->mcanmove
&& (mtmp
->mstrategy
& STRAT_CLOSE
)
373 && !mtmp
->msleeping
&& monnear(mtmp
, u
.ux
, u
.uy
))
374 quest_talk(mtmp
); /* give the leaders a chance to speak */
375 return 0; /* other frozen monsters can't do anything */
378 /* there is a chance we will wake it */
379 if (mtmp
->msleeping
&& !disturb(mtmp
)) {
381 newsym(mtmp
->mx
, mtmp
->my
);
385 /* not frozen or sleeping: wipe out texts written in the dust */
386 wipe_engr_at(mtmp
->mx
, mtmp
->my
, 1, FALSE
);
388 /* confused monsters get unconfused with small probability */
389 if (mtmp
->mconf
&& !rn2(50))
392 /* stunned monsters get un-stunned with larger probability */
393 if (mtmp
->mstun
&& !rn2(10))
396 /* some monsters teleport */
397 if (mtmp
->mflee
&& !rn2(40) && can_teleport(mdat
) && !mtmp
->iswiz
398 && !level
.flags
.noteleport
) {
399 (void) rloc(mtmp
, TRUE
);
402 if (mdat
->msound
== MS_SHRIEK
&& !um_dist(mtmp
->mx
, mtmp
->my
, 1))
404 if (mdat
== &mons
[PM_MEDUSA
] && couldsee(mtmp
->mx
, mtmp
->my
))
407 return 1; /* m_respond gaze can kill medusa */
409 /* fleeing monsters might regain courage */
410 if (mtmp
->mflee
&& !mtmp
->mfleetim
&& mtmp
->mhp
== mtmp
->mhpmax
414 /* cease conflict-induced swallow/grab if conflict has ended */
415 if (mtmp
== u
.ustuck
&& mtmp
->mpeaceful
&& !mtmp
->mconf
&& !Conflict
) {
417 return 0; /* uses up monster's turn */
421 /* Must be done after you move and before the monster does. The
422 * set_apparxy() call in m_move() doesn't suffice since the variables
423 * inrange, etc. all depend on stuff set by set_apparxy().
426 /* Monsters that want to acquire things */
427 /* may teleport, so do it before inrange is set */
428 if (is_covetous(mdat
))
429 (void) tactics(mtmp
);
431 /* check distance and scariness of attacks */
432 distfleeck(mtmp
, &inrange
, &nearby
, &scared
);
434 if (find_defensive(mtmp
)) {
435 if (use_defensive(mtmp
) != 0)
437 } else if (find_misc(mtmp
)) {
438 if (use_misc(mtmp
) != 0)
442 /* Demonic Blackmail! */
443 if (nearby
&& mdat
->msound
== MS_BRIBE
&& mtmp
->mpeaceful
&& !mtmp
->mtame
445 if (mtmp
->mux
!= u
.ux
|| mtmp
->muy
!= u
.uy
) {
446 pline("%s whispers at thin air.",
447 cansee(mtmp
->mux
, mtmp
->muy
) ? Monnam(mtmp
) : "It");
449 if (is_demon(youmonst
.data
)) {
450 /* "Good hunting, brother" */
451 if (!tele_restrict(mtmp
))
452 (void) rloc(mtmp
, TRUE
);
454 mtmp
->minvis
= mtmp
->perminvis
= 0;
455 /* Why? For the same reason in real demon talk */
456 pline("%s gets angry!", Amonnam(mtmp
));
459 /* since no way is an image going to pay it off */
461 } else if (demon_talk(mtmp
))
462 return 1; /* you paid it off */
465 /* the watch will look around and see if you are up to no good :-) */
466 if (is_watch(mdat
)) {
469 } else if (is_mind_flayer(mdat
) && !rn2(20)) {
470 struct monst
*m2
, *nmon
= (struct monst
*) 0;
473 pline("%s concentrates.", Monnam(mtmp
));
474 if (distu(mtmp
->mx
, mtmp
->my
) > BOLT_LIM
* BOLT_LIM
) {
475 You("sense a faint wave of psychic energy.");
478 pline("A wave of psychic energy pours over you!");
480 && (!Conflict
|| resist(mtmp
, RING_CLASS
, 0, 0))) {
481 pline("It feels quite soothing.");
482 } else if (!u
.uinvulnerable
) {
483 register boolean m_sen
= sensemon(mtmp
);
485 if (m_sen
|| (Blind_telepat
&& rn2(2)) || !rn2(10)) {
487 pline("It locks on to your %s!",
488 m_sen
? "telepathy" : Blind_telepat
? "latent telepathy"
491 if (Half_spell_damage
)
493 losehp(dmg
, "psychic blast", KILLED_BY_AN
);
496 for (m2
= fmon
; m2
; m2
= nmon
) {
500 if (m2
->mpeaceful
== mtmp
->mpeaceful
)
502 if (mindless(m2
->data
))
506 if ((telepathic(m2
->data
) && (rn2(2) || m2
->mblinded
))
508 if (cansee(m2
->mx
, m2
->my
))
509 pline("It locks on to %s.", mon_nam(m2
));
512 monkilled(m2
, "", AD_DRIN
);
520 /* If monster is nearby you, and has to wield a weapon, do so. This
521 * costs the monster a move, of course.
523 if ((!mtmp
->mpeaceful
|| Conflict
) && inrange
524 && dist2(mtmp
->mx
, mtmp
->my
, mtmp
->mux
, mtmp
->muy
) <= 8
525 && attacktype(mdat
, AT_WEAP
)) {
528 /* The scared check is necessary. Otherwise a monster that is
529 * one square near the player but fleeing into a wall would keep
530 * switching between pick-axe and weapon. If monster is stuck
531 * in a trap, prefer ranged weapon (wielding is done in thrwmu).
532 * This may cost the monster an attack, but keeps the monster
533 * from switching back and forth if carrying both.
535 mw_tmp
= MON_WEP(mtmp
);
536 if (!(scared
&& mw_tmp
&& is_pick(mw_tmp
))
537 && mtmp
->weapon_check
== NEED_WEAPON
538 && !(mtmp
->mtrapped
&& !nearby
&& select_rwep(mtmp
))) {
539 mtmp
->weapon_check
= NEED_HTH_WEAPON
;
540 if (mon_wield_item(mtmp
) != 0)
545 /* Now the actual movement phase
548 if (!nearby
|| mtmp
->mflee
|| scared
|| mtmp
->mconf
|| mtmp
->mstun
549 || (mtmp
->minvis
&& !rn2(3))
550 || (mdat
->mlet
== S_LEPRECHAUN
&& !findgold(invent
)
551 && (findgold(mtmp
->minvent
) || rn2(2)))
552 || (is_wanderer(mdat
) && !rn2(4)) || (Conflict
&& !mtmp
->iswiz
)
553 || (!mtmp
->mcansee
&& !rn2(4)) || mtmp
->mpeaceful
) {
554 /* Possibly cast an undirected spell if not attacking you */
555 /* note that most of the time castmu() will pick a directed
556 spell and do nothing, so the monster moves normally */
557 /* arbitrary distance restriction to keep monster far away
558 from you from having cast dozens of sticks-to-snakes
559 or similar spells by the time you reach it */
560 if (dist2(mtmp
->mx
, mtmp
->my
, u
.ux
, u
.uy
) <= 49
561 && !mtmp
->mspec_used
) {
564 for (a
= &mdat
->mattk
[0]; a
< &mdat
->mattk
[NATTK
]; a
++) {
565 if (a
->aatyp
== AT_MAGC
566 && (a
->adtyp
== AD_SPEL
|| a
->adtyp
== AD_CLRC
)) {
567 if (castmu(mtmp
, a
, FALSE
, FALSE
)) {
575 tmp
= m_move(mtmp
, 0);
577 distfleeck(mtmp
, &inrange
, &nearby
, &scared
); /* recalc */
579 switch (tmp
) { /* for pets, cases 0 and 3 are equivalent */
580 case 0: /* no movement, but it can still attack you */
581 case 3: /* absolutely no movement */
582 /* vault guard might have vanished */
583 if (mtmp
->isgd
&& (mtmp
->mhp
< 1 || mtmp
->mx
== 0))
584 return 1; /* behave as if it died */
585 /* During hallucination, monster appearance should
586 * still change - even if it doesn't move.
589 newsym(mtmp
->mx
, mtmp
->my
);
591 case 1: /* monster moved */
592 /* Maybe it stepped on a trap and fell asleep... */
593 if (mtmp
->msleeping
|| !mtmp
->mcanmove
)
595 /* Monsters can move and then shoot on same turn;
596 our hero can't. Is that fair? */
597 if (!nearby
&& (ranged_attk(mdat
) || find_offensive(mtmp
)))
599 /* engulfer/grabber checks */
600 if (mtmp
== u
.ustuck
) {
601 /* a monster that's digesting you can move at the
605 return mattacku(mtmp
);
606 /* if confused grabber has wandered off, let go */
607 if (distu(mtmp
->mx
, mtmp
->my
) > 2)
611 case 2: /* monster died */
616 /* Now, attack the player if possible - one attack set per monst
619 if (!mtmp
->mpeaceful
|| (Conflict
&& !resist(mtmp
, RING_CLASS
, 0, 0))) {
620 if (inrange
&& !noattacks(mdat
) && u
.uhp
> 0 && !scared
&& tmp
!= 3)
622 return 1; /* monster died (e.g. exploded) */
627 /* special speeches for quest monsters */
628 if (!mtmp
->msleeping
&& mtmp
->mcanmove
&& nearby
)
630 /* extra emotional attack for vile monsters */
631 if (inrange
&& mtmp
->data
->msound
== MS_CUSS
&& !mtmp
->mpeaceful
632 && couldsee(mtmp
->mx
, mtmp
->my
) && !mtmp
->minvis
&& !rn2(5))
638 static NEARDATA
const char practical
[] = { WEAPON_CLASS
, ARMOR_CLASS
,
639 GEM_CLASS
, FOOD_CLASS
, 0 };
640 static NEARDATA
const char magical
[] = { AMULET_CLASS
, POTION_CLASS
,
641 SCROLL_CLASS
, WAND_CLASS
,
642 RING_CLASS
, SPBOOK_CLASS
, 0 };
643 static NEARDATA
const char indigestion
[] = { BALL_CLASS
, ROCK_CLASS
, 0 };
644 static NEARDATA
const char boulder_class
[] = { ROCK_CLASS
, 0 };
645 static NEARDATA
const char gem_class
[] = { GEM_CLASS
, 0 };
649 register struct monst
*mtmp
;
651 if (sticks(youmonst
.data
) && mtmp
== u
.ustuck
&& !u
.uswallow
) {
652 pline("%s cannot escape from you!", Monnam(mtmp
));
661 * Displacement of another monster is a last resort and only
662 * used on approach. If there are better ways to get to target,
663 * those should be used instead. This function does that evaluation.
666 should_displace(mtmp
, poss
, info
, cnt
, gx
, gy
)
668 coord
*poss
; /* coord poss[9] */
669 long *info
; /* long info[9] */
673 int shortest_with_displacing
= -1;
674 int shortest_without_displacing
= -1;
675 int count_without_displacing
= 0;
676 register int i
, nx
, ny
;
679 for (i
= 0; i
< cnt
; i
++) {
682 ndist
= dist2(nx
, ny
, gx
, gy
);
683 if (MON_AT(nx
, ny
) && (info
[i
] & ALLOW_MDISP
) && !(info
[i
] & ALLOW_M
)
684 && !undesirable_disp(mtmp
, nx
, ny
)) {
685 if (shortest_with_displacing
== -1
686 || (ndist
< shortest_with_displacing
))
687 shortest_with_displacing
= ndist
;
689 if ((shortest_without_displacing
== -1)
690 || (ndist
< shortest_without_displacing
))
691 shortest_without_displacing
= ndist
;
692 count_without_displacing
++;
695 if (shortest_with_displacing
> -1
696 && (shortest_with_displacing
< shortest_without_displacing
697 || !count_without_displacing
))
703 m_digweapon_check(mtmp
, nix
, niy
)
707 boolean can_tunnel
= 0;
710 if (!Is_rogue_level(&u
.uz
))
711 can_tunnel
= tunnels(mtmp
->data
);
713 if (can_tunnel
&& needspick(mtmp
->data
)
714 && mtmp
->weapon_check
!= NO_WEAPON_WANTED
715 && ((IS_ROCK(levl
[nix
][niy
].typ
) && may_dig(nix
, niy
))
716 || closed_door(nix
, niy
))) {
717 if (closed_door(nix
, niy
)) {
718 if (!(mw_tmp
= MON_WEP(mtmp
))
721 mtmp
->weapon_check
= NEED_PICK_OR_AXE
;
722 } else if (IS_TREE(levl
[nix
][niy
].typ
)) {
723 if (!(mw_tmp
= MON_WEP(mtmp
)) || !is_axe(mw_tmp
))
724 mtmp
->weapon_check
= NEED_AXE
;
725 } else if (!(mw_tmp
= MON_WEP(mtmp
)) || !is_pick(mw_tmp
)) {
726 mtmp
->weapon_check
= NEED_PICK_AXE
;
728 if (mtmp
->weapon_check
>= NEED_PICK_AXE
&& mon_wield_item(mtmp
))
735 * 0: did not move, but can still attack and do other stuff.
736 * 1: moved, possibly can attack.
738 * 3: did not move, and can't do anything else either.
742 register struct monst
*mtmp
;
746 xchar gx
, gy
, nix
, niy
, chcnt
;
747 int chi
; /* could be schar except for stupid Sun-2 compiler */
748 boolean likegold
= 0, likegems
= 0, likeobjs
= 0, likemagic
= 0,
750 boolean likerock
= 0, can_tunnel
= 0;
751 boolean can_open
= 0, can_unlock
= 0, doorbuster
= 0;
752 boolean uses_items
= 0, setlikes
= 0;
753 boolean avoid
= FALSE
;
754 boolean better_with_displacing
= FALSE
;
755 struct permonst
*ptr
;
757 schar mmoved
= 0; /* not strictly nec.: chi >= 0 will do */
760 int omx
= mtmp
->mx
, omy
= mtmp
->my
;
762 if (mtmp
->mtrapped
) {
763 int i
= mintrap(mtmp
);
766 newsym(mtmp
->mx
, mtmp
->my
);
770 return 0; /* still in trap, so didn't move */
772 ptr
= mtmp
->data
; /* mintrap() can change mtmp->data -dlc */
776 if (mtmp
->meating
<= 0)
777 finish_meating(mtmp
);
778 return 3; /* still eating */
780 if (hides_under(ptr
) && OBJ_AT(mtmp
->mx
, mtmp
->my
) && rn2(10))
781 return 0; /* do not leave hiding place */
784 /* where does mtmp think you are? */
785 /* Not necessary if m_move called from this file, but necessary in
786 * other calls of m_move (ex. leprechauns dodging)
788 if (!Is_rogue_level(&u
.uz
))
789 can_tunnel
= tunnels(ptr
);
790 can_open
= !(nohands(ptr
) || verysmall(ptr
));
792 ((can_open
&& monhaskey(mtmp
, TRUE
)) || mtmp
->iswiz
|| is_rider(ptr
));
793 doorbuster
= is_giant(ptr
);
796 /* my dog gets special treatment */
798 mmoved
= dog_move(mtmp
, after
);
802 /* likewise for shopkeeper */
804 mmoved
= shk_move(mtmp
);
809 mmoved
= 0; /* follow player outside shop */
812 /* and for the guard */
814 mmoved
= gd_move(mtmp
);
822 /* and the acquisitive monsters get special treatment */
823 if (is_covetous(ptr
)) {
824 xchar tx
= STRAT_GOALX(mtmp
->mstrategy
),
825 ty
= STRAT_GOALY(mtmp
->mstrategy
);
826 struct monst
*intruder
= m_at(tx
, ty
);
828 * if there's a monster on the object or in possession of it,
831 if ((dist2(mtmp
->mx
, mtmp
->my
, tx
, ty
) < 2) && intruder
832 && (intruder
!= mtmp
)) {
833 notonhead
= (intruder
->mx
!= tx
|| intruder
->my
!= ty
);
834 if (mattackm(mtmp
, intruder
) == 2)
842 /* and for the priest */
843 if (mtmp
->ispriest
) {
844 mmoved
= pri_move(mtmp
);
853 if (ptr
== &mons
[PM_MAIL_DAEMON
]) {
854 if (!Deaf
&& canseemon(mtmp
))
855 verbalize("I'm late!");
861 /* teleport if that lies in our nature */
862 if (ptr
== &mons
[PM_TENGU
] && !rn2(5) && !mtmp
->mcan
863 && !tele_restrict(mtmp
)) {
864 if (mtmp
->mhp
< 7 || mtmp
->mpeaceful
|| rn2(2))
865 (void) rloc(mtmp
, TRUE
);
872 if (u
.uswallow
&& !mtmp
->mflee
&& u
.ustuck
!= mtmp
)
878 appr
= mtmp
->mflee
? -1 : 1;
879 if (mtmp
->mconf
|| (u
.uswallow
&& mtmp
== u
.ustuck
)) {
882 struct obj
*lepgold
, *ygold
;
883 boolean should_see
= (couldsee(omx
, omy
)
884 && (levl
[gx
][gy
].lit
|| !levl
[omx
][omy
].lit
)
885 && (dist2(omx
, omy
, gx
, gy
) <= 36));
888 || (should_see
&& Invis
&& !perceives(ptr
) && rn2(11))
889 || is_obj_mappear(&youmonst
,STRANGE_OBJECT
) || u
.uundetected
890 || (is_obj_mappear(&youmonst
,GOLD_PIECE
) && !likes_gold(ptr
))
891 || (mtmp
->mpeaceful
&& !mtmp
->isshk
) /* allow shks to follow */
892 || ((monsndx(ptr
) == PM_STALKER
|| ptr
->mlet
== S_BAT
893 || ptr
->mlet
== S_LIGHT
) && !rn2(3)))
896 if (monsndx(ptr
) == PM_LEPRECHAUN
&& (appr
== 1)
897 && ((lepgold
= findgold(mtmp
->minvent
))
899 > ((ygold
= findgold(invent
)) ? ygold
->quan
: 0L))))
902 if (!should_see
&& can_track(ptr
)) {
905 cp
= gettrack(omx
, omy
);
913 if ((!mtmp
->mpeaceful
|| !rn2(10)) && (!Is_rogue_level(&u
.uz
))) {
914 boolean in_line
= (lined_up(mtmp
)
915 && (distmin(mtmp
->mx
, mtmp
->my
, mtmp
->mux
, mtmp
->muy
)
916 <= (throws_rocks(youmonst
.data
) ? 20 : ACURRSTR
/ 2 + 1)));
918 if (appr
!= 1 || !in_line
) {
919 /* Monsters in combat won't pick stuff up, avoiding the
920 * situation where you toss arrows at it and it has nothing
921 * better to do than pick the arrows up.
923 register int pctload
=
924 (curr_mon_load(mtmp
) * 100) / max_mon_load(mtmp
);
926 /* look for gold or jewels nearby */
927 likegold
= (likes_gold(ptr
) && pctload
< 95);
928 likegems
= (likes_gems(ptr
) && pctload
< 85);
929 uses_items
= (!mindless(ptr
) && !is_animal(ptr
) && pctload
< 75);
930 likeobjs
= (likes_objs(ptr
) && pctload
< 75);
931 likemagic
= (likes_magic(ptr
) && pctload
< 85);
932 likerock
= (throws_rocks(ptr
) && pctload
< 50 && !Sokoban
);
933 conceals
= hides_under(ptr
);
938 #define SQSRCHRADIUS 5
941 register int minr
= SQSRCHRADIUS
; /* not too far away */
942 register struct obj
*otmp
;
944 int oomx
, oomy
, lmx
, lmy
;
946 /* cut down the search radius if it thinks character is closer. */
947 if (distmin(mtmp
->mux
, mtmp
->muy
, omx
, omy
) < SQSRCHRADIUS
950 /* guards shouldn't get too distracted */
951 if (!mtmp
->mpeaceful
&& is_mercenary(ptr
))
954 if ((likegold
|| likegems
|| likeobjs
|| likemagic
|| likerock
955 || conceals
) && (!*in_rooms(omx
, omy
, SHOPBASE
)
956 || (!rn2(25) && !mtmp
->isshk
))) {
958 oomx
= min(COLNO
- 1, omx
+ minr
);
959 oomy
= min(ROWNO
- 1, omy
+ minr
);
960 lmx
= max(1, omx
- minr
);
961 lmy
= max(0, omy
- minr
);
962 for (otmp
= fobj
; otmp
; otmp
= otmp
->nobj
) {
963 /* monsters may pick rocks up, but won't go out of their way
964 to grab them; this might hamper sling wielders, but it cuts
965 down on move overhead by filtering out most common item */
966 if (otmp
->otyp
== ROCK
)
970 /* Nymphs take everything. Most other creatures should not
971 * pick up corpses except as a special case like in
972 * searches_for_item(). We need to do this check in
973 * mpickstuff() as well.
975 if (xx
>= lmx
&& xx
<= oomx
&& yy
>= lmy
&& yy
<= oomy
) {
976 /* don't get stuck circling around object that's
977 underneath an immobile or hidden monster;
978 paralysis victims excluded */
979 if ((mtoo
= m_at(xx
, yy
)) != 0
980 && (mtoo
->msleeping
|| mtoo
->mundetected
981 || (mtoo
->mappearance
&& !mtoo
->iswiz
)
982 || !mtoo
->data
->mmove
))
984 /* the mfndpos() test for whether to allow a move to a
985 water location accepts flyers, but they can't reach
986 underwater objects, so being able to move to a spot
987 is insufficient for deciding whether to do so */
988 if ((is_pool(xx
, yy
) && !is_swimmer(ptr
))
989 || (is_lava(xx
, yy
) && !likes_lava(ptr
)))
992 if (((likegold
&& otmp
->oclass
== COIN_CLASS
)
993 || (likeobjs
&& index(practical
, otmp
->oclass
)
994 && (otmp
->otyp
!= CORPSE
995 || (ptr
->mlet
== S_NYMPH
996 && !is_rider(&mons
[otmp
->corpsenm
]))))
997 || (likemagic
&& index(magical
, otmp
->oclass
))
998 || (uses_items
&& searches_for_item(mtmp
, otmp
))
999 || (likerock
&& otmp
->otyp
== BOULDER
)
1000 || (likegems
&& otmp
->oclass
== GEM_CLASS
1001 && objects
[otmp
->otyp
].oc_material
!= MINERAL
)
1002 || (conceals
&& !cansee(otmp
->ox
, otmp
->oy
))
1003 || (ptr
== &mons
[PM_GELATINOUS_CUBE
]
1004 && !index(indigestion
, otmp
->oclass
)
1005 && !(otmp
->otyp
== CORPSE
1006 && touch_petrifies(&mons
[otmp
->corpsenm
]))))
1007 && touch_artifact(otmp
, mtmp
)) {
1008 if (can_carry(mtmp
, otmp
) > 0
1009 && (throws_rocks(ptr
) || !sobj_at(BOULDER
, xx
, yy
))
1010 && (!is_unicorn(ptr
)
1011 || objects
[otmp
->otyp
].oc_material
== GEMSTONE
)
1012 /* Don't get stuck circling an Elbereth */
1013 && !onscary(xx
, yy
, mtmp
)) {
1014 minr
= distmin(omx
, omy
, xx
, yy
);
1015 oomx
= min(COLNO
- 1, omx
+ minr
);
1016 oomy
= min(ROWNO
- 1, omy
+ minr
);
1017 lmx
= max(1, omx
- minr
);
1018 lmy
= max(0, omy
- minr
);
1021 if (gx
== omx
&& gy
== omy
) {
1022 mmoved
= 3; /* actually unnecessary */
1029 } else if (likegold
) {
1030 /* don't try to pick up anything else, but use the same loop */
1032 likegems
= likeobjs
= likemagic
= likerock
= conceals
= 0;
1036 if (minr
< SQSRCHRADIUS
&& appr
== -1) {
1037 if (distmin(omx
, omy
, mtmp
->mux
, mtmp
->muy
) <= 3) {
1045 /* don't tunnel if hostile and close enough to prefer a weapon */
1046 if (can_tunnel
&& needspick(ptr
)
1047 && ((!mtmp
->mpeaceful
|| Conflict
)
1048 && dist2(mtmp
->mx
, mtmp
->my
, mtmp
->mux
, mtmp
->muy
) <= 8))
1054 if (mtmp
->mpeaceful
&& (!Conflict
|| resist(mtmp
, RING_CLASS
, 0, 0)))
1055 flag
|= (ALLOW_SANCT
| ALLOW_SSM
);
1058 if (is_minion(ptr
) || is_rider(ptr
))
1059 flag
|= ALLOW_SANCT
;
1060 /* unicorn may not be able to avoid hero on a noteleport level */
1061 if (is_unicorn(ptr
) && !level
.flags
.noteleport
)
1063 if (passes_walls(ptr
))
1064 flag
|= (ALLOW_WALL
| ALLOW_ROCK
);
1065 if (passes_bars(ptr
))
1069 if (is_human(ptr
) || ptr
== &mons
[PM_MINOTAUR
])
1071 if ((is_undead(ptr
) && ptr
->mlet
!= S_GHOST
) || is_vampshifter(mtmp
))
1073 if (throws_rocks(ptr
))
1082 register int i
, j
, nx
, ny
, nearer
;
1085 register coord
*mtrk
;
1088 cnt
= mfndpos(mtmp
, poss
, info
, flag
);
1090 jcnt
= min(MTSZ
, cnt
- 1);
1092 nidist
= dist2(nix
, niy
, gx
, gy
);
1093 /* allow monsters be shortsighted on some levels for balance */
1094 if (!mtmp
->mpeaceful
&& level
.flags
.shortsighted
1095 && nidist
> (couldsee(nix
, niy
) ? 144 : 36) && appr
== 1)
1097 if (is_unicorn(ptr
) && level
.flags
.noteleport
) {
1098 /* on noteleport levels, perhaps we cannot avoid hero */
1099 for (i
= 0; i
< cnt
; i
++)
1100 if (!(info
[i
] & NOTONL
))
1103 better_with_displacing
=
1104 should_displace(mtmp
, poss
, info
, cnt
, gx
, gy
);
1105 for (i
= 0; i
< cnt
; i
++) {
1106 if (avoid
&& (info
[i
] & NOTONL
))
1111 if (MON_AT(nx
, ny
) && (info
[i
] & ALLOW_MDISP
)
1112 && !(info
[i
] & ALLOW_M
) && !better_with_displacing
)
1115 mtrk
= &mtmp
->mtrack
[0];
1116 for (j
= 0; j
< jcnt
; mtrk
++, j
++)
1117 if (nx
== mtrk
->x
&& ny
== mtrk
->y
)
1118 if (rn2(4 * (cnt
- j
)))
1122 nearer
= ((ndist
= dist2(nx
, ny
, gx
, gy
)) < nidist
);
1124 if ((appr
== 1 && nearer
) || (appr
== -1 && !nearer
)
1125 || (!appr
&& !rn2(++chcnt
)) || !mmoved
) {
1140 if (mmoved
== 1 && (u
.ux
!= nix
|| u
.uy
!= niy
) && itsstuck(mtmp
))
1143 if (mmoved
== 1 && m_digweapon_check(mtmp
, nix
,niy
))
1146 /* If ALLOW_U is set, either it's trying to attack you, or it
1147 * thinks it is. In either case, attack this spot in preference to
1150 /* Actually, this whole section of code doesn't work as you'd expect.
1151 * Most attacks are handled in dochug(). It calls distfleeck(), which
1152 * among other things sets nearby if the monster is near you--and if
1153 * nearby is set, we never call m_move unless it is a special case
1154 * (confused, stun, etc.) The effect is that this ALLOW_U (and
1155 * mfndpos) has no effect for normal attacks, though it lets a
1156 * confused monster attack you by accident.
1158 if (info
[chi
] & ALLOW_U
) {
1162 if (nix
== u
.ux
&& niy
== u
.uy
) {
1167 /* The monster may attack another based on 1 of 2 conditions:
1168 * 1 - It may be confused.
1169 * 2 - It may mistake the monster for your (displaced) image.
1170 * Pets get taken care of above and shouldn't reach this code.
1171 * Conflict gets handled even farther away (movemon()).
1173 if ((info
[chi
] & ALLOW_M
) || (nix
== mtmp
->mux
&& niy
== mtmp
->muy
)) {
1174 struct monst
*mtmp2
;
1176 mtmp2
= m_at(nix
, niy
);
1178 notonhead
= mtmp2
&& (nix
!= mtmp2
->mx
|| niy
!= mtmp2
->my
);
1179 /* note: mstatus returns 0 if mtmp2 is nonexistent */
1180 mstatus
= mattackm(mtmp
, mtmp2
);
1182 if (mstatus
& MM_AGR_DIED
) /* aggressor died */
1185 if ((mstatus
& MM_HIT
) && !(mstatus
& MM_DEF_DIED
) && rn2(4)
1186 && mtmp2
->movement
>= NORMAL_SPEED
) {
1187 mtmp2
->movement
-= NORMAL_SPEED
;
1189 mstatus
= mattackm(mtmp2
, mtmp
); /* return attack */
1190 if (mstatus
& MM_DEF_DIED
)
1196 if ((info
[chi
] & ALLOW_MDISP
)) {
1197 struct monst
*mtmp2
;
1199 mtmp2
= m_at(nix
, niy
);
1200 mstatus
= mdisplacem(mtmp
, mtmp2
, FALSE
);
1201 if ((mstatus
& MM_AGR_DIED
) || (mstatus
& MM_DEF_DIED
))
1203 if (mstatus
& MM_HIT
)
1208 if (!m_in_out_region(mtmp
, nix
, niy
))
1210 remove_monster(omx
, omy
);
1211 place_monster(mtmp
, nix
, niy
);
1212 for (j
= MTSZ
- 1; j
> 0; j
--)
1213 mtmp
->mtrack
[j
] = mtmp
->mtrack
[j
- 1];
1214 mtmp
->mtrack
[0].x
= omx
;
1215 mtmp
->mtrack
[0].y
= omy
;
1216 /* Place a segment at the old position. */
1220 if (is_unicorn(ptr
) && rn2(2) && !tele_restrict(mtmp
)) {
1221 (void) rloc(mtmp
, TRUE
);
1228 if (mmoved
== 1 || mmoved
== 3) {
1229 boolean canseeit
= cansee(mtmp
->mx
, mtmp
->my
);
1232 newsym(omx
, omy
); /* update the old position */
1233 if (mintrap(mtmp
) >= 2) {
1235 newsym(mtmp
->mx
, mtmp
->my
);
1236 return 2; /* it died */
1240 /* open a door, or crash through it, if 'mtmp' can */
1241 if (IS_DOOR(levl
[mtmp
->mx
][mtmp
->my
].typ
)
1242 && !passes_walls(ptr
) /* doesn't need to open doors */
1243 && !can_tunnel
) { /* taken care of below */
1244 struct rm
*here
= &levl
[mtmp
->mx
][mtmp
->my
];
1245 boolean btrapped
= (here
->doormask
& D_TRAPPED
) != 0,
1246 observeit
= canseeit
&& canspotmon(mtmp
);
1248 if ((here
->doormask
& (D_LOCKED
| D_CLOSED
)) != 0
1251 && vamp_shift(mtmp
, &mons
[PM_FOG_CLOUD
],
1252 canspotmon(mtmp
))))) {
1253 if (flags
.verbose
&& canseemon(mtmp
))
1254 pline("%s %s under the door.", Monnam(mtmp
),
1255 (ptr
== &mons
[PM_FOG_CLOUD
]
1256 || ptr
== &mons
[PM_YELLOW_LIGHT
])
1259 } else if (here
->doormask
& D_LOCKED
&& can_unlock
) {
1261 here
->doormask
= D_NODOOR
;
1262 newsym(mtmp
->mx
, mtmp
->my
);
1263 unblock_point(mtmp
->mx
, mtmp
->my
); /* vision */
1264 if (mb_trapped(mtmp
))
1267 if (flags
.verbose
) {
1269 pline("%s unlocks and opens a door.",
1272 You_see("a door unlock and open.");
1274 You_hear("a door unlock and open.");
1276 here
->doormask
= D_ISOPEN
;
1277 /* newsym(mtmp->mx, mtmp->my); */
1278 unblock_point(mtmp
->mx
, mtmp
->my
); /* vision */
1280 } else if (here
->doormask
== D_CLOSED
&& can_open
) {
1282 here
->doormask
= D_NODOOR
;
1283 newsym(mtmp
->mx
, mtmp
->my
);
1284 unblock_point(mtmp
->mx
, mtmp
->my
); /* vision */
1285 if (mb_trapped(mtmp
))
1288 if (flags
.verbose
) {
1290 pline("%s opens a door.", Monnam(mtmp
));
1292 You_see("a door open.");
1294 You_hear("a door open.");
1296 here
->doormask
= D_ISOPEN
;
1297 /* newsym(mtmp->mx, mtmp->my); */ /* done below */
1298 unblock_point(mtmp
->mx
, mtmp
->my
); /* vision */
1300 } else if (here
->doormask
& (D_LOCKED
| D_CLOSED
)) {
1301 /* mfndpos guarantees this must be a doorbuster */
1303 here
->doormask
= D_NODOOR
;
1304 newsym(mtmp
->mx
, mtmp
->my
);
1305 unblock_point(mtmp
->mx
, mtmp
->my
); /* vision */
1306 if (mb_trapped(mtmp
))
1309 if (flags
.verbose
) {
1311 pline("%s smashes down a door.",
1314 You_see("a door crash open.");
1316 You_hear("a door crash open.");
1318 if ((here
->doormask
& D_LOCKED
) != 0 && !rn2(2))
1319 here
->doormask
= D_NODOOR
;
1321 here
->doormask
= D_BROKEN
;
1322 /* newsym(mtmp->mx, mtmp->my); */ /* done below */
1323 unblock_point(mtmp
->mx
, mtmp
->my
); /* vision */
1325 /* if it's a shop door, schedule repair */
1326 if (*in_rooms(mtmp
->mx
, mtmp
->my
, SHOPBASE
))
1327 add_damage(mtmp
->mx
, mtmp
->my
, 0L);
1329 } else if (levl
[mtmp
->mx
][mtmp
->my
].typ
== IRONBARS
) {
1330 if (may_dig(mtmp
->mx
, mtmp
->my
)
1331 && (dmgtype(ptr
, AD_RUST
) || dmgtype(ptr
, AD_CORR
))) {
1332 if (canseemon(mtmp
))
1333 pline("%s eats through the iron bars.", Monnam(mtmp
));
1334 dissolve_bars(mtmp
->mx
, mtmp
->my
);
1336 } else if (flags
.verbose
&& canseemon(mtmp
))
1337 Norep("%s %s %s the iron bars.", Monnam(mtmp
),
1338 /* pluralization fakes verb conjugation */
1339 makeplural(locomotion(ptr
, "pass")),
1340 passes_walls(ptr
) ? "through" : "between");
1344 if (can_tunnel
&& mdig_tunnel(mtmp
))
1345 return 2; /* mon died (position already updated) */
1347 /* set also in domove(), hack.c */
1348 if (u
.uswallow
&& mtmp
== u
.ustuck
1349 && (mtmp
->mx
!= omx
|| mtmp
->my
!= omy
)) {
1350 /* If the monster moved, then update */
1357 newsym(mtmp
->mx
, mtmp
->my
);
1359 if (OBJ_AT(mtmp
->mx
, mtmp
->my
) && mtmp
->mcanmove
) {
1360 /* recompute the likes tests, in case we polymorphed
1361 * or if the "likegold" case got taken above */
1363 int pctload
= (curr_mon_load(mtmp
) * 100) / max_mon_load(mtmp
);
1365 /* look for gold or jewels nearby */
1366 likegold
= (likes_gold(ptr
) && pctload
< 95);
1367 likegems
= (likes_gems(ptr
) && pctload
< 85);
1369 (!mindless(ptr
) && !is_animal(ptr
) && pctload
< 75);
1370 likeobjs
= (likes_objs(ptr
) && pctload
< 75);
1371 likemagic
= (likes_magic(ptr
) && pctload
< 85);
1372 likerock
= (throws_rocks(ptr
) && pctload
< 50 && !Sokoban
);
1373 conceals
= hides_under(ptr
);
1376 /* Maybe a rock mole just ate some metal object */
1377 if (metallivorous(ptr
)) {
1378 if (meatmetal(mtmp
) == 2)
1379 return 2; /* it died */
1382 if (g_at(mtmp
->mx
, mtmp
->my
) && likegold
)
1385 /* Maybe a cube ate just about anything */
1386 if (ptr
== &mons
[PM_GELATINOUS_CUBE
]) {
1387 if (meatobj(mtmp
) == 2)
1388 return 2; /* it died */
1391 if (!*in_rooms(mtmp
->mx
, mtmp
->my
, SHOPBASE
) || !rn2(25)) {
1392 boolean picked
= FALSE
;
1395 picked
|= mpickstuff(mtmp
, practical
);
1397 picked
|= mpickstuff(mtmp
, magical
);
1399 picked
|= mpickstuff(mtmp
, boulder_class
);
1401 picked
|= mpickstuff(mtmp
, gem_class
);
1403 picked
|= mpickstuff(mtmp
, (char *) 0);
1409 newsym(mtmp
->mx
, mtmp
->my
);
1415 if (hides_under(ptr
) || ptr
->mlet
== S_EEL
) {
1416 /* Always set--or reset--mundetected if it's already hidden
1417 (just in case the object it was hiding under went away);
1418 usually set mundetected unless monster can't move. */
1419 if (mtmp
->mundetected
1420 || (mtmp
->mcanmove
&& !mtmp
->msleeping
&& rn2(5)))
1421 (void) hideunder(mtmp
);
1422 newsym(mtmp
->mx
, mtmp
->my
);
1425 after_shk_move(mtmp
);
1435 levl
[x
][y
].typ
= (Is_special(&u
.uz
) || *in_rooms(x
, y
, 0)) ? ROOM
: CORR
;
1443 return (boolean
) (IS_DOOR(levl
[x
][y
].typ
)
1444 && (levl
[x
][y
].doormask
& (D_LOCKED
| D_CLOSED
)));
1451 int levtyp
= levl
[x
][y
].typ
;
1453 /* use underlying terrain in front of closed drawbridge */
1454 if (levtyp
== DRAWBRIDGE_UP
)
1455 levtyp
= db_under_typ(levl
[x
][y
].drawbridgemask
);
1457 return (boolean
) (ACCESSIBLE(levtyp
) && !closed_door(x
, y
));
1460 /* decide where the monster thinks you are standing */
1463 register struct monst
*mtmp
;
1465 boolean notseen
, gotu
;
1466 register int disp
, mx
= mtmp
->mux
, my
= mtmp
->muy
;
1467 long umoney
= money_cnt(invent
);
1470 * do cheapest and/or most likely tests first
1473 /* pet knows your smell; grabber still has hold of you */
1474 if (mtmp
->mtame
|| mtmp
== u
.ustuck
)
1477 /* monsters which know where you are don't suddenly forget,
1478 if you haven't moved away */
1479 if (mx
== u
.ux
&& my
== u
.uy
)
1482 notseen
= (!mtmp
->mcansee
|| (Invis
&& !perceives(mtmp
->data
)));
1483 /* add cases as required. eg. Displacement ... */
1484 if (notseen
|| Underwater
) {
1485 /* Xorns can smell quantities of valuable metal
1486 like that in solid gold coins, treat as seen */
1487 if ((mtmp
->data
== &mons
[PM_XORN
]) && umoney
&& !Underwater
)
1491 } else if (Displaced
) {
1492 disp
= couldsee(mx
, my
) ? 2 : 1;
1498 /* without something like the following, invisibility and displacement
1500 gotu
= notseen
? !rn2(3) : Displaced
? !rn2(4) : FALSE
;
1503 register int try_cnt
= 0;
1505 if (++try_cnt
> 200)
1506 goto found_you
; /* punt */
1507 mx
= u
.ux
- disp
+ rn2(2 * disp
+ 1);
1508 my
= u
.uy
- disp
+ rn2(2 * disp
+ 1);
1509 } while (!isok(mx
, my
)
1510 || (disp
!= 2 && mx
== mtmp
->mx
&& my
== mtmp
->my
)
1511 || ((mx
!= u
.ux
|| my
!= u
.uy
) && !passes_walls(mtmp
->data
)
1512 && !(accessible(mx
, my
)
1513 || (closed_door(mx
, my
)
1514 && (can_ooze(mtmp
) || can_fog(mtmp
)))))
1515 || !couldsee(mx
, my
));
1527 * mon-to-mon displacement is a deliberate "get out of my way" act,
1528 * not an accidental bump, so we don't consider mstun or mconf in
1531 * We do consider many other things about the target and its
1535 undesirable_disp(mtmp
, x
, y
)
1539 boolean is_pet
= (mtmp
&& mtmp
->mtame
&& !mtmp
->isminion
);
1540 struct trap
*trap
= t_at(x
, y
);
1543 /* Pets avoid a trap if you've seen it usually. */
1544 if (trap
&& trap
->tseen
&& rn2(40))
1546 /* Pets avoid cursed locations */
1547 if (cursed_object_at(x
, y
))
1550 /* Monsters avoid a trap if they've seen that type before */
1551 } else if (trap
&& rn2(40)
1552 && (mtmp
->mtrapseen
& (1 << (trap
->ttyp
- 1))) != 0) {
1560 * Inventory prevents passage under door.
1561 * Used by can_ooze() and can_fog().
1564 stuff_prevents_passage(mtmp
)
1567 struct obj
*chain
, *obj
;
1569 if (mtmp
== &youmonst
) {
1572 chain
= mtmp
->minvent
;
1574 for (obj
= chain
; obj
; obj
= obj
->nobj
) {
1575 int typ
= obj
->otyp
;
1577 if (typ
== COIN_CLASS
&& obj
->quan
> 100L)
1579 if (obj
->oclass
!= GEM_CLASS
&& !(typ
>= ARROW
&& typ
<= BOOMERANG
)
1580 && !(typ
>= DAGGER
&& typ
<= CRYSKNIFE
) && typ
!= SLING
1581 && !is_cloak(obj
) && typ
!= FEDORA
&& !is_gloves(obj
)
1582 && typ
!= LEATHER_JACKET
&& typ
!= CREDIT_CARD
&& !is_shirt(obj
)
1583 && !(typ
== CORPSE
&& verysmall(&mons
[obj
->corpsenm
]))
1584 && typ
!= FORTUNE_COOKIE
&& typ
!= CANDY_BAR
&& typ
!= PANCAKE
1585 && typ
!= LEMBAS_WAFER
&& typ
!= LUMP_OF_ROYAL_JELLY
1586 && obj
->oclass
!= AMULET_CLASS
&& obj
->oclass
!= RING_CLASS
1587 && obj
->oclass
!= VENOM_CLASS
&& typ
!= SACK
1588 && typ
!= BAG_OF_HOLDING
&& typ
!= BAG_OF_TRICKS
1589 && !Is_candle(obj
) && typ
!= OILSKIN_SACK
&& typ
!= LEASH
1590 && typ
!= STETHOSCOPE
&& typ
!= BLINDFOLD
&& typ
!= TOWEL
1591 && typ
!= TIN_WHISTLE
&& typ
!= MAGIC_WHISTLE
1592 && typ
!= MAGIC_MARKER
&& typ
!= TIN_OPENER
&& typ
!= SKELETON_KEY
1593 && typ
!= LOCK_PICK
)
1595 if (Is_container(obj
) && obj
->cobj
)
1605 if (!amorphous(mtmp
->data
) || stuff_prevents_passage(mtmp
))
1610 /* monster can change form into a fog if necessary */
1615 if (!(mvitals
[PM_FOG_CLOUD
].mvflags
& G_GENOD
) && is_vampshifter(mtmp
)
1616 && !Protection_from_shape_changers
&& !stuff_prevents_passage(mtmp
))
1622 vamp_shift(mon
, ptr
, domsg
)
1624 struct permonst
*ptr
;
1631 Sprintf(fmtstr
, "You %s %%s where %s was.",
1632 sensemon(mon
) ? "now detect" : "observe",
1635 if (mon
->data
== ptr
) {
1636 /* already right shape */
1639 } else if (is_vampshifter(mon
)) {
1640 reslt
= newcham(mon
, ptr
, FALSE
, FALSE
);
1642 if (reslt
&& domsg
) {
1643 pline(fmtstr
, an(m_monnam(mon
)));