Crouton Alpha HTML Coding Check: Glass Crane, Globe & Wizard Game

Three single-file HTML requests, two incomplete crane replies, and a careful look at what the final downloads do and do not prove.
Co-Founder & Lead Programmer of AcceleratedLogic AI
What was generated
| Artifact | Download size | Main dependency | What I verified |
|---|---|---|---|
| Glass sphere and crane | 7,597 bytes | None; inline SVG and CSS | Complete HTML document; source was copied without edits |
| Procedural globe | 12,947 bytes | Three.js 0.160.0 from jsDelivr | Complete HTML document; OpenRouter rendered an interactive preview, but I did not test its controls |
| Wizard island game | 19,167 bytes | Three.js 0.160.0 from jsDelivr | Complete HTML document; source includes the requested game systems, but I did not play through the game loop |
1. Glass sphere with an origami crane
<!doctype html>
<html><head><style>body{margin:0;min-height:100vh;display:grid;place-items:center;background:#0b1620}svg{width:min(97vw,1200px);height:auto;display:block}@keyframes floatY{0%,100%{transform:translateY(0)}50%{transform:translateY(-8px)}}.float{animation:floatY 5s ease-in-out infinite}</style></head><body><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 600"><defs><linearGradient id="bg" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#2b4254"/><stop offset="1" stop-color="#070d13"/></linearGradient><radialGradient id="sphere" cx=".35" cy=".28" r=".85"><stop offset="0" stop-color="#ffffff" stop-opacity=".95"/><stop offset=".25" stop-color="#dff4ff" stop-opacity=".55"/><stop offset=".55" stop-color="#9fd4ec" stop-opacity=".25"/><stop offset=".85" stop-color="#3b7ca3" stop-opacity=".35"/><stop offset="1" stop-color="#163c55" stop-opacity=".65"/></radialGradient><radialGradient id="front" cx=".34" cy=".24" r=".85"><stop offset="0" stop-color="#ffffff" stop-opacity=".32"/><stop offset=".22" stop-color="#ffffff" stop-opacity=".07"/><stop offset=".55" stop-color="#ffffff" stop-opacity="0"/><stop offset="1" stop-color="#ffffff" stop-opacity=".22"/></radialGradient><linearGradient id="rim" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#ffffff"/><stop offset=".5" stop-color="#aee7ff"/><stop offset="1" stop-color="#ffe9ba"/></linearGradient><radialGradient id="shadow" cx=".5" cy=".5" r=".5"><stop offset="0" stop-color="#000" stop-opacity=".6"/><stop offset="1" stop-color="#000" stop-opacity="0"/></radialGradient><linearGradient id="p1" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#fffdf2"/><stop offset="1" stop-color="#e7d9b6"/></linearGradient><linearGradient id="p2" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#f2e8ce"/><stop offset="1" stop-color="#c8b88f"/></linearGradient><linearGradient id="p3" x1="0" y1="0" x2=".8" y2="1"><stop offset="0" stop-color="#ddd0ab"/><stop offset="1" stop-color="#94876b"/></linearGradient><linearGradient id="pw" x1="0" y1="0" x2=".6" y2="1"><stop offset="0" stop-color="#ffffff"/><stop offset="1" stop-color="#cfc0a0"/></linearGradient><linearGradient id="pd" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#e8dfc6"/><stop offset="1" stop-color="#8f846c"/></linearGradient><filter id="blur" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="7"/></filter><filter id="blur2" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="2"/></filter><filter id="drop" x="-40%" y="-40%" width="180%" height="180%"><feDropShadow dx="7" dy="10" stdDeviation="8" flood-color="#061520" flood-opacity=".45"/></filter><filter id="refract"><feTurbulence type="fractalNoise" baseFrequency=".012 .018" numOctaves="2" seed="6" result="n"/><feDisplacementMap in="SourceGraphic" in2="n" scale="18"/></filter><clipPath id="clip"><circle cx="400" cy="280" r="200"/></clipPath><g id="crane" stroke-linejoin="round" stroke-linecap="round"><polygon points="380,272 348,142 368,132" fill="url(#pd)" stroke="#6f6653"/><polygon points="380,272 368,132 438,256" fill="url(#p2)" stroke="#6f6653"/><polygon points="368,132 388,128 438,256 420,262" fill="url(#p3)" stroke="#6f6653"/><polygon points="258,262 332,278 302,302" fill="url(#p2)" stroke="#6f6653"/><polygon points="332,278 362,296 302,302" fill="url(#p3)" stroke="#6f6653"/><polygon points="302,302 362,296 330,322" fill="url(#p1)" stroke="#6f6653"/><polygon points="258,262 296,272 302,302" fill="url(#p3)" stroke="#5d5544"/><polygon points="332,278 420,256 428,316 356,324" fill="url(#p1)" stroke="#6f6653"/><polygon points="420,256 500,260 500,300 428,316" fill="url(#p2)" stroke="#6f6653"/><polygon points="356,324 428,316 500,300 462,318 372,318" fill="url(#p3)" stroke="#6f6653"/><polygon points="332,278 420,256 500,260 462,280 372,292" fill="#ffffff" opacity=".22" stroke="none"/><polygon points="428,314 440,316 438,352" fill="url(#p2)" stroke="#6f6653"/><polygon points="446,312 458,310 464,342" fill="url(#p3)" stroke="#6f6653"/><path d="M438 352 L422 358 M438 352 L452 360 M464 342 L478 348 M464 342 L452 350" fill="none" stroke="#5d5544" stroke-width="2"/><polygon points="500,260 550,210 560,226 518,284" fill="url(#p1)" stroke="#6f6653"/><polygon points="518,284 560,226 572,222 526,288 500,300" fill="url(#p2)" stroke="#6f6653"/><polygon points="500,300 526,288 572,222 554,240 512,288" fill="url(#p3)" stroke="#6f6653"/><polygon points="550,210 580,190 596,206 572,222" fill="url(#p1)" stroke="#6f6653"/><polygon points="580,190 596,206 586,224" fill="url(#p1)" stroke="#6f6653"/><polygon points="596,206 618,216 586,224 572,222" fill="#d8bd82" stroke="#7a6a45"/><circle cx="577" cy="205" r="3.5" fill="#191919"/><circle cx="578" cy="204" r="1" fill="#fff"/><polygon points="388,270 410,112 404,266" fill="url(#pw)" stroke="#6f6653"/><polygon points="410,112 450,256 404,266" fill="url(#p1)" stroke="#6f6653"/><polygon points="410,112 450,256 464,242 426,120" fill="url(#pd)" stroke="#6f6653"/><polygon points="410,112 422,116 436,244 450,256" fill="#ffffff" opacity=".28" stroke="none"/><g fill="none" stroke="#5d5544" stroke-opacity=".6"><path d="M388 270 L410 112 L450 256"/><path d="M332 278 L420 256 L500 260"/><path d="M362 296 L500 300 L428 316"/><path d="M500 260 L550 210 M518 284 L560 226"/><path d="M258 262 L332 278 L302 302"/><path d="M380 272 L368 132"/></g><g fill="none" stroke="#ffffff" stroke-opacity=".75"><path d="M392 266 L412 122"/><path d="M338 280 L420 262"/><path d="M504 264 L548 216"/><path d="M554 212 L578 194"/></g><polygon points="420,256 462,280 428,316 436,280" fill="#ffffff" opacity=".16" stroke="none"/><polygon points="410,112 436,244 404,266 398,190" fill="#ffffff" opacity=".14" stroke="none"/></g></defs><rect width="800" height="600" fill="url(#bg)"/><ellipse cx="400" cy="500" rx="195" ry="28" fill="url(#shadow)" filter="url(#blur)"/><circle cx="400" cy="280" r="200" fill="url(#sphere)"/><g clip-path="url(#clip)"><ellipse cx="400" cy="430" rx="140" ry="42" fill="#ffffff" opacity=".28" filter="url(#blur)"/><use href="#crane" transform="translate(400 280) scale(1.06 .95) translate(-400 -280) translate(6 4)" opacity=".28" filter="url(#refract)"/><g class="float" filter="url(#drop)"><use href="#crane"/></g><circle cx="400" cy="280" r="200" fill="url(#front)"/><ellipse cx="320" cy="172" rx="78" ry="42" fill="#ffffff" opacity=".75" transform="rotate(-32 320 172)" filter="url(#blur)"/><ellipse cx="300" cy="148" rx="30" ry="11" fill="#ffffff" opacity=".95" transform="rotate(-32 300 148)" filter="url(#blur2)"/><path d="M535 140 C575 205 582 305 552 390" fill="none" stroke="#ffffff" stroke-width="7" stroke-linecap="round" opacity=".3" filter="url(#blur)"/><path d="M548 160 C576 215 578 295 555 365" fill="none" stroke="#ffffff" stroke-width="2.5" stroke-linecap="round" opacity=".55" filter="url(#blur2)"/><path d="M255 425 C340 468 460 468 545 420" fill="none" stroke="#fff3cf" stroke-width="8" stroke-linecap="round" opacity=".55" filter="url(#blur)"/><circle cx="285" cy="365" r="4" fill="#ffffff" opacity=".45"/><circle cx="525" cy="195" r="3" fill="#ffffff" opacity=".5"/></g><circle cx="400" cy="280" r="200" fill="none" stroke="#8be9ff" stroke-width="2" opacity=".25" transform="translate(-2 0)"/><circle cx="400" cy="280" r="200" fill="none" stroke="#ff9fd6" stroke-width="2" opacity=".18" transform="translate(2 0)"/><circle cx="400" cy="280" r="200" fill="none" stroke="url(#rim)" stroke-width="4"/><circle cx="400" cy="280" r="196" fill="none" stroke="#ffffff" stroke-width="1" opacity=".6"/></svg></body></html>
2. Procedural globe
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive Procedural 3D Globe</title>
<style>
* { box-sizing: border-box; }
html, body { height: 100%; }
body {
margin: 0;
overflow: hidden;
background: radial-gradient(1200px 800px at 50% 38%, #0a2438 0%, #04101d 55%, #01040a 100%);
color: #eaf6ff;
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
}
#app { position: fixed; inset: 0; touch-action: none; }
#app canvas { display: block; }
.panel {
position: fixed;
top: 18px;
left: 18px;
width: min(320px, calc(100vw - 36px));
padding: 16px 18px 14px;
border: 1px solid rgba(125, 211, 252, 0.28);
border-radius: 16px;
background: rgba(3, 18, 32, 0.62);
box-shadow: 0 18px 50px rgba(0,0,0,.45);
backdrop-filter: blur(12px);
}
.panel h1 { margin: 0 0 4px; font-size: 20px; line-height: 1.15; letter-spacing: .02em; }
.panel p { margin: 0 0 14px; font-size: 13px; line-height: 1.45; color: rgba(224,242,254,.78); }
.panel label { display: block; font-size: 12px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: #bae6fd; margin-bottom: 8px; }
.row { display: flex; align-items: center; gap: 12px; }
input[type="range"] { flex: 1; accent-color: #38bdf8; height: 28px; cursor: pointer; }
#val { min-width: 52px; text-align: right; font-variant-numeric: tabular-nums; font-weight: 700; color: #f0f9ff; }
.hint {
position: fixed;
left: 50%;
bottom: 16px;
transform: translateX(-50%);
padding: 8px 14px;
border-radius: 999px;
background: rgba(2, 12, 24, .55);
border: 1px solid rgba(125,211,252,.18);
color: rgba(224,242,254,.82);
font-size: 13px;
pointer-events: none;
white-space: nowrap;
}
</style>
</head>
<body>
<div id="app" aria-label="Interactive 3D procedural globe"></div>
<div class="panel">
<h1>Procedural 3D Globe</h1>
<p>Three.js globe with a canvas-generated continent texture, atmospheric glow, and an orbiting particle ring.</p>
<label for="speed">Rotation speed</label>
<div class="row">
<input id="speed" type="range" min="-2" max="2" step="0.01" value="0.4">
<span id="val">0.40×</span>
</div>
</div>
<div class="hint">Drag to rotate · Scroll or pinch to zoom</div>
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
function mulberry32(seed) {
return function() {
let t = seed += 0x6D2B79F5;
t = Math.imul(t ^ (t >>> 15), t | 1);
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
};
}
function makeGrid(size, rng) {
const g = new Float32Array(size * size);
for (let i = 0; i < g.length; i++) g[i] = rng();
return g;
}
function sampleGrid(grid, size, x, y) {
const x0 = Math.floor(x), y0 = Math.floor(y);
const xf = x - x0, yf = y - y0;
const xi0 = ((x0 % size) + size) % size;
const yi0 = ((y0 % size) + size) % size;
const xi1 = (xi0 + 1) % size;
const yi1 = (yi0 + 1) % size;
const u = xf * xf * (3 - 2 * xf);
const v = yf * yf * (3 - 2 * yf);
const a = grid[yi0 * size + xi0], b = grid[yi0 * size + xi1];
const c = grid[yi1 * size + xi0], d = grid[yi1 * size + xi1];
return a + (b - a) * u + (c - a) * v + (a - b - c + d) * u * v;
}
function createEarthTexture() {
const w = 1024, h = 512;
const canvas = document.createElement('canvas');
canvas.width = w; canvas.height = h;
const ctx = canvas.getContext('2d');
const img = ctx.createImageData(w, h);
const rng = mulberry32(20240229);
const sizes = [4, 8, 16, 32, 64];
const grids = sizes.map(s => makeGrid(s, rng));
const amps = [0.5, 0.27, 0.14, 0.08, 0.04];
function fbm(u, v) {
let sum = 0, ampSum = 0;
for (let i = 0; i < sizes.length; i++) {
const s = sizes[i];
sum += sampleGrid(grids[i], s, u * s, v * s) * amps[i];
ampSum += amps[i];
}
return sum / ampSum;
}
const blobs = [
{ lon: -100, lat: 46, sigma: 24, amp: 0.62 }, // North America
{ lon: -60, lat: -14, sigma: 17, amp: 0.58 }, // South America
{ lon: 20, lat: 5, sigma: 20, amp: 0.60 }, // Africa
{ lon: 16, lat: 50, sigma: 13, amp: 0.50 }, // Europe
{ lon: 82, lat: 36, sigma: 27, amp: 0.66 }, // Asia
{ lon: 135, lat: -26, sigma: 13, amp: 0.52 }, // Australia
{ lon: 45, lat: 65, sigma: 15, amp: 0.45 }, // northern land
{ lon: -42, lat: 65, sigma: 12, amp: 0.42 } // Greenland area
];
const seaLevel = 0.55;
for (let y = 0; y < h; y++) {
const v = y / h;
const lat = 90 - v * 180;
for (let x = 0; x < w; x++) {
const u = x / w;
const lon = u * 360 - 180;
let blob = 0;
for (const c of blobs) {
let dLon = lon - c.lon;
while (dLon > 180) dLon -= 360;
while (dLon < -180) dLon += 360;
const dLat = lat - c.lat;
const dist2 = dLon * dLon + dLat * dLat * 1.7;
blob += Math.exp(-dist2 / (2 * c.sigma * c.sigma)) * c.amp;
}
const n = fbm(u, v);
const elevation = n * 0.52 + blob * 0.78;
const idx = (y * w + x) * 4;
let r, g, b;
if (elevation < seaLevel) {
const depth = Math.min(1, (seaLevel - elevation) / seaLevel);
const shallow = [43, 127, 184], deep = [5, 31, 58];
r = shallow[0] + (deep[0] - shallow[0]) * depth;
g = shallow[1] + (deep[1] - shallow[1]) * depth;
b = shallow[2] + (deep[2] - shallow[2]) * depth;
} else {
const t = Math.min(1, (elevation - seaLevel) / (1 - seaLevel));
const moisture = n;
let land;
if (t > 0.78) land = [238, 240, 235];
else if (moisture > 0.62 && Math.abs(lat) < 38) land = [194, 160, 90];
else if (t > 0.45) land = [139, 119, 72];
else land = [37 + moisture * 35, 102 + moisture * 30, 48 + moisture * 18];
r = land[0]; g = land[1]; b = land[2];
}
const ice = THREE.MathUtils.smoothstep(Math.abs(lat), 68, 82);
if (ice > 0) {
r = r + (242 - r) * ice;
g = g + (248 - g) * ice;
b = b + (252 - b) * ice;
}
img.data[idx] = r;
img.data[idx + 1] = g;
img.data[idx + 2] = b;
img.data[idx + 3] = 255;
}
}
ctx.putImageData(img, 0, 0);
ctx.strokeStyle = 'rgba(255,255,255,0.10)';
ctx.lineWidth = 1;
for (let lon = 0; lon <= w; lon += w / 12) {
ctx.beginPath(); ctx.moveTo(lon, 0); ctx.lineTo(lon, h); ctx.stroke();
}
for (let lat = 0; lat <= h; lat += h / 6) {
ctx.beginPath(); ctx.moveTo(0, lat); ctx.lineTo(w, lat); ctx.stroke();
}
const texture = new THREE.CanvasTexture(canvas);
texture.colorSpace = THREE.SRGBColorSpace;
texture.anisotropy = 4;
return texture;
}
function createSpriteTexture() {
const c = document.createElement('canvas');
c.width = c.height = 64;
const ctx = c.getContext('2d');
const grad = ctx.createRadialGradient(32, 32, 0, 32, 32, 32);
grad.addColorStop(0, 'rgba(255,255,255,1)');
grad.addColorStop(0.25, 'rgba(255,255,255,0.85)');
grad.addColorStop(0.6, 'rgba(255,255,255,0.18)');
grad.addColorStop(1, 'rgba(255,255,255,0)');
ctx.fillStyle = grad;
ctx.fillRect(0, 0, 64, 64);
const tex = new THREE.CanvasTexture(c);
tex.colorSpace = THREE.SRGBColorSpace;
return tex;
}
const container = document.getElementById('app');
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(42, window.innerWidth / window.innerHeight, 0.1, 100);
camera.position.set(0, 1.15, 3.45);
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.outputColorSpace = THREE.SRGBColorSpace;
container.appendChild(renderer.domElement);
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.06;
controls.enablePan = false;
controls.minDistance = 1.65;
controls.maxDistance = 6;
controls.rotateSpeed = 0.65;
controls.zoomSpeed = 0.8;
scene.add(new THREE.AmbientLight(0xbfe3ff, 0.75));
const sun = new THREE.DirectionalLight(0xffffff, 2.6);
sun.position.set(5, 3, 5);
scene.add(sun);
const rim = new THREE.PointLight(0x38bdf8, 18, 20);
rim.position.set(-5, -2, -4);
scene.add(rim);
const globeGroup = new THREE.Group();
scene.add(globeGroup);
const earthTexture = createEarthTexture();
const globe = new THREE.Mesh(
new THREE.SphereGeometry(1, 96, 96),
new THREE.MeshPhongMaterial({
map: earthTexture,
bumpMap: earthTexture,
bumpScale: 0.025,
shininess: 22,
specular: new THREE.Color(0x224455)
})
);
globeGroup.add(globe);
const glowMaterial = new THREE.ShaderMaterial({
uniforms: { glowColor: { value: new THREE.Color(0x38bdf8) } },
vertexShader: `
varying vec3 vNormal;
void main() {
vNormal = normalize(normalMatrix * normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
uniform vec3 glowColor;
varying vec3 vNormal;
void main() {
float intensity = pow(max(0.0, 0.68 - dot(vNormal, vec3(0.0, 0.0, 1.0))), 3.2);
gl_FragColor = vec4(glowColor, 1.0) * intensity * 1.6;
}
`,
side: THREE.BackSide,
blending: THREE.AdditiveBlending,
transparent: true,
depthWrite: false
});
const atmosphere = new THREE.Mesh(new THREE.SphereGeometry(1.23, 64, 64), glowMaterial);
globeGroup.add(atmosphere);
const sprite = createSpriteTexture();
const particleCount = 1100;
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const colorA = new THREE.Color(0x67e8f9);
const colorB = new THREE.Color(0xfde68a);
const colorC = new THREE.Color(0xffffff);
const rngParticles = mulberry32(42);
for (let i = 0; i < particleCount; i++) {
const angle = rngParticles() * Math.PI * 2;
const radius = 2.05 + rngParticles() * 0.75;
positions[i * 3] = Math.cos(angle) * radius;
positions[i * 3 + 1] = (rngParticles() - 0.5) * 0.09;
positions[i * 3 + 2] = Math.sin(angle) * radius;
const pick = rngParticles();
const col = pick < 0.55 ? colorA : (pick < 0.82 ? colorB : colorC);
colors[i * 3] = col.r;
colors[i * 3 + 1] = col.g;
colors[i * 3 + 2] = col.b;
}
const particleGeometry = new THREE.BufferGeometry();
particleGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
particleGeometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
const ringSpin = new THREE.Points(particleGeometry, new THREE.PointsMaterial({
size: 0.045,
map: sprite,
vertexColors: true,
transparent: true,
opacity: 0.95,
depthWrite: false,
blending: THREE.AdditiveBlending,
sizeAttenuation: true
}));
const ringTilt = new THREE.Group();
ringTilt.rotation.set(1.12, 0, -0.28);
ringTilt.add(ringSpin);
scene.add(ringTilt);
const starCount = 900;
const starPos = new Float32Array(starCount * 3);
for (let i = 0; i < starCount; i++) {
const r = 14 + Math.random() * 18;
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos(2 * Math.random() - 1);
starPos[i * 3] = r * Math.sin(phi) * Math.cos(theta);
starPos[i * 3 + 1] = r * Math.cos(phi);
starPos[i * 3 + 2] = r * Math.sin(phi) * Math.sin(theta);
}
const starGeometry = new THREE.BufferGeometry();
starGeometry.setAttribute('position', new THREE.BufferAttribute(starPos, 3));
const stars = new THREE.Points(starGeometry, new THREE.PointsMaterial({
size: 0.055,
map: sprite,
color: 0xbfdbfe,
transparent: true,
opacity: 0.75,
depthWrite: false,
blending: THREE.AdditiveBlending
}));
scene.add(stars);
let rotationSpeed = 0.4;
const speedInput = document.getElementById('speed');
const speedVal = document.getElementById('val');
speedInput.addEventListener('input', () => {
rotationSpeed = parseFloat(speedInput.value);
speedVal.textContent = rotationSpeed.toFixed(2) + '×';
});
const clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
globeGroup.rotation.y += rotationSpeed * delta;
ringSpin.rotation.y += delta * (0.18 + Math.abs(rotationSpeed) * 0.12);
stars.rotation.y += delta * 0.005;
controls.update();
renderer.render(scene, camera);
}
animate();
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
});
</script>
</body>
</html>
3. Wizard on floating islands
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PasteL Archipelago — Wizard Crystal Quest</title>
<style>
*{box-sizing:border-box}html,body{margin:0;height:100%;overflow:hidden;background:#87ceeb;font-family:system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif;color:#fff}
#game{width:100%;height:100%;display:block;touch-action:none;cursor:grab}
#game:active{cursor:grabbing}
.hud{position:fixed;top:16px;left:16px;z-index:10;background:rgba(10,20,35,.55);backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.22);border-radius:14px;padding:14px 16px;min-width:230px;box-shadow:0 10px 30px rgba(0,0,0,.25)}
.hud h1{margin:0 0 8px;font-size:18px;letter-spacing:.02em}
.row{display:flex;justify-content:space-between;gap:12px;font-weight:700;font-size:14px;margin:6px 0}
.barWrap{height:14px;background:rgba(255,255,255,.18);border-radius:999px;overflow:hidden;border:1px solid rgba(255,255,255,.25)}
#healthBar{height:100%;width:100%;background:linear-gradient(90deg,#ff5a7a,#ffb86b);transition:width .2s}
.help{position:fixed;right:16px;top:16px;z-index:10;background:rgba(10,20,35,.5);border:1px solid rgba(255,255,255,.2);border-radius:12px;padding:10px 12px;font-size:13px;line-height:1.5;backdrop-filter:blur(8px)}
#centerMsg{position:fixed;left:50%;top:18%;transform:translate(-50%,-50%);z-index:11;font-size:34px;font-weight:900;text-shadow:0 4px 18px rgba(0,0,0,.45);opacity:0;pointer-events:none;transition:opacity .25s;text-align:center}
.overlay{position:fixed;inset:0;z-index:20;display:none;place-items:center;background:rgba(4,10,20,.62);backdrop-filter:blur(6px)}
.overlay.show{display:grid}
.card{background:linear-gradient(145deg,#1b2f4a,#0f1c2f);border:1px solid rgba(255,255,255,.25);border-radius:20px;padding:28px;text-align:center;box-shadow:0 25px 70px rgba(0,0,0,.5);max-width:90vw}
.card h2{margin:0 0 10px;font-size:34px}.card p{opacity:.9;line-height:1.5}
button{background:linear-gradient(90deg,#38bdf8,#a78bfa);color:white;border:0;border-radius:999px;padding:12px 22px;font-weight:900;font-size:16px;cursor:pointer;box-shadow:0 8px 22px rgba(56,189,248,.35)}
button:hover{filter:brightness(1.1)}
@media(max-width:650px){.help{display:none}.hud{min-width:200px}}
</style>
</head>
<body>
<canvas id="game"></canvas>
<div class="hud">
<h1>✦ Crystal Wizard Quest</h1>
<div class="row"><span>Score</span><span id="score">0</span></div>
<div class="row"><span>Crystals</span><span id="crystals">0 / 8</span></div>
<div class="row"><span>Health</span><span id="healthText">100</span></div>
<div class="barWrap"><div id="healthBar"></div></div>
</div>
<div class="help"><b>Controls</b><br>WASD / Arrows — Move<br>Space — Jump<br>Drag Mouse — Camera<br>R — Restart<br><br>Collect crystals, dodge turrets!</div>
<div id="centerMsg"></div>
<div id="gameOver" class="overlay"><div class="card"><h2>Game Over</h2><p id="finalScore">Score: 0</p><p>The archipelago grows quiet... try again, wizard.</p><button id="restartBtn">Restart Adventure</button></div></div>
<div id="win" class="overlay"><div class="card"><h2>🏆 Quest Complete!</h2><p id="winScore">Score: 0</p><p>You collected every crystal!</p><button id="againBtn">Play Again</button></div></div>
<script type="importmap">
{"imports":{"three":"https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js"}}
</script>
<script type="module">
import * as THREE from 'three';
const canvas=document.getElementById('game');
const renderer=new THREE.WebGLRenderer({canvas,antialias:true});
renderer.setPixelRatio(Math.min(devicePixelRatio,2));
renderer.setSize(innerWidth,innerHeight);
renderer.shadowMap.enabled=true;
renderer.shadowMap.type=THREE.PCFSoftShadowMap;
renderer.outputColorSpace=THREE.SRGBColorSpace;
const scene=new THREE.Scene();
scene.background=new THREE.Color(0x8ed8ff);
scene.fog=new THREE.Fog(0x8ed8ff,45,130);
const camera=new THREE.PerspectiveCamera(60,innerWidth/innerHeight,.1,500);
const ambient=new THREE.AmbientLight(0xffffff,.65); scene.add(ambient);
const sun=new THREE.DirectionalLight(0xfff2c4,2.2);
sun.castShadow=true; sun.shadow.mapSize.set(2048,2048);
sun.shadow.camera.left=-70; sun.shadow.camera.right=70; sun.shadow.camera.top=70; sun.shadow.camera.bottom=-70;
scene.add(sun); scene.add(sun.target);
const moon=new THREE.DirectionalLight(0x8fb8ff,.0); moon.position.set(-30,40,-20); scene.add(moon);
// Audio
let audioCtx=null;
function beep(freq,dur=.12,type='sine',vol=.18,slide=0){
try{
if(!audioCtx) audioCtx=new (window.AudioContext||window.webkitAudioContext)();
if(audioCtx.state==='suspended') audioCtx.resume();
const o=audioCtx.createOscillator(), g=audioCtx.createGain();
o.type=type; o.frequency.setValueAtTime(freq,audioCtx.currentTime);
if(slide) o.frequency.exponentialRampToValueAtTime(Math.max(40,freq+slide),audioCtx.currentTime+dur);
g.gain.setValueAtTime(vol,audioCtx.currentTime);
g.gain.exponentialRampToValueAtTime(.001,audioCtx.currentTime+dur);
o.connect(g).connect(audioCtx.destination); o.start(); o.stop(audioCtx.currentTime+dur);
}catch(e){}
}
const sJump=()=>beep(380,.16,'triangle',.16,260);
const sCollect=()=>{beep(880,.12,'sine',.2); setTimeout(()=>beep(1320,.18,'sine',.18),90)};
const sHit=()=>beep(140,.22,'sawtooth',.22,-80);
const sShoot=()=>beep(700,.08,'square',.06,-300);
// Materials helpers
const mat=(c,r=.85,m=0)=>new THREE.MeshStandardMaterial({color:c,roughness:r,metalness:m});
function mesh(geo,material,x=0,y=0,z=0){const m=new THREE.Mesh(geo,material);m.position.set(x,y,z);m.castShadow=true;m.receiveShadow=true;return m;}
// Islands
const islands=[
{x:0,z:0,r:15,y:0,c:0x8ee6a1},
{x:30,z:-12,r:9,y:2,c:0xa7f3d0},
{x:-32,z:-15,r:10,y:1,c:0xfbcfe8},
{x:20,z:28,r:11,y:3,c:0xbfdbfe},
{x:-24,z:26,r:8,y:4,c:0xfde68a},
{x:0,z:-40,r:9,y:5,c:0xc4b5fd},
{x:44,z:20,r:7,y:6,c:0xfca5a5},
{x:-44,z:8,r:8,y:-1,c:0x99f6e4},
{x:8,z:48,r:7,y:1,c:0xfed7aa}
];
function buildIsland(isl){
const g=new THREE.Group();
const top=mesh(new THREE.CylinderGeometry(isl.r,isl.r*.92,2.2,28),mat(isl.c,.9),0,isl.y,0);
const under=mesh(new THREE.ConeGeometry(isl.r*.9,isl.r*1.1,28),mat(0xb08968,.95),0,isl.y-1.1-isl.r*.55,0);
under.rotation.x=Math.PI; // point down
// Actually cone points up by default; flip to point down
under.rotation.x=0; under.rotation.z=Math.PI;
g.add(top,under);
// rim flowers / rocks
for(let i=0;i<10;i++){
const a=(i/10)*Math.PI*2, rr=isl.r*.78;
const rock=mesh(new THREE.DodecahedronGeometry(.5+Math.random()*.5),mat(0xe7e5e4,.9),Math.cos(a)*rr,isl.y+1.25,Math.sin(a)*rr);
rock.rotation.set(Math.random()*3,Math.random()*3,0); g.add(rock);
}
// trees
const trees=2+Math.floor(Math.random()*3);
for(let i=0;i<trees;i++){
const tx=(Math.random()-.5)*isl.r*1.1, tz=(Math.random()-.5)*isl.r*1.1;
const trunk=mesh(new THREE.CylinderGeometry(.25,.35,1.4),mat(0x8b5a2b),tx,isl.y+1.8,tz);
const leaf=mesh(new THREE.ConeGeometry(1.2,2.6,8),mat(0x34d399),tx,isl.y+3.6,tz);
const leaf2=mesh(new THREE.ConeGeometry(.85,1.8,8),mat(0x10b981),tx,isl.y+4.6,tz);
g.add(trunk,leaf,leaf2);
}
g.position.set(isl.x,0,isl.z);
scene.add(g);
}
islands.forEach(buildIsland);
// Bridges
function bridge(a,b){
const dx=b.x-a.x, dz=b.z-a.z, dist=Math.hypot(dx,dz);
const br=mesh(new THREE.BoxGeometry(dist, .7, 2.2),mat(0xd6a679,.95),(a.x+b.x)/2,(a.y+b.y)/2+1.05,(a.z+b.z)/2);
br.rotation.y=-Math.atan2(dz,dx); scene.add(br);
}
bridge(islands[0],islands[1]); bridge(islands[0],islands[2]); bridge(islands[0],islands[3]); bridge(islands[0],islands[4]); bridge(islands[0],islands[5]);
// Clouds
const clouds=[];
for(let i=0;i<16;i++){
const c=new THREE.Group();
for(let j=0;j<4;j++){const s=mesh(new THREE.SphereGeometry(1.4+Math.random()*1.6,10,8),new THREE.MeshStandardMaterial({color:0xffffff,roughness:1,transparent:true,opacity:.9}),j*1.8-2.5,Math.random()*.5,Math.random());s.castShadow=false;c.add(s);}
c.position.set((Math.random()-.5)*130,16+Math.random()*14,(Math.random()-.5)*130);
clouds.push(c); scene.add(c);
}
// Ambient particles
const pCount=700, pPos=new Float32Array(pCount*3), pCol=new Float32Array(pCount*3);
const palette=[new THREE.Color(0xffc0cb),new THREE.Color(0xa5f3fc),new THREE.Color(0xfde68a),new THREE.Color(0xffffff),new THREE.Color(0xc4b5fd)];
for(let i=0;i<pCount;i++){
pPos[i*3]=(Math.random()-.5)*120; pPos[i*3+1]=Math.random()*22; pPos[i*3+2]=(Math.random()-.5)*120;
const c=palette[i%palette.length]; pCol[i*3]=c.r; pCol[i*3+1]=c.g; pCol[i*3+2]=c.b;
}
const pGeo=new THREE.BufferGeometry();
pGeo.setAttribute('position',new THREE.BufferAttribute(pPos,3));
pGeo.setAttribute('color',new THREE.BufferAttribute(pCol,3));
const particles=new THREE.Points(pGeo,new THREE.PointsMaterial({size:.35,vertexColors:true,transparent:true,opacity:.85,depthWrite:false}));
scene.add(particles);
// Wizard
const wizard=new THREE.Group();
const robe=mesh(new THREE.ConeGeometry(1.05,2.3,10),mat(0x7c3aed,.8),0,1.15,0);
const head=mesh(new THREE.SphereGeometry(.55,12,10),mat(0xffd9b3,.7),0,2.65,0);
const hat=mesh(new THREE.ConeGeometry(.78,1.5,10),mat(0x4c1d95,.85),0,3.55,0);
const brim=mesh(new THREE.CylinderGeometry(.82,.82,.14,12),mat(0x4c1d95,.85),0,2.95,0);
const staff=mesh(new THREE.CylinderGeometry(.09,.09,3.1),mat(0x8b5a2b,.9),.78,1.55,0);
const orb=mesh(new THREE.SphereGeometry(.28,12,10),new THREE.MeshStandardMaterial({color:0x67e8f9,emissive:0x22d3ee,emissiveIntensity:1.6,roughness:.2}),.78,3.25,0);
orb.castShadow=false;
const armL=mesh(new THREE.CylinderGeometry(.16,.16,1,6),mat(0x7c3aed),-.7,1.7,0); armL.rotation.z=.6;
const armR=mesh(new THREE.CylinderGeometry(.16,.16,1,6),mat(0x7c3aed),.7,1.7,0); armR.rotation.z=-.4;
wizard.add(robe,head,hat,brim,staff,orb,armL,armR);
scene.add(wizard);
// Crystals
const crystalData=[
[0,3,0],[30,5,-12],[-32,4,-15],[20,6,28],[-24,7,26],[0,8,-40],[44,9,20],[-44,2,8]
];
const crystals=[];
crystalData.forEach(([x,y,z],i)=>{
const c=mesh(new THREE.OctahedronGeometry(.9,0),new THREE.MeshStandardMaterial({color:0x22d3ee,emissive:0x06b6d4,emissiveIntensity:1.4,roughness:.15,metalness:.1,transparent:true,opacity:.95}),x,y,z);
c.userData={baseY:y,phase:i*0.8,taken:false};
const light=new THREE.PointLight(0x22d3ee,6,9); light.position.copy(c.position); scene.add(light);
c.userData.light=light;
crystals.push(c); scene.add(c);
});
// Turrets
const turrets=[], projectiles=[];
function makeTurret(x,y,z){
const g=new THREE.Group();
const base=mesh(new THREE.CylinderGeometry(.9,1.15,1.2,10),mat(0x64748b,.6,.3),0,.6,0);
const core=mesh(new THREE.SphereGeometry(.65,12,10),new THREE.MeshStandardMaterial({color:0xff6b35,emissive:0xff4500,emissiveIntensity:1.2}),0,1.55,0);
const barrel=mesh(new THREE.CylinderGeometry(.18,.22,1.1,8),mat(0x334155,.4,.5),0,1.55,.65); barrel.rotation.x=Math.PI/2;
g.add(base,core,barrel); g.position.set(x,y,z);
g.userData={core,barrel,timer:2+Math.random()*3,baseY:y};
turrets.push(g); scene.add(g);
}
makeTurret(28,3,-18); makeTurret(-34,2,-8); makeTurret(16,4,20); makeTurret(-18,5,20); makeTurret(38,7,14);
function groundHeight(x,z){
let best=-999;
for(const isl of islands){
const d=Math.hypot(x-isl.x,z-isl.z);
if(d<isl.r) best=Math.max(best,isl.y+1.1);
}
return best;
}
// Game state
let score=0, health=100, collected=0, gameOver=false, won=false;
let playerPos=new THREE.Vector3(0,1.1,6), velY=0, onGround=false, invuln=0;
let camYaw=0, camPitch=.35, camDist=9;
const keys={};
function updateHUD(){
document.getElementById('score').textContent=score;
document.getElementById('crystals').textContent=`${collected} / ${crystals.length}`;
document.getElementById('healthText').textContent=Math.max(0,Math.round(health));
document.getElementById('healthBar').style.width=Math.max(0,health)+'%';
}
function showMsg(t){const el=document.getElementById('centerMsg'); el.textContent=t; el.style.opacity=1; setTimeout(()=>el.style.opacity=0,1800);}
function resetGame(){
score=0; health=100; collected=0; gameOver=false; won=false;
playerPos.set(0,1.1,6); velY=0; invuln=0;
crystals.forEach(c=>{c.visible=true;c.userData.taken=false;c.userData.light.visible=true;});
projectiles.forEach(p=>scene.remove(p.mesh)); projectiles.length=0;
document.getElementById('gameOver').classList.remove('show');
document.getElementById('win').classList.remove('show');
updateHUD(); showMsg('Find the crystals!');
}
document.getElementById('restartBtn').onclick=resetGame;
document.getElementById('againBtn').onclick=resetGame;
addEventListener('keydown',e=>{
keys[e.code]=true;
if(e.code==='Space'){e.preventDefault(); if(onGround&&!gameOver){velY=9.5; onGround=false; sJump();}}
if(e.code==='KeyR') resetGame();
});
addEventListener('keyup',e=>keys[e.code]=false);
// Camera drag
let dragging=false,lastX=0,lastY=0;
canvas.addEventListener('pointerdown',e=>{dragging=true;lastX=e.clientX;lastY=e.clientY;canvas.setPointerCapture(e.pointerId);});
canvas.addEventListener('pointermove',e=>{
if(!dragging) return;
const dx=e.clientX-lastX, dy=e.clientY-lastY; lastX=e.clientX; lastY=e.clientY;
camYaw-=dx*0.008; camPitch=THREE.MathUtils.clamp(camPitch+dy*0.006,.05,1.2);
});
canvas.addEventListener('pointerup',()=>dragging=false);
canvas.addEventListener('wheel',e=>{camDist=THREE.MathUtils.clamp(camDist+e.deltaY*0.01,5,16);},{passive:true});
addEventListener('contextmenu',e=>e.preventDefault());
function damage(amount){
if(invuln>0||gameOver||won) return;
health-=amount; invuln=.6; sHit(); updateHUD();
showMsg(amount>=10?'Ouch! Turret hit!':'');
if(health<=0){
health=0; gameOver=true;
document.getElementById('finalScore').textContent=`Score: ${score} • Crystals: ${collected}/${crystals.length}`;
document.getElementById('gameOver').classList.add('show');
}
}
function shoot(turret){
const from=turret.position.clone(); from.y+=1.55; from.z+=0;
const target=playerPos.clone(); target.y+=1.5;
const dir=target.sub(from).normalize();
const m=mesh(new THREE.SphereGeometry(.28,10,8),new THREE.MeshStandardMaterial({color:0xff8c42,emissive:0xff4500,emissiveIntensity:2}),from.x,from.y,from.z);
m.castShadow=false; scene.add(m);
projectiles.push({mesh:m,vel:dir.multiplyScalar(13),life:6});
sShoot();
}
const clock=new THREE.Clock();
let dayTime=0.25;
function animate(){
requestAnimationFrame(animate);
const dt=Math.min(clock.getDelta(),.05);
const t=clock.elapsedTime;
dayTime=(dayTime+dt*0.015)%1;
// Day-night
const sunAngle=dayTime*Math.PI*2;
const sunY=Math.sin(sunAngle), sunX=Math.cos(sunAngle);
sun.position.set(sunX*60,Math.max(8,sunY*60),30);
sun.intensity=THREE.MathUtils.clamp(sunY*2.2+.4,.15,2.4);
ambient.intensity=.3+Math.max(0,sunY)*.5;
const dayCol=new THREE.Color(0x8ed8ff), nightCol=new THREE.Color(0x07122b);
const mix=THREE.MathUtils.clamp(sunY+.4,0,1);
scene.background.copy(nightCol).lerp(dayCol,mix);
scene.fog.color.copy(scene.background);
moon.intensity=sunY<0? .7:0;
// Movement
if(!gameOver&&!won){
const forward=new THREE.Vector3(Math.sin(camYaw),0,Math.cos(camYaw)).multiplyScalar(-1);
const right=new THREE.Vector3(forward.z,0,-forward.x);
// forward should be away from camera: camera behind player
const move=new THREE.Vector3();
if(keys.KeyW||keys.ArrowUp) move.add(forward);
if(keys.KeyS||keys.ArrowDown) move.sub(forward);
if(keys.KeyD||keys.ArrowRight) move.add(right);
if(keys.KeyA||keys.ArrowLeft) move.sub(right);
if(move.lengthSq()>0){
move.normalize().multiplyScalar(6.2*dt);
playerPos.add(move);
const targetRot=Math.atan2(move.x,move.z);
wizard.rotation.y+=THREE.MathUtils.clamp(((targetRot-wizard.rotation.y+Math.PI*3)%(Math.PI*2))-Math.PI,-.2,.2);
}
// Turret collision push
turrets.forEach(tr=>{
const d=Math.hypot(playerPos.x-tr.position.x,playerPos.z-tr.position.z);
if(d<1.6&&d>0.01){ const push=new THREE.Vector3(playerPos.x-tr.position.x,0,playerPos.z-tr.position.z).normalize().multiplyScalar(1.6-d); playerPos.add(push); }
});
// Gravity / ground
const gY=groundHeight(playerPos.x,playerPos.z);
velY-=24*dt; playerPos.y+=velY*dt;
if(gY>-100 && playerPos.y<=gY){playerPos.y=gY; velY=0; onGround=true;} else onGround=false;
if(playerPos.y<-25){ damage(100); health=0; gameOver=true; document.getElementById('finalScore').textContent=`Score: ${score}`; document.getElementById('gameOver').classList.add('show'); }
}
wizard.position.copy(playerPos);
wizard.position.y+=Math.sin(t*3)*0.05;
orb.material.emissiveIntensity=1.2+Math.sin(t*4)*.5;
invuln=Math.max(0,invuln-dt);
wizard.visible=invuln>0 ? Math.floor(t*14)%2===0 : true;
// Crystals
crystals.forEach(c=>{
if(c.userData.taken) return;
c.rotation.y+=dt*1.8;
c.position.y=c.userData.baseY+Math.sin(t*2+c.userData.phase)*.35;
c.userData.light.position.copy(c.position);
if(playerPos.distanceTo(c.position)<2.1){
c.userData.taken=true; c.visible=false; c.userData.light.visible=false;
collected++; score+=100; sCollect(); showMsg('✦ Crystal collected! +100'); updateHUD();
if(collected>=crystals.length){
won=true; score+=500;
document.getElementById('winScore').textContent=`Final Score: ${score}`;
document.getElementById('win').classList.add('show');
}
}
});
// Turrets AI
turrets.forEach(tr=>{
tr.userData.timer-=dt;
const dist=playerPos.distanceTo(tr.position);
// look at player
const look=new THREE.Vector3(playerPos.x-tr.position.x,0,playerPos.z-tr.position.z);
if(dist<30) tr.rotation.y=Math.atan2(look.x,look.z);
if(dist<26 && tr.userData.timer<=0 && !gameOver && !won){ shoot(tr); tr.userData.timer=2.6+Math.random()*1.8; }
tr.userData.core.material.emissiveIntensity=1+Math.sin(t*6)*.4;
});
// Projectiles
for(let i=projectiles.length-1;i>=0;i--){
const p=projectiles[i];
p.mesh.position.addScaledVector(p.vel,dt); p.life-=dt;
let dead=p.life<=0;
if(p.mesh.position.distanceTo(playerPos.clone().add(new THREE.Vector3(0,1.4,0)))<1.2){ damage(12); dead=true; }
if(p.mesh.position.y<groundHeight(p.mesh.position.x,p.mesh.position.z)) dead=true;
if(dead){scene.remove(p.mesh); projectiles.splice(i,1);}
}
// Environment motion
clouds.forEach((c,i)=>{c.position.x+=dt*(0.4+i*0.02); if(c.position.x>75)c.position.x=-75;});
particles.rotation.y+=dt*0.02;
particles.position.y=Math.sin(t*.5)*.6;
// Camera follow (third-person drag orbit)
const camTarget=playerPos.clone(); camTarget.y+=2.4;
const offset=new THREE.Vector3(
Math.sin(camYaw)*Math.cos(camPitch),
Math.sin(camPitch),
Math.cos(camYaw)*Math.cos(camPitch)
).multiplyScalar(camDist);
const desired=camTarget.clone().add(offset);
camera.position.lerp(desired,1-Math.pow(0.0001,dt));
camera.lookAt(camTarget);
renderer.render(scene,camera);
}
updateHUD();
animate();
addEventListener('resize',()=>{
camera.aspect=innerWidth/innerHeight; camera.updateProjectionMatrix();
renderer.setSize(innerWidth,innerHeight);
});
</script>
</body>
</html>
Notes on the run
</html> tag.Read Next
MiniMax M3.1 Flash: Four HTML Coding Benchmarks on Free OpenCode
MiniMax M3.1 Flash tested through free OpenCode: original crane, globe, wizard-game and task-board HTML, browser screenshots, timings, downloadable evidence, 16 passing board checks and a reproduced game physics failure.
Tencent Hy4 AI Studio Coding Test: Crane, Globe & Wizard Game
We asked Tencent HY AI Studio's Hy4 New to build an SVG glass crane, a Three.js procedural globe, and a floating-island wizard game. This hands-on report includes all three saved HTML files, correction turns, official Hy4 specs, and clear limits on what was tested.
Recursive Flint: All Four LogicMark Benchmarks, Scores and Failures
We test Recursive Flint on both LogicMark 1.0.0 suites in Tool-assisted and Quick modes, documenting objective scores, protocol failures, timing and API usage.