This repository solves the well-known CodinGame Mars Lander problem using a genetic algorithm implemented in C++20 with a live Qt/QML GUI and visualization of the determined trajectories for each iteration of the algorithm. The algorithm searches for a control sequence (rotation and thrust per time step) that safely lands the spaceship in the landing zone.
The genetic algorithm can be configured via the config/config.yaml.
The config is tuned for a fast convergence and directly shapes the newly generated population
for every iteration:
- Elitism (15%) preserves the best chromosomes and copies them unaltered to the new population.
- Perturbation (5%) modifies randomly picked elites. It picks the start, middle or end segment of the elite chromosome and mutates each gene with a 33% chance, applying small random deltas to rotation and power. To every second perturbed chromosome a landing sequence is added to enforce a safe landing quicker.
- Random Chromosomes (2.5%) are newly added via a random walk.
- New Immigrants (15%) are randomly selected elites that bring new diversity by adding climbing sequences of varying length to create chromosomes that can fly farther and higher if needed. A landing sequence is added to every second chromosome.
- Crossover (62.5%) drives the convergence of the genetic algorithm by combining two chromosomes (parents) via BLX-α crossover to create offspring. The parents to be combined are selected based on tournament (50%) and roulette wheel (50%) selection. To 50% of the offspring a landing sequence is added. The offspring are mutated with an adaptive rate: 1% per gene as the base, scaled up for weak parents and towards the end of the trajectory.
-
Roulette wheel selection: The probability of selecting a chromosome is directly proportional to its absolute fitness score. That means fitter individuals get selected with a higher probability, which drives convergence aggressively toward the current global best.
-
Tournament selection: A small group of chromosomes is picked at random, and the one with the highest fitness wins the right to reproduce. Because it relies on relative rank rather than absolute fitness, it prevents very high scoring individuals from completely dominating the pool early on, maintaining steady selection pressure and preserving genetic diversity.
Both genes of a command (rotation and power) are blended independently. For each timestep the
two parent values span an interval [min, max] with d = max - min. BLX-α samples the child
gene uniformly from the widened interval [min - α·d, max + α·d], clamped to the valid gene
ranges (±90° rotation, 0..4 power). With α = 0.2 (blx_alpha in the config) a child can land
slightly outside the span of its parents. That is the reason to prefer BLX-α over simply
averaging the parents: averaging shrinks the variance of the population with every generation
and causes premature convergence, while the widened interval keeps enough spread to explore
without breaking up what both parents agree on.
The command sequences are simulated to obtain trajectories that respect the physical limits of
the lander: the thrust can only change by ±1 and the rotation by ±15° per time step, with Mars
gravity (3.711 m/s²) pulling the craft down. Each trajectory is then rated by a score function
that assesses how close the spaceship comes to landing safely: 0–100 for crashing somewhere
(based on the distance to the landing zone), 100–200 for reaching the zone but breaking a
landing rule, and 200–300 for a safe landing, ranked by the remaining fuel.
The details can be found in src/score_function.cpp.
This project uses Conan 2 for dependency management and CMake for configuration and builds.
The quickest way to build and run the project without installing GCC, Qt or
Conan on your host is the containerised setup in docker/.
It provides an Ubuntu 24.04 + GCC 13 environment with Conan 2 and X11 GUI
forwarding:
cd docker
./build.shSee docker/README.md for details.
The project can also be built directly on the host with GCC 13, Conan 2 and CMake installed. The Conan profiles bundled for the container work outside of it as well:
conan install . -pr:a docker/conan/profiles/release --build=missing
cmake --preset conan-release
cmake --build --preset conan-releaseStart the application:
./build/Release/appRun the unit tests (GoogleTest):
ctest --test-dir build/Release
# or directly:
./build/Release/unit_testsThe application loads its runtime settings from config/config.yaml.
If that file is missing, the built-in defaults are used.
Released under the MIT License. See LICENSE.

