Source:NetHack 3.0.0/mkmaze.c
Jump to navigation
Jump to search
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
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.
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. }