Skip to content

Moregames#96

Merged
folkengine merged 6 commits into
morefrom
moregames
May 13, 2026
Merged

Moregames#96
folkengine merged 6 commits into
morefrom
moregames

Conversation

@folkengine
Copy link
Copy Markdown
Collaborator

No description provided.

@folkengine folkengine merged commit 34c3f20 into more May 13, 2026
@folkengine folkengine deleted the moregames branch May 13, 2026 11:55
folkengine added a commit that referenced this pull request May 16, 2026
* Moregames (#96)

* Added EPICS for adding other poker games

* EPIC-29: variant engine foundation (Phases 1-11) + defect note

* EPIC-30: Fixed-Limit Hold'em (Phases 1-11)

* EPIC-31: Pot-Limit Omaha Hi (Phases 1-10)

* EPIC-31: Pot-Limit Omaha Hi (Phases 1-10)

* ...

* EPIC-32: Seven-Card Stud Hi (Phases 1-13)

EPIC-32 implementation complete. All 13 phases shipped (Phase 12 as live-play smoke; replay round-trip deferred to v1.1 with rationale
  documented).

  ┌────────────────────────────────────────┬─────────────────────────────────────────────────────────────────────────────────────────────┐
  │                 Phase                  │                                           Result                                            │
  ├────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤
  │ 1: GamePhase Stud variants + bet-tier  │ ✅ Stud3rd..Stud7th + stud_street_index + next_stud_street                                  │
  ├────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤
  │ 2: Antes + family-dispatched forced    │ ✅ act_antes + TableAction::BetAnteForced                                                   │
  │ bets                                   │                                                                                             │
  ├────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤
  │ 3: Visibility-aware dealing            │ ✅ deal_card_to_seat_with_visibility, deal_stud_3rd_street, deal_stud_street                │
  ├────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤
  │ 4: Bring-in selection + posting        │ ✅ lowest/highest_upcard_seat, third_street_extreme_upcard_seat, act_bring_in,              │
  │                                        │ TableAction::StudBringInPost                                                                │
  ├────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤
  │ 5: Stud action order                   │ ✅ best_visible_hand_seat with phase-aware upcard truncation;                               │
  │                                        │ VisibleHandMode::HighStud/LowRazz                                                           │
  ├────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤
  │ 6: stud_hi_from_seats + session        │ ✅ PokerSession::start_hand + advance_street Stud branches                                  │
  │ dispatch                               │                                                                                             │
  ├────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤
  │ 7: Stud showdown via Seven::eval       │ ✅ stud_river_case_eval (bypasses build_game's Board requirement)                           │
  ├────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤
  │ 8: Mid-hand Stud equity                │ ✅ 3- and 4-card heuristic bucket in RuleBasedDecider::hand_equity                          │
  ├────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤
  │ 9: HandHistory visibility serde        │ ✅ PlayerEntry.hole_cards_visibility, Stakes.bring_in, PlayerEntry::to_seven, replay routes │
  │                                        │  Stud through stud_hi_from_seats                                                            │
  ├────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤
  │ 10: for_stud_hi factory + profiles     │ ✅ tight_aggressive_stud_hi.yaml + loose_passive_stud_hi.yaml                               │
  ├────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤
  │ 11:                                    │ ✅ 20-hand bot-vs-bot demo                                                                  │
  │ examples/interactive_play_stud_hi.rs   │                                                                                             │
  ├────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤
  │ 12: Stud replay-consistency test       │ ✅ Live smoke + YAML field round-trip (replay round-trip deferred to v1.1)                  │
  ├────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤
  │ 13: corrigendum + verification         │ ✅                                                                                          │
  └────────────────────────────────────────┴─────────────────────────────────────────────────────────────────────────────────────────────┘

  Final pin tests:
  - 9057 lib tests pass (+3 from EPIC-31: for_stud_hi marker + 2 YAML load tests)
  - 657 doc tests pass (+5)
  - 4/4 replay_consistency tests pass — NLHE, FLHE, PLO + Stud live-smoke
  - interactive_play_stud_hi 20 hands run end-to-end
  - bot_selfplay NLHE regression-free
  - Clippy clean on every EPIC-32 file

  Files changed: 10 modified, 3 new (2 YAML + 1 example). ~1279 lines added.

  ★ Insight ─────────────────────────────────────
  - Stud replay round-trip surfaced a deep architectural gap: live action ordering depends on the per-street visible-card set, which doesn't
  survive a one-shot inject_hole_cards injection of all 7 cards. Phase-aware truncation in best_visible_hand_seat +
  third_street_extreme_upcard_seat aligns live and replay for bring-in / first-to-act selection, but the deeper issue is that Streets
  (preflop/flop/turn/river) doesn't carry stud street action lists separately. The proper fix is either incremental dealing during replay or
  a StudStreets enum — both are v1.1 polish.
  - The hand-loop "growth" mostly happened in two methods: PokerSession::start_hand and PokerSession::advance_street both gained Stud-family
  branches at the top, leaving the Hold'em-family path untouched. This is the right shape — variant-specific behavior at the dispatch layer,
  shared infrastructure (bring_it_in, apply_action, side-pot resolution) underneath.
  - The BetAnteForced table-action variant already existed from earlier work but wasn't wired. Phase 2's act_antes finally exercises it. This
   is the third time during the variant initiative that EPIC-29's foundation paid for itself: pre-existing scaffolding (ForcedBets.bring_in,
  SeatHand, Visibility, STUD_HI_STREETS, BetAnteForced) was waiting to be activated.
  ─────────────────────────────────────────────────

* EPIC-33: Razz (A-5 Lowball) [Phases 1-7]

  Wires Razz showdown evaluation on top of EPIC-32's Stud engine.
  Razz reused ~95% of Stud's infrastructure (bring-in, action order,
  dealing, is_game_over, replay visibility) — the only load-bearing
  work was the CaliforniaHandRank → Eval bridge.

  - Phase 1: Eval::from_razz_rank + Eval::from_seven_razz; new
    HandRankName::RazzLow + HandRankClass::Lowball variants.
  - Phase 2: razz_river_case_eval + dispatch split (StudHi vs Razz)
    in river_case_eval_for_variant + build_eval_for_seat.
  - Phase 3: razz_from_seats constructor (mirrors stud_hi_from_seats).
  - Phase 4: BotProfile::for_razz factory + 2 reference YAML profiles.
  - Phase 5: examples/interactive_play_razz.rs — 20-hand smoke.
  - Phase 6: HandHistory replay routes HandVariant::Razz through
    razz_from_seats; new test_razz_bot_selfplay_replay_roundtrip.
  - Phase 7: Verification + EPIC-33 corrigendum.

  Inversion math turned out unnecessary — HandRank::cmp is already
  inverted, cancelling CaliforniaHandRank's lower-is-better ordering.

  Razz full replay round-trip deferred to v1.1 (incremental-dealing
  gap shared with Stud Hi).

