Source:NetHack 3.0.0/dog.c

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

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.  }