Skip to content

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:

typescript
this.iSwap(prop1, prop2, fraction);

At fraction=0.5 (the most common value), starting from |10⟩:

|10⟩  →  (|10⟩ + i|01⟩) / √2

This 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.

typescript
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).

typescript
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.

typescript
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.

typescript
// 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⟩:

typescript
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 iSwap between 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 quantumSplit example above)
typescript
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:

  1. That property collapses to a definite value
  2. The entangled partner's probabilities update instantly
  3. 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:

GameVisualization
Quantum PongGhost balls at reduced opacity based on existence probability
QuantrisGlowing connections between entangled pieces, pulse intensity from coherence
Hex DiffusionProbability gradients across hex grid, color blending at boundaries
Bloch InvadersMatching glow color on entangled twin invaders
PonqCoherence 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.

Powered by Quantum Forge