Models 44

GLM 5.3

by Z.aiReasoningClean
Open in new window

Running live in a sandboxed frame. Click inside it before using the keyboard.

How it went

Total time
26.4 s
Cost
$0.0071
Output tokens
5,049
Spent thinking
63 tokens
Speed
194 tok/s
Console errors
0
First token after
380 ms
First visible text after
820 ms
Prompt tokens
424
Code size
14.2 KB
Finish reason
stop
Served by
Wafer
Model id
z-ai/glm-5.3
Reasoning sent
{"effort":"low"}
Max output
943,718 tokens
Generated
Nov 12, 2026

What it was asked

The prompt
“a 3D aquarium with Three.js where the fish swim away when I move the mouse near them (Load Three.js only through this import map: <script type="importmap">{"imports":{"three":"https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js","three/addons/":"https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/"}}</script>)”
System prompt, sent with every prompt
You are generating a self-contained web demo. It will be rendered automatically in a sandboxed iframe and compared side by side with the output of other AI models given the exact same task.

Output rules:
- Reply with exactly ONE fenced code block containing the complete file: ```html (or ```svg when the task asks for an SVG). No text before or after the code block.
- Everything must be inline: CSS in <style>, JavaScript in <script>. No external files, images, fonts or network requests, except the CDN URLs explicitly allowed by the task.
- Do not use localStorage, sessionStorage, cookies, IndexedDB, alert(), confirm(), prompt() or window.open(): they are blocked in the sandbox and will throw.
- The page must look right in a 1280×800 viewport and adapt gracefully down to 375px wide. No horizontal scrollbar.
- Something meaningful must be visible on first paint: a screenshot is taken automatically about 3 seconds after load, without any interaction.
- Everything that makes the demo interesting must be visible within the first seconds: nothing hidden behind a high score, a later level or a long play session.
- Games must start in a self-playing demo mode (a simple AI plays) behind a "Click or press a key to start" message, so the game can be judged in action without playing.
- The iframe only receives keyboard events after the user clicks it: if the demo uses the keyboard, display a clear "Click or press a key to start" message.
- The code must run with zero errors in the console of the latest Chrome.

Code run-1.html · 392 lines

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Aquarium</title>
<style>
  * { margin: 0; padding: 0; box-sizing: border-box; }
  html, body { height: 100%; overflow: hidden; background: #04121f; font-family: Georgia, serif; }
  #app { position: fixed; inset: 0; }
  canvas { display: block; }
  .panel {
    position: fixed; top: 18px; left: 18px; z-index: 10;
    color: #cfeef5; background: rgba(4,26,44,.55);
    border: 1px solid rgba(120,200,255,.25);
    padding: 14px 18px 12px; border-radius: 10px;
    backdrop-filter: blur(6px); max-width: 300px;
    pointer-events: none;
  }
  .panel h1 { font-size: 19px; letter-spacing: .06em; font-weight: normal; }
  .panel p { font-size: 13px; margin-top: 5px; opacity: .85; line-height: 1.45; }
  .hint {
    position: fixed; bottom: 16px; left: 50%; transform: translateX(-50%);
    color: #bfe9f5; background: rgba(4,26,44,.6);
    border: 1px solid rgba(120,200,255,.25);
    padding: 8px 16px; border-radius: 999px; font-size: 13px;
    z-index: 10; pointer-events: none;
  }
  @media (max-width: 560px) { .panel { max-width: 220px; } .panel h1 { font-size: 16px; } }
</style>
</head>
<body>
<div id="app"></div>
<div class="panel">
  <h1>Reef Tank №7</h1>
  <p>Move your cursor through the water — the fish scatter from your presence. Click to feed them and watch them gather.</p>
</div>
<div class="hint" id="hint">move your mouse · click to feed</div>

<script type="importmap">
{"imports":{"three":"https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js","three/addons/":"https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/"}}
</script>
<script type="module">
import * as THREE from 'three';

const app = document.getElementById('app');
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x0a3550);
scene.fog = new THREE.FogExp2(0x0a3550, 0.035);

const camera = new THREE.PerspectiveCamera(55, innerWidth/innerHeight, 0.1, 100);
camera.position.set(0, 3.5, 14);

const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(innerWidth, innerHeight);
renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
app.appendChild(renderer.domElement);

// ---------- Lights ----------
scene.add(new THREE.HemisphereLight(0x9fd8ff, 0x0b2a3d, 0.9));
const sun = new THREE.DirectionalLight(0xfff2d0, 1.6);
sun.position.set(4, 10, 6);
scene.add(sun);

// ---------- Water surface (top plane, seen from below) ----------
const waterGeo = new THREE.PlaneGeometry(60, 60, 1, 1);
const water = new THREE.Mesh(waterGeo, new THREE.MeshPhongMaterial({
  color: 0x66ccff, transparent: true, opacity: 0.35, side: THREE.DoubleSide, shininess: 90
}));
water.rotation.x = -Math.PI/2;
water.position.y = 9;
scene.add(water);

// ---------- Sand floor ----------
const sand = new THREE.Mesh(
  new THREE.CircleGeometry(30, 48),
  new THREE.MeshStandardMaterial({ color: 0xc9b088, roughness: 1 })
);
sand.rotation.x = -Math.PI/2;
sand.position.y = -3;
scene.add(sand);

// subtle undulation on the sand via vertex noise
{
  const g = new THREE.PlaneGeometry(60, 60, 40, 40);
  const p = g.attributes.position;
  for (let i=0;i<p.count;i++){
    const x = p.getX(i), y = p.getY(i);
    p.setZ(i, Math.sin(x*0.6)*0.15 + Math.cos(y*0.8)*0.12);
  }
  g.computeVertexNormals();
  const m = new THREE.Mesh(g, new THREE.MeshStandardMaterial({ color: 0xbfa87e, roughness: 1 }));
  m.rotation.x = -Math.PI/2; m.position.y = -3.02;
  scene.add(m);
}

// ---------- Rocks ----------
const rockMat = new THREE.MeshStandardMaterial({ color: 0x6b7f8a, roughness: 0.95, flatShading: true });
for (let i=0;i<14;i++){
  const s = 0.4 + Math.random()*1.2;
  const rock = new THREE.Mesh(new THREE.DodecahedronGeometry(s, 0), rockMat);
  const a = Math.random()*Math.PI*2, r = 5 + Math.random()*16;
  rock.position.set(Math.cos(a)*r, -3 + s*0.4, Math.sin(a)*r - 3);
  rock.rotation.set(Math.random()*3, Math.random()*3, Math.random()*3);
  scene.add(rock);
}

// ---------- Plants (swaying blades) ----------
const plants = [];
const bladeMat = new THREE.MeshStandardMaterial({ color: 0x2e8b57, roughness: 0.8, side: THREE.DoubleSide });
for (let i=0;i<26;i++){
  const h = 1.5 + Math.random()*2.5;
  const blade = new THREE.Mesh(new THREE.PlaneGeometry(0.18, h, 1, 4), bladeMat);
  const a = Math.random()*Math.PI*2, r = 3 + Math.random()*18;
  blade.position.set(Math.cos(a)*r, -3 + h/2, Math.sin(a)*r - 3);
  blade.rotation.y = Math.random()*Math.PI;
  blade.userData = { phase: Math.random()*6.28, h };
  plants.push(blade);
  scene.add(blade);
}

// ---------- Fish ----------
function makeFishTexture(hue){
  const c = document.createElement('canvas'); c.width = 128; c.height = 64;
  const ctx = c.getContext('2d');
  const g = ctx.createLinearGradient(0,0,128,64);
  g.addColorStop(0, `hsl(${hue},70%,55%)`);
  g.addColorStop(0.55, `hsl(${hue},75%,45%)`);
  g.addColorStop(1, `hsl(${(hue+30)%360},70%,35%)`);
  ctx.fillStyle = g; ctx.fillRect(0,0,128,64);
  ctx.fillStyle = `hsl(${hue},80%,25%)`;
  for (let i=0;i<7;i++){ ctx.beginPath(); ctx.ellipse(15+i*16, 32+Math.sin(i)*14, 7, 4, 0.5, 0, 6.29); ctx.fill(); }
  const t = new THREE.CanvasTexture(c);
  t.colorSpace = THREE.SRGBColorSpace;
  return t;
}

