DOOM
GPT 5.6 terra · typescript

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 14,809 bytes · SHA-256 e636a4328f5c
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Iron Vault // Retro FPS</title>
<style>
/* ── css: ui ── */
*{box-sizing:border-box}html,body,#game{margin:0;width:100%;height:100%;overflow:hidden;background:#05070c;color:#d9f7e8;font-family:monospace}#screen{width:100%;height:100%;display:block;cursor:crosshair;image-rendering:pixelated}#scanlines{pointer-events:none;position:fixed;inset:0;background:repeating-linear-gradient(0deg,rgba(0,0,0,.13) 0 1px,transparent 1px 4px);mix-blend-mode:multiply;z-index:3}#crosshair{position:fixed;left:50%;top:50%;transform:translate(-50%,-50%);font-size:28px;line-height:20px;color:#e9ffe0;text-shadow:0 0 8px #b4ffbc;z-index:4;pointer-events:none}#hud{position:fixed;z-index:5;bottom:27px;left:28px;right:28px;display:flex;align-items:end;justify-content:space-between;pointer-events:none}.hud-card{border:2px solid #65cf80;background:rgba(3,15,16,.82);padding:7px 12px;min-width:116px;box-shadow:0 0 12px #27aa6955,inset 0 0 12px #073c2b}.hud-card.right{text-align:right}.hud-card.weapon{text-align:center;min-width:230px}.label{display:block;font-size:10px;color:#78ad88;letter-spacing:2px;margin-bottom:2px}b{font-size:22px;color:#f5ffd0;text-shadow:0 0 7px #bfff90}.weapon b{color:#6dffc2;font-size:16px}#weaponbar{position:fixed;z-index:5;top:20px;left:50%;transform:translateX(-50%);display:flex;gap:5px}.slot{font-size:11px;letter-spacing:1px;color:#668477;background:#061711d9;border:1px solid #315848;padding:6px 9px}.slot i{font-style:normal;color:#d3e5a1;margin-right:5px}.slot.active{color:#eaffc8;border-color:#8fff78;box-shadow:0 0 8px #5bff8566}#prompt,#message{position:fixed;z-index:10;left:50%;transform:translateX(-50%);text-align:center;letter-spacing:2px;background:#07140eda;border:2px solid #7be178;padding:15px 22px;color:#eaffca;text-shadow:0 0 8px #9bff83;box-shadow:0 0 28px #36a56c55}#prompt{top:50%;transform:translate(-50%,-50%);font-size:17px}#prompt small{display:block;color:#86af8c;font-size:10px;margin-top:11px;letter-spacing:1px}#message{top:14%;display:none;font-size:19px}.hurt{animation:flash .25s}@keyframes flash{0%,100%{filter:none}50%{filter:brightness(2) sepia(1) hue-rotate(310deg)}}#minimap{position:fixed;z-index:5;top:20px;right:20px;width:130px;height:130px;border:2px solid #355d51;background:rgba(2,10,11,.7);pointer-events:none}
</style>
</head>
<body>
<div id="game"><canvas id="screen"></canvas><div id="scanlines"></div><div id="crosshair">+</div><div id="hud"><div class="hud-card"><span class="label">HP</span><b id="health">100</b></div><div class="hud-card weapon"><span class="label">ARMAMENT</span><b id="weaponName">SIDEARM</b></div><div class="hud-card right"><span class="label">AMMO</span><b id="ammo">12 / ∞</b></div></div><div id="weaponbar"><div class="slot active" data-w="0"><i>1</i> SIDEARM</div><div class="slot" data-w="1"><i>2</i> SHREDDER</div><div class="slot" data-w="2"><i>3</i> PLASMA ARC</div></div><div id="prompt">CLICK TO ENTER THE IRON VAULT<br><small>WASD MOVE · MOUSE AIM · 1–3 SWITCH · CLICK FIRE</small></div><div id="message"></div><canvas id="minimap" width="130" height="130"></canvas></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 canvas = document.querySelector('#screen');
const ctx = canvas.getContext('2d');
const hpEl = document.querySelector('#health'), ammoEl = document.querySelector('#ammo'), weaponEl = document.querySelector('#weaponName'), prompt = document.querySelector('#prompt'), msg = document.querySelector('#message'), mini = document.querySelector('#minimap');
const W = 400, H = 225;
canvas.width = W;
canvas.height = H;
const map = ["1111111111111111", "1000000000000001", "1011110111111101", "1010000100000101", "1010111101110101", "1000100001010001", "1110101111010111", "1000101000010001", "1011101011111101", "1010001000000001", "1010111110111101", "1000000000100001", "1011111111101101", "1000000000000001", "1111111111111111"];
const MW = 16, MH = 15;
let px = 1.6, py = 1.6, pa = 0;
let health = 100, weapon = 0, firing = 0, playing = false, won = false, time = 0;
const weapons = [{ name: 'SIDEARM', ammo: Infinity, rate: 250, damage: 28, color: '#dcebb7' }, { name: 'SHREDDER', ammo: 32, rate: 105, damage: 13, color: '#ffe06d' }, { name: 'PLASMA ARC', ammo: 14, rate: 480, damage: 76, color: '#66f5ff' }];
const things = [{ x: 5.5, y: 1.5, hp: 52, alive: true, kind: 'enemy', cool: 0 }, { x: 11.5, y: 3.5, hp: 60, alive: true, kind: 'enemy', cool: 0 }, { x: 3.5, y: 7.5, hp: 58, alive: true, kind: 'enemy', cool: 0 }, { x: 8.5, y: 9.5, hp: 70, alive: true, kind: 'enemy', cool: 0 }, { x: 13.5, y: 12.5, hp: 82, alive: true, kind: 'enemy', cool: 0 }, { x: 6.5, y: 5.5, hp: 0, alive: true, kind: 'ammo', cool: 0 }, { x: 12.5, y: 9.5, hp: 0, alive: true, kind: 'health', cool: 0 }, { x: 2.5, y: 13.2, hp: 0, alive: true, kind: 'exit', cool: 0 }];
const keys = new Set();
document.addEventListener('keydown', e => { keys.add(e.key.toLowerCase()); if (['1', '2', '3'].includes(e.key)) {
weapon = +e.key - 1;
updateHUD();
} if (e.key.toLowerCase() === 'r' && !playing)
respawn(); });
document.addEventListener('keyup', e => keys.delete(e.key.toLowerCase()));
canvas.addEventListener('click', () => { if (!playing) {
if (won)
restart();
else {
playing = true;
prompt.style.display = 'none';
canvas.requestPointerLock();
}
}
else
shoot(); });
document.addEventListener('mousemove', e => { if (document.pointerLockElement === canvas && playing)
pa += e.movementX * .0028; });
function solid(x, y) { return map[Math.floor(y)]?.[Math.floor(x)] === '1'; }
function dist(x, y) { return Math.hypot(x - px, y - py); }
function updateHUD() { hpEl.textContent = String(Math.max(0, health)); const w = weapons[weapon]; weaponEl.textContent = w.name; ammoEl.textContent = w.ammo === Infinity ? '∞' : `${w.ammo} / ${weapon === 1 ? '32' : '14'}`; document.querySelectorAll('.slot').forEach((s, i) => s.classList.toggle('active', i === weapon)); }
function say(t) { msg.textContent = t; msg.style.display = 'block'; setTimeout(() => msg.style.display = 'none', 1700); }
function shoot() { const w = weapons[weapon]; if (time - firing < w.rate)
return; if (w.ammo <= 0) {
say('NO CHARGE');
return;
} firing = time; if (w.ammo !== Infinity)
w.ammo--; updateHUD(); let target, best = .16; for (const e of things)
if (e.kind === 'enemy' && e.alive) {
let a = Math.atan2(e.y - py, e.x - px) - pa;
a = Math.atan2(Math.sin(a), Math.cos(a));
const d = dist(e.x, e.y);
if (Math.abs(a) < best / d && d < 9) {
best = Math.abs(a) * d;
target = e;
}
} if (target) {
target.hp -= w.damage;
if (target.hp <= 0) {
target.alive = false;
say('HOSTILE NEUTRALIZED');
}
} }
function respawn() { health = 100; px = 1.6; py = 1.6; pa = 0; playing = true; won = false; prompt.style.display = 'none'; updateHUD(); canvas.requestPointerLock(); }
function restart() { for (const t of things) {
t.alive = true;
if (t.kind === 'enemy') {
const start = [52, 60, 58, 70, 82];
t.hp = start[things.filter(q => q.kind === 'enemy').indexOf(t)] || 60;
t.cool = 0;
}
} weapons[1].ammo = 32; weapons[2].ammo = 14; respawn(); }
function tick(dt) {
time += dt;
if (!playing)
return;
let mx = 0, my = 0;
const sp = dt * .003;
if (keys.has('w')) {
mx = Math.cos(pa) * sp;
my = Math.sin(pa) * sp;
}
if (keys.has('s')) {
mx = -Math.cos(pa) * sp;
my = -Math.sin(pa) * sp;
}
if (keys.has('a')) {
mx = Math.cos(pa - Math.PI / 2) * sp;
my = Math.sin(pa - Math.PI / 2) * sp;
}
if (keys.has('d')) {
mx = Math.cos(pa + Math.PI / 2) * sp;
my = Math.sin(pa + Math.PI / 2) * sp;
}
if (!solid(px + mx * .8, py))
px += mx;
if (!solid(px, py + my * .8))
py += my;
for (const t of things)
if (t.alive) {
const d = dist(t.x, t.y);
if (t.kind === 'enemy' && d < 5) {
t.cool -= dt;
if (t.cool <= 0 && d < 3.6) {
health -= 7;
t.cool = 820;
document.body.classList.add('hurt');
setTimeout(() => document.body.classList.remove('hurt'), 180);
updateHUD();
}
}
else if (t.kind === 'ammo' && d < .65) {
weapons[1].ammo = Math.min(32, weapons[1].ammo + 16);
weapons[2].ammo = Math.min(14, weapons[2].ammo + 5);
t.alive = false;
say('MUNITIONS ACQUIRED');
updateHUD();
}
else if (t.kind === 'health' && d < .65) {
health = Math.min(100, health + 35);
t.alive = false;
say('MEDKIT +35');
updateHUD();
}
else if (t.kind === 'exit' && d < .7) {
if (things.filter(q => q.kind === 'enemy' && q.alive).length === 0) {
won = true;
playing = false;
prompt.innerHTML = 'VAULT SECURED<br><small>THE IRON VAULT IS SILENT. CLICK TO RUN AGAIN</small>';
prompt.style.display = 'block';
say('MISSION COMPLETE');
}
else
say('PURGE ALL HOSTILES');
}
}
if (health <= 0) {
playing = false;
document.exitPointerLock();
prompt.innerHTML = 'SYSTEM FAILURE<br><small>PRESS R TO REDEPLOY</small>';
prompt.style.display = 'block';
}
}
function ray(a) { let d = 0; while (d < 16) {
d += .025;
if (solid(px + Math.cos(a) * d, py + Math.sin(a) * d))
return d;
} return 16; }
function render() {
const sky = ctx.createLinearGradient(0, 0, 0, H / 2);
sky.addColorStop(0, '#112b38');
sky.addColorStop(1, '#26343a');
ctx.fillStyle = sky;
ctx.fillRect(0, 0, W, H / 2);
ctx.fillStyle = '#172016';
ctx.fillRect(0, H / 2, W, H / 2);
const depth = [];
for (let x = 0; x < W; x += 2) {
let a = pa + (x / W - .5) * 1.12, d = ray(a) * Math.cos(a - pa);
depth[x] = d;
const wh = Math.min(H, 105 / d);
const shade = Math.max(12, 105 - d * 10);
ctx.fillStyle = `rgb(${Math.floor(shade * .35)},${Math.floor(shade * .95)},${Math.floor(shade * .62)})`;
ctx.fillRect(x, H / 2 - wh / 2, 2, wh);
ctx.fillStyle = 'rgba(0,0,0,.18)';
ctx.fillRect(x, H / 2 + wh / 2 - 2, 2, 2);
}
const sprites = things.filter(t => t.alive).sort((a, b) => dist(b.x, b.y) - dist(a.x, a.y));
for (const t of sprites) {
let dx = t.x - px, dy = t.y - py, d = Math.hypot(dx, dy), a = Math.atan2(dy, dx) - pa;
a = Math.atan2(Math.sin(a), Math.cos(a));
if (Math.abs(a) > .7)
continue;
let sx = W / 2 + (a / .56) * W / 2, size = Math.min(170, 92 / d);
if (depth[Math.max(0, Math.min(W - 1, Math.floor(sx)))] < d - .15)
continue;
let y = H / 2 + size * .14;
if (t.kind === 'enemy') {
ctx.fillStyle = '#381827';
ctx.fillRect(sx - size * .22, y - size * .48, size * .44, size * .75);
ctx.fillStyle = '#e24a54';
ctx.fillRect(sx - size * .18, y - size * .43, size * .36, size * .25);
ctx.fillStyle = '#f7c56b';
ctx.fillRect(sx - size * .11, y - size * .36, size * .07, size * .06);
ctx.fillRect(sx + size * .05, y - size * .36, size * .07, size * .06);
ctx.fillStyle = '#9e2632';
ctx.fillRect(sx - size * .34, y - size * .2, size * .14, size * .4);
ctx.fillRect(sx + size * .2, y - size * .2, size * .14, size * .4);
}
else {
ctx.fillStyle = t.kind === 'health' ? '#74ff83' : t.kind === 'ammo' ? '#ffd85b' : '#50e7ff';
ctx.fillRect(sx - size * .25, y - size * .25, size * .5, size * .5);
ctx.strokeStyle = '#eaffd3';
ctx.strokeRect(sx - size * .25, y - size * .25, size * .5, size * .5);
if (t.kind === 'exit') {
ctx.fillStyle = '#06131b';
ctx.fillRect(sx - size * .14, y - size * .2, size * .28, size * .4);
}
}
}
// weapon
const wc = weapons[weapon].color;
ctx.fillStyle = '#101a1d';
ctx.fillRect(W * .38, H * .84, W * .24, H * .2);
ctx.fillStyle = wc;
ctx.fillRect(W * .46, H * .76, W * .08, H * .16);
ctx.fillStyle = '#243c38';
ctx.fillRect(W * .42, H * .86, W * .16, H * .08);
if (time - firing < 80) {
ctx.fillStyle = '#fff3b0';
ctx.beginPath();
ctx.arc(W * .5, H * .75, 15, 0, 7);
ctx.fill();
}
drawMap();
}
function drawMap() { const m = mini.getContext?.('2d'); if (!m)
return; mini.width = 130; mini.height = 130; m.clearRect(0, 0, 130, 130); let s = 8; m.fillStyle = '#16342e'; for (let y = 0; y < MH; y++)
for (let x = 0; x < MW; x++)
if (map[y][x] === '1')
m.fillRect(x * s, y * s, s, s); for (const e of things)
if (e.alive && e.kind === 'enemy') {
m.fillStyle = '#ed5a62';
m.fillRect(e.x * s - 2, e.y * s - 2, 4, 4);
} m.fillStyle = '#d9ff9a'; m.beginPath(); m.arc(px * s, py * s, 3, 0, 7); m.fill(); m.strokeStyle = '#d9ff9a'; m.beginPath(); m.moveTo(px * s, py * s); m.lineTo((px + Math.cos(pa)) * s, (py + Math.sin(pa)) * s); m.stroke(); }
let last = performance.now();
function loop(n) { let dt = Math.min(40, n - last); last = n; tick(dt); render(); requestAnimationFrame(loop); }
updateHUD();
requestAnimationFrame(loop);
};
// ── entry ──
__require("src/main.ts");
})();
</script>
</body>
</html>
<!-- agent-meta {"model":"openai/gpt-5.6-terra","provider":"openrouter","persona":"typescript","sessionId":"292a84c8-9fce-43ff-8f3f-91e9f8c328fe","tokensIn":116844,"tokensOut":5065,"tokensTotal":121909,"turns":16,"toolCalls":16,"failedToolCalls":1,"timestamp":"2026-07-31T17:43:23.159Z"} -->