Loading
Generation 1 will be a disaster. I know this before writing a single line of code.
This is a design log before implementation.
I'm building a 2D physics-based creature simulator where bodies evolve gaits through a genetic algorithm — no hand-coded movement, no reinforcement learning, just selection pressure and time. Before writing the physics engine, the genome encoding, or the mutation operators, I want to think through what I expect to find. That's this post.
Generation 1 will look like a disaster.
Fifty creatures. I expect most to collapse immediately — tipping forward or sideways within the first half-second of simulation, joints locking into positions that no recovery heuristic could salvage. One will probably vibrate in place, joints oscillating at high frequency, going nowhere with enormous apparent effort. One might launch itself backward at surprising speed and then stop. One will likely freeze completely — no movement at all, no distance traveled, but also no falling penalty, which turns out to be not stupid but rational, in a narrow and depressing way.
None of them will walk. None will come close to anything recognizable as locomotion.
This is just evolution, at the very beginning, before it has had time to find anything at all. And I find that the most interesting part to think through before touching the code.
A strong score can still reward a bad behavior. The objective decides what evolution learns to exploit.
The obvious question: why not write a walking algorithm? You know what walking looks like. You understand the mechanics. Write the gait, tune the parameters, done.
The answer is that programming walking and evolving walking are solving different problems, and only the first is yours. When you program walking, you define the method and the system executes it. When you evolve walking, you define success and the algorithm finds the method. These are not interchangeable approaches. The method you write will be brittle — it will work for the specific body, the specific terrain, the specific conditions you designed it for, and fail outside them. An evolved gait should be more robust because the selection pressure acts on robustness; creatures that stumble on slight perturbations won't produce offspring.
Key insight: A fitness function is a definition of winning, not a solution. The algorithm provides the solution. Your job is only to know what you're looking for.
This seems obvious until you're staring at a creature that has found a way to score well on your fitness function while doing something you never intended. Then you understand that defining success is harder than it looked, and that a blind optimizer will exploit any ambiguity in that definition with ruthless efficiency.
The setup is deliberate in its simplicity:
HEAD ○
|
BODY ▬▬▬
/ \
/ \
LEG LEGWhat evolves is entirely behavioral: six floating-point numbers controlling how the joints move. Each joint has three parameters — frequency (how fast it oscillates), amplitude (how far it swings), and phase offset (where in its cycle it starts relative to the other joint). Two joints, three parameters each — six numbers total. The entire genome is six floating-point values in [0, 1].
The fitness function I'm planning:
def fitness(creature, duration=10.0):
start_x = creature.body.position.x
simulate(creature, duration)
end_x = creature.body.position.x
distance = end_x - start_x
falling_penalty = -50 if creature.is_fallen() else 0
return max(0, distance + falling_penalty)Distance traveled minus a falling penalty. Nothing else. No reward for looking like walking. No reward for energy efficiency. No reward for smoothness or human-likeness. Just: did you move forward, and are you still upright at the end?
The simplicity is intentional. Complex fitness functions introduce implicit constraints that can trap evolution in local optima shaped by those constraints rather than the actual goal. The simpler the fitness function, the more freedom the algorithm has to find solutions I wouldn't have thought to look for.
Before running anything, I can already predict three dominant failure strategies. These aren't bugs — they're rational responses to the fitness function I'm defining.
The Faller — I expect to see this early. It will discover that leaning aggressively forward moves the body's center of mass forward before it falls, at which point the legs catch it. Then repeat. Its gait will look like a controlled stumble: lean, catch, lean, catch. The fitness score will be decent. By every metric the function measures, it will be succeeding.
It won't be walking. But the fitness function won't know what walking is, and neither will the algorithm. The lesson is immediate and uncomfortable: the fitness function doesn't care about method. If stumbling forward achieves the outcome, stumbling forward is what you get. If you care about how a creature moves, not just how far it moves, your fitness function must measure it. Implicit constraints are not constraints.
The Shaker — Maximum joint frequency, minimal amplitude, zero net displacement. It will look like it's trying very hard. It will be going nowhere. But here's the thing: high frequency, low amplitude movement is energetically cheap in this simulation, and the fitness function has no energy term. The Shaker will find a strategy that expends minimum effort while producing enough structural vibration to avoid any minimum-movement penalty I add. It will be gaming the metric — without malice, without understanding, with pure effectiveness.
Local optima look like solutions from inside. The Shaker's fitness will be stable across generations. It won't improve, but it won't be outcompeted either, because its niche — low effort, low reward, high survival — is consistent. Evolution doesn't require progress. It requires survival, and survival is a much easier bar to clear than excellence.
The Freezer — Zero movement. Zero distance. But also zero falling penalty, because you cannot fall if you don't move. The frozen creature will correctly identify that attempting locomotion in early generations is more likely to produce a fall than a gain. Staying still is risk-optimal given the current population's skill level.
This will persist until I add a minimum-movement requirement. Only then should evolution start exploring locomotion seriously. This is the deepest of the three: exploration must be forced. A blind optimizer will find the locally safest strategy, not the globally best one. Curiosity bonuses, diversity pressure, and minimum-exploration constraints are not cheating — they're necessary to make the fitness landscape navigable rather than a trap.
If the failure modes are handled correctly, I think something genuinely surprising might appear within 50–100 generations.
My guess is that the solution won't be the symmetric bipedal stride I'd naively expect. I anticipate the algorithm will find asymmetry before symmetry — one joint running at high frequency with a short arc, the other at low frequency with a wide arc. The asymmetry could create a slight rotational torque that, combined with forward momentum, produces net displacement per cycle that exceeds anything a symmetric strategy achieves.
It would be counterintuitive. It would look wrong. It might work.
The algorithm has no aesthetic bias toward symmetry. I do, because I've watched humans and animals walk. That bias is a liability here, not an asset. The search will cover parameter space I'd exclude on intuition, and that's where the solution probably lives.
This connects to something I keep returning to in building Exira-X: the relationship between competence and comprehension. They come apart in ways that matter.
A system can be very good at something without understanding anything about it. Evolution doesn't understand adaptation — it is adaptation, instantiated in chemistry and time. A language model doesn't understand reasoning — it produces outputs that score well on a distribution of text that happens to contain human reasoning. A market doesn't understand efficiency — it finds prices that clear supply and demand without any participant needing to model the whole system.
Optimization without understanding is the dominant mode of intelligence in the universe. The kind of intelligence that requires explicit understanding — the kind humans do — is recent and possibly unusual.
What I expect this project to change for me is not a belief about robotics. It's a belief about designing systems. If you can define what winning looks like, you may not need to define how to win. That principle runs through everything I'm building here.
The simulation will live at /projects/creature-evolution as it develops. I don't know what generation 100 looks like. That's the point.