ECP-Life: the short version
For someone who already knows particle life. Three changes, in the order they were made, and why each one forced the next.
In one paragraph. Take particle life. Replace the handful of species with a continuous colour, so the attraction matrix becomes a smooth landscape instead of a grid of numbers. Replace the piecewise-linear force with a bond that has a real rest distance, so pairs settle instead of orbiting. Then notice that half of every particle-life matrix is a "chase" that creates energy from nothing, and instead of throwing that energy away with friction, make each particle pay for it by shifting its colour. Colour becomes a battery. Nothing is created, nothing is lost, and the interesting behaviour is what the system does while the battery drains and recharges.
0. Where we start
Classic particle life: $N$ species, an $N \times N$ matrix of attraction strengths, and a force between two particles that is "repel hard when too close, then attract or repel by the matrix entry, fading to zero at a cutoff". Plus friction, always. You already know what it does: blobs, cells, chasers, things that look alive for a while.
the matrix: 5 species
the force vs distance: a tent
The one-line version of the force that this whole project starts from is
$$ \mathbf F_{ij} = f(\text{colour}_i, \text{colour}_j)\; g(r)\; \hat{\mathbf u} $$a colour-dependent strength, times a distance fall-off, along the line between the two. Every change below is a change to one of those two factors, or to what happens to the energy they produce.
1. Continuous hue instead of species
The change. Each particle carries a hue, an angle on the colour wheel from $0$ to $2\pi$, instead of a species index. The attraction matrix becomes a smooth function of two angles, $f(h_i, h_j)$, drawn as tileable Perlin noise over the hue torus. Two particles with nearly the same hue feel nearly the same forces. A particle can be "a bit orange, leaning red".
5 × 5 lookup table
continuous: $f(h_i, h_j)$ from noise
What you get for free. The matrix is no longer a handful of numbers you have to design. Noise gives you a landscape of attractions and repulsions with all the structure of a hand-made matrix (cycles, cliques, predators) at every scale, and one seed changes all of it. The old matrix is the special case where the landscape is piecewise constant.
What it lets you do later. This is the change that makes everything after it possible. Once hue is a continuous number, it can move. A species index cannot drift; an angle can. Change 3 depends on that.
The split that matters. Any function of two colours can be split into a symmetric half and an antisymmetric half:
$$ f(h_i,h_j) = \underbrace{S(h_i,h_j)}_{\text{same both ways}} + \underbrace{\Lambda(h_i,h_j)}_{\text{flips sign when swapped}} $$f, the matrix
= S, mirror across the diagonal
+ Λ, anti-mirror
$S$ is "how much do these two like each other": both feel it equally, Newton's third law holds, it is an ordinary force. $\Lambda$ is "who chases whom": if orange pushes blue away and blue is pulled toward orange, that is the chase, and it is the same force vector on both particles. The chasers and predators you see in particle life all live in $\Lambda$.
2. A well instead of a ramp
The change. Particle life's radial force is a tent: a hard repulsive core, a linear rise to a peak, a linear fall back to zero at the cutoff. Nothing in it says "this is the right distance to sit at", so bonded particles never settle. They orbit, jitter, and lean on friction to calm down.
ECP-Life replaces the tent with a Gaussian well times a taper:
$$ V(r) = -\,e^{-(r-\rho)^2/2\sigma^2}\,\big(1-(r/R)^2\big)^2 $$potential energy of a pair
force on the pair (slope of the left)
The bond force is $S$ times the slope of this. Inside the rest distance $\rho$ it pushes apart, outside it pulls together, and it dies smoothly (zero value and zero slope) at the cutoff $R$. Two particles that like each other have an actual place to be: $\rho$ apart. A small radial friction on the pair (not on the world) drains the "breathing" vibration so they click into place instead of ringing.
Why it matters. Now a bond is a thing. Two particles at rest distance with a mutual $S > 0$ is a stable object with a definable binding energy, which is what the next change needs: it is going to keep a ledger, and a ledger needs objects whose energy you can write down. It also gives you crystal-like clumps with a lattice constant instead of amorphous blobs, and that lattice constant can depend on colour.
The chase follows the well. The chase force also needs a radial envelope, and the choice turns out to matter: it uses the same shape as the well, so a chase can never act at a distance where the bond cannot hold. With a longer-reaching chase, an incoming particle spends all its colour (see below) before it is close enough to be caught, and just flies off faster. With the chase confined to the well, the spending happens where the bond is, and capture works.
3. Conserving mechanics: colour as a battery
This is the big one, and it only works because of the first two.
The problem. The symmetric half $S$ is a potential force and conserves energy by itself. The chase half $\Lambda$ does not and cannot: a force that points the same way on both particles has no potential that produces it. A chase pair accelerates as a unit, forever, gaining kinetic energy from nowhere. Classic particle life hides this with global friction, which throws the energy away as fast as it arrives. That works, but it means the whole system is a pump into a drain, and everything you see is the steady state of that pump.
The idea. Keep the books instead. Give every pair a third energy term that is charged by colour mismatch: zero when the two hues agree, largest exactly where the chase is strongest. The simplest is $\Lambda^2$ times a distance envelope:
$$ U_{ij} = \underbrace{k(r_0-r)^2}_{\text{soft core}} \;+\; \underbrace{S(h_i,h_j)\,V(r)}_{\text{the bond}} \;+\; \underbrace{\lambda\,\Lambda(h_i,h_j)^2\,w(r)}_{\text{the hue battery}} $$The rule. Every step, each particle measures the power the chase is putting into it, $P_i = \mathbf F^{\text{chase}}_i \cdot \mathbf v_i$, and the amount its own hue could change the total energy, $W_i = \partial E / \partial h_i$. Then it moves its hue at exactly the rate that pays the bill:
$$ \dot h_i = -\frac{P_i}{W_i} $$That is the whole mechanic. It is not a tunable "colour drift speed"; it is computed from forces and velocities each frame, and any other value breaks conservation. The only real knobs are how strong the chase is ($\kappa$) and how big the battery is ($\lambda$).
What it does. Three regimes, and a particle cycles through them as it orbits:
| Chase vs. velocity | Energy flow | Hue |
|---|---|---|
| Chase pushes along the motion ($P > 0$) | battery drains into motion | hues converge, the pair becomes more alike |
| Chase is sideways ($P = 0$) | nothing flows | hue frozen |
| Chase pushes against the motion ($P < 0$) | motion is stored back in the battery | hues diverge, the pair becomes more different |
Watch it. Two particles start at rest, bonded at the rest distance of the well from section 2, a quarter turn apart in hue: the point where the chase is strongest. Orange chases teal, the pair accelerates as a unit, and every bit of speed it gains is paid for by the two hues sliding toward each other. When they meet the chase is gone, the battery is empty, and the pair coasts at whatever speed it bought. Blue arrows are the reciprocal force, red arrows the chase, particle colour is hue. The camera follows the pair; the grid shows how far it has travelled.
So a predator that catches prey burns colour doing it, and drifts toward its prey's colour as it goes. A pair braked by the crowd around it charges up and grows more different. A cyclic chase (red chases green chases blue chases red) unwinds as its battery drains, unless collisions with unlike hues feed mismatch back in. Clumps grow by burning the mismatch of what they capture. A hot clump that gets braked charges and loosens.
The ledger. The sim keeps total energy, plus heat (from the bond friction, when routed there), plus a small "unpaid" column for the rare step where a particle's hue gradient is so close to zero that it cannot pay. Their sum is constant to a couple of percent over long runs, and the residual shrinks with the time step, which is the test that the mechanics are really conserving and not just approximately damped.
Why the order matters
- Hue had to be continuous before it could be spent. A species index cannot move a little.
- Bonds had to be real before energy could be accounted per pair. A ramp has no rest state and no binding energy to speak of.
- Only then does "pay for the chase with colour" make sense: there is a smooth quantity to change and a well-defined energy for it to change.
The payoff over ordinary particle life is that nothing is being pumped and drained. Every chase you see is spending something, every capture costs something, and colour is the visible record of the transaction. Structure that persists is structure that has found a way to recharge.
Further reading: the full derivation, the open questions, and a review of the derivation against the code.