# Quantum Forge documentation > Full documentation for building games with real quantum mechanics. Quantum Forge is a quantum simulation SDK for game developers, available for TypeScript/Web (npm) and Unity (UPM). This site documents the complete API, quantum mechanics concepts, framework tools, and showcase games. ## Getting started ### TypeScript/Web Install the core package. It is the whole SDK (WASM simulator, quantum() handles, Vite plugin) and has no runtime dependencies: ```bash npm install quantum-forge ``` Check the install with Quantum Pong, which ships inside the core package and needs nothing else (core 3.1.0 or newer). Non-interactive; `npm test` plays it headless against the WASM: ```bash npx -y quantum-forge example my-pong cd my-pong && npm test ``` Optional: `quantum-forge-engine` bundles the core with web-game extras (Engine, PixiJS rendering, input, audio, collision, particles) and a scaffolder. Use it only if the project wants those: ```bash npx -y quantum-forge-engine init my-game \ --template starter --platforms web --edition qutrit --no-claude-skill ``` Engine flags: `--template starter|quantum-pong`, `--edition qutrit|qubit`, `--platforms web[,desktop,ios,android]`, `--claude-skill` / `--no-claude-skill`. Editions (pick with `useQuantumForgeBuild("qubit")` before `ensureLoaded()`; qutrit is the default): | Edition | Dimensions | Max Qudits | Trade-off | |---------|-----------|------------|-----------| | **Qutrit** (default) | 2 to 3 | 12 | Supports qutrits (3-state) but fewer total qudits | | **Qubit** | 2 only | 20 | More quantum objects, but locked to binary states | Configure Vite: ```typescript import { quantumForgeVitePlugin } from "quantum-forge/vite-plugin"; export default defineConfig({ plugins: [quantumForgeVitePlugin()], }); ``` Note: Packages are ESM-only. Use `vite.config.mjs` or add `"type": "module"` to `package.json`. Load the WASM module once, before the first `quantum()` call: ```typescript import { ensureLoaded, quantum } from "quantum-forge/quantum"; await ensureLoaded(); const coin = quantum([false, true]).superpose(); ``` This documents `quantum-forge` 3.0 and `quantum-forge-engine` 2.0 (engine 2.0 requires core ^3.0.0). 2.x code (`QuantumPropertyManager`, `getModule()`, snake_case gate calls) still runs on 3.x but is deprecated and goes in 4.0. Migration guide: https://docs.quantum.dev/quantum/migrating-to-3 For the Qubit edition, call `useQuantumForgeBuild("qubit")` before `ensureLoaded()`: ```typescript import { useQuantumForgeBuild, ensureLoaded } from "quantum-forge/quantum"; useQuantumForgeBuild("qubit"); await ensureLoaded(); ``` ### Unity Install via Package Manager → Add package from git URL: ``` https://github.com/quantum-native/quantum-forge-unity.git ``` ## Quantum mechanics for games ### Core concepts - **Quantum properties**: `quantum(values)` returns a `Quantum` handle for one qudit (quantum digit). Declare it by the values it can take: `quantum([false, true])` is a qubit, `quantum(["red", "green", "blue"])` a qutrit, `quantum(3)` the numeric form with values 0, 1, 2. It starts at the first value. At least two values; at most 3 in the Qutrit Edition, 2 in the Qubit Edition. `quantum()` is the only way to make one; the constructor is private. - **Superposition**: A property holds several values at once until measured. `superpose()` (the same gate as `hadamard()`) spreads it evenly. - **Measurement**: `prop.measure()` collapses the property and returns the declared value (`true`/`false`, `"red"`, ...), not an index. `measure(a, b)` measures several at once. Read without collapse with `prop.probability(value)` and `prop.probabilities()`. A measured handle is still usable. - **Entanglement**: There is no `entangle()`. Entanglement is what an interaction leaves behind: a two-property gate like `a.iSwap(b, 0.5)`, or a gate whose predicate reads another property, like `b.flip({ when: [a.is(true)] })`. Measuring one entangled property settles the other. - **Interference**: Phase changes no probability on its own; it shows at the next gate that mixes values. Turn it with `phase()` (the same gate as `clock()`) or the free function `phaseRotate(angle, { when })`. - **Lifecycle**: `prop.dispose()` ends a property's life. It measures (collapsing entangled partners) and frees the qudit. Any later call on the handle throws. `using prop = quantum(...)` disposes at scope exit (TypeScript 5.2+, `"ESNext.Disposable"` in tsconfig `lib`). The engine's `EntityManager` disposes handles on entities it removes. ### Gates reference Gates are camelCase methods on the handle and return it, so they chain. Each alias runs exactly the same gate as its physics name. Single-property gates: - `hadamard(f?, opts?)`, alias `superpose()`: equal superposition of all values - `inverseHadamard(opts?)`: undoes hadamard - `cycle(f?, opts?)`, alias `next()`, and `flip()` on two-value properties: next value, wrapping (NOT on a qubit) - `shift(f?, opts?)`, alias `previous()`: previous value, wrapping - `clock(f?, opts?)`, alias `phase()`: phase rotation - `x(f?, opts?)`: Pauli X, the same gate as `shift()` (moves BACKWARD on a qutrit) - `z(f?, opts?)`: Pauli Z, the same gate as `clock()` - `y(f?, opts?)`: Pauli Y, two-value properties only Two-property gates: - `a.iSwap(b, fraction, opts?)`: entangling swap. `fraction` is REQUIRED. - `a.swap(b, opts?)`: exchange states. Takes no fraction. - Both need properties with the same number of values and throw when passed the handle they are called on. Free function: - `phaseRotate(angle, { when: [...] })`: rotate the phase of the part of the state where every predicate holds, by `angle` radians. Fractions: - Every gate except `inverseHadamard`, `swap` and `iSwap` takes an optional FIRST argument, the fraction. Omit it for the discrete gate. Any other number is the continuous version; 0.5 is the square root of the gate. Do not write `1` to mean the discrete gate; omit the fraction. Predicates: - `prop.is(value)` and `prop.isNot(value)` build predicates. `value` is a declared value or its index: `a.is(true)` and `a.is(1)` are the same. - Pass them as the options object: `b.flip({ when: [a.is(true)] })` (CNOT), `b.flip(0.5, { when: [a.is(true)] })`, `b.phase({ when: [a.is(true)] })` (CZ). Several predicates must all hold. - A predicate must read a different property than the gate acts on. Joint and read-only functions (import from `quantum-forge/quantum`): - `measure(...props)`, `forcedMeasure(props, values)`, `measureWhen(preds)`, `forcedMeasureWhen(preds, outcome)` - `probabilities(...props)` returns `{ values, probability }[]`; `densityMatrix(...props)` returns `{ row, col, real, imag }[]` labelled with declared values; `probabilityWhen(preds)` - Forced measurement of an outcome with zero probability throws. ### Entanglement patterns 1. **Entangle-split (iSwap)**: One object splits into an anti-correlated pair; exactly one is real. Build it from definite, different values: `a = quantum([false, true]).flip()` (true), `b = quantum([false, true])` (false), then `a.iSwap(b, 0.5)` gives (|10⟩ + i|01⟩)/√2. iSwap on two equal values does nothing. 2. **Correlated pair (CNOT)**: `a = quantum([false, true]).superpose()`, `b = quantum([false, true])`, `b.flip({ when: [a.is(true)] })`. `a` and `b` always measure equal. 3. **Conditional superposition**: `b.superpose({ when: [a.is(true)] })` superposes `b` only where `a` is true. ### Phase and interference - `phase()` / `clock()` changes no measurement probability on its own - Phase becomes visible at the next gate that mixes values (superpose, a partial iSwap) - On a qubit, `superpose().superpose()` ends at false; `superpose().phase().superpose()` ends at true - Between two half-splits, `a.iSwap(b, 0.5); a.phase(bias); a.iSwap(b, 0.5)` gives `a.probability(true)` of 0, 0.5 and 1 at bias 0, 0.5 and 1 - Grover oracle pattern: mark with `phaseRotate(Math.PI, { when: [...] })`, then diffuse with a small `superpose(0.1)` ### Recording and replay ```typescript import { QuantumRecorder, quantum, measure } from "quantum-forge/quantum"; const recorder = new QuantumRecorder(); // no arguments recorder.startRecording(); // before creating the handles to replay const a = quantum([false, true]); const b = quantum([false, true]); a.superpose(); b.flip({ when: [a.is(true)] }); measure(a, b); const saved = QuantumRecorder.serialize(recorder.stopRecording()); // { version: 1, entries } // Later: replay into fresh handles, measurements forced to recorded outcomes const handles = QuantumRecorder.replay(QuantumRecorder.deserialize(saved)); const replayedA = handles.get(a.id); ``` `getLog()` returns a copy while recording. `new QuantumRecorder(manager)` is the 2.x form and throws; that recorder is now `LegacyQuantumRecorder`, which also replays 2.x logs. ## Framework architecture ### Engine pattern (four layers) 1. **Pure Functions**: Game logic in separate modules, no side effects 2. **Engine**: State coordinator: `Engine` with `getState()`, `setState()`, `getHelpers()`, `reset()` 3. **Renderer**: Derives visuals from state: `PixiRenderer` (WebGL/WebGPU) or `CanvasRenderer` 4. **Controller**: Wires Engine + Renderer + Input + GameLoop ### Package exports ```typescript // Core quantum package import { ensureLoaded, quantum, measure, probabilities, densityMatrix, phaseRotate, QuantumRecorder } from "quantum-forge/quantum"; import type { Quantum } from "quantum-forge/quantum"; import { Logger } from "quantum-forge/logging"; import { quantumForgeVitePlugin } from "quantum-forge/vite-plugin"; // Engine package (optional; npm install quantum-forge-engine) import { Engine } from "quantum-forge-engine/engine"; import { PixiRenderer, CanvasRenderer, GameLoop, Camera } from "quantum-forge-engine/rendering"; import { InputManager, LocalMultiplayerManager, GamepadButtons } from "quantum-forge-engine/input"; import { EventBus } from "quantum-forge-engine/events"; // Optional packages (install via `npx quantum-forge-engine add-system`) import { ... } from "quantum-forge-engine/collision"; import { ... } from "quantum-forge-engine/audio"; import { ... } from "quantum-forge-engine/particles"; import { ... } from "quantum-forge-engine/animation"; import { ... } from "quantum-forge-engine/entities"; import { ... } from "quantum-forge-engine/state-machine"; import { ... } from "quantum-forge-engine/timer"; import { ... } from "quantum-forge-engine/save"; import { ... } from "quantum-forge-engine/scenes"; import { ... } from "quantum-forge-engine/operations"; ``` ### Rendering - **PixiRenderer**: WebGL/WebGPU via PixiJS 8. Requires `await renderer.init()` before use. - **CanvasRenderer**: Canvas 2D for simpler games. - **GameLoop**: Fixed-timestep update/render cycle with configurable target FPS. - **Camera**: World-space transforms for scrolling (no zoom API; width/height required). ### Input system ```typescript const input = new InputManager({ logger }); input.bind("jump", { type: "key", code: "Space" }, { type: "gamepad-button", index: GamepadButtons.A }); // In update loop: if (input.isActionJustPressed("jump")) { ... } ``` Supports keyboard, mouse, gamepad (buttons + axes), and touch (zones, joysticks, gestures). ### Optional packages - **Collision**: AABB, circle, point detection + SpatialGrid - **Audio**: Howler.js wrapper for sound effects and music - **Particles**: Burst, trail, and continuous emitters - **Animation**: Tweening with easing functions - **Entities**: Entity management with spatial queries. `remove()`, `clear()` and replacing `add()` dispose the quantum handles stored on the entity (own fields and arrays in them); pass `{ disposeQuantum: false }` to keep them - **State Machine**: Finite state machine - **Timer**: Pause-aware timers - **Save**: Versioned save/load - **Scenes**: Stack-based scene lifecycle ## CLI tools The core package's `quantum-forge` command runs one command itself, from core 3.1.0: `npx quantum-forge example [dir] [--no-install]` copies Quantum Pong (core only, Canvas 2D, 8 headless tests) into a new project. Every other command ships in the optional ENGINE package. `npx quantum-forge-engine ` always works; `npx quantum-forge ` hands off to it from core 2.7.0 onward. ```bash npx quantum-forge-engine init my-game # Scaffold new project (prompts) npx quantum-forge-engine init my-game --template quantum-pong # With full example npx quantum-forge-engine init my-game --edition qubit # Qubit edition (20 qubits) npx quantum-forge-engine init my-game --platforms web,desktop # Add an Electron target npx quantum-forge-engine add-system # Add optional packages interactively npx quantum-forge-engine validate # Architecture pattern scoring npx quantum-forge-engine doctor # Environment diagnostics ``` Non-interactive scaffold: ```bash npx -y quantum-forge-engine init my-game \ --template starter --platforms web --edition qutrit --no-claude-skill ``` `add-system`, `validate`, and `doctor` are subcommands of the engine bin and require quantum-forge-engine 1.3.0 or later. On older versions they were monorepo-only scripts and cannot be run from a scaffolded project. Scaffolded projects have NO `npm run add-system` / `npm run validate` / `npm run doctor` scripts, so do not suggest those. Templates: `starter` generates a Vite + TypeScript project with pure logic modules, an Engine subclass, a PixiJS renderer, a controller in `main.ts`, and a vitest file. From engine 1.3.0 it also writes `CLAUDE.md` and `AGENTS.md`. `quantum-pong` generates a complete game with a QuantumRegistry of handle functions, pong logic, audio assets, and 75 tests. ## Unity integration ### Installation Unity Package Manager → Add package from git URL: ``` https://github.com/quantum-native/quantum-forge-unity.git ``` Pin a version by appending a tag, e.g. `https://github.com/quantum-native/quantum-forge-unity.git#unity-v1.4.0`. ### Core components - **Basis** (ScriptableObject): Defines quantum dimension and state labels - **QuantumProperty** (MonoBehaviour): Attaches quantum state to a GameObject - **Action components**: Hadamard, Cycle, Clock, iSwap, and the rest, wired to UI buttons - **ProbabilityTracker**: Visualizes quantum state probabilities in real time ### Inspector workflow 1. Create Basis ScriptableObject (e.g., dimension=2, labels=["Dead","Alive"]) 2. Add QuantumProperty component to GameObject, assign Basis 3. Add action components (e.g., Hadamard), configure in inspector 4. Wire the action's apply() method to button clicks 5. Add ProbabilityTracker for visualization ## Showcase games - **Quantum Pong**: Entangle-split balls, phase-biased scoring (dim=2, RDM visualization) - **Quantris** (quantris.io): Quantum existence in puzzle pieces (dim=2) - **Hex Diffusion**: Probability diffusion across hex grid (dim=7, fractional Hadamard, Grover oracle). Runs on a custom internal build; public editions cap at dimension 3 (Qutrit) or 2 (Qubit), so this is not reproducible with a shipped build. - **Bloch Invaders**: Bloch sphere navigation via Y/Z gates (dim=2) - **Ponq** (ponq.io): Coherence-driven ball physics via density matrix (dim=2) ## AI agent support The `quantum-forge` npm package includes `QUANTUM_FORGE.md`, a complete framework reference for AI coding assistants. It covers quantum properties, gates, entanglement patterns, measurement, lifecycle, recording, rendering, input, and performance, with code examples throughout. To use it, point your AI assistant at `node_modules/quantum-forge/QUANTUM_FORGE.md`. Claude Code users get it as a `/quantum-forge` skill by passing `--claude-skill` at scaffold time (`npx quantum-forge-engine init my-game --claude-skill`), which copies the file to `.claude/skills/quantum-forge/SKILL.md`. There is no post-hoc install command yet; copy the file by hand to add it to an existing project. ### Non-interactive scaffold ```bash npx -y quantum-forge-engine init my-game \ --template starter --platforms web --edition qutrit --no-claude-skill ``` ### Running quantum code headlessly (Node, vitest, CI) No Vite plugin is needed in Node. The loader finds the WASM inside the installed `quantum-forge` package, and `useQuantumForgeBuild("qubit")` selects the Qubit Edition the same way. Node 22 or newer. ```typescript import { ensureLoaded, quantum, measure } from "quantum-forge/quantum"; await ensureLoaded(); const a = quantum([false, true]).flip(); // true const b = quantum([false, true]); // false a.iSwap(b, 0.5); // (|10⟩ + i|01⟩)/√2 const [va, vb] = measure(a, b); // always true,false or false,true a.dispose(); b.dispose(); ``` Only when the WASM lives outside the package: `setWasmBasePath(pathToFileURL(dir).href)` before `ensureLoaded()`. `getWasmBasePath()` reports where the loader will look. ### Common agent mistakes - `npx quantum-forge init` on core older than 2.7.0: no bin. `npx quantum-forge-engine init` always works. - 2.x API in new code: `QuantumPropertyManager`, `acquireProperty()`, `getModule().i_swap(...)`, `measure_properties([...])`. Use `quantum()` handles and camelCase methods. - `a.iSwap(b)`: wrong, the fraction is required. - `hadamard(1)` to mean the discrete gate: omit the fraction instead. - `flip()` or `y()` on a three-value property: throws. Use `next()`; `x()` moves backward. - Expecting `measure()` to return 0/1: it returns the declared value. - `entangle()`: does not exist. Interact (iSwap, or a gate with `{ when: [...] }`). - Using a handle after `dispose()` or after `EntityManager.remove()` disposed it: throws. - Requesting more than 3 values: shipped builds hard-cap at 3. - Mutating `engine.getState()`: it returns `Readonly`; spread into `setState`. - `Engine` subclasses must implement both `getHelpers()` and `reset()`; both are abstract. ## Links - Developer site: https://quantum.dev - GitHub: https://github.com/quantum-native - Discord: https://discord.gg/quantumforge - Contact: hello@quantum.dev ## License - TypeScript framework + Unity C# source: MIT - WASM binaries + native plugins: Proprietary (free under $100K annual revenue with attribution)