1 /* 2 * Maze drawing routines. Based on the algorithm presented in the 3 * December 1981 Byte "How to Build a Maze" by David Matuszek. 4 * 5 * maze.c 1.4 (A.I. Design) 12/14/84 6 */ 7 8 #include "rogue.h" 9 #include "curses.h" 10 extern int maxrow; 11 12 #define MAXFRNT 100 13 14 #define FRONTIER 'F' 15 #define NOTHING ' ' 16 17 static shint frcnt, ny, nx, topy, topx; 18 static shint maxx, maxy; 19 static shint *fr_y, *fr_x; 20 21 draw_maze(rp) 22 struct room *rp; 23 { 24 register int y, x; 25 shint fy[MAXFRNT], fx[MAXFRNT]; 26 int psgcnt; 27 coord spos; 28 29 fr_y = fy; 30 fr_x = fx; 31 maxx = maxy = 0; 32 topy = rp->r_pos.y; 33 if (topy == 0) 34 topy = ++rp->r_pos.y; 35 topx = rp->r_pos.x; 36 /* 37 * Choose a random spot in the maze and initialize the frontier 38 * to be the immediate neighbors of this random spot. 39 */ 40 y = topy; 41 x = topx; 42 splat(y,x); 43 new_frontier(y, x); 44 /* 45 * While there are new frontiers, connect them to the path and 46 * possibly expand the frontier even more. 47 */ 48 while(frcnt) 49 { 50 con_frnt(); 51 new_frontier(ny, nx); 52 } 53 /* 54 * According to the Grand Beeking, every maze should have a loop 55 * Don't worry if you don't understand this. 56 */ 57 rp->r_max.x = maxx - rp->r_pos.x + 1; 58 rp->r_max.y = maxy - rp->r_pos.y + 1; 59 do { 60 static coord ld[4] = { 61 -1, 0, 62 0, 1, 63 1, 0, 64 0, -1 65 }; 66 coord *cp; 67 int sh; 68 69 rnd_pos(rp, &spos); 70 for (psgcnt = 0,cp = ld,sh = 1; cp < &ld[4]; sh <<= 1,cp++) { 71 y = cp->y + spos.y; x = cp->x + spos.x; 72 if (!offmap(y, x) && chat(y, x) == PASSAGE) 73 psgcnt += sh; 74 } 75 } while (chat(spos.y, spos.x) == PASSAGE || psgcnt % 5); 76 splat(spos.y, spos.x); 77 } 78 79 new_frontier(y, x) 80 int y, x; 81 { 82 add_frnt(y-2, x); 83 add_frnt(y+2, x); 84 add_frnt(y, x-2); 85 add_frnt(y, x+2); 86 } 87 88 add_frnt(y, x) 89 int y, x; 90 { 91 #ifdef DEBUG 92 if (frcnt == MAXFRNT - 1) 93 debug("MAZE DRAWING ERROR #3\n"); 94 #endif 95 if (inrange(y, x) && chat(y, x) == NOTHING) 96 { 97 chat(y, x) = FRONTIER; 98 fr_y[frcnt] = y; 99 fr_x[frcnt++] = x; 100 } 101 } 102 103 /* 104 * Connect randomly to one of the adjacent points in the spanning tree 105 */ 106 con_frnt() 107 { 108 register int n, which, ydelt = 0, xdelt = 0; 109 int choice[4]; 110 int cnt = 0, y, x; 111 112 113 /* 114 * Choose a random frontier 115 */ 116 n = rnd(frcnt); 117 ny = fr_y[n]; 118 nx = fr_x[n]; 119 fr_y[n] = fr_y[frcnt-1]; 120 fr_x[n] = fr_x[--frcnt]; 121 122 /* 123 * Count and collect the adjacent points we can connect to 124 */ 125 if (maze_at(ny-2, nx) > 0) 126 choice[cnt++] = 0; 127 if (maze_at(ny+2, nx) > 0) 128 choice[cnt++] = 1; 129 if (maze_at(ny, nx-2) > 0) 130 choice[cnt++] = 2; 131 if (maze_at(ny, nx+2) > 0) 132 choice[cnt++] = 3; 133 /* 134 * Choose one of the open places, connect to it and 135 * then the task is complete 136 */ 137 which = choice[rnd(cnt)]; 138 splat(ny, nx); 139 switch(which) 140 { 141 when 0: which = 1; ydelt = -1; 142 when 1: which = 0; ydelt = 1; 143 when 2: which = 3; xdelt = -1; 144 when 3: which = 2; xdelt = 1; 145 } 146 y = ny + ydelt; 147 x = nx + xdelt; 148 if (inrange(y, x)) 149 splat(y, x); 150 } 151 152 maze_at(y, x) 153 { 154 if (inrange(y, x) && chat(y, x) == PASSAGE) 155 return 1; 156 else 157 return 0; 158 } 159 160 splat(y, x) 161 { 162 chat(y, x) = PASSAGE; 163 flat(y, x) = F_MAZE|F_REAL; 164 if (x > maxx) 165 maxx = x; 166 if (y > maxy) 167 maxy = y; 168 } 169 170 #define MAXY (topy+((maxrow+1)/3)) 171 #define MAXX (topx+COLS/3) 172 173 inrange(y, x) 174 int x, y; 175 { 176 return(y >= topy && y < MAXY && x >= topx && x < MAXX); 177 } 178 ÿ