Source:NetHack 3.1.0/dog.c
Jump to navigation
Jump to search
Below is the full text to dog.c from the source code of NetHack 3.1.0.
Warning! This is the source code from an old release. For newer releases, 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.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*/