Wikia

Wikihack

Source:Monmove.c

2,032pages on
this wiki
Talk0

Below is the full text to src/monmove.c from NetHack 3.4.3. To link to a particular line, write [[monmove.c#line123]], for example.

Top of file Edit

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.    
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
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.   
19.   #endif /* OVL0 */
20.   #ifdef OVLB
21.   

mb_trapped Edit

22.   boolean /* TRUE : mtmp died */
23.   mb_trapped(mtmp)
24.   register struct monst *mtmp;
25.   {
26.   	if (flags.verbose) {
27.   	    if (cansee(mtmp->mx, mtmp->my))
28.   		pline("KABOOM!!  You see a door explode.");
29.   	    else if (flags.soundok)
30.   		You_hear("a distant explosion.");
31.   	}
32.   	wake_nearto(mtmp->mx, mtmp->my, 7*7);
33.   	mtmp->mstun = 1;
34.   	mtmp->mhp -= rnd(15);
35.   	if(mtmp->mhp <= 0) {
36.   		mondied(mtmp);
37.   		if (mtmp->mhp > 0) /* lifesaved */
38.   			return(FALSE);
39.   		else
40.   			return(TRUE);
41.   	}
42.   	return(FALSE);
43.   }
44.   
45.   #endif /* OVLB */
46.   #ifdef OVL0
47.   

watch_on_duty Edit

48.   STATIC_OVL void
49.   watch_on_duty(mtmp)
50.   register struct monst *mtmp;
51.   {
52.   	int	x, y;
53.   
54.   	if(mtmp->mpeaceful && in_town(u.ux+u.dx, u.uy+u.dy) &&
55.   	   mtmp->mcansee && m_canseeu(mtmp) && !rn2(3)) {
56.   
57.   	    if(picking_lock(&x, &y) && IS_DOOR(levl[x][y].typ) &&
58.   	       (levl[x][y].doormask & D_LOCKED)) {
59.   
60.   		if(couldsee(mtmp->mx, mtmp->my)) {
61.   
62.   		  pline("%s yells:", Amonnam(mtmp));
63.   		  if(levl[x][y].looted & D_WARNED) {
64.   			verbalize("Halt, thief!  You're under arrest!");
65.   			(void) angry_guards(!(flags.soundok));
66.   		  } else {
67.   			verbalize("Hey, stop picking that lock!");
68.   			levl[x][y].looted |=  D_WARNED;
69.   		  }
70.   		  stop_occupation();
71.   		}
72.   	    } else if (is_digging()) {
73.   		/* chewing, wand/spell of digging are checked elsewhere */
74.   		watch_dig(mtmp, digging.pos.x, digging.pos.y, FALSE);
75.   	    }
76.   	}
77.   }
78.   
79.   #endif /* OVL0 */
80.   #ifdef OVL1
81.   

dochugw Edit

82.   int
83.   dochugw(mtmp)
84.   	register struct monst *mtmp;
85.   {
86.   	register int x = mtmp->mx, y = mtmp->my;
87.   	boolean already_saw_mon = !occupation ? 0 : canspotmon(mtmp);
88.   	int rd = dochug(mtmp);
89.   #if 0
90.   	/* part of the original warning code which was replaced in 3.3.1 */
91.   	int dd;
92.   
93.   	if(Warning && !rd && !mtmp->mpeaceful &&
94.   			(dd = distu(mtmp->mx,mtmp->my)) < distu(x,y) &&
95.   			dd < 100 && !canseemon(mtmp)) {
96.   	    /* Note: this assumes we only want to warn against the monster to
97.   	     * which the weapon does extra damage, as there is no "monster
98.   	     * which the weapon warns against" field.
99.   	     */
100.  	    if (spec_ability(uwep, SPFX_WARN) && spec_dbon(uwep, mtmp, 1))
101.  		warnlevel = 100;
102.  	    else if ((int) (mtmp->m_lev / 4) > warnlevel)
103.  		warnlevel = (mtmp->m_lev / 4);
104.  	}
105.  #endif /* 0 */
106.  
107.  	/* a similar check is in monster_nearby() in hack.c */
108.  	/* check whether hero notices monster and stops current activity */
109.  	if (occupation && !rd && !Confusion &&
110.  	    (!mtmp->mpeaceful || Hallucination) &&
111.  	    /* it's close enough to be a threat */
112.  	    distu(mtmp->mx,mtmp->my) <= (BOLT_LIM+1)*(BOLT_LIM+1) &&
113.  	    /* and either couldn't see it before, or it was too far away */
114.  	    (!already_saw_mon || !couldsee(x,y) ||
115.  		distu(x,y) > (BOLT_LIM+1)*(BOLT_LIM+1)) &&
116.  	    /* can see it now, or sense it and would normally see it */
117.  	    (canseemon(mtmp) ||
118.  		(sensemon(mtmp) && couldsee(mtmp->mx,mtmp->my))) &&
119.  	    mtmp->mcanmove &&
120.  	    !noattacks(mtmp->data) && !onscary(u.ux, u.uy, mtmp))
121.  		stop_occupation();
122.  
123.  	return(rd);
124.  }
125.  
126.  #endif /* OVL1 */
127.  #ifdef OVL2
128.  

onscary Edit

129.  boolean
130.  onscary(x, y, mtmp)
131.  int x, y;
132.  struct monst *mtmp;
133.  {
134.  	if (mtmp->isshk || mtmp->isgd || mtmp->iswiz || !mtmp->mcansee ||
135.  	    mtmp->mpeaceful || mtmp->data->mlet == S_HUMAN ||
136.  	    is_lminion(mtmp) || mtmp->data == &mons[PM_ANGEL] ||
137.  	    is_rider(mtmp->data) || mtmp->data == &mons[PM_MINOTAUR])
138.  		return(FALSE);
139.  
140.  	return (boolean)(sobj_at(SCR_SCARE_MONSTER, x, y)
141.  #ifdef ELBERETH
142.  			 || sengr_at("Elbereth", x, y)
143.  #endif
144.  			 || (mtmp->data->mlet == S_VAMPIRE
145.  			     && IS_ALTAR(levl[x][y].typ)));
146.  }
147.  
148.  #endif /* OVL2 */
149.  #ifdef OVL0
150.  

mon_regen Edit

151.  /* regenerate lost hit points */
152.  void
153.  mon_regen(mon, digest_meal)
154.  struct monst *mon;
155.  boolean digest_meal;
156.  {
157.  	if (mon->mhp < mon->mhpmax &&
158.  	    (moves % 20 == 0 || regenerates(mon->data))) mon->mhp++;
159.  	if (mon->mspec_used) mon->mspec_used--;
160.  	if (digest_meal) {
161.  	    if (mon->meating) mon->meating--;
162.  	}
163.  }
164.  

disturb Edit

165.  /*
166.   * Possibly awaken the given monster.  Return a 1 if the monster has been
167.   * jolted awake.
168.   */
169.  STATIC_OVL int
170.  disturb(mtmp)
171.  	register struct monst *mtmp;
172.  {
173.  	/*
174.  	 * + Ettins are hard to surprise.

This is from Dungeons & Dragons, where ettins have two heads (and so presumably can see anyone sneaking up on them).

175.  	 * + Nymphs, jabberwocks, and leprechauns do not easily wake up.
176.  	 *
177.  	 * Wake up if:
178.  	 *	in direct LOS						AND
179.  	 *	within 10 squares					AND
180.  	 *	not stealthy or (mon is an ettin and 9/10)		AND
181.  	 *	(mon is not a nymph, jabberwock, or leprechaun) or 1/50	AND
182.  	 *	Aggravate or mon is (dog or human) or
183.  	 *	    (1/7 and mon is not mimicing furniture or object)
184.  	 */
185.  	if(couldsee(mtmp->mx,mtmp->my) &&
186.  		distu(mtmp->mx,mtmp->my) <= 100 &&
187.  		(!Stealth || (mtmp->data == &mons[PM_ETTIN] && rn2(10))) &&

The 9-in-10 chance of an ettin waking up is also taken directly from D&D.

188.  		(!(mtmp->data->mlet == S_NYMPH
189.  			|| mtmp->data == &mons[PM_JABBERWOCK]
190.  #if 0	/* DEFERRED */
191.  			|| mtmp->data == &mons[PM_VORPAL_JABBERWOCK]
192.  #endif
193.  			|| mtmp->data->mlet == S_LEPRECHAUN) || !rn2(50)) &&
194.  		(Aggravate_monster
195.  			|| (mtmp->data->mlet == S_DOG ||
196.  				mtmp->data->mlet == S_HUMAN)
197.  			|| (!rn2(7) && mtmp->m_ap_type != M_AP_FURNITURE &&
198.  				mtmp->m_ap_type != M_AP_OBJECT) )) {
199.  		mtmp->msleeping = 0;
200.  		return(1);
201.  	}
202.  	return(0);
203.  }
204.  

monflee Edit

205.  /* monster begins fleeing for the specified time, 0 means untimed flee
206.   * if first, only adds fleetime if monster isn't already fleeing
207.   * if fleemsg, prints a message about new flight, otherwise, caller should */
208.  void
209.  monflee(mtmp, fleetime, first, fleemsg)
210.  struct monst *mtmp;
211.  int fleetime;
212.  boolean first;
213.  boolean fleemsg;
214.  {
215.  	if (u.ustuck == mtmp) {
216.  	    if (u.uswallow)
217.  		expels(mtmp, mtmp->data, TRUE);
218.  	    else if (!sticks(youmonst.data)) {
219.  		unstuck(mtmp);	/* monster lets go when fleeing */
220.  		You("get released!");
221.  	    }
222.  	}
223.  
224.  	if (!first || !mtmp->mflee) {
225.  	    /* don't lose untimed scare */
226.  	    if (!fleetime)
227.  		mtmp->mfleetim = 0;
228.  	    else if (!mtmp->mflee || mtmp->mfleetim) {
229.  		fleetime += mtmp->mfleetim;
230.  		/* ensure monster flees long enough to visibly stop fighting */
231.  		if (fleetime == 1) fleetime++;
232.  		mtmp->mfleetim = min(fleetime, 127);
233.  	    }
234.  	    if (!mtmp->mflee && fleemsg && canseemon(mtmp) && !mtmp->mfrozen)
235.  		pline("%s turns to flee!", (Monnam(mtmp)));
236.  	    mtmp->mflee = 1;
237.  	}
238.  }
239.  

distfleeck Edit

240.  STATIC_OVL void
241.  distfleeck(mtmp,inrange,nearby,scared)
242.  register struct monst *mtmp;
243.  int *inrange, *nearby, *scared;
244.  {
245.  	int seescaryx, seescaryy;
246.  
247.  	*inrange = (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <=
248.  							(BOLT_LIM * BOLT_LIM));
249.  	*nearby = *inrange && monnear(mtmp, mtmp->mux, mtmp->muy);
250.  
251.  	/* Note: if your image is displaced, the monster sees the Elbereth
252.  	 * at your displaced position, thus never attacking your displaced
253.  	 * position, but possibly attacking you by accident.  If you are
254.  	 * invisible, it sees the Elbereth at your real position, thus never
255.  	 * running into you by accident but possibly attacking the spot
256.  	 * where it guesses you are.
257.  	 */
258.  	if (!mtmp->mcansee || (Invis && !perceives(mtmp->data))) {
259.  		seescaryx = mtmp->mux;
260.  		seescaryy = mtmp->muy;
261.  	} else {
262.  		seescaryx = u.ux;
263.  		seescaryy = u.uy;
264.  	}
265.  	*scared = (*nearby && (onscary(seescaryx, seescaryy, mtmp) ||
266.  			       (!mtmp->mpeaceful &&
267.  				    in_your_sanctuary(mtmp, 0, 0))));
268.  
269.  	if(*scared) {
270.  		if (rn2(7))
271.  		    monflee(mtmp, rnd(10), TRUE, TRUE);
272.  		else
273.  		    monflee(mtmp, rnd(100), TRUE, TRUE);
274.  	}
275.  
276.  }
277.  

m_arrival Edit

278.  /* perform a special one-time action for a monster; returns -1 if nothing
279.     special happened, 0 if monster uses up its turn, 1 if monster is killed */
280.  STATIC_OVL int
281.  m_arrival(mon)
282.  struct monst *mon;
283.  {
284.  	mon->mstrategy &= ~STRAT_ARRIVE;	/* always reset */
285.  
286.  	return -1;
287.  }
288.  

dochug Edit

289.  /* returns 1 if monster died moving, 0 otherwise */
290.  /* The whole dochugw/m_move/distfleeck/mfndpos section is serious spaghetti
291.   * code. --KAA
292.   */
293.  int
294.  dochug(mtmp)
295.  register struct monst *mtmp;
296.  {
297.  	register struct permonst *mdat;
298.  	register int tmp=0;
299.  	int inrange, nearby, scared;
300.  #ifdef GOLDOBJ
301.          struct obj *ygold = 0, *lepgold = 0;
302.  #endif
303.  
304.  /*	Pre-movement adjustments	*/
305.  
306.  	mdat = mtmp->data;
307.  
308.  	if (mtmp->mstrategy & STRAT_ARRIVE) {
309.  	    int res = m_arrival(mtmp);
310.  	    if (res >= 0) return res;
311.  	}
312.  
313.  	/* check for waitmask status change */
314.  	if ((mtmp->mstrategy & STRAT_WAITFORU) &&
315.  		(m_canseeu(mtmp) || mtmp->mhp < mtmp->mhpmax))
316.  	    mtmp->mstrategy &= ~STRAT_WAITFORU;
317.  
318.  	/* update quest status flags */
319.  	quest_stat_check(mtmp);
320.  
321.  	if (!mtmp->mcanmove || (mtmp->mstrategy & STRAT_WAITMASK)) {
322.  	    if (Hallucination) newsym(mtmp->mx,mtmp->my);
323.  	    if (mtmp->mcanmove && (mtmp->mstrategy & STRAT_CLOSE) &&
324.  	       !mtmp->msleeping && monnear(mtmp, u.ux, u.uy))
325.  		quest_talk(mtmp);	/* give the leaders a chance to speak */
326.  	    return(0);	/* other frozen monsters can't do anything */
327.  	}
328.  
329.  	/* there is a chance we will wake it */
330.  	if (mtmp->msleeping && !disturb(mtmp)) {
331.  		if (Hallucination) newsym(mtmp->mx,mtmp->my);
332.  		return(0);
333.  	}
334.  
335.  	/* not frozen or sleeping: wipe out texts written in the dust */
336.  	wipe_engr_at(mtmp->mx, mtmp->my, 1);
337.  
338.  	/* confused monsters get unconfused with small probability */
339.  	if (mtmp->mconf && !rn2(50)) mtmp->mconf = 0;
340.  
341.  	/* stunned monsters get un-stunned with larger probability */
342.  	if (mtmp->mstun && !rn2(10)) mtmp->mstun = 0;
343.  
344.  	/* some monsters teleport */
345.  	if (mtmp->mflee && !rn2(40) && can_teleport(mdat) && !mtmp->iswiz &&
346.  	    !level.flags.noteleport) {
347.  		(void) rloc(mtmp, FALSE);
348.  		return(0);
349.  	}
350.  	if (mdat->msound == MS_SHRIEK && !um_dist(mtmp->mx, mtmp->my, 1))
351.  	    m_respond(mtmp);
352.  	if (mdat == &mons[PM_MEDUSA] && couldsee(mtmp->mx, mtmp->my))
353.  	    m_respond(mtmp);
354.  	if (mtmp->mhp <= 0) return(1); /* m_respond gaze can kill medusa */
355.  
356.  	/* fleeing monsters might regain courage */
357.  	if (mtmp->mflee && !mtmp->mfleetim
358.  	   && mtmp->mhp == mtmp->mhpmax && !rn2(25)) mtmp->mflee = 0;
359.  
360.  	set_apparxy(mtmp);
361.  	/* Must be done after you move and before the monster does.  The
362.  	 * set_apparxy() call in m_move() doesn't suffice since the variables
363.  	 * inrange, etc. all depend on stuff set by set_apparxy().
364.  	 */
365.  
366.  	/* Monsters that want to acquire things */
367.  	/* may teleport, so do it before inrange is set */
368.  	if(is_covetous(mdat)) (void) tactics(mtmp);
369.  
370.  	/* check distance and scariness of attacks */
371.  	distfleeck(mtmp,&inrange,&nearby,&scared);
372.  
373.  	if(find_defensive(mtmp)) {
374.  		if (use_defensive(mtmp) != 0)
375.  			return 1;
376.  	} else if(find_misc(mtmp)) {
377.  		if (use_misc(mtmp) != 0)
378.  			return 1;
379.  	}
380.  
381.  	/* Demonic Blackmail! */
382.  	if(nearby && mdat->msound == MS_BRIBE &&
383.  	   mtmp->mpeaceful && !mtmp->mtame && !u.uswallow) {
384.  		if (mtmp->mux != u.ux || mtmp->muy != u.uy) {
385.  			pline("%s whispers at thin air.",
386.  			    cansee(mtmp->mux, mtmp->muy) ? Monnam(mtmp) : "It");
387.  
388.  			if (is_demon(youmonst.data)) {
389.  			  /* "Good hunting, brother" */
390.  			    if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
391.  			} else {
392.  			    mtmp->minvis = mtmp->perminvis = 0;
393.  			    /* Why?  For the same reason in real demon talk */
394.  			    pline("%s gets angry!", Amonnam(mtmp));
395.  			    mtmp->mpeaceful = 0;
396.  			    /* since no way is an image going to pay it off */
397.  			}
398.  		} else if(demon_talk(mtmp)) return(1);	/* you paid it off */
399.  	}
400.  
401.  	/* the watch will look around and see if you are up to no good :-) */
402.  	if (mdat == &mons[PM_WATCHMAN] || mdat == &mons[PM_WATCH_CAPTAIN])
403.  		watch_on_duty(mtmp);
404.  
405.  	else if (is_mind_flayer(mdat) && !rn2(20)) {
406.  		struct monst *m2, *nmon = (struct monst *)0;
407.  
408.  		if (canseemon(mtmp))
409.  			pline("%s concentrates.", Monnam(mtmp));
410.  		if (distu(mtmp->mx, mtmp->my) > BOLT_LIM * BOLT_LIM) {
411.  			You("sense a faint wave of psychic energy.");
412.  			goto toofar;
413.  		}
414.  		pline("A wave of psychic energy pours over you!");
415.  		if (mtmp->mpeaceful &&
416.  		    (!Conflict || resist(mtmp, RING_CLASS, 0, 0)))
417.  			pline("It feels quite soothing.");
418.  		else {
419.  			register boolean m_sen = sensemon(mtmp);
420.  
421.  			if (m_sen || (Blind_telepat && rn2(2)) || !rn2(10)) {
422.  				int dmg;
423.  				pline("It locks on to your %s!",
424.  					m_sen ? "telepathy" :
425.  					Blind_telepat ? "latent telepathy" : "mind");
426.  				dmg = rnd(15);
427.  				if (Half_spell_damage) dmg = (dmg+1) / 2;
428.  				losehp(dmg, "psychic blast", KILLED_BY_AN);
429.  			}
430.  		}
431.  		for(m2=fmon; m2; m2 = nmon) {
432.  			nmon = m2->nmon;
433.  			if (DEADMONSTER(m2)) continue;
434.  			if (m2->mpeaceful == mtmp->mpeaceful) continue;
435.  			if (mindless(m2->data)) continue;
436.  			if (m2 == mtmp) continue;
437.  			if ((telepathic(m2->data) &&
438.  			    (rn2(2) || m2->mblinded)) || !rn2(10)) {
439.  				if (cansee(m2->mx, m2->my))
440.  				    pline("It locks on to %s.", mon_nam(m2));
441.  				m2->mhp -= rnd(15);
442.  				if (m2->mhp <= 0)
443.  				    monkilled(m2, "", AD_DRIN);
444.  				else
445.  				    m2->msleeping = 0;
446.  			}
447.  		}
448.  	}
449.  toofar:
450.  
451.  	/* If monster is nearby you, and has to wield a weapon, do so.   This
452.  	 * costs the monster a move, of course.
453.  	 */
454.  	if((!mtmp->mpeaceful || Conflict) && inrange &&
455.  	   dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= 8
456.  	   && attacktype(mdat, AT_WEAP)) {
457.  	    struct obj *mw_tmp;
458.  
459.  	    /* The scared check is necessary.  Otherwise a monster that is
460.  	     * one square near the player but fleeing into a wall would keep	
461.  	     * switching between pick-axe and weapon.  If monster is stuck
462.  	     * in a trap, prefer ranged weapon (wielding is done in thrwmu).
463.  	     * This may cost the monster an attack, but keeps the monster
464.  	     * from switching back and forth if carrying both.
465.  	     */
466.  	    mw_tmp = MON_WEP(mtmp);
467.  	    if (!(scared && mw_tmp && is_pick(mw_tmp)) &&
468.  		mtmp->weapon_check == NEED_WEAPON &&
469.  		!(mtmp->mtrapped && !nearby && select_rwep(mtmp))) {
470.  		mtmp->weapon_check = NEED_HTH_WEAPON;
471.  		if (mon_wield_item(mtmp) != 0) return(0);
472.  	    }
473.  	}
474.  
475.  /*	Now the actual movement phase	*/
476.  
477.  #ifndef GOLDOBJ
478.  	if(!nearby || mtmp->mflee || scared ||
479.  	   mtmp->mconf || mtmp->mstun || (mtmp->minvis && !rn2(3)) ||
480.  	   (mdat->mlet == S_LEPRECHAUN && !u.ugold && (mtmp->mgold || rn2(2))) ||
481.  #else
482.          if (mdat->mlet == S_LEPRECHAUN) {
483.  	    ygold = findgold(invent);
484.  	    lepgold = findgold(mtmp->minvent);
485.  	}
486.  
487.  	if(!nearby || mtmp->mflee || scared ||
488.  	   mtmp->mconf || mtmp->mstun || (mtmp->minvis && !rn2(3)) ||
489.  	   (mdat->mlet == S_LEPRECHAUN && !ygold && (lepgold || rn2(2))) ||
490.  #endif
491.  	   (is_wanderer(mdat) && !rn2(4)) || (Conflict && !mtmp->iswiz) ||
492.  	   (!mtmp->mcansee && !rn2(4)) || mtmp->mpeaceful) {
493.  		/* Possibly cast an undirected spell if not attacking you */
494.  		/* note that most of the time castmu() will pick a directed
495.  		   spell and do nothing, so the monster moves normally */
496.  		/* arbitrary distance restriction to keep monster far away
497.  		   from you from having cast dozens of sticks-to-snakes
498.  		   or similar spells by the time you reach it */
499.  		if (dist2(mtmp->mx, mtmp->my, u.ux, u.uy) <= 49 && !mtmp->mspec_used) {
500.  		    struct attack *a;
501.  
502.  		    for (a = &mdat->mattk[0]; a < &mdat->mattk[NATTK]; a++) {
503.  			if (a->aatyp == AT_MAGC && (a->adtyp == AD_SPEL || a->adtyp == AD_CLRC)) {
504.  			    if (castmu(mtmp, a, FALSE, FALSE)) {
505.  				tmp = 3;
506.  				break;
507.  			    }
508.  			}
509.  		    }
510.  		}
511.  
512.  		tmp = m_move(mtmp, 0);
513.  		distfleeck(mtmp,&inrange,&nearby,&scared);	/* recalc */
514.  
515.  		switch (tmp) {
516.  		    case 0:	/* no movement, but it can still attack you */
517.  		    case 3:	/* absolutely no movement */
518.  				/* for pets, case 0 and 3 are equivalent */
519.  			/* vault guard might have vanished */
520.  			if (mtmp->isgd && (mtmp->mhp < 1 ||
521.  					    (mtmp->mx == 0 && mtmp->my == 0)))
522.  			    return 1;	/* behave as if it died */
523.  			/* During hallucination, monster appearance should
524.  			 * still change - even if it doesn't move.
525.  			 */
526.  			if(Hallucination) newsym(mtmp->mx,mtmp->my);
527.  			break;
528.  		    case 1:	/* monster moved */
529.  			/* Maybe it stepped on a trap and fell asleep... */
530.  			if (mtmp->msleeping || !mtmp->mcanmove) return(0);
531.  			if(!nearby &&
532.  			  (ranged_attk(mdat) || find_offensive(mtmp)))
533.  			    break;
534.   			else if(u.uswallow && mtmp == u.ustuck) {
535.  			    /* a monster that's digesting you can move at the
536.  			     * same time -dlc
537.  			     */
538.  			    return(mattacku(mtmp));
539.  			} else
540.  				return(0);
541.  			/*NOTREACHED*/
542.  			break;
543.  		    case 2:	/* monster died */
544.  			return(1);
545.  		}
546.  	}
547.  
548.  /*	Now, attack the player if possible - one attack set per monst	*/
549.  
550.  	if (!mtmp->mpeaceful ||
551.  	    (Conflict && !resist(mtmp, RING_CLASS, 0, 0))) {
552.  	    if(inrange && !noattacks(mdat) && u.uhp > 0 && !scared && tmp != 3)
553.  		if(mattacku(mtmp)) return(1); /* monster died (e.g. exploded) */
554.  
555.  	    if(mtmp->wormno) wormhitu(mtmp);
556.  	}
557.  	/* special speeches for quest monsters */
558.  	if (!mtmp->msleeping && mtmp->mcanmove && nearby)
559.  	    quest_talk(mtmp);
560.  	/* extra emotional attack for vile monsters */
561.  	if (inrange && mtmp->data->msound == MS_CUSS && !mtmp->mpeaceful &&
562.  		couldsee(mtmp->mx, mtmp->my) && !mtmp->minvis && !rn2(5))
563.  	    cuss(mtmp);
564.  
565.  	return(tmp == 2);
566.  }
567.  
568.  static NEARDATA const char practical[] = { WEAPON_CLASS, ARMOR_CLASS, GEM_CLASS, FOOD_CLASS, 0 };
569.  static NEARDATA const char magical[] = {
570.  	AMULET_CLASS, POTION_CLASS, SCROLL_CLASS, WAND_CLASS, RING_CLASS,
571.  	SPBOOK_CLASS, 0 };
572.  static NEARDATA const char indigestion[] = { BALL_CLASS, ROCK_CLASS, 0 };
573.  static NEARDATA const char boulder_class[] = { ROCK_CLASS, 0 };
574.  static NEARDATA const char gem_class[] = { GEM_CLASS, 0 };
575.  

itsstuck Edit

576.  boolean
577.  itsstuck(mtmp)
578.  register struct monst *mtmp;
579.  {
580.  	if (sticks(youmonst.data) && mtmp==u.ustuck && !u.uswallow) {
581.  		pline("%s cannot escape from you!", Monnam(mtmp));
582.  		return(TRUE);
583.  	}
584.  	return(FALSE);
585.  }
586.  

m_move Edit

587.  /* Return values:
588.   * 0: did not move, but can still attack and do other stuff.
589.   * 1: moved, possibly can attack.
590.   * 2: monster died.
591.   * 3: did not move, and can't do anything else either.
592.   */
593.  int
594.  m_move(mtmp, after)
595.  register struct monst *mtmp;
596.  register int after;
597.  {
598.  	register int appr;
599.  	xchar gx,gy,nix,niy,chcnt;
600.  	int chi;	/* could be schar except for stupid Sun-2 compiler */
601.  	boolean likegold=0, likegems=0, likeobjs=0, likemagic=0, conceals=0;
602.  	boolean likerock=0, can_tunnel=0;
603.  	boolean can_open=0, can_unlock=0, doorbuster=0;
604.  	boolean uses_items=0, setlikes=0;
605.  	boolean avoid=FALSE;
606.  	struct permonst *ptr;
607.  	struct monst *mtoo;
608.  	schar mmoved = 0;	/* not strictly nec.: chi >= 0 will do */
609.  	long info[9];
610.  	long flag;
611.  	int  omx = mtmp->mx, omy = mtmp->my;
612.  	struct obj *mw_tmp;
613.  
614.  	if(mtmp->mtrapped) {
615.  	    int i = mintrap(mtmp);
616.  	    if(i >= 2) { newsym(mtmp->mx,mtmp->my); return(2); }/* it died */
617.  	    if(i == 1) return(0);	/* still in trap, so didn't move */
618.  	}
619.  	ptr = mtmp->data; /* mintrap() can change mtmp->data -dlc */
620.  
621.  	if (mtmp->meating) {
622.  	    mtmp->meating--;
623.  	    return 3;			/* still eating */
624.  	}
625.  	if (hides_under(ptr) && OBJ_AT(mtmp->mx, mtmp->my) && rn2(10))
626.  	    return 0;		/* do not leave hiding place */
627.  
628.  	set_apparxy(mtmp);
629.  	/* where does mtmp think you are? */
630.  	/* Not necessary if m_move called from this file, but necessary in
631.  	 * other calls of m_move (ex. leprechauns dodging)
632.  	 */
633.  #ifdef REINCARNATION
634.  	if (!Is_rogue_level(&u.uz))
635.  #endif
636.  	    can_tunnel = tunnels(ptr);
637.  	can_open = !(nohands(ptr) || verysmall(ptr));
638.  	can_unlock = ((can_open && m_carrying(mtmp, SKELETON_KEY)) ||
639.  		      mtmp->iswiz || is_rider(ptr));
640.  	doorbuster = is_giant(ptr);
641.  	if(mtmp->wormno) goto not_special;
642.  	/* my dog gets special treatment */
643.  	if(mtmp->mtame) {
644.  	    mmoved = dog_move(mtmp, after);
645.  	    goto postmov;
646.  	}
647.  
648.  	/* likewise for shopkeeper */
649.  	if(mtmp->isshk) {
650.  	    mmoved = shk_move(mtmp);
651.  	    if(mmoved == -2) return(2);
652.  	    if(mmoved >= 0) goto postmov;
653.  	    mmoved = 0;		/* follow player outside shop */
654.  	}
655.  
656.  	/* and for the guard */
657.  	if(mtmp->isgd) {
658.  	    mmoved = gd_move(mtmp);
659.  	    if(mmoved == -2) return(2);
660.  	    if(mmoved >= 0) goto postmov;
661.  	    mmoved = 0;
662.  	}
663.  
664.  	/* and the acquisitive monsters get special treatment */
665.  	if(is_covetous(ptr)) {
666.  	    xchar tx = STRAT_GOALX(mtmp->mstrategy),
667.  		  ty = STRAT_GOALY(mtmp->mstrategy);
668.  	    struct monst *intruder = m_at(tx, ty);
669.  	    /*
670.  	     * if there's a monster on the object or in possesion of it,
671.  	     * attack it.
672.  	     */
673.  	    if((dist2(mtmp->mx, mtmp->my, tx, ty) < 2) &&
674.  	       intruder && (intruder != mtmp)) {
675.  
676.  		notonhead = (intruder->mx != tx || intruder->my != ty);
677.  		if(mattackm(mtmp, intruder) == 2) return(2);
678.  		mmoved = 1;
679.  	    } else mmoved = 0;
680.  	    goto postmov;
681.  	}
682.  
683.  	/* and for the priest */
684.  	if(mtmp->ispriest) {
685.  	    mmoved = pri_move(mtmp);
686.  	    if(mmoved == -2) return(2);
687.  	    if(mmoved >= 0) goto postmov;
688.  	    mmoved = 0;
689.  	}
690.  
691.  #ifdef MAIL
692.  	if(ptr == &mons[PM_MAIL_DAEMON]) {
693.  	    if(flags.soundok && canseemon(mtmp))
694.  		verbalize("I'm late!");
695.  	    mongone(mtmp);
696.  	    return(2);
697.  	}
698.  #endif
699.  
700.  	/* teleport if that lies in our nature */
701.  	if(ptr == &mons[PM_TENGU] && !rn2(5) && !mtmp->mcan &&
702.  	   !tele_restrict(mtmp)) {
703.  	    if(mtmp->mhp < 7 || mtmp->mpeaceful || rn2(2))
704.  		(void) rloc(mtmp, FALSE);
705.  	    else
706.  		mnexto(mtmp);
707.  	    mmoved = 1;
708.  	    goto postmov;
709.  	}
710.  not_special:
711.  	if(u.uswallow && !mtmp->mflee && u.ustuck != mtmp) return(1);
712.  	omx = mtmp->mx;
713.  	omy = mtmp->my;
714.  	gx = mtmp->mux;
715.  	gy = mtmp->muy;
716.  	appr = mtmp->mflee ? -1 : 1;
717.  	if (mtmp->mconf || (u.uswallow && mtmp == u.ustuck))
718.  		appr = 0;
719.  	else {
720.  #ifdef GOLDOBJ
721.  		struct obj *lepgold, *ygold;
722.  #endif
723.  		boolean should_see = (couldsee(omx, omy) &&
724.  				      (levl[gx][gy].lit ||
725.  				       !levl[omx][omy].lit) &&
726.  				      (dist2(omx, omy, gx, gy) <= 36));
727.  
728.  		if (!mtmp->mcansee ||
729.  		    (should_see && Invis && !perceives(ptr) && rn2(11)) ||
730.  		    (youmonst.m_ap_type == M_AP_OBJECT && youmonst.mappearance == STRANGE_OBJECT) || u.uundetected ||
731.  		    (youmonst.m_ap_type == M_AP_OBJECT && youmonst.mappearance == GOLD_PIECE && !likes_gold(ptr)) ||
732.  		    (mtmp->mpeaceful && !mtmp->isshk) ||  /* allow shks to follow */
733.  		    ((monsndx(ptr) == PM_STALKER || ptr->mlet == S_BAT ||
734.  		      ptr->mlet == S_LIGHT) && !rn2(3)))
735.  			appr = 0;
736.  
737.  		if(monsndx(ptr) == PM_LEPRECHAUN && (appr == 1) &&
738.  #ifndef GOLDOBJ
739.  		   (mtmp->mgold > u.ugold))
740.  #else
741.  		   ( (lepgold = findgold(mtmp->minvent)) && 
742.                     (lepgold->quan > ((ygold = findgold(invent)) ? ygold->quan : 0L)) ))
743.  #endif
744.  			appr = -1;
745.  
746.  		if (!should_see && can_track(ptr)) {
747.  			register coord *cp;
748.  
749.  			cp = gettrack(omx,omy);
750.  			if (cp) {
751.  				gx = cp->x;
752.  				gy = cp->y;
753.  			}
754.  		}
755.  	}
756.  
757.  	if ((!mtmp->mpeaceful || !rn2(10))
758.  #ifdef REINCARNATION
759.  				    && (!Is_rogue_level(&u.uz))
760.  #endif
761.  							    ) {
762.  	    boolean in_line = lined_up(mtmp) &&
763.  		(distmin(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <=
764.  		    (throws_rocks(youmonst.data) ? 20 : ACURRSTR/2+1)
765.  		);
766.  
767.  	    if (appr != 1 || !in_line) {
768.  		/* Monsters in combat won't pick stuff up, avoiding the
769.  		 * situation where you toss arrows at it and it has nothing
770.  		 * better to do than pick the arrows up.
771.  		 */
772.  		register int pctload = (curr_mon_load(mtmp) * 100) /
773.  			max_mon_load(mtmp);
774.  
775.  		/* look for gold or jewels nearby */
776.  		likegold = (likes_gold(ptr) && pctload < 95);
777.  		likegems = (likes_gems(ptr) && pctload < 85);
778.  		uses_items = (!mindless(ptr) && !is_animal(ptr)
779.  			&& pctload < 75);
780.  		likeobjs = (likes_objs(ptr) && pctload < 75);
781.  		likemagic = (likes_magic(ptr) && pctload < 85);
782.  		likerock = (throws_rocks(ptr) && pctload < 50 && !In_sokoban(&u.uz));
783.  		conceals = hides_under(ptr);
784.  		setlikes = TRUE;
785.  	    }
786.  	}
787.  
788.  #define SQSRCHRADIUS	5
789.  
790.        { register int minr = SQSRCHRADIUS;	/* not too far away */
791.  	register struct obj *otmp;
792.  	register int xx, yy;
793.  	int oomx, oomy, lmx, lmy;
794.  
795.  	/* cut down the search radius if it thinks character is closer. */
796.  	if(distmin(mtmp->mux, mtmp->muy, omx, omy) < SQSRCHRADIUS &&
797.  	    !mtmp->mpeaceful) minr--;
798.  	/* guards shouldn't get too distracted */
799.  	if(!mtmp->mpeaceful && is_mercenary(ptr)) minr = 1;
800.  
801.  	if((likegold || likegems || likeobjs || likemagic || likerock || conceals)
802.  	      && (!*in_rooms(omx, omy, SHOPBASE) || (!rn2(25) && !mtmp->isshk))) {
803.  	look_for_obj:
804.  	    oomx = min(COLNO-1, omx+minr);
805.  	    oomy = min(ROWNO-1, omy+minr);
806.  	    lmx = max(1, omx-minr);
807.  	    lmy = max(0, omy-minr);
808.  	    for(otmp = fobj; otmp; otmp = otmp->nobj) {
809.  		/* monsters may pick rocks up, but won't go out of their way
810.  		   to grab them; this might hamper sling wielders, but it cuts
811.  		   down on move overhead by filtering out most common item */
812.  		if (otmp->otyp == ROCK) continue;
813.  		xx = otmp->ox;
814.  		yy = otmp->oy;
815.  		/* Nymphs take everything.  Most other creatures should not
816.  		 * pick up corpses except as a special case like in
817.  		 * searches_for_item().  We need to do this check in
818.  		 * mpickstuff() as well.
819.  		 */
820.  		if(xx >= lmx && xx <= oomx && yy >= lmy && yy <= oomy) {
821.  		    /* don't get stuck circling around an object that's underneath
822.  		       an immobile or hidden monster; paralysis victims excluded */
823.  		    if ((mtoo = m_at(xx,yy)) != 0 &&
824.  			(mtoo->msleeping || mtoo->mundetected ||
825.  			 (mtoo->mappearance && !mtoo->iswiz) ||
826.  			 !mtoo->data->mmove)) continue;
827.  
828.  		    if(((likegold && otmp->oclass == COIN_CLASS) ||
829.  		       (likeobjs && index(practical, otmp->oclass) &&
830.  			(otmp->otyp != CORPSE || (ptr->mlet == S_NYMPH
831.  			   && !is_rider(&mons[otmp->corpsenm])))) ||
832.  		       (likemagic && index(magical, otmp->oclass)) ||
833.  		       (uses_items && searches_for_item(mtmp, otmp)) ||
834.  		       (likerock && otmp->otyp == BOULDER) ||
835.  		       (likegems && otmp->oclass == GEM_CLASS &&
836.  			objects[otmp->otyp].oc_material != MINERAL) ||
837.  		       (conceals && !cansee(otmp->ox,otmp->oy)) ||
838.  		       (ptr == &mons[PM_GELATINOUS_CUBE] &&
839.  			!index(indigestion, otmp->oclass) &&
840.  			!(otmp->otyp == CORPSE &&
841.  			  touch_petrifies(&mons[otmp->corpsenm])))
842.  		      ) && touch_artifact(otmp,mtmp)) {
843.  			if(can_carry(mtmp,otmp) &&
844.  			   (throws_rocks(ptr) ||
845.  				!sobj_at(BOULDER,xx,yy)) &&
846.  			   (!is_unicorn(ptr) ||
847.  			    objects[otmp->otyp].oc_material == GEMSTONE) &&
848.  			   /* Don't get stuck circling an Elbereth */
849.  			   !(onscary(xx, yy, mtmp))) {
850.  			    minr = distmin(omx,omy,xx,yy);
851.  			    oomx = min(COLNO-1, omx+minr);
852.  			    oomy = min(ROWNO-1, omy+minr);
853.  			    lmx = max(1, omx-minr);
854.  			    lmy = max(0, omy-minr);
855.  			    gx = otmp->ox;
856.  			    gy = otmp->oy;
857.  			    if (gx == omx && gy == omy) {
858.  				mmoved = 3; /* actually unnecessary */
859.  				goto postmov;
860.  			    }
861.  			}
862.  		    }
863.  		}
864.  	    }
865.  	} else if(likegold) {
866.  	    /* don't try to pick up anything else, but use the same loop */
867.  	    uses_items = 0;
868.  	    likegems = likeobjs = likemagic = likerock = conceals = 0;
869.  	    goto look_for_obj;
870.  	}
871.  
872.  	if(minr < SQSRCHRADIUS && appr == -1) {
873.  	    if(distmin(omx,omy,mtmp->mux,mtmp->muy) <= 3) {
874.  		gx = mtmp->mux;
875.  		gy = mtmp->muy;
876.  	    } else
877.  		appr = 1;
878.  	}
879.        }
880.  
881.  	/* don't tunnel if hostile and close enough to prefer a weapon */
882.  	if (can_tunnel && needspick(ptr) &&
883.  	    ((!mtmp->mpeaceful || Conflict) &&
884.  	     dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= 8))
885.  	    can_tunnel = FALSE;
886.  
887.  	nix = omx;
888.  	niy = omy;
889.  	flag = 0L;
890.  	if (mtmp->mpeaceful && (!Conflict || resist(mtmp, RING_CLASS, 0, 0)))
891.  	    flag |= (ALLOW_SANCT | ALLOW_SSM);
892.  	else flag |= ALLOW_U;
893.  	if (is_minion(ptr) || is_rider(ptr)) flag |= ALLOW_SANCT;
894.  	/* unicorn may not be able to avoid hero on a noteleport level */
895.  	if (is_unicorn(ptr) && !level.flags.noteleport) flag |= NOTONL;
896.  	if (passes_walls(ptr)) flag |= (ALLOW_WALL | ALLOW_ROCK);
897.  	if (passes_bars(ptr)) flag |= ALLOW_BARS;
898.  	if (can_tunnel) flag |= ALLOW_DIG;
899.  	if (is_human(ptr) || ptr == &mons[PM_MINOTAUR]) flag |= ALLOW_SSM;
900.  	if (is_undead(ptr) && ptr->mlet != S_GHOST) flag |= NOGARLIC;
901.  	if (throws_rocks(ptr)) flag |= ALLOW_ROCK;
902.  	if (can_open) flag |= OPENDOOR;
903.  	if (can_unlock) flag |= UNLOCKDOOR;
904.  	if (doorbuster) flag |= BUSTDOOR;
905.  	{
906.  	    register int i, j, nx, ny, nearer;
907.  	    int jcnt, cnt;
908.  	    int ndist, nidist;
909.  	    register coord *mtrk;
910.  	    coord poss[9];
911.  
912.  	    cnt = mfndpos(mtmp, poss, info, flag);
913.  	    chcnt = 0;
914.  	    jcnt = min(MTSZ, cnt-1);
915.  	    chi = -1;
916.  	    nidist = dist2(nix,niy,gx,gy);
917.  	    /* allow monsters be shortsighted on some levels for balance */
918.  	    if(!mtmp->mpeaceful && level.flags.shortsighted &&
919.  	       nidist > (couldsee(nix,niy) ? 144 : 36) && appr == 1) appr = 0;
920.  	    if (is_unicorn(ptr) && level.flags.noteleport) {
921.  		/* on noteleport levels, perhaps we cannot avoid hero */
922.  		for(i = 0; i < cnt; i++)
923.  		    if(!(info[i] & NOTONL)) avoid=TRUE;
924.  	    }
925.  
926.  	    for(i=0; i < cnt; i++) {
927.  		if (avoid && (info[i] & NOTONL)) continue;
928.  		nx = poss[i].x;
929.  		ny = poss[i].y;
930.  
931.  		if (appr != 0) {
932.  		    mtrk = &mtmp->mtrack[0];
933.  		    for(j=0; j < jcnt; mtrk++, j++)
934.  			if(nx == mtrk->x && ny == mtrk->y)
935.  			    if(rn2(4*(cnt-j)))
936.  				goto nxti;
937.  		}
938.  
939.  		nearer = ((ndist = dist2(nx,ny,gx,gy)) < nidist);
940.  
941.  		if((appr == 1 && nearer) || (appr == -1 && !nearer) ||
942.  		   (!appr && !rn2(++chcnt)) || !mmoved) {
943.  		    nix = nx;
944.  		    niy = ny;
945.  		    nidist = ndist;
946.  		    chi = i;
947.  		    mmoved = 1;
948.  		}
949.  	    nxti:	;
950.  	    }
951.  	}
952.  
953.  	if(mmoved) {
954.  	    register int j;
955.  
956.  	    if (mmoved==1 && (u.ux != nix || u.uy != niy) && itsstuck(mtmp))
957.  		return(3);
958.  
959.  	    if (((IS_ROCK(levl[nix][niy].typ) && may_dig(nix,niy)) ||
960.  		 closed_door(nix, niy)) &&
961.  		mmoved==1 && can_tunnel && needspick(ptr)) {
962.  		if (closed_door(nix, niy)) {
963.  		    if (!(mw_tmp = MON_WEP(mtmp)) ||
964.  			!is_pick(mw_tmp) || !is_axe(mw_tmp))
965.  			mtmp->weapon_check = NEED_PICK_OR_AXE;
966.  		} else if (IS_TREE(levl[nix][niy].typ)) {
967.  		    if (!(mw_tmp = MON_WEP(mtmp)) || !is_axe(mw_tmp))
968.  			mtmp->weapon_check = NEED_AXE;
969.  		} else if (!(mw_tmp = MON_WEP(mtmp)) || !is_pick(mw_tmp)) {
970.  		    mtmp->weapon_check = NEED_PICK_AXE;
971.  		}
972.  		if (mtmp->weapon_check >= NEED_PICK_AXE && mon_wield_item(mtmp))
973.  		    return(3);
974.  	    }
975.  	    /* If ALLOW_U is set, either it's trying to attack you, or it
976.  	     * thinks it is.  In either case, attack this spot in preference to
977.  	     * all others.
978.  	     */
979.  	/* Actually, this whole section of code doesn't work as you'd expect.
980.  	 * Most attacks are handled in dochug().  It calls distfleeck(), which
981.  	 * among other things sets nearby if the monster is near you--and if
982.  	 * nearby is set, we never call m_move unless it is a special case
983.  	 * (confused, stun, etc.)  The effect is that this ALLOW_U (and
984.  	 * mfndpos) has no effect for normal attacks, though it lets a confused
985.  	 * monster attack you by accident.
986.  	 */
987.  	    if(info[chi] & ALLOW_U) {
988.  		nix = mtmp->mux;
989.  		niy = mtmp->muy;
990.  	    }
991.  	    if (nix == u.ux && niy == u.uy) {
992.  		mtmp->mux = u.ux;
993.  		mtmp->muy = u.uy;
994.  		return(0);
995.  	    }
996.  	    /* The monster may attack another based on 1 of 2 conditions:
997.  	     * 1 - It may be confused.
998.  	     * 2 - It may mistake the monster for your (displaced) image.
999.  	     * Pets get taken care of above and shouldn't reach this code.
1000. 	     * Conflict gets handled even farther away (movemon()).
1001. 	     */
1002. 	    if((info[chi] & ALLOW_M) ||
1003. 		   (nix == mtmp->mux && niy == mtmp->muy)) {
1004. 		struct monst *mtmp2;
1005. 		int mstatus;
1006. 		mtmp2 = m_at(nix,niy);
1007. 
1008. 		notonhead = mtmp2 && (nix != mtmp2->mx || niy != mtmp2->my);
1009. 		/* note: mstatus returns 0 if mtmp2 is nonexistent */
1010. 		mstatus = mattackm(mtmp, mtmp2);
1011. 
1012. 		if (mstatus & MM_AGR_DIED)		/* aggressor died */
1013. 		    return 2;
1014. 
1015. 		if ((mstatus & MM_HIT) && !(mstatus & MM_DEF_DIED)  &&
1016. 		    rn2(4) && mtmp2->movement >= NORMAL_SPEED) {
1017. 		    mtmp2->movement -= NORMAL_SPEED;
1018. 		    notonhead = 0;
1019. 		    mstatus = mattackm(mtmp2, mtmp);	/* return attack */
1020. 		    if (mstatus & MM_DEF_DIED)
1021. 			return 2;
1022. 		}
1023. 		return 3;
1024. 	    }
1025. 
1026. 	    if (!m_in_out_region(mtmp,nix,niy))
1027. 	        return 3;
1028. 	    remove_monster(omx, omy);
1029. 	    place_monster(mtmp, nix, niy);
1030. 	    for(j = MTSZ-1; j > 0; j--)
1031. 		mtmp->mtrack[j] = mtmp->mtrack[j-1];
1032. 	    mtmp->mtrack[0].x = omx;
1033. 	    mtmp->mtrack[0].y = omy;
1034. 	    /* Place a segment at the old position. */
1035. 	    if (mtmp->wormno) worm_move(mtmp);
1036. 	} else {
1037. 	    if(is_unicorn(ptr) && rn2(2) && !tele_restrict(mtmp)) {
1038. 		(void) rloc(mtmp, FALSE);
1039. 		return(1);
1040. 	    }
1041. 	    if(mtmp->wormno) worm_nomove(mtmp);
1042. 	}
1043. postmov:
1044. 	if(mmoved == 1 || mmoved == 3) {
1045. 	    boolean canseeit = cansee(mtmp->mx, mtmp->my);
1046. 
1047. 	    if(mmoved == 1) {
1048. 		newsym(omx,omy);		/* update the old position */
1049. 		if (mintrap(mtmp) >= 2) {
1050. 		    if(mtmp->mx) newsym(mtmp->mx,mtmp->my);
1051. 		    return(2);	/* it died */
1052. 		}
1053. 		ptr = mtmp->data;
1054. 
1055. 		/* open a door, or crash through it, if you can */
1056. 		if(IS_DOOR(levl[mtmp->mx][mtmp->my].typ)
1057. 			&& !passes_walls(ptr) /* doesn't need to open doors */
1058. 			&& !can_tunnel /* taken care of below */
1059. 		      ) {
1060. 		    struct rm *here = &levl[mtmp->mx][mtmp->my];
1061. 		    boolean btrapped = (here->doormask & D_TRAPPED);
1062. 
1063. 		    if(here->doormask & (D_LOCKED|D_CLOSED) && amorphous(ptr)) {
1064. 			if (flags.verbose && canseemon(mtmp))
1065. 			    pline("%s %s under the door.", Monnam(mtmp),
1066. 				  (ptr == &mons[PM_FOG_CLOUD] ||
1067. 				   ptr == &mons[PM_YELLOW_LIGHT])
1068. 				  ? "flows" : "oozes");
1069. 		    } else if(here->doormask & D_LOCKED && can_unlock) {
1070. 			if(btrapped) {
1071. 			    here->doormask = D_NODOOR;
1072. 			    newsym(mtmp->mx, mtmp->my);
1073. 			    unblock_point(mtmp->mx,mtmp->my); /* vision */
1074. 			    if(mb_trapped(mtmp)) return(2);
1075. 			} else {
1076. 			    if (flags.verbose) {
1077. 				if (canseeit)
1078. 				   You("see a door unlock and open.");
1079. 				else if (flags.soundok)
1080. 				   You_hear("a door unlock and open.");
1081. 			    }
1082. 			    here->doormask = D_ISOPEN;
1083. 			    /* newsym(mtmp->mx, mtmp->my); */
1084. 			    unblock_point(mtmp->mx,mtmp->my); /* vision */
1085. 			}
1086. 		    } else if (here->doormask == D_CLOSED && can_open) {
1087. 			if(btrapped) {
1088. 			    here->doormask = D_NODOOR;
1089. 			    newsym(mtmp->mx, mtmp->my);
1090. 			    unblock_point(mtmp->mx,mtmp->my); /* vision */
1091. 			    if(mb_trapped(mtmp)) return(2);
1092. 			} else {
1093. 			    if (flags.verbose) {
1094. 				if (canseeit)
1095. 				     You("see a door open.");
1096. 				else if (flags.soundok)
1097. 				     You_hear("a door open.");
1098. 			    }
1099. 			    here->doormask = D_ISOPEN;
1100. 			    /* newsym(mtmp->mx, mtmp->my); */  /* done below */
1101. 			    unblock_point(mtmp->mx,mtmp->my); /* vision */
1102. 			}
1103. 		    } else if (here->doormask & (D_LOCKED|D_CLOSED)) {
1104. 			/* mfndpos guarantees this must be a doorbuster */
1105. 			if(btrapped) {
1106. 			    here->doormask = D_NODOOR;
1107. 			    newsym(mtmp->mx, mtmp->my);
1108. 			    unblock_point(mtmp->mx,mtmp->my); /* vision */
1109. 			    if(mb_trapped(mtmp)) return(2);
1110. 			} else {
1111. 			    if (flags.verbose) {
1112. 				if (canseeit)
1113. 				    You("see a door crash open.");
1114. 				else if (flags.soundok)
1115. 				    You_hear("a door crash open.");
1116. 			    }
1117. 			    if (here->doormask & D_LOCKED && !rn2(2))
1118. 				    here->doormask = D_NODOOR;
1119. 			    else here->doormask = D_BROKEN;
1120. 			    /* newsym(mtmp->mx, mtmp->my); */ /* done below */
1121. 			    unblock_point(mtmp->mx,mtmp->my); /* vision */
1122. 			}
1123. 			/* if it's a shop door, schedule repair */
1124. 			if (*in_rooms(mtmp->mx, mtmp->my, SHOPBASE))
1125. 			    add_damage(mtmp->mx, mtmp->my, 0L);
1126. 		    }
1127. 		} else if (levl[mtmp->mx][mtmp->my].typ == IRONBARS) {
1128. 			if (flags.verbose && canseemon(mtmp))
1129. 			    Norep("%s %s %s the iron bars.", Monnam(mtmp),
1130. 				  /* pluralization fakes verb conjugation */
1131. 				  makeplural(locomotion(ptr, "pass")),
1132. 				  passes_walls(ptr) ? "through" : "between");
1133. 		}
1134. 
1135. 		/* possibly dig */
1136. 		if (can_tunnel && mdig_tunnel(mtmp))
1137. 			return(2);  /* mon died (position already updated) */
1138. 
1139. 		/* set also in domove(), hack.c */
1140. 		if (u.uswallow && mtmp == u.ustuck &&
1141. 					(mtmp->mx != omx || mtmp->my != omy)) {
1142. 		    /* If the monster moved, then update */
1143. 		    u.ux0 = u.ux;
1144. 		    u.uy0 = u.uy;
1145. 		    u.ux = mtmp->mx;
1146. 		    u.uy = mtmp->my;
1147. 		    swallowed(0);
1148. 		} else
1149. 		newsym(mtmp->mx,mtmp->my);
1150. 	    }
1151. 	    if(OBJ_AT(mtmp->mx, mtmp->my) && mtmp->mcanmove) {
1152. 		/* recompute the likes tests, in case we polymorphed
1153. 		 * or if the "likegold" case got taken above */
1154. 		if (setlikes) {
1155. 		    register int pctload = (curr_mon_load(mtmp) * 100) /
1156. 			max_mon_load(mtmp);
1157. 
1158. 		    /* look for gold or jewels nearby */
1159. 		    likegold = (likes_gold(ptr) && pctload < 95);
1160. 		    likegems = (likes_gems(ptr) && pctload < 85);
1161. 		    uses_items = (!mindless(ptr) && !is_animal(ptr)
1162. 				  && pctload < 75);
1163. 		    likeobjs = (likes_objs(ptr) && pctload < 75);
1164. 		    likemagic = (likes_magic(ptr) && pctload < 85);
1165. 		    likerock = (throws_rocks(ptr) && pctload < 50 &&
1166. 				!In_sokoban(&u.uz));
1167. 		    conceals = hides_under(ptr);
1168. 		}
1169. 
1170. 		/* Maybe a rock mole just ate some metal object */
1171. 		if (metallivorous(ptr)) {
1172. 		    if (meatmetal(mtmp) == 2) return 2;	/* it died */
1173. 		}
1174. 
1175. 		if(g_at(mtmp->mx,mtmp->my) && likegold) mpickgold(mtmp);
1176. 
1177. 		/* Maybe a cube ate just about anything */
1178. 		if (ptr == &mons[PM_GELATINOUS_CUBE]) {
1179. 		    if (meatobj(mtmp) == 2) return 2;	/* it died */
1180. 		}
1181. 
1182. 		if(!*in_rooms(mtmp->mx, mtmp->my, SHOPBASE) || !rn2(25)) {
1183. 		    boolean picked = FALSE;
1184. 
1185. 		    if(likeobjs) picked |= mpickstuff(mtmp, practical);
1186. 		    if(likemagic) picked |= mpickstuff(mtmp, magical);
1187. 		    if(likerock) picked |= mpickstuff(mtmp, boulder_class);
1188. 		    if(likegems) picked |= mpickstuff(mtmp, gem_class);
1189. 		    if(uses_items) picked |= mpickstuff(mtmp, (char *)0);
1190. 		    if(picked) mmoved = 3;
1191. 		}
1192. 
1193. 		if(mtmp->minvis) {
1194. 		    newsym(mtmp->mx, mtmp->my);
1195. 		    if (mtmp->wormno) see_wsegs(mtmp);
1196. 		}
1197. 	    }
1198. 
1199. 	    if(hides_under(ptr) || ptr->mlet == S_EEL) {
1200. 		/* Always set--or reset--mundetected if it's already hidden
1201. 		   (just in case the object it was hiding under went away);
1202. 		   usually set mundetected unless monster can't move.  */
1203. 		if (mtmp->mundetected ||
1204. 			(mtmp->mcanmove && !mtmp->msleeping && rn2(5)))
1205. 		    mtmp->mundetected = (ptr->mlet != S_EEL) ?
1206. 			OBJ_AT(mtmp->mx, mtmp->my) :
1207. 			(is_pool(mtmp->mx, mtmp->my) && !Is_waterlevel(&u.uz));
1208. 		newsym(mtmp->mx, mtmp->my);
1209. 	    }
1210. 	    if (mtmp->isshk) {
1211. 		after_shk_move(mtmp);
1212. 	    }
1213. 	}
1214. 	return(mmoved);
1215. }
1216. 
1217. #endif /* OVL0 */
1218. #ifdef OVL2
1219. 

closed_door Edit

1220. boolean
1221. closed_door(x, y)
1222. register int x, y;
1223. {
1224. 	return((boolean)(IS_DOOR(levl[x][y].typ) &&
1225. 			(levl[x][y].doormask & (D_LOCKED | D_CLOSED))));
1226. }
1227. 

accessible Edit

1228. boolean
1229. accessible(x, y)
1230. register int x, y;
1231. {
1232. 	return((boolean)(ACCESSIBLE(levl[x][y].typ) && !closed_door(x, y)));
1233. }
1234. 
1235. #endif /* OVL2 */
1236. #ifdef OVL0
1237. 

set_apparxy Edit

1238. /* decide where the monster thinks you are standing */
1239. void
1240. set_apparxy(mtmp)
1241. register struct monst *mtmp;
1242. {
1243. 	boolean notseen, gotu;
1244. 	register int disp, mx = mtmp->mux, my = mtmp->muy;
1245. #ifdef GOLDOBJ
1246. 	long umoney = money_cnt(invent);
1247. #endif
1248. 
1249. 	/*
1250. 	 * do cheapest and/or most likely tests first
1251. 	 */
1252. 
1253. 	/* pet knows your smell; grabber still has hold of you */
1254. 	if (mtmp->mtame || mtmp == u.ustuck) goto found_you;
1255. 
1256. 	/* monsters which know where you are don't suddenly forget,
1257. 	   if you haven't moved away */
1258. 	if (mx == u.ux && my == u.uy) goto found_you;
1259. 
1260. 	notseen = (!mtmp->mcansee || (Invis && !perceives(mtmp->data)));
1261. 	/* add cases as required.  eg. Displacement ... */
1262. 	if (notseen || Underwater) {
1263. 	    /* Xorns can smell valuable metal like gold, treat as seen */
1264. 	    if ((mtmp->data == &mons[PM_XORN]) &&
1265. #ifndef GOLDOBJ
1266. 			u.ugold
1267. #else
1268. 			umoney
1269. #endif
1270. 			&& !Underwater)
1271. 		disp = 0;
1272. 	    else
1273. 		disp = 1;
1274. 	} else if (Displaced) {
1275. 	    disp = couldsee(mx, my) ? 2 : 1;
1276. 	} else disp = 0;
1277. 	if (!disp) goto found_you;
1278. 
1279. 	/* without something like the following, invis. and displ.
1280. 	   are too powerful */
1281. 	gotu = notseen ? !rn2(3) : Displaced ? !rn2(4) : FALSE;
1282. 
1283. #if 0		/* this never worked as intended & isn't needed anyway */
1284. 	/* If invis but not displaced, staying around gets you 'discovered' */
1285. 	gotu |= (!Displaced && u.dx == 0 && u.dy == 0);
1286. #endif
1287. 
1288. 	if (!gotu) {
1289. 	    register int try_cnt = 0;
1290. 	    do {
1291. 		if (++try_cnt > 200) goto found_you;		/* punt */
1292. 		mx = u.ux - disp + rn2(2*disp+1);
1293. 		my = u.uy - disp + rn2(2*disp+1);
1294. 	    } while (!isok(mx,my)
1295. 		  || (disp != 2 && mx == mtmp->mx && my == mtmp->my)
1296. 		  || ((mx != u.ux || my != u.uy) &&
1297. 		      !passes_walls(mtmp->data) &&
1298. 		      (!ACCESSIBLE(levl[mx][my].typ) ||
1299. 		       (closed_door(mx, my) && !can_ooze(mtmp))))
1300. 		  || !couldsee(mx, my));
1301. 	} else {
1302. found_you:
1303. 	    mx = u.ux;
1304. 	    my = u.uy;
1305. 	}
1306. 
1307. 	mtmp->mux = mx;
1308. 	mtmp->muy = my;
1309. }
1310. 

can_ooze Edit

1311. boolean
1312. can_ooze(mtmp)
1313. struct monst *mtmp;
1314. {
1315. 	struct obj *chain, *obj;
1316. 
1317. 	if (!amorphous(mtmp->data)) return FALSE;
1318. 	if (mtmp == &youmonst) {
1319. #ifndef GOLDOBJ
1320. 		if (u.ugold > 100L) return FALSE;
1321. #endif
1322. 		chain = invent;
1323. 	} else {
1324. #ifndef GOLDOBJ
1325. 		if (mtmp->mgold > 100L) return FALSE;
1326. #endif
1327. 		chain = mtmp->minvent;
1328. 	}
1329. 	for (obj = chain; obj; obj = obj->nobj) {
1330. 		int typ = obj->otyp;
1331. 
1332. #ifdef GOLDOBJ
1333.                 if (typ == COIN_CLASS && obj->quan > 100L) return FALSE;
1334. #endif
1335. 		if (obj->oclass != GEM_CLASS &&
1336. 		    !(typ >= ARROW && typ <= BOOMERANG) &&
1337. 		    !(typ >= DAGGER && typ <= CRYSKNIFE) &&
1338. 		    typ != SLING &&
1339. 		    !is_cloak(obj) && typ != FEDORA &&
1340. 		    !is_gloves(obj) && typ != LEATHER_JACKET &&
1341. #ifdef TOURIST
1342. 		    typ != CREDIT_CARD && !is_shirt(obj) &&
1343. #endif
1344. 		    !(typ == CORPSE && verysmall(&mons[obj->corpsenm])) &&
1345. 		    typ != FORTUNE_COOKIE && typ != CANDY_BAR &&
1346. 		    typ != PANCAKE && typ != LEMBAS_WAFER &&
1347. 		    typ != LUMP_OF_ROYAL_JELLY &&
1348. 		    obj->oclass != AMULET_CLASS &&
1349. 		    obj->oclass != RING_CLASS &&
1350. #ifdef WIZARD
1351. 		    obj->oclass != VENOM_CLASS &&
1352. #endif
1353. 		    typ != SACK && typ != BAG_OF_HOLDING &&
1354. 		    typ != BAG_OF_TRICKS && !Is_candle(obj) &&
1355. 		    typ != OILSKIN_SACK && typ != LEASH &&
1356. 		    typ != STETHOSCOPE && typ != BLINDFOLD && typ != TOWEL &&
1357. 		    typ != TIN_WHISTLE && typ != MAGIC_WHISTLE &&
1358. 		    typ != MAGIC_MARKER && typ != TIN_OPENER &&
1359. 		    typ != SKELETON_KEY && typ != LOCK_PICK
1360. 		) return FALSE;
1361. 		if (Is_container(obj) && obj->cobj) return FALSE;
1362. 		    
1363. 	}
1364. 	return TRUE;
1365. }
1366. 
1367. #endif /* OVL0 */
1368. 
1369. /*monmove.c*/

Around Wikia's network

Random Wiki