from __future__ import annotations import json import random from pathlib import Path from typing import List, Dict, Optional from typing import TYPE_CHECKING if TYPE_CHECKING: from .agent import Agent from .card import Card class Simulation: def __init__(self, agents: List[Agent]): self.agents = agents self.history: List[Dict] = [] self.cards: List[Card] = [] self.saved = False self.new_round() def new_round(self): self.history = [] self.cards = Card.all_short() random.shuffle(self.cards) self.saved = False def player_cards(self, pid: int) -> List[Card]: return self.cards[pid * 2 : pid * 2 + 2] def board_cards(self, street: str) -> List[Card]: nplayers = len(self.agents) idx_start = nplayers * 2 if street == "flop": return self.cards[idx_start: idx_start + 3] if street == "turn": return self.cards[idx_start: idx_start + 4] if street == "river": return self.cards[idx_start: idx_start + 5] return [] def node_info(self) -> Dict: return {"bet_min": 1, "bet_max": 100} def apply_action(self, pid: int, action: str, amount: Optional[int] = None): self.history.append({"pid": pid, "action": action, "amount": amount}) def to_save_data(self) -> Dict: players = [f"Agent{a.pid}" for a in self.agents] return { "history": self.history, "players": players, "player_cards": ["".join(str(c) for c in self.player_cards(i)) for i in range(len(self.agents))], "board": "".join(str(c) for c in self.board_cards("river")), } def dump_data(self, path: Path | None = None): if self.saved: return if path is None: path = Path.cwd() / "shortdeck_arena_history.jsonl" with path.open("a", encoding="utf-8") as f: f.write(json.dumps(self.to_save_data(), ensure_ascii=False)) f.write("\n") self.saved = True