1 /* SCCS Id: @(#)dog.c 3.4 2002/09/08 */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
10 STATIC_DCL int NDECL(pet_type);
14 register struct monst *mtmp;
16 mtmp->mtame = is_domestic(mtmp->data) ? 10 : 5;
19 set_malign(mtmp); /* recalc alignment now that it's tamed */
22 EDOG(mtmp)->droptime = 0;
23 EDOG(mtmp)->dropdist = 10000;
24 EDOG(mtmp)->apport = 10;
25 EDOG(mtmp)->whistletime = 0;
26 EDOG(mtmp)->hungrytime = 1000 + monstermoves;
27 EDOG(mtmp)->ogoal.x = -1; /* force error if used before set */
28 EDOG(mtmp)->ogoal.y = -1;
29 EDOG(mtmp)->abuse = 0;
30 EDOG(mtmp)->revivals = 0;
31 EDOG(mtmp)->mhpmax_penalty = 0;
32 EDOG(mtmp)->killed_by_u = 0;
38 if (urole.petnum != NON_PM)
39 return (urole.petnum);
40 else if (preferred_pet == 'c')
42 else if (preferred_pet == 'd')
43 return (PM_LITTLE_DOG);
45 return (rn2(2) ? PM_KITTEN : PM_LITTLE_DOG);
49 make_familiar(otmp,x,y,quietly)
50 register struct obj *otmp;
55 struct monst *mtmp = 0;
56 int chance, trycnt = 100;
59 if (otmp) { /* figurine; otherwise spell */
60 int mndx = otmp->corpsenm;
62 /* activating a figurine provides one way to exceed the
63 maximum number of the target critter created--unless
64 it has a special limit (erinys, Nazgul) */
65 if ((mvitals[mndx].mvflags & G_EXTINCT) &&
66 mbirth_limit(mndx) != MAXMONNO) {
68 /* have just been given "You <do something with>
69 the figurine and it transforms." message */
70 pline("... into a pile of dust.");
71 break; /* mtmp is null */
74 pm = &mons[pet_type()];
79 There("seems to be nothing available for a familiar.");
84 mtmp = makemon(pm, x, y, MM_EDOG|MM_IGNOREWATER);
85 if (otmp && !mtmp) { /* monster was genocided or square occupied */
87 pline_The("figurine writhes and then shatters into pieces!");
90 } while (!mtmp && --trycnt > 0);
92 if (!mtmp) return (struct monst *)0;
94 if (is_pool(mtmp->mx, mtmp->my) && minliquid(mtmp))
95 return (struct monst *)0;
99 if (otmp) { /* figurine; resulting monster might not become a pet */
100 chance = rn2(10); /* 0==tame, 1==peaceful, 2==hostile */
101 if (chance > 2) chance = otmp->blessed ? 0 : !otmp->cursed ? 1 : 2;
102 /* 0,1,2: b=80%,10,10; nc=10%,80,10; c=10%,10,80 */
104 mtmp->mtame = 0; /* not tame after all */
105 if (chance == 2) { /* hostile (cursed figurine) */
107 You("get a bad feeling about this.");
112 /* if figurine has been named, give same name to the monster */
114 mtmp = christen_monst(mtmp, ONAME(otmp));
116 set_malign(mtmp); /* more alignment changes */
117 newsym(mtmp->mx, mtmp->my);
119 /* must wield weapon immediately since pets will otherwise drop it */
120 if (mtmp->mtame && attacktype(mtmp->data, AT_WEAP)) {
121 mtmp->weapon_check = NEED_HTH_WEAPON;
122 (void) mon_wield_item(mtmp);
130 register struct monst *mtmp;
132 register struct obj *otmp;
136 static int petname_used = 0;
138 if (preferred_pet == 'n') return((struct monst *) 0);
140 pettype = pet_type();
141 if (pettype == PM_LITTLE_DOG)
143 else if (pettype == PM_PONY)
148 /* default pet names */
149 if (!*petname && pettype == PM_LITTLE_DOG) {
150 /* All of these names were for dogs. */
151 if(Role_if(PM_CAVEMAN)) petname = "Slasher"; /* The Warrior */
152 if(Role_if(PM_SAMURAI)) petname = "Hachi"; /* Shibuya Station */
153 if(Role_if(PM_BARBARIAN)) petname = "Idefix"; /* Obelix */
154 if(Role_if(PM_RANGER)) petname = "Sirius"; /* Orion's dog */
157 mtmp = makemon(&mons[pettype], u.ux, u.uy, MM_EDOG);
159 if(!mtmp) return((struct monst *) 0); /* pets were genocided */
162 /* Horses already wear a saddle */
163 if (pettype == PM_PONY && !!(otmp = mksobj(SADDLE, TRUE, FALSE))) {
164 if (mpickobj(mtmp, otmp))
165 panic("merged saddle?");
166 mtmp->misc_worn_check |= W_SADDLE;
167 otmp->dknown = otmp->bknown = otmp->rknown = 1;
168 otmp->owornmask = W_SADDLE;
169 otmp->leashmon = mtmp->m_id;
170 update_mon_intrinsics(mtmp, otmp, TRUE, TRUE);
174 if (!petname_used++ && *petname)
175 mtmp = christen_monst(mtmp, petname);
181 /* record `last move time' for all monsters prior to level save so that
182 mon_arrive() can catch up for lost time when they're restored later */
188 /* monst->mlstmv used to be updated every time `monst' actually moved,
189 but that is no longer the case so we just do a blanket assignment */
190 for (mon = fmon; mon; mon = mon->nmon)
191 if (!DEADMONSTER(mon)) mon->mlstmv = monstermoves;
197 register struct monst *mtmp, *mtmp0 = 0, *mtmp2;
199 while ((mtmp = mydogs) != 0) {
201 mon_arrive(mtmp, TRUE);
204 for(mtmp = migrating_mons; mtmp; mtmp = mtmp2) {
206 if (mtmp->mux == u.uz.dnum && mtmp->muy == u.uz.dlevel) {
207 if(mtmp == migrating_mons)
208 migrating_mons = mtmp->nmon;
210 mtmp0->nmon = mtmp->nmon;
211 mon_arrive(mtmp, FALSE);
217 /* called from resurrect() in addition to losedogs() */
219 mon_arrive(mtmp, with_you)
224 xchar xlocale, ylocale, xyloc, xyflags, wander;
230 set_residency(mtmp, FALSE);
232 num_segs = mtmp->wormno;
233 /* baby long worms have no tail so don't use is_longworm() */
234 if ((mtmp->data == &mons[PM_LONG_WORM]) &&
236 (mtmp->wormno = get_wormno(), mtmp->wormno != 0))
238 (mtmp->wormno = get_wormno()) != 0)
241 initworm(mtmp, num_segs);
242 /* tail segs are not yet initialized or displayed */
243 } else mtmp->wormno = 0;
245 /* some monsters might need to do something special upon arrival
246 _after_ the current level has been fully set up; see dochug() */
247 mtmp->mstrategy |= STRAT_ARRIVE;
249 /* make sure mnexto(rloc_to(set_apparxy())) doesn't use stale data */
250 mtmp->mux = u.ux, mtmp->muy = u.uy;
251 xyloc = mtmp->mtrack[0].x;
252 xyflags = mtmp->mtrack[0].y;
253 xlocale = mtmp->mtrack[1].x;
254 ylocale = mtmp->mtrack[1].y;
255 mtmp->mtrack[0].x = mtmp->mtrack[0].y = 0;
256 mtmp->mtrack[1].x = mtmp->mtrack[1].y = 0;
259 if (mtmp == u.usteed)
260 return; /* don't place steed on the map */
263 /* When a monster accompanies you, sometimes it will arrive
264 at your intended destination and you'll end up next to
265 that spot. This code doesn't control the final outcome;
266 goto_level(do.c) decides who ends up at your target spot
267 when there is a monster there too. */
268 if (!MON_AT(u.ux, u.uy) &&
269 !rn2(mtmp->mtame ? 10 : mtmp->mpeaceful ? 5 : 2))
270 rloc_to(mtmp, u.ux, u.uy);
276 * The monster arrived on this level independently of the player.
277 * Its coordinate fields were overloaded for use as flags that
278 * specify its final destination.
281 if (mtmp->mlstmv < monstermoves - 1L) {
282 /* heal monster for time spent in limbo */
283 long nmv = monstermoves - 1L - mtmp->mlstmv;
285 mon_catchup_elapsed_time(mtmp, nmv);
286 mtmp->mlstmv = monstermoves - 1L;
288 /* let monster move a bit on new level (see placement code below) */
289 wander = (xchar) min(nmv, 8);
294 case MIGR_APPROX_XY: /* {x,y}locale set above */
296 case MIGR_EXACT_XY: wander = 0;
298 case MIGR_NEAR_PLAYER: xlocale = u.ux, ylocale = u.uy;
300 case MIGR_STAIRS_UP: xlocale = xupstair, ylocale = yupstair;
302 case MIGR_STAIRS_DOWN: xlocale = xdnstair, ylocale = ydnstair;
304 case MIGR_LADDER_UP: xlocale = xupladder, ylocale = yupladder;
306 case MIGR_LADDER_DOWN: xlocale = xdnladder, ylocale = ydnladder;
308 case MIGR_SSTAIRS: xlocale = sstairs.sx, ylocale = sstairs.sy;
311 if (In_endgame(&u.uz)) {
312 /* there is no arrival portal for endgame levels */
313 /* BUG[?]: for simplicity, this code relies on the fact
314 that we know that the current endgame levels always
315 build upwards and never have any exclusion subregion
316 inside their TELEPORT_REGION settings. */
317 xlocale = rn1(updest.hx - updest.lx + 1, updest.lx);
318 ylocale = rn1(updest.hy - updest.ly + 1, updest.ly);
321 /* find the arrival portal */
322 for (t = ftrap; t; t = t->ntrap)
323 if (t->ttyp == MAGIC_PORTAL) break;
325 xlocale = t->tx, ylocale = t->ty;
328 impossible("mon_arrive: no corresponding portal?");
331 case MIGR_RANDOM: xlocale = ylocale = 0;
335 if (xlocale && wander) {
336 /* monster moved a bit; pick a nearby location */
337 /* mnearto() deals w/stone, et al */
338 char *r = in_rooms(xlocale, ylocale, 0);
341 /* somexy() handles irregular rooms */
342 if (somexy(&rooms[*r - ROOMOFFSET], &c))
343 xlocale = c.x, ylocale = c.y;
345 xlocale = ylocale = 0;
346 } else { /* not in a room */
348 i = max(1, xlocale - wander);
349 j = min(COLNO-1, xlocale + wander);
350 xlocale = rn1(j - i, i);
351 i = max(0, ylocale - wander);
352 j = min(ROWNO-1, ylocale + wander);
353 ylocale = rn1(j - i, i);
357 mtmp->mx = 0; /*(already is 0)*/
360 (void) mnearto(mtmp, xlocale, ylocale, FALSE);
362 if (!rloc(mtmp,TRUE)) {
364 * Failed to place migrating monster,
365 * probably because the level is full.
366 * Dump the monster's cargo and leave the monster dead.
368 struct obj *obj, *corpse;
369 while ((obj = mtmp->minvent) != 0) {
370 obj_extract_self(obj);
371 obj_no_longer_held(obj);
372 if (obj->owornmask & W_WEP)
373 setmnotwielded(mtmp,obj);
375 if (xlocale && ylocale)
376 place_object(obj, xlocale, ylocale);
379 get_obj_location(obj, &xlocale, &ylocale, 0);
382 corpse = mkcorpstat(CORPSE, (struct monst *)0, mtmp->data,
383 xlocale, ylocale, FALSE);
386 if (xlocale == 0 && ylocale == 0 && corpse) {
387 (void) get_obj_location(corpse, &xlocale, &ylocale, 0);
388 (void) mkgold(mtmp->mgold, xlocale, ylocale);
398 /* heal monster for time spent elsewhere */
400 mon_catchup_elapsed_time(mtmp, nmv)
402 long nmv; /* number of moves */
404 int imv = 0; /* avoid zillions of casts and lint warnings */
406 #if defined(DEBUG) || defined(BETA)
407 if (nmv < 0L) { /* crash likely... */
408 panic("catchup from future time?");
411 } else if (nmv == 0L) { /* safe, but should'nt happen */
412 impossible("catchup from now?");
415 if (nmv >= LARGEST_INT) /* paranoia */
416 imv = LARGEST_INT - 1;
420 /* might stop being afraid, blind or frozen */
421 /* set to 1 and allow final decrement in movemon() */
422 if (mtmp->mblinded) {
423 if (imv >= (int) mtmp->mblinded) mtmp->mblinded = 1;
424 else mtmp->mblinded -= imv;
427 if (imv >= (int) mtmp->mfrozen) mtmp->mfrozen = 1;
428 else mtmp->mfrozen -= imv;
430 if (mtmp->mfleetim) {
431 if (imv >= (int) mtmp->mfleetim) mtmp->mfleetim = 1;
432 else mtmp->mfleetim -= imv;
435 /* might recover from temporary trouble */
436 if (mtmp->mtrapped && rn2(imv + 1) > 40/2) mtmp->mtrapped = 0;
437 if (mtmp->mconf && rn2(imv + 1) > 50/2) mtmp->mconf = 0;
438 if (mtmp->mstun && rn2(imv + 1) > 10/2) mtmp->mstun = 0;
440 /* might finish eating or be able to use special ability again */
441 if (imv > mtmp->meating) mtmp->meating = 0;
442 else mtmp->meating -= imv;
443 if (imv > mtmp->mspec_used) mtmp->mspec_used = 0;
444 else mtmp->mspec_used -= imv;
446 /* reduce tameness for every 150 moves you are separated */
448 int wilder = (imv + 75) / 150;
449 if (mtmp->mtame > wilder) mtmp->mtame -= wilder; /* less tame */
450 else if (mtmp->mtame > rn2(wilder)) mtmp->mtame = 0; /* untame */
451 else mtmp->mtame = mtmp->mpeaceful = 0; /* hostile! */
453 /* check to see if it would have died as a pet; if so, go wild instead
454 * of dying the next time we call dog_move()
456 if (mtmp->mtame && !mtmp->isminion &&
457 (carnivorous(mtmp->data) || herbivorous(mtmp->data))) {
458 struct edog *edog = EDOG(mtmp);
460 if ((monstermoves > edog->hungrytime + 500 && mtmp->mhp < 3) ||
461 (monstermoves > edog->hungrytime + 750))
462 mtmp->mtame = mtmp->mpeaceful = 0;
465 if (!mtmp->mtame && mtmp->mleashed) {
466 /* leashed monsters should always be with hero, consequently
467 never losing any time to be accounted for later */
468 impossible("catching up for leashed monster?");
469 m_unleash(mtmp, FALSE);
472 /* recover lost hit points */
473 if (!regenerates(mtmp->data)) imv /= 20;
474 if (mtmp->mhp + imv >= mtmp->mhpmax)
475 mtmp->mhp = mtmp->mhpmax;
476 else mtmp->mhp += imv;
482 /* called when you move to another level */
485 boolean pets_only; /* true for ascension or final escape */
487 register struct monst *mtmp, *mtmp2;
488 register struct obj *obj;
492 for (mtmp = fmon; mtmp; mtmp = mtmp2) {
494 if (DEADMONSTER(mtmp)) continue;
495 if (pets_only && !mtmp->mtame) continue;
496 if (((monnear(mtmp, u.ux, u.uy) && levl_follower(mtmp)) ||
498 (mtmp == u.usteed) ||
500 /* the wiz will level t-port from anywhere to chase
501 the amulet; if you don't have it, will chase you
502 only if in range. -3. */
503 (u.uhave.amulet && mtmp->iswiz))
504 && ((!mtmp->msleeping && mtmp->mcanmove)
506 /* eg if level teleport or new trap, steed has no control
507 to avoid following */
508 || (mtmp == u.usteed)
511 /* monster won't follow if it hasn't noticed you yet */
512 && !(mtmp->mstrategy & STRAT_WAITFORU)) {
514 if (mtmp->mtame && mtmp->meating) {
516 pline("%s is still eating.", Monnam(mtmp));
518 } else if (mon_has_amulet(mtmp)) {
520 pline("%s seems very disoriented for a moment.",
523 } else if (mtmp->mtame && mtmp->mtrapped) {
525 pline("%s is still trapped.", Monnam(mtmp));
529 if (mtmp == u.usteed) stay_behind = FALSE;
532 if (mtmp->mleashed) {
533 pline("%s leash suddenly comes loose.",
535 ? (mtmp->female ? "Her" : "His")
537 m_unleash(mtmp, FALSE);
542 set_residency(mtmp, TRUE);
546 /* NOTE: worm is truncated to # segs = max wormno size */
547 cnt = count_wsegs(mtmp);
548 num_segs = min(cnt, MAX_NUM_WORMS - 1);
552 /* set minvent's obj->no_charge to 0 */
553 for(obj = mtmp->minvent; obj; obj = obj->nobj) {
554 if (Has_contents(obj))
555 picked_container(obj); /* does the right thing */
560 newsym(mtmp->mx,mtmp->my);
561 mtmp->mx = mtmp->my = 0; /* avoid mnexto()/MON_AT() problem */
562 mtmp->wormno = num_segs;
563 mtmp->mlstmv = monstermoves;
566 } else if (mtmp->iswiz) {
567 /* we want to be able to find him when his next resurrection
568 chance comes up, but have him resume his present location
569 if player returns to this level before that time */
570 migrate_to_level(mtmp, ledger_no(&u.uz),
571 MIGR_EXACT_XY, (coord *)0);
572 } else if (mtmp->mleashed) {
573 /* this can happen if your quest leader ejects you from the
574 "home" level while a leashed pet isn't next to you */
575 pline("%s leash goes slack.", s_suffix(Monnam(mtmp)));
576 m_unleash(mtmp, FALSE);
585 migrate_to_level(mtmp, tolev, xyloc, cc)
586 register struct monst *mtmp;
587 xchar tolev; /* destination level */
588 xchar xyloc; /* MIGR_xxx destination xy location: */
589 coord *cc; /* optional destination coordinates */
591 register struct obj *obj;
594 int num_segs = 0; /* count of worm segments */
597 set_residency(mtmp, TRUE);
601 /* **** NOTE: worm is truncated to # segs = max wormno size **** */
602 cnt = count_wsegs(mtmp);
603 num_segs = min(cnt, MAX_NUM_WORMS - 1);
607 /* set minvent's obj->no_charge to 0 */
608 for(obj = mtmp->minvent; obj; obj = obj->nobj) {
609 if (Has_contents(obj))
610 picked_container(obj); /* does the right thing */
614 if (mtmp->mleashed) {
616 m_unleash(mtmp, TRUE);
619 mtmp->nmon = migrating_mons;
620 migrating_mons = mtmp;
621 newsym(mtmp->mx,mtmp->my);
623 new_lev.dnum = ledger_to_dnum((xchar)tolev);
624 new_lev.dlevel = ledger_to_dlev((xchar)tolev);
625 /* overload mtmp->[mx,my], mtmp->[mux,muy], and mtmp->mtrack[] as */
626 /* destination codes (setup flag bits before altering mx or my) */
627 xyflags = (depth(&new_lev) < depth(&u.uz)); /* 1 => up */
628 if (In_W_tower(mtmp->mx, mtmp->my, &u.uz)) xyflags |= 2;
629 mtmp->wormno = num_segs;
630 mtmp->mlstmv = monstermoves;
631 mtmp->mtrack[1].x = cc ? cc->x : mtmp->mx;
632 mtmp->mtrack[1].y = cc ? cc->y : mtmp->my;
633 mtmp->mtrack[0].x = xyloc;
634 mtmp->mtrack[0].y = xyflags;
635 mtmp->mux = new_lev.dnum;
636 mtmp->muy = new_lev.dlevel;
637 mtmp->mx = mtmp->my = 0; /* this implies migration */
643 /* return quality of food; the lower the better */
644 /* fungi will eat even tainted food */
648 register struct obj *obj;
650 boolean carni = carnivorous(mon->data);
651 boolean herbi = herbivorous(mon->data);
652 struct permonst *fptr = &mons[obj->corpsenm];
655 if (is_quest_artifact(obj) || obj_resists(obj, 0, 95))
656 return (obj->cursed ? TABU : APPORT);
658 switch(obj->oclass) {
660 if (obj->otyp == CORPSE &&
661 ((touch_petrifies(&mons[obj->corpsenm]) && !resists_ston(mon))
665 /* Ghouls only eat old corpses... yum! */
666 if (mon->data == &mons[PM_GHOUL])
667 return (obj->otyp == CORPSE &&
668 peek_at_iced_corpse_age(obj) + 50L <= monstermoves) ?
671 if (!carni && !herbi)
672 return (obj->cursed ? UNDEF : APPORT);
674 /* a starving pet will eat almost anything */
675 starving = (mon->mtame && !mon->isminion &&
676 EDOG(mon)->mhpmax_penalty);
683 case HUGE_CHUNK_OF_MEAT:
684 return (carni ? DOGFOOD : MANFOOD);
686 if (touch_petrifies(&mons[obj->corpsenm]) && !resists_ston(mon))
688 return (carni ? CADAVER : MANFOOD);
690 if ((peek_at_iced_corpse_age(obj) + 50L <= monstermoves
691 && obj->corpsenm != PM_LIZARD
692 && obj->corpsenm != PM_LICHEN
693 && mon->data->mlet != S_FUNGUS) ||
694 (acidic(&mons[obj->corpsenm]) && !resists_acid(mon)) ||
695 (poisonous(&mons[obj->corpsenm]) &&
696 !resists_poison(mon)))
698 else if (vegan(fptr))
699 return (herbi ? CADAVER : MANFOOD);
700 else return (carni ? CADAVER : MANFOOD);
701 case CLOVE_OF_GARLIC:
702 return (is_undead(mon->data) ? TABU :
703 ((herbi || starving) ? ACCFOOD : MANFOOD));
705 return (metallivorous(mon->data) ? ACCFOOD : MANFOOD);
708 return (herbi ? DOGFOOD : starving ? ACCFOOD : MANFOOD);
710 return ((mon->data->mlet == S_YETI) ? DOGFOOD :
711 ((herbi || starving) ? ACCFOOD : MANFOOD));
713 if (starving) return ACCFOOD;
714 return (obj->otyp > SLIME_MOLD ?
715 (carni ? ACCFOOD : MANFOOD) :
716 (herbi ? ACCFOOD : MANFOOD));
719 if (obj->otyp == AMULET_OF_STRANGULATION ||
720 obj->otyp == RIN_SLOW_DIGESTION)
722 if (hates_silver(mon->data) &&
723 objects[obj->otyp].oc_material == SILVER)
725 if (mon->data == &mons[PM_GELATINOUS_CUBE] && is_organic(obj))
727 if (metallivorous(mon->data) && is_metallic(obj) && (is_rustprone(obj) || mon->data != &mons[PM_RUST_MONSTER])) {
728 /* Non-rustproofed ferrous based metals are preferred. */
729 return((is_rustprone(obj) && !obj->oerodeproof) ? DOGFOOD :
732 if(!obj->cursed && obj->oclass != BALL_CLASS &&
733 obj->oclass != CHAIN_CLASS)
735 /* fall into next case */
746 register struct monst *mtmp;
747 register struct obj *obj;
749 register struct monst *mtmp2;
751 /* The Wiz, Medusa and the quest nemeses aren't even made peaceful. */
752 if (mtmp->iswiz || mtmp->data == &mons[PM_MEDUSA]
753 || (mtmp->data->mflags3 & M3_WANTSARTI))
754 return((struct monst *)0);
756 /* worst case, at least it'll be peaceful. */
759 if(flags.moonphase == FULL_MOON && night() && rn2(6) && obj
760 && mtmp->data->mlet == S_DOG)
761 return((struct monst *)0);
763 /* If we cannot tame it, at least it's no longer afraid. */
767 /* make grabber let go now, whether it becomes tame or not */
768 if (mtmp == u.ustuck) {
770 expels(mtmp, mtmp->data, TRUE);
771 else if (!(Upolyd && sticks(youmonst.data)))
775 /* feeding it treats makes it tamer */
776 if (mtmp->mtame && obj) {
779 if (mtmp->mcanmove && !mtmp->mconf && !mtmp->meating &&
780 ((tasty = dogfood(mtmp, obj)) == DOGFOOD ||
781 (tasty <= ACCFOOD && EDOG(mtmp)->hungrytime <= monstermoves))) {
782 /* pet will "catch" and eat this thrown food */
783 if (canseemon(mtmp)) {
784 boolean big_corpse = (obj->otyp == CORPSE &&
785 obj->corpsenm >= LOW_PM &&
786 mons[obj->corpsenm].msize > mtmp->data->msize);
787 pline("%s catches %s%s",
788 Monnam(mtmp), the(xname(obj)),
789 !big_corpse ? "." : ", or vice versa!");
790 } else if (cansee(mtmp->mx,mtmp->my))
791 pline("%s.", Tobjnam(obj, "stop"));
792 /* dog_eat expects a floor object */
793 place_object(obj, mtmp->mx, mtmp->my);
794 (void) dog_eat(mtmp, obj, mtmp->mx, mtmp->my, FALSE);
795 /* eating might have killed it, but that doesn't matter here;
796 a non-null result suppresses "miss" message for thrown
797 food and also implies that the object has been deleted */
800 return (struct monst *)0;
803 if (mtmp->mtame || !mtmp->mcanmove ||
804 /* monsters with conflicting structures cannot be tamed */
805 mtmp->isshk || mtmp->isgd || mtmp->ispriest || mtmp->isminion ||
806 is_covetous(mtmp->data) || is_human(mtmp->data) ||
807 (is_demon(mtmp->data) && !is_demon(youmonst.data)) ||
808 (obj && dogfood(mtmp, obj) >= MANFOOD)) return (struct monst *)0;
810 if (mtmp->m_id == quest_status.leader_m_id)
811 return((struct monst *)0);
813 /* make a new monster which has the pet extension */
814 mtmp2 = newmonst(sizeof(struct edog) + mtmp->mnamelth);
816 mtmp2->mxlth = sizeof(struct edog);
817 if (mtmp->mnamelth) Strcpy(NAME(mtmp2), NAME(mtmp));
819 replmon(mtmp, mtmp2);
820 /* `mtmp' is now obsolete */
822 if (obj) { /* thrown food */
823 /* defer eating until the edog extension has been set up */
824 place_object(obj, mtmp2->mx, mtmp2->my); /* put on floor */
825 /* devour the food (might grow into larger, genocided monster) */
826 if (dog_eat(mtmp2, obj, mtmp2->mx, mtmp2->my, TRUE) == 2)
827 return mtmp2; /* oops, it died... */
828 /* `obj' is now obsolete */
831 newsym(mtmp2->mx, mtmp2->my);
832 if (attacktype(mtmp2->data, AT_WEAP)) {
833 mtmp2->weapon_check = NEED_HTH_WEAPON;
834 (void) mon_wield_item(mtmp2);
840 * Called during pet revival or pet life-saving.
841 * If you killed the pet, it revives wild.
842 * If you abused the pet a lot while alive, it revives wild.
843 * If you abused the pet at all while alive, it revives untame.
844 * If the pet wasn't abused and was very tame, it might revive tame.
847 wary_dog(mtmp, was_dead)
852 boolean quietly = was_dead;
855 if (!mtmp->mtame) return;
856 edog = !mtmp->isminion ? EDOG(mtmp) : 0;
858 /* if monster was starving when it died, undo that now */
859 if (edog && edog->mhpmax_penalty) {
860 mtmp->mhpmax += edog->mhpmax_penalty;
861 mtmp->mhp += edog->mhpmax_penalty; /* heal it */
862 edog->mhpmax_penalty = 0;
865 if (edog && (edog->killed_by_u == 1 || edog->abuse > 2)) {
866 mtmp->mpeaceful = mtmp->mtame = 0;
867 if (edog->abuse >= 0 && edog->abuse < 10)
868 if (!rn2(edog->abuse + 1)) mtmp->mpeaceful = 1;
869 if(!quietly && cansee(mtmp->mx, mtmp->my)) {
870 if (haseyes(youmonst.data)) {
871 if (haseyes(mtmp->data))
872 pline("%s %s to look you in the %s.",
874 mtmp->mpeaceful ? "seems unable" :
878 pline("%s avoids your gaze.",
883 /* chance it goes wild anyway - Pet Semetary */
884 if (!rn2(mtmp->mtame)) {
885 mtmp->mpeaceful = mtmp->mtame = 0;
889 newsym(mtmp->mx, mtmp->my);
890 /* a life-saved monster might be leashed;
891 don't leave it that way if it's no longer tame */
892 if (mtmp->mleashed) m_unleash(mtmp, TRUE);
895 /* if its still a pet, start a clean pet-slate now */
896 if (edog && mtmp->mtame) {
898 edog->killed_by_u = 0;
900 edog->ogoal.x = edog->ogoal.y = -1;
901 if (was_dead || edog->hungrytime < monstermoves + 500L)
902 edog->hungrytime = monstermoves + 500L;
905 edog->dropdist = 10000;
906 edog->whistletime = 0L;
908 } /* else lifesaved, so retain current values */
916 if (!mtmp->mtame) return;
918 if (Aggravate_monster || Conflict) mtmp->mtame /=2;
921 if (mtmp->mtame && !mtmp->isminion)
924 if (!mtmp->mtame && mtmp->mleashed)
925 m_unleash(mtmp, TRUE);
927 /* don't make a sound if pet is in the middle of leaving the level */
928 /* newsym isn't necessary in this case either */
930 if (mtmp->mtame && rn2(mtmp->mtame)) yelp(mtmp);
931 else growl(mtmp); /* give them a moment's worry */
933 if (!mtmp->mtame) newsym(mtmp->mx, mtmp->my);