Source:NetHack 3.0.0/dogmove.c
Revision as of 04:30, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 3.0.0/dogmove.c moved to Source:NetHack 3.0.0/dogmove.c: Robot: moved page)
Below is the full text to dogmove.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.0/dogmove.c#line123]], for example.
Warning! This is the source code from an old release. For the latest release, 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: @(#)dogmove.c 3.0 88/04/15 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. #include "hack.h" 6. 7. #include "mfndpos.h" 8. #include "edog.h" 9. 10. static const char nofetch[] = { BALL_SYM, CHAIN_SYM, ROCK_SYM, 0 }; 11. 12. /* return 0 (no move), 1 (move) or 2 (dead) */ 13. int 14. dog_move(mtmp, after) 15. register struct monst *mtmp; 16. register int after; 17. { 18. register int nx,ny,omx,omy,appr,nearer,j; 19. int udist,chi,i,whappr; 20. /* XLINT register struct permonst *mdat = mtmp->data; */ 21. register struct edog *edog = EDOG(mtmp); 22. struct obj *obj; 23. struct trap *trap; 24. xchar cnt,chcnt,nix,niy; 25. schar dogroom,uroom; 26. xchar gx,gy,gtyp,otyp; /* current goal */ 27. coord poss[9]; 28. long info[9]; 29. long allowflags; 30. #define GDIST(x,y) (dist2(x,y,gx,gy)) 31. #define DDIST(x,y) (dist2(x,y,omx,omy)) 32. 33. omx = mtmp->mx; 34. omy = mtmp->my; 35. whappr = (moves - EDOG(mtmp)->whistletime < 5); 36. if(moves > EDOG(mtmp)->hungrytime + 500) { 37. if(!carnivorous(mtmp->data) && !herbivorous(mtmp->data)) { 38. EDOG(mtmp)->hungrytime = moves + 500; 39. /* but not too high; it might polymorph */ 40. } else if (!mtmp->mconf) { 41. mtmp->mconf = 1; 42. mtmp->mhpmax /= 3; 43. if(mtmp->mhp > mtmp->mhpmax) 44. mtmp->mhp = mtmp->mhpmax; 45. if(cansee(omx,omy)) 46. pline("%s is confused from hunger.", Monnam(mtmp)); 47. else You("feel worried about %s.", mon_nam(mtmp)); 48. } else if(moves > EDOG(mtmp)->hungrytime + 750 || 49. mtmp->mhp < 1) { 50. #ifdef WALKIES 51. if(mtmp->mleashed) 52. Your("leash goes slack."); 53. #endif 54. if(cansee(omx,omy)) 55. pline("%s dies%s.", Monnam(mtmp), 56. (mtmp->mhp >= 1) ? "" : " from hunger"); 57. else 58. You("have a sad feeling for a moment, then it passes."); 59. mondied(mtmp); 60. return(2); 61. } 62. } 63. dogroom = inroom(omx,omy); 64. uroom = inroom(u.ux,u.uy); 65. udist = dist(omx,omy); 66. 67. /* maybe we tamed him while being swallowed --jgm */ 68. if(!udist) return(0); 69. 70. /* if we are carrying sth then we drop it (perhaps near @) */ 71. /* Note: if apport == 1 then our behaviour is independent of udist */ 72. if(mtmp->minvent){ 73. if(!rn2(udist) || !rn2((int) edog->apport)) 74. if(rn2(10) < edog->apport){ 75. if (cansee(omx,omy) && flags.verbose) 76. pline("%s drops %s.", Monnam(mtmp), 77. distant_name(mtmp->minvent, doname)); 78. relobj(mtmp, (int) mtmp->minvis); 79. if(edog->apport > 1) edog->apport--; 80. edog->dropdist = udist; /* hpscdi!jon */ 81. edog->droptime = moves; 82. } 83. } else { 84. if(obj = o_at(omx,omy)) if(!index(nofetch, obj->olet)){ 85. if((otyp = dogfood(mtmp, obj)) <= CADAVER){ 86. nix = omx; 87. niy = omy; 88. goto eatobj; 89. } 90. if(can_carry(mtmp, obj)) 91. if(rn2(20) < edog->apport+3) 92. if(rn2(udist) || !rn2((int) edog->apport)){ 93. if (cansee(omx, omy) && flags.verbose) 94. pline("%s picks up %s.", Monnam(mtmp), 95. distant_name(obj, doname)); 96. freeobj(obj); 97. unpobj(obj); 98. /* if(levl[omx][omy].scrsym == obj->olet) 99. newsym(omx,omy); */ 100. mpickobj(mtmp,obj); 101. } 102. } 103. } 104. 105. gtyp = UNDEF; /* no goal as yet */ 106. gx = gy = 0; /* suppress 'used before set' message */ 107. #ifdef WALKIES 108. /* If he's on a leash, he's not going anywhere. */ 109. if(mtmp->mleashed) { 110. 111. gtyp = APPORT; 112. gx = u.ux; 113. gy = u.uy; 114. } else 115. #endif 116. /* first we look for food, then objects */ 117. for(obj = fobj; obj; obj = obj->nobj) { 118. otyp = dogfood(mtmp, obj); 119. if(otyp > gtyp || otyp == UNDEF) continue; 120. if(inroom(obj->ox,obj->oy) != dogroom) continue; 121. if(otyp < MANFOOD && 122. (dogroom >= 0 || DDIST(obj->ox,obj->oy) < 10)) { 123. if(otyp < gtyp || (otyp == gtyp && 124. DDIST(obj->ox,obj->oy) < DDIST(gx,gy))){ 125. gx = obj->ox; 126. gy = obj->oy; 127. gtyp = otyp; 128. } 129. } else if(gtyp == UNDEF && dogroom >= 0 && 130. uroom == dogroom && 131. !mtmp->minvent && edog->apport > rn2(8) && 132. can_carry(mtmp,obj)){ 133. gx = obj->ox; 134. gy = obj->oy; 135. gtyp = APPORT; 136. } 137. } 138. 139. if(gtyp == UNDEF || 140. (gtyp != DOGFOOD && gtyp != APPORT && moves < EDOG(mtmp)->hungrytime)){ 141. if(dogroom < 0 || dogroom == uroom){ 142. gx = u.ux; 143. gy = u.uy; 144. } else { 145. int tmp = rooms[dogroom].fdoor; 146. cnt = rooms[dogroom].doorct; 147. 148. gx = gy = FAR; /* random, far away */ 149. while(cnt--){ 150. if(dist(gx,gy) > 151. dist(doors[tmp].x, doors[tmp].y)){ 152. gx = doors[tmp].x; 153. gy = doors[tmp].y; 154. } 155. tmp++; 156. } 157. /* here gx == FAR e.g. when dog is in a vault */ 158. if(gx == FAR || (gx == omx && gy == omy)){ 159. gx = u.ux; 160. gy = u.uy; 161. } 162. } 163. appr = (udist >= 9) ? 1 : (mtmp->mflee) ? -1 : 0; 164. if(after && udist <= 4 && gx == u.ux && gy == u.uy) 165. return(0); 166. if(udist > 1){ 167. if(!IS_ROOM(levl[u.ux][u.uy].typ) || !rn2(4) || 168. whappr || 169. (mtmp->minvent && rn2((int) edog->apport))) 170. appr = 1; 171. } 172. /* if you have dog food it'll follow you more closely */ 173. if(appr == 0){ 174. obj = invent; 175. while(obj){ 176. if(obj->otyp == TRIPE_RATION){ 177. appr = 1; 178. break; 179. } 180. obj = obj->nobj; 181. } 182. } 183. } else appr = 1; /* gtyp != UNDEF */ 184. if(mtmp->mconf) appr = 0; 185. 186. if(gx == u.ux && gy == u.uy && (dogroom != uroom || dogroom < 0)) { 187. register coord *cp; 188. cp = gettrack(omx,omy); 189. if(cp){ 190. gx = cp->x; 191. gy = cp->y; 192. } 193. } 194. 195. nix = omx; 196. niy = omy; 197. 198. allowflags = ALLOW_M | ALLOW_TRAPS | ALLOW_SSM | ALLOW_SANCT; 199. if (passes_walls(mtmp->data)) allowflags |= (ALLOW_ROCK|ALLOW_WALL); 200. if (tunnels(mtmp->data) && !needspick(mtmp->data)) 201. allowflags |= ALLOW_DIG; 202. cnt = mfndpos(mtmp, poss, info, allowflags); 203. if (allowflags & ALLOW_DIG) if(!mdig_tunnel(mtmp)) return(2); 204. chcnt = 0; 205. chi = -1; 206. for(i=0; i<cnt; i++){ 207. nx = poss[i].x; 208. ny = poss[i].y; 209. #ifdef WALKIES 210. /* if leashed, we drag him along. */ 211. if(dist(nx, ny) > 4 && mtmp->mleashed) continue; 212. #endif 213. if(info[i] & ALLOW_M) { 214. if(levl[nx][ny].mmask) { 215. register struct monst *mtmp2 = m_at(nx,ny); 216. 217. if(mtmp2->m_lev >= mtmp->m_lev+2 || 218. (mtmp2->data->mlet == S_COCKATRICE && 219. !(mtmp->data->mflags1 & M1_STON_RES))) 220. continue; 221. if(after) return(0); /* hit only once each move */ 222. 223. if(mattackm(mtmp, mtmp2) == 1 && rn2(4) && 224. mtmp2->mlstmv != moves && 225. mattackm(mtmp2, mtmp) == 2) return(2); 226. return(0); 227. } 228. } 229. 230. /* dog avoids traps */ 231. /* but perhaps we have to pass a trap in order to follow @ */ 232. if((info[i] & ALLOW_TRAPS) && (trap = t_at(nx,ny))){ 233. #ifdef WALKIES 234. if(!mtmp->mleashed) { 235. #endif 236. if(!trap->tseen && rn2(40)) continue; 237. if(rn2(10)) continue; 238. #ifdef WALKIES 239. } 240. # ifdef SOUNDS 241. else if(flags.soundok) 242. whimper(mtmp); 243. # endif 244. #endif 245. } 246. 247. /* dog eschews cursed objects */ 248. /* but likes dog food */ 249. obj = fobj; 250. if(levl[nx][ny].omask) 251. while(obj){ 252. if(obj->ox != nx || obj->oy != ny) 253. goto nextobj; 254. if(obj->cursed && !mtmp->mleashed) goto nxti; 255. if(obj->olet == FOOD_SYM && 256. (otyp = dogfood(mtmp, obj)) < MANFOOD && 257. (otyp < ACCFOOD || EDOG(mtmp)->hungrytime <= moves)){ 258. /* Note: our dog likes the food so much that he 259. might eat it even when it conceals a cursed object */ 260. nix = nx; 261. niy = ny; 262. chi = i; 263. eatobj: 264. mtmp->meating = 265. obj->quan * objects[obj->otyp].oc_delay; 266. if(EDOG(mtmp)->hungrytime < moves) 267. EDOG(mtmp)->hungrytime = moves; 268. EDOG(mtmp)->hungrytime += 269. 5*obj->quan * objects[obj->otyp].nutrition; 270. mtmp->mconf = 0; 271. if (mtmp->mtame < 20) mtmp->mtame++; 272. if(cansee(nix,niy)) 273. pline("%s eats %s.", Monnam(mtmp), doname(obj)); 274. /* perhaps this was a reward */ 275. if(otyp != CADAVER) 276. #ifdef LINT /* edog->apport += (unsigned) (200L/((long) edog->dropdist...*/ 277. edog->apport = 0; 278. #else 279. edog->apport += (unsigned)(200L/ 280. ((long)edog->dropdist+moves-edog->droptime)); 281. #endif 282. delobj(obj); 283. goto newdogpos; 284. } 285. nextobj: 286. obj = obj->nobj; 287. } 288. 289. for(j=0; j<MTSZ && j<cnt-1; j++) 290. if(nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y) 291. if(rn2(4*(cnt-j))) goto nxti; 292. 293. nearer = (GDIST(nx,ny) - GDIST(nix,niy)) * appr; 294. if((nearer == 0 && !rn2(++chcnt)) || nearer<0 || 295. (nearer > 0 && !whappr && 296. ((omx == nix && omy == niy && !rn2(3)) 297. || !rn2(12)) 298. )){ 299. nix = nx; 300. niy = ny; 301. if(nearer < 0) chcnt = 0; 302. chi = i; 303. } 304. nxti: ; 305. } 306. newdogpos: 307. if(nix != omx || niy != omy) { 308. if(info[chi] & ALLOW_U) { 309. #ifdef WALKIES 310. if(mtmp->mleashed) { /* play it safe */ 311. pline("%s breaks loose of %s leash!", 312. is_female(mtmp) ? "her" : 313. is_human(mtmp->data) ? "his" : "its", 314. Monnam(mtmp)); 315. m_unleash(mtmp); 316. } 317. #endif 318. (void) mattacku(mtmp); 319. return(0); 320. } 321. levl[omx][omy].mmask = 0; 322. levl[nix][niy].mmask = 1; 323. mtmp->mx = nix; 324. mtmp->my = niy; 325. for(j=MTSZ-1; j>0; j--) mtmp->mtrack[j] = mtmp->mtrack[j-1]; 326. mtmp->mtrack[0].x = omx; 327. mtmp->mtrack[0].y = omy; 328. } 329. #ifdef WALKIES 330. /* an incredible kluge, but the only way to keep pooch near 331. * after he spends time eating or in a trap, etc... 332. */ 333. else if(mtmp->mleashed && dist(omx, omy) > 4) { 334. coord cc; 335. 336. nx = sgn(omx - u.ux); 337. ny = sgn(omy - u.uy); 338. if(goodpos((cc.x = u.ux+nx), (cc.y = u.uy+ny))) goto dognext; 339. 340. i = xytod(nx, ny); 341. for(j = (i + 7)%8; j < (i + 1)%8; j++) { 342. 343. dtoxy(&cc, j); 344. if(goodpos(cc.x, cc.y)) goto dognext; 345. } 346. for(j = (i + 6)%8; j < (i + 2)%8; j++) { 347. 348. dtoxy(&cc, j); 349. if(goodpos(cc.x, cc.y)) goto dognext; 350. } 351. cc.x = mtmp->mx; 352. cc.y = mtmp->my; 353. dognext: 354. levl[mtmp->mx][mtmp->my].mmask = 0; 355. levl[cc.x][cc.y].mmask = 1; 356. mtmp->mx = cc.x; 357. mtmp->my = cc.y; 358. pmon(mtmp); 359. set_apparxy(mtmp); 360. } 361. #endif 362. 363. if(mintrap(mtmp) == 2) /* he died */ 364. return(2); 365. pmon(mtmp); 366. return(1); 367. }