summaryrefslogtreecommitdiff
path: root/games/hunt/huntd/makemaze.c
diff options
context:
space:
mode:
Diffstat (limited to 'games/hunt/huntd/makemaze.c')
-rw-r--r--games/hunt/huntd/makemaze.c208
1 files changed, 208 insertions, 0 deletions
diff --git a/games/hunt/huntd/makemaze.c b/games/hunt/huntd/makemaze.c
new file mode 100644
index 00000000000..bcc21c61b27
--- /dev/null
+++ b/games/hunt/huntd/makemaze.c
@@ -0,0 +1,208 @@
+/* $NetBSD: makemaze.c,v 1.2 1997/10/10 16:33:43 lukem Exp $ */
+/*
+ * Hunt
+ * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
+ * San Francisco, California
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: makemaze.c,v 1.2 1997/10/10 16:33:43 lukem Exp $");
+#endif /* not lint */
+
+# include "hunt.h"
+
+# define ISCLEAR(y,x) (Maze[y][x] == SPACE)
+# define ODD(n) ((n) & 01)
+
+static int candig __P((int, int));
+static void dig __P((int, int));
+static void dig_maze __P((int, int));
+static void remap __P((void));
+
+void
+makemaze()
+{
+ char *sp;
+ int y, x;
+
+ /*
+ * fill maze with walls
+ */
+ sp = &Maze[0][0];
+ while (sp < &Maze[HEIGHT - 1][WIDTH])
+ *sp++ = DOOR;
+
+ x = rand_num(WIDTH / 2) * 2 + 1;
+ y = rand_num(HEIGHT / 2) * 2 + 1;
+ dig_maze(x, y);
+ remap();
+}
+
+# define NPERM 24
+# define NDIR 4
+
+int dirs[NPERM][NDIR] = {
+ {0,1,2,3}, {3,0,1,2}, {0,2,3,1}, {0,3,2,1},
+ {1,0,2,3}, {2,3,0,1}, {0,2,1,3}, {2,3,1,0},
+ {1,0,3,2}, {1,2,0,3}, {3,1,2,0}, {2,0,3,1},
+ {1,3,0,2}, {0,3,1,2}, {1,3,2,0}, {2,0,1,3},
+ {0,1,3,2}, {3,1,0,2}, {2,1,0,3}, {1,2,3,0},
+ {2,1,3,0}, {3,0,2,1}, {3,2,0,1}, {3,2,1,0}
+ };
+
+int incr[NDIR][2] = {
+ {0, 1}, {1, 0}, {0, -1}, {-1, 0}
+ };
+
+static void
+dig(y, x)
+ int y, x;
+{
+ int *dp;
+ int *ip;
+ int ny, nx;
+ int *endp;
+
+ Maze[y][x] = SPACE; /* Clear this spot */
+ dp = dirs[rand_num(NPERM)];
+ endp = &dp[NDIR];
+ while (dp < endp) {
+ ip = &incr[*dp++][0];
+ ny = y + *ip++;
+ nx = x + *ip;
+ if (candig(ny, nx))
+ dig(ny, nx);
+ }
+}
+
+/*
+ * candig:
+ * Is it legal to clear this spot?
+ */
+static int
+candig(y, x)
+ int y, x;
+{
+ int i;
+
+ if (ODD(x) && ODD(y))
+ return FALSE; /* can't touch ODD spots */
+
+ if (y < UBOUND || y >= DBOUND)
+ return FALSE; /* Beyond vertical bounds, NO */
+ if (x < LBOUND || x >= RBOUND)
+ return FALSE; /* Beyond horizontal bounds, NO */
+
+ if (ISCLEAR(y, x))
+ return FALSE; /* Already clear, NO */
+
+ i = ISCLEAR(y, x + 1);
+ i += ISCLEAR(y, x - 1);
+ if (i > 1)
+ return FALSE; /* Introduces cycle, NO */
+ i += ISCLEAR(y + 1, x);
+ if (i > 1)
+ return FALSE; /* Introduces cycle, NO */
+ i += ISCLEAR(y - 1, x);
+ if (i > 1)
+ return FALSE; /* Introduces cycle, NO */
+
+ return TRUE; /* OK */
+}
+
+void
+dig_maze(x, y)
+ int x, y;
+{
+ int tx, ty;
+ int i, j;
+ int order[4];
+#define MNORTH 0x1
+#define MSOUTH 0x2
+#define MEAST 0x4
+#define MWEST 0x8
+
+ tx = ty = 0;
+ Maze[y][x] = SPACE;
+ order[0] = MNORTH;
+ for (i = 1; i < 4; i++) {
+ j = rand_num(i + 1);
+ order[i] = order[j];
+ order[j] = 0x1 << i;
+ }
+ for (i = 0; i < 4; i++) {
+ switch (order[i]) {
+ case MNORTH:
+ tx = x;
+ ty = y - 2;
+ break;
+ case MSOUTH:
+ tx = x;
+ ty = y + 2;
+ break;
+ case MEAST:
+ tx = x + 2;
+ ty = y;
+ break;
+ case MWEST:
+ tx = x - 2;
+ ty = y;
+ break;
+ }
+ if (tx < 0 || ty < 0 || tx >= WIDTH || ty >= HEIGHT)
+ continue;
+ if (Maze[ty][tx] == SPACE)
+ continue;
+ Maze[(y + ty) / 2][(x + tx) / 2] = SPACE;
+ dig_maze(tx, ty);
+ }
+}
+
+void
+remap()
+{
+ int y, x;
+ char *sp;
+ int stat;
+
+ for (y = 0; y < HEIGHT; y++)
+ for (x = 0; x < WIDTH; x++) {
+ sp = &Maze[y][x];
+ if (*sp == SPACE)
+ continue;
+ stat = 0;
+ if (y - 1 >= 0 && Maze[y - 1][x] != SPACE)
+ stat |= NORTH;
+ if (y + 1 < HEIGHT && Maze[y + 1][x] != SPACE)
+ stat |= SOUTH;
+ if (x + 1 < WIDTH && Maze[y][x + 1] != SPACE)
+ stat |= EAST;
+ if (x - 1 >= 0 && Maze[y][x - 1] != SPACE)
+ stat |= WEST;
+ switch (stat) {
+ case WEST | EAST:
+ case EAST:
+ case WEST:
+ *sp = WALL1;
+ break;
+ case NORTH | SOUTH:
+ case NORTH:
+ case SOUTH:
+ *sp = WALL2;
+ break;
+ case 0:
+# ifdef RANDOM
+ *sp = DOOR;
+# endif
+# ifdef REFLECT
+ *sp = rand_num(2) ? WALL4 : WALL5;
+# endif
+ break;
+ default:
+ *sp = WALL3;
+ break;
+ }
+ }
+ memcpy(Orig_maze, Maze, sizeof Maze);
+}