Add calling/defense ranges (facing a shove & facing an open) - #4
Merged
Conversation
New CallingRange module covers the two situations PushFoldRange and OpeningRange don't: hero reacting to someone else's action rather than acting first. DefendingPosition extends the six-position scheme with the big blind, since a defending hero can be exactly the position Position deliberately excludes. Both defense models reuse PushFoldRange/OpeningRange's own numbers rather than inventing a second opinion on how wide any position shoves or opens — big-blind-facing-a-shove is the one case with a real Nash equivalent (heads-up SB-shove/BB-call), everything else is a disclosed, hand-tuned extrapolation off that. See ai-docs/RANGES.md for the full source basis, including exactly which numbers are sourced vs. hand-tuned placeholders. PreflopGrid gains callingDecisions/openDefenseDecisions, returning nil for position pairings that can't happen at an unopened table (e.g. UTG can't be facing anyone's shove). 22 new tests: coverage, nil-guards, threshold monotonicity by stack and position, suited-never-loses-to-offsuit, and grid/model consistency.
Extends the four-way mode picker (Push/Fold, Opening, Facing Shove, Facing Open) with an opponent-position + hero-position picker pair for the two new defense modes, replacing the single position picker used by the aggressor modes. The hero picker filters to only positions that could plausibly be facing the chosen opponent (DefendingPosition.actionOrderIndex > Position.actionOrderIndex), auto-resetting to the big blind — always valid — if the opponent choice would otherwise strand it on an impossible pairing. Facing Open renders a third grid color (3-bet vs. call vs. fold) since it's the one mode with three distinct actions. Both defense modes show a persistent caveat line pointing at RANGES.md's confidence notes, rather than presenting these numbers with the same certainty as push/fold or opening.
testtest126
added a commit
that referenced
this pull request
Jul 21, 2026
Resolves conflicts in PreflopRangeView.swift and PreflopRangeUITests.swift by keeping both features: the four-way mode picker (Push/Fold, Opening, Facing Shove, Facing Open) from the calling-ranges PR, and the PKO bounty overlay (toggle, bounty slider, "you cover villain" toggle, bounty-only grid color) from this branch — the overlay only ever applies in Push/Fold mode, so the two never actually compete for the same UI state. CellStyle gains a fourth case (.bountyOnly) alongside the existing .primary/.secondary/.fold from the calling-ranges merge. summaryText and the caveat line both switch on mode plus the bounty-active flag rather than mode alone. ai-docs/RANGES.md and PreflopGrid.swift merged cleanly with no conflicts — the two PRs touched non-overlapping sections/functions there. swift test: 135/135 passing (116 post-#4 baseline + 19 bounty tests, none lost). App builds clean; all 4 PreflopRangeUITests pass (base grid, bounty overlay, facing shove, facing open).
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
Adds the biggest gap flagged in the last repo audit: hero defending rather than acting first. Two new decision types, both built on the existing
PushFoldRange/OpeningRange/ChenScorepipeline — no new hand-ranking system, no new range-model architecture.CallingRange.decideVsShove) — short stacks (~1-20bb), call-or-fold against someone else's all-in.CallingRange.decideVsOpen) — standard stacks (~20-100bb), fold/call/3-bet against someone else's open-raise.New
DefendingPositionenum (UTG...SB + BB) models hero's defending seat —Positiondeliberately excludes BB (it can't open or shove into an unopened pot), but BB is exactly who most often calls one. Both enums share action-order semantics soCallingRange/PreflopGridcan reject nonsensical pairings (e.g. UTG can never be "facing" anyone's shove) by returningnilinstead of a fabricated decision.PreflopGridgainscallingDecisions/openDefenseDecisions;PreflopRangeViewgets a 4-way mode picker (Push/Fold, Opening, Facing Shove, Facing Open) with an opponent+hero position-picker pair for the two new modes, a third grid color for 3-bet vs. call vs. fold, and a persistent on-screen caveat pointing at the docs.Range assumptions & sources — read before trusting a number
Full writeup in
ai-docs/RANGES.md(new "Facing a Shove" / "Facing an Open" sections). Short version:PushFoldRangeSB figure (58% at 10bb) — close enough to treat as the same phenomenon.PushFoldRangepercentage, with per-position discount factors that are hand-tuned placeholders, not sourced.OpeningRangepercentage to the button's — reusesOpeningRange's numbers rather than inventing a second opinion.None of this is solver output. Every model in this codebase says so already; these two say it more, because they're the least certain ones here.
Testing
swift test: 116/116 passing (94 before this PR + 22 new).PreflopRangeUITestspass, including two new tests exercising both defense modes end-to-end (mode switch → position pickers filter correctly → grid renders → summary reacts to position change).Housekeeping
origin/feature/opening-range-rfibranch (PR Add Opening (RFI) range viewer alongside push/fold #3, already merged).Not merging — flagging for review on the honesty/soundness of the range assumptions per instructions.