rsigame-page / index.html
lucy647's picture
Demo: swap in the 78-second walkthrough with credits
9850071 verified
Raw History Blame
16.8 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>RSIGame: Autonomous Agentic Game Development</title>
<meta name="description" content="RSIGame turns open-ended game improvement into goal-oriented, state-controlled progressive development through agentic verification.">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@500;700&family=Space+Grotesk:wght@500;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="static/css/base.css">
<link rel="stylesheet" href="static/css/v1.css">
</head>
<body>
<nav class="nav" id="nav">
<a class="brand" href="#top"><span class="brand-mark">▲</span>RSIGame</a>
<div class="nav-links">
<a href="#overview">Overview</a>
<a href="#demo">Video</a>
<a href="#compare">Before / After</a>
<a href="#play">Play</a>
<a href="#gallery">Gallery</a>
<a href="#results">Results</a>
<a href="#citation">Citation</a>
</div>
</nav>
<header class="hero" id="top">
<div class="hero-bg" aria-hidden="true">
<video id="hero-video" muted loop playsinline preload="auto" data-src="hero_evo.mp4" data-poster="hero_evo.webp"></video>
</div>
<div class="hero-inner">
<p class="eyebrow">Agentic verification · Progressive development</p>
<h1>RSIGame</h1>
<p class="hero-sub">Autonomous Agentic Game Development with Recursive Self-improvement</p>
<p class="authors" style="color: var(--text); margin-bottom: 8px;">Wenyi Wu<sup>1*</sup>, Minghao Fu<sup>1,2*</sup>, Jieyu You<sup>2</sup>, Kun Zhou<sup>1&dagger;</sup>, Siqi Liu<sup>1</sup>, Aayush Salvi<sup>1</sup>, Yiheng Lin<sup>2</sup>, Ce Zhang<sup>3</sup>, Xiaohan Lan<sup>2</sup>, Jiahui Zhu<sup>2</sup>, Yujie Zhong<sup>2&dagger;</sup>, Qi She<sup>2</sup>, Biwei Huang<sup>1</sup></p>
<p class="authors" style="margin-bottom: 4px;"><sup>1</sup>University of California San Diego &nbsp; <sup>2</sup>ByteDance Inc. &nbsp; <sup>3</sup>Carnegie Mellon University</p>
<p class="authors"><small><sup>*</sup>Equal contribution &nbsp; <sup>&dagger;</sup>Corresponding authors</small></p>
<div class="hero-cta">
<a class="btn btn-primary" href="#compare">Watch games evolve</a>
<a class="btn" href="#demo">Video <small>72&nbsp;s</small></a>
<a class="btn" href="#" aria-disabled="true">Paper <small>soon</small></a>
<a class="btn" href="https://github.com/WenyiWU0111/RSIGame/tree/main" target="_blank" rel="noopener">Code <small>GitHub</small></a>
<a class="btn" href="https://huggingface.co/RSIGame" target="_blank" rel="noopener">Datasets <small>on 🤗</small></a>
</div>
</div>
</header>
<section class="section" id="overview">
<div class="wrap">
<div class="stats" id="hero-stats">
<div class="stat"><b>+14.3</b><span>Overall on Codex&nbsp;+&nbsp;GPT-5.5 · 50.3&nbsp;→&nbsp;64.5</span></div>
<div class="stat"><b>61.4</b><span>Qwen3.8-27B games after experience internalization and RSIGame development — past one-shot GPT-5.5 (50.3)</span></div>
<div class="stat"><b>1,998</b><span>runnable agent-written games, to be released</span></div>
<div class="stat"><b>222K</b><span>verified agentic training rows, to be released</span></div>
</div>
<figure class="demo" id="demo">
<video controls playsinline preload="metadata" poster="media/demo/rsigame_demo_poster.webp">
<source src="media/demo/rsigame_demo.mp4" type="video/mp4">
<a href="media/demo/rsigame_demo.mp4">Download the demo video (MP4, 21&nbsp;MB)</a>
</video>
<figcaption>RSIGame in 78 seconds: the local and global loops at work, one game developed across stages with sparse high-level guidance, and before/after comparisons across 2D and 3D games.</figcaption>
</figure>
<div class="overview">
<div>
<h2>Abstract</h2>
<p>Recent advances in large language models have made automatic game generation increasingly feasible, yet reliably improving generated games beyond a playable version remains challenging. Naive iterative refinement can easily overfit a small set of test cases, producing fragile games with unresolved bugs, missing behaviors, and poor generalization to broader player interactions.</p>
<p>We introduce <strong>RSIGame</strong>, an autonomous agentic game development framework with recursive self-improvement. RSIGame organizes development into complementary local and global loops. Concretely, a local <em>explore-diagnose-improve</em> loop broadly explores the executable game, diagnoses and prioritizes discovered issues, and performs evidence-grounded revision, where an evolving checklist continually accumulates new testing and improvement guidance. A global loop tracks overall quality, preserves the best checkpoint, and detects saturation or regression over long-horizon development. Beyond test-time improvement, RSIGame further internalizes successful development experience into the generator through training.</p>
<p>Across 140 GameCraft-Bench tasks, two game engines, and five generators, RSIGame consistently improves game quality under matched development budgets. Notably, experience internalization enables Qwen3.8-27B to reach 61.38 on Godot and 58.53 on Phaser, exceeding GPT-5.5 one-shot scores while reducing Qwen's generation tokens by 11 times.</p></div>
<aside class="loopcard">
<h3>How a game develops</h3>
<section class="loopbox inner">
<div class="loophead"><b>Inner loop</b><span>one development round</span></div>
<ol class="loopsteps">
<li><b>Explore</b><span>An agent plays the executable game and records what actually happens — logs, metrics, screenshots.</span></li>
<li><b>Diagnose</b><span>That evidence becomes one concrete objective: the place with the most improvement headroom.</span></li>
<li><b>Edit</b><span>A repair agent changes code or content against that single objective.</span></li>
<li><b>Verify</b><span>An independent agent replays the game: did the change land, and did anything that worked before break?</span></li>
</ol>
<p class="loopcycle"><span aria-hidden="true">↻</span> Repeats every round, each round starting from the verified state of the last.</p>
</section>
<section class="loopbox outer">
<div class="loophead"><b>Outer loop</b><span>across stages</span></div>
<ul class="loopouter">
<li><b>Global Quality Monitor</b>Scores progress across rounds, holds the globally best checkpoint, and detects when the inner loop has saturated.</li>
<li><b>Sparse high-level guidance</b>On saturation, a human or a stronger model contributes new mechanics, a design direction or an art style — opening the next stage instead of ending the run.</li>
</ul>
</section>
</aside>
</div>
</div>
</section>
<section class="section section-alt" id="compare">
<div class="wrap">
<header class="section-head">
<h2>Before / After</h2>
<p>The ten largest gains we have on record, five per generator. Each pair replays <em>the same scripted inputs</em> on two builds of the same game: the initial generation (round 0) and the build development delivers. Sweep across the frame to wipe between them; pick another game from the ten below.</p>
</header>
<div class="headline" id="headline"></div>
<div class="spotlight" id="spotlight"></div>
</div>
</section>
<section class="section" id="play">
<div class="wrap">
<header class="section-head">
<h2>Play the before and after</h2>
<p>Six games taken all the way through development, in the browser. Switch between the
initial generation and the delivered build — the same game, the same controls, whatever
the rounds changed. Every intermediate round lives in that game's own Space.</p>
</header>
<div class="playbar" id="playbar" role="group" aria-label="Pick a game"></div>
<div class="playwho"><b id="play-title"></b><span id="play-sub"></span></div>
<div class="segbig" id="play-rounds" role="group" aria-label="Which build to play"></div>
<div class="playframe"><iframe id="playframe" title="Playable game" loading="lazy"
allow="autoplay; fullscreen; gamepad; cross-origin-isolated"></iframe></div>
<p class="playnote" id="playnote"></p>
</div>
</section>
<script>
// The six finished games live in this Space (play/<game>/{base,final}), loaded same-origin so they also work while the Space is private.
// All 12 builds share one engine (_engine/godot.wasm, 36 MB); one copy each would fill the 1 GB.
const PLAY_SPACE = {
racing: 'play/racing/',
forest: 'play/forest/',
fps: 'play/fps/',
arcade: 'play/',
};
const PLAY_GAMES = [
{name:'Lawn Guardians', kind:'Tower defence', model:'GPT-5.5', rounds:55, sp:'arcade',
r0:'lawn/base/index.html', fin:'lawn/final/index.html', s0:61.7,
keys:'Click a seed card, then a lawn square · click sun to collect'},
{name:'Alley Brawlers', kind:'Fighting', model:'GPT-5.5', rounds:41, sp:'arcade',
r0:'alley/base/index.html', fin:'alley/final/index.html', s0:56.6, s1:66.0,
keys:'Arrows move · Z / X / C attack'},
{name:'Block Cascade', kind:'Puzzle', model:'GPT-5.5', rounds:46, sp:'arcade',
r0:'block/base/index.html', fin:'block/final/index.html', s0:37.2, s1:50.0,
keys:'Arrows move · UP rotate · SPACE hard drop · SHIFT / C hold'},
{name:'Circuit GT', kind:'Racing · 3D', model:'GLM-5.3-Flash', rounds:64, sp:'racing',
r0:'base/index.html', fin:'final/index.html',
keys:'W / S throttle · A / D steer · SPACE handbrake'},
{name:'Forest Explorer', kind:'Adventure · 3D', model:'GLM-5.3-Flash', rounds:62, sp:'forest',
r0:'base/index.html', fin:'final/index.html',
keys:'WASD move · SHIFT sprint · E chest · Q / RMB bow'},
{name:'FPS Arena', kind:'Shooter · 3D', model:'GLM-5.3-Flash', rounds:58, sp:'fps',
r0:'base/index.html', fin:'final/index.html',
keys:'WASD move · LMB fire · 1 / 2 / 3 weapon · R reload'},
];
(function () {
const bar = document.getElementById('playbar');
const seg = document.getElementById('play-rounds');
const frame = document.getElementById('playframe');
const note = document.getElementById('playnote');
const ttl = document.getElementById('play-title');
const sub = document.getElementById('play-sub');
let cur = 0, side = 'fin', visible = true;
let wanted = ''; // the build that should be loaded; kept while unloaded off-screen
function render() {
const g = PLAY_GAMES[cur];
wanted = PLAY_SPACE[g.sp] + (side === 'r0' ? g.r0 : g.fin);
if (visible) frame.src = wanted;
ttl.textContent = g.name;
const gain = (g.s0 != null && g.s1 != null)
? ' · ' + g.s0.toFixed(1) + ' → ' + g.s1.toFixed(1) +
' (+' + (g.s1 - g.s0).toFixed(1) + ')'
: '';
sub.textContent = g.kind + ' · written by ' + g.model + ' · ' + g.rounds +
' development rounds' + gain;
note.innerHTML = g.keys + (g.more ? ' &nbsp;·&nbsp; <a href="' + g.more +
'" target="_blank" rel="noopener">every round of this game →</a>' : '');
[...bar.children].forEach((b, i) => b.setAttribute('aria-pressed', i === cur));
const sides = [['r0', 'Base game', g.s0, 'as first generated'],
['fin', 'After RSIGame', g.s1, g.rounds + ' rounds of development']];
seg.replaceChildren(...sides.map(([k, t, sc, hint]) => {
const b = document.createElement('button');
b.innerHTML = '<span class="sg-lab">' + t + '</span>' +
'<span class="sg-num">' + (sc != null ? sc.toFixed(1) : '\u2014') + '</span>' +
'<span class="sg-hint">' + hint + '</span>';
b.setAttribute('aria-pressed', k === side);
b.onclick = () => { side = k; render(); };
return b;
}));
}
PLAY_GAMES.forEach((g, i) => {
const b = document.createElement('button');
b.className = 'playbtn';
b.innerHTML = '<b>' + g.name + '</b><span>' + g.kind + '</span>';
b.onclick = () => { cur = i; side = 'fin'; render(); };
bar.appendChild(b);
});
render();
// The games play music, which should stop once scrolled away. The iframe is cross-origin, so its volume
// cannot be set from here; unloading it (about:blank) is the reliable way to silence it.
// A 1.5 s grace period avoids reloading while scrolling quickly.
let timer = null;
const io = new IntersectionObserver((es) => {
const on = es[0].isIntersecting;
clearTimeout(timer);
if (on) {
visible = true;
if (frame.src !== wanted) frame.src = wanted;
} else {
timer = setTimeout(() => {
visible = false;
frame.removeAttribute('src');
frame.src = 'about:blank';
}, 1500);
}
}, { threshold: 0.12 });
io.observe(document.getElementById('play'));
// also stop when the tab is hidden
document.addEventListener('visibilitychange', () => {
if (document.hidden) { frame.src = 'about:blank'; }
else if (visible && frame.src !== wanted) { frame.src = wanted; }
});
})();
</script>
<section class="section" id="gallery">
<div class="wrap">
<header class="section-head">
<h2>Every game, round 0 → round 30</h2>
<p>The GameCraft-Bench games with a replayable before/after pair, from GPT-5.5 and Qwen3.8-27B initial generations in Godot 4. Runs whose retained checkpoint is round 0, or whose two builds share no replayable demo, are not shown; the Results section reports all 140 tasks. Open a game for the side-by-side replay, the score of every checkpoint, what each of the 30 rounds did, and the judge's reasoning before and after.</p>
</header>
<div id="gallery-app"></div>
</div>
</section>
<section class="section section-alt" id="results">
<div class="wrap">
<header class="section-head">
<h2>How far 30 rounds go</h2>
<p>GameCraft-Bench scores a game by replaying scripted demos and judging them against a per-task rubric: <b>Overall = Build × (0.15·Mechanics + 0.35·Depth + 0.15·Visuals + 0.35·Art)</b>, shown ×100. Every method starts from the same frozen base P₀ and is scored by the same judge on the same demo scripts.</p>
</header>
<div class="results">
<figure class="chart-card">
<figcaption><h3>Development-time scaling</h3><p>Mean Overall of the build a budget of <i>k</i> rounds delivers · band = ±1 s.e. over games · hover for values</p></figcaption>
<div class="legend legend-dev" id="dev-legend"></div>
<div id="devscale" class="devgrid"></div>
<p class="chart-foot">A free-form playtest-and-revise baseline finishes a strong base where it started; the Global Quality Monitor is what keeps late rounds from undoing earlier gains. Round 30 minus round 0 under each panel.</p>
</figure>
<figure class="chart-card">
<figcaption><h3>Rubric categories</h3><p>All 140 Godot tasks · frozen base (hollow) → RSIGame (filled)</p></figcaption>
<div class="legend" id="cat-legend"></div>
<div id="cats" class="cats"></div>
<p class="chart-foot">Art and Depth carry the most weight in Overall (0.35 each) and are where the frozen bases are weakest — GPT-5.5 starts at 44.6 Art, Qwen3.8-27B at 33.4 Depth.</p>
</figure>
</div>
<div class="table-head">
<h3>Main results, all 140 tasks</h3>
<div class="seg" id="tbl-seg" role="group" aria-label="Which engine"></div>
</div>
<div class="table-wrap"><table class="table table-main" id="summary"></table></div>
<p class="note" id="judge-note"></p>
</div>
</section>
<section class="section" id="citation">
<div class="wrap">
<header class="section-head"><h2>Citation</h2></header>
<pre class="bibtex"><button class="copy" id="copy-bib">Copy</button><code id="bib">@misc{wu2026rsigame,
title = {RSIGame: Autonomous Agentic Game Development with Recursive Self-improvement},
author = {Wu, Wenyi and Fu, Minghao and You, Jieyu and Zhou, Kun and Liu, Siqi and
Salvi, Aayush and Lin, Yiheng and Zhang, Ce and Lan, Xiaohan and Zhu, Jiahui and
Zhong, Yujie and She, Qi and Huang, Biwei},
year = {2026},
url = {https://github.com/WenyiWU0111/RSIGame}
}</code></pre>
</div>
</section>
<footer class="footer"><div class="wrap">RSIGame project page · demo media hosted on Hugging Face</div></footer>
<script src="static/js/core.js"></script>
<script src="static/js/v1.js"></script>
</body>
</html>