Simple Rules, Complex Behavior: Emergence in Conway’s Game of Life (with Rust)

What is Emergence?
Ever wondered how a colony of ants coordinates to build intricate nests, even though each ant follows just basic instincts? Or how flocks of birds create sweeping patterns in the sky without a leader? These are examples of emergence – the idea that complex behavior arises from collections of simple interactions. In other words, the whole can exhibit properties or behaviors that the individual parts do not have on their own. Essentially, emergent behavior means surprising complexity from simple rules.
It’s a fascinating, almost magical concept: a system of simple pieces, each following basic rules, can generate patterns and behaviors far beyond what any single piece could do by itself.
Conway’s Game of Life: Simple Rules, Surprising Patterns
Conway’s Game of Life (often just called Life) is a classic computer simulation that embodies emergence. Invented by mathematician John Horton Conway in 1970, it’s a type of cellular automaton – essentially a grid-based simulation where each cell follows a small set of rules. Despite the name, it’s not a game you play in the traditional sense. Instead, you set up an initial configuration and then sit back and watch what happens.
How does it work?
Imagine an infinite grid of square cells (we usually simulate a large finite grid). Each cell can be either “alive” (filled in) or “dead” (empty). We start with some pattern of alive/dead cells – this is the seed of the simulation. Then the game progresses in discrete steps (generations) according to four very simple rules Conway defined:
- Underpopulation: If a live cell has fewer than 2 live neighbors, it dies.
- Survival: If a live cell has 2 or 3 live neighbors, it stays alive.
- Overpopulation: If a live cell has more than 3 live neighbors, it dies.
- Reproduction: If a dead cell has exactly 3 live neighbors, it becomes a live cell.
That’s it – those are the only rules! On each tick (generation), you look at every cell and apply those rules simultaneously to decide who lives or dies.

At first glance, if you seed the grid randomly, the screen looks like static noise. But let the simulation run for a while, and order begins to emerge out of chaos. You’ll notice blinkering patterns and moving clusters that weren’t explicitly programmed — they just happen.
For example, a pattern called the “glider” may appear: a small cluster of five cells that marches diagonally across the board forever. Other patterns form oscillators or still life shapes. Amazingly, you can even get patterns that replicate or grow indefinitely. All these intricate behaviors arise naturally from those four rules, with no further intervention!
Coding the Game of Life in Rust
One of the joys of Conway’s Game of Life is that you can easily program it yourself – and doing so is a great exercise for beginners. The logic is straightforward, but the outcome is powerful. Rust, in particular, offers an amazing playground for this.
You can represent the grid as a 2D array or list of boolean values, update it every tick based on the rules, and display the result. Rust’s performance means you can handle big grids, and its safety ensures you won’t hit strange memory issues. And thanks to Rust’s flexibility, you can target desktop apps or the web.
Let’s look at two examples, both written in Rust, but using different approaches:
🧪 rust-dioxus-game-of-life
This project uses Dioxus, a modern UI framework for Rust, to run the Game of Life either as a native app or compiled to WebAssembly for the browser. It’s built similarly to how Angular works, with components that re-render based on state.
With this version, you can easily share the simulation online or run it natively. The rendering is smooth, and the Dioxus framework makes it beginner-friendly to build interfaces. It’s a great example of writing one Rust codebase and running it anywhere.
🧱 rust-minifb-game-of-life
This version uses the lightweight minifb
crate to open a native window and draw directly to a pixel buffer. It’s more low-level and very fast. The grid updates in real time and displays patterns as glowing dots on a dark screen.
You can control speed, restart simulations, and enjoy a very raw and direct implementation. It’s a perfect way to experience how Rust can power graphics and performance with minimal dependencies.
/// Rust implementation of Conway's Game of Life
impl Universe {
/// Creates a new universe with random alive/dead cells.
fn new(width: u32, height: u32) -> Universe {
let mut rng = rand::rng();
// Generate width*height cells, randomly alive (1) or dead (0)
let cells = (0..width * height)
.map(|_| if rng.random_bool(0.5) { 1 } else { 0 })
.collect();
Universe { width, height, cells }
}
/// Exposes the internal cell array for rendering.
fn cells(&self) -> &[u8] {
&self.cells
}
/// Advances the universe by one tick, applying Conway's rules.
fn tick(&mut self) {
let mut next = self.cells.clone();
// Iterate each cell position
for row in 0..self.height {
for col in 0..self.width {
let idx = (row * self.width + col) as usize;
let live_neighbors = self.live_neighbor_count(row, col);
// Apply rules of Life
next[idx] = match (self.cells[idx], live_neighbors) {
(1, x) if x < 2 => 0, // underpopulation
(1, 2) | (1, 3) => 1, // lives on
(1, x) if x > 3 => 0, // overpopulation
(0, 3) => 1, // reproduction
(c, _) => c, // otherwise stays the same
};
}
}
self.cells = next;
}
/// Counts alive neighbors around a given cell (with wrap-around edges).
fn live_neighbor_count(&self, row: u32, col: u32) -> u8 {
let deltas = [self.height - 1, 0, 1];
deltas.iter()
.flat_map(|&dr| deltas.iter().map(move |&dc| (dr, dc)))
.filter(|&(dr, dc)| !(dr == 0 && dc == 0))
.map(|(dr, dc)| {
let r = (row + dr) % self.height;
let c = (col + dc) % self.width;
self.cells[(r * self.width + c) as usize]
})
.sum()
}
}
Reflections:
Emergence is about discovering beauty in the unexpected. And Rust? It gives you the performance, safety, and flexibility to explore that beauty through code.
So go ahead. Write those four rules. Watch life unfold. And see what emerges.