1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64: #include <sys/cdefs.h>
65: #ifndef lint
66: __RCSID("$NetBSD: hack.mon.c,v 1.6 2003/04/02 18:36:38 jsm Exp $");
67: #endif
68:
69: #include <stdlib.h>
70: #include "hack.h"
71: #include "extern.h"
72: #include "hack.mfndpos.h"
73:
74: #ifndef NULL
75: #define NULL (char *) 0
76: #endif
77:
78: int warnlevel;
79: long lastwarntime;
80: int lastwarnlev;
81: const char *const warnings[] = {
82: "white", "pink", "red", "ruby", "purple", "black"
83: };
84:
85: void
86: movemon()
87: {
88: struct monst *mtmp;
89: int fr;
90:
91: warnlevel = 0;
92:
93: while (1) {
94:
95:
96:
97:
98:
99:
100: for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
101: if (mtmp->mlstmv < moves)
102: goto next_mon;
103:
104: break;
105:
106: next_mon:
107: mtmp->mlstmv = moves;
108:
109:
110: {
111: boolean inpool, iseel;
112:
113: inpool = (levl[mtmp->mx][mtmp->my].typ == POOL);
114: iseel = (mtmp->data->mlet == ';');
115: if (inpool && !iseel) {
116: if (cansee(mtmp->mx, mtmp->my))
117: pline("%s drowns.", Monnam(mtmp));
118: mondead(mtmp);
119: continue;
120: }
121:
122: if (iseel && !inpool) {
123: if (mtmp->mhp > 1)
124: mtmp->mhp--;
125: mtmp->mflee = 1;
126: mtmp->mfleetim += 2;
127: }
128: }
129: if (mtmp->mblinded && !--mtmp->mblinded)
130: mtmp->mcansee = 1;
131: if (mtmp->mfleetim && !--mtmp->mfleetim)
132: mtmp->mflee = 0;
133: if (mtmp->mimic)
134: continue;
135: if (mtmp->mspeed != MSLOW || !(moves % 2)) {
136:
137: fr = -1;
138: if (Conflict && cansee(mtmp->mx, mtmp->my)
139: && (fr = fightm(mtmp)) == 2)
140: continue;
141: if (fr < 0 && dochugw(mtmp))
142: continue;
143: }
144: if (mtmp->mspeed == MFAST && dochugw(mtmp))
145: continue;
146: }
147:
148: warnlevel -= u.ulevel;
149: if (warnlevel >= SIZE(warnings))
150: warnlevel = SIZE(warnings) - 1;
151: if (warnlevel >= 0)
152: if (warnlevel > lastwarnlev || moves > lastwarntime + 5) {
153: const char *rr;
154: switch (Warning & (LEFT_RING | RIGHT_RING)) {
155: case LEFT_RING:
156: rr = "Your left ring glows";
157: break;
158: case RIGHT_RING:
159: rr = "Your right ring glows";
160: break;
161: case LEFT_RING | RIGHT_RING:
162: rr = "Both your rings glow";
163: break;
164: default:
165: rr = "Your fingertips glow";
166: break;
167: }
168: pline("%s %s!", rr, warnings[warnlevel]);
169: lastwarntime = moves;
170: lastwarnlev = warnlevel;
171: }
172: dmonsfree();
173: }
174:
175: void
176: justswld(mtmp, name)
177: struct monst *mtmp;
178: const char *name;
179: {
180:
181: mtmp->mx = u.ux;
182: mtmp->my = u.uy;
183: u.ustuck = mtmp;
184: pmon(mtmp);
185: kludge("%s swallows you!", name);
186: more();
187: seeoff(1);
188: u.uswallow = 1;
189: u.uswldtim = 0;
190: swallowed();
191: }
192:
193: void
194: youswld(mtmp, dam, die, name)
195: struct monst *mtmp;
196: int dam, die;
197: const char *name;
198: {
199: if (mtmp != u.ustuck)
200: return;
201: kludge("%s digests you!", name);
202: u.uhp -= dam;
203: if ((int)u.uswldtim++ >= die) {
204: pline("It totally digests you!");
205: u.uhp = -1;
206: }
207: if (u.uhp < 1)
208: done_in_by(mtmp);
209: #if 0
210: flags.botlx = 1;
211: #endif
212: }
213:
214: int
215: dochugw(mtmp)
216: struct monst *mtmp;
217: {
218: int x = mtmp->mx;
219: int y = mtmp->my;
220: int d = dochug(mtmp);
221: int dd;
222: if (!d)
223: if (Warning)
224: if (!mtmp->mpeaceful)
225: if (mtmp->data->mlevel > warnlevel)
226: if ((dd = dist(mtmp->mx, mtmp->my)) < dist(x, y))
227: if (dd < 100)
228: if (!canseemon(mtmp))
229: warnlevel = mtmp->data->mlevel;
230: return (d);
231: }
232:
233:
234: int
235: dochug(mtmp)
236: struct monst *mtmp;
237: {
238: const struct permonst *mdat;
239: int tmp = 0, nearby, scared;
240:
241: if (mtmp->cham && !rn2(6))
242: (void) newcham(mtmp, &mons[dlevel + 14 + rn2(CMNUM - 14 - dlevel)]);
243: mdat = mtmp->data;
244: if (mdat->mlevel < 0)
245: panic("bad monster %c (%d)", mdat->mlet, mdat->mlevel);
246:
247:
248: if ((!(moves % 20) || strchr(MREGEN, mdat->mlet)) &&
249: mtmp->mhp < mtmp->mhpmax)
250: mtmp->mhp++;
251:
252: if (mtmp->mfroz)
253: return (0);
254:
255: if (mtmp->msleep) {
256:
257:
258:
259: if (cansee(mtmp->mx, mtmp->my) &&
260: (!Stealth || (mdat->mlet == 'e' && rn2(10))) &&
261: (!strchr("NL", mdat->mlet) || !rn2(50)) &&
262: (Aggravate_monster || strchr("d1", mdat->mlet)
263: || (!rn2(7) && !mtmp->mimic)))
264: mtmp->msleep = 0;
265: else
266: return (0);
267: }
268:
269: wipe_engr_at(mtmp->mx, mtmp->my, 1);
270:
271:
272: if (mtmp->mconf && !rn2(50))
273: mtmp->mconf = 0;
274:
275:
276: if (mtmp->mflee && strchr("tNL", mdat->mlet) && !rn2(40)) {
277: rloc(mtmp);
278: return (0);
279: }
280: if (mdat->mmove < rnd(6))
281: return (0);
282:
283:
284: if (mtmp->mflee && !mtmp->mfleetim
285: && mtmp->mhp == mtmp->mhpmax && !rn2(25))
286: mtmp->mflee = 0;
287:
288: nearby = (dist(mtmp->mx, mtmp->my) < 3);
289: scared = (nearby && (sengr_at("Elbereth", u.ux, u.uy) ||
290: sobj_at(SCR_SCARE_MONSTER, u.ux, u.uy)));
291: if (scared && !mtmp->mflee) {
292: mtmp->mflee = 1;
293: mtmp->mfleetim = (rn2(7) ? rnd(10) : rnd(100));
294: }
295: if (!nearby ||
296: mtmp->mflee ||
297: mtmp->mconf ||
298: (mtmp->minvis && !rn2(3)) ||
299: (strchr("BIuy", mdat->mlet) && !rn2(4)) ||
300: (mdat->mlet == 'L' && !u.ugold && (mtmp->mgold || rn2(2))) ||
301: (!mtmp->mcansee && !rn2(4)) ||
302: mtmp->mpeaceful
303: ) {
304: tmp = m_move(mtmp, 0);
305: if (tmp == 2 || (tmp && mdat->mmove <= 12))
306: return (tmp == 2);
307: }
308: if (!strchr("Ea", mdat->mlet) && nearby &&
309: !mtmp->mpeaceful && u.uhp > 0 && !scared) {
310: if (mhitu(mtmp))
311: return (1);
312: }
313:
314: if (mdat->mmove - 12 > rnd(12))
315: tmp = m_move(mtmp, 1);
316: return (tmp == 2);
317: }
318:
319: int
320: m_move(struct monst *mtmp, int after)
321: {
322: struct monst *mtmp2;
323: int nx, ny, omx, omy, appr, nearer, cnt, i, j;
324: xchar gx, gy, nix, niy, chcnt;
325: schar chi;
326: boolean likegold = 0, likegems = 0, likeobjs = 0;
327: char msym = mtmp->data->mlet;
328: schar mmoved = 0;
329:
330: coord poss[9];
331: int info[9];
332:
333: if (mtmp->mfroz || mtmp->msleep)
334: return (0);
335: if (mtmp->mtrapped) {
336: i = mintrap(mtmp);
337: if (i == 2)
338: return (2);
339: if (i == 1)
340: return (0);
341: }
342: if (mtmp->mhide && o_at(mtmp->mx, mtmp->my) && rn2(10))
343: return (0);
344:
345: #ifndef NOWORM
346: if (mtmp->wormno)
347: goto not_special;
348: #endif
349:
350:
351: if (mtmp->mtame) {
352: return (dog_move(mtmp, after));
353: }
354:
355: if (mtmp->isshk) {
356: mmoved = shk_move(mtmp);
357: if (mmoved >= 0)
358: goto postmov;
359: mmoved = 0;
360: }
361:
362: if (mtmp->isgd) {
363: mmoved = gd_move();
364: goto postmov;
365: }
366:
367:
368:
369:
370: if ((msym == 't' && !rn2(5))
371: || (msym == '1' && (mtmp->mhp < 7 || (!xdnstair && !rn2(5))
372: || levl[u.ux][u.uy].typ == STAIRS))) {
373: if (mtmp->mhp < 7 || (msym == 't' && rn2(2)))
374: rloc(mtmp);
375: else
376: mnexto(mtmp);
377: mmoved = 1;
378: goto postmov;
379: }
380:
381: if (strchr("D1", msym))
382: inrange(mtmp);
383:
384: if (msym == 'U' && !mtmp->mcan && canseemon(mtmp) &&
385: mtmp->mcansee && rn2(5)) {
386: if (!Confusion)
387: pline("%s's gaze has confused you!", Monnam(mtmp));
388: else
389: pline("You are getting more and more confused.");
390: if (rn2(3))
391: mtmp->mcan = 1;
392: Confusion += d(3, 4);
393: }
394: not_special:
395: if (!mtmp->mflee && u.uswallow && u.ustuck != mtmp)
396: return (1);
397: appr = 1;
398: if (mtmp->mflee)
399: appr = -1;
400: if (mtmp->mconf || Invis || !mtmp->mcansee ||
401: (strchr("BIy", msym) && !rn2(3)))
402: appr = 0;
403: omx = mtmp->mx;
404: omy = mtmp->my;
405: gx = u.ux;
406: gy = u.uy;
407: if (msym == 'L' && appr == 1 && mtmp->mgold > u.ugold)
408: appr = -1;
409:
410:
411:
412:
413:
414: if (msym == '@' ||
415: ('a' <= msym && msym <= 'z')) {
416: coord *cp;
417: schar mroom;
418: mroom = inroom(omx, omy);
419: if (mroom < 0 || mroom != inroom(u.ux, u.uy)) {
420: cp = gettrack(omx, omy);
421: if (cp) {
422: gx = cp->x;
423: gy = cp->y;
424: }
425: }
426: }
427:
428: likegold = (strchr("LOD", msym) != NULL);
429: likegems = (strchr("ODu", msym) != NULL);
430: likeobjs = mtmp->mhide;
431: #define SRCHRADIUS 25
432: {
433: xchar mind = SRCHRADIUS;
434: int dd;
435: if (likegold) {
436: struct gold *gold;
437: for (gold = fgold; gold; gold = gold->ngold)
438: if ((dd = DIST(omx, omy, gold->gx, gold->gy)) < mind) {
439: mind = dd;
440: gx = gold->gx;
441: gy = gold->gy;
442: }
443: }
444: if (likegems || likeobjs) {
445: struct obj *otmp;
446: for (otmp = fobj; otmp; otmp = otmp->nobj)
447: if (likeobjs || otmp->olet == GEM_SYM)
448: if (msym != 'u' ||
449: objects[otmp->otyp].g_val != 0)
450: if ((dd = DIST(omx, omy, otmp->ox, otmp->oy)) < mind) {
451: mind = dd;
452: gx = otmp->ox;
453: gy = otmp->oy;
454: }
455: }
456: if (mind < SRCHRADIUS && appr == -1) {
457: if (dist(omx, omy) < 10) {
458: gx = u.ux;
459: gy = u.uy;
460: } else
461: appr = 1;
462: }
463: }
464: nix = omx;
465: niy = omy;
466: cnt = mfndpos(mtmp, poss, info,
467: msym == 'u' ? NOTONL :
468: (msym == '@' || msym == '1') ? (ALLOW_SSM | ALLOW_TRAPS) :
469: strchr(UNDEAD, msym) ? NOGARLIC : ALLOW_TRAPS);
470:
471: chcnt = 0;
472: chi = -1;
473: for (i = 0; i < cnt; i++) {
474: nx = poss[i].x;
475: ny = poss[i].y;
476: for (j = 0; j < MTSZ && j < cnt - 1; j++)
477: if (nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y)
478: if (rn2(4 * (cnt - j)))
479: goto nxti;
480: #ifdef STUPID
481:
482: {
483: int d1 = DIST(nx, ny, gx, gy);
484: int d2 = DIST(nix, niy, gx, gy);
485: nearer = (d1 < d2);
486: }
487: #else
488: nearer = (DIST(nx, ny, gx, gy) < DIST(nix, niy, gx, gy));
489: #endif
490: if ((appr == 1 && nearer) || (appr == -1 && !nearer) ||
491: !mmoved ||
492: (!appr && !rn2(++chcnt))) {
493: nix = nx;
494: niy = ny;
495: chi = i;
496: mmoved = 1;
497: }
498: nxti: ;
499: }
500: if (mmoved) {
501: if (info[chi] & ALLOW_M) {
502: mtmp2 = m_at(nix, niy);
503: if (hitmm(mtmp, mtmp2) == 1 && rn2(4) &&
504: hitmm(mtmp2, mtmp) == 2)
505: return (2);
506: return (0);
507: }
508: if (info[chi] & ALLOW_U) {
509: (void) hitu(mtmp, d(mtmp->data->damn, mtmp->data->damd) + 1);
510: return (0);
511: }
512: mtmp->mx = nix;
513: mtmp->my = niy;
514: for (j = MTSZ - 1; j > 0; j--)
515: mtmp->mtrack[j] = mtmp->mtrack[j - 1];
516: mtmp->mtrack[0].x = omx;
517: mtmp->mtrack[0].y = omy;
518: #ifndef NOWORM
519: