// Who the felt marks "ALL IN". // // The mark's whole value is that a dealer can scan the ring and see who can still be // bet at, so the test that matters most is the last one: the seats it marks are // exactly the seats the betting round refuses to ask for another chip. const test = require("node:test"); const assert = require("node:assert"); const { Betting, HoldemState, makeTable, chipsOnTable } = require("./load"); test("a player who moved all-in is marked", () => { const state = makeTable({ seatCount: 6, seated: [0, 1, 2, 3], stack: 100 }); state.seats[3].stack = 12; Betting.beginHand(state); Betting.allIn(state, state.actingSeatIndex); assert.equal(Betting.isAllIn(state, state.seats[3]), true); assert.equal(state.seats[3].stack, 0); }); test("a player with chips behind is not", () => { const state = makeTable({ seatCount: 6, seated: [0, 1, 2], stack: 100 }); Betting.beginHand(state); assert.equal(Betting.isAllIn(state, state.seats[0]), false); assert.equal(Betting.isAllIn(state, state.seats[1]), false); }); test("a busted player who was dealt in but has put nothing in is not", () => { // An empty stack alone isn't all-in — it's someone who shouldn't have been dealt // in. Calling that "ALL IN" on the felt would be a lie about a live pot. const state = makeTable({ seatCount: 4, seated: [0, 1, 2], stack: 100 }); state.seats[2].stack = 0; assert.equal(Betting.isAllIn(state, state.seats[2]), false); }); test("a folded player with an empty stack is not", () => { const state = makeTable({ seatCount: 4, seated: [0, 1, 2], stack: 100 }); state.seats[1].committed = 5; state.seats[1].stack = 0; state.seats[1].folded = true; assert.equal(Betting.isAllIn(state, state.seats[1]), false); }); test("an empty chair is not", () => { const state = makeTable({ seatCount: 6, seated: [0, 1], stack: 100 }); assert.equal(Betting.isAllIn(state, state.seats[4]), false); }); test("a seat with no stack of its own falls back to the table's and isn't marked", () => { const state = makeTable({ seatCount: 4, seated: [0, 1, 2], stack: 100 }); state.defaultStack = 200; state.seats[2].stack = null; state.seats[2].committed = 10; assert.equal(Betting.isAllIn(state, state.seats[2]), false); }); test("the seats marked are exactly the ones the action passes over", () => { const state = makeTable({ seatCount: 6, seated: [0, 1, 2, 3], stack: 100 }); state.seats[1].stack = 8; state.seats[3].stack = 30; Betting.beginHand(state); // Everyone in, two of them for less than the others can cover. for (let step = 0; step < 4; step++) Betting.allIn(state, state.actingSeatIndex); const marked = state.seats .map((player, index) => (Betting.isAllIn(state, player) ? index : null)) .filter(index => index !== null); const skipped = state.seats .map((player, index) => player.inHand && !player.folded && Betting.nextToAct(state, index - 1) !== index ? index : null) .filter(index => index !== null); assert.deepEqual(marked, skipped); assert.ok(marked.length > 0, "the scenario should actually produce all-in players"); }); test("nobody is marked once the next hand starts", () => { const state = makeTable({ seatCount: 4, seated: [0, 1, 2], stack: 100 }); state.seats[2].stack = 5; Betting.beginHand(state); Betting.allIn(state, state.actingSeatIndex); assert.ok(state.seats.some(player => Betting.isAllIn(state, player))); // The short stack got there by winning nothing; give them chips back the way a // dealer would before the next deal. HoldemState.startNextHand(state); state.seats[2].stack = 50; assert.equal(state.seats.filter(player => Betting.isAllIn(state, player)).length, 0); }); test("marking nobody doesn't move a chip", () => { const state = makeTable({ seatCount: 6, seated: [0, 1, 2, 3], stack: 100 }); state.seats[3].stack = 12; Betting.beginHand(state); const before = chipsOnTable(state); state.seats.forEach(player => Betting.isAllIn(state, player)); assert.equal(chipsOnTable(state), before); });