FANDOM


Below is the full text to monmove.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/monmove.c#line123]], for example.

The latest source code for vanilla NetHack is at Source code.


The NetHack General Public License applies to screenshots, source code and other content from NetHack.
1.    /*	SCCS Id: @(#)monmove.c	3.4	2002/04/06	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    #include "hack.h"
6.    #include "mfndpos.h"
7.    #include "artifact.h"
8.    #include "epri.h"
9.    
10.   extern boolean notonhead;
11.   
12.   #ifdef OVL0
13.   
14.   STATIC_DCL int FDECL(disturb,(struct monst *));
15.   STATIC_DCL void FDECL(distfleeck,(struct monst *,int *,int *,int *));
16.   STATIC_DCL int FDECL(m_arrival, (struct monst *));
17.   STATIC_DCL void FDECL(watch_on_duty,(struct monst *));
18.   /* WAC for breath door busting */
19.   static int FDECL(bust_door_breath, (struct monst *));
20.   
21.   #endif /* OVL0 */
22.   #ifdef OVLB
23.   
24.   boolean /* TRUE : mtmp died */
25.   mb_trapped(mtmp)
26.   register struct monst *mtmp;
27.   {
28.   	if (flags.verbose) {
29.   	    if (cansee(mtmp->mx, mtmp->my))
30.   		pline("KABOOM!!  You see a door explode.");
31.   	    else if (flags.soundok)
32.   		You_hear("a distant explosion.");
33.   	}
34.   	wake_nearto(mtmp->mx, mtmp->my, 7*7);
35.   	mtmp->mstun = 1;
36.   	mtmp->mhp -= rnd(15);
37.   	if(mtmp->mhp <= 0) {
38.   		mondied(mtmp);
39.   		if (mtmp->mhp > 0) /* lifesaved */
40.   			return(FALSE);
41.   		else
42.   			return(TRUE);
43.   	}
44.   	return(FALSE);
45.   }
46.   
47.   #endif /* OVLB */
48.   #ifdef OVL0
49.   
50.   STATIC_OVL void
51.   watch_on_duty(mtmp)
52.   register struct monst *mtmp;
53.   {
54.   	int	x, y;
55.   
56.   	if(mtmp->mpeaceful && in_town(u.ux+u.dx, u.uy+u.dy) &&
57.   	   mtmp->mcansee && m_canseeu(mtmp) && !rn2(3)) {
58.   
59.   	    if(picking_lock(&x, &y) && IS_DOOR(levl[x][y].typ) &&
60.   	       (levl[x][y].doormask & D_LOCKED)) {
61.   
62.   		if(couldsee(mtmp->mx, mtmp->my)) {
63.   
64.   		  pline("%s yells:", Amonnam(mtmp));
65.   		  if(levl[x][y].looted & D_WARNED) {
66.   			verbalize("Halt, thief!  You're under arrest!");
67.   			(void) angry_guards(!(flags.soundok));
68.   		  } else {
69.   			int i;
70.   			verbalize("Hey, stop picking that lock!");
71.   			/* [ALI] Since marking a door as warned will have
72.   			 * the side effect of trapping the door, it must be
73.   			 * included in the doors[] array in order that trap
74.   			 * detection will find it.
75.   			 */
76.   			for(i = doorindex - 1; i >= 0; i--)
77.   			    if (x == doors[i].x && y == doors[i].y)
78.   				break;
79.   			if (i < 0)
80.   			    i = add_door(x, y, (struct mkroom *)0);
81.   			if (i >= 0)
82.   			    levl[x][y].looted |= D_WARNED;
83.   		  }
84.   		  stop_occupation();
85.   		}
86.   	    } else if (is_digging()) {
87.   		/* chewing, wand/spell of digging are checked elsewhere */
88.   		watch_dig(mtmp, digging.pos.x, digging.pos.y, FALSE);
89.   	    }
90.   	}
91.   }
92.   
93.   #endif /* OVL0 */
94.   #ifdef OVL1
95.   
96.   int
97.   dochugw(mtmp)
98.   register struct monst *mtmp;
99.   {
100.  	register int x = mtmp->mx, y = mtmp->my;
101.  	boolean already_saw_mon = !occupation ? 0 : canspotmon(mtmp);
102.  	int rd = dochug(mtmp);
103.  #if 0
104.  	/* part of the original warning code which was replaced in 3.3.1 */
105.  	register struct permonst *mdat = mtmp->data;        
106.  	int dd;
107.  	if(Warning && !rd && !mtmp->mpeaceful &&
108.  			(dd = distu(mtmp->mx,mtmp->my)) < distu(x,y) &&
109.  			dd < 100 && !canseemon(mtmp)) {
110.  	    /* Note: this assumes we only want to warn against the monster to
111.  	     * which the weapon does extra damage, as there is no "monster
112.  	     * which the weapon warns against" field.
113.  	     */
114.  	    if (spec_ability(uwep, SPFX_WARN) && spec_dbon(uwep, mtmp, 1))
115.  		warnlevel = 100;
116.  	    else if ((int) (mtmp->m_lev / 4) > warnlevel)
117.  		warnlevel = (mtmp->m_lev / 4);
118.  	/* STEPHEN WHITE'S NEW CODE */
119.  	} else if(Undead_warning && !rd && !mtmp->mpeaceful &&
120.  		  (dd = distu(mtmp->mx,mtmp->my)) < distu(x,y) &&
121.  		   dd < 100 && !canseemon(mtmp) && is_undead(mdat)) {
122.  			/* 
123.  			 * The value of warnlevel coresponds to the 8 
124.  			 * cardinal directions, see mon.c.
125.  			 */
126.  			if(((mtmp->mx - u.ux) < 0) && ((mtmp->my - u.uy) < 0))
127.  				warnlevel = 101;
128.  			if(((mtmp->mx - u.ux) == 0) && ((mtmp->my - u.uy) < 0))
129.  				warnlevel = 102;
130.  			if(((mtmp->mx - u.ux) > 0) && ((mtmp->my - u.uy) < 0))
131.  				warnlevel = 103;
132.  			if(((mtmp->mx - u.ux) < 0) && ((mtmp->my - u.uy) == 0))
133.  				warnlevel = 104;
134.  			if(((mtmp->mx - u.ux) > 0) && ((mtmp->my - u.uy) == 0))
135.  				warnlevel = 105;
136.  			if(((mtmp->mx - u.ux) < 0) && ((mtmp->my - u.uy) > 0))
137.  				warnlevel = 106;
138.  			if(((mtmp->mx - u.ux) == 0) && ((mtmp->my - u.uy) > 0))
139.  				warnlevel = 107;
140.  			if(((mtmp->mx - u.ux) > 0) && ((mtmp->my - u.uy) > 0))
141.  				warnlevel = 108;
142.  	}
143.  #endif /* 0 */
144.  
145.  	/* a similar check is in monster_nearby() in hack.c */
146.  	/* check whether hero notices monster and stops current activity */
147.  	if (occupation && !rd && !Confusion &&
148.  	    (!mtmp->mpeaceful || Hallucination) &&
149.  	    /* it's close enough to be a threat */
150.  	    distu(mtmp->mx,mtmp->my) <= (BOLT_LIM+1)*(BOLT_LIM+1) &&
151.  	    /* and either couldn't see it before, or it was too far away */
152.  	    (!already_saw_mon || !couldsee(x,y) ||
153.  		distu(x,y) > (BOLT_LIM+1)*(BOLT_LIM+1)) &&
154.  	    /* can see it now, or sense it and would normally see it */
155.  	    (canseemon(mtmp) ||
156.  		(sensemon(mtmp) && couldsee(mtmp->mx,mtmp->my))) &&
157.  	    mtmp->mcanmove &&
158.  	    !noattacks(mtmp->data) && !onscary(u.ux, u.uy, mtmp))
159.  		stop_occupation();
160.  	return(rd);
161.  }
162.  
163.  #endif /* OVL1 */
164.  #ifdef OVL2
165.  
166.  boolean
167.  onscary(x, y, mtmp)
168.  int x, y;
169.  struct monst *mtmp;
170.  {
171.  	if (mtmp->isshk || mtmp->isgd || mtmp->iswiz || !mtmp->mcansee ||
172.  			mtmp->mpeaceful || mtmp->data->mlet == S_HUMAN ||
173.  	    is_lminion(mtmp) || mtmp->data == &mons[PM_ANGEL] ||
174.  	    mtmp->data == &mons[PM_CTHULHU] ||
175.  	    is_rider(mtmp->data) || mtmp->data == &mons[PM_MINOTAUR])
176.  		return(FALSE);
177.  
178.  	return (boolean)(sobj_at(SCR_SCARE_MONSTER, x, y)
179.  #ifdef ELBERETH
180.  			 || sengr_at("Elbereth", x, y)
181.  #endif
182.  			 || (is_vampire(mtmp->data)
183.  			     && IS_ALTAR(levl[x][y].typ)));
184.  }
185.  
186.  #endif /* OVL2 */
187.  #ifdef OVL0
188.  
189.  /* regenerate lost hit points */
190.  void
191.  mon_regen(mon, digest_meal)
192.  struct monst *mon;
193.  boolean digest_meal;
194.  {
195.  	if (mon->mhp < mon->mhpmax && !is_golem(mon->data) &&
196.  	    (moves % 20 == 0 || regenerates(mon->data))) mon->mhp++;
197.  	if (mon->m_en < mon->m_enmax && 
198.  	    (moves % 20 == 0 || (rn2(mon->m_lev + 5) > 15))) {
199.  	    	mon->m_en += rn1((mon->m_lev % 10 + 1),1);
200.  	    	if (mon->m_en > mon->m_enmax) mon->m_en = mon->m_enmax;
201.  	}
202.  	if (mon->mspec_used) mon->mspec_used--;
203.  	if (digest_meal) {
204.  	    if (mon->meating) mon->meating--;
205.  	}
206.  }
207.  
208.  /*
209.   * Possibly awaken the given monster.  Return a 1 if the monster has been
210.   * jolted awake.
211.   */
212.  STATIC_OVL int
213.  disturb(mtmp)
214.  	register struct monst *mtmp;
215.  {
216.  	/*
217.  	 * + Ettins are hard to surprise.
218.  	 * + Nymphs, jabberwocks, and leprechauns do not easily wake up.
219.  	 *
220.  	 * Wake up if:
221.  	 *	in direct LOS						AND
222.  	 *	within 10 squares					AND
223.  	 *	not stealthy or (mon is an ettin and 9/10)		AND
224.  	 *	(mon is not a nymph, jabberwock, or leprechaun) or 1/50	AND
225.  	 *	Aggravate or mon is (dog or human) or
226.  	 *	    (1/7 and mon is not mimicing furniture or object)
227.  	 */
228.  	if(couldsee(mtmp->mx,mtmp->my) &&
229.  		distu(mtmp->mx,mtmp->my) <= 100 &&
230.  		(!Stealth || (mtmp->data == &mons[PM_ETTIN] && rn2(10))) &&
231.  		(!(mtmp->data->mlet == S_NYMPH
232.  			|| mtmp->data == &mons[PM_JABBERWOCK]
233.  			|| mtmp->data == &mons[PM_VORPAL_JABBERWOCK]
234.  #if 0	/* DEFERRED */
235.  			|| mtmp->data == &mons[PM_VORPAL_JABBERWOCK]
236.  #endif
237.  			|| mtmp->data->mlet == S_LEPRECHAUN) || !rn2(50)) &&
238.  		(Aggravate_monster
239.  			|| (mtmp->data->mlet == S_DOG ||
240.  				mtmp->data->mlet == S_HUMAN)
241.  			|| (!rn2(7) && mtmp->m_ap_type != M_AP_FURNITURE &&
242.  				mtmp->m_ap_type != M_AP_OBJECT) )) {
243.  		mtmp->msleeping = 0;
244.  		return(1);
245.  	}
246.  	return(0);
247.  }
248.  
249.  /* monster begins fleeing for the specified time, 0 means untimed flee
250.   * if first, only adds fleetime if monster isn't already fleeing
251.   * if fleemsg, prints a message about new flight, otherwise, caller should */
252.  void
253.  monflee(mtmp, fleetime, first, fleemsg)
254.  struct monst *mtmp;
255.  int fleetime;
256.  boolean first;
257.  boolean fleemsg;
258.  {
259.  	if (u.ustuck == mtmp) {
260.  	    if (u.uswallow)
261.  		expels(mtmp, mtmp->data, TRUE);
262.  	    else if (!sticks(youmonst.data)) {
263.  		unstuck(mtmp);	/* monster lets go when fleeing */
264.  		You("get released!");
265.  	    }
266.  	}
267.  
268.  	if (!first || !mtmp->mflee) {
269.  	    /* don't lose untimed scare */
270.  	    if (!fleetime)
271.  		mtmp->mfleetim = 0;
272.  	    else if (!mtmp->mflee || mtmp->mfleetim) {
273.  		fleetime += mtmp->mfleetim;
274.  		/* ensure monster flees long enough to visibly stop fighting */
275.  		if (fleetime == 1) fleetime++;
276.  		mtmp->mfleetim = min(fleetime, 127);
277.  	    }
278.  	    if (!mtmp->mflee && fleemsg && canseemon(mtmp) && !mtmp->mfrozen)
279.  		pline("%s turns to flee!", (Monnam(mtmp)));
280.  	    mtmp->mflee = 1;
281.  	}
282.  }
283.  
284.  STATIC_OVL void
285.  distfleeck(mtmp,inrange,nearby,scared)
286.  register struct monst *mtmp;
287.  int *inrange, *nearby, *scared;
288.  {
289.  	int seescaryx, seescaryy;
290.  
291.  	*inrange = (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <=
292.  							(BOLT_LIM * BOLT_LIM));
293.  	*nearby = *inrange && monnear(mtmp, mtmp->mux, mtmp->muy);
294.  
295.  	/* Note: if your image is displaced, the monster sees the Elbereth
296.  	 * at your displaced position, thus never attacking your displaced
297.  	 * position, but possibly attacking you by accident.  If you are
298.  	 * invisible, it sees the Elbereth at your real position, thus never
299.  	 * running into you by accident but possibly attacking the spot
300.  	 * where it guesses you are.
301.  	 */
302.  	if (!mtmp->mcansee || (Invis && !perceives(mtmp->data))) {
303.  		seescaryx = mtmp->mux;
304.  		seescaryy = mtmp->muy;
305.  	} else {
306.  		seescaryx = u.ux;
307.  		seescaryy = u.uy;
308.  	}
309.  	*scared = (*nearby && (onscary(seescaryx, seescaryy, mtmp) ||
310.  			       (!mtmp->mpeaceful &&
311.  				    in_your_sanctuary(mtmp, 0, 0))));
312.  
313.  	if(*scared) {
314.  		if (rn2(7))
315.  		    monflee(mtmp, rnd(10), TRUE, TRUE);
316.  		else
317.  		    monflee(mtmp, rnd(100), TRUE, TRUE);
318.  	}
319.  
320.  }
321.  
322.  /* perform a special one-time action for a monster; returns -1 if nothing
323.     special happened, 0 if monster uses up its turn, 1 if monster is killed */
324.  STATIC_OVL int
325.  m_arrival(mon)
326.  struct monst *mon;
327.  {
328.  	mon->mstrategy &= ~STRAT_ARRIVE;	/* always reset */
329.  
330.  	return -1;
331.  }
332.  
333.  /* returns 1 if monster died moving, 0 otherwise */
334.  /* The whole dochugw/m_move/distfleeck/mfndpos section is serious spaghetti
335.   * code. --KAA
336.   */
337.  int
338.  dochug(mtmp)
339.  register struct monst *mtmp;
340.  {
341.  	register struct permonst *mdat;
342.  	register int tmp=0;
343.  	int inrange, nearby, scared;
344.  #ifdef GOLDOBJ
345.          struct obj *ygold = 0, *lepgold = 0;
346.  #endif
347.  
348.  /*	Pre-movement adjustments	*/
349.  
350.  	mdat = mtmp->data;
351.  
352.  	if (mtmp->mstrategy & STRAT_ARRIVE) {
353.  	    int res = m_arrival(mtmp);
354.  	    if (res >= 0) return res;
355.  	}
356.  
357.  	/* check for waitmask status change */
358.  	if ((mtmp->mstrategy & STRAT_WAITFORU) &&
359.  		(m_canseeu(mtmp) || mtmp->mhp < mtmp->mhpmax))
360.  	    mtmp->mstrategy &= ~STRAT_WAITFORU;
361.  
362.  	/* update quest status flags */
363.  	quest_stat_check(mtmp);
364.  
365.  	if (!mtmp->mcanmove || (mtmp->mstrategy & STRAT_WAITMASK)) {
366.  	    if (Hallucination) newsym(mtmp->mx,mtmp->my);
367.  	    if (mtmp->mcanmove && (mtmp->mstrategy & STRAT_CLOSE) &&
368.  	       !mtmp->msleeping && monnear(mtmp, u.ux, u.uy))
369.  		quest_talk(mtmp);	/* give the leaders a chance to speak */
370.  	    return(0);	/* other frozen monsters can't do anything */
371.  	}
372.  
373.  	/* there is a chance we will wake it */
374.  	if (mtmp->msleeping && !disturb(mtmp)) {
375.  		if (Hallucination) newsym(mtmp->mx,mtmp->my);
376.  		return(0);
377.  	}
378.  
379.  	/* not frozen or sleeping: wipe out texts written in the dust */
380.  	wipe_engr_at(mtmp->mx, mtmp->my, 1);
381.  
382.  	/* confused monsters get unconfused with small probability */
383.  	if (mtmp->mconf && !rn2(50)) mtmp->mconf = 0;
384.  
385.  	/* stunned monsters get un-stunned with larger probability */
386.  	if (mtmp->mstun && !rn2(10)) mtmp->mstun = 0;
387.  
388.  	/* some monsters teleport */
389.  	if (mtmp->mflee && !rn2(40) && can_teleport(mdat) && !mtmp->iswiz &&
390.  	    !level.flags.noteleport) {
391.  		(void) rloc(mtmp, FALSE);
392.  		return(0);
393.  	}
394.  	if (mdat->msound == MS_SHRIEK && !um_dist(mtmp->mx, mtmp->my, 1))
395.  	    m_respond(mtmp);
396.  	if (mdat == &mons[PM_MEDUSA] && couldsee(mtmp->mx, mtmp->my))
397.  	    m_respond(mtmp);
398.  	if (mtmp->mhp <= 0) return(1); /* m_respond gaze can kill medusa */
399.  
400.  	/* fleeing monsters might regain courage */
401.  	if (mtmp->mflee && !mtmp->mfleetim
402.  	   && mtmp->mhp == mtmp->mhpmax && !rn2(25)) mtmp->mflee = 0;
403.  
404.  	set_apparxy(mtmp);
405.  	/* Must be done after you move and before the monster does.  The
406.  	 * set_apparxy() call in m_move() doesn't suffice since the variables
407.  	 * inrange, etc. all depend on stuff set by set_apparxy().
408.  	 */
409.  
410.  	/* Monsters that want to acquire things */
411.  	/* may teleport, so do it before inrange is set */
412.  	if(is_covetous(mdat)) (void) tactics(mtmp);
413.  
414.  	/* check distance and scariness of attacks */
415.  	distfleeck(mtmp,&inrange,&nearby,&scared);
416.  
417.  	if(find_defensive(mtmp)) {
418.  		if (use_defensive(mtmp) != 0)
419.  			return 1;
420.  	} else if(find_misc(mtmp)) {
421.  		if (use_misc(mtmp) != 0)
422.  			return 1;
423.  	}
424.  
425.  	/* Demonic Blackmail! */
426.  	if(nearby && mdat->msound == MS_BRIBE &&
427.  	   mtmp->mpeaceful && !mtmp->mtame && !u.uswallow) {
428.  		if (mtmp->mux != u.ux || mtmp->muy != u.uy) {
429.  			pline("%s whispers at thin air.",
430.  			    cansee(mtmp->mux, mtmp->muy) ? Monnam(mtmp) : "It");
431.  
432.  			if (is_demon(youmonst.data)) {
433.  			  /* "Good hunting, brother" */
434.  			    if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
435.  			} else {
436.  			    mtmp->minvis = mtmp->perminvis = 0;
437.  			    /* Why?  For the same reason in real demon talk */
438.  			    pline("%s gets angry!", Amonnam(mtmp));
439.  			    mtmp->mpeaceful = 0;
440.  			    /* since no way is an image going to pay it off */
441.  			}
442.  		} else if(demon_talk(mtmp)) return(1);	/* you paid it off */
443.  	}
444.  
445.  	/* the watch will look around and see if you are up to no good :-) */
446.  	if (mdat == &mons[PM_WATCHMAN] || mdat == &mons[PM_WATCH_CAPTAIN])
447.  		watch_on_duty(mtmp);
448.  
449.  	/* [DS] Cthulhu also uses psychic blasts */
450.  	else if ((is_mind_flayer(mdat) || mdat == &mons[PM_CTHULHU]) 
451.  			&& !rn2(20)) {
452.  		struct monst *m2, *nmon = (struct monst *)0;
453.  
454.  		if (canseemon(mtmp))
455.  			pline("%s concentrates.", Monnam(mtmp));
456.  		if (distu(mtmp->mx, mtmp->my) > BOLT_LIM * BOLT_LIM) {
457.  			You("sense a faint wave of psychic energy.");
458.  			goto toofar;
459.  		}
460.  		pline("A wave of psychic energy pours over you!");
461.  		if (mtmp->mpeaceful &&
462.  		    (!Conflict || resist(mtmp, RING_CLASS, 0, 0)))
463.  			pline("It feels quite soothing.");
464.  		else {
465.  			register boolean m_sen = sensemon(mtmp);
466.  
467.  			if (m_sen || (Blind_telepat && rn2(2)) || !rn2(10)) {
468.  				int dmg;
469.  				pline("It locks on to your %s!",
470.  					m_sen ? "telepathy" :
471.  					Blind_telepat ? "latent telepathy" : "mind");
472.  				dmg = (mdat == &mons[PM_CTHULHU])?
473.  					rn1(10, 10) :
474.  					rn1(4, 4);
475.  				if (Half_spell_damage) dmg = (dmg+1) / 2;
476.  				losehp(dmg, "psychic blast", KILLED_BY_AN);
477.  			}
478.  		}
479.  		for(m2=fmon; m2; m2 = nmon) {
480.  			nmon = m2->nmon;
481.  			if (DEADMONSTER(m2)) continue;
482.  			if (m2->mpeaceful == mtmp->mpeaceful) continue;
483.  			if (mindless(m2->data)) continue;
484.  			if (m2 == mtmp) continue;
485.  			if ((telepathic(m2->data) &&
486.  			    (rn2(2) || m2->mblinded)) || !rn2(10)) {
487.  				if (cansee(m2->mx, m2->my))
488.  				    pline("It locks on to %s.", mon_nam(m2));
489.  				m2->mhp -= rnd(15);
490.  				if (m2->mhp <= 0)
491.  				    if (mtmp->uexp)
492.  					mon_xkilled(m2, "", AD_DRIN);
493.  				    else
494.  				    monkilled(m2, "", AD_DRIN);
495.  				else
496.  				    m2->msleeping = 0;
497.  			}
498.  		}
499.  	}
500.  toofar:
501.  
502.  	/* If monster is nearby you, and has to wield a weapon, do so.   This
503.  	 * costs the monster a move, of course.
504.  	 */
505.  	if((!mtmp->mpeaceful || Conflict) && inrange &&
506.  	   dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= 8
507.  	   && attacktype(mdat, AT_WEAP)) {
508.  	    struct obj *mw_tmp;
509.  
510.  	    /* The scared check is necessary.  Otherwise a monster that is
511.  	     * one square near the player but fleeing into a wall would keep	
512.  	     * switching between pick-axe and weapon.  If monster is stuck
513.  	     * in a trap, prefer ranged weapon (wielding is done in thrwmu).
514.  	     * This may cost the monster an attack, but keeps the monster
515.  	     * from switching back and forth if carrying both.
516.  	     */
517.  	    mw_tmp = MON_WEP(mtmp);
518.  	    if (!(scared && mw_tmp && is_pick(mw_tmp)) &&
519.  		mtmp->weapon_check == NEED_WEAPON &&
520.  		!(mtmp->mtrapped && !nearby && select_rwep(mtmp))) {
521.  		mtmp->weapon_check = NEED_HTH_WEAPON;
522.  		if (mon_wield_item(mtmp) != 0) return(0);
523.  	    }
524.  	}
525.  
526.  /*	Now the actual movement phase	*/
527.  
528.  #ifndef GOLDOBJ
529.  	if(!nearby || mtmp->mflee || scared ||
530.  	   mtmp->mconf || mtmp->mstun || (mtmp->minvis && !rn2(3)) ||
531.  	   (mdat->mlet == S_LEPRECHAUN && !u.ugold && (mtmp->mgold || rn2(2))) ||
532.  
533.  #else
534.          if (mdat->mlet == S_LEPRECHAUN) {
535.  	    ygold = findgold(invent);
536.  	    lepgold = findgold(mtmp->minvent);
537.  	}
538.  
539.  	if(!nearby || mtmp->mflee || scared ||
540.  	   mtmp->mconf || mtmp->mstun || (mtmp->minvis && !rn2(3)) ||
541.  	   (mdat->mlet == S_LEPRECHAUN && !ygold && (lepgold || rn2(2))) ||
542.  #endif
543.  	   (is_wanderer(mdat) && !rn2(4)) || (Conflict && !mtmp->iswiz
544.  #ifdef BLACKMARKET
545.  	   && !Is_blackmarket(&u.uz)
546.  #endif
547.  	   ) ||
548.  	   (!mtmp->mcansee && !rn2(4)) || mtmp->mpeaceful) {
549.  		/* Possibly cast an undirected spell if not attacking you */
550.  		/* note that most of the time castmu() will pick a directed
551.  		   spell and do nothing, so the monster moves normally */
552.  		/* arbitrary distance restriction to keep monster far away
553.  		   from you from having cast dozens of sticks-to-snakes
554.  		   or similar spells by the time you reach it */
555.  		if (dist2(mtmp->mx, mtmp->my, u.ux, u.uy) <= 49 && !mtmp->mspec_used) {
556.  		    struct attack *a;
557.  
558.  		    for (a = &mdat->mattk[0]; a < &mdat->mattk[NATTK]; a++) {
559.  			if (a->aatyp == AT_MAGC && (a->adtyp == AD_SPEL || a->adtyp == AD_CLRC)) {
560.  			    if (castmu(mtmp, a, FALSE, FALSE)) {
561.  				tmp = 3;
562.  				break;
563.  			    }
564.  			}
565.  		    }
566.  		}
567.  
568.  		tmp = m_move(mtmp, 0);
569.  		distfleeck(mtmp,&inrange,&nearby,&scared);	/* recalc */
570.  		switch (tmp) {
571.  		    case 0:	/* no movement, but it can still attack you */
572.  		    case 3:	/* absolutely no movement */
573.  				/* for pets, case 0 and 3 are equivalent */
574.  			/* vault guard might have vanished */
575.  			if (mtmp->isgd && (mtmp->mhp < 1 ||
576.  					    (mtmp->mx == 0 && mtmp->my == 0)))
577.  			    return 1;	/* behave as if it died */
578.  			/* During hallucination, monster appearance should
579.  			 * still change - even if it doesn't move.
580.  			 */
581.  			if(Hallucination) newsym(mtmp->mx,mtmp->my);
582.  			break;
583.  		    case 1:	/* monster moved */
584.  			/* Maybe it stepped on a trap and fell asleep... */
585.  			if (mtmp->msleeping || !mtmp->mcanmove) return(0);
586.  			if(!nearby &&
587.  			  (ranged_attk(mdat) || find_offensive(mtmp)))
588.  			    break;
589.   			else if(u.uswallow && mtmp == u.ustuck) {
590.  			    /* a monster that's digesting you can move at the
591.  			     * same time -dlc
592.  			     */
593.  			    return(mattacku(mtmp));
594.  			} else
595.  				return(0);
596.  			/*NOTREACHED*/
597.  			break;
598.  		    case 2:	/* monster died */
599.  			return(1);
600.  		}
601.  	}
602.  
603.  /*	Now, attack the player if possible - one attack set per monst	*/
604.  
605.  	if (!mtmp->mpeaceful ||
606.  	    (Conflict && !resist(mtmp, RING_CLASS, 0, 0)
607.  #ifdef BLACKMARKET
608.  		&& !Is_blackmarket(&u.uz)
609.  #endif
610.  	)) {
611.  	    if(inrange && !noattacks(mdat) && u.uhp > 0 && !scared && tmp != 3)
612.  		if(mattacku(mtmp)) return(1); /* monster died (e.g. exploded) */
613.  
614.  	    if(mtmp->wormno) wormhitu(mtmp);
615.  	}
616.  	/* special speeches for quest monsters */
617.  	if (!mtmp->msleeping && mtmp->mcanmove && nearby)
618.  	    quest_talk(mtmp);
619.  	/* extra emotional attack for vile monsters */
620.  	    if(inrange && mtmp->data->msound == MS_CUSS && !mtmp->mpeaceful &&
621.  		couldsee(mtmp->mx, mtmp->my) && !mtmp->minvis && !rn2(5))
622.  	    cuss(mtmp);
623.  
624.  	return(tmp == 2);
625.  }
626.  
627.  static NEARDATA const char practical[] = { 
628.  	WEAPON_CLASS, ARMOR_CLASS, GEM_CLASS, FOOD_CLASS, 0 };
629.  static NEARDATA const char magical[] = {
630.  	AMULET_CLASS, POTION_CLASS, SCROLL_CLASS, WAND_CLASS, RING_CLASS,
631.  	SPBOOK_CLASS, 0 };
632.  static NEARDATA const char indigestion[] = { BALL_CLASS, ROCK_CLASS, 0 };
633.  static NEARDATA const char boulder_class[] = { ROCK_CLASS, 0 };
634.  static NEARDATA const char gem_class[] = { GEM_CLASS, 0 };
635.  
636.  boolean
637.  itsstuck(mtmp)
638.  register struct monst *mtmp;
639.  {
640.  	if (sticks(youmonst.data) && mtmp==u.ustuck && !u.uswallow) {
641.  		pline("%s cannot escape from you!", Monnam(mtmp));
642.  		return(TRUE);
643.  	}
644.  	return(FALSE);
645.  }
646.  
647.  /* Return values:
648.   * 0: did not move, but can still attack and do other stuff.
649.   * 1: moved, possibly can attack.
650.   * 2: monster died.
651.   * 3: did not move, and can't do anything else either.
652.   */
653.  int
654.  m_move(mtmp, after)
655.  register struct monst *mtmp;
656.  register int after;
657.  {
658.  	register int appr;
659.  	xchar gx,gy,nix,niy,chcnt;
660.  	int chi;	/* could be schar except for stupid Sun-2 compiler */
661.  	boolean likegold=0, likegems=0, likeobjs=0, likemagic=0, conceals=0;
662.  	boolean likerock=0, can_tunnel=0;
663.  	boolean can_open=0, can_unlock=0, doorbuster=0;
664.  	boolean uses_items=0, setlikes=0;
665.  	boolean avoid=FALSE;
666.  	struct permonst *ptr;
667.  	struct monst *mtoo;
668.  	schar mmoved = 0;	/* not strictly nec.: chi >= 0 will do */
669.  	long info[9];
670.  	long flag;
671.  	int  omx = mtmp->mx, omy = mtmp->my;
672.  	struct obj *mw_tmp;
673.  
674.  	if(mtmp->mtrapped) {
675.  	    int i = mintrap(mtmp);
676.  	    if(i >= 2) { newsym(mtmp->mx,mtmp->my); return(2); }/* it died */
677.  	    if(i == 1) return(0);	/* still in trap, so didn't move */
678.  	}
679.  
680.  	ptr = mtmp->data; /* mintrap() can change mtmp->data -dlc */
681.  
682.  	if (mtmp->meating) {
683.  	    mtmp->meating--;
684.  	    return 3;			/* still eating */
685.  	}
686.  
687.  	if (hides_under(ptr) && OBJ_AT(mtmp->mx, mtmp->my) && rn2(10))
688.  	    return 0;		/* do not leave hiding place */
689.  
690.  	set_apparxy(mtmp);
691.  	/* where does mtmp think you are? */
692.  	/* Not necessary if m_move called from this file, but necessary in
693.  	 * other calls of m_move (ex. leprechauns dodging)
694.  	 */
695.  #ifdef REINCARNATION
696.  	if (!Is_rogue_level(&u.uz))
697.  #endif
698.  	    can_tunnel = tunnels(ptr);
699.  	can_open = !(nohands(ptr) || verysmall(ptr));
700.  	can_unlock = ((can_open && m_carrying(mtmp, SKELETON_KEY)) ||
701.  		      mtmp->iswiz || is_rider(ptr));
702.  /*        doorbuster = is_giant(ptr);*/
703.  
704.  	/* WAC add dragon breath */
705.  	doorbuster = is_giant(ptr) || (bust_door_breath(mtmp) != -1);
706.  
707.  	if(mtmp->wormno) goto not_special;
708.  	/* my dog gets special treatment */
709.  	if(mtmp->mtame) {
710.  	    mmoved = dog_move(mtmp, after);
711.  	    goto postmov;
712.  	}
713.  
714.  	/* likewise for shopkeeper */
715.  	if(mtmp->isshk) {
716.  	    mmoved = shk_move(mtmp);
717.  	    if(mmoved == -2) return(2);
718.  	    if(mmoved >= 0) goto postmov;
719.  	    mmoved = 0;		/* follow player outside shop */
720.  	}
721.  
722.  	/* and for the guard */
723.  	if(mtmp->isgd) {
724.  	    mmoved = gd_move(mtmp);
725.  	    if(mmoved == -2) return(2);
726.  	    if(mmoved >= 0) goto postmov;
727.  	    mmoved = 0;
728.  	}
729.  
730.  	/* and the acquisitive monsters get special treatment */
731.  	if(is_covetous(ptr)) {
732.  	    xchar tx = STRAT_GOALX(mtmp->mstrategy),
733.  		  ty = STRAT_GOALY(mtmp->mstrategy);
734.  	    struct monst *intruder = m_at(tx, ty);
735.  	    /*
736.  	     * if there's a monster on the object or in possesion of it,
737.  	     * attack it.
738.  	     */
739.  	    if((dist2(mtmp->mx, mtmp->my, tx, ty) < 2) &&
740.  	       intruder && (intruder != mtmp)) {
741.  
742.  		notonhead = (intruder->mx != tx || intruder->my != ty);
743.  		if(mattackm(mtmp, intruder) == 2) return(2);
744.  		mmoved = 1;
745.  	    } else mmoved = 0;
746.  	    goto postmov;
747.  	}
748.  
749.  	/* and for the priest */
750.  	if(mtmp->ispriest) {
751.  	    mmoved = pri_move(mtmp);
752.  	    if(mmoved == -2) return(2);
753.  	    if(mmoved >= 0) goto postmov;
754.  	    mmoved = 0;
755.  	}
756.  
757.  #ifdef MAIL
758.  	if(ptr == &mons[PM_MAIL_DAEMON]) {
759.  	    if(flags.soundok && canseemon(mtmp))
760.  		verbalize("I'm late!");
761.  	    mongone(mtmp);
762.  	    return(2);
763.  	}
764.  #endif
765.  
766.  	/* teleport if that lies in our nature */
767.  	if(ptr == &mons[PM_TENGU] && !rn2(5) && !mtmp->mcan &&
768.  	   !tele_restrict(mtmp)) {
769.  	    if(mtmp->mhp < 7 || mtmp->mpeaceful || rn2(2))
770.  		(void) rloc(mtmp, FALSE);
771.  	    else
772.  		mnexto(mtmp);
773.  	    mmoved = 1;
774.  	    goto postmov;
775.  	}
776.  not_special:
777.  	if(u.uswallow && !mtmp->mflee && u.ustuck != mtmp) return(1);
778.  	omx = mtmp->mx;
779.  	omy = mtmp->my;
780.  	gx = mtmp->mux;
781.  	gy = mtmp->muy;
782.  	appr = mtmp->mflee ? -1 : 1;
783.  	if (mtmp->mconf || (u.uswallow && mtmp == u.ustuck))
784.  		appr = 0;
785.  	else {
786.  #ifdef GOLDOBJ
787.  		struct obj *lepgold, *ygold;
788.  #endif
789.  		boolean should_see = (couldsee(omx, omy) &&
790.  				      (levl[gx][gy].lit ||
791.  				       !levl[omx][omy].lit) &&
792.  				      (dist2(omx, omy, gx, gy) <= 36));
793.  
794.  		if (!mtmp->mcansee ||
795.  		    (should_see && Invis && !perceives(ptr) && rn2(11)) ||
796.  		    (youmonst.m_ap_type == M_AP_OBJECT && youmonst.mappearance == STRANGE_OBJECT) || u.uundetected ||
797.  		    (youmonst.m_ap_type == M_AP_OBJECT && youmonst.mappearance == GOLD_PIECE && !likes_gold(ptr)) ||
798.  		    (mtmp->mpeaceful && !mtmp->isshk) ||  /* allow shks to follow */
799.  		    ((monsndx(ptr) == PM_STALKER || ptr->mlet == S_BAT ||
800.  		      ptr->mlet == S_LIGHT) && !rn2(3)))
801.  			appr = 0;
802.  
803.  		if(monsndx(ptr) == PM_LEPRECHAUN && (appr == 1) &&
804.  #ifndef GOLDOBJ
805.  		   (mtmp->mgold > u.ugold))
806.  #else
807.  		   ( (lepgold = findgold(mtmp->minvent)) && 
808.                     (lepgold->quan > ((ygold = findgold(invent)) ? ygold->quan : 0L)) ))
809.  #endif
810.  			appr = -1;
811.  
812.  		if (!should_see && can_track(ptr)) {
813.  			register coord *cp;
814.  
815.  			cp = gettrack(omx,omy);
816.  			if (cp) {
817.  				gx = cp->x;
818.  				gy = cp->y;
819.  			}
820.  		}
821.  	}
822.  
823.  	if ((!mtmp->mpeaceful || !rn2(10))
824.  #ifdef REINCARNATION
825.  				    && (!Is_rogue_level(&u.uz))
826.  #endif
827.  							    ) {
828.  	    boolean in_line = lined_up(mtmp) &&
829.  		(distmin(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <=
830.  		    (throws_rocks(youmonst.data) ? 20 : ACURRSTR/2+1)
831.  		);
832.  
833.  	    if (appr != 1 || !in_line) {
834.  		/* Monsters in combat won't pick stuff up, avoiding the
835.  		 * situation where you toss arrows at it and it has nothing
836.  		 * better to do than pick the arrows up.
837.  		 */
838.  		register int pctload = (curr_mon_load(mtmp) * 100) /
839.  			max_mon_load(mtmp);
840.  
841.  		/* look for gold or jewels nearby */
842.  		likegold = (likes_gold(ptr) && pctload < 95);
843.  		likegems = (likes_gems(ptr) && pctload < 85);
844.  		uses_items = (!mindless(ptr) && !is_animal(ptr)
845.  			&& pctload < 75);
846.  		likeobjs = (likes_objs(ptr) && pctload < 75);
847.  		likemagic = (likes_magic(ptr) && pctload < 85);
848.  		likerock = (throws_rocks(ptr) && pctload < 50 && !In_sokoban(&u.uz));
849.  		conceals = hides_under(ptr);
850.  		setlikes = TRUE;
851.  	    }
852.  	}
853.  
854.  #define SQSRCHRADIUS	5
855.  
856.        { register int minr = SQSRCHRADIUS;	/* not too far away */
857.  	register struct obj *otmp;
858.  	register int xx, yy;
859.  	int oomx, oomy, lmx, lmy;
860.  
861.  	/* cut down the search radius if it thinks character is closer. */
862.  	if(distmin(mtmp->mux, mtmp->muy, omx, omy) < SQSRCHRADIUS &&
863.  	    !mtmp->mpeaceful) minr--;
864.  	/* guards shouldn't get too distracted */
865.  	if(!mtmp->mpeaceful && is_mercenary(ptr)) minr = 1;
866.  
867.  	if((likegold || likegems || likeobjs || likemagic || likerock || conceals)
868.  	      && (!*in_rooms(omx, omy, SHOPBASE) || (!rn2(25) && !mtmp->isshk))) {
869.  	look_for_obj:
870.  	    oomx = min(COLNO-1, omx+minr);
871.  	    oomy = min(ROWNO-1, omy+minr);
872.  	    lmx = max(1, omx-minr);
873.  	    lmy = max(0, omy-minr);
874.  	    for(otmp = fobj; otmp; otmp = otmp->nobj) {
875.  		/* monsters may pick rocks up, but won't go out of their way
876.  		   to grab them; this might hamper sling wielders, but it cuts
877.  		   down on move overhead by filtering out most common item */
878.  		if (otmp->otyp == ROCK) continue;
879.  		xx = otmp->ox;
880.  		yy = otmp->oy;
881.  		/* Nymphs take everything.  Most other creatures should not
882.  		 * pick up corpses except as a special case like in
883.  		 * searches_for_item().  We need to do this check in
884.  		 * mpickstuff() as well.
885.  		 */
886.  		if(xx >= lmx && xx <= oomx && yy >= lmy && yy <= oomy) {
887.  		    /* don't get stuck circling around an object that's underneath
888.  		       an immobile or hidden monster; paralysis victims excluded */
889.  		    if ((mtoo = m_at(xx,yy)) != 0 &&
890.  			(mtoo->msleeping || mtoo->mundetected ||
891.  			 (mtoo->mappearance && !mtoo->iswiz) ||
892.  			 !mtoo->data->mmove)) continue;
893.  
894.  		    if(((likegold && otmp->oclass == COIN_CLASS) ||
895.  		       (likeobjs && index(practical, otmp->oclass) &&
896.  			(otmp->otyp != CORPSE || (ptr->mlet == S_NYMPH
897.  			   && !is_rider(&mons[otmp->corpsenm])))) ||
898.  		       (likemagic && index(magical, otmp->oclass)) ||
899.  		       (uses_items && searches_for_item(mtmp, otmp)) ||
900.  		       (likerock && otmp->otyp == BOULDER) ||
901.  		       (likegems && otmp->oclass == GEM_CLASS &&
902.  			objects[otmp->otyp].oc_material != MINERAL) ||
903.  		       (conceals && !cansee(otmp->ox,otmp->oy)) ||
904.  		       (ptr == &mons[PM_GELATINOUS_CUBE] &&
905.  			!index(indigestion, otmp->oclass) &&
906.  			!(otmp->otyp == CORPSE &&
907.  			  touch_petrifies(&mons[otmp->corpsenm])))
908.  		      ) && touch_artifact(otmp,mtmp)) {
909.  			if(can_carry(mtmp,otmp) &&
910.  			   (throws_rocks(ptr) ||
911.  				!sobj_at(BOULDER,xx,yy)) &&
912.  			   (!is_unicorn(ptr) ||
913.  			    objects[otmp->otyp].oc_material == GEMSTONE) &&
914.  			   /* Don't get stuck circling an Elbereth */
915.  			   !(onscary(xx, yy, mtmp))) {
916.  			    minr = distmin(omx,omy,xx,yy);
917.  			    oomx = min(COLNO-1, omx+minr);
918.  			    oomy = min(ROWNO-1, omy+minr);
919.  			    lmx = max(1, omx-minr);
920.  			    lmy = max(0, omy-minr);
921.  			    gx = otmp->ox;
922.  			    gy = otmp->oy;
923.  			    if (gx == omx && gy == omy) {
924.  				mmoved = 3; /* actually unnecessary */
925.  				goto postmov;
926.  			    }
927.  			}
928.  		    }
929.  		}
930.  	    }
931.  	} else if(likegold) {
932.  	    /* don't try to pick up anything else, but use the same loop */
933.  	    uses_items = 0;
934.  	    likegems = likeobjs = likemagic = likerock = conceals = 0;
935.  	    goto look_for_obj;
936.  	}
937.  
938.  	if(minr < SQSRCHRADIUS && appr == -1) {
939.  	    if(distmin(omx,omy,mtmp->mux,mtmp->muy) <= 3) {
940.  		gx = mtmp->mux;
941.  		gy = mtmp->muy;
942.  	    } else
943.  		appr = 1;
944.  	}
945.        }
946.  
947.  	/* don't tunnel if hostile and close enough to prefer a weapon */
948.  	if (can_tunnel && needspick(ptr) &&
949.  	    ((!mtmp->mpeaceful || Conflict) &&
950.  	     dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= 8))
951.  	    can_tunnel = FALSE;
952.  
953.  	nix = omx;
954.  	niy = omy;
955.  	flag = 0L;
956.  	if (mtmp->mpeaceful && (!Conflict || resist(mtmp, RING_CLASS, 0, 0)))
957.  	    flag |= (ALLOW_SANCT | ALLOW_SSM);
958.  	else flag |= ALLOW_U;
959.  	if (is_minion(ptr) || is_rider(ptr)) flag |= ALLOW_SANCT;
960.  	/* unicorn may not be able to avoid hero on a noteleport level */
961.  	if (is_unicorn(ptr) && !level.flags.noteleport) flag |= NOTONL;
962.  	if (passes_walls(ptr)) flag |= (ALLOW_WALL | ALLOW_ROCK);
963.  	if (passes_bars(ptr) && !In_sokoban(&u.uz)) flag |= ALLOW_BARS;
964.  	if (can_tunnel) flag |= ALLOW_DIG;
965.  	if (is_human(ptr) || ptr == &mons[PM_MINOTAUR]) flag |= ALLOW_SSM;
966.  	if (is_undead(ptr) && ptr->mlet != S_GHOST) flag |= NOGARLIC;
967.  	if (throws_rocks(ptr)) flag |= ALLOW_ROCK;
968.  	if (can_open) flag |= OPENDOOR;
969.  	if (can_unlock) flag |= UNLOCKDOOR;
970.  	if (doorbuster) flag |= BUSTDOOR;
971.  	{
972.  	    register int i, j, nx, ny, nearer;
973.  	    int jcnt, cnt;
974.  	    int ndist, nidist;
975.  	    register coord *mtrk;
976.  	    coord poss[9];
977.  
978.  	    cnt = mfndpos(mtmp, poss, info, flag);
979.  	    chcnt = 0;
980.  	    jcnt = min(MTSZ, cnt-1);
981.  	    chi = -1;
982.  	    nidist = dist2(nix,niy,gx,gy);
983.  	    /* allow monsters be shortsighted on some levels for balance */
984.  	    if(!mtmp->mpeaceful && level.flags.shortsighted &&
985.  	       nidist > (couldsee(nix,niy) ? 144 : 36) && appr == 1) appr = 0;
986.  	    if (is_unicorn(ptr) && level.flags.noteleport) {
987.  		/* on noteleport levels, perhaps we cannot avoid hero */
988.  		for(i = 0; i < cnt; i++)
989.  		    if(!(info[i] & NOTONL)) avoid=TRUE;
990.  	    }
991.  
992.  	    for(i=0; i < cnt; i++) {
993.  		if (avoid && (info[i] & NOTONL)) continue;
994.  		nx = poss[i].x;
995.  		ny = poss[i].y;
996.  
997.  		if (appr != 0) {
998.  		    mtrk = &mtmp->mtrack[0];
999.  		    for(j=0; j < jcnt; mtrk++, j++)
1000. 			if(nx == mtrk->x && ny == mtrk->y)
1001. 			    if(rn2(4*(cnt-j)))
1002. 				goto nxti;
1003. 		}
1004. 
1005. 		nearer = ((ndist = dist2(nx,ny,gx,gy)) < nidist);
1006. 
1007. 		if((appr == 1 && nearer) || (appr == -1 && !nearer) ||
1008. 		   (!appr && !rn2(++chcnt)) || !mmoved) {
1009. 		    nix = nx;
1010. 		    niy = ny;
1011. 		    nidist = ndist;
1012. 		    chi = i;
1013. 		    mmoved = 1;
1014. 		}
1015. 	    nxti:	;
1016. 	    }
1017. 	}
1018. 
1019. 	if(mmoved) {
1020. 	    register int j;
1021. 
1022. 	    if (mmoved==1 && (u.ux != nix || u.uy != niy) && itsstuck(mtmp))
1023. 		return(3);
1024. 
1025. 	    if (((IS_ROCK(levl[nix][niy].typ) && may_dig(nix,niy)) ||
1026. 		 closed_door(nix, niy)) &&
1027. 		mmoved==1 && can_tunnel && needspick(ptr)) {
1028. 		if (closed_door(nix, niy)) {
1029. 		    if (!(mw_tmp = MON_WEP(mtmp)) ||
1030. 			!is_pick(mw_tmp) || !is_axe(mw_tmp))
1031. 			mtmp->weapon_check = NEED_PICK_OR_AXE;
1032. 		} else if (IS_TREE(levl[nix][niy].typ)) {
1033. 		    if (!(mw_tmp = MON_WEP(mtmp)) || !is_axe(mw_tmp))
1034. 			mtmp->weapon_check = NEED_AXE;
1035. 		} else if (!(mw_tmp = MON_WEP(mtmp)) || !is_pick(mw_tmp)) {
1036. 		mtmp->weapon_check = NEED_PICK_AXE;
1037. 		}
1038. 		if (mtmp->weapon_check >= NEED_PICK_AXE && mon_wield_item(mtmp))
1039. 		    return(3);
1040. 	    }
1041. 	    /* If ALLOW_U is set, either it's trying to attack you, or it
1042. 	     * thinks it is.  In either case, attack this spot in preference to
1043. 	     * all others.
1044. 	     */
1045. 	/* Actually, this whole section of code doesn't work as you'd expect.
1046. 	 * Most attacks are handled in dochug().  It calls distfleeck(), which
1047. 	 * among other things sets nearby if the monster is near you--and if
1048. 	 * nearby is set, we never call m_move unless it is a special case
1049. 	 * (confused, stun, etc.)  The effect is that this ALLOW_U (and
1050. 	 * mfndpos) has no effect for normal attacks, though it lets a confused
1051. 	 * monster attack you by accident.
1052. 	 */
1053. 	    if(info[chi] & ALLOW_U) {
1054. 		nix = mtmp->mux;
1055. 		niy = mtmp->muy;
1056. 	    }
1057. 	    if (nix == u.ux && niy == u.uy) {
1058. 		mtmp->mux = u.ux;
1059. 		mtmp->muy = u.uy;
1060. 		return(0);
1061. 	    }
1062. 	    /* The monster may attack another based on 1 of 2 conditions:
1063. 	     * 1 - It may be confused.
1064. 	     * 2 - It may mistake the monster for your (displaced) image.
1065. 	     * Pets get taken care of above and shouldn't reach this code.
1066. 	     * Conflict gets handled even farther away (movemon()).
1067. 	     */
1068. 	    if((info[chi] & ALLOW_M) ||
1069. 		   (nix == mtmp->mux && niy == mtmp->muy)) {
1070. 		struct monst *mtmp2;
1071. 		int mstatus;
1072. 		mtmp2 = m_at(nix,niy);
1073. 
1074. 		notonhead = mtmp2 && (nix != mtmp2->mx || niy != mtmp2->my);
1075. 		/* note: mstatus returns 0 if mtmp2 is nonexistent */
1076. 		mstatus = mattackm(mtmp, mtmp2);
1077. 
1078. 		if (mstatus & MM_AGR_DIED)		/* aggressor died */
1079. 		    return 2;
1080. 
1081. 		if ((mstatus & MM_HIT) && !(mstatus & MM_DEF_DIED)  &&
1082. 		    rn2(4) && mtmp2->movement >= NORMAL_SPEED) {
1083. 		    mtmp2->movement -= NORMAL_SPEED;
1084. 		    notonhead = 0;
1085. 		    mstatus = mattackm(mtmp2, mtmp);	/* return attack */
1086. 		    if (mstatus & MM_DEF_DIED)
1087. 			return 2;
1088. 		}
1089. 		return 3;
1090. 	    }
1091. 
1092. 	    if (!m_in_out_region(mtmp,nix,niy))
1093. 	        return 3;
1094. 	    remove_monster(omx, omy);
1095. 	    place_monster(mtmp, nix, niy);
1096. 
1097. 	    for(j = MTSZ-1; j > 0; j--)
1098. 		mtmp->mtrack[j] = mtmp->mtrack[j-1];
1099. 	    mtmp->mtrack[0].x = omx;
1100. 	    mtmp->mtrack[0].y = omy;
1101. 	    /* Place a segment at the old position. */
1102. 	    if (mtmp->wormno) worm_move(mtmp);
1103. 	} else {
1104. 	    if(is_unicorn(ptr) && rn2(2) && !tele_restrict(mtmp)) {
1105. 		(void) rloc(mtmp, FALSE);
1106. 		return(1);
1107. 	    }
1108. 	    if(mtmp->wormno) worm_nomove(mtmp);
1109. 	}
1110. postmov:
1111. 	if(mmoved == 1 || mmoved == 3) {
1112. 	    boolean canseeit = cansee(mtmp->mx, mtmp->my);
1113. 
1114. 	    if(mmoved == 1) {
1115. 		newsym(omx,omy);		/* update the old position */
1116. 		if (mintrap(mtmp) >= 2) {
1117. 		    if(mtmp->mx) newsym(mtmp->mx,mtmp->my);
1118. 		    return(2);	/* it died */
1119. 		}
1120. 		ptr = mtmp->data;
1121. 
1122. 		/* open a door, or crash through it, if you can */
1123. 		if(IS_DOOR(levl[mtmp->mx][mtmp->my].typ)
1124. 			&& !passes_walls(ptr) /* doesn't need to open doors */
1125. 			&& !can_tunnel /* taken care of below */
1126. 		      ) {
1127. 		    struct rm *here = &levl[mtmp->mx][mtmp->my];
1128. 		    boolean btrapped = (here->doormask & D_TRAPPED);
1129. 
1130. 		    if(here->doormask & (D_LOCKED|D_CLOSED) && amorphous(ptr)) {
1131. 			if (flags.verbose && canseemon(mtmp))
1132. 			    pline("%s %s under the door.", Monnam(mtmp),
1133. 				  (ptr == &mons[PM_FOG_CLOUD] ||
1134. 				   ptr == &mons[PM_YELLOW_LIGHT])
1135. 				  ? "flows" : "oozes");
1136. 		    } else if(here->doormask & D_LOCKED && can_unlock) {
1137. 			if(btrapped) {
1138. 			    here->doormask = D_NODOOR;
1139. 			    newsym(mtmp->mx, mtmp->my);
1140. 			    unblock_point(mtmp->mx,mtmp->my); /* vision */
1141. 			    if(mb_trapped(mtmp)) return(2);
1142. 			} else {
1143. 			    if (flags.verbose) {
1144. 				if (canseeit)
1145. 				   You("see a door unlock and open.");
1146. 				else if (flags.soundok)
1147. 				   You_hear("a door unlock and open.");
1148. 			    }
1149. 			    here->doormask = D_ISOPEN;
1150. 			    /* newsym(mtmp->mx, mtmp->my); */
1151. 			    unblock_point(mtmp->mx,mtmp->my); /* vision */
1152. 			}
1153. 		    } else if (here->doormask == D_CLOSED && can_open) {
1154. 			if(btrapped) {
1155. 			    here->doormask = D_NODOOR;
1156. 			    newsym(mtmp->mx, mtmp->my);
1157. 			    unblock_point(mtmp->mx,mtmp->my); /* vision */
1158. 			    if(mb_trapped(mtmp)) return(2);
1159. 			} else {
1160. 			    if (flags.verbose) {
1161. 				if (canseeit)
1162. 				     You("see a door open.");
1163. 				else if (flags.soundok)
1164. 				     You_hear("a door open.");
1165. 			    }
1166. 			    here->doormask = D_ISOPEN;
1167. 			    /* newsym(mtmp->mx, mtmp->my); */  /* done below */
1168. 			    unblock_point(mtmp->mx,mtmp->my); /* vision */
1169. 			}
1170. 		    } else if (here->doormask & (D_LOCKED|D_CLOSED)) {
1171. 			/* mfndpos guarantees this must be a doorbuster */
1172. 				/* WAC do dragons and breathers */
1173. 				if (bust_door_breath(mtmp) != -1) {
1174. 				        (void) breamspot(mtmp,
1175. 				                 &ptr->mattk[bust_door_breath(mtmp)],
1176. 				                 (nix-omx), (niy-omy));
1177. 				} else
1178. 			if(btrapped) {
1179. 			    here->doormask = D_NODOOR;
1180. 			    newsym(mtmp->mx, mtmp->my);
1181. 			    unblock_point(mtmp->mx,mtmp->my); /* vision */
1182. 			    if(mb_trapped(mtmp)) return(2);
1183. 			} else {
1184. 			    if (flags.verbose) {
1185. 				if (canseeit)
1186. 				    You("see a door crash open.");
1187. 				else if (flags.soundok)
1188. 				    You_hear("a door crash open.");
1189. 			    }
1190. 			    if (here->doormask & D_LOCKED && !rn2(2))
1191. 				    here->doormask = D_NODOOR;
1192. 			    else here->doormask = D_BROKEN;
1193. 			    /* newsym(mtmp->mx, mtmp->my); */ /* done below */
1194. 			    unblock_point(mtmp->mx,mtmp->my); /* vision */
1195. 			}
1196. 			/* if it's a shop door, schedule repair */
1197. 			if (*in_rooms(mtmp->mx, mtmp->my, SHOPBASE))
1198. 			    add_damage(mtmp->mx, mtmp->my, 0L);
1199. 		    }
1200. 		} else if (levl[mtmp->mx][mtmp->my].typ == IRONBARS) {
1201. 			if (flags.verbose && canseemon(mtmp))
1202. 			    Norep("%s %s %s the iron bars.", Monnam(mtmp),
1203. 				  /* pluralization fakes verb conjugation */
1204. 				  makeplural(locomotion(ptr, "pass")),
1205. 				  passes_walls(ptr) ? "through" : "between");
1206. 		}
1207. 
1208. 		/* possibly dig */
1209. 		if (can_tunnel && mdig_tunnel(mtmp))
1210. 			return(2);  /* mon died (position already updated) */
1211. 
1212. 		/* set also in domove(), hack.c */
1213. 		if (u.uswallow && mtmp == u.ustuck &&
1214. 					(mtmp->mx != omx || mtmp->my != omy)) {
1215. 		    /* If the monster moved, then update */
1216. 		    u.ux0 = u.ux;
1217. 		    u.uy0 = u.uy;
1218. 		    u.ux = mtmp->mx;
1219. 		    u.uy = mtmp->my;
1220. 		    swallowed(0);
1221. 		} else
1222. 		newsym(mtmp->mx,mtmp->my);
1223. 	    }
1224. 	    if(OBJ_AT(mtmp->mx, mtmp->my) && mtmp->mcanmove) {
1225. 		/* recompute the likes tests, in case we polymorphed
1226. 		 * or if the "likegold" case got taken above */
1227. 		if (setlikes) {
1228. 		    register int pctload = (curr_mon_load(mtmp) * 100) /
1229. 			max_mon_load(mtmp);
1230. 
1231. 		    /* look for gold or jewels nearby */
1232. 		    likegold = (likes_gold(ptr) && pctload < 95);
1233. 		    likegems = (likes_gems(ptr) && pctload < 85);
1234. 		    uses_items = (!mindless(ptr) && !is_animal(ptr)
1235. 				  && pctload < 75);
1236. 		    likeobjs = (likes_objs(ptr) && pctload < 75);
1237. 		    likemagic = (likes_magic(ptr) && pctload < 85);
1238. 		    likerock = (throws_rocks(ptr) && pctload < 50 &&
1239. 				!In_sokoban(&u.uz));
1240. 		    conceals = hides_under(ptr);
1241. 		}
1242. 
1243. 		/* Maybe a rock mole just ate some metal object */
1244. 		if (metallivorous(ptr)) {
1245. 		    if (meatmetal(mtmp) == 2) return 2;	/* it died */
1246. 		}
1247. 
1248. 		if(g_at(mtmp->mx,mtmp->my) && likegold) mpickgold(mtmp);
1249. 
1250. 		/* Maybe a cube ate just about anything */
1251. 		/* KMH -- Taz likes organics, too! */
1252. 		if (ptr == &mons[PM_GELATINOUS_CUBE] ||
1253. 			ptr == &mons[PM_TASMANIAN_DEVIL]) {
1254. 		    if (meatobj(mtmp) == 2) return 2;	/* it died */
1255. 		}
1256. 		if (ptr == &mons[PM_GHOUL] || ptr == &mons[PM_GHAST]) meatcorpse(mtmp);
1257. 
1258. 		if(!*in_rooms(mtmp->mx, mtmp->my, SHOPBASE) || !rn2(25)) {
1259. 		    boolean picked = FALSE;
1260. 
1261. 		    if(likeobjs) picked |= mpickstuff(mtmp, practical);
1262. 		    if(likemagic) picked |= mpickstuff(mtmp, magical);
1263. 		    if(likerock) picked |= mpickstuff(mtmp, boulder_class);
1264. 		    if(likegems) picked |= mpickstuff(mtmp, gem_class);
1265. 		    if(uses_items) picked |= mpickstuff(mtmp, (char *)0);
1266. 		    if(picked) mmoved = 3;
1267. 		}
1268. 
1269. 		if(mtmp->minvis) {
1270. 		    newsym(mtmp->mx, mtmp->my);
1271. 		    if (mtmp->wormno) see_wsegs(mtmp);
1272. 		}
1273. 	    }
1274. 
1275. 	    if(hides_under(ptr) || ptr->mlet == S_EEL) {
1276. 		/* Always set--or reset--mundetected if it's already hidden
1277. 		   (just in case the object it was hiding under went away);
1278. 		   usually set mundetected unless monster can't move.  */
1279. 		if (mtmp->mundetected ||
1280. 			(mtmp->mcanmove && !mtmp->msleeping && rn2(5)))
1281. 		    mtmp->mundetected = (ptr->mlet != S_EEL) ?
1282. 			OBJ_AT(mtmp->mx, mtmp->my) :
1283. 			(is_pool(mtmp->mx, mtmp->my) && !Is_waterlevel(&u.uz));
1284. 		newsym(mtmp->mx, mtmp->my);
1285. 	    }
1286. 	    if (mtmp->isshk) {
1287. 		after_shk_move(mtmp);
1288. 	    }
1289. 	}
1290. 	return(mmoved);
1291. }
1292. 
1293. #endif /* OVL0 */
1294. #ifdef OVL2
1295. 
1296. boolean
1297. closed_door(x, y)
1298. register int x, y;
1299. {
1300. 	return((boolean)(IS_DOOR(levl[x][y].typ) &&
1301. 			(levl[x][y].doormask & (D_LOCKED | D_CLOSED))));
1302. }
1303. 
1304. boolean
1305. accessible(x, y)
1306. register int x, y;
1307. {
1308. 	return((boolean)(ACCESSIBLE(levl[x][y].typ) && !closed_door(x, y)));
1309. }
1310. 
1311. #endif /* OVL2 */
1312. #ifdef OVL0
1313. 
1314. /* decide where the monster thinks you are standing */
1315. void
1316. set_apparxy(mtmp)
1317. register struct monst *mtmp;
1318. {
1319. 	boolean notseen, gotu;
1320. 	register int disp, mx = mtmp->mux, my = mtmp->muy;
1321. #ifdef GOLDOBJ
1322. 	long umoney = money_cnt(invent);
1323. #endif
1324. 
1325. 	/*
1326. 	 * do cheapest and/or most likely tests first
1327. 	 */
1328. 
1329. 	/* pet knows your smell; grabber still has hold of you */
1330. 	if (mtmp->mtame || mtmp == u.ustuck) goto found_you;
1331. 
1332. 	/* monsters which know where you are don't suddenly forget,
1333. 	   if you haven't moved away */
1334. 	if (mx == u.ux && my == u.uy) goto found_you;
1335. 
1336. 	notseen = (!mtmp->mcansee || (Invis && !perceives(mtmp->data)));
1337. 	/* add cases as required.  eg. Displacement ... */
1338. 	if (notseen || Underwater) {
1339. 	    /* Xorns can smell valuable metal like gold, treat as seen */
1340. 	    if ((mtmp->data == &mons[PM_XORN]) &&
1341. #ifndef GOLDOBJ
1342. 			u.ugold
1343. #else
1344. 			umoney
1345. #endif
1346. 			&& !Underwater)
1347. 		disp = 0;
1348. 	    else
1349. 		disp = 1;
1350. 	} else if (Displaced) {
1351. 	    disp = couldsee(mx, my) ? 2 : 1;
1352. 	} else disp = 0;
1353. 	if (!disp) goto found_you;
1354. 
1355. 	/* without something like the following, invis. and displ.
1356. 	   are too powerful */
1357. 	gotu = notseen ? !rn2(3) : Displaced ? !rn2(4) : FALSE;
1358. 
1359. #if 0		/* this never worked as intended & isn't needed anyway */
1360. 	/* If invis but not displaced, staying around gets you 'discovered' */
1361. 	gotu |= (!Displaced && u.dx == 0 && u.dy == 0);
1362. #endif
1363. 
1364. 	if (!gotu) {
1365. 	    register int try_cnt = 0;
1366. 	    do {
1367. 		if (++try_cnt > 200) goto found_you;		/* punt */
1368. 		mx = u.ux - disp + rn2(2*disp+1);
1369. 		my = u.uy - disp + rn2(2*disp+1);
1370. 	    } while (!isok(mx,my)
1371. 		  || (disp != 2 && mx == mtmp->mx && my == mtmp->my)
1372. 		  || ((mx != u.ux || my != u.uy) &&
1373. 		      !passes_walls(mtmp->data) &&
1374. 		      (!ACCESSIBLE(levl[mx][my].typ) ||
1375. 		       (closed_door(mx, my) && !can_ooze(mtmp))))
1376. 		  || !couldsee(mx, my));
1377. 	} else {
1378. found_you:
1379. 	    mx = u.ux;
1380. 	    my = u.uy;
1381. 	}
1382. 
1383. 	mtmp->mux = mx;
1384. 	mtmp->muy = my;
1385. }
1386. 
1387. boolean
1388. can_ooze(mtmp)
1389. struct monst *mtmp;
1390. {
1391. 	struct obj *chain, *obj;
1392. 
1393. 	if (!amorphous(mtmp->data)) return FALSE;
1394. 	if (mtmp == &youmonst) {
1395. #ifndef GOLDOBJ
1396. 		if (u.ugold > 100L) return FALSE;
1397. #endif
1398. 		chain = invent;
1399. 	} else {
1400. #ifndef GOLDOBJ
1401. 		if (mtmp->mgold > 100L) return FALSE;
1402. #endif
1403. 		chain = mtmp->minvent;
1404. 	}
1405. 	for (obj = chain; obj; obj = obj->nobj) {
1406. 		int typ = obj->otyp;
1407. 
1408. #ifdef GOLDOBJ
1409.                 if (typ == COIN_CLASS && obj->quan > 100L) return FALSE;
1410. #endif
1411. 		if (obj->oclass != GEM_CLASS &&
1412. 		    !(typ >= ARROW && typ <= BOOMERANG) &&
1413. 		    !(typ >= DAGGER && typ <= CRYSKNIFE) &&
1414. 		    typ != SLING &&
1415. 		    !is_cloak(obj) && typ != FEDORA &&
1416. 		    !is_gloves(obj) && typ != LEATHER_JACKET &&
1417. #ifdef TOURIST
1418. 		    typ != CREDIT_CARD && !is_shirt(obj) &&
1419. #endif
1420. 		    !(typ == CORPSE && verysmall(&mons[obj->corpsenm])) &&
1421. 		    typ != FORTUNE_COOKIE && typ != CANDY_BAR &&
1422. 		    typ != PANCAKE && typ != LEMBAS_WAFER &&
1423. 		    typ != LUMP_OF_ROYAL_JELLY &&
1424. 		    obj->oclass != AMULET_CLASS &&
1425. 		    obj->oclass != RING_CLASS &&
1426. #ifdef WIZARD
1427. 		    obj->oclass != VENOM_CLASS &&
1428. #endif
1429. 		    typ != SACK && typ != BAG_OF_HOLDING &&
1430. 		    typ != BAG_OF_TRICKS && !Is_candle(obj) &&
1431. 		    typ != OILSKIN_SACK && typ != LEASH &&
1432. 		    typ != STETHOSCOPE && typ != BLINDFOLD && typ != TOWEL &&
1433. 		    typ != TIN_WHISTLE && typ != MAGIC_WHISTLE &&
1434. 		    typ != MAGIC_MARKER && typ != TIN_OPENER &&
1435. 		    typ != SKELETON_KEY && typ != LOCK_PICK
1436. 		) return FALSE;
1437. 		if (Is_container(obj) && obj->cobj) return FALSE;
1438. 		    
1439. 	}
1440. 	return TRUE;
1441. }
1442. 
1443. static int
1444. bust_door_breath(mtmp)
1445. 	register struct monst        *mtmp;
1446. {
1447. 	struct permonst *ptr = mtmp->data;
1448. 	int     i;
1449. 
1450. 
1451. 	if (mtmp->mcan || mtmp->mspec_used) return (-1); /* Cancelled/used up */
1452. 
1453. 	for(i = 0; i < NATTK; i++)
1454.             if ((ptr->mattk[i].aatyp == AT_BREA) &&
1455.                 (ptr->mattk[i].adtyp == AD_ACID ||
1456.                 ptr->mattk[i].adtyp == AD_MAGM ||
1457.                 ptr->mattk[i].adtyp == AD_DISN ||
1458.                 ptr->mattk[i].adtyp == AD_ELEC ||
1459.                 ptr->mattk[i].adtyp == AD_FIRE ||
1460.                 ptr->mattk[i].adtyp == AD_COLD)) return(i);
1461. 
1462.         return(-1);
1463. }
1464. 
1465. 
1466. #endif /* OVL0 */
1467. 
1468. /*monmove.c*/

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.