A graphical toolkit for visualization
Protovis
Overview
Examples
Documentation
Download
Index
« Previous / Next »

Conway’s Game of Life

View full screen.

Life is a two-dimensional cellular automaton devised by John Conway in 1970. Each cell is either alive or dead. At each step, each cell can change states dependant on its eight immediate neighbors: “Any live cell with fewer than two live neighbors dies, as if by underpopulation. Any live cell with more than three live neighbors dies, as if by overcrowding. Any dead cell with exactly three live neighbors becomes a live cell.”

Here we initialize the system with an unusual breeder: a configuration of cells that generate secondary and tertiary patterns in its wake. Click on the simulation to reset to a random state.

Next: Automaton Explorer

Source

<html>
  <head>
    <title>Conway&rsquo;s Game of Life</title>
    <link type="text/css" rel="stylesheet" href="ex.css?3.2"/>
    <script type="text/javascript" src="../protovis-r3.2.js"></script>
    <script type="text/javascript" src="life.js"></script>
    <script type="text/javascript" src="breeder.js"></script>
    <style type="text/css">

body {
  background: #222;
}

#fig {
  width: 300px;
  height: 300px;
}

    </style>
  </head>
  <body><div id="center"><div id="fig">
    <script type="text/javascript+protovis">

var vis = new pv.Panel()
    .width(life.size * 2)
    .height(life.size * 2);

vis.add(pv.Image)
    .def("init", function() life.update())
    .imageWidth(life.size)
    .imageHeight(life.size)
    .image(pv.colors(null, "#0f0").by(function(i, j) life[j * life.size + i]))
    .event("click", function() life.reset());

vis.render();

setInterval(function() vis.render(), 42);

    </script>
  </div></div></body>
</html>

Data

var life = [];

life.neighbors = [];

life.neighbors.add = function(x, y, v) {
  for (var i = x - 1; i <= x + 1; i++) {
    for (var j = y - 1; j <= y + 1; j++) {
      this[i * life.size + j] += v;
    }
  }
  this[x * life.size + y] -= v;
};

life.reset = function(source) {
  if (!arguments.length) {
    source = [];
    source.size = 150;
    for (var x = 0, p = 0; x < source.size; x++) {
      for (var y = 0; y < source.size; y++, p++) {
        source[p] = Math.random() > .5 ? 1 : 0;
      }
    }
  }
  life.size = source.size;
  for (var x = 0, p = 0; x < life.size; x++) {
    for (var y = 0; y < life.size; y++, p++) {
      life[p] = source[p];
      life.neighbors[p] = 0;
    }
  }
  for (var x = 0, p = 0; x < life.size; x++) {
    for (var y = 0; y < life.size; y++, p++) {
      if (life[p]) {
        life.neighbors.add(x, y, 1);
      }
    }
  }
};

life.update = function() {
  var neighbors = this.neighbors.concat();
  for (var x = 0, p = 0; x < life.size; x++) {
    for (var y = 0; y < life.size; y++, p++) {
      if (this[p]) {
        if ((neighbors[p] < 2) || (neighbors[p] > 3)) {
          this.neighbors.add(x, y, -1);
          this[p] = 0;
        }
      } else if (neighbors[p] == 3) {
        this.neighbors.add(x, y, 1);
        this[p] = 1;
      }
    }
  }
};

See also breeder.js.

Copyright 2010 Stanford Visualization Group