๐Ÿ“„ Langton's Ant - README.txt
โ”€ โ–ก ร—

Langton's Ant

Artificial Life CanvasRendererTerrain

Langton's Ant (designed by artificial life researcher Christopher Langton) is a cellular automaton with a single agent (the 'ant') moving across a two-dimensional grid. When the ant moves one step forward, it changes the color of the cell it occupies (from black to white and vice-versa). It also rotates clockwise or counter-clockwise depending on if it is on a black or white cell.

Although at the beginning of the simulation the ant appears to traverse a chaotic path, leaving behind random black and white cells in its wake, at about 10,000 steps in, it discovers a pattern, and begins tracing a wide path toward the southeast. On an infinite grid, it would continue in this direction forever, but on a toroidal grid (as shown here), it eventually collides with cells it previously traced, and returns to chaos.

๐Ÿ’ป langtons-ant.js - Interactive Editor
โ”€ โ–ก ร—
import { Environment, CanvasRenderer, Vector, Terrain } from "flocc";

let [width, height] = [window.innerWidth, window.innerHeight];
const scale = 3;
while (width % scale !== 0) width++;
while (height % scale !== 0) height++;

const NORTH = new Vector(0, -1);
const SOUTH = new Vector(0, 1);
const EAST = new Vector(1, 0);
const WEST = new Vector(-1, 0);
const DIRS = [NORTH, EAST, SOUTH, WEST];

const environment = new Environment({ width, height });
const terrain = new Terrain(width / scale, height / scale, {
  grayscale: true,
  scale
});
environment.use(terrain);

const renderer = new CanvasRenderer(environment, { width, height });
renderer.mount("#container");

const ANT = {
  pos: new Vector(
    (window.innerWidth / (2 * scale)) | 0,
    (window.innerHeight / (2 * scale)) | 0
  ),
  dir: WEST
};

function setup() {
  terrain.init((x, y) => 255);
}

let t = 0;

function run() {
  const { pos, dir } = ANT;
  // update the color where the ant is
  terrain.set(pos.x, pos.y, terrain.sample(pos.x, pos.y) === 255 ? 0 : 255);
  // move the ant
  pos.x += dir.x;
  pos.y += dir.y;
  // turn the ant
  const i = DIRS.indexOf(dir);
  if (terrain.sample(pos.x, pos.y) === 0) {
    ANT.dir = i === DIRS.length - 1 ? DIRS[0] : DIRS[i + 1];
  } else {
    ANT.dir = i === 0 ? DIRS[DIRS.length - 1] : DIRS[i - 1];
  }
  if (t < 20) {
    t++;
    return run();
  } else {
    t = 0;
  }
  environment.tick();
  requestAnimationFrame(run);
}

setup();
run();

Edit the code on the left ยท See results on the right