Fandom

Wikihack

Source:NetHack 3.0.0/monmove.c

2,034pages on
this wiki
Add New Page
Talk0

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.

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

Warning! This is the source code from an old release. For the latest release, see Source code

The NetHack General Public License applies to screenshots, source code and other content from NetHack.
1.    /*	SCCS Id: @(#)monmove.c	3.0	88/11/10
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.    #ifdef NAMED_ITEMS
8.    #  include "artifact.h"
9.    #endif
10.   
11.   static boolean /* TRUE : mtmp died */
12.   mb_trapped(mtmp)
13.   register struct monst *mtmp;
14.   {
15.   	if (flags.verbose) {
16.   	    if (cansee(mtmp->mx, mtmp->my))
17.   	       pline("KABOOM!!  You see a door explode.");
18.   	    else if (flags.soundok)
19.                  You("hear a distant explosion.");
20.   	}
21.   	mtmp->mstun = 1;
22.   	mtmp->mhp -= rnd(15);
23.   	if(mtmp->mhp <= 0) {
24.   		mondied(mtmp);
25.   		return(TRUE);
26.   	}
27.   	return(FALSE);
28.   }
29.   
30.   boolean  
31.   mdig_tunnel(mtmp)  /* FALSE: monster died */
32.   register struct monst *mtmp;
33.   {
34.   	register struct rm *here;
35.   	register int pile = rnd(12);
36.   	boolean canseeit = cansee(mtmp->mx, mtmp->my);
37.   	here = &levl[mtmp->mx][mtmp->my];
38.   
39.   	if(IS_ROCK(here->typ)) {
40.   	    /* Just ate something. */
41.   	    if(here->typ == STONE) here->typ = CORR;
42.   	    else if(IS_WALL(here->typ) &&
43.   			!(here->diggable & W_NONDIGGABLE)) {
44.   		if(flags.soundok && flags.verbose && !rn2(5))
45.   		       You("hear the sound of crashing rock.");
46.   		here->typ = DOOR;
47.   		here->doormask = D_NODOOR;
48.   	    }
49.   	}
50.   	/* Eats away door if present & closed or locked */
51.   	else if(IS_DOOR(here->typ) &&
52.   		(here->doormask & (D_LOCKED | D_CLOSED))) {
53.   		if(here->doormask & D_TRAPPED) {
54.   		    here->doormask = D_NODOOR;
55.   		    if(mb_trapped(mtmp)) return(FALSE);
56.   		} else {
57.   		    if(!rn2(3) && flags.verbose) /* not too often.. */
58.   		        You("feel an unexpected draft of air.");
59.   		    here->doormask = D_BROKEN;
60.   		}
61.   	    }
62.   	else pile = 12; /* it doesn't leave rocks if it didn't dig */
63.   
64.   	/* Left behind a pile? */
65.   	if(pile < 5) {
66.   	    if(pile == 1)
67.   		(void) mksobj_at(BOULDER, mtmp->mx, mtmp->my);
68.   	    else
69.   		(void) mksobj_at(ROCK, mtmp->mx, mtmp->my);
70.   	}
71.   	if(canseeit) {
72.   	    here->seen = TRUE;
73.   	    newsym(mtmp->mx,mtmp->my);
74.   	} else
75.   	    mnewsym(mtmp->mx,mtmp->my);
76.   	return(TRUE);
77.   }
78.   
79.   int
80.   dochugw(mtmp)
81.   	register struct monst *mtmp;
82.   {
83.   	register int x = mtmp->mx;
84.   	register int y = mtmp->my;
85.   	register int rd = dochug(mtmp);
86.   	register int dd;
87.   
88.   	if(!rd && !mtmp->mpeaceful &&
89.   			(dd = dist(mtmp->mx,mtmp->my)) < dist(x,y) &&
90.   			dd < 100 && !canseemon(mtmp)) {
91.   #ifdef NAMED_ITEMS
92.   	    /* Note: this assumes we only want to warn against the monster which
93.   	     * the weapon does extra damage to, as there is no "monster which
94.   	     * the weapon warns against" field.
95.   	     */
96.   		if(spec_ability(uwep,SPFX_WARN) && spec_dbon(uwep,mtmp->data,1))
97.   			warnlevel = 100;
98.   		else
99.   #endif
100.  		if (Warning && mtmp->m_lev > warnlevel)
101.  			warnlevel = mtmp->m_lev;
102.  	}
103.  	return(rd);
104.  }
105.  
106.  boolean
107.  onscary(x, y, mtmp)
108.  int x, y;
109.  struct monst *mtmp;
110.  {
111.  	if (mtmp->isshk || mtmp->isgd || mtmp->iswiz || !mtmp->mcansee ||
112.  			mtmp->data->mlet == S_HUMAN || mtmp->mpeaceful)
113.  		return(FALSE);
114.  	return(
115.  #ifdef ELBERETH
116.  		   sengr_at("Elbereth", x, y) ||
117.  #endif
118.  		    sobj_at(SCR_SCARE_MONSTER, x, y) != (struct obj *)0);
119.  }
120.  
121.  /* returns 1 if monster died moving, 0 otherwise */
122.  int
123.  dochug(mtmp)
124.  	register struct monst *mtmp;
125.  {
126.  	register struct permonst *mdat = mtmp->data;
127.  	register int tmp=0, inrange, nearby, scared, seescaryx,
128.  		seescaryy;
129.  
130.  /*	Pre-movement adjustments	*/
131.  
132.  	if(mtmp->cham && !rn2(6))	/* polymorph chameleons */
133.  	    (void) newcham(mtmp, (struct permonst *)0);
134.  
135.  	/* regenerate monsters */
136.  	if((!(moves%20) || regenerates(mdat)) && mtmp->mhp < mtmp->mhpmax)
137.  		mtmp->mhp++;
138.  	if(mtmp->mspec_used) mtmp->mspec_used--;
139.  
140.  	/* polymorph lycanthropes */
141.  	were_change(mtmp);
142.  
143.  	if(mtmp->mfroz) {
144.  		if (Hallucination) pmon(mtmp);
145.  		return(0);	/* frozen monsters don't do anything */
146.  	}
147.  
148.  	if(mtmp->msleep)	/* there is a chance we will wake it */
149.  		if(!disturb(mtmp)) return(0);
150.  
151.  	/* not frozen or sleeping: wipe out texts written in the dust */
152.  	wipe_engr_at(mtmp->mx, mtmp->my, 1);
153.  
154.  	/* confused monsters get unconfused with small probability */
155.  	if(mtmp->mconf && !rn2(50)) mtmp->mconf = 0;
156.  
157.  	/* stunned monsters get un-stunned with larger probability */
158.  	if(mtmp->mstun && !rn2(10)) mtmp->mstun = 0;
159.  
160.  	/* some monsters teleport */
161.  	if(mtmp->mflee && !rn2(40) && can_teleport(mdat) && !mtmp->iswiz) {
162.  		rloc(mtmp);
163.  		return(0);
164.  	}
165.  	if(mdat->mmove < rnd(6)) return(0);
166.  
167.  	/* fleeing monsters might regain courage */
168.  	if(mtmp->mflee && !mtmp->mfleetim
169.  	   && mtmp->mhp == mtmp->mhpmax && !rn2(25)) mtmp->mflee = 0;
170.  
171.  	set_apparxy(mtmp);
172.  	/* Must be done after you move and before the monster does.  The
173.  	 * set_apparxy() call in m_move() doesn't suffice since the variables
174.  	 * inrange, etc... all depend on stuff set by set_apparxy().
175.  	 */
176.  
177.  	/* The Wizard's prime directive */
178.  	/* may teleport, so do it before inrange is set */
179.  	if(mtmp->iswiz)
180.  		(void) wiz_get_amulet(mtmp);
181.  
182.  	inrange = (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <=
183.  							(BOLT_LIM * BOLT_LIM));
184.  	nearby = (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) < 3);
185.  	/* Note: if your image is displaced, the monster sees the Elbereth
186.  	 * at your displaced position, thus never attacking your displaced
187.  	 * position, but possibly attacking you by accident.  If you are
188.  	 * invisible, it sees the Elbereth at your real position, thus never
189.  	 * running into you by accident but possibly attacking the spot
190.  	 * where it guesses you are.
191.  	 */
192.  	if (Invis && !perceives(mdat)) {
193.  		seescaryx = mtmp->mux;
194.  		seescaryy = mtmp->muy;
195.  	} else {
196.  		seescaryx = u.ux;
197.  		seescaryy = u.uy;
198.  	}
199.  	scared = (nearby && onscary(seescaryx, seescaryy, mtmp));
200.  
201.  	if(scared && !mtmp->mflee) {
202.  #ifdef POLYSELF
203.  		if (!sticks(uasmon))
204.  #endif
205.  			unstuck(mtmp);	/* monster lets go when fleeing */
206.  		mtmp->mflee = 1;
207.  		mtmp->mfleetim = (rn2(7) ? rnd(10) : rnd(100));
208.  	}
209.  
210.  #ifdef HARD	/* Demonic Blackmail!!! */
211.  	if(nearby && is_demon(mdat) && mtmp->mpeaceful && !mtmp->mtame) {
212.  		if (mtmp->mux != u.ux || mtmp->muy != u.uy) {
213.  			pline("%s whispers something to thin air.",
214.  			    cansee(mtmp->mux, mtmp->muy) ? Monnam(mtmp) : "It");
215.  #ifdef POLYSELF
216.  			if (is_demon(uasmon)) rloc(mtmp);
217.  			  /* "Good hunting, brother" */
218.  			else
219.  #endif
220.  			if (is_lord(mdat) || is_prince(mdat)) {
221.  			  /* use is_lord instead of is_dlord */
222.  			    mtmp->minvis = 0;
223.  			    /* Why?  For the same reason in real demon talk */
224.  			    pline("%s gets angry.", Xmonnam(mtmp));
225.  			    mtmp->mpeaceful = 0;
226.  			    /* since no way is an image going to pay it off */
227.  			}
228.  		} else if(demon_talk(mtmp)) return(1);	/* you paid it off */
229.  	}
230.  #endif
231.  
232.  /*	Now the actual movement phase	*/
233.  
234.  	if(!nearby || mtmp->mflee || scared ||
235.  	   mtmp->mconf || mtmp->mstun || (mtmp->minvis && !rn2(3)) ||
236.  	   (mdat->mlet == S_LEPRECHAUN && !u.ugold && (mtmp->mgold || rn2(2))) ||
237.  	   (is_wanderer(mdat) && !rn2(4)) || (Conflict && !mtmp->iswiz) ||
238.  	   (!mtmp->mcansee && !rn2(4)) || mtmp->mpeaceful) {
239.  
240.  		tmp = m_move(mtmp, 0);
241.  		nearby = (dist(mtmp->mx, mtmp->my) < 3);	/* recalc */
242.  		scared = (nearby && onscary(seescaryx, seescaryy, mtmp));
243.  		switch (tmp) {
244.  
245.  		    case 0:	/* no movement, but it can still attack you */
246.  		    case 3:	/* absolutely no movement */
247.  				/* for pets, case 0 and 3 are equivalent */
248.   			/* During hallucination, monster appearance should
249.   			 * still change - even if it doesn't move.
250.    			 */
251.   			if(Hallucination) pmon(mtmp);
252.   			break;
253.   		    case 1:	/* monster moved */
254.   			if(!nearby && ranged_attk(mdat)) break;
255.   			else if(mdat->mmove <= 12) return(0);
256.   			break;
257.   		    case 2:	/* monster died */
258.   			return(1);
259.   		}
260.  
261.  		inrange = (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <=
262.  							(BOLT_LIM * BOLT_LIM));
263.  		if(scared && !mtmp->mflee) {
264.  			mtmp->mflee = 1;
265.  			mtmp->mfleetim = (rn2(7) ? rnd(10) : rnd(100));
266.  		}
267.  	}
268.  
269.  /*	Now, attack the player if possible - one attack set per monst	*/
270.  
271.  	if(inrange && !noattacks(mdat) &&
272.  	   !mtmp->mpeaceful && !mtmp->mtame && u.uhp > 0 && !scared && tmp != 3)
273.  	    if(mattacku(mtmp)) return(1); /* monster died (e.g. exploded) */
274.  
275.  #ifdef WORM
276.  	if(mtmp->wormno && !mtmp->mtame) wormhit(mtmp);
277.  #endif
278.  
279.  	/* extra movement for fast monsters */
280.  	if(mdat->mmove-12 > rnd(12)) tmp = m_move(mtmp, 1);
281.  	return(tmp == 2);
282.  }
283.  
284.  static const char practical[] = { WEAPON_SYM, GEM_SYM, FOOD_SYM, 0 };
285.  static const char magical[] = {
286.  	AMULET_SYM, POTION_SYM, SCROLL_SYM, WAND_SYM, RING_SYM,
287.  #ifdef SPELLS
288.  	SPBOOK_SYM,
289.  #endif
290.  	0 };
291.  static const char indigestion[] = { BALL_SYM, ROCK_SYM, 0 };
292.  
293.  #ifdef POLYSELF
294.  static boolean
295.  itsstuck(mtmp)
296.  register struct monst *mtmp;
297.  {
298.  	if (sticks(uasmon) && mtmp==u.ustuck && !u.uswallow) {
299.  		kludge("%s cannot escape from you!", Monnam(mtmp));
300.  		return(TRUE);
301.  	}
302.  	return(FALSE);
303.  }
304.  #endif
305.  
306.  int
307.  m_move(mtmp, after)
308.  register struct monst *mtmp;
309.  register int after;
310.  {
311.  	register struct monst *mtmp2;
312.  	register int nx,ny,omx,omy,appr,nearer,cnt,i,j;
313.  	xchar gx,gy,nix,niy,chcnt;
314.  	schar chi;
315.  	boolean likegold=0, likegems=0, likeobjs=0, likemagic=0, conceals=0;
316.  	boolean likerock=0, can_tunnel=0;
317.  	struct permonst *ptr = mtmp->data;
318.  	schar mmoved = 0;	/* not strictly nec.: chi >= 0 will do */
319.  	coord poss[9];
320.  	long info[9];
321.  	long flag;
322.  
323.  	if(mtmp->mtrapped) {
324.  	    i = mintrap(mtmp);
325.  	    if(i == 2) return(2);	/* it died */
326.  	    if(i == 1) return(0);	/* still in trap, so didn't move */
327.  	}
328.  	if(mtmp->mhide &&
329.  	   (levl[mtmp->mx][mtmp->my].omask || levl[mtmp->mx][mtmp->my].gmask) &&
330.  	   rn2(10))
331.  	    return(0);		/* do not leave hiding place */
332.  	if(mtmp->meating) {
333.  	    mtmp->meating--;
334.  	    return(3);			/* still eating */
335.  	}
336.  
337.  	set_apparxy(mtmp);
338.  	/* where does mtmp think you are? */
339.  	/* Not necessary if m_move called from here, but necessary in
340.  	 * other calls of m_move (i.e. leprechauns dodging)
341.  	 */
342.  	can_tunnel = tunnels(ptr) &&
343.  #ifdef REINCARNATION
344.  		     dlevel != rogue_level &&
345.  #endif
346.  		     (!needspick(ptr) || m_carrying(mtmp, PICK_AXE));
347.  #ifdef WORM
348.  	if(mtmp->wormno) goto not_special;
349.  #endif
350.  	/* my dog gets a special treatment */
351.  	if(mtmp->mtame) return( dog_move(mtmp, after) );
352.  
353.  	/* likewise for shopkeeper */
354.  	if(mtmp->isshk) {
355.  	    mmoved = shk_move(mtmp);
356.  	    if(mmoved == -2) return(2);
357.  	    if(mmoved >= 0) goto postmov;
358.  	    mmoved = 0;		/* follow player outside shop */
359.  	}
360.  
361.  	/* and for the guard */
362.  	if(mtmp->isgd) {
363.  	    mmoved = gd_move();
364.  	    goto postmov;
365.  	}
366.  
367.  	/* and the wiz already got special treatment */
368.  	if(mtmp->iswiz) {
369.  	    mmoved = 0;
370.  	    goto postmov;
371.  	}
372.  #if defined(ALTARS) && defined(THEOLOGY)
373.  	/* and for the priest */
374.  	if(mtmp->ispriest) {
375.  	    mmoved = pri_move(mtmp);
376.  	    if(mmoved == -2) return(2);
377.  	    if(mmoved >= 0) goto postmov;
378.  	    mmoved = 0;
379.  	}
380.  #endif
381.  #ifdef MAIL
382.  	if(ptr == &mons[PM_MAIL_DAEMON]) {
383.  	    if(flags.soundok && canseemon(mtmp))
384.  		pline("\"I'm late!\"");
385.  	    mongone(mtmp);
386.  	    return(2);	    
387.  	}
388.  #endif
389.  
390.  	/* teleport if that lies in our nature */
391.  	if(ptr == &mons[PM_TENGU] && !rn2(5)) {
392.  	    if(mtmp->mhp < 7 || mtmp->mpeaceful || rn2(2))
393.  		rloc(mtmp);
394.  	    else
395.  		mnexto(mtmp);
396.  	    mmoved = 1;
397.  	    goto postmov;
398.  	}
399.  #ifdef WORM
400.  not_special:
401.  #endif
402.  	if(!mtmp->mflee && u.uswallow && u.ustuck != mtmp) return(1);
403.  	appr = 1;
404.  	if(mtmp->mflee) appr = -1;
405.  	if(mtmp->mconf || (Invis && !perceives(ptr)) ||  !mtmp->mcansee ||
406.  	   (mtmp->mpeaceful && !mtmp->isshk) ||	/* allow shks to follow */
407.  	   ((ptr->mlet == S_STALKER || ptr->mlet == S_BAT ||
408.  	     ptr->mlet == S_YLIGHT) && !rn2(3)))
409.  	    appr = 0;
410.  	omx = mtmp->mx;
411.  	omy = mtmp->my;
412.  	gx = mtmp->mux;
413.  	gy = mtmp->muy;
414.  	if(ptr == &mons[PM_LEPRECHAUN] && appr == 1 && mtmp->mgold > u.ugold)
415.  	    appr = -1;
416.  
417.  	if(can_track(ptr)) {
418.  	    register coord *cp;
419.  	    schar mroom;
420.  
421.  	    mroom = inroom(omx,omy);
422.  	    if(mroom < 0 || mroom != inroom(u.ux,u.uy)){
423.  		cp = gettrack(omx,omy);
424.  		if(cp){
425.  		    gx = cp->x;
426.  		    gy = cp->y;
427.  		}
428.  	    }
429.  	}
430.  
431.  #ifdef REINCARNATION
432.  	if (dlevel != rogue_level)
433.  #endif
434.  	{
435.  		register int pctload = (curr_mon_load(mtmp) * 100) /
436.  			max_mon_load(mtmp);
437.  
438.  		/* look for gold or jewels nearby */
439.  		likegold = (likes_gold(ptr) && pctload < 95);
440.  		likegems = (likes_gems(ptr) && pctload < 85);
441.  		likeobjs = (likes_objs(ptr) && pctload < 75);
442.  		likemagic = (likes_magic(ptr) && pctload < 85);
443.  		likerock = (throws_rocks(ptr) && pctload < 50);
444.  		conceals = hides_under(ptr);
445.  	}
446.  
447.  #define	SRCHRADIUS	25
448.  
449.        { xchar mind = SRCHRADIUS;		/* not too far away */
450.  	register int dd;
451.  
452.  	/* cut down the search radius if it thinks character is closer. */
453.  	if(dist2(mtmp->mux, mtmp->muy, omx, omy) < SRCHRADIUS &&
454.  	    !mtmp->mtame && !mtmp->mpeaceful)	 mind /= 2;
455.  
456.  	if(likegold){
457.  	    register struct gold *gold;
458.  
459.  	    for(gold = fgold; gold; gold = gold->ngold)
460.  		if((dd = dist2(omx,omy,gold->gx,gold->gy)) < mind){
461.  		    mind = dd;
462.  		    gx = gold->gx;
463.  		    gy = gold->gy;
464.  		}
465.  	}
466.  	if((likegems || likeobjs || likemagic || likerock || conceals)
467.  	      && (!in_shop(omx, omy) || (!rn2(25) && !mtmp->isshk))) {
468.  	    register struct obj *otmp;
469.  
470.  	    for(otmp = fobj; otmp; otmp = otmp->nobj)
471.  		if((likeobjs && index(practical, otmp->olet)) ||
472.  		   (likemagic && index(magical, otmp->olet)) ||
473.  		   (likerock && otmp->otyp == BOULDER) ||
474.  		   (likegems && otmp->olet == GEM_SYM &&
475.  			otmp->otyp < LAST_GEM + 5) ||
476.  		   (conceals && !cansee(otmp->ox,otmp->oy)) ||
477.  		   (ptr == &mons[PM_GELATINOUS_CUBE] &&
478.  					!index(indigestion, otmp->olet))
479.  		  ) {
480.  			if(can_carry(mtmp,otmp))
481.  			if(ptr->mlet != S_UNICORN ||
482.  					objects[otmp->otyp].g_val != 0)
483.  			    if((dd = dist2(omx,omy,otmp->ox,otmp->oy)) < mind){
484.  				mind = dd;
485.  				gx = otmp->ox;
486.  				gy = otmp->oy;
487.  			    }
488.  		}
489.  	}
490.  	if(mind < SRCHRADIUS && appr == -1) {
491.  	    if(dist2(omx,omy,mtmp->mux,mtmp->muy) < 10) {
492.  		gx = mtmp->mux;
493.  		gy = mtmp->muy;
494.  	    } else
495.  		appr = 1;
496.  	}
497.        }
498.  	nix = omx;
499.  	niy = omy;
500.  	flag = ALLOW_TRAPS;
501.  	if (mtmp->mpeaceful) flag |= (ALLOW_SANCT | ALLOW_SSM);
502.  	else flag |= ALLOW_U;
503.  	if (ptr->mlet == S_UNICORN) flag |= NOTONL;
504.  	if (passes_walls(ptr)) flag |= (ALLOW_WALL | ALLOW_ROCK);
505.  	if (can_tunnel) flag |= ALLOW_DIG;
506.  	if (is_human(ptr)) flag |= ALLOW_SSM;
507.  	if (is_undead(ptr)) flag |= NOGARLIC;
508.  	if (throws_rocks(ptr)) flag |= ALLOW_ROCK;
509.  	cnt = mfndpos(mtmp, poss, info, flag);
510.  	chcnt = 0;
511.  	chi = -1;
512.  
513.  	for(i=0; i < cnt; i++) {
514.  	    nx = poss[i].x;
515.  	    ny = poss[i].y;
516.  
517.  	    for(j=0; j < MTSZ && j < cnt-1; j++)
518.  		if(nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y)
519.  		    if(rn2(4*(cnt-j))) goto nxti;
520.  
521.  	    nearer = (dist2(nx,ny,gx,gy) < dist2(nix,niy,gx,gy));
522.  
523.  	    if((appr == 1 && nearer) || (appr == -1 && !nearer) ||
524.  		   	!mmoved || (!appr && !rn2(++chcnt))) {
525.  		nix = nx;
526.  		niy = ny;
527.  		chi = i;
528.  		mmoved = 1;
529.  	    }
530.  	nxti:	;
531.  	}
532.  
533.  	if(mmoved) {
534.  #ifdef POLYSELF
535.  	    if (mmoved==1 && (u.ux != nix || u.uy != niy) && itsstuck(mtmp))
536.  		return(3);
537.  #endif
538.  	    if((info[chi] & ALLOW_U) || (nix == u.ux && niy == u.uy)) {
539.  		mtmp->mux = u.ux;
540.  		mtmp->muy = u.uy;
541.  		return(0);
542.  	    }
543.  	    /* The monster may attack another based on 1 of 2 conditions:
544.  	     * 1 - He may be under the "conflict" influence.
545.  	     * 2 - He may mistake the monster for your (displaced) image.
546.  	     * Pets get taken care of above and shouldn't reach this code.
547.  	     */
548.  	    if((info[chi] & ALLOW_M) ||
549.  		   (nix == mtmp->mux && niy == mtmp->muy)) {
550.  		mtmp2 = 
551.  		    (levl[nix][niy].mmask ? m_at(nix,niy) : (struct monst *)0);
552.  		if(mattackm(mtmp, mtmp2) == 1 && rn2(4) &&
553.  			mtmp2->mlstmv != moves && mattackm(mtmp2, mtmp) == 2)
554.  		    return(2);
555.  		return(3);
556.  	    }
557.  #ifdef WORM
558.  	    /* The square now has a worm segment and must keep its mmask */
559.  	    if (!mtmp->wormno)
560.  #endif
561.  		    levl[omx][omy].mmask = 0;
562.  	    levl[nix][niy].mmask = 1;
563.  	    mtmp->mx = nix;
564.  	    mtmp->my = niy;
565.  	    for(j = MTSZ-1; j > 0; j--)
566.  		mtmp->mtrack[j] = mtmp->mtrack[j-1];
567.  	    mtmp->mtrack[0].x = omx;
568.  	    mtmp->mtrack[0].y = omy;
569.  #ifdef WORM
570.  	    if(mtmp->wormno) worm_move(mtmp);
571.  #endif
572.  	} else {
573.  	    if(ptr->mlet == S_UNICORN && rn2(2)) {
574.  		rloc(mtmp);
575.  		return(1);
576.  	    }
577.  #ifdef WORM
578.  	    if(mtmp->wormno) worm_nomove(mtmp);
579.  #endif
580.  	}
581.  postmov:
582.  	if(mmoved == 1) {
583.  	    boolean canseeit = cansee(mtmp->mx, mtmp->my);
584.  	    boolean abstain = (mtmp->mpeaceful && !mtmp->mtame);
585.  
586.  	    if(mintrap(mtmp) == 2) return(2);	/* he died */
587.  
588.  	    /* open a door, or crash through it, if you can */
589.  	    if(IS_DOOR(levl[mtmp->mx][mtmp->my].typ)
590.  		    && !passes_walls(ptr) /* doesn't need to open doors */
591.  	            && !amorphous(ptr) /* ditto */
592.  		    && !can_tunnel /* taken care of below */
593.  		  ) {
594.  		struct rm *here = &levl[mtmp->mx][mtmp->my];
595.  		boolean btrapped = (here->doormask & D_TRAPPED);
596.  
597.  		if(here->doormask & D_LOCKED && mtmp->isshk) {
598.  			/* can't lock out shk */
599.  		    if(btrapped) {
600.  			here->doormask = D_NODOOR;
601.  			if(mb_trapped(mtmp)) return(2);
602.  		    } else {
603.  			if (flags.verbose) {
604.  			    if (canseeit)
605.  			       You("see a door being unlocked and opened.");
606.  			    else if (flags.soundok)
607.  			       You("hear a door being unlocked and opened.");
608.  		        }
609.  		        here->doormask = D_ISOPEN;
610.  		    }
611.  		} else if (here->doormask == D_CLOSED && 
612.  					!nohands(mtmp->data)) {
613.  		    if(btrapped) {
614.  			here->doormask = D_NODOOR;
615.  			if(mb_trapped(mtmp)) return(2);
616.  		    } else {
617.  		        if (flags.verbose) {
618.  			    if (canseeit)
619.  			         You("see a door being opened.");
620.  			    else if (flags.soundok)
621.  			         You("hear the sound of a door opening.");
622.  		        }
623.  		        here->doormask = D_ISOPEN;
624.  		    }
625.  		} else if(here->doormask & (D_LOCKED | D_CLOSED)) {
626.  			/* mfndpos guarantees monster is a giant */
627.  		    if(btrapped) {
628.  			here->doormask = D_NODOOR;
629.  			if(mb_trapped(mtmp)) return(2);
630.  		    } else {
631.  		        if (flags.verbose) {
632.  			    if (canseeit)
633.  			        You("see a door crash open.");
634.  			    else if (flags.soundok)
635.  			        You("hear the sound of a door crashing open.");
636.  		        }
637.  		        if (here->doormask & D_LOCKED && !rn2(2))
638.  			        here->doormask = D_NODOOR;
639.  		        else here->doormask = D_BROKEN;
640.  		    }
641.  		}
642.  	    }
643.  	    /* Maybe a rock mole just ate something? */
644.  	    if(can_tunnel) if(!mdig_tunnel(mtmp)) return(2); /* died? */
645.  
646.  	    if(levl[mtmp->mx][mtmp->my].gmask == 1) {
647.  		/* Maybe a rock mole just ate some gold */
648.  		if(ptr == &mons[PM_ROCK_MOLE]) meatgold(mtmp);
649.  		if(likegold && (!abstain || !rn2(10))) mpickgold(mtmp);
650.  	    }
651.  	    if(levl[mtmp->mx][mtmp->my].omask == 1) {
652.  		/* Maybe a rock mole just ate some metal object */
653.  		if(ptr == &mons[PM_ROCK_MOLE]) meatgold(mtmp);
654.  		/* Maybe a cube ate just about anything */
655.  		if(ptr == &mons[PM_GELATINOUS_CUBE]) meatobj(mtmp);
656.  
657.  		if ((!abstain || !rn2(10)) 
658.  			&& (!in_shop(mtmp->mx, mtmp->my) || !rn2(25))) {
659.  		    if(likeobjs) mpickstuff(mtmp, practical);
660.  		    if(likemagic) mpickstuff(mtmp, magical);
661.  		    if(likerock || likegems) mpickgems(mtmp);
662.  		}
663.  	    }
664.  	    if(mtmp->mhide) mtmp->mundetected = (levl[mtmp->mx][mtmp->my].omask
665.  					|| levl[mtmp->mx][mtmp->my].gmask);
666.  
667.  	    /* set also in domove(), hack.c */
668.  	    if(u.uswallow && mtmp == u.ustuck) {
669.  		u.ux = mtmp->mx;
670.  		u.uy = mtmp->my;
671.  	        if(mtmp->mx != mtmp->mdx || mtmp->my != mtmp->mdy) {
672.  		    swallowed(0);
673.  		    mtmp->mdx = mtmp->mx;
674.  		    mtmp->mdy = mtmp->my;
675.  		}
676.  	    }
677.  	}
678.  	pmon(mtmp);
679.  	return(mmoved);
680.  }
681.  
682.  void
683.  set_apparxy(mtmp)		/* where does mtmp think you are standing? */
684.  	register struct monst *mtmp;
685.  {
686.  #define notseen (Invis && !perceives(mtmp->data))
687.  /*	add cases as required.  eg. Displacement ... */
688.  	register int disp = (notseen ? 1 : Displaced ? 2 : 0);
689.  
690.  /* 	without something like the following, invis. and displ. are too */
691.  /*	powerful. */
692.  	register boolean gotu =
693.  		(notseen ? !rn2(3) : Displaced ? !rn2(4) : FALSE);
694.  
695.  /*	Monsters which know where you are don't suddenly forget, if you
696.  	didn't move away. */
697.  	if (mtmp->mux==u.ux && mtmp->muy==u.uy) gotu = 1;
698.  
699.  /* 	your dog follows your smell */
700.  	if(!disp || mtmp->mtame || gotu ||
701.  /*	If invisible but not displaced, staying around gets you 'discovered' */
702.  	    (!Displaced && u.dx == 0 && u.dy == 0)) {
703.  		mtmp->mux = u.ux;
704.  		mtmp->muy = u.uy;
705.  	}
706.  	else do {
707.  		mtmp->mux = u.ux - disp + rn2(2*disp+1);
708.  		mtmp->muy = u.uy - disp + rn2(2*disp+1);
709.  	} while((mtmp->mux != u.ux || mtmp->muy != u.uy) &&
710.  	       (  (!passes_walls(mtmp->data) &&
711.  		      (!ACCESSIBLE(levl[mtmp->mux][mtmp->muy].typ) ||
712.  		       (IS_DOOR(levl[mtmp->mux][mtmp->muy].typ) &&
713.  			(levl[mtmp->mux][mtmp->muy].doormask & (D_LOCKED | D_CLOSED)) &&
714.  			!amorphous(mtmp->data)
715.  		      ))
716.  		  ) ||
717.  		  (disp==1 && mtmp->mux == mtmp->mx && mtmp->muy == mtmp->my)
718.  	       )
719.  	);
720.  }

Also on Fandom

Random Wiki