Spaces:
Running
Running
File size: 16,812 Bytes
4a8582a 368e19c 8717769 0fcc10c 368e19c 0fcc10c 368e19c 08901ec 368e19c 7cc3a78 368e19c 7cc3a78 1ac8436 368e19c 1ac8436 368e19c 0fcc10c 8717769 e628805 368e19c 08901ec 368e19c 08901ec 4c3e832 368e19c 08901ec 3bad82e 49e869a 368e19c 08901ec 9850071 08901ec 9850071 08901ec 368e19c 7cc3a78 8717769 49e869a f48d2fd daba935 f48d2fd 368e19c f48d2fd 368e19c 7cc3a78 9b4203d 7cc3a78 79dd437 7cc3a78 49e869a 9b4203d ff43890 9b4203d 7cc3a78 9b4203d ff43890 9b4203d ff43890 9b4203d ff43890 9b4203d eeeae43 ff43890 9b4203d eeeae43 ff43890 9b4203d eeeae43 ff43890 9b4203d 7cc3a78 9b4203d 7cc3a78 9b4203d eeeae43 9b4203d 49e869a 9b4203d eeeae43 9b4203d ff43890 9b4203d 79dd437 9b4203d 79dd437 9b4203d 7cc3a78 9b4203d 7cc3a78 9b4203d eeeae43 49e869a eeeae43 49e869a eeeae43 7cc3a78 368e19c 49e869a 368e19c 033d216 368e19c 033d216 ff43890 368e19c 033d216 368e19c ff43890 368e19c 033d216 368e19c e628805 8717769 e628805 368e19c 0fcc10c 368e19c 4a8582a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 | <!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†</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†</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 <sup>2</sup>ByteDance Inc. <sup>3</sup>Carnegie Mellon University</p>
<p class="authors"><small><sup>*</sup>Equal contribution <sup>†</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 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 + GPT-5.5 · 50.3 → 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 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 ? ' · <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>
|