Files
holdem_poker/engine
thejayman77 f1222401fb Fix four rules and modelling defects found in review
TDA Rule 47 — cumulative incomplete raises:
A boolean could not express "facing at least a full raise since acting", so
several short all-ins that together reached a full raise failed to reopen
betting. Seat now records lastActedAtBet (the currentBet when it last acted);
mayRaise() reopens when currentBet - lastActedAtBet >= minRaiseSize. This
subsumes the single-incomplete-raise case, so the hasActed reset in apply() is
gone.

TDA Rule 20 — odd chips:
Split-pot remainders were awarded in seat-list order. They now go to the first
winning seat clockwise from the button. The old test also never produced an odd
pot (20 chips heads-up), so it only ever proved an even split; it now builds a
genuinely odd 25-chip pot via a folded small blind and asserts which seat takes
the extra chip.

OpponentModel skipped events across hands:
It inferred a new hand from a shrinking history, but history is cleared each
hand: having consumed 3 events, first observing the next hand at 4 events left
4 < 3 false and silently dropped the first three. observe() now takes an
explicit handNumber, exposed via DecisionContext and Table.handNumber.

PreflopChart percentile semantics:
The 169 classes were ranked equally, but they are not equally likely — a pair is
6 of 1326 combinations, suited 4, offsuit 12. "Top 12%" therefore meant 12% of
classes, not of dealt hands, so looseness did not mean what it claimed.
Percentiles are now weighted by combination count.

Tests: 30 -> 37. Each new test was verified to fail with its fix reverted.
Skill gradient still monotonic: 85.9 / 79.8 / 17.4 / -183.1 bb/100 over 50k
hands, chips conserved on both tables.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 05:03:11 -04:00
..