NetHack->aNetHack
[aNetHack.git] / src / monmove.c
blob0b60d0c1545b2149da081172a3b9a81b12269bb4
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. */
5 #include "hack.h"
6 #include "mfndpos.h"
7 #include "artifact.h"
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 */
20 boolean
21 mb_trapped(mtmp)
22 struct monst *mtmp;
24 if (flags.verbose) {
25 if (cansee(mtmp->mx, mtmp->my) && !Unaware)
26 pline("KABOOM!! You see a door explode.");
27 else if (!Deaf)
28 You_hear("a distant explosion.");
30 wake_nearto(mtmp->mx, mtmp->my, 7 * 7);
31 mtmp->mstun = 1;
32 mtmp->mhp -= rnd(15);
33 if (mtmp->mhp <= 0) {
34 mondied(mtmp);
35 if (mtmp->mhp > 0) /* lifesaved */
36 return FALSE;
37 else
38 return TRUE;
40 return FALSE;
43 /* check whether a monster is carrying a locking/unlocking tool */
44 boolean
45 monhaskey(mon, for_unlocking)
46 struct monst *mon;
47 boolean for_unlocking; /* true => credit card ok, false => not ok */
49 if (for_unlocking && m_carrying(mon, CREDIT_CARD))
50 return TRUE;
51 return m_carrying(mon, SKELETON_KEY) || m_carrying(mon, LOCK_PICK);
54 void
55 mon_yells(mon, shout)
56 struct monst *mon;
57 const char *shout;
59 if (Deaf) {
60 if (canspotmon(mon))
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!",
65 Amonnam(mon),
66 nolimbs(mon->data) ? "shakes" : "waves",
67 mhis(mon),
68 nolimbs(mon->data) ? mbodypart(mon, HEAD)
69 : makeplural(mbodypart(mon, ARM)));
70 } else {
71 if (canspotmon(mon))
72 pline("%s yells:", Amonnam(mon));
73 else
74 You_hear("someone yell:");
75 verbalize1(shout);
79 STATIC_OVL void
80 watch_on_duty(mtmp)
81 register struct monst *mtmp;
83 int x, y;
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);
93 } else {
94 mon_yells(mtmp, "Hey, stop picking that lock!");
95 levl[x][y].looted |= D_WARNED;
97 stop_occupation();
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,
102 FALSE);
108 dochugw(mtmp)
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))
127 stop_occupation();
129 return rd;
132 boolean
133 onscary(x, y, mtmp)
134 int x, y;
135 struct monst *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))
143 return FALSE;
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)))
148 return TRUE;
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))
153 return TRUE;
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. */
164 return (epresent
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 */
175 void
176 mon_regen(mon, digest_meal)
177 struct monst *mon;
178 boolean digest_meal;
180 if (mon->mhp < mon->mhpmax && (moves % 20 == 0 || regenerates(mon->data)))
181 mon->mhp++;
182 if (mon->mspec_used)
183 mon->mspec_used--;
184 if (digest_meal) {
185 if (mon->meating) {
186 mon->meating--;
187 if (mon->meating <= 0)
188 finish_meating(mon);
194 * Possibly awaken the given monster. Return a 1 if the monster has been
195 * jolted awake.
197 STATIC_OVL int
198 disturb(mtmp)
199 register struct monst *mtmp;
202 * + Ettins are hard to surprise.
203 * + Nymphs, jabberwocks, and leprechauns do not easily wake up.
205 * Wake up if:
206 * in direct LOS AND
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]
217 #if 0 /* DEFERRED */
218 || mtmp->data == &mons[PM_VORPAL_JABBERWOCK]
219 #endif
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))) {
225 mtmp->msleeping = 0;
226 return 1;
228 return 0;
231 /* ungrab/expel held/swallowed hero */
232 STATIC_OVL void
233 release_hero(mon)
234 struct monst *mon;
236 if (mon == u.ustuck) {
237 if (u.uswallow) {
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 */
249 void
250 monflee(mtmp, fleetime, first, fleemsg)
251 struct monst *mtmp;
252 int fleetime;
253 boolean first;
254 boolean fleemsg;
256 /* shouldn't happen; maybe warrants impossible()? */
257 if (DEADMONSTER(mtmp))
258 return;
260 if (mtmp == u.ustuck)
261 release_hero(mtmp); /* expels/unstuck */
263 if (!first || !mtmp->mflee) {
264 /* don't lose untimed scare */
265 if (!fleetime)
266 mtmp->mfleetim = 0;
267 else if (!mtmp->mflee || mtmp->mfleetim) {
268 fleetime += (int) mtmp->mfleetim;
269 /* ensure monster flees long enough to visibly stop fighting */
270 if (fleetime == 1)
271 fleetime++;
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"));
282 else
283 pline("%s turns to flee.", Monnam(mtmp));
285 mtmp->mflee = 1;
287 /* ignore recently-stepped spaces when made to flee */
288 memset(mtmp->mtrack, 0, sizeof(mtmp->mtrack));
291 STATIC_OVL void
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;
313 } else {
314 seescaryx = u.ux;
315 seescaryy = u.uy;
318 sawscary = onscary(seescaryx, seescaryy, mtmp);
319 if (*nearby && (sawscary
320 || (!mtmp->mpeaceful && in_your_sanctuary(mtmp, 0, 0)))) {
321 *scared = 1;
322 monflee(mtmp, rnd(rn2(7) ? 10 : 100), TRUE, TRUE);
323 } else
324 *scared = 0;
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 */
329 STATIC_OVL int
330 m_arrival(mon)
331 struct monst *mon;
333 mon->mstrategy &= ~STRAT_ARRIVE; /* always reset */
335 return -1;
338 /* returns 1 if monster died moving, 0 otherwise */
339 /* The whole dochugw/m_move/distfleeck/mfndpos section is serious spaghetti
340 * code. --KAA
343 dochug(mtmp)
344 register struct monst *mtmp;
346 register struct permonst *mdat;
347 register int tmp = 0;
348 int inrange, nearby, scared;
350 /* Pre-movement adjustments
353 mdat = mtmp->data;
355 if (mtmp->mstrategy & STRAT_ARRIVE) {
356 int res = m_arrival(mtmp);
357 if (res >= 0)
358 return res;
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)) {
370 if (Hallucination)
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)) {
380 if (Hallucination)
381 newsym(mtmp->mx, mtmp->my);
382 return 0;
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))
390 mtmp->mconf = 0;
392 /* stunned monsters get un-stunned with larger probability */
393 if (mtmp->mstun && !rn2(10))
394 mtmp->mstun = 0;
396 /* some monsters teleport */
397 if (mtmp->mflee && !rn2(40) && can_teleport(mdat) && !mtmp->iswiz
398 && !level.flags.noteleport) {
399 (void) rloc(mtmp, TRUE);
400 return 0;
402 if (mdat->msound == MS_SHRIEK && !um_dist(mtmp->mx, mtmp->my, 1))
403 m_respond(mtmp);
404 if (mdat == &mons[PM_MEDUSA] && couldsee(mtmp->mx, mtmp->my))
405 m_respond(mtmp);
406 if (mtmp->mhp <= 0)
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
411 && !rn2(25))
412 mtmp->mflee = 0;
414 /* cease conflict-induced swallow/grab if conflict has ended */
415 if (mtmp == u.ustuck && mtmp->mpeaceful && !mtmp->mconf && !Conflict) {
416 release_hero(mtmp);
417 return 0; /* uses up monster's turn */
420 set_apparxy(mtmp);
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)
436 return 1;
437 } else if (find_misc(mtmp)) {
438 if (use_misc(mtmp) != 0)
439 return 1;
442 /* Demonic Blackmail! */
443 if (nearby && mdat->msound == MS_BRIBE && mtmp->mpeaceful && !mtmp->mtame
444 && !u.uswallow) {
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);
453 } else {
454 mtmp->minvis = mtmp->perminvis = 0;
455 /* Why? For the same reason in real demon talk */
456 pline("%s gets angry!", Amonnam(mtmp));
457 mtmp->mpeaceful = 0;
458 set_malign(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)) {
467 watch_on_duty(mtmp);
469 } else if (is_mind_flayer(mdat) && !rn2(20)) {
470 struct monst *m2, *nmon = (struct monst *) 0;
472 if (canseemon(mtmp))
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.");
476 goto toofar;
478 pline("A wave of psychic energy pours over you!");
479 if (mtmp->mpeaceful
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)) {
486 int dmg;
487 pline("It locks on to your %s!",
488 m_sen ? "telepathy" : Blind_telepat ? "latent telepathy"
489 : "mind");
490 dmg = rnd(15);
491 if (Half_spell_damage)
492 dmg = (dmg + 1) / 2;
493 losehp(dmg, "psychic blast", KILLED_BY_AN);
496 for (m2 = fmon; m2; m2 = nmon) {
497 nmon = m2->nmon;
498 if (DEADMONSTER(m2))
499 continue;
500 if (m2->mpeaceful == mtmp->mpeaceful)
501 continue;
502 if (mindless(m2->data))
503 continue;
504 if (m2 == mtmp)
505 continue;
506 if ((telepathic(m2->data) && (rn2(2) || m2->mblinded))
507 || !rn2(10)) {
508 if (cansee(m2->mx, m2->my))
509 pline("It locks on to %s.", mon_nam(m2));
510 m2->mhp -= rnd(15);
511 if (m2->mhp <= 0)
512 monkilled(m2, "", AD_DRIN);
513 else
514 m2->msleeping = 0;
518 toofar:
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)) {
526 struct obj *mw_tmp;
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)
541 return 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) {
562 struct attack *a;
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)) {
568 tmp = 3;
569 break;
575 tmp = m_move(mtmp, 0);
576 if (tmp != 2)
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.
588 if (Hallucination)
589 newsym(mtmp->mx, mtmp->my);
590 break;
591 case 1: /* monster moved */
592 /* Maybe it stepped on a trap and fell asleep... */
593 if (mtmp->msleeping || !mtmp->mcanmove)
594 return 0;
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)))
598 break;
599 /* engulfer/grabber checks */
600 if (mtmp == u.ustuck) {
601 /* a monster that's digesting you can move at the
602 * same time -dlc
604 if (u.uswallow)
605 return mattacku(mtmp);
606 /* if confused grabber has wandered off, let go */
607 if (distu(mtmp->mx, mtmp->my) > 2)
608 unstuck(mtmp);
610 return 0;
611 case 2: /* monster died */
612 return 1;
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)
621 if (mattacku(mtmp))
622 return 1; /* monster died (e.g. exploded) */
624 if (mtmp->wormno)
625 wormhitu(mtmp);
627 /* special speeches for quest monsters */
628 if (!mtmp->msleeping && mtmp->mcanmove && nearby)
629 quest_talk(mtmp);
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))
633 cuss(mtmp);
635 return (tmp == 2);
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 };
647 boolean
648 itsstuck(mtmp)
649 register struct monst *mtmp;
651 if (sticks(youmonst.data) && mtmp == u.ustuck && !u.uswallow) {
652 pline("%s cannot escape from you!", Monnam(mtmp));
653 return TRUE;
655 return FALSE;
659 * should_displace()
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.
665 boolean
666 should_displace(mtmp, poss, info, cnt, gx, gy)
667 struct monst *mtmp;
668 coord *poss; /* coord poss[9] */
669 long *info; /* long info[9] */
670 int cnt;
671 xchar gx, gy;
673 int shortest_with_displacing = -1;
674 int shortest_without_displacing = -1;
675 int count_without_displacing = 0;
676 register int i, nx, ny;
677 int ndist;
679 for (i = 0; i < cnt; i++) {
680 nx = poss[i].x;
681 ny = poss[i].y;
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;
688 } else {
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))
698 return TRUE;
699 return FALSE;
702 boolean
703 m_digweapon_check(mtmp, nix, niy)
704 struct monst *mtmp;
705 xchar nix,niy;
707 boolean can_tunnel = 0;
708 struct obj *mw_tmp;
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))
719 || !is_pick(mw_tmp)
720 || !is_axe(mw_tmp))
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))
729 return TRUE;
731 return FALSE;
734 /* Return values:
735 * 0: did not move, but can still attack and do other stuff.
736 * 1: moved, possibly can attack.
737 * 2: monster died.
738 * 3: did not move, and can't do anything else either.
741 m_move(mtmp, after)
742 register struct monst *mtmp;
743 register int after;
745 register int appr;
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,
749 conceals = 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;
756 struct monst *mtoo;
757 schar mmoved = 0; /* not strictly nec.: chi >= 0 will do */
758 long info[9];
759 long flag;
760 int omx = mtmp->mx, omy = mtmp->my;
762 if (mtmp->mtrapped) {
763 int i = mintrap(mtmp);
765 if (i >= 2) {
766 newsym(mtmp->mx, mtmp->my);
767 return 2;
768 } /* it died */
769 if (i == 1)
770 return 0; /* still in trap, so didn't move */
772 ptr = mtmp->data; /* mintrap() can change mtmp->data -dlc */
774 if (mtmp->meating) {
775 mtmp->meating--;
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 */
783 set_apparxy(mtmp);
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));
791 can_unlock =
792 ((can_open && monhaskey(mtmp, TRUE)) || mtmp->iswiz || is_rider(ptr));
793 doorbuster = is_giant(ptr);
794 if (mtmp->wormno)
795 goto not_special;
796 /* my dog gets special treatment */
797 if (mtmp->mtame) {
798 mmoved = dog_move(mtmp, after);
799 goto postmov;
802 /* likewise for shopkeeper */
803 if (mtmp->isshk) {
804 mmoved = shk_move(mtmp);
805 if (mmoved == -2)
806 return 2;
807 if (mmoved >= 0)
808 goto postmov;
809 mmoved = 0; /* follow player outside shop */
812 /* and for the guard */
813 if (mtmp->isgd) {
814 mmoved = gd_move(mtmp);
815 if (mmoved == -2)
816 return 2;
817 if (mmoved >= 0)
818 goto postmov;
819 mmoved = 0;
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,
829 * attack 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)
835 return 2;
836 mmoved = 1;
837 } else
838 mmoved = 0;
839 goto postmov;
842 /* and for the priest */
843 if (mtmp->ispriest) {
844 mmoved = pri_move(mtmp);
845 if (mmoved == -2)
846 return 2;
847 if (mmoved >= 0)
848 goto postmov;
849 mmoved = 0;
852 #ifdef MAIL
853 if (ptr == &mons[PM_MAIL_DAEMON]) {
854 if (!Deaf && canseemon(mtmp))
855 verbalize("I'm late!");
856 mongone(mtmp);
857 return 2;
859 #endif
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);
866 else
867 mnexto(mtmp);
868 mmoved = 1;
869 goto postmov;
871 not_special:
872 if (u.uswallow && !mtmp->mflee && u.ustuck != mtmp)
873 return 1;
874 omx = mtmp->mx;
875 omy = mtmp->my;
876 gx = mtmp->mux;
877 gy = mtmp->muy;
878 appr = mtmp->mflee ? -1 : 1;
879 if (mtmp->mconf || (u.uswallow && mtmp == u.ustuck)) {
880 appr = 0;
881 } else {
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));
887 if (!mtmp->mcansee
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)))
894 appr = 0;
896 if (monsndx(ptr) == PM_LEPRECHAUN && (appr == 1)
897 && ((lepgold = findgold(mtmp->minvent))
898 && (lepgold->quan
899 > ((ygold = findgold(invent)) ? ygold->quan : 0L))))
900 appr = -1;
902 if (!should_see && can_track(ptr)) {
903 register coord *cp;
905 cp = gettrack(omx, omy);
906 if (cp) {
907 gx = cp->x;
908 gy = cp->y;
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);
934 setlikes = TRUE;
938 #define SQSRCHRADIUS 5
941 register int minr = SQSRCHRADIUS; /* not too far away */
942 register struct obj *otmp;
943 register int xx, yy;
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
948 && !mtmp->mpeaceful)
949 minr--;
950 /* guards shouldn't get too distracted */
951 if (!mtmp->mpeaceful && is_mercenary(ptr))
952 minr = 1;
954 if ((likegold || likegems || likeobjs || likemagic || likerock
955 || conceals) && (!*in_rooms(omx, omy, SHOPBASE)
956 || (!rn2(25) && !mtmp->isshk))) {
957 look_for_obj:
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)
967 continue;
968 xx = otmp->ox;
969 yy = otmp->oy;
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))
983 continue;
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)))
990 continue;
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);
1019 gx = otmp->ox;
1020 gy = otmp->oy;
1021 if (gx == omx && gy == omy) {
1022 mmoved = 3; /* actually unnecessary */
1023 goto postmov;
1029 } else if (likegold) {
1030 /* don't try to pick up anything else, but use the same loop */
1031 uses_items = 0;
1032 likegems = likeobjs = likemagic = likerock = conceals = 0;
1033 goto look_for_obj;
1036 if (minr < SQSRCHRADIUS && appr == -1) {
1037 if (distmin(omx, omy, mtmp->mux, mtmp->muy) <= 3) {
1038 gx = mtmp->mux;
1039 gy = mtmp->muy;
1040 } else
1041 appr = 1;
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))
1049 can_tunnel = FALSE;
1051 nix = omx;
1052 niy = omy;
1053 flag = 0L;
1054 if (mtmp->mpeaceful && (!Conflict || resist(mtmp, RING_CLASS, 0, 0)))
1055 flag |= (ALLOW_SANCT | ALLOW_SSM);
1056 else
1057 flag |= ALLOW_U;
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)
1062 flag |= NOTONL;
1063 if (passes_walls(ptr))
1064 flag |= (ALLOW_WALL | ALLOW_ROCK);
1065 if (passes_bars(ptr))
1066 flag |= ALLOW_BARS;
1067 if (can_tunnel)
1068 flag |= ALLOW_DIG;
1069 if (is_human(ptr) || ptr == &mons[PM_MINOTAUR])
1070 flag |= ALLOW_SSM;
1071 if ((is_undead(ptr) && ptr->mlet != S_GHOST) || is_vampshifter(mtmp))
1072 flag |= NOGARLIC;
1073 if (throws_rocks(ptr))
1074 flag |= ALLOW_ROCK;
1075 if (can_open)
1076 flag |= OPENDOOR;
1077 if (can_unlock)
1078 flag |= UNLOCKDOOR;
1079 if (doorbuster)
1080 flag |= BUSTDOOR;
1082 register int i, j, nx, ny, nearer;
1083 int jcnt, cnt;
1084 int ndist, nidist;
1085 register coord *mtrk;
1086 coord poss[9];
1088 cnt = mfndpos(mtmp, poss, info, flag);
1089 chcnt = 0;
1090 jcnt = min(MTSZ, cnt - 1);
1091 chi = -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)
1096 appr = 0;
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))
1101 avoid = TRUE;
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))
1107 continue;
1108 nx = poss[i].x;
1109 ny = poss[i].y;
1111 if (MON_AT(nx, ny) && (info[i] & ALLOW_MDISP)
1112 && !(info[i] & ALLOW_M) && !better_with_displacing)
1113 continue;
1114 if (appr != 0) {
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)))
1119 goto nxti;
1122 nearer = ((ndist = dist2(nx, ny, gx, gy)) < nidist);
1124 if ((appr == 1 && nearer) || (appr == -1 && !nearer)
1125 || (!appr && !rn2(++chcnt)) || !mmoved) {
1126 nix = nx;
1127 niy = ny;
1128 nidist = ndist;
1129 chi = i;
1130 mmoved = 1;
1132 nxti:
1137 if (mmoved) {
1138 register int j;
1140 if (mmoved == 1 && (u.ux != nix || u.uy != niy) && itsstuck(mtmp))
1141 return 3;
1143 if (mmoved == 1 && m_digweapon_check(mtmp, nix,niy))
1144 return 3;
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
1148 * all others.
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) {
1159 nix = mtmp->mux;
1160 niy = mtmp->muy;
1162 if (nix == u.ux && niy == u.uy) {
1163 mtmp->mux = u.ux;
1164 mtmp->muy = u.uy;
1165 return 0;
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;
1175 int mstatus;
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 */
1183 return 2;
1185 if ((mstatus & MM_HIT) && !(mstatus & MM_DEF_DIED) && rn2(4)
1186 && mtmp2->movement >= NORMAL_SPEED) {
1187 mtmp2->movement -= NORMAL_SPEED;
1188 notonhead = 0;
1189 mstatus = mattackm(mtmp2, mtmp); /* return attack */
1190 if (mstatus & MM_DEF_DIED)
1191 return 2;
1193 return 3;
1196 if ((info[chi] & ALLOW_MDISP)) {
1197 struct monst *mtmp2;
1198 int mstatus;
1199 mtmp2 = m_at(nix, niy);
1200 mstatus = mdisplacem(mtmp, mtmp2, FALSE);
1201 if ((mstatus & MM_AGR_DIED) || (mstatus & MM_DEF_DIED))
1202 return 2;
1203 if (mstatus & MM_HIT)
1204 return 1;
1205 return 3;
1208 if (!m_in_out_region(mtmp, nix, niy))
1209 return 3;
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. */
1217 if (mtmp->wormno)
1218 worm_move(mtmp);
1219 } else {
1220 if (is_unicorn(ptr) && rn2(2) && !tele_restrict(mtmp)) {
1221 (void) rloc(mtmp, TRUE);
1222 return 1;
1224 if (mtmp->wormno)
1225 worm_nomove(mtmp);
1227 postmov:
1228 if (mmoved == 1 || mmoved == 3) {
1229 boolean canseeit = cansee(mtmp->mx, mtmp->my);
1231 if (mmoved == 1) {
1232 newsym(omx, omy); /* update the old position */
1233 if (mintrap(mtmp) >= 2) {
1234 if (mtmp->mx)
1235 newsym(mtmp->mx, mtmp->my);
1236 return 2; /* it died */
1238 ptr = mtmp->data;
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
1249 && (amorphous(ptr)
1250 || (can_fog(mtmp)
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])
1257 ? "flows"
1258 : "oozes");
1259 } else if (here->doormask & D_LOCKED && can_unlock) {
1260 if (btrapped) {
1261 here->doormask = D_NODOOR;
1262 newsym(mtmp->mx, mtmp->my);
1263 unblock_point(mtmp->mx, mtmp->my); /* vision */
1264 if (mb_trapped(mtmp))
1265 return 2;
1266 } else {
1267 if (flags.verbose) {
1268 if (observeit)
1269 pline("%s unlocks and opens a door.",
1270 Monnam(mtmp));
1271 else if (canseeit)
1272 You_see("a door unlock and open.");
1273 else if (!Deaf)
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) {
1281 if (btrapped) {
1282 here->doormask = D_NODOOR;
1283 newsym(mtmp->mx, mtmp->my);
1284 unblock_point(mtmp->mx, mtmp->my); /* vision */
1285 if (mb_trapped(mtmp))
1286 return 2;
1287 } else {
1288 if (flags.verbose) {
1289 if (observeit)
1290 pline("%s opens a door.", Monnam(mtmp));
1291 else if (canseeit)
1292 You_see("a door open.");
1293 else if (!Deaf)
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 */
1302 if (btrapped) {
1303 here->doormask = D_NODOOR;
1304 newsym(mtmp->mx, mtmp->my);
1305 unblock_point(mtmp->mx, mtmp->my); /* vision */
1306 if (mb_trapped(mtmp))
1307 return 2;
1308 } else {
1309 if (flags.verbose) {
1310 if (observeit)
1311 pline("%s smashes down a door.",
1312 Monnam(mtmp));
1313 else if (canseeit)
1314 You_see("a door crash open.");
1315 else if (!Deaf)
1316 You_hear("a door crash open.");
1318 if ((here->doormask & D_LOCKED) != 0 && !rn2(2))
1319 here->doormask = D_NODOOR;
1320 else
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);
1335 return 3;
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");
1343 /* possibly dig */
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 */
1351 u.ux0 = u.ux;
1352 u.uy0 = u.uy;
1353 u.ux = mtmp->mx;
1354 u.uy = mtmp->my;
1355 swallowed(0);
1356 } else
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 */
1362 if (setlikes) {
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);
1368 uses_items =
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)
1383 mpickgold(mtmp);
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;
1394 if (likeobjs)
1395 picked |= mpickstuff(mtmp, practical);
1396 if (likemagic)
1397 picked |= mpickstuff(mtmp, magical);
1398 if (likerock)
1399 picked |= mpickstuff(mtmp, boulder_class);
1400 if (likegems)
1401 picked |= mpickstuff(mtmp, gem_class);
1402 if (uses_items)
1403 picked |= mpickstuff(mtmp, (char *) 0);
1404 if (picked)
1405 mmoved = 3;
1408 if (mtmp->minvis) {
1409 newsym(mtmp->mx, mtmp->my);
1410 if (mtmp->wormno)
1411 see_wsegs(mtmp);
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);
1424 if (mtmp->isshk) {
1425 after_shk_move(mtmp);
1428 return mmoved;
1431 void
1432 dissolve_bars(x, y)
1433 register int x, y;
1435 levl[x][y].typ = (Is_special(&u.uz) || *in_rooms(x, y, 0)) ? ROOM : CORR;
1436 newsym(x, y);
1439 boolean
1440 closed_door(x, y)
1441 register int x, y;
1443 return (boolean) (IS_DOOR(levl[x][y].typ)
1444 && (levl[x][y].doormask & (D_LOCKED | D_CLOSED)));
1447 boolean
1448 accessible(x, y)
1449 register int x, y;
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 */
1461 void
1462 set_apparxy(mtmp)
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)
1475 goto found_you;
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)
1480 goto found_you;
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)
1488 disp = 0;
1489 else
1490 disp = 1;
1491 } else if (Displaced) {
1492 disp = couldsee(mx, my) ? 2 : 1;
1493 } else
1494 disp = 0;
1495 if (!disp)
1496 goto found_you;
1498 /* without something like the following, invisibility and displacement
1499 are too powerful */
1500 gotu = notseen ? !rn2(3) : Displaced ? !rn2(4) : FALSE;
1502 if (!gotu) {
1503 register int try_cnt = 0;
1504 do {
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));
1516 } else {
1517 found_you:
1518 mx = u.ux;
1519 my = u.uy;
1522 mtmp->mux = mx;
1523 mtmp->muy = 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
1529 * undesired_disp().
1531 * We do consider many other things about the target and its
1532 * location however.
1534 boolean
1535 undesirable_disp(mtmp, x, y)
1536 struct monst *mtmp;
1537 xchar x, y;
1539 boolean is_pet = (mtmp && mtmp->mtame && !mtmp->isminion);
1540 struct trap *trap = t_at(x, y);
1542 if (is_pet) {
1543 /* Pets avoid a trap if you've seen it usually. */
1544 if (trap && trap->tseen && rn2(40))
1545 return TRUE;
1546 /* Pets avoid cursed locations */
1547 if (cursed_object_at(x, y))
1548 return TRUE;
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) {
1553 return TRUE;
1556 return FALSE;
1560 * Inventory prevents passage under door.
1561 * Used by can_ooze() and can_fog().
1563 STATIC_OVL boolean
1564 stuff_prevents_passage(mtmp)
1565 struct monst *mtmp;
1567 struct obj *chain, *obj;
1569 if (mtmp == &youmonst) {
1570 chain = invent;
1571 } else {
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)
1578 return TRUE;
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)
1594 return TRUE;
1595 if (Is_container(obj) && obj->cobj)
1596 return TRUE;
1598 return FALSE;
1601 boolean
1602 can_ooze(mtmp)
1603 struct monst *mtmp;
1605 if (!amorphous(mtmp->data) || stuff_prevents_passage(mtmp))
1606 return FALSE;
1607 return TRUE;
1610 /* monster can change form into a fog if necessary */
1611 boolean
1612 can_fog(mtmp)
1613 struct monst *mtmp;
1615 if (!(mvitals[PM_FOG_CLOUD].mvflags & G_GENOD) && is_vampshifter(mtmp)
1616 && !Protection_from_shape_changers && !stuff_prevents_passage(mtmp))
1617 return TRUE;
1618 return FALSE;
1621 STATIC_OVL int
1622 vamp_shift(mon, ptr, domsg)
1623 struct monst *mon;
1624 struct permonst *ptr;
1625 boolean domsg;
1627 int reslt = 0;
1628 char fmtstr[BUFSZ];
1630 if (domsg) {
1631 Sprintf(fmtstr, "You %s %%s where %s was.",
1632 sensemon(mon) ? "now detect" : "observe",
1633 an(m_monnam(mon)));
1635 if (mon->data == ptr) {
1636 /* already right shape */
1637 reslt = 1;
1638 domsg = FALSE;
1639 } else if (is_vampshifter(mon)) {
1640 reslt = newcham(mon, ptr, FALSE, FALSE);
1642 if (reslt && domsg) {
1643 pline(fmtstr, an(m_monnam(mon)));
1645 return reslt;
1648 /*monmove.c*/