EPIC-33: Razz (A-5 Lowball) [Phases 1-7]

  Wires Razz showdown evaluation on top of EPIC-32's Stud engine.
  Razz reused ~95% of Stud's infrastructure (bring-in, action order,
  dealing, is_game_over, replay visibility) — the only load-bearing
  work was the CaliforniaHandRank → Eval bridge.

  - Phase 1: Eval::from_razz_rank + Eval::from_seven_razz; new
    HandRankName::RazzLow + HandRankClass::Lowball variants.
  - Phase 2: razz_river_case_eval + dispatch split (StudHi vs Razz)
    in river_case_eval_for_variant + build_eval_for_seat.
  - Phase 3: razz_from_seats constructor (mirrors stud_hi_from_seats).
  - Phase 4: BotProfile::for_razz factory + 2 reference YAML profiles.
  - Phase 5: examples/interactive_play_razz.rs — 20-hand smoke.
  - Phase 6: HandHistory replay routes HandVariant::Razz through
    razz_from_seats; new test_razz_bot_selfplay_replay_roundtrip.
  - Phase 7: Verification + EPIC-33 corrigendum.

  Inversion math turned out unnecessary — HandRank::cmp is already
  inverted, cancelling CaliforniaHandRank's lower-is-better ordering.

  Razz full replay round-trip deferred to v1.1 (incremental-dealing
  gap shared with Stud Hi).

* fix: accept Axs/Axo/Ax as aliases for A2s+/A2o+/A2+

  The combo parser at src/analysis/gto/combo.rs only knew explicit
  anchor tokens (A2s+, A3s+, etc.), so any-suited-Ace shorthand silently
  fell through to "Unable to process Axs" stdout noise and dropped the
  range entry. loose_passive.yaml's open_raise field tripped this.

  Two-part fix:
  - loose_passive.yaml: Axs -> A2s+ (canonical form).
  - combo.rs: also accept "axs" / "axo" / "ax" as aliases that expand to
    the same Combo constants. Both notations now produce identical
    parsed ranges; YAMLs can use whichever reads better.

  Adds 6 new parametrized rstest cases (both casings).

* docs: spec for position
  indicators in interactive_play examples

* feat(interactive_play): add position_tag helper with HU collapse

* feat(interactive_play): show position tags on Stacks line

* feat(interactive_play): add position tag column to action lines

* feat(interactive_play): show Position field in Your turn box

* docs: spec scope trim + implementation plan

* needs work

* fix(bot): gate YAML-loading tests behind bot-profiles feature

  The PLO/Stud Hi/Razz/FLHE/NLHE *_yaml_loads tests call
  BotProfile::from_yaml_str, which is gated behind feature = \"bot-profiles\".
  Without the matching cfg on the tests, --no-default-features breaks the
  test build in CI.

* bump
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant