1 /* NetHack 3.6 dogmove.c $NHDT-Date: 1557094801 2019/05/05 22:20:01 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.74 $ */
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-2020 */
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 */
357 if (DEADMONSTER(mtmp))
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;
401 if (DEADMONSTER(mtmp))
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
417 || DEADMONSTER(mtmp)) {
419 if (mtmp->mleashed && mtmp != u.usteed)
421 Your("leash goes slack.");
423 Your("
\95R
\82Í
\82½
\82é
\82ñ
\82¾
\81D");
424 else if (cansee(mtmp->mx, mtmp->my))
426 pline("%s starves.", Monnam(mtmp));
428 pline("%s
\82Í
\8bQ
\82¦
\82Å
\8e\80\82ñ
\82¾
\81D", Monnam(mtmp));
431 You_feel("%s for a moment.",
432 Hallucination ? "bummed" : "sad");
434 You("%s
\8bC
\95ª
\82É
\82¨
\82»
\82í
\82ê
\82½
\81D",
435 Hallucination ? "
\82ª
\82Á
\82©
\82è
\82µ
\82½" : "
\94ß
\82µ
\82¢");
444 /* do something with object (drop, pick up, eat) at current position
445 * returns 1 if object eaten (since that counts as dog's move), 2 if died
448 dog_invent(mtmp, edog, udist)
449 register struct monst *mtmp;
450 register struct edog *edog;
453 register int omx, omy, carryamt = 0;
454 struct obj *obj, *otmp;
456 if (mtmp->msleeping || !mtmp->mcanmove)
462 /* If we are carrying something then we drop it (perhaps near @).
463 * Note: if apport == 1 then our behaviour is independent of udist.
464 * Use udist+1 so steed won't cause divide by zero.
466 if (droppables(mtmp)) {
467 if (!rn2(udist + 1) || !rn2(edog->apport))
468 if (rn2(10) < edog->apport) {
469 relobj(mtmp, (int) mtmp->minvis, TRUE);
470 if (edog->apport > 1)
472 edog->dropdist = udist; /* hpscdi!jon */
473 edog->droptime = monstermoves;
476 if ((obj = level.objects[omx][omy]) != 0
477 && !index(nofetch, obj->oclass)
479 && obj->otyp != SCR_MAIL
482 int edible = dogfood(mtmp, obj);
484 if ((edible <= CADAVER
485 /* starving pet is more aggressive about eating */
486 || (edog->mhpmax_penalty && edible == ACCFOOD))
487 && could_reach_item(mtmp, obj->ox, obj->oy))
488 return dog_eat(mtmp, obj, omx, omy, FALSE);
490 carryamt = can_carry(mtmp, obj);
491 if (carryamt > 0 && !obj->cursed
492 && could_reach_item(mtmp, obj->ox, obj->oy)) {
493 if (rn2(20) < edog->apport + 3) {
494 if (rn2(udist) || !rn2(edog->apport)) {
496 if (carryamt != obj->quan)
497 otmp = splitobj(obj, carryamt);
498 if (cansee(omx, omy) && flags.verbose)
500 pline("%s picks up %s.", Monnam(mtmp),
501 distant_name(otmp, doname));
503 pline("%s
\82Í%s
\82ð
\8fE
\82Á
\82½
\81D", Monnam(mtmp),
504 distant_name(obj, doname));
506 obj_extract_self(otmp);
508 (void) mpickobj(mtmp, otmp);
509 if (attacktype(mtmp->data, AT_WEAP)
510 && mtmp->weapon_check == NEED_WEAPON) {
511 mtmp->weapon_check = NEED_HTH_WEAPON;
512 (void) mon_wield_item(mtmp);
514 m_dowear(mtmp, FALSE);
523 /* set dog's goal -- gtyp, gx, gy;
524 returns -1/0/1 (dog's desire to approach player) or -2 (abort move) */
526 dog_goal(mtmp, edog, after, udist, whappr)
527 register struct monst *mtmp;
529 int after, udist, whappr;
531 register int omx, omy;
532 boolean in_masters_sight, dog_has_minvent;
533 register struct obj *obj;
537 /* Steeds don't move on their own will */
538 if (mtmp == u.usteed)
544 in_masters_sight = couldsee(omx, omy);
545 dog_has_minvent = (droppables(mtmp) != 0);
547 if (!edog || mtmp->mleashed) { /* he's not going anywhere... */
552 #define DDIST(x, y) (dist2(x, y, omx, omy))
553 #define SQSRCHRADIUS 5
554 int min_x, max_x, min_y, max_y;
557 gtyp = UNDEF; /* no goal as yet */
558 gx = gy = 0; /* suppress 'used before set' message */
560 if ((min_x = omx - SQSRCHRADIUS) < 1)
562 if ((max_x = omx + SQSRCHRADIUS) >= COLNO)
564 if ((min_y = omy - SQSRCHRADIUS) < 0)
566 if ((max_y = omy + SQSRCHRADIUS) >= ROWNO)
569 /* nearby food is the first choice, then other objects */
570 for (obj = fobj; obj; obj = obj->nobj) {
573 if (nx >= min_x && nx <= max_x && ny >= min_y && ny <= max_y) {
574 otyp = dogfood(mtmp, obj);
575 /* skip inferior goals */
576 if (otyp > gtyp || otyp == UNDEF)
578 /* avoid cursed items unless starving */
579 if (cursed_object_at(nx, ny)
580 && !(edog->mhpmax_penalty && otyp < MANFOOD))
582 /* skip completely unreachable goals */
583 if (!could_reach_item(mtmp, nx, ny)
584 || !can_reach_location(mtmp, mtmp->mx, mtmp->my, nx, ny))
586 if (otyp < MANFOOD) {
587 if (otyp < gtyp || DDIST(nx, ny) < DDIST(gx, gy)) {
592 } else if (gtyp == UNDEF && in_masters_sight
594 && (!levl[omx][omy].lit || levl[u.ux][u.uy].lit)
595 && (otyp == MANFOOD || m_cansee(mtmp, nx, ny))
596 && edog->apport > rn2(8)
597 && can_carry(mtmp, obj) > 0) {
606 /* follow player if appropriate */
607 if (gtyp == UNDEF || (gtyp != DOGFOOD && gtyp != APPORT
608 && monstermoves < edog->hungrytime)) {
611 if (after && udist <= 4 && gx == u.ux && gy == u.uy)
613 appr = (udist >= 9) ? 1 : (mtmp->mflee) ? -1 : 0;
615 if (!IS_ROOM(levl[u.ux][u.uy].typ) || !rn2(4) || whappr
616 || (dog_has_minvent && rn2(edog->apport)))
619 /* if you have dog food it'll follow you more closely */
621 for (obj = invent; obj; obj = obj->nobj)
622 if (dogfood(mtmp, obj) == DOGFOOD) {
627 appr = 1; /* gtyp != UNDEF */
631 #define FARAWAY (COLNO + 2) /* position outside screen */
632 if (gx == u.ux && gy == u.uy && !in_masters_sight) {
635 cp = gettrack(omx, omy);
642 /* assume master hasn't moved far, and reuse previous goal */
643 if (edog && edog->ogoal.x
644 && (edog->ogoal.x != omx || edog->ogoal.y != omy)) {
649 int fardist = FARAWAY * FARAWAY;
650 gx = gy = FARAWAY; /* random */
651 do_clear_area(omx, omy, 9, wantdoor, (genericptr_t) &fardist);
653 /* here gx == FARAWAY e.g. when dog is in a vault */
654 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 if (curx == mtmp->mux && cury == mtmp->muy)
700 if ((targ = m_at(curx, cury)) != 0) {
701 /* Is the monster visible to the pet? */
702 if ((!targ->minvis || perceives(mtmp->data))
703 && !targ->mundetected)
705 /* If the pet can't see it, it assumes it aint there */
713 find_friends(mtmp, mtarg, maxdist)
714 struct monst *mtmp, *mtarg;
718 int dx = sgn(mtarg->mx - mtmp->mx),
719 dy = sgn(mtarg->my - mtmp->my);
720 int curx = mtarg->mx, cury = mtarg->my;
721 int dist = distmin(mtarg->mx, mtarg->my, mtmp->mx, mtmp->my);
723 for ( ; dist <= maxdist; ++dist) {
727 if (!isok(curx, cury))
730 /* If the pet can't see beyond this point, don't
733 if (!m_cansee(mtmp, curx, cury))
736 /* Does pet think you're here? */
737 if (mtmp->mux == curx && mtmp->muy == cury)
740 pal = m_at(curx, cury);
744 /* Pet won't notice invisible pets */
745 if (!pal->minvis || perceives(mtmp->data))
748 /* Quest leaders and guardians are always seen */
749 if (pal->data->msound == MS_LEADER
750 || pal->data->msound == MS_GUARDIAN)
759 score_targ(mtmp, mtarg)
760 struct monst *mtmp, *mtarg;
764 /* If the monster is confused, normal scoring is disrupted -
765 * anything may happen
768 /* Give 1 in 3 chance of safe breathing even if pet is confused or
769 * if you're on the quest start level */
770 if (!mtmp->mconf || !rn2(3) || Is_qstart(&u.uz)) {
772 aligntyp align1 = A_NONE, align2 = A_NONE; /* For priests, minions */
773 boolean faith1 = TRUE, faith2 = TRUE;
776 align1 = EMIN(mtmp)->min_align;
777 else if (mtmp->ispriest)
778 align1 = EPRI(mtmp)->shralign;
782 align2 = EMIN(mtarg)->min_align; /* MAR */
783 else if (mtarg->ispriest)
784 align2 = EPRI(mtarg)->shralign; /* MAR */
788 /* Never target quest friendlies */
789 if (mtarg->data->msound == MS_LEADER
790 || mtarg->data->msound == MS_GUARDIAN)
792 /* D: Fixed angelic beings using gaze attacks on coaligned priests */
793 if (faith1 && faith2 && align1 == align2 && mtarg->mpeaceful) {
797 /* Is monster adjacent? */
798 if (distmin(mtmp->mx, mtmp->my, mtarg->mx, mtarg->my) <= 1) {
802 /* Is the monster peaceful or tame? */
803 if (/*mtarg->mpeaceful ||*/ mtarg->mtame || mtarg == &youmonst) {
804 /* Pets will never be targeted */
808 /* Is master/pet behind monster? Check up to 15 squares beyond pet. */
809 if (find_friends(mtmp, mtarg, 15)) {
813 /* Target hostile monsters in preference to peaceful ones */
814 if (!mtarg->mpeaceful)
816 /* Is the monster passive? Don't waste energy on it, if so */
817 if (mtarg->data->mattk[0].aatyp == AT_NONE)
819 /* Even weak pets with breath attacks shouldn't take on very
820 low-level monsters. Wasting breath on lichens is ridiculous. */
821 if ((mtarg->m_lev < 2 && mtmp->m_lev > 5)
822 || (mtmp->m_lev > 12 && mtarg->m_lev < mtmp->m_lev - 9
823 && u.ulevel > 8 && mtarg->m_lev < u.ulevel - 7))
825 /* for strength purposes, a vampshifter in weak form (vampire bat,
826 fog cloud, maybe wolf) will attack as if in vampire form;
827 otherwise if won't do much and usually wouldn't suffer enough
828 damage (from counterattacks) to switch back to vampire form;
829 make it be more aggressive by behaving as if stronger */
830 mtmp_lev = mtmp->m_lev;
831 if (is_vampshifter(mtmp) && mtmp->data->mlet != S_VAMPIRE) {
832 /* is_vampshifter() implies (mtmp->cham >= LOW_PM) */
833 mtmp_lev = mons[mtmp->cham].mlevel;
834 /* actual vampire level would range from 1.0*mlvl to 1.5*mlvl */
835 mtmp_lev += rn2(mtmp_lev / 2 + 1);
836 /* we don't expect actual level in weak form to exceed
837 base level of strong form, but handle that if it happens */
838 if (mtmp->m_lev > mtmp_lev)
839 mtmp_lev = mtmp->m_lev;
841 /* And pets will hesitate to attack vastly stronger foes.
842 This penalty will be discarded if master's in trouble. */
843 if (mtarg->m_lev > mtmp_lev + 4L)
844 score -= (mtarg->m_lev - mtmp_lev) * 20L;
845 /* All things being the same, go for the beefiest monster. This
846 bonus should not be large enough to override the pet's aversion
847 to attacking much stronger monsters. */
848 score += mtarg->m_lev * 2 + mtarg->mhp / 3;
850 /* Fuzz factor to make things less predictable when very
851 similar targets are abundant. */
853 /* Pet may decide not to use ranged attack when confused */
854 if (mtmp->mconf && !rn2(3))
859 STATIC_OVL struct monst *
861 struct monst *mtmp; /* Pet */
864 long bestscore = -40000L, currscore;
865 struct monst *best_targ = 0, *temp_targ = 0;
871 /* If the pet is blind, it's not going to see any target */
875 /* Search for any monsters lined up with the pet, within an arbitrary
876 * distance from the pet (7 squares, even along diagonals). Monsters
877 * are assigned scores and the best score is chosen.
879 for (dy = -1; dy < 2; ++dy) {
880 for (dx = -1; dx < 2; ++dx) {
883 /* Traverse the line to find the first monster within 7
884 * squares. Invisible monsters are skipped (if the
885 * pet doesn't have see invisible).
887 temp_targ = find_targ(mtmp, dx, dy, 7);
889 /* Nothing in this line? */
893 /* Decide how attractive the target is */
894 currscore = score_targ(mtmp, temp_targ);
896 if (currscore > bestscore) {
897 bestscore = currscore;
898 best_targ = temp_targ;
903 /* Filter out targets the pet doesn't like */
910 /* return 0 (no move), 1 (move) or 2 (dead) */
912 dog_move(mtmp, after)
913 register struct monst *mtmp;
914 int after; /* this is extra fast monster movement */
916 int omx, omy; /* original mtmp position */
917 int appr, whappr, udist;
919 register struct edog *edog = EDOG(mtmp);
920 struct obj *obj = (struct obj *) 0;
922 boolean has_edog, cursemsg[9], do_eat = FALSE;
923 boolean better_with_displacing = FALSE;
924 xchar nix, niy; /* position mtmp is (considering) moving to */
925 register int nx, ny; /* temporary coordinates */
926 xchar cnt, uncursedcnt, chcnt;
927 int chi = -1, nidist, ndist;
929 long info[9], allowflags;
930 #define GDIST(x, y) (dist2(x, y, gx, gy))
933 * Tame Angels have isminion set and an ispriest structure instead of
934 * an edog structure. Fortunately, guardian Angels need not worry
935 * about mundane things like eating and fetching objects, and can
936 * spend all their energy defending the player. (They are the only
937 * monsters with other structures that can be tame.)
939 has_edog = !mtmp->isminion;
943 if (has_edog && dog_hunger(mtmp, edog))
944 return 2; /* starved */
946 udist = distu(omx, omy);
947 /* Let steeds eat and maybe throw rider during Conflict */
948 if (mtmp == u.usteed) {
949 if (Conflict && !resist(mtmp, RING_CLASS, 0, 0)) {
950 dismount_steed(DISMOUNT_THROWN);
955 /* maybe we tamed him while being swallowed --jgm */
958 nix = omx; /* set before newdogpos */
960 cursemsg[0] = FALSE; /* lint suppression */
961 info[0] = 0; /* ditto */
964 j = dog_invent(mtmp, edog, udist);
968 goto newdogpos; /* eating something */
970 whappr = (monstermoves - edog->whistletime < 5);
974 appr = dog_goal(mtmp, has_edog ? edog : (struct edog *) 0, after, udist,
979 allowflags = ALLOW_M | ALLOW_TRAPS | ALLOW_SSM | ALLOW_SANCT;
980 if (passes_walls(mtmp->data))
981 allowflags |= (ALLOW_ROCK | ALLOW_WALL);
982 if (passes_bars(mtmp->data))
983 allowflags |= ALLOW_BARS;
984 if (throws_rocks(mtmp->data))
985 allowflags |= ALLOW_ROCK;
986 if (is_displacer(mtmp->data))
987 allowflags |= ALLOW_MDISP;
988 if (Conflict && !resist(mtmp, RING_CLASS, 0, 0)) {
989 allowflags |= ALLOW_U;
991 /* Guardian angel refuses to be conflicted; rather,
992 * it disappears, angrily, and sends in some nasties
994 lose_guardian_angel(mtmp);
995 return 2; /* current monster is gone */
998 #if 0 /* [this is now handled in dochug()] */
999 if (!Conflict && !mtmp->mconf
1000 && mtmp == u.ustuck && !sticks(youmonst.data)) {
1001 unstuck(mtmp); /* swallowed case handled above */
1003 You("get released!");
1005 You("
\93®
\82¯
\82é
\82æ
\82¤
\82É
\82È
\82Á
\82½
\81I");
1008 if (!nohands(mtmp->data) && !verysmall(mtmp->data)) {
1009 allowflags |= OPENDOOR;
1010 if (monhaskey(mtmp, TRUE))
1011 allowflags |= UNLOCKDOOR;
1012 /* note: the Wizard and Riders can unlock doors without a key;
1013 they won't use that ability if someone manages to tame them */
1015 if (is_giant(mtmp->data))
1016 allowflags |= BUSTDOOR;
1017 if (tunnels(mtmp->data)
1018 && !Is_rogue_level(&u.uz)) /* same restriction as m_move() */
1019 allowflags |= ALLOW_DIG;
1020 cnt = mfndpos(mtmp, poss, info, allowflags);
1022 /* Normally dogs don't step on cursed items, but if they have no
1023 * other choice they will. This requires checking ahead of time
1024 * to see how many uncursed item squares are around.
1027 for (i = 0; i < cnt; i++) {
1030 if (MON_AT(nx, ny) && !((info[i] & ALLOW_M) || info[i] & ALLOW_MDISP))
1032 if (cursed_object_at(nx, ny))
1037 better_with_displacing = should_displace(mtmp, poss, info, cnt, gx, gy);
1041 nidist = GDIST(nix, niy);
1043 for (i = 0; i < cnt; i++) {
1046 cursemsg[i] = FALSE;
1048 /* if leashed, we drag him along. */
1049 if (mtmp->mleashed && distu(nx, ny) > 4)
1052 /* if a guardian, try to stay close by choice */
1053 if (!has_edog && (j = distu(nx, ny)) > 16 && j >= udist)
1056 if ((info[i] & ALLOW_M) && MON_AT(nx, ny)) {
1058 register struct monst *mtmp2 = m_at(nx, ny);
1060 if ((int) mtmp2->m_lev >= (int) mtmp->m_lev + 2
1061 || (mtmp2->data == &mons[PM_FLOATING_EYE] && rn2(10)
1062 && mtmp->mcansee && haseyes(mtmp->data) && mtmp2->mcansee
1063 && (perceives(mtmp->data) || !mtmp2->minvis))
1064 || (mtmp2->data == &mons[PM_GELATINOUS_CUBE] && rn2(10))
1065 || (max_passive_dmg(mtmp2, mtmp) >= mtmp->mhp)
1066 || ((mtmp->mhp * 4 < mtmp->mhpmax
1067 || mtmp2->data->msound == MS_GUARDIAN
1068 || mtmp2->data->msound == MS_LEADER) && mtmp2->mpeaceful
1070 || (touch_petrifies(mtmp2->data) && !resists_ston(mtmp)))
1074 return 0; /* hit only once each move */
1077 mstatus = mattackm(mtmp, mtmp2);
1079 /* aggressor (pet) died */
1080 if (mstatus & MM_AGR_DIED)
1083 if ((mstatus & MM_HIT) && !(mstatus & MM_DEF_DIED) && rn2(4)
1084 && mtmp2->mlstmv != monstermoves
1085 && !onscary(mtmp->mx, mtmp->my, mtmp2)
1086 /* monnear check needed: long worms hit on tail */
1087 && monnear(mtmp2, mtmp->mx, mtmp->my)) {
1088 mstatus = mattackm(mtmp2, mtmp); /* return attack */
1089 if (mstatus & MM_DEF_DIED)
1094 if ((info[i] & ALLOW_MDISP) && MON_AT(nx, ny)
1095 && better_with_displacing && !undesirable_disp(mtmp, nx, ny)) {
1097 register struct monst *mtmp2 = m_at(nx, ny);
1099 mstatus = mdisplacem(mtmp, mtmp2, FALSE); /* displace monster */
1100 if (mstatus & MM_DEF_DIED)
1106 /* Dog avoids harmful traps, but perhaps it has to pass one
1107 * in order to follow player. (Non-harmful traps do not
1108 * have ALLOW_TRAPS in info[].) The dog only avoids the
1109 * trap if you've seen it, unlike enemies who avoid traps
1110 * if they've seen some trap of that type sometime in the
1111 * past. (Neither behavior is really realistic.)
1115 if ((info[i] & ALLOW_TRAPS) && (trap = t_at(nx, ny))) {
1116 if (mtmp->mleashed) {
1120 /* 1/40 chance of stepping on it anyway, in case
1121 * it has to pass one to follow the player...
1123 if (trap->tseen && rn2(40))
1129 /* dog eschews cursed objects, but likes dog food */
1130 /* (minion isn't interested; `cursemsg' stays FALSE) */
1132 for (obj = level.objects[nx][ny]; obj; obj = obj->nexthere) {
1135 } else if ((otyp = dogfood(mtmp, obj)) < MANFOOD
1137 || edog->hungrytime <= monstermoves)) {
1138 /* Note: our dog likes the food so much that he
1139 * might eat it even when it conceals a cursed object */
1144 cursemsg[i] = FALSE; /* not reluctant */
1148 /* didn't find something to eat; if we saw a cursed item and
1149 aren't being forced to walk on it, usually keep looking */
1150 if (cursemsg[i] && !mtmp->mleashed && uncursedcnt > 0
1151 && rn2(13 * uncursedcnt))
1154 /* lessen the chance of backtracking to previous position(s) */
1155 /* This causes unintended issues for pets trying to follow
1156 the hero. Thus, only run it if not leashed and >5 tiles
1158 if (!mtmp->mleashed && distmin(mtmp->mx, mtmp->my, u.ux, u.uy) > 5) {
1159 k = has_edog ? uncursedcnt : cnt;
1160 for (j = 0; j < MTSZ && j < k - 1; j++)
1161 if (nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y)
1162 if (rn2(MTSZ * (k - j)))
1166 j = ((ndist = GDIST(nx, ny)) - nidist) * appr;
1167 if ((j == 0 && !rn2(++chcnt)) || j < 0
1168 || (j > 0 && !whappr
1169 && ((omx == nix && omy == niy && !rn2(3)) || !rn2(12)))) {
1181 /* Pet hasn't attacked anything but is considering moving -
1182 * now's the time for ranged attacks. Note that the pet can move
1183 * after it performs its ranged attack. Should this be changed?
1186 struct monst *mtarg;
1189 /* How hungry is the pet? */
1190 if (!mtmp->isminion) {
1191 struct edog *dog = EDOG(mtmp);
1193 hungry = (monstermoves > (dog->hungrytime + 300));
1196 /* Identify the best target in a straight line from the pet;
1197 * if there is such a target, we'll let the pet attempt an
1200 mtarg = best_target(mtmp);
1202 /* Hungry pets are unlikely to use breath/spit attacks */
1203 if (mtarg && (!hungry || !rn2(5))) {
1206 if (mtarg == &youmonst) {
1210 mstatus = mattackm(mtmp, mtarg);
1212 /* Shouldn't happen, really */
1213 if (mstatus & MM_AGR_DIED)
1216 /* Allow the targeted nasty to strike back - if
1217 * the targeted beast doesn't have a ranged attack,
1218 * nothing will happen.
1220 if ((mstatus & MM_HIT) && !(mstatus & MM_DEF_DIED)
1221 && rn2(4) && mtarg != &youmonst) {
1223 /* Can monster see? If it can, it can retaliate
1224 * even if the pet is invisible, since it'll see
1225 * the direction from which the ranged attack came;
1226 * if it's blind or unseeing, it can't retaliate
1228 if (mtarg->mcansee && haseyes(mtarg->data)) {
1229 mstatus = mattackm(mtarg, mtmp);
1230 if (mstatus & MM_DEF_DIED)
1239 if (nix != omx || niy != omy) {
1242 if (info[chi] & ALLOW_U) {
1243 if (mtmp->mleashed) { /* play it safe */
1245 pline("%s breaks loose of %s leash!", Monnam(mtmp),
1248 pline("%s
\82Í
\8e©
\95ª
\82É
\82Â
\82¢
\82Ä
\82¢
\82é
\95R
\82ð
\82Í
\82¸
\82µ
\82½
\81I",
1251 m_unleash(mtmp, FALSE);
1253 (void) mattacku(mtmp);
1256 if (!m_in_out_region(mtmp, nix, niy))
1258 if (m_digweapon_check(mtmp, nix,niy))
1261 /* insert a worm_move() if worms ever begin to eat things */
1262 wasseen = canseemon(mtmp);
1263 remove_monster(omx, omy);
1264 place_monster(mtmp, nix, niy);
1265 if (cursemsg[chi] && (wasseen || canseemon(mtmp))) {
1266 /* describe top item of pile, not necessarily cursed item itself;
1267 don't use glyph_at() here--it would return the pet but we want
1268 to know whether an object is remembered at this map location */
1269 struct obj *o = (!Hallucination && level.flags.hero_memory
1270 && glyph_is_object(levl[nix][niy].glyph))
1271 ? vobj_at(nix, niy) : 0;
1272 const char *what = o ? distant_name(o, doname) : something;
1275 pline("%s %s reluctantly over %s.", noit_Monnam(mtmp),
1276 vtense((char *) 0, locomotion(mtmp->data, "step")), what);
1278 pline("%s
\82Í%s
\82Ì
\8fã
\82É
\82¢
\82â
\82¢
\82â
\93®
\82¢
\82½
\81D", noit_Monnam(mtmp), what);
1281 for (j = MTSZ - 1; j > 0; j--)
1282 mtmp->mtrack[j] = mtmp->mtrack[j - 1];
1283 mtmp->mtrack[0].x = omx;
1284 mtmp->mtrack[0].y = omy;
1285 /* We have to know if the pet's going to do a combined eat and
1286 * move before moving it, but it can't eat until after being
1287 * moved. Thus the do_eat flag.
1290 if (dog_eat(mtmp, obj, omx, omy, FALSE) == 2)
1293 } else if (mtmp->mleashed && distu(omx, omy) > 4) {
1294 /* an incredible kludge, but the only way to keep pooch near
1295 * after it spends time eating or in a trap, etc.
1299 nx = sgn(omx - u.ux);
1300 ny = sgn(omy - u.uy);
1303 if (goodpos(cc.x, cc.y, mtmp, 0))
1307 for (j = (i + 7) % 8; j < (i + 1) % 8; j++) {
1309 if (goodpos(cc.x, cc.y, mtmp, 0))
1312 for (j = (i + 6) % 8; j < (i + 2) % 8; j++) {
1314 if (goodpos(cc.x, cc.y, mtmp, 0))
1320 if (!m_in_out_region(mtmp, nix, niy))
1322 remove_monster(mtmp->mx, mtmp->my);
1323 place_monster(mtmp, cc.x, cc.y);
1330 /* check if a monster could pick up objects from a location */
1332 could_reach_item(mon, nx, ny)
1336 if ((!is_pool(nx, ny) || is_swimmer(mon->data))
1337 && (!is_lava(nx, ny) || likes_lava(mon->data))
1338 && (!sobj_at(BOULDER, nx, ny) || throws_rocks(mon->data)))
1343 /* Hack to prevent a dog from being endlessly stuck near an object that
1344 * it can't reach, such as caught in a teleport scroll niche. It recursively
1345 * checks to see if the squares in between are good. The checking could be
1346 * a little smarter; a full check would probably be useful in m_move() too.
1347 * Since the maximum food distance is 5, this should never be more than 5
1351 can_reach_location(mon, mx, my, fx, fy)
1353 xchar mx, my, fx, fy;
1358 if (mx == fx && my == fy)
1361 return FALSE; /* should not happen */
1363 dist = dist2(mx, my, fx, fy);
1364 for (i = mx - 1; i <= mx + 1; i++) {
1365 for (j = my - 1; j <= my + 1; j++) {
1368 if (dist2(i, j, fx, fy) >= dist)
1370 if (IS_ROCK(levl[i][j].typ) && !passes_walls(mon->data)
1371 && (!may_dig(i, j) || !tunnels(mon->data)))
1373 if (IS_DOOR(levl[i][j].typ)
1374 && (levl[i][j].doormask & (D_CLOSED | D_LOCKED)))
1376 if (!could_reach_item(mon, i, j))
1378 if (can_reach_location(mon, i, j, fx, fy))
1385 /* do_clear_area client */
1387 wantdoor(x, y, distance)
1389 genericptr_t distance;
1391 int ndist, *dist_ptr = (int *) distance;
1393 if (*dist_ptr > (ndist = distu(x, y))) {
1400 static struct qmchoices {
1401 int mndx; /* type of pet, 0 means any */
1402 char mlet; /* symbol of pet, 0 means any */
1403 unsigned mappearance; /* mimic this */
1404 uchar m_ap_type; /* what is the thing it is mimicing? */
1406 /* Things that some pets might be thinking about at the time */
1407 { PM_LITTLE_DOG, 0, PM_KITTEN, M_AP_MONSTER },
1408 { PM_DOG, 0, PM_HOUSECAT, M_AP_MONSTER },
1409 { PM_LARGE_DOG, 0, PM_LARGE_CAT, M_AP_MONSTER },
1410 { PM_KITTEN, 0, PM_LITTLE_DOG, M_AP_MONSTER },
1411 { PM_HOUSECAT, 0, PM_DOG, M_AP_MONSTER },
1412 { PM_LARGE_CAT, 0, PM_LARGE_DOG, M_AP_MONSTER },
1413 { PM_HOUSECAT, 0, PM_GIANT_RAT, M_AP_MONSTER },
1415 M_AP_FURNITURE }, /* sorry, no fire hydrants in NetHack */
1416 { 0, 0, TRIPE_RATION, M_AP_OBJECT }, /* leave this at end */
1420 finish_meating(mtmp)
1424 if (M_AP_TYPE(mtmp) && mtmp->mappearance && mtmp->cham == NON_PM) {
1425 /* was eating a mimic and now appearance needs resetting */
1426 mtmp->m_ap_type = 0;
1427 mtmp->mappearance = 0;
1428 newsym(mtmp->mx, mtmp->my);
1436 int idx = 0, trycnt = 5, spotted;
1439 if (Protection_from_shape_changers || !mtmp->meating)
1442 /* with polymorph, the steed's equipment would be re-checked and its
1443 saddle would come off, triggering DISMOUNT_FELL, but mimicking
1444 doesn't impact monster's equipment; normally DISMOUNT_POLY is for
1445 rider taking on an unsuitable shape, but its message works fine
1446 for this and also avoids inflicting damage during forced dismount;
1447 do this before changing so that dismount refers to original shape */
1448 if (mtmp == u.usteed)
1449 dismount_steed(DISMOUNT_POLY);
1452 idx = rn2(SIZE(qm));
1453 if (qm[idx].mndx != 0 && monsndx(mtmp->data) == qm[idx].mndx)
1455 if (qm[idx].mlet != 0 && mtmp->data->mlet == qm[idx].mlet)
1457 if (qm[idx].mndx == 0 && qm[idx].mlet == 0)
1459 } while (--trycnt > 0);
1463 Strcpy(buf, mon_nam(mtmp));
1464 spotted = canspotmon(mtmp);
1466 mtmp->m_ap_type = qm[idx].m_ap_type;
1467 mtmp->mappearance = qm[idx].mappearance;
1469 if (spotted || cansee(mtmp->mx, mtmp->my) || canspotmon(mtmp)) {
1470 /* this isn't quite right; if sensing a monster without being
1471 able to see its location, you really shouldn't be told you
1472 sense it becoming furniture or an object that you can't see
1473 (on the other hand, perhaps you're sensing a brief glimpse
1474 of its mind as it changes form) */
1475 newsym(mtmp->mx, mtmp->my);
1477 You("%s %s %sappear%s where %s was!",
1478 cansee(mtmp->mx, mtmp->my) ? "see" : "sense that",
1479 (M_AP_TYPE(mtmp) == M_AP_FURNITURE)
1480 ? an(defsyms[mtmp->mappearance].explanation)
1481 : (M_AP_TYPE(mtmp) == M_AP_OBJECT
1482 && OBJ_DESCR(objects[mtmp->mappearance]))
1483 ? an(OBJ_DESCR(objects[mtmp->mappearance]))
1484 : (M_AP_TYPE(mtmp) == M_AP_OBJECT
1485 && OBJ_NAME(objects[mtmp->mappearance]))
1486 ? an(OBJ_NAME(objects[mtmp->mappearance]))
1487 : (M_AP_TYPE(mtmp) == M_AP_MONSTER)
1488 ? an(mons[mtmp->mappearance].mname)
1490 cansee(mtmp->mx, mtmp->my) ? "" : "has ",
1491 cansee(mtmp->mx, mtmp->my) ? "" : "ed",
1494 You("%s
\82ª
\82 \82Á
\82½
\82Æ
\82±
\82ë
\82É%s
\82ª
\8c»
\82ê
\82½
\82Ì%s
\81I",
1496 (mtmp->m_ap_type == M_AP_FURNITURE)
1497 ? an(defsyms[mtmp->mappearance].explanation)
1498 : (mtmp->m_ap_type == M_AP_OBJECT
1499 && OBJ_DESCR(objects[mtmp->mappearance]))
1500 ? an(OBJ_DESCR(objects[mtmp->mappearance]))
1501 : (mtmp->m_ap_type == M_AP_OBJECT
1502 && OBJ_NAME(objects[mtmp->mappearance]))
1503 ? an(OBJ_NAME(objects[mtmp->mappearance]))
1504 : (mtmp->m_ap_type == M_AP_MONSTER)
1505 ? an(mons[mtmp->mappearance].mname)
1507 cansee(mtmp->mx, mtmp->my) ? "
\82ð
\8c©
\82½" : "
\82É
\8bC
\82Ã
\82¢
\82½");
1509 display_nhwindow(WIN_MAP, TRUE);