Source:NetHack 3.0.0/dog.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to dog.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.0/dog.c#line123]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

1.    /*	SCCS Id: @(#)dog.c	3.0	89/06/12
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.    
8.    char dogname[63] = DUMMY;
9.    char catname[63] = DUMMY;
10.   
11.   #define domestic(mtmp)	(mtmp->data->msound == MS_BARK || mtmp->data->msound == MS_MEW)
12.   
13.   void
14.   initedog(mtmp)
15.   register struct monst *mtmp;
16.   {
17.   	mtmp->mtame = domestic(mtmp) ? 10 : 5;
18.   	mtmp->mpeaceful = 1;
19.   	mtmp->mleashed = 0;
20.   	mtmp->meating = 0;
21.   	EDOG(mtmp)->droptime = 0;
22.   	EDOG(mtmp)->dropdist = 10000;
23.   	EDOG(mtmp)->apport = 10;
24.   	EDOG(mtmp)->whistletime = 0;
25.   	EDOG(mtmp)->hungrytime = 1000 + moves;
26.   }
27.   
28.   void
29.   make_familiar(otmp)
30.   register struct obj *otmp;
31.   {
32.   	register struct monst *mtmp;
33.   	register struct permonst *pm;
34.   
35.   top:
36.   	if (otmp) pm = &mons[otmp->corpsenm]; /* Figurine; otherwise spell */
37.   	else if (rn2(3)) {
38.   	    if (!(pm = rndmonst())) {
39.   		pline("There seems to be nothing available for a familiar.");
40.   		return;
41.   	    }
42.   	}
43.   	else if ((pl_character[0]=='W' || rn2(2)) && pl_character[0]!='C')
44.   		pm = &mons[PM_KITTEN];
45.   	else pm = &mons[PM_LITTLE_DOG];
46.   
47.   	pm->pxlth += sizeof(struct edog);
48.   	mtmp = makemon(pm, u.ux, u.uy);
49.   	pm->pxlth -= sizeof(struct edog);
50.   	if (!mtmp) { /* monster was genocided */
51.   	    if (otmp)
52.   		pline("The figurine writhes and then shatters into pieces!");
53.   	    else goto top;
54.   		/* rndmonst() returns something not genocided always, so this
55.   		 * means it was a cat or dog; loop back to try again until
56.   		 * either rndmonst() is called, or if only one of cat/dog
57.   		 * was genocided, they get the other.
58.   		 */
59.   	    return;
60.   	}
61.   	initedog(mtmp);
62.   	if (otmp && otmp->cursed) { /* cursed figurine */
63.   		You("get a bad feeling about this.");
64.   		mtmp->mtame = mtmp->mpeaceful = 0;
65.   	}
66.   }
67.   
68.   struct monst *
69.   makedog() {
70.   	register struct monst *mtmp;
71.   	register char *petname;
72.   
73.   	if (pl_character[0]=='C' || (pl_character[0] != 'W' && rn2(2))) {
74.   		mons[PM_LITTLE_DOG].pxlth = sizeof(struct edog);
75.   		mtmp = makemon(&mons[PM_LITTLE_DOG], u.ux, u.uy);
76.   		mons[PM_LITTLE_DOG].pxlth = 0;
77.   		petname = dogname;
78.   	} else {
79.   		mons[PM_KITTEN].pxlth = sizeof(struct edog);
80.   		mtmp = makemon(&mons[PM_KITTEN], u.ux, u.uy);
81.   		mons[PM_KITTEN].pxlth = 0;
82.   		petname = catname;
83.   	}
84.   
85.   	if(!mtmp) return((struct monst *) 0); /* dogs were genocided */
86.   
87.   	if (petname[0]) {
88.   		register struct monst *mtmp2;
89.   
90.   		mtmp->mnamelth = strlen(petname) + 1;
91.   		mtmp2 = newmonst(sizeof(struct edog) + mtmp->mnamelth);
92.   		*mtmp2 = *mtmp;
93.   
94.   		replmon(mtmp, mtmp2);
95.   		mtmp = mtmp2;
96.   		Strcpy(NAME(mtmp), petname);
97.   		petname[0] = '\0'; /* name first only; actually unnecessary */
98.   	}
99.   	initedog(mtmp);
100.  	return(mtmp);
101.  }
102.  
103.  /* attach the monsters that went down (or up) together with @ */
104.  struct monst *mydogs = 0;
105.  /* monsters that fell through a trapdoor or stepped on a tele-trap. */
106.  /* 'down' is now true only of trapdooor falling, not for tele-trap. */
107.  struct monst *fallen_down = 0;
108.  				
109.  void
110.  losedogs(){
111.  	register struct monst *mtmp,*mtmp0,*mtmp2;
112.  
113.  	while(mtmp = mydogs){
114.  		mydogs = mtmp->nmon;
115.  		mtmp->nmon = fmon;
116.  		fmon = mtmp;
117.  		mnexto(mtmp);
118.  	}
119.  #ifdef LINT
120.  	mtmp0 = (struct monst *)0;
121.  #endif
122.  	for(mtmp = fallen_down; mtmp; mtmp = mtmp2) {
123.  		mtmp2 = mtmp->nmon;
124.  		if(mtmp->mx == dlevel) {
125.  		    mtmp->mx = 0;
126.  		    if(mtmp == fallen_down)
127.  			fallen_down = mtmp->nmon;
128.  		    else
129.  			mtmp0->nmon = mtmp->nmon;
130.  		    mtmp->nmon = fmon;
131.  		    fmon = mtmp;
132.  		    if (mtmp->isshk)
133.  			home_shk(mtmp);
134.  		    else
135.  			rloc(mtmp);
136.  		} else
137.  		    mtmp0 = mtmp;
138.  	}
139.  }
140.  
141.  void
142.  keepdogs(){
143.  register struct monst *mtmp;
144.  	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
145.  	    if(((dist(mtmp->mx,mtmp->my) < 3 && levl_follower(mtmp)) ||
146.  		/* the wiz will level t-port from anywhere to chase
147.  		   the amulet; if you don't have it, will chase you
148.  		   only if in range. -3. */
149.  			(u.uhave_amulet && mtmp->iswiz))
150.  			&& !mtmp->msleep && !mtmp->mfroz) {
151.  #ifdef WORM
152.  		/* Bug "fix" for worm changing levels collapsing dungeon
153.  		 */
154.  		if (mtmp->data == &mons[PM_LONG_WORM]) {
155.  			if (canseemon(mtmp) || (Blind && Telepat))
156.  				pline("The worm can't fit down the stairwell.");
157.  # ifdef WALKIES
158.  			if (mtmp->mleashed) {
159.  				pline("The leash slides off the slimy worm.");
160.  				m_unleash(mtmp);
161.  			}
162.  # endif
163.  			continue;
164.  		}
165.  #endif
166.  		if (mon_has_amulet(mtmp)) {
167.  			pline("%s seems very disoriented for a moment.",
168.  				Monnam(mtmp));
169.  #ifdef WALKIES
170.  			if (mtmp->mleashed) {
171.  				pline("%s leash suddenly comes loose.",
172.  					is_female(mtmp) ? "Her" :
173.  					humanoid(mtmp->data) ? "His" : "Its");
174.  				m_unleash(mtmp);
175.  			}
176.  #endif
177.  			continue;
178.  		}
179.  		relmon(mtmp);
180.  		mtmp->mx = mtmp->my = 0; /* to avoid mnexto()/mmask problem */
181.  		mtmp->nmon = mydogs;
182.  		mydogs = mtmp;
183.  		unpmon(mtmp);
184.  		keepdogs();	/* we destroyed the link, so use recursion */
185.  		return;		/* (admittedly somewhat primitive) */
186.  	}
187.  }
188.  
189.  void
190.  fall_down(mtmp, tolev) 
191.  register struct monst *mtmp; 
192.  register int tolev;
193.  {
194.  	relmon(mtmp);
195.  	mtmp->nmon = fallen_down;
196.  	fallen_down = mtmp;
197.  #ifdef WALKIES
198.  	if (mtmp->mleashed)  {
199.  		pline("The leash comes off!");
200.  		m_unleash(mtmp);
201.  	}
202.  #endif
203.  	unpmon(mtmp);
204.  	mtmp->mtame = 0;
205.  	mtmp->mx = tolev; 
206.  	mtmp->my = 0;
207.  		/* make sure to reset mtmp->mx to 0 when releasing, */
208.  		/* so rloc() on next level doesn't affect mmask */
209.  }
210.  
211.  /* return quality of food; the lower the better */
212.  /* fungi will eat even tainted food */
213.  int
214.  dogfood(mon,obj)
215.  struct monst *mon;
216.  register struct obj *obj;
217.  {
218.  	boolean carn = carnivorous(mon->data);
219.  
220.  	switch(obj->olet) {
221.  	case FOOD_SYM:
222.  	    if (obj->otyp == CORPSE && obj->corpsenm == PM_COCKATRICE &&
223.  		!resists_ston(mon->data))
224.  		    return TABU;
225.  
226.  	    if (!carn && !herbivorous(mon->data))
227.  		    return (obj->cursed ? UNDEF : APPORT);
228.  
229.  	    switch (obj->otyp) {
230.  		case TRIPE_RATION:
231.  		    return (carn ? DOGFOOD : MANFOOD);
232.  		case CORPSE:
233.  		case EGG:
234.  		    if ((obj->age + 50 <= moves && mon->data->mlet != S_FUNGUS) ||
235.  			(poisonous(&mons[obj->corpsenm]) && !resists_poison(mon->data)) ||
236.  			(obj->corpsenm == PM_COCKATRICE && !resists_ston(mon->data)))
237.  			return POISON;
238.  		    else return (carn ? CADAVER : MANFOOD);
239.  		case DEAD_LIZARD:
240.  		    return (carn ? ACCFOOD : MANFOOD);
241.  		default:
242.  		    return (obj->otyp < CARROT ? ACCFOOD : MANFOOD);
243.  	    }
244.  	default:
245.  	    if(!obj->cursed) return(APPORT);
246.  	    /* fall into next case */
247.  	case BALL_SYM:
248.  	case CHAIN_SYM:
249.  	case ROCK_SYM:
250.  	    return(UNDEF);
251.  	}
252.  }
253.  
254.  /* return roomnumber or -1 */
255.  int
256.  inroom(x,y) xchar x,y; {
257.  	register struct mkroom *croom = &rooms[0];
258.  	while(croom->hx >= 0){
259.  		if(croom->hx >= x-1 && croom->lx <= x+1 &&
260.  		   croom->hy >= y-1 && croom->ly <= y+1)
261.  			return(croom - rooms);
262.  		croom++;
263.  	}
264.  	return(-1);	/* not in room or on door */
265.  }
266.  
267.  int
268.  tamedog(mtmp, obj)
269.  register struct monst *mtmp;
270.  register struct obj *obj;
271.  {
272.  	register struct monst *mtmp2;
273.  
274.  	/* worst case, at least he'll be peaceful. */
275.  	mtmp->mpeaceful = 1;
276.  	if(flags.moonphase == FULL_MOON && night() && rn2(6) && obj
277.  						&& mtmp->data->mlet == S_DOG)
278.  		return(0);
279.  
280.  	/* If we cannot tame him, at least he's no longer afraid. */
281.  	mtmp->mflee = 0;
282.  	mtmp->mfleetim = 0;
283.  	if(mtmp->mtame || mtmp->mfroz ||
284.  #ifdef WORM
285.  	   mtmp->wormno ||
286.  #endif
287.  	   mtmp->isshk || mtmp->isgd ||
288.  #if defined(ALTARS) && defined(THEOLOGY)
289.  	   mtmp->ispriest ||
290.  #endif
291.  #ifdef POLYSELF
292.  	   is_human(mtmp->data) || (is_demon(mtmp->data) && !is_demon(uasmon)))
293.  #else
294.  	   is_human(mtmp->data) || is_demon(mtmp->data))
295.  #endif
296.  		return(0);
297.  	/* no tame long worms so they don't try to follow you down stairs
298.  	   or get in your way */
299.  	if(obj) {
300.  		if(dogfood(mtmp, obj) >= MANFOOD) return(0);
301.  		if(cansee(mtmp->mx,mtmp->my)){
302.  			pline("%s devours the %s.", Monnam(mtmp),
303.  				objects[obj->otyp].oc_name);
304.  		}
305.  		obfree(obj, (struct obj *)0);
306.  	}
307.  	mtmp2 = newmonst(sizeof(struct edog) + mtmp->mnamelth);
308.  	*mtmp2 = *mtmp;
309.  	mtmp2->mxlth = sizeof(struct edog);
310.  	if(mtmp->mnamelth) Strcpy(NAME(mtmp2), NAME(mtmp));
311.  	initedog(mtmp2);
312.  	replmon(mtmp,mtmp2);
313.  	return(1);
314.  }