OSDN Git Service

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