A 2D grid-based cellular automata written in modern C++, modeling cell growth, quiescence, necrosis, and division driven by a diffusing nutrient field.
The simulation is rendered in real time using MiniFB.
The simulation consists of two coupled grids:
- Cell Grid — discrete cell states (Empty, Alive, Quiescent, Necrotic)
- Nutrient Grid — continuous scalar field in the range [0.0, 1.0]
At each simulation step:
- Nutrients diffuse across the grid
- Cells update their state based on local nutrient levels
- Alive cells may divide into neighboring empty cells
- The grid is rendered to a window
The model is inspired by tumor-like growth dynamics and reaction-diffusion systems.
| Parameter | Value |
|---|---|
| Grid size | 512 × 512 |
| Neighborhood | Von Neumann (up, down, left, right) |
| Boundary condition | Nutrient source (fixed maximum) |
enum class CellState
{
Empty,
Alive,
Quiescent,
Necrotic
};| State | Description |
|---|---|
| Empty | No cell present |
| Alive | Actively dividing, well-fed |
| Quiescent | Alive but nutrient-limited |
| Necrotic | Dead tissue (irreversible) |
Nutrients spread through the grid via discrete diffusion.
For each non-boundary cell:
new_value = current + diffusionSpeed × (neighbor_average − current)
Only direct neighbors are considered:
- Top
- Left
- Bottom
- Right
- Nutrient values are clamped to [0.0, 1.0]
- Boundary cells are continuously refilled to
MAX_NUTRIENT - Diffusion is applied before cell updates
Cells react to the local nutrient concentration using two thresholds:
divideThresholddeathThreshold
| Current State | Condition | New State |
|---|---|---|
| Alive | nutrient < divideThreshold | Quiescent |
| Quiescent | nutrient ≥ divideThreshold | Alive |
| Quiescent | nutrient < deathThreshold | Necrotic |
| Alive | nutrient < deathThreshold | Necrotic |
| Necrotic | always | Necrotic |
| Empty | always | Empty |
- Necrotic cells never recover
- Empty cells do not change state
- Only Alive cells are eligible for division
Alive cells can divide stochastically.
A cell may divide if:
- State is Alive
- Nutrient ≥
divideThreshold - At least one neighboring cell is Empty
- Collect all empty neighboring cells
- Choose one at random
- Place a new Alive cell there
- Reduce parent cell nutrient by
divideCost
- Maximum one division per cell per step
- Division is probabilistic, not deterministic
- Nutrient cannot go below
0.0
Rendering is handled via MiniFB in real time.
| Cell State | Color |
|---|---|
| Empty | Black |
| Alive | Bright Green |
| Quiescent | Yellow |
| Necrotic | Blue |
Cells fully override the nutrient field visually.
The simulation uses a builder pattern for clean configuration:
CellularAutomata sim =
SimulationBuilder(cells, nutrients)
.setDiffusionSpeed(0.08f)
.setDeathThreshold(0.18f)
.setDivideThreshold(0.58f)
.setDivisionCost(0.20f)
.build();| Parameter | Meaning |
|---|---|
diffusionSpeed |
Rate of nutrient diffusion |
deathThreshold |
Nutrient level causing necrosis |
divideThreshold |
Nutrient level required to divide |
divideCost |
Nutrient lost during division |
Several initialization helpers are provided in main.cpp:
- Sparse random noise
- Central disk
- Multiple clusters
- Small random cluster
Example:
generate_sparse_noise(cells, nutrients, 0.002f, 0.8f);./comp.sh./build/cellular_automataClose the window to terminate the program.
- C++20
- MiniFB
- Custom diffusion models
- Metabolic nutrient consumption
- Nutrient visualization overlay
