feat: basic function

This commit is contained in:
2026-05-11 00:44:15 +08:00
committed by qianrui.mmmy
commit e46b2b84c5
17 changed files with 1946 additions and 0 deletions
+168
View File
@@ -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,
}