It's turtles all the way down
Log in to post a comment.
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]];
visited.add(cells[0].toString());
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());
visited.add(next.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);
// }
// }
}