Models 44

DeepSeek V4 Flash 0423

by DeepSeekreasoning defaultClean
Open in new window

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

How it went

Total time
25.1 s
Cost
$0.0008
Output tokens
4,630
Spent thinking
0 tokens
Speed
189.6 tok/s
Console errors
0
First token after
643 ms
First visible text after
643 ms
Prompt tokens
434
Code size
15.0 KB
Finish reason
stop
Served by
Wafer
Model id
deepseek/deepseek-v4-flash
Reasoning sent
model default
Max output
393,216 tokens
Generated
Nov 13, 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 · 457 lines

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
  <title>3D Aquarium – fish avoid mouse</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    body {
      background: #0a1a2b;
      overflow: hidden;
      font-family: system-ui, -apple-system, sans-serif;
    }
    canvas {
      display: block;
      width: 100vw;
      height: 100vh;
      cursor: default;
    }
    #overlay {
      position: fixed;
      top: 0; left: 0; width: 100%; height: 100%;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      pointer-events: none;
      color: white;
      text-shadow: 0 2px 12px rgba(0,0,0,0.8);
      z-index: 10;
      transition: opacity 1s ease;
    }
    #overlay h1 {
      font-size: 2.6rem;
      font-weight: 400;
      letter-spacing: 4px;
      margin-bottom: 0.75rem;
      background: rgba(0,30,50,0.5);
      padding: 0.4rem 1.8rem;
      border-radius: 60px;
      backdrop-filter: blur(4px);
    }
    #overlay p {
      font-size: 1.2rem;
      opacity: 0.8;
      background: rgba(0,0,0,0.25);
      padding: 0.3rem 1.2rem;
      border-radius: 30px;
    }
    #overlay.hidden {
      opacity: 0;
      pointer-events: none;
    }
    /* small hint on mobiles */
    @media (max-width: 600px) {
      #overlay h1 { font-size: 1.8rem; padding: 0.2rem 1rem; }
      #overlay p { font-size: 1rem; }
    }
  </style>
  <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>
