1 /* NetHack 3.6 dog.c $NHDT-Date: 1446808440 2015/11/06 11:14:00 $ $NHDT-Branch: master $:$NHDT-Revision: 1.52 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
7 STATIC_DCL
int NDECL(pet_type
);
14 mtmp
->mextra
= newmextra();
16 EDOG(mtmp
) = (struct edog
*) alloc(sizeof(struct edog
));
17 (void) memset((genericptr_t
) EDOG(mtmp
), 0, sizeof(struct edog
));
25 if (mtmp
->mextra
&& EDOG(mtmp
)) {
26 free((genericptr_t
) EDOG(mtmp
));
27 EDOG(mtmp
) = (struct edog
*) 0;
34 register struct monst
*mtmp
;
36 mtmp
->mtame
= is_domestic(mtmp
->data
) ? 10 : 5;
39 set_malign(mtmp
); /* recalc alignment now that it's tamed */
42 EDOG(mtmp
)->droptime
= 0;
43 EDOG(mtmp
)->dropdist
= 10000;
44 EDOG(mtmp
)->apport
= ACURR(A_CHA
);
45 EDOG(mtmp
)->whistletime
= 0;
46 EDOG(mtmp
)->hungrytime
= 1000 + monstermoves
;
47 EDOG(mtmp
)->ogoal
.x
= -1; /* force error if used before set */
48 EDOG(mtmp
)->ogoal
.y
= -1;
49 EDOG(mtmp
)->abuse
= 0;
50 EDOG(mtmp
)->revivals
= 0;
51 EDOG(mtmp
)->mhpmax_penalty
= 0;
52 EDOG(mtmp
)->killed_by_u
= 0;
58 if (urole
.petnum
!= NON_PM
)
60 else if (preferred_pet
== 'c')
62 else if (preferred_pet
== 'd')
65 return rn2(2) ? PM_KITTEN
: PM_LITTLE_DOG
;
69 make_familiar(otmp
, x
, y
, quietly
)
70 register struct obj
*otmp
;
75 struct monst
*mtmp
= 0;
76 int chance
, trycnt
= 100;
79 if (otmp
) { /* figurine; otherwise spell */
80 int mndx
= otmp
->corpsenm
;
82 /* activating a figurine provides one way to exceed the
83 maximum number of the target critter created--unless
84 it has a special limit (erinys, Nazgul) */
85 if ((mvitals
[mndx
].mvflags
& G_EXTINCT
)
86 && mbirth_limit(mndx
) != MAXMONNO
) {
88 /* have just been given "You <do something with>
89 the figurine and it transforms." message */
90 pline("... into a pile of dust.");
91 break; /* mtmp is null */
94 pm
= &mons
[pet_type()];
99 There("seems to be nothing available for a familiar.");
104 mtmp
= makemon(pm
, x
, y
, MM_EDOG
| MM_IGNOREWATER
| NO_MINVENT
);
105 if (otmp
&& !mtmp
) { /* monster was genocided or square occupied */
107 pline_The("figurine writhes and then shatters into pieces!");
110 } while (!mtmp
&& --trycnt
> 0);
113 return (struct monst
*) 0;
115 if (is_pool(mtmp
->mx
, mtmp
->my
) && minliquid(mtmp
))
116 return (struct monst
*) 0;
120 if (otmp
) { /* figurine; resulting monster might not become a pet */
121 chance
= rn2(10); /* 0==tame, 1==peaceful, 2==hostile */
123 chance
= otmp
->blessed
? 0 : !otmp
->cursed
? 1 : 2;
124 /* 0,1,2: b=80%,10,10; nc=10%,80,10; c=10%,10,80 */
126 mtmp
->mtame
= 0; /* not tame after all */
127 if (chance
== 2) { /* hostile (cursed figurine) */
129 You("get a bad feeling about this.");
134 /* if figurine has been named, give same name to the monster */
136 mtmp
= christen_monst(mtmp
, ONAME(otmp
));
138 set_malign(mtmp
); /* more alignment changes */
139 newsym(mtmp
->mx
, mtmp
->my
);
141 /* must wield weapon immediately since pets will otherwise drop it */
142 if (mtmp
->mtame
&& attacktype(mtmp
->data
, AT_WEAP
)) {
143 mtmp
->weapon_check
= NEED_HTH_WEAPON
;
144 (void) mon_wield_item(mtmp
);
152 register struct monst
*mtmp
;
153 register struct obj
*otmp
;
156 static int petname_used
= 0;
158 if (preferred_pet
== 'n')
159 return ((struct monst
*) 0);
161 pettype
= pet_type();
162 if (pettype
== PM_LITTLE_DOG
)
164 else if (pettype
== PM_PONY
)
169 /* default pet names */
170 if (!*petname
&& pettype
== PM_LITTLE_DOG
) {
171 /* All of these names were for dogs. */
172 if (Role_if(PM_CAVEMAN
))
173 petname
= "Slasher"; /* The Warrior */
174 if (Role_if(PM_SAMURAI
))
175 petname
= "Hachi"; /* Shibuya Station */
176 if (Role_if(PM_BARBARIAN
))
177 petname
= "Idefix"; /* Obelix */
178 if (Role_if(PM_RANGER
))
179 petname
= "Sirius"; /* Orion's dog */
182 mtmp
= makemon(&mons
[pettype
], u
.ux
, u
.uy
, MM_EDOG
);
185 return ((struct monst
*) 0); /* pets were genocided */
187 context
.startingpet_mid
= mtmp
->m_id
;
188 /* Horses already wear a saddle */
189 if (pettype
== PM_PONY
&& !!(otmp
= mksobj(SADDLE
, TRUE
, FALSE
))) {
190 otmp
->dknown
= otmp
->bknown
= otmp
->rknown
= 1;
191 put_saddle_on_mon(otmp
, mtmp
);
194 if (!petname_used
++ && *petname
)
195 mtmp
= christen_monst(mtmp
, petname
);
201 /* record `last move time' for all monsters prior to level save so that
202 mon_arrive() can catch up for lost time when they're restored later */
208 /* monst->mlstmv used to be updated every time `monst' actually moved,
209 but that is no longer the case so we just do a blanket assignment */
210 for (mon
= fmon
; mon
; mon
= mon
->nmon
) {
211 if (DEADMONSTER(mon
))
213 mon
->mlstmv
= monstermoves
;
220 register struct monst
*mtmp
, *mtmp0
= 0, *mtmp2
;
224 * First, scan migrating_mons for shopkeepers who want to dismiss Kops,
225 * and scan mydogs for shopkeepers who want to retain kops.
226 * Second, dismiss kops if warranted, making more room for arrival.
227 * Third, place monsters accompanying the hero.
228 * Last, place migrating monsters coming to this level.
230 * Hero might eventually be displaced (due to the third step, but
231 * occurring later), which is the main reason to do the second step
232 * sooner (in turn necessitating the first step, rather than combining
233 * the list scans with monster placement).
236 /* check for returning shk(s) */
237 for (mtmp
= migrating_mons
; mtmp
; mtmp
= mtmp
->nmon
) {
238 if (mtmp
->mux
!= u
.uz
.dnum
|| mtmp
->muy
!= u
.uz
.dlevel
)
241 if (ESHK(mtmp
)->dismiss_kops
) {
242 if (dismissKops
== 0)
244 ESHK(mtmp
)->dismiss_kops
= FALSE
; /* reset */
245 } else if (!mtmp
->mpeaceful
) {
246 /* an unpacified shk is returning; don't dismiss kops
247 even if another pacified one is willing to do so */
249 /* [keep looping; later monsters might need ESHK reset] */
253 /* make the same check for mydogs */
254 for (mtmp
= mydogs
; mtmp
&& dismissKops
>= 0; mtmp
= mtmp
->nmon
) {
256 /* hostile shk might accompany hero [ESHK(mtmp)->dismiss_kops
257 can't be set here; it's only used for migrating_mons] */
258 if (!mtmp
->mpeaceful
)
263 /* when a hostile shopkeeper chases hero to another level
264 and then gets paid off there, get rid of summoned kops
265 here now that he has returned to his shop level */
267 make_happy_shoppers(TRUE
);
269 /* place pets and/or any other monsters who accompany hero */
270 while ((mtmp
= mydogs
) != 0) {
272 mon_arrive(mtmp
, TRUE
);
275 /* time for migrating monsters to arrive */
276 for (mtmp
= migrating_mons
; mtmp
; mtmp
= mtmp2
) {
278 if (mtmp
->mux
== u
.uz
.dnum
&& mtmp
->muy
== u
.uz
.dlevel
) {
279 if (mtmp
== migrating_mons
)
280 migrating_mons
= mtmp
->nmon
;
282 mtmp0
->nmon
= mtmp
->nmon
;
283 mon_arrive(mtmp
, FALSE
);
289 /* called from resurrect() in addition to losedogs() */
291 mon_arrive(mtmp
, with_you
)
296 xchar xlocale
, ylocale
, xyloc
, xyflags
, wander
;
302 set_residency(mtmp
, FALSE
);
304 num_segs
= mtmp
->wormno
;
305 /* baby long worms have no tail so don't use is_longworm() */
306 if (mtmp
->data
== &mons
[PM_LONG_WORM
]) {
307 mtmp
->wormno
= get_wormno();
309 initworm(mtmp
, num_segs
);
313 /* some monsters might need to do something special upon arrival
314 _after_ the current level has been fully set up; see dochug() */
315 mtmp
->mstrategy
|= STRAT_ARRIVE
;
317 /* make sure mnexto(rloc_to(set_apparxy())) doesn't use stale data */
318 mtmp
->mux
= u
.ux
, mtmp
->muy
= u
.uy
;
319 xyloc
= mtmp
->mtrack
[0].x
;
320 xyflags
= mtmp
->mtrack
[0].y
;
321 xlocale
= mtmp
->mtrack
[1].x
;
322 ylocale
= mtmp
->mtrack
[1].y
;
323 memset(mtmp
->mtrack
, 0, sizeof(mtmp
->mtrack
));
325 if (mtmp
== u
.usteed
)
326 return; /* don't place steed on the map */
328 /* When a monster accompanies you, sometimes it will arrive
329 at your intended destination and you'll end up next to
330 that spot. This code doesn't control the final outcome;
331 goto_level(do.c) decides who ends up at your target spot
332 when there is a monster there too. */
333 if (!MON_AT(u
.ux
, u
.uy
)
334 && !rn2(mtmp
->mtame
? 10 : mtmp
->mpeaceful
? 5 : 2))
335 rloc_to(mtmp
, u
.ux
, u
.uy
);
341 * The monster arrived on this level independently of the player.
342 * Its coordinate fields were overloaded for use as flags that
343 * specify its final destination.
346 if (mtmp
->mlstmv
< monstermoves
- 1L) {
347 /* heal monster for time spent in limbo */
348 long nmv
= monstermoves
- 1L - mtmp
->mlstmv
;
350 mon_catchup_elapsed_time(mtmp
, nmv
);
351 mtmp
->mlstmv
= monstermoves
- 1L;
353 /* let monster move a bit on new level (see placement code below) */
354 wander
= (xchar
) min(nmv
, 8);
359 case MIGR_APPROX_XY
: /* {x,y}locale set above */
365 xlocale
= u
.ux
, ylocale
= u
.uy
;
368 xlocale
= xupstair
, ylocale
= yupstair
;
370 case MIGR_STAIRS_DOWN
:
371 xlocale
= xdnstair
, ylocale
= ydnstair
;
374 xlocale
= xupladder
, ylocale
= yupladder
;
376 case MIGR_LADDER_DOWN
:
377 xlocale
= xdnladder
, ylocale
= ydnladder
;
380 xlocale
= sstairs
.sx
, ylocale
= sstairs
.sy
;
383 if (In_endgame(&u
.uz
)) {
384 /* there is no arrival portal for endgame levels */
385 /* BUG[?]: for simplicity, this code relies on the fact
386 that we know that the current endgame levels always
387 build upwards and never have any exclusion subregion
388 inside their TELEPORT_REGION settings. */
389 xlocale
= rn1(updest
.hx
- updest
.lx
+ 1, updest
.lx
);
390 ylocale
= rn1(updest
.hy
- updest
.ly
+ 1, updest
.ly
);
393 /* find the arrival portal */
394 for (t
= ftrap
; t
; t
= t
->ntrap
)
395 if (t
->ttyp
== MAGIC_PORTAL
)
398 xlocale
= t
->tx
, ylocale
= t
->ty
;
401 impossible("mon_arrive: no corresponding portal?");
405 xlocale
= ylocale
= 0;
409 if (xlocale
&& wander
) {
410 /* monster moved a bit; pick a nearby location */
411 /* mnearto() deals w/stone, et al */
412 char *r
= in_rooms(xlocale
, ylocale
, 0);
415 /* somexy() handles irregular rooms */
416 if (somexy(&rooms
[*r
- ROOMOFFSET
], &c
))
417 xlocale
= c
.x
, ylocale
= c
.y
;
419 xlocale
= ylocale
= 0;
420 } else { /* not in a room */
422 i
= max(1, xlocale
- wander
);
423 j
= min(COLNO
- 1, xlocale
+ wander
);
424 xlocale
= rn1(j
- i
, i
);
425 i
= max(0, ylocale
- wander
);
426 j
= min(ROWNO
- 1, ylocale
+ wander
);
427 ylocale
= rn1(j
- i
, i
);
431 mtmp
->mx
= 0; /*(already is 0)*/
434 if (!mnearto(mtmp
, xlocale
, ylocale
, FALSE
))
435 goto fail_mon_placement
;
437 if (!rloc(mtmp
, TRUE
)) {
439 * Failed to place migrating monster,
440 * probably because the level is full.
441 * Dump the monster's cargo and leave the monster dead.
445 while ((obj
= mtmp
->minvent
) != 0) {
446 obj_extract_self(obj
);
447 obj_no_longer_held(obj
);
448 if (obj
->owornmask
& W_WEP
)
449 setmnotwielded(mtmp
, obj
);
451 if (xlocale
&& ylocale
)
452 place_object(obj
, xlocale
, ylocale
);
453 else if (rloco(obj
)) {
454 if (!get_obj_location(obj
, &xlocale
, &ylocale
, 0))
455 impossible("Can't find relocated object.");
458 (void) mkcorpstat(CORPSE
, (struct monst
*) 0, mtmp
->data
, xlocale
,
459 ylocale
, CORPSTAT_NONE
);
465 /* heal monster for time spent elsewhere */
467 mon_catchup_elapsed_time(mtmp
, nmv
)
469 long nmv
; /* number of moves */
471 int imv
= 0; /* avoid zillions of casts and lint warnings */
473 #if defined(DEBUG) || defined(BETA)
474 if (nmv
< 0L) { /* crash likely... */
475 panic("catchup from future time?");
478 } else if (nmv
== 0L) { /* safe, but should'nt happen */
479 impossible("catchup from now?");
482 if (nmv
>= LARGEST_INT
) /* paranoia */
483 imv
= LARGEST_INT
- 1;
487 /* might stop being afraid, blind or frozen */
488 /* set to 1 and allow final decrement in movemon() */
489 if (mtmp
->mblinded
) {
490 if (imv
>= (int) mtmp
->mblinded
)
493 mtmp
->mblinded
-= imv
;
496 if (imv
>= (int) mtmp
->mfrozen
)
499 mtmp
->mfrozen
-= imv
;
501 if (mtmp
->mfleetim
) {
502 if (imv
>= (int) mtmp
->mfleetim
)
505 mtmp
->mfleetim
-= imv
;
508 /* might recover from temporary trouble */
509 if (mtmp
->mtrapped
&& rn2(imv
+ 1) > 40 / 2)
511 if (mtmp
->mconf
&& rn2(imv
+ 1) > 50 / 2)
513 if (mtmp
->mstun
&& rn2(imv
+ 1) > 10 / 2)
516 /* might finish eating or be able to use special ability again */
517 if (imv
> mtmp
->meating
)
518 finish_meating(mtmp
);
520 mtmp
->meating
-= imv
;
521 if (imv
> mtmp
->mspec_used
)
522 mtmp
->mspec_used
= 0;
524 mtmp
->mspec_used
-= imv
;
526 /* reduce tameness for every 150 moves you are separated */
528 int wilder
= (imv
+ 75) / 150;
529 if (mtmp
->mtame
> wilder
)
530 mtmp
->mtame
-= wilder
; /* less tame */
531 else if (mtmp
->mtame
> rn2(wilder
))
532 mtmp
->mtame
= 0; /* untame */
534 mtmp
->mtame
= mtmp
->mpeaceful
= 0; /* hostile! */
536 /* check to see if it would have died as a pet; if so, go wild instead
537 * of dying the next time we call dog_move()
539 if (mtmp
->mtame
&& !mtmp
->isminion
540 && (carnivorous(mtmp
->data
) || herbivorous(mtmp
->data
))) {
541 struct edog
*edog
= EDOG(mtmp
);
543 if ((monstermoves
> edog
->hungrytime
+ 500 && mtmp
->mhp
< 3)
544 || (monstermoves
> edog
->hungrytime
+ 750))
545 mtmp
->mtame
= mtmp
->mpeaceful
= 0;
548 if (!mtmp
->mtame
&& mtmp
->mleashed
) {
549 /* leashed monsters should always be with hero, consequently
550 never losing any time to be accounted for later */
551 impossible("catching up for leashed monster?");
552 m_unleash(mtmp
, FALSE
);
555 /* recover lost hit points */
556 if (!regenerates(mtmp
->data
))
558 if (mtmp
->mhp
+ imv
>= mtmp
->mhpmax
)
559 mtmp
->mhp
= mtmp
->mhpmax
;
564 /* called when you move to another level */
567 boolean pets_only
; /* true for ascension or final escape */
569 register struct monst
*mtmp
, *mtmp2
;
570 register struct obj
*obj
;
574 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp2
) {
576 if (DEADMONSTER(mtmp
))
580 continue; /* reject non-pets */
581 /* don't block pets from accompanying hero's dungeon
582 escape or ascension simply due to mundane trifles;
583 unlike level change for steed, don't bother trying
584 to achieve a normal trap escape first */
591 if (((monnear(mtmp
, u
.ux
, u
.uy
) && levl_follower(mtmp
))
592 /* the wiz will level t-port from anywhere to chase
593 the amulet; if you don't have it, will chase you
594 only if in range. -3. */
595 || (u
.uhave
.amulet
&& mtmp
->iswiz
))
596 && ((!mtmp
->msleeping
&& mtmp
->mcanmove
)
597 /* eg if level teleport or new trap, steed has no control
598 to avoid following */
599 || (mtmp
== u
.usteed
))
600 /* monster won't follow if it hasn't noticed you yet */
601 && !(mtmp
->mstrategy
& STRAT_WAITFORU
)) {
604 (void) mintrap(mtmp
); /* try to escape */
605 if (mtmp
== u
.usteed
) {
606 /* make sure steed is eligible to accompany hero */
607 mtmp
->mtrapped
= 0; /* escape trap */
608 mtmp
->meating
= 0; /* terminate eating */
609 mdrop_special_objs(mtmp
); /* drop Amulet */
610 } else if (mtmp
->meating
|| mtmp
->mtrapped
) {
612 pline("%s is still %s.", Monnam(mtmp
),
613 mtmp
->meating
? "eating" : "trapped");
615 } else if (mon_has_amulet(mtmp
)) {
617 pline("%s seems very disoriented for a moment.",
622 if (mtmp
->mleashed
) {
623 pline("%s leash suddenly comes loose.",
625 ? (mtmp
->female
? "Her" : "His")
627 m_unleash(mtmp
, FALSE
);
629 if (mtmp
== u
.usteed
) {
630 /* can't happen unless someone makes a change
631 which scrambles the stay_behind logic above */
632 impossible("steed left behind?");
633 dismount_steed(DISMOUNT_GENERIC
);
638 set_residency(mtmp
, TRUE
);
642 /* NOTE: worm is truncated to # segs = max wormno size */
643 cnt
= count_wsegs(mtmp
);
644 num_segs
= min(cnt
, MAX_NUM_WORMS
- 1);
649 /* set minvent's obj->no_charge to 0 */
650 for (obj
= mtmp
->minvent
; obj
; obj
= obj
->nobj
) {
651 if (Has_contents(obj
))
652 picked_container(obj
); /* does the right thing */
656 relmon(mtmp
, &mydogs
); /* move it from map to mydogs */
657 mtmp
->mx
= mtmp
->my
= 0; /* avoid mnexto()/MON_AT() problem */
658 mtmp
->wormno
= num_segs
;
659 mtmp
->mlstmv
= monstermoves
;
660 } else if (mtmp
->iswiz
) {
661 /* we want to be able to find him when his next resurrection
662 chance comes up, but have him resume his present location
663 if player returns to this level before that time */
664 migrate_to_level(mtmp
, ledger_no(&u
.uz
), MIGR_EXACT_XY
,
666 } else if (mtmp
->mleashed
) {
667 /* this can happen if your quest leader ejects you from the
668 "home" level while a leashed pet isn't next to you */
669 pline("%s leash goes slack.", s_suffix(Monnam(mtmp
)));
670 m_unleash(mtmp
, FALSE
);
676 migrate_to_level(mtmp
, tolev
, xyloc
, cc
)
677 register struct monst
*mtmp
;
678 xchar tolev
; /* destination level */
679 xchar xyloc
; /* MIGR_xxx destination xy location: */
680 coord
*cc
; /* optional destination coordinates */
682 register struct obj
*obj
;
685 int num_segs
= 0; /* count of worm segments */
688 set_residency(mtmp
, TRUE
);
692 /* **** NOTE: worm is truncated to # segs = max wormno size **** */
693 cnt
= count_wsegs(mtmp
);
694 num_segs
= min(cnt
, MAX_NUM_WORMS
- 1);
698 /* set minvent's obj->no_charge to 0 */
699 for (obj
= mtmp
->minvent
; obj
; obj
= obj
->nobj
) {
700 if (Has_contents(obj
))
701 picked_container(obj
); /* does the right thing */
705 if (mtmp
->mleashed
) {
707 m_unleash(mtmp
, TRUE
);
709 relmon(mtmp
, &migrating_mons
); /* move it from map to migrating_mons */
711 new_lev
.dnum
= ledger_to_dnum((xchar
) tolev
);
712 new_lev
.dlevel
= ledger_to_dlev((xchar
) tolev
);
713 /* overload mtmp->[mx,my], mtmp->[mux,muy], and mtmp->mtrack[] as */
714 /* destination codes (setup flag bits before altering mx or my) */
715 xyflags
= (depth(&new_lev
) < depth(&u
.uz
)); /* 1 => up */
716 if (In_W_tower(mtmp
->mx
, mtmp
->my
, &u
.uz
))
718 mtmp
->wormno
= num_segs
;
719 mtmp
->mlstmv
= monstermoves
;
720 mtmp
->mtrack
[1].x
= cc
? cc
->x
: mtmp
->mx
;
721 mtmp
->mtrack
[1].y
= cc
? cc
->y
: mtmp
->my
;
722 mtmp
->mtrack
[0].x
= xyloc
;
723 mtmp
->mtrack
[0].y
= xyflags
;
724 mtmp
->mux
= new_lev
.dnum
;
725 mtmp
->muy
= new_lev
.dlevel
;
726 mtmp
->mx
= mtmp
->my
= 0; /* this implies migration */
727 if (mtmp
== context
.polearm
.hitmon
)
728 context
.polearm
.hitmon
= NULL
;
731 /* return quality of food; the lower the better */
732 /* fungi will eat even tainted food */
736 register struct obj
*obj
;
738 struct permonst
*mptr
= mon
->data
, *fptr
= 0;
739 boolean carni
= carnivorous(mptr
), herbi
= herbivorous(mptr
), starving
;
741 if (is_quest_artifact(obj
) || obj_resists(obj
, 0, 95))
742 return obj
->cursed
? TABU
: APPORT
;
744 switch (obj
->oclass
) {
746 if (obj
->otyp
== CORPSE
|| obj
->otyp
== TIN
|| obj
->otyp
== EGG
)
747 fptr
= &mons
[obj
->corpsenm
];
749 if (obj
->otyp
== CORPSE
&& is_rider(fptr
))
751 if ((obj
->otyp
== CORPSE
|| obj
->otyp
== EGG
) && touch_petrifies(fptr
)
752 && !resists_ston(mon
))
754 if (!carni
&& !herbi
)
755 return obj
->cursed
? UNDEF
: APPORT
;
757 /* a starving pet will eat almost anything */
759 (mon
->mtame
&& !mon
->isminion
&& EDOG(mon
)->mhpmax_penalty
);
761 /* ghouls prefer old corpses and unhatchable eggs, yum!
762 they'll eat fresh non-veggy corpses and hatchable eggs
763 when starving; they never eat stone-to-flesh'd meat */
764 if (mptr
== &mons
[PM_GHOUL
]) {
765 if (obj
->otyp
== CORPSE
)
766 return (peek_at_iced_corpse_age(obj
) + 50L <= monstermoves
767 && fptr
!= &mons
[PM_LIZARD
]
768 && fptr
!= &mons
[PM_LICHEN
])
770 : (starving
&& !vegan(fptr
))
773 if (obj
->otyp
== EGG
)
774 return stale_egg(obj
) ? CADAVER
: starving
? ACCFOOD
: POISON
;
783 case HUGE_CHUNK_OF_MEAT
:
784 return carni
? DOGFOOD
: MANFOOD
;
786 return carni
? CADAVER
: MANFOOD
;
788 if ((peek_at_iced_corpse_age(obj
) + 50L <= monstermoves
789 && obj
->corpsenm
!= PM_LIZARD
&& obj
->corpsenm
!= PM_LICHEN
790 && mptr
->mlet
!= S_FUNGUS
)
791 || (acidic(fptr
) && !resists_acid(mon
))
792 || (poisonous(fptr
) && !resists_poison(mon
)))
794 /* turning into slime is preferable to starvation */
795 else if (fptr
== &mons
[PM_GREEN_SLIME
] && !slimeproof(mon
->data
))
796 return starving
? ACCFOOD
: POISON
;
797 else if (vegan(fptr
))
798 return herbi
? CADAVER
: MANFOOD
;
799 /* most humanoids will avoid cannibalism unless starving;
800 arbitrary: elves won't eat other elves even then */
801 else if (humanoid(mptr
) && same_race(mptr
, fptr
)
802 && (!is_undead(mptr
) && fptr
->mlet
!= S_KOBOLD
803 && fptr
->mlet
!= S_ORC
&& fptr
->mlet
!= S_OGRE
))
804 return (starving
&& carni
&& !is_elf(mptr
)) ? ACCFOOD
: TABU
;
806 return carni
? CADAVER
: MANFOOD
;
807 case CLOVE_OF_GARLIC
:
808 return (is_undead(mptr
) || is_vampshifter(mon
))
810 : (herbi
|| starving
)
814 return metallivorous(mptr
) ? ACCFOOD
: MANFOOD
;
817 return herbi
? DOGFOOD
: starving
? ACCFOOD
: MANFOOD
;
819 return (mptr
->mlet
== S_YETI
&& herbi
)
820 ? DOGFOOD
/* for monkey and ape (tameable), sasquatch */
821 : (herbi
|| starving
)
827 return (obj
->otyp
> SLIME_MOLD
) ? (carni
? ACCFOOD
: MANFOOD
)
828 : (herbi
? ACCFOOD
: MANFOOD
);
831 if (obj
->otyp
== AMULET_OF_STRANGULATION
832 || obj
->otyp
== RIN_SLOW_DIGESTION
)
834 if (mon_hates_silver(mon
) && objects
[obj
->otyp
].oc_material
== SILVER
)
836 if (mptr
== &mons
[PM_GELATINOUS_CUBE
] && is_organic(obj
))
838 if (metallivorous(mptr
) && is_metallic(obj
)
839 && (is_rustprone(obj
) || mptr
!= &mons
[PM_RUST_MONSTER
])) {
840 /* Non-rustproofed ferrous based metals are preferred. */
841 return (is_rustprone(obj
) && !obj
->oerodeproof
) ? DOGFOOD
845 && obj
->oclass
!= BALL_CLASS
846 && obj
->oclass
!= CHAIN_CLASS
)
855 * With the separate mextra structure added in 3.6.x this always
856 * operates on the original mtmp. It now returns TRUE if the taming
861 register struct monst
*mtmp
;
862 register struct obj
*obj
;
864 /* The Wiz, Medusa and the quest nemeses aren't even made peaceful. */
865 if (mtmp
->iswiz
|| mtmp
->data
== &mons
[PM_MEDUSA
]
866 || (mtmp
->data
->mflags3
& M3_WANTSARTI
))
869 /* worst case, at least it'll be peaceful. */
872 if (flags
.moonphase
== FULL_MOON
&& night() && rn2(6) && obj
873 && mtmp
->data
->mlet
== S_DOG
)
876 /* If we cannot tame it, at least it's no longer afraid. */
880 /* make grabber let go now, whether it becomes tame or not */
881 if (mtmp
== u
.ustuck
) {
883 expels(mtmp
, mtmp
->data
, TRUE
);
884 else if (!(Upolyd
&& sticks(youmonst
.data
)))
888 /* feeding it treats makes it tamer */
889 if (mtmp
->mtame
&& obj
) {
892 if (mtmp
->mcanmove
&& !mtmp
->mconf
&& !mtmp
->meating
893 && ((tasty
= dogfood(mtmp
, obj
)) == DOGFOOD
895 && EDOG(mtmp
)->hungrytime
<= monstermoves
))) {
896 /* pet will "catch" and eat this thrown food */
897 if (canseemon(mtmp
)) {
899 (obj
->otyp
== CORPSE
&& obj
->corpsenm
>= LOW_PM
900 && mons
[obj
->corpsenm
].msize
> mtmp
->data
->msize
);
901 pline("%s catches %s%s", Monnam(mtmp
), the(xname(obj
)),
902 !big_corpse
? "." : ", or vice versa!");
903 } else if (cansee(mtmp
->mx
, mtmp
->my
))
904 pline("%s.", Tobjnam(obj
, "stop"));
905 /* dog_eat expects a floor object */
906 place_object(obj
, mtmp
->mx
, mtmp
->my
);
907 (void) dog_eat(mtmp
, obj
, mtmp
->mx
, mtmp
->my
, FALSE
);
908 /* eating might have killed it, but that doesn't matter here;
909 a non-null result suppresses "miss" message for thrown
910 food and also implies that the object has been deleted */
916 if (mtmp
->mtame
|| !mtmp
->mcanmove
917 /* monsters with conflicting structures cannot be tamed */
918 || mtmp
->isshk
|| mtmp
->isgd
|| mtmp
->ispriest
|| mtmp
->isminion
919 || is_covetous(mtmp
->data
) || is_human(mtmp
->data
)
920 || (is_demon(mtmp
->data
) && !is_demon(youmonst
.data
))
921 || (obj
&& dogfood(mtmp
, obj
) >= MANFOOD
))
924 if (mtmp
->m_id
== quest_status
.leader_m_id
)
927 /* add the pet extension */
931 if (obj
) { /* thrown food */
932 /* defer eating until the edog extension has been set up */
933 place_object(obj
, mtmp
->mx
, mtmp
->my
); /* put on floor */
934 /* devour the food (might grow into larger, genocided monster) */
935 if (dog_eat(mtmp
, obj
, mtmp
->mx
, mtmp
->my
, TRUE
) == 2)
936 return TRUE
; /* oops, it died... */
937 /* `obj' is now obsolete */
940 newsym(mtmp
->mx
, mtmp
->my
);
941 if (attacktype(mtmp
->data
, AT_WEAP
)) {
942 mtmp
->weapon_check
= NEED_HTH_WEAPON
;
943 (void) mon_wield_item(mtmp
);
949 * Called during pet revival or pet life-saving.
950 * If you killed the pet, it revives wild.
951 * If you abused the pet a lot while alive, it revives wild.
952 * If you abused the pet at all while alive, it revives untame.
953 * If the pet wasn't abused and was very tame, it might revive tame.
956 wary_dog(mtmp
, was_dead
)
961 boolean quietly
= was_dead
;
963 finish_meating(mtmp
);
967 edog
= !mtmp
->isminion
? EDOG(mtmp
) : 0;
969 /* if monster was starving when it died, undo that now */
970 if (edog
&& edog
->mhpmax_penalty
) {
971 mtmp
->mhpmax
+= edog
->mhpmax_penalty
;
972 mtmp
->mhp
+= edog
->mhpmax_penalty
; /* heal it */
973 edog
->mhpmax_penalty
= 0;
976 if (edog
&& (edog
->killed_by_u
== 1 || edog
->abuse
> 2)) {
977 mtmp
->mpeaceful
= mtmp
->mtame
= 0;
978 if (edog
->abuse
>= 0 && edog
->abuse
< 10)
979 if (!rn2(edog
->abuse
+ 1))
981 if (!quietly
&& cansee(mtmp
->mx
, mtmp
->my
)) {
982 if (haseyes(youmonst
.data
)) {
983 if (haseyes(mtmp
->data
))
984 pline("%s %s to look you in the %s.", Monnam(mtmp
),
985 mtmp
->mpeaceful
? "seems unable" : "refuses",
988 pline("%s avoids your gaze.", Monnam(mtmp
));
992 /* chance it goes wild anyway - Pet Sematary */
993 mtmp
->mtame
= rn2(mtmp
->mtame
+ 1);
995 mtmp
->mpeaceful
= rn2(2);
999 if (!quietly
&& canspotmon(mtmp
))
1000 pline("%s %s.", Monnam(mtmp
),
1001 mtmp
->mpeaceful
? "is no longer tame" : "has become feral");
1002 newsym(mtmp
->mx
, mtmp
->my
);
1003 /* a life-saved monster might be leashed;
1004 don't leave it that way if it's no longer tame */
1006 m_unleash(mtmp
, TRUE
);
1007 if (mtmp
== u
.usteed
)
1008 dismount_steed(DISMOUNT_THROWN
);
1010 /* it's still a pet; start a clean pet-slate now */
1012 edog
->killed_by_u
= 0;
1014 edog
->ogoal
.x
= edog
->ogoal
.y
= -1;
1015 if (was_dead
|| edog
->hungrytime
< monstermoves
+ 500L)
1016 edog
->hungrytime
= monstermoves
+ 500L;
1018 edog
->droptime
= 0L;
1019 edog
->dropdist
= 10000;
1020 edog
->whistletime
= 0L;
1022 } /* else lifesaved, so retain current values */
1033 if (Aggravate_monster
|| Conflict
)
1038 if (mtmp
->mtame
&& !mtmp
->isminion
)
1039 EDOG(mtmp
)->abuse
++;
1041 if (!mtmp
->mtame
&& mtmp
->mleashed
)
1042 m_unleash(mtmp
, TRUE
);
1044 /* don't make a sound if pet is in the middle of leaving the level */
1045 /* newsym isn't necessary in this case either */
1046 if (mtmp
->mx
!= 0) {
1047 if (mtmp
->mtame
&& rn2(mtmp
->mtame
))
1050 growl(mtmp
); /* give them a moment's worry */
1053 newsym(mtmp
->mx
, mtmp
->my
);