// What a pot-sized raise actually is. // // The raise pad worked it out as "the current bet plus the pot as it stands", which // leaves out the fact that the raiser calls first and their call is in the pot before // the raise is measured off it. Every quick amount came out short — pre-flop at 1/2 it // offered "Pot $5" where a pot raise is $7. Players say "pot" out loud meaning a // definite number, and a dealer tapping the button that claims to be it should record // what was actually said. const test = require("node:test"); const { describe } = require("node:test"); const assert = require("node:assert"); const { Betting, makeTable } = require("./load"); describe("pre-flop at 1/2", () => { const dealt = () => { const state = makeTable({ seatCount: 6, seated: [0, 1, 2, 3], stack: 200, dealerSeatIndex: 0 }); Betting.beginHand(state); return state; }; test("a pot raise from the first player to act is $7", () => { // Call the $2, which makes the pot $5, then raise $5. const state = dealt(); assert.equal(Betting.potSoFar(state), 3, "the blinds"); assert.equal(Betting.potRaiseTo(state, state.actingSeatIndex), 7); }); test("half pot is $4.50, which is above the $4 minimum rather than equal to it", () => { // The old arithmetic gave $3.50, which clamped up to the minimum and put the // same $4 on two buttons side by side. const state = dealt(); assert.equal(Betting.potRaiseTo(state, state.actingSeatIndex, 0.5), 4.5); assert.notEqual(Betting.potRaiseTo(state, state.actingSeatIndex, 0.5), Betting.minRaiseTo(state), "the two quick buttons say different things"); }); test("the small blind owes less, so their pot raise is smaller", () => { // They have $1 in already: call $1, pot becomes $4, raise $4, total $6. const state = dealt(); const { sbIndex } = require("./load").HoldemState.getBlindSeats(state); assert.equal(Betting.toCall(state, state.seats[sbIndex]), 1); assert.equal(Betting.potRaiseTo(state, sbIndex), 6); }); test("the big blind owes nothing, so it is just the pot", () => { const state = dealt(); const { bbIndex } = require("./load").HoldemState.getBlindSeats(state); assert.equal(Betting.toCall(state, state.seats[bbIndex]), 0); assert.equal(Betting.potRaiseTo(state, bbIndex), 5, "the $2 bet plus the $3 pot"); }); }); describe("after the flop", () => { const flopWithBet = () => { const state = makeTable({ seatCount: 6, seated: [0, 1, 2], stack: 500, dealerSeatIndex: 0 }); Betting.beginHand(state); while (state.actingSeatIndex !== null) Betting.call(state, state.actingSeatIndex); Betting.closeStreet(state); return state; }; test("a pot raise facing a bet is three times the bet plus the dead money", () => { const state = flopWithBet(); const potBefore = Betting.potSoFar(state); // $6 carried over const bettor = state.actingSeatIndex; Betting.raiseTo(state, bettor, 10); const raiser = state.actingSeatIndex; // Call $10, pot becomes $26, raise $26 → $36. Which is 3×10 + 6. assert.equal(Betting.potRaiseTo(state, raiser), 36); assert.equal(Betting.potRaiseTo(state, raiser), 3 * 10 + potBefore); }); test("half pot facing that bet is $23", () => { const state = flopWithBet(); Betting.raiseTo(state, state.actingSeatIndex, 10); // Call $10, pot becomes $26, raise $13 → $23. assert.equal(Betting.potRaiseTo(state, state.actingSeatIndex, 0.5), 23); }); test("facing no bet at all it is a plain pot-sized bet", () => { const state = flopWithBet(); assert.equal(state.currentBet, 0, "nobody has bet the flop"); assert.equal(Betting.toCall(state, state.seats[state.actingSeatIndex]), 0); assert.equal(Betting.potRaiseTo(state, state.actingSeatIndex), Betting.potSoFar(state)); }); }); describe("it stays sane at the edges", () => { test("a seat that doesn't exist gets zero rather than throwing", () => { const state = makeTable({ seatCount: 6, seated: [0, 1], stack: 100 }); assert.equal(Betting.potRaiseTo(state, 99), 0); }); test("the amount is always at least a call", () => { // A raise-to below the current bet would be nonsense to offer. Every fraction // from a tenth up lands at or above what the player owes. const state = makeTable({ seatCount: 6, seated: [0, 1, 2, 3], stack: 200 }); Betting.beginHand(state); const index = state.actingSeatIndex; [0.1, 0.25, 0.5, 0.75, 1].forEach(fraction => { assert.ok(Betting.potRaiseTo(state, index, fraction) >= state.currentBet, `${fraction} of the pot should still cover the bet`); }); }); test("cent-sized blinds don't drift", () => { const state = makeTable({ seatCount: 6, seated: [0, 1, 2], stack: 20, smallBlind: 0.05, bigBlind: 0.1 }); Betting.beginHand(state); // Pot $0.15, owes $0.10: call to $0.25, raise $0.25 → $0.35. assert.equal(Betting.potRaiseTo(state, state.actingSeatIndex), 0.35); }); });