Skip to content

Measurement

Measurement is the moment quantum becomes classical. A property in superposition collapses to a single definite value, and that collapse is the most dramatic thing your game can do.

Basic Measurement

typescript
const prop = this.getProperty("ball-1");
const [value] = this.getModule().measure_properties([prop]);
// value is 0 or 1 (for dim=2)
// The property is now in state |value⟩. No more superposition

Key behaviors:

  • The outcome is probabilistic, sampled from the quantum state's probability distribution
  • The state collapses permanently to the measured value
  • Entangled partners collapse instantly too

Measure and Pool

Always release properties after measurement to stay within qudit limits:

typescript
measureEntity(id: string): number {
  const prop = this.getProperty(id);
  if (!prop) return 1; // classical fallback

  const [value] = this.getModule().measure_properties([prop]);
  this.deleteProperty(id);           // remove ID mapping
  this.releaseProperty(prop, value); // reset to |0⟩, return to pool
  return value;
}

This pattern appears in every production game. The specifics vary (what the value means, what to do after), but the sequence (measure, delete, release) is universal.

Batch Measurement

Measure multiple properties at once:

typescript
const props = [this.getProperty("a")!, this.getProperty("b")!, this.getProperty("c")!];
const [va, vb, vc] = this.getModule().measure_properties(props);

Batch measurement is slightly more efficient than measuring one at a time, and the outcomes are correlated correctly (entangled properties respect their correlations within the batch).

Reading Probabilities (No Collapse)

Query the probability distribution without disturbing the quantum state:

typescript
const prop = this.getProperty("ball-1");
const results = this.getModule().probabilities([prop]);
// results: [{ probability: 0.7, qudit_values: [1] }, { probability: 0.3, qudit_values: [0] }]

This is a read-only operation. It does not collapse the state. Use this for:

  • Rendering ghost objects at their existence probability
  • Showing probability meters in the UI
  • AI decision-making based on quantum state

TIP

probabilities() is a read-only query. It does not change state or appear in recording logs.

Reduced Density Matrix

For advanced analysis (phase, coherence, and correlations between properties):

typescript
const rdm = this.getModule().reduced_density_matrix([prop1, prop2]);
// rdm: array of { row_values: number[], col_values: number[], value: { real: number, imag: number } }

The off-diagonal entries carry relative phase information. From Quantum Pong:

typescript
getRelativePhase(refId: string, targetId: string): number {
  const propRef = this.getProperty(refId);
  const propTarget = this.getProperty(targetId);
  if (!propRef || !propTarget) return 0;

  const rdm = this.getModule().reduced_density_matrix([propRef, propTarget]);

  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 { real, imag } = entry.value;
      if (Math.abs(real) < 1e-10 && Math.abs(imag) < 1e-10) return 0;
      return Math.atan2(imag, real);
    }
  }
  return 0;
}

Game use cases:

  • Quantum Pong: Relative phase drives the phase dial display and biases entanglement interactions
  • Ponq: Off-diagonal magnitude (coherence) drives ball steering forces
  • Quantris: Coherence info drives piece glow/pulse visualization

Measure Predicate

Projective measurement that checks whether specific predicates are satisfied:

typescript
import type { PredicateSpec } from "quantum-forge/quantum";

const predicates: PredicateSpec[] = [
  { property: prop1, value: 1, isEqual: true },
  { property: prop2, value: 0, isEqual: true },
];

const wasmPreds = predicates.map(s =>
  s.isEqual ? s.property.is(s.value) : s.property.is_not(s.value)
);
const outcome = this.getModule().measure_predicate(wasmPreds);
// outcome: 0 or 1
// 1 = predicates were satisfied (state projected onto matching subspace)
// 0 = predicates were NOT satisfied

Unlike measureProperties, this doesn't fully collapse to a basis state. It performs a projective measurement onto the subspace defined by the predicates.

Forced Measurement (Replay)

Force a measurement to produce a specific outcome. Used internally by QuantumRecorder.replayLog() to reproduce exact quantum states during save/load:

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

WARNING

Forced measurement is for replay/testing only. Using it during normal gameplay breaks the quantum contract. Outcomes should be probabilistic.

Game Example: Quantum Pong Scoring

When a ball exits the play field, it's measured to determine if it scores:

typescript
const exists = registry.measureExistence(ballId);
if (exists === 1) {
  // Ball existed → scores a point
  state.score[scoringSide]++;
  showScoreBurst(ball.position);
} else {
  // Ball was a ghost → no score
  showGhostBurst(ball.position);
}
// Entangled partner (if any) collapses to the opposite value

Other measurement patterns include batch measurement for line-clearing (measure all pieces in a row), basis measurement (rotate before measuring for different observables), and battle resolution (measure overlapping hexes to determine ownership).

Powered by Quantum Forge