A simple set od rules lets you simulate evolution on the hypothetical planet of wator.
What is the Wator simulation?
Wator is a simulation based on a discrete model of predator-prey interaction. It was originally described by Alexander K. Dewdney in the Scientific American magazine. It simulates the hypothetical toroidal Planet Wa-Tor (Water Torus) whose surface is entirely covered with water, occupied by two species: fish and sharks. The sharks are the predators. They eat the fish. The fish exist on a never ending supply of plankton. Both sharks and fish live according to a strict set of rules. This simulation of a simple ecology is highly dynamic as both species are walking a thin line between continuing life and extinction.A video sequence from the Wa-Tor Simulation.
This article describes the implementation of Wator as a screensaver using OpenGL and C++. The screensaver is based on a dialog based MFC application combined with OpenGL for the 2D drawing. As usual, for OpenGL, using the binary without proper hardware or drivers will result in very low frame rates. The source code requires at least Microsoft Visual Studio 2019 in order to compile and run.
In this paragraph, I will briefly explain the basic rules for a Wator simulation and describe the changes necessary in order to implement the screensaver. The simulation is based on discrete time steps. It runs on a rectangular grid. To represent the toroidal world, opposing sides of the grid are connected. If an individual moves out on one side of the simulation domain, it reenters immediately on the opposing side. Fish and shark move every time step (if possible) and interact according to the following set of rules:
Rules for fish
In every time step, a fish moves randomly to one of the four neighboring fields, provided it is empty. Every fish has a predefined "breed time". On exceeding this time, it gives birth to a new fish in one of the neighboring cells, provided this randomly selected cell is free. (If not nothing happens.) Breed time counter of both the original and the descendant fish will be reset to zero. Technically fish never die. They live until they reach the breed time, then they clone and both parent as well as offspring restart their life cycle. (To clarify: according to the simulation the parent dies and creates two offspring individuals, but I don't delete the parent, I just reset it.)
The image to the left shows the options for the prey movement. Arrows indicate possible movements. Fish are not allowed to move to cells occupied by sharks. If there are no free neighboring cells no movement occurs.Rules for the prey:
- Prey fish move randomly to free neighboring cells
- Once the breed time is up a new fish spawns in a free neighboring cell and the parents breed time is reset.
Rules for sharks
Sharks move randomly to fields that are either free or occupied by fish. Every round they lose one point of energy. If they enter a field occupied by a fish they eat the fish and gain a defined amount of energy. If the energy level drops below zero the shark dies. If the energy exceeds a predefined value sharks create an offspring in a free neighboring field. The energy is split evenly between the parent and the child.Rules for Sharks:
- Sharks move randomly to neighboring cells that are free or occupied by (non shark) fish.
- If the cell to which the shark is moving is occupied by other fish it is consumed. The energy of the shark increases by a predefined value.
- If the shark has enough energy it spawns offspring in a free neighboring cell.
- Sharks lose a small fixed ammount of energy with every time step.
- A shark dies if its energy level drops to zero.
Modifications made to the original algorithm
In order to turn this simulation into a screensaver, I made changes to the original set of rules. According to the original algorithm, sharks do not move randomly. Instead they move specifically to cells in their neighborhood containing fish. Testing this is slow, thus I allow only random movement. Surprisingly there is no visible difference. Alexander K. Dewdney suggested an implementation very similar to a cellular automata. If you implement Wa-Tor that way and by looping over all cells in the simulation domain, you are forced to include cells that do not contain any individual in the calculation. Since this is too slow I chose to implement it as a linked list, thus instead of looping over all cells, my algorithm loops over existing individuals only.
Drawing the number of individuals per species versus time yields curves characteristic for the so called Lotka-Volterra equations (also known as predator-prey equations). This behaviour can be described by two differential equations. There usual form is:Population size vs. time for a predator prey model.
- y is the number of predators (here: sharks)
- x is the number of its prey (here: fish)
- t represents the development of the two populations against time
- alpha, beta, gamma and delta are parameters representing the interaction of the two species.
Although the solution to these differential equations show a periodic behaviour, they can not be expressed in terms of normal trigonometric functions. However, an approximate linearised solution yields a simple harmonic motion with the population of predators leading that of prey by 90 degree.
Wator as a screensaver
Technically a Windows screensaver is a normal executable with the extension scr. Additionally it has to have a defined command line interface in order to display itself in configuration mode, in preview mode or in screen saver mode.
|Command line option||Screensaver action|
|/P:###||Start the screensaver in preview mode. Treat ### as the decimal representation of a HWND. Popup a child window of this HWND and run in preview mode inside that window.|
|/C:###||Open the screen saver configuration dialog. If ### is not present GetForegroundWindow() should be the parent of this dialog. Otherwise ### should be treated as the decimal representation of a HWND, which should be used as a parent.|
|/S||Run as screen saver in full screen mode. When there is some kind of keyboard or mouse activity in the screen saver mode, the screen saver is ended.|
Installation and Configuration
Download and run the installer. As a side node: Using the command line option you can actually start the screen saver under Linux/BSD using wine. The saver will run but won't start automatically. Use "wine WatorSaver.scr" to start the config screen and "wine WatorSaver.scr /s" to start the saver in full screen mode. To edit the settings go to the Windows desktop, right click, and in the context menu, select the display options entry. The configuration dialog allows setting up the simulation parameters described below as well as additional settings for the display options.
All changes made to the parameters will be reflected instantly in the preview window. The following table lists the parameters and their meaning for the simulation process:
|Prey breed time||The number of time steps necessary before a prey can create an offspring.|
|Energy per hunted prey||The energy a predator gets for each prey individual it eats. In each time step, the predator loses one energy point. It dies when the energy falls below zero.|
|Energy to create offspring||The minimum amount of energy a predator must have in order to create an offspring. When creating an offspring, the energy is evenly split between the newly created offspring and the parent.|
|Pixelsize||The size of an individual in pixels. Reducing this number will require very high performance!|
The source code and build files for Visual Studio are available at github.
Writing an OpenGL screensaver for Windows by Rachel Grey.
Probably the simplest possible OpenGL screensaver. All you need to know on OpenGL initialization and basic Windows screensaver design.
Wikipedia article on Lottka Volterra equations.
Find out more about the theoretical background of predator prey simulations at this Wikipedia article.
OpenGL tutorials by NeHe Productions.
Excellent page with a lot of OpenGL tutorials and source code for a variety of platforms and programming languages.