Add Omaha/PLO foundation: hand type, 2+3 evaluator, equity (Phase 1) - #12
Merged
Conversation
Added alongside HoleCards, never replacing it — no existing NLHE model reads or is affected by this type. Canonical (order-independent) storage, explicit per-card notation (no invented Hold'em-style shorthand — Omaha has no standardized one), and a descriptive (not parseable) suitPattern label. Card(notation:) is a small new Card.swift-adjacent parsing helper, added in this file rather than Card.swift itself, matching HoleCards.swift's own precedent of hosting Rank.from(symbol:) alongside the type that needs it.
Enumerates the 60 legal (2-of-4-hole, 3-of-5-board) combinations via the existing, unmodified HandEvaluator.bestHand(from:) and keeps the best. Tests specifically prove the constraint is enforced, not assumed: a four-aces hole hand that could look like quads/trips if the 2-card cap were ignored (must be exactly a pair), and a four-spades hole hand that could look like a royal flush (must be High Card, since only 1 board spade is available) — plus a positive counterpart proving a legal straight flush is still found when the split genuinely allows one, and a brute-force cross-check of the 60-combination enumeration itself.
Same two-mode shape as Equity (headsUp exact, monteCarlo fixed-seed), built on OmahaHandEvaluator instead of HandEvaluator directly. No preflop exact — roughly 2x Hold'em's own already-slow preflop exact case. Validated against the closest thing to a solid citation web search turned up (AAKK double-suited "only a 3-2 favorite" over a strong double-suited rundown, repeated across multiple PLO strategy sources): measured 61.96%, within 2 points of the cited ~60%. Two additional tests are exact and hand-verifiable with no citation needed at all (a locked-quads win, and a symmetric-suits tie by construction) — the primary correctness gate per this project's own "pick a hand-verifiable spot over an unsourced number" rule.
Full write-up of why Omaha needs a new foundation (not a reuse of any NLHE model), the citation search for a validate-able PLO equity figure and why it landed on a directional/wide-tolerance check plus exact hand-verifiable tests, the flop-exact performance finding from building the app screen, and a concrete proposal for what Phase 2 (preflop hand-strength/ranges) should be and why it's judgment-heavy in a way Phase 1 deliberately wasn't.
Explicit 4-card notation in/out (no invented hand-class shorthand), Fast (Monte Carlo) / Precise (exact, postflop only) modes mirroring EquityCalculatorView's own async-safety pattern. Labeled "(Beta)" — Phase 1 foundation, no preflop hand-strength/ranges yet. UI tests found and fixed a real bug along the way: a still-open keyboard intercepted the Calculate button's tap, landing on a keyboard key instead and corrupting the board notation field — fixed by dismissing the keyboard (typing a newline) before the next interaction, not by working around the symptom.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary — Phase 1 of the variants/PLO track
OmahaHoleCards: the 4-card hand type, added alongsideHoleCards— no existing NLHE model (ChenScore, every range model,Equity,ICM,GameFormat) reads or is affected by this type's existence. Canonical (order-independent) storage; explicit per-card notation ("AsKsAhKh") rather than an invented Hold'em-style shorthand — Omaha has no standardized compact notation the way "AKs"/"AKo" is standardized, and inventing one would be exactly the kind of judgment call this phase avoided.OmahaHandEvaluator: enforces Omaha's defining rule — best 5-card hand uses exactly 2 of 4 hole cards + exactly 3 of 5 board cards. Enumerates all 60 legal combinations via the existing, unmodifiedHandEvaluator.bestHand(from:). Tests specifically prove the constraint is enforced (not just assumed): a four-aces hole hand that would look like quads/trips if the cap were ignored (must be exactly a pair), a four-spades hole hand that would look like a royal flush with only 1 board spade available (must be High Card), plus a positive counterpart proving a legal straight flush is still found when the split genuinely allows one.OmahaEquity: same exact/Monte Carlo shape asEquity, built on the legal evaluator. No preflop exact (≈2x Hold'em's already-slow preflop exact case — documented, never called).OmahaEquityCalculatorView, labeled "(Beta)"): explicit notation in/out, Fast/Precise modes, wired intoStudyTool.Validation — actual vs. published, and the hand-verifiable fallback
No single citable source with a precisely-stated PLO equity figure and fully-specified matchup was found (web search surfaced AAKK-vs-random figures ranging 64–73% depending on source, too wide a spread to validate a decimal against per this project's "a bad number is worse than none" rule). What was consistently repeated across independent sources (e.g. pokerlistings.com's "Pot-Limit Omaha: Top 30 Starting Hands"): AA-KK double-suited is only a 3-2 favorite (~60%) over a strong double-suited rundown like 8-7-6-5.
61.96% lands within 2 points of the cited ~60%.
Per this project's own fallback rule (pick a hand-verifiable spot when no solid citation exists), two exact tests carry the real correctness weight:
winRate == 1.0exactly, provable by hand.tieRate == 1.0exactly, a tie by symmetry, not coincidence.What went wrong along the way (and got fixed at the root, not worked around)
Test plan
swift test(PokerKit): 263/263 green (235 baseline + 28 new Omaha tests).BankrollTrackerUITests.testLogSessionUpdatesListAndSummary, previously confirmed pre-existing/flaky on a cleanmaincheckout, unrelated to this branch).OmahaHoleCardsTests,OmahaHandEvaluatorTests,OmahaEquityTests,OmahaEquityCalculatorUITests.Proposed Phase 2 scope
PLO preflop hand-strength / starting-hand ranges — deliberately not started here. This is judgment-heavy in a way Phase 1 wasn't: Chen's heuristic doesn't extend to 4 cards, and the Omaha hand-strength heuristics that do exist in strategy literature are themselves competing/disputed, not an agreed standard the way Chen's is for Hold'em. Proposed approach (see
ai-docs/OMAHA.md's "What Phase 2 should be" section): useOmahaEquity.monteCarloequity-vs-random-hand itself as the ranking signal (this project's own exact math, not a second borrowed heuristic), validate it directionally against known strong/weak Omaha hands, then build push/fold-style thresholds on top with every percentage flagged as hand-tuned — same postureRANGES.mdalready takes for Hold'em.🤖 Generated with Claude Code