cb99a8bcee
Lyra was hallucinating poker facts — phantom flushes, missed straights, wrong equity, only correcting when spoon-fed. Board reading + equity are combinatorial facts an LLM can't do reliably; this is exactly the "math via deterministic tools, never the LLM" principle. - lyra/equity.py: treys-backed analyze(hero, villain, board) -> made hands, who's ahead, EXACT equity (enumerated), and outs (one to come). Handles 'Jx' unknown suits (assigned rainbow to avoid phantom flushes); rejects 'x'/dupes. - analyze_spot tool wired into chat; persona MANDATES it for any equity/board/ who's-ahead/outs question — never eyeballed. - tests on the real JJ-vs-65 hand: flop 78.7%, turn villain straight + hero 6.8% with outs "9s 9h 9c" (correctly excludes 9d, which makes villain a flush). Verified live: she now calls the tool and reports exact numbers, no hallucinated flush. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
43 lines
1.5 KiB
Python
43 lines
1.5 KiB
Python
"""Deterministic equity/board-eval — the JJ-vs-65 hand Lyra kept botching."""
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from lyra import equity
|
|
|
|
|
|
def test_flop_equity_and_made_hands():
|
|
r = equity.analyze(["Jh", "Js"], ["6d", "5d"], ["8c", "7d", "Ts"])
|
|
assert r["ahead"] == "hero"
|
|
assert r["hero_hand"] == "Pair" and r["villain_hand"] == "High Card"
|
|
assert 75 < r["hero_equity"] < 82 # ~78.7%
|
|
|
|
|
|
def test_turn_villain_straight_and_outs_exclude_flush_card():
|
|
r = equity.analyze(["Jh", "Js"], ["6d", "5d"], ["8c", "7d", "Ts", "4d"])
|
|
assert r["ahead"] == "villain"
|
|
assert r["villain_hand"] == "Straight"
|
|
# hero's only outs are the three non-diamond nines — 9d makes villain a flush
|
|
assert r["hero_outs"]["count"] == 3
|
|
assert "9d" not in r["hero_outs"]["cards"]
|
|
assert r["hero_equity"] < 10
|
|
|
|
|
|
def test_rejects_unknown_and_duplicate_cards():
|
|
with pytest.raises(equity.EquityError):
|
|
equity.analyze(["x", "x"], ["6d", "5d"], ["8c", "7d", "Ts"])
|
|
with pytest.raises(equity.EquityError):
|
|
equity.analyze(["8c", "8c"], ["6d", "5d"], ["8c", "7d", "Ts"])
|
|
|
|
|
|
def test_unknown_suits_spread_rainbow_no_phantom_flush():
|
|
# all-unknown-suit board must not become monotone (which would inflate equity)
|
|
r = equity.analyze(["Jx", "Jx"], ["6d", "5d"], ["8x", "7x", "Tx"])
|
|
assert 75 < r["hero_equity"] < 82
|
|
|
|
|
|
def test_tool_dispatch():
|
|
from lyra import tools
|
|
out = tools.dispatch("analyze_spot", {"hero": "Jh Js", "villain": "6d 5d", "board": "8c 7d Ts 4d"})
|
|
assert "EQUITY" in out and "Straight" in out
|