1 /* NetHack 3.6 dogmove.c $NHDT-Date: 1502753407 2017/08/14 23:30:07 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.63 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Robert Patrick Rankin, 2012. */
4 /* NetHack may be freely redistributed. See license for details. */
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2018 */
9 /* JNetHack may be freely redistributed. See license for details. */
15 extern boolean notonhead;
17 STATIC_DCL boolean FDECL(dog_hunger, (struct monst *, struct edog *));
18 STATIC_DCL int FDECL(dog_invent, (struct monst *, struct edog *, int));
19 STATIC_DCL int FDECL(dog_goal, (struct monst *, struct edog *, int, int, int));
20 STATIC_DCL struct monst *FDECL(find_targ, (struct monst *, int, int, int));
21 STATIC_OVL int FDECL(find_friends, (struct monst *, struct monst *, int));
22 STATIC_DCL struct monst *FDECL(best_target, (struct monst *));
23 STATIC_DCL long FDECL(score_targ, (struct monst *, struct monst *));
24 STATIC_DCL boolean FDECL(can_reach_location, (struct monst *, XCHAR_P,
25 XCHAR_P, XCHAR_P, XCHAR_P));
26 STATIC_DCL boolean FDECL(could_reach_item, (struct monst *, XCHAR_P, XCHAR_P));
27 STATIC_DCL void FDECL(quickmimic, (struct monst *));
29 /* pick a carried item for pet to drop */
34 struct obj *obj, *wep, dummy, *pickaxe, *unihorn, *key;
37 dummy.otyp = GOLD_PIECE; /* not STRANGE_OBJECT or tools of interest */
38 dummy.oartifact = 1; /* so real artifact won't override "don't keep it" */
39 pickaxe = unihorn = key = (struct obj *) 0;
42 if (is_animal(mon->data) || mindless(mon->data)) {
43 /* won't hang on to any objects of these types */
44 pickaxe = unihorn = key = &dummy; /* act as if already have them */
46 /* don't hang on to pick-axe if can't use one or don't need one */
47 if (!tunnels(mon->data) || !needspick(mon->data))
49 /* don't hang on to key if can't open doors */
50 if (nohands(mon->data) || verysmall(mon->data))
56 if (wep->otyp == UNICORN_HORN)
58 /* don't need any wielded check for keys... */
61 for (obj = mon->minvent; obj; obj = obj->nobj) {
63 case DWARVISH_MATTOCK:
64 /* reject mattock if couldn't wield it */
65 if (which_armor(mon, W_ARMS))
67 /* keep mattock in preference to pick unless pick is already
68 wielded or is an artifact and mattock isn't */
69 if (pickaxe && pickaxe->otyp == PICK_AXE && pickaxe != wep
70 && (!pickaxe->oartifact || obj->oartifact))
71 return pickaxe; /* drop the one we earlier decided to keep */
74 if (!pickaxe || (obj->oartifact && !pickaxe->oartifact)) {
77 pickaxe = obj; /* keep this digging tool */
83 /* reject cursed unicorn horns */
86 /* keep artifact unihorn in preference to ordinary one */
87 if (!unihorn || (obj->oartifact && !unihorn->oartifact)) {
90 unihorn = obj; /* keep this unicorn horn */
96 /* keep key in preference to lock-pick */
97 if (key && key->otyp == LOCK_PICK
98 && (!key->oartifact || obj->oartifact))
99 return key; /* drop the one we earlier decided to keep */
102 /* keep lock-pick in preference to credit card */
103 if (key && key->otyp == CREDIT_CARD
104 && (!key->oartifact || obj->oartifact))
108 if (!key || (obj->oartifact && !key->oartifact)) {
111 key = obj; /* keep this unlocking tool */
120 if (!obj->owornmask && obj != wep)
124 return (struct obj *) 0; /* don't drop anything */
127 static NEARDATA const char nofetch[] = { BALL_CLASS, CHAIN_CLASS, ROCK_CLASS,
130 STATIC_VAR xchar gtyp, gx, gy; /* type and position of dog's current goal */
132 STATIC_PTR void FDECL(wantdoor, (int, int, genericptr_t));
135 cursed_object_at(x, y)
140 for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
147 dog_nutrition(mtmp, obj)
154 * It is arbitrary that the pet takes the same length of time to eat
155 * as a human, but gets more nutritional value.
157 if (obj->oclass == FOOD_CLASS) {
158 if (obj->otyp == CORPSE) {
159 mtmp->meating = 3 + (mons[obj->corpsenm].cwt >> 6);
160 nutrit = mons[obj->corpsenm].cnutrit;
162 mtmp->meating = objects[obj->otyp].oc_delay;
163 nutrit = objects[obj->otyp].oc_nutrition;
165 switch (mtmp->data->msize) {
187 mtmp->meating = eaten_stat(mtmp->meating, obj);
188 nutrit = eaten_stat(nutrit, obj);
190 } else if (obj->oclass == COIN_CLASS) {
191 mtmp->meating = (int) (obj->quan / 2000) + 1;
192 if (mtmp->meating < 0)
194 nutrit = (int) (obj->quan / 20);
198 /* Unusual pet such as gelatinous cube eating odd stuff.
199 * meating made consistent with wild monsters in mon.c.
200 * nutrit made consistent with polymorphed player nutrit in
201 * eat.c. (This also applies to pets eating gold.)
203 mtmp->meating = obj->owt / 20 + 1;
204 nutrit = 5 * objects[obj->otyp].oc_nutrition;
209 /* returns 2 if pet dies, otherwise 1 */
211 dog_eat(mtmp, obj, x, y, devour)
212 register struct monst *mtmp;
213 register struct obj *obj; /* if unpaid, then thrown or kicked by hero */
214 int x, y; /* dog's starting location, might be different from current */
217 register struct edog *edog = EDOG(mtmp);
218 boolean poly, grow, heal, eyes, slimer, deadmimic;
221 char objnambuf[BUFSZ];
224 if (edog->hungrytime < monstermoves)
225 edog->hungrytime = monstermoves;
226 nutrit = dog_nutrition(mtmp, obj);
228 deadmimic = (obj->otyp == CORPSE && (obj->corpsenm == PM_SMALL_MIMIC
229 || obj->corpsenm == PM_LARGE_MIMIC
230 || obj->corpsenm == PM_GIANT_MIMIC));
231 slimer = (obj->otyp == CORPSE && obj->corpsenm == PM_GREEN_SLIME);
232 poly = polyfodder(obj);
233 grow = mlevelgain(obj);
235 eyes = (obj->otyp == CARROT);
238 if (mtmp->meating > 1)
241 nutrit = (nutrit * 3) / 4;
243 edog->hungrytime += nutrit;
245 if (edog->mhpmax_penalty) {
246 /* no longer starving */
247 mtmp->mhpmax += edog->mhpmax_penalty;
248 edog->mhpmax_penalty = 0;
250 if (mtmp->mflee && mtmp->mfleetim > 1)
252 if (mtmp->mtame < 20)
254 if (x != mtmp->mx || y != mtmp->my) { /* moved & ate on same turn */
256 newsym(mtmp->mx, mtmp->my);
259 /* food items are eaten one at a time; entire stack for other stuff */
260 if (obj->quan > 1L && obj->oclass == FOOD_CLASS)
261 obj = splitobj(obj, 1L);
263 iflags.suppress_price++;
264 if (is_pool(x, y) && !Underwater) {
265 /* Don't print obj */
266 /* TODO: Reveal presence of sea monster (especially sharks) */
268 /* food is at monster's current location, <mx,my>;
269 <x,y> was monster's location at start of this turn;
270 they might be the same but will be different when
271 the monster is moving+eating on same turn */
272 boolean seeobj = cansee(mtmp->mx, mtmp->my),
273 sawpet = cansee(x, y) && mon_visible(mtmp);
275 /* Observe the action if either the food location or the pet
276 itself is in view. When pet which was in view moves to an
277 unseen spot to eat the food there, avoid referring to that
278 pet as "it". However, we want "it" if invisible/unsensed
279 pet eats visible food. */
280 if (sawpet || (seeobj && canspotmon(mtmp))) {
281 if (tunnels(mtmp->data))
283 pline("%s digs in.", noit_Monnam(mtmp));
285 pline("%s
\82Í
\8c@
\82Á
\82Ä
\82¢
\82é
\81D", noit_Monnam(mtmp));
288 pline("%s %s %s.", noit_Monnam(mtmp),
289 devour ? "devours" : "eats", distant_name(obj, doname));
291 pline("%s
\82Í%s
\82ð%s
\82¢
\82é
\81D", noit_Monnam(mtmp),
292 distant_name(obj, doname), devour ? "
\88ù
\82Ý
\8d\9e\82ñ
\82Å" : "
\90H
\82×
\82Ä");
296 pline("It %s %s.", devour ? "devours" : "eats",
297 distant_name(obj, doname));
299 pline("
\82»
\82ê
\82Í%s
\82ð%s
\82¢
\82é
\81D", distant_name(obj, doname),
300 devour ? "
\88ù
\82Ý
\8d\9e\82ñ
\82Å" : "
\90H
\82×
\82Ä");
304 Strcpy(objnambuf, xname(obj));
305 iflags.suppress_price--;
307 /* It's a reward if it's DOGFOOD and the player dropped/threw it.
308 We know the player had it if invlet is set. -dlc */
309 if (dogfood(mtmp, obj) == DOGFOOD && obj->invlet)
313 edog->apport += (int) (200L / ((long) edog->dropdist + monstermoves
316 if (mtmp->data == &mons[PM_RUST_MONSTER] && obj->oerodeproof) {
317 /* The object's rustproofing is gone now */
319 costly_alteration(obj, COST_DEGRD);
320 obj->oerodeproof = 0;
322 if (canseemon(mtmp) && flags.verbose) {
324 pline("%s spits %s out in disgust!", Monnam(mtmp),
325 distant_name(obj, doname));
327 pline("%s
\82Í%s
\82ð
\83y
\83b
\82Æ
\93f
\82«
\8fo
\82µ
\82½
\81I", Monnam(mtmp),
328 distant_name(obj,doname));
331 } else if (obj == uball) {
333 delobj(obj); /* we assume this can't be unpaid */
334 } else if (obj == uchain) {
338 /* edible item owned by shop has been thrown or kicked
339 by hero and caught by tame or food-tameable monst */
340 oprice = unpaid_cost(obj, TRUE);
342 pline("That %s will cost you %ld %s.", objnambuf, oprice,
345 pline("
\82 \82Ì%s
\82Í%ld%s
\82¾
\81D", objnambuf, oprice,
348 /* delobj->obfree will handle actual shop billing update */
353 #if 0 /* pet is eating, so slime recovery is not feasible... */
354 /* turning into slime might be cureable */
355 if (slimer && munslime(mtmp, FALSE)) {
356 /* but the cure (fire directed at self) might be fatal */
359 slimer = FALSE; /* sliming is avoided, skip polymorph */
363 if (poly || slimer) {
364 struct permonst *ptr = slimer ? &mons[PM_GREEN_SLIME] : 0;
366 (void) newcham(mtmp, ptr, FALSE, cansee(mtmp->mx, mtmp->my));
369 /* limit "instant" growth to prevent potential abuse */
370 if (grow && (int) mtmp->m_lev < (int) mtmp->data->mlevel + 15) {
371 if (!grow_up(mtmp, (struct monst *) 0))
375 mtmp->mhp = mtmp->mhpmax;
376 if ((eyes || heal) && !mtmp->mcansee)
377 mcureblindness(mtmp, canseemon(mtmp));
383 /* hunger effects -- returns TRUE on starvation */
385 dog_hunger(mtmp, edog)
389 if (monstermoves > edog->hungrytime + 500) {
390 if (!carnivorous(mtmp->data) && !herbivorous(mtmp->data)) {
391 edog->hungrytime = monstermoves + 500;
392 /* but not too high; it might polymorph */
393 } else if (!edog->mhpmax_penalty) {
394 /* starving pets are limited in healing */
395 int newmhpmax = mtmp->mhpmax / 3;
397 edog->mhpmax_penalty = mtmp->mhpmax - newmhpmax;
398 mtmp->mhpmax = newmhpmax;
399 if (mtmp->mhp > mtmp->mhpmax)
400 mtmp->mhp = mtmp->mhpmax;
403 if (cansee(mtmp->mx, mtmp->my))
405 pline("%s is confused from hunger.", Monnam(mtmp));
407 pline("%s
\82Í
\8bó
\95 \82Ì
\82½
\82ß
\8d¬
\97\90\82µ
\82Ä
\82¢
\82é
\81D", Monnam(mtmp));
408 else if (couldsee(mtmp->mx, mtmp->my))
412 You_feel("worried about %s.", y_monnam(mtmp));
414 You("%s
\82ª
\90S
\94z
\82É
\82È
\82Á
\82½
\81D", y_monnam(mtmp));
416 } else if (monstermoves > edog->hungrytime + 750 || mtmp->mhp < 1) {
418 if (mtmp->mleashed && mtmp != u.usteed)
420 Your("leash goes slack.");
422 Your("
\95R
\82Í
\82½
\82é
\82ñ
\82¾
\81D");
423 else if (cansee(mtmp->mx, mtmp->my))
425 pline("%s starves.", Monnam(mtmp));
427 pline("%s
\82Í
\8bQ
\82¦
\82Å
\8e\80\82ñ
\82¾
\81D", Monnam(mtmp));
430 You_feel("%s for a moment.",
431 Hallucination ? "bummed" : "sad");
433 You("%s
\8bC
\95ª
\82É
\82¨
\82»
\82í
\82ê
\82½
\81D",
434 Hallucination ? "
\82ª
\82Á
\82©
\82è
\82µ
\82½" : "
\94ß
\82µ
\82¢");
443 /* do something with object (drop, pick up, eat) at current position
444 * returns 1 if object eaten (since that counts as dog's move), 2 if died
447 dog_invent(mtmp, edog, udist)
448 register struct monst *mtmp;
449 register struct edog *edog;
452 register int omx, omy, carryamt = 0;
453 struct obj *obj, *otmp;
455 if (mtmp->msleeping || !mtmp->mcanmove)
461 /* If we are carrying something then we drop it (perhaps near @).
462 * Note: if apport == 1 then our behaviour is independent of udist.
463 * Use udist+1 so steed won't cause divide by zero.
465 if (droppables(mtmp)) {
466 if (!rn2(udist + 1) || !rn2(edog->apport))
467 if (rn2(10) < edog->apport) {
468 relobj(mtmp, (int) mtmp->minvis, TRUE);
469 if (edog->apport > 1)
471 edog->dropdist = udist; /* hpscdi!jon */
472 edog->droptime = monstermoves;
475 if ((obj = level.objects[omx][omy]) != 0
476 && !index(nofetch, obj->oclass)
478 && obj->otyp != SCR_MAIL
481 int edible = dogfood(mtmp, obj);
483 if ((edible <= CADAVER
484 /* starving pet is more aggressive about eating */
485 || (edog->mhpmax_penalty && edible == ACCFOOD))
486 && could_reach_item(mtmp, obj->ox, obj->oy))
487 return dog_eat(mtmp, obj, omx, omy, FALSE);
489 carryamt = can_carry(mtmp, obj);
490 if (carryamt > 0 && !obj->cursed
491 && could_reach_item(mtmp, obj->ox, obj->oy)) {
492 if (rn2(20) < edog->apport + 3) {
493 if (rn2(udist) || !rn2(edog->apport)) {
495 if (carryamt != obj->quan)
496 otmp = splitobj(obj, carryamt);
497 if (cansee(omx, omy) && flags.verbose)
499 pline("%s picks up %s.", Monnam(mtmp),
500 distant_name(otmp, doname));
502 pline("%s
\82Í%s
\82ð
\8fE
\82Á
\82½
\81D", Monnam(mtmp),
503 distant_name(obj, doname));
505 obj_extract_self(otmp);
507 (void) mpickobj(mtmp, otmp);
508 if (attacktype(mtmp->data, AT_WEAP)
509 && mtmp->weapon_check == NEED_WEAPON) {
510 mtmp->weapon_check = NEED_HTH_WEAPON;
511 (void) mon_wield_item(mtmp);
513 m_dowear(mtmp, FALSE);
522 /* set dog's goal -- gtyp, gx, gy;
523 returns -1/0/1 (dog's desire to approach player) or -2 (abort move) */
525 dog_goal(mtmp, edog, after, udist, whappr)
526 register struct monst *mtmp;
528 int after, udist, whappr;
530 register int omx, omy;
531 boolean in_masters_sight, dog_has_minvent;
532 register struct obj *obj;
536 /* Steeds don't move on their own will */
537 if (mtmp == u.usteed)
543 in_masters_sight = couldsee(omx, omy);
544 dog_has_minvent = (droppables(mtmp) != 0);
546 if (!edog || mtmp->mleashed) { /* he's not going anywhere... */
551 #define DDIST(x, y) (dist2(x, y, omx, omy))
552 #define SQSRCHRADIUS 5
553 int min_x, max_x, min_y, max_y;
556 gtyp = UNDEF; /* no goal as yet */
557 gx = gy = 0; /* suppress 'used before set' message */
559 if ((min_x = omx - SQSRCHRADIUS) < 1)
561 if ((max_x = omx + SQSRCHRADIUS) >= COLNO)
563 if ((min_y = omy - SQSRCHRADIUS) < 0)
565 if ((max_y = omy + SQSRCHRADIUS) >= ROWNO)
568 /* nearby food is the first choice, then other objects */
569 for (obj = fobj; obj; obj = obj->nobj) {
572 if (nx >= min_x && nx <= max_x && ny >= min_y && ny <= max_y) {
573 otyp = dogfood(mtmp, obj);
574 /* skip inferior goals */
575 if (otyp > gtyp || otyp == UNDEF)
577 /* avoid cursed items unless starving */
578 if (cursed_object_at(nx, ny)
579 && !(edog->mhpmax_penalty && otyp < MANFOOD))
581 /* skip completely unreachable goals */
582 if (!could_reach_item(mtmp, nx, ny)
583 || !can_reach_location(mtmp, mtmp->mx, mtmp->my, nx, ny))
585 if (otyp < MANFOOD) {
586 if (otyp < gtyp || DDIST(nx, ny) < DDIST(gx, gy)) {
591 } else if (gtyp == UNDEF && in_masters_sight
593 && (!levl[omx][omy].lit || levl[u.ux][u.uy].lit)
594 && (otyp == MANFOOD || m_cansee(mtmp, nx, ny))
595 && edog->apport > rn2(8)
596 && can_carry(mtmp, obj) > 0) {
605 /* follow player if appropriate */
606 if (gtyp == UNDEF || (gtyp != DOGFOOD && gtyp != APPORT
607 && monstermoves < edog->hungrytime)) {
610 if (after && udist <= 4 && gx == u.ux && gy == u.uy)
612 appr = (udist >= 9) ? 1 : (mtmp->mflee) ? -1 : 0;
614 if (!IS_ROOM(levl[u.ux][u.uy].typ) || !rn2(4) || whappr
615 || (dog_has_minvent && rn2(edog->apport)))
618 /* if you have dog food it'll follow you more closely */
620 for (obj = invent; obj; obj = obj->nobj)
621 if (dogfood(mtmp, obj) == DOGFOOD) {
626 appr = 1; /* gtyp != UNDEF */
630 #define FARAWAY (COLNO + 2) /* position outside screen */
631 if (gx == u.ux && gy == u.uy && !in_masters_sight) {
634 cp = gettrack(omx, omy);
641 /* assume master hasn't moved far, and reuse previous goal */
642 if (edog && edog->ogoal.x
643 && (edog->ogoal.x != omx || edog->ogoal.y != omy)) {
648 int fardist = FARAWAY * FARAWAY;
649 gx = gy = FARAWAY; /* random */
650 do_clear_area(omx, omy, 9, wantdoor, (genericptr_t) &fardist);
652 /* here gx == FARAWAY e.g. when dog is in a vault */
653 if (gx == FARAWAY || (gx == omx && gy == omy)) {
669 STATIC_OVL struct monst *
670 find_targ(mtmp, dx, dy, maxdist)
671 register struct monst *mtmp;
675 struct monst *targ = 0;
676 int curx = mtmp->mx, cury = mtmp->my;
680 for ( ; dist < maxdist; ++dist) {
683 if (!isok(curx, cury))
686 /* FIXME: Check if we hit a wall/door/boulder to
687 * short-circuit unnecessary subsequent checks
690 /* If we can't see up to here, forget it - will this
691 * mean pets in corridors don't breathe at monsters
692 * in rooms? If so, is that necessarily bad?
694 if (!m_cansee(mtmp, curx, cury))
697 targ = m_at(curx, cury);
699 if (curx == mtmp->mux && cury == mtmp->muy)
703 /* Is the monster visible to the pet? */
704 if ((!targ->minvis || perceives(mtmp->data)) &&
708 /* If the pet can't see it, it assumes it aint there */
716 find_friends(mtmp, mtarg, maxdist)
717 struct monst *mtmp, *mtarg;
721 int dx = sgn(mtarg->mx - mtmp->mx),
722 dy = sgn(mtarg->my - mtmp->my);
723 int curx = mtarg->mx, cury = mtarg->my;
724 int dist = distmin(mtarg->mx, mtarg->my, mtmp->mx, mtmp->my);
726 for ( ; dist <= maxdist; ++dist) {
730 if (!isok(curx, cury))
733 /* If the pet can't see beyond this point, don't
736 if (!m_cansee(mtmp, curx, cury))
739 /* Does pet think you're here? */
740 if (mtmp->mux == curx && mtmp->muy == cury)
743 pal = m_at(curx, cury);
747 /* Pet won't notice invisible pets */
748 if (!pal->minvis || perceives(mtmp->data))
751 /* Quest leaders and guardians are always seen */
752 if (pal->data->msound == MS_LEADER
753 || pal->data->msound == MS_GUARDIAN)
762 score_targ(mtmp, mtarg)
763 struct monst *mtmp, *mtarg;
767 /* If the monster is confused, normal scoring is disrupted -
768 * anything may happen
771 /* Give 1 in 3 chance of safe breathing even if pet is confused or
772 * if you're on the quest start level */
773 if (!mtmp->mconf || !rn2(3) || Is_qstart(&u.uz)) {
774 aligntyp align1 = A_NONE, align2 = A_NONE; /* For priests, minions */
775 boolean faith1 = TRUE, faith2 = TRUE;
778 align1 = EMIN(mtmp)->min_align;
779 else if (mtmp->ispriest)
780 align1 = EPRI(mtmp)->shralign;
784 align2 = EMIN(mtarg)->min_align; /* MAR */
785 else if (mtarg->ispriest)
786 align2 = EPRI(mtarg)->shralign; /* MAR */
790 /* Never target quest friendlies */
791 if (mtarg->data->msound == MS_LEADER
792 || mtarg->data->msound == MS_GUARDIAN)
794 /* D: Fixed angelic beings using gaze attacks on coaligned priests */
795 if (faith1 && faith2 && align1 == align2 && mtarg->mpeaceful) {
799 /* Is monster adjacent? */
800 if (distmin(mtmp->mx, mtmp->my, mtarg->mx, mtarg->my) <= 1) {
804 /* Is the monster peaceful or tame? */
805 if (/*mtarg->mpeaceful ||*/ mtarg->mtame || mtarg == &youmonst) {
806 /* Pets will never be targeted */
810 /* Is master/pet behind monster? Check up to 15 squares beyond pet. */
811 if (find_friends(mtmp, mtarg, 15)) {
815 /* Target hostile monsters in preference to peaceful ones */
816 if (!mtarg->mpeaceful)
818 /* Is the monster passive? Don't waste energy on it, if so */
819 if (mtarg->data->mattk[0].aatyp == AT_NONE)
821 /* Even weak pets with breath attacks shouldn't take on very
822 low-level monsters. Wasting breath on lichens is ridiculous. */
823 if ((mtarg->m_lev < 2 && mtmp->m_lev > 5)
824 || (mtmp->m_lev > 12 && mtarg->m_lev < mtmp->m_lev - 9
825 && u.ulevel > 8 && mtarg->m_lev < u.ulevel - 7))
827 /* And pets will hesitate to attack vastly stronger foes.
828 This penalty will be discarded if master's in trouble. */
829 if (mtarg->m_lev > mtmp->m_lev + 4L)
830 score -= (mtarg->m_lev - mtmp->m_lev) * 20L;
831 /* All things being the same, go for the beefiest monster. This
832 bonus should not be large enough to override the pet's aversion
833 to attacking much stronger monsters. */
834 score += mtarg->m_lev * 2 + mtarg->mhp / 3;
836 /* Fuzz factor to make things less predictable when very
837 similar targets are abundant. */
839 /* Pet may decide not to use ranged attack when confused */
840 if (mtmp->mconf && !rn2(3))
846 STATIC_OVL struct monst *
848 struct monst *mtmp; /* Pet */
851 long bestscore = -40000L, currscore;
852 struct monst *best_targ = 0, *temp_targ = 0;
858 /* If the pet is blind, it's not going to see any target */
862 /* Search for any monsters lined up with the pet, within an arbitrary
863 * distance from the pet (7 squares, even along diagonals). Monsters
864 * are assigned scores and the best score is chosen.
866 for (dy = -1; dy < 2; ++dy) {
867 for (dx = -1; dx < 2; ++dx) {
870 /* Traverse the line to find the first monster within 7
871 * squares. Invisible monsters are skipped (if the
872 * pet doesn't have see invisible).
874 temp_targ = find_targ(mtmp, dx, dy, 7);
876 /* Nothing in this line? */
880 /* Decide how attractive the target is */
881 currscore = score_targ(mtmp, temp_targ);
883 if (currscore > bestscore) {
884 bestscore = currscore;
885 best_targ = temp_targ;
890 /* Filter out targets the pet doesn't like */
898 /* return 0 (no move), 1 (move) or 2 (dead) */
900 dog_move(mtmp, after)
901 register struct monst *mtmp;
902 int after; /* this is extra fast monster movement */
904 int omx, omy; /* original mtmp position */
905 int appr, whappr, udist;
907 register struct edog *edog = EDOG(mtmp);
908 struct obj *obj = (struct obj *) 0;
910 boolean has_edog, cursemsg[9], do_eat = FALSE;
911 boolean better_with_displacing = FALSE;
912 xchar nix, niy; /* position mtmp is (considering) moving to */
913 register int nx, ny; /* temporary coordinates */
914 xchar cnt, uncursedcnt, chcnt;
915 int chi = -1, nidist, ndist;
917 long info[9], allowflags;
918 #define GDIST(x, y) (dist2(x, y, gx, gy))
921 * Tame Angels have isminion set and an ispriest structure instead of
922 * an edog structure. Fortunately, guardian Angels need not worry
923 * about mundane things like eating and fetching objects, and can
924 * spend all their energy defending the player. (They are the only
925 * monsters with other structures that can be tame.)
927 has_edog = !mtmp->isminion;
931 if (has_edog && dog_hunger(mtmp, edog))
932 return 2; /* starved */
934 udist = distu(omx, omy);
935 /* Let steeds eat and maybe throw rider during Conflict */
936 if (mtmp == u.usteed) {
937 if (Conflict && !resist(mtmp, RING_CLASS, 0, 0)) {
938 dismount_steed(DISMOUNT_THROWN);
943 /* maybe we tamed him while being swallowed --jgm */
946 nix = omx; /* set before newdogpos */
948 cursemsg[0] = FALSE; /* lint suppression */
949 info[0] = 0; /* ditto */
952 j = dog_invent(mtmp, edog, udist);
956 goto newdogpos; /* eating something */
958 whappr = (monstermoves - edog->whistletime < 5);
962 appr = dog_goal(mtmp, has_edog ? edog : (struct edog *) 0, after, udist,
967 allowflags = ALLOW_M | ALLOW_TRAPS | ALLOW_SSM | ALLOW_SANCT;
968 if (passes_walls(mtmp->data))
969 allowflags |= (ALLOW_ROCK | ALLOW_WALL);
970 if (passes_bars(mtmp->data))
971 allowflags |= ALLOW_BARS;
972 if (throws_rocks(mtmp->data))
973 allowflags |= ALLOW_ROCK;
974 if (is_displacer(mtmp->data))
975 allowflags |= ALLOW_MDISP;
976 if (Conflict && !resist(mtmp, RING_CLASS, 0, 0)) {
977 allowflags |= ALLOW_U;
979 /* Guardian angel refuses to be conflicted; rather,
980 * it disappears, angrily, and sends in some nasties
982 lose_guardian_angel(mtmp);
983 return 2; /* current monster is gone */
986 #if 0 /* [this is now handled in dochug()] */
987 if (!Conflict && !mtmp->mconf
988 && mtmp == u.ustuck && !sticks(youmonst.data)) {
989 unstuck(mtmp); /* swallowed case handled above */
991 You("get released!");
993 You("
\93®
\82¯
\82é
\82æ
\82¤
\82É
\82È
\82Á
\82½
\81I");
996 if (!nohands(mtmp->data) && !verysmall(mtmp->data)) {
997 allowflags |= OPENDOOR;
998 if (monhaskey(mtmp, TRUE))
999 allowflags |= UNLOCKDOOR;
1000 /* note: the Wizard and Riders can unlock doors without a key;
1001 they won't use that ability if someone manages to tame them */
1003 if (is_giant(mtmp->data))
1004 allowflags |= BUSTDOOR;
1005 if (tunnels(mtmp->data)
1006 && !Is_rogue_level(&u.uz)) /* same restriction as m_move() */
1007 allowflags |= ALLOW_DIG;
1008 cnt = mfndpos(mtmp, poss, info, allowflags);
1010 /* Normally dogs don't step on cursed items, but if they have no
1011 * other choice they will. This requires checking ahead of time
1012 * to see how many uncursed item squares are around.
1015 for (i = 0; i < cnt; i++) {
1018 if (MON_AT(nx, ny) && !((info[i] & ALLOW_M) || info[i] & ALLOW_MDISP))
1020 if (cursed_object_at(nx, ny))
1025 better_with_displacing = should_displace(mtmp, poss, info, cnt, gx, gy);
1029 nidist = GDIST(nix, niy);
1031 for (i = 0; i < cnt; i++) {
1034 cursemsg[i] = FALSE;
1036 /* if leashed, we drag him along. */
1037 if (mtmp->mleashed && distu(nx, ny) > 4)
1040 /* if a guardian, try to stay close by choice */
1041 if (!has_edog && (j = distu(nx, ny)) > 16 && j >= udist)
1044 if ((info[i] & ALLOW_M) && MON_AT(nx, ny)) {
1046 register struct monst *mtmp2 = m_at(nx, ny);
1048 if ((int) mtmp2->m_lev >= (int) mtmp->m_lev + 2
1049 || (mtmp2->data == &mons[PM_FLOATING_EYE] && rn2(10)
1050 && mtmp->mcansee && haseyes(mtmp->data) && mtmp2->mcansee
1051 && (perceives(mtmp->data) || !mtmp2->minvis))
1052 || (mtmp2->data == &mons[PM_GELATINOUS_CUBE] && rn2(10))
1053 || (max_passive_dmg(mtmp2, mtmp) >= mtmp->mhp)
1054 || ((mtmp->mhp * 4 < mtmp->mhpmax
1055 || mtmp2->data->msound == MS_GUARDIAN
1056 || mtmp2->data->msound == MS_LEADER) && mtmp2->mpeaceful
1058 || (touch_petrifies(mtmp2->data) && !resists_ston(mtmp)))
1062 return 0; /* hit only once each move */
1065 mstatus = mattackm(mtmp, mtmp2);
1067 /* aggressor (pet) died */
1068 if (mstatus & MM_AGR_DIED)
1071 if ((mstatus & MM_HIT) && !(mstatus & MM_DEF_DIED) && rn2(4)
1072 && mtmp2->mlstmv != monstermoves
1073 && !onscary(mtmp->mx, mtmp->my, mtmp2)
1074 /* monnear check needed: long worms hit on tail */
1075 && monnear(mtmp2, mtmp->mx, mtmp->my)) {
1076 mstatus = mattackm(mtmp2, mtmp); /* return attack */
1077 if (mstatus & MM_DEF_DIED)
1082 if ((info[i] & ALLOW_MDISP) && MON_AT(nx, ny)
1083 && better_with_displacing && !undesirable_disp(mtmp, nx, ny)) {
1085 register struct monst *mtmp2 = m_at(nx, ny);
1087 mstatus = mdisplacem(mtmp, mtmp2, FALSE); /* displace monster */
1088 if (mstatus & MM_DEF_DIED)
1094 /* Dog avoids harmful traps, but perhaps it has to pass one
1095 * in order to follow player. (Non-harmful traps do not
1096 * have ALLOW_TRAPS in info[].) The dog only avoids the
1097 * trap if you've seen it, unlike enemies who avoid traps
1098 * if they've seen some trap of that type sometime in the
1099 * past. (Neither behavior is really realistic.)
1103 if ((info[i] & ALLOW_TRAPS) && (trap = t_at(nx, ny))) {
1104 if (mtmp->mleashed) {
1108 /* 1/40 chance of stepping on it anyway, in case
1109 * it has to pass one to follow the player...
1111 if (trap->tseen && rn2(40))
1117 /* dog eschews cursed objects, but likes dog food */
1118 /* (minion isn't interested; `cursemsg' stays FALSE) */
1120 for (obj = level.objects[nx][ny]; obj; obj = obj->nexthere) {
1123 } else if ((otyp = dogfood(mtmp, obj)) < MANFOOD
1125 || edog->hungrytime <= monstermoves)) {
1126 /* Note: our dog likes the food so much that he
1127 * might eat it even when it conceals a cursed object */
1132 cursemsg[i] = FALSE; /* not reluctant */
1136 /* didn't find something to eat; if we saw a cursed item and
1137 aren't being forced to walk on it, usually keep looking */
1138 if (cursemsg[i] && !mtmp->mleashed && uncursedcnt > 0
1139 && rn2(13 * uncursedcnt))
1142 /* lessen the chance of backtracking to previous position(s) */
1143 /* This causes unintended issues for pets trying to follow
1144 the hero. Thus, only run it if not leashed and >5 tiles
1146 if (!mtmp->mleashed &&
1147 distmin(mtmp->mx, mtmp->my, u.ux, u.uy) > 5) {
1148 k = has_edog ? uncursedcnt : cnt;
1149 for (j = 0; j < MTSZ && j < k - 1; j++)
1150 if (nx == mtmp->mtrack[j].x &&
1151 ny == mtmp->mtrack[j].y)
1152 if (rn2(MTSZ * (k - j)))
1156 j = ((ndist = GDIST(nx, ny)) - nidist) * appr;
1157 if ((j == 0 && !rn2(++chcnt)) || j < 0
1158 || (j > 0 && !whappr
1159 && ((omx == nix && omy == niy && !rn2(3)) || !rn2(12)))) {
1171 /* Pet hasn't attacked anything but is considering moving -
1172 * now's the time for ranged attacks. Note that the pet can move
1173 * after it performs its ranged attack. Should this be changed?
1176 struct monst *mtarg;
1179 /* How hungry is the pet? */
1180 if (!mtmp->isminion) {
1181 struct edog *dog = EDOG(mtmp);
1182 hungry = (monstermoves > (dog->hungrytime + 300));
1185 /* Identify the best target in a straight line from the pet;
1186 * if there is such a target, we'll let the pet attempt an
1189 mtarg = best_target(mtmp);
1191 /* Hungry pets are unlikely to use breath/spit attacks */
1192 if (mtarg && (!hungry || !rn2(5))) {
1195 if (mtarg == &youmonst) {
1199 mstatus = mattackm(mtmp, mtarg);
1201 /* Shouldn't happen, really */
1202 if (mstatus & MM_AGR_DIED)
1205 /* Allow the targeted nasty to strike back - if
1206 * the targeted beast doesn't have a ranged attack,
1207 * nothing will happen.
1209 if ((mstatus & MM_HIT) && !(mstatus & MM_DEF_DIED)
1210 && rn2(4) && mtarg != &youmonst) {
1212 /* Can monster see? If it can, it can retaliate
1213 * even if the pet is invisible, since it'll see
1214 * the direction from which the ranged attack came;
1215 * if it's blind or unseeing, it can't retaliate
1217 if (mtarg->mcansee && haseyes(mtarg->data)) {
1218 mstatus = mattackm(mtarg, mtmp);
1219 if (mstatus & MM_DEF_DIED)
1228 if (nix != omx || niy != omy) {
1231 if (info[chi] & ALLOW_U) {
1232 if (mtmp->mleashed) { /* play it safe */
1234 pline("%s breaks loose of %s leash!", Monnam(mtmp),
1237 pline("%s
\82Í
\8e©
\95ª
\82É
\82Â
\82¢
\82Ä
\82¢
\82é
\95R
\82ð
\82Í
\82¸
\82µ
\82½
\81I",
1240 m_unleash(mtmp, FALSE);
1242 (void) mattacku(mtmp);
1245 if (!m_in_out_region(mtmp, nix, niy))
1247 if (m_digweapon_check(mtmp, nix,niy))
1250 /* insert a worm_move() if worms ever begin to eat things */
1251 wasseen = canseemon(mtmp);
1252 remove_monster(omx, omy);
1253 place_monster(mtmp, nix, niy);
1254 if (cursemsg[chi] && (wasseen || canseemon(mtmp))) {
1255 /* describe top item of pile, not necessarily cursed item itself;
1256 don't use glyph_at() here--it would return the pet but we want
1257 to know whether an object is remembered at this map location */
1258 struct obj *o = (!Hallucination && level.flags.hero_memory
1259 && glyph_is_object(levl[nix][niy].glyph))
1260 ? vobj_at(nix, niy) : 0;
1261 const char *what = o ? distant_name(o, doname) : something;
1264 pline("%s %s reluctantly over %s.", noit_Monnam(mtmp),
1265 vtense((char *) 0, locomotion(mtmp->data, "step")), what);
1267 pline("%s
\82Í%s
\82Ì
\8fã
\82É
\82¢
\82â
\82¢
\82â
\93®
\82¢
\82½
\81D", noit_Monnam(mtmp), what);
1270 for (j = MTSZ - 1; j > 0; j--)
1271 mtmp->mtrack[j] = mtmp->mtrack[j - 1];
1272 mtmp->mtrack[0].x = omx;
1273 mtmp->mtrack[0].y = omy;
1274 /* We have to know if the pet's going to do a combined eat and
1275 * move before moving it, but it can't eat until after being
1276 * moved. Thus the do_eat flag.
1279 if (dog_eat(mtmp, obj, omx, omy, FALSE) == 2)
1282 } else if (mtmp->mleashed && distu(omx, omy) > 4) {
1283 /* an incredible kludge, but the only way to keep pooch near
1284 * after it spends time eating or in a trap, etc.
1288 nx = sgn(omx - u.ux);
1289 ny = sgn(omy - u.uy);
1292 if (goodpos(cc.x, cc.y, mtmp, 0))
1296 for (j = (i + 7) % 8; j < (i + 1) % 8; j++) {
1298 if (goodpos(cc.x, cc.y, mtmp, 0))
1301 for (j = (i + 6) % 8; j < (i + 2) % 8; j++) {
1303 if (goodpos(cc.x, cc.y, mtmp, 0))
1309 if (!m_in_out_region(mtmp, nix, niy))
1311 remove_monster(mtmp->mx, mtmp->my);
1312 place_monster(mtmp, cc.x, cc.y);
1319 /* check if a monster could pick up objects from a location */
1321 could_reach_item(mon, nx, ny)
1325 if ((!is_pool(nx, ny) || is_swimmer(mon->data))
1326 && (!is_lava(nx, ny) || likes_lava(mon->data))
1327 && (!sobj_at(BOULDER, nx, ny) || throws_rocks(mon->data)))
1332 /* Hack to prevent a dog from being endlessly stuck near an object that
1333 * it can't reach, such as caught in a teleport scroll niche. It recursively
1334 * checks to see if the squares in between are good. The checking could be
1335 * a little smarter; a full check would probably be useful in m_move() too.
1336 * Since the maximum food distance is 5, this should never be more than 5
1340 can_reach_location(mon, mx, my, fx, fy)
1342 xchar mx, my, fx, fy;
1347 if (mx == fx && my == fy)
1350 return FALSE; /* should not happen */
1352 dist = dist2(mx, my, fx, fy);
1353 for (i = mx - 1; i <= mx + 1; i++) {
1354 for (j = my - 1; j <= my + 1; j++) {
1357 if (dist2(i, j, fx, fy) >= dist)
1359 if (IS_ROCK(levl[i][j].typ) && !passes_walls(mon->data)
1360 && (!may_dig(i, j) || !tunnels(mon->data)))
1362 if (IS_DOOR(levl[i][j].typ)
1363 && (levl[i][j].doormask & (D_CLOSED | D_LOCKED)))
1365 if (!could_reach_item(mon, i, j))
1367 if (can_reach_location(mon, i, j, fx, fy))
1374 /* do_clear_area client */
1376 wantdoor(x, y, distance)
1378 genericptr_t distance;
1380 int ndist, *dist_ptr = (int *) distance;
1382 if (*dist_ptr > (ndist = distu(x, y))) {
1389 static struct qmchoices {
1390 int mndx; /* type of pet, 0 means any */
1391 char mlet; /* symbol of pet, 0 means any */
1392 unsigned mappearance; /* mimic this */
1393 uchar m_ap_type; /* what is the thing it is mimicing? */
1395 /* Things that some pets might be thinking about at the time */
1396 { PM_LITTLE_DOG, 0, PM_KITTEN, M_AP_MONSTER },
1397 { PM_DOG, 0, PM_HOUSECAT, M_AP_MONSTER },
1398 { PM_LARGE_DOG, 0, PM_LARGE_CAT, M_AP_MONSTER },
1399 { PM_KITTEN, 0, PM_LITTLE_DOG, M_AP_MONSTER },
1400 { PM_HOUSECAT, 0, PM_DOG, M_AP_MONSTER },
1401 { PM_LARGE_CAT, 0, PM_LARGE_DOG, M_AP_MONSTER },
1402 { PM_HOUSECAT, 0, PM_GIANT_RAT, M_AP_MONSTER },
1404 M_AP_FURNITURE }, /* sorry, no fire hydrants in NetHack */
1405 { 0, 0, TRIPE_RATION, M_AP_OBJECT }, /* leave this at end */
1409 finish_meating(mtmp)
1413 if (mtmp->m_ap_type && mtmp->mappearance && mtmp->cham == NON_PM) {
1414 /* was eating a mimic and now appearance needs resetting */
1415 mtmp->m_ap_type = 0;
1416 mtmp->mappearance = 0;
1417 newsym(mtmp->mx, mtmp->my);
1425 int idx = 0, trycnt = 5, spotted;
1428 if (Protection_from_shape_changers || !mtmp->meating)
1432 idx = rn2(SIZE(qm));
1433 if (qm[idx].mndx != 0 && monsndx(mtmp->data) == qm[idx].mndx)
1435 if (qm[idx].mlet != 0 && mtmp->data->mlet == qm[idx].mlet)
1437 if (qm[idx].mndx == 0 && qm[idx].mlet == 0)
1439 } while (--trycnt > 0);
1443 Strcpy(buf, mon_nam(mtmp));
1444 spotted = canspotmon(mtmp);
1446 mtmp->m_ap_type = qm[idx].m_ap_type;
1447 mtmp->mappearance = qm[idx].mappearance;
1449 if (spotted || cansee(mtmp->mx, mtmp->my) || canspotmon(mtmp)) {
1450 /* this isn't quite right; if sensing a monster without being
1451 able to see its location, you really shouldn't be told you
1452 sense it becoming furniture or an object that you can't see
1453 (on the other hand, perhaps you're sensing a brief glimpse
1454 of its mind as it changes form) */
1455 newsym(mtmp->mx, mtmp->my);
1457 You("%s %s %sappear%s where %s was!",
1458 cansee(mtmp->mx, mtmp->my) ? "see" : "sense that",
1459 (mtmp->m_ap_type == M_AP_FURNITURE)
1460 ? an(defsyms[mtmp->mappearance].explanation)
1461 : (mtmp->m_ap_type == M_AP_OBJECT
1462 && OBJ_DESCR(objects[mtmp->mappearance]))
1463 ? an(OBJ_DESCR(objects[mtmp->mappearance]))
1464 : (mtmp->m_ap_type == M_AP_OBJECT
1465 && OBJ_NAME(objects[mtmp->mappearance]))
1466 ? an(OBJ_NAME(objects[mtmp->mappearance]))
1467 : (mtmp->m_ap_type == M_AP_MONSTER)
1468 ? an(mons[mtmp->mappearance].mname)
1470 cansee(mtmp->mx, mtmp->my) ? "" : "has ",
1471 cansee(mtmp->mx, mtmp->my) ? "" : "ed",
1474 You("%s
\82ª
\82 \82Á
\82½
\82Æ
\82±
\82ë
\82É%s
\82ª
\8c»
\82ê
\82½
\82Ì%s
\81I",
1476 (mtmp->m_ap_type == M_AP_FURNITURE)
1477 ? an(defsyms[mtmp->mappearance].explanation)
1478 : (mtmp->m_ap_type == M_AP_OBJECT
1479 && OBJ_DESCR(objects[mtmp->mappearance]))
1480 ? an(OBJ_DESCR(objects[mtmp->mappearance]))
1481 : (mtmp->m_ap_type == M_AP_OBJECT
1482 && OBJ_NAME(objects[mtmp->mappearance]))
1483 ? an(OBJ_NAME(objects[mtmp->mappearance]))
1484 : (mtmp->m_ap_type == M_AP_MONSTER)
1485 ? an(mons[mtmp->mappearance].mname)
1487 cansee(mtmp->mx, mtmp->my) ? "
\82ð
\8c©
\82½" : "
\82É
\8bC
\82Ã
\82¢
\82½");
1489 display_nhwindow(WIN_MAP, TRUE);