Quantum Pong
The canonical starter example: a Pong game where balls enter quantum superposition when they pass through a quantum zone.
Overview
When a ball enters the quantum zone (center of the field), it splits into two entangled balls. Both exist as quantum ghosts (semi-transparent) until one exits the field and is measured. Measurement collapses both balls: one scores, the other vanishes.
Players can bias which ball survives by applying phase rotations via a paddle-mounted phase dial.
Quantum Mechanics Used
| Mechanism | Gate | Game Effect |
|---|---|---|
| Entangle-split | cycle + i_swap(0.5) | Ball splits into correlated pair |
| Quantum-split | i_swap(0.5) on existing | Already-quantum ball splits again |
| Phase rotation | clock(fraction) | Paddle dial biases survival probability |
| Existence probability | probabilities() | Ghost opacity reflects quantum state |
| Relative phase | reduced_density_matrix() | Phase dial display |
| Measurement | measure_properties() | Scoring, collapses to exists/ghost |
| Pooling | releaseProperty() | Reset measured balls for reuse |
Registry
QuantumRegistry extends QuantumPropertyManager with five operations:
class QuantumRegistry extends QuantumPropertyManager {
constructor(logger?: LoggerInterface) {
super({ dimension: 2, logger });
}
entangleSplit(originalId: string, newId: string): void {
const prop1 = this.acquireProperty();
const prop2 = this.acquireProperty();
const m = this.getModule();
m.cycle(prop1); // |1⟩ (exists)
m.i_swap(prop1, prop2, 0.5); // entangle
this.setProperty(originalId, prop1);
this.setProperty(newId, prop2);
}
quantumSplit(originalId: string, newId: string): boolean {
const prop1 = this.getProperty(originalId);
if (!prop1) return false;
const prop2 = this.acquireProperty();
try {
this.getModule().i_swap(prop1, prop2, 0.5);
} catch {
this.releaseProperty(prop2, 0);
return false;
}
this.setProperty(newId, prop2);
return true;
}
applyPhase(id: string, fraction: number): void {
const prop = this.getProperty(id);
if (!prop) return;
this.getModule().clock(prop, fraction);
}
getExistenceProbability(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;
}
measureExistence(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;
}
}Key Design Patterns
Entangle-Split as Core Mechanic
The quantum zone is a spatial trigger. When a classical ball crosses the threshold:
- Two properties are acquired (from pool if possible)
- One is cycled to
|1⟩, the other stays at|0⟩ i_swap(0.5)entangles them into(|10⟩ + i|01⟩)/√2- Both balls render at ~50% opacity
Phase as Player Skill
The phase dial on each paddle gives players a way to influence quantum outcomes. Applying clock(fraction) rotates the relative phase between entangled balls. When the next iSwap occurs, the phase bias redistributes probability, so a skilled player can increase their scoring chance.
Measurement as Drama
The moment of measurement is the highest-drama event in the game. The player doesn't know which ball will score until it exits the field and gets measured. Ghost bursts (for |0⟩) and score bursts (for |1⟩) provide visual feedback.
Pooling for Sustainability
Every measured ball returns its property to the pool. This means the game can run indefinitely without hitting the qudit limit. There are always recycled properties available for the next entangle-split.
Source
framework/examples/quantum-pong/. Shipped with the framework, available as a template via npx quantum-forge init my-game --template quantum-pong.