Skip to content

Commit 92a5d04

Browse files
committed
Add maze generator and solver program
The program is yet another non-trivial example known to work with AMaCC.
1 parent 293378b commit 92a5d04

File tree

2 files changed

+246
-1
lines changed

2 files changed

+246
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ Run `make check` and you should see this:
5858
[ nested/self compilation ] Passed
5959
[ Compatibility with GCC/Arm ] ........................................
6060
----------------------------------------------------------------------
61-
Ran 45 tests in 7.101s
61+
Ran 48 tests in 7.354s
6262
6363
OK
6464
```

tests/maze.c

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
/* Maze generator in C.
2+
* Written by Joe Wingbermuehle
3+
* 1999-08-05
4+
* Sourced from https://raw.githubusercontent.com/joewing/maze/master/maze.c
5+
* Tweaked for AMaCC.
6+
*/
7+
8+
#include <stdio.h>
9+
#include <stdlib.h>
10+
11+
int maze_rand_v;
12+
int maze_rand()
13+
{
14+
return ((maze_rand_v = maze_rand_v * 214013 + 2531011) >> 16) & 0x7fff;
15+
}
16+
17+
int maze_atoi(char *str, int radix)
18+
{
19+
int v, sign;
20+
21+
v = 0;
22+
sign = 1;
23+
if (*str == '-') {
24+
sign = -1;
25+
++str;
26+
}
27+
while ((*str >= 'A' && *str <= 'Z') || (*str >= 'a' && *str <= 'z') ||
28+
(*str >= '0' && *str <= '9')) {
29+
v = v * radix +
30+
((*str > '9') ? (*str & ~0x20) - 'A' + 10 : (*str - '0'));
31+
++str;
32+
}
33+
return v * sign;
34+
}
35+
36+
/* Display the maze. */
37+
void show_maze(char *maze, int width, int height)
38+
{
39+
int x, y;
40+
for (y = 0; y < height; y++) {
41+
for (x = 0; x < width; x++) {
42+
switch (maze[y * width + x]) {
43+
case 1:
44+
printf("[]");
45+
break;
46+
case 2:
47+
printf("<>");
48+
break;
49+
default:
50+
printf(" ");
51+
break;
52+
}
53+
}
54+
printf("\n");
55+
}
56+
}
57+
58+
/* Carve the maze starting at x, y. */
59+
void carve_maze(char *maze, int width, int height, int x, int y)
60+
{
61+
int x1, y1;
62+
int x2, y2;
63+
int dx, dy;
64+
int dir, count;
65+
66+
dir = maze_rand() % 4;
67+
count = 0;
68+
while (count < 4) {
69+
dx = 0;
70+
dy = 0;
71+
switch (dir) {
72+
case 0:
73+
dx = 1;
74+
break;
75+
case 1:
76+
dy = 1;
77+
break;
78+
case 2:
79+
dx = -1;
80+
break;
81+
default:
82+
dy = -1;
83+
break;
84+
}
85+
x1 = x + dx;
86+
y1 = y + dy;
87+
x2 = x1 + dx;
88+
y2 = y1 + dy;
89+
if (x2 > 0 && x2 < width && y2 > 0 && y2 < height &&
90+
maze[y1 * width + x1] == 1 && maze[y2 * width + x2] == 1) {
91+
maze[y1 * width + x1] = 0;
92+
maze[y2 * width + x2] = 0;
93+
x = x2;
94+
y = y2;
95+
dir = maze_rand() % 4;
96+
count = 0;
97+
} else {
98+
dir = (dir + 1) % 4;
99+
count++;
100+
}
101+
}
102+
}
103+
104+
/* Generate maze in matrix maze with size width, height. */
105+
void generate_maze(char *maze, int width, int height)
106+
{
107+
int x, y;
108+
109+
/* Initialize the maze. */
110+
for (x = 0; x < width * height; x++)
111+
maze[x] = 1;
112+
maze[1 * width + 1] = 0;
113+
114+
/* Carve the maze. */
115+
for (y = 1; y < height; y += 2)
116+
for (x = 1; x < width; x += 2)
117+
carve_maze(maze, width, height, x, y);
118+
119+
/* Set up the entry and exit. */
120+
maze[0 * width + 1] = 0;
121+
maze[(height - 1) * width + (width - 2)] = 0;
122+
}
123+
124+
/* Solve the maze. */
125+
void solve_maze(char *maze, int width, int height)
126+
{
127+
int dir, count;
128+
int x, y;
129+
int dx, dy;
130+
int forward;
131+
132+
/* Remove the entry and exit. */
133+
maze[0 * width + 1] = 1;
134+
maze[(height - 1) * width + (width - 2)] = 1;
135+
136+
forward = 1;
137+
dir = 0;
138+
count = 0;
139+
x = 1;
140+
y = 1;
141+
while (x != width - 2 || y != height - 2) {
142+
dx = 0;
143+
dy = 0;
144+
switch (dir) {
145+
case 0:
146+
dx = 1;
147+
break;
148+
case 1:
149+
dy = 1;
150+
break;
151+
case 2:
152+
dx = -1;
153+
break;
154+
default:
155+
dy = -1;
156+
break;
157+
}
158+
if ((forward && maze[(y + dy) * width + (x + dx)] == 0) ||
159+
(!forward && maze[(y + dy) * width + (x + dx)] == 2)) {
160+
maze[y * width + x] = forward ? 2 : 3;
161+
x = x + dx;
162+
y = y + dy;
163+
forward = 1;
164+
count = 0;
165+
dir = 0;
166+
} else {
167+
dir = (dir + 1) % 4;
168+
count = count + 1;
169+
if (count > 3) {
170+
forward = 0;
171+
count = 0;
172+
}
173+
}
174+
}
175+
176+
/* Replace the entry and exit. */
177+
maze[(height - 2) * width + (width - 2)] = 2;
178+
maze[(height - 1) * width + (width - 2)] = 2;
179+
}
180+
181+
enum { A_RANDV, A_WIDTH, A_HEIGHT, A_SOLVE };
182+
183+
int main(int argc, char **argv)
184+
{
185+
int width, height, solve, mode, v;
186+
char *maze, *invocation;
187+
188+
maze_rand_v = 6; // chosen by fair dice roll, guaranteed to be random
189+
width = 10 * 2 + 3;
190+
height = 10 * 2 + 3;
191+
solve = 0;
192+
193+
invocation = *argv;
194+
--argc;
195+
++argv;
196+
mode = A_RANDV;
197+
while (argc > 0) {
198+
if (**argv == '-' && *(*argv + 1) == 'h') {
199+
printf("Usage: %s [seed] [width] [height] [s]\n", invocation);
200+
return 0;
201+
}
202+
v = maze_atoi(*argv, 10);
203+
if (**argv == 's' || **argv == '2')
204+
solve = 1;
205+
else if (mode == A_RANDV)
206+
maze_rand_v = v * 0xfffa;
207+
else if (mode == A_WIDTH)
208+
width = v * 2 + 3;
209+
else if (mode == A_HEIGHT)
210+
height = v * 2 + 3;
211+
else {
212+
printf("Unknown argument: '%s'\n", *argv);
213+
return 1;
214+
}
215+
++mode;
216+
--argc;
217+
++argv;
218+
}
219+
/* Get and validate the size. */
220+
if (width < 7)
221+
width = 7;
222+
if (height < 7)
223+
height = 7;
224+
225+
/* Allocate the maze array. */
226+
maze = (char *) malloc(width * height * sizeof(char));
227+
if (maze == 0) {
228+
printf("error: not enough memory\n");
229+
exit(1);
230+
}
231+
232+
/* Generate and display the maze. */
233+
generate_maze(maze, width, height);
234+
show_maze(maze, width, height);
235+
236+
/* Solve the maze if requested. */
237+
if (solve) {
238+
solve_maze(maze, width, height);
239+
show_maze(maze, width, height);
240+
}
241+
242+
/* Clean up. */
243+
free(maze);
244+
return 0;
245+
}

0 commit comments

Comments
 (0)