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