Difference between revisions of "User:Killian/Pet food"

From NetHackWiki
Jump to navigation Jump to search
(notes on pets eating thrown food)
m (messed up for some reason, trying fix)
Line 163: Line 163:
  
 
If the food is <tt>ACCFOOD</tt> or better, {{source:dog.c#tamedog}} is called. In order to catch and eat the food, the pet must be able to move, must not be confused or eating, and the food must be a treat (acceptable or better if the pet is hungry). If this is not the case, the food will miss the pet and fall to the floor. (If it is a suitable corpse, the pet should end up eating it on its next turn anyway.) Caught food is eaten with <tt>dog_eat</tt>, which is the same function used by pets eating from the ground.
 
If the food is <tt>ACCFOOD</tt> or better, {{source:dog.c#tamedog}} is called. In order to catch and eat the food, the pet must be able to move, must not be confused or eating, and the food must be a treat (acceptable or better if the pet is hungry). If this is not the case, the food will miss the pet and fall to the floor. (If it is a suitable corpse, the pet should end up eating it on its next turn anyway.) Caught food is eaten with <tt>dog_eat</tt>, which is the same function used by pets eating from the ground.
 
=== Food on the ground ===
 
 
(todo)
 

Revision as of 03:27, 26 May 2008

Item types

  • Treat (DOGFOOD)
  • Suitable corpse (CADAVER)
  • Acceptable (ACCFOOD)
  • Human food (MANFOOD)
  • Apportable (APPORT)
  • Poison (POISON)
  • Uninteresting (UNDEF)
  • Taboo (TABU)

These classifications appear to affect the following:

  • Whether thrown food will tame or pacify a domestic animal
  • The effect of thrown food on a pet
  • Whether a pet will eat an item on the ground
  • Whether or not a pet will try to move to a particular square

They do not seem to affect whether a pet will pick up non-food items.

There are specific checks for DOGFOOD, CADAVER, ACCFOOD, MANFOOD, and UNDEF, and there is at least one generic comparison. There do not seem to be any specific checks for APPORT, POISON, or TABU.

A pet will never use an UNDEF item as its movement goal. If its goal is MANFOOD or worse, it will set gtyp to APPORT, which means that it won't consider any further items that are worse than apportable.

The main use of MANFOOD seems to be that pets can set it as their goal without being able to see it. There does not appear to be any other special treatment of human food.

Pet goal code won't consider goal items with a worse type than the current goal item. This appears to be the main prioritization mechanism. An equal-quality item that is ACCFOOD or better will only become the new goal if it is closer than the existing goal.

Curiously, a pet won't seek a non-food item unless either your square is lit, or its square is not lit.

Classification

  • Quest artifacts (and other artifacts, 5% of the time) are considered taboo if cursed, or apportable otherwise.

Food

  • Rider corpses are taboo.
  • Petrifying corpses are taboo for monsters that are not stoning-resistant.
  • For ghouls, old corpses (more than 50 turns) are treats, and other corpses are taboo. This seems to apply even to corpses that don't degrade, such as lizard or lichen corpses.
  • For monsters (other than ghouls) that are neither carnivores nor herbivores, cursed food is uninteresting and non-cursed food is apportable.
  • Petrifying eggs are considered poison by monsters not stoning-resistant. Other eggs are considered suitable corpses by carnivores, and human food by herbivores.
  • Corpses that are more than 50 turns old and are not lizards or F are considered poison. Acidic corpses are poison for monsters not acid-resistant. Poisonous corpses are poison for monsters not poison-resistant. Vegan corpses are considered suitable corpses by herbivores, and non-vegan corpses are considered suitable by carnivores. All other corpses are considered human food.
  • A clove of garlic is taboo for undead monsters. (Since no undead monster is also a carnivore/herbivore/omnivore, this is irrelevant.) It is acceptable to herbivores and to starving carnivores; otherwise it is considered human food.
  • Tins are considered acceptable to metallivores. (Since no metallivore monster is also a carnivore/herbivore/omnivore, this is irrelevant.) They are considered human food otherwise.
  • Apples and carrots are treats for herbivores. Carnivores will consider them acceptable if starving, and human food otherwise.
  • Bananas are considered treats for Y. They are acceptable to herbivores and starving carnivores, and are otherwise considered human food.
  • All other comestibles are considered acceptable by starving pets. Other fruits and vegetables are acceptable to herbivores, and other processed foods (including royal jelly) are acceptable to carnivores; they are otherwise considered human food.
Comestible Carnivore Herbivore
tripe ration T h
meatball T h
meat ring T h
meat stick T h
huge chunk of meat T h
kelp frond h (A) A
eucalyptus leaf h (A) A
apple h (A) T
orange h (A) A
pear h (A) A
melon h (A) A
banana h (A)* A*
carrot h (A) T
sprig of wolfsbane h (A) A
clove of garlic h (A) A
slime mold h (A) A
lump of royal jelly A h (A)
cream pie A h (A)
candy bar A h (A)
fortune cookie A h (A)
pancake A h (A)
lembas wafer A h (A)
cram ration A h (A)
food ration A h (A)
K-ration A h (A)
C-ration A h (A)
tin h h

Non-food

  • Any object made of silver is taboo for silver-hating monsters.

dog_invent

(from dog_invent in monmove.c)

Pets will only interact with the topmost item.

Pets will not pick up heavy iron balls, iron chains, boulders, statues, or scrolls of mail.

If the item is a treat or a suitable corpse (or acceptable to a starving pet), the pet will eat it. Pets do not seem to care if the food is cursed, though they will still try to avoid the square containing the cursed food.

If the pet is able to carry the item, and it is not cursed, there is a chance that it will pick up the item. The pet will immediately wield its best melee weapon and wear its best armor, if able, in case the new item is better.

There are two probability checks that must both succeed: (rn2(20) < edog->apport+3) and (rn2(udist) || !rn2(edog->apport)). This means the pet must first pass a d20 apport check (with a +3 bonus), and then must be relatively far from the player, have relatively low apport, or else simply be lucky.

The following restrictions apply to monsters picking up items: (from can_carry in mon.c)

  • Monsters marked M1_NOTAKE cannot pick up anything.
  • Monsters cannot take petrifying corpses, unless they are stoning-resistant or are wearing gloves.
  • Rider corpses cannot be taken.
  • Silver-hating monsters cannot take silver items. As an exception, covetous monsters may pick up the Bell of Opening.
  • Monsters being ridden cannot pick up anything.
  • Shopkeepers can always pick up anything, ignoring weight limits.
  • Peaceful monsters cannot pick up anything.
  • Rock-throwing monsters (M2_ROCKTHROW) can always pick up boulders, ignoring weight limits.
  • Nymphs can always pick up anything, except for statues and boulders, ignoring weight limits.
  • Otherwise, the monster must have enough weight capacity to pick up the item in question.

Pets eating

Thrown food

Throwing an egg or cream pie (or spitting venom) at a pet will never be treated as thrown food; it will hit or miss the pet as normal.

If the food is ACCFOOD or better, __MIXEDSYNTAXHIGHLIGHT__ Below is the full text to dog.c from the source code of NetHack 3.6.1. To link to a particular line, write [[Source:NetHack 3.6.1/src/dog.c#line123]], for example.

Top of file

1. /* NetHack 3.6	dog.c	$NHDT-Date: 1502753406 2017/08/14 23:30:06 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.60 $ */
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. */

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

5. 
6. #include "hack.h"
7. 
8. STATIC_DCL int NDECL(pet_type);
9. 

newedog

10. void
11. newedog(mtmp)
12. struct monst *mtmp;
13. {
14.     if (!mtmp->mextra)
15.         mtmp->mextra = newmextra();
16.     if (!EDOG(mtmp)) {
17.         EDOG(mtmp) = (struct edog *) alloc(sizeof(struct edog));
18.         (void) memset((genericptr_t) EDOG(mtmp), 0, sizeof(struct edog));
19.     }
20. }
21. 

free_edog

22. void
23. free_edog(mtmp)
24. struct monst *mtmp;
25. {
26.     if (mtmp->mextra && EDOG(mtmp)) {
27.         free((genericptr_t) EDOG(mtmp));
28.         EDOG(mtmp) = (struct edog *) 0;
29.     }
30.     mtmp->mtame = 0;
31. }
32. 

initedog

33. void
34. initedog(mtmp)
35. register struct monst *mtmp;
36. {
37.     mtmp->mtame = is_domestic(mtmp->data) ? 10 : 5;
38.     mtmp->mpeaceful = 1;
39.     mtmp->mavenge = 0;
40.     set_malign(mtmp); /* recalc alignment now that it's tamed */
41.     mtmp->mleashed = 0;
42.     mtmp->meating = 0;
43.     EDOG(mtmp)->droptime = 0;
44.     EDOG(mtmp)->dropdist = 10000;
45.     EDOG(mtmp)->apport = ACURR(A_CHA);
46.     EDOG(mtmp)->whistletime = 0;
47.     EDOG(mtmp)->hungrytime = 1000 + monstermoves;
48.     EDOG(mtmp)->ogoal.x = -1; /* force error if used before set */
49.     EDOG(mtmp)->ogoal.y = -1;
50.     EDOG(mtmp)->abuse = 0;
51.     EDOG(mtmp)->revivals = 0;
52.     EDOG(mtmp)->mhpmax_penalty = 0;
53.     EDOG(mtmp)->killed_by_u = 0;
54. }
55. 

pet_type

56. STATIC_OVL int
57. pet_type()
58. {
59.     if (urole.petnum != NON_PM)
60.         return  urole.petnum;
61.     else if (preferred_pet == 'c')
62.         return  PM_KITTEN;
63.     else if (preferred_pet == 'd')
64.         return  PM_LITTLE_DOG;
65.     else
66.         return  rn2(2) ? PM_KITTEN : PM_LITTLE_DOG;
67. }
68. 

make_familiar

69. struct monst *
70. make_familiar(otmp, x, y, quietly)
71. register struct obj *otmp;
72. xchar x, y;
73. boolean quietly;
74. {
75.     struct permonst *pm;
76.     struct monst *mtmp = 0;
77.     int chance, trycnt = 100;
78. 
79.     do {
80.         if (otmp) { /* figurine; otherwise spell */
81.             int mndx = otmp->corpsenm;
82.             pm = &mons[mndx];
83.             /* activating a figurine provides one way to exceed the
84.                maximum number of the target critter created--unless
85.                it has a special limit (erinys, Nazgul) */
86.             if ((mvitals[mndx].mvflags & G_EXTINCT)
87.                 && mbirth_limit(mndx) != MAXMONNO) {
88.                 if (!quietly)
89.                     /* have just been given "You <do something with>
90.                        the figurine and it transforms." message */
91.                     pline("... into a pile of dust.");
92.                 break; /* mtmp is null */
93.             }
94.         } else if (!rn2(3)) {
95.             pm = &mons[pet_type()];
96.         } else {
97.             pm = rndmonst();
98.             if (!pm) {
99.                 if (!quietly)
100.                     There("seems to be nothing available for a familiar.");
101.                 break;
102.             }
103.         }
104. 
105.         mtmp = makemon(pm, x, y, MM_EDOG | MM_IGNOREWATER | NO_MINVENT);
106.         if (otmp && !mtmp) { /* monster was genocided or square occupied */
107.             if (!quietly)
108.                 pline_The("figurine writhes and then shatters into pieces!");
109.             break;
110.         }
111.     } while (!mtmp && --trycnt > 0);
112. 
113.     if (!mtmp)
114.         return (struct monst *) 0;
115. 
116.     if (is_pool(mtmp->mx, mtmp->my) && minliquid(mtmp))
117.         return (struct monst *) 0;
118. 
119.     initedog(mtmp);
120.     mtmp->msleeping = 0;
121.     if (otmp) { /* figurine; resulting monster might not become a pet */
122.         chance = rn2(10); /* 0==tame, 1==peaceful, 2==hostile */
123.         if (chance > 2)
124.             chance = otmp->blessed ? 0 : !otmp->cursed ? 1 : 2;
125.         /* 0,1,2:  b=80%,10,10; nc=10%,80,10; c=10%,10,80 */
126.         if (chance > 0) {
127.             mtmp->mtame = 0;   /* not tame after all */
128.             if (chance == 2) { /* hostile (cursed figurine) */
129.                 if (!quietly)
130.                     You("get a bad feeling about this.");
131.                 mtmp->mpeaceful = 0;
132.                 set_malign(mtmp);
133.             }
134.         }
135.         /* if figurine has been named, give same name to the monster */
136.         if (has_oname(otmp))
137.             mtmp = christen_monst(mtmp, ONAME(otmp));
138.     }
139.     set_malign(mtmp); /* more alignment changes */
140.     newsym(mtmp->mx, mtmp->my);
141. 
142.     /* must wield weapon immediately since pets will otherwise drop it */
143.     if (mtmp->mtame && attacktype(mtmp->data, AT_WEAP)) {
144.         mtmp->weapon_check = NEED_HTH_WEAPON;
145.         (void) mon_wield_item(mtmp);
146.     }
147.     return mtmp;
148. }
149. 

makedog

150. struct monst *
151. makedog()
152. {
153.     register struct monst *mtmp;
154.     register struct obj *otmp;
155.     const char *petname;
156.     int pettype;
157.     static int petname_used = 0;
158. 
159.     if (preferred_pet == 'n')
160.         return ((struct monst *) 0);
161. 
162.     pettype = pet_type();
163.     if (pettype == PM_LITTLE_DOG)
164.         petname = dogname;
165.     else if (pettype == PM_PONY)
166.         petname = horsename;
167.     else
168.         petname = catname;
169. 
170.     /* default pet names */
171.     if (!*petname && pettype == PM_LITTLE_DOG) {
172.         /* All of these names were for dogs. */
173.         if (Role_if(PM_CAVEMAN))
174.             petname = "Slasher"; /* The Warrior */
175.         if (Role_if(PM_SAMURAI))
176.             petname = "Hachi"; /* Shibuya Station */
177.         if (Role_if(PM_BARBARIAN))
178.             petname = "Idefix"; /* Obelix */
179.         if (Role_if(PM_RANGER))
180.             petname = "Sirius"; /* Orion's dog */
181.     }
182. 
183.     mtmp = makemon(&mons[pettype], u.ux, u.uy, MM_EDOG);
184. 
185.     if (!mtmp)
186.         return ((struct monst *) 0); /* pets were genocided */
187. 
188.     context.startingpet_mid = mtmp->m_id;
189.     /* Horses already wear a saddle */
190.     if (pettype == PM_PONY && !!(otmp = mksobj(SADDLE, TRUE, FALSE))) {
191.         otmp->dknown = otmp->bknown = otmp->rknown = 1;
192.         put_saddle_on_mon(otmp, mtmp);
193.     }
194. 
195.     if (!petname_used++ && *petname)
196.         mtmp = christen_monst(mtmp, petname);
197. 
198.     initedog(mtmp);
199.     return  mtmp;
200. }
201. 

update_mlstmv

202. /* record `last move time' for all monsters prior to level save so that
203.    mon_arrive() can catch up for lost time when they're restored later */
204. void
205. update_mlstmv()
206. {
207.     struct monst *mon;
208. 
209.     /* monst->mlstmv used to be updated every time `monst' actually moved,
210.        but that is no longer the case so we just do a blanket assignment */
211.     for (mon = fmon; mon; mon = mon->nmon) {
212.         if (DEADMONSTER(mon))
213.             continue;
214.         mon->mlstmv = monstermoves;
215.     }
216. }
217. 

losedogs

218. void
219. losedogs()
220. {
221.     register struct monst *mtmp, *mtmp0 = 0, *mtmp2;
222.     int dismissKops = 0;
223. 
224.     /*
225.      * First, scan migrating_mons for shopkeepers who want to dismiss Kops,
226.      * and scan mydogs for shopkeepers who want to retain kops.
227.      * Second, dismiss kops if warranted, making more room for arrival.
228.      * Third, place monsters accompanying the hero.
229.      * Last, place migrating monsters coming to this level.
230.      *
231.      * Hero might eventually be displaced (due to the third step, but
232.      * occurring later), which is the main reason to do the second step
233.      * sooner (in turn necessitating the first step, rather than combining
234.      * the list scans with monster placement).
235.      */
236. 
237.     /* check for returning shk(s) */
238.     for (mtmp = migrating_mons; mtmp; mtmp = mtmp->nmon) {
239.         if (mtmp->mux != u.uz.dnum || mtmp->muy != u.uz.dlevel)
240.             continue;
241.         if (mtmp->isshk) {
242.             if (ESHK(mtmp)->dismiss_kops) {
243.                 if (dismissKops == 0)
244.                     dismissKops = 1;
245.                 ESHK(mtmp)->dismiss_kops = FALSE; /* reset */
246.             } else if (!mtmp->mpeaceful) {
247.                 /* an unpacified shk is returning; don't dismiss kops
248.                    even if another pacified one is willing to do so */
249.                 dismissKops = -1;
250.                 /* [keep looping; later monsters might need ESHK reset] */
251.             }
252.         }
253.     }
254.     /* make the same check for mydogs */
255.     for (mtmp = mydogs; mtmp && dismissKops >= 0; mtmp = mtmp->nmon) {
256.         if (mtmp->isshk) {
257.             /* hostile shk might accompany hero [ESHK(mtmp)->dismiss_kops
258.                can't be set here; it's only used for migrating_mons] */
259.             if (!mtmp->mpeaceful)
260.                 dismissKops = -1;
261.         }
262.     }
263. 
264.     /* when a hostile shopkeeper chases hero to another level
265.        and then gets paid off there, get rid of summoned kops
266.        here now that he has returned to his shop level */
267.     if (dismissKops > 0)
268.         make_happy_shoppers(TRUE);
269. 
270.     /* place pets and/or any other monsters who accompany hero */
271.     while ((mtmp = mydogs) != 0) {
272.         mydogs = mtmp->nmon;
273.         mon_arrive(mtmp, TRUE);
274.     }
275. 
276.     /* time for migrating monsters to arrive */
277.     for (mtmp = migrating_mons; mtmp; mtmp = mtmp2) {
278.         mtmp2 = mtmp->nmon;
279.         if (mtmp->mux == u.uz.dnum && mtmp->muy == u.uz.dlevel) {
280.             if (mtmp == migrating_mons)
281.                 migrating_mons = mtmp->nmon;
282.             else
283.                 mtmp0->nmon = mtmp->nmon;
284.             mon_arrive(mtmp, FALSE);
285.         } else
286.             mtmp0 = mtmp;
287.     }
288. }
289. 

mon_arrive

290. /* called from resurrect() in addition to losedogs() */
291. void
292. mon_arrive(mtmp, with_you)
293. struct monst *mtmp;
294. boolean with_you;
295. {
296.     struct trap *t;
297.     xchar xlocale, ylocale, xyloc, xyflags, wander;
298.     int num_segs;
299. 
300.     mtmp->nmon = fmon;
301.     fmon = mtmp;
302.     if (mtmp->isshk)
303.         set_residency(mtmp, FALSE);
304. 
305.     num_segs = mtmp->wormno;
306.     /* baby long worms have no tail so don't use is_longworm() */
307.     if (mtmp->data == &mons[PM_LONG_WORM]) {
308.         mtmp->wormno = get_wormno();
309.         if (mtmp->wormno)
310.             initworm(mtmp, num_segs);
311.     } else
312.         mtmp->wormno = 0;
313. 
314.     /* some monsters might need to do something special upon arrival
315.        _after_ the current level has been fully set up; see dochug() */
316.     mtmp->mstrategy |= STRAT_ARRIVE;
317. 
318.     /* make sure mnexto(rloc_to(set_apparxy())) doesn't use stale data */
319.     mtmp->mux = u.ux, mtmp->muy = u.uy;
320.     xyloc = mtmp->mtrack[0].x;
321.     xyflags = mtmp->mtrack[0].y;
322.     xlocale = mtmp->mtrack[1].x;
323.     ylocale = mtmp->mtrack[1].y;
324.     memset(mtmp->mtrack, 0, sizeof(mtmp->mtrack));
325. 
326.     if (mtmp == u.usteed)
327.         return; /* don't place steed on the map */
328.     if (with_you) {
329.         /* When a monster accompanies you, sometimes it will arrive
330.            at your intended destination and you'll end up next to
331.            that spot.  This code doesn't control the final outcome;
332.            goto_level(do.c) decides who ends up at your target spot
333.            when there is a monster there too. */
334.         if (!MON_AT(u.ux, u.uy)
335.             && !rn2(mtmp->mtame ? 10 : mtmp->mpeaceful ? 5 : 2))
336.             rloc_to(mtmp, u.ux, u.uy);
337.         else
338.             mnexto(mtmp);
339.         return;
340.     }
341.     /*
342.      * The monster arrived on this level independently of the player.
343.      * Its coordinate fields were overloaded for use as flags that
344.      * specify its final destination.
345.      */
346. 
347.     if (mtmp->mlstmv < monstermoves - 1L) {
348.         /* heal monster for time spent in limbo */
349.         long nmv = monstermoves - 1L - mtmp->mlstmv;
350. 
351.         mon_catchup_elapsed_time(mtmp, nmv);
352.         mtmp->mlstmv = monstermoves - 1L;
353. 
354.         /* let monster move a bit on new level (see placement code below) */
355.         wander = (xchar) min(nmv, 8);
356.     } else
357.         wander = 0;
358. 
359.     switch (xyloc) {
360.     case MIGR_APPROX_XY: /* {x,y}locale set above */
361.         break;
362.     case MIGR_EXACT_XY:
363.         wander = 0;
364.         break;
365.     case MIGR_WITH_HERO:
366.         xlocale = u.ux, ylocale = u.uy;
367.         break;
368.     case MIGR_STAIRS_UP:
369.         xlocale = xupstair, ylocale = yupstair;
370.         break;
371.     case MIGR_STAIRS_DOWN:
372.         xlocale = xdnstair, ylocale = ydnstair;
373.         break;
374.     case MIGR_LADDER_UP:
375.         xlocale = xupladder, ylocale = yupladder;
376.         break;
377.     case MIGR_LADDER_DOWN:
378.         xlocale = xdnladder, ylocale = ydnladder;
379.         break;
380.     case MIGR_SSTAIRS:
381.         xlocale = sstairs.sx, ylocale = sstairs.sy;
382.         break;
383.     case MIGR_PORTAL:
384.         if (In_endgame(&u.uz)) {
385.             /* there is no arrival portal for endgame levels */
386.             /* BUG[?]: for simplicity, this code relies on the fact
387.                that we know that the current endgame levels always
388.                build upwards and never have any exclusion subregion
389.                inside their TELEPORT_REGION settings. */
390.             xlocale = rn1(updest.hx - updest.lx + 1, updest.lx);
391.             ylocale = rn1(updest.hy - updest.ly + 1, updest.ly);
392.             break;
393.         }
394.         /* find the arrival portal */
395.         for (t = ftrap; t; t = t->ntrap)
396.             if (t->ttyp == MAGIC_PORTAL)
397.                 break;
398.         if (t) {
399.             xlocale = t->tx, ylocale = t->ty;
400.             break;
401.         } else {
402.             impossible("mon_arrive: no corresponding portal?");
403.         } /*FALLTHRU*/
404.     default:
405.     case MIGR_RANDOM:
406.         xlocale = ylocale = 0;
407.         break;
408.     }
409. 
410.     if (xlocale && wander) {
411.         /* monster moved a bit; pick a nearby location */
412.         /* mnearto() deals w/stone, et al */
413.         char *r = in_rooms(xlocale, ylocale, 0);
414.         if (r && *r) {
415.             coord c;
416.             /* somexy() handles irregular rooms */
417.             if (somexy(&rooms[*r - ROOMOFFSET], &c))
418.                 xlocale = c.x, ylocale = c.y;
419.             else
420.                 xlocale = ylocale = 0;
421.         } else { /* not in a room */
422.             int i, j;
423.             i = max(1, xlocale - wander);
424.             j = min(COLNO - 1, xlocale + wander);
425.             xlocale = rn1(j - i, i);
426.             i = max(0, ylocale - wander);
427.             j = min(ROWNO - 1, ylocale + wander);
428.             ylocale = rn1(j - i, i);
429.         }
430.     } /* moved a bit */
431. 
432.     mtmp->mx = 0; /*(already is 0)*/
433.     mtmp->my = xyflags;
434.     if (xlocale) {
435.         if (!mnearto(mtmp, xlocale, ylocale, FALSE))
436.             goto fail_mon_placement;
437.     } else {
438.         if (!rloc(mtmp, TRUE)) {
439.             /*
440.              * Failed to place migrating monster,
441.              * probably because the level is full.
442.              * Dump the monster's cargo and leave the monster dead.
443.              */
444.             struct obj *obj;
445. fail_mon_placement:
446.             while ((obj = mtmp->minvent) != 0) {
447.                 obj_extract_self(obj);
448.                 obj_no_longer_held(obj);
449.                 if (obj->owornmask & W_WEP)
450.                     setmnotwielded(mtmp, obj);
451.                 obj->owornmask = 0L;
452.                 if (xlocale && ylocale)
453.                     place_object(obj, xlocale, ylocale);
454.                 else if (rloco(obj)) {
455.                     if (!get_obj_location(obj, &xlocale, &ylocale, 0))
456.                         impossible("Can't find relocated object.");
457.                 }
458.             }
459.             (void) mkcorpstat(CORPSE, (struct monst *) 0, mtmp->data, xlocale,
460.                               ylocale, CORPSTAT_NONE);
461.             mongone(mtmp);
462.         }
463.     }
464. }
465. 

mon_catchup_elapsed_time

466. /* heal monster for time spent elsewhere */
467. void
468. mon_catchup_elapsed_time(mtmp, nmv)
469. struct monst *mtmp;
470. long nmv; /* number of moves */
471. {
472.     int imv = 0; /* avoid zillions of casts and lint warnings */
473. 
474. #if defined(DEBUG) || defined(BETA)
475.     if (nmv < 0L) { /* crash likely... */
476.         panic("catchup from future time?");
477.         /*NOTREACHED*/
478.         return;
479.     } else if (nmv == 0L) { /* safe, but should'nt happen */
480.         impossible("catchup from now?");
481.     } else
482. #endif
483.         if (nmv >= LARGEST_INT) /* paranoia */
484.         imv = LARGEST_INT - 1;
485.     else
486.         imv = (int) nmv;
487. 
488.     /* might stop being afraid, blind or frozen */
489.     /* set to 1 and allow final decrement in movemon() */
490.     if (mtmp->mblinded) {
491.         if (imv >= (int) mtmp->mblinded)
492.             mtmp->mblinded = 1;
493.         else
494.             mtmp->mblinded -= imv;
495.     }
496.     if (mtmp->mfrozen) {
497.         if (imv >= (int) mtmp->mfrozen)
498.             mtmp->mfrozen = 1;
499.         else
500.             mtmp->mfrozen -= imv;
501.     }
502.     if (mtmp->mfleetim) {
503.         if (imv >= (int) mtmp->mfleetim)
504.             mtmp->mfleetim = 1;
505.         else
506.             mtmp->mfleetim -= imv;
507.     }
508. 
509.     /* might recover from temporary trouble */
510.     if (mtmp->mtrapped && rn2(imv + 1) > 40 / 2)
511.         mtmp->mtrapped = 0;
512.     if (mtmp->mconf && rn2(imv + 1) > 50 / 2)
513.         mtmp->mconf = 0;
514.     if (mtmp->mstun && rn2(imv + 1) > 10 / 2)
515.         mtmp->mstun = 0;
516. 
517.     /* might finish eating or be able to use special ability again */
518.     if (imv > mtmp->meating)
519.         finish_meating(mtmp);
520.     else
521.         mtmp->meating -= imv;
522.     if (imv > mtmp->mspec_used)
523.         mtmp->mspec_used = 0;
524.     else
525.         mtmp->mspec_used -= imv;
526. 
527.     /* reduce tameness for every 150 moves you are separated */
528.     if (mtmp->mtame) {
529.         int wilder = (imv + 75) / 150;
530.         if (mtmp->mtame > wilder)
531.             mtmp->mtame -= wilder; /* less tame */
532.         else if (mtmp->mtame > rn2(wilder))
533.             mtmp->mtame = 0; /* untame */
534.         else
535.             mtmp->mtame = mtmp->mpeaceful = 0; /* hostile! */
536.     }
537.     /* check to see if it would have died as a pet; if so, go wild instead
538.      * of dying the next time we call dog_move()
539.      */
540.     if (mtmp->mtame && !mtmp->isminion
541.         && (carnivorous(mtmp->data) || herbivorous(mtmp->data))) {
542.         struct edog *edog = EDOG(mtmp);
543. 
544.         if ((monstermoves > edog->hungrytime + 500 && mtmp->mhp < 3)
545.             || (monstermoves > edog->hungrytime + 750))
546.             mtmp->mtame = mtmp->mpeaceful = 0;
547.     }
548. 
549.     if (!mtmp->mtame && mtmp->mleashed) {
550.         /* leashed monsters should always be with hero, consequently
551.            never losing any time to be accounted for later */
552.         impossible("catching up for leashed monster?");
553.         m_unleash(mtmp, FALSE);
554.     }
555. 
556.     /* recover lost hit points */
557.     if (!regenerates(mtmp->data))
558.         imv /= 20;
559.     if (mtmp->mhp + imv >= mtmp->mhpmax)
560.         mtmp->mhp = mtmp->mhpmax;
561.     else
562.         mtmp->mhp += imv;
563. }
564. 

keepdogs

565. /* called when you move to another level */
566. void
567. keepdogs(pets_only)
568. boolean pets_only; /* true for ascension or final escape */
569. {
570.     register struct monst *mtmp, *mtmp2;
571.     register struct obj *obj;
572.     int num_segs;
573.     boolean stay_behind;
574. 
575.     for (mtmp = fmon; mtmp; mtmp = mtmp2) {
576.         mtmp2 = mtmp->nmon;
577.         if (DEADMONSTER(mtmp))
578.             continue;
579.         if (pets_only) {
580.             if (!mtmp->mtame)
581.                 continue; /* reject non-pets */
582.             /* don't block pets from accompanying hero's dungeon
583.                escape or ascension simply due to mundane trifles;
584.                unlike level change for steed, don't bother trying
585.                to achieve a normal trap escape first */
586.             mtmp->mtrapped = 0;
587.             mtmp->meating = 0;
588.             mtmp->msleeping = 0;
589.             mtmp->mfrozen = 0;
590.             mtmp->mcanmove = 1;
591.         }
592.         if (((monnear(mtmp, u.ux, u.uy) && levl_follower(mtmp))
593.              /* the wiz will level t-port from anywhere to chase
594.                 the amulet; if you don't have it, will chase you
595.                 only if in range. -3. */
596.              || (u.uhave.amulet && mtmp->iswiz))
597.             && ((!mtmp->msleeping && mtmp->mcanmove)
598.                 /* eg if level teleport or new trap, steed has no control
599.                    to avoid following */
600.                 || (mtmp == u.usteed))
601.             /* monster won't follow if it hasn't noticed you yet */
602.             && !(mtmp->mstrategy & STRAT_WAITFORU)) {
603.             stay_behind = FALSE;
604.             if (mtmp->mtrapped)
605.                 (void) mintrap(mtmp); /* try to escape */
606.             if (mtmp == u.usteed) {
607.                 /* make sure steed is eligible to accompany hero */
608.                 mtmp->mtrapped = 0;       /* escape trap */
609.                 mtmp->meating = 0;        /* terminate eating */
610.                 mdrop_special_objs(mtmp); /* drop Amulet */
611.             } else if (mtmp->meating || mtmp->mtrapped) {
612.                 if (canseemon(mtmp))
613.                     pline("%s is still %s.", Monnam(mtmp),
614.                           mtmp->meating ? "eating" : "trapped");
615.                 stay_behind = TRUE;
616.             } else if (mon_has_amulet(mtmp)) {
617.                 if (canseemon(mtmp))
618.                     pline("%s seems very disoriented for a moment.",
619.                           Monnam(mtmp));
620.                 stay_behind = TRUE;
621.             }
622.             if (stay_behind) {
623.                 if (mtmp->mleashed) {
624.                     pline("%s leash suddenly comes loose.",
625.                           humanoid(mtmp->data)
626.                               ? (mtmp->female ? "Her" : "His")
627.                               : "Its");
628.                     m_unleash(mtmp, FALSE);
629.                 }
630.                 if (mtmp == u.usteed) {
631.                     /* can't happen unless someone makes a change
632.                        which scrambles the stay_behind logic above */
633.                     impossible("steed left behind?");
634.                     dismount_steed(DISMOUNT_GENERIC);
635.                 }
636.                 continue;
637.             }
638.             if (mtmp->isshk)
639.                 set_residency(mtmp, TRUE);
640. 
641.             if (mtmp->wormno) {
642.                 register int cnt;
643.                 /* NOTE: worm is truncated to # segs = max wormno size */
644.                 cnt = count_wsegs(mtmp);
645.                 num_segs = min(cnt, MAX_NUM_WORMS - 1);
646.                 wormgone(mtmp);
647.             } else
648.                 num_segs = 0;
649. 
650.             /* set minvent's obj->no_charge to 0 */
651.             for (obj = mtmp->minvent; obj; obj = obj->nobj) {
652.                 if (Has_contents(obj))
653.                     picked_container(obj); /* does the right thing */
654.                 obj->no_charge = 0;
655.             }
656. 
657.             relmon(mtmp, &mydogs);   /* move it from map to mydogs */
658.             mtmp->mx = mtmp->my = 0; /* avoid mnexto()/MON_AT() problem */
659.             mtmp->wormno = num_segs;
660.             mtmp->mlstmv = monstermoves;
661.         } else if (mtmp->iswiz) {
662.             /* we want to be able to find him when his next resurrection
663.                chance comes up, but have him resume his present location
664.                if player returns to this level before that time */
665.             migrate_to_level(mtmp, ledger_no(&u.uz), MIGR_EXACT_XY,
666.                              (coord *) 0);
667.         } else if (mtmp->mleashed) {
668.             /* this can happen if your quest leader ejects you from the
669.                "home" level while a leashed pet isn't next to you */
670.             pline("%s leash goes slack.", s_suffix(Monnam(mtmp)));
671.             m_unleash(mtmp, FALSE);
672.         }
673.     }
674. }
675. 

migrate_to_level

676. void
677. migrate_to_level(mtmp, tolev, xyloc, cc)
678. register struct monst *mtmp;
679. xchar tolev; /* destination level */
680. xchar xyloc; /* MIGR_xxx destination xy location: */
681. coord *cc;   /* optional destination coordinates */
682. {
683.     register struct obj *obj;
684.     d_level new_lev;
685.     xchar xyflags;
686.     int num_segs = 0; /* count of worm segments */
687. 
688.     if (mtmp->isshk)
689.         set_residency(mtmp, TRUE);
690. 
691.     if (mtmp->wormno) {
692.         register int cnt;
693.         /* **** NOTE: worm is truncated to # segs = max wormno size **** */
694.         cnt = count_wsegs(mtmp);
695.         num_segs = min(cnt, MAX_NUM_WORMS - 1);
696.         wormgone(mtmp);
697.     }
698. 
699.     /* set minvent's obj->no_charge to 0 */
700.     for (obj = mtmp->minvent; obj; obj = obj->nobj) {
701.         if (Has_contents(obj))
702.             picked_container(obj); /* does the right thing */
703.         obj->no_charge = 0;
704.     }
705. 
706.     if (mtmp->mleashed) {
707.         mtmp->mtame--;
708.         m_unleash(mtmp, TRUE);
709.     }
710.     relmon(mtmp, &migrating_mons); /* move it from map to migrating_mons */
711. 
712.     new_lev.dnum = ledger_to_dnum((xchar) tolev);
713.     new_lev.dlevel = ledger_to_dlev((xchar) tolev);
714.     /* overload mtmp->[mx,my], mtmp->[mux,muy], and mtmp->mtrack[] as */
715.     /* destination codes (setup flag bits before altering mx or my) */
716.     xyflags = (depth(&new_lev) < depth(&u.uz)); /* 1 => up */
717.     if (In_W_tower(mtmp->mx, mtmp->my, &u.uz))
718.         xyflags |= 2;
719.     mtmp->wormno = num_segs;
720.     mtmp->mlstmv = monstermoves;
721.     mtmp->mtrack[1].x = cc ? cc->x : mtmp->mx;
722.     mtmp->mtrack[1].y = cc ? cc->y : mtmp->my;
723.     mtmp->mtrack[0].x = xyloc;
724.     mtmp->mtrack[0].y = xyflags;
725.     mtmp->mux = new_lev.dnum;
726.     mtmp->muy = new_lev.dlevel;
727.     mtmp->mx = mtmp->my = 0; /* this implies migration */
728.     if (mtmp == context.polearm.hitmon)
729.         context.polearm.hitmon = NULL;
730. }
731. 

dogfood

732. /* return quality of food; the lower the better */
733. /* fungi will eat even tainted food */
734. int
735. dogfood(mon, obj)
736. struct monst *mon;
737. register struct obj *obj;
738. {
739.     struct permonst *mptr = mon->data, *fptr = 0;
740.     boolean carni = carnivorous(mptr), herbi = herbivorous(mptr),
741.             starving, mblind;
742. 
743.     if (is_quest_artifact(obj) || obj_resists(obj, 0, 95))
744.         return obj->cursed ? TABU : APPORT;
745. 
746.     switch (obj->oclass) {
747.     case FOOD_CLASS:
748.         if (obj->otyp == CORPSE || obj->otyp == TIN || obj->otyp == EGG)
749.             fptr = &mons[obj->corpsenm];
750. 
751.         if (obj->otyp == CORPSE && is_rider(fptr))
752.             return TABU;
753.         if ((obj->otyp == CORPSE || obj->otyp == EGG) && touch_petrifies(fptr)
754.             && !resists_ston(mon))
755.             return POISON;
756.         if (!carni && !herbi)
757.             return obj->cursed ? UNDEF : APPORT;
758. 
759.         /* a starving pet will eat almost anything */
760.         starving = (mon->mtame && !mon->isminion
761.                     && EDOG(mon)->mhpmax_penalty);
762.         /* even carnivores will eat carrots if they're temporarily blind */
763.         mblind = (!mon->mcansee && haseyes(mon->data));
764. 
765.         /* ghouls prefer old corpses and unhatchable eggs, yum!
766.            they'll eat fresh non-veggy corpses and hatchable eggs
767.            when starving; they never eat stone-to-flesh'd meat */
768.         if (mptr == &mons[PM_GHOUL]) {
769.             if (obj->otyp == CORPSE)
770.                 return (peek_at_iced_corpse_age(obj) + 50L <= monstermoves
771.                         && fptr != &mons[PM_LIZARD]
772.                         && fptr != &mons[PM_LICHEN])
773.                            ? DOGFOOD
774.                            : (starving && !vegan(fptr))
775.                               ? ACCFOOD
776.                               : POISON;
777.             if (obj->otyp == EGG)
778.                 return stale_egg(obj) ? CADAVER : starving ? ACCFOOD : POISON;
779.             return TABU;
780.         }
781. 
782.         switch (obj->otyp) {
783.         case TRIPE_RATION:
784.         case MEATBALL:
785.         case MEAT_RING:
786.         case MEAT_STICK:
787.         case HUGE_CHUNK_OF_MEAT:
788.             return carni ? DOGFOOD : MANFOOD;
789.         case EGG:
790.             return carni ? CADAVER : MANFOOD;
791.         case CORPSE:
792.             if ((peek_at_iced_corpse_age(obj) + 50L <= monstermoves
793.                  && obj->corpsenm != PM_LIZARD && obj->corpsenm != PM_LICHEN
794.                  && mptr->mlet != S_FUNGUS)
795.                 || (acidic(fptr) && !resists_acid(mon))
796.                 || (poisonous(fptr) && !resists_poison(mon)))
797.                 return POISON;
798.             /* turning into slime is preferable to starvation */
799.             else if (fptr == &mons[PM_GREEN_SLIME] && !slimeproof(mon->data))
800.                 return starving ? ACCFOOD : POISON;
801.             else if (vegan(fptr))
802.                 return herbi ? CADAVER : MANFOOD;
803.             /* most humanoids will avoid cannibalism unless starving;
804.                arbitrary: elves won't eat other elves even then */
805.             else if (humanoid(mptr) && same_race(mptr, fptr)
806.                      && (!is_undead(mptr) && fptr->mlet != S_KOBOLD
807.                          && fptr->mlet != S_ORC && fptr->mlet != S_OGRE))
808.                 return (starving && carni && !is_elf(mptr)) ? ACCFOOD : TABU;
809.             else
810.                 return carni ? CADAVER : MANFOOD;
811.         case CLOVE_OF_GARLIC:
812.             return (is_undead(mptr) || is_vampshifter(mon))
813.                       ? TABU
814.                       : (herbi || starving)
815.                          ? ACCFOOD
816.                          : MANFOOD;
817.         case TIN:
818.             return metallivorous(mptr) ? ACCFOOD : MANFOOD;
819.         case APPLE:
820.             return herbi ? DOGFOOD : starving ? ACCFOOD : MANFOOD;
821.         case CARROT:
822.             return (herbi || mblind) ? DOGFOOD : starving ? ACCFOOD : MANFOOD;
823.         case BANANA:
824.             return (mptr->mlet == S_YETI && herbi)
825.                       ? DOGFOOD /* for monkey and ape (tameable), sasquatch */
826.                       : (herbi || starving)
827.                          ? ACCFOOD
828.                          : MANFOOD;
829.         default:
830.             if (starving)
831.                 return ACCFOOD;
832.             return (obj->otyp > SLIME_MOLD) ? (carni ? ACCFOOD : MANFOOD)
833.                                             : (herbi ? ACCFOOD : MANFOOD);
834.         }
835.     default:
836.         if (obj->otyp == AMULET_OF_STRANGULATION
837.             || obj->otyp == RIN_SLOW_DIGESTION)
838.             return TABU;
839.         if (mon_hates_silver(mon) && objects[obj->otyp].oc_material == SILVER)
840.             return TABU;
841.         if (mptr == &mons[PM_GELATINOUS_CUBE] && is_organic(obj))
842.             return ACCFOOD;
843.         if (metallivorous(mptr) && is_metallic(obj)
844.             && (is_rustprone(obj) || mptr != &mons[PM_RUST_MONSTER])) {
845.             /* Non-rustproofed ferrous based metals are preferred. */
846.             return (is_rustprone(obj) && !obj->oerodeproof) ? DOGFOOD
847.                                                             : ACCFOOD;
848.         }
849.         if (!obj->cursed
850.             && obj->oclass != BALL_CLASS
851.             && obj->oclass != CHAIN_CLASS)
852.             return APPORT;
853.         /*FALLTHRU*/
854.     case ROCK_CLASS:
855.         return UNDEF;
856.     }
857. }
858. 

tamedog

859. /*
860.  * With the separate mextra structure added in 3.6.x this always
861.  * operates on the original mtmp. It now returns TRUE if the taming
862.  * succeeded.
863.  */
864. boolean
865. tamedog(mtmp, obj)
866. register struct monst *mtmp;
867. register struct obj *obj;
868. {
869.     /* The Wiz, Medusa and the quest nemeses aren't even made peaceful. */
870.     if (mtmp->iswiz || mtmp->data == &mons[PM_MEDUSA]
871.         || (mtmp->data->mflags3 & M3_WANTSARTI))
872.         return FALSE;
873. 
874.     /* worst case, at least it'll be peaceful. */
875.     mtmp->mpeaceful = 1;
876.     set_malign(mtmp);
877.     if (flags.moonphase == FULL_MOON && night() && rn2(6) && obj
878.         && mtmp->data->mlet == S_DOG)
879.         return FALSE;
880. 
881.     /* If we cannot tame it, at least it's no longer afraid. */
882.     mtmp->mflee = 0;
883.     mtmp->mfleetim = 0;
884. 
885.     /* make grabber let go now, whether it becomes tame or not */
886.     if (mtmp == u.ustuck) {
887.         if (u.uswallow)
888.             expels(mtmp, mtmp->data, TRUE);
889.         else if (!(Upolyd && sticks(youmonst.data)))
890.             unstuck(mtmp);
891.     }
892. 
893.     /* feeding it treats makes it tamer */
894.     if (mtmp->mtame && obj) {
895.         int tasty;
896. 
897.         if (mtmp->mcanmove && !mtmp->mconf && !mtmp->meating
898.             && ((tasty = dogfood(mtmp, obj)) == DOGFOOD
899.                 || (tasty <= ACCFOOD
900.                     && EDOG(mtmp)->hungrytime <= monstermoves))) {
901.             /* pet will "catch" and eat this thrown food */
902.             if (canseemon(mtmp)) {
903.                 boolean big_corpse =
904.                     (obj->otyp == CORPSE && obj->corpsenm >= LOW_PM
905.                      && mons[obj->corpsenm].msize > mtmp->data->msize);
906.                 pline("%s catches %s%s", Monnam(mtmp), the(xname(obj)),
907.                       !big_corpse ? "." : ", or vice versa!");
908.             } else if (cansee(mtmp->mx, mtmp->my))
909.                 pline("%s.", Tobjnam(obj, "stop"));
910.             /* dog_eat expects a floor object */
911.             place_object(obj, mtmp->mx, mtmp->my);
912.             (void) dog_eat(mtmp, obj, mtmp->mx, mtmp->my, FALSE);
913.             /* eating might have killed it, but that doesn't matter here;
914.                a non-null result suppresses "miss" message for thrown
915.                food and also implies that the object has been deleted */
916.             return TRUE;
917.         } else
918.             return FALSE;
919.     }
920. 
921.     if (mtmp->mtame || !mtmp->mcanmove
922.         /* monsters with conflicting structures cannot be tamed */
923.         || mtmp->isshk || mtmp->isgd || mtmp->ispriest || mtmp->isminion
924.         || is_covetous(mtmp->data) || is_human(mtmp->data)
925.         || (is_demon(mtmp->data) && !is_demon(youmonst.data))
926.         || (obj && dogfood(mtmp, obj) >= MANFOOD))
927.         return FALSE;
928. 
929.     if (mtmp->m_id == quest_status.leader_m_id)
930.         return FALSE;
931. 
932.     /* add the pet extension */
933.     newedog(mtmp);
934.     initedog(mtmp);
935. 
936.     if (obj) { /* thrown food */
937.         /* defer eating until the edog extension has been set up */
938.         place_object(obj, mtmp->mx, mtmp->my); /* put on floor */
939.         /* devour the food (might grow into larger, genocided monster) */
940.         if (dog_eat(mtmp, obj, mtmp->mx, mtmp->my, TRUE) == 2)
941.             return TRUE; /* oops, it died... */
942.         /* `obj' is now obsolete */
943.     }
944. 
945.     newsym(mtmp->mx, mtmp->my);
946.     if (attacktype(mtmp->data, AT_WEAP)) {
947.         mtmp->weapon_check = NEED_HTH_WEAPON;
948.         (void) mon_wield_item(mtmp);
949.     }
950.     return TRUE;
951. }
952. 

wary_dog

953. /*
954.  * Called during pet revival or pet life-saving.
955.  * If you killed the pet, it revives wild.
956.  * If you abused the pet a lot while alive, it revives wild.
957.  * If you abused the pet at all while alive, it revives untame.
958.  * If the pet wasn't abused and was very tame, it might revive tame.
959.  */
960. void
961. wary_dog(mtmp, was_dead)
962. struct monst *mtmp;
963. boolean was_dead;
964. {
965.     struct edog *edog;
966.     boolean quietly = was_dead;
967. 
968.     finish_meating(mtmp);
969. 
970.     if (!mtmp->mtame)
971.         return;
972.     edog = !mtmp->isminion ? EDOG(mtmp) : 0;
973. 
974.     /* if monster was starving when it died, undo that now */
975.     if (edog && edog->mhpmax_penalty) {
976.         mtmp->mhpmax += edog->mhpmax_penalty;
977.         mtmp->mhp += edog->mhpmax_penalty; /* heal it */
978.         edog->mhpmax_penalty = 0;
979.     }
980. 
981.     if (edog && (edog->killed_by_u == 1 || edog->abuse > 2)) {
982.         mtmp->mpeaceful = mtmp->mtame = 0;
983.         if (edog->abuse >= 0 && edog->abuse < 10)
984.             if (!rn2(edog->abuse + 1))
985.                 mtmp->mpeaceful = 1;
986.         if (!quietly && cansee(mtmp->mx, mtmp->my)) {
987.             if (haseyes(youmonst.data)) {
988.                 if (haseyes(mtmp->data))
989.                     pline("%s %s to look you in the %s.", Monnam(mtmp),
990.                           mtmp->mpeaceful ? "seems unable" : "refuses",
991.                           body_part(EYE));
992.                 else
993.                     pline("%s avoids your gaze.", Monnam(mtmp));
994.             }
995.         }
996.     } else {
997.         /* chance it goes wild anyway - Pet Sematary */
998.         mtmp->mtame = rn2(mtmp->mtame + 1);
999.         if (!mtmp->mtame)
1000.             mtmp->mpeaceful = rn2(2);
1001.     }
1002. 
1003.     if (!mtmp->mtame) {
1004.         if (!quietly && canspotmon(mtmp))
1005.             pline("%s %s.", Monnam(mtmp),
1006.                   mtmp->mpeaceful ? "is no longer tame" : "has become feral");
1007.         newsym(mtmp->mx, mtmp->my);
1008.         /* a life-saved monster might be leashed;
1009.            don't leave it that way if it's no longer tame */
1010.         if (mtmp->mleashed)
1011.             m_unleash(mtmp, TRUE);
1012.         if (mtmp == u.usteed)
1013.             dismount_steed(DISMOUNT_THROWN);
1014.     } else if (edog) {
1015.         /* it's still a pet; start a clean pet-slate now */
1016.         edog->revivals++;
1017.         edog->killed_by_u = 0;
1018.         edog->abuse = 0;
1019.         edog->ogoal.x = edog->ogoal.y = -1;
1020.         if (was_dead || edog->hungrytime < monstermoves + 500L)
1021.             edog->hungrytime = monstermoves + 500L;
1022.         if (was_dead) {
1023.             edog->droptime = 0L;
1024.             edog->dropdist = 10000;
1025.             edog->whistletime = 0L;
1026.             edog->apport = 5;
1027.         } /* else lifesaved, so retain current values */
1028.     }
1029. }
1030. 

abuse_dog

1031. void
1032. abuse_dog(mtmp)
1033. struct monst *mtmp;
1034. {
1035.     if (!mtmp->mtame)
1036.         return;
1037. 
1038.     if (Aggravate_monster || Conflict)
1039.         mtmp->mtame /= 2;
1040.     else
1041.         mtmp->mtame--;
1042. 
1043.     if (mtmp->mtame && !mtmp->isminion)
1044.         EDOG(mtmp)->abuse++;
1045. 
1046.     if (!mtmp->mtame && mtmp->mleashed)
1047.         m_unleash(mtmp, TRUE);
1048. 
1049.     /* don't make a sound if pet is in the middle of leaving the level */
1050.     /* newsym isn't necessary in this case either */
1051.     if (mtmp->mx != 0) {
1052.         if (mtmp->mtame && rn2(mtmp->mtame))
1053.             yelp(mtmp);
1054.         else
1055.             growl(mtmp); /* give them a moment's worry */
1056. 
1057.         if (!mtmp->mtame)
1058.             newsym(mtmp->mx, mtmp->my);
1059.     }
1060. }
1061. 
1062. /*dog.c*/ is called. In order to catch and eat the food, the pet must be able to move, must not be confused or eating, and the food must be a treat (acceptable or better if the pet is hungry). If this is not the case, the food will miss the pet and fall to the floor. (If it is a suitable corpse, the pet should end up eating it on its next turn anyway.) Caught food is eaten with dog_eat, which is the same function used by pets eating from the ground.