Pandemic Simulations


Due to COVID-19 I have seen some infection simulations going around the Internet. Most popular (or what I have seen linked to the most) seems to be this simulation from the Washington Post.

I have been wanting to experiment with virus infection simulations for a while now, so now is the time.

Before going further I want to make it clear that this is in no way specific to COVID-19 and I have no professional training in viruses or infections. This is Softology, not Virology.

Simulation Version 1

This version is a blatant ripoff the Washington Post simulation but allows more settings to be tweaked and larger population sizes to be experimented with. People (shown as circles) move around in random directions bouncing off each other.

The simulation starts with all the people healthy (not infected) and a single person set as infected in the middle of the world. These are the settings for the simulation that can be tweaked.

Pandemic Settings

The above default parameters result in the following run. The virus spreads quickly to the entire population. The 50% recovery probability results in roughly half the population dying with the other half recovering from infection.

Now let’s take a look at modifying some parameters.

The next run had increased population density so people are much closer together. The virus now spreads much faster and ends the same as the previous run with a 50/50 dead/recovered ratio.

Now with the density lowered so people are not as packed together. This time the virus does not infect all healthy people. This is a good example of “social distancing” helping.

Lowering the speed at which people move. If infected and healthy people move slower then the virus has less chances to spread. In the end about a third of al people never get infected and another third recover from infection.

Lowering the probability that people will move each step of the simulation to 10%. This could represent the majority of the population staying home and people only going out for essentials. With this change the virus dies out and the impact on the population is minimal.

If the probability of movement is 0 then the initial virus cannot spread and it dies out.

Simulation Version 2

This time I used an even simpler model. People live on a square grid and only move randomly in a north, south, east or west direction.

Here are the default settings this time

Pandemic Settings

Using those parameters gives the following result

Again a higher density population allows the virus to spread much faster

Social distancing can be simulated by lowering the population density to 10%. People are still freely moving around but keeping their distance from each other due to lower density. The virus spreads much more slowly and not all people get infected.

The original settings are run again, but this time there is only a 5% chance people move around each step of the simulation. This models people who are isolating themselves at home. The fewer people who do move around can be thought of as the people who have to go out for food or medicine. This results in the virus barely spreads at all before dying out.


Both of these very simplistic models show clearly that the best way to stop or severely limit a virus spreading is social distancing and self isolation.

If you want to play with these simulations yourself and try tweaking other parameters they are now included in Visions of Chaos.

Another Example

Grant Sanderson aka 3Blue1Brown made the following video about his simulation tests. Much more detailed than my simple tests and as with all his videos highly recommended.


Ant Colony Simulations


This is a simple example of an agent-based model that tries to emulate behavior of ants as they forage for food.

The basic principals of the simulation are;
1. Ants leave the nest moving randomly.
2. If an ant finds some food it picks it up and takes it back to the nest.
3. Ants carrying food leave a pheromone trail on their way back to the nest.
4. Ants looking for food will follow pheromone trails to have a better chance at finding food.

Once an ant finds food, it turns around 180 degrees and then heads towards the nest (with some random turns thrown in so their paths are not always straight lines). In reality ants seem to be able to use the sun position and landmarks to find their way back to the nest.

Using those very simple principals shows how a colony of ants with no other means of communication can coordinate to locate and retrieve food in the surrounding areas.

Programming the ants

For these simulations each ant has some simple properties that control its behavior like position, direction, maximum angle it can turn, move speed, sense angle and sense direction.

Position is the X,Y coordinates of the ant. Direction is the angle the ant is facing. Maximum angle determines how far an ant can turn left or right each step of the simulation. Move speed is how far the ant moves forward each simulation step.

For the process of how an ant looks for pheromones I based this on a similar way to how the Physarum Simulation particles work. An ant looks a certain distance and angle to the left, front and right ahead of itself and senses how many pheromones are in these three locations. The ant then turns towards the spot with the highest pheromone count. If an ant is moving randomly and gets near a pheromone trail it will turn towards the trail and hopefully follow the trail to find food.

The pheromones can be slightly blurred out each frame to simulate diffusion.

If an ant hits the edge of the world it turns 90 degrees and keeps moving.

I had an early attempt at ants simulation for many years that kept the ants on a fixed integer coordinate 2D grid. The change here to using floating point values for ant positions and angles really helped give more natural looking movement as shown in the animated gifs in this post.


