47:51Ranking major U.S. Open-Weights Models. (Where does Ripple 65B fit in?)
Nov 6, 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
29:55Kimi K3.1 Pro Looked Incredible. Then I Kept Testing.
Oct 26, 2026 · YouTube
22:47Mistral Large 4 Is Cheap. But Is It Good Enough to Compete?
Oct 6, 2026 · YouTube
16:54Stealth Union Alpha: Is this another cheap GPT model? (better than Luna, cheaper than Terra?)
Sep 16, 2026 · YouTube
16:45DeepSeek V4.1 Flash Is Shockingly Good for the Price
Sep 10, 2026 · YouTube
17:37Tencent Hy4 Preview Tested: Is It Really Better Than Kimi K3 and GLM 5.3?
Aug 28, 2026 · YouTube
23:58Qwen 3.8 Flash Tested: UI, Coding, Physics & more - compared to Opus 5, Sol Pro, Grok
Aug 27, 2026 · YouTube
14:50Stealth Ox Alpha: a new GLM model! Full test (coding & writing) against Grok, Gemini, GPT & others
Aug 21, 2026 · YouTube
My buddy runs a bar. I told him I'd build him something for Thursdays. He's the one talking here — I just write down what he says and hand it to you.
It's not real pool. Three balls on the table, you shoot until all three are down, and we count how many shots it took you. Low is good. Everybody takes a turn, then we go around again — that's a round.
Twenty bucks to play. You start with five chips. Take more than four shots to clear the table and it costs you a chip. Out of chips and you're out, go back to drinking. Last one with chips left takes the pot.
There's a clock on your turn — a minute, minute and a half, we've never really settled it. Clock runs out and you're not at the table, that's a chip.
It's a Thursday. Nine o'clock, everybody's had a few, the jukebox is loud and half the room is outside smoking. Twelve, sixteen people usually, however many show up. It runs two, three hours and nobody's in a hurry.
Last year I ran the whole thing on a legal pad and it got away from me around round four. Two guys arguing with me about what they shot, me trying to remember whose turn it was, somebody's beer on the pad. Never again.
I'm running this off my phone, one-handed, standing at the table with a beer in the other. There's a TV over the bar and that's the only screen anybody in the room can see — from across the room, in the dark, so it's got to be big. People want to know where they stand without walking over and asking me.
My phone's on 15% by ten. The bar's wifi is the bar's wifi.
Twenty a head, all of it in the pot. Winner takes it — mostly. We kick a little to second. And there's a side thing we do for whoever's shooting best early on, I never wrote that part down properly.
The app doesn't hold the money. I do. But at the end of the night it has to tell me what I owe who, and I'm reading that off my phone with sixteen people standing around the table.
Two pages.
The console — the thing I run it from, and the thing that goes up on the TV. Open it and there's already a game going. I'm not typing in twelve names to find out whether it works.
The playback — a separate page that plays a whole night through, start to finish, so I can watch it work before Thursday. One step at a time, a step being one thing happening, with the scorecard filling in as it goes and a slider for how fast it runs. I want to slow it down, back it up, and read what just happened. Show me the way a night actually goes.
The playback runs the same rules the console runs. If the two of them drift apart, the playback is a cartoon and it's no use to me.
data: URIs are fine.localStorage, sessionStorage, cookies or indexedDB — these run in a sandboxed frame where those throw.html blocks: the console first, the playback second. Leave yourself room for the second one.I know I wasn't clear about everything. Everything you had to decide for me, one line each — what you decided and why. Short.
The first fenced html block.
The second fenced html block.
It's Thursday, it's nine o'clock, and I'm running this for real. What comes up that this doesn't handle? Be straight with me. I'd much rather hear it now than find out with sixteen people around a pool table and three hundred dollars sitting on the bar.
Rules() function is copied into both files. Playback only feeds a scripted night through it, so the cartoon can't drift.<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>Three-Ball</title>
<style>
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{margin:0;height:100%;background:#0a140d;color:#f3e6c4;font-family:system-ui,-apple-system,sans-serif}
body{display:flex;flex-direction:column;height:100dvh;overflow:hidden}
#top{display:flex;gap:10px;padding:8px 12px;align-items:baseline;flex-wrap:wrap;background:#07100a;border-bottom:2px solid #c4a35a}
#top b{font-size:clamp(22px,5vw,48px);color:#f5d76e;letter-spacing:.04em}
#top span{font-size:clamp(14px,2.4vw,22px);opacity:.9}
#now{padding:10px 12px 6px;text-align:center;min-height:22vh}
#now .who{font-size:clamp(40px,10vw,112px);line-height:1;font-weight:800;color:#fff;text-shadow:0 2px 0 #000}
#now .sub{font-size:clamp(16px,3vw,28px);margin-top:6px}
#now .sub em{color:#f5d76e;font-style:normal;font-size:1.3em}
#msg{padding:4px 12px 8px;text-align:center;font-size:clamp(14px,2.6vw,24px);color:#c9e0c0;min-height:1.4em}
#roster{flex:1;overflow:auto;padding:0 8px 8px;display:grid;grid-template-columns:1fr 1fr;gap:4px}
.row{display:flex;align-items:center;gap:8px;padding:6px 8px;background:#122318;border-radius:6px;border:2px solid transparent}
.row.on{border-color:#f5d76e;background:#1c3a24}
.row.dead{opacity:.35}
.row .nm{flex:1;font-size:clamp(16px,3.1vw,36px);font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.row .ls{font-size:clamp(14px,2.4vw,26px);min-width:1.6em;text-align:right;color:#9bb}
.row .ls.bad{color:#e66}
.row .ch{font-size:clamp(20px,4vw,44px);font-weight:800;color:#f5d76e;min-width:1.2em;text-align:right}
#ops{background:#161616;padding:8px 8px calc(8px + env(safe-area-inset-bottom));border-top:1px solid #333}
.clk{display:flex;gap:6px;align-items:center;margin-bottom:8px}
.clk #ctime{flex:1;text-align:center;font-size:42px;font-weight:800;font-variant-numeric:tabular-nums}
.clk.zero #ctime{color:#e44}
.clk button{height:44px;padding:0 10px;font-weight:800;border:0;border-radius:8px;background:#333;color:#eee}
#bclk{background:#c4a35a;color:#111}
.pad{display:grid;grid-template-columns:repeat(5,1fr);gap:6px}
.pad button{height:52px;font-size:22px;font-weight:800;border:0;border-radius:8px;background:#c4a35a;color:#111}
#b10{font-size:16px}
#bns{grid-column:span 2;background:#a33;color:#fff;font-size:16px}
#bundo{grid-column:span 3;background:#555;color:#fff}
#badd,#bnew{height:40px;font-size:12px;background:#2a2a2a;color:#bbb}
#mask{position:fixed;inset:0;background:rgba(0,0,0,.75);display:flex;align-items:center;justify-content:center;padding:16px;z-index:9}
#mask.hide{display:none}
#card{background:#142018;border:3px solid #f5d76e;border-radius:12px;padding:22px;max-width:640px;width:100%;text-align:center}
#card h2{margin:0 0 12px;font-size:clamp(28px,6vw,52px);color:#f5d76e}
#card p{font-size:clamp(20px,4vw,36px);margin:8px 0;font-weight:700}
#card button{margin-top:14px;height:52px;padding:0 24px;font-size:20px;font-weight:800;border:0;border-radius:8px;background:#c4a35a;color:#111}
</style>
</head>
<body>
<div id="top"></div>
<div id="now"></div>
<div id="msg"></div>
<div id="roster"></div>
<div id="ops">
<div class="clk" id="clk">
<button id="bclk">START CLOCK</button>
<div id="ctime">1:30</div>
<button id="b60">60</button>
<button id="b90">90</button>
<button id="b120">120</button>
</div>
<div class="pad">
<button data-s="1">1</button><button data-s="2">2</button><button data-s="3">3</button><button data-s="4">4</button><button data-s="5">5</button>
<button data-s="6">6</button><button data-s="7">7</button><button data-s="8">8</button><button data-s="9">9</button><button id="b10" data-s="10">10+</button>
<button id="bns">NOT HERE</button><button id="bundo">UNDO</button>
<button id="badd">ADD</button><button id="bnew">NEW NIGHT</button>
</div>
</div>
<div id="mask" class="hide"><div id="card"></div></div>
<script>
function Rules(){
var BUY=20,C0=5,LIM=4,HOTR=2,HOT=20,SEC=40;
function np(n){return {name:n,chips:C0,hist:[],total:0,turns:0,out:false,outOrd:0};}
function create(names){
var ps=[],i;
for(i=0;i<names.length;i++) ps.push(np(names[i]));
return {players:ps,round:1,queue:[],qi:0,pot:names.length*BUY,hotPaid:false,hotName:null,hotAmt:0,outN:0,over:false,winner:null,second:null,alert:'',msg:'Thursday. Pot is $'+(names.length*BUY)+'. First shooter to the table.',buy:BUY,winAmt:0,secAmt:0};
}
function fillQ(g){
g.queue=[];
for(var i=0;i<g.players.length;i++) if(!g.players[i].out) g.queue.push(i);
g.qi=0;
}
function begin(g){fillQ(g);return g;}
function nAlive(g){var n=0,i;for(i=0;i<g.players.length;i++) if(!g.players[i].out) n++; return n;}
function payout(g){
var w=null,s=null,i,p,mx=-1;
for(i=0;i<g.players.length;i++){
p=g.players[i];
if(!p.out) w=p;
if(p.out && p.outOrd>mx){mx=p.outOrd;s=p;}
}
if(!w){
for(i=0;i<g.players.length;i++) if(g.players[i].outOrd===g.outN) w=g.players[i];
mx=-1;s=null;
for(i=0;i<g.players.length;i++) if(g.players[i]!==w && g.players[i].outOrd>mx){mx=g.players[i].outOrd;s=g.players[i];}
}
g.winner=w;g.second=s;g.over=true;
var rem=g.pot,sAmt=0;
if(s && rem>SEC) sAmt=SEC;
g.winAmt=rem-sAmt;g.secAmt=sAmt;
g.msg=(w?w.name:'Nobody')+' takes the pot';
}
function hot(g){
if(g.hotPaid||g.round<=HOTR) return;
var best=null,bt=1e9,i,p;
for(i=0;i<g.players.length;i++){
p=g.players[i];
if(p.turns<HOTR) continue;
if(p.total<bt){bt=p.total;best=p;}
}
if(best && g.pot>=HOT){
g.hotPaid=true;g.hotName=best.name;g.hotAmt=HOT;g.pot-=HOT;
g.alert='PAY '+best.name+' $'+HOT+' NOW — Hot Stick, '+bt+' shots over two rounds';
}
}
function who(g){
if(g.over) return null;
if(!g.queue.length){
fillQ(g);
if(!g.queue.length) return null;
}
var hops=0;
while(hops++<80){
if(g.qi<g.queue.length){
var p=g.players[g.queue[g.qi]];
if(!p.out) return p;
g.qi++;
continue;
}
g.round++;
fillQ(g);
hot(g);
if(!g.queue.length) return null;
}
return null;
}
function apply(g,kind,n){
if(g.over) return g;
var p=who(g);
if(!p) return g;
var chip=false,bust=false,label;
if(kind==='T'){p.hist.push('T');p.turns++;chip=true;label='not at the table';}
else {n=+n;if(!(n>=1)) n=1;p.hist.push(n);p.turns++;p.total+=n;chip=n>LIM;label=n+' shot'+(n===1?'':'s');}
if(chip){p.chips--;if(p.chips<=0){p.chips=0;p.out=true;g.outN++;p.outOrd=g.outN;bust=true;}}
g.msg=p.name+' — '+label+(chip?' — loses a chip':' — clean')+(bust?' — OUT':'');
g.alert='';
if(nAlive(g)<=1){payout(g);return g;}
g.qi++;
who(g);
return g;
}
function add(g,name){
if(!name||g.over) return;
g.players.push(np(name));
g.pot+=BUY;
g.msg=name+' is in. $'+BUY+'. Shoots next round.';
}
return {create:create,begin:begin,who:who,apply:apply,add:add,LIM:LIM,C0:C0,BUY:BUY};
}
function esc(s){return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/"/g,'"');}
var NAMES=["Dez","Tommy","Big Rick","Sarah","Moose","Nikki","Carlos","Walsh","Jen","Darnell","Pat","Liz","Connor","Mike"];
var R=Rules();
var g=R.begin(R.create(NAMES));
var snap=[];
var TMAX=90,tLeft=90,tRun=false,tId=null,dismissed=false,hotSeen='';
function fmt(s){return Math.floor(s/60)+':'+(s%60<10?'0':'')+(s%60);}
function aliveN(){var n=0,i;for(i=0;i<g.players.length;i++) if(!g.players[i].out) n++; return n;}
function push(){snap.push(JSON.parse(JSON.stringify(g))); if(snap.length>80) snap.shift();}
function resetClock(auto){
tLeft=TMAX; tRun=!!auto;
if(tId){clearInterval(tId);tId=null;}
if(tRun) tId=setInterval(tick,1000);
}
function tick(){
if(!tRun) return;
tLeft--;
if(tLeft<=0){
tLeft=0;tRun=false;
if(navigator.vibrate) navigator.vibrate([180,80,180]);
}
drawClock();
}
function drawClock(){
document.getElementById('ctime').textContent=fmt(tLeft);
document.getElementById('clk').className='clk'+(tLeft===0?' zero':'');
document.getElementById('bclk').textContent=tRun?'PAUSE':'START CLOCK';
}
function render(){
var p=R.who(g), i, html, last, bad, inN=aliveN();
document.getElementById('top').innerHTML='<b>R'+g.round+'</b><span>POT $'+g.pot+'</span><span>'+inN+' IN</span>'+(g.hotPaid?'<span>HOT '+esc(g.hotName)+' $'+g.hotAmt+'</span>':'')+'<span>5+ or no-show = chip</span>';
if(g.over && g.winner){
document.getElementById('now').innerHTML='<div class="who">'+esc(g.winner.name)+'</div><div class="sub">WINS $'+g.winAmt+'</div>';
} else if(p){
document.getElementById('now').innerHTML='<div class="who">'+esc(p.name)+'</div><div class="sub"><em>'+p.chips+'</em> chips · tap name on the list to edit</div>';
} else {
document.getElementById('now').innerHTML='<div class="who">—</div>';
}
document.getElementById('msg').textContent=g.msg||'';
html='';
for(i=0;i<g.players.length;i++){
p=g.players[i];
last=p.hist.length?p.hist[p.hist.length-1]:'';
bad=last==='T'||last>4;
html+='<div class="row'+(p.out?' dead':'')+(R.who(g)===p?' on':'')+'" data-i="'+i+'"><span class="nm">'+esc(p.name)+'</span><span class="ls'+(bad?' bad':'')+'">'+last+'</span><span class="ch">'+p.chips+'</span></div>';
}
document.getElementById('roster').innerHTML=html;
drawClock();
var mask=document.getElementById('mask'), card=document.getElementById('card');
if(g.over && !dismissed){
mask.className='';
card.innerHTML='<h2>PAY THESE PEOPLE</h2>'
+(g.hotPaid?'<p>Hot Stick already paid: '+esc(g.hotName)+' $'+g.hotAmt+'</p>':'')
+'<p>'+esc(g.winner?g.winner.name:'?')+' — winner — $'+g.winAmt+'</p>'
+(g.second?'<p>'+esc(g.second.name)+' — second — $'+g.secAmt+'</p>':'')
+'<button id="bok">GOT IT</button>';
} else if(g.alert && g.alert!==hotSeen){
mask.className='';
card.innerHTML='<h2>CASH OUT</h2><p>'+esc(g.alert)+'</p><button id="bok">I PAID IT</button>';
} else {
mask.className='hide';
}
}
document.getElementById('roster').onclick=function(e){
var row=e.target.closest?e.target.closest('.row'):null;
if(!row) return;
var i=+row.getAttribute('data-i'), p=g.players[i];
var n=prompt('Name (blank removes them only if nobody has shot yet)', p.name);
if(n===null) return;
n=n.replace(/^\s+|\s+$/g,'');
if(n===''){
var any=false,k;
for(k=0;k<g.players.length;k++) if(g.players[k].turns) any=true;
if(any){alert('Too late to take someone off. Only before the first shot.');return;}
if(g.players.length<2) return;
g.players.splice(i,1);
g.pot=g.players.length*R.BUY;
R.begin(g);
g.msg='Thursday. Pot is $'+g.pot+'. First shooter to the table.';
render();return;
}
p.name=n; render();
};
function enter(kind,n){
if(g.over) return;
if(kind==='S' && n===10){
var x=prompt('How many shots?');
n=parseInt(x,10);
if(!(n>=10)) return;
}
push();
dismissed=false;
R.apply(g,kind,n);
resetClock(!g.over);
render();
}
document.querySelector('.pad').onclick=function(e){
var b=e.target;
if(!b || b.tagName!=='BUTTON') return;
if(b.id==='bns') enter('T');
else if(b.id==='bundo'){
if(!snap.length) return;
g=snap.pop();
dismissed=false; hotSeen='';
resetClock(false); render();
} else if(b.id==='badd'){
var n=prompt('Name');
if(!n) return;
n=n.replace(/^\s+|\s+$/g,'');
if(!n) return;
push(); R.add(g,n); render();
} else if(b.id==='bnew'){
if(!confirm('New night? This wipes the scores.')) return;
var names=[],i;
for(i=0;i<g.players.length;i++) names.push(g.players[i].name);
g=R.begin(R.create(names)); snap=[]; dismissed=false; hotSeen='';
resetClock(false); render();
} else if(b.getAttribute('data-s')) enter('S', +b.getAttribute('data-s'));
};
document.getElementById('bclk').onclick=function(){
if(g.over) return;
tRun=!tRun;
if(tRun){
if(tLeft<=0) tLeft=TMAX;
if(tId) clearInterval(tId);
tId=setInterval(tick,1000);
}
drawClock();
};
function setT(n){TMAX=n; if(!tRun) tLeft=n; drawClock();}
document.getElementById('b60').onclick=function(){setT(60);};
document.getElementById('b90').onclick=function(){setT(90);};
document.getElementById('b120').onclick=function(){setT(120);};
document.getElementById('mask').onclick=function(e){
if(e.target.id!=='bok') return;
if(g.over) dismissed=true;
if(g.alert) hotSeen=g.alert;
render();
};
resetClock(false);
render();
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Three-Ball — Thursday playback</title>
<style>
*{box-sizing:border-box}
html,body{margin:0;background:#0a140d;color:#f3e6c4;font-family:system-ui,-apple-system,sans-serif}
body{max-width:1100px;margin:0 auto;padding:16px 16px 120px}
h1{font-size:22px;color:#f5d76e;margin:0 0 8px}
#cap{background:#122318;border:2px solid #c4a35a;border-radius:10px;padding:14px 16px;font-size:22px;font-weight:700;min-height:3.2em;margin:8px 0 14px}
#meta{opacity:.85;margin-bottom:12px}
#board{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-bottom:18px}
.row{display:flex;gap:8px;align-items:center;padding:6px 8px;background:#122318;border-radius:6px;border:2px solid transparent}
.row.on{border-color:#f5d76e}
.row.dead{opacity:.35}
.row .nm{flex:1;font-weight:700}
.row .ch{color:#f5d76e;font-weight:800;font-size:22px}
.row .ls.bad{color:#e66}
table{width:100%;border-collapse:collapse;font-variant-numeric:tabular-nums}
th,td{border:1px solid #2a4;padding:5px 6px;text-align:center}
th{background:#07100a;position:sticky;top:0}
th.nm,td.nm{text-align:left}
td.ok{color:#8d8}
td.bad{color:#e66;font-weight:800}
tr.win th{color:#f5d76e}
#tape{position:fixed;left:0;right:0;bottom:0;background:#161616;padding:10px 16px calc(10px + env(safe-area-inset-bottom));display:flex;flex-wrap:wrap;gap:10px;align-items:center;border-top:1px solid #333}
#tape button{height:44px;padding:0 16px;font-weight:800;border:0;border-radius:8px;background:#c4a35a;color:#111}
#tape label{display:flex;align-items:center;gap:8px}
input[type=range]{width:160px}
#stepn{margin-left:auto;opacity:.8}
</style>
</head>
<body>
<h1>Thursday night — playback</h1>
<div id="meta"></div>
<div id="cap"></div>
<div id="board"></div>
<div id="card"></div>
<div id="tape">
<button id="back">Back</button>
<button id="play">Play</button>
<button id="fwd">Step</button>
<label>Speed <input id="spd" type="range" min="1" max="8" value="3"></label>
<span id="stepn"></span>
</div>
<script>
function Rules(){
var BUY=20,C0=5,LIM=4,HOTR=2,HOT=20,SEC=40;
function np(n){return {name:n,chips:C0,hist:[],total:0,turns:0,out:false,outOrd:0};}
function create(names){
var ps=[],i;
for(i=0;i<names.length;i++) ps.push(np(names[i]));
return {players:ps,round:1,queue:[],qi:0,pot:names.length*BUY,hotPaid:false,hotName:null,hotAmt:0,outN:0,over:false,winner:null,second:null,alert:'',msg:'Thursday. Pot is $'+(names.length*BUY)+'. First shooter to the table.',buy:BUY,winAmt:0,secAmt:0};
}
function fillQ(g){
g.queue=[];
for(var i=0;i<g.players.length;i++) if(!g.players[i].out) g.queue.push(i);
g.qi=0;
}
function begin(g){fillQ(g);return g;}
function nAlive(g){var n=0,i;for(i=0;i<g.players.length;i++) if(!g.players[i].out) n++; return n;}
function payout(g){
var w=null,s=null,i,p,mx=-1;
for(i=0;i<g.players.length;i++){
p=g.players[i];
if(!p.out) w=p;
if(p.out && p.outOrd>mx){mx=p.outOrd;s=p;}
}
if(!w){
for(i=0;i<g.players.length;i++) if(g.players[i].outOrd===g.outN) w=g.players[i];
mx=-1;s=null;
for(i=0;i<g.players.length;i++) if(g.players[i]!==w && g.players[i].outOrd>mx){mx=g.players[i].outOrd;s=g.players[i];}
}
g.winner=w;g.second=s;g.over=true;
var rem=g.pot,sAmt=0;
if(s && rem>SEC) sAmt=SEC;
g.winAmt=rem-sAmt;g.secAmt=sAmt;
g.msg=(w?w.name:'Nobody')+' takes the pot';
}
function hot(g){
if(g.hotPaid||g.round<=HOTR) return;
var best=null,bt=1e9,i,p;
for(i=0;i<g.players.length;i++){
p=g.players[i];
if(p.turns<HOTR) continue;
if(p.total<bt){bt=p.total;best=p;}
}
if(best && g.pot>=HOT){
g.hotPaid=true;g.hotName=best.name;g.hotAmt=HOT;g.pot-=HOT;
g.alert='PAY '+best.name+' $'+HOT+' NOW — Hot Stick, '+bt+' shots over two rounds';
}
}
function who(g){
if(g.over) return null;
if(!g.queue.length){
fillQ(g);
if(!g.queue.length) return null;
}
var hops=0;
while(hops++<80){
if(g.qi<g.queue.length){
var p=g.players[g.queue[g.qi]];
if(!p.out) return p;
g.qi++;
continue;
}
g.round++;
fillQ(g);
hot(g);
if(!g.queue.length) return null;
}
return null;
}
function apply(g,kind,n){
if(g.over) return g;
var p=who(g);
if(!p) return g;
var chip=false,bust=false,label;
if(kind==='T'){p.hist.push('T');p.turns++;chip=true;label='not at the table';}
else {n=+n;if(!(n>=1)) n=1;p.hist.push(n);p.turns++;p.total+=n;chip=n>LIM;label=n+' shot'+(n===1?'':'s');}
if(chip){p.chips--;if(p.chips<=0){p.chips=0;p.out=true;g.outN++;p.outOrd=g.outN;bust=true;}}
g.msg=p.name+' — '+label+(chip?' — loses a chip':' — clean')+(bust?' — OUT':'');
g.alert='';
if(nAlive(g)<=1){payout(g);return g;}
g.qi++;
who(g);
return g;
}
function add(g,name){
if(!name||g.over) return;
g.players.push(np(name));
g.pot+=BUY;
g.msg=name+' is in. $'+BUY+'. Shoots next round.';
}
return {create:create,begin:begin,who:who,apply:apply,add:add,LIM:LIM,C0:C0,BUY:BUY};
}
function esc(s){return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/"/g,'"');}
var NAMES=["Dez","Tommy","Big Rick","Sarah","Moose","Nikki","Carlos","Walsh","Jen","Darnell","Pat","Liz","Connor","Mike"];
var R=Rules();
var actions=[];
(function generate(){
var g=R.begin(R.create(NAMES));
var seed=77;
function rnd(){seed=(seed*16807)%2147483647;return (seed-1)/2147483646;}
var means=[3.1,5.4,4.0,3.7,4.9,3.4,5.2,4.3,3.8,5.6,4.1,3.5,4.5,5.0];
var guard=0;
while(!g.over && guard<400){
guard++;
var idx=g.queue[g.qi];
var mean=means[idx]+(g.round-1)*0.18;
if(g.round>12) mean+=1.5;
var tc=0.025+(g.round>8?0.04:0);
if(rnd()<tc){actions.push({k:'T'});R.apply(g,'T');}
else{
var u1=Math.max(rnd(),1e-6),u2=rnd();
var z=Math.sqrt(-2*Math.log(u1))*Math.cos(2*Math.PI*u2);
var n=Math.round(mean+1.15*z);
if(n<1)n=1;if(n>12)n=12;
actions.push({k:'S',n:n});R.apply(g,'S',n);
}
}
})();
function at(step){
var g=R.begin(R.create(NAMES)),i,a;
for(i=0;i<step;i++){
a=actions[i];
if(a.k==='T') R.apply(g,'T'); else R.apply(g,'S',a.n);
}
return g;
}
var step=0, playing=false, timer=null;
function delay(){var s=+document.getElementById('spd').value; return 1600/s;}
function show(){
var g=at(step), i,j,p,html,last,bad,maxr=0,cur=R.who(g);
var inN=0;
for(i=0;i<g.players.length;i++) if(!g.players[i].out) inN++;
document.getElementById('meta').textContent='Round '+g.round+' · pot $'+g.pot+' · '+inN+' still in'+(g.hotPaid?' · Hot Stick '+g.hotName+' $'+g.hotAmt:'');
var cap=step===0?'Fourteen names, $280 in the envelope, Dez to the table. This is how a night actually starts.':g.msg;
if(g.alert) cap=g.alert;
if(g.over){
cap=g.msg+'. Pay '+(g.winner?g.winner.name:'?')+' $'+g.winAmt+(g.second?' and '+g.second.name+' $'+g.secAmt:'')+(g.hotPaid?'. Hot Stick already went to '+g.hotName+'.':'');
}
document.getElementById('cap').textContent=cap;
html='';
for(i=0;i<g.players.length;i++){
p=g.players[i];
last=p.hist.length?p.hist[p.hist.length-1]:'';
bad=last==='T'||last>4;
html+='<div class="row'+(p.out?' dead':'')+(cur===p?' on':'')+'"><span class="nm">'+esc(p.name)+'</span><span class="ls'+(bad?' bad':'')+'">'+last+'</span><span class="ch">'+p.chips+'</span></div>';
}
document.getElementById('board').innerHTML=html;
for(i=0;i<g.players.length;i++) if(g.players[i].hist.length>maxr) maxr=g.players[i].hist.length;
html='<table><thead><tr><th class="nm"></th>';
for(j=1;j<=maxr;j++) html+='<th>R'+j+'</th>';
html+='<th>Σ</th><th>chips</th></tr></thead><tbody>';
for(i=0;i<g.players.length;i++){
p=g.players[i];
html+='<tr class="'+(p.out?'dead':'')+(g.winner&&g.winner.name===p.name?' win':'')+'"><th class="nm">'+esc(p.name)+'</th>';
for(j=0;j<maxr;j++){
var v=j<p.hist.length?p.hist[j]:'';
var cls=v===''?'':(v==='T'||v>4?'bad':'ok');
html+='<td class="'+cls+'">'+v+'</td>';
}
html+='<td>'+(p.total||'')+'</td><td>'+p.chips+'</td></tr>';
}
html+='</tbody></table>';
document.getElementById('card').innerHTML=html;
document.getElementById('stepn').textContent='Step '+step+' / '+actions.length;
document.getElementById('play').textContent=playing?'Pause':'Play';
}
function go(n){
step+=n;
if(step<0) step=0;
if(step>actions.length) step=actions.length;
if(step===actions.length) playing=false;
show();
}
function tick(){
if(!playing) return;
if(step>=actions.length){playing=false;show();return;}
go(1);
timer=setTimeout(tick, delay());
}
document.getElementById('back').onclick=function(){playing=false;go(-1);};
document.getElementById('fwd').onclick=function(){playing=false;go(1);};
document.getElementById('play').onclick=function(){
playing=!playing;
if(playing){
if(step>=actions.length) step=0;
timer=setTimeout(tick, delay());
}
show();
};
show();
</script>
</body>
</html>
Refresh, a crash, a phone call that iOS uses to kill Safari, or the 15% battery hitting zero — the night is gone. Nothing is saved. That is the one that actually ruins Thursday. Plug the phone in before you take the first name, and do not open another tab.
You cannot fix a disputed score from three rounds ago. UNDO only peels the last thing off. The argument you had on the legal pad in round 4 is still coming; you'll be negotiating chips by mouth while the board is wrong.
If Moose is on the sheet and he doesn't show, you can only take him off before anybody has shot. After that his $20 is in the pot whether he paid you or not. Add people who have handed you cash. Take the no-shows off at 8:55, not 9:20.
Hot Stick throws a full-screen PAY THEM NOW in the middle of a round. You will dismiss it with a beer in your hand and then not be sure whether you peeled off the $20. The header keeps saying HOT so-and-so — believe that, not your pocket.
Late joiners get five fresh chips. The table will call that unfair if they walk in at round 6. That's a house call, not an app call.
The clock has no teeth unless you hit NOT HERE. You will forget to start it. Someone will be in the bathroom. Do not let the clock be the fight; you are the fight.
If you mirror to the TV and the TV takes touch, someone will enter a 9. Put the phone in your hand, not on the rail.
When the second-to-last player busts, the game ends even if the winner wanted a pride round. The overlay is the payout. Pride shots are off the book.
Names are fake regulars. Changing fourteen of them with a prompt on a phone, one-handed, with people talking to you, is miserable. Do it before the room fills up.
The app never sees the cash. If you let someone IOU, or one guy pays for two, or you already bought a round out of the envelope, the payout screen will still tell you to hand over the math on 14 × 20. Count the envelope before you read the screen out loud.