### Infinite recursive maze

It's turtles all the way down

```const seed = 1100; // min=1, max=2000, step=1
const width = 30; // min=15, max=50, step=1
const depth = 70; // min=20, max=150, step=1
const link = 5; // min=1, max=10, step=1
const draw_between = 1; // min=0, max=1, step=1 (No, Yes)

Canvas.setpenopacity(-1);

const t = new Turtle();

let cur_rand = seed;
function rand() { cur_rand = (cur_rand * 48271) % (2**31 - 1); return cur_rand; }
function rand_bool() { return rand() % 2 == 0; }
function rand_elem(ar) { return ar[rand() % ar.length]; }

const cells = [];
const visited = new Set();
const deleted_walls = new Set();

let x0 = -100, y0 = -100;
let s = 200 / width;

for (let i = 0; i < depth; i++) {
for (let j = 0; j < width; j++) {
cells.push([i, j, 0]); // level, x, y
cells.push([i, j, width - 1]);
}

for (let j = 1; j < width - 1; j++) {
cells.push([i, 0, j]);
cells.push([i, width - 1, j]);
}
}

function get_neighbours(level, x, y) {
let neighb = [];

if ((y == 0) || (y == width - 1)) {
if (x > 0) {
neighb.push([level, x - 1, y]);
}

if (x < width - 1) {
neighb.push([level, x + 1, y]);
}

if ((level > 0) && (x > 0) && (x < width - 1)) {
if ((Math.abs(width / 2 - x) < link) || (x < link) || (x > width - 1 - link)) {
neighb.push([level - 1, x, y]);
}
}

if ((level < depth - 1) && (x > 0) && (x < width - 1)) {
if ((Math.abs(width / 2 - x) < link) || (x < link) || (x > width - 1 - link)) {
neighb.push([level + 1, x, y]);
}
}
}

if ((x == 0) || (x == width - 1)) {
if (y > 0) {
neighb.push([level, x, y - 1]);
}

if (y < width - 1) {
neighb.push([level, x, y + 1]);
}

if ((level > 0) && (y > 0) && (y < width - 1)) {
if ((Math.abs(width / 2 - y) < link) || (y < link) || (y > width - 1 - link)) {
neighb.push([level - 1, x, y]);
}
}

if ((level < depth - 1) && (y > 0) && (y < width - 1)) {
if ((Math.abs(width / 2 - y) < link) || (y < link) || (y > width - 1 - link)) {
neighb.push([level + 1, x, y]);
}
}
}

return neighb;
}

let stack = [cells[0]];

while (stack.length > 0) {
let cur = stack.pop();

var cur_level, cur_x, cur_y;
[cur_level, cur_x, cur_y] = cur;

let neighb = get_neighbours(cur_level, cur_x, cur_y);

let unvisited_neighb = [];
for (let n of neighb) {
if (! visited.has(n.toString())) {
unvisited_neighb.push(n);
}
}

if (unvisited_neighb.length > 0) {
stack.push(cur);

let next = rand_elem(unvisited_neighb);

deleted_walls.add(cur.toString() + ' ' + next.toString());
deleted_walls.add(next.toString() + ' ' + cur.toString());

stack.push(next);
}
}

let depth_shift = [-100];
let cell_size = [200 / width];

for (let i = 1; i < depth; i++) {
depth_shift[i] = depth_shift[i - 1] + cell_size[i - 1];
cell_size[i] = ((width - 2) * cell_size[i - 1]) / width;
}

for (let c of cells) {
var cur_level, cur_x, cur_y;
[cur_level, cur_x, cur_y] = c;

let d = depth_shift[cur_level];
let s = cell_size[cur_level];

let neighb = get_neighbours(cur_level, cur_x, cur_y);

let left = false, right = false, up = false, down = false;

for (let n of neighb) {
var n_level, n_x, n_y;
[n_level, n_x, n_y] = n;

let draw = ! deleted_walls.has(c.toString() + ' ' + n.toString());

if ((n_level == cur_level) && (n_x == cur_x - 1)) {
if (draw) {
t.jump(d + cur_x * s, d + cur_y * s);
t.goto(d + cur_x * s, d + (cur_y + 1) * s);
}

left = true;
}

if ((n_level == cur_level - 1) && (n_x == 0) && (cur_x == 0)) {
if (draw) {
t.jump(d + cur_x * s, d + cur_y * s);
t.goto(d + cur_x * s, d + (cur_y + 1) * s);
}

left = true;
}

if ((n_level == cur_level + 1) && (n_x == width - 1) && (cur_x == width - 1)) {
if (draw) {
t.jump(d + cur_x * s, d + cur_y * s);
t.goto(d + cur_x * s, d + (cur_y + 1) * s);
}

left = true;
}

if ((n_level == cur_level) && (n_y == cur_y - 1)) {
if (draw) {
t.jump(d + cur_x * s, d + cur_y * s);
t.goto(d + (cur_x + 1) * s, d + cur_y * s);
}

up = true;
}

if ((n_level == cur_level - 1) && (n_y == 0) && (cur_y == 0)) {
if (draw) {
t.jump(d + cur_x * s, d + cur_y * s);
t.goto(d + (cur_x + 1) * s, d + cur_y * s);
}

up = true;
}

if ((n_level == cur_level + 1) && (n_y == width - 1) && (cur_y == width - 1)) {
if (draw) {
t.jump(d + cur_x * s, d + cur_y * s);
t.goto(d + (cur_x + 1) * s, d + cur_y * s);
}

up = true;
}
}

if (draw_between == 1) {
if (! left) {
t.jump(d + cur_x * s, d + cur_y * s);
t.goto(d + cur_x * s, d + (cur_y + 1) * s);
}

if (! up) {
t.jump(d + cur_x * s, d + cur_y * s);
t.goto(d + (cur_x + 1) * s, d + cur_y * s);
}
}

// t.jump(d + cur_x * s, d + cur_y * s);
// t.seth(0);
// for (let k = 0; k < 4; k++) {
//     t.forward(s);
//     t.right(90);
// }

// let neighb = get_neighbours(cur_level, cur_x, cur_y);
// for (let n of neighb) {
//     var nlevel, nx, ny;
//     [nlevel, nx, ny] = n;
//     let dn = depth_shift[nlevel];
//     let sn = cell_size[nlevel];
//     t.jump(d + (cur_x + 0.5) * s, d + (cur_y + 0.5) * s);
//     t.goto(dn + (nx + 0.5) * sn, dn + (ny + 0.5) * sn);
// }

// if (visited.has(c.toString())) {
//     t.jump(d + (cur_x + 0.5) * s, d + (cur_y + 0.5) * s);
//     t.seth(45);
//     for (let i = 0; i < 4; i++) {
//         t.forward(2);
//         t.back(2);
//         t.right(90);
//     }
// }
}```