Source:NetHack 1.3d/makemon.c

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

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

1.   /*	SCCS Id: @(#)makemon.c	1.3	87/07/14 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* makemon.c - version 1.0.2 */ 4.    5.    #include	"hack.h"  6.    extern char fut_geno[]; 7.   extern char *index; 8.   extern struct obj *mkobj_at, *mksobj, *mkobj; 9.   struct monst zeromonst; 10.  extern boolean in_mklev; 11.   12.   #ifdef HARD		/* used in hell for bigger, badder demons! */ 13.    14.   struct permonst d_lord   = { "demon lord",	'&',12,13,-5,50,1,5,0 }, 15.  		d_prince = { "demon prince",	'&',14,14,-6,70,1,6,0 }; 16.  #endif 17.   18.   /*  19.    * called with [x,y] = coordinates; 20.   *	[0,0] means anyplace 21.   *	[u.ux,u.uy] means: call mnexto (if !in_mklev) 22.   *  23.    *	In case we make an Orc or killer bee, we make an entire horde 24.   *	(swarm); note that in this case we return only one of them 25.   *	(the one at [x,y]). 26.   */  27.   struct monst * 28.  makemon(ptr,x,y) 29.  register struct permonst *ptr; 30.  {  31.   	register struct monst *mtmp; 32.  	register tmp, ct; 33.  	boolean anything = (!ptr); 34.   35.   	if(x != 0 || y != 0) if(m_at(x,y)) return((struct monst *) 0); 36.  	if(ptr){ 37.  		if(index(fut_geno, ptr->mlet)) return((struct monst *) 0); 38.  	} else { 39.  		ct = CMNUM - strlen(fut_geno); 40.  		if(index(fut_geno, 'm')) ct++;  /* make only 1 minotaur */ 41.  		if(index(fut_geno, '@')) ct++; 42.  		if(ct <= 0) return(0); 		  /* no more monsters! */ 43.   		tmp = 7; 44.  #ifdef KOPS 45.  		tmp--; 46.  #endif 47.  #ifdef ROCKMOLE 48.  		if(dlevel<4) tmp--; 49.  #endif 50.  		tmp = rn2(ct*dlevel/24 + 7); 51.  		if(tmp < dlevel - 4) tmp = rn2(ct*dlevel/24 + 12); 52.  		if(tmp >= ct) tmp = rn1(ct - ct/2, ct/2); 53.  		ct = 0; 54.  #ifdef KOPS 55.  		ct++; 56.  #endif 57.  		while(!(tmp + 1 <= CMNUM - ct))	tmp--; 58.  		for(ct < CMNUM; ct++){ 59.  			ptr = &mons[ct]; 60.  #ifdef KOPS 61.  			if(ptr->mlet == 'K') { 62.  				tmp--; 63.  				continue; 64.  			}  65.   #endif 66.  			if(index(fut_geno, ptr->mlet)) continue; 67.  			if(tmp-- <= 0) goto gotmon; 68.  		}  69.   		panic("makemon?"); 70.  	}  71.   gotmon: 72.  	mtmp = newmonst(ptr->pxlth); 73.  	*mtmp = zeromonst;	/* clear all entries in structure */ 74.  	for(ct = 0; ct < ptr->pxlth; ct++) 75.  		((char *) &(mtmp->mextra[0]))[ct] = 0; 76.  	mtmp->nmon = fmon; 77.  	fmon = mtmp; 78.  	mtmp->m_id = flags.ident++; 79.  	mtmp->data = ptr; 80.  	mtmp->mxlth = ptr->pxlth; 81.  	if(ptr->mlet == 'D') mtmp->mhpmax = mtmp->mhp = 80; 82.  	else if(!ptr->mlevel) mtmp->mhpmax = mtmp->mhp = rnd(4); 83.  	else mtmp->mhpmax = mtmp->mhp = d(ptr->mlevel, 8); 84.  	mtmp->mx = x;  85. mtmp->my = y; 86. mtmp->mcansee = 1; 87.  	if(ptr->mlet == 'M'){ 88.  		mtmp->mimic = 1; 89.  		mtmp->mappearance = ']'; 90.  	}  91.   	if(!in_mklev) { 92.  		if(x == u.ux && y == u.uy && ptr->mlet != ' ') 93.  			mnexto(mtmp); 94.  		if(x == 0 && y == 0) 95.  			rloc(mtmp); 96.  	}  97.   	if(ptr->mlet == 's' || ptr->mlet == 'S') { 98.  		mtmp->mhide = mtmp->mundetected = 1; 99.  		if(in_mklev) 100. 		if(mtmp->mx && mtmp->my) 101. 			(void) mkobj_at(0, mtmp->mx, mtmp->my); 102. 	}  103.  	if(ptr->mlet == ':') { 104. #ifdef DGKMOD 105. 		/* If you're protected with a ring, don't create 106. 		 * any shape-changing chameleons -dgk 107. 		 */  108.  		if (Protection_from_shape_changers) 109. 			mtmp->cham = 0; 110. 		else { 111. 			mtmp->cham = 1; 112. 			(void) newcham(mtmp,  113.  				&mons[dlevel+14+rn2(CMNUM-14-dlevel)]); 114. 		}  115.  #else 116. 		mtmp->cham = 1; 117. 		(void) newcham(mtmp, &mons[dlevel+14+rn2(CMNUM-14-dlevel)]); 118. #endif 119. 	}  120.  	if(ptr->mlet == 'I' || ptr->mlet == ';') 121. 		mtmp->minvis = 1; 122. 	if(ptr->mlet == 'L' || ptr->mlet == 'N'  123.  	    || (in_mklev && index("&w;", ptr->mlet) && rn2(5))  124.  	) mtmp->msleep = 1; 125. #ifdef HARD 126. 	if(ptr->mlet == '&' && (Inhell || u.udemigod)) { 127.  128.  		if(!rn2(5 + !Inhell)) { 129. 		    if (rn2(3 + Inhell)) mtmp->data = &d_lord; 130. 		    else  { 131. 				mtmp->data = &d_prince; 132. 				mtmp->mpeaceful = 1; 133. 				mtmp->minvis = 1; 134. 		    }  135.  		}  136.  	}  137.  #endif /* HARD /**/ 138. #ifndef NOWORM 139. 	if(ptr->mlet == 'w' && getwn(mtmp))  initworm(mtmp); 140. #endif 141.  142.  	if(anything) if(ptr->mlet == 'O' || ptr->mlet == 'k') { 143. 		coord enexto; 144. 		coord mm; 145. 		register int cnt = rnd(10); 146. 		mm.x = x;  147. mm.y = y; 148. while(cnt--) { 149. 			mm = enexto(mm.x, mm.y); 150. 			(void) makemon(ptr, mm.x, mm.y); 151. 		}  152.  	}  153.  #ifdef DGKMOD 154. 	m_initinv(mtmp); 155. #endif 156. 	return(mtmp); 157. }  158.   159.  #ifdef DGKMOD 160. /* Give some monsters an initial inventory to use */ 161. m_initinv(mtmp) 162. struct monst *mtmp; 163. {  164.  	struct obj *otmp; 165.  166.  	switch (mtmp->data->mlet) { 167. # ifdef KAA 168. 	case '9': 169. 		if (rn2(2)) { 170. 			otmp = mksobj(ENORMOUS_ROCK); 171. 			mpickobj(mtmp, otmp); 172. 		}  173.  # endif 174. # ifdef KOPS 175. 	case 'K':		/* create Keystone Kops with cream pies to  176. * throw. As suggested by KAA. [MRS] 177. 				 */  178.  		if (!rn2(4)) { 179. 			otmp = mksobj(CREAM_PIE); 180. 			otmp->quan = 2 + rnd(2); 181. 			mpickobj(mtmp, otmp); 182. 		}  183.  		break; 184. 	case 'O': 185. # else 186. 	case 'K': 187. # endif 188. 		if (!rn2(4)) { 189. 			otmp = mksobj(DART); 190. 			otmp->quan = 2 + rnd(12); 191. 			mpickobj(mtmp, otmp); 192. 		}  193.  		break; 194. 	case 'C': 195. 		if (rn2(2)) { 196. 			otmp = mksobj(CROSSBOW); 197. 			otmp->cursed = rn2(2); 198. 			mpickobj(mtmp, otmp); 199. 			otmp = mksobj(CROSSBOW_BOLT); 200. 			otmp->quan = 2 + rnd(12); 201. 			mpickobj(mtmp, otmp); 202. 		}  203.  		break; 204. 	default: 205. 		break; 206. 	}  207.  }  208.  #endif 209.  210.  coord 211. enexto(xx,yy) 212. register xchar xx,yy; 213. {  214.  	register xchar x,y; 215. 	coord foo[15], *tfoo; 216. 	int range; 217.  218.  	tfoo = foo; 219. 	range = 1; 220. 	do {	/* full kludge action. */ 221.  		for(x = xx-range; x <= xx+range; x++) 222. 			if(goodpos(x, yy-range)) { 223. 				tfoo->x = x;  224. (tfoo++)->y = yy-range; 225. 				if(tfoo == &foo[15]) goto foofull; 226. 			}  227.  		for(x = xx-range; x <= xx+range; x++) 228. 			if(goodpos(x,yy+range)) { 229. 				tfoo->x = x;  230. (tfoo++)->y = yy+range; 231. 				if(tfoo == &foo[15]) goto foofull; 232. 			}  233.  		for(y = yy+1-range; y < yy+range; y++) 234. 			if(goodpos(xx-range,y)) { 235. 				tfoo->x = xx-range; 236. 				(tfoo++)->y = y;  237. if(tfoo == &foo[15]) goto foofull; 238. 			}  239.  		for(y = yy+1-range; y < yy+range; y++) 240. 			if(goodpos(xx+range,y)) { 241. 				tfoo->x = xx+range; 242. 				(tfoo++)->y = y;  243. if(tfoo == &foo[15]) goto foofull; 244. 			}  245.  		range++; 246. 	} while(tfoo == foo); 247. foofull: 248. 	return( foo[rn2(tfoo-foo)] ); 249. }  250.   251.  goodpos(x,y)	/* used only in mnexto and rloc */ 252. {  253.  	return(  254.  	! (x < 1 || x > COLNO-2 || y < 1 || y > ROWNO-2 || 255. 	   m_at(x,y) || !ACCESSIBLE(levl[x][y].typ) 256. 	   || (x == u.ux && y == u.uy) 257. 	   || sobj_at(ENORMOUS_ROCK, x, y)  258. )); 259.  }  260.   261.  rloc(mtmp) 262. struct monst *mtmp; 263. {  264.  	register tx,ty; 265. 	register char ch = mtmp->data->mlet; 266.  267.  #ifndef NOWORM 268. 	if(ch == 'w' && mtmp->mx) return;	/* do not relocate worms */ 269. #endif 270. 	do { 271. 		tx = rn1(COLNO-3,2); 272. 		ty = rn2(ROWNO); 273. 	} while(!goodpos(tx,ty)); 274. 	mtmp->mx = tx; 275. 	mtmp->my = ty; 276. 	if(u.ustuck == mtmp){ 277. 		if(u.uswallow) { 278. 			u.ux = tx; 279. 			u.uy = ty; 280. 			docrt; 281. 		} else	u.ustuck = 0; 282. 	}  283.  	pmon(mtmp); 284. }  285.   286.  struct monst * 287. mkmon_at(let,x,y) 288. char let; 289. register int x,y; 290. {  291.  	register int ct; 292. 	register struct permonst *ptr; 293.  294.  	for(ct = 0; ct < CMNUM; ct++) { 295. 		ptr = &mons[ct]; 296. 		if(ptr->mlet == let) 297. 			return(makemon(ptr,x,y)); 298. 	}  299.  	return(0); 300. }