← Rally results

Rally

GPT 5.6 terra · typescript

Initial view of Rally

Reviews & generation details

Reviews

No human review yet. Unreviewed does not mean unsuccessful.

Generation context

Imported historical artifact. Its exact original instructions and lineage are not known.

Generation prompt · exact text unavailable

See the current prompt for reference. It may differ from the instructions used to generate this artifact.

Inspect original source 17,505 bytes · SHA-256 e2bd86e97950
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Rally Run — Forest Stage</title>
<script src="https://cdn.jsdelivr.net/npm/three@0.160.1/build/three.min.js"></script>
<style>
/* ── css: ui ── */
*{box-sizing:border-box}html,body,#app,#game{margin:0;width:100%;height:100%;overflow:hidden;background:#87b9d0;font-family:Arial,Helvetica,sans-serif;color:#fff}#game canvas{display:block}#hud{position:fixed;inset:0;pointer-events:none;text-shadow:0 2px 3px #000}.brand{position:absolute;top:22px;left:28px;font-size:25px;font-weight:900;letter-spacing:3px;font-style:italic}.brand b,.logo b{color:#ffb21c}.brand span{display:block;font-size:9px;letter-spacing:3px;color:#ffd27c;margin-top:2px}.topstats{position:absolute;top:23px;right:28px;display:flex;gap:30px;text-align:right}.topstats small{display:block;font-size:9px;letter-spacing:2px;color:#ffca67;font-weight:bold}.topstats strong{font-size:18px;letter-spacing:1px}.topstats i{color:#b8d0dc;font-style:normal;font-size:13px}#speed{position:absolute;left:30px;bottom:27px;width:185px}.speed{}#speed b{font-size:56px;line-height:.8;letter-spacing:-3px}#speed em{font-size:11px;color:#ffbd30;font-style:normal;letter-spacing:2px;margin-left:8px}.gear{margin-top:10px;font-size:10px;color:#a9c2cd;letter-spacing:2px}.gear strong{font-size:16px;color:#fff;margin-left:6px}.rpm{height:5px;background:#234553;margin-top:7px;transform:skew(-20deg)}.rpm i{display:block;height:100%;background:#ffaf19;width:0;transition:width .1s}#minimap{position:absolute;right:25px;bottom:25px;width:190px;height:150px;background:#102936aa;border:1px solid #a5cbd566;padding:5px;clip-path:polygon(8% 0,100% 0,100% 91%,92% 100%,0 100%,0 8%)}#minimap canvas{width:180px;height:130px}#minimap span{font-size:8px;letter-spacing:2px;position:absolute;bottom:5px;left:9px;color:#eac46e}#status{position:absolute;top:17%;width:100%;text-align:center;font-size:58px;font-weight:900;font-style:italic;letter-spacing:4px;color:#ffc12a;opacity:0;transition:opacity .15s}#help{position:absolute;bottom:15px;width:100%;text-align:center;font-size:10px;letter-spacing:1.5px;color:#d5e8ec}.logo{font-size:64px;font-style:italic;font-weight:900;letter-spacing:7px}.logo b{color:#ffae18}#start{position:fixed;inset:0;background:linear-gradient(#0b1e2aaa,#0b1e2ad9);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:18px;text-align:center}#start p{font-size:12px;letter-spacing:3px;color:#c9dce0}button{font:900 13px Arial;letter-spacing:2px;color:#10242c;background:#ffb31c;border:0;padding:16px 28px;cursor:pointer;box-shadow:0 5px #a45b0b}button:hover{background:#ffcc55}button span{margin-left:20px}.panel{position:fixed;inset:0;background:#081820d9;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:16px;text-align:center}.panel h1{font-style:italic;font-size:58px;margin:0;color:#ffbd22}.panel p{font-size:12px;letter-spacing:4px;color:#f6c052;margin:0}.panel button{min-width:190px}.hidden{display:none!important}#result{font-size:17px;line-height:2;color:#d8e8eb;margin-bottom:8px}#touch{display:none}@media(max-width:700px){.topstats{right:12px;gap:12px}.brand{left:12px}.brand span{display:none}#speed{left:14px;bottom:115px}.topstats strong{font-size:14px}#minimap{transform:scale(.75);transform-origin:bottom right;right:5px;bottom:100px}#help{display:none}#touch{display:flex;position:fixed;bottom:16px;left:14px;right:14px;justify-content:space-between;align-items:end;pointer-events:auto}#touch button{padding:15px 12px;box-shadow:none;background:#193d4bbb;border:1px solid #9fbdc7;font-size:11px}.logo{font-size:42px}}
</style>
</head>
<body>
<div id="app"><div id="game"></div><div id="hud"><div class="brand">RALLY <b>RUN</b><span>FOREST STAGE</span></div><div class="topstats"><div><small>LAP</small><strong id="lap">1 <i>/ 3</i></strong></div><div><small>TIME</small><strong id="time">00:00.000</strong></div><div><small>BEST</small><strong id="best">--:--.---</strong></div></div><div id="minimap"><canvas id="map" width="180" height="130"></canvas><span>STAGE MAP</span></div><div id="speed"><b id="speednum">000</b><em>KM/H</em><div class="gear">GEAR <strong id="gear">1</strong></div><div class="rpm"><i id="rpm"></i></div></div><div id="status">GET READY</div><div id="help">WASD / ARROWS DRIVE &nbsp; • &nbsp; SPACE DRIFT &nbsp; • &nbsp; C CAMERA &nbsp; • &nbsp; P PAUSE</div></div><div id="start"><div class="logo">RALLY <b>RUN</b></div><p>THREE LAPS. ONE WILD FOREST STAGE.</p><button id="startBtn">START ENGINE <span>↵</span></button><small>WASD / ARROWS TO DRIVE &nbsp; · &nbsp; SPACE TO DRIFT</small></div><div id="pause" class="panel hidden"><h1>PAUSED</h1><button id="resume">RESUME</button><button id="restart">RESTART STAGE</button></div><div id="finish" class="panel hidden"><p>STAGE COMPLETE</p><h1>FINISH!</h1><div id="result"></div><button id="again">RACE AGAIN</button></div><div id="touch"><button data-k="left">◀</button><button data-k="right">▶</button><button data-k="down">BRAKE</button><button data-k="up">GAS</button><button data-k="space">DRIFT</button></div></div>
<script>
(function () {
'use strict';
var __mods = {};
var __cache = {};
var __map = {};
function __require(id) {
  if (__cache[id]) return __cache[id].exports;
  var module = __cache[id] = { exports: {} };
  var factory = __mods[id];
  if (!factory) throw new Error("Module not found: " + id);
  factory(module.exports, function (spec) {
    var target = (__map[id] && __map[id][spec]) || spec;
    return __require(target);
  }, module);
  return module.exports;
}

// ── module: src/main.ts ──
__mods["src/main.ts"] = function (exports, require, module) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const T = THREE;
const $ = (id) => document.getElementById(id);
const game = $('game'), map = $('map'), mx = map.getContext('2d');
let scene, camera, renderer, car, roadPts = [];
let running = false, paused = false, finished = false, cinematic = false, startedAt = 0, lapStart = 0, laps = 1, best = 0, nextGate = 1;
let s = 0, lateral = 0, speed = 0, yaw = 0, camPos;
let last = performance.now();
const keys = {};
const samples = 360, gates = 12;
const control = [[-80, 0, -40], [-35, 6, -92], [35, 1, -85], [93, 12, -42], [104, 4, 24], [62, 14, 75], [5, 2, 91], [-60, 10, 72], [-104, 2, 27], [-105, 8, -30]];
function v(i) { const p = control[(i + control.length) % control.length]; return new T.Vector3(p[0], p[1], p[2]); }
function init() {
    scene = new T.Scene();
    scene.background = new T.Color(0x83b7cf);
    scene.fog = new T.Fog(0x83b7cf, 110, 300);
    camera = new T.PerspectiveCamera(62, innerWidth / innerHeight, .1, 500);
    renderer = new T.WebGLRenderer({ antialias: true });
    renderer.setSize(innerWidth, innerHeight);
    renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
    renderer.shadowMap.enabled = true;
    game.appendChild(renderer.domElement);
    scene.add(new T.HemisphereLight(0xbfe8ff, 0x38552e, 2));
    const sun = new T.DirectionalLight(0xffefcc, 2.2);
    sun.position.set(80, 120, 20);
    sun.castShadow = true;
    scene.add(sun);
    const ground = new T.Mesh(new T.PlaneGeometry(800, 800), new T.MeshLambertMaterial({ color: 0x527b3d }));
    ground.rotation.x = -Math.PI / 2;
    ground.receiveShadow = true;
    scene.add(ground);
    const curve = new T.CatmullRomCurve3(control.map((_, i) => v(i)), true, 'catmullrom', .2);
    for (let i = 0; i < samples; i++)
        roadPts.push(curve.getPointAt(i / samples));
    buildRoad();
    buildScenery();
    car = makeCar();
    scene.add(car);
    camPos = new T.Vector3();
    reset();
    addEventListener('resize', () => { camera.aspect = innerWidth / innerHeight; camera.updateProjectionMatrix(); renderer.setSize(innerWidth, innerHeight); });
    addEventListener('keydown', e => { keys[e.key.toLowerCase()] = true; if (e.key === ' ')
        e.preventDefault(); if (e.key.toLowerCase() === 'p' && running) {
        paused = !paused;
        $('pause').classList.toggle('hidden', !paused);
    } if (e.key.toLowerCase() === 'c')
        cinematic = !cinematic; if (e.key.toLowerCase() === 'r')
        reset(); });
    addEventListener('keyup', e => keys[e.key.toLowerCase()] = false);
    document.querySelectorAll('#touch button').forEach(b => { const k = b.dataset.k; b.addEventListener('pointerdown', e => { e.preventDefault(); keys[k] = true; }); b.addEventListener('pointerup', () => keys[k] = false); b.addEventListener('pointerleave', () => keys[k] = false); });
    $('startBtn').onclick = () => begin();
    $('resume').onclick = () => { paused = false; $('pause').classList.add('hidden'); };
    $('restart').onclick = reset;
    $('again').onclick = reset;
    drawMap();
    requestAnimationFrame(loop);
}
function buildRoad() {
    const verts = [];
    const w = 8;
    for (let i = 0; i < samples; i++) {
        const a = roadPts[i], b = roadPts[(i + 1) % samples], d = b.clone().sub(a).normalize(), side = new T.Vector3(-d.z, 0, d.x);
        verts.push(a.x + side.x * w, a.y + .1, a.z + side.z * w, a.x - side.x * w, a.y + .1, a.z - side.z * w);
    }
    const ind = [];
    for (let i = 0; i < samples; i++) {
        let n = (i + 1) % samples;
        ind.push(i * 2, i * 2 + 1, n * 2, n * 2, n * 2 + 1, i * 2 + 1);
    }
    const g = new T.BufferGeometry();
    g.setAttribute('position', new T.Float32BufferAttribute(verts, 3));
    g.setIndex(ind);
    g.computeVertexNormals();
    scene.add(new T.Mesh(g, new T.MeshLambertMaterial({ color: 0x9a744d })));
    // dashed center and markers
    for (let i = 0; i < samples; i += 12) {
        const p = roadPts[i], q = roadPts[(i + 1) % samples];
        const dash = new T.Mesh(new T.BoxGeometry(.25, .04, 5), new T.MeshBasicMaterial({ color: 0xffd370 }));
        dash.position.copy(p);
        dash.position.y += .15;
        dash.rotation.y = -Math.atan2(q.z - p.z, q.x - p.x) + Math.PI / 2;
        scene.add(dash);
    }
}
function tree(x, z, scale) { const y = 0; const trunk = new T.Mesh(new T.CylinderGeometry(.35, .5, 3 * scale, 6), new T.MeshLambertMaterial({ color: 0x5b3923 })); trunk.position.set(x, y + 1.5 * scale, z); scene.add(trunk); const crown = new T.Mesh(new T.ConeGeometry(2.1 * scale, 6 * scale, 7), new T.MeshLambertMaterial({ color: 0x1d5935 })); crown.position.set(x, y + 5 * scale, z); crown.castShadow = true; scene.add(crown); }
function buildScenery() { for (let i = 0; i < 150; i++) {
    const a = i * 2.399, r = 28 + (i % 7) * 10;
    tree(Math.cos(a) * r, Math.sin(a) * r, .65 + (i % 3) * .18);
} for (let i = 0; i < gates; i++) {
    let p = roadPts[Math.floor(i * samples / gates)], n = roadPts[(Math.floor(i * samples / gates) + 1) % samples], d = n.clone().sub(p).normalize(), side = new T.Vector3(-d.z, 0, d.x);
    for (const sign of [-1, 1]) {
        let post = new T.Mesh(new T.BoxGeometry(.35, 4, .35), new T.MeshLambertMaterial({ color: 0xf3e2bc }));
        post.position.copy(p).addScaledVector(side, sign * 8.5);
        post.position.y += 2;
        scene.add(post);
    }
    if (i === 0) {
        const banner = new T.Mesh(new T.BoxGeometry(17, .9, .3), new T.MeshBasicMaterial({ color: 0xe54a27 }));
        banner.position.copy(p);
        banner.position.y += 4;
        scene.add(banner);
    }
} }
function makeCar() { const root = new T.Group(); const body = new T.Mesh(new T.BoxGeometry(3.5, 1, 6.4), new T.MeshLambertMaterial({ color: 0xd52f25 })); body.position.y = 1.15; body.castShadow = true; root.add(body); const cabin = new T.Mesh(new T.BoxGeometry(2.8, .9, 2.8), new T.MeshLambertMaterial({ color: 0x153343 })); cabin.position.set(0, 1.9, -.35); root.add(cabin); const spoiler = new T.Mesh(new T.BoxGeometry(3.4, .22, .55), new T.MeshLambertMaterial({ color: 0x222222 })); spoiler.position.set(0, 2.15, 2.6); root.add(spoiler); for (const x of [-1.65, 1.65])
    for (const z of [-2.1, 2.1]) {
        const wh = new T.Mesh(new T.CylinderGeometry(.72, .72, .45, 10), new T.MeshLambertMaterial({ color: 0x171717 }));
        wh.rotation.z = Math.PI / 2;
        wh.position.set(x, .7, z);
        root.add(wh);
    } for (const x of [-1.1, 1.1]) {
    let light = new T.Mesh(new T.BoxGeometry(.5, .28, .12), new T.MeshBasicMaterial({ color: 0xff3020 }));
    light.position.set(x, 1.2, 3.25);
    root.add(light);
} return root; }
function pointAt(t) { const f = ((t % samples) + samples) % samples; const i = Math.floor(f), u = f - i, a = roadPts[i], b = roadPts[(i + 1) % samples]; return a.clone().lerp(b, u); }
function reset() { running = false; finished = false; paused = false; speed = 0; s = 3; lateral = 0; laps = 1; nextGate = 1; best = 0; $('finish').classList.add('hidden'); $('pause').classList.add('hidden'); $('start').style.display = 'flex'; $('status').style.opacity = '0'; }
function begin() { $('start').style.display = 'none'; running = true; startedAt = performance.now(); lapStart = startedAt; let n = 3; const tick = () => { if (!running)
    return; if (n > 0) {
    $('status').textContent = String(n);
    beep(440, .12);
    n--;
    setTimeout(tick, 850);
}
else {
    $('status').textContent = 'GO!';
    beep(760, .18);
    setTimeout(() => $('status').style.opacity = '0', 500);
} $('status').style.opacity = '1'; }; tick(); }
function beep(freq, d) { try {
    const ac = new AudioContext(), o = ac.createOscillator(), g = ac.createGain();
    o.frequency.value = freq;
    g.gain.value = .05;
    o.connect(g);
    g.connect(ac.destination);
    o.start();
    o.stop(ac.currentTime + d);
}
catch (e) { } }
function loop(now) { const dt = Math.min(.04, (now - last) / 1000); last = now; if (running && !paused && !finished)
    update(dt, now); renderer.render(scene, camera); requestAnimationFrame(loop); }
function update(dt, now) {
    const up = keys.w || keys.arrowup || keys.up, down = keys.s || keys.arrowdown || keys.down, turn = (keys.a || keys.arrowleft || keys.left ? -1 : 0) + (keys.d || keys.arrowright || keys.right ? 1 : 0);
    const off = Math.abs(lateral) > 7.3;
    let max = off ? 25 : 62;
    if (up)
        speed += 30 * dt;
    if (down)
        speed -= 38 * dt;
    if (!up && !down)
        speed *= 1 - 1.1 * dt;
    if (keys.space)
        speed *= 1 - 1.6 * dt;
    speed = Math.max(-12, Math.min(max, speed));
    lateral += turn * speed * dt * (keys.space ? 1.2 : .55);
    lateral *= 1 - dt * (off ? 1.2 : 3.5);
    s += speed * dt;
    const p = pointAt(s), ahead = pointAt(s + 1), dir = ahead.clone().sub(p).normalize(), side = new T.Vector3(-dir.z, 0, dir.x);
    car.position.copy(p).addScaledVector(side, lateral);
    car.position.y += .55;
    const targetYaw = Math.atan2(dir.x, dir.z) + (turn * .12);
    yaw += (targetYaw - yaw) * Math.min(1, dt * 7);
    car.rotation.y = yaw;
    if (off && speed > 20)
        car.position.y += Math.sin(now * .025) * .05;
    const g = Math.max(1, Math.min(5, Math.floor(Math.abs(speed) / 13) + 1));
    $('speednum').textContent = String(Math.round(Math.abs(speed) * 3.6)).padStart(3, '0');
    $('gear').textContent = String(g);
    $('rpm').style.width = Math.min(100, 20 + Math.abs(speed) / max * 78) + '%';
    const gate = Math.floor(((s % samples) + samples) % samples / (samples / gates));
    if (gate === nextGate) {
        nextGate = (nextGate + 1) % gates;
        if (nextGate === 0) {
            const lt = now - lapStart;
            best = !best || lt < best ? lt : best;
            laps++;
            lapStart = now;
            if (laps > 3) {
                finished = true;
                const total = now - startedAt;
                $('result').innerHTML = 'FINAL TIME <b>' + fmt(total) + '</b><br>BEST LAP <b>' + fmt(best) + '</b>';
                $('finish').classList.remove('hidden');
                beep(880, .5);
            }
        }
    }
    $('lap').innerHTML = Math.min(laps, 3) + ' <i>/ 3</i>';
    $('time').textContent = fmt(now - startedAt);
    $('best').textContent = best ? fmt(best) : '--:--.---';
    let desired = cinematic ? car.position.clone().add(new T.Vector3(0, 28, 25)) : car.position.clone().addScaledVector(dir, -16).add(new T.Vector3(0, 7, 0));
    camPos.lerp(desired, dt * 3);
    camera.position.copy(camPos);
    camera.lookAt(car.position.clone().addScaledVector(dir, 10).add(new T.Vector3(0, 2, 0)));
    drawMap();
}
function fmt(ms) { const m = Math.floor(ms / 60000), sec = ((ms % 60000) / 1000).toFixed(3).padStart(6, '0'); return String(m).padStart(2, '0') + ':' + sec; }
function drawMap() { mx.clearRect(0, 0, 180, 130); mx.strokeStyle = '#678d83'; mx.lineWidth = 8; mx.lineJoin = 'round'; mx.beginPath(); roadPts.forEach((p, i) => { let x = 90 + p.x * .65, y = 65 + p.z * .48; i ? mx.lineTo(x, y) : mx.moveTo(x, y); }); mx.closePath(); mx.stroke(); mx.strokeStyle = '#f0c45c'; mx.lineWidth = 2; mx.stroke(); const p = pointAt(s); mx.fillStyle = '#ff3f27'; mx.beginPath(); mx.arc(90 + p.x * .65, 65 + p.z * .48, 4, 0, 7); mx.fill(); }
init();
};

// ── types: globals.d.ts ──
__mods["globals.d.ts"] = function (exports) {};

// ── entry ──
__require("src/main.ts");
})();
</script>
</body>
</html>
<!-- agent-meta {"model":"openai/gpt-5.6-terra","provider":"openrouter","persona":"typescript","sessionId":"bd4015c9-d9d7-4be9-bcd4-38a234ee7e3a","tokensIn":140760,"tokensOut":5706,"tokensTotal":146466,"turns":17,"toolCalls":16,"failedToolCalls":0,"timestamp":"2026-07-31T18:14:11.780Z"} -->