Show control key combos with uppercase alpha
[aNetHack.git] / src / dog.c
blob0b9d2ae9fc9a1c86f8369d8a67c6d05d66ac1fd9
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 = ACURR(A_CHA);
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 if (!mnearto(mtmp, xlocale, ylocale, FALSE))
435 goto fail_mon_placement;
436 } else {
437 if (!rloc(mtmp, TRUE)) {
439 * Failed to place migrating monster,
440 * probably because the level is full.
441 * Dump the monster's cargo and leave the monster dead.
443 struct obj *obj;
444 fail_mon_placement:
445 while ((obj = mtmp->minvent) != 0) {
446 obj_extract_self(obj);
447 obj_no_longer_held(obj);
448 if (obj->owornmask & W_WEP)
449 setmnotwielded(mtmp, obj);
450 obj->owornmask = 0L;
451 if (xlocale && ylocale)
452 place_object(obj, xlocale, ylocale);
453 else if (rloco(obj)) {
454 if (!get_obj_location(obj, &xlocale, &ylocale, 0))
455 impossible("Can't find relocated object.");
458 (void) mkcorpstat(CORPSE, (struct monst *) 0, mtmp->data, xlocale,
459 ylocale, CORPSTAT_NONE);
460 mongone(mtmp);
465 /* heal monster for time spent elsewhere */
466 void
467 mon_catchup_elapsed_time(mtmp, nmv)
468 struct monst *mtmp;
469 long nmv; /* number of moves */
471 int imv = 0; /* avoid zillions of casts and lint warnings */
473 #if defined(DEBUG) || defined(BETA)
474 if (nmv < 0L) { /* crash likely... */
475 panic("catchup from future time?");
476 /*NOTREACHED*/
477 return;
478 } else if (nmv == 0L) { /* safe, but should'nt happen */
479 impossible("catchup from now?");
480 } else
481 #endif
482 if (nmv >= LARGEST_INT) /* paranoia */
483 imv = LARGEST_INT - 1;
484 else
485 imv = (int) nmv;
487 /* might stop being afraid, blind or frozen */
488 /* set to 1 and allow final decrement in movemon() */
489 if (mtmp->mblinded) {
490 if (imv >= (int) mtmp->mblinded)
491 mtmp->mblinded = 1;
492 else
493 mtmp->mblinded -= imv;
495 if (mtmp->mfrozen) {
496 if (imv >= (int) mtmp->mfrozen)
497 mtmp->mfrozen = 1;
498 else
499 mtmp->mfrozen -= imv;
501 if (mtmp->mfleetim) {
502 if (imv >= (int) mtmp->mfleetim)
503 mtmp->mfleetim = 1;
504 else
505 mtmp->mfleetim -= imv;
508 /* might recover from temporary trouble */
509 if (mtmp->mtrapped && rn2(imv + 1) > 40 / 2)
510 mtmp->mtrapped = 0;
511 if (mtmp->mconf && rn2(imv + 1) > 50 / 2)
512 mtmp->mconf = 0;
513 if (mtmp->mstun && rn2(imv + 1) > 10 / 2)
514 mtmp->mstun = 0;
516 /* might finish eating or be able to use special ability again */
517 if (imv > mtmp->meating)
518 finish_meating(mtmp);
519 else
520 mtmp->meating -= imv;
521 if (imv > mtmp->mspec_used)
522 mtmp->mspec_used = 0;
523 else
524 mtmp->mspec_used -= imv;
526 /* reduce tameness for every 150 moves you are separated */
527 if (mtmp->mtame) {
528 int wilder = (imv + 75) / 150;
529 if (mtmp->mtame > wilder)
530 mtmp->mtame -= wilder; /* less tame */
531 else if (mtmp->mtame > rn2(wilder))
532 mtmp->mtame = 0; /* untame */
533 else
534 mtmp->mtame = mtmp->mpeaceful = 0; /* hostile! */
536 /* check to see if it would have died as a pet; if so, go wild instead
537 * of dying the next time we call dog_move()
539 if (mtmp->mtame && !mtmp->isminion
540 && (carnivorous(mtmp->data) || herbivorous(mtmp->data))) {
541 struct edog *edog = EDOG(mtmp);
543 if ((monstermoves > edog->hungrytime + 500 && mtmp->mhp < 3)
544 || (monstermoves > edog->hungrytime + 750))
545 mtmp->mtame = mtmp->mpeaceful = 0;
548 if (!mtmp->mtame && mtmp->mleashed) {
549 /* leashed monsters should always be with hero, consequently
550 never losing any time to be accounted for later */
551 impossible("catching up for leashed monster?");
552 m_unleash(mtmp, FALSE);
555 /* recover lost hit points */
556 if (!regenerates(mtmp->data))
557 imv /= 20;
558 if (mtmp->mhp + imv >= mtmp->mhpmax)
559 mtmp->mhp = mtmp->mhpmax;
560 else
561 mtmp->mhp += imv;
564 /* called when you move to another level */
565 void
566 keepdogs(pets_only)
567 boolean pets_only; /* true for ascension or final escape */
569 register struct monst *mtmp, *mtmp2;
570 register struct obj *obj;
571 int num_segs;
572 boolean stay_behind;
574 for (mtmp = fmon; mtmp; mtmp = mtmp2) {
575 mtmp2 = mtmp->nmon;
576 if (DEADMONSTER(mtmp))
577 continue;
578 if (pets_only) {
579 if (!mtmp->mtame)
580 continue; /* reject non-pets */
581 /* don't block pets from accompanying hero's dungeon
582 escape or ascension simply due to mundane trifles;
583 unlike level change for steed, don't bother trying
584 to achieve a normal trap escape first */
585 mtmp->mtrapped = 0;
586 mtmp->meating = 0;
587 mtmp->msleeping = 0;
588 mtmp->mfrozen = 0;
589 mtmp->mcanmove = 1;
591 if (((monnear(mtmp, u.ux, u.uy) && levl_follower(mtmp))
592 /* the wiz will level t-port from anywhere to chase
593 the amulet; if you don't have it, will chase you
594 only if in range. -3. */
595 || (u.uhave.amulet && mtmp->iswiz))
596 && ((!mtmp->msleeping && mtmp->mcanmove)
597 /* eg if level teleport or new trap, steed has no control
598 to avoid following */
599 || (mtmp == u.usteed))
600 /* monster won't follow if it hasn't noticed you yet */
601 && !(mtmp->mstrategy & STRAT_WAITFORU)) {
602 stay_behind = FALSE;
603 if (mtmp->mtrapped)
604 (void) mintrap(mtmp); /* try to escape */
605 if (mtmp == u.usteed) {
606 /* make sure steed is eligible to accompany hero */
607 mtmp->mtrapped = 0; /* escape trap */
608 mtmp->meating = 0; /* terminate eating */
609 mdrop_special_objs(mtmp); /* drop Amulet */
610 } else if (mtmp->meating || mtmp->mtrapped) {
611 if (canseemon(mtmp))
612 pline("%s is still %s.", Monnam(mtmp),
613 mtmp->meating ? "eating" : "trapped");
614 stay_behind = TRUE;
615 } else if (mon_has_amulet(mtmp)) {
616 if (canseemon(mtmp))
617 pline("%s seems very disoriented for a moment.",
618 Monnam(mtmp));
619 stay_behind = TRUE;
621 if (stay_behind) {
622 if (mtmp->mleashed) {
623 pline("%s leash suddenly comes loose.",
624 humanoid(mtmp->data)
625 ? (mtmp->female ? "Her" : "His")
626 : "Its");
627 m_unleash(mtmp, FALSE);
629 if (mtmp == u.usteed) {
630 /* can't happen unless someone makes a change
631 which scrambles the stay_behind logic above */
632 impossible("steed left behind?");
633 dismount_steed(DISMOUNT_GENERIC);
635 continue;
637 if (mtmp->isshk)
638 set_residency(mtmp, TRUE);
640 if (mtmp->wormno) {
641 register int cnt;
642 /* NOTE: worm is truncated to # segs = max wormno size */
643 cnt = count_wsegs(mtmp);
644 num_segs = min(cnt, MAX_NUM_WORMS - 1);
645 wormgone(mtmp);
646 } else
647 num_segs = 0;
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;
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);
675 void
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 */
682 register struct obj *obj;
683 d_level new_lev;
684 xchar xyflags;
685 int num_segs = 0; /* count of worm segments */
687 if (mtmp->isshk)
688 set_residency(mtmp, TRUE);
690 if (mtmp->wormno) {
691 register int cnt;
692 /* **** NOTE: worm is truncated to # segs = max wormno size **** */
693 cnt = count_wsegs(mtmp);
694 num_segs = min(cnt, MAX_NUM_WORMS - 1);
695 wormgone(mtmp);
698 /* set minvent's obj->no_charge to 0 */
699 for (obj = mtmp->minvent; obj; obj = obj->nobj) {
700 if (Has_contents(obj))
701 picked_container(obj); /* does the right thing */
702 obj->no_charge = 0;
705 if (mtmp->mleashed) {
706 mtmp->mtame--;
707 m_unleash(mtmp, TRUE);
709 relmon(mtmp, &migrating_mons); /* move it from map to migrating_mons */
711 new_lev.dnum = ledger_to_dnum((xchar) tolev);
712 new_lev.dlevel = ledger_to_dlev((xchar) tolev);
713 /* overload mtmp->[mx,my], mtmp->[mux,muy], and mtmp->mtrack[] as */
714 /* destination codes (setup flag bits before altering mx or my) */
715 xyflags = (depth(&new_lev) < depth(&u.uz)); /* 1 => up */
716 if (In_W_tower(mtmp->mx, mtmp->my, &u.uz))
717 xyflags |= 2;
718 mtmp->wormno = num_segs;
719 mtmp->mlstmv = monstermoves;
720 mtmp->mtrack[1].x = cc ? cc->x : mtmp->mx;
721 mtmp->mtrack[1].y = cc ? cc->y : mtmp->my;
722 mtmp->mtrack[0].x = xyloc;
723 mtmp->mtrack[0].y = xyflags;
724 mtmp->mux = new_lev.dnum;
725 mtmp->muy = new_lev.dlevel;
726 mtmp->mx = mtmp->my = 0; /* this implies migration */
727 if (mtmp == context.polearm.hitmon)
728 context.polearm.hitmon = NULL;
731 /* return quality of food; the lower the better */
732 /* fungi will eat even tainted food */
734 dogfood(mon, obj)
735 struct monst *mon;
736 register struct obj *obj;
738 struct permonst *mptr = mon->data, *fptr = 0;
739 boolean carni = carnivorous(mptr), herbi = herbivorous(mptr), starving;
741 if (is_quest_artifact(obj) || obj_resists(obj, 0, 95))
742 return obj->cursed ? TABU : APPORT;
744 switch (obj->oclass) {
745 case FOOD_CLASS:
746 if (obj->otyp == CORPSE || obj->otyp == TIN || obj->otyp == EGG)
747 fptr = &mons[obj->corpsenm];
749 if (obj->otyp == CORPSE && is_rider(fptr))
750 return TABU;
751 if ((obj->otyp == CORPSE || obj->otyp == EGG) && touch_petrifies(fptr)
752 && !resists_ston(mon))
753 return POISON;
754 if (!carni && !herbi)
755 return obj->cursed ? UNDEF : APPORT;
757 /* a starving pet will eat almost anything */
758 starving =
759 (mon->mtame && !mon->isminion && EDOG(mon)->mhpmax_penalty);
761 /* ghouls prefer old corpses and unhatchable eggs, yum!
762 they'll eat fresh non-veggy corpses and hatchable eggs
763 when starving; they never eat stone-to-flesh'd meat */
764 if (mptr == &mons[PM_GHOUL]) {
765 if (obj->otyp == CORPSE)
766 return (peek_at_iced_corpse_age(obj) + 50L <= monstermoves
767 && fptr != &mons[PM_LIZARD]
768 && fptr != &mons[PM_LICHEN])
769 ? DOGFOOD
770 : (starving && !vegan(fptr))
771 ? ACCFOOD
772 : POISON;
773 if (obj->otyp == EGG)
774 return stale_egg(obj) ? CADAVER : starving ? ACCFOOD : POISON;
775 return TABU;
778 switch (obj->otyp) {
779 case TRIPE_RATION:
780 case MEATBALL:
781 case MEAT_RING:
782 case MEAT_STICK:
783 case HUGE_CHUNK_OF_MEAT:
784 return carni ? DOGFOOD : MANFOOD;
785 case EGG:
786 return carni ? CADAVER : MANFOOD;
787 case CORPSE:
788 if ((peek_at_iced_corpse_age(obj) + 50L <= monstermoves
789 && obj->corpsenm != PM_LIZARD && obj->corpsenm != PM_LICHEN
790 && mptr->mlet != S_FUNGUS)
791 || (acidic(fptr) && !resists_acid(mon))
792 || (poisonous(fptr) && !resists_poison(mon)))
793 return POISON;
794 /* turning into slime is preferable to starvation */
795 else if (fptr == &mons[PM_GREEN_SLIME] && !slimeproof(mon->data))
796 return starving ? ACCFOOD : POISON;
797 else if (vegan(fptr))
798 return herbi ? CADAVER : MANFOOD;
799 /* most humanoids will avoid cannibalism unless starving;
800 arbitrary: elves won't eat other elves even then */
801 else if (humanoid(mptr) && same_race(mptr, fptr)
802 && (!is_undead(mptr) && fptr->mlet != S_KOBOLD
803 && fptr->mlet != S_ORC && fptr->mlet != S_OGRE))
804 return (starving && carni && !is_elf(mptr)) ? ACCFOOD : TABU;
805 else
806 return carni ? CADAVER : MANFOOD;
807 case CLOVE_OF_GARLIC:
808 return (is_undead(mptr) || is_vampshifter(mon))
809 ? TABU
810 : (herbi || starving)
811 ? ACCFOOD
812 : MANFOOD;
813 case TIN:
814 return metallivorous(mptr) ? ACCFOOD : MANFOOD;
815 case APPLE:
816 case CARROT:
817 return herbi ? DOGFOOD : starving ? ACCFOOD : MANFOOD;
818 case BANANA:
819 return (mptr->mlet == S_YETI && herbi)
820 ? DOGFOOD /* for monkey and ape (tameable), sasquatch */
821 : (herbi || starving)
822 ? ACCFOOD
823 : MANFOOD;
824 default:
825 if (starving)
826 return ACCFOOD;
827 return (obj->otyp > SLIME_MOLD) ? (carni ? ACCFOOD : MANFOOD)
828 : (herbi ? ACCFOOD : MANFOOD);
830 default:
831 if (obj->otyp == AMULET_OF_STRANGULATION
832 || obj->otyp == RIN_SLOW_DIGESTION)
833 return TABU;
834 if (mon_hates_silver(mon) && objects[obj->otyp].oc_material == SILVER)
835 return TABU;
836 if (mptr == &mons[PM_GELATINOUS_CUBE] && is_organic(obj))
837 return ACCFOOD;
838 if (metallivorous(mptr) && is_metallic(obj)
839 && (is_rustprone(obj) || mptr != &mons[PM_RUST_MONSTER])) {
840 /* Non-rustproofed ferrous based metals are preferred. */
841 return (is_rustprone(obj) && !obj->oerodeproof) ? DOGFOOD
842 : ACCFOOD;
844 if (!obj->cursed
845 && obj->oclass != BALL_CLASS
846 && obj->oclass != CHAIN_CLASS)
847 return APPORT;
848 /*FALLTHRU*/
849 case ROCK_CLASS:
850 return UNDEF;
855 * With the separate mextra structure added in 3.6.x this always
856 * operates on the original mtmp. It now returns TRUE if the taming
857 * succeeded.
859 boolean
860 tamedog(mtmp, obj)
861 register struct monst *mtmp;
862 register struct obj *obj;
864 /* The Wiz, Medusa and the quest nemeses aren't even made peaceful. */
865 if (mtmp->iswiz || mtmp->data == &mons[PM_MEDUSA]
866 || (mtmp->data->mflags3 & M3_WANTSARTI))
867 return FALSE;
869 /* worst case, at least it'll be peaceful. */
870 mtmp->mpeaceful = 1;
871 set_malign(mtmp);
872 if (flags.moonphase == FULL_MOON && night() && rn2(6) && obj
873 && mtmp->data->mlet == S_DOG)
874 return FALSE;
876 /* If we cannot tame it, at least it's no longer afraid. */
877 mtmp->mflee = 0;
878 mtmp->mfleetim = 0;
880 /* make grabber let go now, whether it becomes tame or not */
881 if (mtmp == u.ustuck) {
882 if (u.uswallow)
883 expels(mtmp, mtmp->data, TRUE);
884 else if (!(Upolyd && sticks(youmonst.data)))
885 unstuck(mtmp);
888 /* feeding it treats makes it tamer */
889 if (mtmp->mtame && obj) {
890 int tasty;
892 if (mtmp->mcanmove && !mtmp->mconf && !mtmp->meating
893 && ((tasty = dogfood(mtmp, obj)) == DOGFOOD
894 || (tasty <= ACCFOOD
895 && EDOG(mtmp)->hungrytime <= monstermoves))) {
896 /* pet will "catch" and eat this thrown food */
897 if (canseemon(mtmp)) {
898 boolean big_corpse =
899 (obj->otyp == CORPSE && obj->corpsenm >= LOW_PM
900 && mons[obj->corpsenm].msize > mtmp->data->msize);
901 pline("%s catches %s%s", Monnam(mtmp), the(xname(obj)),
902 !big_corpse ? "." : ", or vice versa!");
903 } else if (cansee(mtmp->mx, mtmp->my))
904 pline("%s.", Tobjnam(obj, "stop"));
905 /* dog_eat expects a floor object */
906 place_object(obj, mtmp->mx, mtmp->my);
907 (void) dog_eat(mtmp, obj, mtmp->mx, mtmp->my, FALSE);
908 /* eating might have killed it, but that doesn't matter here;
909 a non-null result suppresses "miss" message for thrown
910 food and also implies that the object has been deleted */
911 return TRUE;
912 } else
913 return FALSE;
916 if (mtmp->mtame || !mtmp->mcanmove
917 /* monsters with conflicting structures cannot be tamed */
918 || mtmp->isshk || mtmp->isgd || mtmp->ispriest || mtmp->isminion
919 || is_covetous(mtmp->data) || is_human(mtmp->data)
920 || (is_demon(mtmp->data) && !is_demon(youmonst.data))
921 || (obj && dogfood(mtmp, obj) >= MANFOOD))
922 return FALSE;
924 if (mtmp->m_id == quest_status.leader_m_id)
925 return FALSE;
927 /* add the pet extension */
928 newedog(mtmp);
929 initedog(mtmp);
931 if (obj) { /* thrown food */
932 /* defer eating until the edog extension has been set up */
933 place_object(obj, mtmp->mx, mtmp->my); /* put on floor */
934 /* devour the food (might grow into larger, genocided monster) */
935 if (dog_eat(mtmp, obj, mtmp->mx, mtmp->my, TRUE) == 2)
936 return TRUE; /* oops, it died... */
937 /* `obj' is now obsolete */
940 newsym(mtmp->mx, mtmp->my);
941 if (attacktype(mtmp->data, AT_WEAP)) {
942 mtmp->weapon_check = NEED_HTH_WEAPON;
943 (void) mon_wield_item(mtmp);
945 return TRUE;
949 * Called during pet revival or pet life-saving.
950 * If you killed the pet, it revives wild.
951 * If you abused the pet a lot while alive, it revives wild.
952 * If you abused the pet at all while alive, it revives untame.
953 * If the pet wasn't abused and was very tame, it might revive tame.
955 void
956 wary_dog(mtmp, was_dead)
957 struct monst *mtmp;
958 boolean was_dead;
960 struct edog *edog;
961 boolean quietly = was_dead;
963 finish_meating(mtmp);
965 if (!mtmp->mtame)
966 return;
967 edog = !mtmp->isminion ? EDOG(mtmp) : 0;
969 /* if monster was starving when it died, undo that now */
970 if (edog && edog->mhpmax_penalty) {
971 mtmp->mhpmax += edog->mhpmax_penalty;
972 mtmp->mhp += edog->mhpmax_penalty; /* heal it */
973 edog->mhpmax_penalty = 0;
976 if (edog && (edog->killed_by_u == 1 || edog->abuse > 2)) {
977 mtmp->mpeaceful = mtmp->mtame = 0;
978 if (edog->abuse >= 0 && edog->abuse < 10)
979 if (!rn2(edog->abuse + 1))
980 mtmp->mpeaceful = 1;
981 if (!quietly && cansee(mtmp->mx, mtmp->my)) {
982 if (haseyes(youmonst.data)) {
983 if (haseyes(mtmp->data))
984 pline("%s %s to look you in the %s.", Monnam(mtmp),
985 mtmp->mpeaceful ? "seems unable" : "refuses",
986 body_part(EYE));
987 else
988 pline("%s avoids your gaze.", Monnam(mtmp));
991 } else {
992 /* chance it goes wild anyway - Pet Sematary */
993 mtmp->mtame = rn2(mtmp->mtame + 1);
994 if (!mtmp->mtame)
995 mtmp->mpeaceful = rn2(2);
998 if (!mtmp->mtame) {
999 if (!quietly && canspotmon(mtmp))
1000 pline("%s %s.", Monnam(mtmp),
1001 mtmp->mpeaceful ? "is no longer tame" : "has become feral");
1002 newsym(mtmp->mx, mtmp->my);
1003 /* a life-saved monster might be leashed;
1004 don't leave it that way if it's no longer tame */
1005 if (mtmp->mleashed)
1006 m_unleash(mtmp, TRUE);
1007 if (mtmp == u.usteed)
1008 dismount_steed(DISMOUNT_THROWN);
1009 } else if (edog) {
1010 /* it's still a pet; start a clean pet-slate now */
1011 edog->revivals++;
1012 edog->killed_by_u = 0;
1013 edog->abuse = 0;
1014 edog->ogoal.x = edog->ogoal.y = -1;
1015 if (was_dead || edog->hungrytime < monstermoves + 500L)
1016 edog->hungrytime = monstermoves + 500L;
1017 if (was_dead) {
1018 edog->droptime = 0L;
1019 edog->dropdist = 10000;
1020 edog->whistletime = 0L;
1021 edog->apport = 5;
1022 } /* else lifesaved, so retain current values */
1026 void
1027 abuse_dog(mtmp)
1028 struct monst *mtmp;
1030 if (!mtmp->mtame)
1031 return;
1033 if (Aggravate_monster || Conflict)
1034 mtmp->mtame /= 2;
1035 else
1036 mtmp->mtame--;
1038 if (mtmp->mtame && !mtmp->isminion)
1039 EDOG(mtmp)->abuse++;
1041 if (!mtmp->mtame && mtmp->mleashed)
1042 m_unleash(mtmp, TRUE);
1044 /* don't make a sound if pet is in the middle of leaving the level */
1045 /* newsym isn't necessary in this case either */
1046 if (mtmp->mx != 0) {
1047 if (mtmp->mtame && rn2(mtmp->mtame))
1048 yelp(mtmp);
1049 else
1050 growl(mtmp); /* give them a moment's worry */
1052 if (!mtmp->mtame)
1053 newsym(mtmp->mx, mtmp->my);
1057 /*dog.c*/