The Game of Life

How does it work?
Gen 0
Pop 334
PAUSED

Interesting patterns

Spaceships
These patterns cycle over a fixed number of generations while traveling across the grid. Three of the smallest elementary ships are demonstrated here.
Glider Array
First discovered in 1969, the glider is the smallest and most common spaceship. It travels diagonally over a period of 4 generations and can be used to transmit information over large distances in complex systems.
Glider Gun
A gun is a stationary pattern that continuously emits spaceships. Shown here is a well-known pattern called the Gosper glider gun. Because the edges of our grid wrap around to their opposite edge, this gun will eventually be destroyed by its own fire.
Oscillators
These patterns are stationary and cycle over a fixed period. Oscillators with a period of 1 appear constant and are known as still life; those that move around the grid are spaceships.

WTH is it?

Invented by Cambridge mathematician John Conway in 1970, the Game of Life is a "game" with no players. Cells on a grid live and die according to a simple set of rules. A cell's fate is determined by the properties of neighboring cells. Upon each iteration of the grid:

  • A living cell with less than 2 neighbors will die from loneliness
  • A living cell with more than 3 neighbors will die from overcrowding
  • A living cell with 2 or 3 neighbors is contented and lives on
  • An empty cell with exactly 3 neighbors will begin life

Conway's game was inspired by work done in the 1940s by John von Neumann who was working on an idea for a hypothetical self-replicating machine. The Game of Life is a classic cellular automaton and the product of Conway's efforts to simplify von Neumann's ideas.

The work is of interest to computer scientists because it's possible to build the elementary parts of a computer, including memory and logic gates, inside the simulation. This makes Life a universal Turing machine — theoretically capable of computing anything that can be computed algorithmically, given a large enough grid and sufficient time.

The game's concepts of emergent complexity and self-organization are influential in a wide range of fields including physics, biology, math, economics, philosophy and art.

Big ideas

I’d encountered Conway’s game years ago after I read Emergence by Steven Johnson. The ideas in that book led me to Wolfram’s A New Kind of Science, which I found completely impenetrable, but further led me to the field of cellular automata, where I found The Game of Life.

At the time I was fascinated with the idea of enormously complex systems emerging from a simple set of rules and constraints. Ruminating on these these concepts, I wondered: could the entire universe, with its extraordinary complexity, have evolved from just a relatively few laws of physics? Do we exist in a giant simulation, albeit one that is the size of the universe and has been running for 14 billion years?

What distinguishes this simulation from “reality”, or is there any meaningful difference at all? And what about free will; if every moment in time is determined by the state of the universe in the moment before it and will evolve according to a set of fixed rules, is the future not already set?

These ideas still interest me today so I was excited to build my own simple version Conway’s game.

My process

Polya's famous method for solving mathematical problems is widely applicable to other fields of study, especially computer science and algorithm design. He outlines four steps to follow when approaching a problem:

  • take time to fully understand the problem,
  • devise a plan,
  • implement the plan,
  • reflect upon, verify, and possibly improve the solution.

Understanding the problem

First, I knew that I wanted to build this project for the web so that it was accessible to the widest possible audience. If I’d built it with Python for example, the user would have to download some code and figure out how to run it locally. My library of choice is React when building UIs for the web.

After some quick research on the web and taking a look at other examples of the game, I knew we’d need components for a grid, cells on the grid, and controls for the simulation. We’d also have to maintain the state of the grid and have functions that could manipulate the state as well as transform the state between iterations.

Would using plain React components to represent cells be sufficiently performant? What if our grid has thousands of cells? I decided to render each cell as a styled div and I’d explore other possibilities if and when it became a performance bottleneck. Get it working first, optimize later as needed.

Planning

A 2d array of 1s and 0s (alive or empty) seemed like a good choice for cells on the grid. During each iteration we loop through all the cells in the grid, count the immediate neighbors of each cell, and determine the cell’s next state based on the rules of the game.

Evolving the grid from one state to the next is a pure function—we return a new array based on the previous grid’s state instead of mutating the array in place. This is important because if we change the state of the grid while we're iterating over it we won’t get the results we’re after. We’re in luck since in React state is immutable, this concept of a “double buffer” is built in. We grab the application state, build a new state array based on it, and set our application state to the new array.

Evolving the grid from one state to the next would be implemented using setInterval, probably without too much effort in React with hooks.

We’d need a way to toggle cells on the grid as well, in a way that was comfortable and obvious for the user. And there should be a display for the current generation and population count.

Implementation

Within a few hours, I had the app working with about 80% of features implemented. It turns out that React is really good at rendering a lot of components while making only the minimum required updates to the DOM. Especially after build optimizations, using a div for each cell performed perfectly fine even with 2500+ cells.

Using React hooks, I was able to painlessly incorporate setInterval in the app and set the interval to a value saved in the game’s configuration state.

It took the better part of a day to work out the logic and combination of event listeners to get the cell toggle functionality to work the way I envisioned. I wanted the user to not only be able to click and toggle a cell's state, but also able to click and drag to “draw” cells on the grid in a natural way. After some trial and error, I was able to achieve the desired outcome.

I spent some time creating the speed toggle component from scratch. I could have searched for a 3rd party library to accomplish the same functionality, but I find that it takes time to locate the right solution and even when found, it’s often more complex than necessary. I value simplicity in the code that I write, or at least only as much complexity as necessary to solve the problem and no more. I ended up with exactly what I wanted in surprisingly little time, further testament to the power of React.

Ensuring that the game was mobile-first and also took full advantage of a wide-screen desktop display was not as trivial as I expected, though it was time well spent. I had to brush up on some CSS techniques to maintain the square aspect ratio of the grid at all times.

To jazz it up a little, I added keyboard shortcuts for the controls and spent some extra time getting the styling just right. We know that the user’s first impression is important; if we don’t get the UI right, no one will want to use it, no matter how elegant or clever the code under the hood.

Retrospective

Looking back, I would like to explore re-writing the grid and cells with the canvas API. While the app works just fine now, the performance would be improved significantly and we would be able to play with a much larger grid. I could explore a full-screen mode with a pannable grid as well.

I enjoyed building this project, learned a few things along the way, and hope you have some fun tinkering in the Game of Life!