No gradients, no training data. A population of cars drives the same track at the same time. Each car’s
neural network is encoded as one flat vector of numbers (its genome). After every generation the
better drivers are more likely to become parents, so good driving spreads through the population.
Sensing and thinking
Each car casts 7 rays (−90°, −50°, −22°, 0°, 22°, 50°, 90°). A spatial grid over the track walls and an
Amanatides–Woo grid walk keep every ray query exact and fast. The inputs are the ray proximities 1 − d/R
plus the car’s own speed. A fully connected network with tanh units, 8 → H → 2, outputs steering
and throttle/brake in [−1, 1].
Physics
ψ̇ = v / L · tan(δ), |ψ̇| ≤ a_lat / v (kinematic bicycle + grip limit)
v̇ = a_throttle − c_d · v
With the grip limit, a car that enters a corner too fast understeers and runs wide (skid marks).
Holding full throttle is not enough: good drivers learn to brake before tight corners.
Fitness
f = 100 · (furthest progress in laps) + [finished] · 100 · (1 − t / t_max)
A car is out when it touches a wall, stops making progress for 2.5 s, or runs out of time. Finishing 3 laps earns
a bonus that grows the faster the laps were driven.
Genetic algorithm
- Elitism: the best genomes are copied unchanged (gold cars), so the record never gets worse.
- Tournament selection (k = 3) picks the parents.
- Uniform crossover: each weight comes from one of the two parents.
- Gaussian mutation: each weight is perturbed with probability p by 𝒩(0, σ²).
Things to try
- Let it solve the track, then press New track: some champions generalise, others only memorised one circuit.
Turn on New track every generation to breed drivers that generalise.
- Lower the tyre grip: the drivers now have to learn to brake.
- Try 2 hidden neurons, or a very high mutation strength, and compare how fast the population learns.
- Race the champion with the arrow keys or WASD.