Obstacles turned out to be a problem. If there is an obstacle between the food and nest and ant who finds the food will then head towards the nest and get stuck on the obstacle wall. They do eventually bump along the edge of the obstacle and make it around, but they should be smarter and follow a known “good trail”.

If an ant hit an obstacle I got it to only move randomly for the next 100 simulation steps and not leave any pheromones (as we don’t want a trail heading to an obstacle). Still doesn’t really help. Ants still get stuck at the obstacle. More thought and testing required.

Then I got a twitter reply from @psychobiotic suggesting having a foraging pheromone trail left by ants as they look for food. When an ant finds food it can then use the foraging trail to get back to the nest.

That works much better than my previous method above.


This new version of the ant simulation is now available in Visions of Chaos.



I first heard about Huegene after watching the following video from Dave Ackley.

Similarities to Wa-Tor

Huegene is similar to Wa-Tor with the following differences;

1. Plants and herbivores rather than fish and sharks.

2. Plants cannot move like fish can. They spread through self propagation.

3. Herbivores have a probability chance of eating plants based on how close in color the herbivores and plants are.

Color Genes

Both the plants and herbivores have genes that determine their color.

When a new plant or herbivore is created it has a slightly mutated color from the parent. This results in plants growing in clumps of similar colors.

Plant Consumption Probability

This is the main difference between Huegene and Wa-Tor. In Wa-Tor the sharks happily gobble up any fish they land on. In Huegene the herbivores have a probability of eating a plant based on how close in color they are to the plant. So a blue herbivore will have a greater chance of eating a light blue plant than a yellow plant.

Herbivores eat the plants around them with the most similar color, which leads to the less similar plants in the area being able to thrive which then have more resistance to the herbivores in the area. The herbivores also mutate and can adapt to eating the new plant colors. This feedback cycle continues as the plants and herbivores adapt to the changes in each other.

Gene Color Methods

For the gene colors I use the following 3 options;

1. Hue. Hue is a floating point value between 0 and 1. For display the HSL(hue,1.0,0.5) value is converted to RGB.

2. RGB. Each plant or herbivore has 3 color genes for red, green and blue.

3. Hue and Saturation. Hue is between 0 and 1. Saturation is between 0.5 and 1. For display the HSL(hue,saturation,1) value is converted to RGB.

The following three sections explain how these different gene methods are used to determine a probability of a herbivore eating a plant next to it.

Hue Genes

Hue is a floating point value between 0 and 1. It is converted to RGB values for display.

The following code is used to determine if a herbivore eats a plant near it.

//difference between hue values
//wraparound difference - make sure difference is between 0 and 0.5
if difference>0.5 then difference:=1-difference;
//scale difference to between 0 and 1
//test probability
if random*probabilityfactor<(1.0-difference) then EatPlant

The difference takes into account the fact that the Hue values wrap around from 1 back to 0 on the hue color wheel. For example, if you have a plant hue at 0.1 and a herbivore hue at 0.9 you want their difference to be calculated as 0.2 and not 0.8.

I also added a “probability factor” in. If this is greater than 1 it lessens the chance of the herbivore eating the plant. If you get a simulation that the herbivores are too plentiful increasing this factor will help keep them under control.

RGB Genes

Each plant and herbivore now has 3 red green and blue values that are used for display and the probability of the plants being eaten by herbivores.

//difference between RGB values
//test probability
if random*probabilityfactor<(1.0-difference) then EatPlant

Hue and Saturation

Now takes into account hue and saturation values. Hue is between 0 and 1. Saturation is between 0.5 and 1.

//difference between hue values
//wraparound difference - make sure difference is between 0 and 0.5
if difference>0.5 then difference:=1-difference;
//saturation contributes 50% of difference value
//test probability
if random*probabilityfactor<(1.0-difference) then EatPlant

Other Examples

Plants actively look for empty neighbor locations to spread into. Herbivores move at random rather than actively looking for plant neighbors.

Plants actively looking for empty neighbors. Herbivores hunting for available plant neighbors.

Plants spread randomly. Herbivores hunt for available plant neighbors.

Sample Movie

Extension Into Three Dimensions

This next movie extends 2D into 3D. Same logic and parameters as the 2D movie, just adding the third Z dimension into the calculations.