const fishes = [];
const FISH_COUNT = 26;
const fishGroup = new THREE.Group();
scene.add(fishGroup);

for (let i=0;i<FISH_COUNT;i++){
  const hue = Math.floor(Math.random()*360);
  const scale = 0.55 + Math.random()*0.9;

  // body: elongated ellipsoid via scaled sphere
  const body = new THREE.Mesh(
    new THREE.SphereGeometry(0.5, 12, 10),
    new THREE.MeshStandardMaterial({ map: makeFishTexture(hue), roughness: 0.6 })
  );
  body.scale.set(1.6, 0.8, 0.5);

  // tail (cone pointing back)
  const tail = new THREE.Mesh(
    new THREE.ConeGeometry(0.32, 0.6, 8),
    new THREE.MeshStandardMaterial({ color: new THREE.Color().setHSL(hue/360, 0.7, 0.4), roughness: 0.7, flatShading: true })
  );
  tail.rotation.z = Math.PI/2;
  tail.position.x = -0.85;

  // fins
  const finGeo = new THREE.ConeGeometry(0.16, 0.4, 4);
  const finMat = new THREE.MeshStandardMaterial({ color: new THREE.Color().setHSL(hue/360, 0.6, 0.55), transparent: true, opacity: 0.85, flatShading: true });
  const topFin = new THREE.Mesh(finGeo, finMat);
  topFin.position.set(0.05, 0.35, 0); topFin.scale.set(0.8, 1, 0.35);
  const sideFinL = new THREE.Mesh(finGeo, finMat.clone());
  sideFinL.position.set(0.1, -0.05, 0.25); sideFinL.rotation.x = Math.PI/2.4; sideFinL.scale.set(0.7,1,0.3);
  const sideFinR = new MeshMirror(sideFinL);
  function MeshMirror(m){ const c = m.clone(); c.position.z = -0.25; c.rotation.x = -Math.PI/2.4; return c; }

  const f = new THREE.Group();
  f.add(body, tail, topFin, sideFinL, sideFinR);
  f.scale.setScalar(scale);

  const a = Math.random()*Math.PI*2, r = 3 + Math.random()*10;
  f.userData = {
    pos: new THREE.Vector3(Math.cos(a)*r, -1 + Math.random()*5, Math.sin(a)*r - 2),
    vel: new THREE.Vector3((Math.random()-0.5)*2, 0, (Math.random()-0.5)*2),
    phase: Math.random()*Math.PI*2,
    hue,
    wander: Math.random()*Math.PI*2,
    scared: 0
  };
  f.position.copy(f.userData.pos);
  fishes.push(f);
  fishGroup.add(f);
}

// ---------- Bubbles ----------
const bubbles = [];
const bubbleMat = new THREE.MeshPhongMaterial({ color: 0xbfeaff, transparent: true, opacity: 0.4, shininess: 100 });
for (let i=0;i<40;i++){
  const b = new THREE.Mesh(new THREE.SphereGeometry(0.05 + Math.random()*0.09, 8, 8), bubbleMat);
  b.userData = {
    x: (Math.random()-0.5)*20, z: (Math.random()-0.5)*20 - 2,
    y: -3 + Math.random()*12, spd: 0.4 + Math.random()*0.9,
    wob: Math.random()*6.28
  };
  bubbles.push(b); scene.add(b);
}

// ---------- Floating motes ----------
const moteGeo = new THREE.BufferGeometry();
const moteCount = 300;
const mp = new Float32Array(moteCount*3);
for (let i=0;i<moteCount;i++){
  mp[i*3] = (Math.random()-0.5)*30;
  mp[i*3+1] = -3 + Math.random()*12;
  mp[i*3+2] = (Math.random()-0.5)*30 - 2;
}
moteGeo.setAttribute('position', new THREE.BufferAttribute(mp, 3));
const motes = new THREE.Points(moteGeo, new THREE.PointsMaterial({ color: 0xcde8ff, size: 0.06, transparent: true, opacity: 0.6 }));
scene.add(motes);

