xxxxxxxxxx
392
// let patt;
// let pati = 0;
// let pos;
// let dirs =[]
// let step = 2;
// function setup() {
// createCanvas(400, 400);
// genpatt();
// pos = createVector(width/2, height/2)
// dirs.push(createVector(1,0))
// dirs.push(createVector(-1,0))
// dirs.push(createVector(0,-1))
// dirs.push(createVector(0,1))
// }
// function genpatt(){
// //unimplemented yet
// type = random([
// // not implemented
// // 'L-sys',
// // 'space-fill',
// 'stupid'
// ])
// patt = stupid()
// print(patt)
// }
// function stupid(){
// patt = ''
// hori = 'RL'.split("")
// verti = 'UD'.split("")
// curr = 'R'
// for (var i = 0 ; i < 15 ; i++){
// c = random()
// if (0.8 < c){
// if (verti.includes(curr)){
// patt = patt + random(hori)
// } else {
// patt = patt + random(verti)
// }
// }
// else if (0.6 < c){
// patt = patt + curr
// }
// else if (0.4 < c){
// if (verti.includes(curr)){
// curr = random(hori)
// } else {
// curr = random(verti)
// }
// }
// }
// return patt
// }
// function mouseClicked(){
// genpatt()
// }
// function draw() {
// background(220);
// let direction;
// let d;
// switch (patt[pati]) {
// case "R":
// d = dirs[0];
// break
// case "L":
// d = dirs[1];
// break
// case "U":
// d = dirs[2];
// break
// case "D":
// default:
// d = dirs[3];
// break
// }
// direction = d;
// pos.add(d.copy().mult(step))
// square(pos.x, pos.y, 10);
// pati = (pati + 1) % patt.length;
// }
// fed the above into chatgpt and asked to improve it lol
// Global state variables
let currentGenerator;
let currentPatternType;
let pos;
let currentHeading = 0; // used for relative commands
let step = 2;
// Direction vectors for relative movementment (0: right, 1: down, 2: left, 3: up)
let dirs
// For absolute commands (mapping commands to vectors)
let absDirs
// Pattern generators collection. Each object provides an init() and step() method.
let patternGenerators = {
// 1. L-system (Dragon curve) – relative instructions ("F", "+", "–")
"l-system": {
relative: true,
pattern: "",
index: 0,
init: function() {
let iterations = 8; // Adjust iterations for complexity/performance.
let axiom = "FX";
let pattern = axiom;
for (let i = 0; i < iterations; i++) {
let next = "";
for (let j = 0; j < pattern.length; j++) {
let char = pattern[j];
if (char === "X") {
next += "X+YF+";
} else if (char === "Y") {
next += "-FX-Y";
} else {
next += char;
}
}
pattern = next;
}
// Removement extraneous characters; we only need F, +, and -
pattern = pattern.replace(/[^F\+\-]/g, "");
this.pattern = pattern;
this.index = 0;
},
step: function() {
let cmd = this.pattern[this.index];
this.index = (this.index + 1) % this.pattern.length;
return cmd;
}
},
// 2. Space-fill (Hilbert curve) – here we precompute a full sequence of absolute directions.
"space-fill": {
relative: false,
pattern: "",
index: 0,
init: function() {
let order = 4; // Hilbert curve order; total points = (2^order)^2
let n = Math.pow(2, order);
let total = n * n;
let points = [];
for (let i = 0; i < total; i++) {
let pt = d2xy(n, i);
points.push(pt);
}
// Convert differences between consecutive points into commands:
let pattern = "";
for (let i = 1; i < points.length; i++) {
let dx = points[i].x - points[i - 1].x;
let dy = points[i].y - points[i - 1].y;
if (dx === 1) pattern += "R";
else if (dx === -1) pattern += "L";
else if (dy === 1) pattern += "D";
else if (dy === -1) pattern += "U";
}
this.pattern = pattern;
this.index = 0;
},
step: function() {
let cmd = this.pattern[this.index];
this.index = (this.index + 1) % this.pattern.length;
return cmd;
}
},
// 3. Stupid – the original random absolute generator.
"stupid": {
relative: false,
pattern: "",
index: 0,
init: function() {
let patt = '';
let hori = ['R', 'L'];
let verti = ['U', 'D'];
let curr = 'R';
for (let i = 0; i < 15; i++) {
let c = random();
if (c > 0.8) {
if (verti.includes(curr)) {
patt += random(hori);
} else {
patt += random(verti);
}
} else if (c > 0.6) {
patt += curr;
} else if (c > 0.4) {
if (verti.includes(curr)) {
curr = random(hori);
} else {
curr = random(verti);
}
}
}
this.pattern = patt;
this.index = 0;
},
step: function() {
let cmd = this.pattern[this.index];
this.index = (this.index + 1) % this.pattern.length;
return cmd;
}
},
// 4. Langton's Ant – a dynamic generator that doesn’t precompute a full path.
"langton": {
// Mark this generator as dynamic.
dynamic: true,
init: function() {
this.gridSize = 40;
this.cellSize = 10;
// Create a 2D grid (all cells start white, 0)
this.grid = [];
for (let i = 0; i < this.gridSize; i++) {
this.grid[i] = [];
for (let j = 0; j < this.gridSize; j++) {
this.grid[i][j] = 0;
}
}
// Place the ant at the center with an initial direction (0: up, 1: right, 2: down, 3: left)
this.ant = {
x: Math.floor(this.gridSize / 2),
y: Math.floor(this.gridSize / 2),
dir: 0
};
},
step: function() {
let x = this.ant.x;
let y = this.ant.y;
let cell = this.grid[y][x]; // Note: grid indexed [row][column]
if (cell === 0) {
this.grid[y][x] = 1;
this.ant.dir = (this.ant.dir + 1) % 4; // turn right
} else {
this.grid[y][x] = 0;
this.ant.dir = (this.ant.dir + 3) % 4; // turn left
}
// movement the ant one cell forward (with wraparound)
if (this.ant.dir === 0) { // up
this.ant.y = (this.ant.y - 1 + this.gridSize) % this.gridSize;
} else if (this.ant.dir === 1) { // right
this.ant.x = (this.ant.x + 1) % this.gridSize;
} else if (this.ant.dir === 2) { // down
this.ant.y = (this.ant.y + 1) % this.gridSize;
} else if (this.ant.dir === 3) { // left
this.ant.x = (this.ant.x - 1 + this.gridSize) % this.gridSize;
}
// (The grid state is updated and used for drawing below.)
return null;
}
}
};
// d2xy converts a Hilbert index (d) into an (x,y) coordinate.
// Adapted from common Hilbert curve implementations.
function d2xy(n, d) {
let rx, ry, s, t = d;
let x = 0;
let y = 0;
for (s = 1; s < n; s *= 2) {
rx = 1 & Math.floor(t / 2);
ry = 1 & (t ^ rx);
if (ry === 0) {
if (rx === 1) {
x = s - 1 - x;
y = s - 1 - y;
}
// swap x and y
let temp = x;
x = y;
y = temp;
}
x += s * rx;
y += s * ry;
t = Math.floor(t / 4);
}
return { x: x, y: y };
}
// Switches the current generator based on type.
function switchPattern(type) {
if (patternGenerators[type]) {
currentPatternType = type;
currentGenerator = patternGenerators[type];
currentGenerator.init();
pos = createVector(width / 2, height / 2);
if (currentGenerator.relative) {
currentHeading = 0; // default heading: right
}
}
}
function setup() {
createCanvas(400, 400);
// Start with a default pattern; you can change with keys.
dirs = [
createVector(1, 0),
createVector(0, 1),
createVector(-1, 0),
createVector(0, -1)
];
// For absolute commands (mapping commands to vectors)
absDirs = {
"R": createVector(1, 0),
"L": createVector(-1, 0),
"U": createVector(0, -1),
"D": createVector(0, 1)
};
switchPattern("stupid");
}
function draw() {
background(220);
// If the current generator is dynamic (e.g. Langton's ant):
if (currentPatternType === "langton") {
currentGenerator.step();
// Draw the grid – white cells for 0, black for 1.
for (let i = 0; i < currentGenerator.gridSize; i++) {
for (let j = 0; j < currentGenerator.gridSize; j++) {
if (currentGenerator.grid[i][j] === 1) fill(0);
else fill(255);
stroke(200);
rect(j * currentGenerator.cellSize, i * currentGenerator.cellSize, currentGenerator.cellSize, currentGenerator.cellSize);
}
}
// Draw the ant as a red square.
fill(255, 0, 0);
rect(currentGenerator.ant.x * currentGenerator.cellSize, currentGenerator.ant.y * currentGenerator.cellSize, currentGenerator.cellSize, currentGenerator.cellSize);
} else {
// For static generators:
let cmd = currentGenerator.step();
if (currentGenerator.relative) {
// Relative instructions: "F" means movement forward,
// "+" and "-" turn right or left (without an extra movement)
if (cmd === "F") {
pos.add(dirs[currentHeading].copy().mult(step));
} else if (cmd === "+") {
currentHeading = (currentHeading + 1) % 4;
} else if (cmd === "-") {
currentHeading = (currentHeading + 3) % 4;
}
// (Uncomment the next line if you want a movement after turning.)
// pos.add(dirs[currentHeading].copy().mult(step));
} else {
// Absolute instructions: directly interpret as direction.
let movement = absDirs[cmd];
pos.add(movement.copy().mult(step));
}
// Draw a square at the new position.
square(pos.x, pos.y, 10);
}
}
// Use keys 1-4 to switch between the generators:
// 1: stupid, 2: l-system, 3: space-fill, 4: langton.
function keyPressed() {
if (key === '1') {
switchPattern("stupid");
} else if (key === '2') {
switchPattern("l-system");
} else if (key === '3') {
switchPattern("space-fill");
} else if (key === '4') {
switchPattern("langton");
}
}