PropertyValue
rdfs:label
  • Source:NetHack 3.1.0/dog.c
rdfs:comment
  • 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
dcterms:subject
dbkwik:nethack/property/wikiPageUsesTemplate
abstract
  • 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*/