DeepSeek V4.1 Flash 1017
by DeepSeekReasoningClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 18.3 s
- Cost
- $0.0026
- Output tokens
- 5,163
- Spent thinking
- 0 tokens
- Speed
- 287.6 tok/s
- Console errors
- 0
- First token after
- 366 ms
- First visible text after
- 366 ms
- Prompt tokens
- 573
- Code size
- 14.6 KB
- Finish reason
- stop
- Served by
- Wafer
- Model id
deepseek/deepseek-v4.1-flash-1017- Reasoning sent
{"effort":"none"}- Max output
- 64,000 tokens
- Generated
- Nov 11, 2026
What it was asked
The prompt
Build a low-poly 3D scene of a campfire in a forest clearing at night, with Three.js in a single HTML file. Load Three.js only through this import map (do not use any other URL or version): <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> Requirements: - A ground with a few low-poly rocks and logs around a campfire in the center. - At least 30 low-poly trees placed randomly around the clearing (not on the fire). - The campfire has animated flames and a warm point light that flickers and casts shadows. - Sparks rising from the fire as a simple particle system. - A dark night sky with stars and a moon, plus fog that fades the distant trees. - OrbitControls to look around, with limits so the camera stays above the ground. - The renderer fills the window and handles resizing correctly.
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 · 403 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Campfire in the Forest Clearing</title>
<style>
html, body { margin: 0; padding: 0; overflow: hidden; background: #05070d; }
canvas { display: block; }
#hint {
position: fixed; left: 50%; bottom: 22px; transform: translateX(-50%);
font-family: system-ui, -apple-system, sans-serif; font-size: 13px;
color: #ffd9a0; background: rgba(20, 12, 6, 0.55); border: 1px solid rgba(255, 190, 120, 0.25);
padding: 6px 14px; border-radius: 999px; letter-spacing: .04em;
pointer-events: none; user-select: none; backdrop-filter: blur(3px);
transition: opacity 1s ease;
}
</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="hint">drag to look around · scroll to zoom</div>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
/* ---------- Renderer ---------- */
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1.05;
document.body.appendChild(renderer.domElement);
/* ---------- Scene & Fog ---------- */
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x05070d);
scene.fog = new THREE.FogExp2(0x0a0e18, 0.024);
/* ---------- Camera ---------- */
const camera = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight, 0.1, 500);
camera.position.set(9, 5.5, 12);
/* ---------- Controls ---------- */
const controls = new OrbitControls(camera, renderer.domElement);
controls.target.set(0, 1.2, 0);
controls.enableDamping = true;
controls.dampingFactor = 0.06;
controls.minDistance = 4;
controls.maxDistance = 34;
controls.maxPolarAngle = Math.PI * 0.495; // keeps camera above ground
controls.minPolarAngle = 0.15;
controls.enablePan = false;
controls.update();
/* ---------- Lights ---------- */
const ambient = new THREE.AmbientLight(0x223055, 0.35);
scene.add(ambient);
const moonLight = new THREE.DirectionalLight(0x8fa8d8, 0.55);
moonLight.position.set(-40, 60, -30);
moonLight.castShadow = true;
moonLight.shadow.mapSize.set(1024, 1024);
moonLight.shadow.camera.left = -40;
moonLight.shadow.camera.right = 40;
moonLight.shadow.camera.top = 40;
moonLight.shadow.camera.bottom = -40;
moonLight.shadow.camera.far = 160;
scene.add(moonLight);
const fireLight = new THREE.PointLight(0xff7a2a, 6, 30, 2);
fireLight.position.set(0, 1.6, 0);
fireLight.castShadow = true;
fireLight.shadow.mapSize.set(1024, 1024);
fireLight.shadow.bias = -0.002;
fireLight.shadow.camera.far = 30;
scene.add(fireLight);
/* ---------- Ground ---------- */
const groundGeo = new THREE.PlaneGeometry(160, 160, 40, 40);
groundGeo.rotateX(-Math.PI / 2);
const gp = groundGeo.attributes.position;
for (let i = 0; i < gp.count; i++) {
const x = gp.getX(i), z = gp.getZ(i);
const d = Math.sqrt(x * x + z * z);
const bump = Math.sin(x * 0.35) * Math.cos(z * 0.32) * 0.22
+ Math.sin(x * 0.11 + z * 0.17) * 0.4;
// flatten near the fire
const f = Math.min(1, Math.max(0, (d - 3) / 6));
gp.setY(i, bump * f + (d < 60 ? 0 : 0));
}
groundGeo.computeVertexNormals();
const groundMat = new THREE.MeshStandardMaterial({
color: 0x1c2a1a, flatShading: true, roughness: 1, metalness: 0
});
const ground = new THREE.Mesh(groundGeo, groundMat);
ground.receiveShadow = true;
scene.add(ground);
// dirt patch under the fire
const dirtGeo = new THREE.CircleGeometry(3.2, 24);
dirtGeo.rotateX(-Math.PI / 2);
const dirt = new THREE.Mesh(dirtGeo, new THREE.MeshStandardMaterial({
color: 0x2a1f14, roughness: 1, flatShading: true
}));
dirt.position.y = 0.02;
dirt.receiveShadow = true;
scene.add(dirt);
/* ---------- Fire pit ring of stones ---------- */
const stoneMat = new THREE.MeshStandardMaterial({ color: 0x55585c, flatShading: true, roughness: 0.95 });
const ringCount = 11;
const fireRing = new THREE.Group();
for (let i = 0; i < ringCount; i++) {
const a = (i / ringCount) * Math.PI * 2;
const s = new THREE.DodecahedronGeometry(0.28 + Math.random() * 0.12, 0);
const m = new THREE.Mesh(s, stoneMat);
m.position.set(Math.cos(a) * 1.15, 0.18, Math.sin(a) * 1.15);
m.rotation.set(Math.random() * 3, Math.random() * 3, Math.random() * 3);
m.scale.y = 0.75;
m.castShadow = true; m.receiveShadow = true;
fireRing.add(m);
}
scene.add(fireRing);
/* ---------- Logs around the fire ---------- */
const logMat = new THREE.MeshStandardMaterial({ color: 0x3a2414, flatShading: true, roughness: 1 });
function makeLog(len, rad) {
const g = new THREE.CylinderGeometry(rad, rad * 1.05, len, 6);
g.rotateZ(Math.PI / 2);
const m = new THREE.Mesh(g, logMat);
m.castShadow = true; m.receiveShadow = true;
return m;
}
for (let i = 0; i < 5; i++) {
const a = (i / 5) * Math.PI * 2 + 0.3;
const log = makeLog(2.6, 0.18);
log.position.set(Math.cos(a) * 0.55, 0.35 + i * 0.09, Math.sin(a) * 0.55);
log.rotation.y = a;
log.rotation.z = 0.22;
scene.add(log);
}
// a couple of bigger logs out in the clearing
for (let i = 0; i < 5; i++) {
const a = Math.random() * Math.PI * 2;
const r = 3.5 + Math.random() * 4;
const log = makeLog(1.8 + Math.random() * 1.2, 0.22 + Math.random() * 0.08);
log.position.set(Math.cos(a) * r, 0.22, Math.sin(a) * r);
log.rotation.y = Math.random() * Math.PI;
log.rotation.z = Math.PI / 2;
scene.add(log);
}
/* ---------- Rocks around clearing ---------- */
const rockMat = new THREE.MeshStandardMaterial({ color: 0x4b4e55, flatShading: true, roughness: 1 });
for (let i = 0; i < 22; i++) {
const a = Math.random() * Math.PI * 2;
const r = 2.6 + Math.random() * 12;
const s = 0.3 + Math.random() * 0.8;
const geo = new THREE.DodecahedronGeometry(s, 0);
const m = new THREE.Mesh(geo, rockMat);
m.position.set(Math.cos(a) * r, s * 0.45, Math.sin(a) * r);
m.rotation.set(Math.random() * 3, Math.random() * 3, Math.random() * 3);
m.scale.set(1, 0.7 + Math.random() * 0.4, 1);
m.castShadow = true; m.receiveShadow = true;
scene.add(m);
}
/* ---------- Low-poly trees ---------- */
const trunkMat = new THREE.MeshStandardMaterial({ color: 0x2c1c10, flatShading: true, roughness: 1 });
const leafColors = [0x14351c, 0x1a4022, 0x0f2a17, 0x1d4a26];
const leafMats = leafColors.map(c => new THREE.MeshStandardMaterial({ color: c, flatShading: true, roughness: 1 }));
function makeTree(x, z, scale) {
const tree = new THREE.Group();
const h = 3.5 + Math.random() * 3.5;
const trunkH = h * 0.45;
const trunk = new THREE.Mesh(new THREE.CylinderGeometry(0.16, 0.26, trunkH, 5), trunkMat);
trunk.position.y = trunkH / 2;
trunk.castShadow = true; trunk.receiveShadow = true;
tree.add(trunk);
const layers = 3;
for (let l = 0; l < layers; l++) {
const r = (1.35 - l * 0.32) * (0.85 + Math.random() * 0.3);
const lh = h * (0.34 - l * 0.05);
const cone = new THREE.Mesh(new THREE.ConeGeometry(r, lh, 6), leafMats[(l + Math.floor(Math.random() * 4)) % 4]);
cone.position.y = trunkH + l * lh * 0.55 + lh / 2;
cone.rotation.y = Math.random() * Math.PI;
cone.castShadow = true; cone.receiveShadow = true;
tree.add(cone);
}
tree.position.set(x, 0, z);
tree.scale.setScalar(scale);
return tree;
}
const treeCount = 42;
let placed = 0;
let guard = 0;
while (placed < treeCount && guard < 2000) {
guard++;
const a = Math.random() * Math.PI * 2;
const r = 6 + Math.random() * 30;
const x = Math.cos(a) * r, z = Math.sin(a) * r;
// no trees in the clearing
const d = Math.sqrt(x * x + z * z);
if (d < 6) continue;
const s = 0.8 + Math.random() * 0.8;
scene.add(makeTree(x, z, s));
placed++;
}
/* ---------- Stars ---------- */
function makeStars() {
const N = 1800;
const pos = new Float32Array(N * 3);
const col = new Float32Array(N * 3);
const c = new THREE.Color();
for (let i = 0; i < N; i++) {
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos(Math.random() * 0.95); // upper hemisphere
const R = 200;
pos[i*3] = R * Math.sin(phi) * Math.cos(theta);
pos[i*3+1] = R * Math.cos(phi) + 5;
pos[i*3+2] = R * Math.sin(phi) * Math.sin(theta);
const t = Math.random();
c.setHSL(0.55 + Math.random() * 0.12, 0.15 + Math.random() * 0.25, 0.7 + Math.random() * 0.3);
col[i*3] = c.r; col[i*3+1] = c.g; col[i*3+2] = c.b;
void t;
}
const g = new THREE.BufferGeometry();
g.setAttribute('position', new THREE.BufferAttribute(pos, 3));
g.setAttribute('color', new THREE.BufferAttribute(col, 3));
const m = new THREE.PointsMaterial({
size: 1.1, sizeAttenuation: true, vertexColors: true,
transparent: true, opacity: 0.95, depthWrite: false,
fog: false, blending: THREE.AdditiveBlending
});
return new THREE.Points(g, m);
}
const stars = makeStars();
scene.add(stars);
/* ---------- Moon ---------- */
const moonGroup = new THREE.Group();
const moonGeo = new THREE.IcosahedronGeometry(6, 1);
const moonMat = new THREE.MeshBasicMaterial({ color: 0xf2f4e0, fog: false });
const moon = new THREE.Mesh(moonGeo, moonMat);
moonGroup.add(moon);
// soft halo
const haloMat = new THREE.MeshBasicMaterial({ color: 0x9fb6e0, transparent: true, opacity: 0.12, fog: false, blending: THREE.AdditiveBlending, depthWrite: false });
const halo = new THREE.Mesh(new THREE.IcosahedronGeometry(11, 1), haloMat);
moonGroup.add(halo);
moonGroup.position.set(-70, 80, -110);
scene.add(moonGroup);
/* ---------- Flames ---------- */
const flameGroup = new THREE.Group();
scene.add(flameGroup);
const flames = [];
const flameColors = [0xffcf5a, 0xff9a2e, 0xff5c1a, 0xffe9a8];
for (let i = 0; i < 7; i++) {
const geo = new THREE.ConeGeometry(0.32 + Math.random() * 0.15, 1.1 + Math.random() * 0.7, 5, 1);
geo.translate(0, 0.55, 0);
const mat = new THREE.MeshBasicMaterial({
color: flameColors[i % flameColors.length],
transparent: true, opacity: 0.85, depthWrite: false,
blending: THREE.AdditiveBlending
});
const m = new THREE.Mesh(geo, mat);
const a = Math.random() * Math.PI * 2;
const r = Math.random() * 0.35;
m.position.set(Math.cos(a) * r, 0.35, Math.sin(a) * r);
m.userData = {
baseY: 0.35, phase: Math.random() * Math.PI * 2,
speed: 4 + Math.random() * 4,
amp: 0.15 + Math.random() * 0.2,
scaleBase: 0.85 + Math.random() * 0.4
};
flameGroup.add(m);
flames.push(m);
}
// glowing embers base
const emberGeo = new THREE.SphereGeometry(0.5, 8, 6, 0, Math.PI * 2, 0, Math.PI / 2);
emberGeo.rotateX(Math.PI);
const emberMat = new THREE.MeshBasicMaterial({ color: 0xff6a1a, transparent: true, opacity: 0.7, blending: THREE.AdditiveBlending, depthWrite: false });
const embers = new THREE.Mesh(emberGeo, emberMat);
embers.position.y = 0.1;
embers.scale.y = 0.5;
scene.add(embers);
/* ---------- Sparks ---------- */
const SPARK_COUNT = 160;
const sparkPos = new Float32Array(SPARK_COUNT * 3);
const sparkVel = new Float32Array(SPARK_COUNT * 3);
const sparkLife = new Float32Array(SPARK_COUNT);
const sparkMaxLife = new Float32Array(SPARK_COUNT);
function spawnSpark(i) {
const a = Math.random() * Math.PI * 2;
const r = Math.random() * 0.4;
sparkPos[i*3] = Math.cos(a) * r;
sparkPos[i*3+1] = 0.6 + Math.random() * 0.3;
sparkPos[i*3+2] = Math.sin(a) * r;
sparkVel[i*3] = (Math.random() - 0.5) * 0.6;
sparkVel[i*3+1] = 1.6 + Math.random() * 2.2;
sparkVel[i*3+2] = (Math.random() - 0.5) * 0.6;
sparkLife[i] = 0;
sparkMaxLife[i] = 1.2 + Math.random() * 1.6;
}
for (let i = 0; i < SPARK_COUNT; i++) { spawnSpark(i); sparkLife[i] = Math.random() * sparkMaxLife[i]; }
const sparkGeo = new THREE.BufferGeometry();
sparkGeo.setAttribute('position', new THREE.BufferAttribute(sparkPos, 3));
const sparkColors = new Float32Array(SPARK_COUNT * 3);
for (let i = 0; i < SPARK_COUNT; i++) {
sparkColors[i*3] = 1.0; sparkColors[i*3+1] = 0.6; sparkColors[i*3+2] = 0.2;
}
sparkGeo.setAttribute('color', new THREE.BufferAttribute(sparkColors, 3));
const sparkMat = new THREE.PointsMaterial({
size: 0.11, sizeAttenuation: true, vertexColors: true,
transparent: true, opacity: 0.95, depthWrite: false,
blending: THREE.AdditiveBlending, fog: true
});
const sparks = new THREE.Points(sparkGeo, sparkMat);
scene.add(sparks);
/* ---------- Animate ---------- */
const clock = new THREE.Clock();
const hint = document.getElementById('hint');
let hintFaded = false;
function animate() {
const t = clock.getElapsedTime();
const dt = Math.min(clock.getDelta(), 0.05);
// flames
for (const f of flames) {
const u = f.userData;
const flick = Math.sin(t * u.speed + u.phase) * 0.5 + 0.5;
const flick2 = Math.sin(t * (u.speed * 1.7) + u.phase * 2.3) * 0.5 + 0.5;
f.position.y = u.baseY + flick * u.amp;
f.scale.set(
u.scaleBase * (0.85 + flick * 0.3),
u.scaleBase * (0.8 + flick2 * 0.6),
u.scaleBase * (0.85 + flick * 0.3)
);
f.rotation.y = t * 0.8 + u.phase;
f.material.opacity = 0.55 + flick * 0.4;
}
embers.material.opacity = 0.5 + Math.sin(t * 9) * 0.15;
flameGroup.rotation.y = t * 0.2;
// fire light flicker
const n = Math.sin(t * 11.3) * 0.35 + Math.sin(t * 23.7) * 0.2 + Math.sin(t * 4.1) * 0.3;
fireLight.intensity = 6 + n * 3.5;
fireLight.position.x = Math.sin(t * 9) * 0.15;
fireLight.position.z = Math.cos(t * 7.3) * 0.15;
fireLight.position.y = 1.5 + Math.sin(t * 5) * 0.15;
// sparks
for (let i = 0; i < SPARK_COUNT; i++) {
sparkLife[i] += dt;
if (sparkLife[i] > sparkMaxLife[i]) { spawnSpark(i); continue; }
sparkPos[i*3] += sparkVel[i*3] * dt;
sparkPos[i*3+1] += sparkVel[i*3+1] * dt;
sparkPos[i*3+2] += sparkVel[i*3+2] * dt;
sparkVel[i*3] += Math.sin(t * 2 + i) * 0.4 * dt;
sparkVel[i*3+2] += Math.cos(t * 1.7 + i) * 0.4 * dt;
sparkVel[i*3+1] -= 0.6 * dt;
}
sparkGeo.attributes.position.needsUpdate = true;
// fade sparks by life using a second attribute trick via size
sparkMat.opacity = 0.9;
// stars slow rotation
stars.rotation.y = t * 0.005;
controls.update();
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
animate();
/* fade hint after a few seconds */
setTimeout(() => { if (!hintFaded) { hint.style.opacity = '0'; hintFaded = true; } }, 5000);
/* ---------- Resize ---------- */
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>