1 /* SCCS Id: @(#)monmove.c 3.4 2002/04/06 */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
10 extern boolean notonhead;
14 STATIC_DCL int FDECL(disturb,(struct monst *));
15 STATIC_DCL void FDECL(distfleeck,(struct monst *,int *,int *,int *));
16 STATIC_DCL int FDECL(m_arrival, (struct monst *));
17 STATIC_DCL void FDECL(watch_on_duty,(struct monst *));
22 boolean /* TRUE : mtmp died */
24 register struct monst *mtmp;
27 if (cansee(mtmp->mx, mtmp->my))
28 pline("KABOOM!! You see a door explode.");
29 else if (flags.soundok)
30 You_hear("a distant explosion.");
32 wake_nearto(mtmp->mx, mtmp->my, 7*7);
37 if (mtmp->mhp > 0) /* lifesaved */
50 register struct monst *mtmp;
54 if(mtmp->mpeaceful && in_town(u.ux+u.dx, u.uy+u.dy) &&
55 mtmp->mcansee && m_canseeu(mtmp) && !rn2(3)) {
57 if(picking_lock(&x, &y) && IS_DOOR(levl[x][y].typ) &&
58 (levl[x][y].doormask & D_LOCKED)) {
60 if(couldsee(mtmp->mx, mtmp->my)) {
62 pline("%s yells:", Amonnam(mtmp));
63 if(levl[x][y].looted & D_WARNED) {
64 verbalize("Halt, thief! You're under arrest!");
65 (void) angry_guards(!(flags.soundok));
67 verbalize("Hey, stop picking that lock!");
68 levl[x][y].looted |= D_WARNED;
72 } else if (is_digging()) {
73 /* chewing, wand/spell of digging are checked elsewhere */
74 watch_dig(mtmp, digging.pos.x, digging.pos.y, FALSE);
84 register struct monst *mtmp;
86 register int x = mtmp->mx, y = mtmp->my;
87 boolean already_saw_mon = !occupation ? 0 : canspotmon(mtmp);
88 int rd = dochug(mtmp);
90 /* part of the original warning code which was replaced in 3.3.1 */
93 if(Warning && !rd && !mtmp->mpeaceful &&
94 (dd = distu(mtmp->mx,mtmp->my)) < distu(x,y) &&
95 dd < 100 && !canseemon(mtmp)) {
96 /* Note: this assumes we only want to warn against the monster to
97 * which the weapon does extra damage, as there is no "monster
98 * which the weapon warns against" field.
100 if (spec_ability(uwep, SPFX_WARN) && spec_dbon(uwep, mtmp, 1))
102 else if ((int) (mtmp->m_lev / 4) > warnlevel)
103 warnlevel = (mtmp->m_lev / 4);
107 /* a similar check is in monster_nearby() in hack.c */
108 /* check whether hero notices monster and stops current activity */
109 if (occupation && !rd && !Confusion &&
110 (!mtmp->mpeaceful || Hallucination) &&
111 /* it's close enough to be a threat */
112 distu(mtmp->mx,mtmp->my) <= (BOLT_LIM+1)*(BOLT_LIM+1) &&
113 /* and either couldn't see it before, or it was too far away */
114 (!already_saw_mon || !couldsee(x,y) ||
115 distu(x,y) > (BOLT_LIM+1)*(BOLT_LIM+1)) &&
116 /* can see it now, or sense it and would normally see it */
118 (sensemon(mtmp) && couldsee(mtmp->mx,mtmp->my))) &&
120 !noattacks(mtmp->data) && !onscary(u.ux, u.uy, mtmp))
134 if (mtmp->isshk || mtmp->isgd || mtmp->iswiz || !mtmp->mcansee ||
135 mtmp->mpeaceful || mtmp->data->mlet == S_HUMAN ||
136 is_lminion(mtmp) || mtmp->data == &mons[PM_ANGEL] ||
137 is_rider(mtmp->data) || mtmp->data == &mons[PM_MINOTAUR])
140 return (boolean)(sobj_at(SCR_SCARE_MONSTER, x, y)
142 || sengr_at("Elbereth", x, y)
144 || (mtmp->data->mlet == S_VAMPIRE
145 && IS_ALTAR(levl[x][y].typ)));
151 /* regenerate lost hit points */
153 mon_regen(mon, digest_meal)
157 if (mon->mhp < mon->mhpmax &&
158 (moves % 20 == 0 || regenerates(mon->data))) mon->mhp++;
159 if (mon->mspec_used) mon->mspec_used--;
161 if (mon->meating) mon->meating--;
166 * Possibly awaken the given monster. Return a 1 if the monster has been
171 register struct monst *mtmp;
174 * + Ettins are hard to surprise.
175 * + Nymphs, jabberwocks, and leprechauns do not easily wake up.
179 * within 10 squares AND
180 * not stealthy or (mon is an ettin and 9/10) AND
181 * (mon is not a nymph, jabberwock, or leprechaun) or 1/50 AND
182 * Aggravate or mon is (dog or human) or
183 * (1/7 and mon is not mimicing furniture or object)
185 if(couldsee(mtmp->mx,mtmp->my) &&
186 distu(mtmp->mx,mtmp->my) <= 100 &&
187 (!Stealth || (mtmp->data == &mons[PM_ETTIN] && rn2(10))) &&
188 (!(mtmp->data->mlet == S_NYMPH
189 || mtmp->data == &mons[PM_JABBERWOCK]
191 || mtmp->data == &mons[PM_VORPAL_JABBERWOCK]
193 || mtmp->data->mlet == S_LEPRECHAUN) || !rn2(50)) &&
195 || (mtmp->data->mlet == S_DOG ||
196 mtmp->data->mlet == S_HUMAN)
197 || (!rn2(7) && mtmp->m_ap_type != M_AP_FURNITURE &&
198 mtmp->m_ap_type != M_AP_OBJECT) )) {
205 /* monster begins fleeing for the specified time, 0 means untimed flee
206 * if first, only adds fleetime if monster isn't already fleeing
207 * if fleemsg, prints a message about new flight, otherwise, caller should */
209 monflee(mtmp, fleetime, first, fleemsg)
215 if (u.ustuck == mtmp) {
217 expels(mtmp, mtmp->data, TRUE);
218 else if (!sticks(youmonst.data)) {
219 unstuck(mtmp); /* monster lets go when fleeing */
220 You("get released!");
224 if (!first || !mtmp->mflee) {
225 /* don't lose untimed scare */
228 else if (!mtmp->mflee || mtmp->mfleetim) {
229 fleetime += mtmp->mfleetim;
230 /* ensure monster flees long enough to visibly stop fighting */
231 if (fleetime == 1) fleetime++;
232 mtmp->mfleetim = min(fleetime, 127);
234 if (!mtmp->mflee && fleemsg && canseemon(mtmp) && !mtmp->mfrozen)
235 pline("%s turns to flee!", (Monnam(mtmp)));
241 distfleeck(mtmp,inrange,nearby,scared)
242 register struct monst *mtmp;
243 int *inrange, *nearby, *scared;
245 int seescaryx, seescaryy;
247 *inrange = (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <=
248 (BOLT_LIM * BOLT_LIM));
249 *nearby = *inrange && monnear(mtmp, mtmp->mux, mtmp->muy);
251 /* Note: if your image is displaced, the monster sees the Elbereth
252 * at your displaced position, thus never attacking your displaced
253 * position, but possibly attacking you by accident. If you are
254 * invisible, it sees the Elbereth at your real position, thus never
255 * running into you by accident but possibly attacking the spot
256 * where it guesses you are.
258 if (!mtmp->mcansee || (Invis && !perceives(mtmp->data))) {
259 seescaryx = mtmp->mux;
260 seescaryy = mtmp->muy;
265 *scared = (*nearby && (onscary(seescaryx, seescaryy, mtmp) ||
267 in_your_sanctuary(mtmp, 0, 0))));
271 monflee(mtmp, rnd(10), TRUE, TRUE);
273 monflee(mtmp, rnd(100), TRUE, TRUE);
278 /* perform a special one-time action for a monster; returns -1 if nothing
279 special happened, 0 if monster uses up its turn, 1 if monster is killed */
284 mon->mstrategy &= ~STRAT_ARRIVE; /* always reset */
289 /* returns 1 if monster died moving, 0 otherwise */
290 /* The whole dochugw/m_move/distfleeck/mfndpos section is serious spaghetti
295 register struct monst *mtmp;
297 register struct permonst *mdat;
299 int inrange, nearby, scared;
301 struct obj *ygold = 0, *lepgold = 0;
304 /* Pre-movement adjustments */
308 if (mtmp->mstrategy & STRAT_ARRIVE) {
309 int res = m_arrival(mtmp);
310 if (res >= 0) return res;
313 /* check for waitmask status change */
314 if ((mtmp->mstrategy & STRAT_WAITFORU) &&
315 (m_canseeu(mtmp) || mtmp->mhp < mtmp->mhpmax))
316 mtmp->mstrategy &= ~STRAT_WAITFORU;
318 /* update quest status flags */
319 quest_stat_check(mtmp);
321 if (!mtmp->mcanmove || (mtmp->mstrategy & STRAT_WAITMASK)) {
322 if (Hallucination) newsym(mtmp->mx,mtmp->my);
323 if (mtmp->mcanmove && (mtmp->mstrategy & STRAT_CLOSE) &&
324 !mtmp->msleeping && monnear(mtmp, u.ux, u.uy))
325 quest_talk(mtmp); /* give the leaders a chance to speak */
326 return(0); /* other frozen monsters can't do anything */
329 /* there is a chance we will wake it */
330 if (mtmp->msleeping && !disturb(mtmp)) {
331 if (Hallucination) newsym(mtmp->mx,mtmp->my);
335 /* not frozen or sleeping: wipe out texts written in the dust */
336 wipe_engr_at(mtmp->mx, mtmp->my, 1);
338 /* confused monsters get unconfused with small probability */
339 if (mtmp->mconf && !rn2(50)) mtmp->mconf = 0;
341 /* stunned monsters get un-stunned with larger probability */
342 if (mtmp->mstun && !rn2(10)) mtmp->mstun = 0;
344 /* some monsters teleport */
345 if (mtmp->mflee && !rn2(40) && can_teleport(mdat) && !mtmp->iswiz &&
346 !level.flags.noteleport) {
347 (void) rloc(mtmp, FALSE);
350 if (mdat->msound == MS_SHRIEK && !um_dist(mtmp->mx, mtmp->my, 1))
352 if (mdat == &mons[PM_MEDUSA] && couldsee(mtmp->mx, mtmp->my))
354 if (mtmp->mhp <= 0) return(1); /* m_respond gaze can kill medusa */
356 /* fleeing monsters might regain courage */
357 if (mtmp->mflee && !mtmp->mfleetim
358 && mtmp->mhp == mtmp->mhpmax && !rn2(25)) mtmp->mflee = 0;
361 /* Must be done after you move and before the monster does. The
362 * set_apparxy() call in m_move() doesn't suffice since the variables
363 * inrange, etc. all depend on stuff set by set_apparxy().
366 /* Monsters that want to acquire things */
367 /* may teleport, so do it before inrange is set */
368 if(is_covetous(mdat)) (void) tactics(mtmp);
370 /* check distance and scariness of attacks */
371 distfleeck(mtmp,&inrange,&nearby,&scared);
373 if(find_defensive(mtmp)) {
374 if (use_defensive(mtmp) != 0)
376 } else if(find_misc(mtmp)) {
377 if (use_misc(mtmp) != 0)
381 /* Demonic Blackmail! */
382 if(nearby && mdat->msound == MS_BRIBE &&
383 mtmp->mpeaceful && !mtmp->mtame && !u.uswallow) {
384 if (mtmp->mux != u.ux || mtmp->muy != u.uy) {
385 pline("%s whispers at thin air.",
386 cansee(mtmp->mux, mtmp->muy) ? Monnam(mtmp) : "It");
388 if (is_demon(youmonst.data)) {
389 /* "Good hunting, brother" */
390 if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
392 mtmp->minvis = mtmp->perminvis = 0;
393 /* Why? For the same reason in real demon talk */
394 pline("%s gets angry!", Amonnam(mtmp));
396 /* since no way is an image going to pay it off */
398 } else if(demon_talk(mtmp)) return(1); /* you paid it off */
401 /* the watch will look around and see if you are up to no good :-) */
402 if (mdat == &mons[PM_WATCHMAN] || mdat == &mons[PM_WATCH_CAPTAIN])
405 else if (is_mind_flayer(mdat) && !rn2(20)) {
406 struct monst *m2, *nmon = (struct monst *)0;
409 pline("%s concentrates.", Monnam(mtmp));
410 if (distu(mtmp->mx, mtmp->my) > BOLT_LIM * BOLT_LIM) {
411 You("sense a faint wave of psychic energy.");
414 pline("A wave of psychic energy pours over you!");
415 if (mtmp->mpeaceful &&
416 (!Conflict || resist(mtmp, RING_CLASS, 0, 0)))
417 pline("It feels quite soothing.");
419 register boolean m_sen = sensemon(mtmp);
421 if (m_sen || (Blind_telepat && rn2(2)) || !rn2(10)) {
423 pline("It locks on to your %s!",
424 m_sen ? "telepathy" :
425 Blind_telepat ? "latent telepathy" : "mind");
427 if (Half_spell_damage) dmg = (dmg+1) / 2;
428 losehp(dmg, "psychic blast", KILLED_BY_AN);
431 for(m2=fmon; m2; m2 = nmon) {
433 if (DEADMONSTER(m2)) continue;
434 if (m2->mpeaceful == mtmp->mpeaceful) continue;
435 if (mindless(m2->data)) continue;
436 if (m2 == mtmp) continue;
437 if ((telepathic(m2->data) &&
438 (rn2(2) || m2->mblinded)) || !rn2(10)) {
439 if (cansee(m2->mx, m2->my))
440 pline("It locks on to %s.", mon_nam(m2));
443 monkilled(m2, "", AD_DRIN);
451 /* If monster is nearby you, and has to wield a weapon, do so. This
452 * costs the monster a move, of course.
454 if((!mtmp->mpeaceful || Conflict) && inrange &&
455 dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= 8
456 && attacktype(mdat, AT_WEAP)) {
459 /* The scared check is necessary. Otherwise a monster that is
460 * one square near the player but fleeing into a wall would keep
461 * switching between pick-axe and weapon. If monster is stuck
462 * in a trap, prefer ranged weapon (wielding is done in thrwmu).
463 * This may cost the monster an attack, but keeps the monster
464 * from switching back and forth if carrying both.
466 mw_tmp = MON_WEP(mtmp);
467 if (!(scared && mw_tmp && is_pick(mw_tmp)) &&
468 mtmp->weapon_check == NEED_WEAPON &&
469 !(mtmp->mtrapped && !nearby && select_rwep(mtmp))) {
470 mtmp->weapon_check = NEED_HTH_WEAPON;
471 if (mon_wield_item(mtmp) != 0) return(0);
475 /* Now the actual movement phase */
478 if(!nearby || mtmp->mflee || scared ||
479 mtmp->mconf || mtmp->mstun || (mtmp->minvis && !rn2(3)) ||
480 (mdat->mlet == S_LEPRECHAUN && !u.ugold && (mtmp->mgold || rn2(2))) ||
482 if (mdat->mlet == S_LEPRECHAUN) {
483 ygold = findgold(invent);
484 lepgold = findgold(mtmp->minvent);
487 if(!nearby || mtmp->mflee || scared ||
488 mtmp->mconf || mtmp->mstun || (mtmp->minvis && !rn2(3)) ||
489 (mdat->mlet == S_LEPRECHAUN && !ygold && (lepgold || rn2(2))) ||
491 (is_wanderer(mdat) && !rn2(4)) || (Conflict && !mtmp->iswiz) ||
492 (!mtmp->mcansee && !rn2(4)) || mtmp->mpeaceful) {
493 /* Possibly cast an undirected spell if not attacking you */
494 /* note that most of the time castmu() will pick a directed
495 spell and do nothing, so the monster moves normally */
496 /* arbitrary distance restriction to keep monster far away
497 from you from having cast dozens of sticks-to-snakes
498 or similar spells by the time you reach it */
499 if (dist2(mtmp->mx, mtmp->my, u.ux, u.uy) <= 49 && !mtmp->mspec_used) {
502 for (a = &mdat->mattk[0]; a < &mdat->mattk[NATTK]; a++) {
503 if (a->aatyp == AT_MAGC && (a->adtyp == AD_SPEL || a->adtyp == AD_CLRC)) {
504 if (castmu(mtmp, a, FALSE, FALSE)) {
512 tmp = m_move(mtmp, 0);
513 distfleeck(mtmp,&inrange,&nearby,&scared); /* recalc */
516 case 0: /* no movement, but it can still attack you */
517 case 3: /* absolutely no movement */
518 /* for pets, case 0 and 3 are equivalent */
519 /* vault guard might have vanished */
520 if (mtmp->isgd && (mtmp->mhp < 1 ||
521 (mtmp->mx == 0 && mtmp->my == 0)))
522 return 1; /* behave as if it died */
523 /* During hallucination, monster appearance should
524 * still change - even if it doesn't move.
526 if(Hallucination) newsym(mtmp->mx,mtmp->my);
528 case 1: /* monster moved */
529 /* Maybe it stepped on a trap and fell asleep... */
530 if (mtmp->msleeping || !mtmp->mcanmove) return(0);
532 (ranged_attk(mdat) || find_offensive(mtmp)))
534 else if(u.uswallow && mtmp == u.ustuck) {
535 /* a monster that's digesting you can move at the
538 return(mattacku(mtmp));
543 case 2: /* monster died */
548 /* Now, attack the player if possible - one attack set per monst */
550 if (!mtmp->mpeaceful ||
551 (Conflict && !resist(mtmp, RING_CLASS, 0, 0))) {
552 if(inrange && !noattacks(mdat) && u.uhp > 0 && !scared && tmp != 3)
553 if(mattacku(mtmp)) return(1); /* monster died (e.g. exploded) */
555 if(mtmp->wormno) wormhitu(mtmp);
557 /* special speeches for quest monsters */
558 if (!mtmp->msleeping && mtmp->mcanmove && nearby)
560 /* extra emotional attack for vile monsters */
561 if (inrange && mtmp->data->msound == MS_CUSS && !mtmp->mpeaceful &&
562 couldsee(mtmp->mx, mtmp->my) && !mtmp->minvis && !rn2(5))
568 static NEARDATA const char practical[] = { WEAPON_CLASS, ARMOR_CLASS, GEM_CLASS, FOOD_CLASS, 0 };
569 static NEARDATA const char magical[] = {
570 AMULET_CLASS, POTION_CLASS, SCROLL_CLASS, WAND_CLASS, RING_CLASS,
572 static NEARDATA const char indigestion[] = { BALL_CLASS, ROCK_CLASS, 0 };
573 static NEARDATA const char boulder_class[] = { ROCK_CLASS, 0 };
574 static NEARDATA const char gem_class[] = { GEM_CLASS, 0 };
578 register struct monst *mtmp;
580 if (sticks(youmonst.data) && mtmp==u.ustuck && !u.uswallow) {
581 pline("%s cannot escape from you!", Monnam(mtmp));
588 * 0: did not move, but can still attack and do other stuff.
589 * 1: moved, possibly can attack.
591 * 3: did not move, and can't do anything else either.
595 register struct monst *mtmp;
599 xchar gx,gy,nix,niy,chcnt;
600 int chi; /* could be schar except for stupid Sun-2 compiler */
601 boolean likegold=0, likegems=0, likeobjs=0, likemagic=0, conceals=0;
602 boolean likerock=0, can_tunnel=0;
603 boolean can_open=0, can_unlock=0, doorbuster=0;
604 boolean uses_items=0, setlikes=0;
606 struct permonst *ptr;
608 schar mmoved = 0; /* not strictly nec.: chi >= 0 will do */
611 int omx = mtmp->mx, omy = mtmp->my;
615 int i = mintrap(mtmp);
616 if(i >= 2) { newsym(mtmp->mx,mtmp->my); return(2); }/* it died */
617 if(i == 1) return(0); /* still in trap, so didn't move */
619 ptr = mtmp->data; /* mintrap() can change mtmp->data -dlc */
623 return 3; /* still eating */
625 if (hides_under(ptr) && OBJ_AT(mtmp->mx, mtmp->my) && rn2(10))
626 return 0; /* do not leave hiding place */
629 /* where does mtmp think you are? */
630 /* Not necessary if m_move called from this file, but necessary in
631 * other calls of m_move (ex. leprechauns dodging)
634 if (!Is_rogue_level(&u.uz))
636 can_tunnel = tunnels(ptr);
637 can_open = !(nohands(ptr) || verysmall(ptr));
638 can_unlock = ((can_open && m_carrying(mtmp, SKELETON_KEY)) ||
639 mtmp->iswiz || is_rider(ptr));
640 doorbuster = is_giant(ptr);
641 if(mtmp->wormno) goto not_special;
642 /* my dog gets special treatment */
644 mmoved = dog_move(mtmp, after);
648 /* likewise for shopkeeper */
650 mmoved = shk_move(mtmp);
651 if(mmoved == -2) return(2);
652 if(mmoved >= 0) goto postmov;
653 mmoved = 0; /* follow player outside shop */
656 /* and for the guard */
658 mmoved = gd_move(mtmp);
659 if(mmoved == -2) return(2);
660 if(mmoved >= 0) goto postmov;
664 /* and the acquisitive monsters get special treatment */
665 if(is_covetous(ptr)) {
666 xchar tx = STRAT_GOALX(mtmp->mstrategy),
667 ty = STRAT_GOALY(mtmp->mstrategy);
668 struct monst *intruder = m_at(tx, ty);
670 * if there's a monster on the object or in possesion of it,
673 if((dist2(mtmp->mx, mtmp->my, tx, ty) < 2) &&
674 intruder && (intruder != mtmp)) {
676 notonhead = (intruder->mx != tx || intruder->my != ty);
677 if(mattackm(mtmp, intruder) == 2) return(2);
683 /* and for the priest */
685 mmoved = pri_move(mtmp);
686 if(mmoved == -2) return(2);
687 if(mmoved >= 0) goto postmov;
692 if(ptr == &mons[PM_MAIL_DAEMON]) {
693 if(flags.soundok && canseemon(mtmp))
694 verbalize("I'm late!");
700 /* teleport if that lies in our nature */
701 if(ptr == &mons[PM_TENGU] && !rn2(5) && !mtmp->mcan &&
702 !tele_restrict(mtmp)) {
703 if(mtmp->mhp < 7 || mtmp->mpeaceful || rn2(2))
704 (void) rloc(mtmp, FALSE);
711 if(u.uswallow && !mtmp->mflee && u.ustuck != mtmp) return(1);
716 appr = mtmp->mflee ? -1 : 1;
717 if (mtmp->mconf || (u.uswallow && mtmp == u.ustuck))
721 struct obj *lepgold, *ygold;
723 boolean should_see = (couldsee(omx, omy) &&
725 !levl[omx][omy].lit) &&
726 (dist2(omx, omy, gx, gy) <= 36));
728 if (!mtmp->mcansee ||
729 (should_see && Invis && !perceives(ptr) && rn2(11)) ||
730 (youmonst.m_ap_type == M_AP_OBJECT && youmonst.mappearance == STRANGE_OBJECT) || u.uundetected ||
731 (youmonst.m_ap_type == M_AP_OBJECT && youmonst.mappearance == GOLD_PIECE && !likes_gold(ptr)) ||
732 (mtmp->mpeaceful && !mtmp->isshk) || /* allow shks to follow */
733 ((monsndx(ptr) == PM_STALKER || ptr->mlet == S_BAT ||
734 ptr->mlet == S_LIGHT) && !rn2(3)))
737 if(monsndx(ptr) == PM_LEPRECHAUN && (appr == 1) &&
739 (mtmp->mgold > u.ugold))
741 ( (lepgold = findgold(mtmp->minvent)) &&
742 (lepgold->quan > ((ygold = findgold(invent)) ? ygold->quan : 0L)) ))
746 if (!should_see && can_track(ptr)) {
749 cp = gettrack(omx,omy);
757 if ((!mtmp->mpeaceful || !rn2(10))
759 && (!Is_rogue_level(&u.uz))
762 boolean in_line = lined_up(mtmp) &&
763 (distmin(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <=
764 (throws_rocks(youmonst.data) ? 20 : ACURRSTR/2+1)
767 if (appr != 1 || !in_line) {
768 /* Monsters in combat won't pick stuff up, avoiding the
769 * situation where you toss arrows at it and it has nothing
770 * better to do than pick the arrows up.
772 register int pctload = (curr_mon_load(mtmp) * 100) /
775 /* look for gold or jewels nearby */
776 likegold = (likes_gold(ptr) && pctload < 95);
777 likegems = (likes_gems(ptr) && pctload < 85);
778 uses_items = (!mindless(ptr) && !is_animal(ptr)
780 likeobjs = (likes_objs(ptr) && pctload < 75);
781 likemagic = (likes_magic(ptr) && pctload < 85);
782 likerock = (throws_rocks(ptr) && pctload < 50 && !In_sokoban(&u.uz));
783 conceals = hides_under(ptr);
788 #define SQSRCHRADIUS 5
790 { register int minr = SQSRCHRADIUS; /* not too far away */
791 register struct obj *otmp;
793 int oomx, oomy, lmx, lmy;
795 /* cut down the search radius if it thinks character is closer. */
796 if(distmin(mtmp->mux, mtmp->muy, omx, omy) < SQSRCHRADIUS &&
797 !mtmp->mpeaceful) minr--;
798 /* guards shouldn't get too distracted */
799 if(!mtmp->mpeaceful && is_mercenary(ptr)) minr = 1;
801 if((likegold || likegems || likeobjs || likemagic || likerock || conceals)
802 && (!*in_rooms(omx, omy, SHOPBASE) || (!rn2(25) && !mtmp->isshk))) {
804 oomx = min(COLNO-1, omx+minr);
805 oomy = min(ROWNO-1, omy+minr);
806 lmx = max(1, omx-minr);
807 lmy = max(0, omy-minr);
808 for(otmp = fobj; otmp; otmp = otmp->nobj) {
809 /* monsters may pick rocks up, but won't go out of their way
810 to grab them; this might hamper sling wielders, but it cuts
811 down on move overhead by filtering out most common item */
812 if (otmp->otyp == ROCK) continue;
815 /* Nymphs take everything. Most other creatures should not
816 * pick up corpses except as a special case like in
817 * searches_for_item(). We need to do this check in
818 * mpickstuff() as well.
820 if(xx >= lmx && xx <= oomx && yy >= lmy && yy <= oomy) {
821 /* don't get stuck circling around an object that's underneath
822 an immobile or hidden monster; paralysis victims excluded */
823 if ((mtoo = m_at(xx,yy)) != 0 &&
824 (mtoo->msleeping || mtoo->mundetected ||
825 (mtoo->mappearance && !mtoo->iswiz) ||
826 !mtoo->data->mmove)) continue;
828 if(((likegold && otmp->oclass == COIN_CLASS) ||
829 (likeobjs && index(practical, otmp->oclass) &&
830 (otmp->otyp != CORPSE || (ptr->mlet == S_NYMPH
831 && !is_rider(&mons[otmp->corpsenm])))) ||
832 (likemagic && index(magical, otmp->oclass)) ||
833 (uses_items && searches_for_item(mtmp, otmp)) ||
834 (likerock && otmp->otyp == BOULDER) ||
835 (likegems && otmp->oclass == GEM_CLASS &&
836 objects[otmp->otyp].oc_material != MINERAL) ||
837 (conceals && !cansee(otmp->ox,otmp->oy)) ||
838 (ptr == &mons[PM_GELATINOUS_CUBE] &&
839 !index(indigestion, otmp->oclass) &&
840 !(otmp->otyp == CORPSE &&
841 touch_petrifies(&mons[otmp->corpsenm])))
842 ) && touch_artifact(otmp,mtmp)) {
843 if(can_carry(mtmp,otmp) &&
844 (throws_rocks(ptr) ||
845 !sobj_at(BOULDER,xx,yy)) &&
847 objects[otmp->otyp].oc_material == GEMSTONE) &&
848 /* Don't get stuck circling an Elbereth */
849 !(onscary(xx, yy, mtmp))) {
850 minr = distmin(omx,omy,xx,yy);
851 oomx = min(COLNO-1, omx+minr);
852 oomy = min(ROWNO-1, omy+minr);
853 lmx = max(1, omx-minr);
854 lmy = max(0, omy-minr);
857 if (gx == omx && gy == omy) {
858 mmoved = 3; /* actually unnecessary */
865 } else if(likegold) {
866 /* don't try to pick up anything else, but use the same loop */
868 likegems = likeobjs = likemagic = likerock = conceals = 0;
872 if(minr < SQSRCHRADIUS && appr == -1) {
873 if(distmin(omx,omy,mtmp->mux,mtmp->muy) <= 3) {
881 /* don't tunnel if hostile and close enough to prefer a weapon */
882 if (can_tunnel && needspick(ptr) &&
883 ((!mtmp->mpeaceful || Conflict) &&
884 dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= 8))
890 if (mtmp->mpeaceful && (!Conflict || resist(mtmp, RING_CLASS, 0, 0)))
891 flag |= (ALLOW_SANCT | ALLOW_SSM);
892 else flag |= ALLOW_U;
893 if (is_minion(ptr) || is_rider(ptr)) flag |= ALLOW_SANCT;
894 /* unicorn may not be able to avoid hero on a noteleport level */
895 if (is_unicorn(ptr) && !level.flags.noteleport) flag |= NOTONL;
896 if (passes_walls(ptr)) flag |= (ALLOW_WALL | ALLOW_ROCK);
897 if (passes_bars(ptr)) flag |= ALLOW_BARS;
898 if (can_tunnel) flag |= ALLOW_DIG;
899 if (is_human(ptr) || ptr == &mons[PM_MINOTAUR]) flag |= ALLOW_SSM;
900 if (is_undead(ptr) && ptr->mlet != S_GHOST) flag |= NOGARLIC;
901 if (throws_rocks(ptr)) flag |= ALLOW_ROCK;
902 if (can_open) flag |= OPENDOOR;
903 if (can_unlock) flag |= UNLOCKDOOR;
904 if (doorbuster) flag |= BUSTDOOR;
906 register int i, j, nx, ny, nearer;
909 register coord *mtrk;
912 cnt = mfndpos(mtmp, poss, info, flag);
914 jcnt = min(MTSZ, cnt-1);
916 nidist = dist2(nix,niy,gx,gy);
917 /* allow monsters be shortsighted on some levels for balance */
918 if(!mtmp->mpeaceful && level.flags.shortsighted &&
919 nidist > (couldsee(nix,niy) ? 144 : 36) && appr == 1) appr = 0;
920 if (is_unicorn(ptr) && level.flags.noteleport) {
921 /* on noteleport levels, perhaps we cannot avoid hero */
922 for(i = 0; i < cnt; i++)
923 if(!(info[i] & NOTONL)) avoid=TRUE;
926 for(i=0; i < cnt; i++) {
927 if (avoid && (info[i] & NOTONL)) continue;
932 mtrk = &mtmp->mtrack[0];
933 for(j=0; j < jcnt; mtrk++, j++)
934 if(nx == mtrk->x && ny == mtrk->y)
939 nearer = ((ndist = dist2(nx,ny,gx,gy)) < nidist);
941 if((appr == 1 && nearer) || (appr == -1 && !nearer) ||
942 (!appr && !rn2(++chcnt)) || !mmoved) {
956 if (mmoved==1 && (u.ux != nix || u.uy != niy) && itsstuck(mtmp))
959 if (((IS_ROCK(levl[nix][niy].typ) && may_dig(nix,niy)) ||
960 closed_door(nix, niy)) &&
961 mmoved==1 && can_tunnel && needspick(ptr)) {
962 if (closed_door(nix, niy)) {
963 if (!(mw_tmp = MON_WEP(mtmp)) ||
964 !is_pick(mw_tmp) || !is_axe(mw_tmp))
965 mtmp->weapon_check = NEED_PICK_OR_AXE;
966 } else if (IS_TREE(levl[nix][niy].typ)) {
967 if (!(mw_tmp = MON_WEP(mtmp)) || !is_axe(mw_tmp))
968 mtmp->weapon_check = NEED_AXE;
969 } else if (!(mw_tmp = MON_WEP(mtmp)) || !is_pick(mw_tmp)) {
970 mtmp->weapon_check = NEED_PICK_AXE;
972 if (mtmp->weapon_check >= NEED_PICK_AXE && mon_wield_item(mtmp))
975 /* If ALLOW_U is set, either it's trying to attack you, or it
976 * thinks it is. In either case, attack this spot in preference to
979 /* Actually, this whole section of code doesn't work as you'd expect.
980 * Most attacks are handled in dochug(). It calls distfleeck(), which
981 * among other things sets nearby if the monster is near you--and if
982 * nearby is set, we never call m_move unless it is a special case
983 * (confused, stun, etc.) The effect is that this ALLOW_U (and
984 * mfndpos) has no effect for normal attacks, though it lets a confused
985 * monster attack you by accident.
987 if(info[chi] & ALLOW_U) {
991 if (nix == u.ux && niy == u.uy) {
996 /* The monster may attack another based on 1 of 2 conditions:
997 * 1 - It may be confused.
998 * 2 - It may mistake the monster for your (displaced) image.
999 * Pets get taken care of above and shouldn't reach this code.
1000 * Conflict gets handled even farther away (movemon()).
1002 if((info[chi] & ALLOW_M) ||
1003 (nix == mtmp->mux && niy == mtmp->muy)) {
1004 struct monst *mtmp2;
1006 mtmp2 = m_at(nix,niy);
1008 notonhead = mtmp2 && (nix != mtmp2->mx || niy != mtmp2->my);
1009 /* note: mstatus returns 0 if mtmp2 is nonexistent */
1010 mstatus = mattackm(mtmp, mtmp2);
1012 if (mstatus & MM_AGR_DIED) /* aggressor died */
1015 if ((mstatus & MM_HIT) && !(mstatus & MM_DEF_DIED) &&
1016 rn2(4) && mtmp2->movement >= NORMAL_SPEED) {
1017 mtmp2->movement -= NORMAL_SPEED;
1019 mstatus = mattackm(mtmp2, mtmp); /* return attack */
1020 if (mstatus & MM_DEF_DIED)
1026 if (!m_in_out_region(mtmp,nix,niy))
1028 remove_monster(omx, omy);
1029 place_monster(mtmp, nix, niy);
1030 for(j = MTSZ-1; j > 0; j--)
1031 mtmp->mtrack[j] = mtmp->mtrack[j-1];
1032 mtmp->mtrack[0].x = omx;
1033 mtmp->mtrack[0].y = omy;
1034 /* Place a segment at the old position. */
1035 if (mtmp->wormno) worm_move(mtmp);
1037 if(is_unicorn(ptr) && rn2(2) && !tele_restrict(mtmp)) {
1038 (void) rloc(mtmp, FALSE);
1041 if(mtmp->wormno) worm_nomove(mtmp);
1044 if(mmoved == 1 || mmoved == 3) {
1045 boolean canseeit = cansee(mtmp->mx, mtmp->my);
1048 newsym(omx,omy); /* update the old position */
1049 if (mintrap(mtmp) >= 2) {
1050 if(mtmp->mx) newsym(mtmp->mx,mtmp->my);
1051 return(2); /* it died */
1055 /* open a door, or crash through it, if you can */
1056 if(IS_DOOR(levl[mtmp->mx][mtmp->my].typ)
1057 && !passes_walls(ptr) /* doesn't need to open doors */
1058 && !can_tunnel /* taken care of below */
1060 struct rm *here = &levl[mtmp->mx][mtmp->my];
1061 boolean btrapped = (here->doormask & D_TRAPPED);
1063 if(here->doormask & (D_LOCKED|D_CLOSED) && amorphous(ptr)) {
1064 if (flags.verbose && canseemon(mtmp))
1065 pline("%s %s under the door.", Monnam(mtmp),
1066 (ptr == &mons[PM_FOG_CLOUD] ||
1067 ptr == &mons[PM_YELLOW_LIGHT])
1068 ? "flows" : "oozes");
1069 } else if(here->doormask & D_LOCKED && can_unlock) {
1071 here->doormask = D_NODOOR;
1072 newsym(mtmp->mx, mtmp->my);
1073 unblock_point(mtmp->mx,mtmp->my); /* vision */
1074 if(mb_trapped(mtmp)) return(2);
1076 if (flags.verbose) {
1078 You("see a door unlock and open.");
1079 else if (flags.soundok)
1080 You_hear("a door unlock and open.");
1082 here->doormask = D_ISOPEN;
1083 /* newsym(mtmp->mx, mtmp->my); */
1084 unblock_point(mtmp->mx,mtmp->my); /* vision */
1086 } else if (here->doormask == D_CLOSED && can_open) {
1088 here->doormask = D_NODOOR;
1089 newsym(mtmp->mx, mtmp->my);
1090 unblock_point(mtmp->mx,mtmp->my); /* vision */
1091 if(mb_trapped(mtmp)) return(2);
1093 if (flags.verbose) {
1095 You("see a door open.");
1096 else if (flags.soundok)
1097 You_hear("a door open.");
1099 here->doormask = D_ISOPEN;
1100 /* newsym(mtmp->mx, mtmp->my); */ /* done below */
1101 unblock_point(mtmp->mx,mtmp->my); /* vision */
1103 } else if (here->doormask & (D_LOCKED|D_CLOSED)) {
1104 /* mfndpos guarantees this must be a doorbuster */
1106 here->doormask = D_NODOOR;
1107 newsym(mtmp->mx, mtmp->my);
1108 unblock_point(mtmp->mx,mtmp->my); /* vision */
1109 if(mb_trapped(mtmp)) return(2);
1111 if (flags.verbose) {
1113 You("see a door crash open.");
1114 else if (flags.soundok)
1115 You_hear("a door crash open.");
1117 if (here->doormask & D_LOCKED && !rn2(2))
1118 here->doormask = D_NODOOR;
1119 else here->doormask = D_BROKEN;
1120 /* newsym(mtmp->mx, mtmp->my); */ /* done below */
1121 unblock_point(mtmp->mx,mtmp->my); /* vision */
1123 /* if it's a shop door, schedule repair */
1124 if (*in_rooms(mtmp->mx, mtmp->my, SHOPBASE))
1125 add_damage(mtmp->mx, mtmp->my, 0L);
1127 } else if (levl[mtmp->mx][mtmp->my].typ == IRONBARS) {
1128 if (flags.verbose && canseemon(mtmp))
1129 Norep("%s %s %s the iron bars.", Monnam(mtmp),
1130 /* pluralization fakes verb conjugation */
1131 makeplural(locomotion(ptr, "pass")),
1132 passes_walls(ptr) ? "through" : "between");
1136 if (can_tunnel && mdig_tunnel(mtmp))
1137 return(2); /* mon died (position already updated) */
1139 /* set also in domove(), hack.c */
1140 if (u.uswallow && mtmp == u.ustuck &&
1141 (mtmp->mx != omx || mtmp->my != omy)) {
1142 /* If the monster moved, then update */
1149 newsym(mtmp->mx,mtmp->my);
1151 if(OBJ_AT(mtmp->mx, mtmp->my) && mtmp->mcanmove) {
1152 /* recompute the likes tests, in case we polymorphed
1153 * or if the "likegold" case got taken above */
1155 register int pctload = (curr_mon_load(mtmp) * 100) /
1158 /* look for gold or jewels nearby */
1159 likegold = (likes_gold(ptr) && pctload < 95);
1160 likegems = (likes_gems(ptr) && pctload < 85);
1161 uses_items = (!mindless(ptr) && !is_animal(ptr)
1163 likeobjs = (likes_objs(ptr) && pctload < 75);
1164 likemagic = (likes_magic(ptr) && pctload < 85);
1165 likerock = (throws_rocks(ptr) && pctload < 50 &&
1166 !In_sokoban(&u.uz));
1167 conceals = hides_under(ptr);
1170 /* Maybe a rock mole just ate some metal object */
1171 if (metallivorous(ptr)) {
1172 if (meatmetal(mtmp) == 2) return 2; /* it died */
1175 if(g_at(mtmp->mx,mtmp->my) && likegold) mpickgold(mtmp);
1177 /* Maybe a cube ate just about anything */
1178 if (ptr == &mons[PM_GELATINOUS_CUBE]) {
1179 if (meatobj(mtmp) == 2) return 2; /* it died */
1182 if(!*in_rooms(mtmp->mx, mtmp->my, SHOPBASE) || !rn2(25)) {
1183 boolean picked = FALSE;
1185 if(likeobjs) picked |= mpickstuff(mtmp, practical);
1186 if(likemagic) picked |= mpickstuff(mtmp, magical);
1187 if(likerock) picked |= mpickstuff(mtmp, boulder_class);
1188 if(likegems) picked |= mpickstuff(mtmp, gem_class);
1189 if(uses_items) picked |= mpickstuff(mtmp, (char *)0);
1190 if(picked) mmoved = 3;
1194 newsym(mtmp->mx, mtmp->my);
1195 if (mtmp->wormno) see_wsegs(mtmp);
1199 if(hides_under(ptr) || ptr->mlet == S_EEL) {
1200 /* Always set--or reset--mundetected if it's already hidden
1201 (just in case the object it was hiding under went away);
1202 usually set mundetected unless monster can't move. */
1203 if (mtmp->mundetected ||
1204 (mtmp->mcanmove && !mtmp->msleeping && rn2(5)))
1205 mtmp->mundetected = (ptr->mlet != S_EEL) ?
1206 OBJ_AT(mtmp->mx, mtmp->my) :
1207 (is_pool(mtmp->mx, mtmp->my) && !Is_waterlevel(&u.uz));
1208 newsym(mtmp->mx, mtmp->my);
1211 after_shk_move(mtmp);
1224 return((boolean)(IS_DOOR(levl[x][y].typ) &&
1225 (levl[x][y].doormask & (D_LOCKED | D_CLOSED))));
1232 return((boolean)(ACCESSIBLE(levl[x][y].typ) && !closed_door(x, y)));
1238 /* decide where the monster thinks you are standing */
1241 register struct monst *mtmp;
1243 boolean notseen, gotu;
1244 register int disp, mx = mtmp->mux, my = mtmp->muy;
1246 long umoney = money_cnt(invent);
1250 * do cheapest and/or most likely tests first
1253 /* pet knows your smell; grabber still has hold of you */
1254 if (mtmp->mtame || mtmp == u.ustuck) goto found_you;
1256 /* monsters which know where you are don't suddenly forget,
1257 if you haven't moved away */
1258 if (mx == u.ux && my == u.uy) goto found_you;
1260 notseen = (!mtmp->mcansee || (Invis && !perceives(mtmp->data)));
1261 /* add cases as required. eg. Displacement ... */
1262 if (notseen || Underwater) {
1263 /* Xorns can smell valuable metal like gold, treat as seen */
1264 if ((mtmp->data == &mons[PM_XORN]) &&
1274 } else if (Displaced) {
1275 disp = couldsee(mx, my) ? 2 : 1;
1277 if (!disp) goto found_you;
1279 /* without something like the following, invis. and displ.
1281 gotu = notseen ? !rn2(3) : Displaced ? !rn2(4) : FALSE;
1283 #if 0 /* this never worked as intended & isn't needed anyway */
1284 /* If invis but not displaced, staying around gets you 'discovered' */
1285 gotu |= (!Displaced && u.dx == 0 && u.dy == 0);
1289 register int try_cnt = 0;
1291 if (++try_cnt > 200) goto found_you; /* punt */
1292 mx = u.ux - disp + rn2(2*disp+1);
1293 my = u.uy - disp + rn2(2*disp+1);
1294 } while (!isok(mx,my)
1295 || (disp != 2 && mx == mtmp->mx && my == mtmp->my)
1296 || ((mx != u.ux || my != u.uy) &&
1297 !passes_walls(mtmp->data) &&
1298 (!ACCESSIBLE(levl[mx][my].typ) ||
1299 (closed_door(mx, my) && !can_ooze(mtmp))))
1300 || !couldsee(mx, my));
1315 struct obj *chain, *obj;
1317 if (!amorphous(mtmp->data)) return FALSE;
1318 if (mtmp == &youmonst) {
1320 if (u.ugold > 100L) return FALSE;
1325 if (mtmp->mgold > 100L) return FALSE;
1327 chain = mtmp->minvent;
1329 for (obj = chain; obj; obj = obj->nobj) {
1330 int typ = obj->otyp;
1333 if (typ == COIN_CLASS && obj->quan > 100L) return FALSE;
1335 if (obj->oclass != GEM_CLASS &&
1336 !(typ >= ARROW && typ <= BOOMERANG) &&
1337 !(typ >= DAGGER && typ <= CRYSKNIFE) &&
1339 !is_cloak(obj) && typ != FEDORA &&
1340 !is_gloves(obj) && typ != LEATHER_JACKET &&
1342 typ != CREDIT_CARD && !is_shirt(obj) &&
1344 !(typ == CORPSE && verysmall(&mons[obj->corpsenm])) &&
1345 typ != FORTUNE_COOKIE && typ != CANDY_BAR &&
1346 typ != PANCAKE && typ != LEMBAS_WAFER &&
1347 typ != LUMP_OF_ROYAL_JELLY &&
1348 obj->oclass != AMULET_CLASS &&
1349 obj->oclass != RING_CLASS &&
1351 obj->oclass != VENOM_CLASS &&
1353 typ != SACK && typ != BAG_OF_HOLDING &&
1354 typ != BAG_OF_TRICKS && !Is_candle(obj) &&
1355 typ != OILSKIN_SACK && typ != LEASH &&
1356 typ != STETHOSCOPE && typ != BLINDFOLD && typ != TOWEL &&
1357 typ != TIN_WHISTLE && typ != MAGIC_WHISTLE &&
1358 typ != MAGIC_MARKER && typ != TIN_OPENER &&
1359 typ != SKELETON_KEY && typ != LOCK_PICK
1361 if (Is_container(obj) && obj->cobj) return FALSE;