// ---------- Mouse "finger" in the water ----------
const finger = new THREE.Mesh(
  new THREE.SphereGeometry(0.5, 16, 16),
  new THREE.MeshPhongMaterial({ color: 0xffe9b0, emissive: 0x553300, transparent: true, opacity: 0.35 })
);
scene.add(finger);

// ---------- Interaction ----------
const raycaster = new THREE.Raycaster();
const mouseNDC = new THREE.Vector2(10, 10); // off-screen initially
const waterPlane = new THREE.Plane(new THREE.Vector3(0,1,0), 0);
let mouseWorld = new THREE.Vector3(0, 0.5, 0);
let feedSpots = []; // food positions fish are attracted to
let hasMouse = false;

function updateMouse(e){
  mouseNDC.x = (e.clientX / innerWidth) * 2 - 1;
  mouseNDC.y = -(e.clientY / innerHeight) * 2 + 1;
  hasMouse = true;
}
addEventListener('pointermove', updateMouse);

addEventListener('pointerdown', (e) => {
  updateMouse(e);
  // drop food at mouse position — fish rush toward it briefly
  raycaster.setFromCamera(mouseNDC, camera);
  const pt = new THREE.Vector3();
  if (raycaster.ray.intersectPlane(waterPlane, pt)){
    feedSpots.push({ pos: new THREE.Vector3(pt.x, 0, pt.z), t: 5 });
    // visual food puff
    const puff = new THREE.Group();
    for (let i=0;i<8;i++){
      const p = new THREE.Mesh(new THREE.SphereGeometry(0.05, 6, 6),
        new THREE.MeshStandardMaterial({ color: 0xd9a05a }));
      p.position.set((Math.random()-0.5)*0.8, Math.random()*0.6, (Math.random()-0.5)*0.8);
      puff.add(p);
    }
    puff.position.copy(pt).setY(0.2);
    puff.userData = { t: 5, food: true };
    feedSpots[feedSpots.length-1].puff = puff;
    scene.add(puff);
  }
});

// keyboard not required, but let's rotate view with drag-like keys? Keep simple.

// ---------- Animation ----------
const clock = new THREE.Clock();
let time = 0;

// fish tank bounds
const BOUND = 13;
const Y_MIN = -2.4, Y_MAX = 7.5;