The next movie averages the colors of the cells for display. The simulation genes themselves are not averaged/blurred, just the display colors. This cuts down the color noise and allows the more general waves of plant types to be seen. Or maybe it doesn’t? Anyway, it is another option to experiment with.


Huegene is now included in Visions of Chaos.



Wa-Tor is a simulation of fish vs sharks in a toroidal wraparound world. It was devised by AK Dewdney in 1984 and published in Scientific American under the name “Sharks and fish wage an ecological war on the toroidal planet Wa-Tor

The original Wa-Tor simulations took place on a VAX system with a display 80×23 characters in size. Each step of the simulation took a while to run (no exact time specs given). It is interesting to read in Dewdney’s article that to test a theory he had about the system he let a setup run overnight to see what happened in the morning. Now with a decent computer you can run these over thousands of cells in almost real time.


The world consists of a 2D array that wraps around at the edges. When you have the wrapped edges the world becomes a donut (or toroid) shape.

A number of sharks and fish are randomly distributed into the world.

Fish look for empty cells directly next to themselves (using a von Neumann neighborhood of neighbor cells directly north, south, east and west) and randomly move into one of them. If they are older than a specified breed age they will leave a child fish behind in their current location.

Sharks look for fish next to themselves and randomly eat one of them if found. When they move they will leave a child shark in their old spot if they are older than a specified breed age. If no fish are found they will randomly move into an available empty space. If they do not eat their starvation level increases. If they starve for too many steps of the simulation they die and are removed from the world.

Here is an example movie Wa-Tor. Green pixels are fish, red pixels are feeding sharks, gray pixels are sharks.

If you balance the settings right this sort of simulation will continue to cycle indefinitely.

Wa-Tor Parameters

Wa-Tor is controlled by the following parameters the user can play with;

Fish breed age – how many simulation steps does a fish need to survive for before it can give birth to baby fish. For these simulations I used 3 cycles.

Shark breed age – how many simulation steps does a shark need to survive for before it can give birth to baby fish. 15 cycles.

Shark starve time – how many simulation steps it takes for a shark to starve to death if it does not eat. 10 cycles.

Random Movement

An alternative method is to allow fish and sharks to only move randomly.

Fish pick one of the 4 directions at random. If it is empty they move into it and potentially have a child. If it is occupied they do nothing.

Sharks also pick a random direction. If a fish is there the shark eats it. If the spot it empty the shark moves into it. If it is occupied by another shark the shark does nothing.

Here is an animated gif showing fish and sharks both moving randomly.

Color Fish

This was a quick idea I had. Each fish has a color assigned to it. When it has a child fish, the child fish has the same color with slightly different RGB values. This way you can see how a “family” of similar fish spreads.


Wa-Tor can also be extended to 3D. In the following movie the simulation takes place in a 3D cube of cells, but cells outside a centered sphere are hidden to see the inner structures more clearly.

In this next movie only the fish are visible and they are colored to show how fish and their offspring spread.


Wa-Tor is available in Visions of Chaos.




This is a relatively simple simulation of multiple species fighting for survival.

Simulation World

A terrain is generated using Perlin noise. The noise values are blurred to smooth out the edges a little.


Multiple types of creatures are created that inhabit the world. They each have properties like;
X and Y position – where the creature is in the world
Radius – how large the creature is
Direction – what direction the creature is facing
Speed – how far the creature moves each step of the simulation
Color – what color it is so creature types can easily be distinguished from one another
Sides – creatures are shown as polygons with between 3 and 8 sides
Age – how many simulation steps has the creature lived for
Maximum Age – if a creature reaches this age it dies of old age
Minimum and Maximum Breed Ages – a range of ages that the creature can reproduce

The simulation is started by creating a bunch of random creatures in the world. They all move according to their properties.


When 2 creatures come into contact with each other they fight for survival. At this stage I have 3 possible fight methods to determine which creature wins;
1. Random – one of the creatures in the fight is randomly chosen to die
2. Attacker wins – whichever creature first moves and hits another creature kills the creature it hits
3. Strongest wins – Creature strength goes up from birth to middle age then down again as the creature ages. This is so “babies” and “elderly” creatures are not as strong in battle against middle age creatures.


Creatures have a chance to duplicate themselves if they are between a minimum and maximum breed age and if there is room near them for the child creature to be born into. There is an option for the child properties to be mutated slightly (or not so slightly).


Here is a sample movie showing a full run that lasts until one of the species manages to kill all others. No mutations in this example.

Species is now available as a mode within Visions of Chaos.


Primordial Particle Systems

Primordial Particle Systems

A while back I was playing with Particle Life simulations. At that time, another video I came across was the following

Click here to read the paper “How a life-like system emerges from a simple particle motion law” that describes how it works in great detail.

Primordial Particle Systems

For a simpler overview I recommend this page by Brian H that includes snippets of the source code that helped me get my version working.

Primordial Particle Systems

My even (hopefully) simpler explanation is as follows;

1. Fill the simulation space with a bunch of particles.
2. Particles have settings for radius, alpha, beta and velocity.
– radius is how far around itself each particle can sense the other particles.
– alpha is the fixed rotation amount. Each particle turns by this amount each step of the simulation.
– beta is the proportional rotation. This is the amount the particle turns depending on its neighbor particles.
– velocity is how far the particles move forward each step.
3. Each particle maintains a heading which is the direction it is facing.
4. Each of the particles move by the following steps
– Count how many neighbor particles are within the radius
– Work out how many of them are to the left and right of the particle
– Turn towards the left or right with the larger count
– Move forward

That’s all there is. From those relatively local and simple steps you can get some nice cell like and amoeba like structures emerging.

Primordial Particle Systems

More sample images in this gallery.

The following movie shows some example results created with the latest version of Visions of Chaos.

Here is another sample movie. This time using 2D metaballs so individual particles in close proximity to other particles merge into blobs.


Physarum Simulations

Physarum Polycephalum

Physarum Polycephalum aka slime mold is made up of a vast number of individual single cell organisms. These organisms have no brains or intelligence, but complex behaviors emerge when many of them are put together. Depending on their environment they move like what seems to be a much more complex entity.

Here are some great videos about slime molds with some awesome time lapse footage.

Once you have watched those you should hopefully have a better appreciation for the simple slime mold and the rest of this post will make more sense.

Simulating Slime Molds

I have been interested in trying to simulate slime molds fror years now and my interest was once again peaked from seeing Sage Jenson‘s Physarum page here describing his simulations which were inspired by the paper Characteristics of Pattern Formation and Evolution in Approximations of Physarum Transport Networks.

Sage gives this simple diagram explaining the steps.

The basic explanation is a bunch of particles move over an area turning towards spots with higher concentrations of a pheromone trail. They also leave a trail as they move. These basic steps create interesting patterns and structures.

My method

Physarum Simulation

Following the principals from Sage and the paper, this is how my take on simulating Physarum works.

Physarum Simulation

1. Create a 2D array that tracks the pheromone trail intensity at every pixel location. Initially all spots are set to 0 intensity.

Physarum Simulation

2. Create a list of particles with properties heading (direction/angle the particle is moving), x,y (positions), sense angle (how wide the particle looks to the left and right) and sense distance (how far in front the particle looks), turn angle (how quick the particle turns towards the sensed areas). I set the number of particles to match the image width multiplied by the image height. That seems to nicely adjust the particle count when changing image sizes.

Physarum Simulation

3. Main loop

Physarum Simulation

a) Display. For display I scale the minimum and maximum trail values to between 0 and 255 for a gray scale intensity (or to be used as an index into a color palette, but simple gray scale seems to look the best).

Physarum Simulation

b) Each particle looks at the 3 locations in front of it based on the sense angle and distance. You then work out which of the left, front and right spots have the highest concentration of the pheromone trail.

Physarum Simulation

c) Turn the particle towards the highest pheromone intensity. ie if the left spot is highest then subtract turn angle from the particle heading. If the front is highest do not make any change to the particle heading. If the right is highest add turn angle to the particle heading. You can also reverse this process so the particles turn away from the highest pheromone levels.

Physarum Simulation

d) Move the particle forwards by a specified move amount.

Physarum Simulation

e) Deposit an amount of pheromone onto the trail to increase it.

Physarum Simulation

f) Blur the trail array. This simulates the pheromones diffusing over the surface. I use this quick blur with an option for a blur radius between 1 and 5.

Physarum Simulation

g) Evaporate the pheromone trails by a small amount. Subtract a small amount from all of the trail array cells. This slowly decays the amount of pheromone.

Physarum Simulation

Repeat the main loop as long as necessary.

Physarum Simulation


