id: 7b21afdb64474a29be4e2566bb6b3597
parent_id: 
item_type: 1
item_id: 88c7a2bd92a64a459996ffd2ae01ee04
item_updated_time: 1782797680039
title_diff: "[{\"diffs\":[[1,\"Gen 4 — Adaptive Table & Player Models (Implementation Plan)\"]],\"start1\":0,\"start2\":0,\"length1\":0,\"length2\":60}]"
body_diff: "[{\"diffs\":[[1,\"# Gen 4 — Adaptive Table & Player Models\\\n\\\n## Goal\\\n\\\nReplace static config profiles (cash_nl, cash_nl_normal, cash_nl_loose) with a single adaptive strategy that learns opponent behavior from observed play. Profiles persist across sessions as JSON files.\\\n\\\n## Architecture\\\n\\\n```\\\nEvent Stream → Observation Engine → TableProfile + PlayerProfile(s)\\\n→ Range Inference (VPIP/AF → per-opponent HandRange)\\\n→ Config Interpolation (table stats → floating Gen3Config params)\\\n→ Gen3 Equity (per-opponent MC) + Decision (floating thresholds)\\\n→ Prediction Logging at showdown\\\n```\\\n\\\n## Data Model\\\n\\\n### PlayerProfile (per opponent, keyed by name + game context)\\\n\\\nStats tracked via EMA (exponential moving average) with sample_count:\\\n- **VPIP** — voluntarily put money in pot preflop\\\n- **PFR** — preflop raise frequency  \\\n- **AF** — postflop aggression factor (bets+raises)/calls\\\n- **Fold-to-Bet** — fold frequency facing postflop bets\\\n- **Fold-to-Cbet** — fold facing continuation bets\\\n- **Cbet freq** — bet flop after raising preflop\\\n- **3-bet frequency**\\\n- **WTSD** — went to showdown\\\n- Showdown hand histogram (for range validation)\\\n\\\n### TableProfile (aggregate across all players)\\\n\\\nSame stats pooled across all observed players. Converges faster (~20-30 hands) because data is shared.\\\n\\\n### Storage Layout\\\n\\\n```\\\nprofiles/\\\n  cash_nl_500_1000/\\\n    table_torn-holdem.json\\\n    player_Bolsa.json\\\n    player_xxShadowsFallxx.json\\\n  sng_9max/\\\n    table_table1.json\\\n    player_Alice.json\\\n```\\\n\\\nKeyed by {format, stakes, player_name} — same player at different stakes gets separate profiles.\\\n\\\n### EMA Half-Life\\\n- Live play: 100 hands (players adjust over time)\\\n- Simulation: 30 hands (faster convergence for testing)\\\n\\\n## Three-Tier Fallback\\\n\\\n```\\\nhands < 5     → Default (Gen3Config)\\\n5 ≤ h < 20    → Table model (pooled aggregate)\\\n20 ≤ h < 50   → Blend player × table (linear weight)\\\nhands ≥ 50    → Player model dominates\\\n```\\\n\\\n## Range Inference: VPIP → HandRange\\\n\\\n```\\\nVPIP 15% (rock):     frac=0.20, looseness=0.02, floor=0.0\\\nVPIP 30% (standard): frac=0.35, looseness=0.10, floor=0.02\\\nVPIP 45% (loose):    frac=0.45, looseness=0.25, floor=0.05\\\nVPIP 70% (maniac):   frac=0.65, looseness=0.40, floor=0.10\\\n```\\\n\\\nAF adjusts draw weight: passive (0.3) → 0.5, normal (1.5) → 1.0, aggressive (3.0) → 1.5\\\n\\\n## Config Interpolation: Floating Parameters\\\n\\\n**Float with table stats:**\\\n| Parameter | Driver | Tight→Loose |\\\n|---|---|---|\\\n| strong_hands_fraction | VPIP | 0.25→0.50 |\\\n| range_looseness | VPIP | 0.02→0.35 |\\\n| fold_freq_multiplier | F2B | 0.25→1.0 |\\\n| bluff_factor | F2B | 3.0→1.5 |\\\n| call_base | AF | 0.50→0.38 |\\\n| bet_value_fraction | VPIP | 0.60→0.75 |\\\n\\\n**Stay static (universal poker math):**\\\n- bet_flop_base, bet_turn_base, raise_w_draw, call_w_draw, raise_w_protection, call_w_pot_odds\\\n\\\n## Per-Opponent Range Computation\\\n\\\nEach opponent gets their own HandRange based on their effective VPIP/AF.\\\n- **Heads-up**: exhaustive enumeration with opponent's range (unchanged)\\\n- **Multi-way**: MC with per-opponent ranges (importance sampling — sample uniformly, weight by individual range membership)\\\n- Fast path: if all ranges identical → existing shared MC\\\n\\\n## Preflop Adjustments\\\n\\\nPosition-based thresholds in ng_preflop float with table VPIP:\\\n- Tight table → steal wider, call tighter\\\n- Loose table → steal narrower, call looser for implied odds\\\n\\\nMultiplier = `(table_vpip / 0.30).clamp(0.7, 1.4)` applied to opening/stealing ranges.\\\n\\\n## Prediction Measurement & Logging\\\n\\\nAt decision time: log predicted ranges, equity, config source (default/table/player blend).\\\nAt showdown: validate — was shown hand in predicted range? Track running accuracy.\\\nMetrics: in_range_rate, mean_percentile_error, bias (too tight vs too loose).\\\n\\\n## Implementation Steps (11 steps)\\\n\\\n1. **Profile data structures** — EmaStat, PlayerStats, PlayerProfile, TableProfile, range inference, config interpolation\\\n2. **JSON persistence** — serialize/deserialize, path construction, graceful fallback\\\n3. **Observation engine** — consumes game events, updates EMA stats (VPIP/PFR/AF/F2B)\\\n4. **Per-opponent range computation** — extend MC to accept individual ranges\\\n5. **Adaptive strategy wrapper** — composes observer + Gen3 with floating config\\\n6. **Gen3 refactor** — accept external equity + config (separate computation from decision)\\\n7. **Preflop adjustments** — VPIP multiplier on ng_preflop thresholds\\\n8. **Prediction logging** — decision logs + showdown validation + accuracy tracker\\\n9. **Testing harness** — mixed bot tables (chump/flock/gen2/gen3), A/B adaptive vs static\\\n10. **Live server integration** — observer per table, feed events, save/load profiles\\\n11. **Registration & config** — g4_adaptive strategy type, adaptive_mode toggle\\\n\\\n## Testing\\\n\\\n- **Unit**: EMA convergence, range interpolation, blending, JSON round-trip\\\n- **Integration**: event sequence → profile → range prediction → decision\\\n- **Simulation**: 4 table compositions × 10k hands × 20 seeds, A/B adaptive vs static\\\n- **Key validation**: adaptive hero correctly exploits chump_bot (value bet, no bluff) and flock_bot (bluff more, call lighter)\\\n\\\n## Migration\\\n\\\nGen 4 runs alongside Gen 3. `adaptive_mode = false` (default) = Gen 3. Once validated, flip to true.\\\n\\\nFull plan with code sketches: `.kilo/plans/gen4-adaptive-models.md`\"]],\"start1\":0,\"start2\":0,\"length1\":0,\"length2\":5250}]"
metadata_diff: {"new":{"id":"88c7a2bd92a64a459996ffd2ae01ee04","parent_id":"abc167de888d41bf9391c373e90dec8d","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":1782376297434,"user_updated_time":1782376297434,"markup_language":1,"is_shared":0,"share_id":"","conflict_original_id":"","master_key_id":"","user_data":"","deleted_time":1782797680039},"deleted":[]}
encryption_cipher_text: 
encryption_applied: 0
updated_time: 2026-06-30T05:37:46.373Z
created_time: 2026-06-30T05:37:46.373Z
type_: 13