"""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