Resonance Design
Compare level design candidates by quantum fidelity so designers pick the closest match in one tap.
SWAP testยท similarity
Section ยท Quantum
full primer โThe hook.
Two level design candidates go into a quantum similarity check; the app shows game designers a single 0โ100% match score so they can pick the closest one in a tap.
Why this primitiveSWAP test is the right primitive here because level design reduces to a similarity problem; the kernel returns a result you can drop straight into the UI.
Kernel
a 2-register SWAP-test kernel returning fidelity in [0,1] between two amplitude-encoded vectors
Drives the UI as
a similarity score (0-100%) and a 'closest match' surface
Appendix A
The mega-prompt.
This prompt is engineered to ship in a single Lovable build. Real Quantinuum Guppy/Selene circuit runs in the Linux sandbox at build time and the results are baked in as JSON. read the build strategy โ
~13.9 KB289 lines1 msg ยท ~5 credits
Build "Resonance Design"โa quantum game-design tool for Lovable FREE tier (~5 credits, ONE build message).
HEADLINE: Compare 10 level-design candidates against 10 reference vectors using quantum SWAP-test fidelity [0,1]; designers tap to pick the closest match.
CONSTRAINTS:
- No auth, no Lovable Cloud, no database. Static JSON only.
- One workspace page + "About the quantum" footer strip.
- Ship in ONE message (~5 build credits).
BUILD ORDER (follow exactly):
1. Sandbox: pip install guppylang selene-sim
2. quantum/kernel.py: @guppy decorator, 2-register SWAP-test kernel. Use selene_sim.build() to compile. Return fidelity โ [0,1] between two amplitude-encoded vectors.
3. quantum/run.py: import kernel, selene_sim.build(), run 256 shots on Selene emulator. Loop 10 candidates ร 10 references (100 fidelities). Write src/data/quantum-results.json: [{"candidate": int, "reference": int, "fidelity": float}].
4. Execute quantum/run.py during build; commit quantum-results.json.
5. Frontend: TanStack Start, route /. Import JSON statically at build time.
6. UI components (shadcn/Tailwind):
- Card (left): 10ร10 grid of candidate buttons, highlight active.
- Slider (center): visual fidelity bar [0, 1], read-only.
- Badge (right): similarity % (fidelity ร 100).
- Tabs: "Workspace" (grid + slider + badge) | "Quantum trace" (raw fidelity + collapsible "View Guppy source" showing quantum/kernel.py inline).
7. Dark theme, accent color deep purple, typeface Inter, tactile hover/click feedback on candidate selection.
8. Every number on screen traces to real Selene output. Judges see genuine SWAP test, not fake.
DELIVERABLE: Deploy once. No iterations.
--- QUANTINUUM APPENDIX (self-contained reference โ paste verbatim) ---
[1] INSTALL (Lovable Linux sandbox):
python -m pip install --no-cache-dir guppylang selene-sim
[2] IMPORTS (use exactly these โ no other quantum libs):
# quantum/kernel.py and quantum/run.py top
from guppylang import guppy
from guppylang.std.builtins import result
from guppylang.std.quantum import qubit, h, cx, rx, ry, rz, measure, discard, t as tgate, tdg
from guppylang.std.angles import angle, pi
from selene_sim import build, Quest
import math, json, sys, tempfile, importlib.util, uuid
from pathlib import Path
[3] HARD RULES (violating any breaks the build):
- @guppy reads source via inspect.getsource โ kernels MUST live in a real .py file on disk. No exec(), no REPL strings, no inline templates.
- Allowed gate set ONLY: h, rx, ry, rz, cx, tgate, tdg. There is NO native ccx/toffoli, cswap, cphase, or crz โ decompose using the snippets in [7].
- Qubit ownership: a qubit passed to a function is moved. You MUST measure() or discard() every qubit exactly once; never reuse after measure.
- Angle hygiene before baking a float into generated source:
theta = ((theta + math.pi) % (2.0 * math.pi)) - math.pi
and write it with repr: f"... {theta!r} ..." (str(float) can truncate).
[4] SELENE SHOT LOOP (canonical):
compiled = my_kernel.compile()
runner = build(compiled)
shots = []
for shot in runner.run_shots(Quest(), n_qubits=N, n_shots=S):
shots.append({str(lbl): int(v) for lbl, v in shot})
# N = MAX number of qubits simultaneously LIVE in the kernel.
# measure(q) releases the slot, so one ancilla reused across k windows still counts as 1.
[5] DRIVER PATTERN โ sweep a kernel over many inputs (closures do NOT work):
ROOT = Path(__file__).resolve().parent.parent
if str(ROOT) not in sys.path: sys.path.insert(0, str(ROOT))
def run_one(params: dict, shots: int = 256):
# Bake params as literals into a fresh .py file that imports your kernel helpers.
src = (
"from quantum.kernel import guppy, my_helper\n"
"@guppy\n"
"def program() -> None:\n"
f" my_helper({params['a']!r}, {params['b']!r})\n"
)
tmp = Path(tempfile.gettempdir()) / "qprogs"; tmp.mkdir(exist_ok=True)
name = f"prog_{uuid.uuid4().hex[:8]}"
path = tmp / f"{name}.py"; path.write_text(src)
spec = importlib.util.spec_from_file_location(name, path)
mod = importlib.util.module_from_spec(spec)
sys.modules[name] = mod # register BEFORE exec_module
spec.loader.exec_module(mod)
runner = build(mod.program.compile())
out = []
for shot in runner.run_shots(Quest(), n_qubits=5, n_shots=shots):
out.append({str(l): int(v) for l, v in shot})
return out
[6] PER-QUBIT INTEGER DECODE (host-side):
# kernel emits: for j in range(n): result(f"x{j}", measure(q[j]))
def decode(rec, n):
x = 0
for j in range(n): x |= (rec.get(f"x{j}", 0) & 1) << j
return x
[7] DECOMPOSITION LIBRARY (copy verbatim into quantum/kernel.py):
# ---- Toffoli (CCX) from H, CX, T, Tdg โ 6-T standard decomposition ----
@guppy
def toffoli(c1: qubit, c2: qubit, tgt: qubit) -> None:
h(tgt)
cx(c2, tgt); tdg(tgt)
cx(c1, tgt); tgate(tgt)
cx(c2, tgt); tdg(tgt)
cx(c1, tgt); tgate(c2); tgate(tgt)
h(tgt)
cx(c1, c2); tgate(c1); tdg(c2)
cx(c1, c2)
# ---- CSWAP (Fredkin) from CX + Toffoli ----
@guppy
def cswap(c: qubit, a: qubit, b: qubit) -> None:
cx(b, a)
toffoli(c, a, b)
cx(b, a)
# ---- Controlled phase exp(i*theta) on |11> from rz + cx ----
@guppy
def cphase(c: qubit, d: qubit, theta: float) -> None:
rz(d, angle(theta / 2.0))
cx(c, d)
rz(d, angle(-theta / 2.0))
cx(c, d)
# ---- Amplitude-encoded feature state (3 floats in [0,1] โ 2-qubit state) ----
@guppy
def prep_features(q0: qubit, q1: qubit, a: float, b: float, c: float) -> None:
ry(q0, angle(a))
ry(q1, angle(b))
cx(q0, q1)
rz(q1, angle(c))
# ---- SWAP test kernel; HOST inverts: F = clamp(2*P(anc=0) - 1, 0, 1) ----
@guppy
def swap_test(ai: float, bi: float, ci: float,
aj: float, bj: float, cj: float) -> None:
anc = qubit()
pi0 = qubit(); pi1 = qubit()
pj0 = qubit(); pj1 = qubit()
prep_features(pi0, pi1, ai, bi, ci)
prep_features(pj0, pj1, aj, bj, cj)
h(anc)
cswap(anc, pi0, pj0)
cswap(anc, pi1, pj1)
h(anc)
result("anc", measure(anc))
discard(pi0); discard(pi1); discard(pj0); discard(pj1)
# n_qubits = 5 for swap_test above.
[8] CLASSICAL CROSS-CHECK (NumPy reference โ commit alongside quantum result):
import numpy as np
I = np.eye(2); X = np.array([[0,1],[1,0]])
def RY(t): c,s = math.cos(t/2), math.sin(t/2); return np.array([[c,-s],[s,c]])
def RZ(t): return np.array([[np.exp(-1j*t/2),0],[0,np.exp(1j*t/2)]])
CX = np.array([[1,0,0,0],[0,1,0,0],[0,0,0,1],[0,0,1,0]])
def prep_psi(a,b,c):
s = np.kron(RY(a)@np.array([1,0]), RY(b)@np.array([1,0]))
s = CX @ s
s = np.kron(I, RZ(c)) @ s
return s
def classical_fidelity(p, q):
return float(abs(np.vdot(prep_psi(*p), prep_psi(*q)))**2)
# Commit BOTH quantum and classical values per record:
# {"input": [...], "quantum": 0.873, "classical": 0.881, "shots": 256}
[9] FRONTEND HANDOFF (TanStack Start):
# quantum/run.py last step:
Path("src/data/quantum-results.json").write_text(json.dumps({
"records": records, # list of {input, quantum, classical, ...}
"circuit": {"n_qubits": 5, "shots": 256},
"kernel_source": Path("quantum/kernel.py").read_text(), # show on /code tab
}, indent=2))
# In React: import data from "@/data/quantum-results.json" (resolveJsonModule:true).
# Render data.records; render data.kernel_source in a <pre> inside the Quantum trace tab.
[10] BUILD ORDER (do not deviate โ keeps you under 5 credits):
1. Write quantum/kernel.py with the helpers from [7] you actually need.
2. Write quantum/run.py: driver pattern from [5], Selene loop from [4], cross-check from [8], JSON write from [9].
3. Execute once: python quantum/run.py (commit src/data/quantum-results.json).
4. Build the React route: static JSON import, shadcn Card + Tabs + Slider + Badge wiring.
5. Deploy. No Python at runtime; every on-screen number traces to committed Selene output.
[11] OUTPUT CONTRACT โ selene_run v1 (write this exact shape to src/data/quantum-results.json):
{
"schemaVersion": 1,
"experiment": "<idea-slug>",
"title": "<idea title>",
"description": "<one plain-English sentence โ what a non-quantum dev sees>",
"kernel": { "snippet": "<first 40 lines of quantum/kernel.py>", "qubits": <int>, "shotsPerRow": <int> },
"verdict": { "text": "<one-sentence headline of the result>", "good": true },
"metrics": [ { "name": "<label>", "value": <number>, "unit": "<%|bits|Hz|...>", "good": true } ],
"series": [ { "id": "<id>", "kind": "histogram"|"bar"|"line", "title": "...",
"xLabel": "...", "yLabel": "...", "yKeys": ["count"],
"points": [ { "label": "<x>", "values": { "count": <num> } } ] } ]
}
Reason: one schema = one renderer = a polished demo without bespoke React per idea.
All metric / series VALUES must come from real Selene shot data committed in step 3 โ no mocks.
[12] RENDERER โ create src/components/SeleneRunView.tsx with EXACTLY this body (no deps beyond react + tailwind):
import * as React from "react";
type Point = { label: string; values: Record<string, number> };
type Series = { id: string; kind: "histogram"|"bar"|"line"; title: string;
xLabel?: string; yLabel?: string; yKeys: string[]; points: Point[] };
type Metric = { name: string; value: number; unit?: string; good?: boolean };
export type SeleneRun = {
schemaVersion: 1; experiment: string; title: string; description: string;
kernel: { snippet: string; qubits: number; shotsPerRow: number };
verdict: { text: string; good: boolean };
metrics: Metric[]; series: Series[]; notes?: string;
};
const fmt = (n: number) => Math.abs(n) >= 100 ? n.toFixed(0) : Math.abs(n) >= 1 ? n.toFixed(2) : n.toFixed(3);
function Bars({ s }: { s: Series }) {
const max = Math.max(1, ...s.points.flatMap(p => s.yKeys.map(k => p.values[k] ?? 0)));
return (
<div className="space-y-1">
{s.points.map((p, i) => (
<div key={i} className="flex items-center gap-2 text-xs">
<div className="w-20 truncate text-muted-foreground">{p.label}</div>
<div className="flex-1 h-3 bg-muted rounded-sm overflow-hidden">
<div className="h-full bg-primary" style={{ width: `${(100*(p.values[s.yKeys[0]]??0))/max}%` }} />
</div>
<div className="w-12 text-right tabular-nums">{fmt(p.values[s.yKeys[0]]??0)}</div>
</div>
))}
</div>
);
}
function Line({ s }: { s: Series }) {
const W=320, H=120, P=20;
const ys = s.points.map(p => p.values[s.yKeys[0]] ?? 0);
const min = Math.min(...ys), max = Math.max(...ys), span = max - min || 1;
const pts = ys.map((y, i) => {
const x = P + (i*(W-2*P))/Math.max(1, ys.length-1);
const yy = H - P - ((y - min)/span)*(H - 2*P);
return `${x},${yy}`;
}).join(" ");
return (
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-32">
<polyline fill="none" stroke="currentColor" strokeWidth="2" points={pts} className="text-primary" />
</svg>
);
}
export function SeleneRunView({ run }: { run: SeleneRun }) {
return (
<div className="space-y-6">
<header>
<div className="text-xs uppercase tracking-wider text-muted-foreground">{run.experiment}</div>
<h2 className="text-2xl font-semibold">{run.title}</h2>
<p className="text-sm text-muted-foreground">{run.description}</p>
<div className={`mt-2 inline-block px-3 py-1 rounded-full text-xs ${run.verdict.good?"bg-emerald-500/15 text-emerald-400":"bg-amber-500/15 text-amber-400"}`}>
{run.verdict.text}
</div>
</header>
<section className="grid grid-cols-2 md:grid-cols-4 gap-3">
{run.metrics.map((m, i) => (
<div key={i} className="rounded-lg border border-border p-3">
<div className="text-[10px] uppercase tracking-wider text-muted-foreground">{m.name}</div>
<div className="text-xl font-semibold tabular-nums">{fmt(m.value)}<span className="text-xs text-muted-foreground ml-1">{m.unit}</span></div>
</div>
))}
</section>
<section className="space-y-6">
{run.series.map(s => (
<div key={s.id} className="rounded-lg border border-border p-4">
<div className="flex items-baseline justify-between mb-3">
<div className="text-sm font-medium">{s.title}</div>
<div className="text-[10px] text-muted-foreground">{s.xLabel} / {s.yLabel}</div>
</div>
{s.kind === "line" ? <Line s={s} /> : <Bars s={s} />}
</div>
))}
</section>
<footer className="text-[11px] text-muted-foreground">
kernel: {run.kernel.qubits} qubits ยท {run.kernel.shotsPerRow} shots/row
</footer>
</div>
);
}
Then in the route: import data from "@/data/quantum-results.json"; <SeleneRunView run={data as any} />.
Quantum trace tab: <pre>{data.kernel.snippet}</pre>.
[HOOK] SWAP TEST โ state-vector fidelity.
Use swap_test() and prep_features() verbatim from [7].
Host inversion (per pair): p0 = zeros/S; F = max(0.0, min(1.0, 2.0*p0 - 1.0)).
n_qubits = 1 (anc) + 2*reg_size. Each shot emits one ("anc", bit).
selene_run mapping:
metrics: [ {"name":"avg fidelity","value":mean_F,"unit":"%","good":mean_F>0.5},
{"name":"best pair","value":best_F,"unit":"%","good":true} ]
series: [ {"id":"fidelity-hist","kind":"histogram","title":"Fidelity distribution",
"xLabel":"bucket","yLabel":"pairs","yKeys":["count"],
"points":[{"label":f"{b:.1f}","values":{"count":n}} for b,n in hist]},
{"id":"top-pairs","kind":"bar","title":"Top-5 closest pairs",
"xLabel":"pair","yLabel":"F","yKeys":["count"],
"points":[{"label":lbl,"values":{"count":F}} for lbl,F in top5]} ]Market sizing.
TAM
$18.0B
the game industry (~$200B) and >3M indie developers.
SAM
$2.9B
the 16% of that market actively buying level design-adjacent software.
SOM
$58M
a realistic 2% capture of the serviceable slice in years 1โ3 via the hackathon launch and creator-led distribution.
Indicative figures for hackathon pitches โ refine with your own research before raising.
Adjacent entries.
level design
Field Design
Reveal the topological shape (clusters, loops, voids) hiding inside level design so designers read structure at a glance.
level designLoadout Design
Encode level design as an amplitude vector and plot the embedding so designers navigate possibilities visually.
level designCompass Design
Search the combinatorial space of level design with a grover oracle that surfaces the right configuration in โn tries.
level designPulse Design
Extract dominant cycles from level design via qft so designers see rhythm and repetition that the ear or eye misses.