aefb22c823
"Clear the table" had no tool behind it, so she claimed she did it and nothing changed. Add clear_table (empties the roster, keeps the session/stack/reads) and a `replace` flag on seat_players for a one-shot table swap. Cash card: on a table change / "clear the table", call clear_table then seat the new table — never claim it without calling the tool. 2 tests. Full suite green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
102 lines
3.7 KiB
Python
102 lines
3.7 KiB
Python
"""Live table roster: seat players, attach reads by handle, roster on the HUD."""
|
|
from __future__ import annotations
|
|
|
|
import importlib
|
|
|
|
import numpy as np
|
|
import pytest
|
|
|
|
|
|
def _fake_embed(texts):
|
|
out = []
|
|
for t in texts:
|
|
v = np.zeros(64, dtype=np.float32)
|
|
for w in t.lower().split():
|
|
v[hash(w) % 64] += 1.0
|
|
out.append((v if v.any() else np.full(64, 1e-6, dtype=np.float32)).tolist())
|
|
return out
|
|
|
|
|
|
@pytest.fixture
|
|
def mods(tmp_path, monkeypatch):
|
|
monkeypatch.setenv("LYRA_DB_PATH", str(tmp_path / "test.db"))
|
|
from lyra import llm
|
|
monkeypatch.setattr(llm, "embed", _fake_embed)
|
|
import lyra.memory as memory
|
|
importlib.reload(memory)
|
|
import lyra.poker as poker
|
|
importlib.reload(poker)
|
|
import lyra.tools as tools
|
|
importlib.reload(tools)
|
|
return poker, tools
|
|
|
|
|
|
def test_seat_players_builds_roster(mods):
|
|
poker, _ = mods
|
|
poker.start_session(venue="Meadows", buy_in=300)
|
|
n = poker.seat_players(["TAG", "Jonathan", {"name": "Wheelz", "seat": "3"}])
|
|
assert n == 3
|
|
roster = poker.session_roster()
|
|
names = {r["name"] for r in roster}
|
|
assert names == {"TAG", "Jonathan", "Wheelz"}
|
|
assert next(r for r in roster if r["name"] == "Wheelz")["seat"] == "3"
|
|
|
|
|
|
def test_read_attaches_to_seated_player_by_handle(mods):
|
|
poker, _ = mods
|
|
poker.start_session(venue="Meadows", buy_in=300)
|
|
poker.seat_players(["TAG"])
|
|
poker.add_read(note="limped A4o from the SB, UTG straddle", name="TAG")
|
|
roster = poker.session_roster()
|
|
tag = next(r for r in roster if r["name"] == "TAG")
|
|
assert tag["reads"] == 1 and "A4o" in tag["last_note"]
|
|
# No duplicate TAG spawned — the read landed on the seated player.
|
|
assert sum(p["name"] == "TAG" for p in poker.get_villain_file()) == 1
|
|
|
|
|
|
def test_seat_players_tool_and_roster_in_hud(mods):
|
|
poker, tools = mods
|
|
poker.start_session(venue="Meadows", buy_in=300)
|
|
out = tools.dispatch("seat_players", {"players": [{"name": "TAG"}, {"name": "JD"}]}, {})
|
|
assert "TAG" in out and "JD" in out
|
|
assert len(poker.hud()["roster"]) == 2
|
|
|
|
|
|
def test_unseat_player_removes_from_roster_keeps_history(mods):
|
|
poker, _ = mods
|
|
poker.start_session(venue="Meadows", buy_in=300)
|
|
poker.seat_players(["TAG"])
|
|
poker.add_read(note="showed a bluff", name="TAG")
|
|
assert poker.unseat_player(name="TAG") is True
|
|
assert poker.session_roster() == [] # off the table
|
|
assert poker.player_profile("TAG")["reads"] # history intact
|
|
|
|
|
|
def test_clear_table_empties_roster_keeps_reads(mods):
|
|
poker, tools = mods
|
|
poker.start_session(venue="Meadows", buy_in=300)
|
|
poker.seat_players(["TAG", "Jonathan"])
|
|
poker.add_read(note="limped A4o", name="TAG")
|
|
out = tools.dispatch("clear_table", {}, {})
|
|
assert "cleared" in out.lower()
|
|
assert poker.session_roster() == [] # roster emptied
|
|
assert poker.player_profile("TAG")["reads"] # reads kept
|
|
# A live session is untouched by clearing the table.
|
|
assert poker.live_session() is not None
|
|
|
|
|
|
def test_seat_players_replace_swaps_to_new_table(mods):
|
|
poker, tools = mods
|
|
poker.start_session(venue="Meadows", buy_in=300)
|
|
poker.seat_players(["TAG", "Jonathan"])
|
|
tools.dispatch("seat_players", {"players": [{"name": "Doyle"}, {"name": "Ivey"}],
|
|
"replace": True}, {})
|
|
assert {r["name"] for r in poker.session_roster()} == {"Doyle", "Ivey"}
|
|
|
|
|
|
def test_seat_players_accepts_plain_name_list_via_tool(mods):
|
|
poker, tools = mods
|
|
poker.start_session(venue="Meadows", buy_in=300)
|
|
tools.dispatch("seat_players", {"players": "TAG, JD, Wheelz"}, {})
|
|
assert {r["name"] for r in poker.session_roster()} == {"TAG", "JD", "Wheelz"}
|