Reimplementation of Edward Zajec’s “Il Cubo” from 1971. Based on the images from edwardzajec.com/tvc4/pil1/index.html (I don't speak Italian).
Log in to post a comment.
// Il Cubo. Created by Reinder Nijhoff 2019 // @reindernijhoff // // https://turtletoy.net/turtle/cc4d10a96c // // Reimplementation of Edward Zajec’s “Il Cubo” from 1971. // Based on the images from http://www.edwardzajec.com/tvc4/pil1/index.html (I don't speak Italian). // // Different at every Compile & Run. // const buffer_steps = 1; // min=1, max=3, step=1 const buffer_size = 24; // min=16, max=64, step=1 const cell_size = 170/buffer_size; const drawFrame = 0; // min=0, max=1, step=1 (No, Yes) const dens_func = 1; // min=0, max=2, step=1 (Circle, Even, Gradient) const p = dens_func > 1.5 ? // density function (x,y) => x : dens_func > .5 ? (x,y) => .7 : (x,y) => 1-3*Math.pow((x-.5)*(x-.5)+(y-.5)*(y-.5),.75); let buffer = []; const turtle = new Turtle(); function init_buffer() { for (let x=0; x<buffer_size; x++) { buffer[x] = []; for (let y=0; y<buffer_size; y++) { buffer[x][y] = Math.random() > p(x/buffer_size,y/buffer_size) ? 0b10110 : 0; } } } function half_tile(type, x, y, lower) { const s = type == 1 ? 8 : type == 2 ? 32 : 2; let xs, xe, ys, ye; for (let i=0; i<=s; i++) { if (type == 1) { ys = ye = xe = i/s; xs = 0; } else if (type == 2) { ys = xs = xe = i/s; ye = 1; } else { ys = i/s; xe = 1-i/s; ye = 1; xs = 0; } if (lower) { draw_line(1-xs, ys, 1-xe, ye, x, y); } else { draw_line(xs, 1-ys, xe, 1-ye, x, y); } } } function tile(type, x, y) { if (!(type & 0b10000)) { const t1 = type >> 2, t2 = type & 0b11; half_tile(t1, x, y, false); half_tile(t2, x, y, true); if (t1 != t2) draw_line(0,1,1,0,x,y); } } function buffer_step(buffer) { const nb = [], rb = (buffer, x, y) =>x >= 0 && y >= 0 ? buffer[x][y] : 0; for (let x=0; x<buffer_size; x++) { nb[x] = []; for (let y=0; y<buffer_size; y++) { nb[x][y] = buffer[x][y]; if (!(nb[x][y] & 0b10000)) { nb[x][y] |= (rb(buffer,x-1,y) & 0b0011) << 2; nb[x][y] |= (rb(buffer,x,y-1) & 0b1100) >> 2; } } } return nb; } function draw_border(l,t,r,b,x,y) { l && draw_line(0,0,0,1,x,y); t && draw_line(0,1,1,1,x,y); r && draw_line(1,0,1,1,x,y); b && draw_line(0,0,1,0,x,y); } // line draw functions const hashMap = {}; function draw_line(xs, ys, xe, ye, x, y) { xs = (x+xs-.5)*cell_size, ys = (y+ys-.5)*cell_size; xe = (x+xe-.5)*cell_size, ye = (y+ye-.5)*cell_size; // Don't draw the same line twice const ks = xs.toFixed(4)+ys.toFixed(4), ke = xe.toFixed(4)+ye.toFixed(4); if (ks != ke && !hashMap[ks+ke] && !hashMap[ke+ks]) { hashMap[ks+ke] = hashMap[ke+ks] = true; turtle.jump(xs,ys); turtle.goto(xe,ye); } } function walk(i) { if (i==0) { init_buffer(); for (let j=0; j<buffer_steps*2; j++) { buffer = buffer_step(buffer); } } const x = i % buffer_size, y = (i / buffer_size)|0; const xc = x-buffer_size/2 + .5, yc = buffer_size/2-y - .5; tile( buffer[x][y], xc, yc); if (buffer[x][y] & 0b10000) { // border for white squares draw_border(x>0 && !(buffer[x-1][y]&0b10000), y>0 && !(buffer[x][y-1]&0b10000), x<buffer_size-2 && !(buffer[x+1][y]&0b10000), y<buffer_size-2 && !(buffer[x][y+1]&0b10000),xc,yc); } if (!(buffer[x][y] & 0b10000) || drawFrame) { draw_border(x==0, y==0, x==buffer_size-1, y==buffer_size-1, xc, yc); } return i < buffer_size*buffer_size-1; }