Source:NetHack 3.1.0/dog.c

Below is the full text to dog.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.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.1	92/10/18	*/ 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.   #define domestic(mtmp)	(mtmp->data->msound == MS_BARK || \  9.    			 mtmp->data->msound == MS_MEW) 10.   11.   #ifdef OVLB 12.   13.   static int NDECL(pet_type); 14.   15.   void 16.  initedog(mtmp) 17.  register struct monst *mtmp; 18.  {  19.   	mtmp->mtame = domestic(mtmp) ? 10 : 5; 20.   	mtmp->mpeaceful = 1; 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 + moves; 29.  }  30.    31.   static int 32.  pet_type 33.  {  34.   	register int pettype; 35.   36.   	switch (pl_character[0]) { 37.  		/* some character classes have restricted ideas of pets */ 38.  		case 'C': 39.  		case 'S': 40.  			pettype = PM_LITTLE_DOG; 41.  			break; 42.  		case 'W': 43.  			pettype = PM_KITTEN; 44.  			break; 45.  		/* otherwise, see if the player has a preference */ 46.  		default: 47.  			if (preferred_pet == 'c') 48.  				pettype = PM_KITTEN; 49.  			else if (preferred_pet == 'd') 50.  				pettype = PM_LITTLE_DOG; 51.  			else	pettype = rn2(2) ? PM_KITTEN : PM_LITTLE_DOG; 52.  			break; 53.  	}  54.   	return pettype; 55.  }  56.    57.   void 58.  make_familiar(otmp,x,y) 59.  register struct obj *otmp; 60.  xchar x, y;  61. { 62.   	register struct monst *mtmp; 63.  	register struct permonst *pm; 64.   65.   top: 66.  	if (otmp) pm = &mons[otmp->corpsenm]; /* Figurine; otherwise spell */ 67.  	else if (rn2(3)) { 68.  	    if (!(pm = rndmonst)) { 69.  		pline("There seems to be nothing available for a familiar."); 70.  		return; 71.  	    }  72.   	}  73.   	else pm = &mons[pet_type]; 74.   75.   	pm->pxlth += sizeof(struct edog); 76.  	mtmp = makemon(pm, x, y); 77.  	pm->pxlth -= sizeof(struct edog); 78.  	if (!mtmp) { /* monster was genocided */ 79.  	    if (otmp) 80.  		pline("The figurine writhes and then shatters into pieces!"); 81.  	    else goto top; 82.  		/* rndmonst returns something not genocided always, so this 83.  		 * means it was a cat or dog; loop back to try again until 84.  		 * either rndmonst is called, or if only one of cat/dog 85.  		 * was genocided, they get the other. 86.  		 */  87.   	    return; 88.  	}  89.   	initedog(mtmp); 90.  	mtmp->msleep = 0; 91.  	if (otmp && otmp->cursed) { /* cursed figurine */ 92.  		You("get a bad feeling about this."); 93.  		mtmp->mtame = mtmp->mpeaceful = 0; 94.  		newsym(mtmp->mx, mtmp->my); 95.  	}  96.   	set_malign(mtmp); /* more alignment changes */ 97.  }  98.    99.   struct monst * 100. makedog 101. {  102.  	register struct monst *mtmp; 103. 	char *petname; 104. 	int   pettype; 105. 	static int petname_used = 0; 106.  107.  	pettype = pet_type; 108. 	if (pettype == PM_LITTLE_DOG) 109. 		petname = dogname; 110. 	else 111. 		petname = catname; 112.  113.  	mons[pettype].pxlth = sizeof(struct edog); 114. 	mtmp = makemon(&mons[pettype], u.ux, u.uy); 115. 	mons[pettype].pxlth = 0; 116.  117.  	if(!mtmp) return((struct monst *) 0); /* pets were genocided */ 118.  119.  	if (!petname_used++ && *petname) 120. 		mtmp = christen_monst(mtmp, petname); 121.  122.  	initedog(mtmp); 123. 	return(mtmp); 124. }  125.   126.  void 127. losedogs 128. {  129.  	register struct monst *mtmp,*mtmp0,*mtmp2; 130. 	int num_segs; 131.  132.  	while(mtmp = mydogs){ 133. 		mydogs = mtmp->nmon; 134. 		mtmp->nmon = fmon; 135. 		fmon = mtmp; 136. 		if (mtmp->isshk) 137. 		    set_residency(mtmp, FALSE); 138.  139.  		num_segs = mtmp->wormno; 140. 		/* baby long worms have no tail so don't use is_longworm */ 141. 		if ( (mtmp->data == &mons[PM_LONG_WORM]) &&  142.  		     (mtmp->wormno = get_wormno) ) { 143. 		    initworm(mtmp, num_segs); 144. 		    /* tail segs are not yet initialized or displayed */ 145. 		} else mtmp->wormno = 0; 146. 		mnexto(mtmp); 147. 	}  148.   149.  #if defined(LINT) || defined(GCC_WARN) 150. 	mtmp0 = (struct monst *)0; 151. #endif 152. 	for(mtmp = migrating_mons; mtmp; mtmp = mtmp2) { 153. 		mtmp2 = mtmp->nmon; 154. 		if(mtmp->mx == u.uz.dnum && mtmp->mux == u.uz.dlevel) { 155. 		    mtmp->mx = 0;		   /* save xyloc in mtmp->my */ 156. 		    mtmp->mux = u.ux; mtmp->muy = u.uy; /* not really req'd */ 157. 		    if(mtmp == migrating_mons) 158. 			migrating_mons = mtmp->nmon; 159. 		    else 160. 			mtmp0->nmon = mtmp->nmon; 161. 		    mtmp->nmon = fmon; 162. 		    fmon = mtmp; 163. 		    num_segs = mtmp->wormno; 164. 		    if ( (mtmp->data == &mons[PM_LONG_WORM]) &&  165.  			 (mtmp->wormno = get_wormno) ) { 166. 			initworm(mtmp, num_segs); 167. 			/* tail segs are not yet initialized or displayed */ 168. 		    } else mtmp->wormno = 0; 169.  170.  		    if(mtmp->mlstmv < monstermoves-1) { 171. 			/* heal monster for time spent in limbo */ 172. 			long nmv = monstermoves - mtmp->mlstmv - 1; 173.  174.  			/* might stop being afraid, blind or frozen */ 175. 			/* set to 1 and allow final decrement in movemon */ 176. 			if(nmv >= (long)mtmp->mblinded) mtmp->mblinded = 1; 177. 			else mtmp->mblinded -= nmv; 178. 			if(nmv >= (long)mtmp->mfrozen) mtmp->mfrozen = 1; 179. 			else mtmp->mfrozen -= nmv; 180. 			if(nmv >= (long)mtmp->mfleetim) mtmp->mfleetim = 1; 181. 			else mtmp->mfleetim -= nmv; 182.  183.  			/* might be able to use special ability again */ 184. 			if(nmv > (long)mtmp->mspec_used) mtmp->mspec_used = 0; 185. 			else mtmp->mspec_used -= nmv; 186.  187.  			if(!regenerates(mtmp->data)) nmv /= 20; 188. 			if((long)mtmp->mhp + nmv >= (long)mtmp->mhpmax) 189. 			    mtmp->mhp = mtmp->mhpmax; 190. 			else mtmp->mhp += nmv; 191. 			mtmp->mlstmv = monstermoves-1; 192. 		    }  193.   194.  		    if (mtmp->data->geno & G_GENOD) { 195. #ifdef KOPS 196. 			allow_kops = FALSE; 197. #endif 198. 			mondead(mtmp);	/* must put in fmon list first */ 199. #ifdef KOPS 200. 			allow_kops = TRUE; 201. #endif 202. 		    } else if (mtmp->isshk && mtmp->mpeaceful) 203. 			home_shk(mtmp, TRUE); 204. 		    else switch(mtmp->my) { 205. 			xchar *xlocale, *ylocale; 206.  207.  			case 1: xlocale = &xupstair; ylocale = &yupstair; 208. 				goto common; 209. 			case 2: xlocale = &xdnstair; ylocale = &ydnstair; 210. 				goto common; 211. 			case 3: xlocale = &xupladder; ylocale = &yupladder; 212. 				goto common; 213. 			case 4: xlocale = &xdnladder; ylocale = &ydnladder; 214. 				goto common; 215. 			case 5: xlocale = &sstairs.sx; ylocale = &sstairs.sy; 216. 				goto common; 217. common: 218. 				if (*xlocale && *ylocale) { 219. 			    (void) mnearto(mtmp, *xlocale, *ylocale, FALSE); 220. 				    break; 221. 				} /* else fall through */ 222. 			default: 223. 				rloc(mtmp); 224. 				break; 225. 			}  226.  		} else 227. 		    mtmp0 = mtmp; 228. 		if (mtmp->isshk) 229. 		    set_residency(mtmp, FALSE); 230. 	}  231.  }  232.   233.  #endif /* OVLB */ 234. #ifdef OVL2 235.  236.  void 237. keepdogs 238. {  239.  	register struct monst *mtmp; 240. 	register struct obj *obj; 241. 	int num_segs = 0; 242.  243.  	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 244. 	    if(((monnear(mtmp, u.ux, u.uy) && levl_follower(mtmp)) || 245. 		/* the wiz will level t-port from anywhere to chase 246. 		   the amulet; if you don't have it, will chase you 247. 		   only if in range. -3. */ 248.  			(u.uhave.amulet && mtmp->iswiz))  249.  			&& !mtmp->msleep && mtmp->mcanmove) { 250.  251.  		/* long worms can now change levels! - Norm */ 252.  253.  		if (mtmp->mtame && mtmp->meating && canseemon(mtmp)) { 254. 			pline("%s is still eating.", Monnam(mtmp)); 255. 			goto merge; 256. 		}  257.  		if (mon_has_amulet(mtmp)) { 258. 			pline("%s seems very disoriented for a moment.",  259.  				Monnam(mtmp)); 260. 		merge: 261. #ifdef WALKIES 262. 			if (mtmp->mleashed) { 263. 				pline("%s leash suddenly comes loose.",  264.  					humanoid(mtmp->data)  265.  					    ? (mtmp->female ? "Her" : "His") 266.  					    : "Its"); 267. 				m_unleash(mtmp); 268. 			}  269.  #endif 270. 			continue; 271. 		}  272.  		if (mtmp->isshk) 273. 			set_residency(mtmp, TRUE); 274.  275.  		if (mtmp->wormno) { 276. 		    /* NOTE: worm is truncated to # segs = max wormno size */ 277. 		    num_segs = min(count_wsegs(mtmp), MAX_NUM_WORMS - 1); 278. 		    wormgone(mtmp); 279. 		}  280.   281.  		/* set minvent's obj->no_charge to 0 */ 282. 		for(obj = mtmp->minvent; obj; obj = obj->nobj) { 283. 		    if(Is_container(obj)) 284. 		        picked_container(obj); /* does the right thing */ 285. 		    obj->no_charge = 0; 286. 		}  287.   288.  		relmon(mtmp); 289. 		newsym(mtmp->mx,mtmp->my); 290. 		mtmp->mx = mtmp->my = 0; /* avoid mnexto/MON_AT problem */ 291. 		mtmp->wormno = num_segs; 292. 		mtmp->nmon = mydogs; 293. 		mydogs = mtmp; 294. 		keepdogs;	/* we destroyed the link, so use recursion */ 295. 		return;		/* (admittedly somewhat primitive) */ 296. 	}  297.  }  298.   299.  #endif /* OVL2 */ 300. #ifdef OVLB 301.  302.  void 303. migrate_to_level(mtmp, tolev, xyloc) 304. 	register struct monst *mtmp; 305. 	xchar tolev;  	/* destination level */ 306. 	xchar xyloc;	/* destination xy location: */ 307. 			/* 	0: rnd, 308. 			 *	1: <,  309.  			 *	2: >,  310.  			 *	3: < ladder, 311. 			 *	4: > ladder, 312. 			 *	5: sstairs 313. 			 */  314.  {  315.          register struct obj *obj; 316. 	int num_segs = 0;	/* count of worm segments */ 317.  318.  	if (mtmp->isshk) 319. 	    set_residency(mtmp, TRUE); 320.  321.  	if (mtmp->wormno) { 322. 	  /* **** NOTE: worm is truncated to # segs = max wormno size **** */ 323. 	    num_segs = min(count_wsegs(mtmp), MAX_NUM_WORMS - 1); 324. 	    wormgone(mtmp); 325. 	}  326.   327.  	/* set minvent's obj->no_charge to 0 */ 328. 	for(obj = mtmp->minvent; obj; obj = obj->nobj) { 329. 	    if(Is_container(obj)) 330. 	        picked_container(obj); /* does the right thing */ 331. 	    obj->no_charge = 0; 332. 	}  333.   334.  	relmon(mtmp); 335. 	mtmp->nmon = migrating_mons; 336. 	migrating_mons = mtmp; 337. #ifdef WALKIES 338. 	if (mtmp->mleashed)  { 339. 		pline("The leash comes off!"); 340. 		m_unleash(mtmp); 341. 	}  342.  #endif 343. 	mtmp->mtame = 0; 344. 	newsym(mtmp->mx,mtmp->my); 345. 	/* make sure to reset mtmp->[mx,my] to 0 when releasing, */ 346. 	/* so rloc on next level doesn't affect MON_AT state */ 347. 	mtmp->mx = ledger_to_dnum((xchar)tolev); 348. 	mtmp->mux = ledger_to_dlev((xchar)tolev); 349. 	mtmp->my = xyloc; 350. 	mtmp->muy = 0; 351. 	mtmp->wormno = num_segs; 352. 	mtmp->mlstmv = monstermoves; 353. }  354.   355.  #endif /* OVLB */ 356. #ifdef OVL1 357.  358.  /* return quality of food; the lower the better */ 359. /* fungi will eat even tainted food */ 360. int 361. dogfood(mon,obj) 362. struct monst *mon; 363. register struct obj *obj; 364. {  365.  	boolean carni = carnivorous(mon->data); 366. 	boolean herbi = herbivorous(mon->data); 367. 	struct permonst *fptr = &mons[obj->corpsenm]; 368.  369.  	switch(obj->oclass) { 370. 	case FOOD_CLASS: 371. 	    if (obj->otyp == CORPSE &&  372.  		((obj->corpsenm == PM_COCKATRICE && !resists_ston(mon->data)) 373. 		 || is_rider(fptr))) 374. 		    return TABU; 375.  376.  	    if (!carni && !herbi) 377. 		    return (obj->cursed ? UNDEF : APPORT); 378.  379.  	    switch (obj->otyp) { 380. 		case TRIPE_RATION: 381. 		    return (carni ? DOGFOOD : MANFOOD); 382. 		case EGG: 383. 		    if (obj->corpsenm == PM_COCKATRICE &&  384.  						!resists_ston(mon->data)) 385. 			return POISON; 386. 		    return (carni ? CADAVER : MANFOOD); 387. 		case CORPSE: 388. 		    if ((obj->age+50 <= monstermoves 389. 					    && obj->corpsenm != PM_LIZARD 390. 					    && mon->data->mlet != S_FUNGUS) ||  391.  			(acidic(&mons[obj->corpsenm]) && 392. 						!resists_acid(mon->data)) ||  393.  			(poisonous(&mons[obj->corpsenm]) && 394. 						!resists_poison(mon->data))) 395. 			return POISON; 396. 		    else if (fptr->mlet == S_FUNGUS) 397. 			return (herbi ? CADAVER : MANFOOD); 398. 		    else if (is_meaty(fptr)) 399. 		        return (carni ? CADAVER : MANFOOD); 400. 		    else return (carni ? ACCFOOD : MANFOOD); 401. 		case CLOVE_OF_GARLIC: 402. 		    return (is_undead(mon->data) ? TABU :  403.  			    (herbi ? ACCFOOD : MANFOOD)); 404. 		case TIN: 405. 		    return (metallivorous(mon->data) ? ACCFOOD : MANFOOD); 406. 		case APPLE: 407. 		case CARROT: 408. 		    return (herbi ? DOGFOOD : MANFOOD); 409. 		case BANANA: 410. 		    return ((mon->data->mlet == S_YETI) ? DOGFOOD :  411.  			    (herbi ? ACCFOOD : MANFOOD)); 412. 		default: 413. #ifdef TUTTI_FRUTTI 414. 		    return (obj->otyp > SLIME_MOLD ?  415.  #else  416.  		    return (obj->otyp > CLOVE_OF_GARLIC ? 417. #endif 418. 			    (carni ? ACCFOOD : MANFOOD) : 419. 			    (herbi ? ACCFOOD : MANFOOD));  420.  	    }  421.  	default:  422.  	    if (hates_silver(mon->data) && 423. 		objects[obj->otyp].oc_material == SILVER)  424.  		return(TABU);  425.  	    if (mon->data == &mons[PM_GELATINOUS_CUBE] && is_organic(obj))  426.  		return(ACCFOOD);  427.  	    if (metallivorous(mon->data) && is_metallic(obj))  428.  		/* Ferrous based metals are preferred. */  429.  		return(objects[obj->otyp].oc_material == IRON ? DOGFOOD : 430. 		       ACCFOOD);  431.  	    if(!obj->cursed && obj->oclass != BALL_CLASS && 432. 						obj->oclass != CHAIN_CLASS)  433.  		return(APPORT);  434.  	    /* fall into next case */  435.  	case ROCK_CLASS:  436.  	    return(UNDEF);  437.  	}  438.  }  439.   440.  #endif /* OVL1 */  441.  #ifdef OVLB  442.   443.  struct monst *  444.  tamedog(mtmp, obj)  445.  register struct monst *mtmp;  446.  register struct obj *obj;  447.  {  448.  	register struct monst *mtmp2;  449.   450.  	/* The Wiz, Medusa and the quest nemeses aren't even made peaceful. */  451.  	if (mtmp->iswiz || mtmp->data == &mons[PM_MEDUSA] 452. #ifdef MULDGN 453. 	    || (mtmp->data->mflags3 & M3_WANTSARTI) 454. #endif 455. 	    )  456.  		return((struct monst *)0);  457.   458.  	/* worst case, at least he'll be peaceful. */  459.  	mtmp->mpeaceful = 1;  460.  	set_malign(mtmp);  461.  	if(flags.moonphase == FULL_MOON && night && rn2(6) && obj 462. 						&& mtmp->data->mlet == S_DOG)  463.  		return((struct monst *)0);  464.   465.  	/* If we cannot tame him, at least he's no longer afraid. */  466.  	mtmp->mflee = 0;  467.  	mtmp->mfleetim = 0;  468.  	if(mtmp->mtame || !mtmp->mcanmove || 469. 	   /* monsters with conflicting structures cannot be tamed */ 470. 	   mtmp->isshk || mtmp->isgd || mtmp->ispriest || mtmp->isminion || 471. #ifdef POLYSELF 472. 	   is_human(mtmp->data) || (is_demon(mtmp->data) && !is_demon(uasmon)) 473. #else 474. 	   is_human(mtmp->data) || is_demon(mtmp->data) 475. #endif 476. 	   || (mtmp->data->mflags3 &  477.  	       (M3_WANTSAMUL|M3_WANTSBELL|M3_WANTSBOOK|M3_WANTSCAND)) 478. 	   )  479.  		return((struct monst *)0);  480.  	if(obj) {  481.  		if(dogfood(mtmp, obj) >= MANFOOD) return((struct monst *)0);  482.  		if(cansee(mtmp->mx,mtmp->my))  483.  			pline("%s devours the %s.", Monnam(mtmp), xname(obj));  484.  		obfree(obj, (struct obj *)0);  485.  	}  486.  	if (u.uswallow && mtmp == u.ustuck)  487.  		expels(mtmp, mtmp->data, TRUE);  488.  	mtmp2 = newmonst(sizeof(struct edog) + mtmp->mnamelth);  489.  	*mtmp2 = *mtmp;  490.  	mtmp2->mxlth = sizeof(struct edog);  491.  	if(mtmp->mnamelth) Strcpy(NAME(mtmp2), NAME(mtmp));  492.  	initedog(mtmp2);  493.  	replmon(mtmp,mtmp2);  494.  	newsym(mtmp2->mx, mtmp2->my);  495.  	return(mtmp2);  496.  }  497.   498.  #endif /* OVLB */  499.   500.  /*dog.c*/