1 /* NetHack 3.6 dog.c $NHDT-Date: 1554580624 2019/04/06 19:57:04 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.85 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Robert Patrick Rankin, 2011. */
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-2022 */
9 /* JNetHack may be freely redistributed. See license for details. */
13 STATIC_DCL int NDECL(pet_type);
20 mtmp->mextra = newmextra();
22 EDOG(mtmp) = (struct edog *) alloc(sizeof(struct edog));
23 (void) memset((genericptr_t) EDOG(mtmp), 0, sizeof(struct edog));
31 if (mtmp->mextra && EDOG(mtmp)) {
32 free((genericptr_t) EDOG(mtmp));
33 EDOG(mtmp) = (struct edog *) 0;
40 register struct monst *mtmp;
42 mtmp->mtame = is_domestic(mtmp->data) ? 10 : 5;
45 set_malign(mtmp); /* recalc alignment now that it's tamed */
48 EDOG(mtmp)->droptime = 0;
49 EDOG(mtmp)->dropdist = 10000;
50 EDOG(mtmp)->apport = ACURR(A_CHA);
51 EDOG(mtmp)->whistletime = 0;
52 EDOG(mtmp)->hungrytime = 1000 + monstermoves;
53 EDOG(mtmp)->ogoal.x = -1; /* force error if used before set */
54 EDOG(mtmp)->ogoal.y = -1;
55 EDOG(mtmp)->abuse = 0;
56 EDOG(mtmp)->revivals = 0;
57 EDOG(mtmp)->mhpmax_penalty = 0;
58 EDOG(mtmp)->killed_by_u = 0;
64 if (urole.petnum != NON_PM)
66 else if (preferred_pet == 'c')
68 else if (preferred_pet == 'd')
71 return rn2(2) ? PM_KITTEN : PM_LITTLE_DOG;
75 make_familiar(otmp, x, y, quietly)
76 register struct obj *otmp;
81 struct monst *mtmp = 0;
82 int chance, trycnt = 100;
85 if (otmp) { /* figurine; otherwise spell */
86 int mndx = otmp->corpsenm;
89 /* activating a figurine provides one way to exceed the
90 maximum number of the target critter created--unless
91 it has a special limit (erinys, Nazgul) */
92 if ((mvitals[mndx].mvflags & G_EXTINCT)
93 && mbirth_limit(mndx) != MAXMONNO) {
95 /* have just been given "You <do something with>
96 the figurine and it transforms." message */
98 pline("... into a pile of dust.");
100 pline("
\81D
\81D
\81D
\82»
\82µ
\82Ä
\82¿
\82è
\82Ì
\8eR
\82É
\82È
\82Á
\82½
\81D");
101 break; /* mtmp is null */
103 } else if (!rn2(3)) {
104 pm = &mons[pet_type()];
110 There("seems to be nothing available for a familiar.");
112 pline("
\89º
\96l
\82Í
\8c»
\82ê
\82È
\82©
\82Á
\82½
\81D");
117 mtmp = makemon(pm, x, y, MM_EDOG | MM_IGNOREWATER | NO_MINVENT);
118 if (otmp && !mtmp) { /* monster was genocided or square occupied */
121 pline_The("figurine writhes and then shatters into pieces!");
123 pline("
\90l
\8c`
\82Í
\82à
\82ª
\82«
\81C
\82
\82¾
\82¯
\8eU
\82Á
\82½
\81I");
126 } while (!mtmp && --trycnt > 0);
129 return (struct monst *) 0;
131 if (is_pool(mtmp->mx, mtmp->my) && minliquid(mtmp))
132 return (struct monst *) 0;
136 if (otmp) { /* figurine; resulting monster might not become a pet */
137 chance = rn2(10); /* 0==tame, 1==peaceful, 2==hostile */
139 chance = otmp->blessed ? 0 : !otmp->cursed ? 1 : 2;
140 /* 0,1,2: b=80%,10,10; nc=10%,80,10; c=10%,10,80 */
142 mtmp->mtame = 0; /* not tame after all */
143 if (chance == 2) { /* hostile (cursed figurine) */
146 You("get a bad feeling about this.");
148 You("
\8c\99\82È
\97\
\8a´
\82ª
\82µ
\82½
\81D");
153 /* if figurine has been named, give same name to the monster */
155 mtmp = christen_monst(mtmp, ONAME(otmp));
157 set_malign(mtmp); /* more alignment changes */
158 newsym(mtmp->mx, mtmp->my);
160 /* must wield weapon immediately since pets will otherwise drop it */
161 if (mtmp->mtame && attacktype(mtmp->data, AT_WEAP)) {
162 mtmp->weapon_check = NEED_HTH_WEAPON;
163 (void) mon_wield_item(mtmp);
171 register struct monst *mtmp;
172 register struct obj *otmp;
175 static int petname_used = 0;
177 if (preferred_pet == 'n')
178 return ((struct monst *) 0);
180 pettype = pet_type();
181 if (pettype == PM_LITTLE_DOG)
183 else if (pettype == PM_PONY)
188 /* default pet names */
189 if (!*petname && pettype == PM_LITTLE_DOG) {
190 /* All of these names were for dogs. */
191 if (Role_if(PM_CAVEMAN))
193 petname = "Slasher"; /* The Warrior */
195 petname = "
\83X
\83\89\83b
\83V
\83\83\81[";
197 if (Role_if(PM_SAMURAI))
199 petname = "Hachi"; /* Shibuya Station */
201 petname = "
\83n
\83`
\8cö";
203 if (Role_if(PM_BARBARIAN))
205 petname = "Idefix"; /* Obelix */
207 petname = "
\83C
\83f
\83t
\83B
\83N
\83X";
209 if (Role_if(PM_RANGER))
211 petname = "Sirius"; /* Orion's dog */
213 petname = "
\83V
\83\8a\83E
\83X";
217 mtmp = makemon(&mons[pettype], u.ux, u.uy, MM_EDOG);
220 return ((struct monst *) 0); /* pets were genocided */
222 context.startingpet_mid = mtmp->m_id;
223 /* Horses already wear a saddle */
224 if (pettype == PM_PONY && !!(otmp = mksobj(SADDLE, TRUE, FALSE))) {
225 otmp->dknown = otmp->bknown = otmp->rknown = 1;
226 put_saddle_on_mon(otmp, mtmp);
229 if (!petname_used++ && *petname)
230 mtmp = christen_monst(mtmp, petname);
236 /* record `last move time' for all monsters prior to level save so that
237 mon_arrive() can catch up for lost time when they're restored later */
243 /* monst->mlstmv used to be updated every time `monst' actually moved,
244 but that is no longer the case so we just do a blanket assignment */
245 for (mon = fmon; mon; mon = mon->nmon) {
246 if (DEADMONSTER(mon))
248 mon->mlstmv = monstermoves;
255 register struct monst *mtmp, *mtmp0, *mtmp2;
259 * First, scan migrating_mons for shopkeepers who want to dismiss Kops,
260 * and scan mydogs for shopkeepers who want to retain kops.
261 * Second, dismiss kops if warranted, making more room for arrival.
262 * Third, place monsters accompanying the hero.
263 * Last, place migrating monsters coming to this level.
265 * Hero might eventually be displaced (due to the third step, but
266 * occurring later), which is the main reason to do the second step
267 * sooner (in turn necessitating the first step, rather than combining
268 * the list scans with monster placement).
271 /* check for returning shk(s) */
272 for (mtmp = migrating_mons; mtmp; mtmp = mtmp->nmon) {
273 if (mtmp->mux != u.uz.dnum || mtmp->muy != u.uz.dlevel)
276 if (ESHK(mtmp)->dismiss_kops) {
277 if (dismissKops == 0)
279 ESHK(mtmp)->dismiss_kops = FALSE; /* reset */
280 } else if (!mtmp->mpeaceful) {
281 /* an unpacified shk is returning; don't dismiss kops
282 even if another pacified one is willing to do so */
284 /* [keep looping; later monsters might need ESHK reset] */
288 /* make the same check for mydogs */
289 for (mtmp = mydogs; mtmp && dismissKops >= 0; mtmp = mtmp->nmon) {
291 /* hostile shk might accompany hero [ESHK(mtmp)->dismiss_kops
292 can't be set here; it's only used for migrating_mons] */
293 if (!mtmp->mpeaceful)
298 /* when a hostile shopkeeper chases hero to another level
299 and then gets paid off there, get rid of summoned kops
300 here now that he has returned to his shop level */
302 make_happy_shoppers(TRUE);
304 /* place pets and/or any other monsters who accompany hero */
305 while ((mtmp = mydogs) != 0) {
307 mon_arrive(mtmp, TRUE);
310 /* time for migrating monsters to arrive;
311 monsters who belong on this level but fail to arrive get put
312 back onto the list (at head), so traversing it is tricky */
313 for (mtmp = migrating_mons; mtmp; mtmp = mtmp2) {
315 if (mtmp->mux == u.uz.dnum && mtmp->muy == u.uz.dlevel) {
316 /* remove mtmp from migrating_mons list */
317 if (mtmp == migrating_mons) {
318 migrating_mons = mtmp->nmon;
320 for (mtmp0 = migrating_mons; mtmp0; mtmp0 = mtmp0->nmon)
321 if (mtmp0->nmon == mtmp) {
322 mtmp0->nmon = mtmp->nmon;
326 panic("losedogs: can't find migrating mon");
328 mon_arrive(mtmp, FALSE);
333 /* called from resurrect() in addition to losedogs() */
335 mon_arrive(mtmp, with_you)
340 xchar xlocale, ylocale, xyloc, xyflags, wander;
342 boolean failed_to_place = FALSE;
347 set_residency(mtmp, FALSE);
349 num_segs = mtmp->wormno;
350 /* baby long worms have no tail so don't use is_longworm() */
351 if (mtmp->data == &mons[PM_LONG_WORM]) {
352 mtmp->wormno = get_wormno();
354 initworm(mtmp, num_segs);
358 /* some monsters might need to do something special upon arrival
359 _after_ the current level has been fully set up; see dochug() */
360 mtmp->mstrategy |= STRAT_ARRIVE;
362 /* make sure mnexto(rloc_to(set_apparxy())) doesn't use stale data */
363 mtmp->mux = u.ux, mtmp->muy = u.uy;
364 xyloc = mtmp->mtrack[0].x;
365 xyflags = mtmp->mtrack[0].y;
366 xlocale = mtmp->mtrack[1].x;
367 ylocale = mtmp->mtrack[1].y;
368 memset(mtmp->mtrack, 0, sizeof mtmp->mtrack);
370 if (mtmp == u.usteed)
371 return; /* don't place steed on the map */
373 /* When a monster accompanies you, sometimes it will arrive
374 at your intended destination and you'll end up next to
375 that spot. This code doesn't control the final outcome;
376 goto_level(do.c) decides who ends up at your target spot
377 when there is a monster there too. */
378 if (!MON_AT(u.ux, u.uy)
379 && !rn2(mtmp->mtame ? 10 : mtmp->mpeaceful ? 5 : 2))
380 rloc_to(mtmp, u.ux, u.uy);
386 * The monster arrived on this level independently of the player.
387 * Its coordinate fields were overloaded for use as flags that
388 * specify its final destination.
391 if (mtmp->mlstmv < monstermoves - 1L) {
392 /* heal monster for time spent in limbo */
393 long nmv = monstermoves - 1L - mtmp->mlstmv;
395 mon_catchup_elapsed_time(mtmp, nmv);
396 mtmp->mlstmv = monstermoves - 1L;
398 /* let monster move a bit on new level (see placement code below) */
399 wander = (xchar) min(nmv, 8);
404 case MIGR_APPROX_XY: /* {x,y}locale set above */
410 xlocale = u.ux, ylocale = u.uy;
413 xlocale = xupstair, ylocale = yupstair;
415 case MIGR_STAIRS_DOWN:
416 xlocale = xdnstair, ylocale = ydnstair;
419 xlocale = xupladder, ylocale = yupladder;
421 case MIGR_LADDER_DOWN:
422 xlocale = xdnladder, ylocale = ydnladder;
425 xlocale = sstairs.sx, ylocale = sstairs.sy;
428 if (In_endgame(&u.uz)) {
429 /* there is no arrival portal for endgame levels */
430 /* BUG[?]: for simplicity, this code relies on the fact
431 that we know that the current endgame levels always
432 build upwards and never have any exclusion subregion
433 inside their TELEPORT_REGION settings. */
434 xlocale = rn1(updest.hx - updest.lx + 1, updest.lx);
435 ylocale = rn1(updest.hy - updest.ly + 1, updest.ly);
438 /* find the arrival portal */
439 for (t = ftrap; t; t = t->ntrap)
440 if (t->ttyp == MAGIC_PORTAL)
443 xlocale = t->tx, ylocale = t->ty;
446 impossible("mon_arrive: no corresponding portal?");
450 xlocale = ylocale = 0;
454 if ((mtmp->mspare1 & MIGR_LEFTOVERS) != 0L) {
455 /* Pick up the rest of the MIGR_TO_SPECIES objects */
457 deliver_obj_to_mon(mtmp, 0, DF_ALL);
460 if (xlocale && wander) {
461 /* monster moved a bit; pick a nearby location */
462 /* mnearto() deals w/stone, et al */
463 char *r = in_rooms(xlocale, ylocale, 0);
468 /* somexy() handles irregular rooms */
469 if (somexy(&rooms[*r - ROOMOFFSET], &c))
470 xlocale = c.x, ylocale = c.y;
472 xlocale = ylocale = 0;
473 } else { /* not in a room */
476 i = max(1, xlocale - wander);
477 j = min(COLNO - 1, xlocale + wander);
478 xlocale = rn1(j - i, i);
479 i = max(0, ylocale - wander);
480 j = min(ROWNO - 1, ylocale + wander);
481 ylocale = rn1(j - i, i);
485 mtmp->mx = 0; /*(already is 0)*/
488 failed_to_place = !mnearto(mtmp, xlocale, ylocale, FALSE);
490 failed_to_place = !rloc(mtmp, TRUE);
493 m_into_limbo(mtmp); /* try again next time hero comes to this level */
496 /* heal monster for time spent elsewhere */
498 mon_catchup_elapsed_time(mtmp, nmv)
500 long nmv; /* number of moves */
502 int imv = 0; /* avoid zillions of casts and lint warnings */
504 #if defined(DEBUG) || (NH_DEVEL_STATUS != NH_STATUS_RELEASED)
506 if (nmv < 0L) { /* crash likely... */
507 panic("catchup from future time?");
510 } else if (nmv == 0L) { /* safe, but should'nt happen */
511 impossible("catchup from now?");
514 if (nmv >= LARGEST_INT) /* paranoia */
515 imv = LARGEST_INT - 1;
519 /* might stop being afraid, blind or frozen */
520 /* set to 1 and allow final decrement in movemon() */
521 if (mtmp->mblinded) {
522 if (imv >= (int) mtmp->mblinded)
525 mtmp->mblinded -= imv;
528 if (imv >= (int) mtmp->mfrozen)
531 mtmp->mfrozen -= imv;
533 if (mtmp->mfleetim) {
534 if (imv >= (int) mtmp->mfleetim)
537 mtmp->mfleetim -= imv;
540 /* might recover from temporary trouble */
541 if (mtmp->mtrapped && rn2(imv + 1) > 40 / 2)
543 if (mtmp->mconf && rn2(imv + 1) > 50 / 2)
545 if (mtmp->mstun && rn2(imv + 1) > 10 / 2)
548 /* might finish eating or be able to use special ability again */
549 if (imv > mtmp->meating)
550 finish_meating(mtmp);
552 mtmp->meating -= imv;
553 if (imv > mtmp->mspec_used)
554 mtmp->mspec_used = 0;
556 mtmp->mspec_used -= imv;
558 /* reduce tameness for every 150 moves you are separated */
560 int wilder = (imv + 75) / 150;
561 if (mtmp->mtame > wilder)
562 mtmp->mtame -= wilder; /* less tame */
563 else if (mtmp->mtame > rn2(wilder))
564 mtmp->mtame = 0; /* untame */
566 mtmp->mtame = mtmp->mpeaceful = 0; /* hostile! */
568 /* check to see if it would have died as a pet; if so, go wild instead
569 * of dying the next time we call dog_move()
571 if (mtmp->mtame && !mtmp->isminion
572 && (carnivorous(mtmp->data) || herbivorous(mtmp->data))) {
573 struct edog *edog = EDOG(mtmp);
575 if ((monstermoves > edog->hungrytime + 500 && mtmp->mhp < 3)
576 || (monstermoves > edog->hungrytime + 750))
577 mtmp->mtame = mtmp->mpeaceful = 0;
580 if (!mtmp->mtame && mtmp->mleashed) {
581 /* leashed monsters should always be with hero, consequently
582 never losing any time to be accounted for later */
583 impossible("catching up for leashed monster?");
584 m_unleash(mtmp, FALSE);
587 /* recover lost hit points */
588 if (!regenerates(mtmp->data))
590 if (mtmp->mhp + imv >= mtmp->mhpmax)
591 mtmp->mhp = mtmp->mhpmax;
596 /* called when you move to another level */
599 boolean pets_only; /* true for ascension or final escape */
601 register struct monst *mtmp, *mtmp2;
602 register struct obj *obj;
606 for (mtmp = fmon; mtmp; mtmp = mtmp2) {
608 if (DEADMONSTER(mtmp))
612 continue; /* reject non-pets */
613 /* don't block pets from accompanying hero's dungeon
614 escape or ascension simply due to mundane trifles;
615 unlike level change for steed, don't bother trying
616 to achieve a normal trap escape first */
623 if (((monnear(mtmp, u.ux, u.uy) && levl_follower(mtmp))
624 /* the wiz will level t-port from anywhere to chase
625 the amulet; if you don't have it, will chase you
626 only if in range. -3. */
627 || (u.uhave.amulet && mtmp->iswiz))
628 && ((!mtmp->msleeping && mtmp->mcanmove)
629 /* eg if level teleport or new trap, steed has no control
630 to avoid following */
631 || (mtmp == u.usteed))
632 /* monster won't follow if it hasn't noticed you yet */
633 && !(mtmp->mstrategy & STRAT_WAITFORU)) {
636 (void) mintrap(mtmp); /* try to escape */
637 if (mtmp == u.usteed) {
638 /* make sure steed is eligible to accompany hero */
639 mtmp->mtrapped = 0; /* escape trap */
640 mtmp->meating = 0; /* terminate eating */
641 mdrop_special_objs(mtmp); /* drop Amulet */
642 } else if (mtmp->meating || mtmp->mtrapped) {
645 pline("%s is still %s.", Monnam(mtmp),
646 mtmp->meating ? "eating" : "trapped");
648 pline("%s
\82Í
\82Ü
\82¾%s
\81D", Monnam(mtmp),
649 mtmp->meating ? "
\90H
\82×
\82Ä
\82¢
\82é" : "ã©
\82É
\82©
\82©
\82Á
\82½
\82Ü
\82Ü
\82¾");
652 } else if (mon_has_amulet(mtmp)) {
655 pline("%s seems very disoriented for a moment.",
657 pline("%s
\82Í
\88ê
\8fu
\95û
\8cü
\8a´
\8ao
\82ð
\8e¸
\82Á
\82½
\82æ
\82¤
\82¾
\81D",
662 if (mtmp->mleashed) {
664 pline("%s leash suddenly comes loose.",
666 ? (mtmp->female ? "Her" : "His")
669 pline("%s
\82É
\8c\8b\82Î
\82ê
\82½
\95R
\82Í
\93Ë
\91R
\82ä
\82é
\82ñ
\82¾
\81D",
671 ? (mtmp->female ? "
\94Þ
\8f\97" : "
\94Þ")
672 : "
\82»
\82Ì
\90¶
\95¨");
674 m_unleash(mtmp, FALSE);
676 if (mtmp == u.usteed) {
677 /* can't happen unless someone makes a change
678 which scrambles the stay_behind logic above */
679 impossible("steed left behind?");
680 dismount_steed(DISMOUNT_GENERIC);
685 set_residency(mtmp, TRUE);
689 /* NOTE: worm is truncated to # segs = max wormno size */
690 cnt = count_wsegs(mtmp);
691 num_segs = min(cnt, MAX_NUM_WORMS - 1);
693 place_monster(mtmp, mtmp->mx, mtmp->my);
697 /* set minvent's obj->no_charge to 0 */
698 for (obj = mtmp->minvent; obj; obj = obj->nobj) {
699 if (Has_contents(obj))
700 picked_container(obj); /* does the right thing */
704 relmon(mtmp, &mydogs); /* move it from map to mydogs */
705 mtmp->mx = mtmp->my = 0; /* avoid mnexto()/MON_AT() problem */
706 mtmp->wormno = num_segs;
707 mtmp->mlstmv = monstermoves;
708 } else if (mtmp->iswiz) {
709 /* we want to be able to find him when his next resurrection
710 chance comes up, but have him resume his present location
711 if player returns to this level before that time */
712 migrate_to_level(mtmp, ledger_no(&u.uz), MIGR_EXACT_XY,
714 } else if (mtmp->mleashed) {
715 /* this can happen if your quest leader ejects you from the
716 "home" level while a leashed pet isn't next to you */
718 pline("%s leash goes slack.", s_suffix(Monnam(mtmp)));
720 pline("%s
\82É
\8c\8b\82Î
\82ê
\82½
\95R
\82Í
\82½
\82é
\82ñ
\82¾
\81D", Monnam(mtmp));
721 m_unleash(mtmp, FALSE);
727 migrate_to_level(mtmp, tolev, xyloc, cc)
728 register struct monst *mtmp;
729 xchar tolev; /* destination level */
730 xchar xyloc; /* MIGR_xxx destination xy location: */
731 coord *cc; /* optional destination coordinates */
736 int num_segs = 0; /* count of worm segments */
739 set_residency(mtmp, TRUE);
742 int cnt = count_wsegs(mtmp);
744 /* **** NOTE: worm is truncated to # segs = max wormno size **** */
745 num_segs = min(cnt, MAX_NUM_WORMS - 1); /* used below */
746 wormgone(mtmp); /* destroys tail and takes head off map */
747 /* there used to be a place_monster() here for the relmon() below,
748 but it doesn't require the monster to be on the map anymore */
751 /* set minvent's obj->no_charge to 0 */
752 for (obj = mtmp->minvent; obj; obj = obj->nobj) {
753 if (Has_contents(obj))
754 picked_container(obj); /* does the right thing */
758 if (mtmp->mleashed) {
760 m_unleash(mtmp, TRUE);
762 relmon(mtmp, &migrating_mons); /* move it from map to migrating_mons */
764 new_lev.dnum = ledger_to_dnum((xchar) tolev);
765 new_lev.dlevel = ledger_to_dlev((xchar) tolev);
766 /* overload mtmp->[mx,my], mtmp->[mux,muy], and mtmp->mtrack[] as */
767 /* destination codes (setup flag bits before altering mx or my) */
768 xyflags = (depth(&new_lev) < depth(&u.uz)); /* 1 => up */
769 if (In_W_tower(mtmp->mx, mtmp->my, &u.uz))
771 mtmp->wormno = num_segs;
772 mtmp->mlstmv = monstermoves;
773 mtmp->mtrack[1].x = cc ? cc->x : mtmp->mx;
774 mtmp->mtrack[1].y = cc ? cc->y : mtmp->my;
775 mtmp->mtrack[0].x = xyloc;
776 mtmp->mtrack[0].y = xyflags;
777 mtmp->mux = new_lev.dnum;
778 mtmp->muy = new_lev.dlevel;
779 mtmp->mx = mtmp->my = 0; /* this implies migration */
780 if (mtmp == context.polearm.hitmon)
781 context.polearm.hitmon = (struct monst *) 0;
784 /* return quality of food; the lower the better */
785 /* fungi will eat even tainted food */
789 register struct obj *obj;
791 struct permonst *mptr = mon->data, *fptr = 0;
792 boolean carni = carnivorous(mptr), herbi = herbivorous(mptr),
795 if (is_quest_artifact(obj) || obj_resists(obj, 0, 95))
796 return obj->cursed ? TABU : APPORT;
798 switch (obj->oclass) {
800 if (obj->otyp == CORPSE || obj->otyp == TIN || obj->otyp == EGG)
801 fptr = &mons[obj->corpsenm];
803 if (obj->otyp == CORPSE && is_rider(fptr))
805 if ((obj->otyp == CORPSE || obj->otyp == EGG) && touch_petrifies(fptr)
806 && !resists_ston(mon))
808 if (!carni && !herbi)
809 return obj->cursed ? UNDEF : APPORT;
811 /* a starving pet will eat almost anything */
812 starving = (mon->mtame && !mon->isminion
813 && EDOG(mon)->mhpmax_penalty);
814 /* even carnivores will eat carrots if they're temporarily blind */
815 mblind = (!mon->mcansee && haseyes(mon->data));
817 /* ghouls prefer old corpses and unhatchable eggs, yum!
818 they'll eat fresh non-veggy corpses and hatchable eggs
819 when starving; they never eat stone-to-flesh'd meat */
820 if (mptr == &mons[PM_GHOUL]) {
821 if (obj->otyp == CORPSE)
822 return (peek_at_iced_corpse_age(obj) + 50L <= monstermoves
823 && fptr != &mons[PM_LIZARD]
824 && fptr != &mons[PM_LICHEN])
826 : (starving && !vegan(fptr))
829 if (obj->otyp == EGG)
830 return stale_egg(obj) ? CADAVER : starving ? ACCFOOD : POISON;
839 case HUGE_CHUNK_OF_MEAT:
840 return carni ? DOGFOOD : MANFOOD;
842 return carni ? CADAVER : MANFOOD;
844 if ((peek_at_iced_corpse_age(obj) + 50L <= monstermoves
845 && obj->corpsenm != PM_LIZARD && obj->corpsenm != PM_LICHEN
846 && mptr->mlet != S_FUNGUS)
847 || (acidic(fptr) && !resists_acid(mon))
848 || (poisonous(fptr) && !resists_poison(mon)))
850 /* turning into slime is preferable to starvation */
851 else if (fptr == &mons[PM_GREEN_SLIME] && !slimeproof(mon->data))
852 return starving ? ACCFOOD : POISON;
853 else if (vegan(fptr))
854 return herbi ? CADAVER : MANFOOD;
855 /* most humanoids will avoid cannibalism unless starving;
856 arbitrary: elves won't eat other elves even then */
857 else if (humanoid(mptr) && same_race(mptr, fptr)
858 && (!is_undead(mptr) && fptr->mlet != S_KOBOLD
859 && fptr->mlet != S_ORC && fptr->mlet != S_OGRE))
860 return (starving && carni && !is_elf(mptr)) ? ACCFOOD : TABU;
862 return carni ? CADAVER : MANFOOD;
863 case CLOVE_OF_GARLIC:
864 return (is_undead(mptr) || is_vampshifter(mon))
866 : (herbi || starving)
870 return metallivorous(mptr) ? ACCFOOD : MANFOOD;
872 return herbi ? DOGFOOD : starving ? ACCFOOD : MANFOOD;
874 return (herbi || mblind) ? DOGFOOD : starving ? ACCFOOD : MANFOOD;
876 return (mptr->mlet == S_YETI && herbi)
877 ? DOGFOOD /* for monkey and ape (tameable), sasquatch */
878 : (herbi || starving)
884 return (obj->otyp > SLIME_MOLD) ? (carni ? ACCFOOD : MANFOOD)
885 : (herbi ? ACCFOOD : MANFOOD);
888 if (obj->otyp == AMULET_OF_STRANGULATION
889 || obj->otyp == RIN_SLOW_DIGESTION)
891 if (mon_hates_silver(mon) && objects[obj->otyp].oc_material == SILVER)
893 if (mptr == &mons[PM_GELATINOUS_CUBE] && is_organic(obj))
895 if (metallivorous(mptr) && is_metallic(obj)
896 && (is_rustprone(obj) || mptr != &mons[PM_RUST_MONSTER])) {
897 /* Non-rustproofed ferrous based metals are preferred. */
898 return (is_rustprone(obj) && !obj->oerodeproof) ? DOGFOOD
902 && obj->oclass != BALL_CLASS
903 && obj->oclass != CHAIN_CLASS)
912 * With the separate mextra structure added in 3.6.x this always
913 * operates on the original mtmp. It now returns TRUE if the taming
918 register struct monst *mtmp;
919 register struct obj *obj;
921 /* The Wiz, Medusa and the quest nemeses aren't even made peaceful. */
922 if (mtmp->iswiz || mtmp->data == &mons[PM_MEDUSA]
923 || (mtmp->data->mflags3 & M3_WANTSARTI))
926 /* worst case, at least it'll be peaceful. */
929 if (flags.moonphase == FULL_MOON && night() && rn2(6) && obj
930 && mtmp->data->mlet == S_DOG)
933 /* If we cannot tame it, at least it's no longer afraid. */
937 /* make grabber let go now, whether it becomes tame or not */
938 if (mtmp == u.ustuck) {
940 expels(mtmp, mtmp->data, TRUE);
941 else if (!(Upolyd && sticks(youmonst.data)))
945 /* feeding it treats makes it tamer */
946 if (mtmp->mtame && obj) {
949 if (mtmp->mcanmove && !mtmp->mconf && !mtmp->meating
950 && ((tasty = dogfood(mtmp, obj)) == DOGFOOD
952 && EDOG(mtmp)->hungrytime <= monstermoves))) {
953 /* pet will "catch" and eat this thrown food */
954 if (canseemon(mtmp)) {
956 (obj->otyp == CORPSE && obj->corpsenm >= LOW_PM
957 && mons[obj->corpsenm].msize > mtmp->data->msize);
959 pline("%s catches %s%s", Monnam(mtmp), the(xname(obj)),
960 !big_corpse ? "." : ", or vice versa!");
962 pline("%s
\82Í%s
\82ð
\82Â
\82©
\82Ü
\82¦
\82½%s",
963 Monnam(mtmp), xname(obj),
964 !big_corpse ? "
\81D" : "
\81C
\82Æ
\8c¾
\82¤
\82æ
\82è
\82»
\82Ì
\8bt
\82©
\81I");
966 } else if (cansee(mtmp->mx, mtmp->my))
968 pline("%s.", Tobjnam(obj, "stop"));
970 pline("%s
\82Í
\8e~
\82Ü
\82Á
\82½
\81D", xname(obj));
971 /* dog_eat expects a floor object */
972 place_object(obj, mtmp->mx, mtmp->my);
973 (void) dog_eat(mtmp, obj, mtmp->mx, mtmp->my, FALSE);
974 /* eating might have killed it, but that doesn't matter here;
975 a non-null result suppresses "miss" message for thrown
976 food and also implies that the object has been deleted */
982 if (mtmp->mtame || !mtmp->mcanmove
983 /* monsters with conflicting structures cannot be tamed */
984 || mtmp->isshk || mtmp->isgd || mtmp->ispriest || mtmp->isminion
985 || is_covetous(mtmp->data) || is_human(mtmp->data)
986 || (is_demon(mtmp->data) && !is_demon(youmonst.data))
987 || (obj && dogfood(mtmp, obj) >= MANFOOD))
990 if (mtmp->m_id == quest_status.leader_m_id)
993 /* add the pet extension */
997 if (obj) { /* thrown food */
998 /* defer eating until the edog extension has been set up */
999 place_object(obj, mtmp->mx, mtmp->my); /* put on floor */
1000 /* devour the food (might grow into larger, genocided monster) */
1001 if (dog_eat(mtmp, obj, mtmp->mx, mtmp->my, TRUE) == 2)
1002 return TRUE; /* oops, it died... */
1003 /* `obj' is now obsolete */
1006 newsym(mtmp->mx, mtmp->my);
1007 if (attacktype(mtmp->data, AT_WEAP)) {
1008 mtmp->weapon_check = NEED_HTH_WEAPON;
1009 (void) mon_wield_item(mtmp);
1015 * Called during pet revival or pet life-saving.
1016 * If you killed the pet, it revives wild.
1017 * If you abused the pet a lot while alive, it revives wild.
1018 * If you abused the pet at all while alive, it revives untame.
1019 * If the pet wasn't abused and was very tame, it might revive tame.
1022 wary_dog(mtmp, was_dead)
1027 boolean quietly = was_dead;
1029 finish_meating(mtmp);
1033 edog = !mtmp->isminion ? EDOG(mtmp) : 0;
1035 /* if monster was starving when it died, undo that now */
1036 if (edog && edog->mhpmax_penalty) {
1037 mtmp->mhpmax += edog->mhpmax_penalty;
1038 mtmp->mhp += edog->mhpmax_penalty; /* heal it */
1039 edog->mhpmax_penalty = 0;
1042 if (edog && (edog->killed_by_u == 1 || edog->abuse > 2)) {
1043 mtmp->mpeaceful = mtmp->mtame = 0;
1044 if (edog->abuse >= 0 && edog->abuse < 10)
1045 if (!rn2(edog->abuse + 1))
1046 mtmp->mpeaceful = 1;
1047 if (!quietly && cansee(mtmp->mx, mtmp->my)) {
1048 if (haseyes(youmonst.data)) {
1049 if (haseyes(mtmp->data))
1051 pline("%s %s to look you in the %s.", Monnam(mtmp),
1052 mtmp->mpeaceful ? "seems unable" : "refuses",
1055 pline("%s
\82Í
\82 \82È
\82½
\82Ì%s%s
\81D", Monnam(mtmp),
1057 mtmp->mpeaceful ? "
\82ð
\8c©
\82é
\82±
\82Æ
\82ª
\82Å
\82«
\82È
\82¢
\82æ
\82¤
\82¾" :
1058 "
\82©
\82ç
\96Ú
\82ð
\82»
\82ç
\82µ
\82½");
1062 pline("%s avoids your gaze.", Monnam(mtmp));
1064 pline("%s
\82Í
\82 \82È
\82½
\82Ì
\82É
\82ç
\82Ý
\82ð
\89ñ
\94ð
\82µ
\82½
\81D", Monnam(mtmp));
1068 /* chance it goes wild anyway - Pet Sematary */
1069 mtmp->mtame = rn2(mtmp->mtame + 1);
1071 mtmp->mpeaceful = rn2(2);
1075 if (!quietly && canspotmon(mtmp))
1077 pline("%s %s.", Monnam(mtmp),
1078 mtmp->mpeaceful ? "is no longer tame" : "has become feral");
1080 pline("%s
\82Í%s
\81D", Monnam(mtmp),
1081 mtmp->mpeaceful ? "
\83y
\83b
\83g
\82Å
\82È
\82
\82È
\82Á
\82½" : "
\96ì
\90¶
\89»
\82µ
\82½");
1083 newsym(mtmp->mx, mtmp->my);
1084 /* a life-saved monster might be leashed;
1085 don't leave it that way if it's no longer tame */
1087 m_unleash(mtmp, TRUE);
1088 if (mtmp == u.usteed)
1089 dismount_steed(DISMOUNT_THROWN);
1091 /* it's still a pet; start a clean pet-slate now */
1093 edog->killed_by_u = 0;
1095 edog->ogoal.x = edog->ogoal.y = -1;
1096 if (was_dead || edog->hungrytime < monstermoves + 500L)
1097 edog->hungrytime = monstermoves + 500L;
1099 edog->droptime = 0L;
1100 edog->dropdist = 10000;
1101 edog->whistletime = 0L;
1103 } /* else lifesaved, so retain current values */
1114 if (Aggravate_monster || Conflict)
1119 if (mtmp->mtame && !mtmp->isminion)
1120 EDOG(mtmp)->abuse++;
1122 if (!mtmp->mtame && mtmp->mleashed)
1123 m_unleash(mtmp, TRUE);
1125 /* don't make a sound if pet is in the middle of leaving the level */
1126 /* newsym isn't necessary in this case either */
1127 if (mtmp->mx != 0) {
1128 if (mtmp->mtame && rn2(mtmp->mtame))
1131 growl(mtmp); /* give them a moment's worry */
1134 newsym(mtmp->mx, mtmp->my);