Fandom

Wikihack

Source:SLASH'EM 0.0.7E7F2/dog.c

2,034pages on
this wiki
Add New Page
Talk0

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.

Below is the full text to dog.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/dog.c#line123]], for example.

The latest source code for vanilla NetHack is at Source code.


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

Also on Fandom

Random Wiki