Source:Extralev.c

Below is the full text to src/extralev.c from NetHack 3.4.3. To link to a particular line, write [[extralev.c#line123 ]], for example. 1.   /*	SCCS Id: @(#)extralev.c	3.4	2001/09/06	*/ 2.   /*	Copyright 1988, 1989 by Ken Arromdee				*/ 3.   /* NetHack may be freely redistributed. See license for details. */ 4.

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