Source:NetHack 1.4f/makemon.c

Below is the full text to makemon.c from the source code of NetHack 1.4f. To link to a particular line, write [[NetHack 1.4f/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.4	87/08/08 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 mm; 144. 		register int cnt = rnd(10); 145. 		mm.x = x;  146. mm.y = y; 147. while(cnt--) { 148. 			enexto(&mm, mm.x, mm.y); 149. 			(void) makemon(ptr, mm.x, mm.y); 150. 		}  151.  	}  152.  #ifdef DGKMOD 153. 	m_initinv(mtmp); 154. #endif 155. 	return(mtmp); 156. }  157.   158.  #ifdef DGKMOD 159. /* Give some monsters an initial inventory to use */ 160. m_initinv(mtmp) 161. struct monst *mtmp; 162. {  163.  	struct obj *otmp; 164.  165.  	switch (mtmp->data->mlet) { 166. # ifdef KAA 167. 	case '9': 168. 		if (rn2(2)) { 169. 			otmp = mksobj(ENORMOUS_ROCK); 170. 			mpickobj(mtmp, otmp); 171. 		}  172.  # endif 173. # ifdef KOPS 174. 	case 'K':		/* create Keystone Kops with cream pies to  175. * throw. As suggested by KAA. [MRS] 176. 				 */  177.  		if (!rn2(4)) { 178. 			otmp = mksobj(CREAM_PIE); 179. 			otmp->quan = 2 + rnd(2); 180. 			mpickobj(mtmp, otmp); 181. 		}  182.  		break; 183. 	case 'O': 184. # else 185. 	case 'K': 186. # endif 187. 		if (!rn2(4)) { 188. 			otmp = mksobj(DART); 189. 			otmp->quan = 2 + rnd(12); 190. 			mpickobj(mtmp, otmp); 191. 		}  192.  		break; 193. 	case 'C': 194. 		if (rn2(2)) { 195. 			otmp = mksobj(CROSSBOW); 196. 			otmp->cursed = rn2(2); 197. 			mpickobj(mtmp, otmp); 198. 			otmp = mksobj(CROSSBOW_BOLT); 199. 			otmp->quan = 2 + rnd(12); 200. 			mpickobj(mtmp, otmp); 201. 		}  202.  		break; 203. 	default: 204. 		break; 205. 	}  206.  }  207.  #endif 208.  209.  enexto(cc, xx,yy) 210. coord	*cc; 211. register xchar xx,yy; 212. {  213.  	register xchar x,y; 214. 	coord foo[15], *tfoo; 215. 	int range; 216.  217.  	tfoo = foo; 218. 	range = 1; 219. 	do {	/* full kludge action. */ 220.  		for(x = xx-range; x <= xx+range; x++) 221. 			if(goodpos(x, yy-range)) { 222. 				tfoo->x = x;  223. (tfoo++)->y = yy-range; 224. 				if(tfoo == &foo[15]) goto foofull; 225. 			}  226.  		for(x = xx-range; x <= xx+range; x++) 227. 			if(goodpos(x,yy+range)) { 228. 				tfoo->x = x;  229. (tfoo++)->y = yy+range; 230. 				if(tfoo == &foo[15]) goto foofull; 231. 			}  232.  		for(y = yy+1-range; y < yy+range; y++) 233. 			if(goodpos(xx-range,y)) { 234. 				tfoo->x = xx-range; 235. 				(tfoo++)->y = y;  236. if(tfoo == &foo[15]) goto foofull; 237. 			}  238.  		for(y = yy+1-range; y < yy+range; y++) 239. 			if(goodpos(xx+range,y)) { 240. 				tfoo->x = xx+range; 241. 				(tfoo++)->y = y;  242. if(tfoo == &foo[15]) goto foofull; 243. 			}  244.  		range++; 245. 	} while(tfoo == foo); 246. foofull: 247. 	cc->x = foo[rn2(tfoo-foo)].x;  248. cc->y = foo[rn2(tfoo-foo)].y; 249. return(0); 250. }  251.   252.  goodpos(x,y)	/* used only in mnexto and rloc */ 253. {  254.  	return(  255.  	! (x < 1 || x > COLNO-2 || y < 1 || y > ROWNO-2 || 256. 	   m_at(x,y) || !ACCESSIBLE(levl[x][y].typ) 257. 	   || (x == u.ux && y == u.uy) 258. 	   || sobj_at(ENORMOUS_ROCK, x, y)  259. )); 260.  }  261.   262.  rloc(mtmp) 263. struct monst *mtmp; 264. {  265.  	register tx,ty; 266. 	register char ch = mtmp->data->mlet; 267.  268.  #ifndef NOWORM 269. 	if(ch == 'w' && mtmp->mx) return;	/* do not relocate worms */ 270. #endif 271. 	do { 272. 		tx = rn1(COLNO-3,2); 273. 		ty = rn2(ROWNO); 274. 	} while(!goodpos(tx,ty)); 275. 	mtmp->mx = tx; 276. 	mtmp->my = ty; 277. 	if(u.ustuck == mtmp){ 278. 		if(u.uswallow) { 279. 			u.ux = tx; 280. 			u.uy = ty; 281. 			docrt; 282. 		} else	u.ustuck = 0; 283. 	}  284.  	pmon(mtmp); 285. }  286.   287.  struct monst * 288. mkmon_at(let,x,y) 289. char let; 290. register int x,y; 291. {  292.  	register int ct; 293. 	register struct permonst *ptr; 294.  295.  	for(ct = 0; ct < CMNUM; ct++) { 296. 		ptr = &mons[ct]; 297. 		if(ptr->mlet == let) 298. 			return(makemon(ptr,x,y)); 299. 	}  300.  	return(0); 301. }