66 lines
2.0 KiB
Python
66 lines
2.0 KiB
Python
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
|