Source:NetHack 1.4f/mon.c

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

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

1.   /*	SCCS Id: @(#)mon.c	1.4	87/08/08 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* mon.c - version 1.0.3 */ 4.    5.    #include "hack.h"  6.    #include "mfndpos.h"  7.    extern struct obj *mkobj_at; 8.   extern char *hcolor; 9.   #ifdef KAA 10.  extern boolean	stoned; 11.  extern char mlarge[]; 12.  #endif 13.   14.   int warnlevel;		/* used by movemon and dochugw */ 15.  long lastwarntime; 16.  int lastwarnlev; 17.  char	*warnings[] = {	"white", "pink", "red", "ruby", "purple", "black"  }; 18.   19.   movemon 20.  {  21.   	register struct monst *mtmp; 22.  	register int fr; 23.   24.   	warnlevel = 0; 25.   26.   	while(1) { 27.  		/* find a monster that we haven't treated yet */ 28.  		/* note that mtmp or mtmp->nmon might get killed 29.  		   while mtmp moves, so we cannot just walk down the 30.  		   chain (even new monsters might get created!) */ 31.  		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 32.  			if(mtmp->mlstmv < moves) goto next_mon; 33.  		/* treated all monsters */ 34.  		break; 35.   36.   	next_mon: 37.  		mtmp->mlstmv = moves; 38.   39.   		/* most monsters drown in pools */ 40.  		{ boolean inpool, iseel; 41.   42.   		  inpool = (levl[mtmp->mx][mtmp->my].typ == POOL); 43.  		  iseel = (mtmp->data->mlet == ';'); 44.  		  if(inpool && !iseel) { 45.  			if(cansee(mtmp->mx,mtmp->my)) 46.  			    pline("%s drowns.", Monnam(mtmp)); 47.  			mondead(mtmp); 48.  			continue; 49.  		  }  50.   		/* but eels have a difficult time outside */ 51.  		  if(iseel && !inpool) { 52.  			if(mtmp->mhp > 1) mtmp->mhp--; 53.  			mtmp->mflee = 1; 54.  			mtmp->mfleetim += 2; 55.  		  }  56.   		}  57.   		if(mtmp->mblinded && !--mtmp->mblinded) 58.  			mtmp->mcansee = 1; 59.  		if(mtmp->mfleetim && !--mtmp->mfleetim) 60.  			mtmp->mflee = 0; 61.  #ifdef HARD 62.  		/* unwatched mimics and piercers may hide again  [MRS] */ 63.  		if(restrap(mtmp))	continue; 64.  #endif 65.  		if(mtmp->mimic) continue; 66.  		if(mtmp->mspeed != MSLOW || !(moves%2)){ 67.  			/* continue if the monster died fighting */ 68.  			fr = -1; 69.  			if(Conflict && cansee(mtmp->mx,mtmp->my)  70.   				&& (fr = fightm(mtmp)) == 2) 71.  				continue; 72.  			if(fr<0 && dochugw(mtmp)) 73.  				continue; 74.  		}  75.   		if(mtmp->mspeed == MFAST && dochugw(mtmp)) 76.  			continue; 77.  	}  78.    79.   	warnlevel -= u.ulevel; 80.  	if(warnlevel >= SIZE(warnings)) 81.  		warnlevel = SIZE(warnings)-1; 82.  	if(warnlevel >= 0) 83.  	if(warnlevel > lastwarnlev || moves > lastwarntime + 5){ 84.  	    register char *rr; 85.  	    switch(Warning & (LEFT_RING | RIGHT_RING)){ 86.  	    case LEFT_RING: 87.  		rr = "Your left ring glows"; 88.  		break; 89.  	    case RIGHT_RING: 90.  		rr = "Your right ring glows"; 91.  		break; 92.  	    case LEFT_RING | RIGHT_RING: 93.  		rr = "Both your rings glow"; 94.  		break; 95.  	    default: 96.  		rr = "Your fingertips glow"; 97.  		break; 98.  	    }  99.   	    pline("%s %s!", rr, Hallucination ? hcolor : warnings[warnlevel]); 100. 	    lastwarntime = moves; 101. 	    lastwarnlev = warnlevel; 102. 	}  103.   104.  	dmonsfree;	/* remove all dead monsters */ 105. }  106.   107.  justswld(mtmp,name) 108. register struct monst *mtmp; 109. char *name; 110. {  111.   112.  	mtmp->mx = u.ux; 113. 	mtmp->my = u.uy; 114. 	u.ustuck = mtmp; 115. 	pmon(mtmp); 116. 	kludge("%s swallows you!",name); 117. 	more; 118. 	seeoff(1); 119. 	u.uswallow = 1; 120. 	u.uswldtim = 0; 121. 	swallowed; 122. }  123.   124.  youswld(mtmp,dam,die,name) 125. register struct monst *mtmp; 126. register dam,die; 127. char *name; 128. {  129.  	if(mtmp != u.ustuck) return; 130. 	kludge("%s digests you!",name); 131. 	u.uhp -= dam; 132. 	if(u.uswldtim++ >= die){	/* a3 */ 133. 		pline("It totally digests you!"); 134. 		u.uhp = -1; 135. 	}  136.  	if(u.uhp < 1) done_in_by(mtmp); 137. 	/* flags.botlx = 1;		/* should we show status line ? */ 138.  }  139.   140.  #ifdef ROCKMOLE 141. meatgold(mtmp) register struct monst *mtmp; { 142. register struct gold *gold; 143. register int pile; 144. register struct obj *otmp; 145.        /* Eats gold if it is there */ 146.       while(gold = g_at(mtmp->mx, mtmp->my)){ 147. 	      freegold(gold); 148. 	       /* Left behind a pile? */ 149.  	       pile = rnd(25); 150. 	       if(pile < 3) 151. 		 mksobj_at(ROCK, mtmp->mx, mtmp->my); 152. 	      newsym(mtmp->mx, mtmp->my); 153. 	}  154.         /* Eats armor if it is there */ 155.        otmp = o_at(mtmp->mx,mtmp->my); 156.        if((otmp) && (otmp->otyp >= PLATE_MAIL) && (otmp->otyp <= RING_MAIL)){ 157. 	      freeobj(otmp); 158. 	       /* Left behind a pile? */ 159.  	       pile = rnd(25); 160. 	       if(pile < 3) 161. 		  mksobj_at(ROCK, mtmp->mx, mtmp->my); 162. 	      newsym(mtmp->mx, mtmp->my); 163. 	}  164.  }  165.  #endif /* ROCKMOLE /**/ 166.  167.  mpickgold(mtmp) register struct monst *mtmp; { 168. register struct gold *gold; 169. register struct obj *otmp; 170. 	while(gold = g_at(mtmp->mx, mtmp->my)){ 171. 		mtmp->mgold += gold->amount; 172. 		freegold(gold); 173. 		if(levl[mtmp->mx][mtmp->my].scrsym == GOLD_SYM) 174. 			newsym(mtmp->mx, mtmp->my); 175. 	}  176.  }  177.   178.  /* Now includes giants which pick up enormous rocks. KAA */ 179. mpickgems(mtmp) register struct monst *mtmp; { 180. register struct obj *otmp; 181. 	for(otmp = fobj; otmp; otmp = otmp->nobj) 182. 	  if(otmp->olet ==  183.  #ifdef KAA  184.  			   (mtmp->data->mlet=='9' ? ROCK_SYM : GEM_SYM)) 185. #else 186. 			   GEM_SYM)  187.  #endif  188.  	    if(otmp->ox == mtmp->mx && otmp->oy == mtmp->my)  189.  	      if(mtmp->data->mlet != 'u' || objects[otmp->otyp].g_val != 0){  190.  		freeobj(otmp);  191.  		mpickobj(mtmp, otmp);  192.  #ifndef KAA  193.  		if(levl[mtmp->mx][mtmp->my].scrsym == GEM_SYM)  194.  #endif  195.  			newsym(mtmp->mx, mtmp->my);	/* %% */  196.  		return;	/* pick only one object */  197.  	      }  198.  }  199.   200.  /* return number of acceptable neighbour positions */  201.  mfndpos(mon,poss,info,flag)  202.  register struct monst *mon;  203.  coord poss[9];  204.  long info[9], flag;  205.  {  206.  	register int x,y,nx,ny,cnt = 0,ntyp;  207.  	register struct monst *mtmp;  208.  	int nowtyp;  209.  	boolean pool;  210.   211.  	x = mon->mx;  212.  	y = mon->my;  213.  	nowtyp = levl[x][y].typ;  214.   215.  	pool = (mon->data->mlet == ';');  216.  nexttry:	/* eels prefer the water, but if there is no water nearby, 217. 		   they will crawl over land */ 218. 	if(mon->mconf) { 219. 		flag |= ALLOW_ALL; 220. 		flag &= ~NOTONL; 221. 	}  222.  	for(nx = x-1; nx <= x+1; nx++) for(ny = y-1; ny <= y+1; ny++) 223. 	if(nx != x || ny != y) if(isok(nx,ny)) 224. #ifdef ROCKMOLE 225. 	if(!IS_ROCK(ntyp = levl[nx][ny].typ) || (flag & ALLOW_WALL)) 226. #else 227. 	if(!IS_ROCK(ntyp = levl[nx][ny].typ)) 228. #endif 229. 	if(!(nx != x && ny != y && (nowtyp == DOOR || ntyp == DOOR))) 230. 	if((ntyp == POOL) == pool) { 231. 		info[cnt] = 0; 232. 		if(nx == u.ux && ny == u.uy){ 233. 			if(!(flag & ALLOW_U)) continue; 234. 			info[cnt] = ALLOW_U; 235. 		} else if(mtmp = m_at(nx,ny)){ 236. 			if(!(flag & ALLOW_M)) continue; 237. 			info[cnt] = ALLOW_M; 238. 			if(mtmp->mtame){ 239. 				if(!(flag & ALLOW_TM)) continue; 240. 				info[cnt] |= ALLOW_TM; 241. 			}  242.  		}  243.  		if(sobj_at(CLOVE_OF_GARLIC, nx, ny)) { 244. 			if(flag & NOGARLIC) continue; 245. 			info[cnt] |= NOGARLIC; 246. 		}  247.  		if(sobj_at(SCR_SCARE_MONSTER, nx, ny) ||  248.  		   (!mon->mpeaceful && sengr_at("Elbereth", nx, ny))) { 249. 			if(!(flag & ALLOW_SSM)) continue; 250. 			info[cnt] |= ALLOW_SSM; 251. 		}  252.  		if(sobj_at(ENORMOUS_ROCK, nx, ny)) { 253. 			if(!(flag & ALLOW_ROCK)) continue; 254. 			info[cnt] |= ALLOW_ROCK; 255. 		}  256.  		if(!Invis && online(nx,ny)){ 257. 			if(flag & NOTONL) continue; 258. 			info[cnt] |= NOTONL; 259. 		}  260.  		/* we cannot avoid traps of an unknown kind */ 261. 		{ register struct trap *ttmp = t_at(nx, ny); 262. 		  register long tt; 263. 			if(ttmp) { 264. 				tt = 1L <<" ttmp->ttyp;" 265. 				/* below if added by GAN 02/06/87 to avoid 266. 				 * traps out of range 267. 				 */  268.  				if(!(tt & ALLOW_TRAPS))  { 269. 					impossible("A monster looked at a very strange trap"); 270. 					continue; 271. 				}  272.  				if(mon->mtrapseen & tt){ 273. 					if(!(flag & tt)) continue; 274. 					info[cnt] |= tt; 275. 				}  276.  			}  277.  		}  278.  		poss[cnt].x = nx; 279. 		poss[cnt].y = ny; 280. 		cnt++; 281. 	}  282.  	if(!cnt && pool && nowtyp != POOL) { 283. 		pool = FALSE; 284. 		goto nexttry; 285. 	}  286.  	return(cnt); 287. }  288.   289.  dist(x,y) int x,y; { 290. 	return((x-u.ux)*(x-u.ux) + (y-u.uy)*(y-u.uy)); 291. }  292.   293.  poisoned(string, pname) 294. register char *string, *pname; 295. {  296.  	register i, plural; 297.  298.  	plural = (string[strlen(string) - 1] == 's')? 1 : 0; 299.  	if(Blind) { 300. 		if (plural)	pline("They were poisoned."); 301. 		else		pline("It was poisoned."); 302. 	} else	{ 303. 		if (plural)	pline("The %s were poisoned!", string); 304. 		else		pline("The %s was poisoned!", string); 305. 	}  306.   307.  	if(Poison_resistance) { 308. 		pline("The poison doesn't seem to affect you."); 309. 		return; 310. 	}  311.  	i = rn2(10); 312. 	if(i == 0) { 313. 		u.uhp = -1; 314. 		pline("I am afraid the poison was deadly ..."); 315. 	} else if(i <= 5) { 316. 		losestr(rn1(3,3)); 317. 	} else { 318. 		losehp(rn1(10,6), pname); 319. 	}  320.  	if(u.uhp < 1) { 321. 		killer = pname; 322. 		done("died"); 323. 	}  324.  }  325.   326.  mondead(mtmp) 327. register struct monst *mtmp; 328. {  329.  	relobj(mtmp,1); 330. 	unpmon(mtmp); 331. 	relmon(mtmp); 332. 	unstuck(mtmp); 333. #ifdef KOPS 334.        if(mtmp->data->mlet == 'K') { 335. 	   /* When a Kop dies, he probably comes back. */ 336.  	   register int fate = rnd(3); 337. 	   if(fate == 1) { 338. 	     /* returns near the stairs */ 339. 	     mkmon_at('K',xdnstair,ydnstair); 340. 	   } else if(fate == 2) { 341. 	     /* randomly */ 342. 	     mkmon_at('K',0,0); 343. 	   }  344.         }  345.  #endif 346. 	if(mtmp->isshk) shkdead(mtmp); 347. 	if(mtmp->isgd) gddead; 348. #ifndef NOWORM 349. 	if(mtmp->wormno) wormdead(mtmp); 350. #endif 351. #ifdef HARD 352. 	if(mtmp->data->mlet == '1') wizdead(mtmp); 353. #endif 354. 	monfree(mtmp); 355. }  356.   357.  /* called when monster is moved to larger structure */ 358. replmon(mtmp,mtmp2) 359. register struct monst *mtmp, *mtmp2; 360. {  361.  	relmon(mtmp); 362. 	monfree(mtmp); 363. 	mtmp2->nmon = fmon; 364. 	fmon = mtmp2; 365. 	if(u.ustuck == mtmp) u.ustuck = mtmp2; 366. 	if(mtmp2->isshk) replshk(mtmp,mtmp2); 367. 	if(mtmp2->isgd) replgd(mtmp,mtmp2); 368. }  369.   370.  relmon(mon) 371. register struct monst *mon; 372. {  373.  	register struct monst *mtmp; 374.  375.  	if (fmon == 0)  panic ("relmon: no fmon available."); 376.  377.  	if(mon == fmon) fmon = fmon->nmon; 378. 	else { 379. 		for(mtmp = fmon; mtmp->nmon != mon; mtmp = mtmp->nmon) ; 380. 		mtmp->nmon = mon->nmon; 381. 	}  382.  }  383.   384.  /* we do not free monsters immediately, in order to have their name 385.    available shortly after their demise */ 386. struct monst *fdmon;	/* chain of dead monsters, need not to be saved */ 387.  388.  monfree(mtmp) register struct monst *mtmp; { 389. 	mtmp->nmon = fdmon; 390. 	fdmon = mtmp; 391. }  392.   393.  dmonsfree{ 394. register struct monst *mtmp; 395. 	while(mtmp = fdmon){ 396. 		fdmon = mtmp->nmon; 397. 		free((char *) mtmp); 398. 	}  399.  }  400.   401.  unstuck(mtmp) 402. register struct monst *mtmp; 403. {  404.  	if(u.ustuck == mtmp) { 405. 		if(u.uswallow){ 406. 			u.ux = mtmp->mx; 407. 			u.uy = mtmp->my; 408. 			u.uswallow = 0; 409. 			setsee; 410. 			docrt; 411. 		}  412.  		u.ustuck = 0; 413. 	}  414.  }  415.   416.  killed(mtmp) 417. register struct monst *mtmp; 418. {  419.  	xkilled(mtmp, 1); 420. }  421.   422.  xkilled(mtmp, dest) 423. register struct monst *mtmp; 424. int	dest; 425. /* Dest=1, normal; dest=0, don't print message; dest=2, don't drop corpse 426.    either; dest=3, message but no corpse */ 427. {  428.  #ifdef lint 429. #define	NEW_SCORING 430. #endif 431. 	register int tmp,tmp2,nk,x,y; 432. 	register struct permonst *mdat = mtmp->data; 433. 	extern long newuexp; 434.  435.  	if(mtmp->cham) mdat = PM_CHAMELEON; 436. 	if (dest & 1) { 437. 	    if(Blind) pline("You destroy it!"); 438. 	    else { 439. 		pline("You destroy %s!",  440.  			mtmp->mtame ? amonnam(mtmp, "poor") : monnam(mtmp)); 441. 	    }  442.  	}  443.  	if(u.umconf) { 444. 		if(!Blind) 445. 		{  446.  			pline("Your hands stop glowing %s.",  447.  			Hallucination ? hcolor : "blue"); 448. 		}  449.  		u.umconf = 0; 450. 	}  451.   452.  	/* count killed monsters */ 453. #define	MAXMONNO	100 454. 	nk = 1;		      /* in case we cannot find it in mons */ 455. 	tmp = mdat - mons;    /* index in mons array (if not 'd', '@', ...) */ 456. 	if(tmp >= 0 && tmp < CMNUM+2) { 457. 	    extern char fut_geno[]; 458. 	    u.nr_killed[tmp]++; 459. 	    if((nk = u.nr_killed[tmp]) > MAXMONNO &&  460.  		!index(fut_geno, mdat->mlet)) 461. 		    charcat(fut_geno,  mdat->mlet); 462. 	}  463.   464.  	/* punish bad behaviour */ 465. 	if(mdat->mlet == '@') { 466. 		HTelepat = 0; 467. 		u.uluck -= 2; 468. 	}  469.  	if(mtmp->mpeaceful || mtmp->mtame) u.uluck--; 470. 	if(mdat->mlet == 'u') u.uluck -= 5; 471. 	if((int)u.uluck < LUCKMIN) u.uluck = LUCKMIN; 472.  473.  	/* give experience points */ 474. 	tmp = 1 + mdat->mlevel * mdat->mlevel; 475. 	if(mdat->ac < 3) tmp += 2*(7 - mdat->ac); 476. #ifdef KAA 477. 	if(index("AcsSDXaeRTVWU&In:P9", mdat->mlet)) 478. #else 479. 	if(index("AcsSDXaeRTVWU&In:P", mdat->mlet)) 480. #endif 481. 		tmp += 2*mdat->mlevel; 482. 	if(index("DeV&P",mdat->mlet)) tmp += (7*mdat->mlevel); 483. 	if(mdat->mlevel > 6) tmp += 50; 484. 	if(mdat->mlet == ';') tmp += 1000; 485.  486.  #ifdef NEW_SCORING 487. 	/* --- recent addition: make nr of points decrease 488. 		   when this is not the first of this kind */ 489. 	{ int ul = u.ulevel; 490. 	  int ml = mdat->mlevel; 491.  492.  	if(ul < 14)    /* points are given based on present and future level */ 493. 	    for(tmp2 = 0; !tmp2 || ul + tmp2 <= ml; tmp2++) 494. 		if(u.uexp + 1 + (tmp + ((tmp2 <= 0) ? 0 : 4<<(tmp2-1)))/nk  495.  		    >= 10*pow((unsigned)(ul-1))) 496. 			if(++ul == 14) break; 497.  498.  	tmp2 = ml - ul -1; 499. 	tmp = (tmp + ((tmp2 < 0) ? 0 : 4<= newuexp){ 509. 		pline("Welcome to experience level %u.", ++u.ulevel); 510. 		tmp = rnd(10); 511. 		if(tmp < 3) tmp = rnd(10); 512. 		u.uhpmax += tmp; 513. 		u.uhp += tmp; 514. #ifdef SPELLS 515. 		tmp = rnd(u.ulevel/2+1) + 1;	/* M. Stephenson */ 516. 		u.uenmax += tmp; 517. 		u.uen += tmp; 518. #endif 519. 		flags.botl = 1; 520. 	}  521.   522.  	/* dispose of monster and make cadaver */ 523. 	x = mtmp->mx;	y = mtmp->my; 524. 	mondead(mtmp); 525. 	tmp = mdat->mlet; 526. 	if(tmp == 'm') { /* he killed a minotaur, give him a wand of digging */ 527. 			/* note: the dead minotaur will be on top of it! */ 528.  		mksobj_at(WAN_DIGGING, x, y); 529. 		/* if(cansee(x,y)) atl(x,y,fobj->olet); */ 530. 		stackobj(fobj); 531. 	} else 532. #ifndef NOWORM 533. 	if(tmp == 'w') { 534. 		mksobj_at(WORM_TOOTH, x, y); 535. 		stackobj(fobj); 536. 	} else 537. #endif 538. #ifdef KAA 539. 	if(tmp == '&') (void) mkobj_at(0, x, y); 540. 	else 541. 	if(stoned == FALSE && (!letter(tmp) || (!index("9&1", tmp) && !rn2(3)))) tmp = 0; 542. 	    if(dest & 2) { 543. 		newsym(x,y); 544. 		return; 545. 	    }  546.  #else 547. 	if(!letter(tmp) || (!index("mw", tmp) && !rn2(3))) tmp = 0; 548. #endif 549.  550.  	if(ACCESSIBLE(levl[x][y].typ))	/* might be mimic in wall or dead eel*/ 551. 	    if(x != u.ux || y != u.uy) {  /* might be here after swallowed */ 552. #ifdef KAA 553. 		if(stoned) { 554. 			register char typetmp; 555. 			if(index(mlarge, tmp))	typetmp = ENORMOUS_ROCK; 556. 			else			typetmp = ROCK; 557. 			mksobj_at(typetmp, x, y); 558. 			if(cansee(x,y)) 559. 				atl(x,y,Hallucination ? rndobjsym :  560.  				objects[typetmp].oc_olet); 561. 		} else if(index("NTVm&w",mdat->mlet) || rn2(5)) { 562. #else 563. 		if(index("NTVm&w",mdat->mlet) || rn2(5)) { 564. #endif 565. 			register struct obj *obj2 = mkobj_at(tmp,x,y); 566. 			if(cansee(x,y)) 567. 			    atl(x, y, Hallucination ? rndobjsym : obj2->olet); 568. 			stackobj(obj2); 569. 		}  570.  	    }  571.  }  572.   573.  kludge(str,arg) 574. register char *str,*arg; 575. {  576.  	if(Blind) { 577. 		if(*str == '%') pline(str,"It"); 578. 		else pline(str,"it"); 579. 	} else pline(str,arg); 580. }  581.   582.  rescham	/* force all chameleons to become normal */ 583. {  584.  	register struct monst *mtmp; 585.  586.  	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 587. 		if(mtmp->cham) { 588. 			mtmp->cham = 0; 589. 			(void) newcham(mtmp, PM_CHAMELEON); 590. 		}  591.  }  592.   593.  #ifdef DGKMOD 594. /* Let the chameleons change again -dgk */ 595. restartcham 596. {  597.  	register struct monst *mtmp; 598.  599.  	for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) 600. 		if (mtmp->data->mlet == ':') 601. 			mtmp->cham = 1; 602. }  603.  #endif 604.  605.  newcham(mtmp,mdat)	/* make a chameleon look like a new monster */ 606. 			/* returns 1 if the monster actually changed */ 607. register struct monst *mtmp; 608. register struct permonst *mdat; 609. {  610.  	register mhp, hpn, hpd; 611.  612.  	if(mdat == mtmp->data) return(0);	/* still the same monster */ 613. #ifndef NOWORM 614. 	if(mtmp->wormno) wormdead(mtmp);	/* throw tail away */ 615. #endif 616. 	hpn = mtmp->mhp; 617. 	hpd = (mtmp->data->mlevel)*8;	if(!hpd) hpd = 4; 618. 	mhp = (mdat->mlevel)*8;		if(!mhp) mhp = 4; 619.  620.  	/* new hp: same fraction of max as before */ 621. 	mtmp->mhp = (hpn*mhp)/hpd; 622. 	if (mhp > hpd && mtmp->mhp < hpn) mtmp->mhp = 127; 623. /* Not totally foolproof. A 2HD monster with 80 HP that changes into a 6HD 624.    monster that really should have 240 and actually should have 127, the 625.    maximum possible, will wind up having 113. */ 626.  	if (!mtmp->mhp) mtmp->mhp = 1; 627. /* Unlikely but not impossible; a 1HD creature with 1HP that changes into a  628. 0HD creature will require this statement */ 629. 	mtmp->data = mdat; 630. /* and the same for maximum hit points */ 631. 	hpn = mtmp->mhpmax; 632. 	mtmp->mhpmax = (hpn*mhp)/hpd; 633. 	if (mhp > hpd && mtmp->mhpmax < hpn) mtmp->mhp = 127; 634. 	if (!mtmp->mhp) mtmp->mhp = 1; 635.  636.  	mtmp->minvis = (mdat->mlet == 'I') ? 1 : 0; 637.  	/* only snakes and scorpions can hide under things -dgk */ 638. 	/* also generated by GAN */ 639. 	mtmp->mhide = (mdat->mlet == 'S' || mdat->mlet == 's') ? 1 : 0; 640.  	if (!mtmp->mhide) mtmp->mundetected = 0; 641. #ifndef NOWORM 642. 	if(mdat->mlet == 'w' && getwn(mtmp)) initworm(mtmp); 643. 			/* perhaps we should clear mtmp->mtame here? */ 644.  #endif 645. 	unpmon(mtmp);	/* necessary for 'I' and to force pmon */ 646. 	pmon(mtmp); 647. 	return(1); 648. }  649.   650.  mnexto(mtmp)	/* Make monster mtmp next to you (if possible) */ 651. struct monst *mtmp; 652. {  653.  	coord mm; 654. 	enexto(&mm, u.ux, u.uy); 655. 	mtmp->mx = mm.x;  656. mtmp->my = mm.y; 657. pmon(mtmp); 658. }  659.   660.  ishuman(mtmp) register struct monst *mtmp; { 661. 	return(mtmp->data->mlet == '@'); 662. }  663.   664.  setmangry(mtmp) register struct monst *mtmp; { 665. 	if(!mtmp->mpeaceful) return; 666. 	if(mtmp->mtame) return; 667. 	mtmp->mpeaceful = 0; 668. 	if(ishuman(mtmp)) pline("%s gets angry!", Monnam(mtmp)); 669. }  670.   671.  /* not one hundred procent correct: now a snake may hide under an  672. invisible object */ 673. canseemon(mtmp) 674. register struct monst *mtmp; 675. {  676.  	return((!mtmp->minvis || See_invisible)  677.  		&& (!mtmp->mhide || !o_at(mtmp->mx,mtmp->my))  678.  		&& cansee(mtmp->mx, mtmp->my)); 679. }  680.   681.  disturb(mtmp)		/* awaken monsters while in the same room. 682. 			 * return a 1 if they have been woken. 683. 			 */  684.  register struct monst *mtmp; 685. {  686.  	/* wake up, or get out of here. */ 687.  	/* ettins are hard to surprise */ 688. 	/* Nymphs and Leprechauns do not easily wake up */ 689. 	if(cansee(mtmp->mx,mtmp->my) &&  690.  		(!Stealth || (mtmp->data->mlet == 'e' && rn2(10))) &&  691.  		(!index("NL",mtmp->data->mlet) || !rn2(50)) &&  692.  		(Aggravate_monster || index("d1", mtmp->data->mlet) 693. 			|| (!rn2(7) && !mtmp->mimic))) { 694. 		mtmp->msleep = 0; 695. 		return(1); 696. 	}  697.  	if(Hallucination) pmon(mtmp); 698. 	return(0); 699. }  700.   701.  #ifdef HARD 702. restrap(mtmp)		/* unwatched mimics and piercers may hide again, 703. 			 * if so, a 1 is returned. 704. 			 */  705.  register struct monst *mtmp; 706. {  707.  	if(mtmp->data->mlet == 'M' && !mtmp->mimic && !mtmp->cham  708.  	   && !mtmp->mcan && !cansee(mtmp->mx, mtmp->my)  709.  	   && !rn2(3)) { 710. 		mtmp->mimic = 1; 711. 		mtmp->mappearance = (levl[mtmp->mx][mtmp->my].typ == DOOR) ? DOOR_SYM : GOLD_SYM; 712. 		return(1); 713. 	   }  714.   715.  	if(mtmp->data->mlet == 'p' && !mtmp->cham  716.  	   && !mtmp->mcan && !cansee(mtmp->mx, mtmp->my)  717.  	   && !rn2(3))  { 718.  719.  		if(levl[mtmp->mx][mtmp->my].typ == ROOM)  { 720.  721.  			maketrap(mtmp->mx, mtmp->my, PIERC); 722. 			mondead(mtmp); 723. 			return(1); 724. 		}  725.  	   }  726.  	return(0); 727. }  728.  #endif