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-2019 */
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) || defined(BETA)
505 if (nmv < 0L) { /* crash likely... */
506 panic("catchup from future time?");
509 } else if (nmv == 0L) { /* safe, but should'nt happen */
510 impossible("catchup from now?");
513 if (nmv >= LARGEST_INT) /* paranoia */
514 imv = LARGEST_INT - 1;
518 /* might stop being afraid, blind or frozen */
519 /* set to 1 and allow final decrement in movemon() */
520 if (mtmp->mblinded) {
521 if (imv >= (int) mtmp->mblinded)
524 mtmp->mblinded -= imv;
527 if (imv >= (int) mtmp->mfrozen)
530 mtmp->mfrozen -= imv;
532 if (mtmp->mfleetim) {
533 if (imv >= (int) mtmp->mfleetim)
536 mtmp->mfleetim -= imv;
539 /* might recover from temporary trouble */
540 if (mtmp->mtrapped && rn2(imv + 1) > 40 / 2)
542 if (mtmp->mconf && rn2(imv + 1) > 50 / 2)
544 if (mtmp->mstun && rn2(imv + 1) > 10 / 2)
547 /* might finish eating or be able to use special ability again */
548 if (imv > mtmp->meating)
549 finish_meating(mtmp);
551 mtmp->meating -= imv;
552 if (imv > mtmp->mspec_used)
553 mtmp->mspec_used = 0;
555 mtmp->mspec_used -= imv;
557 /* reduce tameness for every 150 moves you are separated */
559 int wilder = (imv + 75) / 150;
560 if (mtmp->mtame > wilder)
561 mtmp->mtame -= wilder; /* less tame */
562 else if (mtmp->mtame > rn2(wilder))
563 mtmp->mtame = 0; /* untame */
565 mtmp->mtame = mtmp->mpeaceful = 0; /* hostile! */
567 /* check to see if it would have died as a pet; if so, go wild instead
568 * of dying the next time we call dog_move()
570 if (mtmp->mtame && !mtmp->isminion
571 && (carnivorous(mtmp->data) || herbivorous(mtmp->data))) {
572 struct edog *edog = EDOG(mtmp);
574 if ((monstermoves > edog->hungrytime + 500 && mtmp->mhp < 3)
575 || (monstermoves > edog->hungrytime + 750))
576 mtmp->mtame = mtmp->mpeaceful = 0;
579 if (!mtmp->mtame && mtmp->mleashed) {
580 /* leashed monsters should always be with hero, consequently
581 never losing any time to be accounted for later */
582 impossible("catching up for leashed monster?");
583 m_unleash(mtmp, FALSE);
586 /* recover lost hit points */
587 if (!regenerates(mtmp->data))
589 if (mtmp->mhp + imv >= mtmp->mhpmax)
590 mtmp->mhp = mtmp->mhpmax;
595 /* called when you move to another level */
598 boolean pets_only; /* true for ascension or final escape */
600 register struct monst *mtmp, *mtmp2;
601 register struct obj *obj;
605 for (mtmp = fmon; mtmp; mtmp = mtmp2) {
607 if (DEADMONSTER(mtmp))
611 continue; /* reject non-pets */
612 /* don't block pets from accompanying hero's dungeon
613 escape or ascension simply due to mundane trifles;
614 unlike level change for steed, don't bother trying
615 to achieve a normal trap escape first */
622 if (((monnear(mtmp, u.ux, u.uy) && levl_follower(mtmp))
623 /* the wiz will level t-port from anywhere to chase
624 the amulet; if you don't have it, will chase you
625 only if in range. -3. */
626 || (u.uhave.amulet && mtmp->iswiz))
627 && ((!mtmp->msleeping && mtmp->mcanmove)
628 /* eg if level teleport or new trap, steed has no control
629 to avoid following */
630 || (mtmp == u.usteed))
631 /* monster won't follow if it hasn't noticed you yet */
632 && !(mtmp->mstrategy & STRAT_WAITFORU)) {
635 (void) mintrap(mtmp); /* try to escape */
636 if (mtmp == u.usteed) {
637 /* make sure steed is eligible to accompany hero */
638 mtmp->mtrapped = 0; /* escape trap */
639 mtmp->meating = 0; /* terminate eating */
640 mdrop_special_objs(mtmp); /* drop Amulet */
641 } else if (mtmp->meating || mtmp->mtrapped) {
644 pline("%s is still %s.", Monnam(mtmp),
645 mtmp->meating ? "eating" : "trapped");
647 pline("%s
\82Í
\82Ü
\82¾%s
\81D", Monnam(mtmp),
648 mtmp->meating ? "
\90H
\82×
\82Ä
\82¢
\82é" : "ã©
\82É
\82©
\82©
\82Á
\82½
\82Ü
\82Ü
\82¾");
651 } else if (mon_has_amulet(mtmp)) {
654 pline("%s seems very disoriented for a moment.",
656 pline("%s
\82Í
\88ê
\8fu
\95û
\8cü
\8a´
\8ao
\82ð
\8e¸
\82Á
\82½
\82æ
\82¤
\82¾
\81D",
661 if (mtmp->mleashed) {
663 pline("%s leash suddenly comes loose.",
665 ? (mtmp->female ? "Her" : "His")
668 pline("%s
\82É
\8c\8b\82Î
\82ê
\82½
\95R
\82Í
\93Ë
\91R
\82ä
\82é
\82ñ
\82¾
\81D",
670 ? (mtmp->female ? "
\94Þ
\8f\97" : "
\94Þ")
671 : "
\82»
\82Ì
\90¶
\95¨");
673 m_unleash(mtmp, FALSE);
675 if (mtmp == u.usteed) {
676 /* can't happen unless someone makes a change
677 which scrambles the stay_behind logic above */
678 impossible("steed left behind?");
679 dismount_steed(DISMOUNT_GENERIC);
684 set_residency(mtmp, TRUE);
688 /* NOTE: worm is truncated to # segs = max wormno size */
689 cnt = count_wsegs(mtmp);
690 num_segs = min(cnt, MAX_NUM_WORMS - 1);
692 place_monster(mtmp, mtmp->mx, mtmp->my);
696 /* set minvent's obj->no_charge to 0 */
697 for (obj = mtmp->minvent; obj; obj = obj->nobj) {
698 if (Has_contents(obj))
699 picked_container(obj); /* does the right thing */
703 relmon(mtmp, &mydogs); /* move it from map to mydogs */
704 mtmp->mx = mtmp->my = 0; /* avoid mnexto()/MON_AT() problem */
705 mtmp->wormno = num_segs;
706 mtmp->mlstmv = monstermoves;
707 } else if (mtmp->iswiz) {
708 /* we want to be able to find him when his next resurrection
709 chance comes up, but have him resume his present location
710 if player returns to this level before that time */
711 migrate_to_level(mtmp, ledger_no(&u.uz), MIGR_EXACT_XY,
713 } else if (mtmp->mleashed) {
714 /* this can happen if your quest leader ejects you from the
715 "home" level while a leashed pet isn't next to you */
717 pline("%s leash goes slack.", s_suffix(Monnam(mtmp)));
719 pline("%s
\82É
\8c\8b\82Î
\82ê
\82½
\95R
\82Í
\82½
\82é
\82ñ
\82¾
\81D", Monnam(mtmp));
720 m_unleash(mtmp, FALSE);
726 migrate_to_level(mtmp, tolev, xyloc, cc)
727 register struct monst *mtmp;
728 xchar tolev; /* destination level */
729 xchar xyloc; /* MIGR_xxx destination xy location: */
730 coord *cc; /* optional destination coordinates */
735 int num_segs = 0; /* count of worm segments */
738 set_residency(mtmp, TRUE);
741 int cnt = count_wsegs(mtmp);
743 /* **** NOTE: worm is truncated to # segs = max wormno size **** */
744 num_segs = min(cnt, MAX_NUM_WORMS - 1); /* used below */
745 wormgone(mtmp); /* destroys tail and takes head off map */
746 /* there used to be a place_monster() here for the relmon() below,
747 but it doesn't require the monster to be on the map anymore */
750 /* set minvent's obj->no_charge to 0 */
751 for (obj = mtmp->minvent; obj; obj = obj->nobj) {
752 if (Has_contents(obj))
753 picked_container(obj); /* does the right thing */
757 if (mtmp->mleashed) {
759 m_unleash(mtmp, TRUE);
761 relmon(mtmp, &migrating_mons); /* move it from map to migrating_mons */
763 new_lev.dnum = ledger_to_dnum((xchar) tolev);
764 new_lev.dlevel = ledger_to_dlev((xchar) tolev);
765 /* overload mtmp->[mx,my], mtmp->[mux,muy], and mtmp->mtrack[] as */
766 /* destination codes (setup flag bits before altering mx or my) */
767 xyflags = (depth(&new_lev) < depth(&u.uz)); /* 1 => up */
768 if (In_W_tower(mtmp->mx, mtmp->my, &u.uz))
770 mtmp->wormno = num_segs;
771 mtmp->mlstmv = monstermoves;
772 mtmp->mtrack[1].x = cc ? cc->x : mtmp->mx;
773 mtmp->mtrack[1].y = cc ? cc->y : mtmp->my;
774 mtmp->mtrack[0].x = xyloc;
775 mtmp->mtrack[0].y = xyflags;
776 mtmp->mux = new_lev.dnum;
777 mtmp->muy = new_lev.dlevel;
778 mtmp->mx = mtmp->my = 0; /* this implies migration */
779 if (mtmp == context.polearm.hitmon)
780 context.polearm.hitmon = (struct monst *) 0;
783 /* return quality of food; the lower the better */
784 /* fungi will eat even tainted food */
788 register struct obj *obj;
790 struct permonst *mptr = mon->data, *fptr = 0;
791 boolean carni = carnivorous(mptr), herbi = herbivorous(mptr),
794 if (is_quest_artifact(obj) || obj_resists(obj, 0, 95))
795 return obj->cursed ? TABU : APPORT;
797 switch (obj->oclass) {
799 if (obj->otyp == CORPSE || obj->otyp == TIN || obj->otyp == EGG)
800 fptr = &mons[obj->corpsenm];
802 if (obj->otyp == CORPSE && is_rider(fptr))
804 if ((obj->otyp == CORPSE || obj->otyp == EGG) && touch_petrifies(fptr)
805 && !resists_ston(mon))
807 if (!carni && !herbi)
808 return obj->cursed ? UNDEF : APPORT;
810 /* a starving pet will eat almost anything */
811 starving = (mon->mtame && !mon->isminion
812 && EDOG(mon)->mhpmax_penalty);
813 /* even carnivores will eat carrots if they're temporarily blind */
814 mblind = (!mon->mcansee && haseyes(mon->data));
816 /* ghouls prefer old corpses and unhatchable eggs, yum!
817 they'll eat fresh non-veggy corpses and hatchable eggs
818 when starving; they never eat stone-to-flesh'd meat */
819 if (mptr == &mons[PM_GHOUL]) {
820 if (obj->otyp == CORPSE)
821 return (peek_at_iced_corpse_age(obj) + 50L <= monstermoves
822 && fptr != &mons[PM_LIZARD]
823 && fptr != &mons[PM_LICHEN])
825 : (starving && !vegan(fptr))
828 if (obj->otyp == EGG)
829 return stale_egg(obj) ? CADAVER : starving ? ACCFOOD : POISON;
838 case HUGE_CHUNK_OF_MEAT:
839 return carni ? DOGFOOD : MANFOOD;
841 return carni ? CADAVER : MANFOOD;
843 if ((peek_at_iced_corpse_age(obj) + 50L <= monstermoves
844 && obj->corpsenm != PM_LIZARD && obj->corpsenm != PM_LICHEN
845 && mptr->mlet != S_FUNGUS)
846 || (acidic(fptr) && !resists_acid(mon))
847 || (poisonous(fptr) && !resists_poison(mon)))
849 /* turning into slime is preferable to starvation */
850 else if (fptr == &mons[PM_GREEN_SLIME] && !slimeproof(mon->data))
851 return starving ? ACCFOOD : POISON;
852 else if (vegan(fptr))
853 return herbi ? CADAVER : MANFOOD;
854 /* most humanoids will avoid cannibalism unless starving;
855 arbitrary: elves won't eat other elves even then */
856 else if (humanoid(mptr) && same_race(mptr, fptr)
857 && (!is_undead(mptr) && fptr->mlet != S_KOBOLD
858 && fptr->mlet != S_ORC && fptr->mlet != S_OGRE))
859 return (starving && carni && !is_elf(mptr)) ? ACCFOOD : TABU;
861 return carni ? CADAVER : MANFOOD;
862 case CLOVE_OF_GARLIC:
863 return (is_undead(mptr) || is_vampshifter(mon))
865 : (herbi || starving)
869 return metallivorous(mptr) ? ACCFOOD : MANFOOD;
871 return herbi ? DOGFOOD : starving ? ACCFOOD : MANFOOD;
873 return (herbi || mblind) ? DOGFOOD : starving ? ACCFOOD : MANFOOD;
875 return (mptr->mlet == S_YETI && herbi)
876 ? DOGFOOD /* for monkey and ape (tameable), sasquatch */
877 : (herbi || starving)
883 return (obj->otyp > SLIME_MOLD) ? (carni ? ACCFOOD : MANFOOD)
884 : (herbi ? ACCFOOD : MANFOOD);
887 if (obj->otyp == AMULET_OF_STRANGULATION
888 || obj->otyp == RIN_SLOW_DIGESTION)
890 if (mon_hates_silver(mon) && objects[obj->otyp].oc_material == SILVER)
892 if (mptr == &mons[PM_GELATINOUS_CUBE] && is_organic(obj))
894 if (metallivorous(mptr) && is_metallic(obj)
895 && (is_rustprone(obj) || mptr != &mons[PM_RUST_MONSTER])) {
896 /* Non-rustproofed ferrous based metals are preferred. */
897 return (is_rustprone(obj) && !obj->oerodeproof) ? DOGFOOD
901 && obj->oclass != BALL_CLASS
902 && obj->oclass != CHAIN_CLASS)
911 * With the separate mextra structure added in 3.6.x this always
912 * operates on the original mtmp. It now returns TRUE if the taming
917 register struct monst *mtmp;
918 register struct obj *obj;
920 /* The Wiz, Medusa and the quest nemeses aren't even made peaceful. */
921 if (mtmp->iswiz || mtmp->data == &mons[PM_MEDUSA]
922 || (mtmp->data->mflags3 & M3_WANTSARTI))
925 /* worst case, at least it'll be peaceful. */
928 if (flags.moonphase == FULL_MOON && night() && rn2(6) && obj
929 && mtmp->data->mlet == S_DOG)
932 /* If we cannot tame it, at least it's no longer afraid. */
936 /* make grabber let go now, whether it becomes tame or not */
937 if (mtmp == u.ustuck) {
939 expels(mtmp, mtmp->data, TRUE);
940 else if (!(Upolyd && sticks(youmonst.data)))
944 /* feeding it treats makes it tamer */
945 if (mtmp->mtame && obj) {
948 if (mtmp->mcanmove && !mtmp->mconf && !mtmp->meating
949 && ((tasty = dogfood(mtmp, obj)) == DOGFOOD
951 && EDOG(mtmp)->hungrytime <= monstermoves))) {
952 /* pet will "catch" and eat this thrown food */
953 if (canseemon(mtmp)) {
955 (obj->otyp == CORPSE && obj->corpsenm >= LOW_PM
956 && mons[obj->corpsenm].msize > mtmp->data->msize);
958 pline("%s catches %s%s", Monnam(mtmp), the(xname(obj)),
959 !big_corpse ? "." : ", or vice versa!");
961 pline("%s
\82Í%s
\82ð
\82Â
\82©
\82Ü
\82¦
\82½%s",
962 Monnam(mtmp), xname(obj),
963 !big_corpse ? "
\81D" : "
\81C
\82Æ
\8c¾
\82¤
\82æ
\82è
\82»
\82Ì
\8bt
\82©
\81I");
965 } else if (cansee(mtmp->mx, mtmp->my))
967 pline("%s.", Tobjnam(obj, "stop"));
969 pline("%s
\82Í
\8e~
\82Ü
\82Á
\82½
\81D", xname(obj));
970 /* dog_eat expects a floor object */
971 place_object(obj, mtmp->mx, mtmp->my);
972 (void) dog_eat(mtmp, obj, mtmp->mx, mtmp->my, FALSE);
973 /* eating might have killed it, but that doesn't matter here;
974 a non-null result suppresses "miss" message for thrown
975 food and also implies that the object has been deleted */
981 if (mtmp->mtame || !mtmp->mcanmove
982 /* monsters with conflicting structures cannot be tamed */
983 || mtmp->isshk || mtmp->isgd || mtmp->ispriest || mtmp->isminion
984 || is_covetous(mtmp->data) || is_human(mtmp->data)
985 || (is_demon(mtmp->data) && !is_demon(youmonst.data))
986 || (obj && dogfood(mtmp, obj) >= MANFOOD))
989 if (mtmp->m_id == quest_status.leader_m_id)
992 /* add the pet extension */
996 if (obj) { /* thrown food */
997 /* defer eating until the edog extension has been set up */
998 place_object(obj, mtmp->mx, mtmp->my); /* put on floor */
999 /* devour the food (might grow into larger, genocided monster) */
1000 if (dog_eat(mtmp, obj, mtmp->mx, mtmp->my, TRUE) == 2)
1001 return TRUE; /* oops, it died... */
1002 /* `obj' is now obsolete */
1005 newsym(mtmp->mx, mtmp->my);
1006 if (attacktype(mtmp->data, AT_WEAP)) {
1007 mtmp->weapon_check = NEED_HTH_WEAPON;
1008 (void) mon_wield_item(mtmp);
1014 * Called during pet revival or pet life-saving.
1015 * If you killed the pet, it revives wild.
1016 * If you abused the pet a lot while alive, it revives wild.
1017 * If you abused the pet at all while alive, it revives untame.
1018 * If the pet wasn't abused and was very tame, it might revive tame.
1021 wary_dog(mtmp, was_dead)
1026 boolean quietly = was_dead;
1028 finish_meating(mtmp);
1032 edog = !mtmp->isminion ? EDOG(mtmp) : 0;
1034 /* if monster was starving when it died, undo that now */
1035 if (edog && edog->mhpmax_penalty) {
1036 mtmp->mhpmax += edog->mhpmax_penalty;
1037 mtmp->mhp += edog->mhpmax_penalty; /* heal it */
1038 edog->mhpmax_penalty = 0;
1041 if (edog && (edog->killed_by_u == 1 || edog->abuse > 2)) {
1042 mtmp->mpeaceful = mtmp->mtame = 0;
1043 if (edog->abuse >= 0 && edog->abuse < 10)
1044 if (!rn2(edog->abuse + 1))
1045 mtmp->mpeaceful = 1;
1046 if (!quietly && cansee(mtmp->mx, mtmp->my)) {
1047 if (haseyes(youmonst.data)) {
1048 if (haseyes(mtmp->data))
1050 pline("%s %s to look you in the %s.", Monnam(mtmp),
1051 mtmp->mpeaceful ? "seems unable" : "refuses",
1054 pline("%s
\82Í
\82 \82È
\82½
\82Ì%s%s
\81D", Monnam(mtmp),
1056 mtmp->mpeaceful ? "
\82ð
\8c©
\82é
\82±
\82Æ
\82ª
\82Å
\82«
\82È
\82¢
\82æ
\82¤
\82¾" :
1057 "
\82©
\82ç
\96Ú
\82ð
\82»
\82ç
\82µ
\82½");
1061 pline("%s avoids your gaze.", Monnam(mtmp));
1063 pline("%s
\82Í
\82 \82È
\82½
\82Ì
\82É
\82ç
\82Ý
\82ð
\89ñ
\94ð
\82µ
\82½
\81D", Monnam(mtmp));
1067 /* chance it goes wild anyway - Pet Sematary */
1068 mtmp->mtame = rn2(mtmp->mtame + 1);
1070 mtmp->mpeaceful = rn2(2);
1074 if (!quietly && canspotmon(mtmp))
1076 pline("%s %s.", Monnam(mtmp),
1077 mtmp->mpeaceful ? "is no longer tame" : "has become feral");
1079 pline("%s
\82Í%s
\81D", Monnam(mtmp),
1080 mtmp->mpeaceful ? "
\83y
\83b
\83g
\82Å
\82È
\82
\82È
\82Á
\82½" : "
\96ì
\90¶
\89»
\82µ
\82½");
1082 newsym(mtmp->mx, mtmp->my);
1083 /* a life-saved monster might be leashed;
1084 don't leave it that way if it's no longer tame */
1086 m_unleash(mtmp, TRUE);
1087 if (mtmp == u.usteed)
1088 dismount_steed(DISMOUNT_THROWN);
1090 /* it's still a pet; start a clean pet-slate now */
1092 edog->killed_by_u = 0;
1094 edog->ogoal.x = edog->ogoal.y = -1;
1095 if (was_dead || edog->hungrytime < monstermoves + 500L)
1096 edog->hungrytime = monstermoves + 500L;
1098 edog->droptime = 0L;
1099 edog->dropdist = 10000;
1100 edog->whistletime = 0L;
1102 } /* else lifesaved, so retain current values */
1113 if (Aggravate_monster || Conflict)
1118 if (mtmp->mtame && !mtmp->isminion)
1119 EDOG(mtmp)->abuse++;
1121 if (!mtmp->mtame && mtmp->mleashed)
1122 m_unleash(mtmp, TRUE);
1124 /* don't make a sound if pet is in the middle of leaving the level */
1125 /* newsym isn't necessary in this case either */
1126 if (mtmp->mx != 0) {
1127 if (mtmp->mtame && rn2(mtmp->mtame))
1130 growl(mtmp); /* give them a moment's worry */
1133 newsym(mtmp->mx, mtmp->my);