A C++ simulation of neuro-evolution: a population of creatures, each controlled by a small neural network encoded in its genome, lives on a grid and evolves under selection pressure. Over successive generations the creatures breed, mutate, and adapt to survive their environment — and you can watch it happen in real time through a Qt interface.
Inspired by the "evolving creatures with tiny brains" family of simulations (e.g. biosim4), implemented from scratch in modern C++.
- Genome-encoded brains. Each creature carries a genome of hexadecimal genes. Every gene decodes into a wire of the creature's neural network — a connection between a sensor, internal, or action neuron, with a weight and an activation threshold.
- Perceive → think → act. Sensor neurons read the environment (borders, position, local density…), internal neurons combine those signals as weighted sums, and action neurons turn the result into movement or interaction.
- Selection, breeding, mutation. At the end of each generation the environment culls creatures according to a selection rule; survivors breed, their genomes recombine and mutate, and the next generation begins.
- Live visualisation. Creatures are drawn on the grid, each coloured by its genome, so related lineages share a colour and you can literally see structure emerge.
Each 8-digit hex gene is expanded to bits that specify:
| Field | Meaning |
|---|---|
| source type | sensor neuron vs internal neuron |
| source id | which neuron (taken modulo the number of active neurons) |
| end type | internal neuron vs action neuron |
| end id | which neuron |
| weight | strength of the connection |
| threshold | activation threshold of the target action neuron |
Decoding every gene wires up the network; the same genome also determines the creature's RGB colour, so visually similar creatures are genetically similar.
Sensor neurons — Rnd (random), BDx / BDy (distance to the E–W / N–S border),
BD (nearest border), Lx / Ly (x / y position), Dens (local population density).
Action neurons — MFR (move forward/back), MRL (move left/right), Mx / My
(move along an axis), Mrn (move randomly), Kill (kill the creature ahead).
- Square — creatures in a central square are culled each generation.
- West / South border — creatures near a chosen edge are culled.
- Dense — creatures in overcrowded regions are culled, modelling resource competition.
All parameters are set from the GUI's configuration dialog before a run: environment size and type, kill-zone size, number of creatures, genes per genome, maximum internal neurons, mutation rate, the active sensor/action neuron sets, and the number of generations and steps per generation.
- A C++20 compiler (GCC 11+, Clang, or MSVC)
- CMake ≥ 3.16
- Qt 6 — either from your system package manager, or fetched via vcpkg
sudo apt install qt6-base-dev cmake build-essential ninja-build # Debian/Ubuntu
cmake -S src -B build -G Ninja
cmake --build build
./build/SimulationOfEvolutionSet the VCPKG_ROOT environment variable, or add vcpkg as a submodule at the repo root
(git submodule add https://github.com/microsoft/vcpkg), then configure as above. vcpkg builds
Qt from source on the first configure, which can take 10–20 minutes.
Open the folder in Visual Studio as a CMake project — system Qt or vcpkg both work.
.
├── src/ # sources + CMakeLists.txt + vcpkg.json
│ ├── Main.cpp
│ ├── Creature.{h,cpp} # genome, brain-building, breeding, mutation
│ ├── Neurons.{h,cpp} # sensor / internal / action neuron hierarchy
│ ├── Environment.{h,cpp} # grid, movement, selection, generations
│ ├── QtGraphics.{h,cpp} # GUI and rendering
│ └── utilities.h
├── docs/ # design overview and specification
├── assets/ # demo GIF
├── README.md
└── LICENSE
The neuron hierarchy is designed to be extended: add a new sensor or action neuron by deriving
from SensorNeuron / ActionNeuron, add a new selection rule in Environment, or add
per-generation data logging to plot how diversity and population change over time.
MIT — see LICENSE.
Radoslav Jochman
