1    | /*	SCCS Id: @(#)muse.c	3.3	2000/06/02	*/
2    | /*	Copyright (C) 1990 by Ken Arromdee			   */
3    | /* NetHack may be freely redistributed.  See license for details.  */
4    | 
5    | /*
6    |  * Monster item usage routines.
7    |  */
8    | 
9    | #include "hack.h"
10   | #include "edog.h"
11   | 
12   | extern const int monstr[];
13   | 
14   | boolean m_using = FALSE;
15   | 
16   | /* Let monsters use magic items.  Arbitrary assumptions: Monsters only use
17   |  * scrolls when they can see, monsters know when wands have 0 charges, monsters
18   |  * cannot recognize if items are cursed are not, monsters which are confused
19   |  * don't know not to read scrolls, etc....
20   |  */
21   | 
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,
28   | 	(struct monst *,int,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   | 
32   | static struct musable {
33   | 	struct obj *offensive;
34   | 	struct obj *defensive;
35   | 	struct obj *misc;
36   | 	int has_offense, has_defense, has_misc;
37   | 	/* =0, no capability; otherwise, different numbers.
38   | 	 * If it's an object, the object is also set (it's 0 otherwise).
39   | 	 */
40   | } m;
41   | static int trapx, trapy;
42   | static boolean zap_oseen;
43   | 	/* for wands which use mbhitm and are zapped at players.  We usually
44   | 	 * want an oseen local to the function, but this is impossible since the
45   | 	 * function mbhitm has to be compatible with the normal zap routines,
46   | 	 * and those routines don't remember who zapped the wand.
47   | 	 */
48   | 
49   | /* Any preliminary checks which may result in the monster being unable to use
50   |  * the item.  Returns 0 if nothing happened, 2 if the monster can't do anything
51   |  * (i.e. it teleported) and 1 if it's dead.
52   |  */
53   | STATIC_OVL int
54   | precheck(mon, obj)
55   | struct monst *mon;
56   | struct obj *obj;
57   | {
58   | 	boolean vis;
59   | 
60   | 	if (!obj) return 0;
61   | 	vis = cansee(mon->mx, mon->my);
62   | 
63   | 	if (obj->oclass == POTION_CLASS) {
64   | 	    coord cc;
65   | 	    static const char *empty = "The potion turns out to be empty.";
66   | 	    const char *potion_descr;
67   | 	    struct monst *mtmp;
68   | #define POTION_OCCUPANT_CHANCE(n) (13 + 2*(n))	/* also in potion.c */
69   | 
70   | 	    potion_descr = OBJ_DESCR(objects[obj->otyp]);
71   | 	    if (potion_descr && !strcmp(potion_descr, "milky")) {
72   | 	        if ( flags.ghost_count < MAXMONNO &&
73   | 		    !rn2(POTION_OCCUPANT_CHANCE(flags.ghost_count))) {
74   | 		    if (!enexto(&cc, mon->mx, mon->my, &mons[PM_GHOST])) return 0;
75   | 		    mquaffmsg(mon, obj);
76   | 		    m_useup(mon, obj);
77   | 		    mtmp = makemon(&mons[PM_GHOST], cc.x, cc.y, NO_MM_FLAGS);
78   | 		    if (!mtmp) {
79   | 			if (vis) pline(empty);
80   | 		    } else {
81   | 			if (vis) {
82   | 			    pline("As %s opens the bottle, an enormous %s emerges!",
83   | 			       mon_nam(mon),
84   | 			       Hallucination ? rndmonnam() : (const char *)"ghost");
85   | 			    pline("%s is frightened to death, and unable to move.",
86   | 				    Monnam(mon));
87   | 			}
88   | 			mon->mcanmove = 0;
89   | 			mon->mfrozen = 3;
90   | 		    }
91   | 		    return 2;
92   | 		}
93   | 	    }
94   | 	    if (potion_descr && !strcmp(potion_descr, "smoky") &&
95   | 		    flags.djinni_count < MAXMONNO &&
96   | 		    !rn2(POTION_OCCUPANT_CHANCE(flags.djinni_count))) {
97   | 		if (!enexto(&cc, mon->mx, mon->my, &mons[PM_DJINNI])) return 0;
98   | 		mquaffmsg(mon, obj);
99   | 		m_useup(mon, obj);
100  | 		mtmp = makemon(&mons[PM_DJINNI], cc.x, cc.y, NO_MM_FLAGS);
101  | 		if (!mtmp) {
102  | 		    if (vis) pline(empty);
103  | 		} else {
104  | 		    if (vis)
105  | 			pline("In a cloud of smoke, %s emerges!",
106  | 							a_monnam(mtmp));
107  | 		    pline("%s speaks.", vis ? Monnam(mtmp) : Something);
108  | 		/* I suspect few players will be upset that monsters */
109  | 		/* can't wish for wands of death here.... */
110  | 		    if (rn2(2)) {
111  | 			verbalize("You freed me!");
112  | 			mtmp->mpeaceful = 1;
113  | 			set_malign(mtmp);
114  | 		    } else {
115  | 			verbalize("It is about time.");
116  | 			if (vis) pline("%s vanishes.", Monnam(mtmp));
117  | 			mongone(mtmp);
118  | 		    }
119  | 		}
120  | 		return 2;
121  | 	    }
122  | 	}
123  | 	if (obj->oclass == WAND_CLASS && obj->cursed && !rn2(100)) {
124  | 	    int dam = d(obj->spe+2, 6);
125  | 
126  | 	    if (flags.soundok) {
127  | 		if (vis) pline("%s zaps %s, which suddenly explodes!",
128  | 			Monnam(mon), an(xname(obj)));
129  | 		else You_hear("a zap and an explosion in the distance.");
130  | 	    }
131  | 	    m_useup(mon, obj);
132  | 	    if (mon->mhp <= dam) {
133  | 		monkilled(mon, "", AD_RBRE);
134  | 		return 1;
135  | 	    }
136  | 	    else mon->mhp -= dam;
137  | 	    m.has_defense = m.has_offense = m.has_misc = 0;
138  | 	    /* Only one needed to be set to 0 but the others are harmless */
139  | 	}
140  | 	return 0;
141  | }
142  | 
143  | STATIC_OVL void
144  | mzapmsg(mtmp, otmp, self)
145  | struct monst *mtmp;
146  | struct obj *otmp;
147  | boolean self;
148  | {
149  | 	if (!canseemon(mtmp)) {
150  | 		if (flags.soundok)
151  | 			You_hear("a %s zap.",
152  | 					(distu(mtmp->mx,mtmp->my) <= (BOLT_LIM+1)*(BOLT_LIM+1)) ?
153  | 					"nearby" : "distant");
154  | 	} else if (self)
155  | 		pline("%s zaps %sself with %s!",
156  | 		      Monnam(mtmp), him[pronoun_gender(mtmp)], doname(otmp));
157  | 	else {
158  | 		pline("%s zaps %s!", Monnam(mtmp), an(xname(otmp)));
159  | 		stop_occupation();
160  | 	}
161  | }
162  | 
163  | STATIC_OVL void
164  | mreadmsg(mtmp, otmp)
165  | struct monst *mtmp;
166  | struct obj *otmp;
167  | {
168  | 	boolean vismon = canseemon(mtmp);
169  | 	char onambuf[BUFSZ];
170  | 	short saverole;
171  | 	unsigned savebknown;
172  | 
173  | 	if (!vismon && !flags.soundok)
174  | 	    return;		/* no feedback */
175  | 
176  | 	otmp->dknown = 1;  /* seeing or hearing it read reveals its label */
177  | 	/* shouldn't be able to hear curse/bless status of unseen scrolls;
178  | 	   for priest characters, bknown will always be set during naming */
179  | 	savebknown = otmp->bknown;
180  | 	saverole = Role_switch;
181  | 	if (!vismon) {
182  | 	    otmp->bknown = 0;
183  | 	    if (Role_if(PM_PRIEST)) Role_switch = 0;
184  | 	}
185  | 	Strcpy(onambuf, singular(otmp, doname));
186  | 	Role_switch = saverole;
187  | 	otmp->bknown = savebknown;
188  | 
189  | 	if (vismon)
190  | 	    pline("%s reads %s!", Monnam(mtmp), onambuf);
191  | 	else
192  | 	    You_hear("%s reading %s.",
193  | 		x_monnam(mtmp, ARTICLE_A, (char *)0,
194  | 		    (SUPPRESS_IT|SUPPRESS_INVISIBLE|SUPPRESS_SADDLE), FALSE),
195  | 		onambuf);
196  | 
197  | 	if (mtmp->mconf)
198  | 	    pline("Being confused, %s mispronounces the magic words...",
199  | 		  vismon ? mon_nam(mtmp) : he[pronoun_gender(mtmp)]);
200  | }
201  | 
202  | STATIC_OVL void
203  | mquaffmsg(mtmp, otmp)
204  | struct monst *mtmp;
205  | struct obj *otmp;
206  | {
207  | 	if (canseemon(mtmp)) {
208  | 		otmp->dknown = 1;
209  | 		pline("%s drinks %s!", Monnam(mtmp), singular(otmp, doname));
210  | 	} else
211  | 		if (flags.soundok)
212  | 			You_hear("a chugging sound.");
213  | }
214  | 
215  | /* Defines for various types of stuff.  The order in which monsters prefer
216  |  * to use them is determined by the order of the code logic, not the
217  |  * numerical order in which they are defined.
218  |  */
219  | #define MUSE_SCR_TELEPORTATION 1
220  | #define MUSE_WAN_TELEPORTATION_SELF 2
221  | #define MUSE_POT_HEALING 3
222  | #define MUSE_POT_EXTRA_HEALING 4
223  | #define MUSE_WAN_DIGGING 5
224  | #define MUSE_TRAPDOOR 6
225  | #define MUSE_TELEPORT_TRAP 7
226  | #define MUSE_UPSTAIRS 8
227  | #define MUSE_DOWNSTAIRS 9
228  | #define MUSE_WAN_CREATE_MONSTER 10
229  | #define MUSE_SCR_CREATE_MONSTER 11
230  | #define MUSE_UP_LADDER 12
231  | #define MUSE_DN_LADDER 13
232  | #define MUSE_SSTAIRS 14
233  | #define MUSE_WAN_TELEPORTATION 15
234  | #define MUSE_BUGLE 16
235  | #define MUSE_UNICORN_HORN 17
236  | #define MUSE_POT_FULL_HEALING 18
237  | /*
238  | #define MUSE_INNATE_TPT 9999
239  |  * We cannot use this.  Since monsters get unlimited teleportation, if they
240  |  * were allowed to teleport at will you could never catch them.  Instead,
241  |  * assume they only teleport at random times, despite the inconsistency that if
242  |  * you polymorph into one you teleport at will.
243  |  */
244  | 
245  | /* Select a defensive item/action for a monster.  Returns TRUE iff one is
246  |  * found.
247  |  */
248  | boolean
249  | find_defensive(mtmp)
250  | struct monst *mtmp;
251  | {
252  | 	register struct obj *obj = 0;
253  | 	struct trap *t;
254  | 	int x=mtmp->mx, y=mtmp->my;
255  | 	boolean stuck = (mtmp == u.ustuck);
256  | 	boolean immobile = (mtmp->data->mmove == 0);
257  | 	int fraction;
258  | 
259  | 	if (is_animal(mtmp->data) || mindless(mtmp->data))
260  | 		return FALSE;
261  | 	if(dist2(x, y, mtmp->mux, mtmp->muy) > 25)
262  | 		return FALSE;
263  | 	if (u.uswallow && stuck) return FALSE;
264  | 
265  | 	m.defensive = (struct obj *)0;
266  | 	m.has_defense = 0;
267  | 
268  | 	/* since unicorn horns don't get used up, the monster would look
269  | 	 * silly trying to use the same cursed horn round after round
270  | 	 */
271  | 	if (mtmp->mconf || mtmp->mstun || !mtmp->mcansee) {
272  | 	    if (!is_unicorn(mtmp->data) && !nohands(mtmp->data)) {
273  | 		for(obj = mtmp->minvent; obj; obj = obj->nobj)
274  | 		    if (obj->otyp == UNICORN_HORN && !obj->cursed)
275  | 			break;
276  | 	    }
277  | 	    if (obj || is_unicorn(mtmp->data)) {
278  | 		m.defensive = obj;
279  | 		m.has_defense = MUSE_UNICORN_HORN;
280  | 		return TRUE;
281  | 	    }
282  | 	}
283  | 
284  | 	/* It so happens there are two unrelated cases when we might want to
285  | 	 * check specifically for healing alone.  The first is when the monster
286  | 	 * is blind (healing cures blindness).  The second is when the monster
287  | 	 * is peaceful; then we don't want to flee the player, and by
288  | 	 * coincidence healing is all there is that doesn't involve fleeing.
289  | 	 * These would be hard to combine because of the control flow.
290  | 	 * Pestilence won't use healing even when blind.
291  | 	 */
292  | 	if (!mtmp->mcansee && !nohands(mtmp->data) &&
293  | 		mtmp->data != &mons[PM_PESTILENCE]) {
294  | 	    if ((obj = m_carrying(mtmp, POT_FULL_HEALING)) != 0) {
295  | 		m.defensive = obj;
296  | 		m.has_defense = MUSE_POT_FULL_HEALING;
297  | 		return TRUE;
298  | 	    }
299  | 	    if ((obj = m_carrying(mtmp, POT_EXTRA_HEALING)) != 0) {
300  | 		m.defensive = obj;
301  | 		m.has_defense = MUSE_POT_EXTRA_HEALING;
302  | 		return TRUE;
303  | 	    }
304  | 	    if ((obj = m_carrying(mtmp, POT_HEALING)) != 0) {
305  | 		m.defensive = obj;
306  | 		m.has_defense = MUSE_POT_HEALING;
307  | 		return TRUE;
308  | 	    }
309  | 	}
310  | 
311  | 	fraction = u.ulevel < 10 ? 5 : u.ulevel < 14 ? 4 : 3;
312  | 	if(mtmp->mhp >= mtmp->mhpmax ||
313  | 			(mtmp->mhp >= 10 && mtmp->mhp*fraction >= mtmp->mhpmax))
314  | 		return FALSE;
315  | 
316  | 	if (mtmp->mpeaceful) {
317  | 	    if (!nohands(mtmp->data)) {
318  | 		if ((obj = m_carrying(mtmp, POT_FULL_HEALING)) != 0) {
319  | 		    m.defensive = obj;
320  | 		    m.has_defense = MUSE_POT_FULL_HEALING;
321  | 		    return TRUE;
322  | 		}
323  | 		if ((obj = m_carrying(mtmp, POT_EXTRA_HEALING)) != 0) {
324  | 		    m.defensive = obj;
325  | 		    m.has_defense = MUSE_POT_EXTRA_HEALING;
326  | 		    return TRUE;
327  | 		}
328  | 		if ((obj = m_carrying(mtmp, POT_HEALING)) != 0) {
329  | 		    m.defensive = obj;
330  | 		    m.has_defense = MUSE_POT_HEALING;
331  | 		    return TRUE;
332  | 		}
333  | 	    }
334  | 	    return FALSE;
335  | 	}
336  | 
337  | 	if (levl[x][y].typ == STAIRS && !stuck && !immobile) {
338  | 		if (x == xdnstair && y == ydnstair && !is_floater(mtmp->data))
339  | 			m.has_defense = MUSE_DOWNSTAIRS;
340  | 		if (x == xupstair && y == yupstair && ledger_no(&u.uz) != 1)
341  | 	/* Unfair to let the monsters leave the dungeon with the Amulet */
342  | 	/* (or go to the endlevel since you also need it, to get there) */
343  | 			m.has_defense = MUSE_UPSTAIRS;
344  | 	} else if (levl[x][y].typ == LADDER && !stuck && !immobile) {
345  | 		if (x == xupladder && y == yupladder)
346  | 			m.has_defense = MUSE_UP_LADDER;
347  | 		if (x == xdnladder && y == ydnladder && !is_floater(mtmp->data))
348  | 			m.has_defense = MUSE_DN_LADDER;
349  | 	} else if (sstairs.sx && sstairs.sx == x && sstairs.sy == y) {
350  | 		m.has_defense = MUSE_SSTAIRS;
351  | 	} else if (!stuck && !immobile) {
352  | 	/* Note: trap doors take precedence over teleport traps. */
353  | 		int xx, yy;
354  | 
355  | 		for(xx = x-1; xx <= x+1; xx++) for(yy = y-1; yy <= y+1; yy++)
356  | 		if (isok(xx,yy))
357  | 		if (xx != u.ux && yy != u.uy)
358  | 		if (mtmp->data != &mons[PM_GRID_BUG] || xx == x || yy == y)
359  | 		if ((xx==x && yy==y) || !level.monsters[xx][yy])
360  | 		if ((t = t_at(xx,yy)) != 0)
361  | 		if ((verysmall(mtmp->data) || throws_rocks(mtmp->data) ||
362  | 		     passes_walls(mtmp->data)) || !sobj_at(BOULDER, xx, yy))
363  | 		if (!onscary(xx,yy,mtmp)) {
364  | 			if ((t->ttyp == TRAPDOOR || t->ttyp == HOLE)
365  | 				&& !is_floater(mtmp->data)
366  | 				&& !mtmp->isshk && !mtmp->isgd
367  | 				&& !mtmp->ispriest
368  | 				&& Can_fall_thru(&u.uz)
369  | 						) {
370  | 				trapx = xx;
371  | 				trapy = yy;
372  | 				m.has_defense = MUSE_TRAPDOOR;
373  | 			} else if (t->ttyp == TELEP_TRAP && m.has_defense != MUSE_TRAPDOOR) {
374  | 				trapx = xx;
375  | 				trapy = yy;
376  | 				m.has_defense = MUSE_TELEPORT_TRAP;
377  | 			}
378  | 		}
379  | 	}
380  | 
381  | 	if (nohands(mtmp->data))	/* can't use objects */
382  | 		goto botm;
383  | 
384  | 	if (is_mercenary(mtmp->data) && (obj = m_carrying(mtmp, BUGLE))) {
385  | 		int xx, yy;
386  | 		struct monst *mon;
387  | 
388  | 		/* Distance is arbitrary.  What we really want to do is
389  | 		 * have the soldier play the bugle when it sees or
390  | 		 * remembers soldiers nearby...
391  | 		 */
392  | 		for(xx = x-3; xx <= x+3; xx++) for(yy = y-3; yy <= y+3; yy++)
393  | 		if (isok(xx,yy))
394  | 		if ((mon = m_at(xx,yy)) && is_mercenary(mon->data) &&
395  | 				mon->data != &mons[PM_GUARD] &&
396  | 				(mon->msleeping || (!mon->mcanmove))) {
397  | 			m.defensive = obj;
398  | 			m.has_defense = MUSE_BUGLE;
399  | 		}
400  | 	}
401  | 
402  | 	/* use immediate physical escape prior to attempting magic */
403  | 	if (m.has_defense)    /* stairs, trap door or tele-trap, bugle alert */
404  | 		goto botm;
405  | 
406  | 	/* kludge to cut down on trap destruction (particularly portals) */
407  | 	t = t_at(x,y);
408  | 	if (t && (t->ttyp == PIT || t->ttyp == SPIKED_PIT ||
409  | 		  t->ttyp == WEB || t->ttyp == BEAR_TRAP))
410  | 		t = 0;		/* ok for monster to dig here */
411  | 
412  | #define nomore(x) if(m.has_defense==x) continue;
413  | 	for (obj = mtmp->minvent; obj; obj = obj->nobj) {
414  | 		/* don't always use the same selection pattern */
415  | 		if (m.has_defense && !rn2(3)) break;
416  | 
417  | 		/* nomore(MUSE_WAN_DIGGING); */
418  | 		if (m.has_defense == MUSE_WAN_DIGGING) break;
419  | 		if (obj->otyp == WAN_DIGGING && obj->spe > 0 && !stuck && !t
420  | 		    && !mtmp->isshk && !mtmp->isgd && !mtmp->ispriest
421  | 		    && !is_floater(mtmp->data)
422  | 		    /* digging wouldn't be effective; assume they know that */
423  | 		    && !(levl[x][y].wall_info & W_NONDIGGABLE)
424  | 		    && !(Is_botlevel(&u.uz) || In_endgame(&u.uz))
425  | 		    && !(is_ice(x,y) || is_pool(x,y) || is_lava(x,y))) {
426  | 			m.defensive = obj;
427  | 			m.has_defense = MUSE_WAN_DIGGING;
428  | 		}
429  | 		nomore(MUSE_WAN_TELEPORTATION_SELF);
430  | 		nomore(MUSE_WAN_TELEPORTATION);
431  | 		if(obj->otyp == WAN_TELEPORTATION && obj->spe > 0) {
432  | 			m.defensive = obj;
433  | 			m.has_defense = (mon_has_amulet(mtmp))
434  | 				? MUSE_WAN_TELEPORTATION
435  | 				: MUSE_WAN_TELEPORTATION_SELF;
436  | 		}
437  | 		nomore(MUSE_SCR_TELEPORTATION);
438  | 		if(obj->otyp == SCR_TELEPORTATION && mtmp->mcansee
439  | 		   && haseyes(mtmp->data)
440  | 		   && (!obj->cursed ||
441  | 		       (!(mtmp->isshk && inhishop(mtmp))
442  | 			    && !mtmp->isgd && !mtmp->ispriest))) {
443  | 			m.defensive = obj;
444  | 			m.has_defense = MUSE_SCR_TELEPORTATION;
445  | 		}
446  | 
447  | 	    if (mtmp->data != &mons[PM_PESTILENCE]) {
448  | 		nomore(MUSE_POT_FULL_HEALING);
449  | 		if(obj->otyp == POT_FULL_HEALING) {
450  | 			m.defensive = obj;
451  | 			m.has_defense = MUSE_POT_FULL_HEALING;
452  | 		}
453  | 		nomore(MUSE_POT_EXTRA_HEALING);
454  | 		if(obj->otyp == POT_EXTRA_HEALING) {
455  | 			m.defensive = obj;
456  | 			m.has_defense = MUSE_POT_EXTRA_HEALING;
457  | 		}
458  | 		nomore(MUSE_WAN_CREATE_MONSTER);
459  | 		if(obj->otyp == WAN_CREATE_MONSTER && obj->spe > 0) {
460  | 			m.defensive = obj;
461  | 			m.has_defense = MUSE_WAN_CREATE_MONSTER;
462  | 		}
463  | 		nomore(MUSE_POT_HEALING);
464  | 		if(obj->otyp == POT_HEALING) {
465  | 			m.defensive = obj;
466  | 			m.has_defense = MUSE_POT_HEALING;
467  | 		}
468  | 	    } else {	/* Pestilence */
469  | 		nomore(MUSE_POT_FULL_HEALING);
470  | 		if (obj->otyp == POT_SICKNESS) {
471  | 			m.defensive = obj;
472  | 			m.has_defense = MUSE_POT_FULL_HEALING;
473  | 		}
474  | 		nomore(MUSE_WAN_CREATE_MONSTER);
475  | 		if (obj->otyp == WAN_CREATE_MONSTER && obj->spe > 0) {
476  | 			m.defensive = obj;
477  | 			m.has_defense = MUSE_WAN_CREATE_MONSTER;
478  | 		}
479  | 	    }
480  | 		nomore(MUSE_SCR_CREATE_MONSTER);
481  | 		if(obj->otyp == SCR_CREATE_MONSTER) {
482  | 			m.defensive = obj;
483  | 			m.has_defense = MUSE_SCR_CREATE_MONSTER;
484  | 		}
485  | 	}
486  | botm:	return((boolean)(!!m.has_defense));
487  | #undef nomore
488  | }
489  | 
490  | /* Perform a defensive action for a monster.  Must be called immediately
491  |  * after find_defensive().  Return values are 0: did something, 1: died,
492  |  * 2: did something and can't attack again (i.e. teleported).
493  |  */
494  | int
495  | use_defensive(mtmp)
496  | struct monst *mtmp;
497  | {
498  | 	int i, fleetim, how = 0;
499  | 	struct obj *otmp = m.defensive;
500  | 	boolean vis, vismon, oseen;
501  | 	const char *mcsa = "%s can see again.";
502  | 
503  | 	if ((i = precheck(mtmp, otmp)) != 0) return i;
504  | 	vis = cansee(mtmp->mx, mtmp->my);
505  | 	vismon = canseemon(mtmp);
506  | 	oseen = otmp && vismon;
507  | 
508  | 	/* when using defensive choice to run away, we want monster to avoid
509  | 	   rushing right straight back; don't override if already scared */
510  | 	fleetim = !mtmp->mflee ? (33 - (30 * mtmp->mhp / mtmp->mhpmax)) : 0;
511  | #define m_flee(m)	if (fleetim && !m->iswiz) \
512  | 			{ m->mflee = 1; m->mfleetim = fleetim; }
513  | 
514  | 	switch(m.has_defense) {
515  | 	case MUSE_UNICORN_HORN:
516  | 		if (vismon) {
517  | 		    if (otmp)
518  | 			pline("%s uses a unicorn horn!", Monnam(mtmp));
519  | 		    else
520  | 			pline_The("tip of %s's horn glows!", mon_nam(mtmp));
521  | 		}
522  | 		if (!mtmp->mcansee) {
523  | 		    mtmp->mcansee = 1;
524  | 		    mtmp->mblinded = 0;
525  | 		    if (vismon) pline(mcsa, Monnam(mtmp));
526  | 		} else if (mtmp->mconf || mtmp->mstun) {
527  | 		    mtmp->mconf = mtmp->mstun = 0;
528  | 		    if (vismon)
529  | 			pline("%s seems steadier now.", Monnam(mtmp));
530  | 		} else impossible("No need for unicorn horn?");
531  | 		return 2;
532  | 	case MUSE_BUGLE:
533  | 		if (vismon)
534  | 			pline("%s plays %s!", Monnam(mtmp), doname(otmp));
535  | 		else if (flags.soundok)
536  | 			You_hear("a bugle playing reveille!");
537  | 		awaken_soldiers();
538  | 		return 2;
539  | 	case MUSE_WAN_TELEPORTATION_SELF:
540  | 		if ((mtmp->isshk && inhishop(mtmp))
541  | 		       || mtmp->isgd || mtmp->ispriest) return 2;
542  | 		m_flee(mtmp);
543  | 		mzapmsg(mtmp, otmp, TRUE);
544  | 		otmp->spe--;
545  | 		how = WAN_TELEPORTATION;
546  | mon_tele:
547  | 		if (tele_restrict(mtmp)) {	/* mysterious force... */
548  | 		    if (vismon && how)		/* mentions 'teleport' */
549  | 			makeknown(how);
550  | 		    return 2;
551  | 		}
552  | 		if ((
553  | #if 0
554  | 			mon_has_amulet(mtmp) ||
555  | #endif
556  | 			On_W_tower_level(&u.uz)) && !rn2(3)) {
557  | 		    if (vismon)
558  | 			pline("%s seems disoriented for a moment.",
559  | 				Monnam(mtmp));
560  | 		    return 2;
561  | 		}
562  | 		if (oseen && how) makeknown(how);
563  | 		rloc(mtmp);
564  | 		return 2;
565  | 	case MUSE_WAN_TELEPORTATION:
566  | 		zap_oseen = oseen;
567  | 		mzapmsg(mtmp, otmp, FALSE);
568  | 		otmp->spe--;
569  | 		m_using = TRUE;
570  | 		mbhit(mtmp,rn1(8,6),mbhitm,bhito,otmp);
571  | 		m_using = FALSE;
572  | 		return 2;
573  | 	case MUSE_SCR_TELEPORTATION:
574  | 	    {
575  | 		int obj_is_cursed = otmp->cursed;
576  | 
577  | 		if (mtmp->isshk || mtmp->isgd || mtmp->ispriest) return 2;
578  | 		m_flee(mtmp);
579  | 		mreadmsg(mtmp, otmp);
580  | 		m_useup(mtmp, otmp);	/* otmp might be free'ed */
581  | 		how = SCR_TELEPORTATION;
582  | 		if (obj_is_cursed || mtmp->mconf) {
583  | 			int nlev;
584  | 			d_level flev;
585  | 
586  | 			if (mon_has_amulet(mtmp) || In_endgame(&u.uz)) {
587  | 			    if (vismon)
588  | 				pline("%s seems very disoriented for a moment.",
589  | 					Monnam(mtmp));
590  | 			    return 2;
591  | 			}
592  | 			nlev = random_teleport_level();
593  | 			if (nlev == depth(&u.uz)) {
594  | 			    if (vismon)
595  | 				pline("%s shudders for a moment.",
596  | 								Monnam(mtmp));
597  | 			    return 2;
598  | 			}
599  | 			get_level(&flev, nlev);
600  | 			migrate_to_level(mtmp, ledger_no(&flev), MIGR_RANDOM,
601  | 				(coord *)0);
602  | 			if (oseen) makeknown(SCR_TELEPORTATION);
603  | 		} else goto mon_tele;
604  | 		return 2;
605  | 	    }
606  | 	case MUSE_WAN_DIGGING:
607  | 	    {	struct trap *ttmp;
608  | 
609  | 		m_flee(mtmp);
610  | 		mzapmsg(mtmp, otmp, FALSE);
611  | 		otmp->spe--;
612  | 		if (oseen) makeknown(WAN_DIGGING);
613  | 		if (IS_FURNITURE(levl[mtmp->mx][mtmp->my].typ) ||
614  | 		    IS_DRAWBRIDGE(levl[mtmp->mx][mtmp->my].typ) ||
615  | 		    (is_drawbridge_wall(mtmp->mx, mtmp->my) >= 0) ||
616  | 		    (sstairs.sx && sstairs.sx == mtmp->mx &&
617  | 				   sstairs.sy == mtmp->my)) {
618  | 			pline_The("digging ray is ineffective.");
619  | 			return 2;
620  | 		}
621  | 		if (!Can_dig_down(&u.uz)) {
622  | 		    if(canseemon(mtmp))
623  | 			pline_The("%s here is too hard to dig in.",
624  | 					surface(mtmp->mx, mtmp->my));
625  | 		    return 2;
626  | 		}
627  | 		ttmp = maketrap(mtmp->mx, mtmp->my, HOLE);
628  | 		if (!ttmp) return 2;
629  | 		seetrap(ttmp);
630  | 		if (vis) {
631  | 		    pline("%s has made a hole in the %s.", Monnam(mtmp),
632  | 				surface(mtmp->mx, mtmp->my));
633  | 		    pline("%s %s through...", Monnam(mtmp),
634  | 			  is_flyer(mtmp->data) ? "dives" : "falls");
635  | 		} else if (flags.soundok)
636  | 			You_hear("%s crash through the %s.", something,
637  | 				surface(mtmp->mx, mtmp->my));
638  | 		/* we made sure that there is a level for mtmp to go to */
639  | 		migrate_to_level(mtmp, ledger_no(&u.uz) + 1,
640  | 				 MIGR_RANDOM, (coord *)0);
641  | 		return 2;
642  | 	    }
643  | 	case MUSE_WAN_CREATE_MONSTER:
644  | 	    {	coord cc;
645  | 		    /* pm: 0 => random, eel => aquatic, croc => amphibious */
646  | 		struct permonst *pm = !is_pool(mtmp->mx, mtmp->my) ? 0 :
647  | 			     &mons[u.uinwater ? PM_GIANT_EEL : PM_CROCODILE];
648  | 		struct monst *mon;
649  | 
650  | 		if (!enexto(&cc, mtmp->mx, mtmp->my, pm)) return 0;
651  | 		mzapmsg(mtmp, otmp, FALSE);
652  | 		otmp->spe--;
653  | 		mon = makemon((struct permonst *)0, cc.x, cc.y, NO_MM_FLAGS);
654  | 		if (mon && canspotmon(mon) && oseen)
655  | 		    makeknown(WAN_CREATE_MONSTER);
656  | 		return 2;
657  | 	    }
658  | 	case MUSE_SCR_CREATE_MONSTER:
659  | 	    {	coord cc;
660  | 		struct permonst *pm = 0, *fish = 0;
661  | 		int cnt = 1;
662  | 		struct monst *mon;
663  | 		boolean known = FALSE;
664  | 
665  | 		if (!rn2(73)) cnt += rnd(4);
666  | 		if (mtmp->mconf || otmp->cursed) cnt += 12;
667  | 		if (mtmp->mconf) pm = fish = &mons[PM_ACID_BLOB];
668  | 		else if (is_pool(mtmp->mx, mtmp->my))
669  | 		    fish = &mons[u.uinwater ? PM_GIANT_EEL : PM_CROCODILE];
670  | 		mreadmsg(mtmp, otmp);
671  | 		while(cnt--) {
672  | 		    /* `fish' potentially gives bias towards water locations;
673  | 		       `pm' is what to actually create (0 => random) */
674  | 		    if (!enexto(&cc, mtmp->mx, mtmp->my, fish)) break;
675  | 		    mon = makemon(pm, cc.x, cc.y, NO_MM_FLAGS);
676  | 		    if (mon && canspotmon(mon)) known = TRUE;
677  | 		}
678  | 		/* The only case where we don't use oseen.  For wands, you
679  | 		 * have to be able to see the monster zap the wand to know
680  | 		 * what type it is.  For teleport scrolls, you have to see
681  | 		 * the monster to know it teleported.
682  | 		 */
683  | 		if (known)
684  | 		    makeknown(SCR_CREATE_MONSTER);
685  | 		else if (!objects[SCR_CREATE_MONSTER].oc_name_known
686  | 			&& !objects[SCR_CREATE_MONSTER].oc_uname)
687  | 		    docall(otmp);
688  | 		m_useup(mtmp, otmp);
689  | 		return 2;
690  | 	    }
691  | 	case MUSE_TRAPDOOR:
692  | 		/* trap doors on "bottom" levels of dungeons are rock-drop
693  | 		 * trap doors, not holes in the floor.  We check here for
694  | 		 * safety.
695  | 		 */
696  | 		if (Is_botlevel(&u.uz)) return 0;
697  | 		m_flee(mtmp);
698  | 		if (vis) {
699  | 			struct trap *t;
700  | 			t = t_at(trapx,trapy);
701  | 			pline("%s %s into a %s!", Monnam(mtmp),
702  | 			makeplural(locomotion(mtmp->data, "jump")),
703  | 			t->ttyp == TRAPDOOR ? "trap door" : "hole");
704  | 			seetrap(t_at(trapx,trapy));
705  | 		}
706  | 
707  | 		/*  don't use rloc_to() because worm tails must "move" */
708  | 		remove_monster(mtmp->mx, mtmp->my);
709  | 		newsym(mtmp->mx, mtmp->my);	/* update old location */
710  | 		place_monster(mtmp, trapx, trapy);
711  | 		if (mtmp->wormno) worm_move(mtmp);
712  | 		newsym(trapx, trapy);
713  | 
714  | 		migrate_to_level(mtmp, ledger_no(&u.uz) + 1,
715  | 				 MIGR_RANDOM, (coord *)0);
716  | 		return 2;
717  | 	case MUSE_UPSTAIRS:
718  | 		/* Monsters without amulets escape the dungeon and are
719  | 		 * gone for good when they leave up the up stairs.
720  | 		 * Monsters with amulets would reach the endlevel,
721  | 		 * which we cannot allow since that would leave the
722  | 		 * player stranded.
723  | 		 */
724  | 		if (ledger_no(&u.uz) == 1) {
725  | 			if (mon_has_special(mtmp))
726  | 				return 0;
727  | 			if (vismon)
728  | 			    pline("%s escapes the dungeon!", Monnam(mtmp));
729  | 			mongone(mtmp);
730  | 			return 2;
731  | 		}
732  | 		m_flee(mtmp);
733  | 		if (Inhell && mon_has_amulet(mtmp) && !rn2(4) &&
734  | 			(dunlev(&u.uz) < dunlevs_in_dungeon(&u.uz) - 3)) {
735  | 		    if (vismon) pline(
736  |      "As %s climbs the stairs, a mysterious force momentarily surrounds %s...",
737  | 				     mon_nam(mtmp), him[pronoun_gender(mtmp)]);
738  | 		    /* simpler than for the player; this will usually be
739  | 		       the Wizard and he'll immediately go right to the
740  | 		       upstairs, so there's not much point in having any
741  | 		       chance for a random position on the current level */
742  | 		    migrate_to_level(mtmp, ledger_no(&u.uz) + 1,
743  | 				     MIGR_RANDOM, (coord *)0);
744  | 		} else {
745  | 		    if (vismon) pline("%s escapes upstairs!", Monnam(mtmp));
746  | 		    migrate_to_level(mtmp, ledger_no(&u.uz) - 1,
747  | 				     MIGR_STAIRS_DOWN, (coord *)0);
748  | 		}
749  | 		return 2;
750  | 	case MUSE_DOWNSTAIRS:
751  | 		m_flee(mtmp);
752  | 		if (vismon) pline("%s escapes downstairs!", Monnam(mtmp));
753  | 		migrate_to_level(mtmp, ledger_no(&u.uz) + 1,
754  | 				 MIGR_STAIRS_UP, (coord *)0);
755  | 		return 2;
756  | 	case MUSE_UP_LADDER:
757  | 		m_flee(mtmp);
758  | 		if (vismon) pline("%s escapes up the ladder!", Monnam(mtmp));
759  | 		migrate_to_level(mtmp, ledger_no(&u.uz) - 1,
760  | 				 MIGR_LADDER_DOWN, (coord *)0);
761  | 		return 2;
762  | 	case MUSE_DN_LADDER:
763  | 		m_flee(mtmp);
764  | 		if (vismon) pline("%s escapes down the ladder!", Monnam(mtmp));
765  | 		migrate_to_level(mtmp, ledger_no(&u.uz) + 1,
766  | 				 MIGR_LADDER_UP, (coord *)0);
767  | 		return 2;
768  | 	case MUSE_SSTAIRS:
769  | 		m_flee(mtmp);
770  | 		/* the stairs leading up from the 1st level are */
771  | 		/* regular stairs, not sstairs.			*/
772  | 		if (sstairs.up) {
773  | 			if (vismon)
774  | 			    pline("%s escapes upstairs!", Monnam(mtmp));
775  | 			if(Inhell) {
776  | 			    migrate_to_level(mtmp, ledger_no(&sstairs.tolev),
777  | 					     MIGR_RANDOM, (coord *)0);
778  | 			    return 2;
779  | 			}
780  | 		} else	if (vismon)
781  | 		    pline("%s escapes downstairs!", Monnam(mtmp));
782  | 		migrate_to_level(mtmp, ledger_no(&sstairs.tolev),
783  | 				 MIGR_SSTAIRS, (coord *)0);
784  | 		return 2;
785  | 	case MUSE_TELEPORT_TRAP:
786  | 		m_flee(mtmp);
787  | 		if (vis) {
788  | 			pline("%s %s onto a teleport trap!", Monnam(mtmp),
789  | 				makeplural(locomotion(mtmp->data, "jump")));
790  | 			seetrap(t_at(trapx,trapy));
791  | 		}
792  | 		/*  don't use rloc_to() because worm tails must "move" */
793  | 		remove_monster(mtmp->mx, mtmp->my);
794  | 		newsym(mtmp->mx, mtmp->my);	/* update old location */
795  | 		place_monster(mtmp, trapx, trapy);
796  | 		if (mtmp->wormno) worm_move(mtmp);
797  | 		newsym(trapx, trapy);
798  | 
799  | 		goto mon_tele;
800  | 	case MUSE_POT_HEALING:
801  | 		mquaffmsg(mtmp, otmp);
802  | 		i = d(6 + 2 * bcsign(otmp), 4);
803  | 		mtmp->mhp += i;
804  | 		if (mtmp->mhp > mtmp->mhpmax) mtmp->mhp = ++mtmp->mhpmax;
805  | 		if (!otmp->cursed && !mtmp->mcansee) {
806  | 			mtmp->mcansee = 1;
807  | 			mtmp->mblinded = 0;
808  | 			if (vismon) pline(mcsa, Monnam(mtmp));
809  | 		}
810  | 		if (vismon) pline("%s looks better.", Monnam(mtmp));
811  | 		if (oseen) makeknown(POT_HEALING);
812  | 		m_useup(mtmp, otmp);
813  | 		return 2;
814  | 	case MUSE_POT_EXTRA_HEALING:
815  | 		mquaffmsg(mtmp, otmp);
816  | 		i = d(6 + 2 * bcsign(otmp), 8);
817  | 		mtmp->mhp += i;
818  | 		if (mtmp->mhp > mtmp->mhpmax)
819  | 			mtmp->mhp = (mtmp->mhpmax += (otmp->blessed ? 5 : 2));
820  | 		if (!mtmp->mcansee) {
821  | 			mtmp->mcansee = 1;
822  | 			mtmp->mblinded = 0;
823  | 			if (vismon) pline(mcsa, Monnam(mtmp));
824  | 		}
825  | 		if (vismon) pline("%s looks much better.", Monnam(mtmp));
826  | 		if (oseen) makeknown(POT_EXTRA_HEALING);
827  | 		m_useup(mtmp, otmp);
828  | 		return 2;
829  | 	case MUSE_POT_FULL_HEALING:
830  | 		mquaffmsg(mtmp, otmp);
831  | 		if (otmp->otyp == POT_SICKNESS) unbless(otmp); /* Pestilence */
832  | 		mtmp->mhp = (mtmp->mhpmax += (otmp->blessed ? 8 : 4));
833  | 		if (!mtmp->mcansee && otmp->otyp != POT_SICKNESS) {
834  | 			mtmp->mcansee = 1;
835  | 			mtmp->mblinded = 0;
836  | 			if (vismon) pline(mcsa, Monnam(mtmp));
837  | 		}
838  | 		if (vismon) pline("%s looks completely healed.", Monnam(mtmp));
839  | 		if (oseen) makeknown(otmp->otyp);
840  | 		m_useup(mtmp, otmp);
841  | 		return 2;
842  | 	case 0: return 0; /* i.e. an exploded wand */
843  | 	default: impossible("%s wanted to perform action %d?", Monnam(mtmp),
844  | 			m.has_defense);
845  | 		break;
846  | 	}
847  | 	return 0;
848  | #undef m_flee
849  | }
850  | 
851  | int
852  | rnd_defensive_item(mtmp)
853  | struct monst *mtmp;
854  | {
855  | 	struct permonst *pm = mtmp->data;
856  | 	int difficulty = monstr[(monsndx(pm))];
857  | 
858  | 	if(is_animal(pm) || attacktype(pm, AT_EXPL) || mindless(mtmp->data)
859  | 			|| pm->mlet == S_GHOST
860  | # ifdef KOPS
861  | 			|| pm->mlet == S_KOP
862  | # endif
863  | 		) return 0;
864  | 	switch (rn2(8 + (difficulty > 3) + (difficulty > 6) +
865  | 				(difficulty > 8))) {
866  | 		case 6: case 9:
867  | 			if (!rn2(3)) return WAN_TELEPORTATION;
868  | 			/* else FALLTHRU */
869  | 		case 0: case 1:
870  | 			return SCR_TELEPORTATION;
871  | 		case 8: case 10:
872  | 			if (!rn2(3)) return WAN_CREATE_MONSTER;
873  | 			/* else FALLTHRU */
874  | 		case 2: return SCR_CREATE_MONSTER;
875  | 		case 3: return POT_HEALING;
876  | 		case 4: return POT_EXTRA_HEALING;
877  | 		case 5: return (mtmp->data != &mons[PM_PESTILENCE]) ?
878  | 				POT_FULL_HEALING : POT_SICKNESS;
879  | 		case 7: if (is_floater(pm) || mtmp->isshk || mtmp->isgd
880  | 						|| mtmp->ispriest
881  | 									)
882  | 				return 0;
883  | 			else
884  | 				return WAN_DIGGING;
885  | 	}
886  | 	/*NOTREACHED*/
887  | 	return 0;
888  | }
889  | 
890  | #define MUSE_WAN_DEATH 1
891  | #define MUSE_WAN_SLEEP 2
892  | #define MUSE_WAN_FIRE 3
893  | #define MUSE_WAN_COLD 4
894  | #define MUSE_WAN_LIGHTNING 5
895  | #define MUSE_WAN_MAGIC_MISSILE 6
896  | #define MUSE_WAN_STRIKING 7
897  | #define MUSE_SCR_FIRE 8
898  | #define MUSE_POT_PARALYSIS 9
899  | #define MUSE_POT_BLINDNESS 10
900  | #define MUSE_POT_CONFUSION 11
901  | #define MUSE_FROST_HORN 12
902  | #define MUSE_FIRE_HORN 13
903  | #define MUSE_POT_ACID 14
904  | /*#define MUSE_WAN_TELEPORTATION 15*/
905  | #define MUSE_POT_SLEEPING 16
906  | #define MUSE_SCR_EARTH 17
907  | 
908  | /* Select an offensive item/action for a monster.  Returns TRUE iff one is
909  |  * found.
910  |  */
911  | boolean
912  | find_offensive(mtmp)
913  | struct monst *mtmp;
914  | {
915  | 	register struct obj *obj;
916  | 	boolean ranged_stuff = lined_up(mtmp);
917  | 	boolean reflection_skip = (Reflecting && rn2(2));
918  | 	struct obj *helmet = which_armor(mtmp, W_ARMH);
919  | 
920  | 	m.offensive = (struct obj *)0;
921  | 	m.has_offense = 0;
922  | 	if (mtmp->mpeaceful || is_animal(mtmp->data) ||
923  | 				mindless(mtmp->data) || nohands(mtmp->data))
924  | 		return FALSE;
925  | 	if (u.uswallow) return FALSE;
926  | 	if (in_your_sanctuary(mtmp, 0, 0)) return FALSE;
927  | 	if (dmgtype(mtmp->data, AD_HEAL) && !uwep
928  | #ifdef TOURIST
929  | 	    && !uarmu
930  | #endif
931  | 	    && !uarm && !uarmh && !uarms && !uarmg && !uarmc && !uarmf)
932  | 		return FALSE;
933  | 
934  | 	if (!ranged_stuff) return FALSE;
935  | #define nomore(x) if(m.has_offense==x) continue;
936  | 	for(obj=mtmp->minvent; obj; obj=obj->nobj) {
937  | 		/* nomore(MUSE_WAN_DEATH); */
938  | 		if (!reflection_skip) {
939  | 		    if(obj->otyp == WAN_DEATH && obj->spe > 0) {
940  | 			m.offensive = obj;
941  | 			m.has_offense = MUSE_WAN_DEATH;
942  | 		    }
943  | 		    nomore(MUSE_WAN_SLEEP);
944  | 		    if(obj->otyp == WAN_SLEEP && obj->spe > 0 && multi >= 0) {
945  | 			m.offensive = obj;
946  | 			m.has_offense = MUSE_WAN_SLEEP;
947  | 		    }
948  | 		    nomore(MUSE_WAN_FIRE);
949  | 		    if(obj->otyp == WAN_FIRE && obj->spe > 0) {
950  | 			m.offensive = obj;
951  | 			m.has_offense = MUSE_WAN_FIRE;
952  | 		    }
953  | 		    nomore(MUSE_FIRE_HORN);
954  | 		    if(obj->otyp == FIRE_HORN && obj->spe > 0) {
955  | 			m.offensive = obj;
956  | 			m.has_offense = MUSE_FIRE_HORN;
957  | 		    }
958  | 		    nomore(MUSE_WAN_COLD);
959  | 		    if(obj->otyp == WAN_COLD && obj->spe > 0) {
960  | 			m.offensive = obj;
961  | 			m.has_offense = MUSE_WAN_COLD;
962  | 		    }
963  | 		    nomore(MUSE_FROST_HORN);
964  | 		    if(obj->otyp == FROST_HORN && obj->spe > 0) {
965  | 			m.offensive = obj;
966  | 			m.has_offense = MUSE_FROST_HORN;
967  | 		    }
968  | 		    nomore(MUSE_WAN_LIGHTNING);
969  | 		    if(obj->otyp == WAN_LIGHTNING && obj->spe > 0) {
970  | 			m.offensive = obj;
971  | 			m.has_offense = MUSE_WAN_LIGHTNING;
972  | 		    }
973  | 		    nomore(MUSE_WAN_MAGIC_MISSILE);
974  | 		    if(obj->otyp == WAN_MAGIC_MISSILE && obj->spe > 0) {
975  | 			m.offensive = obj;
976  | 			m.has_offense = MUSE_WAN_MAGIC_MISSILE;
977  | 		    }
978  | 		}
979  | 		nomore(MUSE_WAN_STRIKING);
980  | 		if(obj->otyp == WAN_STRIKING && obj->spe > 0) {
981  | 			m.offensive = obj;
982  | 			m.has_offense = MUSE_WAN_STRIKING;
983  | 		}
984  | 		nomore(MUSE_POT_PARALYSIS);
985  | 		if(obj->otyp == POT_PARALYSIS && multi >= 0) {
986  | 			m.offensive = obj;
987  | 			m.has_offense = MUSE_POT_PARALYSIS;
988  | 		}
989  | 		nomore(MUSE_POT_BLINDNESS);
990  | 		if(obj->otyp == POT_BLINDNESS) {
991  | 			m.offensive = obj;
992  | 			m.has_offense = MUSE_POT_BLINDNESS;
993  | 		}
994  | 		nomore(MUSE_POT_CONFUSION);
995  | 		if(obj->otyp == POT_CONFUSION) {
996  | 			m.offensive = obj;
997  | 			m.has_offense = MUSE_POT_CONFUSION;
998  | 		}
999  | 		nomore(MUSE_POT_SLEEPING);
1000 | 		if(obj->otyp == POT_SLEEPING) {
1001 | 			m.offensive = obj;
1002 | 			m.has_offense = MUSE_POT_SLEEPING;
1003 | 		}
1004 | 		nomore(MUSE_POT_ACID);
1005 | 		if(obj->otyp == POT_ACID) {
1006 | 			m.offensive = obj;
1007 | 			m.has_offense = MUSE_POT_ACID;
1008 | 		}
1009 | 		/* we can safely put this scroll here since the locations that
1010 | 		 * are in a 1 square radius are a subset of the locations that
1011 | 		 * are in wand range
1012 | 		 */
1013 | 		nomore(MUSE_SCR_EARTH);
1014 | 		if (obj->otyp == SCR_EARTH
1015 | 		       && ((helmet && is_metallic(helmet)) ||
1016 | 				mtmp->mconf || amorphous(mtmp->data) ||
1017 | 				passes_walls(mtmp->data) ||
1018 | 				noncorporeal(mtmp->data) ||
1019 | 				unsolid(mtmp->data) || !rn2(10))
1020 | 		       && dist2(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy) <= 2
1021 | 		       && mtmp->mcansee && haseyes(mtmp->data)
1022 | #ifdef REINCARNATION
1023 | 		       && !Is_rogue_level(&u.uz)
1024 | #endif
1025 | 		       && (!In_endgame(&u.uz) || Is_earthlevel(&u.uz))) {
1026 | 		    m.offensive = obj;
1027 | 		    m.has_offense = MUSE_SCR_EARTH;
1028 | 		}
1029 | #if 0
1030 | 		nomore(MUSE_SCR_FIRE);
1031 | 		if (obj->otyp == SCR_FIRE && resists_fire(mtmp)
1032 | 		   && dist2(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy) <= 2
1033 | 		   && mtmp->mcansee && haseyes(mtmp->data)) {
1034 | 			m.offensive = obj;
1035 | 			m.has_offense = MUSE_SCR_FIRE;
1036 | 		}
1037 | #endif
1038 | 	}
1039 | 	return((boolean)(!!m.has_offense));
1040 | #undef nomore
1041 | }
1042 | 
1043 | STATIC_PTR
1044 | int
1045 | mbhitm(mtmp, otmp)
1046 | register struct monst *mtmp;
1047 | register struct obj *otmp;
1048 | {
1049 | 	int tmp;
1050 | 
1051 | 	boolean reveal_invis = FALSE;
1052 | 	if (mtmp != &youmonst) {
1053 | 		mtmp->msleeping = 0;
1054 | 		if (mtmp->m_ap_type) seemimic(mtmp);
1055 | 	}
1056 | 	switch(otmp->otyp) {
1057 | 	case WAN_STRIKING:
1058 | 		reveal_invis = TRUE;
1059 | 		if (mtmp == &youmonst) {
1060 | 			if (zap_oseen) makeknown(WAN_STRIKING);
1061 | 			if (Antimagic) {
1062 | 			    shieldeff(u.ux, u.uy);
1063 | 			    pline("Boing!");
1064 | 			} else if (rnd(20) < 10 + u.uac) {
1065 | 			    pline_The("wand hits you!");
1066 | 			    tmp = d(2,12);
1067 | 			    if(Half_spell_damage) tmp = (tmp+1) / 2;
1068 | 			    losehp(tmp, "wand", KILLED_BY_AN);
1069 | 			} else pline_The("wand misses you.");
1070 | 			stop_occupation();
1071 | 			nomul(0);
1072 | 		} else if (resists_magm(mtmp)) {
1073 | 			shieldeff(mtmp->mx, mtmp->my);
1074 | 			pline("Boing!");
1075 | 		} else if (rnd(20) < 10+find_mac(mtmp)) {
1076 | 			tmp = d(2,12);
1077 | 			hit("wand", mtmp, exclam(tmp));
1078 | 			(void) resist(mtmp, otmp->oclass, tmp, TELL);
1079 | 			if (cansee(mtmp->mx, mtmp->my) && zap_oseen)
1080 | 				makeknown(WAN_STRIKING);
1081 | 		} else {
1082 | 			miss("wand", mtmp);
1083 | 			if (cansee(mtmp->mx, mtmp->my) && zap_oseen)
1084 | 				makeknown(WAN_STRIKING);
1085 | 		}
1086 | 		break;
1087 | 	case WAN_TELEPORTATION:
1088 | 		if (mtmp == &youmonst) {
1089 | 			if (zap_oseen) makeknown(WAN_TELEPORTATION);
1090 | 			tele();
1091 | 		} else {
1092 | 			/* for consistency with zap.c, don't identify */
1093 | 			if (mtmp->ispriest &&
1094 | 				*in_rooms(mtmp->mx, mtmp->my, TEMPLE)) {
1095 | 			    if (cansee(mtmp->mx, mtmp->my))
1096 | 				pline("%s resists the magic!", Monnam(mtmp));
1097 | 			    mtmp->msleeping = 0;
1098 | 			    if(mtmp->m_ap_type) seemimic(mtmp);
1099 | 			} else if (!tele_restrict(mtmp))
1100 | 			    rloc(mtmp);
1101 | 		}
1102 | 		break;
1103 | 	case WAN_CANCELLATION:
1104 | 	case SPE_CANCELLATION:
1105 | 		cancel_monst(mtmp, otmp, FALSE, TRUE, FALSE);
1106 | 		break;
1107 | 	}
1108 | 	if (reveal_invis) {
1109 | 	    if (mtmp->mhp > 0 && cansee(bhitpos.x,bhitpos.y)
1110 | 							&& !canspotmon(mtmp))
1111 | 		map_invisible(bhitpos.x, bhitpos.y);
1112 | 	}
1113 | 	return 0;
1114 | }
1115 | 
1116 | /* A modified bhit() for monsters.  Based on bhit() in zap.c.  Unlike
1117 |  * buzz(), bhit() doesn't take into account the possibility of a monster
1118 |  * zapping you, so we need a special function for it.  (Unless someone wants
1119 |  * to merge the two functions...)
1120 |  */
1121 | STATIC_OVL void
1122 | mbhit(mon,range,fhitm,fhito,obj)
1123 | struct monst *mon;			/* monster shooting the wand */
1124 | register int range;			/* direction and range */
1125 | int FDECL((*fhitm),(MONST_P,OBJ_P));
1126 | int FDECL((*fhito),(OBJ_P,OBJ_P));	/* fns called when mon/obj hit */
1127 | struct obj *obj;			/* 2nd arg to fhitm/fhito */
1128 | {
1129 | 	register struct monst *mtmp;
1130 | 	register struct obj *otmp;
1131 | 	register uchar typ;
1132 | 	int ddx, ddy;
1133 | 
1134 | 	bhitpos.x = mon->mx;
1135 | 	bhitpos.y = mon->my;
1136 | 	ddx = sgn(mon->mux - mon->mx);
1137 | 	ddy = sgn(mon->muy - mon->my);
1138 | 
1139 | 	while(range-- > 0) {
1140 | 		int x,y;
1141 | 
1142 | 		bhitpos.x += ddx;
1143 | 		bhitpos.y += ddy;
1144 | 		x = bhitpos.x; y = bhitpos.y;
1145 | 
1146 | 		if (!isok(x,y)) {
1147 | 		    bhitpos.x -= ddx;
1148 | 		    bhitpos.y -= ddy;
1149 | 		    break;
1150 | 		}
1151 | 		if (find_drawbridge(&x,&y))
1152 | 		    switch (obj->otyp) {
1153 | 			case WAN_STRIKING:
1154 | 			    destroy_drawbridge(x,y);
1155 | 		    }
1156 | 		if(bhitpos.x==u.ux && bhitpos.y==u.uy) {
1157 | 			(*fhitm)(&youmonst, obj);
1158 | 			range -= 3;
1159 | 		} else if(MON_AT(bhitpos.x, bhitpos.y)){
1160 | 			mtmp = m_at(bhitpos.x,bhitpos.y);
1161 | 			if (cansee(bhitpos.x,bhitpos.y) && !canspotmon(mtmp))
1162 | 			    map_invisible(bhitpos.x, bhitpos.y);
1163 | 			(*fhitm)(mtmp, obj);
1164 | 			range -= 3;
1165 | 		}
1166 | 		/* modified by GAN to hit all objects */
1167 | 		if(fhito){
1168 | 		    int hitanything = 0;
1169 | 		    register struct obj *next_obj;
1170 | 
1171 | 		    for(otmp = level.objects[bhitpos.x][bhitpos.y];
1172 | 							otmp; otmp = next_obj) {
1173 | 			/* Fix for polymorph bug, Tim Wright */
1174 | 			next_obj = otmp->nexthere;
1175 | 			hitanything += (*fhito)(otmp, obj);
1176 | 		    }
1177 | 		    if(hitanything)	range--;
1178 | 		}
1179 | 		typ = levl[bhitpos.x][bhitpos.y].typ;
1180 | 		if(IS_DOOR(typ) || typ == SDOOR) {
1181 | 		    switch (obj->otyp) {
1182 | 			/* note: monsters don't use opening or locking magic
1183 | 			   at present, but keep these as placeholders */
1184 | 			case WAN_OPENING:
1185 | 			case WAN_LOCKING:
1186 | 			case WAN_STRIKING:
1187 | 			    if (doorlock(obj, bhitpos.x, bhitpos.y)) {
1188 | 				makeknown(obj->otyp);
1189 | 				/* if a shop door gets broken, add it to
1190 | 				   the shk's fix list (no cost to player) */
1191 | 				if (levl[bhitpos.x][bhitpos.y].doormask ==
1192 | 					D_BROKEN &&
1193 | 				    *in_rooms(bhitpos.x, bhitpos.y, SHOPBASE))
1194 | 				    add_damage(bhitpos.x, bhitpos.y, 0L);
1195 | 			    }
1196 | 			    break;
1197 | 		    }
1198 | 		}
1199 | 		if(!ZAP_POS(typ) || (IS_DOOR(typ) &&
1200 | 		   (levl[bhitpos.x][bhitpos.y].doormask & (D_LOCKED | D_CLOSED)))
1201 | 		  ) {
1202 | 			bhitpos.x -= ddx;
1203 | 			bhitpos.y -= ddy;
1204 | 			break;
1205 | 		}
1206 | 	}
1207 | }
1208 | 
1209 | /* Perform an offensive action for a monster.  Must be called immediately
1210 |  * after find_offensive().  Return values are same as use_defensive().
1211 |  */
1212 | int
1213 | use_offensive(mtmp)
1214 | struct monst *mtmp;
1215 | {
1216 | 	int i;
1217 | 	struct obj *otmp = m.offensive;
1218 | 	boolean oseen;
1219 | 
1220 | 	/* offensive potions are not drunk, they're thrown */
1221 | 	if (otmp->oclass != POTION_CLASS && (i = precheck(mtmp, otmp)) != 0)
1222 | 		return i;
1223 | 	oseen = otmp && canseemon(mtmp);
1224 | 
1225 | 	switch(m.has_offense) {
1226 | 	case MUSE_WAN_DEATH:
1227 | 	case MUSE_WAN_SLEEP:
1228 | 	case MUSE_WAN_FIRE:
1229 | 	case MUSE_WAN_COLD:
1230 | 	case MUSE_WAN_LIGHTNING:
1231 | 	case MUSE_WAN_MAGIC_MISSILE:
1232 | 		mzapmsg(mtmp, otmp, FALSE);
1233 | 		otmp->spe--;
1234 | 		if (oseen) makeknown(otmp->otyp);
1235 | 		m_using = TRUE;
1236 | 		buzz((int)(-30 - (otmp->otyp - WAN_MAGIC_MISSILE)),
1237 | 			(otmp->otyp == WAN_MAGIC_MISSILE) ? 2 : 6,
1238 | 			mtmp->mx, mtmp->my,
1239 | 			sgn(mtmp->mux-mtmp->mx), sgn(mtmp->muy-mtmp->my));
1240 | 		m_using = FALSE;
1241 | 		return (mtmp->mhp <= 0) ? 1 : 2;
1242 | 	case MUSE_FIRE_HORN:
1243 | 	case MUSE_FROST_HORN:
1244 | 		if (oseen) {
1245 | 			makeknown(otmp->otyp);
1246 | 			pline("%s plays a %s!", Monnam(mtmp), xname(otmp));
1247 | 		} else
1248 | 			You_hear("a horn being played.");
1249 | 		otmp->spe--;
1250 | 		m_using = TRUE;
1251 | 		buzz(-30 - ((otmp->otyp==FROST_HORN) ? AD_COLD-1 : AD_FIRE-1),
1252 | 			rn1(6,6), mtmp->mx, mtmp->my,
1253 | 			sgn(mtmp->mux-mtmp->mx), sgn(mtmp->muy-mtmp->my));
1254 | 		m_using = FALSE;
1255 | 		return (mtmp->mhp <= 0) ? 1 : 2;
1256 | 	case MUSE_WAN_TELEPORTATION:
1257 | 	case MUSE_WAN_STRIKING:
1258 | 		zap_oseen = oseen;
1259 | 		mzapmsg(mtmp, otmp, FALSE);
1260 | 		otmp->spe--;
1261 | 		m_using = TRUE;
1262 | 		mbhit(mtmp,rn1(8,6),mbhitm,bhito,otmp);
1263 | 		m_using = FALSE;
1264 | 		return 2;
1265 | 	case MUSE_SCR_EARTH:
1266 | 	    {
1267 | 		/* TODO: handle steeds */
1268 | 	    	register int x, y;
1269 | 		/* don't use monster fields after killing it */
1270 | 		boolean confused = (mtmp->mconf ? TRUE : FALSE);
1271 | 		int mmx = mtmp->mx, mmy = mtmp->my;
1272 | 
1273 | 		mreadmsg(mtmp, otmp);
1274 | 	    	/* Identify the scroll */
1275 | 		if (canspotmon(mtmp)) {
1276 | 		    pline_The("%s rumbles %s %s!", ceiling(mtmp->mx, mtmp->my),
1277 | 	    			otmp->blessed ? "around" : "above",
1278 | 				mon_nam(mtmp));
1279 | 		    if (oseen) makeknown(otmp->otyp);
1280 | 		} else if (cansee(mtmp->mx, mtmp->my)) {
1281 | 		    pline_The("%s rumbles in the middle of nowhere!",
1282 | 			ceiling(mtmp->mx, mtmp->my));
1283 | 		    if (mtmp->minvis)
1284 | 			map_invisible(mtmp->mx, mtmp->my);
1285 | 		    if (oseen) makeknown(otmp->otyp);
1286 | 		}
1287 | 
1288 | 	    	/* Loop through the surrounding squares */
1289 | 	    	for (x = mmx-1; x <= mmx+1; x++) {
1290 | 	    	    for (y = mmy-1; y <= mmy+1; y++) {
1291 | 	    	    	/* Is this a suitable spot? */
1292 | 	    	    	if (isok(x, y) && !closed_door(x, y) &&
1293 | 	    	    			!IS_ROCK(levl[x][y].typ) &&
1294 | 	    	    			!IS_AIR(levl[x][y].typ) &&
1295 | 	    	    			(((x == mmx) && (y == mmy)) ?
1296 | 	    	    			    !otmp->blessed : !otmp->cursed) &&
1297 | 					(x != u.ux || y != u.uy)) {
1298 | 			    register struct obj *otmp2;
1299 | 			    register struct monst *mtmp2;
1300 | 
1301 | 	    	    	    /* Make the object(s) */
1302 | 	    	    	    otmp2 = mksobj(confused ? ROCK : BOULDER,
1303 | 	    	    	    		FALSE, FALSE);
1304 | 	    	    	    if (!otmp2) continue;  /* Shouldn't happen */
1305 | 	    	    	    otmp2->quan = confused ? rn1(5,2) : 1;
1306 | 	    	    	    otmp2->owt = weight(otmp2);
1307 | 
1308 | 	    	    	    /* Find the monster here (might be same as mtmp) */
1309 | 	    	    	    mtmp2 = m_at(x, y);
1310 | 	    	    	    if (mtmp2 && !amorphous(mtmp2->data) &&
1311 | 	    	    	    		!passes_walls(mtmp2->data) &&
1312 | 	    	    	    		!noncorporeal(mtmp2->data) &&
1313 | 	    	    	    		!unsolid(mtmp2->data)) {
1314 | 				struct obj *helmet = which_armor(mtmp2, W_ARMH);
1315 | 				int mdmg;
1316 | 
1317 | 				if (cansee(mtmp2->mx, mtmp2->my)) {
1318 | 				    pline("%s is hit by %s!", Monnam(mtmp2),
1319 | 	    	    	    			doname(otmp2));
1320 | 				    if (mtmp2->minvis && !canspotmon(mtmp2))
1321 | 					map_invisible(mtmp2->mx, mtmp2->my);
1322 | 				}
1323 | 	    	    	    	mdmg = dmgval(otmp2, mtmp2) * otmp2->quan;
1324 | 				if (helmet) {
1325 | 				    if(is_metallic(helmet)) {
1326 | 					if (canspotmon(mtmp2))
1327 | 					    pline("Fortunately, %s is wearing a hard helmet.", mon_nam(mtmp2));
1328 | 					else if (flags.soundok)
1329 | 					    You_hear("a clanging sound.");
1330 | 					if (mdmg > 2) mdmg = 2;
1331 | 				    } else {
1332 | 					if (canspotmon(mtmp2))
1333 | 					    pline("%s's %s does not protect %s.",
1334 | 						Monnam(mtmp2), xname(helmet),
1335 | 						him[pronoun_gender(mtmp2)]);
1336 | 				    }
1337 | 				}
1338 | 	    	    	    	mtmp2->mhp -= mdmg;
1339 | 	    	    	    	if (mtmp2->mhp <= 0) {
1340 | 				    pline("%s is killed.", Monnam(mtmp2));
1341 | 	    	    	    	    mondied(mtmp2);
1342 | 				}
1343 | 	    	    	    }
1344 | 	    	    	    /* Drop the rock/boulder to the floor */
1345 | 	    	    	    if (!flooreffects(otmp2, x, y, "fall")) {
1346 | 	    	    	    	place_object(otmp2, x, y);
1347 | 	    	    	    	stackobj(otmp2);
1348 | 	    	    	    	newsym(x, y);  /* map the rock */
1349 | 	    	    	    }
1350 | 	    	    	}
1351 | 		    }
1352 | 		}
1353 | 		m_useup(mtmp, otmp);
1354 | 		/* Attack the player */
1355 | 		if (dist2(mmx, mmy, u.ux, u.uy) == 1 && !otmp->cursed) {
1356 | 		    int dmg;
1357 | 		    struct obj *otmp2;
1358 | 
1359 | 		    /* Okay, _you_ write this without repeating the code */
1360 | 		    otmp2 = mksobj(confused ? ROCK : BOULDER,
1361 | 				FALSE, FALSE);
1362 | 		    if (!otmp2) goto xxx_noobj;  /* Shouldn't happen */
1363 | 		    otmp2->quan = confused ? rn1(5,2) : 1;
1364 | 		    otmp2->owt = weight(otmp2);
1365 | 		    if (!amorphous(youmonst.data) &&
1366 | 			    !Passes_walls &&
1367 | 			    !noncorporeal(youmonst.data) &&
1368 | 			    !unsolid(youmonst.data)) {
1369 | 			You("are hit by %s!", doname(otmp2));
1370 | 			dmg = dmgval(otmp2, &youmonst) * otmp2->quan;
1371 | 			if (uarmh) {
1372 | 			    if(is_metallic(uarmh)) {
1373 | 				pline("Fortunately, you are wearing a hard helmet.");
1374 | 				if (dmg > 2) dmg = 2;
1375 | 			    } else if (flags.verbose) {
1376 | 				Your("%s does not protect you.",
1377 | 						xname(uarmh));
1378 | 			    }
1379 | 			}
1380 | 		    } else
1381 | 			dmg = 0;
1382 | 		    if (!flooreffects(otmp2, u.ux, u.uy, "fall")) {
1383 | 			place_object(otmp2, u.ux, u.uy);
1384 | 			stackobj(otmp2);
1385 | 			newsym(u.ux, u.uy);
1386 | 		    }
1387 | 		    if (dmg) losehp(dmg, "scroll of earth", KILLED_BY_AN);
1388 | 		}
1389 | 	    xxx_noobj:
1390 | 
1391 | 		return (mtmp->mhp <= 0) ? 1 : 2;
1392 | 	    }
1393 | #if 0
1394 | 	case MUSE_SCR_FIRE:
1395 | 	      {
1396 | 		boolean vis = cansee(mtmp->mx, mtmp->my);
1397 | 
1398 | 		mreadmsg(mtmp, otmp);
1399 | 		if (mtmp->mconf) {
1400 | 			if (vis)
1401 | 			    pline("Oh, what a pretty fire!");
1402 | 		} else {
1403 | 			struct monst *mtmp2;
1404 | 			int num;
1405 | 
1406 | 			if (vis)
1407 | 			    pline_The("scroll erupts in a tower of flame!");
1408 | 			shieldeff(mtmp->mx, mtmp->my);
1409 | 			pline("%s is uninjured.", Monnam(mtmp));
1410 | 			(void) destroy_mitem(mtmp, SCROLL_CLASS, AD_FIRE);
1411 | 			(void) destroy_mitem(mtmp, SPBOOK_CLASS, AD_FIRE);
1412 | 			(void) destroy_mitem(mtmp, POTION_CLASS, AD_FIRE);
1413 | 			num = (2*(rn1(3, 3) + 2 * bcsign(otmp)) + 1)/3;
1414 | 			if (Fire_resistance)
1415 | 			    You("are not harmed.");
1416 | 			burn_away_slime();
1417 | 			if (Half_spell_damage) num = (num+1) / 2;
1418 | 			else losehp(num, "scroll of fire", KILLED_BY_AN);
1419 | 			for(mtmp2 = fmon; mtmp2; mtmp2 = mtmp2->nmon) {
1420 | 			   if(DEADMONSTER(mtmp2)) continue;
1421 | 			   if(mtmp == mtmp2) continue;
1422 | 			   if(dist2(mtmp2->mx,mtmp2->my,mtmp->mx,mtmp->my) < 3){
1423 | 				if (resists_fire(mtmp2)) continue;
1424 | 				mtmp2->mhp -= num;
1425 | 				if (resists_cold(mtmp2))
1426 | 				    mtmp2->mhp -= 3*num;
1427 | 				if(mtmp2->mhp < 1) {
1428 | 				    mondied(mtmp2);
1429 | 				    break;
1430 | 				}
1431 | 			    }
1432 | 			}
1433 | 		}
1434 | 		return 2;
1435 | 	      }
1436 | #endif	/* 0 */
1437 | 	case MUSE_POT_PARALYSIS:
1438 | 	case MUSE_POT_BLINDNESS:
1439 | 	case MUSE_POT_CONFUSION:
1440 | 	case MUSE_POT_SLEEPING:
1441 | 	case MUSE_POT_ACID:
1442 | 		/* Note: this setting of dknown doesn't suffice.  A monster
1443 | 		 * which is out of sight might throw and it hits something _in_
1444 | 		 * sight, a problem not existing with wands because wand rays
1445 | 		 * are not objects.  Also set dknown in mthrowu.c.
1446 | 		 */
1447 | 		if (cansee(mtmp->mx, mtmp->my)) {
1448 | 			otmp->dknown = 1;
1449 | 			pline("%s hurls %s!", Monnam(mtmp),
1450 | 						singular(otmp, doname));
1451 | 		}
1452 | 		m_throw(mtmp, mtmp->mx, mtmp->my, sgn(mtmp->mux-mtmp->mx),
1453 | 			sgn(mtmp->muy-mtmp->my),
1454 | 			distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy), otmp);
1455 | 		return 2;
1456 | 	case 0: return 0; /* i.e. an exploded wand */
1457 | 	default: impossible("%s wanted to perform action %d?", Monnam(mtmp),
1458 | 			m.has_offense);
1459 | 		break;
1460 | 	}
1461 | 	return 0;
1462 | }
1463 | 
1464 | int
1465 | rnd_offensive_item(mtmp)
1466 | struct monst *mtmp;
1467 | {
1468 | 	struct permonst *pm = mtmp->data;
1469 | 	int difficulty = monstr[(monsndx(pm))];
1470 | 
1471 | 	if(is_animal(pm) || attacktype(pm, AT_EXPL) || mindless(mtmp->data)
1472 | 			|| pm->mlet == S_GHOST
1473 | # ifdef KOPS
1474 | 			|| pm->mlet == S_KOP
1475 | # endif
1476 | 		) return 0;
1477 | 	if (difficulty > 7 && !rn2(35)) return WAN_DEATH;
1478 | 	switch (rn2(9 - (difficulty < 4) + 4 * (difficulty > 6))) {
1479 | 		case 0: {
1480 | 		    struct obj *helmet = which_armor(mtmp, W_ARMH);
1481 | 
1482 | 		    if ((helmet && is_metallic(helmet)) || amorphous(pm) || passes_walls(pm) || noncorporeal(pm) || unsolid(pm))
1483 | 			return SCR_EARTH;
1484 | 		} /* fall through */
1485 | 		case 1: return WAN_STRIKING;
1486 | 		case 2: return POT_ACID;
1487 | 		case 3: return POT_CONFUSION;
1488 | 		case 4: return POT_BLINDNESS;
1489 | 		case 5: return POT_SLEEPING;
1490 | 		case 6: return POT_PARALYSIS;
1491 | 		case 7: case 8:
1492 | 			return WAN_MAGIC_MISSILE;
1493 | 		case 9: return WAN_SLEEP;
1494 | 		case 10: return WAN_FIRE;
1495 | 		case 11: return WAN_COLD;
1496 | 		case 12: return WAN_LIGHTNING;
1497 | 	}
1498 | 	/*NOTREACHED*/
1499 | 	return 0;
1500 | }
1501 | 
1502 | #define MUSE_POT_GAIN_LEVEL 1
1503 | #define MUSE_WAN_MAKE_INVISIBLE 2
1504 | #define MUSE_POT_INVISIBILITY 3
1505 | #define MUSE_POLY_TRAP 4
1506 | #define MUSE_WAN_POLYMORPH 5
1507 | #define MUSE_POT_SPEED 6
1508 | #define MUSE_WAN_SPEED_MONSTER 7
1509 | #define MUSE_BULLWHIP 8
1510 | #define MUSE_POT_POLYMORPH 9
1511 | 
1512 | boolean
1513 | find_misc(mtmp)
1514 | struct monst *mtmp;
1515 | {
1516 | 	register struct obj *obj;
1517 | 	struct permonst *mdat = mtmp->data;
1518 | 	int x = mtmp->mx, y = mtmp->my;
1519 | 	struct trap *t;
1520 | 	int xx, yy;
1521 | 	boolean immobile = (mdat->mmove == 0);
1522 | 	boolean stuck = (mtmp == u.ustuck);
1523 | 
1524 | 	m.misc = (struct obj *)0;
1525 | 	m.has_misc = 0;
1526 | 	if (is_animal(mdat) || mindless(mdat))
1527 | 		return 0;
1528 | 	if (u.uswallow && stuck) return FALSE;
1529 | 
1530 | 	/* We arbitrarily limit to times when a player is nearby for the
1531 | 	 * same reason as Junior Pac-Man doesn't have energizers eaten until
1532 | 	 * you can see them...
1533 | 	 */
1534 | 	if(dist2(x, y, mtmp->mux, mtmp->muy) > 36)
1535 | 		return FALSE;
1536 | 
1537 | 	if (!stuck && !immobile && !mtmp->cham && monstr[monsndx(mdat)] < 6) {
1538 | 	  boolean ignore_boulders = (verysmall(mdat) ||
1539 | 				     throws_rocks(mdat) ||
1540 | 				     passes_walls(mdat));
1541 | 	  for(xx = x-1; xx <= x+1; xx++)
1542 | 	    for(yy = y-1; yy <= y+1; yy++)
1543 | 		if (isok(xx,yy) && (xx != u.ux || yy != u.uy))
1544 | 		    if (mdat != &mons[PM_GRID_BUG] || xx == x || yy == y)
1545 | 			if (/* (xx==x && yy==y) || */ !level.monsters[xx][yy])
1546 | 			    if ((t = t_at(xx, yy)) != 0 &&
1547 | 			      (ignore_boulders || !sobj_at(BOULDER, xx, yy))
1548 | 			      && !onscary(xx, yy, mtmp)) {
1549 | 				if (t->ttyp == POLY_TRAP) {
1550 | 				    trapx = xx;
1551 | 				    trapy = yy;
1552 | 				    m.has_misc = MUSE_POLY_TRAP;
1553 | 				    return TRUE;
1554 | 				}
1555 | 			    }
1556 | 	}
1557 | 	if (nohands(mdat))
1558 | 		return 0;
1559 | 
1560 | #define nomore(x) if(m.has_misc==x) continue;
1561 | 	for(obj=mtmp->minvent; obj; obj=obj->nobj) {
1562 | 		/* Monsters shouldn't recognize cursed items; this kludge is */
1563 | 		/* necessary to prevent serious problems though... */
1564 | 		if(obj->otyp == POT_GAIN_LEVEL && (!obj->cursed ||
1565 | 			    (!mtmp->isgd && !mtmp->isshk && !mtmp->ispriest))) {
1566 | 			m.misc = obj;
1567 | 			m.has_misc = MUSE_POT_GAIN_LEVEL;
1568 | 		}
1569 | 		nomore(MUSE_BULLWHIP);
1570 | 		if(obj->otyp == BULLWHIP && (MON_WEP(mtmp) == obj) &&
1571 | 		   distu(mtmp->mx,mtmp->my)==1 && uwep && !mtmp->mpeaceful) {
1572 | 			m.misc = obj;
1573 | 			m.has_misc = MUSE_BULLWHIP;
1574 | 		}
1575 | 		/* Note: peaceful/tame monsters won't make themselves
1576 | 		 * invisible unless you can see them.  Not really right, but...
1577 | 		 */
1578 | 		nomore(MUSE_WAN_MAKE_INVISIBLE);
1579 | 		if(obj->otyp == WAN_MAKE_INVISIBLE && obj->spe > 0 &&
1580 | 		    !mtmp->minvis && !mtmp->invis_blkd &&
1581 | 		    (!mtmp->mpeaceful || See_invisible) &&
1582 | 		    (mdat != &mons[PM_MEDUSA] || mtmp->mcan)) {
1583 | 			m.misc = obj;
1584 | 			m.has_misc = MUSE_WAN_MAKE_INVISIBLE;
1585 | 		}
1586 | 		nomore(MUSE_POT_INVISIBILITY);
1587 | 		if(obj->otyp == POT_INVISIBILITY &&
1588 | 		    !mtmp->minvis && !mtmp->invis_blkd &&
1589 | 		    (!mtmp->mpeaceful || See_invisible) &&
1590 | 		    (mdat != &mons[PM_MEDUSA] || mtmp->mcan)) {
1591 | 			m.misc = obj;
1592 | 			m.has_misc = MUSE_POT_INVISIBILITY;
1593 | 		}
1594 | 		nomore(MUSE_WAN_SPEED_MONSTER);
1595 | 		if(obj->otyp == WAN_SPEED_MONSTER && obj->spe > 0
1596 | 				&& mtmp->mspeed != MFAST && !mtmp->isgd) {
1597 | 			m.misc = obj;
1598 | 			m.has_misc = MUSE_WAN_SPEED_MONSTER;
1599 | 		}
1600 | 		nomore(MUSE_POT_SPEED);
1601 | 		if(obj->otyp == POT_SPEED && mtmp->mspeed != MFAST
1602 | 							&& !mtmp->isgd) {
1603 | 			m.misc = obj;
1604 | 			m.has_misc = MUSE_POT_SPEED;
1605 | 		}
1606 | 		nomore(MUSE_WAN_POLYMORPH);
1607 | 		if(obj->otyp == WAN_POLYMORPH && obj->spe > 0 && !mtmp->cham
1608 | 				&& monstr[monsndx(mdat)] < 6) {
1609 | 			m.misc = obj;
1610 | 			m.has_misc = MUSE_WAN_POLYMORPH;
1611 | 		}
1612 | 		nomore(MUSE_POT_POLYMORPH);
1613 | 		if(obj->otyp == POT_POLYMORPH && !mtmp->cham
1614 | 				&& monstr[monsndx(mdat)] < 6) {
1615 | 			m.misc = obj;
1616 | 			m.has_misc = MUSE_POT_POLYMORPH;
1617 | 		}
1618 | 	}
1619 | 	return((boolean)(!!m.has_misc));
1620 | #undef nomore
1621 | }
1622 | 
1623 | int
1624 | use_misc(mtmp)
1625 | struct monst *mtmp;
1626 | {
1627 | 	int i;
1628 | 	struct obj *otmp = m.misc;
1629 | 	boolean vis, vismon, oseen;
1630 | 	char nambuf[BUFSZ];
1631 | 
1632 | 	if ((i = precheck(mtmp, otmp)) != 0) return i;
1633 | 	vis = cansee(mtmp->mx, mtmp->my);
1634 | 	vismon = canseemon(mtmp);
1635 | 	oseen = otmp && vismon;
1636 | 
1637 | 	switch(m.has_misc) {
1638 | 	case MUSE_POT_GAIN_LEVEL:
1639 | 		mquaffmsg(mtmp, otmp);
1640 | 		if (otmp->cursed) {
1641 | 		    if (Can_rise_up(mtmp->mx, mtmp->my, &u.uz)) {
1642 | 			register int tolev = depth(&u.uz)-1;
1643 | 			d_level tolevel;
1644 | 
1645 | 			get_level(&tolevel, tolev);
1646 | 			/* insurance against future changes... */
1647 | 			if(on_level(&tolevel, &u.uz)) goto skipmsg;
1648 | 			if (vismon) {
1649 | 			    pline("%s rises up, through the %s!",
1650 | 				  Monnam(mtmp), ceiling(mtmp->mx, mtmp->my));
1651 | 			    if(!objects[POT_GAIN_LEVEL].oc_name_known
1652 | 			      && !objects[POT_GAIN_LEVEL].oc_uname)
1653 | 				docall(otmp);
1654 | 			}
1655 | 			m_useup(mtmp, otmp);
1656 | 			migrate_to_level(mtmp, ledger_no(&tolevel),
1657 | 					 MIGR_RANDOM, (coord *)0);
1658 | 			return 2;
1659 | 		    } else {
1660 | skipmsg:
1661 | 			if (vismon) {
1662 | 			    pline("%s looks uneasy.", Monnam(mtmp));
1663 | 			    if(!objects[POT_GAIN_LEVEL].oc_name_known
1664 | 			      && !objects[POT_GAIN_LEVEL].oc_uname)
1665 | 				docall(otmp);
1666 | 			}
1667 | 			m_useup(mtmp, otmp);
1668 | 			return 2;
1669 | 		    }
1670 | 		}
1671 | 		if (vismon) pline("%s seems more experienced.", Monnam(mtmp));
1672 | 		if (oseen) makeknown(POT_GAIN_LEVEL);
1673 | 		m_useup(mtmp, otmp);
1674 | 		if (!grow_up(mtmp,(struct monst *)0)) return 1;
1675 | 			/* grew into genocided monster */
1676 | 		return 2;
1677 | 	case MUSE_WAN_MAKE_INVISIBLE:
1678 | 	case MUSE_POT_INVISIBILITY:
1679 | 		if (otmp->otyp == WAN_MAKE_INVISIBLE) {
1680 | 		    mzapmsg(mtmp, otmp, TRUE);
1681 | 		    otmp->spe--;
1682 | 		} else
1683 | 		    mquaffmsg(mtmp, otmp);
1684 | 		/* format monster's name before altering its visibility */
1685 | 		Strcpy(nambuf, See_invisible ? Monnam(mtmp) : mon_nam(mtmp));
1686 | 		mon_set_minvis(mtmp);
1687 | 		if (vismon && mtmp->minvis) {	/* was seen, now invisible */
1688 | 		    if (See_invisible)
1689 | 			pline("%s body takes on a %s transparency.",
1690 | 			      s_suffix(nambuf),
1691 | 			      Hallucination ? "normal" : "strange");
1692 | 		    else
1693 | 			pline("Suddenly you cannot see %s.", nambuf);
1694 | 		    if (oseen) makeknown(otmp->otyp);
1695 | 		}
1696 | 		if (otmp->otyp == POT_INVISIBILITY) {
1697 | 		    if (otmp->cursed) you_aggravate(mtmp);
1698 | 		    m_useup(mtmp, otmp);
1699 | 		}
1700 | 		return 2;
1701 | 	case MUSE_WAN_SPEED_MONSTER:
1702 | 		mzapmsg(mtmp, otmp, TRUE);
1703 | 		otmp->spe--;
1704 | 		mon_adjust_speed(mtmp, 1);
1705 | 		return 2;
1706 | 	case MUSE_POT_SPEED:
1707 | 		mquaffmsg(mtmp, otmp);
1708 | 		/* note difference in potion effect due to substantially
1709 | 		   different methods of maintaining speed ratings:
1710 | 		   player's character becomes "very fast" temporarily;
1711 | 		   monster becomes "one stage faster" permanently */
1712 | 		if (vismon)
1713 | 		    pline("%s is suddenly moving faster.", Monnam(mtmp));
1714 | 		if (oseen) makeknown(POT_SPEED);
1715 | 		mon_adjust_speed(mtmp, 1);
1716 | 		m_useup(mtmp, otmp);
1717 | 		return 2;
1718 | 	case MUSE_WAN_POLYMORPH:
1719 | 		mzapmsg(mtmp, otmp, TRUE);
1720 | 		otmp->spe--;
1721 | 		(void) newcham(mtmp, rndmonst());
1722 | 		if (oseen) makeknown(WAN_POLYMORPH);
1723 | 		return 2;
1724 | 	case MUSE_POT_POLYMORPH:
1725 | 		mquaffmsg(mtmp, otmp);
1726 | 		if (vismon) pline("%s suddenly mutates!", Monnam(mtmp));
1727 | 		(void) newcham(mtmp, rndmonst());
1728 | 		if (oseen) makeknown(POT_POLYMORPH);
1729 | 		m_useup(mtmp, otmp);
1730 | 		return 2;
1731 | 	case MUSE_POLY_TRAP:
1732 | 		if (vismon)
1733 | 		    pline("%s deliberately %s onto a polymorph trap!",
1734 | 			Monnam(mtmp),
1735 | 			makeplural(locomotion(mtmp->data, "jump")));
1736 | 		if (vis) seetrap(t_at(trapx,trapy));
1737 | 
1738 | 		/*  don't use rloc() due to worms */
1739 | 		remove_monster(mtmp->mx, mtmp->my);
1740 | 		newsym(mtmp->mx, mtmp->my);
1741 | 		place_monster(mtmp, trapx, trapy);
1742 | 		if (mtmp->wormno) worm_move(mtmp);
1743 | 		newsym(trapx, trapy);
1744 | 
1745 | 		(void) newcham(mtmp, (struct permonst *)0);
1746 | 		return 2;
1747 | 	case MUSE_BULLWHIP:
1748 | 		/* attempt to disarm hero */
1749 | 		if (uwep && !rn2(5)) {
1750 | 		    const char *The_whip = vismon ? "The bullwhip" : "A whip";
1751 | 		    int where_to = rn2(4);
1752 | 		    struct obj *obj = uwep;
1753 | 		    const char *hand;
1754 | 		    char the_weapon[BUFSZ];
1755 | 
1756 | 		    Strcpy(the_weapon, the(xname(obj)));
1757 | 		    hand = body_part(HAND);
1758 | 		    if (bimanual(obj)) hand = makeplural(hand);
1759 | 
1760 | 		    if (vismon)
1761 | 			pline("%s flicks a bullwhip towards your %s!",
1762 | 			      Monnam(mtmp), hand);
1763 | 		    if (obj->otyp == HEAVY_IRON_BALL) {
1764 | 			pline("%s fails to wrap around %s.",
1765 | 			      The_whip, the_weapon);
1766 | 			return 1;
1767 | 		    }
1768 | 		    pline("%s wraps around %s you're wielding!",
1769 | 			  The_whip, the_weapon);
1770 | 		    if (obj->cursed) {
1771 | 			pline("%s is welded to your %s%c",
1772 | 			      (obj->quan == 1L) ? "It" : "They",
1773 | 			      hand, !obj->bknown ? '!' : '.');
1774 | 			obj->bknown = 1;
1775 | 			where_to = 0;
1776 | 		    }
1777 | 		    if (!where_to) {
1778 | 			pline_The("whip slips free.");  /* not `The_whip' */
1779 | 			return 1;
1780 | 		    }
1781 | 		    freeinv(obj);
1782 | 		    uwepgone();
1783 | 		    switch (where_to) {
1784 | 			case 1:		/* onto floor beneath mon */
1785 | 			    pline("%s yanks %s from your %s!", Monnam(mtmp),
1786 | 				  the_weapon, hand);
1787 | 			    if (obj->otyp == CRYSKNIFE && (!obj->oerodeproof || !rn2(10))) {
1788 | 			    	obj->otyp = WORM_TOOTH;
1789 | 			    	obj->oerodeproof = 0;
1790 | 			    }
1791 | 			    place_object(obj, mtmp->mx, mtmp->my);
1792 | 			    break;
1793 | 			case 2:		/* onto floor beneath you */
1794 | 			    pline("%s yanks %s to the %s!", Monnam(mtmp),
1795 | 				  the_weapon, surface(u.ux, u.uy));
1796 | 			    dropy(obj);
1797 | 			    break;
1798 | 			case 3:		/* into mon's inventory */
1799 | 			    pline("%s snatches %s!", Monnam(mtmp),
1800 | 				  the_weapon);
1801 | 			    (void) mpickobj(mtmp,obj);
1802 | 			    break;
1803 | 		    }
1804 | 		    return 1;
1805 | 		}
1806 | 		return 0;
1807 | 	case 0: return 0; /* i.e. an exploded wand */
1808 | 	default: impossible("%s wanted to perform action %d?", Monnam(mtmp),
1809 | 			m.has_misc);
1810 | 		break;
1811 | 	}
1812 | 	return 0;
1813 | }
1814 | 
1815 | STATIC_OVL void
1816 | you_aggravate(mtmp)
1817 | struct monst *mtmp;
1818 | {
1819 | 	pline("For some reason, %s presence is known to you.",
1820 | 		s_suffix(noit_mon_nam(mtmp)));
1821 | 	cls();
1822 | #ifdef CLIPPING
1823 | 	cliparound(mtmp->mx, mtmp->my);
1824 | #endif
1825 | 	show_glyph(mtmp->mx, mtmp->my, mon_to_glyph(mtmp));
1826 | 	display_self();
1827 | 	You_feel("aggravated at %s.", noit_mon_nam(mtmp));
1828 | 	display_nhwindow(WIN_MAP, TRUE);
1829 | 	docrt();
1830 | 	if (unconscious()) {
1831 | 		multi = -1;
1832 | 		nomovemsg =
1833 | 		      "Aggravated, you are jolted into full consciousness.";
1834 | 	}
1835 | 	newsym(mtmp->mx,mtmp->my);
1836 | 	if (!canspotmon(mtmp))
1837 | 	    map_invisible(mtmp->mx, mtmp->my);
1838 | }
1839 | 
1840 | int
1841 | rnd_misc_item(mtmp)
1842 | struct monst *mtmp;
1843 | {
1844 | 	struct permonst *pm = mtmp->data;
1845 | 	int difficulty = monstr[(monsndx(pm))];
1846 | 
1847 | 	if(is_animal(pm) || attacktype(pm, AT_EXPL) || mindless(mtmp->data)
1848 | 			|| pm->mlet == S_GHOST
1849 | # ifdef KOPS
1850 | 			|| pm->mlet == S_KOP
1851 | # endif
1852 | 		) return 0;
1853 | 	/* Unlike other rnd_item functions, we only allow _weak_ monsters
1854 | 	 * to have this item; after all, the item will be used to strengthen
1855 | 	 * the monster and strong monsters won't use it at all...
1856 | 	 */
1857 | 	if (difficulty < 6 && !rn2(30))
1858 | 	    return rn2(6) ? POT_POLYMORPH : WAN_POLYMORPH;
1859 | 
1860 | 	if (!rn2(40) && !nonliving(pm)) return AMULET_OF_LIFE_SAVING;
1861 | 
1862 | 	switch (rn2(3)) {
1863 | 		case 0:
1864 | 			if (mtmp->isgd) return 0;
1865 | 			return rn2(6) ? POT_SPEED : WAN_SPEED_MONSTER;
1866 | 		case 1:
1867 | 			if (mtmp->mpeaceful && !See_invisible) return 0;
1868 | 			return rn2(6) ? POT_INVISIBILITY : WAN_MAKE_INVISIBLE;
1869 | 		case 2:
1870 | 			return POT_GAIN_LEVEL;
1871 | 	}
1872 | 	/*NOTREACHED*/
1873 | 	return 0;
1874 | }
1875 | 
1876 | boolean
1877 | searches_for_item(mon, obj)
1878 | struct monst *mon;
1879 | struct obj *obj;
1880 | {
1881 | 	int typ = obj->otyp;
1882 | 
1883 | 	if (is_animal(mon->data) ||
1884 | 		mindless(mon->data) ||
1885 | 		mon->data == &mons[PM_GHOST])	/* don't loot bones piles */
1886 | 	    return FALSE;
1887 | 
1888 | 	if (typ == WAN_MAKE_INVISIBLE || typ == POT_INVISIBILITY)
1889 | 	    return (boolean)(!mon->minvis && !mon->invis_blkd);
1890 | 	if (typ == WAN_SPEED_MONSTER || typ == POT_SPEED)
1891 | 	    return (boolean)(mon->mspeed != MFAST);
1892 | 
1893 | 	switch (obj->oclass) {
1894 | 	case WAND_CLASS:
1895 | 	    if (typ == WAN_DIGGING)
1896 | 		return (boolean)(!is_floater(mon->data));
1897 | 	    if (typ == WAN_POLYMORPH)
1898 | 		return (boolean)(monstr[monsndx(mon->data)] < 6);
1899 | 	    if (objects[typ].oc_dir == RAY ||
1900 | 		    typ == WAN_STRIKING ||
1901 | 		    typ == WAN_TELEPORTATION ||
1902 | 		    typ == WAN_CREATE_MONSTER)
1903 | 		return TRUE;
1904 | 	    break;
1905 | 	case POTION_CLASS:
1906 | 	    if (typ == POT_HEALING ||
1907 | 		    typ == POT_EXTRA_HEALING ||
1908 | 		    typ == POT_FULL_HEALING ||
1909 | 		    typ == POT_POLYMORPH ||
1910 | 		    typ == POT_GAIN_LEVEL ||
1911 | 		    typ == POT_PARALYSIS ||
1912 | 		    typ == POT_SLEEPING ||
1913 | 		    typ == POT_ACID ||
1914 | 		    typ == POT_BLINDNESS ||
1915 | 		    typ == POT_CONFUSION)
1916 | 		return TRUE;
1917 | 	    break;
1918 | 	case SCROLL_CLASS:
1919 | 	    if (typ == SCR_TELEPORTATION || typ == SCR_CREATE_MONSTER
1920 | 		    || typ == SCR_EARTH)
1921 | 		return TRUE;
1922 | 	    break;
1923 | 	case AMULET_CLASS:
1924 | 	    if (typ == AMULET_OF_LIFE_SAVING)
1925 | 		return (boolean)(!nonliving(mon->data));
1926 | 	    if (typ == AMULET_OF_REFLECTION)
1927 | 		return TRUE;
1928 | 	    break;
1929 | 	case TOOL_CLASS:
1930 | 	    if (typ == PICK_AXE)
1931 | 		return (boolean)needspick(mon->data);
1932 | 	    if (typ == UNICORN_HORN)
1933 | 		return (boolean)(!obj->cursed && !is_unicorn(mon->data));
1934 | 	    if (typ == FROST_HORN || typ == FIRE_HORN)
1935 | 		return TRUE;
1936 | 	    break;
1937 | 	case FOOD_CLASS:
1938 | 	    if (typ == CORPSE)
1939 | 		return (boolean)(((mon->misc_worn_check & W_ARMG) &&
1940 | 				    touch_petrifies(&mons[obj->corpsenm])) ||
1941 | 				(!resists_ston(mon) &&
1942 | 				    (obj->corpsenm == PM_LIZARD ||
1943 | 					acidic(&mons[obj->corpsenm]))));
1944 | 	    if (typ == EGG)
1945 | 		return (boolean)(touch_petrifies(&mons[obj->corpsenm]));
1946 | 	    break;
1947 | 	default:
1948 | 	    break;
1949 | 	}
1950 | 
1951 | 	return FALSE;
1952 | }
1953 | 
1954 | boolean
1955 | mon_reflects(mon,str)
1956 | struct monst *mon;
1957 | const char *str;
1958 | {
1959 | 	struct obj *orefl = which_armor(mon, W_ARMS);
1960 | 
1961 | 	if (orefl && orefl->otyp == SHIELD_OF_REFLECTION) {
1962 | 	    if (str) {
1963 | 		pline(str, s_suffix(mon_nam(mon)), "shield");
1964 | 		makeknown(SHIELD_OF_REFLECTION);
1965 | 	    }
1966 | 	    return TRUE;
1967 | 	} else if ((orefl = which_armor(mon, W_AMUL)) &&
1968 | 				orefl->otyp == AMULET_OF_REFLECTION) {
1969 | 	    if (str) {
1970 | 		pline(str, s_suffix(mon_nam(mon)), "amulet");
1971 | 		makeknown(AMULET_OF_REFLECTION);
1972 | 	    }
1973 | 	    return TRUE;
1974 | 	} else if ((orefl = which_armor(mon, W_ARM)) &&
1975 | 		(orefl->otyp == SILVER_DRAGON_SCALES || orefl->otyp == SILVER_DRAGON_SCALE_MAIL)) {
1976 | 	    if (str)
1977 | 		pline(str, s_suffix(mon_nam(mon)), "armor");
1978 | 	    return TRUE;
1979 | 	} else if (mon->data == &mons[PM_SILVER_DRAGON]) {
1980 | 	    /* Silver dragons only reflect when mature; babies do not */
1981 | 	    if (str)
1982 | 		pline(str, s_suffix(mon_nam(mon)), "scales");
1983 | 	    return TRUE;
1984 | 	}
1985 | 	return FALSE;
1986 | }
1987 | 
1988 | boolean
1989 | ureflects (fmt, str)
1990 | const char *fmt, *str;
1991 | {
1992 | 	/* Check from outermost to innermost objects */
1993 | 	if (EReflecting & W_ARMS) {
1994 | 	    if (fmt && str) {
1995 | 	    	pline(fmt, str, "shield");
1996 | 	    	makeknown(SHIELD_OF_REFLECTION);
1997 | 	    }
1998 | 	    return TRUE;
1999 | 	} else if (EReflecting & W_WEP) {
2000 | 	    /* Due to wielded artifact weapon */
2001 | 	    if (fmt && str)
2002 | 	    	pline(fmt, str, "weapon");
2003 | 	    return TRUE;
2004 | 	} else if (EReflecting & W_AMUL) {
2005 | 	    if (fmt && str) {
2006 | 	    	pline(fmt, str, "medallion");
2007 | 	    	makeknown(AMULET_OF_REFLECTION);
2008 | 	    }
2009 | 	    return TRUE;
2010 | 	} else if (EReflecting & W_ARM) {
2011 | 	    if (fmt && str)
2012 | 	    	pline(fmt, str, "armor");
2013 | 	    return TRUE;
2014 | 	} else if (youmonst.data == &mons[PM_SILVER_DRAGON]) {
2015 | 	    if (fmt && str)
2016 | 	    	pline(fmt, str, "scales");
2017 | 	    return TRUE;
2018 | 	}
2019 | 	return FALSE;
2020 | }
2021 | 
2022 | 
2023 | /* TRUE if the monster ate something */
2024 | boolean
2025 | munstone(mon, by_you)
2026 | struct monst *mon;
2027 | boolean by_you;
2028 | {
2029 | 	struct obj *obj;
2030 | 
2031 | 	if (resists_ston(mon)) return FALSE;
2032 | 	if (mon->meating || !mon->mcanmove || mon->msleeping) return FALSE;
2033 | 
2034 | 	for(obj = mon->minvent; obj; obj = obj->nobj) {
2035 | 	    /* Monsters can also use potions of acid */
2036 | 	    if ((obj->otyp == POT_ACID) || (obj->otyp == CORPSE &&
2037 | 	    		(obj->corpsenm == PM_LIZARD || acidic(&mons[obj->corpsenm])))) {
2038 | 		int nutrit = dog_nutrition(mon, obj); /* also sets meating */
2039 | 
2040 | 		if (canseemon(mon)) {
2041 | 		    long save_quan = obj->quan;
2042 | 
2043 | 		    obj->quan = 1L;
2044 | 		    pline("%s %ss %s.", Monnam(mon),
2045 | 		    		(obj->otyp == POT_ACID) ? "quaff" : "eat",
2046 | 		    		distant_name(obj,doname));
2047 | 		    obj->quan = save_quan;
2048 | 		} else if (flags.soundok)
2049 | 		    You_hear("%s.", (obj->otyp == POT_ACID) ? "drinking" : "chewing");
2050 | 		m_useup(mon, obj);
2051 | 		if (((obj->otyp == POT_ACID) || acidic(&mons[obj->corpsenm])) &&
2052 | 				!resists_acid(mon)) {
2053 | 		    mon->mhp -= rnd(15);
2054 | 		    pline("%s has a very bad case of stomach acid.",
2055 | 			Monnam(mon));
2056 | 		}
2057 | 		if (mon->mhp <= 0) {
2058 | 		    pline("%s dies!", Monnam(mon));
2059 | 		    if (by_you) xkilled(mon, 0);
2060 | 		    else mondead(mon);
2061 | 		    return TRUE;
2062 | 		}
2063 | 		if (canseemon(mon)) {
2064 | 		    if (Hallucination)
2065 | 		pline("What a pity - %s just ruined a future piece of art!",
2066 | 			mon_nam(mon));
2067 | 		    else
2068 | 			pline("%s seems limber!", Monnam(mon));
2069 | 		}
2070 | 		if (mon->mtame && !mon->isminion) {
2071 | 		    struct edog *edog = EDOG(mon);
2072 | 
2073 | 		    if (edog->hungrytime < moves) edog->hungrytime = moves;
2074 | 		    edog->hungrytime += nutrit;
2075 | 		    mon->mconf = 0;
2076 | 		}
2077 | 		mon->mlstmv = monstermoves; /* it takes a turn */
2078 | 		return TRUE;
2079 | 	    }
2080 | 	}
2081 | 	return FALSE;
2082 | }
2083 | 
2084 | /*muse.c*/