As a hobby algorist, I’m always looking for new algorithms that can help me create interesting pieces of art. Recently, I came across a paper written by Brian P. Hoke. It was written 22 years ago, but there’s a lot of useful information in it. The paper, among other things, talks about using a simple 2D cellular automata rule named “stepping stone” to modify photos such that they look like paintings. The thing I like the most about the rule is that you can pass random noise to it and it will turn it into something beautiful after enough iterations.
I’ll now briefly describe how I implemented the stepping stone rule using P5.js.
As usual, inside the
setup() function, I created a canvas of size 400x400.
Then, I filled it up with random colors using the following code:
With the above code, the canvas looks like this:
The idea behind the stepping stone rule is extremely simple: For each pixel X on the canvas, toss a coin. If it’s heads, randomly pick one of its four neighbors and change its color such that it matches the color of pixel X.
A more visual description would be that, at any given time, every pixel has a 50% chance of consuming one of its neighbors.
Coding the above rule takes just a few minutes. Here’s what my
draw() function looks like:
To save time, I’m using the
set() function. For better performance, you could try manipulating the
pixels array directly.
Also note that I’m using the
% operator while finding neighbors. This helps me wrap around edges very easily and concisely.
With the above code, I get a piece of art that looks like this:
That was all too simple. I wanted more. So, while searching for other rules that are similar to the stepping stone rule, I came across papers written by David Griffeath, a professor at the University of Wisconsin. He, and a few of his students, have detailed several different approaches you can follow to create art with cellular automata. Some of them create art that’s truly mesmerising. For now, I’ll focus on cyclic cellular automata. Implementing them is slightly more difficult, but the results are definitely worth the effort.
The idea behind a cyclic cellular automaton is that you have a large grid containing hundreds of cells. Each cell has a state associated with it. The state is essentially just a number–something between 3 and 16 usually. At any given point, a cell can increment its state if and only if one of its neighbors is at a higher state than it–usually by just 1 point.
For example, if cell A’s state is 3, and it has at least one neighbor whose state is 4, then A’s state too becomes 4.
You’re going to need a few global variables to implement this logic. Let’s say we have a variable named
matrix to represent the large grid. To store temporary copies of the grid, we have another variable named
Next, let’s say the state of a cell can be a number between
14. You are free to change the maximum state number.
Lastly, we can have an array of colors, which we use to represent a cell as a pixel.
Here’s how I initialized the above variables inside the
As you can probably tell, I’ve assigned random states and colors to the cells and pixels.
Next, inside the
draw() function, I have one large
if condition that checks if a cell has at least one neighbor with state difference of +1. If that’s true, I update the state. This needs to be done with a copy of the original grid to make sure that the
if condition is not using intermediate values.
Once the grid has been updated, I update the colors of the pixels in the canvas using the
set() function as usual.
Note that the
cloneMatrix() function is necessary because array methods like
slice() don’t create copies of sub-arrays.
With the above code, you should see spirals being generated within seconds.
If you let it run for some more time, your canvas will be full of large spirals!
Isn’t it amazing how such simple rules can lead to so much complexity? I, for one, am very impressed.