abstract
| - 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 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 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 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. }
|