Background
The real basics
Conway's Game of Life is a famous cellular simulation in computer science: using a few simple rules, it mimics cells in a petri dish as they reproduce and die off. This is pretty cool in itself, but it's also the gateway to a much more important concept: Life is itself a universal Turing machine, which means that anything an algorithm can compute deterministically can be done in the Game of Life.
The basics
Like so many others, I'll direct you to the Wikipedia article on the subject for extensive reading. However, the quick version is that the Game of Life is defined by a grid (or field) where each spot can either be turned off (empty) or on (occupied by a cell). As time advances, the cells interact by the following rules:
- A live cell with fewer than two neighbors dies as if unable to reproduce (the spot becomes empty).
- A live cell with more than three neighbors dies as if by starvation (the spot becomes empty).
- Thus any cell with exactly two or three neighbors (of eight possible positions) survives to the next round, having found the perfect balance between reproductive partners and resource concumption.
- An empty space with three neighbors will generate a new cell.
Technical details
This is a full implementation of the above rules (with some optional additions) contained in a single JavaScript library. Any browser with JavaScript should be able to run this code.
Installation
There's no installation required, per se. To use the file, download a copy from the links above and copy it to the server where your web files live. Then you can include it in your page by inserting the following (example) HTML:
After that, you should be able to create new boards and run them with no trouble. It's recommended to get the minified version (download Current-min, above) unless you really need debugging capability.
Use
To create a new board, you'll first need to provide a place for the board to go. I recommend a div with a special ID (which can be anything you want):
Then you need to set up the initial board state and create the game object. The initial board state is a two-dimensional JavaScript array where 1 corresponds to a live cell and 0 corresponds to an empty spot. Creating the game object consists of calling the library with the ID of the element you want it to be added to, plus the initial game state. For example:
var pentomino = [[0,0,0,0,0], [0,0,1,1,0], [0,1,1,0,0], [0,0,1,0,0], [0,0,0,0,0]] var pentominoLife = new JSConway("#conwayboard", fPentominoGrid);
...would add the following board under the element with the ID "conwayboard" (notice the extra hash in front of the ID--that's jQuery syntax):
Then you can use the various functions (enumerated below) to manipulate the board. You can have several boards running simultaneously; simply create them individually and store them in separate variables to address them each individually.
API
Properties
There are several properties that can be set when you create the JSConway object. These are passed in as a third argument, so for example:
...would initialize the object so that each step would occur after 300ms (instead of the default 200ms), and the board would be white cells on a black background (instead of the other way around).
- delay
- The delay in milliseconds between each step when the game is being played. Default: 10
- height
- The height of the board (in cells). Like width, it's guessed automatically and you shouldn't really need to set this. Default: 10
- cellWidth
- The width in pxels for each cell when the canvas renderer is used. Meaningless for the table renderer. Default: 10
- cellHeight
- The height in pixels for each cell when the canvas renderer is used. Meaningless for the table renderer. Default: 10
- initrender
- Set to true if you want the board to be rendered as soon as it's initialized. If false, you're responsible for calling the render function yourself. Default: true
- colors
- An array of arrays defining colors to use for background and foreground. Each tuple is an RGB value from 0 to 255, e.g. [0, 0, 0] is black and [255, 0, 0] is bright red. The first tuple in the array is the background color (or the color for dead cells), and the second tuple is the foreground color (for the live cells). You can set as many colors as you need; there's no reason the array is restricted to only two tuples. Default: [[255, 255, 255], [0, 0, 0], [100,0,0], [0, 100, 0], [0, 0, 100], [100, 100, 0]]
- renderer
- Which renderer to use for displaying the game board: options are "table" or "canvas". Canvas is preferred, but there are several issues with it: it will only work on modern browsers that support the HTML5 canvas element, and it makes it difficult to assert your own custom styles with CSS. Also, it's not as easy to read the state directly from the canvas as from the table, but for reading state you can use the getState function. Default: canvas
Functions
- JSConway(el, state, settings)
- The constructor. Use this every time you need a new board.
- el
- The element to add the game board to.
- state
- The initial state of the board.
- settings
- (Optional) Additional settings beyond the defaults to apply to the board.
- create()
- Creates the HTML object which is used to display the game state. Calls out to one of two internal functions depending on the renderer: createTable() or createCanvas().
- getNeighbors(x, y)
- Return an array of two values. The first value is the
number of neighbors (live cells) surrounding the given position
(from 0-8); edges of the board will not count as neighbors. The
second element of the array is the most dominant state: for a
traditional Conway board, it should always be 1.
- x
- The X coordinate of the target cell.
- y
- The Y coordinate of the target cell.
- advance(steps, render)
- Advances the game state a certain number of steps.
- steps
- The number of steps to advance the game state. If ommitted, defaults to 1.
- render
- Whether to render the new board state at the end. Defaults to true.
- render()
- Renders the board based on the current state. Calls out to one oftwo internal functions depending on the renderer: renderTable() and renderCanvas(). (renderCanvas(), in turn, calls out to the helper function drawCanvasCell()).
- go()
- Starts the board regularly updating. Left to its own, it will continue to update the board until the new board state is the same as the old board state (that is, until there's no change between any two steps), at which point it will stop.
- pause()
- Pauses the board if it's currently in "go" mode. It won't do anything for an already-paused board or one that is in a stable state (after "go" has stopped).
- reset(render)
- Resets the board to the state given when the JSConway
object was created.
- render
- If true, the board is rendered as soon as it's reset; otherwise, you have to call the render method yoruself. If ommitted, defaults to true.
- get(x, y)
- Gets the state of a certain cell, or a range of cells. If
both x and y are ommitted, the entire board state is returned.
- x
- The X coordinate of the cell to get. If ommitted, all cells in the row corresponding to the Y coordinate are returned.
- y
- The Y coordinate of the cell to get. If ommitted, all cells in the column corresponding to the X coordinate are returned.
- set(x, y, state)
- Sets a particular cell state, or a range of cells.
- x
- The X coordinate of the cell to set. If ommitted, an entire row of cells is set.
- y
- The Y coordinate of the cell to set. If ommitted, an entire column of cells is set.
- state
- The state value to set. If X and Y are specified, this is one value. If one is ommitted, this is an array of values to set--if the array is shorter than the width or height of the board, remaining values will be filled in with zeroes. If both X and Y are ommitted, this is a brand new board state in a two-dimensional array.
Enhancements
This library has one enhancement: rather than each cell being strictly on or off, it can take a variety of states. This means that several different "colonies" of cells can be active on the same board, and can even overwhelm one another. To take advantage of this, simply initialize a cell's state to be higher than one. Just makes sure you put a color tuple in the color setting whose index corresponds to the state number!