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