Sort supported hardware by name.
[netbsd-mini2440.git] / games / hack / hack.dog.c
blobd46f6bfc7b06bf5637a2b8e1140ed762be016168
1 /* $NetBSD: hack.dog.c,v 1.9 2008/01/28 06:55:41 dholland Exp $ */
3 /*
4 * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
5 * Amsterdam
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met:
12 * - Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * - Neither the name of the Stichting Centrum voor Wiskunde en
20 * Informatica, nor the names of its contributors may be used to endorse or
21 * promote products derived from this software without specific prior
22 * written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39 * All rights reserved.
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. The name of the author may not be used to endorse or promote products
50 * derived from this software without specific prior written permission.
52 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
55 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64 #include <sys/cdefs.h>
65 #ifndef lint
66 __RCSID("$NetBSD: hack.dog.c,v 1.9 2008/01/28 06:55:41 dholland Exp $");
67 #endif /* not lint */
69 #include "hack.h"
70 #include "extern.h"
71 #include "hack.mfndpos.h"
72 #include "def.edog.h"
73 #include "def.mkroom.h"
75 const struct permonst li_dog =
76 {"little dog", 'd', 2, 18, 6, 1, 6, sizeof(struct edog)};
77 const struct permonst dog =
78 {"dog", 'd', 4, 16, 5, 1, 6, sizeof(struct edog)};
79 const struct permonst la_dog =
80 {"large dog", 'd', 6, 15, 4, 2, 4, sizeof(struct edog)};
83 void
84 makedog(void)
86 struct monst *mtmp = makemon(&li_dog, u.ux, u.uy);
87 if (!mtmp)
88 return; /* dogs were genocided */
89 initedog(mtmp);
92 void
93 initedog(struct monst *mtmp)
95 mtmp->mtame = mtmp->mpeaceful = 1;
96 EDOG(mtmp)->hungrytime = 1000 + moves;
97 EDOG(mtmp)->eattime = 0;
98 EDOG(mtmp)->droptime = 0;
99 EDOG(mtmp)->dropdist = 10000;
100 EDOG(mtmp)->apport = 10;
101 EDOG(mtmp)->whistletime = 0;
104 /* attach the monsters that went down (or up) together with @ */
105 struct monst *mydogs = 0;
106 struct monst *fallen_down = 0;/* monsters that fell through a trapdoor */
107 /* they will appear on the next level @ goes to, even if he goes up! */
109 void
110 losedogs(void)
112 struct monst *mtmp;
113 while ((mtmp = mydogs) != NULL) {
114 mydogs = mtmp->nmon;
115 mtmp->nmon = fmon;
116 fmon = mtmp;
117 mnexto(mtmp);
119 while ((mtmp = fallen_down) != NULL) {
120 fallen_down = mtmp->nmon;
121 mtmp->nmon = fmon;
122 fmon = mtmp;
123 rloc(mtmp);
127 void
128 keepdogs(void)
130 struct monst *mtmp;
131 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
132 if (dist(mtmp->mx, mtmp->my) < 3 && follower(mtmp)
133 && !mtmp->msleep && !mtmp->mfroz) {
134 relmon(mtmp);
135 mtmp->nmon = mydogs;
136 mydogs = mtmp;
137 unpmon(mtmp);
138 keepdogs(); /* we destroyed the link, so use
139 * recursion */
140 return; /* (admittedly somewhat primitive) */
144 void
145 fall_down(struct monst *mtmp)
147 relmon(mtmp);
148 mtmp->nmon = fallen_down;
149 fallen_down = mtmp;
150 unpmon(mtmp);
151 mtmp->mtame = 0;
154 /* return quality of food; the lower the better */
155 #define DOGFOOD 0
156 #define CADAVER 1
157 #define ACCFOOD 2
158 #define MANFOOD 3
159 #define APPORT 4
160 #define POISON 5
161 #define UNDEF 6
163 dogfood(struct obj *obj)
165 switch (obj->olet) {
166 case FOOD_SYM:
167 return (
168 (obj->otyp == TRIPE_RATION) ? DOGFOOD :
169 (obj->otyp < CARROT) ? ACCFOOD :
170 (obj->otyp < CORPSE) ? MANFOOD :
171 (poisonous(obj) || obj->age + 50 <= moves ||
172 obj->otyp == DEAD_COCKATRICE)
173 ? POISON : CADAVER
175 default:
176 if (!obj->cursed)
177 return (APPORT);
178 /* fall into next case */
179 case BALL_SYM:
180 case CHAIN_SYM:
181 case ROCK_SYM:
182 return (UNDEF);
186 /* return 0 (no move), 1 (move) or 2 (dead) */
188 dog_move(struct monst *mtmp, int after)
190 int nx, ny, omx, omy, appr, nearer, j;
191 int udist, chi = 0, i, whappr;
192 struct monst *mtmp2;
193 const struct permonst *mdat = mtmp->data;
194 struct edog *edog = EDOG(mtmp);
195 struct obj *obj;
196 struct trap *trap;
197 xchar cnt, chcnt, nix, niy;
198 schar dogroom, uroom;
199 xchar gx = 0, gy = 0, gtyp, otyp; /* current goal */
200 coord poss[9];
201 int info[9];
202 #define GDIST(x,y) ((x-gx)*(x-gx) + (y-gy)*(y-gy))
203 #define DDIST(x,y) ((x-omx)*(x-omx) + (y-omy)*(y-omy))
205 if (moves <= edog->eattime)
206 return (0); /* dog is still eating */
207 omx = mtmp->mx;
208 omy = mtmp->my;
209 whappr = (moves - EDOG(mtmp)->whistletime < 5);
210 if (moves > edog->hungrytime + 500 && !mtmp->mconf) {
211 mtmp->mconf = 1;
212 mtmp->mhpmax /= 3;
213 if (mtmp->mhp > mtmp->mhpmax)
214 mtmp->mhp = mtmp->mhpmax;
215 if (cansee(omx, omy))
216 pline("%s is confused from hunger.", Monnam(mtmp));
217 else
218 pline("You feel worried about %s.", monnam(mtmp));
219 } else if (moves > edog->hungrytime + 750 || mtmp->mhp < 1) {
220 if (cansee(omx, omy))
221 pline("%s dies from hunger.", Monnam(mtmp));
222 else
223 pline("You have a sad feeling for a moment, then it passes.");
224 mondied(mtmp);
225 return (2);
227 dogroom = inroom(omx, omy);
228 uroom = inroom(u.ux, u.uy);
229 udist = dist(omx, omy);
231 /* maybe we tamed him while being swallowed --jgm */
232 if (!udist)
233 return (0);
235 /* if we are carrying sth then we drop it (perhaps near @) */
236 /* Note: if apport == 1 then our behaviour is independent of udist */
237 if (mtmp->minvent) {
238 if (!rn2(udist) || !rn2((int) edog->apport))
239 if ((unsigned) rn2(10) < edog->apport) {
240 relobj(mtmp, (int) mtmp->minvis);
241 if (edog->apport > 1)
242 edog->apport--;
243 edog->dropdist = udist; /* hpscdi!jon */
244 edog->droptime = moves;
246 } else {
247 if ((obj = o_at(omx, omy)) != NULL)
248 if (!strchr("0_", obj->olet)) {
249 if ((otyp = dogfood(obj)) <= CADAVER) {
250 nix = omx;
251 niy = omy;
252 goto eatobj;
254 if (obj->owt < 10 * mtmp->data->mlevel)
255 if ((unsigned) rn2(20) < edog->apport + 3)
256 if (rn2(udist) || !rn2((int) edog->apport)) {
257 freeobj(obj);
258 unpobj(obj);
260 * if(levl[omx][omy].s
261 * crsym ==
262 * obj->olet)
263 * newsym(omx,omy);
265 mpickobj(mtmp, obj);
270 /* first we look for food */
271 gtyp = UNDEF; /* no goal as yet */
272 #ifdef LINT
273 gx = gy = 0; /* suppress 'used before set' message */
274 #endif /* LINT */
275 for (obj = fobj; obj; obj = obj->nobj) {
276 otyp = dogfood(obj);
277 if (otyp > gtyp || otyp == UNDEF)
278 continue;
279 if (inroom(obj->ox, obj->oy) != dogroom)
280 continue;
281 if (otyp < MANFOOD &&
282 (dogroom >= 0 || DDIST(obj->ox, obj->oy) < 10)) {
283 if (otyp < gtyp || (otyp == gtyp &&
284 DDIST(obj->ox, obj->oy) < DDIST(gx, gy))) {
285 gx = obj->ox;
286 gy = obj->oy;
287 gtyp = otyp;
289 } else if (gtyp == UNDEF && dogroom >= 0 &&
290 uroom == dogroom &&
291 !mtmp->minvent && edog->apport > (unsigned)rn2(8)) {
292 gx = obj->ox;
293 gy = obj->oy;
294 gtyp = APPORT;
297 if (gtyp == UNDEF ||
298 (gtyp != DOGFOOD && gtyp != APPORT && moves < edog->hungrytime)) {
299 if (dogroom < 0 || dogroom == uroom) {
300 gx = u.ux;
301 gy = u.uy;
302 #ifndef QUEST
303 } else {
304 int tmp = rooms[dogroom].fdoor;
305 cnt = rooms[dogroom].doorct;
307 gx = gy = FAR; /* random, far away */
308 while (cnt--) {
309 if (dist(gx, gy) >
310 dist(doors[tmp].x, doors[tmp].y)) {
311 gx = doors[tmp].x;
312 gy = doors[tmp].y;
314 tmp++;
316 /* here gx == FAR e.g. when dog is in a vault */
317 if (gx == FAR || (gx == omx && gy == omy)) {
318 gx = u.ux;
319 gy = u.uy;
321 #endif /* QUEST */
323 appr = (udist >= 9) ? 1 : (mtmp->mflee) ? -1 : 0;
324 if (after && udist <= 4 && gx == u.ux && gy == u.uy)
325 return (0);
326 if (udist > 1) {
327 if (!IS_ROOM(levl[u.ux][u.uy].typ) || !rn2(4) ||
328 whappr ||
329 (mtmp->minvent && rn2((int) edog->apport)))
330 appr = 1;
332 /* if you have dog food he'll follow you more closely */
333 if (appr == 0) {
334 obj = invent;
335 while (obj) {
336 if (obj->otyp == TRIPE_RATION) {
337 appr = 1;
338 break;
340 obj = obj->nobj;
343 } else
344 appr = 1; /* gtyp != UNDEF */
345 if (mtmp->mconf)
346 appr = 0;
348 if (gx == u.ux && gy == u.uy && (dogroom != uroom || dogroom < 0)) {
349 coord *cp;
350 cp = gettrack(omx, omy);
351 if (cp) {
352 gx = cp->x;
353 gy = cp->y;
356 nix = omx;
357 niy = omy;
358 cnt = mfndpos(mtmp, poss, info, ALLOW_M | ALLOW_TRAPS);
359 chcnt = 0;
360 chi = -1;
361 for (i = 0; i < cnt; i++) {
362 nx = poss[i].x;
363 ny = poss[i].y;
364 if (info[i] & ALLOW_M) {
365 mtmp2 = m_at(nx, ny);
366 if (mtmp2 == NULL)
367 panic("error in dog_move");
368 if (mtmp2->data->mlevel >= mdat->mlevel + 2 ||
369 mtmp2->data->mlet == 'c')
370 continue;
371 if (after)
372 return (0); /* hit only once each move */
374 if (hitmm(mtmp, mtmp2) == 1 && rn2(4) &&
375 mtmp2->mlstmv != moves &&
376 hitmm(mtmp2, mtmp) == 2)
377 return (2);
378 return (0);
380 /* dog avoids traps */
381 /* but perhaps we have to pass a trap in order to follow @ */
382 if ((info[i] & ALLOW_TRAPS) && (trap = t_at(nx, ny))) {
383 if (!trap->tseen && rn2(40))
384 continue;
385 if (rn2(10))
386 continue;
388 /* dog eschewes cursed objects */
389 /* but likes dog food */
390 obj = fobj;
391 while (obj) {
392 if (obj->ox != nx || obj->oy != ny)
393 goto nextobj;
394 if (obj->cursed)
395 goto nxti;
396 if (obj->olet == FOOD_SYM &&
397 (otyp = dogfood(obj)) < MANFOOD &&
398 (otyp < ACCFOOD || edog->hungrytime <= moves)) {
400 * Note: our dog likes the food so much that
401 * he might eat it even when it conceals a
402 * cursed object
404 nix = nx;
405 niy = ny;
406 chi = i;
407 eatobj:
408 edog->eattime =
409 moves + obj->quan * objects[obj->otyp].oc_delay;
410 if (edog->hungrytime < moves)
411 edog->hungrytime = moves;
412 edog->hungrytime +=
413 5 * obj->quan * objects[obj->otyp].nutrition;
414 mtmp->mconf = 0;
415 if (cansee(nix, niy))
416 pline("%s ate %s.", Monnam(mtmp), doname(obj));
417 /* perhaps this was a reward */
418 if (otyp != CADAVER)
419 edog->apport += 200 / (edog->dropdist + moves - edog->droptime);
420 delobj(obj);
421 goto newdogpos;
423 nextobj:
424 obj = obj->nobj;
427 for (j = 0; j < MTSZ && j < cnt - 1; j++)
428 if (nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y)
429 if (rn2(4 * (cnt - j)))
430 goto nxti;
433 * Some stupid C compilers cannot compute the whole
434 * expression at once.
436 nearer = GDIST(nx, ny);
437 nearer -= GDIST(nix, niy);
438 nearer *= appr;
439 if ((nearer == 0 && !rn2(++chcnt)) || nearer < 0 ||
440 (nearer > 0 && !whappr &&
441 ((omx == nix && omy == niy && !rn2(3))
442 || !rn2(12))
443 )) {
444 nix = nx;
445 niy = ny;
446 if (nearer < 0)
447 chcnt = 0;
448 chi = i;
450 nxti: ;
452 newdogpos:
453 if (nix != omx || niy != omy) {
454 if (info[chi] & ALLOW_U) {
455 (void) hitu(mtmp, d(mdat->damn, mdat->damd) + 1);
456 return (0);
458 mtmp->mx = nix;
459 mtmp->my = niy;
460 for (j = MTSZ - 1; j > 0; j--)
461 mtmp->mtrack[j] = mtmp->mtrack[j - 1];
462 mtmp->mtrack[0].x = omx;
463 mtmp->mtrack[0].y = omy;
465 if (mintrap(mtmp) == 2) /* he died */
466 return (2);
467 pmon(mtmp);
468 return (1);
471 /* return roomnumber or -1 */
473 inroom(xchar x, xchar y)
475 #ifndef QUEST
476 struct mkroom *croom = &rooms[0];
477 while (croom->hx >= 0) {
478 if (croom->hx >= x - 1 && croom->lx <= x + 1 &&
479 croom->hy >= y - 1 && croom->ly <= y + 1)
480 return (croom - rooms);
481 croom++;
483 #endif /* QUEST */
484 return (-1); /* not in room or on door */
488 tamedog(struct monst *mtmp, struct obj *obj)
490 struct monst *mtmp2;
492 if (flags.moonphase == FULL_MOON && night() && rn2(6))
493 return (0);
495 /* If we cannot tame him, at least he's no longer afraid. */
496 mtmp->mflee = 0;
497 mtmp->mfleetim = 0;
498 if (mtmp->mtame || mtmp->mfroz ||
499 #ifndef NOWORM
500 mtmp->wormno ||
501 #endif /* NOWORM */
502 mtmp->isshk || mtmp->isgd || strchr(" &@12", mtmp->data->mlet))
503 return (0); /* no tame long worms? */
504 if (obj) {
505 if (dogfood(obj) >= MANFOOD)
506 return (0);
507 if (cansee(mtmp->mx, mtmp->my)) {
508 pline("%s devours the %s.", Monnam(mtmp),
509 objects[obj->otyp].oc_name);
511 obfree(obj, (struct obj *) 0);
513 mtmp2 = newmonst(sizeof(struct edog) + mtmp->mnamelth);
514 *mtmp2 = *mtmp;
515 mtmp2->mxlth = sizeof(struct edog);
516 if (mtmp->mnamelth)
517 (void) strcpy(NAME(mtmp2), NAME(mtmp));
518 initedog(mtmp2);
519 replmon(mtmp, mtmp2);
520 return (1);