1 /* NetHack 3.6 monmove.c $NHDT-Date: 1456959639 2016/03/02 23:00:39 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.85 $ */
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
);
324 /* magical protection won't last forever, so there'll be a
325 * chance of the magic being used up regardless of type */
327 wipe_engr_at(seescaryx
, seescaryy
, 1, TRUE
);
333 /* perform a special one-time action for a monster; returns -1 if nothing
334 special happened, 0 if monster uses up its turn, 1 if monster is killed */
339 mon
->mstrategy
&= ~STRAT_ARRIVE
; /* always reset */
344 /* returns 1 if monster died moving, 0 otherwise */
345 /* The whole dochugw/m_move/distfleeck/mfndpos section is serious spaghetti
350 register struct monst
*mtmp
;
352 register struct permonst
*mdat
;
353 register int tmp
= 0;
354 int inrange
, nearby
, scared
;
356 /* Pre-movement adjustments
361 if (mtmp
->mstrategy
& STRAT_ARRIVE
) {
362 int res
= m_arrival(mtmp
);
367 /* check for waitmask status change */
368 if ((mtmp
->mstrategy
& STRAT_WAITFORU
)
369 && (m_canseeu(mtmp
) || mtmp
->mhp
< mtmp
->mhpmax
))
370 mtmp
->mstrategy
&= ~STRAT_WAITFORU
;
372 /* update quest status flags */
373 quest_stat_check(mtmp
);
375 if (!mtmp
->mcanmove
|| (mtmp
->mstrategy
& STRAT_WAITMASK
)) {
377 newsym(mtmp
->mx
, mtmp
->my
);
378 if (mtmp
->mcanmove
&& (mtmp
->mstrategy
& STRAT_CLOSE
)
379 && !mtmp
->msleeping
&& monnear(mtmp
, u
.ux
, u
.uy
))
380 quest_talk(mtmp
); /* give the leaders a chance to speak */
381 return 0; /* other frozen monsters can't do anything */
384 /* there is a chance we will wake it */
385 if (mtmp
->msleeping
&& !disturb(mtmp
)) {
387 newsym(mtmp
->mx
, mtmp
->my
);
391 /* not frozen or sleeping: wipe out texts written in the dust */
392 wipe_engr_at(mtmp
->mx
, mtmp
->my
, 1, FALSE
);
394 /* confused monsters get unconfused with small probability */
395 if (mtmp
->mconf
&& !rn2(50))
398 /* stunned monsters get un-stunned with larger probability */
399 if (mtmp
->mstun
&& !rn2(10))
402 /* some monsters teleport */
403 if (mtmp
->mflee
&& !rn2(40) && can_teleport(mdat
) && !mtmp
->iswiz
404 && !level
.flags
.noteleport
) {
405 (void) rloc(mtmp
, TRUE
);
408 if (mdat
->msound
== MS_SHRIEK
&& !um_dist(mtmp
->mx
, mtmp
->my
, 1))
410 if (mdat
== &mons
[PM_MEDUSA
] && couldsee(mtmp
->mx
, mtmp
->my
))
413 return 1; /* m_respond gaze can kill medusa */
415 /* fleeing monsters might regain courage */
416 if (mtmp
->mflee
&& !mtmp
->mfleetim
&& mtmp
->mhp
== mtmp
->mhpmax
420 /* cease conflict-induced swallow/grab if conflict has ended */
421 if (mtmp
== u
.ustuck
&& mtmp
->mpeaceful
&& !mtmp
->mconf
&& !Conflict
) {
423 return 0; /* uses up monster's turn */
427 /* Must be done after you move and before the monster does. The
428 * set_apparxy() call in m_move() doesn't suffice since the variables
429 * inrange, etc. all depend on stuff set by set_apparxy().
432 /* Monsters that want to acquire things */
433 /* may teleport, so do it before inrange is set */
434 if (is_covetous(mdat
))
435 (void) tactics(mtmp
);
437 /* check distance and scariness of attacks */
438 distfleeck(mtmp
, &inrange
, &nearby
, &scared
);
440 if (find_defensive(mtmp
)) {
441 if (use_defensive(mtmp
) != 0)
443 } else if (find_misc(mtmp
)) {
444 if (use_misc(mtmp
) != 0)
448 /* Demonic Blackmail! */
449 if (nearby
&& mdat
->msound
== MS_BRIBE
&& mtmp
->mpeaceful
&& !mtmp
->mtame
451 if (mtmp
->mux
!= u
.ux
|| mtmp
->muy
!= u
.uy
) {
452 pline("%s whispers at thin air.",
453 cansee(mtmp
->mux
, mtmp
->muy
) ? Monnam(mtmp
) : "It");
455 if (is_demon(youmonst
.data
)) {
456 /* "Good hunting, brother" */
457 if (!tele_restrict(mtmp
))
458 (void) rloc(mtmp
, TRUE
);
460 mtmp
->minvis
= mtmp
->perminvis
= 0;
461 /* Why? For the same reason in real demon talk */
462 pline("%s gets angry!", Amonnam(mtmp
));
465 /* since no way is an image going to pay it off */
467 } else if (demon_talk(mtmp
))
468 return 1; /* you paid it off */
471 /* the watch will look around and see if you are up to no good :-) */
472 if (is_watch(mdat
)) {
475 } else if (is_mind_flayer(mdat
) && !rn2(20)) {
476 struct monst
*m2
, *nmon
= (struct monst
*) 0;
479 pline("%s concentrates.", Monnam(mtmp
));
480 if (distu(mtmp
->mx
, mtmp
->my
) > BOLT_LIM
* BOLT_LIM
) {
481 You("sense a faint wave of psychic energy.");
484 pline("A wave of psychic energy pours over you!");
486 && (!Conflict
|| resist(mtmp
, RING_CLASS
, 0, 0))) {
487 pline("It feels quite soothing.");
488 } else if (!u
.uinvulnerable
) {
489 register boolean m_sen
= sensemon(mtmp
);
491 if (m_sen
|| (Blind_telepat
&& rn2(2)) || !rn2(10)) {
493 pline("It locks on to your %s!",
494 m_sen
? "telepathy" : Blind_telepat
? "latent telepathy"
497 if (Half_spell_damage
)
499 losehp(dmg
, "psychic blast", KILLED_BY_AN
);
502 for (m2
= fmon
; m2
; m2
= nmon
) {
506 if (m2
->mpeaceful
== mtmp
->mpeaceful
)
508 if (mindless(m2
->data
))
512 if ((telepathic(m2
->data
) && (rn2(2) || m2
->mblinded
))
514 if (cansee(m2
->mx
, m2
->my
))
515 pline("It locks on to %s.", mon_nam(m2
));
518 monkilled(m2
, "", AD_DRIN
);
526 /* If monster is nearby you, and has to wield a weapon, do so. This
527 * costs the monster a move, of course.
529 if ((!mtmp
->mpeaceful
|| Conflict
) && inrange
530 && dist2(mtmp
->mx
, mtmp
->my
, mtmp
->mux
, mtmp
->muy
) <= 8
531 && attacktype(mdat
, AT_WEAP
)) {
534 /* The scared check is necessary. Otherwise a monster that is
535 * one square near the player but fleeing into a wall would keep
536 * switching between pick-axe and weapon. If monster is stuck
537 * in a trap, prefer ranged weapon (wielding is done in thrwmu).
538 * This may cost the monster an attack, but keeps the monster
539 * from switching back and forth if carrying both.
541 mw_tmp
= MON_WEP(mtmp
);
542 if (!(scared
&& mw_tmp
&& is_pick(mw_tmp
))
543 && mtmp
->weapon_check
== NEED_WEAPON
544 && !(mtmp
->mtrapped
&& !nearby
&& select_rwep(mtmp
))) {
545 mtmp
->weapon_check
= NEED_HTH_WEAPON
;
546 if (mon_wield_item(mtmp
) != 0)
551 /* Now the actual movement phase
554 if (!nearby
|| mtmp
->mflee
|| scared
|| mtmp
->mconf
|| mtmp
->mstun
555 || (mtmp
->minvis
&& !rn2(3))
556 || (mdat
->mlet
== S_LEPRECHAUN
&& !findgold(invent
)
557 && (findgold(mtmp
->minvent
) || rn2(2)))
558 || (is_wanderer(mdat
) && !rn2(4)) || (Conflict
&& !mtmp
->iswiz
)
559 || (!mtmp
->mcansee
&& !rn2(4)) || mtmp
->mpeaceful
) {
560 /* Possibly cast an undirected spell if not attacking you */
561 /* note that most of the time castmu() will pick a directed
562 spell and do nothing, so the monster moves normally */
563 /* arbitrary distance restriction to keep monster far away
564 from you from having cast dozens of sticks-to-snakes
565 or similar spells by the time you reach it */
566 if (dist2(mtmp
->mx
, mtmp
->my
, u
.ux
, u
.uy
) <= 49
567 && !mtmp
->mspec_used
) {
570 for (a
= &mdat
->mattk
[0]; a
< &mdat
->mattk
[NATTK
]; a
++) {
571 if (a
->aatyp
== AT_MAGC
572 && (a
->adtyp
== AD_SPEL
|| a
->adtyp
== AD_CLRC
)) {
573 if (castmu(mtmp
, a
, FALSE
, FALSE
)) {
581 tmp
= m_move(mtmp
, 0);
583 distfleeck(mtmp
, &inrange
, &nearby
, &scared
); /* recalc */
585 switch (tmp
) { /* for pets, cases 0 and 3 are equivalent */
586 case 0: /* no movement, but it can still attack you */
587 case 3: /* absolutely no movement */
588 /* vault guard might have vanished */
589 if (mtmp
->isgd
&& (mtmp
->mhp
< 1 || mtmp
->mx
== 0))
590 return 1; /* behave as if it died */
591 /* During hallucination, monster appearance should
592 * still change - even if it doesn't move.
595 newsym(mtmp
->mx
, mtmp
->my
);
597 case 1: /* monster moved */
598 /* Maybe it stepped on a trap and fell asleep... */
599 if (mtmp
->msleeping
|| !mtmp
->mcanmove
)
601 /* Monsters can move and then shoot on same turn;
602 our hero can't. Is that fair? */
603 if (!nearby
&& (ranged_attk(mdat
) || find_offensive(mtmp
)))
605 /* engulfer/grabber checks */
606 if (mtmp
== u
.ustuck
) {
607 /* a monster that's digesting you can move at the
611 return mattacku(mtmp
);
612 /* if confused grabber has wandered off, let go */
613 if (distu(mtmp
->mx
, mtmp
->my
) > 2)
617 case 2: /* monster died */
622 /* Now, attack the player if possible - one attack set per monst
625 if (!mtmp
->mpeaceful
|| (Conflict
&& !resist(mtmp
, RING_CLASS
, 0, 0))) {
626 if (inrange
&& !noattacks(mdat
) && u
.uhp
> 0 && !scared
&& tmp
!= 3)
628 return 1; /* monster died (e.g. exploded) */
633 /* special speeches for quest monsters */
634 if (!mtmp
->msleeping
&& mtmp
->mcanmove
&& nearby
)
636 /* extra emotional attack for vile monsters */
637 if (inrange
&& mtmp
->data
->msound
== MS_CUSS
&& !mtmp
->mpeaceful
638 && couldsee(mtmp
->mx
, mtmp
->my
) && !mtmp
->minvis
&& !rn2(5))
644 static NEARDATA
const char practical
[] = { WEAPON_CLASS
, ARMOR_CLASS
,
645 GEM_CLASS
, FOOD_CLASS
, 0 };
646 static NEARDATA
const char magical
[] = { AMULET_CLASS
, POTION_CLASS
,
647 SCROLL_CLASS
, WAND_CLASS
,
648 RING_CLASS
, SPBOOK_CLASS
, 0 };
649 static NEARDATA
const char indigestion
[] = { BALL_CLASS
, ROCK_CLASS
, 0 };
650 static NEARDATA
const char boulder_class
[] = { ROCK_CLASS
, 0 };
651 static NEARDATA
const char gem_class
[] = { GEM_CLASS
, 0 };
655 register struct monst
*mtmp
;
657 if (sticks(youmonst
.data
) && mtmp
== u
.ustuck
&& !u
.uswallow
) {
658 pline("%s cannot escape from you!", Monnam(mtmp
));
667 * Displacement of another monster is a last resort and only
668 * used on approach. If there are better ways to get to target,
669 * those should be used instead. This function does that evaluation.
672 should_displace(mtmp
, poss
, info
, cnt
, gx
, gy
)
674 coord
*poss
; /* coord poss[9] */
675 long *info
; /* long info[9] */
679 int shortest_with_displacing
= -1;
680 int shortest_without_displacing
= -1;
681 int count_without_displacing
= 0;
682 register int i
, nx
, ny
;
685 for (i
= 0; i
< cnt
; i
++) {
688 ndist
= dist2(nx
, ny
, gx
, gy
);
689 if (MON_AT(nx
, ny
) && (info
[i
] & ALLOW_MDISP
) && !(info
[i
] & ALLOW_M
)
690 && !undesirable_disp(mtmp
, nx
, ny
)) {
691 if (shortest_with_displacing
== -1
692 || (ndist
< shortest_with_displacing
))
693 shortest_with_displacing
= ndist
;
695 if ((shortest_without_displacing
== -1)
696 || (ndist
< shortest_without_displacing
))
697 shortest_without_displacing
= ndist
;
698 count_without_displacing
++;
701 if (shortest_with_displacing
> -1
702 && (shortest_with_displacing
< shortest_without_displacing
703 || !count_without_displacing
))
709 * 0: did not move, but can still attack and do other stuff.
710 * 1: moved, possibly can attack.
712 * 3: did not move, and can't do anything else either.
716 register struct monst
*mtmp
;
720 xchar gx
, gy
, nix
, niy
, chcnt
;
721 int chi
; /* could be schar except for stupid Sun-2 compiler */
722 boolean likegold
= 0, likegems
= 0, likeobjs
= 0, likemagic
= 0,
724 boolean likerock
= 0, can_tunnel
= 0;
725 boolean can_open
= 0, can_unlock
= 0, doorbuster
= 0;
726 boolean uses_items
= 0, setlikes
= 0;
727 boolean avoid
= FALSE
;
728 boolean better_with_displacing
= FALSE
;
729 struct permonst
*ptr
;
731 schar mmoved
= 0; /* not strictly nec.: chi >= 0 will do */
734 int omx
= mtmp
->mx
, omy
= mtmp
->my
;
737 if (mtmp
->mtrapped
) {
738 int i
= mintrap(mtmp
);
740 newsym(mtmp
->mx
, mtmp
->my
);
744 return 0; /* still in trap, so didn't move */
746 ptr
= mtmp
->data
; /* mintrap() can change mtmp->data -dlc */
750 if (mtmp
->meating
<= 0)
751 finish_meating(mtmp
);
752 return 3; /* still eating */
754 if (hides_under(ptr
) && OBJ_AT(mtmp
->mx
, mtmp
->my
) && rn2(10))
755 return 0; /* do not leave hiding place */
758 /* where does mtmp think you are? */
759 /* Not necessary if m_move called from this file, but necessary in
760 * other calls of m_move (ex. leprechauns dodging)
762 if (!Is_rogue_level(&u
.uz
))
763 can_tunnel
= tunnels(ptr
);
764 can_open
= !(nohands(ptr
) || verysmall(ptr
));
766 ((can_open
&& monhaskey(mtmp
, TRUE
)) || mtmp
->iswiz
|| is_rider(ptr
));
767 doorbuster
= is_giant(ptr
);
770 /* my dog gets special treatment */
772 mmoved
= dog_move(mtmp
, after
);
776 /* likewise for shopkeeper */
778 mmoved
= shk_move(mtmp
);
783 mmoved
= 0; /* follow player outside shop */
786 /* and for the guard */
788 mmoved
= gd_move(mtmp
);
796 /* and the acquisitive monsters get special treatment */
797 if (is_covetous(ptr
)) {
798 xchar tx
= STRAT_GOALX(mtmp
->mstrategy
),
799 ty
= STRAT_GOALY(mtmp
->mstrategy
);
800 struct monst
*intruder
= m_at(tx
, ty
);
802 * if there's a monster on the object or in possession of it,
805 if ((dist2(mtmp
->mx
, mtmp
->my
, tx
, ty
) < 2) && intruder
806 && (intruder
!= mtmp
)) {
807 notonhead
= (intruder
->mx
!= tx
|| intruder
->my
!= ty
);
808 if (mattackm(mtmp
, intruder
) == 2)
816 /* and for the priest */
817 if (mtmp
->ispriest
) {
818 mmoved
= pri_move(mtmp
);
827 if (ptr
== &mons
[PM_MAIL_DAEMON
]) {
828 if (!Deaf
&& canseemon(mtmp
))
829 verbalize("I'm late!");
835 /* teleport if that lies in our nature */
836 if (ptr
== &mons
[PM_TENGU
] && !rn2(5) && !mtmp
->mcan
837 && !tele_restrict(mtmp
)) {
838 if (mtmp
->mhp
< 7 || mtmp
->mpeaceful
|| rn2(2))
839 (void) rloc(mtmp
, TRUE
);
846 if (u
.uswallow
&& !mtmp
->mflee
&& u
.ustuck
!= mtmp
)
852 appr
= mtmp
->mflee
? -1 : 1;
853 if (mtmp
->mconf
|| (u
.uswallow
&& mtmp
== u
.ustuck
)) {
856 struct obj
*lepgold
, *ygold
;
857 boolean should_see
= (couldsee(omx
, omy
)
858 && (levl
[gx
][gy
].lit
|| !levl
[omx
][omy
].lit
)
859 && (dist2(omx
, omy
, gx
, gy
) <= 36));
862 || (should_see
&& Invis
&& !perceives(ptr
) && rn2(11))
863 || is_obj_mappear(&youmonst
,STRANGE_OBJECT
) || u
.uundetected
864 || (is_obj_mappear(&youmonst
,GOLD_PIECE
) && !likes_gold(ptr
))
865 || (mtmp
->mpeaceful
&& !mtmp
->isshk
) /* allow shks to follow */
866 || ((monsndx(ptr
) == PM_STALKER
|| ptr
->mlet
== S_BAT
867 || ptr
->mlet
== S_LIGHT
) && !rn2(3)))
870 if (monsndx(ptr
) == PM_LEPRECHAUN
&& (appr
== 1)
871 && ((lepgold
= findgold(mtmp
->minvent
))
873 > ((ygold
= findgold(invent
)) ? ygold
->quan
: 0L))))
876 if (!should_see
&& can_track(ptr
)) {
879 cp
= gettrack(omx
, omy
);
887 if ((!mtmp
->mpeaceful
|| !rn2(10)) && (!Is_rogue_level(&u
.uz
))) {
888 boolean in_line
= (lined_up(mtmp
)
889 && (distmin(mtmp
->mx
, mtmp
->my
, mtmp
->mux
, mtmp
->muy
)
890 <= (throws_rocks(youmonst
.data
) ? 20 : ACURRSTR
/ 2 + 1)));
892 if (appr
!= 1 || !in_line
) {
893 /* Monsters in combat won't pick stuff up, avoiding the
894 * situation where you toss arrows at it and it has nothing
895 * better to do than pick the arrows up.
897 register int pctload
=
898 (curr_mon_load(mtmp
) * 100) / max_mon_load(mtmp
);
900 /* look for gold or jewels nearby */
901 likegold
= (likes_gold(ptr
) && pctload
< 95);
902 likegems
= (likes_gems(ptr
) && pctload
< 85);
903 uses_items
= (!mindless(ptr
) && !is_animal(ptr
) && pctload
< 75);
904 likeobjs
= (likes_objs(ptr
) && pctload
< 75);
905 likemagic
= (likes_magic(ptr
) && pctload
< 85);
906 likerock
= (throws_rocks(ptr
) && pctload
< 50 && !Sokoban
);
907 conceals
= hides_under(ptr
);
912 #define SQSRCHRADIUS 5
915 register int minr
= SQSRCHRADIUS
; /* not too far away */
916 register struct obj
*otmp
;
918 int oomx
, oomy
, lmx
, lmy
;
920 /* cut down the search radius if it thinks character is closer. */
921 if (distmin(mtmp
->mux
, mtmp
->muy
, omx
, omy
) < SQSRCHRADIUS
924 /* guards shouldn't get too distracted */
925 if (!mtmp
->mpeaceful
&& is_mercenary(ptr
))
928 if ((likegold
|| likegems
|| likeobjs
|| likemagic
|| likerock
929 || conceals
) && (!*in_rooms(omx
, omy
, SHOPBASE
)
930 || (!rn2(25) && !mtmp
->isshk
))) {
932 oomx
= min(COLNO
- 1, omx
+ minr
);
933 oomy
= min(ROWNO
- 1, omy
+ minr
);
934 lmx
= max(1, omx
- minr
);
935 lmy
= max(0, omy
- minr
);
936 for (otmp
= fobj
; otmp
; otmp
= otmp
->nobj
) {
937 /* monsters may pick rocks up, but won't go out of their way
938 to grab them; this might hamper sling wielders, but it cuts
939 down on move overhead by filtering out most common item */
940 if (otmp
->otyp
== ROCK
)
944 /* Nymphs take everything. Most other creatures should not
945 * pick up corpses except as a special case like in
946 * searches_for_item(). We need to do this check in
947 * mpickstuff() as well.
949 if (xx
>= lmx
&& xx
<= oomx
&& yy
>= lmy
&& yy
<= oomy
) {
950 /* don't get stuck circling around an object that's
952 an immobile or hidden monster; paralysis victims
954 if ((mtoo
= m_at(xx
, yy
)) != 0
955 && (mtoo
->msleeping
|| mtoo
->mundetected
956 || (mtoo
->mappearance
&& !mtoo
->iswiz
)
957 || !mtoo
->data
->mmove
))
960 if (((likegold
&& otmp
->oclass
== COIN_CLASS
)
961 || (likeobjs
&& index(practical
, otmp
->oclass
)
962 && (otmp
->otyp
!= CORPSE
963 || (ptr
->mlet
== S_NYMPH
964 && !is_rider(&mons
[otmp
->corpsenm
]))))
965 || (likemagic
&& index(magical
, otmp
->oclass
))
966 || (uses_items
&& searches_for_item(mtmp
, otmp
))
967 || (likerock
&& otmp
->otyp
== BOULDER
)
968 || (likegems
&& otmp
->oclass
== GEM_CLASS
969 && objects
[otmp
->otyp
].oc_material
!= MINERAL
)
970 || (conceals
&& !cansee(otmp
->ox
, otmp
->oy
))
971 || (ptr
== &mons
[PM_GELATINOUS_CUBE
]
972 && !index(indigestion
, otmp
->oclass
)
973 && !(otmp
->otyp
== CORPSE
974 && touch_petrifies(&mons
[otmp
->corpsenm
]))))
975 && touch_artifact(otmp
, mtmp
)) {
976 if (can_carry(mtmp
, otmp
) > 0
977 && (throws_rocks(ptr
) || !sobj_at(BOULDER
, xx
, yy
))
979 || objects
[otmp
->otyp
].oc_material
== GEMSTONE
)
980 /* Don't get stuck circling an Elbereth */
981 && !onscary(xx
, yy
, mtmp
)) {
982 minr
= distmin(omx
, omy
, xx
, yy
);
983 oomx
= min(COLNO
- 1, omx
+ minr
);
984 oomy
= min(ROWNO
- 1, omy
+ minr
);
985 lmx
= max(1, omx
- minr
);
986 lmy
= max(0, omy
- minr
);
989 if (gx
== omx
&& gy
== omy
) {
990 mmoved
= 3; /* actually unnecessary */
997 } else if (likegold
) {
998 /* don't try to pick up anything else, but use the same loop */
1000 likegems
= likeobjs
= likemagic
= likerock
= conceals
= 0;
1004 if (minr
< SQSRCHRADIUS
&& appr
== -1) {
1005 if (distmin(omx
, omy
, mtmp
->mux
, mtmp
->muy
) <= 3) {
1013 /* don't tunnel if hostile and close enough to prefer a weapon */
1014 if (can_tunnel
&& needspick(ptr
)
1015 && ((!mtmp
->mpeaceful
|| Conflict
)
1016 && dist2(mtmp
->mx
, mtmp
->my
, mtmp
->mux
, mtmp
->muy
) <= 8))
1022 if (mtmp
->mpeaceful
&& (!Conflict
|| resist(mtmp
, RING_CLASS
, 0, 0)))
1023 flag
|= (ALLOW_SANCT
| ALLOW_SSM
);
1026 if (is_minion(ptr
) || is_rider(ptr
))
1027 flag
|= ALLOW_SANCT
;
1028 /* unicorn may not be able to avoid hero on a noteleport level */
1029 if (is_unicorn(ptr
) && !level
.flags
.noteleport
)
1031 if (passes_walls(ptr
))
1032 flag
|= (ALLOW_WALL
| ALLOW_ROCK
);
1033 if (passes_bars(ptr
))
1037 if (is_human(ptr
) || ptr
== &mons
[PM_MINOTAUR
])
1039 if ((is_undead(ptr
) && ptr
->mlet
!= S_GHOST
) || is_vampshifter(mtmp
))
1041 if (throws_rocks(ptr
))
1050 register int i
, j
, nx
, ny
, nearer
;
1053 register coord
*mtrk
;
1056 cnt
= mfndpos(mtmp
, poss
, info
, flag
);
1058 jcnt
= min(MTSZ
, cnt
- 1);
1060 nidist
= dist2(nix
, niy
, gx
, gy
);
1061 /* allow monsters be shortsighted on some levels for balance */
1062 if (!mtmp
->mpeaceful
&& level
.flags
.shortsighted
1063 && nidist
> (couldsee(nix
, niy
) ? 144 : 36) && appr
== 1)
1065 if (is_unicorn(ptr
) && level
.flags
.noteleport
) {
1066 /* on noteleport levels, perhaps we cannot avoid hero */
1067 for (i
= 0; i
< cnt
; i
++)
1068 if (!(info
[i
] & NOTONL
))
1071 better_with_displacing
=
1072 should_displace(mtmp
, poss
, info
, cnt
, gx
, gy
);
1073 for (i
= 0; i
< cnt
; i
++) {
1074 if (avoid
&& (info
[i
] & NOTONL
))
1079 if (MON_AT(nx
, ny
) && (info
[i
] & ALLOW_MDISP
)
1080 && !(info
[i
] & ALLOW_M
) && !better_with_displacing
)
1083 mtrk
= &mtmp
->mtrack
[0];
1084 for (j
= 0; j
< jcnt
; mtrk
++, j
++)
1085 if (nx
== mtrk
->x
&& ny
== mtrk
->y
)
1086 if (rn2(4 * (cnt
- j
)))
1090 nearer
= ((ndist
= dist2(nx
, ny
, gx
, gy
)) < nidist
);
1092 if ((appr
== 1 && nearer
) || (appr
== -1 && !nearer
)
1093 || (!appr
&& !rn2(++chcnt
)) || !mmoved
) {
1108 if (mmoved
== 1 && (u
.ux
!= nix
|| u
.uy
!= niy
) && itsstuck(mtmp
))
1111 if (mmoved
== 1 && can_tunnel
&& needspick(ptr
)
1112 && ((IS_ROCK(levl
[nix
][niy
].typ
) && may_dig(nix
, niy
))
1113 || closed_door(nix
, niy
))) {
1114 if (closed_door(nix
, niy
)) {
1115 if (!(mw_tmp
= MON_WEP(mtmp
)) || !is_pick(mw_tmp
)
1117 mtmp
->weapon_check
= NEED_PICK_OR_AXE
;
1118 } else if (IS_TREE(levl
[nix
][niy
].typ
)) {
1119 if (!(mw_tmp
= MON_WEP(mtmp
)) || !is_axe(mw_tmp
))
1120 mtmp
->weapon_check
= NEED_AXE
;
1121 } else if (!(mw_tmp
= MON_WEP(mtmp
)) || !is_pick(mw_tmp
)) {
1122 mtmp
->weapon_check
= NEED_PICK_AXE
;
1124 if (mtmp
->weapon_check
>= NEED_PICK_AXE
&& mon_wield_item(mtmp
))
1127 /* If ALLOW_U is set, either it's trying to attack you, or it
1128 * thinks it is. In either case, attack this spot in preference to
1131 /* Actually, this whole section of code doesn't work as you'd expect.
1132 * Most attacks are handled in dochug(). It calls distfleeck(), which
1133 * among other things sets nearby if the monster is near you--and if
1134 * nearby is set, we never call m_move unless it is a special case
1135 * (confused, stun, etc.) The effect is that this ALLOW_U (and
1136 * mfndpos) has no effect for normal attacks, though it lets a
1137 * confused monster attack you by accident.
1139 if (info
[chi
] & ALLOW_U
) {
1143 if (nix
== u
.ux
&& niy
== u
.uy
) {
1148 /* The monster may attack another based on 1 of 2 conditions:
1149 * 1 - It may be confused.
1150 * 2 - It may mistake the monster for your (displaced) image.
1151 * Pets get taken care of above and shouldn't reach this code.
1152 * Conflict gets handled even farther away (movemon()).
1154 if ((info
[chi
] & ALLOW_M
) || (nix
== mtmp
->mux
&& niy
== mtmp
->muy
)) {
1155 struct monst
*mtmp2
;
1157 mtmp2
= m_at(nix
, niy
);
1159 notonhead
= mtmp2
&& (nix
!= mtmp2
->mx
|| niy
!= mtmp2
->my
);
1160 /* note: mstatus returns 0 if mtmp2 is nonexistent */
1161 mstatus
= mattackm(mtmp
, mtmp2
);
1163 if (mstatus
& MM_AGR_DIED
) /* aggressor died */
1166 if ((mstatus
& MM_HIT
) && !(mstatus
& MM_DEF_DIED
) && rn2(4)
1167 && mtmp2
->movement
>= NORMAL_SPEED
) {
1168 mtmp2
->movement
-= NORMAL_SPEED
;
1170 mstatus
= mattackm(mtmp2
, mtmp
); /* return attack */
1171 if (mstatus
& MM_DEF_DIED
)
1177 if ((info
[chi
] & ALLOW_MDISP
)) {
1178 struct monst
*mtmp2
;
1180 mtmp2
= m_at(nix
, niy
);
1181 mstatus
= mdisplacem(mtmp
, mtmp2
, FALSE
);
1182 if ((mstatus
& MM_AGR_DIED
) || (mstatus
& MM_DEF_DIED
))
1184 if (mstatus
& MM_HIT
)
1189 if (!m_in_out_region(mtmp
, nix
, niy
))
1191 remove_monster(omx
, omy
);
1192 place_monster(mtmp
, nix
, niy
);
1193 for (j
= MTSZ
- 1; j
> 0; j
--)
1194 mtmp
->mtrack
[j
] = mtmp
->mtrack
[j
- 1];
1195 mtmp
->mtrack
[0].x
= omx
;
1196 mtmp
->mtrack
[0].y
= omy
;
1197 /* Place a segment at the old position. */
1201 if (is_unicorn(ptr
) && rn2(2) && !tele_restrict(mtmp
)) {
1202 (void) rloc(mtmp
, TRUE
);
1209 if (mmoved
== 1 || mmoved
== 3) {
1210 boolean canseeit
= cansee(mtmp
->mx
, mtmp
->my
);
1213 newsym(omx
, omy
); /* update the old position */
1214 if (mintrap(mtmp
) >= 2) {
1216 newsym(mtmp
->mx
, mtmp
->my
);
1217 return 2; /* it died */
1221 /* open a door, or crash through it, if 'mtmp' can */
1222 if (IS_DOOR(levl
[mtmp
->mx
][mtmp
->my
].typ
)
1223 && !passes_walls(ptr
) /* doesn't need to open doors */
1224 && !can_tunnel
) { /* taken care of below */
1225 struct rm
*here
= &levl
[mtmp
->mx
][mtmp
->my
];
1226 boolean btrapped
= (here
->doormask
& D_TRAPPED
) != 0,
1227 observeit
= canseeit
&& canspotmon(mtmp
);
1229 if ((here
->doormask
& (D_LOCKED
| D_CLOSED
)) != 0
1232 && vamp_shift(mtmp
, &mons
[PM_FOG_CLOUD
],
1233 canspotmon(mtmp
))))) {
1234 if (flags
.verbose
&& canseemon(mtmp
))
1235 pline("%s %s under the door.", Monnam(mtmp
),
1236 (ptr
== &mons
[PM_FOG_CLOUD
]
1237 || ptr
== &mons
[PM_YELLOW_LIGHT
])
1240 } else if (here
->doormask
& D_LOCKED
&& can_unlock
) {
1242 here
->doormask
= D_NODOOR
;
1243 newsym(mtmp
->mx
, mtmp
->my
);
1244 unblock_point(mtmp
->mx
, mtmp
->my
); /* vision */
1245 if (mb_trapped(mtmp
))
1248 if (flags
.verbose
) {
1250 pline("%s unlocks and opens a door.",
1253 You_see("a door unlock and open.");
1255 You_hear("a door unlock and open.");
1257 here
->doormask
= D_ISOPEN
;
1258 /* newsym(mtmp->mx, mtmp->my); */
1259 unblock_point(mtmp
->mx
, mtmp
->my
); /* vision */
1261 } else if (here
->doormask
== D_CLOSED
&& can_open
) {
1263 here
->doormask
= D_NODOOR
;
1264 newsym(mtmp
->mx
, mtmp
->my
);
1265 unblock_point(mtmp
->mx
, mtmp
->my
); /* vision */
1266 if (mb_trapped(mtmp
))
1269 if (flags
.verbose
) {
1271 pline("%s opens a door.", Monnam(mtmp
));
1273 You_see("a door open.");
1275 You_hear("a door open.");
1277 here
->doormask
= D_ISOPEN
;
1278 /* newsym(mtmp->mx, mtmp->my); */ /* done below */
1279 unblock_point(mtmp
->mx
, mtmp
->my
); /* vision */
1281 } else if (here
->doormask
& (D_LOCKED
| D_CLOSED
)) {
1282 /* mfndpos guarantees this must be a doorbuster */
1284 here
->doormask
= D_NODOOR
;
1285 newsym(mtmp
->mx
, mtmp
->my
);
1286 unblock_point(mtmp
->mx
, mtmp
->my
); /* vision */
1287 if (mb_trapped(mtmp
))
1290 if (flags
.verbose
) {
1292 pline("%s smashes down a door.",
1295 You_see("a door crash open.");
1297 You_hear("a door crash open.");
1299 if ((here
->doormask
& D_LOCKED
) != 0 && !rn2(2))
1300 here
->doormask
= D_NODOOR
;
1302 here
->doormask
= D_BROKEN
;
1303 /* newsym(mtmp->mx, mtmp->my); */ /* done below */
1304 unblock_point(mtmp
->mx
, mtmp
->my
); /* vision */
1306 /* if it's a shop door, schedule repair */
1307 if (*in_rooms(mtmp
->mx
, mtmp
->my
, SHOPBASE
))
1308 add_damage(mtmp
->mx
, mtmp
->my
, 0L);
1310 } else if (levl
[mtmp
->mx
][mtmp
->my
].typ
== IRONBARS
) {
1311 if (may_dig(mtmp
->mx
, mtmp
->my
)
1312 && (dmgtype(ptr
, AD_RUST
) || dmgtype(ptr
, AD_CORR
))) {
1313 if (canseemon(mtmp
))
1314 pline("%s eats through the iron bars.", Monnam(mtmp
));
1315 dissolve_bars(mtmp
->mx
, mtmp
->my
);
1317 } else if (flags
.verbose
&& canseemon(mtmp
))
1318 Norep("%s %s %s the iron bars.", Monnam(mtmp
),
1319 /* pluralization fakes verb conjugation */
1320 makeplural(locomotion(ptr
, "pass")),
1321 passes_walls(ptr
) ? "through" : "between");
1325 if (can_tunnel
&& mdig_tunnel(mtmp
))
1326 return 2; /* mon died (position already updated) */
1328 /* set also in domove(), hack.c */
1329 if (u
.uswallow
&& mtmp
== u
.ustuck
1330 && (mtmp
->mx
!= omx
|| mtmp
->my
!= omy
)) {
1331 /* If the monster moved, then update */
1338 newsym(mtmp
->mx
, mtmp
->my
);
1340 if (OBJ_AT(mtmp
->mx
, mtmp
->my
) && mtmp
->mcanmove
) {
1341 /* recompute the likes tests, in case we polymorphed
1342 * or if the "likegold" case got taken above */
1344 int pctload
= (curr_mon_load(mtmp
) * 100) / max_mon_load(mtmp
);
1346 /* look for gold or jewels nearby */
1347 likegold
= (likes_gold(ptr
) && pctload
< 95);
1348 likegems
= (likes_gems(ptr
) && pctload
< 85);
1350 (!mindless(ptr
) && !is_animal(ptr
) && pctload
< 75);
1351 likeobjs
= (likes_objs(ptr
) && pctload
< 75);
1352 likemagic
= (likes_magic(ptr
) && pctload
< 85);
1353 likerock
= (throws_rocks(ptr
) && pctload
< 50 && !Sokoban
);
1354 conceals
= hides_under(ptr
);
1357 /* Maybe a rock mole just ate some metal object */
1358 if (metallivorous(ptr
)) {
1359 if (meatmetal(mtmp
) == 2)
1360 return 2; /* it died */
1363 if (g_at(mtmp
->mx
, mtmp
->my
) && likegold
)
1366 /* Maybe a cube ate just about anything */
1367 if (ptr
== &mons
[PM_GELATINOUS_CUBE
]) {
1368 if (meatobj(mtmp
) == 2)
1369 return 2; /* it died */
1372 if (!*in_rooms(mtmp
->mx
, mtmp
->my
, SHOPBASE
) || !rn2(25)) {
1373 boolean picked
= FALSE
;
1376 picked
|= mpickstuff(mtmp
, practical
);
1378 picked
|= mpickstuff(mtmp
, magical
);
1380 picked
|= mpickstuff(mtmp
, boulder_class
);
1382 picked
|= mpickstuff(mtmp
, gem_class
);
1384 picked
|= mpickstuff(mtmp
, (char *) 0);
1390 newsym(mtmp
->mx
, mtmp
->my
);
1396 if (hides_under(ptr
) || ptr
->mlet
== S_EEL
) {
1397 /* Always set--or reset--mundetected if it's already hidden
1398 (just in case the object it was hiding under went away);
1399 usually set mundetected unless monster can't move. */
1400 if (mtmp
->mundetected
1401 || (mtmp
->mcanmove
&& !mtmp
->msleeping
&& rn2(5)))
1402 (void) hideunder(mtmp
);
1403 newsym(mtmp
->mx
, mtmp
->my
);
1406 after_shk_move(mtmp
);
1416 levl
[x
][y
].typ
= (Is_special(&u
.uz
) || *in_rooms(x
, y
, 0)) ? ROOM
: CORR
;
1424 return (boolean
) (IS_DOOR(levl
[x
][y
].typ
)
1425 && (levl
[x
][y
].doormask
& (D_LOCKED
| D_CLOSED
)));
1432 int levtyp
= levl
[x
][y
].typ
;
1434 /* use underlying terrain in front of closed drawbridge */
1435 if (levtyp
== DRAWBRIDGE_UP
)
1436 levtyp
= db_under_typ(levl
[x
][y
].drawbridgemask
);
1438 return (boolean
) (ACCESSIBLE(levtyp
) && !closed_door(x
, y
));
1441 /* decide where the monster thinks you are standing */
1444 register struct monst
*mtmp
;
1446 boolean notseen
, gotu
;
1447 register int disp
, mx
= mtmp
->mux
, my
= mtmp
->muy
;
1448 long umoney
= money_cnt(invent
);
1451 * do cheapest and/or most likely tests first
1454 /* pet knows your smell; grabber still has hold of you */
1455 if (mtmp
->mtame
|| mtmp
== u
.ustuck
)
1458 /* monsters which know where you are don't suddenly forget,
1459 if you haven't moved away */
1460 if (mx
== u
.ux
&& my
== u
.uy
)
1463 notseen
= (!mtmp
->mcansee
|| (Invis
&& !perceives(mtmp
->data
)));
1464 /* add cases as required. eg. Displacement ... */
1465 if (notseen
|| Underwater
) {
1466 /* Xorns can smell quantities of valuable metal
1467 like that in solid gold coins, treat as seen */
1468 if ((mtmp
->data
== &mons
[PM_XORN
]) && umoney
&& !Underwater
)
1472 } else if (Displaced
) {
1473 disp
= couldsee(mx
, my
) ? 2 : 1;
1479 /* without something like the following, invisibility and displacement
1481 gotu
= notseen
? !rn2(3) : Displaced
? !rn2(4) : FALSE
;
1484 register int try_cnt
= 0;
1486 if (++try_cnt
> 200)
1487 goto found_you
; /* punt */
1488 mx
= u
.ux
- disp
+ rn2(2 * disp
+ 1);
1489 my
= u
.uy
- disp
+ rn2(2 * disp
+ 1);
1490 } while (!isok(mx
, my
)
1491 || (disp
!= 2 && mx
== mtmp
->mx
&& my
== mtmp
->my
)
1492 || ((mx
!= u
.ux
|| my
!= u
.uy
) && !passes_walls(mtmp
->data
)
1493 && !(accessible(mx
, my
)
1494 || (closed_door(mx
, my
)
1495 && (can_ooze(mtmp
) || can_fog(mtmp
)))))
1496 || !couldsee(mx
, my
));
1508 * mon-to-mon displacement is a deliberate "get out of my way" act,
1509 * not an accidental bump, so we don't consider mstun or mconf in
1512 * We do consider many other things about the target and its
1516 undesirable_disp(mtmp
, x
, y
)
1520 boolean is_pet
= (mtmp
&& mtmp
->mtame
&& !mtmp
->isminion
);
1521 struct trap
*trap
= t_at(x
, y
);
1524 /* Pets avoid a trap if you've seen it usually. */
1525 if (trap
&& trap
->tseen
&& rn2(40))
1527 /* Pets avoid cursed locations */
1528 if (cursed_object_at(x
, y
))
1531 /* Monsters avoid a trap if they've seen that type before */
1532 } else if (trap
&& rn2(40)
1533 && (mtmp
->mtrapseen
& (1 << (trap
->ttyp
- 1))) != 0) {
1541 * Inventory prevents passage under door.
1542 * Used by can_ooze() and can_fog().
1545 stuff_prevents_passage(mtmp
)
1548 struct obj
*chain
, *obj
;
1550 if (mtmp
== &youmonst
) {
1553 chain
= mtmp
->minvent
;
1555 for (obj
= chain
; obj
; obj
= obj
->nobj
) {
1556 int typ
= obj
->otyp
;
1558 if (typ
== COIN_CLASS
&& obj
->quan
> 100L)
1560 if (obj
->oclass
!= GEM_CLASS
&& !(typ
>= ARROW
&& typ
<= BOOMERANG
)
1561 && !(typ
>= DAGGER
&& typ
<= CRYSKNIFE
) && typ
!= SLING
1562 && !is_cloak(obj
) && typ
!= FEDORA
&& !is_gloves(obj
)
1563 && typ
!= LEATHER_JACKET
&& typ
!= CREDIT_CARD
&& !is_shirt(obj
)
1564 && !(typ
== CORPSE
&& verysmall(&mons
[obj
->corpsenm
]))
1565 && typ
!= FORTUNE_COOKIE
&& typ
!= CANDY_BAR
&& typ
!= PANCAKE
1566 && typ
!= LEMBAS_WAFER
&& typ
!= LUMP_OF_ROYAL_JELLY
1567 && obj
->oclass
!= AMULET_CLASS
&& obj
->oclass
!= RING_CLASS
1568 && obj
->oclass
!= VENOM_CLASS
&& typ
!= SACK
1569 && typ
!= BAG_OF_HOLDING
&& typ
!= BAG_OF_TRICKS
1570 && !Is_candle(obj
) && typ
!= OILSKIN_SACK
&& typ
!= LEASH
1571 && typ
!= STETHOSCOPE
&& typ
!= BLINDFOLD
&& typ
!= TOWEL
1572 && typ
!= TIN_WHISTLE
&& typ
!= MAGIC_WHISTLE
1573 && typ
!= MAGIC_MARKER
&& typ
!= TIN_OPENER
&& typ
!= SKELETON_KEY
1574 && typ
!= LOCK_PICK
)
1576 if (Is_container(obj
) && obj
->cobj
)
1586 if (!amorphous(mtmp
->data
) || stuff_prevents_passage(mtmp
))
1591 /* monster can change form into a fog if necessary */
1596 if (!(mvitals
[PM_FOG_CLOUD
].mvflags
& G_GENOD
) && is_vampshifter(mtmp
)
1597 && !Protection_from_shape_changers
&& !stuff_prevents_passage(mtmp
))
1603 vamp_shift(mon
, ptr
, domsg
)
1605 struct permonst
*ptr
;
1612 Sprintf(fmtstr
, "You %s %%s where %s was.",
1613 sensemon(mon
) ? "now detect" : "observe",
1616 if (mon
->data
== ptr
) {
1617 /* already right shape */
1620 } else if (is_vampshifter(mon
)) {
1621 reslt
= newcham(mon
, ptr
, FALSE
, FALSE
);
1623 if (reslt
&& domsg
) {
1624 pline(fmtstr
, an(m_monnam(mon
)));