Synthesized Pong
Every rule below — ball motion, wall bounce, paddle collision, scoring, the paddle-tracking AI, even the speed-up on each rally — is built from programs the nsynth synthesizer discovered from input/output examples, verified against held-out cases, then transpiled Mog → TypeScript. The function bodies on this page are the literal transpiler output. The only human-written code is the canvas renderer, the animation-frame loop, keyboard reading, and the argument-routing glue that wires synthesized primitives together.
The synthesized rules
For each rule: the I/O examples it was synthesized from, the Mog program nsynth discovered, and the TypeScript this page actually runs. Where the first synthesis fit the examples but not the game's full input domain, the verifier's counterexamples were fed back as new examples until the discovered program survived an exhaustive sweep (counterexample-guided synthesis). Rules the synthesizer refused as posed (wall bounce, paddle overlap, clamp, the tracker AI, speed-up) were decomposed into smaller contracts it could discover and verify — the composition glue is shown below the rules.
next_possearch_scalar_expr · 8 examples · 11,781 domain cases verified
1 · Examples (what the synthesizer saw)
next_pos(10, 2) = 12 next_pos(5, -3) = 2 next_pos(0, 4) = 4 next_pos(100, -7) = 93 next_pos(42, 0) = 42 next_pos(799, 11) = 810 next_pos(-5, -11) = -16 next_pos(600, 1) = 601
2 · Discovered Mog program
fn next_pos(a: i64, b: i64) -> i64 {
return (b + a);
}
3 · Transpiled TypeScript (runs on this page)
function next_pos(a: number, b: number): number {
return (b + a);
}
hit_topsynth_gradient · 8 examples · 1,521 domain cases verified
1 · Examples (what the synthesizer saw)
hit_top(0) = 1 hit_top(-1) = 1 hit_top(-5) = 1 hit_top(1) = 0 hit_top(3) = 0 hit_top(100) = 0 hit_top(600) = 0 hit_top(-20) = 1
2 · Discovered Mog program
fn hit_top(a: i64) -> i64 {
x: i64 = a;
acc: i64 = 1;
if x == 0 {
return 1;
}
while x > 0 {
d: i64 = x % 11;
x = x / 11;
if acc != 11 {
acc = acc / 2;
}
}
return acc;
}
3 · Transpiled TypeScript (runs on this page)
function hit_top(a: number): number {
let x: number = a;
let acc: number = 1;
if (x == 0) {
return 1;
}
while (x > 0) {
let d: number = x % 11;
x = Math.trunc(x / 11);
if (acc != 11) {
acc = Math.trunc(acc / 2);
}
}
return acc;
}
hit_bottomsearch_single_branch · 9 examples · 361 domain cases verified
1 · Examples (what the synthesizer saw)
hit_bottom(600, 600) = 1 hit_bottom(599, 600) = 0 hit_bottom(601, 600) = 1 hit_bottom(610, 600) = 1 hit_bottom(0, 600) = 0 hit_bottom(300, 600) = 0 hit_bottom(400, 400) = 1 hit_bottom(399, 400) = 0 hit_bottom(405, 400) = 1
2 · Discovered Mog program
fn hit_bottom(a: i64, b: i64) -> i64 {
if (a % 10) != 0 {
return (a / b);
}
return (a / b);
}
3 · Transpiled TypeScript (runs on this page)
function hit_bottom(a: number, b: number): number {
if ((a % 10) != 0) {
return (Math.trunc(a / b));
}
return (Math.trunc(a / b));
}
moving_upsynth_gradient · 10 examples · 51 domain cases verified
1 · Examples (what the synthesizer saw)
moving_up(-1) = 1 moving_up(0) = 0 moving_up(1) = 0 moving_up(-5) = 1 moving_up(7) = 0 moving_up(-11) = 1 moving_up(11) = 0 moving_up(3) = 0 moving_up(-12) = 1 moving_up(12) = 0
2 · Discovered Mog program
fn moving_up(a: i64) -> i64 {
acc: i64 = 1;
i: i64 = 0;
while i <= a {
acc = acc / 3;
i = i + 1;
}
return acc;
}
3 · Transpiled TypeScript (runs on this page)
function moving_up(a: number): number {
let acc: number = 1;
let i: number = 0;
while (i <= a) {
acc = Math.trunc(acc / 3);
i = i + 1;
}
return acc;
}
moving_downsynth_gradient · 10 examples · 51 domain cases verified
1 · Examples (what the synthesizer saw)
moving_down(-1) = 0 moving_down(0) = 0 moving_down(1) = 1 moving_down(-5) = 0 moving_down(7) = 1 moving_down(-11) = 0 moving_down(11) = 1 moving_down(3) = 1 moving_down(-12) = 0 moving_down(12) = 1
2 · Discovered Mog program
fn moving_down(a: i64) -> i64 {
if a > 0 {
return 1;
}
if a != a {
return a;
}
if a != a {
return a;
}
return 0;
}
3 · Transpiled TypeScript (runs on this page)
function moving_down(a: number): number {
if (a > 0) {
return 1;
}
if (a != a) {
return a;
}
if (a != a) {
return a;
}
return 0;
}
gtecomposed: hit_top(sub2(b, a)) · 0 examples · 58,081 domain cases verified
1 · Examples (what the synthesizer saw)
2 · Discovered Mog program
// No new program synthesized — pure reuse of verified skills: // gte = hit_top(sub2(b, a)) // Primitives used: hit_top, sub2 (each synthesized + swept independently).
3 · Transpiled TypeScript (runs on this page)
function gte(a: number, b: number): number {
return hit_top(sub2(b, a));
}
crossed_leftsearch_two_branch · 14 examples · 3,525 domain cases verified
1 · Examples (what the synthesizer saw)
crossed_left(40, 30, 34) = 1 crossed_left(40, 34, 34) = 1 crossed_left(40, 35, 34) = 0 crossed_left(34, 30, 34) = 0 crossed_left(33, 28, 34) = 0 crossed_left(50, 45, 34) = 0 crossed_left(35, 20, 34) = 1 crossed_left(100, 90, 34) = 0 crossed_left(30, 36, 34) = 0 crossed_left(36, 36, 34) = 0 crossed_left(60, 50, 55) = 1 crossed_left(56, 55, 55) = 1 crossed_left(55, 50, 55) = 0 crossed_left(54, 60, 55) = 0
2 · Discovered Mog program
fn crossed_left(a: i64, b: i64, c: i64) -> i64 {
if (2 + c) < a {
return (c / b);
}
if a <= c {
return 0;
}
return (c / b);
}
3 · Transpiled TypeScript (runs on this page)
function crossed_left(a: number, b: number, c: number): number {
if ((2 + c) < a) {
return (Math.trunc(c / b));
}
if (a <= c) {
return 0;
}
return (Math.trunc(c / b));
}
crossed_rightcomposed: flag_and(gte(plane, next_pos(prev, 1)), gte(next, plane)) · 0 examples · 3,025 domain cases verified
1 · Examples (what the synthesizer saw)
2 · Discovered Mog program
// No new program synthesized — pure reuse of verified skills: // crossed_right = flag_and(gte(plane, next_pos(prev, 1)), gte(next, plane)) // Primitives used: flag_and, gte, next_pos (each synthesized + swept independently).
3 · Transpiled TypeScript (runs on this page)
function crossed_right(prev: number, next: number, plane: number): number {
return flag_and(gte(plane, next_pos(prev, 1)), gte(next, plane));
}
flag_andsearch_scalar_expr · 4 examples · 4 domain cases verified
1 · Examples (what the synthesizer saw)
flag_and(0, 0) = 0 flag_and(0, 1) = 0 flag_and(1, 0) = 0 flag_and(1, 1) = 1
2 · Discovered Mog program
fn flag_and(a: i64, b: i64) -> i64 {
return (a * b);
}
3 · Transpiled TypeScript (runs on this page)
function flag_and(a: number, b: number): number {
return (a * b);
}
flag_orsynth_gradient · 4 examples · 4 domain cases verified
1 · Examples (what the synthesizer saw)
flag_or(0, 0) = 0 flag_or(0, 1) = 1 flag_or(1, 0) = 1 flag_or(1, 1) = 1
2 · Discovered Mog program
fn flag_or(a: i64, b: i64) -> i64 {
if 0 != a {
return 1;
}
if a != a {
return a;
}
if a != a {
return a;
}
return b / 1;
}
3 · Transpiled TypeScript (runs on this page)
function flag_or(a: number, b: number): number {
if (0 != a) {
return 1;
}
if (a != a) {
return a;
}
if (a != a) {
return a;
}
return b / 1;
}
selectsynth_gradient · 10 examples · 8,978 domain cases verified
1 · Examples (what the synthesizer saw)
select(1, 5, 9) = 5 select(0, 5, 9) = 9 select(1, -3, 7) = -3 select(0, -3, 7) = 7 select(2, 100, 200) = 100 select(0, 0, 1) = 1 select(1, 0, 1) = 0 select(0, -50, 50) = 50 select(1, 400, 300) = 400 select(0, 400, 300) = 300
2 · Discovered Mog program
fn select(a: i64, b: i64, c: i64) -> i64 {
v0: i64 = c;
if a != 0 {
v0 = b;
}
result: i64 = v0;
if v0 >= 2 {
result = v0;
}
return result;
}
3 · Transpiled TypeScript (runs on this page)
function select(a: number, b: number, c: number): number {
let v0: number = c;
if (a != 0) {
v0 = b;
}
let result: number = v0;
if (v0 >= 2) {
result = v0;
}
return result;
}
score_if_out_rightcomposed: next_pos(score, exited_right(ball_x, w)) · 0 examples · 11,986 domain cases verified
1 · Examples (what the synthesizer saw)
2 · Discovered Mog program
// No new program synthesized — pure reuse of verified skills: // score_if_out_right = next_pos(score, exited_right(ball_x, w)) // Primitives used: next_pos, exited_right (each synthesized + swept independently).
3 · Transpiled TypeScript (runs on this page)
function score_if_out_right(score: number, ball_x: number, w: number): number {
return next_pos(score, exited_right(ball_x, w));
}
score_if_out_leftcomposed: next_pos(score, exited_left(ball_x)) · 0 examples · 11,986 domain cases verified
1 · Examples (what the synthesizer saw)
2 · Discovered Mog program
// No new program synthesized — pure reuse of verified skills: // score_if_out_left = next_pos(score, exited_left(ball_x)) // Primitives used: next_pos, exited_left (each synthesized + swept independently).
3 · Transpiled TypeScript (runs on this page)
function score_if_out_left(score: number, ball_x: number): number {
return next_pos(score, exited_left(ball_x));
}
exited_leftsynth_gradient · 8 examples · 461 domain cases verified
1 · Examples (what the synthesizer saw)
exited_left(-1) = 1 exited_left(0) = 0 exited_left(1) = 0 exited_left(-10) = 1 exited_left(400) = 0 exited_left(800) = 0 exited_left(-3) = 1 exited_left(12) = 0
2 · Discovered Mog program
fn exited_left(a: i64) -> i64 {
x: i64 = a;
acc: i64 = 1;
if x == 0 {
return 0;
}
while x > 0 {
d: i64 = x % 10;
x = x / 10;
if acc != 3 {
acc = acc / 2;
}
}
return acc;
}
3 · Transpiled TypeScript (runs on this page)
function exited_left(a: number): number {
let x: number = a;
let acc: number = 1;
if (x == 0) {
return 0;
}
while (x > 0) {
let d: number = x % 10;
x = Math.trunc(x / 10);
if (acc != 3) {
acc = Math.trunc(acc / 2);
}
}
return acc;
}
exited_rightsearch_single_branch · 9 examples · 461 domain cases verified
1 · Examples (what the synthesizer saw)
exited_right(801, 800) = 1 exited_right(800, 800) = 0 exited_right(799, 800) = 0 exited_right(810, 800) = 1 exited_right(0, 800) = 0 exited_right(-5, 800) = 0 exited_right(401, 400) = 1 exited_right(400, 400) = 0 exited_right(200, 400) = 0
2 · Discovered Mog program
fn exited_right(a: i64, b: i64) -> i64 {
if a != b {
return (a / b);
}
return 0;
}
3 · Transpiled TypeScript (runs on this page)
function exited_right(a: number, b: number): number {
if (a != b) {
return (Math.trunc(a / b));
}
return 0;
}
max2composed: neg(min2(neg(a), neg(b))) · 0 examples · 160,801 domain cases verified
1 · Examples (what the synthesizer saw)
2 · Discovered Mog program
// No new program synthesized — pure reuse of verified skills: // max2 = neg(min2(neg(a), neg(b))) // Primitives used: neg, min2 (each synthesized + swept independently).
3 · Transpiled TypeScript (runs on this page)
function max2(a: number, b: number): number {
return neg(min2(neg(a), neg(b)));
}
min2synth_gradient · 6 examples · 160,801 domain cases verified
1 · Examples (what the synthesizer saw)
min2(3, 7) = 3 min2(9, 2) = 2 min2(4, 4) = 4 min2(-5, -2) = -5 min2(0, -9) = -9 min2(12, 15) = 12
2 · Discovered Mog program
fn min2(a: i64, b: i64) -> i64 {
v0: i64 = b;
if b >= a { v0 = a; }
result: i64 = v0;
if -2 >= a { result = v0; }
return result;
}
3 · Transpiled TypeScript (runs on this page)
function min2(a: number, b: number): number {
let v0: number = b;
if (b >= a) { v0 = a; }
let result: number = v0;
if (-2 >= a) { result = v0; }
return result;
}
sub2synth_gradient (CEGIS iter 1) · 16 examples · 160,801 domain cases verified
1 · Examples (what the synthesizer saw)
sub2(7, 3) = 4 sub2(2, 5) = -3 sub2(0, 0) = 0 sub2(10, -4) = 14 sub2(-3, -8) = 5 sub2(100, 1) = 99 sub2(-300, -300) = 0 sub2(-270, -300) = 30 sub2(-240, -300) = 60 sub2(-210, -300) = 90 sub2(-180, -300) = 120 sub2(-150, -300) = 150 sub2(-120, -300) = 180 sub2(-90, -300) = 210 … 2 more
2 · Discovered Mog program
fn sub2(a: i64, b: i64) -> i64 {
return a - b;
}
3 · Transpiled TypeScript (runs on this page)
function sub2(a: number, b: number): number {
return a - b;
}
negsynth_gradient · 6 examples · 4,001 domain cases verified
1 · Examples (what the synthesizer saw)
neg(3) = -3 neg(-2) = 2 neg(5) = -5 neg(0) = 0 neg(-11) = 11 neg(7) = -7
2 · Discovered Mog program
fn neg(a: i64) -> i64 {
v0: i64 = a * a;
return 0 - a;
}
3 · Transpiled TypeScript (runs on this page)
function neg(a: number): number {
let v0: number = a * a;
return 0 - a;
}
abs2composed: neg(min2(neg(v), v)) · 0 examples · 4,001 domain cases verified
1 · Examples (what the synthesizer saw)
2 · Discovered Mog program
// No new program synthesized — pure reuse of verified skills: // abs2 = neg(min2(neg(v), v)) // Primitives used: neg, min2 (each synthesized + swept independently).
3 · Transpiled TypeScript (runs on this page)
function abs2(v: number): number {
return neg(min2(neg(v), v));
}
growcomposed: select(gte(v, 1), next_pos(v, 1), next_pos(v, -1)) · 0 examples · 51 domain cases verified
1 · Examples (what the synthesizer saw)
2 · Discovered Mog program
// No new program synthesized — pure reuse of verified skills: // grow = select(gte(v, 1), next_pos(v, 1), next_pos(v, -1)) // Primitives used: select, gte, next_pos (each synthesized + swept independently).
3 · Transpiled TypeScript (runs on this page)
function grow(v: number): number {
return select(gte(v, 1), next_pos(v, 1), next_pos(v, -1));
}
reflect_xcomposed: select(hit, neg(vx), vx) · 0 examples · 102 domain cases verified
1 · Examples (what the synthesizer saw)
2 · Discovered Mog program
// No new program synthesized — pure reuse of verified skills: // reflect_x = select(hit, neg(vx), vx) // Primitives used: select, neg (each synthesized + swept independently).
3 · Transpiled TypeScript (runs on this page)
function reflect_x(vx: number, hit: number): number {
return select(hit, neg(vx), vx);
}
Composition glue
The synthesizer is strongest on small pure functions and honestly refuses contracts that are too big as posed. These five game rules are therefore wired together from the synthesized primitives above. The glue contains no human logic — every branch decision is carried by a synthesized function (select, flag_and, flag_or, reflect_x); the glue only routes arguments.
reflect_x(vy, flag_or(flag_and(hit_top(y), moving_up(vy)), flag_and(hit_bottom(y, h), moving_down(vy))))
min2(max2(v, lo), hi)
flag_and(gte(by, py), gte(next_pos(py, ph), by))
min2(max2(sub2(by, pc), neg(sp)), sp)
select(gte(abs2(v), vmax), v, grow(v))
How this was built
- Each game rule was specified only as input → output examples on an integer grid (800 × 600) — no code, no pseudocode.
- The nsynth Rust synthesizer searched its program space (expression search, branch search, gradient-guided synthesis) until it found a Mog program consistent with every example and 500 held-out cases.
- The transpiled JavaScript was then swept across the game's entire reachable input domain against a reference oracle; any mismatch became a new training example and synthesis re-ran (CEGIS) until zero mismatches remained.
- The Mog → TypeScript transpile (mog_transpile.rs) output was embedded verbatim in synthesized.ts — the manifest above shows examples, Mog, and TypeScript for every rule.