Entanglement
Entanglement is the mechanic that makes quantum games fundamentally different from classical ones. When two properties are entangled, they share a quantum state — measuring one instantly determines the other. No classical system can do this.
iSwap: The Entanglement Primitive
All entanglement in Quantum Forge goes through iSwap:
this.iSwap(prop1, prop2, fraction);At fraction=0.5 (the most common value), starting from |10⟩:
|10⟩ → (|10⟩ + i|01⟩) / √2This means:
- 50% chance prop1 is
|1⟩and prop2 is|0⟩ - 50% chance prop1 is
|0⟩and prop2 is|1⟩ - These outcomes are anti-correlated — exactly one of the pair is
|1⟩ - Measuring either one instantly collapses the other
Entanglement Patterns
Five production games use entanglement in different ways. Here are the patterns:
Pattern 1: Entangle-Split
Used by: Quantum Pong, Ponq
A classical object enters a quantum zone and splits into an entangled pair. One property starts at |1⟩ (exists), the other at |0⟩ (doesn't exist), then iSwap(0.5) creates correlated superposition.
entangleSplit(originalId: string, newId: string): void {
const prop1 = this.acquireProperty();
const prop2 = this.acquireProperty();
this.cycle(prop1); // |0⟩ → |1⟩ (exists)
// prop2 stays at |0⟩ (doesn't exist)
this.iSwap(prop1, prop2, 0.5); // entangle
this.setProperty(originalId, prop1);
this.setProperty(newId, prop2);
}After entangle-split:
- Both objects exist with ~50% probability
- Measuring one to "exists" collapses the other to "doesn't exist"
- The game shows both objects as semi-transparent ghosts
Pattern 2: Quantum-Split
Used by: Quantum Pong, Ponq
Split an already quantum object. The new property starts at |0⟩ and entangles with the existing one. Pooled properties are preferred because they're already in the shared state (no tensor product growth).
quantumSplit(originalId: string, newId: string): boolean {
const prop1 = this.getProperty(originalId);
if (!prop1) return false;
const prop2 = this.acquireProperty(); // prefers pooled
this.iSwap(prop1, prop2, 0.5);
this.setProperty(newId, prop2);
return true;
}Pattern 3: Correlated Pairs
Used by: Bloch Invaders
Create a pair of objects whose quantum states are inherently linked. The "twins" boss in Bloch Invaders consists of two entangled invaders — damage to one affects the other.
createTwins(id1: string, id2: string): void {
const prop1 = this.acquireProperty();
const prop2 = this.acquireProperty();
this.cycle(prop1); // |1⟩
this.hadamard(prop1); // superposition
this.iSwap(prop1, prop2, 0.5); // entangle
this.setProperty(id1, prop1);
this.setProperty(id2, prop2);
}Pattern 4: Overlap Entanglement
Used by: Hex Diffusion, Quantris
Objects that spatially overlap become entangled. In Hex Diffusion, adjacent hexes entangle at shared boundaries. In Quantris, overlapping pieces entangle into groups.
// When two hex cells share a boundary
entangleNeighbors(hexA: string, hexB: string): void {
const propA = this.getProperty(hexA);
const propB = this.getProperty(hexB);
if (!propA || !propB) return;
this.iSwap(propA, propB, 0.5);
}Pattern 5: Predicate-Triggered Entanglement
Used by: Quantris
Entanglement or gates conditioned on other properties' states. A gate on piece A fires only when piece B is in state |1⟩:
conditionalEntangle(targetId: string, controlId: string): void {
const target = this.getProperty(targetId);
const control = this.getProperty(controlId);
if (!target || !control) return;
const predicates: PredicateSpec[] = [
{ property: control, value: 1, isEqual: true }
];
this.hadamard(target, 1, predicates); // only fires if control is |1⟩
}Tensor Product Growth
When iSwap connects properties from different shared states, the WASM module computes a tensor product to merge them into one combined state. This is the most expensive operation in quantum simulation.
What triggers it:
iSwap(propA, propB, ...)where propA and propB are in different shared states- This typically happens when both properties were freshly acquired (not from pool)
What prevents it:
- Pooled properties are already in the shared state, so
iSwapbetween a pooled property and an existing one is cheap - Measuring and releasing properties via
releaseProperty()keeps the pool full
What happens when you run out:
- The qudit limit depends on the WASM build variant (e.g., 8 qudits for medium)
- Exceeding the limit throws an error
- Your game should handle this gracefully (see the
quantumSplitexample above)
try {
this.iSwap(prop1, prop2, 0.5);
} catch {
this.logger?.warn?.("Qudit limit reached — cannot entangle");
this.releaseProperty(prop2, 0); // return unused property
return false;
}Entanglement and Measurement
When you measure one property of an entangled pair:
- That property collapses to a definite value
- The entangled partner's probabilities update instantly
- For maximally entangled pairs (
iSwap(0.5)from|10⟩), measuring one to|1⟩forces the other to|0⟩
This is what makes quantum scoring work in Quantum Pong: measuring one ball's existence immediately determines the other ball's existence.
Visualizing Entanglement
Production games visualize entanglement in different ways:
| Game | Visualization |
|---|---|
| Quantum Pong | Ghost balls at reduced opacity based on existence probability |
| Quantris | Glowing connections between entangled pieces, pulse intensity from coherence |
| Hex Diffusion | Probability gradients across hex grid, color blending at boundaries |
| Bloch Invaders | Matching glow color on entangled twin invaders |
| Ponq | Coherence meter driving ball steering force magnitude |
The common pattern: read probability via this.getModule().probabilities([prop]) and map it to visual opacity, size, color intensity, or glow.