feat: basic function
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from time import time
|
||||
from typing import Any
|
||||
|
||||
from texas_holdem.cards import Card
|
||||
from texas_holdem.evaluator import HandValue
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class PlayerAction:
|
||||
action: str
|
||||
amount: int = 0
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, payload: dict[str, Any]) -> "PlayerAction":
|
||||
return cls(str(payload.get("action", "")).lower(), int(payload.get("amount") or 0))
|
||||
|
||||
def to_dict(self) -> dict[str, object]:
|
||||
return {"action": self.action, "amount": self.amount}
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class PlayerState:
|
||||
player_id: str
|
||||
name: str
|
||||
stack: int
|
||||
seat: int
|
||||
hole_cards: list[Card] = field(default_factory=list)
|
||||
folded: bool = False
|
||||
all_in: bool = False
|
||||
in_hand: bool = False
|
||||
street_bet: int = 0
|
||||
total_bet: int = 0
|
||||
|
||||
def reset_for_hand(self) -> None:
|
||||
self.hole_cards = []
|
||||
self.folded = False
|
||||
self.all_in = False
|
||||
self.in_hand = self.stack > 0
|
||||
self.street_bet = 0
|
||||
self.total_bet = 0
|
||||
|
||||
def reset_for_street(self) -> None:
|
||||
self.street_bet = 0
|
||||
|
||||
def commit(self, amount: int) -> int:
|
||||
committed = max(0, min(amount, self.stack))
|
||||
self.stack -= committed
|
||||
self.street_bet += committed
|
||||
self.total_bet += committed
|
||||
if self.stack == 0 and self.in_hand and not self.folded:
|
||||
self.all_in = True
|
||||
return committed
|
||||
|
||||
def public_dict(self) -> dict[str, object]:
|
||||
return {
|
||||
"player_id": self.player_id,
|
||||
"name": self.name,
|
||||
"seat": self.seat,
|
||||
"stack": self.stack,
|
||||
"folded": self.folded,
|
||||
"all_in": self.all_in,
|
||||
"in_hand": self.in_hand,
|
||||
"street_bet": self.street_bet,
|
||||
"total_bet": self.total_bet,
|
||||
}
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class ActionRecord:
|
||||
hand_number: int
|
||||
street: str
|
||||
player_id: str
|
||||
action: str
|
||||
amount: int
|
||||
street_bet: int
|
||||
stack: int
|
||||
|
||||
def to_dict(self) -> dict[str, object]:
|
||||
return {
|
||||
"hand_number": self.hand_number,
|
||||
"street": self.street,
|
||||
"player_id": self.player_id,
|
||||
"action": self.action,
|
||||
"amount": self.amount,
|
||||
"street_bet": self.street_bet,
|
||||
"stack": self.stack,
|
||||
}
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class Observation:
|
||||
game_id: str
|
||||
hand_number: int
|
||||
street: str
|
||||
player_id: str
|
||||
seat: int
|
||||
button_seat: int
|
||||
small_blind: int
|
||||
big_blind: int
|
||||
board: list[Card]
|
||||
hole_cards: list[Card]
|
||||
players: list[dict[str, object]]
|
||||
pot: int
|
||||
to_call: int
|
||||
min_raise_to: int | None
|
||||
legal_actions: list[dict[str, object]]
|
||||
action_history: list[ActionRecord]
|
||||
|
||||
def to_dict(self) -> dict[str, object]:
|
||||
return {
|
||||
"game_id": self.game_id,
|
||||
"hand_number": self.hand_number,
|
||||
"street": self.street,
|
||||
"player_id": self.player_id,
|
||||
"seat": self.seat,
|
||||
"button_seat": self.button_seat,
|
||||
"small_blind": self.small_blind,
|
||||
"big_blind": self.big_blind,
|
||||
"board": [str(card) for card in self.board],
|
||||
"hole_cards": [str(card) for card in self.hole_cards],
|
||||
"players": self.players,
|
||||
"pot": self.pot,
|
||||
"to_call": self.to_call,
|
||||
"min_raise_to": self.min_raise_to,
|
||||
"legal_actions": self.legal_actions,
|
||||
"action_history": [record.to_dict() for record in self.action_history],
|
||||
}
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class PotAward:
|
||||
amount: int
|
||||
winners: list[str]
|
||||
hand_value: HandValue | None
|
||||
|
||||
def to_dict(self) -> dict[str, object]:
|
||||
return {
|
||||
"amount": self.amount,
|
||||
"winners": self.winners,
|
||||
"hand_value": self.hand_value.to_dict() if self.hand_value else None,
|
||||
}
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class HandSummary:
|
||||
game_id: str
|
||||
hand_number: int
|
||||
button_seat: int
|
||||
board: list[Card]
|
||||
actions: list[ActionRecord]
|
||||
awards: list[PotAward]
|
||||
started_at: float = field(default_factory=time)
|
||||
finished_at: float = field(default_factory=time)
|
||||
|
||||
def to_dict(self) -> dict[str, object]:
|
||||
return {
|
||||
"game_id": self.game_id,
|
||||
"hand_number": self.hand_number,
|
||||
"button_seat": self.button_seat,
|
||||
"board": [str(card) for card in self.board],
|
||||
"actions": [record.to_dict() for record in self.actions],
|
||||
"awards": [award.to_dict() for award in self.awards],
|
||||
"started_at": self.started_at,
|
||||
"finished_at": self.finished_at,
|
||||
}
|
||||
Reference in New Issue
Block a user