makemaze.c revision 1.1 1 1.1 mrg /*
2 1.1 mrg * Hunt
3 1.1 mrg * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
4 1.1 mrg * San Francisco, California
5 1.1 mrg */
6 1.1 mrg
7 1.1 mrg # include "hunt.h"
8 1.1 mrg
9 1.1 mrg # define ISCLEAR(y,x) (Maze[y][x] == SPACE)
10 1.1 mrg # define ODD(n) ((n) & 01)
11 1.1 mrg
12 1.1 mrg makemaze()
13 1.1 mrg {
14 1.1 mrg register char *sp;
15 1.1 mrg register int y, x;
16 1.1 mrg
17 1.1 mrg /*
18 1.1 mrg * fill maze with walls
19 1.1 mrg */
20 1.1 mrg sp = &Maze[0][0];
21 1.1 mrg while (sp < &Maze[HEIGHT - 1][WIDTH])
22 1.1 mrg *sp++ = DOOR;
23 1.1 mrg
24 1.1 mrg x = rand_num(WIDTH / 2) * 2 + 1;
25 1.1 mrg y = rand_num(HEIGHT / 2) * 2 + 1;
26 1.1 mrg dig_maze(x, y);
27 1.1 mrg remap();
28 1.1 mrg }
29 1.1 mrg
30 1.1 mrg # define NPERM 24
31 1.1 mrg # define NDIR 4
32 1.1 mrg
33 1.1 mrg int dirs[NPERM][NDIR] = {
34 1.1 mrg {0,1,2,3}, {3,0,1,2}, {0,2,3,1}, {0,3,2,1},
35 1.1 mrg {1,0,2,3}, {2,3,0,1}, {0,2,1,3}, {2,3,1,0},
36 1.1 mrg {1,0,3,2}, {1,2,0,3}, {3,1,2,0}, {2,0,3,1},
37 1.1 mrg {1,3,0,2}, {0,3,1,2}, {1,3,2,0}, {2,0,1,3},
38 1.1 mrg {0,1,3,2}, {3,1,0,2}, {2,1,0,3}, {1,2,3,0},
39 1.1 mrg {2,1,3,0}, {3,0,2,1}, {3,2,0,1}, {3,2,1,0}
40 1.1 mrg };
41 1.1 mrg
42 1.1 mrg int incr[NDIR][2] = {
43 1.1 mrg {0, 1}, {1, 0}, {0, -1}, {-1, 0}
44 1.1 mrg };
45 1.1 mrg
46 1.1 mrg dig(y, x)
47 1.1 mrg int y, x;
48 1.1 mrg {
49 1.1 mrg register int *dp;
50 1.1 mrg register int *ip;
51 1.1 mrg register int ny, nx;
52 1.1 mrg register int *endp;
53 1.1 mrg
54 1.1 mrg Maze[y][x] = SPACE; /* Clear this spot */
55 1.1 mrg dp = dirs[rand_num(NPERM)];
56 1.1 mrg endp = &dp[NDIR];
57 1.1 mrg while (dp < endp) {
58 1.1 mrg ip = &incr[*dp++][0];
59 1.1 mrg ny = y + *ip++;
60 1.1 mrg nx = x + *ip;
61 1.1 mrg if (candig(ny, nx))
62 1.1 mrg dig(ny, nx);
63 1.1 mrg }
64 1.1 mrg }
65 1.1 mrg
66 1.1 mrg /*
67 1.1 mrg * candig:
68 1.1 mrg * Is it legal to clear this spot?
69 1.1 mrg */
70 1.1 mrg candig(y, x)
71 1.1 mrg register int y, x;
72 1.1 mrg {
73 1.1 mrg register int i;
74 1.1 mrg
75 1.1 mrg if (ODD(x) && ODD(y))
76 1.1 mrg return FALSE; /* can't touch ODD spots */
77 1.1 mrg
78 1.1 mrg if (y < UBOUND || y >= DBOUND)
79 1.1 mrg return FALSE; /* Beyond vertical bounds, NO */
80 1.1 mrg if (x < LBOUND || x >= RBOUND)
81 1.1 mrg return FALSE; /* Beyond horizontal bounds, NO */
82 1.1 mrg
83 1.1 mrg if (ISCLEAR(y, x))
84 1.1 mrg return FALSE; /* Already clear, NO */
85 1.1 mrg
86 1.1 mrg i = ISCLEAR(y, x + 1);
87 1.1 mrg i += ISCLEAR(y, x - 1);
88 1.1 mrg if (i > 1)
89 1.1 mrg return FALSE; /* Introduces cycle, NO */
90 1.1 mrg i += ISCLEAR(y + 1, x);
91 1.1 mrg if (i > 1)
92 1.1 mrg return FALSE; /* Introduces cycle, NO */
93 1.1 mrg i += ISCLEAR(y - 1, x);
94 1.1 mrg if (i > 1)
95 1.1 mrg return FALSE; /* Introduces cycle, NO */
96 1.1 mrg
97 1.1 mrg return TRUE; /* OK */
98 1.1 mrg }
99 1.1 mrg
100 1.1 mrg dig_maze(x, y)
101 1.1 mrg int x, y;
102 1.1 mrg {
103 1.1 mrg register int tx, ty;
104 1.1 mrg register int i, j;
105 1.1 mrg int order[4];
106 1.1 mrg #define MNORTH 0x1
107 1.1 mrg #define MSOUTH 0x2
108 1.1 mrg #define MEAST 0x4
109 1.1 mrg #define MWEST 0x8
110 1.1 mrg
111 1.1 mrg Maze[y][x] = SPACE;
112 1.1 mrg order[0] = MNORTH;
113 1.1 mrg for (i = 1; i < 4; i++) {
114 1.1 mrg j = rand_num(i + 1);
115 1.1 mrg order[i] = order[j];
116 1.1 mrg order[j] = 0x1 << i;
117 1.1 mrg }
118 1.1 mrg for (i = 0; i < 4; i++) {
119 1.1 mrg switch (order[i]) {
120 1.1 mrg case MNORTH:
121 1.1 mrg tx = x;
122 1.1 mrg ty = y - 2;
123 1.1 mrg break;
124 1.1 mrg case MSOUTH:
125 1.1 mrg tx = x;
126 1.1 mrg ty = y + 2;
127 1.1 mrg break;
128 1.1 mrg case MEAST:
129 1.1 mrg tx = x + 2;
130 1.1 mrg ty = y;
131 1.1 mrg break;
132 1.1 mrg case MWEST:
133 1.1 mrg tx = x - 2;
134 1.1 mrg ty = y;
135 1.1 mrg break;
136 1.1 mrg }
137 1.1 mrg if (tx < 0 || ty < 0 || tx >= WIDTH || ty >= HEIGHT)
138 1.1 mrg continue;
139 1.1 mrg if (Maze[ty][tx] == SPACE)
140 1.1 mrg continue;
141 1.1 mrg Maze[(y + ty) / 2][(x + tx) / 2] = SPACE;
142 1.1 mrg dig_maze(tx, ty);
143 1.1 mrg }
144 1.1 mrg }
145 1.1 mrg
146 1.1 mrg remap()
147 1.1 mrg {
148 1.1 mrg register int y, x;
149 1.1 mrg register char *sp;
150 1.1 mrg register int stat;
151 1.1 mrg
152 1.1 mrg for (y = 0; y < HEIGHT; y++)
153 1.1 mrg for (x = 0; x < WIDTH; x++) {
154 1.1 mrg sp = &Maze[y][x];
155 1.1 mrg if (*sp == SPACE)
156 1.1 mrg continue;
157 1.1 mrg stat = 0;
158 1.1 mrg if (y - 1 >= 0 && Maze[y - 1][x] != SPACE)
159 1.1 mrg stat |= NORTH;
160 1.1 mrg if (y + 1 < HEIGHT && Maze[y + 1][x] != SPACE)
161 1.1 mrg stat |= SOUTH;
162 1.1 mrg if (x + 1 < WIDTH && Maze[y][x + 1] != SPACE)
163 1.1 mrg stat |= EAST;
164 1.1 mrg if (x - 1 >= 0 && Maze[y][x - 1] != SPACE)
165 1.1 mrg stat |= WEST;
166 1.1 mrg switch (stat) {
167 1.1 mrg case WEST | EAST:
168 1.1 mrg case EAST:
169 1.1 mrg case WEST:
170 1.1 mrg *sp = WALL1;
171 1.1 mrg break;
172 1.1 mrg case NORTH | SOUTH:
173 1.1 mrg case NORTH:
174 1.1 mrg case SOUTH:
175 1.1 mrg *sp = WALL2;
176 1.1 mrg break;
177 1.1 mrg case 0:
178 1.1 mrg # ifdef RANDOM
179 1.1 mrg *sp = DOOR;
180 1.1 mrg # endif
181 1.1 mrg # ifdef REFLECT
182 1.1 mrg *sp = rand_num(2) ? WALL4 : WALL5;
183 1.1 mrg # endif
184 1.1 mrg break;
185 1.1 mrg default:
186 1.1 mrg *sp = WALL3;
187 1.1 mrg break;
188 1.1 mrg }
189 1.1 mrg }
190 1.1 mrg memcpy(Orig_maze, Maze, sizeof Maze);
191 1.1 mrg }
192