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