abstract
| - Below is the full text to mkmaze.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.0/mkmaze.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code 1. /* SCCS Id: @(#)mkmaze.c 3.0 88/10/25 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. #include "hack.h" 6. 7. extern int x_maze_max, y_maze_max; 8. 9. #if defined(WALLIFIED_MAZE) || defined(STRONGHOLD) 10. static int 11. iswall(x,y) 12. int x,y; 13. { 14. # ifndef WALLIFIED_MAZE 15. if (x<0 || y<0 || x>COLNO-1 || y>ROWNO-1) 16. # else 17. if (x<0 || y<0 || x>COLNO || y>ROWNO) 18. # endif 19. return 0; 20. return (IS_WALL(levl[x][y].typ) || IS_DOOR(levl[x][y].typ) 21. || levl[x][y].typ == SDOOR); 22. } 23. 24. void 25. wallification(x1, y1, x2, y2, see) 26. int x1, y1, x2, y2; 27. boolean see; 28. { 29. char type; 30. short x,y; 31. register struct rm *room; 32. 33. if (x1 < 0) x1 = 0; 34. if (x2 < x1) x2 = x1; 35. if (x2 > COLNO-1) x2 = COLNO-1; 36. if (x1 > x2) x1 = x2; 37. if (y1 < 0) y1 = 0; 38. if (y2 < y1) y2 = y1; 39. if (y2 > COLNO-1) y2 = ROWNO-1; 40. if (y1 > y2) y1 = y2; 41. for(x = x1; x <= x2; x++) 42. for(y = y1; y <= y2; y++) { 43. room = &levl[x][y]; 44. type = room->typ; 45. if (iswall(x,y)) { 46. if (IS_DOOR(type)) { 47. room->scrsym = DOOR_SYM; 48. continue; 49. } else 50. if (iswall(x,y-1)) 51. if (iswall(x,y+1)) 52. if (iswall(x-1,y)) 53. if (iswall(x+1,y)) { 54. room->scrsym = CRWALL_SYM; /* -+- */ 55. room->typ = CROSSWALL; 56. } else { 57. room->scrsym = TLWALL_SYM; /* -| */ 58. room->typ = TLWALL; 59. } 60. else 61. if (iswall(x+1,y)) { 62. room->scrsym = TRWALL_SYM; /* |- */ 63. room->typ = TRWALL; 64. } else { 65. room->typ = VWALL; 66. #ifdef STRONGHOLD 67. if (is_drawbridge_wall(x,y) >= 0) 68. room->scrsym = DB_VWALL_SYM; 69. else 70. #endif 71. room->scrsym = VWALL_SYM; /* | */ 72. } 73. else 74. if (iswall(x-1,y)) 75. if (iswall(x+1,y)) { 76. room->scrsym = TUWALL_SYM; /* | */ 77. room->typ = TUWALL; /* -+- */ 78. } else { 79. room->scrsym = BRCORN_SYM; /* | */ 80. room->typ = BRCORNER; /* -+ */ 81. } 82. else 83. if (iswall(x+1,y)) { 84. room->scrsym = BLCORN_SYM; /* | */ 85. room->typ = BLCORNER; /* +- */ 86. } else { 87. room->typ = VWALL; 88. #ifdef STRONGHOLD 89. if (is_drawbridge_wall(x,y) >= 0) 90. room->scrsym = DB_VWALL_SYM; 91. else 92. #endif 93. room->scrsym = VWALL_SYM; /* | */ 94. } 95. else 96. if (iswall(x,y+1)) 97. if (iswall(x-1,y)) 98. if (iswall(x+1,y)) { 99. room->scrsym = TDWALL_SYM; /* -+- */ 100. room->typ = TDWALL; /* | */ 101. } else { 102. room->scrsym = TRCORN_SYM; /* -+ */ 103. room->typ = TRCORNER; /* | */ 104. } 105. else 106. if (iswall(x+1,y)) { 107. room->scrsym = TLCORN_SYM; /* +- */ 108. room->typ = TLCORNER; /* | */ 109. } else { 110. room->typ = VWALL; 111. #ifdef STRONGHOLD 112. if (is_drawbridge_wall(x,y) >= 0) 113. room->scrsym = DB_VWALL_SYM; 114. else 115. #endif 116. room->scrsym = VWALL_SYM; /* | */ 117. } 118. else { 119. room->typ = HWALL; 120. #ifdef STRONGHOLD 121. if (is_drawbridge_wall(x,y) >= 0) 122. room->scrsym = DB_HWALL_SYM; 123. else 124. #endif 125. room->scrsym = HWALL_SYM; 126. } 127. if (type == SDOOR) room->typ = type; 128. if (see) room->seen = 0; 129. } else { 130. switch(room->typ) { 131. case STONE: 132. room->scrsym = STONE_SYM; 133. break; 134. case CORR: 135. room->scrsym = CORR_SYM; 136. break; 137. case ROOM: 138. room->scrsym = ROOM_SYM; 139. } 140. if (see) room->seen = 0; 141. } 142. } 143. } 144. #endif /* WALLIFIED_MAZE /**/ 145. 146. static boolean 147. okay(x,y,dir) 148. int x,y; 149. register int dir; 150. { 151. move(&x,&y,dir); 152. move(&x,&y,dir); 153. if(x<3 || y<3 || x>x_maze_max || y>y_maze_max || levl[x][y].typ != 0) 154. return(FALSE); 155. return(TRUE); 156. } 157. 158. static void 159. maze0xy(cc) /* find random starting point for maze generation */ 160. coord *cc; 161. { 162. cc->x = 3 + 2*rn2((x_maze_max>>1) - 1); 163. cc->y = 3 + 2*rn2((y_maze_max>>1) - 1); 164. return; 165. } 166. 167. static const uchar tower[] = { 168. MOAT, MOAT, MOAT, MOAT, MOAT, MOAT, MOAT, 169. MOAT, MOAT, TLCORNER, HWALL, TRCORNER, MOAT, MOAT, 170. MOAT, TLCORNER, BRCORNER, ROOM, BLCORNER, TRCORNER, MOAT, 171. MOAT, VWALL, ROOM, ROOM, ROOM, VWALL, MOAT, 172. MOAT, BLCORNER, TRCORNER, ROOM, TLCORNER, BRCORNER, MOAT, 173. MOAT, MOAT, BLCORNER, HWALL, BRCORNER, MOAT, MOAT, 174. MOAT, MOAT, MOAT, MOAT, MOAT, MOAT, MOAT, 175. }; 176. 177. void 178. makemaz() 179. { 180. int x,y; 181. register int zx,zy; 182. coord mm; 183. int i; 184. 185. is_maze_lev = TRUE; 186. #ifdef STRONGHOLD 187. xdnladder = ydnladder = xupladder = yupladder = 0; 188. if (dlevel == stronghold_level) { 189. if (load_special("castle")) { 190. xupstair = yupstair = 3; 191. levl[xupstair][yupstair].scrsym = UP_SYM; 192. levl[xupstair][yupstair].typ = STAIRS; 193. return; 194. } 195. impossible("Cannot build the STRONGHOLD!"); 196. } 197. if (dlevel == tower_level) { 198. if (load_special("tower1")) { 199. xupstair = yupstair = 3; 200. levl[xupstair][yupstair].scrsym = UP_SYM; 201. levl[xupstair][yupstair].typ = STAIRS; 202. return; 203. } 204. impossible("Cannot build the TOWER!"); 205. } 206. if (dlevel == tower_level+1) { 207. if (load_special("tower2")) { 208. xupstair = yupstair = 3; 209. levl[xupstair][yupstair].scrsym = UP_SYM; 210. levl[xupstair][yupstair].typ = STAIRS; 211. return; 212. } 213. impossible("Cannot build the TOWER!"); 214. } 215. if (dlevel == tower_level+2) { 216. if (load_special("tower3")) { 217. xupstair = yupstair = 3; 218. levl[xupstair][yupstair].scrsym = UP_SYM; 219. levl[xupstair][yupstair].typ = STAIRS; 220. return; 221. } 222. impossible("Cannot build the TOWER!"); 223. } 224. # ifdef ENDGAME 225. if (dlevel == ENDLEVEL) { /* EndGame level */ 226. if (load_special("endgame")) { 227. pline("Well done, mortal!"); 228. pline("But now thou must face the final Test..."); 229. pline("Prove thyself worthy or perish!"); 230. u.ux = x_maze_max - 1; 231. u.uy = y_maze_max - 1; 232. xupstair = yupstair = 0; 233. return; 234. } 235. impossible("Cannot build the EndGame Level!"); 236. done("escaped"); 237. } 238. # endif 239. #endif 240. #ifndef WALLIFIED_MAZE 241. for(x = 2; x < x_maze_max; x++) 242. for(y = 2; y < y_maze_max; y++) 243. levl[x][y].typ = STONE; 244. #else 245. for(x = 2; x <= x_maze_max; x++) 246. for(y = 2; y <= y_maze_max; y++) 247. levl[x][y].typ = ((x % 2) && (y % 2)) ? STONE : HWALL; 248. #endif 249. 250. /* make decoy wizard levels */ 251. if((dlevel == wiz_level) || 252. #ifdef STRONGHOLD 253. (!rn2(3) && (dlevel > stronghold_level+1))) { 254. #else 255. (!rn2(3) && (dlevel > medusa_level+1))) { 256. #endif 257. 258. register struct monst *mtmp; 259. 260. zx = x_maze_max / 2; 261. zy = y_maze_max / 2; 262. if (!(zx % 2)) zx++; 263. if (!(zy % 2)) zy++; 264. for(y = zy-3, i=0; y <= zy+3; y++) 265. for(x = zx-3; x <= zx+3; x++) 266. levl[x][y].typ = tower[i++]; 267. walkfrom(zx+4, zy); 268. if(mtmp = makemon(&mons[PM_HELL_HOUND], zx+1, zy)) 269. mtmp->msleep = 1; 270. (void) makemon(&mons[PM_KRAKEN], zx+2, zy+2); 271. if (dlevel == wiz_level) { 272. 273. (void) mksobj_at(AMULET_OF_YENDOR, zx, zy); 274. flags.made_amulet = 1; 275. #ifndef STRONGHOLD 276. if(mtmp = makemon(&mons[PM_VLAD_THE_IMPALER], zx-1, zy)) 277. mtmp->msleep = 1; 278. #endif 279. if(mtmp = makemon(&mons[PM_WIZARD_OF_YENDOR], zx, zy)) 280. mtmp->msleep = 1; 281. } else { 282. struct obj *ot; 283. /* make a cheap plastic imitation */ 284. if (ot = mksobj_at(AMULET_OF_YENDOR, zx, zy)) 285. ot-> spe = -1; 286. #ifndef STRONGHOLD 287. if (mtmp = makemon(&mons[PM_VAMPIRE_LORD], zx-1, zy)) 288. mtmp->msleep = 1; 289. #endif 290. (void) makemon(&mons[dprince()], zx, zy); 291. } 292. /* they should wake up when we intrude */ 293. (void) maketrap(zx-1, zy, SQBRD); 294. (void) maketrap(zx+1, zy, SQBRD); 295. (void) maketrap(zx, zy-1, SQBRD); 296. (void) maketrap(zx, zy+1, SQBRD); 297. } else { 298. maze0xy(&mm); 299. zx = mm.x; 300. zy = mm.y; 301. walkfrom(zx,zy); 302. #ifndef STRONGHOLD /* it's in the castle */ 303. # ifdef HARD /* only one wand of wishing created */ 304. if(!rn2(10) || (dlevel == medusa_level + 1)) 305. # endif 306. (void) mksobj_at(WAN_WISHING, zx, zy); 307. #endif 308. (void) mksobj_at(BOULDER, zx, zy); /* put a boulder on top of it */ 309. } 310. 311. #ifdef WALLIFIED_MAZE 312. wallification(2, 2, x_maze_max, y_maze_max, TRUE); 313. #else 314. for(x = 2; x < x_maze_max; x++) 315. for(y = 2; y < y_maze_max; y++) { 316. switch(levl[x][y].typ) { 317. case STONE: 318. levl[x][y].scrsym = STONE_SYM; 319. break; 320. case CORR: 321. levl[x][y].scrsym = CORR_SYM; 322. break; 323. case ROOM: 324. levl[x][y].scrsym = ROOM_SYM; 325. break; 326. case HWALL: 327. levl[x][y].scrsym = HWALL_SYM; 328. break; 329. case VWALL: 330. levl[x][y].scrsym = VWALL_SYM; 331. break; 332. case TLCORNER: 333. levl[x][y].scrsym = TLCORN_SYM; 334. break; 335. case TRCORNER: 336. levl[x][y].scrsym = TRCORN_SYM; 337. break; 338. case BLCORNER: 339. levl[x][y].scrsym = BLCORN_SYM; 340. break; 341. case BRCORNER: 342. levl[x][y].scrsym = BRCORN_SYM; 343. break; 344. } 345. } 346. #endif 347. mazexy(&mm); 348. levl[(xupstair = mm.x)][(yupstair = mm.y)].scrsym = UP_SYM; 349. levl[xupstair][yupstair].typ = STAIRS; 350. xdnstair = ydnstair = 0; 351. #ifdef STRONGHOLD 352. if (dlevel < stronghold_level) { 353. mazexy(&mm); 354. levl[(xdnstair = mm.x)][(ydnstair = mm.y)].scrsym = DN_SYM; 355. levl[xdnstair][ydnstair].typ = STAIRS; 356. } 357. #endif 358. for(x = rn1(8,11); x; x--) { 359. mazexy(&mm); 360. (void) mkobj_at(rn2(2) ? GEM_SYM : 0, mm.x, mm.y); 361. } 362. for(x = rn1(10,2); x; x--) { 363. mazexy(&mm); 364. (void) mksobj_at(BOULDER, mm.x, mm.y); 365. } 366. mazexy(&mm); 367. (void) makemon(&mons[PM_MINOTAUR], mm.x, mm.y); 368. for(x = rn1(5,7); x; x--) { 369. mazexy(&mm); 370. (void) makemon((struct permonst *) 0, mm.x, mm.y); 371. } 372. for(x = rn1(6,7); x; x--) { 373. mazexy(&mm); 374. mkgold(0L,mm.x,mm.y); 375. } 376. for(x = rn1(6,7); x; x--) 377. mktrap(0,1,(struct mkroom *) 0); 378. } 379. 380. #ifdef MSDOS 381. /* Make the mazewalk iterative by faking a stack. This is needed to 382. * ensure the mazewalk is successful in the limited stack space of 383. * the program. This iterative version uses the mimumum amount of stack 384. * that is totally safe. 385. */ 386. void 387. walkfrom(x,y) 388. int x,y; 389. { 390. #define CELLS (ROWNO * COLNO) / 4 /* a maze cell is 4 squares */ 391. char mazex[CELLS + 1], mazey[CELLS + 1]; /* char's are OK */ 392. int q, a, dir, pos; 393. int dirs[4]; 394. 395. pos = 1; 396. mazex[pos] = (char) x; 397. mazey[pos] = (char) y; 398. while (pos) { 399. x = (int) mazex[pos]; 400. y = (int) mazey[pos]; 401. #ifndef WALLIFIED_MAZE 402. levl[x][y].typ = CORR; 403. #else 404. levl[x][y].typ = ROOM; 405. #endif 406. q = 0; 407. for (a = 0; a < 4; a++) 408. if(okay(x, y, a)) dirs[q++]= a; 409. if (!q) 410. pos--; 411. else { 412. dir = dirs[rn2(q)]; 413. move(&x, &y, dir); 414. #ifndef WALLIFIED_MAZE 415. levl[x][y].typ = CORR; 416. #else 417. levl[x][y].typ = ROOM; 418. #endif 419. move(&x, &y, dir); 420. pos++; 421. if (pos > CELLS) 422. panic("Overflow in walkfrom"); 423. mazex[pos] = (char) x; 424. mazey[pos] = (char) y; 425. } 426. } 427. } 428. #else 429. 430. void 431. walkfrom(x,y) int x,y; { 432. register int q,a,dir; 433. int dirs[4]; 434. #ifndef WALLIFIED_MAZE 435. levl[x][y].typ = CORR; 436. #else 437. levl[x][y].typ = ROOM; 438. #endif 439. while(1) { 440. q = 0; 441. for(a = 0; a < 4; a++) 442. if(okay(x,y,a)) dirs[q++]= a; 443. if(!q) return; 444. dir = dirs[rn2(q)]; 445. move(&x,&y,dir); 446. #ifndef WALLIFIED_MAZE 447. levl[x][y].typ = CORR; 448. #else 449. levl[x][y].typ = ROOM; 450. #endif 451. move(&x,&y,dir); 452. walkfrom(x,y); 453. } 454. } 455. #endif /* MSDOS */ 456. 457. void 458. move(x,y,dir) 459. register int *x, *y; 460. register int dir; 461. { 462. switch(dir){ 463. case 0: --(*y); break; 464. case 1: (*x)++; break; 465. case 2: (*y)++; break; 466. case 3: --(*x); break; 467. } 468. } 469. 470. void 471. mazexy(cc) /* find random point in generated corridors 472. i.e., don't create items in moats, bunkers, or walls */ 473. coord *cc; 474. { 475. int cpt=0; 476. 477. do { 478. cc->x = 3 + 2*rn2((x_maze_max>>1) - 1); 479. cc->y = 3 + 2*rn2((y_maze_max>>1) - 1); 480. cpt++; 481. #ifndef WALLIFIED_MAZE 482. } while (cpt < 100 && levl[cc->x][cc->y].typ != CORR); 483. #else 484. } while (cpt < 100 && levl[cc->x][cc->y].typ != ROOM); 485. #endif 486. if (cpt >= 100) panic("mazexy: can't find a place!"); 487. return; 488. } 489. 490. void 491. bound_digging() 492. /* put a non-diggable boundary around the initial portion of a level map. 493. * assumes that no level will initially put things beyond the isok() range. 494. */ 495. { 496. register int x,y; 497. register boolean found; 498. int xmin,xmax,ymin,ymax; 499. 500. found = FALSE; 501. for(xmin=1; !found; xmin++) 502. for(y=0; y<=ROWNO-1; y++) 503. if(levl[xmin][y].typ != STONE) found = TRUE; 504. xmin -= 2; 505. 506. found = FALSE; 507. for(xmax=COLNO-2; !found; xmax--) 508. for(y=0; y<=ROWNO-1; y++) 509. if(levl[xmax][y].typ != STONE) found = TRUE; 510. xmax += 2; 511. 512. found = FALSE; 513. for(ymin=1; !found; ymin++) 514. for(x=xmin; x<=xmax; x++) 515. if(levl[x][ymin].typ != STONE) found = TRUE; 516. ymin -= 2; 517. 518. found = FALSE; 519. for(ymax=ROWNO-2; !found; ymax--) 520. for(x=xmin; x<=xmax; x++) 521. if(levl[x][ymax].typ != STONE) found = TRUE; 522. ymax += 2; 523. 524. for(x=xmin; x<=xmax; x++) { 525. levl[x][ymin].diggable = W_NONDIGGABLE; 526. levl[x][ymax].diggable = W_NONDIGGABLE; 527. } 528. 529. for(y=ymin; y<=ymax; y++) { 530. levl[xmin][y].diggable = W_NONDIGGABLE; 531. levl[xmax][y].diggable = W_NONDIGGABLE; 532. } 533. }
|