</head>
<body>
  <div id="overlay">
    <h1>🐟 Aquarium</h1>
    <p>move mouse • fish swim away</p>
  </div>

  <script type="module">
    import * as THREE from 'three';
    import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
    import { CSS2DRenderer, CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js';

    // ---------- setup ----------
    const scene = new THREE.Scene();
    scene.background = new THREE.Color(0x0a2a3a);
    scene.fog = new THREE.FogExp2(0x0a2a3a, 0.007);

    const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 100);
    camera.position.set(12, 6, 18);
    camera.lookAt(0, 0, 0);

    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.shadowMap.enabled = true;
    renderer.shadowMap.type = THREE.PCFSoftShadowMap;
    renderer.toneMapping = THREE.ACESFilmicToneMapping;
    renderer.toneMappingExposure = 1.2;
    document.body.prepend(renderer.domElement);

    // optional CSS2D for labels (not used, but import shows we can)
    // just keep it simple

    // ---------- lighting ----------
    const ambient = new THREE.AmbientLight(0x446688, 0.6);
    scene.add(ambient);

    const mainLight = new THREE.DirectionalLight(0xffeedd, 2.2);
    mainLight.position.set(8, 20, 10);
    mainLight.castShadow = true;
    mainLight.shadow.mapSize.width = 1024;
    mainLight.shadow.mapSize.height = 1024;
    scene.add(mainLight);

    const backLight = new THREE.DirectionalLight(0x88ccff, 0.9);
    backLight.position.set(-5, 0, -10);
    scene.add(backLight);

    const fillLight = new THREE.PointLight(0x66aaff, 0.5);
    fillLight.position.set(0, 6, 6);
    scene.add(fillLight);

    // ---------- environment: water effect & background particles ----------
    // subtle caustic-like circles
    const particleGeo = new THREE.BufferGeometry();
    const count = 600;
    const pos = new Float32Array(count * 3);
    for (let i = 0; i < count; i++) {
      const r = 12 + Math.random() * 14;
      const theta = Math.random() * Math.PI * 2;
      const phi = Math.random() * Math.PI - Math.PI/2;
      pos[i*3] = Math.cos(theta) * Math.cos(phi) * r;
      pos[i*3+1] = Math.sin(phi) * r * 0.6 + 1;
      pos[i*3+2] = Math.sin(theta) * Math.cos(phi) * r;
    }
    particleGeo.setAttribute('position', new THREE.BufferAttribute(pos, 3));
    const particleMat = new THREE.PointsMaterial({
      color: 0x88ccff,
      size: 0.12,
      transparent: true,
      opacity: 0.25,
      blending: THREE.AdditiveBlending,
    });
    const particles = new THREE.Points(particleGeo, particleMat);
    scene.add(particles);

    // ground – sandy with pebbles
    const groundGeo = new THREE.CircleGeometry(14, 40);
    const groundMat = new THREE.MeshStandardMaterial({
      color: 0x5c8a6b,
      roughness: 0.9,
      metalness: 0.1,
    });
    const ground = new THREE.Mesh(groundGeo, groundMat);
    ground.rotation.x = -Math.PI / 2;
    ground.position.y = -2.4;
    ground.receiveShadow = true;
    scene.add(ground);

    // some rocks / coral
    for (let i = 0; i < 22; i++) {
      const size = 0.3 + Math.random() * 0.8;
      const rock = new THREE.Mesh(
        new THREE.DodecahedronGeometry(size * (0.7 + Math.random()*0.6), 0),
        new THREE.MeshStandardMaterial({ color: 0xc97a5e + Math.floor(Math.random()*0x553322), roughness: 0.8 })
      );
      const angle = Math.random() * Math.PI * 2;
      const rad = 3 + Math.random() * 8;
      rock.position.set(
        Math.cos(angle) * rad,
        -2.4 + size * 0.3,
        Math.sin(angle) * rad
      );
      rock.rotation.set(Math.random(), Math.random(), Math.random());
      rock.castShadow = true;
      rock.receiveShadow = true;
      scene.add(rock);
    }

    // seaweed-like stems (simple cylinders)
    for (let i = 0; i < 40; i++) {
      const height = 0.5 + Math.random() * 1.8;
      const stem = new THREE.Mesh(
        new THREE.CylinderGeometry(0.06, 0.09, height, 4),
        new THREE.MeshStandardMaterial({ color: 0x4c9a6a, roughness: 0.7 })
      );
      const angle = Math.random() * Math.PI * 2;
      const rad = 2 + Math.random() * 9;
      stem.position.set(
        Math.cos(angle) * rad,
        -2.4 + height/2,
        Math.sin(angle) * rad
      );
      stem.rotation.x = (Math.random() - 0.5) * 0.5;
      stem.rotation.z = (Math.random() - 0.5) * 0.5;
      stem.castShadow = true;
      scene.add(stem);
    }

    // ---------- fish ----------
    const fishGroup = new THREE.Group();
    scene.add(fishGroup);

    // create a simple fish mesh (reusable)
    function createFishBody(color = 0xff8844) {
      const group = new THREE.Group();
      
      // body (ellipsoid)
      const bodyGeo = new THREE.SphereGeometry(0.6, 10, 8);
      const bodyMat = new THREE.MeshStandardMaterial({ color, roughness: 0.3, metalness: 0.2 });
      const body = new THREE.Mesh(bodyGeo, bodyMat);
      body.scale.set(1.3, 0.8, 0.7);
      body.castShadow = true;
      group.add(body);

      // tail
      const tailMat = new THREE.MeshStandardMaterial({ color: 0xdd8844, roughness: 0.6 });
      const tail = new THREE.Mesh(new THREE.ConeGeometry(0.35, 0.6, 4), tailMat);
      tail.position.set(-0.8, 0, 0);
      tail.rotation.z = Math.PI/2;
      group.add(tail);

      // dorsal fin
      const finMat = new THREE.MeshStandardMaterial({ color: 0xdd9955, transparent: true, opacity: 0.7 });
      const fin = new THREE.Mesh(new THREE.ConeGeometry(0.2, 0.35, 4), finMat);
      fin.position.set(0.1, 0.5, 0);
      fin.rotation.x = 0.3;
      group.add(fin);

      // eyes
      const eyeMat = new THREE.MeshStandardMaterial({ color: 0xffffff });
      const pupilMat = new THREE.MeshStandardMaterial({ color: 0x222222 });
      const eyeGeo = new THREE.SphereGeometry(0.16, 8, 8);
      const pupilGeo = new THREE.SphereGeometry(0.08, 8, 8);
      const eyeL = new THREE.Mesh(eyeGeo, eyeMat);
      eyeL.position.set(0.7, 0.22, 0.35);
      group.add(eyeL);
      const pupilL = new THREE.Mesh(pupilGeo, pupilMat);
      pupilL.position.set(0.85, 0.22, 0.38);
      group.add(pupilL);
      const eyeR = new THREE.Mesh(eyeGeo, eyeMat);
      eyeR.position.set(0.7, 0.22, -0.35);
      group.add(eyeR);
      const pupilR = new THREE.Mesh(pupilGeo, pupilMat);
      pupilR.position.set(0.85, 0.22, -0.38);
      group.add(pupilR);

      return group;
    }

    // create 24 fish with random colors and positions
    const fishObjects = [];
    const fishColors = [0xff8844, 0x44aaff, 0xff4d6d, 0x66ddaa, 0xffbb33, 0xcc66cc, 0x88aaff, 0xff9966];

    for (let i = 0; i < 26; i++) {
      const color = fishColors[Math.floor(Math.random() * fishColors.length)];
      const fish = createFishBody(color);
      
      // random position inside aquarium bounds
      const radius = 3 + Math.random() * 7;
      const angle = Math.random() * Math.PI * 2;
      const y = -1.5 + Math.random() * 3.5;
      fish.position.set(
        Math.cos(angle) * radius,
        y,
        Math.sin(angle) * radius
      );
      
      // random orientation
      fish.rotation.y = Math.random() * Math.PI * 2;
      
      // store some custom data
      fish.userData = {
        speed: 0.3 + Math.random() * 0.4,
        angle: Math.random() * Math.PI * 2,
        verticalOsc: Math.random() * 0.6,
        verticalPhase: Math.random() * 6.28,
        radius: radius,
        centerY: y,
        swimDir: 1,
        turnTimer: 0,
        avoidSpeed: 0,
        avoidDir: 0,
        panic: 0,
      };
      
      fishGroup.add(fish);
      fishObjects.push(fish);
    }

    // ---------- tiny floating bubbles ----------
    const bubbleGeo = new THREE.BufferGeometry();
    const bCount = 130;
    const bPos = new Float32Array(bCount * 3);
    for (let i = 0; i < bCount; i++) {
      const r = 2 + Math.random() * 10;
      const theta = Math.random() * Math.PI * 2;
      bPos[i*3] = Math.cos(theta) * r;
      bPos[i*3+1] = -2 + Math.random() * 5;
      bPos[i*3+2] = Math.sin(theta) * r;
    }
    bubbleGeo.setAttribute('position', new THREE.BufferAttribute(bPos, 3));
    const bubbleMat = new THREE.PointsMaterial({
      color: 0xaaddff,
      size: 0.08,
      transparent: true,
      opacity: 0.25,
      blending: THREE.AdditiveBlending,
    });
    const bubbles = new THREE.Points(bubbleGeo, bubbleMat);
    scene.add(bubbles);

    // ---------- mouse tracking ----------
    const mouseWorld = new THREE.Vector3(0, 0, 10);
    const raycaster = new THREE.Raycaster();
    const pointer = new THREE.Vector2();

    function updateMouse(clientX, clientY) {
      pointer.x = (clientX / window.innerWidth) * 2 - 1;
      pointer.y = -(clientY / window.innerHeight) * 2 + 1;
      
      raycaster.setFromCamera(pointer, camera);
      // project onto plane y = 0 (approx water level)
      const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);
      const intersectPoint = new THREE.Vector3();
      raycaster.ray.intersectPlane(plane, intersectPoint);
      if (intersectPoint) {
        mouseWorld.copy(intersectPoint);
      } else {
        // fallback
        mouseWorld.set(0, 0, 10);
      }
    }

    window.addEventListener('mousemove', (e) => {
      updateMouse(e.clientX, e.clientY);
    });
    window.addEventListener('touchmove', (e) => {
      if (e.touches.length > 0) {
        updateMouse(e.touches[0].clientX, e.touches[0].clientY);
      }
    }, { passive: true });
    // also on touch start
    window.addEventListener('touchstart', (e) => {
      if (e.touches.length > 0) {
        updateMouse(e.touches[0].clientX, e.touches[0].clientY);
      }
    }, { passive: true });

    // ---------- hide overlay on interaction ----------
    const overlay = document.getElementById('overlay');
    function hideOverlay() {
      overlay.classList.add('hidden');
    }
    window.addEventListener('click', hideOverlay);
    window.addEventListener('touchstart', hideOverlay, { passive: true });
    window.addEventListener('keydown', hideOverlay);

    // ---------- animation loop ----------
    const clock = new THREE.Clock();

    function animate() {
      const delta = Math.min(clock.getDelta(), 0.05);
      const time = clock.elapsedTime;

      // rotate particles slowly
      particles.rotation.y += 0.0002;
      bubbles.rotation.y += 0.0005;

      // animate fish
      const avoidRadius = 3.2; // distance that triggers avoidance
      const strongAvoidRadius = 1.8;

      fishObjects.forEach((fish, idx) => {
        const ud = fish.userData;
        const pos = fish.position;
        
        // distance from mouse in XZ plane
        const dx = pos.x - mouseWorld.x;
        const dz = pos.z - mouseWorld.z;
        const dist = Math.sqrt(dx*dx + dz*dz);

        let avoidX = 0, avoidZ = 0;
        let panic = 0;

        if (dist < avoidRadius) {
          // fish swims away from mouse
          const strength = Math.max(0, 1 - dist / avoidRadius);
          const dirX = dx / (dist + 0.001);
          const dirZ = dz / (dist + 0.001);
          const factor = strength * 1.8;
          avoidX = dirX * factor;
          avoidZ = dirZ * factor;
          panic = strength;
          
          // extra speed
          ud.avoidSpeed = Math.min(ud.avoidSpeed + 0.6 * delta, 2.0);
        } else {
          ud.avoidSpeed = Math.max(0, ud.avoidSpeed - 0.2 * delta);
        }

        // normal idle movement: gentle circle & vertical bob
        ud.angle += 0.005 + ud.speed * 0.002;
        const targetX = Math.cos(ud.angle + idx) * ud.radius;
        const targetZ = Math.sin(ud.angle + idx) * ud.radius;
        const targetY = ud.centerY + Math.sin(time * 0.5 + ud.verticalPhase) * ud.verticalOsc * 0.7;

        // blend towards target (smooth)
        const lerpFactor = 0.02 + panic * 0.06;
        pos.x += (targetX - pos.x) * lerpFactor;
        pos.z += (targetZ - pos.z) * lerpFactor;
        pos.y += (targetY - pos.y) * lerpFactor * 0.5;

        // apply avoidance (additive)
        pos.x += avoidX * delta * 2.8;
        pos.z += avoidZ * delta * 2.8;

        // rotation: face movement direction
        const dir = new THREE.Vector3(
          targetX - pos.x + avoidX * 0.5,
          0,
          targetZ - pos.z + avoidZ * 0.5
        );
        if (dir.length() > 0.01) {
          const targetRot = Math.atan2(dir.x, dir.z);
          let diff = targetRot - fish.rotation.y;
          while (diff > Math.PI) diff -= Math.PI * 2;
          while (diff < -Math.PI) diff += Math.PI * 2;
          fish.rotation.y += diff * 0.1;
        }

        // slight body tilt when avoiding
        fish.rotation.z = -avoidX * 0.08;
        fish.rotation.x = avoidZ * 0.06;
      });

      // camera subtle drift
      camera.position.x = 12 + Math.sin(time * 0.02) * 1.2;
      camera.position.z = 18 + Math.cos(time * 0.023) * 1.2;
      camera.lookAt(0, 0.5, 0);

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

    animate();

    // ---------- resize ----------
    window.addEventListener('resize', () => {
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
      renderer.setSize(window.innerWidth, window.innerHeight);
    });

    // ---------- pointer click to hide overlay ----------
    // also hide after 2 sec anyway (auto)
    setTimeout(() => {
      overlay.classList.add('hidden');
    }, 3000);

    console.log('🐠 3D aquarium ready – move mouse to scare fish!');
  </script>
</body>
</html>