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.
Top of file[]
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.
The NetHack General Public License applies to screenshots, source code and other content from NetHack. |
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.
roguejoin[]
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.
roguecorr[]
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.
miniwalk[]
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.
makeroguerooms[]
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.
corr[]
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.
makerogueghost[]
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*/