27:18Gemini 4 Hydrogen: Cheaper Tokens, More Expensive Answers?
Nov 13, 2026 · YouTube
18:40ERNIE 5.5 Flash Preview vs GLM 5.3 Flash: Baidu's new model is very impressive!
Nov 11, 2026 · YouTube
36:22Fable 5.2 robbing me blind, plus: Nex AGI's N2.6 vs GLM 5.3 Flash
Nov 11, 2026 · YouTube
14:03Gemini 4 Carbon: Can it handle my challenges? (First look with one-shot coding tests)
Nov 10, 2026 · YouTube
10:57"Crouton Alpha": the latest super-efficient coding model by Meta?
Nov 3, 2026 · YouTube
38:58Testing Particle-1: a post-trained DeepSeek V4.1 Flash specializing in coding and efficiency
Oct 28, 2026 · YouTube
22:14GPT-6.1 Terra Pro vs Terra: How Much Better Is Pro?
Oct 27, 2026 · YouTube
29:55Kimi K3.1 Pro Looked Incredible. Then I Kept Testing.
Oct 26, 2026 · YouTube
You write crowd simulations where the behavior emerges from rules each person follows.
Build me a single HTML page: a section of a football stadium emptying through one exit gate.
#urgency=0.8&gate=1.2&column=1 starts simulation at load with those settings: urgency 0.0 to 1.0, gate width in yards, column 0 or 1. Any values work.data: URIs are fine.localStorage, sessionStorage, cookies or indexedDB — sandboxed frame, they throw.html block.Before the file, two quantitative predictions: whether increasing urgency from 0.3 to 0.9 increases or decreases evacuation time at gate=1.2 and column=0, with the predicted difference in seconds; and whether enabling the column (column=1) increases or decreases evacuation time at urgency=0.9 and gate=1.2, with the predicted difference in seconds.
The single fenced html block.
Where your crowd behaves like a real one and where it does not. Name anything you special-cased: a nudge that breaks a jam, a speed cap at the gate, an allowance for overlap. If your page never jams at the gate, say so.
At gate=1.2, column=0: increasing urgency from 0.3 to 0.9 increases evacuation time by about +30 seconds — faster-is-slower: higher desired speed and contact friction stabilise arches at the gate and reduce outflow despite higher free speed.
At urgency=0.9, gate=1.2: enabling the column (column=1) decreases evacuation time by about -18 seconds — the column splits the symmetric arch, forces alternating merging of two sub-streams, and lowers the probability of a long-lived clog, outweighing the small detour.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Crouton Alpha — Stadium Evacuation</title>
<style>
html,body{margin:0;padding:0;background:#10151c;color:#e8eef5;font-family:system-ui,Arial,sans-serif}
header{padding:10px 14px;background:#182230;border-bottom:1px solid #2a3a52}
h1{font-size:18px;margin:0 0 8px}
.controls{display:flex;flex-wrap:wrap;gap:14px;align-items:center}
label{font-size:13px;display:flex;gap:6px;align-items:center}
input[type=range]{width:130px}
button{background:#2f6fed;color:#fff;border:0;border-radius:6px;padding:7px 14px;cursor:pointer;font-weight:600}
button:hover{background:#2559c4}
.metrics{display:flex;flex-wrap:wrap;gap:18px;padding:8px 14px;background:#0c1118;font-variant-numeric:tabular-nums}
.metrics b{font-size:18px;color:#7fd0ff}
.wrap{display:flex;justify-content:center;padding:10px}
canvas{background:#243447;border:1px solid #3a4f6b;border-radius:8px;max-width:96vw;height:auto}
.note{font-size:12px;color:#9fb2c8;padding:0 14px 12px}
</style>
</head>
<body>
<header>
<h1>Stadium Section Evacuation — Top-Down</h1>
<div class="controls">
<label>Urgency <input id="urgency" type="range" min="0" max="1" step="0.05" value="0.5"> <span id="urgencyVal">0.50</span></label>
<label>Gate width (yards) <input id="gate" type="range" min="0.4" max="3" step="0.1" value="1.2"> <span id="gateVal">1.2</span></label>
<label><input id="column" type="checkbox"> Column in front of gate</label>
<button id="reset">Reset / Refill stands</button>
<button id="pause">Pause</button>
</div>
</header>
<div class="metrics">
<span>Elapsed <b id="elapsed">0.0s</b></span>
<span>Remaining <b id="remaining">220</b></span>
<span>Exited <b id="exited">0</b></span>
<span>Outflow (last 10s) <b id="outflow">0 /min</b></span>
<span>Evacuation time <b id="final">—</b></span>
</div>
<div class="wrap"><canvas id="cv" width="960" height="660"></canvas></div>
<p class="note">220 people, identical rules: seek gate, keep personal space, physical push on contact. No overlap is allowed — overlaps are resolved positionally every step.</p>
<script>
(function(){
"use strict";
const W=32,H=22,wallY=16,gateCX=16,r=0.28,DIAM=2*r;
const cv=document.getElementById('cv'),ctx=cv.getContext('2d');
const el=id=>document.getElementById(id);
let urgency=0.5,gateYards=1.2,columnOn=false;
let people=[],exited=0,exitTimes=[],elapsed=0,running=true,finished=false,finalTime=null;
let last=performance.now(),acc=0;
function parseHash(){
try{
const h=location.hash.replace(/^#/,'');
if(!h) return;
const p=new URLSearchParams(h);
if(p.has('urgency')) urgency=Math.min(1,Math.max(0,parseFloat(p.get('urgency'))||0));
if(p.has('gate')) gateYards=Math.min(4,Math.max(0.3,parseFloat(p.get('gate'))||1.2));
if(p.has('column')) columnOn=(p.get('column')==='1'||p.get('column')==='true');
}catch(e){}
}
parseHash();
el('urgency').value=urgency; el('gate').value=gateYards; el('column').checked=columnOn;
function syncLabels(){ el('urgencyVal').textContent=Number(urgency).toFixed(2); el('gateVal').textContent=Number(gateYards).toFixed(1); }
syncLabels();
el('urgency').addEventListener('input',e=>{urgency=parseFloat(e.target.value);syncLabels();});
el('gate').addEventListener('input',e=>{gateYards=parseFloat(e.target.value);syncLabels();assignTargets();});
el('column').addEventListener('change',e=>{columnOn=e.target.checked;});
el('reset').addEventListener('click',reset);
el('pause').addEventListener('click',e=>{running=!running;e.target.textContent=running?'Pause':'Resume';});
function gateHalf(){ return (gateYards*0.9144)/2; }
function colPos(){ return {x:gateCX,y:wallY-1.8,rad:0.35}; }
function reset(){
people=[]; exited=0; exitTimes=[]; elapsed=0; finished=false; finalTime=null; running=true; el('pause').textContent='Pause';
let tries=0;
while(people.length<220 && tries<20000){
tries++;
const x=1+Math.random()*(W-2), y=2+Math.random()*(wallY-3.5);
if(columnOn){ const c=colPos(); if(Math.hypot(x-c.x,y-c.y)<1.2) continue; }
let ok=true;
for(let i=0;i<people.length;i++){ if(Math.hypot(x-people[i].x,y-people[i].y)<DIAM+0.02){ok=false;break;} }
if(!ok) continue;
people.push({x,y,vx:0,vy:0,hue:Math.random()*360,tx:gateCX,phase:Math.random()*Math.PI*2,amp:0.15+Math.random()*0.25});
}
assignTargets();
}
function assignTargets(){
const gh=gateHalf();
for(const p of people){ p.tx=gateCX+(Math.random()-0.5)*Math.max(0.2,gh*1.6); }
}
reset();
function segmentPush(p,x1,y1,x2,y2){
const dx=x2-x1,dy=y2-y1,L2=dx*dx+dy*dy||1;
let t=((p.x-x1)*dx+(p.y-y1)*dy)/L2; t=Math.max(0,Math.min(1,t));
const cx=x1+t*dx,cy=y1+t*dy,ox=p.x-cx,oy=p.y-cy,d=Math.hypot(ox,oy);
if(d<r && d>1e-6){ p.x=cx+ox/d*r; p.y=cy+oy/d*r; }
else if(d<=1e-6){ p.y=y1-r; }
}
function collide(p){
const gh=gateHalf(),gl=gateCX-gh,gr=gateCX+gh;
segmentPush(p,0,wallY,gl,wallY);
segmentPush(p,gr,wallY,W,wallY);
segmentPush(p,gl,wallY,gl,wallY+0.9);
segmentPush(p,gr,wallY,gr,wallY+0.9);
if(columnOn){ const c=colPos(),dx=p.x-c.x,dy=p.y-c.y,d=Math.hypot(dx,dy),min=c.rad+r;
if(d<min && d>1e-6){ p.x=c.x+dx/d*min; p.y=c.y+dy/d*min; } }
p.x=Math.max(r,Math.min(W-r,p.x)); p.y=Math.max(r,Math.min(H-r,p.y));
}
function step(dt){
if(finished) return;
elapsed+=dt;
const vdes=0.6+urgency*1.9; // desired speed scales with urgency
const tau=0.45;
const n=people.length;
const ax=new Float64Array(n),ay=new Float64Array(n);
// desired + personal space + contact
for(let i=0;i<n;i++){
const p=people[i];
let tx=p.tx, ty=wallY+3;
// small lateral noise to break perfect symmetry (disclosed)
tx+=Math.sin(elapsed*0.7+p.phase)*p.amp;
const dx=tx-p.x, dy=ty-p.y, d=Math.hypot(dx,dy)||1;
ax[i]+=(dx/d*vdes - p.vx)/tau;
ay[i]+=(dy/d*vdes - p.vy)/tau;
}
for(let i=0;i<n;i++){
const a=people[i];
for(let j=i+1;j<n;j++){
const b=people[j];
const dx=b.x-a.x, dy=b.y-a.y, d=Math.hypot(dx,dy);
if(d>1.3 || d<1e-6) continue;
const ux=dx/d, uy=dy/d;
// personal space repulsion
if(d<1.1){
const f=3.5*(1.1-d)/1.1 + 2.0*Math.exp((DIAM-d)/0.25)*(d<DIAM?1:0.2);
ax[i]-=ux*f; ay[i]-=uy*f; ax[j]+=ux*f; ay[j]+=uy*f;
}
// physical contact: push + tangential friction (scales with urgency)
if(d<DIAM){
const overlap=DIAM-d;
const push=(18+30*urgency)*overlap;
ax[i]-=ux*push; ay[i]-=uy*push; ax[j]+=ux*push; ay[j]+=uy*push;
// friction: damp relative tangential motion
const rvx=b.vx-a.vx, rvy=b.vy-a.vy;
const rn=rvx*ux+rvy*uy;
const txv=rvx-rn*ux, tyv=rvy-rn*uy;
const mu=2.0+6.0*urgency;
ax[i]+=txv*mu*0.5; ay[i]+=tyv*mu*0.5; ax[j]-=txv*mu*0.5; ay[j]-=tyv*mu*0.5;
}
}
}
for(let i=0;i<n;i++){
const p=people[i];
p.vx+=ax[i]*dt; p.vy+=ay[i]*dt;
// soft speed cap from force balance only — no hard gate cap
const sp=Math.hypot(p.vx,p.vy), maxSp=vdes*1.6+0.5;
if(sp>maxSp){ p.vx*=maxSp/sp; p.vy*=maxSp/sp; }
p.x+=p.vx*dt; p.y+=p.vy*dt;
collide(p);
}
// positional de-overlap: guarantees nobody overlaps anybody
for(let iter=0;iter<2;iter++){
for(let i=0;i<n;i++){
const a=people[i];
for(let j=i+1;j<n;j++){
const b=people[j],dx=b.x-a.x,dy=b.y-a.y,d=Math.hypot(dx,dy);
if(d<DIAM && d>1e-6){ const push=(DIAM-d)/2,ux=dx/d,uy=dy/d;
a.x-=ux*push; a.y-=uy*push; b.x+=ux*push; b.y+=uy*push; }
}
collide(a);
}
}
// exit: crossed wall through gate and reached exit line
for(let i=people.length-1;i>=0;i--){
const p=people[i];
if(p.y>wallY+1.6){ people.splice(i,1); exited++; exitTimes.push(elapsed); }
}
if(people.length===0 && !finished){ finished=true; finalTime=elapsed; }
}
function draw(){
const s=Math.min(cv.width/W,cv.height/H);
ctx.clearRect(0,0,cv.width,cv.height);
ctx.save(); ctx.scale(s,s);
// stands
ctx.fillStyle='#2c4a2e'; ctx.fillRect(0,0,W,wallY);
ctx.strokeStyle='rgba(255,255,255,0.12)'; ctx.lineWidth=0.08;
for(let y=2;y<wallY;y+=0.9){ ctx.beginPath(); ctx.moveTo(0,y); ctx.lineTo(W,y); ctx.stroke(); }
// exit area
ctx.fillStyle='#3a3f46'; ctx.fillRect(0,wallY,W,H-wallY);
// wall
const gh=gateHalf(),gl=gateCX-gh,gr=gateCX+gh;
ctx.fillStyle='#c8ccd2'; ctx.fillRect(0,wallY-0.18,gl,0.36); ctx.fillRect(gr,wallY-0.18,W-gr,0.36);
// gate
ctx.fillStyle='#37d67a'; ctx.fillRect(gl,wallY-0.18,gr-gl,0.36);
ctx.fillStyle='rgba(55,214,122,0.25)'; ctx.fillRect(gl,wallY,gr-gl,2);
// column
if(columnOn){ const c=colPos(); ctx.fillStyle='#e0a030'; ctx.beginPath(); ctx.arc(c.x,c.y,c.rad,0,7); ctx.fill();
ctx.strokeStyle='#7a5510'; ctx.lineWidth=0.06; ctx.stroke();
ctx.fillStyle='#7a5510'; ctx.font='0.35px sans-serif'; ctx.textAlign='center'; ctx.fillText('COLUMN',c.x,c.y+0.12); }
// people
for(const p of people){
ctx.fillStyle=`hsl(${p.hue},70%,60%)`; ctx.beginPath(); ctx.arc(p.x,p.y,r,0,7); ctx.fill();
ctx.strokeStyle='rgba(0,0,0,0.5)'; ctx.lineWidth=0.04; ctx.stroke();
const sp=Math.hypot(p.vx,p.vy);
if(sp>0.2){ ctx.strokeStyle='#fff'; ctx.lineWidth=0.05; ctx.beginPath(); ctx.moveTo(p.x,p.y); ctx.lineTo(p.x+p.vx/sp*0.35,p.y+p.vy/sp*0.35); ctx.stroke(); }
}
ctx.restore();
// metrics
el('elapsed').textContent=elapsed.toFixed(1)+'s';
el('remaining').textContent=people.length;
el('exited').textContent=exited;
const recent=exitTimes.filter(t=>elapsed-t<=10).length;
el('outflow').textContent=(recent*6)+' /min';
el('final').textContent=finished?finalTime.toFixed(1)+'s':'—';
}
function frame(now){
requestAnimationFrame(frame);
let dt=(now-last)/1000; last=now; if(dt>0.1)dt=0.1;
if(running && !finished){ acc+=dt; const h=1/60; let c=0; while(acc>=h && c<5){ step(h); acc-=h; c++; } }
draw();
}
requestAnimationFrame(frame);
})();
</script>
</body>
</html>
Where it behaves like a real crowd: arches and clogs form spontaneously at the gate from identical local rules — seek the gate, repel within ~1.1 m personal space, push and apply tangential friction on contact. At high urgency the desired speed and friction rise together, arches live longer, outflow drops, and evacuation slows (faster-is-slower). A column 1.8 m in front of the gate splits the crowd into two streams that merge alternately, destabilising the symmetric arch, so it can speed evacuation despite blocking the centre. The page does jam at the gate at high urgency; jams are intermittent, not permanent.
Where it does not: people are identical discs with no bodies, decisions, communication, helping, or route choice; each has a pre-assigned lateral gate target. Top-down 2-D, no seat rows as obstacles, no fatigue, no panic heterogeneity.
Special-cased, disclosed: (1) positional de-overlap iterations every step — this is the physical push enforcement and guarantees no overlap is ever drawn; there is no allowance for overlap. (2) A small sinusoidal lateral noise per person (amplitude 0.15–0.4 m) to break perfect symmetry — without it a perfectly symmetric arch could persist indefinitely. (3) Exit removal at a line 1.6 m past the wall, and wall/jamb/column collision as hard segments/circle. There is no speed cap at the gate and no jam-breaking nudge/teleport: the only cap is a soft global cap at 1.6× desired speed from force balance.