1 /* NetHack 3.7	dog.c	$NHDT-Date: 1599330917 2020/09/05 18:35:17 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.104 $ */
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. */
5 
6 #include "hack.h"
7 
8 static int pet_type(void);
9 
10 void
newedog(struct monst * mtmp)11 newedog(struct monst *mtmp)
12 {
13     if (!mtmp->mextra)
14         mtmp->mextra = newmextra();
15     if (!EDOG(mtmp)) {
16         EDOG(mtmp) = (struct edog *) alloc(sizeof(struct edog));
17         (void) memset((genericptr_t) EDOG(mtmp), 0, sizeof(struct edog));
18     }
19 }
20 
21 void
free_edog(struct monst * mtmp)22 free_edog(struct monst *mtmp)
23 {
24     if (mtmp->mextra && EDOG(mtmp)) {
25         free((genericptr_t) EDOG(mtmp));
26         EDOG(mtmp) = (struct edog *) 0;
27     }
28     mtmp->mtame = 0;
29 }
30 
31 void
initedog(struct monst * mtmp)32 initedog(struct monst *mtmp)
33 {
34     mtmp->mtame = is_domestic(mtmp->data) ? 10 : 5;
35     mtmp->mpeaceful = 1;
36     mtmp->mavenge = 0;
37     set_malign(mtmp); /* recalc alignment now that it's tamed */
38     mtmp->mleashed = 0;
39     mtmp->meating = 0;
40     EDOG(mtmp)->droptime = 0;
41     EDOG(mtmp)->dropdist = 10000;
42     EDOG(mtmp)->apport = ACURR(A_CHA);
43     EDOG(mtmp)->whistletime = 0;
44     EDOG(mtmp)->hungrytime = 1000 + g.monstermoves;
45     EDOG(mtmp)->ogoal.x = -1; /* force error if used before set */
46     EDOG(mtmp)->ogoal.y = -1;
47     EDOG(mtmp)->abuse = 0;
48     EDOG(mtmp)->revivals = 0;
49     EDOG(mtmp)->mhpmax_penalty = 0;
50     EDOG(mtmp)->killed_by_u = 0;
51 }
52 
53 static int
pet_type(void)54 pet_type(void)
55 {
56     if (g.urole.petnum != NON_PM)
57         return  g.urole.petnum;
58     else if (g.preferred_pet == 'c')
59         return  PM_KITTEN;
60     else if (g.preferred_pet == 'd')
61         return  PM_LITTLE_DOG;
62     else
63         return  rn2(2) ? PM_KITTEN : PM_LITTLE_DOG;
64 }
65 
66 struct monst *
make_familiar(struct obj * otmp,xchar x,xchar y,boolean quietly)67 make_familiar(struct obj *otmp, xchar x, xchar y, boolean quietly)
68 {
69     struct permonst *pm;
70     struct monst *mtmp = 0;
71     int chance, trycnt = 100;
72 
73     do {
74         if (otmp) { /* figurine; otherwise spell */
75             int mndx = otmp->corpsenm;
76 
77             pm = &mons[mndx];
78             /* activating a figurine provides one way to exceed the
79                maximum number of the target critter created--unless
80                it has a special limit (erinys, Nazgul) */
81             if ((g.mvitals[mndx].mvflags & G_EXTINCT)
82                 && mbirth_limit(mndx) != MAXMONNO) {
83                 if (!quietly)
84                     /* have just been given "You <do something with>
85                        the figurine and it transforms." message */
86                     pline("... into a pile of dust.");
87                 break; /* mtmp is null */
88             }
89         } else if (!rn2(3)) {
90             pm = &mons[pet_type()];
91         } else {
92             pm = rndmonst();
93             if (!pm) {
94                 if (!quietly)
95                     There("seems to be nothing available for a familiar.");
96                 break;
97             }
98         }
99 
100         mtmp = makemon(pm, x, y, MM_EDOG | MM_IGNOREWATER | NO_MINVENT);
101         if (otmp && !mtmp) { /* monster was genocided or square occupied */
102             if (!quietly)
103                 pline_The("figurine writhes and then shatters into pieces!");
104             break;
105         }
106     } while (!mtmp && --trycnt > 0);
107 
108     if (!mtmp)
109         return (struct monst *) 0;
110 
111     if (is_pool(mtmp->mx, mtmp->my) && minliquid(mtmp))
112         return (struct monst *) 0;
113 
114     initedog(mtmp);
115     u.uconduct.pets++;
116     mtmp->msleeping = 0;
117     if (otmp) { /* figurine; resulting monster might not become a pet */
118         chance = rn2(10); /* 0==tame, 1==peaceful, 2==hostile */
119         if (chance > 2)
120             chance = otmp->blessed ? 0 : !otmp->cursed ? 1 : 2;
121         /* 0,1,2:  b=80%,10,10; nc=10%,80,10; c=10%,10,80 */
122         if (chance > 0) {
123             mtmp->mtame = 0;   /* not tame after all */
124             u.uconduct.pets--; /* doesn't count as creating a pet */
125             if (chance == 2) { /* hostile (cursed figurine) */
126                 if (!quietly)
127                     You("get a bad feeling about this.");
128                 mtmp->mpeaceful = 0;
129                 set_malign(mtmp);
130             }
131         }
132         /* if figurine has been named, give same name to the monster */
133         if (has_oname(otmp))
134             mtmp = christen_monst(mtmp, ONAME(otmp));
135     }
136     set_malign(mtmp); /* more alignment changes */
137     newsym(mtmp->mx, mtmp->my);
138 
139     /* must wield weapon immediately since pets will otherwise drop it */
140     if (mtmp->mtame && attacktype(mtmp->data, AT_WEAP)) {
141         mtmp->weapon_check = NEED_HTH_WEAPON;
142         (void) mon_wield_item(mtmp);
143     }
144     return mtmp;
145 }
146 
147 struct monst *
makedog(void)148 makedog(void)
149 {
150     register struct monst *mtmp;
151     register struct obj *otmp;
152     const char *petname;
153     int pettype;
154 
155     if (g.preferred_pet == 'n')
156         return ((struct monst *) 0);
157 
158     u.uconduct.pets++;
159 
160     pettype = pet_type();
161     if (pettype == PM_LITTLE_DOG)
162         petname = g.dogname;
163     else if (pettype == PM_PONY)
164         petname = g.horsename;
165     else
166         petname = g.catname;
167 
168     /* default pet names */
169     if (!*petname && pettype == PM_LITTLE_DOG) {
170         /* All of these names were for dogs. */
171         if (Role_if(PM_CAVE_DWELLER))
172             petname = "Slasher"; /* The Warrior */
173         if (Role_if(PM_SAMURAI))
174             petname = "Hachi"; /* Shibuya Station */
175         if (Role_if(PM_BARBARIAN))
176             petname = "Idefix"; /* Obelix */
177         if (Role_if(PM_RANGER))
178             petname = "Sirius"; /* Orion's dog */
179     }
180 
181     mtmp = makemon(&mons[pettype], u.ux, u.uy, MM_EDOG);
182 
183     if (!mtmp)
184         return ((struct monst *) 0); /* pets were genocided */
185 
186     g.context.startingpet_mid = mtmp->m_id;
187     /* Horses already wear a saddle */
188     if (pettype == PM_PONY && !!(otmp = mksobj(SADDLE, TRUE, FALSE))) {
189         otmp->dknown = otmp->bknown = otmp->rknown = 1;
190         put_saddle_on_mon(otmp, mtmp);
191     }
192 
193     if (!g.petname_used++ && *petname)
194         mtmp = christen_monst(mtmp, petname);
195 
196     initedog(mtmp);
197     return  mtmp;
198 }
199 
200 /* record `last move time' for all monsters prior to level save so that
201    mon_arrive() can catch up for lost time when they're restored later */
202 void
update_mlstmv(void)203 update_mlstmv(void)
204 {
205     struct monst *mon;
206 
207     /* monst->mlstmv used to be updated every time `monst' actually moved,
208        but that is no longer the case so we just do a blanket assignment */
209     for (mon = fmon; mon; mon = mon->nmon) {
210         if (DEADMONSTER(mon))
211             continue;
212         mon->mlstmv = g.monstermoves;
213     }
214 }
215 
216 void
losedogs(void)217 losedogs(void)
218 {
219     register struct monst *mtmp, *mtmp0, *mtmp2;
220     int dismissKops = 0;
221 
222     FUZLOG("losedogs");
223     /*
224      * First, scan g.migrating_mons for shopkeepers who want to dismiss Kops,
225      * and scan g.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.
229      *
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).
234      */
235 
236     /* check for returning shk(s) */
237     for (mtmp = g.migrating_mons; mtmp; mtmp = mtmp->nmon) {
238         if (mtmp->mux != u.uz.dnum || mtmp->muy != u.uz.dlevel)
239             continue;
240         if (mtmp->isshk) {
241             if (ESHK(mtmp)->dismiss_kops) {
242                 if (dismissKops == 0)
243                     dismissKops = 1;
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 */
248                 dismissKops = -1;
249                 /* [keep looping; later monsters might need ESHK reset] */
250             }
251         }
252     }
253     /* make the same check for g.mydogs */
254     for (mtmp = g.mydogs; mtmp && dismissKops >= 0; mtmp = mtmp->nmon) {
255         if (mtmp->isshk) {
256             /* hostile shk might accompany hero [ESHK(mtmp)->dismiss_kops
257                can't be set here; it's only used for g.migrating_mons] */
258             if (!mtmp->mpeaceful)
259                 dismissKops = -1;
260         }
261     }
262 
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 */
266     if (dismissKops > 0)
267         make_happy_shoppers(TRUE);
268 
269     /* place pets and/or any other monsters who accompany hero */
270     while ((mtmp = g.mydogs) != 0) {
271         g.mydogs = mtmp->nmon;
272         mon_arrive(mtmp, TRUE);
273     }
274 
275     /* time for migrating monsters to arrive;
276        monsters who belong on this level but fail to arrive get put
277        back onto the list (at head), so traversing it is tricky */
278     for (mtmp = g.migrating_mons; mtmp; mtmp = mtmp2) {
279         mtmp2 = mtmp->nmon;
280         if (mtmp->mux == u.uz.dnum && mtmp->muy == u.uz.dlevel) {
281             /* remove mtmp from g.migrating_mons list */
282             if (mtmp == g.migrating_mons) {
283                 g.migrating_mons = mtmp->nmon;
284             } else {
285                 for (mtmp0 = g.migrating_mons; mtmp0; mtmp0 = mtmp0->nmon)
286                     if (mtmp0->nmon == mtmp) {
287                         mtmp0->nmon = mtmp->nmon;
288                         break;
289                     }
290                 if (!mtmp0)
291                     panic("losedogs: can't find migrating mon");
292             }
293             mon_arrive(mtmp, FALSE);
294         }
295     }
296 }
297 
298 /* called from resurrect() in addition to losedogs() */
299 void
mon_arrive(struct monst * mtmp,boolean with_you)300 mon_arrive(struct monst *mtmp, boolean with_you)
301 {
302     struct trap *t;
303     xchar xlocale, ylocale, xyloc, xyflags, wander;
304     int num_segs;
305     boolean failed_to_place = FALSE;
306     stairway *stway;
307     d_level fromdlev;
308 
309     fuzl_mtmp("mon_arrive", mtmp);
310     mtmp->nmon = fmon;
311     fmon = mtmp;
312     if (mtmp->isshk)
313         set_residency(mtmp, FALSE);
314 
315     num_segs = mtmp->wormno;
316     /* baby long worms have no tail so don't use is_longworm() */
317     if (mtmp->data == &mons[PM_LONG_WORM]) {
318         mtmp->wormno = get_wormno();
319         if (mtmp->wormno)
320             initworm(mtmp, num_segs);
321     } else
322         mtmp->wormno = 0;
323 
324     /* some monsters might need to do something special upon arrival
325        _after_ the current level has been fully set up; see dochug() */
326     mtmp->mstrategy |= STRAT_ARRIVE;
327 
328     /* make sure mnexto(rloc_to(set_apparxy())) doesn't use stale data */
329     mtmp->mux = u.ux, mtmp->muy = u.uy;
330     xyloc = mtmp->mtrack[0].x;
331     xyflags = mtmp->mtrack[0].y;
332     xlocale = mtmp->mtrack[1].x;
333     ylocale = mtmp->mtrack[1].y;
334     fromdlev.dnum = mtmp->mtrack[2].x;
335     fromdlev.dlevel = mtmp->mtrack[2].y;
336     memset(mtmp->mtrack, 0, sizeof mtmp->mtrack);
337 
338     if (mtmp == u.usteed)
339         return; /* don't place steed on the map */
340     if (with_you) {
341         /* When a monster accompanies you, sometimes it will arrive
342            at your intended destination and you'll end up next to
343            that spot.  This code doesn't control the final outcome;
344            goto_level(do.c) decides who ends up at your target spot
345            when there is a monster there too. */
346         if (!MON_AT(u.ux, u.uy)
347             && !rn2(mtmp->mtame ? 10 : mtmp->mpeaceful ? 5 : 2))
348             rloc_to(mtmp, u.ux, u.uy);
349         else
350             mnexto(mtmp);
351         return;
352     }
353     /*
354      * The monster arrived on this level independently of the player.
355      * Its coordinate fields were overloaded for use as flags that
356      * specify its final destination.
357      */
358 
359     if (mtmp->mlstmv < g.monstermoves - 1L) {
360         /* heal monster for time spent in limbo */
361         long nmv = g.monstermoves - 1L - mtmp->mlstmv;
362 
363         mon_catchup_elapsed_time(mtmp, nmv);
364         mtmp->mlstmv = g.monstermoves - 1L;
365 
366         /* let monster move a bit on new level (see placement code below) */
367         wander = (xchar) min(nmv, 8);
368     } else
369         wander = 0;
370 
371     switch (xyloc) {
372     case MIGR_APPROX_XY: /* {x,y}locale set above */
373         break;
374     case MIGR_EXACT_XY:
375         wander = 0;
376         break;
377     case MIGR_WITH_HERO:
378         xlocale = u.ux, ylocale = u.uy;
379         break;
380     case MIGR_STAIRS_UP:
381         if ((stway = stairway_find_from(&fromdlev, FALSE)) != 0) {
382             xlocale = stway->sx;
383             ylocale = stway->sy;
384         }
385         break;
386     case MIGR_STAIRS_DOWN:
387         if ((stway = stairway_find_from(&fromdlev, FALSE)) != 0) {
388             xlocale = stway->sx;
389             ylocale = stway->sy;
390         }
391         break;
392     case MIGR_LADDER_UP:
393         if ((stway = stairway_find_from(&fromdlev, TRUE)) != 0) {
394             xlocale = stway->sx;
395             ylocale = stway->sy;
396         }
397         break;
398     case MIGR_LADDER_DOWN:
399         if ((stway = stairway_find_from(&fromdlev, TRUE)) != 0) {
400             xlocale = stway->sx;
401             ylocale = stway->sy;
402         }
403         break;
404     case MIGR_SSTAIRS:
405         if ((stway = stairway_find(&fromdlev)) != 0) {
406             xlocale = stway->sx;
407             ylocale = stway->sy;
408         }
409         break;
410     case MIGR_PORTAL:
411         if (In_endgame(&u.uz)) {
412             /* there is no arrival portal for endgame levels */
413             /* BUG[?]: for simplicity, this code relies on the fact
414                that we know that the current endgame levels always
415                build upwards and never have any exclusion subregion
416                inside their TELEPORT_REGION settings. */
417             xlocale = rn1(g.updest.hx - g.updest.lx + 1, g.updest.lx);
418             ylocale = rn1(g.updest.hy - g.updest.ly + 1, g.updest.ly);
419             break;
420         }
421         /* find the arrival portal */
422         for (t = g.ftrap; t; t = t->ntrap)
423             if (t->ttyp == MAGIC_PORTAL)
424                 break;
425         if (t) {
426             xlocale = t->tx, ylocale = t->ty;
427             break;
428         } else if (!(u.uevent.qexpelled
429                      && (Is_qstart(&u.uz0) || Is_qstart(&u.uz)))) {
430             impossible("mon_arrive: no corresponding portal?");
431         } /*FALLTHRU*/
432     default:
433     case MIGR_RANDOM:
434         xlocale = ylocale = 0;
435         break;
436     }
437 
438     if ((mtmp->migflags & MIGR_LEFTOVERS) != 0L) {
439         /* Pick up the rest of the MIGR_TO_SPECIES objects */
440         if (g.migrating_objs)
441             deliver_obj_to_mon(mtmp, 0, DF_ALL);
442     }
443 
444     if (xlocale && wander) {
445         /* monster moved a bit; pick a nearby location */
446         /* mnearto() deals w/stone, et al */
447         char *r = in_rooms(xlocale, ylocale, 0);
448 
449         if (r && *r) {
450             coord c;
451 
452             /* somexy() handles irregular rooms */
453             if (somexy(&g.rooms[*r - ROOMOFFSET], &c))
454                 xlocale = c.x, ylocale = c.y;
455             else
456                 xlocale = ylocale = 0;
457         } else { /* not in a room */
458             int i, j;
459 
460             i = max(1, xlocale - wander);
461             j = min(COLNO - 1, xlocale + wander);
462             xlocale = rn1(j - i, i);
463             i = max(0, ylocale - wander);
464             j = min(ROWNO - 1, ylocale + wander);
465             ylocale = rn1(j - i, i);
466         }
467     } /* moved a bit */
468 
469     mtmp->mx = 0; /*(already is 0)*/
470     mtmp->my = xyflags;
471     if (xlocale)
472         failed_to_place = !mnearto(mtmp, xlocale, ylocale, FALSE);
473     else
474         failed_to_place = !rloc(mtmp, TRUE);
475 
476     if (failed_to_place)
477         m_into_limbo(mtmp); /* try again next time hero comes to this level */
478 }
479 
480 /* heal monster for time spent elsewhere */
481 void
mon_catchup_elapsed_time(struct monst * mtmp,long nmv)482 mon_catchup_elapsed_time(struct monst *mtmp,
483                          long nmv) /* number of moves */
484 {
485     int imv = 0; /* avoid zillions of casts and lint warnings */
486 
487 #if defined(DEBUG) || (NH_DEVEL_STATUS != NH_STATUS_RELEASED)
488 
489     if (nmv < 0L) { /* crash likely... */
490         panic("catchup from future time?");
491         /*NOTREACHED*/
492         return;
493     } else if (nmv == 0L) { /* safe, but should'nt happen */
494         impossible("catchup from now?");
495     } else
496 #endif
497         if (nmv >= LARGEST_INT) /* paranoia */
498         imv = LARGEST_INT - 1;
499     else
500         imv = (int) nmv;
501 
502     /* might stop being afraid, blind or frozen */
503     /* set to 1 and allow final decrement in movemon() */
504     if (mtmp->mblinded) {
505         if (imv >= (int) mtmp->mblinded)
506             mtmp->mblinded = 1;
507         else
508             mtmp->mblinded -= imv;
509     }
510     if (mtmp->mfrozen) {
511         if (imv >= (int) mtmp->mfrozen)
512             mtmp->mfrozen = 1;
513         else
514             mtmp->mfrozen -= imv;
515     }
516     if (mtmp->mfleetim) {
517         if (imv >= (int) mtmp->mfleetim)
518             mtmp->mfleetim = 1;
519         else
520             mtmp->mfleetim -= imv;
521     }
522 
523     /* Withering monsters by rights ought to keep withering while off-level, but
524      * it brings up a host of problems to have a monster die in this function
525      * (if the player were responsible, would they get experience for the kill
526      * and potentially level up just by returning to the level? should messages
527      * such as "You have a sad feeling" or vampire polyself/rise again print
528      * upon arrival?)  Instead, just don't affect their hp or withering status;
529      * they will begin re-withering when the hero comes back. */
530 
531     /* might recover from temporary trouble */
532     if (mtmp->mtrapped && rn2(imv + 1) > 40 / 2)
533         mtmp->mtrapped = 0;
534     if (mtmp->mconf && rn2(imv + 1) > 50 / 2)
535         mtmp->mconf = 0;
536     if (mtmp->mstun && rn2(imv + 1) > 10 / 2)
537         mtmp->mstun = 0;
538 
539     /* might finish eating or be able to use special ability again */
540     if (imv > mtmp->meating)
541         finish_meating(mtmp);
542     else
543         mtmp->meating -= imv;
544     if (imv > mtmp->mspec_used)
545         mtmp->mspec_used = 0;
546     else
547         mtmp->mspec_used -= imv;
548 
549     /* reduce tameness for every 150 moves you are separated */
550     if (mtmp->mtame) {
551         int wilder = (imv + rn1(50,50)) / 150;
552         if (mtmp->mtame > wilder)
553             mtmp->mtame -= wilder; /* less tame */
554         else if (mtmp->mtame > rn2(wilder))
555             mtmp->mtame = 0; /* untame */
556         else
557             mtmp->mtame = mtmp->mpeaceful = 0; /* hostile! */
558     }
559     /* check to see if it would have died as a pet; if so, go wild instead
560      * of dying the next time we call dog_move()
561      */
562     if (mtmp->mtame && !mtmp->isminion
563         && (carnivorous(mtmp->data) || herbivorous(mtmp->data))) {
564         struct edog *edog = EDOG(mtmp);
565 
566         if ((g.monstermoves > edog->hungrytime + 500 && mtmp->mhp < 3)
567             || (g.monstermoves > edog->hungrytime + 750))
568             mtmp->mtame = mtmp->mpeaceful = 0;
569     }
570 
571     if (!mtmp->mtame && mtmp->mleashed) {
572         /* leashed monsters should always be with hero, consequently
573            never losing any time to be accounted for later */
574         impossible("catching up for leashed monster?");
575         m_unleash(mtmp, FALSE);
576     }
577 
578     /* recover lost hit points */
579     if (!mtmp->mwither) {
580         if (!regenerates(mtmp->data))
581             imv /= 20;
582         if (mtmp->mhp + imv >= mtmp->mhpmax)
583             mtmp->mhp = mtmp->mhpmax;
584         else
585             mtmp->mhp += imv;
586     }
587 }
588 
589 /* called when you move to another level */
590 void
keepdogs(boolean pets_only,boolean stairs)591 keepdogs(boolean pets_only, /* true for ascension or final escape */
592          boolean stairs)
593 {
594     register struct monst *mtmp, *mtmp2;
595     register struct obj *obj;
596     int num_segs;
597     boolean stay_behind;
598 
599     for (mtmp = fmon; mtmp; mtmp = mtmp2) {
600         mtmp2 = mtmp->nmon;
601         if (DEADMONSTER(mtmp))
602             continue;
603         if (pets_only) {
604             if (!mtmp->mtame)
605                 continue; /* reject non-pets */
606             /* don't block pets from accompanying hero's dungeon
607                escape or ascension simply due to mundane trifles;
608                unlike level change for steed, don't bother trying
609                to achieve a normal trap escape first */
610             mtmp->mtrapped = 0;
611             mtmp->meating = 0;
612             mtmp->msleeping = 0;
613             mtmp->mfrozen = 0;
614             mtmp->mcanmove = 1;
615         }
616         if (((monnear(mtmp, u.ux, u.uy) && levl_follower(mtmp))
617              /* the wiz will level t-port from anywhere to chase
618                 the amulet; if you don't have it, will chase you
619                 only if in range. -3. */
620              || (u.uhave.amulet && mtmp->iswiz))
621             && ((!mtmp->msleeping && mtmp->mcanmove)
622                 /* eg if level teleport or new trap, steed has no control
623                    to avoid following */
624                 || (mtmp == u.usteed))
625             /* monster won't follow if it hasn't noticed you yet */
626             && !(mtmp->mstrategy & STRAT_WAITFORU)) {
627             stay_behind = FALSE;
628             if (mtmp->mtrapped)
629                 (void) mintrap(mtmp); /* try to escape */
630             if (mtmp == u.usteed) {
631                 /* make sure steed is eligible to accompany hero */
632                 mtmp->mtrapped = 0;       /* escape trap */
633                 mtmp->meating = 0;        /* terminate eating */
634                 mdrop_special_objs(mtmp); /* drop Amulet */
635             } else if (mtmp->meating || mtmp->mtrapped) {
636                 if (canseemon(mtmp))
637                     pline("%s is still %s.", Monnam(mtmp),
638                           mtmp->meating ? "eating" : "trapped");
639                 stay_behind = TRUE;
640             } else if (mon_has_amulet(mtmp)) {
641                 if (canseemon(mtmp))
642                     pline("%s seems very disoriented for a moment.",
643                           Monnam(mtmp));
644                 stay_behind = TRUE;
645             }
646             if (stay_behind) {
647                 if (mtmp->mleashed) {
648                     pline("%s leash suddenly comes loose.",
649                           humanoid(mtmp->data)
650                               ? (mtmp->female ? "Her" : "His")
651                               : "Its");
652                     m_unleash(mtmp, FALSE);
653                 }
654                 if (mtmp == u.usteed) {
655                     /* can't happen unless someone makes a change
656                        which scrambles the stay_behind logic above */
657                     impossible("steed left behind?");
658                     dismount_steed(DISMOUNT_GENERIC);
659                 }
660                 continue;
661             }
662             if (mtmp->isshk)
663                 set_residency(mtmp, TRUE);
664 
665             if (mtmp->wormno) {
666                 register int cnt;
667                 /* NOTE: worm is truncated to # segs = max wormno size */
668                 cnt = count_wsegs(mtmp);
669                 num_segs = min(cnt, MAX_NUM_WORMS - 1);
670                 wormgone(mtmp);
671                 place_monster(mtmp, mtmp->mx, mtmp->my);
672             } else
673                 num_segs = 0;
674 
675             if (!stay_behind && !mtmp->mpeaceful){
676                   if (stairs)
677                       pline("%s pursues you!", Monnam(mtmp));
678                   else
679                       pline("%s manages to get a grip on you!", Monnam(mtmp));
680             }
681 
682             /* set minvent's obj->no_charge to 0 */
683             for (obj = mtmp->minvent; obj; obj = obj->nobj) {
684                 if (Has_contents(obj))
685                     picked_container(obj); /* does the right thing */
686                 obj->no_charge = 0;
687             }
688 
689             relmon(mtmp, &g.mydogs);   /* move it from map to g.mydogs */
690             mtmp->mx = mtmp->my = 0; /* avoid mnexto()/MON_AT() problem */
691             mtmp->wormno = num_segs;
692             mtmp->mlstmv = g.monstermoves;
693         } else if (mtmp->iswiz) {
694             /* we want to be able to find him when his next resurrection
695                chance comes up, but have him resume his present location
696                if player returns to this level before that time */
697             migrate_to_level(mtmp, ledger_no(&u.uz), MIGR_EXACT_XY,
698                              (coord *) 0);
699         } else if (mtmp->mleashed) {
700             /* this can happen if your quest leader ejects you from the
701                "home" level while a leashed pet isn't next to you */
702             pline("%s leash goes slack.", s_suffix(Monnam(mtmp)));
703             m_unleash(mtmp, FALSE);
704         }
705     }
706 }
707 
708 void
migrate_to_level(struct monst * mtmp,xchar tolev,xchar xyloc,coord * cc)709 migrate_to_level(struct monst *mtmp,
710                  xchar tolev, /* destination level */
711                  xchar xyloc, /* MIGR_xxx destination xy location: */
712                  coord *cc)   /* optional destination coordinates */
713 {
714     struct obj *obj;
715     d_level new_lev;
716     xchar xyflags;
717     int num_segs = 0; /* count of worm segments */
718 
719     fuzl_mtmp("migrate_to_level", mtmp);
720     if (mtmp->isshk)
721         set_residency(mtmp, TRUE);
722 
723     if (mtmp->wormno) {
724         int cnt = count_wsegs(mtmp);
725 
726         /* **** NOTE: worm is truncated to # segs = max wormno size **** */
727         num_segs = min(cnt, MAX_NUM_WORMS - 1); /* used below */
728         wormgone(mtmp); /* destroys tail and takes head off map */
729         /* there used to be a place_monster() here for the relmon() below,
730            but it doesn't require the monster to be on the map anymore */
731     }
732 
733     /* set minvent's obj->no_charge to 0 */
734     for (obj = mtmp->minvent; obj; obj = obj->nobj) {
735         if (Has_contents(obj))
736             picked_container(obj); /* does the right thing */
737         obj->no_charge = 0;
738     }
739 
740     if (mtmp->mleashed) {
741         mtmp->mtame--;
742         m_unleash(mtmp, TRUE);
743     }
744     relmon(mtmp, &g.migrating_mons); /* move it from map to g.migrating_mons */
745 
746     new_lev.dnum = ledger_to_dnum((xchar) tolev);
747     new_lev.dlevel = ledger_to_dlev((xchar) tolev);
748     /* overload mtmp->[mx,my], mtmp->[mux,muy], and mtmp->mtrack[] as */
749     /* destination codes (setup flag bits before altering mx or my) */
750     xyflags = (depth(&new_lev) < depth(&u.uz)); /* 1 => up */
751     if (In_W_tower(mtmp->mx, mtmp->my, &u.uz))
752         xyflags |= 2;
753     mtmp->wormno = num_segs;
754     mtmp->mlstmv = g.monstermoves;
755     mtmp->mtrack[2].x = u.uz.dnum; /* migrating from this dungeon */
756     mtmp->mtrack[2].y = u.uz.dlevel; /* migrating from this dungeon level */
757     mtmp->mtrack[1].x = cc ? cc->x : mtmp->mx;
758     mtmp->mtrack[1].y = cc ? cc->y : mtmp->my;
759     mtmp->mtrack[0].x = xyloc;
760     mtmp->mtrack[0].y = xyflags;
761     mtmp->mux = new_lev.dnum;
762     mtmp->muy = new_lev.dlevel;
763     mtmp->mx = mtmp->my = 0; /* this implies migration */
764 }
765 
766 /* return quality of food; the lower the better */
767 /* fungi will eat even tainted food */
768 int
dogfood(struct monst * mon,struct obj * obj)769 dogfood(struct monst *mon, struct obj *obj)
770 {
771     struct permonst *mptr = mon->data, *fptr = 0;
772     boolean carni = carnivorous(mptr), herbi = herbivorous(mptr),
773             starving, mblind;
774 
775     if (is_quest_artifact(obj) || obj_resists(obj, 0, 95))
776         return obj->cursed ? TABU : APPORT;
777 
778     switch (obj->oclass) {
779     case FOOD_CLASS:
780         if (obj->otyp == CORPSE || obj->otyp == TIN || obj->otyp == EGG)
781             fptr = &mons[obj->corpsenm];
782 
783         if (obj->otyp == CORPSE && is_rider(fptr))
784             return TABU;
785         if ((obj->otyp == CORPSE || obj->otyp == EGG) && touch_petrifies(fptr)
786             && !resists_ston(mon))
787             return POISON;
788         if (obj->otyp == LUMP_OF_ROYAL_JELLY
789             && mon->data == &mons[PM_KILLER_BEE]) {
790             struct monst *mtmp = find_pmmonst(PM_QUEEN_BEE);
791 
792             /* if there's a queen bee on the level, don't eat royal jelly;
793                if there isn't, do eat it and grow into a queen */
794             return !mtmp ? DOGFOOD : TABU;
795         }
796         if (!carni && !herbi)
797             return obj->cursed ? UNDEF : APPORT;
798 
799         /* a starving pet will eat almost anything */
800         starving = (mon->mtame && !mon->isminion
801                     && EDOG(mon)->mhpmax_penalty);
802         /* even carnivores will eat carrots if they're temporarily blind */
803         mblind = (!mon->mcansee && haseyes(mon->data));
804 
805         /* ghouls prefer old corpses and unhatchable eggs, yum!
806            they'll eat fresh non-veggy corpses and hatchable eggs
807            when starving; they never eat stone-to-flesh'd meat */
808         if (mptr == &mons[PM_GHOUL]) {
809             if (obj->otyp == CORPSE)
810                 return (peek_at_iced_corpse_age(obj) + 50L <= g.monstermoves
811                         && fptr != &mons[PM_LIZARD]
812                         && fptr != &mons[PM_LICHEN])
813                            ? DOGFOOD
814                            : (starving && !vegan(fptr))
815                               ? ACCFOOD
816                               : POISON;
817             if (obj->otyp == EGG)
818                 return stale_egg(obj) ? CADAVER : starving ? ACCFOOD : POISON;
819             return TABU;
820         }
821 
822         switch (obj->otyp) {
823         case TRIPE_RATION:
824         case MEATBALL:
825         case MEAT_RING:
826         case MEAT_STICK:
827         case HUGE_CHUNK_OF_MEAT:
828             return carni ? DOGFOOD : MANFOOD;
829         case EGG:
830             return carni ? CADAVER : MANFOOD;
831         case CORPSE:
832             if ((peek_at_iced_corpse_age(obj) + 50L <= g.monstermoves
833                  && obj->corpsenm != PM_LIZARD && obj->corpsenm != PM_LICHEN
834                  && mptr->mlet != S_FUNGUS)
835                 || (acidic(fptr) && !resists_acid(mon))
836                 || (poisonous(fptr) && !resists_poison(mon)))
837                 return POISON;
838             /* polymorphing is preferable to starvation, and pet might also
839                want to take its chances on that if they've been mistreated */
840             else if (is_shapeshifter(fptr)) {
841                 if (mon->mtame == 1) {
842                     /* A herbivore still won't eat a nonvegan corpse, but
843                        in any other circumstance a pet with tameness 1 will
844                        happily eat a shapeshifter. */
845                     return (herbi && !vegan(fptr)) ? MANFOOD : CADAVER;
846                 }
847                 return starving ? ACCFOOD : MANFOOD;
848             } else if (vegan(fptr))
849                 return herbi ? CADAVER : MANFOOD;
850             /* most humanoids will avoid cannibalism unless starving;
851                arbitrary: elves won't eat other elves even then */
852             else if (humanoid(mptr) && same_race(mptr, fptr)
853                      && (!is_undead(mptr) && fptr->mlet != S_KOBOLD
854                          && fptr->mlet != S_ORC && fptr->mlet != S_OGRE))
855                 return (starving && carni && !is_elf(mptr)) ? ACCFOOD : TABU;
856             else
857                 return carni ? CADAVER : MANFOOD;
858         case GLOB_OF_GREEN_SLIME: /* other globs use the default case */
859             /* turning into slime is preferable to starvation */
860             return (starving || slimeproof(mon->data)) ? ACCFOOD : POISON;
861         case CLOVE_OF_GARLIC:
862             return (is_undead(mptr) || is_vampshifter(mon))
863                       ? TABU
864                       : (herbi || starving)
865                          ? ACCFOOD
866                          : MANFOOD;
867         case TIN:
868             return metallivorous(mptr) ? ACCFOOD : MANFOOD;
869         case APPLE:
870             return herbi ? DOGFOOD : starving ? ACCFOOD : MANFOOD;
871         case CARROT:
872             return (herbi || mblind) ? DOGFOOD : starving ? ACCFOOD : MANFOOD;
873         case BANANA:
874             return (mptr->mlet == S_YETI && herbi)
875                       ? DOGFOOD /* for monkey and ape (tameable), sasquatch */
876                       : (herbi || starving)
877                          ? ACCFOOD
878                          : MANFOOD;
879         default:
880             if (starving)
881                 return ACCFOOD;
882             return (obj->otyp > SLIME_MOLD) ? (carni ? ACCFOOD : MANFOOD)
883                                             : (herbi ? ACCFOOD : MANFOOD);
884         }
885     default:
886         if (obj->otyp == AMULET_OF_STRANGULATION
887             || obj->otyp == RIN_SLOW_DIGESTION)
888             return TABU;
889         if (mon_hates_material(mon, obj->material))
890             return TABU;
891         if (mptr == &mons[PM_GELATINOUS_CUBE] && is_organic(obj))
892             return ACCFOOD;
893         if (metallivorous(mptr) && is_metallic(obj)
894             && can_eat_material(mptr, obj->material)) {
895             /* Non-rustproofed ferrous based metals are preferred. */
896             return (is_rustprone(obj) && !obj->oerodeproof) ? DOGFOOD
897                                                             : ACCFOOD;
898         }
899         if (!obj->cursed
900             && obj->oclass != BALL_CLASS
901             && obj->oclass != CHAIN_CLASS)
902             return APPORT;
903         /*FALLTHRU*/
904     case ROCK_CLASS:
905         return UNDEF;
906     }
907 }
908 
909 /*
910  * With the separate mextra structure added in 3.6.x this always
911  * operates on the original mtmp. It now returns TRUE if the taming
912  * succeeded.
913  */
914 boolean
tamedog(struct monst * mtmp,struct obj * obj,boolean pacify_only)915 tamedog(struct monst *mtmp, struct obj *obj, boolean pacify_only)
916 {
917     /* The Wiz, Medusa and the quest nemeses aren't even made peaceful. */
918     if (mtmp->iswiz || mtmp->data == &mons[PM_MEDUSA]
919         || (mtmp->data->mflags3 & M3_WANTSARTI))
920         return FALSE;
921 
922     /* worst case, at least it'll be peaceful. */
923     mtmp->mpeaceful = 1;
924     set_malign(mtmp);
925     if (flags.moonphase == FULL_MOON && night() && rn2(6) && obj
926         && mtmp->data->mlet == S_DOG)
927         return FALSE;
928 
929     /* If we cannot tame it, at least it's no longer afraid. */
930     mtmp->mflee = 0;
931     mtmp->mfleetim = 0;
932 
933     /* make grabber let go now, whether it becomes tame or not */
934     if (mtmp == u.ustuck) {
935         if (u.uswallow)
936             expels(mtmp, mtmp->data, TRUE);
937         else if (!(Upolyd && sticks(g.youmonst.data)))
938             unstuck(mtmp);
939     }
940 
941     /* feeding it treats makes it tamer */
942     if (mtmp->mtame && obj) {
943         int tasty;
944 
945         if (mtmp->mcanmove && !mtmp->mconf && !mtmp->meating
946             && ((tasty = dogfood(mtmp, obj)) == DOGFOOD
947                 || (tasty <= ACCFOOD
948                     && EDOG(mtmp)->hungrytime <= g.monstermoves))) {
949             /* pet will "catch" and eat this thrown food */
950             if (canseemon(mtmp)) {
951                 boolean big_corpse =
952                     (obj->otyp == CORPSE && obj->corpsenm >= LOW_PM
953                      && mons[obj->corpsenm].msize > mtmp->data->msize);
954                 pline("%s catches %s%s", Monnam(mtmp), the(xname(obj)),
955                       !big_corpse ? "." : ", or vice versa!");
956             } else if (cansee(mtmp->mx, mtmp->my))
957                 pline("%s.", Tobjnam(obj, "stop"));
958             /* dog_eat expects a floor object */
959             place_object(obj, mtmp->mx, mtmp->my);
960             (void) dog_eat(mtmp, obj, mtmp->mx, mtmp->my, FALSE);
961             /* eating might have killed it, but that doesn't matter here;
962                a non-null result suppresses "miss" message for thrown
963                food and also implies that the object has been deleted */
964             return TRUE;
965         } else
966             return FALSE;
967     }
968 
969     if (mtmp->mtame || !mtmp->mcanmove
970         /* monsters with conflicting structures cannot be tamed */
971         || mtmp->isshk || mtmp->isgd || mtmp->ispriest || mtmp->isminion
972         || is_covetous(mtmp->data) || is_human(mtmp->data)
973         || (is_demon(mtmp->data) && !is_demon(g.youmonst.data))
974         || (obj && dogfood(mtmp, obj) >= MANFOOD))
975         return FALSE;
976 
977     if (mtmp->m_id == g.quest_status.leader_m_id)
978         return FALSE;
979 
980     if (pacify_only) {
981        return FALSE;
982     }
983 
984     /* add the pet extension */
985     newedog(mtmp);
986     initedog(mtmp);
987     u.uconduct.pets++;
988 
989     if (obj) { /* thrown food */
990         /* defer eating until the edog extension has been set up */
991         place_object(obj, mtmp->mx, mtmp->my); /* put on floor */
992         /* devour the food (might grow into larger, genocided monster) */
993         if (dog_eat(mtmp, obj, mtmp->mx, mtmp->my, TRUE) == 2)
994             return TRUE; /* oops, it died... */
995         /* `obj' is now obsolete */
996     }
997 
998     newsym(mtmp->mx, mtmp->my);
999     if (attacktype(mtmp->data, AT_WEAP)) {
1000         mtmp->weapon_check = NEED_HTH_WEAPON;
1001         (void) mon_wield_item(mtmp);
1002     }
1003     return TRUE;
1004 }
1005 
1006 /*
1007  * Called during pet revival or pet life-saving.
1008  * If you killed the pet, it revives wild.
1009  * If you abused the pet a lot while alive, it revives wild.
1010  * If you abused the pet at all while alive, it revives untame.
1011  * If the pet wasn't abused and was very tame, it might revive tame.
1012  */
1013 void
wary_dog(struct monst * mtmp,boolean was_dead)1014 wary_dog(struct monst *mtmp, boolean was_dead)
1015 {
1016     struct edog *edog;
1017     boolean quietly = was_dead;
1018 
1019     finish_meating(mtmp);
1020 
1021     if (!mtmp->mtame)
1022         return;
1023     edog = !mtmp->isminion ? EDOG(mtmp) : 0;
1024 
1025     /* if monster was starving when it died, undo that now */
1026     if (edog && edog->mhpmax_penalty) {
1027         mtmp->mhpmax += edog->mhpmax_penalty;
1028         mtmp->mhp += edog->mhpmax_penalty; /* heal it */
1029         edog->mhpmax_penalty = 0;
1030     }
1031 
1032     if (edog && (edog->killed_by_u == 1 || edog->abuse > 2)) {
1033         mtmp->mpeaceful = mtmp->mtame = 0;
1034         if (edog->abuse >= 0 && edog->abuse < 10)
1035             if (!rn2(edog->abuse + 1))
1036                 mtmp->mpeaceful = 1;
1037         if (!quietly && cansee(mtmp->mx, mtmp->my)) {
1038             if (haseyes(g.youmonst.data)) {
1039                 if (haseyes(mtmp->data))
1040                     pline("%s %s to look you in the %s.", Monnam(mtmp),
1041                           mtmp->mpeaceful ? "seems unable" : "refuses",
1042                           body_part(EYE));
1043                 else
1044                     pline("%s avoids your gaze.", Monnam(mtmp));
1045             }
1046         }
1047     } else {
1048         /* chance it goes wild anyway - Pet Sematary */
1049         mtmp->mtame = rn2(mtmp->mtame + 1);
1050         if (!mtmp->mtame)
1051             mtmp->mpeaceful = rn2(2);
1052     }
1053 
1054     if (!mtmp->mtame) {
1055         if (!quietly && canspotmon(mtmp))
1056             pline("%s %s.", Monnam(mtmp),
1057                   mtmp->mpeaceful ? "is no longer tame" : "has become feral");
1058         newsym(mtmp->mx, mtmp->my);
1059         /* a life-saved monster might be leashed;
1060            don't leave it that way if it's no longer tame */
1061         if (mtmp->mleashed)
1062             m_unleash(mtmp, TRUE);
1063         if (mtmp == u.usteed)
1064             dismount_steed(DISMOUNT_THROWN);
1065     } else if (edog) {
1066         /* it's still a pet; start a clean pet-slate now */
1067         edog->revivals++;
1068         edog->killed_by_u = 0;
1069         edog->abuse = 0;
1070         edog->ogoal.x = edog->ogoal.y = -1;
1071         if (was_dead || edog->hungrytime < g.monstermoves + 500L)
1072             edog->hungrytime = g.monstermoves + 500L;
1073         if (was_dead) {
1074             edog->droptime = 0L;
1075             edog->dropdist = 10000;
1076             edog->whistletime = 0L;
1077             edog->apport = 5;
1078         } /* else lifesaved, so retain current values */
1079     }
1080 }
1081 
1082 void
abuse_dog(struct monst * mtmp)1083 abuse_dog(struct monst *mtmp)
1084 {
1085     if (!mtmp->mtame)
1086         return;
1087 
1088     if (Aggravate_monster || Conflict)
1089         mtmp->mtame /= 2;
1090     else
1091         mtmp->mtame--;
1092 
1093     if (mtmp->mtame && !mtmp->isminion)
1094         EDOG(mtmp)->abuse++;
1095 
1096     if (!mtmp->mtame && mtmp->mleashed)
1097         m_unleash(mtmp, TRUE);
1098 
1099     /* don't make a sound if pet is in the middle of leaving the level */
1100     /* newsym isn't necessary in this case either */
1101     if (mtmp->mx != 0) {
1102         if (mtmp->mtame && rn2(mtmp->mtame))
1103             yelp(mtmp);
1104         else
1105             growl(mtmp); /* give them a moment's worry */
1106 
1107         if (!mtmp->mtame)
1108             newsym(mtmp->mx, mtmp->my);
1109     }
1110 }
1111 
1112 /*dog.c*/
1113