← RPG results

RPG

GPT 5.6 terra Pro · full

Initial view of RPG

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 19,077 bytes · SHA-256 81809d309e33
<!doctype html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Emberfall: Pocket Adventure</title><style>
:root{--ink:#172333;--panel:#f5e9cb;--gold:#f4bd45;--red:#e8554f;--mint:#62c7aa;--blue:#4e94c7}*{box-sizing:border-box}body{margin:0;background:#0f1721;color:var(--ink);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;overflow:hidden}#game{display:block;width:100vw;height:100vh;image-rendering:pixelated;background:#1c4450}.hud{position:fixed;z-index:3;pointer-events:none}.top{top:16px;left:18px;display:flex;gap:14px;align-items:center}.badge{background:rgba(255,248,223,.92);border:3px solid #172333;border-radius:9px;box-shadow:4px 4px 0 rgba(0,0,0,.28);padding:7px 10px;font-weight:800;font-size:13px}.hearts{letter-spacing:3px;color:var(--red);font-size:20px;text-shadow:1px 1px #172333}.right{top:16px;right:18px;text-align:right}.quest{max-width:315px;line-height:1.45}.hint{bottom:14px;left:50%;transform:translateX(-50%);background:rgba(23,35,51,.86);color:#fff7dd;border:2px solid #f5e9cb;border-radius:8px;padding:9px 15px;font-size:12px;transition:.2s}.toast{bottom:66px;left:50%;transform:translateX(-50%);background:#f4bd45;border:3px solid #172333;border-radius:8px;padding:9px 15px;font-weight:900;opacity:0;transition:.25s}.toast.show{opacity:1}.modal{position:fixed;z-index:5;inset:0;background:rgba(8,14,20,.66);display:none;align-items:center;justify-content:center}.modal.open{display:flex}.paper{width:min(560px,90vw);max-height:85vh;overflow:auto;background:var(--panel);border:5px solid var(--ink);border-radius:12px;box-shadow:10px 10px 0 rgba(0,0,0,.35);padding:22px}.paper h1{margin:0 0 6px;font-size:24px}.paper p{line-height:1.5}.grid{display:grid;grid-template-columns:repeat(2,1fr);gap:9px}.item{border:2px solid #253a45;background:#fff8e4;padding:10px;min-height:62px}.item.locked{opacity:.38;filter:grayscale(1)}.item b{display:block}.close{float:right;background:#172333;color:white;border:0;padding:7px 10px;font:inherit;cursor:pointer}.shoprow{display:flex;align-items:center;justify-content:space-between;border-top:2px dashed #b39a69;padding:12px 0;gap:10px}.buy{background:#e8554f;color:#fff;border:2px solid #172333;border-radius:5px;padding:7px 10px;font:inherit;font-weight:bold;cursor:pointer}.buy:disabled{opacity:.35}.legend{font-size:12px;color:#4c5963}.titlecard{position:fixed;inset:0;z-index:8;background:#132934;display:flex;align-items:center;justify-content:center;color:#fff7dd}.titlecard.hidden{display:none}.titlebox{text-align:center;border:4px solid #f4bd45;padding:34px;background:#1b3d45;box-shadow:9px 9px 0 #080e14;max-width:570px;margin:20px}.titlebox h1{font-size:42px;margin:0;color:#f4bd45;text-shadow:3px 3px #b94d42}.titlebox p{line-height:1.6}.start{margin-top:10px;background:#f4bd45;border:3px solid #fff7dd;padding:13px 20px;font:bold 16px inherit;cursor:pointer;color:#172333}@media(max-width:620px){.top{top:8px;left:8px}.right{top:8px;right:8px}.badge{padding:5px;font-size:10px}.hearts{font-size:15px}.quest{display:none}.hint{font-size:10px;white-space:nowrap}.titlebox h1{font-size:30px}}
</style></head><body>
<canvas id="game"></canvas>
<div class="hud top"><div class="badge"><span class="hearts" id="hearts"></span><br><span id="hpText"></span></div><div class="badge">✦ <span id="coins">0</span></div></div>
<div class="hud right"><div class="badge quest" id="quest">Awaken at the Mossgate Shrine.</div><div class="badge" style="margin-top:8px">⚔ <span id="weaponName">Rustblade</span> · <span id="bowName">No bow</span></div></div>
<div class="hud hint" id="hint">WASD / arrows to explore · SPACE attack · E interact · I inventory</div><div class="hud toast" id="toast"></div>
<div class="modal" id="inventory"><div class="paper"><button class="close" onclick="toggleInventory()">ESC</button><h1>Field Satchel</h1><p class="legend">Equipment changes your silhouette. Accessories are passive and always active.</p><div class="grid" id="invGrid"></div></div></div>
<div class="modal" id="shop"><div class="paper"><button class="close" onclick="closeShop()">ESC</button><h1>Fern & Flint Outfitters</h1><p>“Fine finds for brave wayfarers.” Your purse: <b>✦ <span id="shopCoins"></span></b></p><div id="shopItems"></div></div></div>
<div class="titlecard" id="title"><div class="titlebox"><h1>EMBERFALL</h1><h2>the Mossgate Trail</h2><p>A compact action-adventure: explore the wilds, uncover two forge upgrades, earn five heart containers, and find the bow beyond the sealed pass.</p><p class="legend" style="color:#d5e7d1">Controls: move WASD / arrows · attack SPACE · interact E · inventory I</p><button class="start" onclick="begin()">BEGIN THE TRAIL</button></div></div>
<script>
const canvas=document.getElementById('game'),ctx=canvas.getContext('2d');let W,H,scale=1;
function resize(){W=canvas.width=innerWidth*devicePixelRatio;H=canvas.height=innerHeight*devicePixelRatio;ctx.setTransform(devicePixelRatio,0,0,devicePixelRatio,0,0);scale=Math.min(innerWidth/900,innerHeight/600)}addEventListener('resize',resize);resize();
const keys={};let started=false,last=0,elapsed=0,toastTimer=0,shake=0;
const player={x:145,y:355,r:13,dir:0,hp:6,max:6,coins:12,weapon:0,bow:false,attack:0,inv:[],speed:155,iframes:0,checkpoint:{x:145,y:355},walk:0};
const weapons=[{name:'Rustblade',dmg:1,range:42,cd:.42,color:'#cbd5ca'},{name:'Sunsteel Saber',dmg:2,range:58,cd:.32,color:'#f4bd45'},{name:'Thornbrand',dmg:3,range:76,cd:.52,color:'#d85560'}];
let cooldown=0,progress=0,gateOpen=false,particles=[],slashes=[],projectiles=[];
const walls=[{x:0,y:0,w:900,h:55},{x:0,y:545,w:900,h:55},{x:0,y:0,w:55,h:600},{x:845,y:0,w:55,h:600},{x:260,y:55,w:30,h:280},{x:260,y:405,w:30,h:140},{x:530,y:55,w:30,h:155},{x:530,y:290,w:30,h:255},{x:700,y:55,w:25,h:170},{x:700,y:290,w:25,h:255}];
const enemies=[{x:190,y:160,hp:3,max:3,type:'mossling',coin:5},{x:420,y:145,hp:4,max:4,type:'mossling',coin:7},{x:436,y:427,hp:5,max:5,type:'bramble',coin:9},{x:650,y:165,hp:5,max:5,type:'bramble',coin:10},{x:775,y:410,hp:8,max:8,type:'warden',coin:18,boss:true}];
const pickups=[{x:155,y:210,type:'coin',value:6},{x:188,y:455,type:'item',name:'Moss Tonic',desc:'Restores 2 hearts when found.',use:'heal'},{x:345,y:430,type:'coin',value:9},{x:390,y:245,type:'upgrade',name:'Sunsteel Saber',desc:'Forge upgrade I — wider, faster strikes.'},{x:480,y:485,type:'heart',name:'Heart Container',desc:'A fourth heart container.'},{x:610,y:350,type:'item',name:'Trail Boots',desc:'+15% movement speed.',use:'boots'},{x:640,y:100,type:'coin',value:12},{x:770,y:155,type:'bow',name:'Willow Bow',desc:'Mid-trail discovery — press F to fire.'},{x:770,y:265,type:'item',name:'Moonleaf Charm',desc:'Damage taken is softened.',use:'charm'},{x:785,y:475,type:'upgrade',name:'Thornbrand',desc:'Forge upgrade II — long, crushing arcs.'},{x:735,y:335,type:'heart',name:'Heart Container',desc:'A fifth heart container.'}];
const saves=[{x:115,y:110,active:true},{x:600,y:470,active:false}];
const shopStock=[{name:'Lantern Oil',price:15,desc:'A warm glow that reveals hidden paths.'},{name:'Iron Buckler',price:25,desc:'Reduces incoming damage.'},{name:'Berry Ration',price:10,desc:'Restores 2 hearts.'}];let bought=[];
function rectHit(x,y,r,w){return x+r>w.x&&x-r<w.x+w.w&&y+r>w.y&&y-r<w.y+w.h}
function collides(x,y){return walls.some(w=>rectHit(x,y,player.r,w))||(gateOpen?false: x+player.r>530&&x-player.r<560&&y>210&&y<290)}
function particle(x,y,color,n=9){for(let i=0;i<n;i++)particles.push({x,y,vx:(Math.random()-.5)*145,vy:(Math.random()-.5)*145,life:.45+Math.random()*.35,color})}
function sound(kind){try{const ac=window._ac||(window._ac=new AudioContext()),o=ac.createOscillator(),g=ac.createGain();let f={walk:110,attack:260,damage:80,pickup:650,shop:420,shoot:520,save:330}[kind]||300;o.frequency.value=f;o.type=kind==='damage'?'sawtooth':'triangle';g.gain.setValueAtTime(kind==='walk'?.018:.055,ac.currentTime);g.gain.exponentialRampToValueAtTime(.001,ac.currentTime+.12);o.connect(g);g.connect(ac.destination);o.start();o.stop(ac.currentTime+.13)}catch(e){}}
function message(s){const el=document.getElementById('toast');el.textContent=s;el.classList.add('show');toastTimer=2.3}
function addItem(name,desc){if(!player.inv.some(i=>i.name===name))player.inv.push({name,desc});}
function updateHud(){let hearts='';for(let i=0;i<player.max/2;i++)hearts+=player.hp>=i*2+2?'♥':player.hp===i*2+1?'♡':'♡';document.getElementById('hearts').textContent=hearts;document.getElementById('hpText').textContent=`${player.hp} / ${player.max} vitality`;document.getElementById('coins').textContent=player.coins;document.getElementById('weaponName').textContent=weapons[player.weapon].name;document.getElementById('bowName').textContent=player.bow?'Willow Bow':'No bow';}
function objective(){let q=!gateOpen?'Find the Sunsteel Saber to cut the thorn gate.':!player.bow?'Beyond the pass: seek a ranged weapon.':player.weapon<2?'Defeat the Briar Warden and claim Thornbrand.':player.max<10?'Find the final heart container near the warden.':'The trail is restored — explore and stock up.';document.getElementById('quest').textContent=q;}
function begin(){document.getElementById('title').classList.add('hidden');started=true;sound('pickup');}
function move(dt){let dx=(keys.d||keys.ArrowRight?1:0)-(keys.a||keys.ArrowLeft?1:0),dy=(keys.s||keys.ArrowDown?1:0)-(keys.w||keys.ArrowUp?1:0);if(dx||dy){let l=Math.hypot(dx,dy);dx/=l;dy/=l;player.dir=Math.atan2(dy,dx);let sp=player.speed*(player.inv.some(i=>i.name==='Trail Boots')?1.15:1);let nx=player.x+dx*sp*dt,ny=player.y+dy*sp*dt;if(!collides(nx,player.y))player.x=nx;if(!collides(player.x,ny))player.y=ny;player.walk+=dt*10;if(Math.floor(player.walk)%5===0&&Math.random()<.15)sound('walk')}}
function attack(){if(cooldown>0)return;cooldown=weapons[player.weapon].cd;player.attack=.16;let w=weapons[player.weapon];slashes.push({x:player.x,y:player.y,a:player.dir,r:w.range,life:.16,color:w.color});sound('attack');for(const e of enemies){if(e.hp<=0)continue;let d=Math.hypot(e.x-player.x,e.y-player.y),a=Math.atan2(e.y-player.y,e.x-player.x),dif=Math.abs(Math.atan2(Math.sin(a-player.dir),Math.cos(a-player.dir)));if(d<w.range+20&&dif<1.2){e.hp-=w.dmg;particle(e.x,e.y,w.color,10);if(e.hp<=0){player.coins+=e.coin;progress++;particle(e.x,e.y,'#f4bd45',18);message(`Enemy cleared! +${e.coin} ✦`);sound('pickup')}}}}
function shoot(){if(!player.bow||cooldown>.05)return;cooldown=.28;projectiles.push({x:player.x,y:player.y,vx:Math.cos(player.dir)*390,vy:Math.sin(player.dir)*390,life:1.3});sound('shoot')}
function hurt(){if(player.iframes>0)return;let dmg=player.inv.some(i=>i.name==='Iron Buckler')?1:player.inv.some(i=>i.name==='Moonleaf Charm')?1:2;player.hp-=dmg;player.iframes=1;shake=.2;particle(player.x,player.y,'#e8554f',13);sound('damage');if(player.hp<=0){player.hp=Math.max(2,player.max-2);player.x=player.checkpoint.x;player.y=player.checkpoint.y;message('Felled — returned to your marked shrine.')}}
function interact(){let sv=saves.find(s=>Math.hypot(s.x-player.x,s.y-player.y)<34);if(sv){saves.forEach(s=>s.active=false);sv.active=true;player.checkpoint={x:sv.x,y:sv.y};player.hp=player.max;particle(sv.x,sv.y,'#62c7aa',20);message('Trail marked. Vitality restored.');sound('save');return}if(Math.hypot(player.x-155,player.y-500)<55){openShop();return}message('Nothing to use here.');}
function collect(){for(let i=pickups.length-1;i>=0;i--){let p=pickups[i];if(Math.hypot(p.x-player.x,p.y-player.y)<26){if(p.type==='upgrade'){if(p.name==='Sunsteel Saber'){player.weapon=1;gateOpen=true}else if(progress<4){message('The thorn forge stirs: defeat more foes first.');continue}else player.weapon=2}else if(p.type==='heart'){player.max+=2;player.hp=Math.min(player.max,player.hp+2);addItem(p.name,p.desc)}else if(p.type==='coin')player.coins+=p.value;else if(p.type==='bow'){player.bow=true;addItem(p.name,p.desc)}else {addItem(p.name,p.desc);if(p.use==='heal')player.hp=Math.min(player.max,player.hp+2);if(p.use==='boots')player.speed=155}particle(p.x,p.y,p.type==='heart'?'#e8554f':'#f4bd45',18);sound('pickup');message(p.type==='coin'?`Found ${p.value} ✦`:`Acquired: ${p.name}`);pickups.splice(i,1)}}}
function update(dt){if(!started||document.querySelector('.modal.open'))return;elapsed+=dt;cooldown=Math.max(0,cooldown-dt);player.attack=Math.max(0,player.attack-dt);player.iframes=Math.max(0,player.iframes-dt);shake=Math.max(0,shake-dt);move(dt);collect();for(const e of enemies){if(e.hp<=0)continue;let dx=player.x-e.x,dy=player.y-e.y,d=Math.hypot(dx,dy);if(d<205){e.x+=dx/d*38*dt;e.y+=dy/d*38*dt}if(d<27)hurt()}for(let i=projectiles.length-1;i>=0;i--){let p=projectiles[i];p.x+=p.vx*dt;p.y+=p.vy*dt;p.life-=dt;for(const e of enemies)if(e.hp>0&&Math.hypot(e.x-p.x,e.y-p.y)<20){e.hp-=2;p.life=0;particle(e.x,e.y,'#9ed9dc',9);if(e.hp<=0){player.coins+=e.coin;progress++;sound('pickup')}}if(p.life<0)projectiles.splice(i,1)}for(let i=particles.length-1;i>=0;i--){let p=particles[i];p.x+=p.vx*dt;p.y+=p.vy*dt;p.vx*=.92;p.vy*=.92;p.life-=dt;if(p.life<0)particles.splice(i,1)}if(toastTimer>0){toastTimer-=dt;if(toastTimer<=0)document.getElementById('toast').classList.remove('show')}objective();updateHud()}
function draw(){let cw=innerWidth,ch=innerHeight;ctx.clearRect(0,0,cw,ch);ctx.save();let s=scale,ox=(cw-900*s)/2,oy=(ch-600*s)/2;ctx.translate(ox+(shake?Math.random()*6-3:0),oy);ctx.scale(s,s);ctx.fillStyle='#285e57';ctx.fillRect(0,0,900,600); // ground
for(let i=0;i<145;i++){let x=(i*79)%870+15,y=(i*137)%540+30;ctx.fillStyle=i%3?'#347263':'#3e8069';ctx.fillRect(x,y,3,7);ctx.fillRect(x-2,y+4,7,3)}
// area bands
ctx.fillStyle='rgba(245,213,125,.12)';ctx.fillRect(290,55,235,490);ctx.fillStyle='rgba(103,151,187,.12)';ctx.fillRect(560,55,140,490);ctx.fillStyle='rgba(206,91,82,.1)';ctx.fillRect(725,55,120,490);
for(const w of walls){ctx.fillStyle='#193c42';ctx.fillRect(w.x,w.y,w.w,w.h);ctx.fillStyle='#4c936c';ctx.fillRect(w.x+3,w.y+3,w.w-6,8)}
if(!gateOpen){ctx.fillStyle='#7f4054';ctx.fillRect(530,210,30,80);ctx.fillStyle='#d46861';for(let y=215;y<285;y+=12){ctx.fillRect(530,y,30,4)}}
// labels
ctx.font='bold 12px monospace';ctx.fillStyle='#d8edbb';ctx.fillText('MOSS GATE',80,78);ctx.fillText('SUNLIT RUINS',325,78);ctx.fillText('THE FAR TRAIL',590,78);ctx.fillText('BRIAR KEEP',745,78);
for(const spt of saves){ctx.fillStyle=spt.active?'#87efd2':'#4a9291';ctx.beginPath();ctx.arc(spt.x,spt.y,13+Math.sin(elapsed*3)*2,0,7);ctx.fill();ctx.fillStyle='#efffde';ctx.fillRect(spt.x-3,spt.y-20,6,32);ctx.fillStyle='#f4bd45';ctx.fillRect(spt.x-7,spt.y-19,14,5)}
// shop
ctx.fillStyle='#e6bc6a';ctx.fillRect(105,468,98,55);ctx.fillStyle='#b95349';ctx.fillRect(98,457,112,20);ctx.fillStyle='#172333';ctx.fillText('SHOP',129,490);
for(const p of pickups){let col={coin:'#f4bd45',upgrade:'#ed8a4d',heart:'#e8554f',bow:'#9ed9dc',item:'#c1a2dd'}[p.type];ctx.fillStyle=col;ctx.beginPath();ctx.arc(p.x,p.y,10+Math.sin(elapsed*4+p.x)*2,0,7);ctx.fill();ctx.strokeStyle='#172333';ctx.lineWidth=2;ctx.stroke();ctx.fillStyle='#172333';ctx.font='10px monospace';ctx.fillText(p.type==='coin'?'✦':p.type==='heart'?'♥':p.type==='bow'?'➶':'!',p.x-4,p.y+4)}
for(const e of enemies){if(e.hp<=0)continue;ctx.fillStyle=e.boss?'#9e3e56':e.type==='bramble'?'#76536e':'#507d54';ctx.beginPath();ctx.arc(e.x,e.y,e.boss?18:13,0,7);ctx.fill();ctx.fillStyle='#edddad';ctx.fillRect(e.x-5,e.y-2,3,3);ctx.fillRect(e.x+3,e.y-2,3,3);ctx.fillStyle='#172333';ctx.fillRect(e.x-15,e.y-23,30,4);ctx.fillStyle='#e8554f';ctx.fillRect(e.x-15,e.y-23,30*(e.hp/e.max),4)}
for(const p of projectiles){ctx.fillStyle='#d9f8ec';ctx.beginPath();ctx.arc(p.x,p.y,4,0,7);ctx.fill()}
for(const p of particles){ctx.globalAlpha=Math.max(0,p.life*2);ctx.fillStyle=p.color;ctx.fillRect(p.x-2,p.y-2,4,4)}ctx.globalAlpha=1;
for(const sl of slashes){sl.life-=1/60;ctx.strokeStyle=sl.color;ctx.lineWidth=8;ctx.beginPath();ctx.arc(sl.x,sl.y,sl.r,sl.a-.75,sl.a+.75);ctx.stroke()}slashes=slashes.filter(s=>s.life>0);
// player body/equipment
ctx.save();ctx.translate(player.x,player.y);if(player.iframes>0&&Math.floor(elapsed*14)%2)ctx.globalAlpha=.35;ctx.fillStyle='#f2c18e';ctx.beginPath();ctx.arc(0,-8,8,0,7);ctx.fill();ctx.fillStyle='#426da1';ctx.fillRect(-9,-3,18,18);ctx.fillStyle='#263c58';ctx.fillRect(-8,15,6,6);ctx.fillRect(3,15,6,6);ctx.strokeStyle=weapons[player.weapon].color;ctx.lineWidth=5;ctx.beginPath();ctx.moveTo(5,4);ctx.lineTo(Math.cos(player.dir)*25,Math.sin(player.dir)*25);ctx.stroke();if(player.bow){ctx.strokeStyle='#9ed9dc';ctx.lineWidth=3;ctx.beginPath();ctx.arc(-8,3,8,-1.4,1.4);ctx.stroke()}ctx.restore();
ctx.restore();requestAnimationFrame(loop)}
function loop(t){let dt=Math.min(.033,(t-last)/1000||0);last=t;update(dt);draw()}
function toggleInventory(){document.getElementById('inventory').classList.toggle('open');renderInv()}function renderInv(){const essentials=[{name:'Rustblade',desc:'Your starting blade.'},{name:weapons[player.weapon].name,desc:weapons[player.weapon].name==='Rustblade'?'Locked in the wild.':'Equipped main weapon.'},{name:'Thornbrand',desc:'Forge upgrade II.'},{name:'Willow Bow',desc:'Mid-game ranged weapon.'}];let all=[...essentials,...player.inv];document.getElementById('invGrid').innerHTML=all.map(i=>`<div class="item ${(i.name==='Thornbrand'&&player.weapon<2)||(i.name==='Willow Bow'&&!player.bow)?'locked':''}"><b>${i.name}</b><span class="legend">${i.desc}</span></div>`).join('')}
function openShop(){document.getElementById('shop').classList.add('open');renderShop();sound('shop')}function closeShop(){document.getElementById('shop').classList.remove('open')}function renderShop(){document.getElementById('shopCoins').textContent=player.coins;document.getElementById('shopItems').innerHTML=shopStock.map((it,i)=>`<div class="shoprow"><div><b>${it.name}</b><br><span class="legend">${it.desc}</span></div><button class="buy" ${bought.includes(i)||player.coins<it.price?'disabled':''} onclick="buy(${i})">${bought.includes(i)?'OWNED':it.price+' ✦'}</button></div>`).join('')}
function buy(i){let it=shopStock[i];if(player.coins<it.price||bought.includes(i))return;player.coins-=it.price;bought.push(i);addItem(it.name,it.desc);if(it.name==='Berry Ration')player.hp=Math.min(player.max,player.hp+2);particle(player.x,player.y,'#f4bd45',14);sound('shop');message(`Purchased ${it.name}`);renderShop()}
addEventListener('keydown',e=>{keys[e.key]=true;if(e.key===' '){e.preventDefault();attack()}if(e.key.toLowerCase()==='f')shoot();if(e.key.toLowerCase()==='e')interact();if(e.key.toLowerCase()==='i')toggleInventory();if(e.key==='Escape'){document.querySelectorAll('.modal').forEach(x=>x.classList.remove('open'))}});addEventListener('keyup',e=>keys[e.key]=false);updateHud();requestAnimationFrame(loop);
</script></body></html>
<!-- agent-meta {"model":"openai/gpt-5.6-terra-pro","provider":"openrouter","persona":"full","sessionId":"430e9ff2-1f49-4d34-a62c-46065edf9864","tokensIn":192881,"tokensOut":16372,"tokensTotal":209253,"cost":0.17727385000000004,"turns":5,"toolCalls":4,"failedToolCalls":1,"timestamp":"2026-08-01T05:46:13.218Z"} -->