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