Source:NetHack 3.1.0/extralev.c

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

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

1.   /*	SCCS Id: @(#)extralev.c	3.1	92/05/27			*/ 2.   /*	Copyright 1988, 1989 by Ken Arromdee				*/ 3.   /* NetHack may be freely redistributed. See license for details. */ 4.     5.    #include "hack.h"  6. 7.   #ifdef REINCARNATION 8.    9.    struct rogueroom { 10.  	xchar rlx, rly; 11.  	xchar dx, dy; 12.  	boolean real; 13.  	uchar doortable; 14.  	int nroom; /* Only meaningful for "real" rooms */ 15.  };  16.   #define UP 1 17.  #define DOWN 2 18.  #define LEFT 4 19.  #define RIGHT 8 20.   21.   static struct rogueroom NEARDATA r[3][3]; 22.  static void FDECL(roguejoin,(int,int,int,int,int)); 23.  static void FDECL(roguecorr,(int,int,int)); 24.  static void FDECL(miniwalk,(int,int)); 25.   26.   static 27.  void 28.  roguejoin(x1,y1,x2,y2, horiz) 29.  int x1,y1,x2,y2; 30.  int horiz; 31.  {  32.   	register int x,y,middle; 33.  #ifndef MAX 34.  #define MAX(a,b) (((a) > (b)) ? (a) : (b)) 35.  #endif 36.  #ifndef MIN 37.  #define MIN(a,b) (((a) < (b)) ? (a) : (b)) 38.  #endif 39.  	if (horiz) { 40.  		middle = x1 + rn2(x2-x1+1); 41.  		for(x=MIN(x1,middle); x<=MAX(x1,middle); x++) 42.  			corr(x, y1); 43.  		for(y=MIN(y1,y2); y<=MAX(y1,y2); y++) 44.  			corr(middle,y); 45.  		for(x=MIN(middle,x2); x<=MAX(middle,x2); x++) 46.  			corr(x, y2); 47.  	} else { 48.  		middle = y1 + rn2(y2-y1+1); 49.  		for(y=MIN(y1,middle); y<=MAX(y1,middle); y++) 50.  			corr(x1, y); 51.  		for(x=MIN(x1,x2); x<=MAX(x1,x2); x++) 52.  			corr(x, middle); 53.  		for(y=MIN(middle,y2); y<=MAX(middle,y2); y++) 54.  			corr(x2,y); 55.  	}  56.   }  57.    58.   static 59.  void 60.  roguecorr(x, y, dir) 61.  int x,y,dir; 62.  {  63.   	register int fromx, fromy, tox, toy; 64.   65.   	if (dir==DOWN) { 66.  		r[x][y].doortable &= ~DOWN; 67.  		if (!r[x][y].real) { 68.  			fromx = r[x][y].rlx; fromy = r[x][y].rly; 69.  			fromx += 1 + 26*x; fromy += 7*y; 70.  		} else { 71.  			fromx = r[x][y].rlx + rn2(r[x][y].dx); 72.  			fromy = r[x][y].rly + r[x][y].dy; 73.  			fromx += 1 + 26*x; fromy += 7*y; 74.  			if (!IS_WALL(levl[fromx][fromy].typ)) 75.  				impossible("down: no wall at %d,%d?",fromx,  76.   									fromy); 77.  			dodoor(fromx, fromy, &rooms[r[x][y].nroom]); 78.  			levl[fromx][fromy].doormask = D_NODOOR; 79.  			fromy++; 80.  		}  81.   		if(y >= 2) { 82.  			impossible("down door from %d,%d going nowhere?",x,y); 83.  			return; 84.  		}  85.   		y++; 86.  		r[x][y].doortable &= ~UP; 87.  		if (!r[x][y].real) { 88.  			tox = r[x][y].rlx; toy = r[x][y].rly; 89.  			tox += 1 + 26*x; toy += 7*y; 90.  		} else { 91.  			tox = r[x][y].rlx + rn2(r[x][y].dx); 92.  			toy = r[x][y].rly - 1; 93.  			tox += 1 + 26*x; toy += 7*y; 94.  			if (!IS_WALL(levl[tox][toy].typ)) 95.  				impossible("up: no wall at %d,%d?",tox,toy); 96.  			dodoor(tox, toy, &rooms[r[x][y].nroom]); 97.  			levl[tox][toy].doormask = D_NODOOR; 98.  			toy--; 99.  		}  100.  		roguejoin(fromx, fromy, tox, toy, FALSE); 101. 		return; 102. 	} else if (dir == RIGHT) { 103. 		r[x][y].doortable &= ~RIGHT; 104. 		if (!r[x][y].real) { 105. 			fromx = r[x][y].rlx; fromy = r[x][y].rly; 106. 			fromx += 1 + 26*x; fromy += 7*y; 107. 		} else { 108. 			fromx = r[x][y].rlx + r[x][y].dx; 109. 			fromy = r[x][y].rly + rn2(r[x][y].dy); 110. 			fromx += 1 + 26*x; fromy += 7*y; 111. 			if (!IS_WALL(levl[fromx][fromy].typ)) 112. 				impossible("down: no wall at %d,%d?",fromx,  113.  									fromy); 114. 			dodoor(fromx, fromy, &rooms[r[x][y].nroom]); 115. 			levl[fromx][fromy].doormask = D_NODOOR; 116. 			fromx++; 117. 		}  118.  		if(x >= 2) { 119. 			impossible("right door from %d,%d going nowhere?",x,y); 120. 			return; 121. 		}  122.  		x++; 123. 		r[x][y].doortable &= ~LEFT; 124. 		if (!r[x][y].real) { 125. 			tox = r[x][y].rlx; toy = r[x][y].rly; 126. 			tox += 1 + 26*x; toy += 7*y; 127. 		} else { 128. 			tox = r[x][y].rlx - 1; 129. 			toy = r[x][y].rly + rn2(r[x][y].dy); 130. 			tox += 1 + 26*x; toy += 7*y; 131. 			if (!IS_WALL(levl[tox][toy].typ)) 132. 				impossible("left: no wall at %d,%d?",tox,toy); 133. 			dodoor(tox, toy, &rooms[r[x][y].nroom]); 134. 			levl[tox][toy].doormask = D_NODOOR; 135. 			tox--; 136. 		}  137.  		roguejoin(fromx, fromy, tox, toy, TRUE); 138. 		return; 139. 	} else impossible("corridor in direction %d?",dir); 140. }  141.  			  142.  /* Modified walkfrom from mkmaze.c */ 143. static 144. void 145. miniwalk(x, y)  146. int x,y; 147. {  148.  	register int q, dir; 149. 	int dirs[4]; 150.  151.  	while(1) { 152. 		q = 0; 153. #define doorhere (r[x][y].doortable) 154. 		if (x>0 && (!(doorhere & LEFT)) &&  155.  					(!r[x-1][y].doortable || !rn2(10))) 156. 			dirs[q++] = 0; 157. 		if (x<2 && (!(doorhere & RIGHT)) &&  158.  					(!r[x+1][y].doortable || !rn2(10))) 159. 			dirs[q++] = 1; 160. 		if (y>0 && (!(doorhere & UP)) &&  161.  					(!r[x][y-1].doortable || !rn2(10))) 162. 			dirs[q++] = 2; 163. 		if (y<2 && (!(doorhere & DOWN)) &&  164.  					(!r[x][y+1].doortable || !rn2(10))) 165. 			dirs[q++] = 3; 166. 	/* Rogue levels aren't just 3 by 3 mazes; they have some extra 167. 	 * connections, thus that 1/10 chance 168. 	 */  169.  		if (!q) return; 170. 		dir = dirs[rn2(q)]; 171. 		switch(dir) { /* Move in direction */ 172. 			case 0: doorhere |= LEFT; 173. 				x--; 174. 				doorhere |= RIGHT; 175. 				break; 176. 			case 1: doorhere |= RIGHT; 177. 				x++; 178. 				doorhere |= LEFT; 179. 				break; 180. 			case 2: doorhere |= UP; 181. 				y--; 182. 				doorhere |= DOWN; 183. 				break; 184. 			case 3: doorhere |= DOWN; 185. 				y++; 186. 				doorhere |= UP; 187. 				break; 188. 		}  189.  		miniwalk(x,y); 190. 	}  191.  }  192.   193.  void 194. makeroguerooms { 195. 	register int x,y; 196. 	/* Rogue levels are structured 3 by 3, with each section containing 197. 	 * a room or an intersection. The minimum width is 2 each way. 198. 	 * One difference between these and "real" Rogue levels: real Rogue 199. 	 * uses 24 rows and NetHack only 23. So we cheat a bit by making the 200. 	 * second row of rooms not as deep. 201. 	 *  202.  	 * Each normal space has 6/7 rows and 25 columns in which a room may 203. 	 * actually be placed. Walls go from rows 0-5/6 and columns 0-24. 204. 	 * Not counting walls, the room may go in  205. * rows 1-5 and columns 1-23 (numbering starting at 0). A room 206. 	 * coordinate of this type may be converted to a level coordinate 207. 	 * by adding 1+28*x to the column, and 7*y to the row. (The 1 208.  	 * is because column 0 isn't used [we only use 1-78]). 209. 	 * Room height may be 2-4 (2-5 on last row), length 2-23 (not  210.  	 * counting walls) 211. 	 */  212.  #define here r[x][y] 213.  214.  	nroom = 0; 215. 	for(y=0; y<3; y++) for(x=0; x<3; x++) { 216. 		/* Note: we want to insure at least 1 room. So, if the 217. 		 * first 8 are all dummies, force the last to be a room. 218. 		 */  219.  		if (!rn2(5) && (nroom || (x<2 && y<2))) { 220. 			/* Arbitrary: dummy rooms may only go where real 221. 			 * ones do. 222. 			 */  223.  			here.real = FALSE; 224. 			here.rlx = rn1(22, 2); 225. 			here.rly = rn1((y==2)?4:3, 2); 226. 		} else { 227. 			here.real = TRUE; 228. 			here.dx = rn1(22, 2); /* 2-23 long, plus walls */ 229. 			here.dy = rn1((y==2)?4:3, 2); /* 2-5 high, plus walls */ 230.  231.  			/* boundaries of room floor */ 232. 			here.rlx = rnd(23 - here.dx + 1); 233. 			here.rly = rnd(((y==2) ? 5 : 4)- here.dy + 1); 234. 			nroom++; 235. 		}  236.  		here.doortable = 0; 237. 	}  238.  	miniwalk(rn2(3), rn2(3)); 239. 	nroom = 0; 240. 	for(y=0; y<3; y++) for(x=0; x<3; x++) { 241. 		if (here.real) { /* Make a room */ 242. 			int lowx, lowy, hix, hiy; 243.  244.  			r[x][y].nroom = nroom; 245. 			smeq[nroom] = nroom; 246.  247.  			lowx = 1 + 26*x + here.rlx; 248. 			lowy = 7*y + here.rly; 249. 			hix = 1 + 26*x + here.rlx + here.dx - 1; 250. 			hiy = 7*y + here.rly + here.dy - 1; 251. 			/* Strictly speaking, it should be lit only if above 252. 			 * level 10, but since Rogue rooms are only 253. 			 * encountered below level 10, use !rn2(7). 254. 			 */  255.   256.  			add_room(lowx, lowy, hix, hiy, !rn2(7), OROOM, FALSE); 257. 		}  258.  	}  259.   260.  	/* Now, add connecting corridors. */ 261.  	for(y=0; y<3; y++) for(x=0; x<3; x++) { 262. 		if (here.doortable & DOWN) 263. 			roguecorr(x, y, DOWN); 264. 		if (here.doortable & RIGHT) 265. 			roguecorr(x, y, RIGHT); 266. 		if (here.doortable & LEFT) 267. 			impossible ("left end of %d, %d never connected?",x,y); 268. 		if (here.doortable & UP) 269. 			impossible ("up end of %d, %d never connected?",x,y); 270. 	}  271.  }  272.   273.  void 274. corr(x,y) 275. int x, y;  276. { 277.  	if (rn2(50)) { 278. 		levl[x][y].typ = CORR; 279. 	} else { 280. 		levl[x][y].typ = SCORR; 281. 	}  282.  }  283.   284.  void 285. makerogueghost 286. {  287.  	register struct monst *ghost; 288. 	struct obj *ghostobj; 289. 	struct mkroom *croom; 290. 	int x,y; 291.  292.  	if (!nroom) return; /* Should never happen */ 293. 	croom = &rooms[rn2(nroom)]; 294. 	x = somex(croom); y = somey(croom); 295. 	if (!(ghost = makemon(&mons[PM_GHOST], x, y))) 296. 		return; 297. 	ghost->msleep = 1; 298. 	Strcpy((char *)ghost->mextra, roguename); 299.  300.  	if (rn2(4)) { 301. 		ghostobj = mksobj_at(FOOD_RATION,x,y,FALSE); 302. 		ghostobj->quan = (long) rnd(7); 303. 		ghostobj->owt = weight(ghostobj); 304. 	}  305.  	if (rn2(2)) { 306. 		ghostobj = mksobj_at(MACE,x,y,FALSE); 307. 		ghostobj->spe = rnd(3); 308. 		if (rn2(4)) curse(ghostobj); 309. 	} else { 310. 		ghostobj = mksobj_at(TWO_HANDED_SWORD,x,y,FALSE); 311. 		ghostobj->spe = rnd(5) - 2; 312. 		if (rn2(4)) curse(ghostobj); 313. 	}  314.  	ghostobj = mksobj_at(BOW,x,y,FALSE); 315. 	ghostobj->spe = 1; 316. 	if (rn2(4)) curse(ghostobj); 317.  318.  	ghostobj = mksobj_at(ARROW,x,y,FALSE); 319. 	ghostobj->spe = 0; 320. 	ghostobj->quan = (long) rn1(10,25); 321. 	ghostobj->owt = weight(ghostobj); 322. 	if (rn2(4)) curse(ghostobj); 323.  324.  	if (rn2(2)) { 325. 		ghostobj = mksobj_at(RING_MAIL,x,y,FALSE); 326. 		ghostobj->spe = rn2(3); 327. 		if (!rn2(3)) ghostobj->oerodeproof = TRUE; 328. 		if (rn2(4)) curse(ghostobj); 329. 	} else { 330. 		ghostobj = mksobj_at(PLATE_MAIL,x,y,FALSE); 331. 		ghostobj->spe = rnd(5) - 2; 332. 		if (!rn2(3)) ghostobj->oerodeproof = TRUE; 333. 		if (rn2(4)) curse(ghostobj); 334. 	}  335.  	if (rn2(2)) { 336. 		ghostobj = mksobj_at(FAKE_AMULET_OF_YENDOR,x,y,TRUE); 337. 		ghostobj->known = TRUE; 338. 	}  339.  }  340.  #endif /* REINCARNATION /**/ 341.  342.  /*extralev.c*/