Source:NetHack 3.2.0/dog.c

Below is the full text to dog.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.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.2	96/02/11	*/ 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.   #ifdef OVLB 9.    10.   static int NDECL(pet_type); 11.   12.   void 13.  initedog(mtmp) 14.  register struct monst *mtmp; 15.  {  16.   	mtmp->mtame = is_domestic(mtmp->data) ? 10 : 5; 17.   	mtmp->mpeaceful = 1; 18.  	set_malign(mtmp); /* recalc alignment now that it's tamed */ 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.  	EDOG(mtmp)->ogoal.x = -1;	/* force error if used before set */ 27.  	EDOG(mtmp)->ogoal.y = -1; 28.  }  29.    30.   static int 31.  pet_type 32.  {  33.   	register int pettype; 34.   35.   	switch (u.role) { 36.  		/* some character classes have restricted ideas of pets */ 37.  		case 'C': 38.  		case 'S': 39.  			pettype = PM_LITTLE_DOG; 40.  			break; 41.  		case 'W': 42.  			pettype = PM_KITTEN; 43.  			break; 44.  		/* otherwise, see if the player has a preference */ 45.  		default: 46.  			if (preferred_pet == 'c') 47.  				pettype = PM_KITTEN; 48.  			else if (preferred_pet == 'd') 49.  				pettype = PM_LITTLE_DOG; 50.  			else	pettype = rn2(2) ? PM_KITTEN : PM_LITTLE_DOG; 51.  			break; 52.  	}  53.   	return pettype; 54.  }  55.    56.   void 57.  make_familiar(otmp,x,y) 58.  register struct obj *otmp; 59.  xchar x, y;  60. { 61.   	struct permonst *pm; 62.  	struct monst *mtmp = 0; 63.  	int chance, trycnt = 100; 64.   65.   	do { 66.  	    if (otmp) { 67.  		pm = &mons[otmp->corpsenm]; /* Figurine; otherwise spell */ 68.  	    } else if (!rn2(3)) { 69.  		pm = &mons[pet_type]; 70.  	    } else { 71.  		pm = rndmonst; 72.  		if (!pm) { 73.  		    pline("There seems to be nothing available for a familiar."); 74.  		    break; 75.  		}  76.   	    }  77.    78.   	    pm->pxlth += sizeof (struct edog); 79.  	    mtmp = makemon(pm, x, y); 80.  	    pm->pxlth -= sizeof (struct edog); 81.  	    if (otmp && !mtmp) { /* monster was genocided or square occupied */ 82.  		pline_The("figurine writhes and then shatters into pieces!"); 83.  		break; 84.  	    }  85.   	} while (!mtmp && --trycnt > 0); 86.   87.   	if (!mtmp) return; 88.   89.   	initedog(mtmp); 90.  	mtmp->msleep = 0; 91.  	if (otmp) { /* figurine; resulting monster might not become a pet */ 92.  	    chance = rn2(10);	/* 0==tame, 1==peaceful, 2==hostile */ 93.  	    if (chance > 2) chance = otmp->blessed ? 0 : !otmp->cursed ? 1 : 2; 94.   	    /* 0,1,2:  b=80%,10,10; nc=10%,80,10; c=10%,10,80 */ 95.  	    if (chance > 0) { 96.  		mtmp->mtame = 0;	/* not tame after all */ 97.  		if (chance == 2) { /* hostile (cursed figurine) */ 98.  		    You("get a bad feeling about this."); 99.  		    mtmp->mpeaceful = 0; 100. 		}  101.  	    }  102.  	}  103.  	set_malign(mtmp); /* more alignment changes */ 104. 	newsym(mtmp->mx, mtmp->my); 105.  106.  	/* must wield weapon immediately since pets will otherwise drop it */ 107. 	if (mtmp->mtame && attacktype(mtmp->data, AT_WEAP)) { 108. 		mtmp->weapon_check = NEED_HTH_WEAPON; 109. 		(void) mon_wield_item(mtmp); 110. 	}  111.  }  112.   113.  struct monst * 114. makedog 115. {  116.  	register struct monst *mtmp; 117. 	const char *petname; 118. 	int   pettype; 119. 	static int petname_used = 0; 120.  121.  	pettype = pet_type; 122. 	if (pettype == PM_LITTLE_DOG) 123. 		petname = dogname; 124. 	else 125. 		petname = catname; 126.  127.  	/* default pet names */ 128. 	if (!*petname) { 129. 	    if(Role_is('C')) petname = "Slasher";   /* The Warrior */ 130. 	    if(Role_is('S')) petname = "Hachi";     /* Shibuya Station */ 131. 	    if(Role_is('B')) petname = "Idefix";    /* Obelix */ 132. 	}  133.   134.  	mons[pettype].pxlth = sizeof(struct edog); 135. 	mtmp = makemon(&mons[pettype], u.ux, u.uy); 136. 	mons[pettype].pxlth = 0; 137.  138.  	if(!mtmp) return((struct monst *) 0); /* pets were genocided */ 139.  140.  	if (!petname_used++ && *petname) 141. 		mtmp = christen_monst(mtmp, petname); 142.  143.  	initedog(mtmp); 144. 	return(mtmp); 145. }  146.   147.  void 148. losedogs 149. {  150.  	register struct monst *mtmp, *mtmp0 = 0, *mtmp2; 151.  152.  	while ((mtmp = mydogs) != 0) { 153. 		mydogs = mtmp->nmon; 154. 		mon_arrive(mtmp, TRUE); 155. 	}  156.   157.  	for(mtmp = migrating_mons; mtmp; mtmp = mtmp2) { 158. 		mtmp2 = mtmp->nmon; 159. 		if (mtmp->mux == u.uz.dnum && mtmp->muy == u.uz.dlevel) { 160. 		    if(mtmp == migrating_mons) 161. 			migrating_mons = mtmp->nmon; 162. 		    else 163. 			mtmp0->nmon = mtmp->nmon; 164. 		    mon_arrive(mtmp, FALSE); 165. 		} else 166. 		    mtmp0 = mtmp; 167. 	}  168.  }  169.   170.  /* called from resurrect in addition to losedogs */ 171. void 172. mon_arrive(mtmp, with_you) 173. struct monst *mtmp; 174. boolean with_you; 175. {  176.  	struct trap *t; 177. 	xchar xlocale, ylocale, xyloc, xyflags, wander; 178. 	int num_segs; 179.  180.  	mtmp->nmon = fmon; 181. 	fmon = mtmp; 182. 	if (mtmp->isshk) 183. 	    set_residency(mtmp, FALSE); 184.  185.  	num_segs = mtmp->wormno; 186. 	/* baby long worms have no tail so don't use is_longworm */ 187. 	if ((mtmp->data == &mons[PM_LONG_WORM]) &&  188.  #ifdef DCC30_BUG  189.  	    (mtmp->wormno = get_wormno, mtmp->wormno != 0)) { 190. #else 191. 	    (mtmp->wormno = get_wormno) != 0) {  192.  #endif  193.  	    initworm(mtmp, num_segs);  194.  	    /* tail segs are not yet initialized or displayed */  195.  	} else mtmp->wormno = 0;  196.   197.  	/* some monsters might need to do something special upon arrival  198.  	   _after_ the current level has been fully set up; see dochug */  199.  	mtmp->mstrategy |= STRAT_ARRIVE;  200.   201.  	if (with_you) {  202.  	    mnexto(mtmp);  203.  	    return;  204.  	}  205.  	/*  206.  	 * The monster arrived on this level independently of the player.  207.  	 * Its coordinate fields were overloaded for use as flags that  208.  	 * specify its final destination.  209.  	 */  210.   211.  	xyloc	= mtmp->mtrack[0].x;  212.  	xyflags = mtmp->mtrack[0].y;  213.  	xlocale = mtmp->mtrack[1].x;  214.  	ylocale = mtmp->mtrack[1].y;  215.  	mtmp->mtrack[0].x = mtmp->mtrack[0].y = 0;  216. mtmp->mtrack[1].x = mtmp->mtrack[1].y = 0; 217. 	mtmp->mux = u.ux,  mtmp->muy = u.uy;	/* not really req'd */ 218.  219.  	if (mtmp->mlstmv < monstermoves - 1L) { 220. 	    /* heal monster for time spent in limbo */ 221. 	    long nmv = monstermoves - 1L - mtmp->mlstmv; 222.  223.  	    mon_catchup_elapsed_time(mtmp, nmv); 224. 	    mtmp->mlstmv = monstermoves - 1L; 225.  226.  	    /* let monster move a bit on new level (see placement code below) */ 227. 	    wander = (xchar) min(nmv, 8); 228. 	} else 229. 	    wander = 0; 230.  231.  	switch (xyloc) { 232. 	 case MIGR_APPROX_XY:	/* {x,y}locale set above */ 233. 		break; 234. 	 case MIGR_EXACT_XY:	wander = 0; 235. 		break; 236. 	 case MIGR_NEAR_PLAYER:	xlocale = u.ux,  ylocale = u.uy; 237. 		break; 238. 	 case MIGR_STAIRS_UP:	xlocale = xupstair,  ylocale = yupstair; 239. 		break; 240. 	 case MIGR_STAIRS_DOWN:	xlocale = xdnstair,  ylocale = ydnstair; 241. 		break; 242. 	 case MIGR_LADDER_UP:	xlocale = xupladder,  ylocale = yupladder; 243. 		break; 244. 	 case MIGR_LADDER_DOWN:	xlocale = xdnladder,  ylocale = ydnladder; 245. 		break; 246. 	 case MIGR_SSTAIRS:	xlocale = sstairs.sx,  ylocale = sstairs.sy; 247. 		break; 248. 	 case MIGR_PORTAL: 249. 		for (t = ftrap; t; t = t->ntrap) 250. 		    if (t->ttyp == MAGIC_PORTAL) break; 251. 		if (t) { 252. 		    xlocale = t->tx,  ylocale = t->ty; 253. 		    break; 254. 		} else { 255. 		    if (!In_endgame(&u.uz)) 256. 			impossible("mon_arrive: no corresponding portal?"); 257. 		} /*FALLTHRU*/ 258. 	 default: 259. 	 case MIGR_RANDOM:	xlocale = ylocale = 0; 260. 		    break; 261. 	    }  262.   263.  	if (xlocale && wander) { 264. 	    /* monster moved a bit; pick a nearby location */ 265. 	    /* mnearto deals w/stone, et al */ 266. 	    char *r = in_rooms(xlocale, ylocale, 0); 267. 	    if (r && *r) { 268. 		coord c;  269. /* somexy handles irregular rooms */ 270. 		if (somexy(&rooms[*r - ROOMOFFSET], &c)) 271. 		    xlocale = c.x,  ylocale = c.y;  272. else 273. 		    xlocale = ylocale = 0; 274. 	    } else {		/* not in a room */ 275. 		int i, j;  276. i = max(1, xlocale - wander); 277. 		j = min(COLNO-1, xlocale + wander); 278. 		xlocale = rn1(j - i, i); 279. 		i = max(0, ylocale - wander); 280. 		j = min(ROWNO-1, ylocale + wander); 281. 		ylocale = rn1(j - i, i); 282. 	    }  283.  	}	/* moved a bit */ 284.  285.  	mtmp->mx = 0;	/*(already is 0)*/ 286. 	mtmp->my = xyflags; 287. 	if (xlocale) 288. 	    (void) mnearto(mtmp, xlocale, ylocale, FALSE); 289. 	else 290. 	    rloc(mtmp); 291. }  292.   293.  /* heal monster for time spent elsewhere */ 294. void 295. mon_catchup_elapsed_time(mtmp, nmv) 296. struct monst *mtmp; 297. long nmv;		/* number of moves */ 298. {  299.  	int imv = 0;	/* avoid zillions of casts and lint warnings */ 300.  301.  #if defined(DEBUG) || defined(BETA) 302. 	if (nmv < 0L) {			/* crash likely... */ 303.  	    panic("catchup from future time?"); 304. 	    /*NOTREACHED*/ 305. 	    return; 306. 	} else if (nmv == 0L) {		/* safe, but should'nt happen */ 307. 	    impossible("catchup from now?"); 308. 	} else 309. #endif 310. 	if (nmv >= LARGEST_INT)		/* paranoia */ 311. 	    imv = LARGEST_INT - 1; 312. 	else 313. 	    imv = (int)nmv; 314.  315.  	/* might stop being afraid, blind or frozen */ 316. 	/* set to 1 and allow final decrement in movemon */ 317. 	if (mtmp->mblinded) { 318. 	    if (imv >= (int) mtmp->mblinded) mtmp->mblinded = 1; 319. 	    else mtmp->mblinded -= imv; 320. 	}  321.  	if (mtmp->mfrozen) { 322. 	    if (imv >= (int) mtmp->mfrozen) mtmp->mfrozen = 1; 323. 	    else mtmp->mfrozen -= imv; 324. 	}  325.  	if (mtmp->mfleetim) { 326. 	    if (imv >= (int) mtmp->mfleetim) mtmp->mfleetim = 1; 327. 	    else mtmp->mfleetim -= imv; 328. 	}  329.   330.  	/* might recover from temporary trouble */ 331. 	if (mtmp->mtrapped && rn2(imv + 1) > 40/2) mtmp->mtrapped = 0; 332. 	if (mtmp->mconf    && rn2(imv + 1) > 50/2) mtmp->mconf = 0; 333. 	if (mtmp->mstun    && rn2(imv + 1) > 10/2) mtmp->mstun = 0; 334.  335.  	/* might finish eating or be able to use special ability again */ 336. 	if (imv > mtmp->meating) mtmp->meating = 0; 337. 	else mtmp->meating -= imv; 338. 	if (imv > mtmp->mspec_used) mtmp->mspec_used = 0; 339. 	else mtmp->mspec_used -= imv; 340.  341.  	/* reduce tameness for every 150 moves you are separated */ 342. 	if (mtmp->mtame) { 343. 	    int wilder = (imv + 75) / 150; 344. 	    if (mtmp->mtame > wilder) mtmp->mtame -= wilder;	/* less tame */ 345. 	    else if (mtmp->mtame > rn2(wilder)) mtmp->mtame = 0;  /* untame */ 346. 	    else mtmp->mtame = mtmp->mpeaceful = 0;		/* hostile! */ 347.  	}  348.   349.  	/* recover lost hit points */ 350. 	if (!regenerates(mtmp->data)) imv /= 20; 351. 	if (mtmp->mhp + imv >= mtmp->mhpmax) 352. 	    mtmp->mhp = mtmp->mhpmax; 353. 	else mtmp->mhp += imv; 354. }  355.   356.  #endif /* OVLB */ 357. #ifdef OVL2 358.  359.  /* called when you move to another level */ 360. void 361. keepdogs(pets_only) 362. boolean pets_only;	/* true for ascension or final escape */ 363. {  364.  	register struct monst *mtmp, *mtmp2; 365. 	register struct obj *obj; 366. 	int num_segs; 367. 	boolean stay_behind; 368.  369.  	for (mtmp = fmon; mtmp; mtmp = mtmp2) { 370. 	    mtmp2 = mtmp->nmon; 371. 	    if (pets_only && !mtmp->mtame) continue; 372. 	    if (((monnear(mtmp, u.ux, u.uy) && levl_follower(mtmp)) || 373. 		/* the wiz will level t-port from anywhere to chase 374. 		   the amulet; if you don't have it, will chase you 375. 		   only if in range. -3. */ 376.  			(u.uhave.amulet && mtmp->iswiz))  377.  			&& !mtmp->msleep && mtmp->mcanmove) { 378. 		stay_behind = FALSE; 379. 		if (mtmp->mtame && mtmp->meating) { 380. 			if (canseemon(mtmp)) 381. 			    pline("%s is still eating.", Monnam(mtmp)); 382. 			stay_behind = TRUE; 383. 		} else if (mon_has_amulet(mtmp)) { 384. 			if (canseemon(mtmp)) 385. 			    pline("%s seems very disoriented for a moment.",  386.  				Monnam(mtmp)); 387. 			stay_behind = TRUE; 388. 		}  389.  		if (stay_behind) { 390. 			if (mtmp->mleashed) { 391. 				pline("%s leash suddenly comes loose.",  392.  					humanoid(mtmp->data)  393.  					    ? (mtmp->female ? "Her" : "His") 394.  					    : "Its"); 395. 				m_unleash(mtmp); 396. 			}  397.  			continue; 398. 		}  399.  		if (mtmp->isshk) 400. 			set_residency(mtmp, TRUE); 401.  402.  		if (mtmp->wormno) { 403. 		    register int cnt; 404. 		    /* NOTE: worm is truncated to # segs = max wormno size */ 405. 		    cnt = count_wsegs(mtmp); 406. 		    num_segs = min(cnt, MAX_NUM_WORMS - 1); 407. 		    wormgone(mtmp); 408. 		} else num_segs = 0; 409.  410.  		/* set minvent's obj->no_charge to 0 */ 411. 		for(obj = mtmp->minvent; obj; obj = obj->nobj) { 412. 		    if (Has_contents(obj)) 413. 			picked_container(obj);	/* does the right thing */ 414. 		    obj->no_charge = 0; 415. 		}  416.   417.  		relmon(mtmp); 418. 		newsym(mtmp->mx,mtmp->my); 419. 		mtmp->mx = mtmp->my = 0; /* avoid mnexto/MON_AT problem */ 420. 		mtmp->wormno = num_segs; 421. 		mtmp->nmon = mydogs; 422. 		mydogs = mtmp; 423. 	    } else if (mtmp->iswiz) { 424. 		/* we want to be able to find him when his next resurrection 425. 		   chance comes up, but have him resume his present location 426. 		   if player returns to this level before that time */ 427. 		migrate_to_level(mtmp, ledger_no(&u.uz),  428.  				 MIGR_EXACT_XY, (coord *)0); 429. 	    } else if (mtmp->mleashed) { 430. 		/* this can happen if your quest leader ejects you from the 431. 		   "home" level while a leashed pet isn't next to you */ 432. 		pline("%s leash goes slack.", s_suffix(Monnam(mtmp))); 433. 		m_unleash(mtmp); 434. 	    }  435.  	}  436.  }  437.   438.  #endif /* OVL2 */ 439. #ifdef OVLB 440.  441.  void 442. migrate_to_level(mtmp, tolev, xyloc, cc) 443. 	register struct monst *mtmp; 444. 	xchar tolev;	/* destination level */ 445. 	xchar xyloc;	/* MIGR_xxx destination xy location: */ 446. 	coord *cc;	/* optional destination coordinates */ 447. {  448.  	register struct obj *obj; 449. 	d_level new_lev; 450. 	xchar xyflags; 451. 	int num_segs = 0;	/* count of worm segments */ 452.  453.  	if (mtmp->isshk) 454. 	    set_residency(mtmp, TRUE); 455.  456.  	if (mtmp->wormno) { 457. 	    register int cnt; 458. 	  /* **** NOTE: worm is truncated to # segs = max wormno size **** */ 459. 	    cnt = count_wsegs(mtmp); 460. 	    num_segs = min(cnt, MAX_NUM_WORMS - 1); 461. 	    wormgone(mtmp); 462. 	}  463.   464.  	/* set minvent's obj->no_charge to 0 */ 465. 	for(obj = mtmp->minvent; obj; obj = obj->nobj) { 466. 	    if (Has_contents(obj)) 467. 		picked_container(obj);	/* does the right thing */ 468. 	    obj->no_charge = 0; 469. 	}  470.   471.  	relmon(mtmp); 472. 	mtmp->nmon = migrating_mons; 473. 	migrating_mons = mtmp; 474. 	if (mtmp->mleashed)  { 475. 		m_unleash(mtmp); 476. 		mtmp->mtame--; 477. 		pline_The("leash comes off!"); 478. 	}  479.  	newsym(mtmp->mx,mtmp->my); 480.  481.  	new_lev.dnum = ledger_to_dnum((xchar)tolev); 482. 	new_lev.dlevel = ledger_to_dlev((xchar)tolev); 483. 	/* overload mtmp->[mx,my], mtmp->[mux,muy], and mtmp->mtrack[] as */ 484. 	/* destination codes (setup flag bits before altering mx or my) */ 485. 	xyflags = (depth(&new_lev) < depth(&u.uz));	/* 1 => up */ 486. 	if (In_W_tower(mtmp->mx, mtmp->my, &u.uz)) xyflags |= 2; 487. 	mtmp->wormno = num_segs; 488. 	mtmp->mlstmv = monstermoves; 489. 	mtmp->mtrack[1].x = cc ? cc->x : mtmp->mx; 490. 	mtmp->mtrack[1].y = cc ? cc->y : mtmp->my; 491. 	mtmp->mtrack[0].x = xyloc; 492. 	mtmp->mtrack[0].y = xyflags; 493. 	mtmp->mux = new_lev.dnum; 494. 	mtmp->muy = new_lev.dlevel; 495. 	mtmp->mx = mtmp->my = 0;	/* this implies migration */ 496. }  497.   498.  #endif /* OVLB */ 499. #ifdef OVL1 500.  501.  /* return quality of food; the lower the better */ 502. /* fungi will eat even tainted food */ 503. int 504. dogfood(mon,obj) 505. struct monst *mon; 506. register struct obj *obj; 507. {  508.  	boolean carni = carnivorous(mon->data); 509. 	boolean herbi = herbivorous(mon->data); 510. 	struct permonst *fptr = &mons[obj->corpsenm]; 511.  512.  	if (is_quest_artifact(obj) || obj_resists(obj, 0, 95)) 513. 	    return (obj->cursed ? TABU : APPORT); 514.  515.  	switch(obj->oclass) { 516. 	case FOOD_CLASS: 517. 	    if (obj->otyp == CORPSE &&  518.  		((obj->corpsenm == PM_COCKATRICE && !resists_ston(mon)) 519. 		 || is_rider(fptr))) 520. 		    return TABU; 521.  522.  	    if (!carni && !herbi) 523. 		    return (obj->cursed ? UNDEF : APPORT); 524.  525.  	    switch (obj->otyp) { 526. 		case TRIPE_RATION: 527. 		    return (carni ? DOGFOOD : MANFOOD); 528. 		case EGG: 529. 		    if (obj->corpsenm == PM_COCKATRICE && !resists_ston(mon)) 530. 			return POISON; 531. 		    return (carni ? CADAVER : MANFOOD); 532. 		case CORPSE: 533. 		   if ((peek_at_iced_corpse_age(obj)+50 <= monstermoves 534. 					    && obj->corpsenm != PM_LIZARD 535. 					    && mon->data->mlet != S_FUNGUS) ||  536.  			(acidic(&mons[obj->corpsenm]) && !resists_acid(mon)) ||  537.  			(poisonous(&mons[obj->corpsenm]) && 538. 						!resists_poison(mon))) 539. 			return POISON; 540. 		    else if (fptr->mlet == S_FUNGUS) 541. 			return (herbi ? CADAVER : MANFOOD); 542. 		    else if (is_meaty(fptr)) 543. 		        return (carni ? CADAVER : MANFOOD); 544. 		    else return (carni ? ACCFOOD : MANFOOD); 545. 		case CLOVE_OF_GARLIC: 546. 		    return (is_undead(mon->data) ? TABU :  547.  			    (herbi ? ACCFOOD : MANFOOD)); 548. 		case TIN: 549. 		    return (metallivorous(mon->data) ? ACCFOOD : MANFOOD); 550. 		case APPLE: 551. 		case CARROT: 552. 		    return (herbi ? DOGFOOD : MANFOOD); 553. 		case BANANA: 554. 		    return ((mon->data->mlet == S_YETI) ? DOGFOOD :  555.  			    (herbi ? ACCFOOD : MANFOOD)); 556. 		default: 557. 		    return (obj->otyp > SLIME_MOLD ?  558.  			    (carni ? ACCFOOD : MANFOOD) : 559.  			    (herbi ? ACCFOOD : MANFOOD)); 560. 	    }  561.  	default: 562. 	    if (hates_silver(mon->data) &&  563.  		objects[obj->otyp].oc_material == SILVER) 564. 		return(TABU); 565. 	    if (mon->data == &mons[PM_GELATINOUS_CUBE] && is_organic(obj)) 566. 		return(ACCFOOD); 567. 	    if (metallivorous(mon->data) && is_metallic(obj)) 568. 		/* Ferrous based metals are preferred. */ 569.  		return(objects[obj->otyp].oc_material == IRON ? DOGFOOD :  570.  		       ACCFOOD); 571. 	    if(!obj->cursed && obj->oclass != BALL_CLASS &&  572.  						obj->oclass != CHAIN_CLASS) 573. 		return(APPORT); 574. 	    /* fall into next case */ 575. 	case ROCK_CLASS: 576. 	    return(UNDEF); 577. 	}  578.  }  579.   580.  #endif /* OVL1 */ 581. #ifdef OVLB 582.  583.  struct monst * 584. tamedog(mtmp, obj) 585. register struct monst *mtmp; 586. register struct obj *obj; 587. {  588.  	register struct monst *mtmp2; 589.  590.  	/* The Wiz, Medusa and the quest nemeses aren't even made peaceful. */ 591.  	if (mtmp->iswiz || mtmp->data == &mons[PM_MEDUSA]  592.  				|| (mtmp->data->mflags3 & M3_WANTSARTI)) 593. 		return((struct monst *)0); 594.  595.  	/* worst case, at least it'll be peaceful. */ 596.  	mtmp->mpeaceful = 1; 597. 	set_malign(mtmp); 598. 	if(flags.moonphase == FULL_MOON && night && rn2(6) && obj  599.  						&& mtmp->data->mlet == S_DOG) 600. 		return((struct monst *)0); 601.  602.  	/* If we cannot tame it, at least it's no longer afraid. */ 603.  	mtmp->mflee = 0; 604. 	mtmp->mfleetim = 0; 605.  606.  	/* make grabber let go now, whether it becomes tame or not */ 607. 	if (mtmp == u.ustuck) { 608. 	    if (u.uswallow) 609. 		expels(mtmp, mtmp->data, TRUE); 610. 	    else if (!(Upolyd && sticks(uasmon))) 611. 		unstuck(mtmp); 612. 	}  613.   614.  	/* feeding it treats makes it tamer */ 615. 	if (mtmp->mtame && obj) { 616. 	    int tasty; 617.  618.  	    if (mtmp->mcanmove && !mtmp->mconf && !mtmp->meating &&  619.  		((tasty = dogfood(mtmp, obj)) == DOGFOOD || 620. 		 (tasty <= ACCFOOD && EDOG(mtmp)->hungrytime <= moves))) { 621. 		/* pet will "catch" and eat this thrown food */ 622. 		if (canseemon(mtmp)) { 623. 		    boolean big_corpse = (obj->otyp == CORPSE &&  624.  					  obj->corpsenm >= LOW_PM &&  625.  				mons[obj->corpsenm].msize > mtmp->data->msize); 626. 		    pline("%s catches %s%s",  627.  			  Monnam(mtmp), the(xname(obj)),  628.  			  !big_corpse ? "." : ", or vice versa!"); 629. 		} else if (cansee(mtmp->mx,mtmp->my)) 630. 		    pline("%s stops.", The(xname(obj))); 631. 		/* dog_eat expects a floor object */ 632. 		place_object(obj, mtmp->mx, mtmp->my); 633. 		(void) dog_eat(mtmp, obj, mtmp->mx, mtmp->my, FALSE); 634. 		/* eating might have killed it, but that doesn't matter here; 635. 		   a non-null result suppresses "miss" message for thrown 636. 		   food and also implies that the object has been deleted */ 637. 		return mtmp; 638. 	    } else 639. 		return (struct monst *)0; 640. 	}  641.   642.  	if (mtmp->mtame || !mtmp->mcanmove ||  643.  	    /* monsters with conflicting structures cannot be tamed */  644.  	    mtmp->isshk || mtmp->isgd || mtmp->ispriest || mtmp->isminion ||  645.  	    is_covetous(mtmp->data) || is_human(mtmp->data) ||  646.  	    (is_demon(mtmp->data) && !is_demon(uasmon)) ||  647.  	    (obj && dogfood(mtmp, obj) >= MANFOOD)) return (struct monst *)0; 648.  649.  	/* make a new monster which has the pet extension */ 650. 	mtmp2 = newmonst(sizeof(struct edog) + mtmp->mnamelth); 651. 	*mtmp2 = *mtmp; 652. 	mtmp2->mxlth = sizeof(struct edog); 653. 	if (mtmp->mnamelth) Strcpy(NAME(mtmp2), NAME(mtmp)); 654. 	initedog(mtmp2); 655. 	replmon(mtmp, mtmp2); 656. 	/* `mtmp' is now obsolete */ 657.  658.  	if (obj) {		/* thrown food */ 659. 	    /* defer eating until the edog extension has been set up */ 660. 	    place_object(obj, mtmp2->mx, mtmp2->my);	/* put on floor */ 661. 	    /* devour the food (might grow into larger, genocided monster) */ 662. 	    if (dog_eat(mtmp2, obj, mtmp2->mx, mtmp2->my, TRUE) == 2) 663. 		return mtmp2;		/* oops, it died... */ 664.  	    /* `obj' is now obsolete */ 665. 	}  666.   667.  	newsym(mtmp2->mx, mtmp2->my); 668. 	if (attacktype(mtmp2->data, AT_WEAP)) { 669. 		mtmp2->weapon_check = NEED_HTH_WEAPON; 670. 		(void) mon_wield_item(mtmp2); 671. 	}  672.  	return(mtmp2); 673. }  674.   675.  void 676. abuse_dog(mtmp) 677. struct monst *mtmp; 678. {  679.  	if (!mtmp->mtame) return; 680.  681.  	if (Aggravate_monster || Conflict) mtmp->mtame /=2; 682. 	else mtmp->mtame--; 683.  684.  	if (mtmp->mtame && rn2(mtmp->mtame)) yelp(mtmp); 685. 	else growl(mtmp);	/* give them a moment's worry */ 686.  687.  	if (!mtmp->mtame) newsym(mtmp->mx, mtmp->my); 688. }  689.   690.  #endif /* OVLB */ 691.  692.  /*dog.c*/