from __future__ import annotations from typing import List, Dict, Optional from pathlib import Path from shortdeck_arena.simulation import Simulation from shortdeck_arena.agent import HumanAgent import uuid class ArenaGame: def __init__(self, starting_stack: int = 1000, max_players: int = 6): self.agents = [] self.player_names: List[str] = [] self.starting_stack = starting_stack self.max_players = max_players self.sim: Optional[Simulation] = None self.stacks: List[int] = [] self.current_turn: int = 0 self.pot: int = 0 self.game_id = [str(name) for name in self.player_names] def join_game(self, name: str) -> int: if len(self.player_names) >= self.max_players: raise ValueError("table full") pid = len(self.player_names) self.player_names.append(name) agent = HumanAgent(pid) self.agents.append(agent) self.stacks.append(self.starting_stack) self.sim = Simulation(self.agents) return pid def info(self, player_id) -> Dict: if not self.sim: return { "game_id": self.game_id, "players": self.player_names, "stacks": [], "dealer_index": 0, "current_turn": 0, "pot": 0, "stage": "preflop", "actions": {}, "player_cards": [], "board_cards": [], } player_cards = [] board_cards = [] try: if player_id is not None and 0 <= player_id < len(self.agents): player_cards = [str(c) for c in self.sim.player_cards(player_id)] except Exception: player_cards = [] try: board_cards = [str(c) for c in self.sim.board_cards("river")] except Exception: board_cards = [] return { "game_id": self.game_id, "players": self.player_names, "stacks": list(self.stacks), "dealer_index": 0, "current_turn": self.current_turn, "pot": self.pot, "stage": "preflop", "actions": {"bet_min": 1, "bet_max": 100}, "player_cards": player_cards, "board_cards": board_cards, } def apply_action(self, pid: int, action: str, amount: Optional[int] = None): if not self.sim: raise ValueError("no game") if pid != self.current_turn: raise ValueError("not your turn") action = action.lower() if action == "check": pass elif action == "bet": if amount is None: raise ValueError("bet requires amount") if amount < 0: raise ValueError("invalid amount") if amount > self.stacks[pid]: amount = self.stacks[pid] self.stacks[pid] -= amount self.pot += amount elif action == "fold": self.stacks[pid] = 0 else: raise ValueError(f"unknown action: {action}") self.sim.apply_action(pid, action, amount) self.sim.dump_data(Path.cwd() / "shortdeck_arena_history.jsonl") if len(self.agents) > 0: self.current_turn = (self.current_turn + 1) % len(self.agents) @property def history(self) -> List[Dict]: if not self.sim: return [] return self.sim.history