abstract
| - Below is the full text to mkmap.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.0/mkmap.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code 1. /* SCCS Id: @(#)mkmap.c 3.1 92/07/15 */ 2. /* Copyright (c) J. C. Collet, M. Stephenson and D. Cohrs, 1992 */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. #include "hack.h" 6. #include "sp_lev.h" 7. 8. #define HEIGHT (ROWNO - 1) 9. #define WIDTH (COLNO - 2) 10. 11. static void FDECL(init_map,(SCHAR_P)); 12. static void FDECL(init_fill,(SCHAR_P,SCHAR_P)); 13. static schar FDECL(get_map,(int,int,SCHAR_P)); 14. static void FDECL(pass_one,(SCHAR_P,SCHAR_P)); 15. static void FDECL(pass_two,(SCHAR_P,SCHAR_P)); 16. static void FDECL(pass_three,(SCHAR_P,SCHAR_P)); 17. static void NDECL(wallify_map); 18. static void FDECL(join_map,(SCHAR_P,SCHAR_P)); 19. static void FDECL(finish_map,(SCHAR_P,SCHAR_P,XCHAR_P,XCHAR_P)); 20. void FDECL(mkmap, (lev_init *)); 21. 22. char *new_locations; 23. int min_rx, max_rx, min_ry, max_ry; /* rectangle bounds for regions */ 24. static int n_loc_filled; 25. 26. static void 27. init_map(bg_typ) 28. schar bg_typ; 29. { 30. register int i,j; 31. 32. for(i=1; i 33. for(j=0; j 34. levl[i][j].typ = bg_typ; 35. } 36. 37. static void 38. init_fill(bg_typ, fg_typ) 39. schar bg_typ, fg_typ; 40. { 41. register int i,j; 42. long limit, count; 43. 44. limit = (WIDTH * HEIGHT * 2) / 5; 45. count = 0; 46. while(count < limit) { 47. i = rn1(WIDTH-1, 2); 48. j = rnd(HEIGHT-1); 49. if (levl[i][j].typ == bg_typ) { 50. levl[i][j].typ = fg_typ; 51. count++; 52. } 53. } 54. } 55. 56. static schar 57. get_map(col,row, bg_typ) 58. int col,row; 59. schar bg_typ; 60. { 61. if (col <= 0 || row < 0 || col > WIDTH || row >= HEIGHT) 62. return bg_typ; 63. return levl[col][row].typ; 64. } 65. 66. static int dirs[16] = { 67. -1, -1 /**/, -1, 0 /**/, -1, 1 /**/, 68. 0, -1 /**/, 0, 1 /**/, 69. 1, -1 /**/, 1, 0 /**/, 1, 1}; 70. 71. static void 72. pass_one(bg_typ, fg_typ) 73. schar bg_typ, fg_typ; 74. { 75. register int i,j; 76. short count, dr; 77. 78. for(i=2; i<=WIDTH; i++) 79. for(j=1; j 80. for(count=0, dr=0; dr < 8; dr++) 81. if(get_map(i+dirs[dr*2], j+dirs[(dr*2)+1], bg_typ) 82. == fg_typ) 83. count++; 84. 85. switch(count) { 86. case 0 : /* death */ 87. case 1 : 88. case 2: 89. levl[i][j].typ = bg_typ; 90. break; 91. case 5: 92. case 6: 93. case 7: 94. case 8: 95. levl[i][j].typ = fg_typ; 96. break; 97. default: 98. break; 99. } 100. } 101. } 102. 103. #define new_loc(i,j) *(new_locations+ ((j)*(WIDTH+1)) + (i)) 104. 105. static void 106. pass_two(bg_typ, fg_typ) 107. schar bg_typ, fg_typ; 108. { 109. register int i,j; 110. short count, dr; 111. 112. for(i=2; i<=WIDTH; i++) 113. for(j=1; j 114. for(count=0, dr=0; dr < 8; dr++) 115. if(get_map(i+dirs[dr*2], j+dirs[(dr*2)+1], bg_typ) 116. == fg_typ) 117. count++; 118. if (count == 5) 119. new_loc(i,j) = bg_typ; 120. else 121. new_loc(i,j) = get_map(i,j, bg_typ); 122. } 123. 124. for(i=2; i<=WIDTH; i++) 125. for(j=1; j 126. levl[i][j].typ = new_loc(i,j); 127. } 128. 129. static void 130. pass_three(bg_typ, fg_typ) 131. schar bg_typ, fg_typ; 132. { 133. register int i,j; 134. short count, dr; 135. 136. for(i=2; i<=WIDTH; i++) 137. for(j=1; j 138. for(count=0, dr=0; dr < 8; dr++) 139. if(get_map(i+dirs[dr*2], j+dirs[(dr*2)+1], bg_typ) 140. == fg_typ) 141. count++; 142. if (count < 3) 143. new_loc(i,j) = bg_typ; 144. else 145. new_loc(i,j) = get_map(i,j, bg_typ); 146. } 147. 148. for(i=2; i<=WIDTH; i++) 149. for(j=1; j 150. levl[i][j].typ = new_loc(i,j); 151. } 152. 153. /* 154. * use a flooding algorithm to find all locations that should 155. * have the same rm number as the current location. 156. * if anyroom is TRUE, use IS_ROOM to check room membership instead of 157. * exactly matching levl[sx][sy].typ and walls are included as well. 158. */ 159. void 160. flood_fill_rm(sx, sy, rmno, lit, anyroom) 161. int sx; 162. register int sy; 163. register int rmno; 164. boolean lit; 165. boolean anyroom; 166. { 167. register int i; 168. int nx; 169. schar fg_typ = levl[sx][sy].typ; 170. 171. /* back up to find leftmost uninitialized location */ 172. while(sx > 0 173. && (anyroom ? IS_ROOM(levl[sx][sy].typ) : levl[sx][sy].typ == fg_typ) 174. && levl[sx][sy].roomno != rmno) 175. sx--; 176. sx++; /* compensate for extra decrement */ 177. 178. /* assume sx,sy is valid */ 179. if(sx < min_rx) min_rx = sx; 180. if(sy < min_ry) min_ry = sy; 181. 182. for(i=sx; i<=WIDTH && levl[i][sy].typ == fg_typ; i++) { 183. levl[i][sy].roomno = rmno; 184. levl[i][sy].lit = lit; 185. if(anyroom) { 186. /* add walls to room as well */ 187. register int ii,jj; 188. for(ii= (i == sx ? i-1 : i); ii <= i+1; ii++) 189. for(jj = sy-1; jj <= sy+1; jj++) 190. if(isok(ii,jj) && 191. (IS_WALL(levl[ii][jj].typ) || 192. IS_DOOR(levl[ii][jj].typ))) { 193. levl[ii][jj].edge = 1; 194. if(lit) levl[ii][jj].lit = lit; 195. if (levl[ii][jj].roomno != rmno) 196. levl[ii][jj].roomno = SHARED; 197. else 198. levl[ii][jj].roomno = rmno; 199. } 200. } 201. n_loc_filled++; 202. } 203. nx = i; 204. 205. if(isok(sx,sy-1)) 206. for(i=sx; i 207. if(levl[i][sy-1].typ == fg_typ) { 208. if(levl[i][sy-1].roomno != rmno) 209. flood_fill_rm(i,sy-1,rmno,lit,anyroom); 210. } else { 211. if((i>sx || isok(i-1,sy-1)) && 212. levl[i-1][sy-1].typ == fg_typ) { 213. if(levl[i-1][sy-1].roomno != rmno) 214. flood_fill_rm(i-1,sy-1,rmno,lit,anyroom); 215. } 216. if((i 217. levl[i+1][sy-1].typ == fg_typ) { 218. if(levl[i+1][sy-1].roomno != rmno) 219. flood_fill_rm(i+1,sy-1,rmno,lit,anyroom); 220. } 221. } 222. if(isok(sx,sy+1)) 223. for(i=sx; i 224. if(levl[i][sy+1].typ == fg_typ) { 225. if(levl[i][sy+1].roomno != rmno) 226. flood_fill_rm(i,sy+1,rmno,lit,anyroom); 227. } else { 228. if((i>sx || isok(i-1,sy+1)) && 229. levl[i-1][sy+1].typ == fg_typ) { 230. if(levl[i-1][sy+1].roomno != rmno) 231. flood_fill_rm(i-1,sy+1,rmno,lit,anyroom); 232. } 233. if((i 234. levl[i+1][sy+1].typ == fg_typ) { 235. if(levl[i+1][sy+1].roomno != rmno) 236. flood_fill_rm(i+1,sy+1,rmno,lit,anyroom); 237. } 238. } 239. 240. if(nx > max_rx) max_rx = nx - 1; /* nx is just past valid region */ 241. if(sy > max_ry) max_ry = sy; 242. } 243. 244. /* 245. * If we have drawn a map without walls, this allows us to 246. * auto-magically wallify it. Taken from lev_main.c. 247. */ 248. static void 249. wallify_map() 250. { 251. 252. int x, y, xx, yy; 253. 254. for(x = 1; x < COLNO; x++) 255. for(y = 0; y < ROWNO; y++) 256. if(levl[x][y].typ == STONE) { 257. for(yy = y - 1; yy <= y+1; yy++) 258. for(xx = x - 1; xx <= x+1; xx++) 259. if(isok(xx,yy) && levl[xx][yy].typ == ROOM) { 260. if(yy != y) levl[x][y].typ = HWALL; 261. else levl[x][y].typ = VWALL; 262. } 263. } 264. } 265. 266. static void 267. join_map(bg_typ, fg_typ) 268. schar bg_typ, fg_typ; 269. { 270. register struct mkroom *croom, *croom2; 271. 272. register int i, j; 273. int sx, sy; 274. coord sm, em; 275. 276. /* first, use flood filling to find all of the regions that need joining */ 277. for(i=2; i<=WIDTH; i++) 278. for(j=1; j 279. if(levl[i][j].typ == fg_typ && levl[i][j].roomno == NO_ROOM) { 280. min_rx = max_rx = i; 281. min_ry = max_ry = j; 282. n_loc_filled = 0; 283. flood_fill_rm(i,j,nroom+ROOMOFFSET,FALSE,FALSE); 284. if(n_loc_filled > 3) { 285. add_room(min_rx, min_ry, max_rx, max_ry, 286. FALSE, OROOM, TRUE); 287. rooms[nroom-1].irregular = TRUE; 288. if(nroom >= (MAXNROFROOMS*2)) 289. goto joinm; 290. } else { 291. /* 292. * it's a tiny hole; erase it from the map to avoid 293. * having the player end up here with no way out. 294. */ 295. for(sx = min_rx; sx<=max_rx; sx++) 296. for(sy = min_ry; sy<=max_ry; sy++) 297. if(levl[sx][sy].roomno == nroom+ROOMOFFSET) { 298. levl[sx][sy].typ = bg_typ; 299. levl[sx][sy].roomno = NO_ROOM; 300. } 301. } 302. } 303. } 304. 305. joinm: 306. /* 307. * Ok, now we can actually join the regions with fg_typ's. 308. * The rooms are already sorted due to the previous loop, 309. * so don't call sort_rooms(), which can screw up the roomno's 310. * validity in the levl structure. 311. */ 312. for(croom = &rooms[0], croom2 = croom + 1; croom2 < &rooms[nroom]; ) { 313. /* pick random starting and end locations for "corridor" */ 314. if(!somexy(croom, &sm) || !somexy(croom2, &em)) { 315. /* ack! -- the level is going to be busted */ 316. /* arbitrarily pick centers of both rooms and hope for the best */ 317. impossible("No start/end room loc in join_map."); 318. sm.x = croom->lx + ((croom->hx - croom->lx) / 2); 319. sm.y = croom->ly + ((croom->hy - croom->ly) / 2); 320. em.x = croom2->lx + ((croom2->hx - croom2->lx) / 2); 321. em.y = croom2->ly + ((croom2->hy - croom2->ly) / 2); 322. } 323. 324. (void) dig_corridor(sm, em, FALSE, fg_typ, bg_typ); 325. 326. /* choose next region to join */ 327. /* only increment croom if croom and croom2 are non-overlapping */ 328. if(croom2->lx > croom->hx || 329. ((croom2->ly > croom->hy || croom2->hy < croom->ly) && rn2(3))) { 330. croom = croom2; 331. } 332. croom2++; /* always increment the next room */ 333. } 334. } 335. 336. static void 337. finish_map(fg_typ, bg_typ, lit, walled) 338. schar fg_typ, bg_typ; 339. boolean lit, walled; 340. { 341. int i, j; 342. 343. if(walled) wallify_map(); 344. 345. if(lit) { 346. for(i=1; i 347. for(j=0; j 348. if((!IS_ROCK(fg_typ) && levl[i][j].typ == fg_typ) || 349. (!IS_ROCK(bg_typ) && levl[i][j].typ == bg_typ) || 350. (walled && IS_WALL(levl[i][j].typ))) 351. levl[i][j].lit = TRUE; 352. for(i = 0; i < nroom; i++) 353. rooms[i].rlit = 1; 354. } 355. } 356. 357. #define N_P1_ITER 1 /* tune map generation via this value */ 358. #define N_P2_ITER 1 /* tune map generation via this value */ 359. #define N_P3_ITER 2 /* tune map smoothing via this value */ 360. 361. void 362. mkmap(init_lev) 363. 364. lev_init *init_lev; 365. { 366. schar bg_typ = init_lev->bg, 367. fg_typ = init_lev->fg; 368. boolean smooth = init_lev->smoothed, 369. join = init_lev->joined; 370. xchar lit = init_lev->lit, 371. walled = init_lev->walled; 372. int i; 373. 374. if(lit < 0) 375. lit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77)) ? 1 : 0; 376. 377. new_locations = (char *)alloc((WIDTH+1) * HEIGHT); 378. 379. init_map(bg_typ); 380. init_fill(bg_typ, fg_typ); 381. 382. for(i = 0; i < N_P1_ITER; i++) 383. pass_one(bg_typ, fg_typ); 384. 385. for(i = 0; i < N_P2_ITER; i++) 386. pass_two(bg_typ, fg_typ); 387. 388. if(smooth) 389. for(i = 0; i < N_P3_ITER; i++) 390. pass_three(bg_typ, fg_typ); 391. 392. if(join) 393. join_map(bg_typ, fg_typ); 394. 395. finish_map(fg_typ, bg_typ, (boolean)lit, (boolean)walled); 396. /* a walled, joined level is cavernous, not mazelike -dlc */ 397. if (walled && join) { 398. level.flags.is_maze_lev = FALSE; 399. level.flags.is_cavernous_lev = TRUE; 400. } 401. free(new_locations); 402. }
|