Maze generation: Difference between revisions

Content added Content deleted
(→‎{{header|jq}}: simplify)
Line 5,589: Line 5,589:
</pre>
</pre>
In the following, a maze is represented by a matrix, each of whose elements
In the following, a maze is represented by a matrix, each of whose elements
is in turn a boolean array representing the bounding box:
is in turn a JSON object representing the bounding box:
$box[$i] is true iff edge $i open,
$box["N"] is true iff the northern edge open, and similarly for the
other points of the compass.
where $i is:


Note that in the following, the "walk" always starts at the (0,0)
0 for the top (north) side,
cell; this is just to make it clear that walk starts at the top left of the
1 bottom (south)
display.
2 right (east)
3 left (west)

Note that for simplicity, in the following the "walk" always starts at the (0,0) cell.
<syntaxhighlight lang="jq">
<syntaxhighlight lang="jq">
# Output: a prn in range(0;$n) where $n is .
# Output: a prn in range(0;$n) where $n is .
Line 5,622: Line 5,619:
| .a
| .a
end;
end;

# Arrays wherein `false` and `null` are the only falsey values.
# The input array and $y need not be of the same length.
def lor($y): [., $y] | transpose | map(.[0] or .[1]);
def falsey: all(.[]; IN(false, null) );

# Create an array such that .[$n] is true, and .[$i] is null for $i < $n
def bit($n): [] | .[$n] = true;


# Compass is a JSON object {n,s,e,w} representing the four possible
# Compass is a JSON object {n,s,e,w} representing the four possible
# directions in which to move, i.e. to open a gate.
# directions in which to move, i.e. to open a gate.
# For example, Compass.n corresponds to a move north (i.e. dx is 0, dy is 1),
# For example, Compass.n corresponds to a move north (i.e. dx is 0, dy is 1),
# and Compass.n.gates[0] is true indicating that the "northern" gate should be opened.
# and Compass.n.gates["N"] is true indicating that the "northern" gate should be opened.
def Compass:
def Compass:
{n: { gates: bit(0), dx: 0, dy: -1},
{n: { gates: {"N": true}, dx: 0, dy: -1},
s: { gates: bit(1), dx: 0, dy: 1},
s: { gates: {"S": true}, dx: 0, dy: 1},
e: { gates: bit(2), dx: 1, dy: 0},
e: { gates: {"E": true}, dx: 1, dy: 0},
w: { gates: bit(3), dx:-1, dy: 0} }
w: { gates: {"W": true}, dx:-1, dy: 0} }
| .n.opposite = .s
| .n.opposite = .s
| .s.opposite = .n
| .s.opposite = .n
Line 5,648: Line 5,637:
# Produce a matrix representing an $x x $y maze.
# Produce a matrix representing an $x x $y maze.
# .[$i][$j] represents the box in row $i, column $j.
# .[$i][$j] represents the box in row $i, column $j.
# Initially, all the gates of all the boxes are closed (falsey).
# Initially, all the gates of all the boxes are closed.
def MazeMatrix($x; $y):
def MazeMatrix($x; $y):
[range(0;$x) | [] ] as $v | [range(0;$y) | $v];
[range(0;$x) | {} ] as $v | [range(0;$y) | $v];


# Input: a MazeMatrix
# Input: a MazeMatrix
Line 5,662: Line 5,651:
($cx + $v.dx) as $nx
($cx + $v.dx) as $nx
| ($cy + $v.dy) as $ny
| ($cy + $v.dy) as $ny
| if interior($nx; $x) and interior($ny; $y) and (.[$nx][$ny]|falsey)
| if interior($nx; $x) and interior($ny; $y) and .[$nx][$ny] == {}
then .[$cx][$cy] |= lor($v.gates)
then .[$cx][$cy] += $v.gates
| .[$nx][$ny] |= lor($v.opposite.gates)
| .[$nx][$ny] += $v.opposite.gates
| generate($nx; $ny)
| generate($nx; $ny)
end );
end );
Line 5,676: Line 5,665:
# draw the north edge
# draw the north edge
| ([range(0;$x) as $j
| ([range(0;$x) as $j
| if $maze[$j][$i][0] then "+ " else "+---" end] | join("")) + "+",
| if $maze[$j][$i]["N"] then "+ " else "+---" end] | join("")) + "+",
# draw the west edge
# draw the west edge
([range(0;$x) as $j
([range(0;$x) as $j
| if $maze[$j][$i][3] then " " else "| " end] | join("")) + "|" ),
| if $maze[$j][$i]["W"] then " " else "| " end] | join("")) + "|" ),
# draw the bottom line
# draw the bottom line
($x * "+---") + "+"
($x * "+---") + "+"
;
;


# Always start at (0,0)
# Start the walk at the top left
def amaze($x;$y):
def amaze($x;$y):
MazeMatrix($x; $y)
MazeMatrix($x; $y)