]>
git.cameronkatri.com Git - bsdgames-darwin.git/blob - hack/hack.dog.c
2 * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985.
6 static char rcsid
[] = "$NetBSD: hack.dog.c,v 1.3 1995/03/23 08:29:59 cgd Exp $";
10 #include "hack.mfndpos.h"
11 extern struct monst
*makemon();
13 #include "def.mkroom.h"
15 struct permonst li_dog
=
16 { "little dog", 'd',2,18,6,1,6,sizeof(struct edog
) };
18 { "dog", 'd',4,16,5,1,6,sizeof(struct edog
) };
19 struct permonst la_dog
=
20 { "large dog", 'd',6,15,4,2,4,sizeof(struct edog
) };
24 register struct monst
*mtmp
= makemon(&li_dog
,u
.ux
,u
.uy
);
25 if(!mtmp
) return; /* dogs were genocided */
29 initedog(mtmp
) register struct monst
*mtmp
; {
30 mtmp
->mtame
= mtmp
->mpeaceful
= 1;
31 EDOG(mtmp
)->hungrytime
= 1000 + moves
;
32 EDOG(mtmp
)->eattime
= 0;
33 EDOG(mtmp
)->droptime
= 0;
34 EDOG(mtmp
)->dropdist
= 10000;
35 EDOG(mtmp
)->apport
= 10;
36 EDOG(mtmp
)->whistletime
= 0;
39 /* attach the monsters that went down (or up) together with @ */
40 struct monst
*mydogs
= 0;
41 struct monst
*fallen_down
= 0; /* monsters that fell through a trapdoor */
42 /* they will appear on the next level @ goes to, even if he goes up! */
45 register struct monst
*mtmp
;
52 while(mtmp
= fallen_down
){
53 fallen_down
= mtmp
->nmon
;
61 register struct monst
*mtmp
;
62 for(mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
)
63 if(dist(mtmp
->mx
,mtmp
->my
) < 3 && follower(mtmp
)
64 && !mtmp
->msleep
&& !mtmp
->mfroz
) {
69 keepdogs(); /* we destroyed the link, so use recursion */
70 return; /* (admittedly somewhat primitive) */
74 fall_down(mtmp
) register struct monst
*mtmp
; {
76 mtmp
->nmon
= fallen_down
;
82 /* return quality of food; the lower the better */
90 dogfood(obj
) register struct obj
*obj
; {
94 (obj
->otyp
== TRIPE_RATION
) ? DOGFOOD
:
95 (obj
->otyp
< CARROT
) ? ACCFOOD
:
96 (obj
->otyp
< CORPSE
) ? MANFOOD
:
97 (poisonous(obj
) || obj
->age
+ 50 <= moves
||
98 obj
->otyp
== DEAD_COCKATRICE
)
102 if(!obj
->cursed
) return(APPORT
);
103 /* fall into next case */
111 /* return 0 (no move), 1 (move) or 2 (dead) */
112 dog_move(mtmp
, after
) register struct monst
*mtmp
; {
113 register int nx
,ny
,omx
,omy
,appr
,nearer
,j
;
114 int udist
,chi
,i
,whappr
;
115 register struct monst
*mtmp2
;
116 register struct permonst
*mdat
= mtmp
->data
;
117 register struct edog
*edog
= EDOG(mtmp
);
120 xchar cnt
,chcnt
,nix
,niy
;
122 xchar gx
,gy
,gtyp
,otyp
; /* current goal */
125 #define GDIST(x,y) ((x-gx)*(x-gx) + (y-gy)*(y-gy))
126 #define DDIST(x,y) ((x-omx)*(x-omx) + (y-omy)*(y-omy))
128 if(moves
<= edog
->eattime
) return(0); /* dog is still eating */
131 whappr
= (moves
- EDOG(mtmp
)->whistletime
< 5);
132 if(moves
> edog
->hungrytime
+ 500 && !mtmp
->mconf
){
135 if(mtmp
->mhp
> mtmp
->mhpmax
)
136 mtmp
->mhp
= mtmp
->mhpmax
;
138 pline("%s is confused from hunger.", Monnam(mtmp
));
139 else pline("You feel worried about %s.", monnam(mtmp
));
141 if(moves
> edog
->hungrytime
+ 750 || mtmp
->mhp
< 1){
143 pline("%s dies from hunger.", Monnam(mtmp
));
145 pline("You have a sad feeling for a moment, then it passes.");
149 dogroom
= inroom(omx
,omy
);
150 uroom
= inroom(u
.ux
,u
.uy
);
151 udist
= dist(omx
,omy
);
153 /* maybe we tamed him while being swallowed --jgm */
154 if(!udist
) return(0);
156 /* if we are carrying sth then we drop it (perhaps near @) */
157 /* Note: if apport == 1 then our behaviour is independent of udist */
159 if(!rn2(udist
) || !rn2((int) edog
->apport
))
160 if(rn2(10) < edog
->apport
){
161 relobj(mtmp
, (int) mtmp
->minvis
);
162 if(edog
->apport
> 1) edog
->apport
--;
163 edog
->dropdist
= udist
; /* hpscdi!jon */
164 edog
->droptime
= moves
;
167 if(obj
= o_at(omx
,omy
)) if(!index("0_", obj
->olet
)){
168 if((otyp
= dogfood(obj
)) <= CADAVER
){
173 if(obj
->owt
< 10*mtmp
->data
->mlevel
)
174 if(rn2(20) < edog
->apport
+3)
175 if(rn2(udist
) || !rn2((int) edog
->apport
)){
178 /* if(levl[omx][omy].scrsym == obj->olet)
185 /* first we look for food */
186 gtyp
= UNDEF
; /* no goal as yet */
188 gx
= gy
= 0; /* suppress 'used before set' message */
190 for(obj
= fobj
; obj
; obj
= obj
->nobj
) {
192 if(otyp
> gtyp
|| otyp
== UNDEF
) continue;
193 if(inroom(obj
->ox
,obj
->oy
) != dogroom
) continue;
195 (dogroom
>= 0 || DDIST(obj
->ox
,obj
->oy
) < 10)) {
196 if(otyp
< gtyp
|| (otyp
== gtyp
&&
197 DDIST(obj
->ox
,obj
->oy
) < DDIST(gx
,gy
))){
203 if(gtyp
== UNDEF
&& dogroom
>= 0 &&
205 !mtmp
->minvent
&& edog
->apport
> rn2(8)){
212 (gtyp
!= DOGFOOD
&& gtyp
!= APPORT
&& moves
< edog
->hungrytime
)){
213 if(dogroom
< 0 || dogroom
== uroom
){
218 int tmp
= rooms
[dogroom
].fdoor
;
219 cnt
= rooms
[dogroom
].doorct
;
221 gx
= gy
= FAR
; /* random, far away */
224 dist(doors
[tmp
].x
, doors
[tmp
].y
)){
230 /* here gx == FAR e.g. when dog is in a vault */
231 if(gx
== FAR
|| (gx
== omx
&& gy
== omy
)){
237 appr
= (udist
>= 9) ? 1 : (mtmp
->mflee
) ? -1 : 0;
238 if(after
&& udist
<= 4 && gx
== u
.ux
&& gy
== u
.uy
)
241 if(!IS_ROOM(levl
[u
.ux
][u
.uy
].typ
) || !rn2(4) ||
243 (mtmp
->minvent
&& rn2((int) edog
->apport
)))
246 /* if you have dog food he'll follow you more closely */
250 if(obj
->otyp
== TRIPE_RATION
){
257 } else appr
= 1; /* gtyp != UNDEF */
258 if(mtmp
->mconf
) appr
= 0;
260 if(gx
== u
.ux
&& gy
== u
.uy
&& (dogroom
!= uroom
|| dogroom
< 0)){
261 extern coord
*gettrack();
263 cp
= gettrack(omx
,omy
);
272 cnt
= mfndpos(mtmp
,poss
,info
,ALLOW_M
| ALLOW_TRAPS
);
275 for(i
=0; i
<cnt
; i
++){
278 if(info
[i
] & ALLOW_M
){
280 if(mtmp2
->data
->mlevel
>= mdat
->mlevel
+2 ||
281 mtmp2
->data
->mlet
== 'c')
283 if(after
) return(0); /* hit only once each move */
285 if(hitmm(mtmp
, mtmp2
) == 1 && rn2(4) &&
286 mtmp2
->mlstmv
!= moves
&&
287 hitmm(mtmp2
,mtmp
) == 2) return(2);
291 /* dog avoids traps */
292 /* but perhaps we have to pass a trap in order to follow @ */
293 if((info
[i
] & ALLOW_TRAPS
) && (trap
= t_at(nx
,ny
))){
294 if(!trap
->tseen
&& rn2(40)) continue;
295 if(rn2(10)) continue;
298 /* dog eschewes cursed objects */
299 /* but likes dog food */
302 if(obj
->ox
!= nx
|| obj
->oy
!= ny
)
304 if(obj
->cursed
) goto nxti
;
305 if(obj
->olet
== FOOD_SYM
&&
306 (otyp
= dogfood(obj
)) < MANFOOD
&&
307 (otyp
< ACCFOOD
|| edog
->hungrytime
<= moves
)){
308 /* Note: our dog likes the food so much that he
309 might eat it even when it conceals a cursed object */
315 moves
+ obj
->quan
* objects
[obj
->otyp
].oc_delay
;
316 if(edog
->hungrytime
< moves
)
317 edog
->hungrytime
= moves
;
319 5*obj
->quan
* objects
[obj
->otyp
].nutrition
;
322 pline("%s ate %s.", Monnam(mtmp
), doname(obj
));
323 /* perhaps this was a reward */
325 edog
->apport
+= 200/(edog
->dropdist
+moves
-edog
->droptime
);
333 for(j
=0; j
<MTSZ
&& j
<cnt
-1; j
++)
334 if(nx
== mtmp
->mtrack
[j
].x
&& ny
== mtmp
->mtrack
[j
].y
)
335 if(rn2(4*(cnt
-j
))) goto nxti
;
337 /* Some stupid C compilers cannot compute the whole expression at once. */
338 nearer
= GDIST(nx
,ny
);
339 nearer
-= GDIST(nix
,niy
);
341 if((nearer
== 0 && !rn2(++chcnt
)) || nearer
<0 ||
342 (nearer
> 0 && !whappr
&&
343 ((omx
== nix
&& omy
== niy
&& !rn2(3))
348 if(nearer
< 0) chcnt
= 0;
354 if(nix
!= omx
|| niy
!= omy
){
355 if(info
[chi
] & ALLOW_U
){
356 (void) hitu(mtmp
, d(mdat
->damn
, mdat
->damd
)+1);
361 for(j
=MTSZ
-1; j
>0; j
--) mtmp
->mtrack
[j
] = mtmp
->mtrack
[j
-1];
362 mtmp
->mtrack
[0].x
= omx
;
363 mtmp
->mtrack
[0].y
= omy
;
365 if(mintrap(mtmp
) == 2) /* he died */
371 /* return roomnumber or -1 */
372 inroom(x
,y
) xchar x
,y
; {
374 register struct mkroom
*croom
= &rooms
[0];
375 while(croom
->hx
>= 0){
376 if(croom
->hx
>= x
-1 && croom
->lx
<= x
+1 &&
377 croom
->hy
>= y
-1 && croom
->ly
<= y
+1)
378 return(croom
- rooms
);
382 return(-1); /* not in room or on door */
386 register struct monst
*mtmp
;
387 register struct obj
*obj
;
389 register struct monst
*mtmp2
;
391 if(flags
.moonphase
== FULL_MOON
&& night() && rn2(6))
394 /* If we cannot tame him, at least he's no longer afraid. */
397 if(mtmp
->mtame
|| mtmp
->mfroz
||
401 mtmp
->isshk
|| mtmp
->isgd
|| index(" &@12", mtmp
->data
->mlet
))
402 return(0); /* no tame long worms? */
404 if(dogfood(obj
) >= MANFOOD
) return(0);
405 if(cansee(mtmp
->mx
,mtmp
->my
)){
406 pline("%s devours the %s.", Monnam(mtmp
),
407 objects
[obj
->otyp
].oc_name
);
409 obfree(obj
, (struct obj
*) 0);
411 mtmp2
= newmonst(sizeof(struct edog
) + mtmp
->mnamelth
);
413 mtmp2
->mxlth
= sizeof(struct edog
);
414 if(mtmp
->mnamelth
) (void) strcpy(NAME(mtmp2
), NAME(mtmp
));