// GAME OF LIFE PLUS LANGTON'S ANT const sketch = function (p) { const gridSize = [200, 200]; const cellSize = 4; const ant_val = 20; const game_val = 1; const mouse_val = 20; const fill_randomly = false; const random_fill_value = 1; let agent = { x: cellSize * 30, y: cellSize * 30, angle: 0 }; let cols, rows; let grid = []; let nextGrid = []; let cActive, cInactive, cAnt; p.setup = function () { p.createCanvas(gridSize[0] * cellSize, gridSize[1] * cellSize).parent( "sketch" ); cols = p.width / cellSize; rows = p.height / cellSize; // Initialize grid if (fill_randomly) { grid = Array.from({ length: cols }, () => // Array.from => arg1: length of array, arg2: function for each item Array.from({ length: rows }, () => ({ val: p.random() < 0.5 ? random_fill_value : 0, })) ); } else { grid = Array.from({ length: cols }, () => Array.from({ length: rows }, () => ({ val: 0 })) ); } nextGrid = Array.from({ length: cols }, () => Array(rows).fill(0)); cActive = p.color(127, 0, 127, 255); cInactive = p.color(0, 0, 0, 255); cAnt = p.color(0, 255, 255, 255); p.background(0); p.frameRate(10); }; p.draw = function () { p.noStroke(); // Draw the grid for (let i = 0; i < cols; i++) { for (let j = 0; j < rows; j++) { if (grid[i][j].val > 0) { const brightness = p.map(grid[i][j].val, 0, ant_val, 50, 255); // Map range t0 50-255 p.fill(127, 0, brightness, 255); } else { p.fill(cInactive); } p.rect(i * cellSize, j * cellSize, cellSize, cellSize); } } p.fill(cAnt); p.rect(agent.x, agent.y, cellSize, cellSize); // Langton's Ant logic const col = Math.floor(agent.x / cellSize); const row = Math.floor(agent.y / cellSize); if (grid[col][row].val > 0) { agent.angle += 90; grid[col][row].val = 0; } else { agent.angle -= 90; grid[col][row].val = ant_val; } agent.angle = (agent.angle + 360) % 360; switch (agent.angle) { case 0: agent.y -= cellSize; break; case 90: agent.x += cellSize; break; case 180: agent.y += cellSize; break; case 270: agent.x -= cellSize; break; } agent.x = (agent.x + p.width) % p.width; agent.y = (agent.y + p.height) % p.height; // Game of Life logic for (let i = 0; i < cols; i++) { for (let j = 0; j < rows; j++) { const neighbors = countNeighbors(i, j); if (grid[i][j].val > 0) { switch (neighbors) { case 2: case 3: nextGrid[i][j] = grid[i][j].val; break; default: nextGrid[i][j] = grid[i][j].val - 1; break; } } else { if (neighbors === 3) { nextGrid[i][j] = game_val; } else { nextGrid[i][j] = 0; } } } } // Swap grids for (let i = 0; i < cols; i++) { for (let j = 0; j < rows; j++) { grid[i][j].val = nextGrid[i][j]; } } }; function countNeighbors(x, y) { let count = 0; for (let i = -1; i <= 1; i++) { for (let j = -1; j <= 1; j++) { if (i === 0 && j === 0) continue; const col = (x + i + cols) % cols; const row = (y + j + rows) % rows; count += grid[col][row].val > 0 ? 1 : 0; } } return count; } p.mouseClicked = function () { const x = Math.floor(p.mouseX / cellSize); const y = Math.floor(p.mouseY / cellSize); if (x >= 0 && x < cols && y >= 0 && y < rows) { grid[x][y].val = grid[x][y].val > 0 ? 0 : mouse_val; } }; p.keyPressed = function () { if (p.keyCode === 32) { p.isLooping() ? p.noLoop() : p.loop(); } }; }; new p5(sketch);