id: d37f017147f141c48d1c9ac533d846a8
parent_id: 
item_type: 1
item_id: 31997234919d40e7acbd146715540d51
item_updated_time: 1780223889422
title_diff: "[{\"diffs\":[[1,\"SNG Strategy Architecture Design\"]],\"start1\":0,\"start2\":0,\"length1\":0,\"length2\":32}]"
body_diff: "[{\"diffs\":[[1,\"> **Status**: Design — not yet implemented\\\n> **Scope**: Add Sit-and-Go tournament strategy chain to `super_marvin`\\\n\\\n---\\\n\\\n## 1. Overview\\\n\\\nArchitecture for porting the Java SNG strategy chain (`JointNoLimitSnGStrategy`) into the Rust `holdem_bots` crate. The SNG bot uses `FirstApplicable` voting to select among prioritized sub-strategies.\\\n\\\nIntroduces a new `holdem_bots/src/sng/` module with five new strategies, reuses two existing cash strategies, and adds one new helper method to `StrategyContext`.\\\n\\\n```\\\nSNG Bot Assembly (FirstApplicable Voting)\\\n├── 1. FoldMicroStack\\\n├── 2. StealFromInactive\\\n├── 3. PushOrFold\\\n├── 4. BlindSteal\\\n├── 5. BlindReSteal\\\n├── 6. BigStackPreFlop (reuse)\\\n└── 7. PostFlopStrategy (reuse)\\\n```\\\n\\\n---\\\n\\\n## 2. Strategy Comparison Table\\\n\\\n| # | Java Strategy | Rust Name | Status | Module |\\\n|---|--------------|-----------|--------|--------|\\\n| 1 | `FoldMicroStackStrategyV1` | `FoldMicroStack` | **New** | `sng::fold_micro_stack` |\\\n| 2 | `StealFromInactiveStrategyV1` | `StealFromInactive` | **New** | `sng::steal_from_inactive` |\\\n| 3 | `ModularNashICM` | — | **Skipped** | Using `PushOrFold` instead |\\\n| 4 | `PushOrFoldStrategyV3` | `PushOrFold` | **New** | `sng::push_or_fold` |\\\n| 5 | `BlindStealStrategyV1` | `BlindSteal` | **New** | `sng::blind_steal` |\\\n| 6 | `BlindReStealStrategyV1` | `BlindReSteal` | **New** | `sng::blind_re_steal` |\\\n| 7 | `ShortStackPreFlopStrategyV2` | `ShortStackPreFlop` | **Replaced** | Cash version NOT used in SNG |\\\n| 8 | `BigStackPreFlopStrategyV2` | `BigStackPreFlop` | **Reuse** | `cash::big_stack_preflop` |\\\n| 9 | `PostFlopStrategyV1` | `PostFlopStrategy` | **Reuse** | `cash::postflop` |\\\n\\\n**Key design decision**: SNG chain does NOT include `ShortStackPreFlop` from cash module. Instead, `PushOrFold` (≤14 BB), `BlindSteal` (13–24 BB), and `BlindReSteal` (13–24 BB) cover short-stack SNG-specific play.\\\n\\\n---\\\n\\\n## 3. Strategy Designs\\\n\\\n### 3.1 FoldMicroStack (Low complexity)\\\n- **Applicable when:** Preflop, stack < 0.5 × SB, 4-5 active players\\\n- **Action:** AA/KK/QQ → AllIn, otherwise Fold\\\n- `consider_fold_as_not_applicable()` = `false`\\\n\\\n### 3.2 StealFromInactive (Low-Medium complexity)\\\n- **Applicable when:** Preflop, stack ≤ 50 BB, no raises, all opponents sitting out\\\n- **Action:** Min-raise (2× BB), or AllIn if raise > stack\\\n- Needs `all_opponents_inactive()` helper on StrategyContext\\\n\\\n### 3.3 PushOrFold (High complexity)\\\n- **Applicable when:** Preflop, stack ≤ 14 BB\\\n- **Action:** Chart-based push/fold decision\\\n- Uses position-based hand range charts\\\n- Stack ≤ 5 BB: wider ranges; ≤ 10 BB: medium; ≤ 14 BB: tighter\\\n- `consider_fold_as_not_applicable()` = `false` (owns the decision when ≤14 BB)\\\n\\\n**Push range chart (simplified):**\\\n| Position | ≤ 5 BB | ≤ 10 BB | ≤ 14 BB |\\\n|----------|--------|---------|---------|\\\n| SB | Any ace, K7+, Q9+, J9+, T9+, 22+ | A8+, KJ+, QJ+, 55+ | AT+, KQ+, 77+ |\\\n| BTN | Any ace, K8+, Q9+, J9+, 22+ | A9+, KJ+, QJ+, 55+ | AJ+, KQ+, 88+ |\\\n| CO | A5+, K9+, Q9+, 33+ | AT+, KJ+, 66+ | AQ+, 99+ |\\\n| Early | A8+, KJ+, QJ+, 66+ | AJ+, KQ+, 88+ | AK+, TT+ |\\\n\\\n### 3.4 BlindSteal (Medium complexity)\\\n- **Applicable when:** Preflop, 13-24 BB, no raises/callers, position in [CO, BTN, SB]\\\n- **Action:** Classify hand (Premium/Strong/Steal-worthy/Weak) → Raise or Fold\\\n- `consider_fold_as_not_applicable()` = `true`\\\n\\\n### 3.5 BlindReSteal (Medium complexity)\\\n- **Applicable when:** Preflop, 13-24 BB, someone raised, we are BB, raiser in late position, heads-up\\\n- **Action:** Premium/Strong → AllIn, Good → Call if pot odds, Weak → Fold\\\n- `consider_fold_as_not_applicable()` = `true`\\\n\\\n---\\\n\\\n## 4. SNG Bot Assembly Config\\\n\\\n```toml\\\n# configs/bots/sng_nl.toml\\\n[bot]\\\nname = \\\"sng_nl\\\"\\\nvoting_mode = \\\"first_applicable\\\"\\\n\\\n[[strategies]]\\\ntype = \\\"fold_micro_stack\\\"\\\n\\\n[[strategies]]\\\ntype = \\\"steal_from_inactive\\\"\\\n\\\n[[strategies]]\\\ntype = \\\"push_or_fold\\\"\\\nconfig = { max_stack_bb = 14.0 }\\\n\\\n[[strategies]]\\\ntype = \\\"blind_steal\\\"\\\nconfig = { min_stack_bb = 13.0, max_stack_bb = 24.0, raise_size_bb = 2.5 }\\\n\\\n[[strategies]]\\\ntype = \\\"blind_re_steal\\\"\\\nconfig = { min_stack_bb = 13.0, max_stack_bb = 24.0 }\\\n\\\n[[strategies]]\\\ntype = \\\"big_stack_preflop\\\"\\\n\\\n[[strategies]]\\\ntype = \\\"postflop_static\\\"\\\n```\\\n\\\n---\\\n\\\n## 5. StrategyContext Extensions Needed\\\n\\\n1. **`num_opponents_sitting_out()`** — count inactive opponents\\\n2. **`all_opponents_inactive()`** — check if all opponents sitting out\\\n3. **`position_for_seat(seat)`** — get position of player at given seat\\\n\\\n---\\\n\\\n## 6. Implementation Order\\\n\\\n1. StrategyContext extensions (context.rs)\\\n2. FoldMicroStack — simplest, validates module structure\\\n3. StealFromInactive\\\n4. BlindSteal\\\n5. BlindReSteal\\\n6. PushOrFold — most complex, hand range charts\\\n7. sng/mod.rs — module declarations\\\n8. registrations.rs — register all SNG strategies\\\n9. lib.rs — add `pub mod sng`\\\n10. Config files — create all TOML configs\\\n11. Integration test — verify full chain assembles and plays\\\n\\\n---\\\n\\\n## 7. Open Questions\\\n\\\n1. **PlayerState for sitting-out**: Does `holdem_core` have a `SittingOut` variant, or infer from `!is_in_hand() && stack > 0`?\\\n2. **Tournament simulation support**: Does `holdem_sim` support `game_type = \\\"Tournament\\\"` with blind levels and payouts?\\\n3. **PushOrFold chart data**: Exact ranges should be ported verbatim from Java source.\\\n4. **BlindReSteal BB position**: Is `our_position == 1` always correct for BB?\"]],\"start1\":0,\"start2\":0,\"length1\":0,\"length2\":5298}]"
metadata_diff: {"new":{"id":"31997234919d40e7acbd146715540d51","parent_id":"2c8da247905946c3aa19eb4936e16323","latitude":"0.00000000","longitude":"0.00000000","altitude":"0.0000","author":"","source_url":"","is_todo":0,"todo_due":0,"todo_completed":0,"source":"joplin-desktop","source_application":"net.cozic.joplin-desktop","application_data":"","order":1780223817215,"user_updated_time":1780223817215,"markup_language":1,"is_shared":0,"share_id":"","conflict_original_id":"","master_key_id":"","user_data":"","deleted_time":1780223889422},"deleted":[]}
encryption_cipher_text: 
encryption_applied: 0
updated_time: 2026-05-31T10:46:29.050Z
created_time: 2026-05-31T10:46:29.050Z
type_: 13