Skip to content

Core Concepts

Quantum Forge gives game objects real quantum state. The core usage pattern is:

  1. Attach quantum properties to things, giving them quantum state
  2. Apply operations to change that state. Gates transform without collapsing
  3. Use predicated operations to create entanglement. Controlled gates link properties together
  4. Measure to collapse quantum state and make it classical (the dramatic game moment)

Everything else (pooling, registries, recording) is tooling around this loop.

Programmer's Mental Model

If you know how to work with collections, you already have the intuition for quantum state.

Superposition is a weighted collection of values. Each entry is a basis state (a value, or a combination of values when multiple properties are involved), paired with a weight. A qubit in equal superposition is just a collection with two entries: |0⟩ and |1⟩, each weighted equally.

Operations are collection algorithms. They can modify the values, the weights, or both, and they apply to every element in the collection. cycle is "increment each value mod d". shift is "decrement each value mod d" (the inverse). You're running a transform over the whole collection at once.

Predicated operations are the same thing with a filter condition on each entry's value. "If the mth bit is 0, flip the nth bit." The operation only fires for entries where the condition holds. This is how entanglement happens: a predicated operation correlates two properties because it changes some entries and not others based on value combinations.

The quantum part is what the weights actually are. They aren't probabilities. They're complex amplitudes. This matters when an operation produces two entries with the same value: their amplitudes add. If they're in phase, the weights reinforce (constructive interference). If they're out of phase, the weights cancel (destructive interference). This is where quantum behavior diverges from classical randomness.

The probability of getting a particular value on measurement is the squared magnitude of its amplitude. That's it. Build up amplitude on values you want, cancel amplitude on values you don't.

Quantum Properties

A quantum property is a handle to a single qudit: a d-dimensional quantum digit. For dimension 2 (the most common), a property can be in state |0⟩, state |1⟩, or any superposition of both.

You create properties through a QuantumPropertyManager:

typescript
import { QuantumPropertyManager, ensureLoaded } from "quantum-forge/quantum";

await ensureLoaded(); // load the WASM simulator

const manager = new QuantumPropertyManager({ dimension: 2 });
const prop = manager.acquireProperty(); // starts in |0⟩

Every acquired property starts in the definite state |0⟩. You assign it meaning by mapping it to a game object:

typescript
manager.setProperty("ball-1", prop);

// Later, retrieve it:
const p = manager.getProperty("ball-1"); // QFProperty handle

Dimension

The dimension parameter controls how many basis states each property has:

DimensionStatesUse Case
2 (qubit)|0⟩, |1⟩Binary: exists/doesn't, alive/dead, left/right
3 (qutrit)|0⟩|2⟩Three-way: rock/paper/scissors, left/center/right

The package ships two editions: the Qutrit edition (default) supports dimensions 2–3 with up to 12 qudits, while the Qubit edition supports dimension 2 only but allows up to 20 qubits. You choose your edition during npx quantum-forge init. Start with dimension 2 unless your design specifically needs three-valued states. Higher dimensions grow the state space exponentially. See Quantum Setup: Editions.

Operations (Gates)

Gates transform quantum state without collapsing it. All gates are called via getModule():

typescript
const m = manager.getModule();

// Put a property into superposition
m.cycle(prop);      // |0⟩ → |1⟩ (flip)
m.hadamard(prop);   // |1⟩ → (|0⟩ − |1⟩)/√2 (equal superposition)

// Rotate phase (invisible to measurement, but affects interactions)
m.clock(prop, 0.5); // apply π/2 phase to |1⟩ component

Key gates:

GateWhat it doesCommon use
cycle(prop)Cyclic permutation (|0⟩→|1⟩→|0⟩ for dim=2). Alias: x for qubitsInitialize to |1⟩
hadamard(prop)Create equal superpositionPut objects "into quantum"
clock(prop, fraction)Rotate phase. Alias: zBias future interactions
i_swap(p1, p2, fraction)Anti-correlated entanglementSplit one object into two
shift(prop)Inverse of cycle. Alias: xSame as cycle for dim=2
y(prop)Pauli Y (dim=2 only)Bloch sphere rotation

Gates accept an optional fraction parameter for partial application. hadamard(prop, 0.1) barely moves the state, while hadamard(prop, 1) is the full gate. See Gates for the complete reference.

Predicated Operations

This is the mechanism that makes quantum games work. Every gate accepts an optional predicates parameter that conditions the gate on the state of other properties:

typescript
const m = manager.getModule();

// Build predicates: "only fire if controlProp is in state |1⟩"
const preds = [controlProp.is(1)];

// This Hadamard only applies when the control is |1⟩
m.hadamard(targetProp, 1, preds);

When a gate is predicated on another property, the two properties become entangled. Their quantum states are now correlated. This is how entanglement works in Quantum Forge: it's not a special operation, it's what happens when operations depend on other properties' states.

Predicated Gates Create Entanglement

Before a predicated gate, the control and target are independent. After, they share a quantum state. Measuring one instantly determines the other.

The simplest example: a predicated shift on a qubit is the CNOT gate, the most fundamental entangling operation in quantum computing.

typescript
const control = manager.acquireProperty();
const target = manager.acquireProperty();
const m = manager.getModule();

// Put control in superposition
m.cycle(control);     // |0⟩ → |1⟩
m.hadamard(control);  // → (|0⟩ + |1⟩)/√2

// CNOT: flip target ONLY when control is |1⟩
m.shift(target, 1, [control.is(1)]);

// Now they're entangled:
// State is (|00⟩ + |11⟩)/√2
// Measuring control as 0 → target must be 0
// Measuring control as 1 → target must be 1
// Positively correlated

Any predicated gate creates entanglement. A predicated hadamard puts the target into conditional superposition, a predicated clock rotates phase conditionally, each producing different correlations.

iSwap: Anti-Correlated Entanglement

i_swap is a two-property gate that creates anti-correlated entanglement: exactly one of the pair will be measured as |1⟩. Use it when an object splits into two ghosts.

typescript
m.cycle(prop1);                   // |0⟩ → |1⟩ (exists)
// prop2 stays at |0⟩              (doesn't exist)
m.i_swap(prop1, prop2, 0.5);     // entangle

// Result: (|10⟩ + i|01⟩)/√2
// 50% chance prop1=1, prop2=0
// 50% chance prop1=0, prop2=1
// Anti-correlated: exactly one "exists"

Where CNOT creates positive correlation (both match), i_swap creates anti-correlation (exactly one). Which you use depends on the game mechanic you want. See Entanglement for the full pattern catalog.

i_swap also accepts predicates, enabling controlled entanglement:

typescript
// Only entangle if a third property is in state |1⟩
m.i_swap(prop1, prop2, 0.5, [gateProp.is(1)]);

Predicate Types

typescript
prop.is(value)      // true when property is in state |value⟩
prop.is_not(value)  // true when property is NOT in state |value⟩

Multiple predicates are AND'd. All must be satisfied for the gate to fire. See Gates: Conditional Gates for the full PredicateSpec type.

Measurement

Measurement collapses quantum state to a definite classical value. This is the moment quantum becomes real.

typescript
const [value] = m.measure_properties([prop]);
// value is now 0 or 1 (for dim=2)
// The property has collapsed. No more superposition
// Entangled partners collapse instantly too

Key behaviors:

  • The outcome is probabilistic, sampled from the quantum state's probability distribution
  • The state collapses permanently to the measured value
  • Entangled partners update instantly. Measuring one determines the other

After measurement, release the property back to the pool:

typescript
const [value] = m.measure_properties([prop]);
manager.deleteProperty("ball-1");         // remove ID mapping
manager.releaseProperty(prop, value);     // reset to |0⟩, return to pool

Pooling is important for staying within the qudit limit (12 in the Qutrit edition, 20 in the Qubit edition). See Performance for details. But the core concept is simple: measure, then release.

Forced Measurement

For replay/save-load, you can force a measurement to produce a specific outcome:

typescript
const [value] = m.forced_measure_properties([prop], [1]); // forces outcome to 1

This is used internally by QuantumRecorder. See Recording & Replay.

Reading Quantum State

You can inspect quantum state without collapsing it. These are read-only queries that don't change anything.

Probabilities

typescript
const results = m.probabilities([prop]);
// Returns: [{ probability: 0.5, qudit_values: [0] }, { probability: 0.5, qudit_values: [1] }]

Use this to:

  • Render ghost objects at their existence probability (opacity = probability)
  • Show probability meters in the UI
  • Make AI decisions based on quantum state

Reduced Density Matrix

For phase, coherence, and correlations between properties:

typescript
const rdm = m.reduced_density_matrix([prop1, prop2]);
// Returns: [{ row_values, col_values, value: { real, imag } }, ...]

The off-diagonal entries carry relative phase, invisible to probabilities() but critical for how properties interact. Games extract phase to drive visual effects:

typescript
// Extract relative phase between two entangled properties
for (const entry of rdm) {
  if (entry.row_values[0] === 1 && entry.row_values[1] === 0 &&
      entry.col_values[0] === 0 && entry.col_values[1] === 1) {
    const phase = Math.atan2(entry.value.imag, entry.value.real);
    // Map to dial rotation, color hue, force magnitude, etc.
  }
}

Measure Predicate

Check whether specific predicates are satisfied without fully collapsing to a basis state:

typescript
const preds = [prop1.is(1), prop2.is(0)];
const outcome = m.measure_predicate(preds);
// 1 = predicates satisfied, 0 = not satisfied

Putting It Together

Here's the complete pattern: a quantum registry for a game where objects can enter superposition and entangle:

typescript
import { QuantumPropertyManager, ensureLoaded } from "quantum-forge/quantum";

await ensureLoaded();

class QuantumRegistry extends QuantumPropertyManager {
  constructor(logger?: any) { super({ dimension: 2, logger }); }

  /** Give an object quantum state (equal superposition of exists/doesn't) */
  makeQuantum(id: string): void {
    const prop = this.acquireProperty();
    const m = this.getModule();
    m.cycle(prop);        // |0⟩ → |1⟩
    m.hadamard(prop);     // → 50/50 superposition
    this.setProperty(id, prop);
  }

  /** Entangle two quantum objects (anti-correlated existence) */
  entangle(id1: string, id2: string): void {
    const p1 = this.getProperty(id1);
    const p2 = this.getProperty(id2);
    if (!p1 || !p2) return;
    this.getModule().i_swap(p1, p2, 0.5);
  }

  /** Read existence probability without collapsing */
  getProbability(id: string): number {
    const prop = this.getProperty(id);
    if (!prop) return 1.0;
    const results = this.getModule().probabilities([prop]);
    for (const r of results) {
      if (r.qudit_values[0] === 1) return r.probability;
    }
    return 0;
  }

  /** Collapse. Returns 1 (exists) or 0 (gone) */
  measure(id: string): number {
    const prop = this.getProperty(id);
    if (!prop) return 1;
    const [value] = this.getModule().measure_properties([prop]);
    this.deleteProperty(id);
    this.releaseProperty(prop, value);
    return value;
  }
}

This registry handles the full loop: create properties, apply gates, read state, measure and collapse. Every production game follows this pattern. The specifics of which gates to apply and what measurement means vary, but the structure is the same.

What's Next

  • Gates: Full gate reference with predicates and fractional gates
  • Measurement: Collapse mechanics, batch measurement, measure predicate
  • Entanglement: Entanglement patterns (split, correlated pairs, overlap, predicate-triggered)
  • Phase & Interference: Phase rotation, interference, Grover oracle
  • Lifecycle & State Management: Destroying properties, state budget queries, isolated simulations
  • Error Handling: Typed JS errors, OOM guard, graceful degradation
  • Performance: Pooling, qudit limits, optimization strategies

Powered by Quantum Forge