Bouncing balls in a heptagon · llama-4-scout
Show 20 numbered balls (1 to 20) dropping from the center of a heptagon that spins 360 degrees every 5 seconds. The balls are affected by gravity and friction, collide with each other, and bounce realistically off the rotating walls; show each ball's spin via the rotation of its number. Implement all collision detection yourself.
This one-shot run produced no runnable artifact.
agent produced no index.html
The transcript below shows what the model did — read it to see why the one shot fell short.
transcript · 2 messages
Show 20 numbered balls (1 to 20) dropping from the center of a heptagon that spins 360 degrees every 5 seconds. The balls are affected by gravity and friction, collide with each other, and bounce realistically off the rotating walls; show each ball's spin via the rotation of its number. Implement all collision detection yourself.
[write(index.html, content='<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Spinning Heptagon with Dropping Balls</title> <style> body { margin: 0; background-color: #f0f0f0; } #canvas { border: 1px solid black; } </style> </head> <body> <canvas id="canvas" width="600" height="600"></canvas> <script> const canvas = document.getElementById("canvas"); const ctx = canvas.getContext("2d"); const numBalls = 20; const ballRadius = 10; const heptagonSize = 200; const gravity = 0.1; const friction = 0.99; const spinSpeed = 360 / 5; // degrees per second let angle = 0; let balls = []; for (let i = 0; i < numBalls; i++) { balls.push({ x: canvas.width / 2 + Math.cos(Math.PI / 7 * i) * heptagonSize / 2, y: canvas.height / 2 + Math.sin(Math.PI / 7 * i) * heptagonSize / 2, vx: Math.random() * 2 - 1, vy: Math.random() * 2 - 1, number: i + 1 }); } function drawHeptagon() { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.save(); ctx.translate(canvas.width / 2, canvas.height / 2); ctx.rotate(angle * Math.PI / 180); ctx.beginPath(); for (let i = 0; i < 7; i++) { const x = Math.cos(Math.PI / 3.5 * i) * heptagonSize / 2; const y = Math.sin(Math.PI / 3.5 * i) * heptagonSize / 2; if (i === 0) { ctx.moveTo(x, y); } else { ctx.lineTo(x, y); } } ctx.closePath(); ctx.stroke(); ctx.restore(); } function drawBalls() { for (let i = 0; i < balls.length; i++) { const ball = balls[i]; ctx.save(); ctx.translate(canvas.width / 2, canvas.height / 2); ctx.rotate(angle * Math.PI / 180); ctx.beginPath(); ctx.arc(ball.x - canvas.width / 2, ball.y - canvas.height / 2, ballRadius, 0, 2 * Math.PI); ctx.fillStyle = "blue"; ctx.fill(); ctx.fillStyle = "white"; ctx.font = "24px Arial"; ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.save(); ctx.translate(ball.x - canvas.width / 2, ball.y - canvas.height / 2); ctx.rotate(Math.atan2(ball.vy, ball.vx)); ctx.fillText(ball.number, 0, 0); ctx.restore(); ctx.restore(); } } function updateBalls() { for (let i = 0; i < balls.length; i++) { const ball = balls[i]; ball.vy += gravity; ball.x += ball.vx; ball.y += ball.vy; // collision with heptagon walls for (let j = 0; j < 7; j++) { const x1 = Math.cos(Math.PI / 3.5 * j) * heptagonSize / 2; const y1 = Math.sin(Math.PI / 3.5 * j) * heptagonSize / 2; const x2 = Math.cos(Math.PI / 3.5 * (j + 1)) * heptagonSize / 2; const y2 = Math.sin(Math.PI / 3.5 * (j + 1)) * heptagonSize / 2; const distance = Math.abs((x2 - x1) * (y1 - ball.y) - (x1 - ball.x) * (y2 - y1)) / Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2); if (distance < ballRadius) { const normalX = (y2 - y1); const normalY = (x1 - x2); const tangentX = (-normalY); const tangentY = normalX; const vNormal = ball.vx * normalX + ball.vy * normalY; const vTangent = ball.vx * tangentX + ball.vy * tangentY; vNormal = -vNormal * friction; ball.vx = vNormal * normalX + vTangent * tangentX; ball.vy = vNormal * normalY + vTangent * tangentY; ball.x -= normalX * (distance - ballRadius); ball.y -= normalY * (distance - ballRadius); } } // collision with other balls for (let j = 0; j < balls.length; j++) { if (i !== j) { const otherBall = balls[j]; const dx = ball.x - otherBall.x; const dy = ball.y - otherBall.y; const distance = Math.sqrt(dx ** 2 + dy ** 2); if (distance < 2 * ballRadius) { const normalX = dx / distance; const normalY = dy / distance; const tangentX = -normalY; const tangentY = normalX; const v1n = ball.vx * normalX + ball.vy * normalY; const v1t = ball.vx * tangentX + ball.vy * tangentY; const v2n = otherBall.vx * normalX + otherBall.vy * normalY; const v2t = otherBall.vx * tangentX + otherBall.vy * tangentY; const v1nAfter = (v1n * (1 - friction) + 2 * friction * v2n) / (1 + friction); const v2nAfter = (v2n * (1 - friction) + 2 * friction * v1n) / (1 + friction); ball.vx = v1nAfter * normalX + v1t * tangentX; ball.vy = v1nAfter * normalY + v1t * tangentY; otherBall.vx = v2nAfter * normalX + v2t * tangentX; otherBall.vy = v2nAfter * normalY + v2t * tangentY; ball.x += normalX * (2 * ballRadius - distance) / 2; ball.y += normalY * (2 * ballRadius - distance) / 2; otherBall.x -= normalX * (2 * ballRadius - distance) / 2; otherBall.y -= normalY * (2 * ballRadius - distance) / 2; } } } } } function animate() { angle += spinSpeed / 60; // adjust for 60fps if (angle >= 360) { angle -= 360; } drawHeptagon(); updateBalls(); drawBalls(); requestAnimationFrame(animate); } animate(); </script> </body> </html> ')])
TAKE IT TO CODE
This run produced no artifact — reuse the prompt with a different model or your own pi-agent run.