function animate(){
  requestAnimationFrame(animate);
  const dt = Math.min(clock.getDelta(), 0.05);
  time += dt;

  // raycast mouse to horizontal plane at y=0.. approximate depth using camera-facing plane at z=0
  if (hasMouse){
    raycaster.setFromCamera(mouseNDC, camera);
    const hit = raycaster.ray.intersectPlane(waterPlane, new THREE.Vector3());
    if (hit) mouseWorld.copy(hit);
  }
  finger.position.lerp(new THREE.Vector3(mouseWorld.x, Math.max(-2, Math.min(7, mouseWorld.y + 1)), mouseWorld.z), 0.2);

  // decay feed spots
  feedSpots = feedSpots.filter(s => { s.t -= dt; if (s.puff){ s.puff.userData.t = s.t; s.puff.children.forEach((c,i)=>{ c.position.y += dt*0.15; c.scale.setScalar(Math.max(0.01, Math.min(1, s.t))); }); } if (s.t <= 0){ if (s.puff) scene.remove(s.puff); return false; } return true; });
  const nearestFeed = feedSpots.length ? feedSpots[feedSpots.length-1].pos : null;

  // fish update
  for (const f of fishes){
    const u = f.userData;
    const p = u.pos, v = u.vel;

    // steering: wander
    u.wander += dt * 0.7;
    const wanderDir = new THREE.Vector3(Math.sin(u.wander), Math.sin(u.wander*0.6)*0.3, Math.cos(u.wander*1.3));
    v.addScaledVector(wanderDir, dt * 1.6);

    // flee from mouseWorld (in x/z, mild in y)
    const toMouse = new THREE.Vector3().subVectors(p, new THREE.Vector3(mouseWorld.x, p.y, mouseWorld.z));
    const dist = toMouse.length();
    const scareR = 4.5;
    if (hasMouse && dist < scareR){
      const strength = (1 - dist/scareR) * 14;
      toMouse.normalize();
      v.addScaledVector(toMouse, strength * dt);
      u.scared = Math.min(1, u.scared + dt*4);
    } else {
      u.scared = Math.max(0, u.scared - dt*1.5);
    }

    // attracted to food
    if (nearestFeed){
      const toFood = new THREE.Vector3().subVectors(nearestFeed, p);
      if (toFood.length() < 14){
        toFood.normalize();
        v.addScaledVector(toFood, dt * 5);
      }
    }

    // schooling-lite: mild pull toward center
    v.addScaledVector(new THREE.Vector3().subVectors(new THREE.Vector3(0, 2, -2), p), dt * 0.25);

    // bounds
    if (Math.abs(p.x) > BOUND) v.x += (Math.sign(-p.x) * (Math.abs(p.x)-BOUND) * 3) * dt * 3;
    if (Math.abs(p.z) > BOUND) v.z += (Math.sign(-p.z) * (Math.abs(p.z)-BOUND) * 3) * dt * 3;
    if (p.y < Y_MIN) v.y += (Y_MIN - p.y) * 2 * dt * 3;
    if (p.y > Y_MAX) v.y += (Y_MAX - p.y) * 2 * dt * 3;

    // drag & speed clamp (scared fish swim faster)
    const maxSpd = 2.2 + u.scared*4;
    v.multiplyScalar(1 - dt * (1.2 + u.scared*0.5));
    if (v.length() > maxSpd) v.setLength(maxSpd);
    if (v.length() < 0.6) v.setLength(0.6);

    p.addScaledVector(v, dt);

    // orient fish along velocity
    f.position.copy(p);
    const look = new THREE.Vector3().addVectors(p, v);
    if (look.distanceToSquared(p) > 0.0001) f.lookAt(look);
    // bank/roll into turn + tail wiggle
    u.phase += dt * (4 + v.length()*2 + u.scared*6);
    f.rotation.z = 0; // keep simple: apply wiggle to scale
    const wig = Math.sin(u.phase) * 0.12;
    f.children[1].rotation.z = Math.PI/2 + wig;           // tail swings in local plane
    f.children[1].rotation.y = wig * 1.2;
    f.children[3].rotation.z = Math.sin(time*3 + u.phase)*0.2;
    f.children[4].rotation.z = -Math.sin(time*3 + u.phase)*0.2;
  }

  // camera gentle drift
  const cx = Math.sin(time*0.1)*1.5;
  camera.position.x += (cx - camera.position.x)*0.02;
  camera.lookAt(0, 1.5, -2);

  // water shimmer
  water.position.y = 9 + Math.sin(time*0.7)*0.06;

  // plants sway
  for (const b of plants){
    b.rotation.z = Math.sin(time*1.1 + b.userData.phase) * 0.14;
    b.rotation.x = Math.cos(time*0.8 + b.userData.phase) * 0.1;
  }

  // bubbles rise
  for (const b of bubbles){
    const u = b.userData;
    u.y += u.spd * dt;
    u.wob += dt * 3;
    b.position.set(u.x + Math.sin(u.wob)*0.3, u.y, u.z + Math.cos(u.wob*0.7)*0.3);
    if (u.y > 8.8){ u.y = -3; u.x = (Math.random()-0.5)*20; u.z = (Math.random()-0.5)*20 - 2; }
  }

  // motes drift
  const marr = moteGeo.attributes.position.array;
  for (let i=0;i<moteCount;i++){
    marr[i*3+1] += dt*0.08;
    if (marr[i*3+1] > 9) marr[i*3+1] = -3;
  }
  moteGeo.attributes.position.needsUpdate = true;

  renderer.render(scene, camera);
}
animate();

addEventListener('resize', () => {
  camera.aspect = innerWidth/innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(innerWidth, innerHeight);
});
</script>
</body>
</html>
Reasoning trace (63 tokens)
Build a 3D aquarium with Three.js, fish fleeing from mouse. Use import map. Fish made from simple geometry (cones/ellipsoids). Raycast mouse to water plane, fish flee from that point. Add caustics-ish lighting, bubbles, plants, sand. Self-contained.