See my Physarum Simulations gallery for more images.

Here is a movie with some example results showing the simulations running. For the display the pheromone trail intensities are mapped to a gray scale palette (brighter = higher intensities).

The next movie is an example of Physarum simulations starting from a circular region of Physaruym particles.

Multiple Species Physarum Simulations

Physarum Simulation

My next idea was to have multiple Physarum types in the same area. For these cases I used 3 sets of Physarum (3 groups of particles with their own unique settings) as shown in the following settings dialog.

Physarum Simulation

Each of the pheromone trail intensities are then converted to RGB color components.

Physarum Simulation

This works but the results are just 3 separate simulations that do not interact. The idea is to have each of the particle types attract to their pheromones, but move away from the other 2 types of pheromones.

Physarum Simulation

The main change is in the pheromone detection and turn code. For the single Physarum simulation the particles look left, forward and right and then turn and move based on the location with the highest pheromone concentration. For 3 particle types they take into account their pheromone concentrations but subtract the pheromone concentrations of the other 2 types. For example if the 3 trail/pheromone arrays are called rtrail, gtrail and btrail, then the red particles pheromones are calculated by using rtrail[x,y]-gtrail[x,y]-btrail[x,y]. The highest concentration of left, forward and right is then turned and moved towards.

Physarum Simulation

More example images can be seen in my Physarum Simulations Gallery.

Here is a sample movie showing some of the multiple species results.

Physarum Image Processing

This was inspired after seeing the following video from Magic Jesus.

A bunch of Physarum particles start on the surface of an image. The particle colors are based on the image color they start on.

After this let them wander around the image area following Physarum simulation rules with a slight change. In this case rather than turning left or right based on a pheromone trail intensity, they turn towards the pixel that is closest in color to themselves.

This is my result after running Physarum simulations on three colorful paintings. The first and third are from Leonid Afremov and the second by Kandinsky (same painting as in Magic Jesus’ example movie).

These would look great on a large wall in a modern art gallery. Playing slowly enough so you could just notice the changing colors (like clouds moving slow enough you don’t notice they change until you look away and back again). The exhibits with those dark rooms you enter and read the little white plaque with a blurb on what it is all about. “The slow interplay of colors represents the human condition and the struggles of how humans still cannot find a peaceful equilibrium of coexistence with themselves and the planet.”

Zooming In And Out

Thanks to a great tip from @Foglebird you can easily “zoom” in and out of these simulations by scaling the move and sensor lengths. So if you find a nice result that the details or curls are too small for you, double the move distance and sensor distances.

I have added Zoom In and Zoom Out buttons to my Physarum modes in Visions of Chaos that do the scaling automatically.


See the following movie for a more detailed explanation of this blog post and the Physarum modes within Visions of Chaos.

Demoscene Physarum

Razor1911 used Physarum for their demo La Vie Opportuniste. Note that the executable for this demo is only 4K (4096 bytes) in size!


Both single and multiple species Physarum Simulations and Physarum Pixel Flow are now included with the latest version of Visions of Chaos.


Clusters and Particle Life

This is another great example of emergence. Complex behavior results from many individual particles following simple rules.

Jeffrey Ventrella explains his Clusters here.

Here is another particle based life model

I learned about Clusters when Code Parade posted the following video explaining his version of Clusters he calls Particle Life.

The source code to Particle Life was generously shared here so I had a go at converting the code and playing with these myself.


Here are some of my results.

Here is another more recent example. This time using 2D metaballs to render the particles. This results in nearby particles merging into blobs.

Extension Into 3D

Once I had the 2D version working, extending into 3D was the next step. These movie parts use the same settings as in the 2D movie above.

The most obvious problem with that movie is all the single particles blocking or obscuring the interesting structures from view. To fix this I added an option for the user to specify to hide particles connected to a small number of others. For example, any particle that has 3 or less “attached” particles is hidden.

I also now have an option to skip a number of initial steps. For the next movie I skipped the first 1000 steps of each part. This helps show the emerged structures more clearly without having to wait for the random dust particles to form into more coherent structures.

Also, now that I got RenderMan implicit blobby surfaces (aka metaballs) supported I used metaballs to show the connected particles. Change the lighting to use the RenderMan DayLight model and you have the following improved examples of how particle life works in 3D.


Both the 2D and 3D Particle Life are included with Visions of Chaos.