option parsing buffer overflow vulnerability
[aNetHack.git] / src / muse.c
blobb0a843d7d61cef1589a376993945c9e053449596
1 /* NetHack 3.6 muse.c $NHDT-Date: 1457254910 2016/03/06 09:01:50 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.72 $ */
2 /* Copyright (C) 1990 by Ken Arromdee */
3 /* NetHack may be freely redistributed. See license for details. */
5 /*
6 * Monster item usage routines.
7 */
9 #include "hack.h"
11 extern const int monstr[];
13 boolean m_using = FALSE;
15 /* Let monsters use magic items. Arbitrary assumptions: Monsters only use
16 * scrolls when they can see, monsters know when wands have 0 charges,
17 * monsters cannot recognize if items are cursed are not, monsters which
18 * are confused don't know not to read scrolls, etc....
21 STATIC_DCL struct permonst *FDECL(muse_newcham_mon, (struct monst *));
22 STATIC_DCL int FDECL(precheck, (struct monst *, struct obj *));
23 STATIC_DCL void FDECL(mzapmsg, (struct monst *, struct obj *, BOOLEAN_P));
24 STATIC_DCL void FDECL(mreadmsg, (struct monst *, struct obj *));
25 STATIC_DCL void FDECL(mquaffmsg, (struct monst *, struct obj *));
26 STATIC_PTR int FDECL(mbhitm, (struct monst *, struct obj *));
27 STATIC_DCL void FDECL(mbhit, (struct monst *, int,
28 int FDECL((*), (MONST_P, OBJ_P)),
29 int FDECL((*), (OBJ_P, OBJ_P)), struct obj *));
30 STATIC_DCL void FDECL(you_aggravate, (struct monst *));
31 STATIC_DCL void FDECL(mon_consume_unstone, (struct monst *, struct obj *,
32 BOOLEAN_P, BOOLEAN_P));
33 STATIC_DCL boolean FDECL(cures_stoning, (struct monst *, struct obj *,
34 BOOLEAN_P));
35 STATIC_DCL boolean FDECL(mcould_eat_tin, (struct monst *));
36 STATIC_DCL boolean FDECL(muse_unslime, (struct monst *, struct obj *,
37 struct trap *, BOOLEAN_P));
38 STATIC_DCL int FDECL(cures_sliming, (struct monst *, struct obj *));
39 STATIC_DCL boolean FDECL(green_mon, (struct monst *));
41 static struct musable {
42 struct obj *offensive;
43 struct obj *defensive;
44 struct obj *misc;
45 int has_offense, has_defense, has_misc;
46 /* =0, no capability; otherwise, different numbers.
47 * If it's an object, the object is also set (it's 0 otherwise).
49 } m;
50 static int trapx, trapy;
51 static boolean zap_oseen; /* for wands which use mbhitm and are zapped at
52 * players. We usually want an oseen local to
53 * the function, but this is impossible since the
54 * function mbhitm has to be compatible with the
55 * normal zap routines, and those routines don't
56 * remember who zapped the wand. */
58 /* Any preliminary checks which may result in the monster being unable to use
59 * the item. Returns 0 if nothing happened, 2 if the monster can't do
60 * anything (i.e. it teleported) and 1 if it's dead.
62 STATIC_OVL int
63 precheck(mon, obj)
64 struct monst *mon;
65 struct obj *obj;
67 boolean vis;
69 if (!obj)
70 return 0;
71 vis = cansee(mon->mx, mon->my);
73 if (obj->oclass == POTION_CLASS) {
74 coord cc;
75 static const char *empty = "The potion turns out to be empty.";
76 const char *potion_descr;
77 struct monst *mtmp;
79 potion_descr = OBJ_DESCR(objects[obj->otyp]);
80 if (potion_descr && !strcmp(potion_descr, "milky")) {
81 if (!(mvitals[PM_GHOST].mvflags & G_GONE)
82 && !rn2(POTION_OCCUPANT_CHANCE(mvitals[PM_GHOST].born))) {
83 if (!enexto(&cc, mon->mx, mon->my, &mons[PM_GHOST]))
84 return 0;
85 mquaffmsg(mon, obj);
86 m_useup(mon, obj);
87 mtmp = makemon(&mons[PM_GHOST], cc.x, cc.y, NO_MM_FLAGS);
88 if (!mtmp) {
89 if (vis)
90 pline1(empty);
91 } else {
92 if (vis) {
93 pline(
94 "As %s opens the bottle, an enormous %s emerges!",
95 mon_nam(mon),
96 Hallucination ? rndmonnam(NULL)
97 : (const char *) "ghost");
98 pline("%s is frightened to death, and unable to move.",
99 Monnam(mon));
101 paralyze_monst(mon, 3);
103 return 2;
106 if (potion_descr && !strcmp(potion_descr, "smoky")
107 && !(mvitals[PM_DJINNI].mvflags & G_GONE)
108 && !rn2(POTION_OCCUPANT_CHANCE(mvitals[PM_DJINNI].born))) {
109 if (!enexto(&cc, mon->mx, mon->my, &mons[PM_DJINNI]))
110 return 0;
111 mquaffmsg(mon, obj);
112 m_useup(mon, obj);
113 mtmp = makemon(&mons[PM_DJINNI], cc.x, cc.y, NO_MM_FLAGS);
114 if (!mtmp) {
115 if (vis)
116 pline1(empty);
117 } else {
118 if (vis)
119 pline("In a cloud of smoke, %s emerges!", a_monnam(mtmp));
120 pline("%s speaks.", vis ? Monnam(mtmp) : Something);
121 /* I suspect few players will be upset that monsters */
122 /* can't wish for wands of death here.... */
123 if (rn2(2)) {
124 verbalize("You freed me!");
125 mtmp->mpeaceful = 1;
126 set_malign(mtmp);
127 } else {
128 verbalize("It is about time.");
129 if (vis)
130 pline("%s vanishes.", Monnam(mtmp));
131 mongone(mtmp);
134 return 2;
137 if (obj->oclass == WAND_CLASS && obj->cursed
138 && !rn2(WAND_BACKFIRE_CHANCE)) {
139 int dam = d(obj->spe + 2, 6);
141 /* 3.6.1: no Deaf filter; 'if' message doesn't warrant it, 'else'
142 message doesn't need it since Your_hear() has one of its own */
143 if (vis) {
144 pline("%s zaps %s, which suddenly explodes!", Monnam(mon),
145 an(xname(obj)));
146 } else {
147 /* same near/far threshold as mzapmsg() */
148 int range = couldsee(mon->mx, mon->my) /* 9 or 5 */
149 ? (BOLT_LIM + 1) : (BOLT_LIM - 3);
151 You_hear("a zap and an explosion %s.",
152 (distu(mon->mx, mon->my) <= range * range)
153 ? "nearby" : "in the distance");
155 m_useup(mon, obj);
156 if (mon->mhp <= dam) {
157 monkilled(mon, "", AD_RBRE);
158 return 1;
159 } else
160 mon->mhp -= dam;
161 m.has_defense = m.has_offense = m.has_misc = 0;
162 /* Only one needed to be set to 0 but the others are harmless */
164 return 0;
167 STATIC_OVL void
168 mzapmsg(mtmp, otmp, self)
169 struct monst *mtmp;
170 struct obj *otmp;
171 boolean self;
173 if (!canseemon(mtmp)) {
174 int range = couldsee(mtmp->mx, mtmp->my) /* 9 or 5 */
175 ? (BOLT_LIM + 1) : (BOLT_LIM - 3);
177 You_hear("a %s zap.", (distu(mtmp->mx, mtmp->my) <= range * range)
178 ? "nearby" : "distant");
179 } else if (self) {
180 pline("%s zaps %sself with %s!", Monnam(mtmp), mhim(mtmp),
181 doname(otmp));
182 } else {
183 pline("%s zaps %s!", Monnam(mtmp), an(xname(otmp)));
184 stop_occupation();
188 STATIC_OVL void
189 mreadmsg(mtmp, otmp)
190 struct monst *mtmp;
191 struct obj *otmp;
193 boolean vismon = canseemon(mtmp);
194 char onambuf[BUFSZ];
195 short saverole;
196 unsigned savebknown;
198 if (!vismon && Deaf)
199 return; /* no feedback */
201 otmp->dknown = 1; /* seeing or hearing it read reveals its label */
202 /* shouldn't be able to hear curse/bless status of unseen scrolls;
203 for priest characters, bknown will always be set during naming */
204 savebknown = otmp->bknown;
205 saverole = Role_switch;
206 if (!vismon) {
207 otmp->bknown = 0;
208 if (Role_if(PM_PRIEST))
209 Role_switch = 0;
211 Strcpy(onambuf, singular(otmp, doname));
212 Role_switch = saverole;
213 otmp->bknown = savebknown;
215 if (vismon)
216 pline("%s reads %s!", Monnam(mtmp), onambuf);
217 else
218 You_hear("%s reading %s.",
219 x_monnam(mtmp, ARTICLE_A, (char *) 0,
220 (SUPPRESS_IT | SUPPRESS_INVISIBLE | SUPPRESS_SADDLE),
221 FALSE),
222 onambuf);
224 if (mtmp->mconf)
225 pline("Being confused, %s mispronounces the magic words...",
226 vismon ? mon_nam(mtmp) : mhe(mtmp));
229 STATIC_OVL void
230 mquaffmsg(mtmp, otmp)
231 struct monst *mtmp;
232 struct obj *otmp;
234 if (canseemon(mtmp)) {
235 otmp->dknown = 1;
236 pline("%s drinks %s!", Monnam(mtmp), singular(otmp, doname));
237 } else if (!Deaf)
238 You_hear("a chugging sound.");
241 /* Defines for various types of stuff. The order in which monsters prefer
242 * to use them is determined by the order of the code logic, not the
243 * numerical order in which they are defined.
245 #define MUSE_SCR_TELEPORTATION 1
246 #define MUSE_WAN_TELEPORTATION_SELF 2
247 #define MUSE_POT_HEALING 3
248 #define MUSE_POT_EXTRA_HEALING 4
249 #define MUSE_WAN_DIGGING 5
250 #define MUSE_TRAPDOOR 6
251 #define MUSE_TELEPORT_TRAP 7
252 #define MUSE_UPSTAIRS 8
253 #define MUSE_DOWNSTAIRS 9
254 #define MUSE_WAN_CREATE_MONSTER 10
255 #define MUSE_SCR_CREATE_MONSTER 11
256 #define MUSE_UP_LADDER 12
257 #define MUSE_DN_LADDER 13
258 #define MUSE_SSTAIRS 14
259 #define MUSE_WAN_TELEPORTATION 15
260 #define MUSE_BUGLE 16
261 #define MUSE_UNICORN_HORN 17
262 #define MUSE_POT_FULL_HEALING 18
263 #define MUSE_LIZARD_CORPSE 19
265 #define MUSE_INNATE_TPT 9999
266 * We cannot use this. Since monsters get unlimited teleportation, if they
267 * were allowed to teleport at will you could never catch them. Instead,
268 * assume they only teleport at random times, despite the inconsistency
269 * that if you polymorph into one you teleport at will.
272 /* Select a defensive item/action for a monster. Returns TRUE iff one is
273 found. */
274 boolean
275 find_defensive(mtmp)
276 struct monst *mtmp;
278 register struct obj *obj = 0;
279 struct trap *t;
280 int x = mtmp->mx, y = mtmp->my;
281 boolean stuck = (mtmp == u.ustuck);
282 boolean immobile = (mtmp->data->mmove == 0);
283 int fraction;
285 if (is_animal(mtmp->data) || mindless(mtmp->data))
286 return FALSE;
287 if (dist2(x, y, mtmp->mux, mtmp->muy) > 25)
288 return FALSE;
289 if (u.uswallow && stuck)
290 return FALSE;
292 m.defensive = (struct obj *) 0;
293 m.has_defense = 0;
295 /* since unicorn horns don't get used up, the monster would look
296 * silly trying to use the same cursed horn round after round
298 if (mtmp->mconf || mtmp->mstun || !mtmp->mcansee) {
299 if (!is_unicorn(mtmp->data) && !nohands(mtmp->data)) {
300 for (obj = mtmp->minvent; obj; obj = obj->nobj)
301 if (obj->otyp == UNICORN_HORN && !obj->cursed)
302 break;
304 if (obj || is_unicorn(mtmp->data)) {
305 m.defensive = obj;
306 m.has_defense = MUSE_UNICORN_HORN;
307 return TRUE;
311 if (mtmp->mconf || mtmp->mstun) {
312 struct obj *liztin = 0;
314 for (obj = mtmp->minvent; obj; obj = obj->nobj) {
315 if (obj->otyp == CORPSE && obj->corpsenm == PM_LIZARD) {
316 m.defensive = obj;
317 m.has_defense = MUSE_LIZARD_CORPSE;
318 return TRUE;
319 } else if (obj->otyp == TIN && obj->corpsenm == PM_LIZARD) {
320 liztin = obj;
323 /* confused or stunned monster might not be able to open tin */
324 if (liztin && mcould_eat_tin(mtmp) && rn2(3)) {
325 m.defensive = liztin;
326 /* tin and corpse ultimately end up being handled the same */
327 m.has_defense = MUSE_LIZARD_CORPSE;
328 return TRUE;
332 /* It so happens there are two unrelated cases when we might want to
333 * check specifically for healing alone. The first is when the monster
334 * is blind (healing cures blindness). The second is when the monster
335 * is peaceful; then we don't want to flee the player, and by
336 * coincidence healing is all there is that doesn't involve fleeing.
337 * These would be hard to combine because of the control flow.
338 * Pestilence won't use healing even when blind.
340 if (!mtmp->mcansee && !nohands(mtmp->data)
341 && mtmp->data != &mons[PM_PESTILENCE]) {
342 if ((obj = m_carrying(mtmp, POT_FULL_HEALING)) != 0) {
343 m.defensive = obj;
344 m.has_defense = MUSE_POT_FULL_HEALING;
345 return TRUE;
347 if ((obj = m_carrying(mtmp, POT_EXTRA_HEALING)) != 0) {
348 m.defensive = obj;
349 m.has_defense = MUSE_POT_EXTRA_HEALING;
350 return TRUE;
352 if ((obj = m_carrying(mtmp, POT_HEALING)) != 0) {
353 m.defensive = obj;
354 m.has_defense = MUSE_POT_HEALING;
355 return TRUE;
359 fraction = u.ulevel < 10 ? 5 : u.ulevel < 14 ? 4 : 3;
360 if (mtmp->mhp >= mtmp->mhpmax
361 || (mtmp->mhp >= 10 && mtmp->mhp * fraction >= mtmp->mhpmax))
362 return FALSE;
364 if (mtmp->mpeaceful) {
365 if (!nohands(mtmp->data)) {
366 if ((obj = m_carrying(mtmp, POT_FULL_HEALING)) != 0) {
367 m.defensive = obj;
368 m.has_defense = MUSE_POT_FULL_HEALING;
369 return TRUE;
371 if ((obj = m_carrying(mtmp, POT_EXTRA_HEALING)) != 0) {
372 m.defensive = obj;
373 m.has_defense = MUSE_POT_EXTRA_HEALING;
374 return TRUE;
376 if ((obj = m_carrying(mtmp, POT_HEALING)) != 0) {
377 m.defensive = obj;
378 m.has_defense = MUSE_POT_HEALING;
379 return TRUE;
382 return FALSE;
385 if (stuck || immobile) {
386 ; /* fleeing by stairs or traps is not possible */
387 } else if (levl[x][y].typ == STAIRS) {
388 if (x == xdnstair && y == ydnstair) {
389 if (!is_floater(mtmp->data))
390 m.has_defense = MUSE_DOWNSTAIRS;
391 } else if (x == xupstair && y == yupstair) {
392 m.has_defense = MUSE_UPSTAIRS;
393 } else if (sstairs.sx && x == sstairs.sx && y == sstairs.sy) {
394 if (sstairs.up || !is_floater(mtmp->data))
395 m.has_defense = MUSE_SSTAIRS;
397 } else if (levl[x][y].typ == LADDER) {
398 if (x == xupladder && y == yupladder) {
399 m.has_defense = MUSE_UP_LADDER;
400 } else if (x == xdnladder && y == ydnladder) {
401 if (!is_floater(mtmp->data))
402 m.has_defense = MUSE_DN_LADDER;
403 } else if (sstairs.sx && x == sstairs.sx && y == sstairs.sy) {
404 if (sstairs.up || !is_floater(mtmp->data))
405 m.has_defense = MUSE_SSTAIRS;
407 } else {
408 /* Note: trap doors take precedence over teleport traps. */
409 int xx, yy, i, locs[10][2];
410 boolean ignore_boulders = (verysmall(mtmp->data)
411 || throws_rocks(mtmp->data)
412 || passes_walls(mtmp->data)),
413 diag_ok = !NODIAG(monsndx(mtmp->data));
415 for (i = 0; i < 10; ++i) /* 10: 9 spots plus sentinel */
416 locs[i][0] = locs[i][1] = 0;
417 /* collect viable spots; monster's <mx,my> comes first */
418 locs[0][0] = x, locs[0][1] = y;
419 i = 1;
420 for (xx = x - 1; xx <= x + 1; xx++)
421 for (yy = y - 1; yy <= y + 1; yy++)
422 if (isok(xx, yy) && (xx != x || yy != y)) {
423 locs[i][0] = xx, locs[i][1] = yy;
424 ++i;
426 /* look for a suitable trap among the viable spots */
427 for (i = 0; i < 10; ++i) {
428 xx = locs[i][0], yy = locs[i][1];
429 if (!xx)
430 break; /* we've run out of spots */
431 /* skip if it's hero's location
432 or a diagonal spot and monster can't move diagonally
433 or some other monster is there */
434 if ((xx == u.ux && yy == u.uy)
435 || (xx != x && yy != y && !diag_ok)
436 || (level.monsters[xx][yy] && !(xx == x && yy == y)))
437 continue;
438 /* skip if there's no trap or can't/won't move onto trap */
439 if ((t = t_at(xx, yy)) == 0
440 || (!ignore_boulders && sobj_at(BOULDER, xx, yy))
441 || onscary(xx, yy, mtmp))
442 continue;
443 /* use trap if it's the correct type */
444 if ((t->ttyp == TRAPDOOR || t->ttyp == HOLE)
445 && !is_floater(mtmp->data)
446 && !mtmp->isshk && !mtmp->isgd && !mtmp->ispriest
447 && Can_fall_thru(&u.uz)) {
448 trapx = xx;
449 trapy = yy;
450 m.has_defense = MUSE_TRAPDOOR;
451 break; /* no need to look at any other spots */
452 } else if (t->ttyp == TELEP_TRAP) {
453 trapx = xx;
454 trapy = yy;
455 m.has_defense = MUSE_TELEPORT_TRAP;
460 if (nohands(mtmp->data)) /* can't use objects */
461 goto botm;
463 if (is_mercenary(mtmp->data) && (obj = m_carrying(mtmp, BUGLE)) != 0) {
464 int xx, yy;
465 struct monst *mon;
467 /* Distance is arbitrary. What we really want to do is
468 * have the soldier play the bugle when it sees or
469 * remembers soldiers nearby...
471 for (xx = x - 3; xx <= x + 3; xx++) {
472 for (yy = y - 3; yy <= y + 3; yy++) {
473 if (!isok(xx, yy) || (xx == x && yy == y))
474 continue;
475 if ((mon = m_at(xx, yy)) != 0 && is_mercenary(mon->data)
476 && mon->data != &mons[PM_GUARD]
477 && (mon->msleeping || !mon->mcanmove)) {
478 m.defensive = obj;
479 m.has_defense = MUSE_BUGLE;
480 goto toot; /* double break */
484 toot:
488 /* use immediate physical escape prior to attempting magic */
489 if (m.has_defense) /* stairs, trap door or tele-trap, bugle alert */
490 goto botm;
492 /* kludge to cut down on trap destruction (particularly portals) */
493 t = t_at(x, y);
494 if (t && (t->ttyp == PIT || t->ttyp == SPIKED_PIT || t->ttyp == WEB
495 || t->ttyp == BEAR_TRAP))
496 t = 0; /* ok for monster to dig here */
498 #define nomore(x) if (m.has_defense == x) continue;
499 /* selection could be improved by collecting all possibilities
500 into an array and then picking one at random */
501 for (obj = mtmp->minvent; obj; obj = obj->nobj) {
502 /* don't always use the same selection pattern */
503 if (m.has_defense && !rn2(3))
504 break;
506 /* nomore(MUSE_WAN_DIGGING); */
507 if (m.has_defense == MUSE_WAN_DIGGING)
508 break;
509 if (obj->otyp == WAN_DIGGING && obj->spe > 0 && !stuck && !t
510 && !mtmp->isshk && !mtmp->isgd && !mtmp->ispriest
511 && !is_floater(mtmp->data)
512 /* monsters digging in Sokoban can ruin things */
513 && !Sokoban
514 /* digging wouldn't be effective; assume they know that */
515 && !(levl[x][y].wall_info & W_NONDIGGABLE)
516 && !(Is_botlevel(&u.uz) || In_endgame(&u.uz))
517 && !(is_ice(x, y) || is_pool(x, y) || is_lava(x, y))
518 && !(mtmp->data == &mons[PM_VLAD_THE_IMPALER]
519 && In_V_tower(&u.uz))) {
520 m.defensive = obj;
521 m.has_defense = MUSE_WAN_DIGGING;
523 nomore(MUSE_WAN_TELEPORTATION_SELF);
524 nomore(MUSE_WAN_TELEPORTATION);
525 if (obj->otyp == WAN_TELEPORTATION && obj->spe > 0) {
526 /* use the TELEP_TRAP bit to determine if they know
527 * about noteleport on this level or not. Avoids
528 * ineffective re-use of teleportation. This does
529 * mean if the monster leaves the level, they'll know
530 * about teleport traps.
532 if (!level.flags.noteleport
533 || !(mtmp->mtrapseen & (1 << (TELEP_TRAP - 1)))) {
534 m.defensive = obj;
535 m.has_defense = (mon_has_amulet(mtmp))
536 ? MUSE_WAN_TELEPORTATION
537 : MUSE_WAN_TELEPORTATION_SELF;
540 nomore(MUSE_SCR_TELEPORTATION);
541 if (obj->otyp == SCR_TELEPORTATION && mtmp->mcansee
542 && haseyes(mtmp->data)
543 && (!obj->cursed || (!(mtmp->isshk && inhishop(mtmp))
544 && !mtmp->isgd && !mtmp->ispriest))) {
545 /* see WAN_TELEPORTATION case above */
546 if (!level.flags.noteleport
547 || !(mtmp->mtrapseen & (1 << (TELEP_TRAP - 1)))) {
548 m.defensive = obj;
549 m.has_defense = MUSE_SCR_TELEPORTATION;
553 if (mtmp->data != &mons[PM_PESTILENCE]) {
554 nomore(MUSE_POT_FULL_HEALING);
555 if (obj->otyp == POT_FULL_HEALING) {
556 m.defensive = obj;
557 m.has_defense = MUSE_POT_FULL_HEALING;
559 nomore(MUSE_POT_EXTRA_HEALING);
560 if (obj->otyp == POT_EXTRA_HEALING) {
561 m.defensive = obj;
562 m.has_defense = MUSE_POT_EXTRA_HEALING;
564 nomore(MUSE_WAN_CREATE_MONSTER);
565 if (obj->otyp == WAN_CREATE_MONSTER && obj->spe > 0) {
566 m.defensive = obj;
567 m.has_defense = MUSE_WAN_CREATE_MONSTER;
569 nomore(MUSE_POT_HEALING);
570 if (obj->otyp == POT_HEALING) {
571 m.defensive = obj;
572 m.has_defense = MUSE_POT_HEALING;
574 } else { /* Pestilence */
575 nomore(MUSE_POT_FULL_HEALING);
576 if (obj->otyp == POT_SICKNESS) {
577 m.defensive = obj;
578 m.has_defense = MUSE_POT_FULL_HEALING;
580 nomore(MUSE_WAN_CREATE_MONSTER);
581 if (obj->otyp == WAN_CREATE_MONSTER && obj->spe > 0) {
582 m.defensive = obj;
583 m.has_defense = MUSE_WAN_CREATE_MONSTER;
586 nomore(MUSE_SCR_CREATE_MONSTER);
587 if (obj->otyp == SCR_CREATE_MONSTER) {
588 m.defensive = obj;
589 m.has_defense = MUSE_SCR_CREATE_MONSTER;
592 botm:
593 return (boolean) !!m.has_defense;
594 #undef nomore
597 /* Perform a defensive action for a monster. Must be called immediately
598 * after find_defensive(). Return values are 0: did something, 1: died,
599 * 2: did something and can't attack again (i.e. teleported).
602 use_defensive(mtmp)
603 struct monst *mtmp;
605 int i, fleetim, how = 0;
606 struct obj *otmp = m.defensive;
607 boolean vis, vismon, oseen;
608 const char *Mnam, *mcsa = "%s can see again.";
610 if ((i = precheck(mtmp, otmp)) != 0)
611 return i;
612 vis = cansee(mtmp->mx, mtmp->my);
613 vismon = canseemon(mtmp);
614 oseen = otmp && vismon;
616 /* when using defensive choice to run away, we want monster to avoid
617 rushing right straight back; don't override if already scared */
618 fleetim = !mtmp->mflee ? (33 - (30 * mtmp->mhp / mtmp->mhpmax)) : 0;
619 #define m_flee(m) \
620 if (fleetim && !m->iswiz) { \
621 monflee(m, fleetim, FALSE, FALSE); \
624 switch (m.has_defense) {
625 case MUSE_UNICORN_HORN:
626 if (vismon) {
627 if (otmp)
628 pline("%s uses a unicorn horn!", Monnam(mtmp));
629 else
630 pline_The("tip of %s's horn glows!", mon_nam(mtmp));
632 if (!mtmp->mcansee) {
633 mtmp->mcansee = 1;
634 mtmp->mblinded = 0;
635 if (vismon)
636 pline(mcsa, Monnam(mtmp));
637 } else if (mtmp->mconf || mtmp->mstun) {
638 mtmp->mconf = mtmp->mstun = 0;
639 if (vismon)
640 pline("%s seems steadier now.", Monnam(mtmp));
641 } else
642 impossible("No need for unicorn horn?");
643 return 2;
644 case MUSE_BUGLE:
645 if (vismon)
646 pline("%s plays %s!", Monnam(mtmp), doname(otmp));
647 else if (!Deaf)
648 You_hear("a bugle playing reveille!");
649 awaken_soldiers(mtmp);
650 return 2;
651 case MUSE_WAN_TELEPORTATION_SELF:
652 if ((mtmp->isshk && inhishop(mtmp)) || mtmp->isgd || mtmp->ispriest)
653 return 2;
654 m_flee(mtmp);
655 mzapmsg(mtmp, otmp, TRUE);
656 otmp->spe--;
657 how = WAN_TELEPORTATION;
658 mon_tele:
659 if (tele_restrict(mtmp)) { /* mysterious force... */
660 if (vismon && how) /* mentions 'teleport' */
661 makeknown(how);
662 /* monster learns that teleportation isn't useful here */
663 if (level.flags.noteleport)
664 mtmp->mtrapseen |= (1 << (TELEP_TRAP - 1));
665 return 2;
667 if ((mon_has_amulet(mtmp) || On_W_tower_level(&u.uz)) && !rn2(3)) {
668 if (vismon)
669 pline("%s seems disoriented for a moment.", Monnam(mtmp));
670 return 2;
672 if (oseen && how)
673 makeknown(how);
674 (void) rloc(mtmp, TRUE);
675 return 2;
676 case MUSE_WAN_TELEPORTATION:
677 zap_oseen = oseen;
678 mzapmsg(mtmp, otmp, FALSE);
679 otmp->spe--;
680 m_using = TRUE;
681 mbhit(mtmp, rn1(8, 6), mbhitm, bhito, otmp);
682 /* monster learns that teleportation isn't useful here */
683 if (level.flags.noteleport)
684 mtmp->mtrapseen |= (1 << (TELEP_TRAP - 1));
685 m_using = FALSE;
686 return 2;
687 case MUSE_SCR_TELEPORTATION: {
688 int obj_is_cursed = otmp->cursed;
690 if (mtmp->isshk || mtmp->isgd || mtmp->ispriest)
691 return 2;
692 m_flee(mtmp);
693 mreadmsg(mtmp, otmp);
694 m_useup(mtmp, otmp); /* otmp might be free'ed */
695 how = SCR_TELEPORTATION;
696 if (obj_is_cursed || mtmp->mconf) {
697 int nlev;
698 d_level flev;
700 if (mon_has_amulet(mtmp) || In_endgame(&u.uz)) {
701 if (vismon)
702 pline("%s seems very disoriented for a moment.",
703 Monnam(mtmp));
704 return 2;
706 nlev = random_teleport_level();
707 if (nlev == depth(&u.uz)) {
708 if (vismon)
709 pline("%s shudders for a moment.", Monnam(mtmp));
710 return 2;
712 get_level(&flev, nlev);
713 migrate_to_level(mtmp, ledger_no(&flev), MIGR_RANDOM,
714 (coord *) 0);
715 if (oseen)
716 makeknown(SCR_TELEPORTATION);
717 } else
718 goto mon_tele;
719 return 2;
721 case MUSE_WAN_DIGGING: {
722 struct trap *ttmp;
724 m_flee(mtmp);
725 mzapmsg(mtmp, otmp, FALSE);
726 otmp->spe--;
727 if (oseen)
728 makeknown(WAN_DIGGING);
729 if (IS_FURNITURE(levl[mtmp->mx][mtmp->my].typ)
730 || IS_DRAWBRIDGE(levl[mtmp->mx][mtmp->my].typ)
731 || (is_drawbridge_wall(mtmp->mx, mtmp->my) >= 0)
732 || (sstairs.sx && sstairs.sx == mtmp->mx
733 && sstairs.sy == mtmp->my)) {
734 pline_The("digging ray is ineffective.");
735 return 2;
737 if (!Can_dig_down(&u.uz) && !levl[mtmp->mx][mtmp->my].candig) {
738 if (canseemon(mtmp))
739 pline_The("%s here is too hard to dig in.",
740 surface(mtmp->mx, mtmp->my));
741 return 2;
743 ttmp = maketrap(mtmp->mx, mtmp->my, HOLE);
744 if (!ttmp)
745 return 2;
746 seetrap(ttmp);
747 if (vis) {
748 pline("%s has made a hole in the %s.", Monnam(mtmp),
749 surface(mtmp->mx, mtmp->my));
750 pline("%s %s through...", Monnam(mtmp),
751 is_flyer(mtmp->data) ? "dives" : "falls");
752 } else if (!Deaf)
753 You_hear("%s crash through the %s.", something,
754 surface(mtmp->mx, mtmp->my));
755 /* we made sure that there is a level for mtmp to go to */
756 migrate_to_level(mtmp, ledger_no(&u.uz) + 1, MIGR_RANDOM,
757 (coord *) 0);
758 return 2;
760 case MUSE_WAN_CREATE_MONSTER: {
761 coord cc;
762 /* pm: 0 => random, eel => aquatic, croc => amphibious */
763 struct permonst *pm =
764 !is_pool(mtmp->mx, mtmp->my)
766 : &mons[u.uinwater ? PM_GIANT_EEL : PM_CROCODILE];
767 struct monst *mon;
769 if (!enexto(&cc, mtmp->mx, mtmp->my, pm))
770 return 0;
771 mzapmsg(mtmp, otmp, FALSE);
772 otmp->spe--;
773 mon = makemon((struct permonst *) 0, cc.x, cc.y, NO_MM_FLAGS);
774 if (mon && canspotmon(mon) && oseen)
775 makeknown(WAN_CREATE_MONSTER);
776 return 2;
778 case MUSE_SCR_CREATE_MONSTER: {
779 coord cc;
780 struct permonst *pm = 0, *fish = 0;
781 int cnt = 1;
782 struct monst *mon;
783 boolean known = FALSE;
785 if (!rn2(73))
786 cnt += rnd(4);
787 if (mtmp->mconf || otmp->cursed)
788 cnt += 12;
789 if (mtmp->mconf)
790 pm = fish = &mons[PM_ACID_BLOB];
791 else if (is_pool(mtmp->mx, mtmp->my))
792 fish = &mons[u.uinwater ? PM_GIANT_EEL : PM_CROCODILE];
793 mreadmsg(mtmp, otmp);
794 while (cnt--) {
795 /* `fish' potentially gives bias towards water locations;
796 `pm' is what to actually create (0 => random) */
797 if (!enexto(&cc, mtmp->mx, mtmp->my, fish))
798 break;
799 mon = makemon(pm, cc.x, cc.y, NO_MM_FLAGS);
800 if (mon && canspotmon(mon))
801 known = TRUE;
803 /* The only case where we don't use oseen. For wands, you
804 * have to be able to see the monster zap the wand to know
805 * what type it is. For teleport scrolls, you have to see
806 * the monster to know it teleported.
808 if (known)
809 makeknown(SCR_CREATE_MONSTER);
810 else if (!objects[SCR_CREATE_MONSTER].oc_name_known
811 && !objects[SCR_CREATE_MONSTER].oc_uname)
812 docall(otmp);
813 m_useup(mtmp, otmp);
814 return 2;
816 case MUSE_TRAPDOOR:
817 /* trap doors on "bottom" levels of dungeons are rock-drop
818 * trap doors, not holes in the floor. We check here for
819 * safety.
821 if (Is_botlevel(&u.uz))
822 return 0;
823 m_flee(mtmp);
824 if (vis) {
825 struct trap *t = t_at(trapx, trapy);
827 Mnam = Monnam(mtmp);
828 pline("%s %s into a %s!", Mnam,
829 vtense(Mnam, locomotion(mtmp->data, "jump")),
830 (t->ttyp == TRAPDOOR) ? "trap door" : "hole");
831 if (levl[trapx][trapy].typ == SCORR) {
832 levl[trapx][trapy].typ = CORR;
833 unblock_point(trapx, trapy);
835 seetrap(t_at(trapx, trapy));
838 /* don't use rloc_to() because worm tails must "move" */
839 remove_monster(mtmp->mx, mtmp->my);
840 newsym(mtmp->mx, mtmp->my); /* update old location */
841 place_monster(mtmp, trapx, trapy);
842 if (mtmp->wormno)
843 worm_move(mtmp);
844 newsym(trapx, trapy);
846 migrate_to_level(mtmp, ledger_no(&u.uz) + 1, MIGR_RANDOM,
847 (coord *) 0);
848 return 2;
849 case MUSE_UPSTAIRS:
850 m_flee(mtmp);
851 if (ledger_no(&u.uz) == 1)
852 goto escape; /* impossible; level 1 upstairs are SSTAIRS */
853 if (Inhell && mon_has_amulet(mtmp) && !rn2(4)
854 && (dunlev(&u.uz) < dunlevs_in_dungeon(&u.uz) - 3)) {
855 if (vismon)
856 pline(
857 "As %s climbs the stairs, a mysterious force momentarily surrounds %s...",
858 mon_nam(mtmp), mhim(mtmp));
859 /* simpler than for the player; this will usually be
860 the Wizard and he'll immediately go right to the
861 upstairs, so there's not much point in having any
862 chance for a random position on the current level */
863 migrate_to_level(mtmp, ledger_no(&u.uz) + 1, MIGR_RANDOM,
864 (coord *) 0);
865 } else {
866 if (vismon)
867 pline("%s escapes upstairs!", Monnam(mtmp));
868 migrate_to_level(mtmp, ledger_no(&u.uz) - 1, MIGR_STAIRS_DOWN,
869 (coord *) 0);
871 return 2;
872 case MUSE_DOWNSTAIRS:
873 m_flee(mtmp);
874 if (vismon)
875 pline("%s escapes downstairs!", Monnam(mtmp));
876 migrate_to_level(mtmp, ledger_no(&u.uz) + 1, MIGR_STAIRS_UP,
877 (coord *) 0);
878 return 2;
879 case MUSE_UP_LADDER:
880 m_flee(mtmp);
881 if (vismon)
882 pline("%s escapes up the ladder!", Monnam(mtmp));
883 migrate_to_level(mtmp, ledger_no(&u.uz) - 1, MIGR_LADDER_DOWN,
884 (coord *) 0);
885 return 2;
886 case MUSE_DN_LADDER:
887 m_flee(mtmp);
888 if (vismon)
889 pline("%s escapes down the ladder!", Monnam(mtmp));
890 migrate_to_level(mtmp, ledger_no(&u.uz) + 1, MIGR_LADDER_UP,
891 (coord *) 0);
892 return 2;
893 case MUSE_SSTAIRS:
894 m_flee(mtmp);
895 if (ledger_no(&u.uz) == 1) {
896 escape:
897 /* Monsters without the Amulet escape the dungeon and
898 * are gone for good when they leave up the up stairs.
899 * A monster with the Amulet would leave it behind
900 * (mongone -> mdrop_special_objs) but we force any
901 * monster who manages to acquire it or the invocation
902 * tools to stick around instead of letting it escape.
904 if (mon_has_special(mtmp))
905 return 0;
906 if (vismon)
907 pline("%s escapes the dungeon!", Monnam(mtmp));
908 mongone(mtmp);
909 return 2;
911 if (vismon)
912 pline("%s escapes %sstairs!", Monnam(mtmp),
913 sstairs.up ? "up" : "down");
914 /* going from the Valley to Castle (Stronghold) has no sstairs
915 to target, but having sstairs.<sx,sy> == <0,0> will work the
916 same as specifying MIGR_RANDOM when mon_arrive() eventually
917 places the monster, so we can use MIGR_SSTAIRS unconditionally */
918 migrate_to_level(mtmp, ledger_no(&sstairs.tolev), MIGR_SSTAIRS,
919 (coord *) 0);
920 return 2;
921 case MUSE_TELEPORT_TRAP:
922 m_flee(mtmp);
923 if (vis) {
924 Mnam = Monnam(mtmp);
925 pline("%s %s onto a teleport trap!", Mnam,
926 vtense(Mnam, locomotion(mtmp->data, "jump")));
927 seetrap(t_at(trapx, trapy));
929 /* don't use rloc_to() because worm tails must "move" */
930 remove_monster(mtmp->mx, mtmp->my);
931 newsym(mtmp->mx, mtmp->my); /* update old location */
932 place_monster(mtmp, trapx, trapy);
933 if (mtmp->wormno)
934 worm_move(mtmp);
935 newsym(trapx, trapy);
937 goto mon_tele;
938 case MUSE_POT_HEALING:
939 mquaffmsg(mtmp, otmp);
940 i = d(6 + 2 * bcsign(otmp), 4);
941 mtmp->mhp += i;
942 if (mtmp->mhp > mtmp->mhpmax)
943 mtmp->mhp = ++mtmp->mhpmax;
944 if (!otmp->cursed && !mtmp->mcansee) {
945 mtmp->mcansee = 1;
946 mtmp->mblinded = 0;
947 if (vismon)
948 pline(mcsa, Monnam(mtmp));
950 if (vismon)
951 pline("%s looks better.", Monnam(mtmp));
952 if (oseen)
953 makeknown(POT_HEALING);
954 m_useup(mtmp, otmp);
955 return 2;
956 case MUSE_POT_EXTRA_HEALING:
957 mquaffmsg(mtmp, otmp);
958 i = d(6 + 2 * bcsign(otmp), 8);
959 mtmp->mhp += i;
960 if (mtmp->mhp > mtmp->mhpmax)
961 mtmp->mhp = (mtmp->mhpmax += (otmp->blessed ? 5 : 2));
962 if (!mtmp->mcansee) {
963 mtmp->mcansee = 1;
964 mtmp->mblinded = 0;
965 if (vismon)
966 pline(mcsa, Monnam(mtmp));
968 if (vismon)
969 pline("%s looks much better.", Monnam(mtmp));
970 if (oseen)
971 makeknown(POT_EXTRA_HEALING);
972 m_useup(mtmp, otmp);
973 return 2;
974 case MUSE_POT_FULL_HEALING:
975 mquaffmsg(mtmp, otmp);
976 if (otmp->otyp == POT_SICKNESS)
977 unbless(otmp); /* Pestilence */
978 mtmp->mhp = (mtmp->mhpmax += (otmp->blessed ? 8 : 4));
979 if (!mtmp->mcansee && otmp->otyp != POT_SICKNESS) {
980 mtmp->mcansee = 1;
981 mtmp->mblinded = 0;
982 if (vismon)
983 pline(mcsa, Monnam(mtmp));
985 if (vismon)
986 pline("%s looks completely healed.", Monnam(mtmp));
987 if (oseen)
988 makeknown(otmp->otyp);
989 m_useup(mtmp, otmp);
990 return 2;
991 case MUSE_LIZARD_CORPSE:
992 /* not actually called for its unstoning effect */
993 mon_consume_unstone(mtmp, otmp, FALSE, FALSE);
994 return 2;
995 case 0:
996 return 0; /* i.e. an exploded wand */
997 default:
998 impossible("%s wanted to perform action %d?", Monnam(mtmp),
999 m.has_defense);
1000 break;
1002 return 0;
1003 #undef m_flee
1007 rnd_defensive_item(mtmp)
1008 struct monst *mtmp;
1010 struct permonst *pm = mtmp->data;
1011 int difficulty = monstr[(monsndx(pm))];
1012 int trycnt = 0;
1014 if (is_animal(pm) || attacktype(pm, AT_EXPL) || mindless(mtmp->data)
1015 || pm->mlet == S_GHOST || pm->mlet == S_KOP)
1016 return 0;
1017 try_again:
1018 switch (rn2(8 + (difficulty > 3) + (difficulty > 6) + (difficulty > 8))) {
1019 case 6:
1020 case 9:
1021 if (level.flags.noteleport && ++trycnt < 2)
1022 goto try_again;
1023 if (!rn2(3))
1024 return WAN_TELEPORTATION;
1025 /* else FALLTHRU */
1026 case 0:
1027 case 1:
1028 return SCR_TELEPORTATION;
1029 case 8:
1030 case 10:
1031 if (!rn2(3))
1032 return WAN_CREATE_MONSTER;
1033 /* else FALLTHRU */
1034 case 2:
1035 return SCR_CREATE_MONSTER;
1036 case 3:
1037 return POT_HEALING;
1038 case 4:
1039 return POT_EXTRA_HEALING;
1040 case 5:
1041 return (mtmp->data != &mons[PM_PESTILENCE]) ? POT_FULL_HEALING
1042 : POT_SICKNESS;
1043 case 7:
1044 if (is_floater(pm) || mtmp->isshk || mtmp->isgd || mtmp->ispriest)
1045 return 0;
1046 else
1047 return WAN_DIGGING;
1049 /*NOTREACHED*/
1050 return 0;
1053 #define MUSE_WAN_DEATH 1
1054 #define MUSE_WAN_SLEEP 2
1055 #define MUSE_WAN_FIRE 3
1056 #define MUSE_WAN_COLD 4
1057 #define MUSE_WAN_LIGHTNING 5
1058 #define MUSE_WAN_MAGIC_MISSILE 6
1059 #define MUSE_WAN_STRIKING 7
1060 #define MUSE_SCR_FIRE 8
1061 #define MUSE_POT_PARALYSIS 9
1062 #define MUSE_POT_BLINDNESS 10
1063 #define MUSE_POT_CONFUSION 11
1064 #define MUSE_FROST_HORN 12
1065 #define MUSE_FIRE_HORN 13
1066 #define MUSE_POT_ACID 14
1067 /*#define MUSE_WAN_TELEPORTATION 15*/
1068 #define MUSE_POT_SLEEPING 16
1069 #define MUSE_SCR_EARTH 17
1071 /* Select an offensive item/action for a monster. Returns TRUE iff one is
1072 * found.
1074 boolean
1075 find_offensive(mtmp)
1076 struct monst *mtmp;
1078 register struct obj *obj;
1079 boolean reflection_skip = (Reflecting && rn2(2));
1080 struct obj *helmet = which_armor(mtmp, W_ARMH);
1082 m.offensive = (struct obj *) 0;
1083 m.has_offense = 0;
1084 if (mtmp->mpeaceful || is_animal(mtmp->data) || mindless(mtmp->data)
1085 || nohands(mtmp->data))
1086 return FALSE;
1087 if (u.uswallow)
1088 return FALSE;
1089 if (in_your_sanctuary(mtmp, 0, 0))
1090 return FALSE;
1091 if (dmgtype(mtmp->data, AD_HEAL)
1092 && !uwep && !uarmu && !uarm && !uarmh
1093 && !uarms && !uarmg && !uarmc && !uarmf)
1094 return FALSE;
1095 /* all offensive items require orthogonal or diagonal targetting */
1096 if (!lined_up(mtmp))
1097 return FALSE;
1099 #define nomore(x) if (m.has_offense == x) continue;
1100 /* this picks the last viable item rather than prioritizing choices */
1101 for (obj = mtmp->minvent; obj; obj = obj->nobj) {
1102 if (!reflection_skip) {
1103 nomore(MUSE_WAN_DEATH);
1104 if (obj->otyp == WAN_DEATH && obj->spe > 0) {
1105 m.offensive = obj;
1106 m.has_offense = MUSE_WAN_DEATH;
1108 nomore(MUSE_WAN_SLEEP);
1109 if (obj->otyp == WAN_SLEEP && obj->spe > 0 && multi >= 0) {
1110 m.offensive = obj;
1111 m.has_offense = MUSE_WAN_SLEEP;
1113 nomore(MUSE_WAN_FIRE);
1114 if (obj->otyp == WAN_FIRE && obj->spe > 0) {
1115 m.offensive = obj;
1116 m.has_offense = MUSE_WAN_FIRE;
1118 nomore(MUSE_FIRE_HORN);
1119 if (obj->otyp == FIRE_HORN && obj->spe > 0 && can_blow(mtmp)) {
1120 m.offensive = obj;
1121 m.has_offense = MUSE_FIRE_HORN;
1123 nomore(MUSE_WAN_COLD);
1124 if (obj->otyp == WAN_COLD && obj->spe > 0) {
1125 m.offensive = obj;
1126 m.has_offense = MUSE_WAN_COLD;
1128 nomore(MUSE_FROST_HORN);
1129 if (obj->otyp == FROST_HORN && obj->spe > 0 && can_blow(mtmp)) {
1130 m.offensive = obj;
1131 m.has_offense = MUSE_FROST_HORN;
1133 nomore(MUSE_WAN_LIGHTNING);
1134 if (obj->otyp == WAN_LIGHTNING && obj->spe > 0) {
1135 m.offensive = obj;
1136 m.has_offense = MUSE_WAN_LIGHTNING;
1138 nomore(MUSE_WAN_MAGIC_MISSILE);
1139 if (obj->otyp == WAN_MAGIC_MISSILE && obj->spe > 0) {
1140 m.offensive = obj;
1141 m.has_offense = MUSE_WAN_MAGIC_MISSILE;
1144 nomore(MUSE_WAN_STRIKING);
1145 if (obj->otyp == WAN_STRIKING && obj->spe > 0) {
1146 m.offensive = obj;
1147 m.has_offense = MUSE_WAN_STRIKING;
1149 nomore(MUSE_POT_PARALYSIS);
1150 if (obj->otyp == POT_PARALYSIS && multi >= 0) {
1151 m.offensive = obj;
1152 m.has_offense = MUSE_POT_PARALYSIS;
1154 nomore(MUSE_POT_BLINDNESS);
1155 if (obj->otyp == POT_BLINDNESS && !attacktype(mtmp->data, AT_GAZE)) {
1156 m.offensive = obj;
1157 m.has_offense = MUSE_POT_BLINDNESS;
1159 nomore(MUSE_POT_CONFUSION);
1160 if (obj->otyp == POT_CONFUSION) {
1161 m.offensive = obj;
1162 m.has_offense = MUSE_POT_CONFUSION;
1164 nomore(MUSE_POT_SLEEPING);
1165 if (obj->otyp == POT_SLEEPING) {
1166 m.offensive = obj;
1167 m.has_offense = MUSE_POT_SLEEPING;
1169 nomore(MUSE_POT_ACID);
1170 if (obj->otyp == POT_ACID) {
1171 m.offensive = obj;
1172 m.has_offense = MUSE_POT_ACID;
1174 /* we can safely put this scroll here since the locations that
1175 * are in a 1 square radius are a subset of the locations that
1176 * are in wand or throwing range (in other words, always lined_up())
1178 nomore(MUSE_SCR_EARTH);
1179 if (obj->otyp == SCR_EARTH
1180 && ((helmet && is_metallic(helmet)) || mtmp->mconf
1181 || amorphous(mtmp->data) || passes_walls(mtmp->data)
1182 || noncorporeal(mtmp->data) || unsolid(mtmp->data)
1183 || !rn2(10))
1184 && dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= 2
1185 && mtmp->mcansee && haseyes(mtmp->data)
1186 && !Is_rogue_level(&u.uz)
1187 && (!In_endgame(&u.uz) || Is_earthlevel(&u.uz))) {
1188 m.offensive = obj;
1189 m.has_offense = MUSE_SCR_EARTH;
1191 #if 0
1192 nomore(MUSE_SCR_FIRE);
1193 if (obj->otyp == SCR_FIRE && resists_fire(mtmp)
1194 && dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= 2
1195 && mtmp->mcansee && haseyes(mtmp->data)) {
1196 m.offensive = obj;
1197 m.has_offense = MUSE_SCR_FIRE;
1199 #endif /* 0 */
1201 return (boolean) !!m.has_offense;
1202 #undef nomore
1205 STATIC_PTR
1207 mbhitm(mtmp, otmp)
1208 register struct monst *mtmp;
1209 register struct obj *otmp;
1211 int tmp;
1213 boolean reveal_invis = FALSE;
1214 if (mtmp != &youmonst) {
1215 mtmp->msleeping = 0;
1216 if (mtmp->m_ap_type)
1217 seemimic(mtmp);
1219 switch (otmp->otyp) {
1220 case WAN_STRIKING:
1221 reveal_invis = TRUE;
1222 if (mtmp == &youmonst) {
1223 if (zap_oseen)
1224 makeknown(WAN_STRIKING);
1225 if (Antimagic) {
1226 shieldeff(u.ux, u.uy);
1227 pline("Boing!");
1228 } else if (rnd(20) < 10 + u.uac) {
1229 pline_The("wand hits you!");
1230 tmp = d(2, 12);
1231 if (Half_spell_damage)
1232 tmp = (tmp + 1) / 2;
1233 losehp(tmp, "wand", KILLED_BY_AN);
1234 } else
1235 pline_The("wand misses you.");
1236 stop_occupation();
1237 nomul(0);
1238 } else if (resists_magm(mtmp)) {
1239 shieldeff(mtmp->mx, mtmp->my);
1240 pline("Boing!");
1241 } else if (rnd(20) < 10 + find_mac(mtmp)) {
1242 tmp = d(2, 12);
1243 hit("wand", mtmp, exclam(tmp));
1244 (void) resist(mtmp, otmp->oclass, tmp, TELL);
1245 if (cansee(mtmp->mx, mtmp->my) && zap_oseen)
1246 makeknown(WAN_STRIKING);
1247 } else {
1248 miss("wand", mtmp);
1249 if (cansee(mtmp->mx, mtmp->my) && zap_oseen)
1250 makeknown(WAN_STRIKING);
1252 break;
1253 case WAN_TELEPORTATION:
1254 if (mtmp == &youmonst) {
1255 if (zap_oseen)
1256 makeknown(WAN_TELEPORTATION);
1257 tele();
1258 } else {
1259 /* for consistency with zap.c, don't identify */
1260 if (mtmp->ispriest && *in_rooms(mtmp->mx, mtmp->my, TEMPLE)) {
1261 if (cansee(mtmp->mx, mtmp->my))
1262 pline("%s resists the magic!", Monnam(mtmp));
1263 } else if (!tele_restrict(mtmp))
1264 (void) rloc(mtmp, TRUE);
1266 break;
1267 case WAN_CANCELLATION:
1268 case SPE_CANCELLATION:
1269 (void) cancel_monst(mtmp, otmp, FALSE, TRUE, FALSE);
1270 break;
1272 if (reveal_invis) {
1273 if (mtmp->mhp > 0 && cansee(bhitpos.x, bhitpos.y)
1274 && !canspotmon(mtmp))
1275 map_invisible(bhitpos.x, bhitpos.y);
1277 return 0;
1280 /* A modified bhit() for monsters. Based on bhit() in zap.c. Unlike
1281 * buzz(), bhit() doesn't take into account the possibility of a monster
1282 * zapping you, so we need a special function for it. (Unless someone wants
1283 * to merge the two functions...)
1285 STATIC_OVL void
1286 mbhit(mon, range, fhitm, fhito, obj)
1287 struct monst *mon; /* monster shooting the wand */
1288 register int range; /* direction and range */
1289 int FDECL((*fhitm), (MONST_P, OBJ_P));
1290 int FDECL((*fhito), (OBJ_P, OBJ_P)); /* fns called when mon/obj hit */
1291 struct obj *obj; /* 2nd arg to fhitm/fhito */
1293 register struct monst *mtmp;
1294 register struct obj *otmp;
1295 register uchar typ;
1296 int ddx, ddy;
1298 bhitpos.x = mon->mx;
1299 bhitpos.y = mon->my;
1300 ddx = sgn(mon->mux - mon->mx);
1301 ddy = sgn(mon->muy - mon->my);
1303 while (range-- > 0) {
1304 int x, y;
1306 bhitpos.x += ddx;
1307 bhitpos.y += ddy;
1308 x = bhitpos.x;
1309 y = bhitpos.y;
1311 if (!isok(x, y)) {
1312 bhitpos.x -= ddx;
1313 bhitpos.y -= ddy;
1314 break;
1316 if (find_drawbridge(&x, &y))
1317 switch (obj->otyp) {
1318 case WAN_STRIKING:
1319 destroy_drawbridge(x, y);
1321 if (bhitpos.x == u.ux && bhitpos.y == u.uy) {
1322 (*fhitm)(&youmonst, obj);
1323 range -= 3;
1324 } else if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != 0) {
1325 if (cansee(bhitpos.x, bhitpos.y) && !canspotmon(mtmp))
1326 map_invisible(bhitpos.x, bhitpos.y);
1327 (*fhitm)(mtmp, obj);
1328 range -= 3;
1330 /* modified by GAN to hit all objects */
1331 if (fhito) {
1332 int hitanything = 0;
1333 register struct obj *next_obj;
1335 for (otmp = level.objects[bhitpos.x][bhitpos.y]; otmp;
1336 otmp = next_obj) {
1337 /* Fix for polymorph bug, Tim Wright */
1338 next_obj = otmp->nexthere;
1339 hitanything += (*fhito)(otmp, obj);
1341 if (hitanything)
1342 range--;
1344 typ = levl[bhitpos.x][bhitpos.y].typ;
1345 if (IS_DOOR(typ) || typ == SDOOR) {
1346 switch (obj->otyp) {
1347 /* note: monsters don't use opening or locking magic
1348 at present, but keep these as placeholders */
1349 case WAN_OPENING:
1350 case WAN_LOCKING:
1351 case WAN_STRIKING:
1352 if (doorlock(obj, bhitpos.x, bhitpos.y)) {
1353 if (zap_oseen)
1354 makeknown(obj->otyp);
1355 /* if a shop door gets broken, add it to
1356 the shk's fix list (no cost to player) */
1357 if (levl[bhitpos.x][bhitpos.y].doormask == D_BROKEN
1358 && *in_rooms(bhitpos.x, bhitpos.y, SHOPBASE))
1359 add_damage(bhitpos.x, bhitpos.y, 0L);
1361 break;
1364 if (!ZAP_POS(typ)
1365 || (IS_DOOR(typ) && (levl[bhitpos.x][bhitpos.y].doormask
1366 & (D_LOCKED | D_CLOSED)))) {
1367 bhitpos.x -= ddx;
1368 bhitpos.y -= ddy;
1369 break;
1374 /* Perform an offensive action for a monster. Must be called immediately
1375 * after find_offensive(). Return values are same as use_defensive().
1378 use_offensive(mtmp)
1379 struct monst *mtmp;
1381 int i;
1382 struct obj *otmp = m.offensive;
1383 boolean oseen;
1385 /* offensive potions are not drunk, they're thrown */
1386 if (otmp->oclass != POTION_CLASS && (i = precheck(mtmp, otmp)) != 0)
1387 return i;
1388 oseen = otmp && canseemon(mtmp);
1390 switch (m.has_offense) {
1391 case MUSE_WAN_DEATH:
1392 case MUSE_WAN_SLEEP:
1393 case MUSE_WAN_FIRE:
1394 case MUSE_WAN_COLD:
1395 case MUSE_WAN_LIGHTNING:
1396 case MUSE_WAN_MAGIC_MISSILE:
1397 mzapmsg(mtmp, otmp, FALSE);
1398 otmp->spe--;
1399 if (oseen)
1400 makeknown(otmp->otyp);
1401 m_using = TRUE;
1402 buzz((int) (-30 - (otmp->otyp - WAN_MAGIC_MISSILE)),
1403 (otmp->otyp == WAN_MAGIC_MISSILE) ? 2 : 6, mtmp->mx, mtmp->my,
1404 sgn(mtmp->mux - mtmp->mx), sgn(mtmp->muy - mtmp->my));
1405 m_using = FALSE;
1406 return (mtmp->mhp <= 0) ? 1 : 2;
1407 case MUSE_FIRE_HORN:
1408 case MUSE_FROST_HORN:
1409 if (oseen) {
1410 makeknown(otmp->otyp);
1411 pline("%s plays a %s!", Monnam(mtmp), xname(otmp));
1412 } else
1413 You_hear("a horn being played.");
1414 otmp->spe--;
1415 m_using = TRUE;
1416 buzz(-30 - ((otmp->otyp == FROST_HORN) ? AD_COLD - 1 : AD_FIRE - 1),
1417 rn1(6, 6), mtmp->mx, mtmp->my, sgn(mtmp->mux - mtmp->mx),
1418 sgn(mtmp->muy - mtmp->my));
1419 m_using = FALSE;
1420 return (mtmp->mhp <= 0) ? 1 : 2;
1421 case MUSE_WAN_TELEPORTATION:
1422 case MUSE_WAN_STRIKING:
1423 zap_oseen = oseen;
1424 mzapmsg(mtmp, otmp, FALSE);
1425 otmp->spe--;
1426 m_using = TRUE;
1427 mbhit(mtmp, rn1(8, 6), mbhitm, bhito, otmp);
1428 m_using = FALSE;
1429 return 2;
1430 case MUSE_SCR_EARTH: {
1431 /* TODO: handle steeds */
1432 register int x, y;
1433 /* don't use monster fields after killing it */
1434 boolean confused = (mtmp->mconf ? TRUE : FALSE);
1435 int mmx = mtmp->mx, mmy = mtmp->my;
1436 boolean is_cursed = otmp->cursed;
1438 mreadmsg(mtmp, otmp);
1439 /* Identify the scroll */
1440 if (canspotmon(mtmp)) {
1441 pline_The("%s rumbles %s %s!", ceiling(mtmp->mx, mtmp->my),
1442 otmp->blessed ? "around" : "above", mon_nam(mtmp));
1443 if (oseen)
1444 makeknown(otmp->otyp);
1445 } else if (cansee(mtmp->mx, mtmp->my)) {
1446 pline_The("%s rumbles in the middle of nowhere!",
1447 ceiling(mtmp->mx, mtmp->my));
1448 if (mtmp->minvis)
1449 map_invisible(mtmp->mx, mtmp->my);
1450 if (oseen)
1451 makeknown(otmp->otyp);
1454 /* Loop through the surrounding squares */
1455 for (x = mmx - 1; x <= mmx + 1; x++) {
1456 for (y = mmy - 1; y <= mmy + 1; y++) {
1457 /* Is this a suitable spot? */
1458 if (isok(x, y) && !closed_door(x, y)
1459 && !IS_ROCK(levl[x][y].typ) && !IS_AIR(levl[x][y].typ)
1460 && (((x == mmx) && (y == mmy)) ? !otmp->blessed
1461 : !otmp->cursed)
1462 && (x != u.ux || y != u.uy)) {
1463 (void) drop_boulder_on_monster(x, y, confused, FALSE);
1467 m_useup(mtmp, otmp);
1468 /* Attack the player */
1469 if (distmin(mmx, mmy, u.ux, u.uy) == 1 && !is_cursed) {
1470 drop_boulder_on_player(confused, !is_cursed, FALSE, TRUE);
1473 return (mtmp->mhp <= 0) ? 1 : 2;
1475 #if 0
1476 case MUSE_SCR_FIRE: {
1477 boolean vis = cansee(mtmp->mx, mtmp->my);
1479 mreadmsg(mtmp, otmp);
1480 if (mtmp->mconf) {
1481 if (vis)
1482 pline("Oh, what a pretty fire!");
1483 } else {
1484 struct monst *mtmp2;
1485 int num;
1487 if (vis)
1488 pline_The("scroll erupts in a tower of flame!");
1489 shieldeff(mtmp->mx, mtmp->my);
1490 pline("%s is uninjured.", Monnam(mtmp));
1491 (void) destroy_mitem(mtmp, SCROLL_CLASS, AD_FIRE);
1492 (void) destroy_mitem(mtmp, SPBOOK_CLASS, AD_FIRE);
1493 (void) destroy_mitem(mtmp, POTION_CLASS, AD_FIRE);
1494 num = (2 * (rn1(3, 3) + 2 * bcsign(otmp)) + 1) / 3;
1495 if (Fire_resistance)
1496 You("are not harmed.");
1497 burn_away_slime();
1498 if (Half_spell_damage)
1499 num = (num + 1) / 2;
1500 else
1501 losehp(num, "scroll of fire", KILLED_BY_AN);
1502 for (mtmp2 = fmon; mtmp2; mtmp2 = mtmp2->nmon) {
1503 if (DEADMONSTER(mtmp2)) continue;
1504 if (mtmp == mtmp2) continue;
1505 if (dist2(mtmp2->mx, mtmp2->my, mtmp->mx, mtmp->my) < 3) {
1506 if (resists_fire(mtmp2)) continue;
1507 mtmp2->mhp -= num;
1508 if (resists_cold(mtmp2))
1509 mtmp2->mhp -= 3 * num;
1510 if (mtmp2->mhp < 1) {
1511 mondied(mtmp2);
1512 break;
1517 return 2;
1519 #endif /* 0 */
1520 case MUSE_POT_PARALYSIS:
1521 case MUSE_POT_BLINDNESS:
1522 case MUSE_POT_CONFUSION:
1523 case MUSE_POT_SLEEPING:
1524 case MUSE_POT_ACID:
1525 /* Note: this setting of dknown doesn't suffice. A monster
1526 * which is out of sight might throw and it hits something _in_
1527 * sight, a problem not existing with wands because wand rays
1528 * are not objects. Also set dknown in mthrowu.c.
1530 if (cansee(mtmp->mx, mtmp->my)) {
1531 otmp->dknown = 1;
1532 pline("%s hurls %s!", Monnam(mtmp), singular(otmp, doname));
1534 m_throw(mtmp, mtmp->mx, mtmp->my, sgn(mtmp->mux - mtmp->mx),
1535 sgn(mtmp->muy - mtmp->my),
1536 distmin(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy), otmp);
1537 return 2;
1538 case 0:
1539 return 0; /* i.e. an exploded wand */
1540 default:
1541 impossible("%s wanted to perform action %d?", Monnam(mtmp),
1542 m.has_offense);
1543 break;
1545 return 0;
1549 rnd_offensive_item(mtmp)
1550 struct monst *mtmp;
1552 struct permonst *pm = mtmp->data;
1553 int difficulty = monstr[(monsndx(pm))];
1555 if (is_animal(pm) || attacktype(pm, AT_EXPL) || mindless(mtmp->data)
1556 || pm->mlet == S_GHOST || pm->mlet == S_KOP)
1557 return 0;
1558 if (difficulty > 7 && !rn2(35))
1559 return WAN_DEATH;
1560 switch (rn2(9 - (difficulty < 4) + 4 * (difficulty > 6))) {
1561 case 0: {
1562 struct obj *helmet = which_armor(mtmp, W_ARMH);
1564 if ((helmet && is_metallic(helmet)) || amorphous(pm)
1565 || passes_walls(pm) || noncorporeal(pm) || unsolid(pm))
1566 return SCR_EARTH;
1567 } /* fall through */
1568 case 1:
1569 return WAN_STRIKING;
1570 case 2:
1571 return POT_ACID;
1572 case 3:
1573 return POT_CONFUSION;
1574 case 4:
1575 return POT_BLINDNESS;
1576 case 5:
1577 return POT_SLEEPING;
1578 case 6:
1579 return POT_PARALYSIS;
1580 case 7:
1581 case 8:
1582 return WAN_MAGIC_MISSILE;
1583 case 9:
1584 return WAN_SLEEP;
1585 case 10:
1586 return WAN_FIRE;
1587 case 11:
1588 return WAN_COLD;
1589 case 12:
1590 return WAN_LIGHTNING;
1592 /*NOTREACHED*/
1593 return 0;
1596 #define MUSE_POT_GAIN_LEVEL 1
1597 #define MUSE_WAN_MAKE_INVISIBLE 2
1598 #define MUSE_POT_INVISIBILITY 3
1599 #define MUSE_POLY_TRAP 4
1600 #define MUSE_WAN_POLYMORPH 5
1601 #define MUSE_POT_SPEED 6
1602 #define MUSE_WAN_SPEED_MONSTER 7
1603 #define MUSE_BULLWHIP 8
1604 #define MUSE_POT_POLYMORPH 9
1606 boolean
1607 find_misc(mtmp)
1608 struct monst *mtmp;
1610 register struct obj *obj;
1611 struct permonst *mdat = mtmp->data;
1612 int x = mtmp->mx, y = mtmp->my;
1613 struct trap *t;
1614 int xx, yy, pmidx = NON_PM;
1615 boolean immobile = (mdat->mmove == 0);
1616 boolean stuck = (mtmp == u.ustuck);
1618 m.misc = (struct obj *) 0;
1619 m.has_misc = 0;
1620 if (is_animal(mdat) || mindless(mdat))
1621 return 0;
1622 if (u.uswallow && stuck)
1623 return FALSE;
1625 /* We arbitrarily limit to times when a player is nearby for the
1626 * same reason as Junior Pac-Man doesn't have energizers eaten until
1627 * you can see them...
1629 if (dist2(x, y, mtmp->mux, mtmp->muy) > 36)
1630 return FALSE;
1632 if (!stuck && !immobile && (mtmp->cham == NON_PM)
1633 && monstr[(pmidx = monsndx(mdat))] < 6) {
1634 boolean ignore_boulders = (verysmall(mdat) || throws_rocks(mdat)
1635 || passes_walls(mdat)),
1636 diag_ok = !NODIAG(pmidx);
1638 for (xx = x - 1; xx <= x + 1; xx++)
1639 for (yy = y - 1; yy <= y + 1; yy++)
1640 if (isok(xx, yy) && (xx != u.ux || yy != u.uy)
1641 && (diag_ok || xx == x || yy == y)
1642 && ((xx == x && yy == y) || !level.monsters[xx][yy]))
1643 if ((t = t_at(xx, yy)) != 0
1644 && (ignore_boulders || !sobj_at(BOULDER, xx, yy))
1645 && !onscary(xx, yy, mtmp)) {
1646 /* use trap if it's the correct type */
1647 if (t->ttyp == POLY_TRAP) {
1648 trapx = xx;
1649 trapy = yy;
1650 m.has_misc = MUSE_POLY_TRAP;
1651 return TRUE;
1655 if (nohands(mdat))
1656 return 0;
1658 #define nomore(x) if (m.has_misc == x) continue
1660 * [bug?] Choice of item is not prioritized; the last viable one
1661 * in the monster's inventory will be chosen.
1662 * 'nomore()' is nearly worthless because it only screens checking
1663 * of duplicates when there is no alternate type in between them.
1665 for (obj = mtmp->minvent; obj; obj = obj->nobj) {
1666 /* Monsters shouldn't recognize cursed items; this kludge is
1667 necessary to prevent serious problems though... */
1668 if (obj->otyp == POT_GAIN_LEVEL
1669 && (!obj->cursed
1670 || (!mtmp->isgd && !mtmp->isshk && !mtmp->ispriest))) {
1671 m.misc = obj;
1672 m.has_misc = MUSE_POT_GAIN_LEVEL;
1674 nomore(MUSE_BULLWHIP);
1675 if (obj->otyp == BULLWHIP && !mtmp->mpeaceful
1676 /* the random test prevents whip-wielding
1677 monster from attempting disarm every turn */
1678 && uwep && !rn2(5) && obj == MON_WEP(mtmp)
1679 /* hero's location must be known and adjacent */
1680 && mtmp->mux == u.ux && mtmp->muy == u.uy
1681 && distu(mtmp->mx, mtmp->my) <= 2
1682 /* don't bother if it can't work (this doesn't
1683 prevent cursed weapons from being targetted) */
1684 && (canletgo(uwep, "")
1685 || (u.twoweap && canletgo(uswapwep, "")))) {
1686 m.misc = obj;
1687 m.has_misc = MUSE_BULLWHIP;
1689 /* Note: peaceful/tame monsters won't make themselves
1690 * invisible unless you can see them. Not really right, but...
1692 nomore(MUSE_WAN_MAKE_INVISIBLE);
1693 if (obj->otyp == WAN_MAKE_INVISIBLE && obj->spe > 0 && !mtmp->minvis
1694 && !mtmp->invis_blkd && (!mtmp->mpeaceful || See_invisible)
1695 && (!attacktype(mtmp->data, AT_GAZE) || mtmp->mcan)) {
1696 m.misc = obj;
1697 m.has_misc = MUSE_WAN_MAKE_INVISIBLE;
1699 nomore(MUSE_POT_INVISIBILITY);
1700 if (obj->otyp == POT_INVISIBILITY && !mtmp->minvis
1701 && !mtmp->invis_blkd && (!mtmp->mpeaceful || See_invisible)
1702 && (!attacktype(mtmp->data, AT_GAZE) || mtmp->mcan)) {
1703 m.misc = obj;
1704 m.has_misc = MUSE_POT_INVISIBILITY;
1706 nomore(MUSE_WAN_SPEED_MONSTER);
1707 if (obj->otyp == WAN_SPEED_MONSTER && obj->spe > 0
1708 && mtmp->mspeed != MFAST && !mtmp->isgd) {
1709 m.misc = obj;
1710 m.has_misc = MUSE_WAN_SPEED_MONSTER;
1712 nomore(MUSE_POT_SPEED);
1713 if (obj->otyp == POT_SPEED && mtmp->mspeed != MFAST && !mtmp->isgd) {
1714 m.misc = obj;
1715 m.has_misc = MUSE_POT_SPEED;
1717 nomore(MUSE_WAN_POLYMORPH);
1718 if (obj->otyp == WAN_POLYMORPH && obj->spe > 0
1719 && (mtmp->cham == NON_PM) && monstr[monsndx(mdat)] < 6) {
1720 m.misc = obj;
1721 m.has_misc = MUSE_WAN_POLYMORPH;
1723 nomore(MUSE_POT_POLYMORPH);
1724 if (obj->otyp == POT_POLYMORPH && (mtmp->cham == NON_PM)
1725 && monstr[monsndx(mdat)] < 6) {
1726 m.misc = obj;
1727 m.has_misc = MUSE_POT_POLYMORPH;
1730 return (boolean) !!m.has_misc;
1731 #undef nomore
1734 /* type of monster to polymorph into; defaults to one suitable for the
1735 current level rather than the totally arbitrary choice of newcham() */
1736 static struct permonst *
1737 muse_newcham_mon(mon)
1738 struct monst *mon;
1740 struct obj *m_armr;
1742 if ((m_armr = which_armor(mon, W_ARM)) != 0) {
1743 if (Is_dragon_scales(m_armr))
1744 return Dragon_scales_to_pm(m_armr);
1745 else if (Is_dragon_mail(m_armr))
1746 return Dragon_mail_to_pm(m_armr);
1748 return rndmonst();
1752 use_misc(mtmp)
1753 struct monst *mtmp;
1755 int i;
1756 struct obj *otmp = m.misc;
1757 boolean vis, vismon, oseen;
1758 char nambuf[BUFSZ];
1760 if ((i = precheck(mtmp, otmp)) != 0)
1761 return i;
1762 vis = cansee(mtmp->mx, mtmp->my);
1763 vismon = canseemon(mtmp);
1764 oseen = otmp && vismon;
1766 switch (m.has_misc) {
1767 case MUSE_POT_GAIN_LEVEL:
1768 mquaffmsg(mtmp, otmp);
1769 if (otmp->cursed) {
1770 if (Can_rise_up(mtmp->mx, mtmp->my, &u.uz)) {
1771 register int tolev = depth(&u.uz) - 1;
1772 d_level tolevel;
1774 get_level(&tolevel, tolev);
1775 /* insurance against future changes... */
1776 if (on_level(&tolevel, &u.uz))
1777 goto skipmsg;
1778 if (vismon) {
1779 pline("%s rises up, through the %s!", Monnam(mtmp),
1780 ceiling(mtmp->mx, mtmp->my));
1781 if (!objects[POT_GAIN_LEVEL].oc_name_known
1782 && !objects[POT_GAIN_LEVEL].oc_uname)
1783 docall(otmp);
1785 m_useup(mtmp, otmp);
1786 migrate_to_level(mtmp, ledger_no(&tolevel), MIGR_RANDOM,
1787 (coord *) 0);
1788 return 2;
1789 } else {
1790 skipmsg:
1791 if (vismon) {
1792 pline("%s looks uneasy.", Monnam(mtmp));
1793 if (!objects[POT_GAIN_LEVEL].oc_name_known
1794 && !objects[POT_GAIN_LEVEL].oc_uname)
1795 docall(otmp);
1797 m_useup(mtmp, otmp);
1798 return 2;
1801 if (vismon)
1802 pline("%s seems more experienced.", Monnam(mtmp));
1803 if (oseen)
1804 makeknown(POT_GAIN_LEVEL);
1805 m_useup(mtmp, otmp);
1806 if (!grow_up(mtmp, (struct monst *) 0))
1807 return 1;
1808 /* grew into genocided monster */
1809 return 2;
1810 case MUSE_WAN_MAKE_INVISIBLE:
1811 case MUSE_POT_INVISIBILITY:
1812 if (otmp->otyp == WAN_MAKE_INVISIBLE) {
1813 mzapmsg(mtmp, otmp, TRUE);
1814 otmp->spe--;
1815 } else
1816 mquaffmsg(mtmp, otmp);
1817 /* format monster's name before altering its visibility */
1818 Strcpy(nambuf, mon_nam(mtmp));
1819 mon_set_minvis(mtmp);
1820 if (vismon && mtmp->minvis) { /* was seen, now invisible */
1821 if (canspotmon(mtmp))
1822 pline("%s body takes on a %s transparency.",
1823 upstart(s_suffix(nambuf)),
1824 Hallucination ? "normal" : "strange");
1825 else
1826 pline("Suddenly you cannot see %s.", nambuf);
1827 if (oseen)
1828 makeknown(otmp->otyp);
1830 if (otmp->otyp == POT_INVISIBILITY) {
1831 if (otmp->cursed)
1832 you_aggravate(mtmp);
1833 m_useup(mtmp, otmp);
1835 return 2;
1836 case MUSE_WAN_SPEED_MONSTER:
1837 mzapmsg(mtmp, otmp, TRUE);
1838 otmp->spe--;
1839 mon_adjust_speed(mtmp, 1, otmp);
1840 return 2;
1841 case MUSE_POT_SPEED:
1842 mquaffmsg(mtmp, otmp);
1843 /* note difference in potion effect due to substantially
1844 different methods of maintaining speed ratings:
1845 player's character becomes "very fast" temporarily;
1846 monster becomes "one stage faster" permanently */
1847 mon_adjust_speed(mtmp, 1, otmp);
1848 m_useup(mtmp, otmp);
1849 return 2;
1850 case MUSE_WAN_POLYMORPH:
1851 mzapmsg(mtmp, otmp, TRUE);
1852 otmp->spe--;
1853 (void) newcham(mtmp, muse_newcham_mon(mtmp), TRUE, FALSE);
1854 if (oseen)
1855 makeknown(WAN_POLYMORPH);
1856 return 2;
1857 case MUSE_POT_POLYMORPH:
1858 mquaffmsg(mtmp, otmp);
1859 if (vismon)
1860 pline("%s suddenly mutates!", Monnam(mtmp));
1861 (void) newcham(mtmp, muse_newcham_mon(mtmp), FALSE, FALSE);
1862 if (oseen)
1863 makeknown(POT_POLYMORPH);
1864 m_useup(mtmp, otmp);
1865 return 2;
1866 case MUSE_POLY_TRAP:
1867 if (vismon) {
1868 const char *Mnam = Monnam(mtmp);
1870 pline("%s deliberately %s onto a polymorph trap!", Mnam,
1871 vtense(Mnam, locomotion(mtmp->data, "jump")));
1873 if (vis)
1874 seetrap(t_at(trapx, trapy));
1876 /* don't use rloc() due to worms */
1877 remove_monster(mtmp->mx, mtmp->my);
1878 newsym(mtmp->mx, mtmp->my);
1879 place_monster(mtmp, trapx, trapy);
1880 if (mtmp->wormno)
1881 worm_move(mtmp);
1882 newsym(trapx, trapy);
1884 (void) newcham(mtmp, (struct permonst *) 0, FALSE, FALSE);
1885 return 2;
1886 case MUSE_BULLWHIP:
1887 /* attempt to disarm hero */
1889 const char *The_whip = vismon ? "The bullwhip" : "A whip";
1890 int where_to = rn2(4);
1891 struct obj *obj = uwep;
1892 const char *hand;
1893 char the_weapon[BUFSZ];
1895 if (!obj || !canletgo(obj, "")
1896 || (u.twoweap && canletgo(uswapwep, "") && rn2(2)))
1897 obj = uswapwep;
1898 if (!obj)
1899 break; /* shouldn't happen after find_misc() */
1901 Strcpy(the_weapon, the(xname(obj)));
1902 hand = body_part(HAND);
1903 if (bimanual(obj))
1904 hand = makeplural(hand);
1906 if (vismon)
1907 pline("%s flicks a bullwhip towards your %s!", Monnam(mtmp),
1908 hand);
1909 if (obj->otyp == HEAVY_IRON_BALL) {
1910 pline("%s fails to wrap around %s.", The_whip, the_weapon);
1911 return 1;
1913 pline("%s wraps around %s you're wielding!", The_whip,
1914 the_weapon);
1915 if (welded(obj)) {
1916 pline("%s welded to your %s%c",
1917 !is_plural(obj) ? "It is" : "They are", hand,
1918 !obj->bknown ? '!' : '.');
1919 /* obj->bknown = 1; */ /* welded() takes care of this */
1920 where_to = 0;
1922 if (!where_to) {
1923 pline_The("whip slips free."); /* not `The_whip' */
1924 return 1;
1925 } else if (where_to == 3 && mon_hates_silver(mtmp)
1926 && objects[obj->otyp].oc_material == SILVER) {
1927 /* this monster won't want to catch a silver
1928 weapon; drop it at hero's feet instead */
1929 where_to = 2;
1931 remove_worn_item(obj, FALSE);
1932 freeinv(obj);
1933 switch (where_to) {
1934 case 1: /* onto floor beneath mon */
1935 pline("%s yanks %s from your %s!", Monnam(mtmp), the_weapon,
1936 hand);
1937 place_object(obj, mtmp->mx, mtmp->my);
1938 break;
1939 case 2: /* onto floor beneath you */
1940 pline("%s yanks %s to the %s!", Monnam(mtmp), the_weapon,
1941 surface(u.ux, u.uy));
1942 dropy(obj);
1943 break;
1944 case 3: /* into mon's inventory */
1945 pline("%s snatches %s!", Monnam(mtmp), the_weapon);
1946 (void) mpickobj(mtmp, obj);
1947 break;
1949 return 1;
1951 return 0;
1952 case 0:
1953 return 0; /* i.e. an exploded wand */
1954 default:
1955 impossible("%s wanted to perform action %d?", Monnam(mtmp),
1956 m.has_misc);
1957 break;
1959 return 0;
1962 STATIC_OVL void
1963 you_aggravate(mtmp)
1964 struct monst *mtmp;
1966 pline("For some reason, %s presence is known to you.",
1967 s_suffix(noit_mon_nam(mtmp)));
1968 cls();
1969 #ifdef CLIPPING
1970 cliparound(mtmp->mx, mtmp->my);
1971 #endif
1972 show_glyph(mtmp->mx, mtmp->my, mon_to_glyph(mtmp));
1973 display_self();
1974 You_feel("aggravated at %s.", noit_mon_nam(mtmp));
1975 display_nhwindow(WIN_MAP, TRUE);
1976 docrt();
1977 if (unconscious()) {
1978 multi = -1;
1979 nomovemsg = "Aggravated, you are jolted into full consciousness.";
1981 newsym(mtmp->mx, mtmp->my);
1982 if (!canspotmon(mtmp))
1983 map_invisible(mtmp->mx, mtmp->my);
1987 rnd_misc_item(mtmp)
1988 struct monst *mtmp;
1990 struct permonst *pm = mtmp->data;
1991 int difficulty = monstr[(monsndx(pm))];
1993 if (is_animal(pm) || attacktype(pm, AT_EXPL) || mindless(mtmp->data)
1994 || pm->mlet == S_GHOST || pm->mlet == S_KOP)
1995 return 0;
1996 /* Unlike other rnd_item functions, we only allow _weak_ monsters
1997 * to have this item; after all, the item will be used to strengthen
1998 * the monster and strong monsters won't use it at all...
2000 if (difficulty < 6 && !rn2(30))
2001 return rn2(6) ? POT_POLYMORPH : WAN_POLYMORPH;
2003 if (!rn2(40) && !nonliving(pm) && !is_vampshifter(mtmp))
2004 return AMULET_OF_LIFE_SAVING;
2006 switch (rn2(3)) {
2007 case 0:
2008 if (mtmp->isgd)
2009 return 0;
2010 return rn2(6) ? POT_SPEED : WAN_SPEED_MONSTER;
2011 case 1:
2012 if (mtmp->mpeaceful && !See_invisible)
2013 return 0;
2014 return rn2(6) ? POT_INVISIBILITY : WAN_MAKE_INVISIBLE;
2015 case 2:
2016 return POT_GAIN_LEVEL;
2018 /*NOTREACHED*/
2019 return 0;
2022 boolean
2023 searches_for_item(mon, obj)
2024 struct monst *mon;
2025 struct obj *obj;
2027 int typ = obj->otyp;
2029 if (is_animal(mon->data) || mindless(mon->data)
2030 || mon->data == &mons[PM_GHOST]) /* don't loot bones piles */
2031 return FALSE;
2033 if (typ == WAN_MAKE_INVISIBLE || typ == POT_INVISIBILITY)
2034 return (boolean) (!mon->minvis && !mon->invis_blkd
2035 && !attacktype(mon->data, AT_GAZE));
2036 if (typ == WAN_SPEED_MONSTER || typ == POT_SPEED)
2037 return (boolean) (mon->mspeed != MFAST);
2039 switch (obj->oclass) {
2040 case WAND_CLASS:
2041 if (obj->spe <= 0)
2042 return FALSE;
2043 if (typ == WAN_DIGGING)
2044 return (boolean) !is_floater(mon->data);
2045 if (typ == WAN_POLYMORPH)
2046 return (boolean) (monstr[monsndx(mon->data)] < 6);
2047 if (objects[typ].oc_dir == RAY || typ == WAN_STRIKING
2048 || typ == WAN_TELEPORTATION || typ == WAN_CREATE_MONSTER)
2049 return TRUE;
2050 break;
2051 case POTION_CLASS:
2052 if (typ == POT_HEALING || typ == POT_EXTRA_HEALING
2053 || typ == POT_FULL_HEALING || typ == POT_POLYMORPH
2054 || typ == POT_GAIN_LEVEL || typ == POT_PARALYSIS
2055 || typ == POT_SLEEPING || typ == POT_ACID || typ == POT_CONFUSION)
2056 return TRUE;
2057 if (typ == POT_BLINDNESS && !attacktype(mon->data, AT_GAZE))
2058 return TRUE;
2059 break;
2060 case SCROLL_CLASS:
2061 if (typ == SCR_TELEPORTATION || typ == SCR_CREATE_MONSTER
2062 || typ == SCR_EARTH || typ == SCR_FIRE)
2063 return TRUE;
2064 break;
2065 case AMULET_CLASS:
2066 if (typ == AMULET_OF_LIFE_SAVING)
2067 return (boolean) !(nonliving(mon->data) || is_vampshifter(mon));
2068 if (typ == AMULET_OF_REFLECTION)
2069 return TRUE;
2070 break;
2071 case TOOL_CLASS:
2072 if (typ == PICK_AXE)
2073 return (boolean) needspick(mon->data);
2074 if (typ == UNICORN_HORN)
2075 return (boolean) (!obj->cursed && !is_unicorn(mon->data));
2076 if (typ == FROST_HORN || typ == FIRE_HORN)
2077 return (obj->spe > 0 && can_blow(mon));
2078 break;
2079 case FOOD_CLASS:
2080 if (typ == CORPSE)
2081 return (boolean) (((mon->misc_worn_check & W_ARMG) != 0L
2082 && touch_petrifies(&mons[obj->corpsenm]))
2083 || (!resists_ston(mon)
2084 && cures_stoning(mon, obj, FALSE)));
2085 if (typ == TIN)
2086 return (boolean) (mcould_eat_tin(mon)
2087 && (!resists_ston(mon)
2088 && cures_stoning(mon, obj, TRUE)));
2089 if (typ == EGG)
2090 return (boolean) touch_petrifies(&mons[obj->corpsenm]);
2091 break;
2092 default:
2093 break;
2096 return FALSE;
2099 boolean
2100 mon_reflects(mon, str)
2101 struct monst *mon;
2102 const char *str;
2104 struct obj *orefl = which_armor(mon, W_ARMS);
2106 if (orefl && orefl->otyp == SHIELD_OF_REFLECTION) {
2107 if (str) {
2108 pline(str, s_suffix(mon_nam(mon)), "shield");
2109 makeknown(SHIELD_OF_REFLECTION);
2111 return TRUE;
2112 } else if (arti_reflects(MON_WEP(mon))) {
2113 /* due to wielded artifact weapon */
2114 if (str)
2115 pline(str, s_suffix(mon_nam(mon)), "weapon");
2116 return TRUE;
2117 } else if ((orefl = which_armor(mon, W_AMUL))
2118 && orefl->otyp == AMULET_OF_REFLECTION) {
2119 if (str) {
2120 pline(str, s_suffix(mon_nam(mon)), "amulet");
2121 makeknown(AMULET_OF_REFLECTION);
2123 return TRUE;
2124 } else if ((orefl = which_armor(mon, W_ARM))
2125 && (orefl->otyp == SILVER_DRAGON_SCALES
2126 || orefl->otyp == SILVER_DRAGON_SCALE_MAIL)) {
2127 if (str)
2128 pline(str, s_suffix(mon_nam(mon)), "armor");
2129 return TRUE;
2130 } else if (mon->data == &mons[PM_SILVER_DRAGON]
2131 || mon->data == &mons[PM_CHROMATIC_DRAGON]) {
2132 /* Silver dragons only reflect when mature; babies do not */
2133 if (str)
2134 pline(str, s_suffix(mon_nam(mon)), "scales");
2135 return TRUE;
2137 return FALSE;
2140 boolean
2141 ureflects(fmt, str)
2142 const char *fmt, *str;
2144 /* Check from outermost to innermost objects */
2145 if (EReflecting & W_ARMS) {
2146 if (fmt && str) {
2147 pline(fmt, str, "shield");
2148 makeknown(SHIELD_OF_REFLECTION);
2150 return TRUE;
2151 } else if (EReflecting & W_WEP) {
2152 /* Due to wielded artifact weapon */
2153 if (fmt && str)
2154 pline(fmt, str, "weapon");
2155 return TRUE;
2156 } else if (EReflecting & W_AMUL) {
2157 if (fmt && str) {
2158 pline(fmt, str, "medallion");
2159 makeknown(AMULET_OF_REFLECTION);
2161 return TRUE;
2162 } else if (EReflecting & W_ARM) {
2163 if (fmt && str)
2164 pline(fmt, str, uskin ? "luster" : "armor");
2165 return TRUE;
2166 } else if (youmonst.data == &mons[PM_SILVER_DRAGON]) {
2167 if (fmt && str)
2168 pline(fmt, str, "scales");
2169 return TRUE;
2171 return FALSE;
2174 /* TRUE if the monster ate something */
2175 boolean
2176 munstone(mon, by_you)
2177 struct monst *mon;
2178 boolean by_you;
2180 struct obj *obj;
2181 boolean tinok;
2183 if (resists_ston(mon))
2184 return FALSE;
2185 if (mon->meating || !mon->mcanmove || mon->msleeping)
2186 return FALSE;
2187 mon->mstrategy &= ~STRAT_WAITFORU;
2189 tinok = mcould_eat_tin(mon);
2190 for (obj = mon->minvent; obj; obj = obj->nobj) {
2191 if (cures_stoning(mon, obj, tinok)) {
2192 mon_consume_unstone(mon, obj, by_you, TRUE);
2193 return TRUE;
2196 return FALSE;
2199 STATIC_OVL void
2200 mon_consume_unstone(mon, obj, by_you, stoning)
2201 struct monst *mon;
2202 struct obj *obj;
2203 boolean by_you;
2204 boolean stoning;
2206 boolean vis = canseemon(mon), tinned = obj->otyp == TIN,
2207 food = obj->otyp == CORPSE || tinned,
2208 acid = obj->otyp == POT_ACID
2209 || (food && acidic(&mons[obj->corpsenm])),
2210 lizard = food && obj->corpsenm == PM_LIZARD;
2211 int nutrit = food ? dog_nutrition(mon, obj) : 0; /* also sets meating */
2213 /* give a "<mon> is slowing down" message and also remove
2214 intrinsic speed (comparable to similar effect on the hero) */
2215 if (stoning)
2216 mon_adjust_speed(mon, -3, (struct obj *) 0);
2218 if (vis) {
2219 long save_quan = obj->quan;
2221 obj->quan = 1L;
2222 pline("%s %s %s.", Monnam(mon),
2223 (obj->oclass == POTION_CLASS)
2224 ? "quaffs"
2225 : (obj->otyp == TIN) ? "opens and eats the contents of"
2226 : "eats",
2227 distant_name(obj, doname));
2228 obj->quan = save_quan;
2229 } else if (!Deaf)
2230 You_hear("%s.",
2231 (obj->oclass == POTION_CLASS) ? "drinking" : "chewing");
2233 m_useup(mon, obj);
2234 /* obj is now gone */
2236 if (acid && !tinned && !resists_acid(mon)) {
2237 mon->mhp -= rnd(15);
2238 if (vis)
2239 pline("%s has a very bad case of stomach acid.", Monnam(mon));
2240 if (mon->mhp <= 0) {
2241 pline("%s dies!", Monnam(mon));
2242 if (by_you)
2243 xkilled(mon, 0);
2244 else
2245 mondead(mon);
2246 return;
2249 if (stoning && vis) {
2250 if (Hallucination)
2251 pline("What a pity - %s just ruined a future piece of art!",
2252 mon_nam(mon));
2253 else
2254 pline("%s seems limber!", Monnam(mon));
2256 if (lizard && (mon->mconf || mon->mstun)) {
2257 mon->mconf = 0;
2258 mon->mstun = 0;
2259 if (vis && !is_bat(mon->data) && mon->data != &mons[PM_STALKER])
2260 pline("%s seems steadier now.", Monnam(mon));
2262 if (mon->mtame && !mon->isminion && nutrit > 0) {
2263 struct edog *edog = EDOG(mon);
2265 if (edog->hungrytime < monstermoves)
2266 edog->hungrytime = monstermoves;
2267 edog->hungrytime += nutrit;
2268 mon->mconf = 0;
2270 /* use up monster's next move */
2271 mon->movement -= NORMAL_SPEED;
2272 mon->mlstmv = monstermoves;
2275 /* decide whether obj can cure petrification; also used when picking up */
2276 STATIC_OVL boolean
2277 cures_stoning(mon, obj, tinok)
2278 struct monst *mon;
2279 struct obj *obj;
2280 boolean tinok;
2282 if (obj->otyp == POT_ACID)
2283 return TRUE;
2284 if (obj->otyp != CORPSE && (obj->otyp != TIN || !tinok))
2285 return FALSE;
2286 /* corpse, or tin that mon can open */
2287 return (boolean) (obj->corpsenm == PM_LIZARD
2288 || (acidic(&mons[obj->corpsenm])
2289 && (obj->corpsenm != PM_GREEN_SLIME
2290 || slimeproof(mon->data))));
2293 STATIC_OVL boolean
2294 mcould_eat_tin(mon)
2295 struct monst *mon;
2297 struct obj *obj, *mwep;
2298 boolean welded_wep;
2300 /* monkeys who manage to steal tins can't open and eat them
2301 even if they happen to also have the appropriate tool */
2302 if (is_animal(mon->data))
2303 return FALSE;
2305 mwep = MON_WEP(mon);
2306 welded_wep = mwep && mwelded(mwep);
2307 /* this is different from the player; tin opener or dagger doesn't
2308 have to be wielded, and knife can be used instead of dagger */
2309 for (obj = mon->minvent; obj; obj = obj->nobj) {
2310 /* if stuck with a cursed weapon, don't check rest of inventory */
2311 if (welded_wep && obj != mwep)
2312 continue;
2314 if (obj->otyp == TIN_OPENER
2315 || (obj->oclass == WEAPON_CLASS
2316 && (objects[obj->otyp].oc_skill == P_DAGGER
2317 || objects[obj->otyp].oc_skill == P_KNIFE)))
2318 return TRUE;
2320 return FALSE;
2323 /* TRUE if monster does something to avoid turning into green slime */
2324 boolean
2325 munslime(mon, by_you)
2326 struct monst *mon;
2327 boolean by_you;
2329 struct obj *obj, odummy;
2330 struct permonst *mptr = mon->data;
2333 * muse_unslime() gives "mon starts turning green", "mon zaps
2334 * itself with a wand of fire", and "mon's slime burns away"
2335 * messages. Monsters who don't get any chance at that just have
2336 * (via our caller) newcham()'s "mon turns into slime" feedback.
2339 if (slimeproof(mptr))
2340 return FALSE;
2341 if (mon->meating || !mon->mcanmove || mon->msleeping)
2342 return FALSE;
2343 mon->mstrategy &= ~STRAT_WAITFORU;
2345 /* if monster can breathe fire, do so upon self; a monster who deals
2346 fire damage by biting, clawing, gazing, and especially exploding
2347 isn't able to cure itself of green slime with its own attack
2348 [possible extension: monst capable of casting high level clerical
2349 spells could toss pillar of fire at self--probably too suicidal] */
2350 if (!mon->mcan && !mon->mspec_used
2351 && attacktype_fordmg(mptr, AT_BREA, AD_FIRE)) {
2352 odummy = zeroobj; /* otyp == STRANGE_OBJECT */
2353 return muse_unslime(mon, &odummy, (struct trap *) 0, by_you);
2356 /* same MUSE criteria as use_defensive() */
2357 if (!is_animal(mptr) && !mindless(mptr)) {
2358 struct trap *t;
2360 for (obj = mon->minvent; obj; obj = obj->nobj)
2361 if (cures_sliming(mon, obj))
2362 return muse_unslime(mon, obj, (struct trap *) 0, by_you);
2364 if (((t = t_at(mon->mx, mon->my)) == 0 || t->ttyp != FIRE_TRAP)
2365 && !mon->mtrapped && !mptr->mmove == 0) {
2366 int xy[2][8], x, y, idx, ridx, nxy = 0;
2368 for (x = mon->mx - 1; x <= mon->mx + 1; ++x)
2369 for (y = mon->my - 1; y <= mon->my + 1; ++y)
2370 if (isok(x, y) && accessible(x, y)
2371 && !m_at(x, y) && (x != u.ux || y != u.uy)) {
2372 xy[0][nxy] = x, xy[1][nxy] = y;
2373 ++nxy;
2375 for (idx = 0; idx < nxy; ++idx) {
2376 ridx = rn1(nxy - idx, idx);
2377 if (ridx != idx) {
2378 x = xy[0][idx];
2379 xy[0][idx] = xy[0][ridx];
2380 xy[0][ridx] = x;
2381 y = xy[1][idx];
2382 xy[1][idx] = xy[1][ridx];
2383 xy[1][ridx] = y;
2385 if ((t = t_at(xy[0][idx], xy[1][idx])) != 0
2386 && t->ttyp == FIRE_TRAP)
2387 break;
2390 if (t && t->ttyp == FIRE_TRAP)
2391 return muse_unslime(mon, &zeroobj, t, by_you);
2393 } /* MUSE */
2395 return FALSE;
2398 /* mon uses an item--selected by caller--to burn away incipient slime */
2399 STATIC_OVL boolean
2400 muse_unslime(mon, obj, trap, by_you)
2401 struct monst *mon;
2402 struct obj *obj;
2403 struct trap *trap;
2404 boolean by_you; /* true: if mon kills itself, hero gets credit/blame */
2405 { /* [by_you not honored if 'mon' triggers fire trap]. */
2406 struct obj *odummyp;
2407 int otyp = obj->otyp, dmg;
2408 boolean vis = canseemon(mon), res = TRUE;
2410 if (vis)
2411 pline("%s starts turning %s.", Monnam(mon),
2412 green_mon(mon) ? "into ooze" : hcolor(NH_GREEN));
2413 /* -4 => sliming, causes quiet loss of enhanced speed */
2414 mon_adjust_speed(mon, -4, (struct obj *) 0);
2416 if (trap) {
2417 const char *Mnam = vis ? Monnam(mon) : 0;
2419 if (mon->mx == trap->tx && mon->my == trap->ty) {
2420 if (vis)
2421 pline("%s triggers %s fire trap!", Mnam,
2422 trap->tseen ? "the" : "a");
2423 } else {
2424 remove_monster(mon->mx, mon->my);
2425 newsym(mon->mx, mon->my);
2426 place_monster(mon, trap->tx, trap->ty);
2427 if (mon->wormno) /* won't happen; worms don't MUSE to unslime */
2428 worm_move(mon);
2429 newsym(mon->mx, mon->my);
2430 if (vis)
2431 pline("%s %s %s %s fire trap!", Mnam,
2432 vtense(Mnam, locomotion(mon->data, "move")),
2433 is_floater(mon->data) ? "over" : "onto",
2434 trap->tseen ? "the" : "a");
2436 /* hack to avoid mintrap()'s chance of avoiding known trap */
2437 mon->mtrapseen &= ~(1 << (FIRE_TRAP - 1));
2438 mintrap(mon);
2439 } else if (otyp == STRANGE_OBJECT) {
2440 /* monster is using fire breath on self */
2441 if (vis)
2442 pline("%s breathes fire on %sself.", Monnam(mon), mhim(mon));
2443 if (!rn2(3))
2444 mon->mspec_used = rn1(10, 5);
2445 /* -21 => monster's fire breath; 1 => # of damage dice */
2446 (void) zhitm(mon, by_you ? 21 : -21, 1, &odummyp);
2447 } else if (otyp == SCR_FIRE) {
2448 mreadmsg(mon, obj);
2449 if (mon->mconf) {
2450 if (cansee(mon->mx, mon->my))
2451 pline("Oh, what a pretty fire!");
2452 if (vis && !objects[otyp].oc_name_known
2453 && !objects[otyp].oc_uname)
2454 docall(obj);
2455 m_useup(mon, obj); /* after docall() */
2456 vis = FALSE; /* skip makeknown() below */
2457 res = FALSE; /* failed to cure sliming */
2458 } else {
2459 m_useup(mon, obj); /* before explode() */
2460 dmg = (2 * (rn1(3, 3) + 2 * bcsign(obj)) + 1) / 3;
2461 /* -11 => monster's fireball */
2462 explode(mon->mx, mon->my, -11, dmg, SCROLL_CLASS,
2463 /* by_you: override -11 for mon but not others */
2464 by_you ? -EXPL_FIERY : EXPL_FIERY);
2466 } else { /* wand/horn of fire w/ positive charge count */
2467 mzapmsg(mon, obj, TRUE);
2468 obj->spe--;
2469 /* -1 => monster's wand of fire; 2 => # of damage dice */
2470 (void) zhitm(mon, by_you ? 1 : -1, 2, &odummyp);
2473 if (vis) {
2474 if (res && mon->mhp > 0)
2475 pline("%s slime is burned away!", s_suffix(Monnam(mon)));
2476 if (otyp != STRANGE_OBJECT)
2477 makeknown(otyp);
2479 /* use up monster's next move */
2480 mon->movement -= NORMAL_SPEED;
2481 mon->mlstmv = monstermoves;
2482 return res;
2485 /* decide whether obj can be used to cure green slime */
2486 STATIC_OVL int
2487 cures_sliming(mon, obj)
2488 struct monst *mon;
2489 struct obj *obj;
2491 /* scroll of fire, non-empty wand or horn of fire */
2492 if (obj->otyp == SCR_FIRE)
2493 return (haseyes(mon->data) && mon->mcansee);
2494 /* hero doesn't need hands or even limbs to zap, so mon doesn't either */
2495 return ((obj->otyp == WAN_FIRE
2496 || (obj->otyp == FIRE_HORN && can_blow(mon)))
2497 && obj->spe > 0);
2500 /* TRUE if monster appears to be green; for active TEXTCOLOR, we go by
2501 the display color, otherwise we just pick things that seem plausibly
2502 green (which doesn't necessarily match the TEXTCOLOR categorization) */
2503 STATIC_OVL boolean
2504 green_mon(mon)
2505 struct monst *mon;
2507 struct permonst *ptr = mon->data;
2509 if (Hallucination)
2510 return FALSE;
2511 #ifdef TEXTCOLOR
2512 if (iflags.use_color)
2513 return (ptr->mcolor == CLR_GREEN || ptr->mcolor == CLR_BRIGHT_GREEN);
2514 #endif
2515 /* approximation */
2516 if (strstri(ptr->mname, "green"))
2517 return TRUE;
2518 switch (monsndx(ptr)) {
2519 case PM_FOREST_CENTAUR:
2520 case PM_GARTER_SNAKE:
2521 case PM_GECKO:
2522 case PM_GREMLIN:
2523 case PM_HOMUNCULUS:
2524 case PM_JUIBLEX:
2525 case PM_LEPRECHAUN:
2526 case PM_LICHEN:
2527 case PM_LIZARD:
2528 case PM_WOOD_NYMPH:
2529 return TRUE;
2530 default:
2531 if (is_elf(ptr) && !is_prince(ptr) && !is_lord(ptr)
2532 && ptr != &mons[PM_GREY_ELF])
2533 return TRUE;
2534 break;
2536 return FALSE;
2539 /*muse.c*/